tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Intel 82801H SATA interrupt issues



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
manu%netbsd.org@localhost
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];
 


Home | Main Index | Thread Index | Old Index