The following diff is ported from NetBSD (the workaround originated from
OpenSolaris) to workaround the issue of data corruption with the ALI M5229
IDE chipset when using UltraDMA. Same workaround is also used by FreeBSD/Linux.
This chipset is found in some sparc64 systems such as the Blade 100 and
Netra X1.

I don't have any such systems but I went digging for this being curious
why the nasty hack was added to the kernel configs to disable UltraDMA
to workaround this bug and thus penalizing other IDE/SATA controllers
that could be in the same system. If you have one of the mentioned
systems please test this.


Index: dev/pci/pciide.c
===================================================================
RCS file: /home/cvs/src/sys/dev/pci/pciide.c,v
retrieving revision 1.323
diff -u -p -r1.323 pciide.c
--- dev/pci/pciide.c    18 Nov 2010 18:12:52 -0000      1.323
+++ dev/pci/pciide.c    13 Jan 2011 00:22:14 -0000
@@ -212,6 +212,8 @@ void natsemi_irqack(struct channel_softc
 void ns_scx200_chip_map(struct pciide_softc *, struct pci_attach_args *);
 void ns_scx200_setup_channel(struct channel_softc *);
 
+int acer_pcib_match(struct pci_attach_args *);
+void acer_do_reset(struct channel_softc *);
 void acer_chip_map(struct pciide_softc *, struct pci_attach_args *);
 void acer_setup_channel(struct channel_softc *);
 int  acer_pci_intr(void *);
@@ -289,6 +291,11 @@ struct pciide_product_desc {
        void (*chip_map)(struct pciide_softc *, struct pci_attach_args *);
 };
 
+struct pciide_acer_softc {
+       struct pciide_softc pciide_sc;
+       struct pci_attach_args pcib_pa;
+};
+
 /* Flags for ide_flags */
 #define IDE_PCI_CLASS_OVERRIDE 0x0001  /* accept even if class != pciide */
 #define IDE_16BIT_IOSPACE      0x0002  /* I/O space BARS ignore upper word */
@@ -5619,10 +5626,27 @@ ns_scx200_setup_channel(struct channel_s
        pciide_print_modes(cp);
 }
 
+int
+acer_pcib_match(struct pci_attach_args *pa)
+{
+       /*
+        * We need to access the PCI config space of the pcib, see
+        * acer_do_reset().
+        */
+       if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
+           PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA &&
+           PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ALI &&
+           PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ALI_M1533)
+               return (1);
+
+       return (0);
+}
+
 void
 acer_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa)
 {
        struct pciide_channel *cp;
+       struct pciide_acer_softc *acer_sc = (struct pciide_acer_softc *)sc;
        int channel;
        pcireg_t cr, interface;
        bus_size_t cmdsize, ctlsize;
@@ -5684,6 +5708,12 @@ acer_chip_map(struct pciide_softc *sc, s
                    pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_0x4B)
                    | ACER_0x4B_CDETECT);
 
+       if (rev == 0xC3) {
+               /* Install reset bug workaround */
+               if (pci_find_device(&acer_sc->pcib_pa, acer_pcib_match))
+                       sc->sc_wdcdev.reset = acer_do_reset;
+       }
+
        for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
                cp = &sc->pciide_channels[channel];
                if (pciide_chansetup(sc, channel, interface) == 0)
@@ -5713,6 +5743,31 @@ acer_chip_map(struct pciide_softc *sc, s
                }
                acer_setup_channel(&cp->wdc_channel);
        }
