Subject: kern/18015: pciide accesses to wrong registers on newer SiS chips
To: None <gnats-bugs@gnats.netbsd.org>
From: None <toshii@netbsd.org>
List: netbsd-bugs
Date: 08/22/2002 02:04:58
>Number:         18015
>Category:       kern
>Synopsis:       pciide accesses to wrong registers on newer SiS chips
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Aug 21 10:06:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     IWAMOTO Toshihiro
>Release:        NetBSD 1.6F
>Organization:
	
>Environment:
System: NetBSD pepper.my.domain 1.6F NetBSD 1.6F (PEPPER) #8: Wed Aug 21 23:43:08 JST 2002 root@pepper.my.domain:/usr/src/syssrc/sys/arch/i386/compile/PEPPER i386
Architecture: i386
Machine: i386
pchb0: Silicon Integrated System SiS 745 Host Bridge (rev. 0x01)
wd0 at pciide0 channel 0 drive 0: <ST380021A>
>Description:
	Linux's driver says the register programming is different on SiS735
	and newer.  See
		http://gyver.homeip.net/sis5513/
	or recent linux kernel source code.

	My SiS745 based system has very bad response when there are
	heavy disk accesses, and this fix may solve this problem.
	(I don't know how to reproduce this problem.)

>How-To-Repeat:
	Read the code.
>Fix:
	This patch should do the same thing that the linux one does.
	But this isn't tested much (only UDMA5), and needs some tweaks to
	make it work with older chips.

Index: pciide.c
===================================================================
RCS file: /net/kiku/NetBSD/NetBSD-CVS/syssrc/sys/dev/pci/pciide.c,v
retrieving revision 1.164
diff -u -r1.164 pciide.c
--- pciide.c	2002/08/10 16:33:23	1.164
+++ pciide.c	2002/08/21 14:42:38
@@ -3115,9 +3115,27 @@
 	sc->sc_wdcdev.channels = sc->wdc_chanarray;
 	sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS;
 
+#if 0
 	pciide_pci_write(sc->sc_pc, sc->sc_tag, SIS_MISC,
 	    pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_MISC) |
 	    SIS_MISC_TIM_SEL | SIS_MISC_FIFO_SIZE);
+#else
+	pciide_pci_write(sc->sc_pc, sc->sc_tag, 0x49,
+	    pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_MISC) |
+	    0x01);
+	{
+		pcireg_t reg;
+
+		reg = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_BHLC_REG);
+#if 1 /* DEBUG */
+		printf("%s: latency was %d\n",
+		    sc->sc_wdcdev.sc_dev.dv_xname, PCI_LATTIMER(reg));
+#endif
+		reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
+		reg |= (0x80 << PCI_LATTIMER_SHIFT);
+		pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BHLC_REG, reg);
+	}
+#endif
 
 	for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
 		cp = &sc->pciide_channels[channel];
@@ -3180,9 +3198,15 @@
 
 		if (drvp->drive_flags & DRIVE_UDMA) {
 			/* use Ultra/DMA */
+#if 0
 			drvp->drive_flags &= ~DRIVE_DMA;
-			sis_tim |= sis_udma_tim[drvp->UDMA_mode] << 
+			sis_tim |= sis_udma_tim[0][drvp->UDMA_mode] << 
 			    SIS_TIM_UDMA_TIME_OFF(drive);
+#else
+			drvp->drive_flags &= ~DRIVE_DMA;
+			sis_tim |= sis_udma_tim[1][drvp->UDMA_mode] << 
+			    (8 + 16 * drive);
+#endif
 			sis_tim |= SIS_TIM_UDMA_EN(drive);
 		} else {
 			/*
@@ -3199,10 +3223,18 @@
 				drvp->PIO_mode = 0;
 		}
 		idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
-pio:		sis_tim |= sis_pio_act[drvp->PIO_mode] <<
+pio:
+#if 0
+		sis_tim |= sis_pio_act[drvp->PIO_mode] <<
 		    SIS_TIM_ACT_OFF(drive);
 		sis_tim |= sis_pio_rec[drvp->PIO_mode] <<
 		    SIS_TIM_REC_OFF(drive);
+#else
+		sis_tim |= sis_pio_act[drvp->PIO_mode] <<
+		    (4 + 16 * drive);
+		sis_tim |= sis_pio_rec[drvp->PIO_mode] <<
+		    SIS_TIM_REC_OFF(drive);
+#endif
 	}
 	WDCDEBUG_PRINT(("sis_setup_channel: new timings reg for "
 	    "channel %d 0x%x\n", chp->channel, sis_tim), DEBUG_PROBE);
Index: pciide_sis_reg.h
===================================================================
RCS file: /net/kiku/NetBSD/NetBSD-CVS/syssrc/sys/dev/pci/pciide_sis_reg.h,v
retrieving revision 1.9
diff -u -r1.9 pciide_sis_reg.h
--- pciide_sis_reg.h	2002/04/23 20:41:18	1.9
+++ pciide_sis_reg.h	2002/08/21 13:40:28
@@ -72,5 +72,6 @@
 static const int8_t sis_dma_rec[] __attribute__((__unused__)) =
     {0, 2, 1};
 #endif
-static const int8_t sis_udma_tim[] __attribute__((__unused__)) =
-    {14, 12, 10, 10, 9, 8};
+static const int8_t sis_udma_tim[][6] __attribute__((__unused__)) =
+    {{14, 12, 10, 10, 9, 8},
+     {11,  7,  5,  4, 2, 1}};
>Release-Note:
>Audit-Trail:
>Unformatted: