No longer builds, but this is a good intermediate save point.
[akaros.git] / kern / arch / x86 / pci.c
1 /* Copyright (c) 2009, 2010 The Regents of the University of California
2  * See LICENSE for details.
3  *
4  * Barret Rhoden <brho@cs.berkeley.edu>
5  * Original by Paul Pearce <pearce@eecs.berkeley.edu> */
6
7 #include <arch/x86.h>
8 #include <arch/pci.h>
9 #include <trap.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <assert.h>
13 #include <kmalloc.h>
14 #include <arch/pci_defs.h>
15
16 /* List of all discovered devices */
17 struct pcidev_stailq pci_devices = STAILQ_HEAD_INITIALIZER(pci_devices);
18
19 /* PCI accesses are two-stage PIO, which need to complete atomically */
20 spinlock_t pci_lock = SPINLOCK_INITIALIZER_IRQSAVE;
21
22 static char STD_PCI_DEV[] = "Standard PCI Device";
23 static char PCI2PCI[] = "PCI-to-PCI Bridge";
24 static char PCI2CARDBUS[] = "PCI-Cardbus Bridge";
25
26 /* Gets any old raw bar, with some catches based on type. */
27 static uint32_t pci_getbar(struct pci_device *pcidev, unsigned int bar)
28 {
29         uint8_t type;
30         if (bar >= MAX_PCI_BAR)
31                 panic("Nonexistant bar requested!");
32         type = pcidev_read8(pcidev, PCI_HEADER_REG);
33         type &= ~0x80;  /* drop the MF bit */
34         /* Only types 0 and 1 have BARS */
35         if ((type != 0x00) && (type != 0x01))
36                 return 0;
37         /* Only type 0 has BAR2 - BAR5 */
38         if ((bar > 1) && (type != 0x00))
39                 return 0;
40         return pcidev_read32(pcidev, PCI_BAR0_STD + bar * PCI_BAR_OFF);
41 }
42
43 /* Determines if a given bar is IO (o/w, it's mem) */
44 static bool pci_is_iobar(uint32_t bar)
45 {
46         return bar & PCI_BAR_IO;
47 }
48
49 static bool pci_is_membar32(uint32_t bar)
50 {
51         if (pci_is_iobar(bar))
52                 return FALSE;
53         return (bar & PCI_MEMBAR_TYPE) == PCI_MEMBAR_32BIT;
54 }
55
56 static bool pci_is_membar64(uint32_t bar)
57 {
58         if (pci_is_iobar(bar))
59                 return FALSE;
60         return (bar & PCI_MEMBAR_TYPE) == PCI_MEMBAR_64BIT;
61 }
62
63 /* Helper to get the address from a membar.  Check the type beforehand */
64 static uint32_t pci_getmembar32(uint32_t bar)
65 {
66         uint8_t type = bar & PCI_MEMBAR_TYPE;
67         if (type != PCI_MEMBAR_32BIT) {
68                 warn("Unhandled PCI membar type: %02p\n", type >> 1);
69                 return 0;
70         }
71         return bar & 0xfffffff0;
72 }
73
74 /* Helper to get the address from an IObar.  Check the type beforehand */
75 static uint32_t pci_getiobar32(uint32_t bar)
76 {
77         return bar & 0xfffffffc;
78 }
79
80 /* memory bars have a little dance you go through to detect what the size of the
81  * memory region is.  for 64 bit bars, i'm assuming you only need to do this to
82  * the lower part (no device will need > 4GB, right?).
83  *
84  * Hold the dev's lock, or o/w avoid sync issues. */
85 static uint32_t __pci_membar_get_sz(struct pci_device *pcidev, int bar)
86 {
87         /* save the old value, write all 1s, invert, add 1, restore.
88          * http://wiki.osdev.org/PCI for details. */
89         uint32_t bar_off = PCI_BAR0_STD + bar * PCI_BAR_OFF;
90         uint32_t old_val = pcidev_read32(pcidev, bar_off);
91         uint32_t retval;
92         pcidev_write32(pcidev, bar_off, 0xffffffff);
93         /* Don't forget to mask the lower 3 bits! */
94         retval = pcidev_read32(pcidev, bar_off) & PCI_BAR_MEM_MASK;
95         retval = ~retval + 1;
96         pcidev_write32(pcidev, bar_off, old_val);
97         return retval;
98 }
99
100 /* process the bars.  these will tell us what address space (PIO or memory) and
101  * where the base is.  fills results into pcidev.  i don't know if you can have
102  * multiple bars with conflicting/different regions (like two separate PIO
103  * ranges).  I'm assuming you don't, and will warn if we see one. */
104 static void __pci_handle_bars(struct pci_device *pcidev)
105 {
106         uint32_t bar_val;
107         int max_bars;
108         if (pcidev->header_type == STD_PCI_DEV)
109                 max_bars = MAX_PCI_BAR;
110         else if (pcidev->header_type == PCI2PCI)
111                 max_bars = 2;
112         else
113                 max_bars = 0;
114         /* TODO: consider aborting for classes 00, 05 (memory ctlr), 06 (bridge) */
115         for (int i = 0; i < max_bars; i++) {
116                 bar_val = pci_getbar(pcidev, i);
117                 pcidev->bar[i].raw_bar = bar_val;
118                 if (!bar_val)   /* (0 denotes no valid data) */
119                         continue;
120                 if (pci_is_iobar(bar_val)) {
121                         pcidev->bar[i].pio_base = pci_getiobar32(bar_val);
122                 } else {
123                         if (pci_is_membar32(bar_val)) {
124                                 pcidev->bar[i].mmio_base32 = bar_val & PCI_BAR_MEM_MASK;
125                                 pcidev->bar[i].mmio_sz = __pci_membar_get_sz(pcidev, i);
126                         } else if (pci_is_membar64(bar_val)) {
127                                 /* 64 bit, the lower 32 are in this bar, the upper
128                                  * are in the next bar */
129                                 pcidev->bar[i].mmio_base64 = bar_val & PCI_BAR_MEM_MASK;
130                                 assert(i < max_bars - 1);
131                                 bar_val = pci_getbar(pcidev, i + 1);    /* read next bar */
132                                 /* note we don't check for IO or memsize.  the entire next bar
133                                  * is supposed to be for the upper 32 bits. */
134                                 pcidev->bar[i].mmio_base64 |= (uint64_t)bar_val << 32;
135                                 pcidev->bar[i].mmio_sz = __pci_membar_get_sz(pcidev, i);
136                                 i++;
137                         }
138                 }
139                 /* this will track the maximum bar we've had.  it'll include the 64 bit
140                  * uppers, as well as devices that have only higher numbered bars. */
141                 pcidev->nr_bars = i + 1;
142         }
143 }
144
145 static void __pci_parse_caps(struct pci_device *pcidev)
146 {
147         uint32_t cap_off;       /* not sure if this can be extended from u8 */
148         uint8_t cap_id;
149         if (!(pcidev_read16(pcidev, PCI_STATUS_REG) & (1 << 4)))
150                 return;
151         switch (pcidev_read8(pcidev, PCI_HEADER_REG) & 0x7f) {
152                 case 0:                         /* etc */
153                 case 1:                         /* pci to pci bridge */
154                         cap_off = 0x34;
155                         break;
156                 case 2:                         /* cardbus bridge */
157                         cap_off = 0x14;
158                         break;
159                 default:
160                         return;
161         }
162         /* initial offset points to the addr of the first cap */
163         cap_off = pcidev_read8(pcidev, cap_off);
164         cap_off &= ~0x3;        /* osdev says the lower 2 bits are reserved */
165         while (cap_off) {
166                 cap_id = pcidev_read8(pcidev, cap_off);
167                 if (cap_id > PCI_CAP_ID_MAX) {
168                         printk("PCI %x:%x:%x had bad cap 0x%x\n", pcidev->bus, pcidev->dev,
169                                pcidev->func, cap_id);
170                         return;
171                 }
172                 pcidev->caps[cap_id] = cap_off;
173                 cap_off = pcidev_read8(pcidev, cap_off + 1);
174                 /* not sure if subsequent caps must be aligned or not */
175                 if (cap_off & 0x3)
176                         printk("PCI %x:%x:%x had unaligned cap offset 0x%x\n", pcidev->bus,
177                                pcidev->dev, pcidev->func, cap_off);
178         }
179 }
180
181 /* Scans the PCI bus.  Won't actually work for anything other than bus 0, til we
182  * sort out how to handle bridge devices. */
183 void pci_init(void)
184 {
185         uint32_t result = 0;
186         uint16_t dev_id, ven_id;
187         struct pci_device *pcidev;
188         int max_nr_func;
189         for (int i = 0; i < PCI_MAX_BUS - 1; i++) {     /* phantoms at 0xff */
190                 for (int j = 0; j < PCI_MAX_DEV; j++) {
191                         max_nr_func = 1;
192                         for (int k = 0; k < max_nr_func; k++) {
193                                 result = pci_read32(i, j, k, PCI_DEV_VEND_REG);
194                                 dev_id = result >> 16;
195                                 ven_id = result & 0xffff;
196                                 /* Skip invalid IDs (not a device) */
197                                 if (ven_id == INVALID_VENDOR_ID) 
198                                         break;  /* skip functions too, they won't exist */
199                                 pcidev = kzmalloc(sizeof(struct pci_device), 0);
200                                 /* we don't need to lock it til we post the pcidev to the list*/
201                                 spinlock_init_irqsave(&pcidev->lock);
202                                 pcidev->bus = i;
203                                 pcidev->dev = j;
204                                 pcidev->func = k;
205                                 pcidev->dev_id = dev_id;
206                                 pcidev->ven_id = ven_id;
207                                 /* Get the Class/subclass */
208                                 pcidev->class = pcidev_read8(pcidev, PCI_CLASS_REG);
209                                 pcidev->subclass = pcidev_read8(pcidev, PCI_SUBCLASS_REG);
210                                 pcidev->progif = pcidev_read8(pcidev, PCI_PROGIF_REG);
211                                 /* All device types (0, 1, 2) have the IRQ in the same place */
212                                 /* This is the PIC IRQ the device is wired to */
213                                 pcidev->irqline = pcidev_read8(pcidev, PCI_IRQLINE_STD);
214                                 /* This is the interrupt pin the device uses (INTA# - INTD#) */
215                                 pcidev->irqpin = pcidev_read8(pcidev, PCI_IRQPIN_STD);
216                                 /* bottom 7 bits are header type */
217                                 switch (pcidev_read8(pcidev, PCI_HEADER_REG) & 0x7c) {
218                                         case 0x00:
219                                                 pcidev->header_type = STD_PCI_DEV;
220                                                 break;
221                                         case 0x01:
222                                                 pcidev->header_type = PCI2PCI;
223                                                 break;
224                                         case 0x02:
225                                                 pcidev->header_type = PCI2CARDBUS;
226                                                 break;
227                                         default:
228                                                 pcidev->header_type = "Unknown Header Type";
229                                 }
230                                 __pci_handle_bars(pcidev);
231                                 __pci_parse_caps(pcidev);
232                                 /* we're the only writer at this point in the boot process */
233                                 STAILQ_INSERT_TAIL(&pci_devices, pcidev, all_dev);
234                                 #ifdef CONFIG_PCI_VERBOSE
235                                 pcidev_print_info(pcidev, 4);
236                                 #else
237                                 pcidev_print_info(pcidev, 0);
238                                 #endif /* CONFIG_PCI_VERBOSE */
239                                 /* Top bit determines if we have multiple functions on this
240                                  * device.  We can't just check for more functions, since
241                                  * non-multifunction devices exist that respond to different
242                                  * functions with the same underlying device (same bars etc).
243                                  * Note that this style allows for devices that only report
244                                  * multifunction in the first function's header. */
245                                 if (pcidev_read8(pcidev, PCI_HEADER_REG) & 0x80)
246                                         max_nr_func = PCI_MAX_FUNC;
247                         }
248                 }
249         }
250 }
251
252 uint32_t pci_config_addr(uint8_t bus, uint8_t dev, uint8_t func, uint32_t reg)
253 {
254         return (uint32_t)(((uint32_t)bus << 16) |
255                           ((uint32_t)dev << 11) |
256                           ((uint32_t)func << 8) |
257                           (reg & 0xfc) |
258                           ((reg & 0xf00) << 16) |       /* extended PCI CFG space... */
259                                           0x80000000);
260 }
261
262 /* Helper to read 32 bits from the config space of B:D:F.  'Offset' is how far
263  * into the config space we offset before reading, aka: where we are reading. */
264 uint32_t pci_read32(uint8_t bus, uint8_t dev, uint8_t func, uint32_t offset)
265 {
266         uint32_t ret;
267         spin_lock_irqsave(&pci_lock);
268         outl(PCI_CONFIG_ADDR, pci_config_addr(bus, dev, func, offset));
269         ret = inl(PCI_CONFIG_DATA);
270         spin_unlock_irqsave(&pci_lock);
271         return ret;
272 }
273
274 /* Same, but writes (doing 32bit at a time).  Never actually tested (not sure if
275  * PCI lets you write back). */
276 void pci_write32(uint8_t bus, uint8_t dev, uint8_t func, uint32_t offset,
277                  uint32_t value)
278 {
279         spin_lock_irqsave(&pci_lock);
280         outl(PCI_CONFIG_ADDR, pci_config_addr(bus, dev, func, offset));
281         outl(PCI_CONFIG_DATA, value);
282         spin_unlock_irqsave(&pci_lock);
283 }
284
285 uint16_t pci_read16(uint8_t bus, uint8_t dev, uint8_t func, uint32_t offset)
286 {
287         uint16_t ret;
288         spin_lock_irqsave(&pci_lock);
289         outl(PCI_CONFIG_ADDR, pci_config_addr(bus, dev, func, offset));
290         ret = inw(PCI_CONFIG_DATA + (offset & 2));
291         spin_unlock_irqsave(&pci_lock);
292         return ret;
293 }
294
295 void pci_write16(uint8_t bus, uint8_t dev, uint8_t func, uint32_t offset,
296                  uint16_t value)
297 {
298         spin_lock_irqsave(&pci_lock);
299         outl(PCI_CONFIG_ADDR, pci_config_addr(bus, dev, func, offset));
300         outw(PCI_CONFIG_DATA + (offset & 2), value);
301         spin_unlock_irqsave(&pci_lock);
302 }
303
304 uint8_t pci_read8(uint8_t bus, uint8_t dev, uint8_t func, uint32_t offset)
305 {
306         uint8_t ret;
307         spin_lock_irqsave(&pci_lock);
308         outl(PCI_CONFIG_ADDR, pci_config_addr(bus, dev, func, offset));
309         ret = inb(PCI_CONFIG_DATA + (offset & 3));
310         spin_unlock_irqsave(&pci_lock);
311         return ret;
312 }
313
314 void pci_write8(uint8_t bus, uint8_t dev, uint8_t func, uint32_t offset,
315                 uint8_t value)
316 {
317         spin_lock_irqsave(&pci_lock);
318         outl(PCI_CONFIG_ADDR, pci_config_addr(bus, dev, func, offset));
319         outb(PCI_CONFIG_DATA + (offset & 3), value);
320         spin_unlock_irqsave(&pci_lock);
321 }
322
323 uint32_t pcidev_read32(struct pci_device *pcidev, uint32_t offset)
324 {
325         return pci_read32(pcidev->bus, pcidev->dev, pcidev->func, offset);
326 }
327
328 void pcidev_write32(struct pci_device *pcidev, uint32_t offset, uint32_t value)
329 {
330         pci_write32(pcidev->bus, pcidev->dev, pcidev->func, offset, value);
331 }
332
333 uint16_t pcidev_read16(struct pci_device *pcidev, uint32_t offset)
334 {
335         return pci_read16(pcidev->bus, pcidev->dev, pcidev->func, offset);
336 }
337
338 void pcidev_write16(struct pci_device *pcidev, uint32_t offset, uint16_t value)
339 {
340         pci_write16(pcidev->bus, pcidev->dev, pcidev->func, offset, value);
341 }
342
343 uint8_t pcidev_read8(struct pci_device *pcidev, uint32_t offset)
344 {
345         return pci_read8(pcidev->bus, pcidev->dev, pcidev->func, offset);
346 }
347
348 void pcidev_write8(struct pci_device *pcidev, uint32_t offset, uint8_t value)
349 {
350         pci_write8(pcidev->bus, pcidev->dev, pcidev->func, offset, value);
351 }
352
353 /* Helper to get the class description strings.  Adapted from
354  * http://www.pcidatabase.com/reports.php?type=c-header */
355 static void pcidev_get_cldesc(struct pci_device *pcidev, char **class,
356                               char **subclass, char **progif)
357 {
358         int     i ;
359         *class = *subclass = *progif = "";
360
361         for (i = 0; i < PCI_CLASSCODETABLE_LEN; i++) {
362                 if (PciClassCodeTable[i].BaseClass == pcidev->class) {
363                         if (!(**class))
364                                 *class = PciClassCodeTable[i].BaseDesc;
365                         if (PciClassCodeTable[i].SubClass == pcidev->subclass) {
366                                 if (!(**subclass))
367                                         *subclass = PciClassCodeTable[i].SubDesc;
368                                 if (PciClassCodeTable[i].ProgIf == pcidev->progif) {
369                                         *progif = PciClassCodeTable[i].ProgDesc;
370                                         break ;
371                                 }
372                         }
373                 }
374         }
375 }
376
377 /* Helper to get the vendor and device description strings */
378 static void pcidev_get_devdesc(struct pci_device *pcidev, char **vend_short,
379                                char **vend_full, char **chip, char **chip_desc)
380 {
381         int     i ;
382         *vend_short = *vend_full = *chip = *chip_desc = "";
383
384         for (i = 0; i < PCI_VENTABLE_LEN; i++) {
385                 if (PciVenTable[i].VenId == pcidev->ven_id) {
386                         *vend_short = PciVenTable[i].VenShort;
387                         *vend_full = PciVenTable[i].VenFull;
388                         break ;
389                 }
390         }
391         for (i = 0; i < PCI_DEVTABLE_LEN; i++) {
392                 if ((PciDevTable[i].VenId == pcidev->ven_id) &&
393                    (PciDevTable[i].DevId == pcidev->dev_id)) {
394                         *chip = PciDevTable[i].Chip;
395                         *chip_desc = PciDevTable[i].ChipDesc;
396                         break ;
397                 }
398         }
399 }
400
401 /* Prints info (like lspci) for a device */
402 void pcidev_print_info(struct pci_device *pcidev, int verbosity)
403 {
404         char *ven_sht, *ven_fl, *chip, *chip_txt, *class, *subcl, *progif;
405         pcidev_get_cldesc(pcidev, &class, &subcl, &progif);
406         pcidev_get_devdesc(pcidev, &ven_sht, &ven_fl, &chip, &chip_txt);
407
408         printk("%02x:%02x.%x %s: %s %s %s: %s\n",
409                pcidev->bus,
410                pcidev->dev,
411                pcidev->func,
412                subcl,
413                ven_sht,
414                chip,
415                chip_txt,
416                    pcidev->header_type);
417         if (verbosity < 1)      /* whatever */
418                 return;
419         printk("\tIRQ: %02d IRQ pin: 0x%02x\n",
420                pcidev->irqline,
421                pcidev->irqpin);
422         printk("\tVendor Id: 0x%04x Device Id: 0x%04x\n",
423                pcidev->ven_id,
424                pcidev->dev_id);
425         printk("\t%s %s %s\n",
426                class,
427                progif,
428                ven_fl);
429         for (int i = 0; i < pcidev->nr_bars; i++) {
430                 if (pcidev->bar[i].raw_bar == 0)
431                         continue;
432                 printk("\tBAR %d: ", i);
433                 if (pci_is_iobar(pcidev->bar[i].raw_bar)) {
434                         assert(pcidev->bar[i].pio_base);
435                         printk("IO port 0x%04x\n", pcidev->bar[i].pio_base);
436                 } else {
437                         bool bar_is_64 = pci_is_membar64(pcidev->bar[i].raw_bar);
438                         printk("MMIO Base%s %p, MMIO Size %p\n",
439                                bar_is_64 ? "64" : "32",
440                                bar_is_64 ? pcidev->bar[i].mmio_base64 :
441                                            pcidev->bar[i].mmio_base32,
442                                pcidev->bar[i].mmio_sz);
443                         /* Takes up two bars */
444                         if (bar_is_64) {
445                                 assert(!pcidev->bar[i].mmio_base32);    /* double-check */
446                                 i++;
447                         }
448                 }
449         }
450         printk("\tCapabilities:");
451         for (int i = 0; i < PCI_CAP_ID_MAX + 1; i++) {
452                 if (pcidev->caps[i])
453                         printk(" 0x%02x", i);
454         }
455         printk("\n");
456 }
457
458 void pci_set_bus_master(struct pci_device *pcidev)
459 {
460         spin_lock_irqsave(&pcidev->lock);
461         pcidev_write16(pcidev, PCI_CMD_REG, pcidev_read16(pcidev, PCI_CMD_REG) |
462                                             PCI_CMD_BUS_MAS);
463         spin_unlock_irqsave(&pcidev->lock);
464 }
465
466 void pci_clr_bus_master(struct pci_device *pcidev)
467 {
468         uint16_t reg;
469         spin_lock_irqsave(&pcidev->lock);
470         reg = pcidev_read16(pcidev, PCI_CMD_REG);
471         reg &= ~PCI_CMD_BUS_MAS;
472         pcidev_write16(pcidev, PCI_CMD_REG, reg);
473         spin_unlock_irqsave(&pcidev->lock);
474 }
475
476 struct pci_device *pci_match_tbdf(int tbdf)
477 {
478         struct pci_device *search;
479         int bus, dev, func;
480         bus = BUSBNO(tbdf);
481         dev = BUSDNO(tbdf);
482         func = BUSFNO(tbdf);
483
484         STAILQ_FOREACH(search, &pci_devices, all_dev) {
485                 if ((search->bus == bus) &&
486                     (search->dev == dev) &&
487                     (search->func == func))
488                         return search;
489         }
490         return NULL;
491 }
492
493 /* Helper to get the membar value for BAR index bir */
494 uintptr_t pci_get_membar(struct pci_device *pcidev, int bir)
495 {
496         if (bir >= pcidev->nr_bars)
497                 return 0;
498         if (pci_is_iobar(pcidev->bar[bir].raw_bar))
499                 return 0;
500         return (pci_is_membar64(pcidev->bar[bir].raw_bar) ?
501                 pcidev->bar[bir].mmio_base64 :
502                 pcidev->bar[bir].mmio_base32);
503 }