summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgrog <grog@FreeBSD.org>1999-03-28 05:05:12 +0000
committergrog <grog@FreeBSD.org>1999-03-28 05:05:12 +0000
commit2efb84e8c42f3cb8ea74dde5d65a0f11599f5d74 (patch)
tree4142d55039876accd2a0d091e3e794e8df50c455
parent4af7c4543d69efa54070a979c558a5b8a9cae495 (diff)
downloadFreeBSD-src-2efb84e8c42f3cb8ea74dde5d65a0f11599f5d74.zip
FreeBSD-src-2efb84e8c42f3cb8ea74dde5d65a0f11599f5d74.tar.gz
Add support for SiS 5591/5595 chipset.
Contributed-by: "Richard Seaman, Jr." <dick@tar.com> Tested-by: Chris Piazza <cpiazza@home.net> Tugrul Galatali <tugrul@ianai.BlackSun.org> grog This code includes lots of stuff for verbose probing. I'm not 100% sure that the output of the verbose probe is correct, but everything else works fine, and -CURRENT was broken for the 5591 before, so I'm committing it anyway.
-rw-r--r--sys/pci/ide_pci.c227
1 files changed, 224 insertions, 3 deletions
diff --git a/sys/pci/ide_pci.c b/sys/pci/ide_pci.c
index 39c53a5..51de2c1 100644
--- a/sys/pci/ide_pci.c
+++ b/sys/pci/ide_pci.c
@@ -26,7 +26,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ide_pci.c,v 1.27 1999/01/17 05:18:54 bde Exp $
+ * $Id: ide_pci.c,v 1.28 1999/01/17 05:46:25 bde Exp $
*/
#include "pci.h"
@@ -110,6 +110,15 @@ generic_dmainit(struct ide_pci_cookie *cookie,
static void
generic_status(struct ide_pci_cookie *cookie);
+static int
+sis_5591_dmainit(struct ide_pci_cookie *cookie,
+ struct wdparams *wp,
+ int (*wdcmd)(int, void *),
+ void *wdinfo);
+
+static void
+sis_5591_status(struct ide_pci_cookie *cookie);
+
static void
via_571_status(struct ide_pci_cookie *cookie);
@@ -279,7 +288,7 @@ generic_dmainit(struct ide_pci_cookie *cookie,
/* 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;
@@ -1081,7 +1090,214 @@ static struct vendor_fns vs_acer =
acer_status
};
-
+/* SiS 5591 */
+
+static void
+sis_5591_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) ? "disabled\n" : "enabled");
+ if ((DATC & 0x80) == 0)
+ 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 int
+sis_5591_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_5591_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_5591_status(cookie);
+
+ return 1;
+
+ }
+ return 0;
+}
+
+static struct vendor_fns vs_sis_5591 =
+{
+ sis_5591_dmainit,
+ sis_5591_status
+};
/* Generic SFF-8038i code-- all code below here, except for PCI probes,
* more or less conforms to the SFF-8038i spec as extended for PCI.
@@ -1169,6 +1385,8 @@ ide_pci_probe(pcici_t tag, pcidi_t type)
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
@@ -1239,6 +1457,9 @@ ide_pci_attach(pcici_t tag, int unit)
case 0x522910B9: /* Acer Aladdin IV/V (M5229) */
vp = &vs_acer;
break;
+ case 0x55131039: /* SiS 5591 */
+ vp = &vs_sis_5591;
+ break;
default:
/* everybody else */
vp = &vs_generic;
OpenPOWER on IntegriCloud