Re: Intel 82801H SATA interrupt issues

Emmanuel Dreyfus <[email protected]>
Newsgroups gmane.os.netbsd.devel.kernel
Message-ID <[email protected]>
On Thu, Sep 05, 2024 at 12:53:00AM +0000, Emmanuel Dreyfus wrote:
> Is there something I am doing obviously wrong? I note the documentation
> says only the BIOS should do this, but how is this different from the 
> BIOS doing it? The controller is not yet in operation.

I got more success: the operation must be done while enumerating PCI
bridge children, before they are configured. I run it from 
pci_enumerate_bus. Patch (which is just a hacking in progress) attached .

I get this:

pci_force_ahci: try 0:31:2
armval = 0x81030000
write back armval = 0x81030040
updated armval = 0x81030040

pci_force_ahci: try 0:31:5
armval = 0x00030000
write back armval = 0x00030040
updated armval = 0x00030000

Then the AHCI controller appears instead of piixide at 0:31:2
(...)
ahcisata0 at pci0 dev 31 function 2: Intel 82801H AHCI SATA Controller w/ 4 ports (rev. 0x02)
autoconfiguration error: ahcisata0: reset failed

Not a full success. Then piixide appears at 0:31:5. Because ahcisata failed?
piixide0 at pci0 dev 31 function 5: Intel 82801H Serial ATA Controller (ICH8) (rev. 0x02)


-- 
Emmanuel Dreyfus
[email protected]
force_ahci.patch (text/x-diff, 3.9 KB)
Index: pci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/pci.c,v
retrieving revision 1.165
diff -U4 -r1.165 pci.c
--- pci.c	24 Aug 2022 11:19:25 -0000	1.165
+++ pci.c	7 Sep 2024 02:31:51 -0000
@@ -260,9 +260,9 @@
 			snprintb(devinfo, sizeof (devinfo),
 			    "\002\001multifn\002singlefn\003skipfunc0"
 			    "\004skipfunc1\005skipfunc2\006skipfunc3"
 			    "\007skipfunc4\010skipfunc5\011skipfunc6"
-			    "\012skipfunc7", qd->quirks);
+			    "\012skipfunc7\013forceahci", qd->quirks);
 			printf(" quirks %s", devinfo);
 		}
 		printf(")");
 	}
@@ -702,8 +702,51 @@
 	}
 	return 0;
 }
 
+static void
+pci_force_ahci(pci_chipset_tag_t pc, pcitag_t tag)
+{
+	int bus, device, function;
+	pci_class_t class;
+	pcireg_t v;
+	const int ich89_address_map_reg = 0x90;
+
+	pci_decompose_tag(pc, tag, &bus, &device, &function);
+	printf("%s: try %d:%d:%d\n", __func__, bus, device, function);
+
+	class = pci_conf_read(pc, tag, PCI_CLASS_REG);
+
+	printf("%s: classreg = 0x%08x, class = 0x%02x, subclass = 0x%02x\n",
+	       __func__, class, PCI_CLASS(class), PCI_SUBCLASS(class));
+
+#if 0
+	if (PCI_CLASS(class) != PCI_CLASS_MASS_STORAGE ||
+	    PCI_SUBCLASS(class) != PCI_SUBCLASS_MASS_STORAGE_IDE)
+		return;
+#endif
+	if (device != 31 || (function != 2 && function != 5))
+		return;
+
+	printf("Force Intel AHCI mode function\n");
+
+	v = pci_conf_read(pc, tag, ich89_address_map_reg);
+	printf("armval = 0x%08x\n", v);
+
+	v |= 0x40;
+	v &= ~0x80;
+
+	printf("write back armval = 0x%08x\n", v);
+
+	pci_conf_write(pc, tag, ich89_address_map_reg, v);
+
+	v = pci_conf_read(pc, tag, ich89_address_map_reg);
+
+	printf("updated armval = 0x%08x\n", v);
+
+	return;
+}
+
 #ifndef PCI_MACHDEP_ENUMERATE_BUS
 /*
  * Generic PCI bus enumeration routine.  Used unless machine-dependent
  * code needs to provide something else.
@@ -815,11 +858,18 @@
 			if (qd != NULL &&
 			    (qd->quirks & PCI_QUIRK_SKIP_FUNC(function)) != 0)
 				continue;
 			tag = pci_make_tag(pc, sc->sc_bus, device, function);
+
+			if (qd != NULL &&
+			    (qd->quirks & PCI_QUIRK_FORCE_AHCI) != 0) {
+				pci_force_ahci(pc, tag);
+			}
+
 			ret = pci_probe_device(sc, tag, match, pap);
 			if (match != NULL && ret != 0)
 				return ret;
+
 		}
 	}
 	return 0;
 }
Index: pci_quirks.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/pci_quirks.c,v
retrieving revision 1.12
diff -U4 -r1.12 pci_quirks.c
--- pci_quirks.c	17 Oct 2018 01:16:50 -0000	1.12
+++ pci_quirks.c	7 Sep 2024 02:31:51 -0000
@@ -52,8 +52,20 @@
 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_XEOND_MEM_0_TTR_1,
 	    PCI_QUIRK_HASEXTCNF },
 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_COREI76K_IMC_0,
 	    PCI_QUIRK_HASEXTCNF },
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801GBM_LPC,
+	    PCI_QUIRK_FORCE_AHCI },
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801HEM_LPC,
+	    PCI_QUIRK_FORCE_AHCI },
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IR_LPC,
+	    PCI_QUIRK_FORCE_AHCI },
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IEM_LPC,
+	    PCI_QUIRK_FORCE_AHCI },
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IM_LPC,
+	    PCI_QUIRK_FORCE_AHCI },
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_LPC,
+	    PCI_QUIRK_FORCE_AHCI },
 };
 
 const struct pci_quirkdata *
 pci_lookup_quirkdata(pci_vendor_id_t vendor, pci_product_id_t product)
Index: pcivar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/pcivar.h,v
retrieving revision 1.117
diff -U4 -r1.117 pcivar.h
--- pcivar.h	27 Feb 2022 14:18:52 -0000	1.117
+++ pcivar.h	7 Sep 2024 02:31:51 -0000
@@ -228,8 +228,9 @@
 #define	PCI_QUIRK_SKIP_FUNC6		PCI_QUIRK_SKIP_FUNC(6)
 #define	PCI_QUIRK_SKIP_FUNC7		PCI_QUIRK_SKIP_FUNC(7)
 #define	PCI_QUIRK_HASEXTCNF		__BIT(10)
 #define	PCI_QUIRK_NOEXTCNF		__BIT(11)
+#define	PCI_QUIRK_FORCE_AHCI		__BIT(12)
 
 struct pci_conf_state {
 	pcireg_t reg[16];
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.