6651ca0f794cf8c71714e4cfcf7cb14ff19f86c1
[reactos.git] / reactos / boot / freeldr / freeldr / arch / powerpc / prep_pci.c
1 #include <freeldr.h>
2 #include "prep.h"
3
4 typedef struct _pci_cfg {
5 unsigned long addr;
6 unsigned long data;
7 } pci_cfg;
8
9 typedef struct _pci_desc {
10 pci_cfg *cfg;
11 } pci_desc;
12
13 pci_desc pci1_desc = { (void *)0x80000cf8 };
14 #define rev16(x) ((((x)>>8)&0xff)|(((x)&0xff)<<8))
15 #define rev32(x) ((((x)>>24)&0xff)|(((x)>>8)&0xff00)|(((x)&0xff00)<<8)|(((x)&0xff)<<24))
16 #define pci_addr(bus,dev,fn,reg) \
17 (0x80000000 | \
18 ((bus & 0xff) << 16) | \
19 ((dev & 0x1f) << 11) | \
20 ((fn & 7) << 8) | \
21 (reg & 0xfc))
22 #if 0
23 #define pci_cfg_addr(bus,dev,fn,reg) \
24 ((bus == 0) ? \
25 ((1 << (dev + 16)) | \
26 (dev << 11) | \
27 (fn << 8) | \
28 ((reg & 0xfc) | 1)) : pci_addr(bus,dev,fn,reg))
29 #else
30 #define pci_cfg_addr(bus,dev,fn,reg) pci_addr(bus,dev,fn,reg)
31 #endif
32 unsigned long pci_read( pci_desc *desc, int bus, int dev, int fn, int reg, int len ) {
33 sync();
34 unsigned long save_state = desc->cfg->addr, ret = 0;
35 unsigned long addr = pci_cfg_addr(bus,dev,fn,reg);
36 unsigned long offset = reg & 3;
37 desc->cfg->addr = rev32(addr);
38 sync();
39 switch( len ) {
40 case 4:
41 ret = desc->cfg->data;
42 break;
43 case 2:
44 ret = desc->cfg->data;
45 ret = (ret >> (offset << 3)) & 0xffff;
46 break;
47 case 1:
48 ret = desc->cfg->data;
49 ret = (ret >> (offset << 3)) & 0xff;
50 break;
51 }
52 desc->cfg->addr = save_state;
53 sync();
54 return ret;
55 }
56
57 void pci_read_bar( pci_desc *desc, int bus, int dev, int fn, int bar,
58 struct _pci_bar *bar_data ) {
59 bar_data->data = pci_read( desc, bus, dev, fn, 0x10 + (bar * 4), 4 );
60 }
61
62 /*
63 * Imagine: offset 3, len 1
64 * let oldval = 0x12345678 and val = 0xabcd1234;
65 * mask = ((1 << 8) - 1) << 24; // 0xff000000
66 * oldval = (0x12345678 & 0x00ffffff) | (0xabcd1234 & 0xff000000) = 0xab345678;
67 */
68 void pci_write( pci_desc *desc, int bus, int dev, int fn, int reg, int len, int val ) {
69 unsigned long save_state = desc->cfg->addr;
70 unsigned long addr = pci_cfg_addr(bus,dev,fn,reg);
71 unsigned long offset = reg & 3;
72 unsigned long oldval = pci_read( desc, bus, dev, fn, reg & ~3, 4 );
73 unsigned long mask = ((1 << (len * 8)) - 1) << (offset << 3);
74 oldval = (oldval & ~mask) | ((val << (offset << 3)) & mask);
75 desc->cfg->addr = rev32(addr);
76 sync();
77 desc->cfg->data = rev32(oldval);
78 sync();
79 desc->cfg->addr = save_state;
80 sync();
81 }
82
83 void pci_write_bar( pci_desc *desc, int bus, int dev, int fn, int bar, struct _pci_bar *bar_data ) {
84 pci_write( desc, bus, dev, fn, 0x10 + (bar * 4), 4, bar_data->data );
85 }
86
87 void print_bar( struct _pci_bar *bar ) {
88 printf("BAR: %x\n", bar->data);
89 }
90
91 #define PCI_VENDORID 0
92 #define PCI_DEVICEID 2
93 #define PCI_HEADER_TYPE 0xe
94 #define PCI_BASECLASS 0xb
95
96 void pci_setup( PPC_DEVICE_TREE *tree, pci_desc *desc ) {
97 unsigned char type;
98 unsigned short vendor, device, devclass;
99 int funcs, bus, dev, fn;
100
101 pci1_desc.cfg = (pci_cfg *)0x80000cf8;
102
103 printf("PCI Bus:\n");
104 for( bus = 0; bus < 1; bus++ ) {
105 for( dev = 0; dev < 32; dev++ ) {
106 type = pci_read(desc,bus,dev,0,PCI_HEADER_TYPE,1);
107 vendor = pci_read(desc,bus,dev,0,PCI_VENDORID,2);
108 device = pci_read(desc,bus,dev,0,PCI_DEVICEID,2);
109
110 if(vendor == 0 || vendor == 0xffff) continue;
111 if(type & 0x80) funcs = 8; else funcs = 1;
112
113 for( fn = 0; fn < funcs; fn++ ) {
114 devclass = pci_read(desc,bus,dev,fn,PCI_BASECLASS,1);
115 printf(" %d:%d -> vendor:device:class %x:%x:%x\n",
116 bus, dev, vendor, device, devclass);
117
118 if( devclass == 3 ) {
119 printf("Setting up vga...\n");
120 vga_setup(tree,desc,&vga1_desc,bus,dev,fn);
121 printf("Done with vga\n");
122 }
123 }
124 }
125 }
126 printf("^-- end PCI\n");
127 }