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.