Any successful installs on a Broadcom HT1000 chipset?

Søren Schmidt sos at deepcore.dk
Fri Dec 7 08:46:43 PST 2007


Hi All!

I've made my first rounds on the Tyan HW that Travis Mikalson at 
TerraNovaNet has kindly donated to work on.

One thing I found out was that it doesn't handle the LBA48 case 
correctly, that is accesses above ~137G gets wrapped around which breaks 
all kinds of things. Now this is strange as that works just fine on my 
old SuperMicro board, but not on the Tyan.
I've yet to find out if its diffs in the HW (doesn't look like at as its 
the same HW revision), or if its differences in how the chipset is setup 
from the BIOS.
The sparse docs I have on the chipset doesn't suggest anything to that 
effect though.

Anyhow, enough ramblings, the attached patch makes 48bit access work on 
the Tyan, so that problem should be fixored, can you all please test 
that and let me know how it goes, thanks!

Patch is against RELENG_7, but should fit on RELENG_6 and -current as well.

-Søren
-------------- next part --------------
? ff
? swks-p1
Index: ata-all.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-all.h,v
retrieving revision 1.124.2.1
diff -u -r1.124.2.1 ata-all.h
--- ata-all.h	21 Nov 2007 21:15:00 -0000	1.124.2.1
+++ ata-all.h	7 Dec 2007 15:12:09 -0000
@@ -464,6 +464,8 @@
     int (*begin_transaction)(struct ata_request *request);
     int (*end_transaction)(struct ata_request *request);
     int (*command)(struct ata_request *request);
+    void (*tf_read)(struct ata_request *request);
+    void (*tf_write)(struct ata_request *request);
 };
 
 /* structure holding resources for an ATA channel */
Index: ata-chipset.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-chipset.c,v
retrieving revision 1.202.2.3
diff -u -r1.202.2.3 ata-chipset.c
--- ata-chipset.c	21 Nov 2007 21:15:00 -0000	1.202.2.3
+++ ata-chipset.c	7 Dec 2007 15:12:09 -0000
@@ -98,7 +98,7 @@
 static void ata_intel_new_setmode(device_t dev, int mode);
 static int ata_intel_31244_allocate(device_t dev);
 static int ata_intel_31244_status(device_t dev);
-static int ata_intel_31244_command(struct ata_request *request);
+static void ata_intel_31244_tf_write(struct ata_request *request);
 static void ata_intel_31244_reset(device_t dev);
 static int ata_ite_chipinit(device_t dev);
 static void ata_ite_setmode(device_t dev, int mode);
@@ -151,6 +151,8 @@
 static void ata_promise_next_hpkt(struct ata_pci_controller *ctlr);
 static int ata_serverworks_chipinit(device_t dev);
 static int ata_serverworks_allocate(device_t dev);
+static void ata_serverworks_tf_read(struct ata_request *request);
+static void ata_serverworks_tf_write(struct ata_request *request);
 static void ata_serverworks_setmode(device_t dev, int mode);
 static int ata_sii_chipinit(device_t dev);
 static int ata_cmd_allocate(device_t dev);
@@ -2044,7 +2046,7 @@
     ch->flags |= ATA_NO_SLAVE;
     ata_pci_hw(dev);
     ch->hw.status = ata_intel_31244_status;
-    ch->hw.command = ata_intel_31244_command;
+    ch->hw.tf_write = ata_intel_31244_tf_write;
 
     /* enable PHY state change interrupt */
     ATA_OUTL(ctlr->r_res2, 0x4,
@@ -2062,32 +2064,55 @@
     return ata_pci_status(dev);
 }
 
-static int
-ata_intel_31244_command(struct ata_request *request)
+static void
+ata_intel_31244_tf_write(struct ata_request *request)
 {
     struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
     struct ata_device *atadev = device_get_softc(request->dev);
-    u_int64_t lba;
-
-    if (!(atadev->flags & ATA_D_48BIT_ACTIVE))
-	    return (ata_generic_command(request));
-
-    lba = request->u.ata.lba;
-    ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | atadev->unit);
-    /* enable interrupt */
-    ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT);
-    ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
-    ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);
-    ATA_IDX_OUTW(ch, ATA_SECTOR, ((lba >> 16) & 0xff00) | (lba & 0x00ff));
-    ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((lba >> 24) & 0xff00) |
-				  ((lba >> 8) & 0x00ff));
-    ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((lba >> 32) & 0xff00) | 
-				  ((lba >> 16) & 0x00ff));
-
-    /* issue command to controller */
-    ATA_IDX_OUTB(ch, ATA_COMMAND, request->u.ata.command);
 
