Subject: kern/16897: HPT374 support for pciide driver
To: None <gnats-bugs@gnats.netbsd.org>
From: None <mrezny@umr.edu>
List: netbsd-bugs
Date: 05/19/2002 06:50:45
>Number:         16897
>Category:       kern
>Synopsis:       pciide does not support HPT374
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun May 19 04:54:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Matthew Rezny
>Release:        NetBSD 1.5.2
>Organization:
n/a
	
>Environment:
	
System: NetBSD terabyte 1.5.3_RC2 NetBSD 1.5.3_RC2 (CUSTOM) #5: Sun May 19 06:16:47 CDT 2002 root@terabyte:/usr/src/sys/arch/i386/compile/CUSTOM i386


>Description:
	The Highpoint 374 chip is not suported by the pciide driver.
	
>How-To-Repeat:
	Install a card using that chip. i.e. RocketRAID 404
	
>Fix:
	I added support for it based on the FreeBSD and Linux drivers
	for this card. Included is the patch. The patch was made against
	the source tree version 1.5.3_RC2 (obtained via CVSUP) with
	the BigDrive (LBA48 support) patch added. The code layout might
	need some tweaking to fit the standards for kernel code. It
	is working for me using 160GB Maxtor drives in ATA133 mode.
	Someone else should probably test it if they have the hardware.

===================================================================
--- pciide_hpt_reg.h.orig	Mon May  6 05:23:08 2002
+++ pciide_hpt_reg.h	Sun May 19 06:19:09 2002
@@ -47,6 +47,7 @@
 #define HPT366_REV 0x01
 #define HPT370_REV 0x03
 #define HPT370A_REV 0x04
+#define HPT374_REV 0x07
 
 #define HPT_IDETIM(chan, drive) (0x40 + ((drive) * 4) + ((chan) * 8))
 #define HPT_IDETIM_BUFEN		0x80000000
@@ -128,3 +129,23 @@
 static u_int32_t hpt370_udma[] = 
 	{0x16514e31, 0x164d4e31, 0x16494e31, 0x166d4e31, 0x16454e31,
 	 0x1a85f442};
+
+/* faster timing, used by freebsd, included unused in linux driver */
+static u_int32_t hpt374_pio[] =
+	{0x0ac1f48a, 0x0ac1f465, 0x0a81f454, 0x0a81f443, 0x0a81f442};
+static u_int32_t hpt374_dma[] =
+	{0x228082ea, 0x22808254, 0x22808242};
+static u_int32_t hpt374_udma[] =
+	{0x121882ea, 0x12148254, 0x120c8242, 0x128c8242, 0x12ac8242,
+	 0x12848242, 0x12808242};
+
+/* alternate timing, slower but is what linux driver uses */
+//static u_int32_t hpt374_pio[] = 
+//	{0x06814ea7, 0x06814e93, 0x06414e53, 0x06414e42, 0x06414e31};
+//static u_int32_t hpt374_dma[] =
+//	{0x22406c97, 0x22406c33, 0x22406c31};
+//static u_int32_t hpt374_udma[] =
+//	{0x121882ea, 0x12148254, 0x120c8242, 0x128c8242, 0x12ac8242,
+//	 0x12848242, 0x12808242};
+
+
===================================================================
--- pciide.c.orig	Mon May  6 05:23:07 2002
+++ pciide.c	Sun May 19 06:19:03 2002
@@ -448,6 +448,11 @@
 	  NULL,
 	  hpt_chip_map,
 	},
+	{ PCI_PRODUCT_TRIONES_HPT374,
+	  IDE_PCI_CLASS_OVERRIDE,
+	  NULL,
+	  hpt_chip_map
+	},
 	{ 0,
 	  0,
 	  NULL,
@@ -3066,6 +3071,8 @@
 		printf("HPT370A IDE Controller\n");
 	else if (revision == HPT366_REV)
 		printf("HPT366 IDE Controller\n");
+	else if (revision == HPT374_REV)
+		printf("HPT374 IDE Controller\n");
 	else
 		printf("unknown HPT IDE controller rev %d\n", revision);
 
@@ -3078,7 +3085,7 @@
 	} else {
 		interface = PCIIDE_INTERFACE_BUS_MASTER_DMA |
 		    PCIIDE_INTERFACE_PCI(0);
-		if (revision == HPT370_REV || revision == HPT370A_REV)
+		if (revision == HPT370_REV || revision == HPT370A_REV || revision == HPT374_REV)
 			interface |= PCIIDE_INTERFACE_PCI(1);
 	}
 
