1 #include <geekos/malloc.h>
2 #include <geekos/pci.h>
4 #include <geekos/debug.h>
6 #define PCI_CONFIG_ADDRESS 0xcf8 // 32 bit, little endian
7 #define PCI_CONFIG_DATA 0xcfc // 32 bit, little endian
9 #define PCI_MAX_NUM_BUSES 4
12 struct pci_device_config {
23 uchar_t cache_line_size;
25 uint_t cardbus_cis_pointer;
26 ushort_t subsystem_id;
27 ushort_t subsystem_vendor_id;
28 uint_t expansion_rom_address;
34 } __attribute__((__packed__)) ;
40 struct pci_device *device_list; //
47 struct pci_device *next;
49 struct pci_device_config config;
54 struct pci_bus *bus_list;
58 static uint_t ReadPCIDWord(uint_t bus, uint_t dev, uint_t func, uint_t offset)
63 address = ((bus << 16) | (dev << 11) |
64 (func << 8) | (offset & 0xfc) | ((uint_t)0x80000000));
66 Out_DWord(PCI_CONFIG_ADDRESS,address);
67 data=In_DWord(PCI_CONFIG_DATA);
74 static ushort_t ReadPCIWord(uint_t bus, uint_t dev, uint_t func, uint_t offset)
79 address = ((bus << 16) | (dev << 11) |
80 (func << 8) | (offset & 0xfc) | ((uint_t)0x80000000));
82 Out_DWord(PCI_CONFIG_ADDRESS,address);
83 data=In_DWord(PCI_CONFIG_DATA);
85 //PrintBoth("PCI: [0x%x] = 0x%x\n",address,data);
88 return (ushort_t) ((data>>((offset&0x2)*8)) & 0xffff);
93 static ushort_t ReadPCIWord(uint_t bus, uint_t dev, uint_t func, uint_t offset)
95 return (ushort_t) (ReadPCIDWord(bus,dev,func,offset)>>((offset&0x2)*8));
98 #if 0 // not currently used
99 static uchar_t ReadPCIByte(uint_t bus, uint_t dev, uint_t func, uint_t offset)
101 return (uchar_t) (ReadPCIDWord(bus,dev,func,offset)>>((offset&0x3)*8));
105 static struct pci *NewPCI()
107 struct pci *p = (struct pci *)Malloc(sizeof(struct pci));
113 static void AddPCIBus(struct pci *p, struct pci_bus *bus)
115 bus->next = p->bus_list;
120 static struct pci_bus *NewPCIBus(struct pci *p)
122 struct pci_bus *pb = (struct pci_bus *)Malloc(sizeof(struct pci_bus));
123 pb->device_list=NULL;
124 pb->number = (p->num_buses);
129 static void AddPCIDevice(struct pci_bus *b, struct pci_device *d)
132 d->next=b->device_list;
136 static struct pci_device *NewPCIDevice(struct pci_bus *pb)
138 struct pci_device *pd = (struct pci_device *)Malloc(sizeof(struct pci_device));
145 static void GetPCIDeviceConfig(uint_t bus,
147 struct pci_device *d)
149 uint_t numdwords=sizeof(struct pci_device_config) / 4;
152 uint_t *p = (uint_t *) (&(d->config));
154 for (i=0;i<numdwords;i++) {
155 p[i]=ReadPCIDWord(bus,dev,0,i*4);
161 static struct pci *ScanPCI()
166 struct pci *thepci = NewPCI();
167 struct pci_bus *thebus;
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) {
180 // There are devices. Create a bus.
181 thebus = NewPCIBus(thepci);
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);
189 GetPCIDeviceConfig(bus,dev,thedev);
190 AddPCIDevice(thebus,thedev);
193 AddPCIBus(thepci,thebus);
198 static void PrintPCIDevice(struct pci_device *thedev)
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);
231 static void PrintPCIBus(struct pci_bus *thebus)
233 struct pci_device *thedev;
235 PrintBoth(" PCI Bus:\n");
236 PrintBoth(" Number: %u\n",thebus->number);
238 thedev=thebus->device_list;
241 PrintPCIDevice(thedev);
246 static void PrintPCI(struct pci *thepci)
248 struct pci_bus *thebus;
250 PrintBoth("PCI Configuration:\n");
251 PrintBoth(" Number of Buses: %u\n",thepci->num_buses);
252 thebus=thepci->bus_list;