Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 25 Jan 1999 07:02:08 -0600
From:      "Richard Seaman, Jr." <dick@tar.com>
To:        grog@lemis.com
Cc:        Bruce Evans <bde@zeta.org.au>, lcremean@tidalwave.net, current@FreeBSD.ORG
Subject:   Re: IDE DMA works, I'll be a...
Message-ID:  <19990125070208.C445@tar.com>
In-Reply-To: <199901250608.RAA24912@godzilla.zeta.org.au>; from Bruce Evans on Mon, Jan 25, 1999 at 05:08:19PM %2B1100
References:  <199901250608.RAA24912@godzilla.zeta.org.au>

next in thread | previous in thread | raw e-mail | index | archive | help

--rS8CxjVDS/+yyDmU
Content-Type: text/plain; charset=us-ascii

On Mon, Jan 25, 1999 at 05:08:19PM +1100, Bruce Evans wrote:
> >> Can you find out what chipset is in this guy? There's support for anything
> >> Intel or VIA, Promise UDMA cards, Cyrix MediaGX, and Acer Aladdin IV/V right
> >> now.
> >
> >See kern/9550.  The driver *used* to support my SiS chipset, but it no
> >longer does when both master and slave drive are present since I
> >updated about a week ago.  Possibly the same bug is biting Matt.
> 
> The driver doesn't have any special support for SiS.  It uses generic
> support in some cases, apparently including your case.  Recent fixes
> made it actually initialize DMA on the correct drive, but the
> initialization in generic_dmainit() is buggy (it assumes multi-word
> DMA mode 2 but your IDE timing is apparently incompatible with this).

I also experienced breakage with a SiS chip set.  The following lines of
code in generic_dmainit in ide_pci.c are the problem:

		/* If we're here, then this controller is most likely not set 
		   for UDMA, even if the drive may be. Make the drive wise
		   up. */  

		if(!wdcmd(WDDMA_MDMA2, wdinfo)) 
			printf("generic_dmainit: could not set multiword DMA mode!\n");


You can try the attached patch if you want.  It seems to work here.

-- 
Richard Seamman, Jr.          email: dick@tar.com
5182 N. Maple Lane            phone: 414-367-5450
Chenequa WI 53058             fax:   414-367-5852

--rS8CxjVDS/+yyDmU
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=sisdiff

Index: ide_pci.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/ide_pci.c,v
retrieving revision 1.28
diff -c -r1.28 ide_pci.c
*** ide_pci.c	1999/01/17 05:46:25	1.28
--- ide_pci.c	1999/01/20 18:06:54
***************
*** 110,115 ****
--- 110,124 ----
  static void
  generic_status(struct ide_pci_cookie *cookie);
  
+ static int
+ sis_dmainit(struct	ide_pci_cookie *cookie, 
+ 	struct	wdparams *wp, 
+ 	int	(*wdcmd)(int, void *),
+ 	void	*wdinfo);
+ 
+ static void
+ sis_status(struct ide_pci_cookie *cookie);
+ 
  static void
  via_571_status(struct ide_pci_cookie *cookie);
  
***************
*** 279,285 ****
  		/* If we're here, then this controller is most likely not set 
  		   for UDMA, even if the drive may be. Make the drive wise
  		   up. */  
! 		   
  		if(!wdcmd(WDDMA_MDMA2, wdinfo)) 
  			printf("generic_dmainit: could not set multiword DMA mode!\n");
  		return 1;
--- 288,294 ----
  		/* If we're here, then this controller is most likely not set 
  		   for UDMA, even if the drive may be. Make the drive wise
  		   up. */  
! 
  		if(!wdcmd(WDDMA_MDMA2, wdinfo)) 
  			printf("generic_dmainit: could not set multiword DMA mode!\n");
  		return 1;
***************
*** 303,308 ****
--- 312,527 ----
  	generic_status
  };
  