-    return 0;
+    if (atadev->flags & ATA_D_48BIT_ACTIVE) {
+	ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
+	ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);
+	ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) |
+				      (request->u.ata.lba & 0x00ff));
+	ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((request->u.ata.lba >> 24) & 0xff00) |
+				       ((request->u.ata.lba >> 8) & 0x00ff));
+	ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) | 
+				       ((request->u.ata.lba >> 16) & 0x00ff));
+	ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | atadev->unit);
+    }
+    else {
+	ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
+	ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count);
+	if (atadev->flags & ATA_D_USE_CHS) {
+	    int heads, sectors;
+    
+	    if (atadev->param.atavalid & ATA_FLAG_54_58) {
+		heads = atadev->param.current_heads;
+		sectors = atadev->param.current_sectors;
+	    }
+	    else {
+		heads = atadev->param.heads;
+		sectors = atadev->param.sectors;
+	    }
+	    ATA_IDX_OUTB(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1);
+	    ATA_IDX_OUTB(ch, ATA_CYL_LSB,
+			 (request->u.ata.lba / (sectors * heads)));
+	    ATA_IDX_OUTB(ch, ATA_CYL_MSB,
+			 (request->u.ata.lba / (sectors * heads)) >> 8);
+	    ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit | 
+			 (((request->u.ata.lba% (sectors * heads)) /
+			   sectors) & 0xf));
+	}
+	else {
+	    ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba);
+	    ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
+	    ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
+	    ATA_IDX_OUTB(ch, ATA_DRIVE,
+			 ATA_D_IBM | ATA_D_LBA | atadev->unit |
+			 ((request->u.ata.lba >> 24) & 0x0f));
+	}
+    }
 }
 
 static void
@@ -4199,10 +4224,92 @@
 
     ch->flags |= ATA_NO_SLAVE;
     ata_pci_hw(dev);
+    ch->hw.tf_read = ata_serverworks_tf_read;
+    ch->hw.tf_write = ata_serverworks_tf_write;
     return 0;
 }
 
 static void