@@ -3119,6 +3126,8 @@
 		sc->sc_wdcdev.nchannels = 2;
 		sc->sc_wdcdev.UDMA_cap = 5;
 	}
+	if (revision == HPT374_REV)
+		sc->sc_wdcdev.UDMA_cap = 6;
 	for (i = 0; i < sc->sc_wdcdev.nchannels; i++) {
 		cp = &sc->pciide_channels[i];
 		if (sc->sc_wdcdev.nchannels > 1) {
@@ -3146,14 +3155,29 @@
 		wdcattach(&cp->wdc_channel);
 		hpt_setup_channel(&cp->wdc_channel);
 	}
-	if (revision == HPT370_REV || revision == HPT370A_REV) {
+	if (revision == HPT370_REV || revision == HPT370A_REV || revision == HPT374_REV) {
+		/* disable interrupt prediction, use optional, slower  */
+//		pciide_pci_write(sc->sc_pc, sc->sc_tag, HPT370_CTRL2(0),
+//		    pciide_pci_read(sc->sc_pc, sc->sc_tag, HPT370_CTRL2(0)) &
+//		    ~HPT370_CTRL2_FASTIRQ & ~HPT370_CTRL2_HIRQ);
+//		pciide_pci_write(sc->sc_pc, sc->sc_tag, HPT370_CTRL2(1),
+//		    pciide_pci_read(sc->sc_pc, sc->sc_tag, HPT370_CTRL2(1)) &
+//		    ~HPT370_CTRL2_FASTIRQ & ~HPT370_CTRL2_HIRQ);
 		/*
-		 * HPT370_REV has a bit to disable interrupts, make sure
-		 * to clear it
+		 * HPT370_REV+ has a bit to disable interrupts, make sure
+		 * to clear it (enable interrupts)
 		 */
 		pciide_pci_write(sc->sc_pc, sc->sc_tag, HPT_CSEL,
 		    pciide_pci_read(sc->sc_pc, sc->sc_tag, HPT_CSEL) &
 		    ~HPT_CSEL_IRQDIS);
+
+		/* set clocks, etc (mandatory on 374, optional otherwise) */
+		if (revision == HPT374_REV)	
+			pciide_pci_write(sc->sc_pc, sc->sc_tag, 0x5b,
+			    (pciide_pci_read(sc->sc_pc, sc->sc_tag, 0x5b) &
+			    0x01) | 0x20);
+		else
+			pciide_pci_write(sc->sc_pc, sc->sc_tag, 0x5b, 0x22);
 	}
 	return;
 }
@@ -3194,7 +3218,9 @@
 			    drvp->UDMA_mode > 2)
 				drvp->UDMA_mode = 2;
                         after = (sc->sc_wdcdev.nchannels == 2) ?
-			    hpt370_udma[drvp->UDMA_mode] :
+			    ( (sc->sc_wdcdev.UDMA_cap == 6) ?
+			    hpt374_udma[drvp->UDMA_mode] :
+			    hpt370_udma[drvp->UDMA_mode]) :
 			    hpt366_udma[drvp->UDMA_mode];
                         idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
                 } else if (drvp->drive_flags & DRIVE_DMA) {
@@ -3208,13 +3234,17 @@
                                 drvp->DMA_mode = drvp->PIO_mode - 2;
                         }
                         after = (sc->sc_wdcdev.nchannels == 2) ?
-			    hpt370_dma[drvp->DMA_mode] :
+			    ( (sc->sc_wdcdev.UDMA_cap == 6) ?
+			    hpt374_dma[drvp->DMA_mode] :
+			    hpt370_dma[drvp->DMA_mode]) :
 			    hpt366_dma[drvp->DMA_mode];
                         idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
                 } else {
 			/* PIO only */
                 	after = (sc->sc_wdcdev.nchannels == 2) ?
-			    hpt370_pio[drvp->PIO_mode] :
+			    ( (sc->sc_wdcdev.UDMA_cap == 6) ?
+			    hpt374_pio[drvp->PIO_mode] :
+			    hpt370_pio[drvp->PIO_mode]) :
 			    hpt366_pio[drvp->PIO_mode];
 		}
 		pci_conf_write(sc->sc_pc, sc->sc_tag,
	
>Release-Note:
>Audit-Trail:
>Unformatted: