NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/53716: PCengines APU2 requires AHCI enabler
The following reply was made to PR kern/53716; it has been noted by GNATS.
From: clare%csel.org@localhost
To: gnats-bugs%NetBSD.org@localhost
Cc: matthew green <mrg%eterna.com.au@localhost>, kern-bug-people%netbsd.org@localhost,
gnats-admin%netbsd.org@localhost, netbsd-bugs%netbsd.org@localhost
Subject: Re: kern/53716: PCengines APU2 requires AHCI enabler
Date: Sun, 11 Nov 2018 20:00:47 +0900
I re-worked the patch as following:
Index: sys/dev/ic/ahcisatavar.h
===================================================================
RCS file: /export/cvsroot/netbsd/src/sys/dev/ic/ahcisatavar.h,v
retrieving revision 1.17
diff -u -r1.17 ahcisatavar.h
--- sys/dev/ic/ahcisatavar.h 24 May 2015 22:30:05 -0000 1.17
+++ sys/dev/ic/ahcisatavar.h 11 Nov 2018 05:30:32 -0000
@@ -60,6 +60,7 @@
#define AHCI_QUIRK_BADPMP __BIT(2) /* broken PMP support, ignore */
#define AHCI_QUIRK_BADPMPRESET __BIT(3) /* broken PMP support for reset */
#define AHCI_QUIRK_SKIP_RESET __BIT(4) /* skip drive reset sequence */
+#define AHCI_PCI_QUIRK_FIXUP __BIT(5) /* interface needs fixup */
uint32_t sc_ahci_cap; /* copy of AHCI_CAP */
int sc_ncmds; /* number of command slots */
Index: sys/dev/pci/ahcisata_pci.c
===================================================================
RCS file: /export/cvsroot/netbsd/src/sys/dev/pci/ahcisata_pci.c,v
retrieving revision 1.38
diff -u -r1.38 ahcisata_pci.c
--- sys/dev/pci/ahcisata_pci.c 13 Oct 2016 17:11:09 -0000 1.38
+++ sys/dev/pci/ahcisata_pci.c 11 Nov 2018 10:57:34 -0000
@@ -194,6 +194,8 @@
AHCI_PCI_QUIRK_FORCE },
{ PCI_VENDOR_ASMEDIA, PCI_PRODUCT_ASMEDIA_ASM1061_12,
AHCI_PCI_QUIRK_FORCE },
+ { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_HUDSON_SATA,
+ AHCI_PCI_QUIRK_FORCE | AHCI_PCI_QUIRK_FIXUP },
};
struct ahci_pci_softc {
@@ -208,7 +210,7 @@
static void ahci_pci_attach(device_t, device_t, void *);
static int ahci_pci_detach(device_t, int);
static bool ahci_pci_resume(device_t, const pmf_qual_t *);
-
+static void ahci_pci_fixup_interface(device_t);
CFATTACH_DECL_NEW(ahcisata_pci, sizeof(struct ahci_pci_softc),
ahci_pci_match, ahci_pci_attach, ahci_pci_detach, NULL);
@@ -273,7 +275,17 @@
pci_intr_handle_t intrhandle;
char intrbuf[PCI_INTRSTR_LEN];
+ pci_aprint_devinfo(pa, "AHCI disk controller");
+
sc->sc_atac.atac_dev = self;
+ sc->sc_ahci_quirks = ahci_pci_has_quirk(PCI_VENDOR(pa->pa_id),
+ PCI_PRODUCT(pa->pa_id));
+
+ psc->sc_pc = pa->pa_pc;
+ psc->sc_pcitag = pa->pa_tag;
+
+ if (sc->sc_ahci_quirks & AHCI_PCI_QUIRK_FIXUP)
+ ahci_pci_fixup_interface(self);
if (pci_mapreg_map(pa, AHCI_PCI_ABAR,
PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
@@ -281,11 +293,7 @@
aprint_error_dev(self, "can't map ahci registers\n");
return;
}
- psc->sc_pc = pa->pa_pc;
- psc->sc_pcitag = pa->pa_tag;
- pci_aprint_devinfo(pa, "AHCI disk controller");
-
if (pci_intr_map(pa, &intrhandle) != 0) {
aprint_error_dev(self, "couldn't map interrupt\n");
return;
@@ -302,8 +310,6 @@
sc->sc_dmat = pa->pa_dmat;
- sc->sc_ahci_quirks = ahci_pci_has_quirk(PCI_VENDOR(pa->pa_id),
- PCI_PRODUCT(pa->pa_id));
ahci_cap_64bit = (AHCI_READ(sc, AHCI_CAP) & AHCI_CAP_64BIT) != 0;
ahci_bad_64bit = ((sc->sc_ahci_quirks & AHCI_PCI_QUIRK_BAD64) != 0);
@@ -364,3 +370,58 @@
return true;
}
+
+/*
+ * Switch devices in legacy IDE interface to native AHCI, if desired.
+ *
+ * In some devices, especially in PCengines APU2 series, the BIOS left
+ * AHCI devices in IDE/legacy mode to simplify their code and some
+ * unknown compatibility reasons. Since we have no PCI-IDE DMA
+ * handler for the AMD Hudson SATA IDE controller, we should re-program
+ * interfacing mode and use it in native AHCI.
+ *
+ * see ftp://kolibrios.org/users/art_zh/doc/public/A50_RPR.pdf
+ * for register programming details.
+ */
+static void
+ahci_pci_fixup_interface(device_t dv)
+{
+ struct ahci_pci_softc *psc = device_private(dv);
+ int cc;
+ int reg;
+
+ /*
+ * check the interface mode in IDE/legacy
+ */
+ cc = pci_conf_read(psc->sc_pc, psc->sc_pcitag, 0x08);
+ if (!(PCI_CLASS(cc) == PCI_CLASS_MASS_STORAGE &&
+ PCI_SUBCLASS(cc) == PCI_SUBCLASS_MASS_STORAGE_IDE))
+ return;
+
+ aprint_normal_dev(dv, "switch legacy IDE to native AHCI\n");
+
+ /*
+ * make subclass/interface register is writeable.
+ */
+ reg = pci_conf_read(psc->sc_pc, psc->sc_pcitag, 0x40);
+ reg |= 1;
+ pci_conf_write(psc->sc_pc, psc->sc_pcitag, 0x40, reg);
+
+ /*
+ * rewrite subclass/interface register.
+ * this causes switch interface logic.
+ */
+ reg = pci_conf_read(psc->sc_pc, psc->sc_pcitag, PCI_CLASS_REG);
+ reg &= ~PCI_SUBCLASS(PCI_SUBCLASS_MASK);
+ reg |= PCI_SUBCLASS(PCI_SUBCLASS_MASS_STORAGE_SATA);
+ reg &= ~PCI_INTERFACE(PCI_INTERFACE_MASK);
+ reg |= PCI_INTERFACE(PCI_INTERFACE_SATA_AHCI);
+ pci_conf_write(psc->sc_pc, psc->sc_pcitag, PCI_CLASS_REG, reg);
+
+ /*
+ * make subclass/interface register is read-only.
+ */
+ reg = pci_conf_read(psc->sc_pc, psc->sc_pcitag, 0x40);
+ reg &= ~1;
+ pci_conf_write(psc->sc_pc, psc->sc_pcitag, 0x40, reg);
+}
--
Shinichi Doyashiki <clare%csel.org@localhost>
Home |
Main Index |
Thread Index |
Old Index