+ata_serverworks_tf_read(struct ata_request *request)
+{
+    struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+    struct ata_device *atadev = device_get_softc(request->dev);
+
+    if (atadev->flags & ATA_D_48BIT_ACTIVE) {
+	u_int16_t temp;
+
+	request->u.ata.count = ATA_IDX_INW(ch, ATA_COUNT);
+	temp = ATA_IDX_INW(ch, ATA_SECTOR);
+	request->u.ata.lba = (u_int64_t)(temp & 0x00ff) |
+			     ((u_int64_t)(temp & 0xff00) << 24);
+	temp = ATA_IDX_INW(ch, ATA_CYL_LSB);
+	request->u.ata.lba |= ((u_int64_t)(temp & 0x00ff) << 8) |
+			      ((u_int64_t)(temp & 0xff00) << 32);
+	temp = ATA_IDX_INW(ch, ATA_CYL_MSB);
+	request->u.ata.lba |= ((u_int64_t)(temp & 0x00ff) << 16) |
+			      ((u_int64_t)(temp & 0xff00) << 40);
+    }
+    else {
+	request->u.ata.count = ATA_IDX_INW(ch, ATA_COUNT) & 0x00ff;
+	request->u.ata.lba = (ATA_IDX_INW(ch, ATA_SECTOR) & 0x00ff) |
+			     ((ATA_IDX_INW(ch, ATA_CYL_LSB) & 0x00ff) << 8) |
+			     ((ATA_IDX_INW(ch, ATA_CYL_MSB) & 0x00ff) << 16) |
+			     ((ATA_IDX_INW(ch, ATA_DRIVE) & 0xf) << 24);
+    }
+}
+
+static void
+ata_serverworks_tf_write(struct ata_request *request)
+{
+    struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+    struct ata_device *atadev = device_get_softc(request->dev);
+
+    if (atadev->flags & ATA_D_48BIT_ACTIVE) {
+	ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
+	ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);
+	ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) |
+				      (request->u.ata.lba & 0x00ff));
+	ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((request->u.ata.lba >> 24) & 0xff00) |
+				       ((request->u.ata.lba >> 8) & 0x00ff));
+	ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) | 
+				       ((request->u.ata.lba >> 16) & 0x00ff));
+	ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | atadev->unit);
+    }
+    else {
+	ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
+	ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);
+	if (atadev->flags & ATA_D_USE_CHS) {
+	    int heads, sectors;
+    
+	    if (atadev->param.atavalid & ATA_FLAG_54_58) {
+		heads = atadev->param.current_heads;
+		sectors = atadev->param.current_sectors;
+	    }
+	    else {
+		heads = atadev->param.heads;
+		sectors = atadev->param.sectors;
+	    }
+	    ATA_IDX_OUTW(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1);
+	    ATA_IDX_OUTW(ch, ATA_CYL_LSB,
+			 (request->u.ata.lba / (sectors * heads)));
+	    ATA_IDX_OUTW(ch, ATA_CYL_MSB,
+			 (request->u.ata.lba / (sectors * heads)) >> 8);
+	    ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit | 
+			 (((request->u.ata.lba% (sectors * heads)) /
+			   sectors) & 0xf));
+	}
+	else {
+	    ATA_IDX_OUTW(ch, ATA_SECTOR, request->u.ata.lba);
+	    ATA_IDX_OUTW(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
+	    ATA_IDX_OUTW(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
+	    ATA_IDX_OUTW(ch, ATA_DRIVE,
+			 ATA_D_IBM | ATA_D_LBA | atadev->unit |
+			 ((request->u.ata.lba >> 24) & 0x0f));
+	}
+    }
+}
+
+static void
 ata_serverworks_setmode(device_t dev, int mode)
 {
     device_t gparent = GRANDPARENT(dev);
Index: ata-lowlevel.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-lowlevel.c,v
retrieving revision 1.79
diff -u -r1.79 ata-lowlevel.c
--- ata-lowlevel.c	6 Apr 2007 16:18:59 -0000	1.79
+++ ata-lowlevel.c	7 Dec 2007 15:12:09 -0000
@@ -50,6 +50,8 @@
 static int ata_wait(struct ata_channel *ch, struct ata_device *, u_int8_t);
 static void ata_pio_read(struct ata_request *, int);
 static void ata_pio_write(struct ata_request *, int);
+static void ata_tf_read(struct ata_request *);
+static void ata_tf_write(struct ata_request *);
 
 /*
  * low level ATA functions 
@@ -63,6 +65,8 @@
     ch->hw.end_transaction = ata_end_transaction;
     ch->hw.status = ata_generic_status;
     ch->hw.command = ata_generic_command;
+    ch->hw.tf_read = ata_tf_read;
+    ch->hw.tf_write = ata_tf_write;
 }
 
 /* must be called with ATA channel locked and state_mtx held */
@@ -244,28 +248,7 @@
 
 	/* on control commands read back registers to the request struct */
 	if (request->flags & ATA_R_CONTROL) {
-	    if (atadev->flags & ATA_D_48BIT_ACTIVE) {
-		ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT | ATA_A_HOB);
-		request->u.ata.count = (ATA_IDX_INB(ch, ATA_COUNT) << 8);
-		request->u.ata.lba =
-		    ((u_int64_t)(ATA_IDX_INB(ch, ATA_SECTOR)) << 24) |
-		    ((u_int64_t)(ATA_IDX_INB(ch, ATA_CYL_LSB)) << 32) |
-		    ((u_int64_t)(ATA_IDX_INB(ch, ATA_CYL_MSB)) << 40);
-
-		ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT);
-		request->u.ata.count |= ATA_IDX_INB(ch, ATA_COUNT);
-		request->u.ata.lba |= 
-		    (ATA_IDX_INB(ch, ATA_SECTOR) |
-		     (ATA_IDX_INB(ch, ATA_CYL_LSB) << 8) |
-		     (ATA_IDX_INB(ch, ATA_CYL_MSB) << 16));
-	    }
-	    else {
-		request->u.ata.count = ATA_IDX_INB(ch, ATA_COUNT);
-		request->u.ata.lba = ATA_IDX_INB(ch, ATA_SECTOR) |
-				     (ATA_IDX_INB(ch, ATA_CYL_LSB) << 8) |
-				     (ATA_IDX_INB(ch, ATA_CYL_MSB) << 16) |
-				     ((ATA_IDX_INB(ch, ATA_DRIVE) & 0xf) << 24);
-	    }
+	    ch->hw.tf_read(request);
 	}
 
 	/* if we got an error we are done with the HW */
