Re: Any successful installs on a Broadcom HT1000 chipset?

From: Søren Schmidt <sos_at_deepcore.dk>
Date: Fri, 07 Dec 2007 17:46:25 +0100
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

? 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
_at__at_ -464,6 +464,8 _at__at_
     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
_at__at_ -98,7 +98,7 _at__at_
 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);
_at__at_ -151,6 +151,8 _at__at_
 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);
_at__at_ -2044,7 +2046,7 _at__at_
     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,
_at__at_ -2062,32 +2064,55 _at__at_
     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
_at__at_ -4199,10 +4224,92 _at__at_
 
     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
_at__at_ -50,6 +50,8 _at__at_
 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 
_at__at_ -63,6 +65,8 _at__at_
     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 */
_at__at_ -244,28 +248,7 _at__at_
 
 	/* 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 */
_at__at_ -734,57 +717,96 _at__at_
 			   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
Received on Fri Dec 07 2007 - 15:46:43 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:23 UTC