Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


3657bcf2d374f22c55fa3aaa5c8db2c6194cad03
[palacios.git] / palacios / src / geekos / pci.c
1 #include <geekos/malloc.h>
2 #include <geekos/pci.h>
3 #include <geekos/io.h>
4 #include <geekos/debug.h>
5
6 #define PCI_CONFIG_ADDRESS 0xcf8  // 32 bit, little endian
7 #define PCI_CONFIG_DATA    0xcfc  // 32 bit, little endian
8
9 #define PCI_MAX_NUM_BUSES  4
10
11
12 struct pci_device_config {
13   ushort_t   device_id;
14   ushort_t   vendor_id;
15   ushort_t   status;
16   ushort_t   command;
17   uchar_t    class_code;
18   uchar_t    subclass;
19   ushort_t   revision;
20   uchar_t    BIST;
21   uchar_t    header_type;
22   uchar_t    latency_time;
23   uchar_t    cache_line_size;
24   uint_t     BAR[6];
25   uint_t     cardbus_cis_pointer;
26   ushort_t   subsystem_id;
27   ushort_t   subsystem_vendor_id;
28   uint_t     expansion_rom_address;
29   uint_t     reserved[2];
30   uchar_t    max_latency;
31   uchar_t    min_grant;
32   uchar_t    intr_pin;
33   uchar_t    intr_line;
34 }  __attribute__((__packed__)) ;
35
36 struct pci_bus {
37   uint_t number;
38   struct pci_bus *next;
39
40   struct pci_device *device_list; //
41
42 };
43
44 struct pci_device {
45   uint_t number;
46   struct pci_bus    *bus;
47   struct pci_device *next;
48   
49   struct pci_device_config config;
50 };
51
52 struct pci {
53   uint_t          num_buses;
54   struct pci_bus *bus_list;
55 };
56     
57
58 static uint_t ReadPCIDWord(uint_t bus, uint_t dev, uint_t func, uint_t offset)
59 {
60    uint_t address;
61    uint_t data;
62  
63    address = ((bus << 16) | (dev << 11) |
64               (func << 8) | (offset & 0xfc) | ((uint_t)0x80000000));
65  
66    Out_DWord(PCI_CONFIG_ADDRESS,address);
67    data=In_DWord(PCI_CONFIG_DATA);
68
69    return data;
70 }
71
72 #if 0
73
74 static ushort_t ReadPCIWord(uint_t bus, uint_t dev, uint_t func, uint_t offset)
75 {
76    uint_t address;
77    uint_t data;
78  
79    address = ((bus << 16) | (dev << 11) |
80              (func << 8) | (offset & 0xfc) | ((uint_t)0x80000000));
81  
82    Out_DWord(PCI_CONFIG_ADDRESS,address);
83    data=In_DWord(PCI_CONFIG_DATA);
84
85    //PrintBoth("PCI: [0x%x] = 0x%x\n",address,data);
86
87
88    return (ushort_t) ((data>>((offset&0x2)*8)) & 0xffff);
89 }
90
91 #endif
92
93 static ushort_t ReadPCIWord(uint_t bus, uint_t dev, uint_t func, uint_t offset)
94 {
95   return (ushort_t) (ReadPCIDWord(bus,dev,func,offset)>>((offset&0x2)*8));
96 }
97
98 #if 0  // not currently used
99 static uchar_t ReadPCIByte(uint_t bus, uint_t dev, uint_t func, uint_t offset)
100 {
101   return (uchar_t) (ReadPCIDWord(bus,dev,func,offset)>>((offset&0x3)*8));
102 }
103 #endif
104
105 static struct pci *NewPCI()
106 {
107   struct pci *p = (struct pci *)Malloc(sizeof(struct pci));
108   p->bus_list=NULL;
109   p->num_buses=0;
110   return p;
111 }
112
113 static void AddPCIBus(struct pci *p, struct pci_bus *bus) 
114 {
115   bus->next = p->bus_list;
116   p->bus_list=bus;
117 }
118     
119
120 static struct pci_bus *NewPCIBus(struct pci *p)
121 {
122   struct pci_bus *pb = (struct pci_bus *)Malloc(sizeof(struct pci_bus));
123   pb->device_list=NULL;
124   pb->number = (p->num_buses);
125   p->num_buses++;
126   return pb;
127 }
128
129 static void AddPCIDevice(struct pci_bus *b, struct pci_device *d)
130 {
131   d->bus=b;
132   d->next=b->device_list;
133   b->device_list=d;
134 }
135  
136 static struct pci_device *NewPCIDevice(struct pci_bus *pb) 
137 {
138   struct pci_device *pd = (struct pci_device *)Malloc(sizeof(struct pci_device));
139   pd->number=0;
140   pd->bus=NULL;
141   pd->next=NULL;
142   return pd;
143 }
144
145 static void GetPCIDeviceConfig(uint_t bus,
146                                uint_t dev,
147                                struct pci_device *d)
148 {
149   uint_t numdwords=sizeof(struct pci_device_config) / 4;
150   uint_t i;
151
152   uint_t *p = (uint_t *) (&(d->config));
153
154   for (i=0;i<numdwords;i++) {
155     p[i]=ReadPCIDWord(bus,dev,0,i*4);
156   }
157 }
158
159
160
161 static struct pci *ScanPCI()
162 {
163   uint_t bus, dev;
164   ushort_t vendor;
165
166   struct pci *thepci = NewPCI();
167   struct pci_bus *thebus;
168  
169   for (bus=0;bus<PCI_MAX_NUM_BUSES;bus++) {
170     // Are there any devices on the bus?
171     for (dev=0;dev<32;dev++) { 
172       vendor=ReadPCIWord(bus,dev,0,0);
173       if (vendor!=0xffff) { 
174         break;
175       }
176     }
177     if (dev==32) { 
178       continue;
179     }
180     // There are devices.  Create a bus.
181     thebus = NewPCIBus(thepci);
182     thebus->number=bus;
183     // Add the devices to the bus
184     for (dev=0;dev<32;dev++) { 
185       vendor=ReadPCIWord(bus,dev,0,0);
186       if (vendor!=0xffff) { 
187         struct pci_device *thedev=NewPCIDevice(thebus);
188         thedev->number=dev;
189         GetPCIDeviceConfig(bus,dev,thedev);
190         AddPCIDevice(thebus,thedev);
191       }
192     }
193     AddPCIBus(thepci,thebus);
194   }
195   return thepci;
196 }
197
198 static void PrintPCIDevice(struct pci_device *thedev)
199 {
200   PrintBoth("    PCI Device: \n");
201   PrintBoth("     Slot: %u\n",thedev->number);
202   PrintBoth("      device_id:        0x%x\n", (uint_t) thedev->config.device_id);
203   PrintBoth("      vendor_id:        0x%x\n", (uint_t) thedev->config.vendor_id);
204   PrintBoth("      status:           0x%x\n", (uint_t) thedev->config.status);
205   PrintBoth("      command:          0x%x\n", (uint_t) thedev->config.command);
206   PrintBoth("      class_code:       0x%x\n", (uint_t) thedev->config.class_code);
207   PrintBoth("      subclass:         0x%x\n", (uint_t) thedev->config.subclass);
208   PrintBoth("      revision:         0x%x\n", (uint_t) thedev->config.revision);
209   PrintBoth("      BIST:             0x%x\n", (uint_t) thedev->config.BIST);
210   PrintBoth("      header_type:      0x%x\n", (uint_t) thedev->config.header_type);
211   PrintBoth("      latency_time:     0x%x\n", (uint_t) thedev->config.latency_time);
212   PrintBoth("      cache_line_size:  0x%x\n", (uint_t) thedev->config.cache_line_size);
213   PrintBoth("      BAR[0]:           0x%x\n", (uint_t) thedev->config.BAR[0]);
214   PrintBoth("      BAR[1]:           0x%x\n", (uint_t) thedev->config.BAR[1]);
215   PrintBoth("      BAR[2]:           0x%x\n", (uint_t) thedev->config.BAR[2]);
216   PrintBoth("      BAR[3]:           0x%x\n", (uint_t) thedev->config.BAR[3]);
217   PrintBoth("      BAR[4]:           0x%x\n", (uint_t) thedev->config.BAR[4]);
218   PrintBoth("      BAR[5]:           0x%x\n", (uint_t) thedev->config.BAR[5]);
219   PrintBoth("      cardbus_cis_ptr:  0x%x\n", (uint_t) thedev->config.cardbus_cis_pointer);
220   PrintBoth("      subsystem_id:     0x%x\n", (uint_t) thedev->config.subsystem_id);
221   PrintBoth("      subsystem_vendor: 0x%x\n", (uint_t) thedev->config.subsystem_vendor_id);
222   PrintBoth("      exp_rom_address:  0x%x\n", (uint_t) thedev->config.expansion_rom_address);
223   PrintBoth("      reserved[0]:      0x%x\n", (uint_t) thedev->config.reserved[0]);
224   PrintBoth("      reserved[1]:      0x%x\n", (uint_t) thedev->config.reserved[1]);
225   PrintBoth("      max_latency:      0x%x\n", (uint_t) thedev->config.max_latency);
226   PrintBoth("      min_grant:        0x%x\n", (uint_t) thedev->config.min_grant);
227   PrintBoth("      intr_pin:         0x%x\n", (uint_t) thedev->config.intr_pin);
228   PrintBoth("      intr_line:        0x%x\n", (uint_t) thedev->config.intr_line);
229 }
230
231 static void PrintPCIBus(struct pci_bus *thebus)
232 {
233   struct pci_device *thedev;
234
235   PrintBoth("  PCI Bus:\n");
236   PrintBoth("   Number: %u\n",thebus->number);
237
238   thedev=thebus->device_list;
239
240   while (thedev) { 
241     PrintPCIDevice(thedev);
242     thedev=thedev->next;
243   }
244 }
245
246 static void PrintPCI(struct pci *thepci)
247 {
248   struct pci_bus *thebus;
249
250   PrintBoth("PCI Configuration:\n");
251   PrintBoth(" Number of Buses: %u\n",thepci->num_buses);
252   thebus=thepci->bus_list;
253   while (thebus) { 
254     PrintPCIBus(thebus);
255     thebus=thebus->next;
256   }
257
258 }
259
260 int Init_PCI()
261 {
262   PrintPCI(ScanPCI());
263
264   return 0;
265
266 }