AHCI: Add C600 HBA and fix PCI iteration bugs
authorFergus Simpson <afergs@google.com>
Tue, 18 Oct 2016 00:09:30 +0000 (17:09 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 18 Oct 2016 20:02:14 +0000 (16:02 -0400)
This commit adds the C600 HBA to the list of recognized Intel HBAs so my
machine with one can use it and makes two fixes to the PCI driver.

It also fixed a bug in the PCI driver. When detecting PCI devices it
iterates over all functions on all devices. A device can have up to 8
functions (0-7) and the driver assumes they are sequential, giving up
when one is not found. This should not be done. A device is detected by
whether function 0 is implemented - if it is not no device is connected.
While a device must implement function 0, it does not need to implement
its other functions sequentially. The C600 for example implements 0, 2,
3, so the driver did not detect functions 2 and 3 and the HBA did not
work. The driver has been changed so that it will only give up if
function 0 is not found.

Another issue was fixed with the PCI driver where it would not detect
devices on bus 0xff - the last bus. There was a comment about issues
with bus 0xff but that doesn't seem to be an issue any more so the
driver will now check the last bus.

Change-Id: I8dcac3f27b4983a9141e5700d73a758389cef75a
Signed-off-by: Fergus Simpson <afergs@google.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/pci.c
kern/drivers/dev/sdiahci.c

index 127be3e..9b153a5 100644 (file)
@@ -188,16 +188,25 @@ void pci_init(void)
        uint16_t dev_id, ven_id;
        struct pci_device *pcidev;
        int max_nr_func;
-       for (int i = 0; i < PCI_MAX_BUS - 1; i++) {     /* phantoms at 0xff */
+       /* In earlier days bus address 0xff caused problems so we only iterated to
+        * PCI_MAX_BUS - 1, but this should no longer be an issue.
+        * Old comment: phantoms at 0xff */
+       for (int i = 0; i < PCI_MAX_BUS; i++) {
                for (int j = 0; j < PCI_MAX_DEV; j++) {
                        max_nr_func = 1;
                        for (int k = 0; k < max_nr_func; k++) {
                                result = pci_read32(i, j, k, PCI_DEV_VEND_REG);
                                dev_id = result >> 16;
                                ven_id = result & 0xffff;
-                               /* Skip invalid IDs (not a device) */
-                               if (ven_id == INVALID_VENDOR_ID)
-                                       break;  /* skip functions too, they won't exist */
+                               /* Skip invalid IDs (not a device)
+                                * If the first function doesn't exist then no device is
+                                * connected, but there can be gaps in the other function
+                                * numbers. Eg. 0,2,3 is ok. */
+                               if (ven_id == INVALID_VENDOR_ID) {
+                                       if (k == 0)
+                                               break;
+                                       continue;
+                               }
                                pcidev = kzmalloc(sizeof(struct pci_device), 0);
                                /* we don't need to lock it til we post the pcidev to the list*/
                                spinlock_init_irqsave(&pcidev->lock);
index e48ec01..172b854 100644 (file)
@@ -2111,7 +2111,8 @@ static int didtype(struct pci_device *p)
                    (p->dev_id & 0xfffe) == 0x2922 || /* ich9 */
                    p->dev_id == 0x3a02 ||            /* 82801jd/do */
                    (p->dev_id & 0xfefe) == 0x3a22 || /* ich10, pch */
-                   (p->dev_id & 0xfff8) == 0x3b28)   /* pchm */
+                   (p->dev_id & 0xfff8) == 0x3b28 || /* pchm */
+                   p->dev_id == 0x1d02)              /* c600/x79 pch */
                        return Tich;
                break;
        case Vatiamd: