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>