Hello all,

I ran into an issue with AHCI BAR allocation on arm64. The AHCI PCI driver
in sys/dev/ahci/ahci_pci.c assumes that ABAR (AHCI Base Address) register
is located at offset 0x24 (BAR5) in the PCI header. Specification for AHCI
confirms this is indeed the default address of the main BAR. However, if
AHCI uses 64-bit base addresses, then this register consists of two dwords
starting at offset 0x20 - BAR4 and BAR5. This is the case on our arm64
target and possibly other platforms using 64-bit BARs for AHCI.

The following patch adds a check for the extended BAR in ahci_pci_attach()
and sets the 'rid' in bus_alloc_resource_any accordingly. It fixes the
allocation error on our platform.

Please review and test this patch on other platforms. If there are no
issues then it will be committed in a week.

Thanks,
Michal Stanek
From cab60cd7fc5a517df4d8c55da5e87288c41a985a Mon Sep 17 00:00:00 2001
From: Michal Stanek <m...@semihalf.com>
Date: Wed, 7 Jan 2015 18:28:18 +0100
Subject: [PATCH] Add support for 64-bit AHCI BAR.

---
 sys/dev/ahci/ahci_pci.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/sys/dev/ahci/ahci_pci.c b/sys/dev/ahci/ahci_pci.c
index af26951..43723a6 100644
--- a/sys/dev/ahci/ahci_pci.c
+++ b/sys/dev/ahci/ahci_pci.c
@@ -373,6 +373,7 @@ ahci_pci_attach(device_t dev)
 	int	error, i;
 	uint32_t devid = pci_get_devid(dev);
 	uint8_t revid = pci_get_revid(dev);
+	struct pci_map *map;
 
 	i = 0;
 	while (ahci_ids[i].id != 0 &&
@@ -386,12 +387,18 @@ ahci_pci_attach(device_t dev)
 	    pci_get_subvendor(dev) == 0x1043 &&
 	    pci_get_subdevice(dev) == 0x81e4)
 		ctlr->quirks |= AHCI_Q_SATA1_UNIT0;
-	/* if we have a memory BAR(5) we are likely on an AHCI part */
 	ctlr->vendorid = pci_get_vendor(dev);
 	ctlr->deviceid = pci_get_device(dev);
 	ctlr->subvendorid = pci_get_subvendor(dev);
 	ctlr->subdeviceid = pci_get_subdevice(dev);
-	ctlr->r_rid = PCIR_BAR(5);
+
+	/* AHCI Base Address is BAR(5) by default, unless BARs are 64-bit */
+	map = pci_find_bar(dev, PCIR_BAR(4));
+	if (map != NULL &&
+	    ((map->pm_value & PCIM_BAR_MEM_TYPE) == PCIM_BAR_MEM_64))
+		ctlr->r_rid = PCIR_BAR(4);
+	else
+		ctlr->r_rid = PCIR_BAR(5);
 	if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
 	    &ctlr->r_rid, RF_ACTIVE)))
 		return ENXIO;
-- 
2.2.1

_______________________________________________
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscr...@freebsd.org"

Reply via email to