@@ -734,57 +717,96 @@
 			   ATA_PROTO_ATAPI_12 ? 6 : 8);
     }
     else {
-	if (atadev->flags & ATA_D_48BIT_ACTIVE) {
-	    ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature >> 8);
-	    ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
-	    ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count >> 8);
-	    ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count);
-	    ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba >> 24);
-	    ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba);
-	    ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 32);
-	    ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
-	    ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 40);
-	    ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
-	    ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_LBA | atadev->unit);
-	}
-	else {
-	    ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
-	    ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count);
-	    if (atadev->flags & ATA_D_USE_CHS) {
-		int heads, sectors;
+	ch->hw.tf_write(request);
+
+	/* issue command to controller */
+	ATA_IDX_OUTB(ch, ATA_COMMAND, request->u.ata.command);
+    }
+    return 0;
+}
+
+static void
+ata_tf_read(struct ata_request *request)
+{
+    struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+    struct ata_device *atadev = device_get_softc(request->dev);
+
+    if (atadev->flags & ATA_D_48BIT_ACTIVE) {
+	ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT | ATA_A_HOB);
+	request->u.ata.count = (ATA_IDX_INB(ch, ATA_COUNT) << 8);
+	request->u.ata.lba =
+	    ((u_int64_t)(ATA_IDX_INB(ch, ATA_SECTOR)) << 24) |
+	    ((u_int64_t)(ATA_IDX_INB(ch, ATA_CYL_LSB)) << 32) |
+	    ((u_int64_t)(ATA_IDX_INB(ch, ATA_CYL_MSB)) << 40);
+
+	ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT);
+	request->u.ata.count |= ATA_IDX_INB(ch, ATA_COUNT);
+	request->u.ata.lba |= 
+	    (ATA_IDX_INB(ch, ATA_SECTOR) |
+	     (ATA_IDX_INB(ch, ATA_CYL_LSB) << 8) |
+	     (ATA_IDX_INB(ch, ATA_CYL_MSB) << 16));
+    }
+    else {
+	request->u.ata.count = ATA_IDX_INB(ch, ATA_COUNT);
+	request->u.ata.lba = ATA_IDX_INB(ch, ATA_SECTOR) |
+			     (ATA_IDX_INB(ch, ATA_CYL_LSB) << 8) |
+			     (ATA_IDX_INB(ch, ATA_CYL_MSB) << 16) |
+			     ((ATA_IDX_INB(ch, ATA_DRIVE) & 0xf) << 24);
+    }
+}
+
+static void
+ata_tf_write(struct ata_request *request)
+{
+    struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
+    struct ata_device *atadev = device_get_softc(request->dev);
+
+    if (atadev->flags & ATA_D_48BIT_ACTIVE) {
+	ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature >> 8);
+	ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
+	ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count >> 8);
+	ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count);
+	ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba >> 24);
+	ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba);
+	ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 32);
+	ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
+	ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 40);
+	ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
+	ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_LBA | atadev->unit);
+    }
+    else {
+	ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
+	ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count);
+	if (atadev->flags & ATA_D_USE_CHS) {
+	    int heads, sectors;
     
-		if (atadev->param.atavalid & ATA_FLAG_54_58) {
-		    heads = atadev->param.current_heads;
-		    sectors = atadev->param.current_sectors;
-		}
-		else {
-		    heads = atadev->param.heads;
-		    sectors = atadev->param.sectors;
-		}
-		ATA_IDX_OUTB(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1);
-		ATA_IDX_OUTB(ch, ATA_CYL_LSB,
-			     (request->u.ata.lba / (sectors * heads)));
-		ATA_IDX_OUTB(ch, ATA_CYL_MSB,
-			     (request->u.ata.lba / (sectors * heads)) >> 8);
-		ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit | 
-			     (((request->u.ata.lba% (sectors * heads)) /
-			       sectors) & 0xf));
+	    if (atadev->param.atavalid & ATA_FLAG_54_58) {
+		heads = atadev->param.current_heads;
+		sectors = atadev->param.current_sectors;
 	    }
 	    else {
-		ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba);
-		ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
-		ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
-		ATA_IDX_OUTB(ch, ATA_DRIVE,
-			     ATA_D_IBM | ATA_D_LBA | atadev->unit |
-			     ((request->u.ata.lba >> 24) & 0x0f));
+		heads = atadev->param.heads;
+		sectors = atadev->param.sectors;
 	    }
-	}
 
-	/* issue command to controller */
-	ATA_IDX_OUTB(ch, ATA_COMMAND, request->u.ata.command);
+	    ATA_IDX_OUTB(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1);
+	    ATA_IDX_OUTB(ch, ATA_CYL_LSB,
+			 (request->u.ata.lba / (sectors * heads)));
+	    ATA_IDX_OUTB(ch, ATA_CYL_MSB,
+			 (request->u.ata.lba / (sectors * heads)) >> 8);
+	    ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit | 
+			 (((request->u.ata.lba% (sectors * heads)) /
+			   sectors) & 0xf));
+	}
+	else {
+	    ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba);
+	    ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
+	    ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
+	    ATA_IDX_OUTB(ch, ATA_DRIVE,
+			 ATA_D_IBM | ATA_D_LBA | atadev->unit |
+			 ((request->u.ata.lba >> 24) & 0x0f));
+	}
     }
-
-    return 0;
 }
 
 static void


More information about the freebsd-current mailing list