5 #include "devices/pci.h"
6 #include "threads/io.h"
7 #include "threads/malloc.h"
9 struct list pci_dev_list;
11 static void scan_bus(uint8_t bus);
14 pci_read_config (unsigned bus, unsigned dev, unsigned func, unsigned reg)
22 0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg << 2));
27 pci_write_config (unsigned bus, unsigned dev, unsigned func, unsigned reg,
36 0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg << 2));
41 pci_dump_dev (struct pci_dev *dev)
45 printf ("PCI: Device %04x:%02x:%02x.%x %04x:%04x\n",
46 0, dev->bus_id, dev->devfn >> 4, dev->devfn & 0xf,
47 dev->ven_id, dev->dev_id);
48 printf ("PCI: Class %02x:%02x:%02x\n",
49 dev->base_class, dev->sub_class, dev->interface);
51 for (bar = 0; bar < PCI_NUM_BARS; bar++)
53 if (dev->resources[bar].start != 0 ||
54 dev->resources[bar].end != 0)
57 dev->resources[bar].type == PCI_BAR_TYPE_MEM
59 printf ("range %d: %08x-%08x\n",
60 bar, dev->resources[bar].start, dev->resources[bar].end);
64 printf ("PCI: Interrupt: %u\n", dev->irq);
69 pci_setup_irq (struct pci_dev *dev)
72 pinline = pci_read_config(dev->bus_id,
75 PCI_REGNUM_INTERRUPT);
77 /* Devices without a non-zero pin get IRQ 0. I guess this is acceptable? */
78 if (pinline & PCI_INTERRUPT_MASK_PIN) {
79 dev->irq = pinline & PCI_INTERRUPT_MASK_LINE;
84 pci_setup_bases (struct pci_dev *dev)
91 for (bar = 0; bar < PCI_NUM_BARS; bar++)
93 bar_reg = PCI_REGNUM_BASE_ADDRESS + bar;
95 res = &dev->resources[bar];
99 /* Get the base address out of the BAR */
100 base = pci_read_config(dev->bus_id,
105 /* Write 1's and get the size from the BAR */
106 pci_write_config(dev->bus_id,
111 size = pci_read_config(dev->bus_id,
116 /* Put the base address back in the BAR */
117 pci_write_config(dev->bus_id,
123 /* If the size is unreasonable, skip this BAR.
124 Is this redundant for Pintos? */
125 if (!size || size == 0xffffffff) {
129 /* Broken hardware that requests a base at the end?
130 Maybe redundant for Pintos? */
131 if (base == 0xffffffff) {
135 /* Make a new resource, tag it for I/O vs. memory */
136 res->type = base & PCI_BAR_TYPE_MASK;
137 if (res->type == PCI_BAR_TYPE_MEM)
139 res->start = base & PCI_BAR_MASK_MEM;
140 size = size & PCI_BAR_MASK_MEM;
144 res->start = base & PCI_BAR_MASK_IO;
145 size = size & PCI_BAR_MASK_IO;
147 res->end = res->start + size;
152 scan_device (uint8_t bus, uint8_t dev, uint8_t func)
156 int dev_id, vendor_id;
159 struct pci_dev *new_pci_dev;
161 byte_cfg = (uint8_t *) cfg;
163 /* Read configuration space header */
164 for (reg = 0; reg < 16; reg++)
165 cfg[reg] = pci_read_config (bus, dev, func, reg);
167 /* Get vendor and device ID */
168 dev_id = cfg[0] >> 16;
169 vendor_id = cfg[0] & 0xffff;
171 if (dev_id == 0 || dev_id == PCI_BAD_DEVICE ||
172 vendor_id == 0 || vendor_id == PCI_BAD_DEVICE)
175 /* We have a valid PCI device, set it up */
176 new_pci_dev = malloc (sizeof *new_pci_dev);
178 PANIC ("couldn't allocate memory for PCI device");
180 new_pci_dev->bus_id = bus;
181 new_pci_dev->devfn = (dev << 4) | func;
182 new_pci_dev->ven_id = vendor_id;
183 new_pci_dev->dev_id = dev_id;
184 new_pci_dev->base_class = byte_cfg[PCI_REG_CLASS_BASE];
185 new_pci_dev->sub_class = byte_cfg[PCI_REG_CLASS_SUB];
186 new_pci_dev->interface = byte_cfg[PCI_REG_CLASS_INTERFACE];
187 list_push_front (&pci_dev_list, &new_pci_dev->elem);
189 pci_setup_irq (new_pci_dev);
191 /* If device is PCI-to-PCI bridge, scan the bus behind it */
192 if (new_pci_dev->base_class == PCI_BRIDGE_BASE_CLASS &&
193 new_pci_dev->sub_class == PCI_BRIDGE_SUB_CLASS &&
194 (byte_cfg[PCI_REG_HEADER_TYPE] & 0x3f) == PCI_BRIDGE_HEADER_TYPE)
196 scan_bus(byte_cfg[PCI_BRIDGE_REG_SBUS]);
199 /* For normal devices, set up the BARs */
202 pci_setup_bases (new_pci_dev);
205 /* Debugging output */
206 pci_dump_dev(new_pci_dev);
207 for (line = 0; line < 16; line++)
211 printf ("PCI: %02x:", line * 4);
212 for (byte = 3; byte >= 0; byte--)
213 printf (" %02x", byte_cfg[line * 4 + byte]);
219 /* Return if we're a multifunction device */
220 return byte_cfg[PCI_REG_HEADER_TYPE] & 0x80;
224 scan_bus(uint8_t bus)
228 printf ("PCI: Scanning bus (%u)\n", bus);
231 for (dev = 0; dev < 32; dev++)
233 /* Returns true if device is multi-function */
234 if (scan_device (bus, dev, 0))
238 for (func = 1; func < 8; func++)
239 scan_device (bus, dev, func);
242 printf ("PCI: Done (%u)\n", bus);
250 printf ("PCI: Initializating\n");
251 list_init (&pci_dev_list);
253 printf ("PCI: Initialization done\n");
261 for (e = list_begin (&pci_dev_list); e != list_end (&pci_dev_list);
264 struct pci_dev *dev = list_entry (e, struct pci_dev, elem);