+ /* SiS 5591 */
+ 
+ static int
+ sis_dmainit(struct ide_pci_cookie *cookie, 
+ 		struct wdparams *wp, 
+ 		int(*wdcmd)(int, void *),
+ 		void *wdinfo)
+ {
+ 	int r;
+ 	unsigned int workword, new, mask;
+ 	int ctlr, unit;
+ 	int iobase_bm;
+ 	pcici_t tag;
+ 	int unitno;
+ 
+ 	unit = cookie->unit;
+ 	ctlr = cookie->ctlr;
+ 	iobase_bm = cookie->iobase_bm;
+ 	tag = cookie->tag;
+ 
+ 	unitno = ctlr * 2 + unit;
+ 
+ 	if (udma_mode(wp) >= 2) {
+ 		workword = pci_conf_read(tag, ctlr * 4 + 0x40);
+ 
+ 		/* These settings are a little arbitrary.  They're taken from my
+ 		 * system, where the BIOS has already set the values, but where 
+ 		 * we don't detect that we're initialized because the
+ 		 * BMISTA_DMA?CAP values aren't set by the BIOS.
+ 		 * 0x8000 turns on UDMA
+ 		 * 0x2000 sets UDMA cycle time to 2 PCI clocks for data out
+ 		 * 0x0300 sets DATC to 3 PCI clocks
+ 		 * 0x0001 sets DRTC to 1 PCI clock
+ 		 */
+ 		if (unit) {
+ 			mask = 0x0000ffff;
+ 			new  = 0xa3010000;
+ 		} else {
+ 			mask = 0xffff0000;
+ 			new  = 0x0000a301;
+ 		}
+ 
+ 		workword &= mask;
+ 		workword |= new;
+ 
+ 		pci_conf_write(tag, ctlr * 4 + 0x40, workword);
+ 
+ 		outb(iobase_bm + BMISTA_PORT,
+ 		     (inb(iobase_bm + BMISTA_PORT) | ((unit == 0) ? BMISTA_DMA0CAP : BMISTA_DMA1CAP)));
+ 
+ 		if (bootverbose)
+ 			printf("SiS 5591 dmainit: %s drive %d setting ultra DMA mode 2\n",
+ 			       unitno < 2 ? "primary" : "secondary", 
+ 			       unitno & 1);
+ 		r = wdcmd(WDDMA_UDMA2, wdinfo);
+ 		if (!r) {
+ 			printf("SiS 5591 dmainit: %s drive %d setting DMA mode failed\n",
+ 			       unitno < 2 ? "primary" : "secondary", 
+ 			       unitno & 1);
+ 			return 0;
+ 		}
+ 
+ 		if (bootverbose)
+ 			sis_status(cookie);
+ 
+ 		return 1;
+ 
+ 	}
+ 
+ 	/* otherwise, try and program it for MW DMA mode 2 */
+ 	else if (mwdma_mode(wp) >= 2 && pio_mode(wp) >= 4) {
+ 		workword = pci_conf_read(tag, ctlr * 4 + 0x40);
+ 
+ 		/* These settings are a little arbitrary.  They're taken from my
+ 		 * system, where the BIOS has already set the values, but where 
+ 		 * we don't detect that we're initialized because the
+ 		 * BMISTA_DMA?CAP values aren't set by the BIOS.
+ 		 * 0x0300 sets DATC to 3 PCI clocks
+ 		 * 0x0001 sets DRTC to 1 PCI clock
+ 		 */
+ 		if (unit) {
+ 			mask = 0x0000ffff;
+ 			new  = 0x03010000;
+ 		} else {
+ 			mask = 0xffff0000;
+ 			new  = 0x00000301;
+ 		}
+ 
+ 		workword &= mask;
+ 		workword |= new;
+ 
+ 		pci_conf_write(tag, ctlr * 4 + 0x40, workword);
+ 
+ 		outb(iobase_bm + BMISTA_PORT,
+ 		     (inb(iobase_bm + BMISTA_PORT) | ((unit == 0) ? BMISTA_DMA0CAP : BMISTA_DMA1CAP)));
+ 
+ 		/* Set multiword DMA mode 2 on drive */
+ 		if (bootverbose)
+ 			printf("SiS 5591 dmainit: %s drive %d setting multiword DMA mode 2\n",
+ 			       unitno < 2 ? "primary" : "secondary", 
+ 			       unitno & 1);
+ 		r = wdcmd(WDDMA_MDMA2, wdinfo);
+ 		if (!r) {
+ 			printf("SiS 5591 dmainit: %s drive %d setting DMA mode failed\n",
+ 			       unitno < 2 ? "primary" : "secondary", 
+ 			       unitno & 1);
+ 			return 0;
+ 		}
+ 
+ 		if (bootverbose)
+ 			sis_status(cookie);
+ 
+ 		return 1;
+ 
+ 	}
+ 	return 0;
+ }
+ 
+ static void
+ sis_status(struct ide_pci_cookie *cookie)
+ {
+ 	int iobase_wd;
+ 	int ctlr, unit;
+ 	int iobase_bm;
+ 	pcici_t tag;
+ 	pcidi_t type;
+ 	u_int word40[5];
+ 	int i, unitno;
+ 	int DRTC, DATC;
+ 	int val;
+ 
+ 	iobase_wd = cookie->iobase_wd;
+ 	unit = cookie->unit;
+ 	ctlr = cookie->ctlr;
+ 	iobase_bm = cookie->iobase_bm;
+ 	tag = cookie->tag;
+ 	type = cookie->type;
+ 
+ 	unitno = ctlr * 2 + unit;
+ 
+ 	for (i=0; i<5; i++) {
+ 		word40[i] = pci_conf_read(tag, i * 4 + 0x40);
+ 	}
+ 
+ 	DRTC = word40[ctlr] >> (16 * unit);
+ 	DATC = word40[ctlr] >> (8 + 16*unit);
+ 
+ 	if (unitno == 0) {
+ 		if ((word40[4] & 0x80000) == 0) {
+ 			val = word40[2] & 0xf;
+ 			if (val == 0)
+ 				val = 12;
+ 			else if (val > 11)
+ 				val++;
+ 			printf ("SiS 5591 status: CRTC %d PCICLK, ", val);
+ 			val = (word40[2] >> 8) & 0x7;
+ 			if (val == 0)
+ 				val = 8 ;
+ 			else if (val > 6)
+ 				val = 12;
+ 			printf ("CATC %d PCICLK, applies to all IDE devices\n", val);
+ 		} else {
+ 			printf ("SiS 5591 status: CRTC and CATC timings are per device, taken from DRTC and DATC\n");
+ 		}
+ 		printf ("SiS 5591 status: burst cycles %s, fast post write control %s\n",
+ 			((word40[2] >> 16) & 0x80) ? "enabled" : "disabled",
+ 			((word40[2] >> 16) & 0x20) ? "enabled" : "disabled");
+ 
+ 	}
+         val = DRTC & 0xf;
+         if (val == 0)
+ 		val = 12;
+ 	else if (val > 11)
+ 		val++;
+ 	printf ("SiS 5591 status: %s drive %d DRTC %d PCICLK,",
+ 		unitno < 2 ? "primary" : "secondary", 
+ 		unitno & 1,
+ 		val);
+         val = DATC & 0x7;
+         if (val == 0)
+ 		val = 8 ;
+ 	else if (val > 6)
+ 		val = 12;
+ 	printf (" DATC %d PCICLK\n", val);
+ 	printf ("SiS 5591 status: %s drive %d Ultra DMA %s",
+ 		unitno < 2 ? "primary" : "secondary", 
+ 		unitno & 1,
+ 		(DATC & 0x80) ? "enabled" : "disabled\n");
+ 	if (DATC & 0x80)
+ 		printf (", %d PCICLK data out\n", ((DATC >> 5) & 0x3) + 1);
+ 	printf ("SiS 5591 status: %s drive %d postwrite %s, prefetch %s prefetch count is %d\n",
+ 		unitno < 2 ? "primary" : "secondary", 
+ 		unitno & 1,
+ 		((word40[2] >> (28 + unitno)) & 1) ? "enabled" : "disabled",
+ 		((word40[2] >> (24 + unitno)) & 1) ? "enabled" : "disabled",
+ 		(word40[3] >> (16 * ctlr)) & 0xffff);
+ 	printf ("SiS 5591 status: %s drive %d has%s been configured for DMA\n",
+ 		unitno < 2 ? "primary" : "secondary", 
+ 		unitno & 1,
+ 		(inb(iobase_bm + BMISTA_PORT) & ((unit == 0) ? BMISTA_DMA0CAP : BMISTA_DMA1CAP)) ?
+ 		" " : " not");
+ }
+ 
+ static struct vendor_fns vs_sis = 
+ { 
+ 	sis_dmainit, 
+ 	sis_status
+ };
+ 
+ 
  /* VIA Technologies "82C571" PCI-IDE controller core */
  
  static void
***************
*** 1169,1174 ****
--- 1388,1395 ----
  			return ("Cyrix 5530 Bus-master IDE controller");
  		if (type == 0x522910b9)
  			return ("Acer Aladdin IV/V (M5229) Bus-master IDE controller");
+ 	        if (type == 0x55131039)
+ 			return ("SiS 5591 Bus-master IDE Controller");
  		if (data & 0x8000)
  			return ("PCI IDE controller (busmaster capable)");
  #ifndef CMD640
***************
*** 1238,1243 ****
--- 1459,1467 ----
  		break;
  	case 0x522910B9: /* Acer Aladdin IV/V (M5229) */
  		vp = &vs_acer;
+ 		break;
+ 	case 0x55131039: /* SiS 5591 */
+ 		vp = &vs_sis;
  		break;
  	default:
  		/* everybody else */

--rS8CxjVDS/+yyDmU--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19990125070208.C445>