+}
+
+void
+acer_do_reset(struct channel_softc *chp)
+{
+       struct pciide_channel *cp = (struct pciide_channel *)chp;
+       struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc;
+       struct pciide_acer_softc *acer_sc = (struct pciide_acer_softc *)sc;
+       u_int8_t reg;
+
+       /*
+        * From OpenSolaris: after a reset we need to disable/enable the
+        * corresponding channel, or data corruption will occur in
+        * UltraDMA modes.
+        */
+
+       wdc_do_reset(chp);
+
+       reg = pciide_pci_read(acer_sc->pcib_pa.pa_pc, acer_sc->pcib_pa.pa_tag,
+           ACER_PCIB_CTRL);
+       pciide_pci_write(acer_sc->pcib_pa.pa_pc, acer_sc->pcib_pa.pa_tag,
+           ACER_PCIB_CTRL, reg & ~ACER_PCIB_CTRL_ENCHAN(chp->channel));
+       delay(1000);
+       pciide_pci_write(acer_sc->pcib_pa.pa_pc, acer_sc->pcib_pa.pa_tag,
+           ACER_PCIB_CTRL, reg);
 }
 
 void
Index: dev/pci/pciide_acer_reg.h
===================================================================
RCS file: /home/cvs/src/sys/dev/pci/pciide_acer_reg.h,v
retrieving revision 1.8
diff -u -p -r1.8 pciide_acer_reg.h
--- dev/pci/pciide_acer_reg.h   23 Jul 2010 07:47:13 -0000      1.8
+++ dev/pci/pciide_acer_reg.h   12 Jan 2011 05:14:26 -0000
@@ -89,6 +89,10 @@
 #define ACER_0x79_REVC2_EN     0x4
 #define ACER_0x79_EN           0x2
 
+/* OpenSolaris: channel enable/disable in the PCI-ISA bridge */
+#define ACER_PCIB_CTRL 0x58
+#define ACER_PCIB_CTRL_ENCHAN(chan) (0x4 << (chan))
+
 /*
  * IDE bus frequency (1 byte)
  * This should be setup by the BIOS - can we rely on this ?
Index: arch/sparc64/conf/GENERIC
===================================================================
RCS file: /home/cvs/src/sys/arch/sparc64/conf/GENERIC,v
retrieving revision 1.261
diff -u -p -r1.261 GENERIC
--- arch/sparc64/conf/GENERIC   12 Dec 2010 14:33:57 -0000      1.261
+++ arch/sparc64/conf/GENERIC   11 Jan 2011 23:41:06 -0000
@@ -381,7 +381,7 @@ stty*               at spif?
 sbpp*          at spif?
 
 pciide*        at pci? flags 0x0000
-wd*    at pciide? flags 0x0a00
+wd*    at pciide? flags 0x0000
 atapiscsi* at pciide?
 scsibus* at atapiscsi?
 
Index: arch/sparc64/conf/RAMDISK
===================================================================
RCS file: /home/cvs/src/sys/arch/sparc64/conf/RAMDISK,v
retrieving revision 1.98
diff -u -p -r1.98 RAMDISK
--- arch/sparc64/conf/RAMDISK   19 Apr 2010 10:44:33 -0000      1.98
+++ arch/sparc64/conf/RAMDISK   11 Jan 2011 23:41:13 -0000
@@ -151,7 +151,7 @@ ti* at sbus?
 gem*   at sbus?
 
 pciide*        at pci? flags 0x0000
-wd*    at pciide? flags 0x0a00
+wd*    at pciide? flags 0x0000
 atapiscsi* at pciide?
 scsibus* at atapiscsi?
 
Index: arch/sparc64/conf/RAMDISKU5
===================================================================
RCS file: /home/cvs/src/sys/arch/sparc64/conf/RAMDISKU5,v
retrieving revision 1.16
diff -u -p -r1.16 RAMDISKU5
--- arch/sparc64/conf/RAMDISKU5 24 Jun 2009 11:38:40 -0000      1.16
+++ arch/sparc64/conf/RAMDISKU5 11 Jan 2011 23:41:30 -0000
@@ -55,7 +55,7 @@ pcons0        at mainbus0             # PROM console
 timer* at mainbus0             # Timer chip (some systems)
 
 pciide*        at pci? flags 0x0000
-wd*    at pciide? flags 0x0a00
+wd*    at pciide? flags 0x0000
 atapiscsi* at pciide?
 scsibus* at atapiscsi?
 

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

Reply via email to