Module Name:    src
Committed By:   tsutsui
Date:           Sun Jan 10 16:20:45 UTC 2010

Modified Files:
        src/sys/arch/cobalt/stand/boot: version wd.c wdc.c wdvar.h

Log Message:
Add support for LBA48 read command to standalone wdc/wd driver.
Thanks to bouyer@ for comments about LBA48 boundary checks.

Tested on:
> Cobalt Qube 2700
> wd0 at atabus0 drive 0: <Hitachi HDS721616PLA380>
> wd0: 153 GB, 319120 cyl, 16 head, 63 sec, 512 bytes/sect x 321672960 sectors
via SATA-IDE converter, and NetBSD partition allocated at:
> 1: NetBSD (sysid 169)
>     start 293603940, size 28069020 (13706 MB, Cyls 18276-20023/54/63)

Also bump version.


To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/cobalt/stand/boot/version \
    src/sys/arch/cobalt/stand/boot/wd.c
cvs rdiff -u -r1.11 -r1.12 src/sys/arch/cobalt/stand/boot/wdc.c
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/cobalt/stand/boot/wdvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/cobalt/stand/boot/version
diff -u src/sys/arch/cobalt/stand/boot/version:1.10 src/sys/arch/cobalt/stand/boot/version:1.11
--- src/sys/arch/cobalt/stand/boot/version:1.10	Wed May 28 14:04:07 2008
+++ src/sys/arch/cobalt/stand/boot/version	Sun Jan 10 16:20:45 2010
@@ -1,4 +1,4 @@
-$NetBSD: version,v 1.10 2008/05/28 14:04:07 tsutsui Exp $
+$NetBSD: version,v 1.11 2010/01/10 16:20:45 tsutsui Exp $
 
 NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE.  The format of this
 file is important - make sure the entries are appended on end, last item
@@ -14,3 +14,4 @@
 0.7:	Add support for netboot via 21041 on Qube2700
 0.8:	Add support for optional Z85C30 serial console on Qube2700
 0.9:	Print banner and a loading kernel name onto LCD
+1.0:	Add support for LBA48 read command
Index: src/sys/arch/cobalt/stand/boot/wd.c
diff -u src/sys/arch/cobalt/stand/boot/wd.c:1.10 src/sys/arch/cobalt/stand/boot/wd.c:1.11
--- src/sys/arch/cobalt/stand/boot/wd.c:1.10	Mon Apr 28 20:23:16 2008
+++ src/sys/arch/cobalt/stand/boot/wd.c	Sun Jan 10 16:20:45 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: wd.c,v 1.10 2008/04/28 20:23:16 martin Exp $	*/
+/*	$NetBSD: wd.c,v 1.11 2010/01/10 16:20:45 tsutsui Exp $	*/
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -61,18 +61,45 @@
 	wd->sc_params = *(struct ataparams *)buf;
 
 	/* 48-bit LBA addressing */
-	if ((wd->sc_params.atap_cmd2_en & ATA_CMD2_LBA48) != 0) {
-		DPRINTF(("Drive supports LBA48.\n"));
-#if defined(_ENABLE_LBA48)
+	if ((wd->sc_params.atap_cmd2_en & ATA_CMD2_LBA48) != 0)
 		wd->sc_flags |= WDF_LBA48;
-#endif
-	}
 
 	/* Prior to ATA-4, LBA was optional. */
-	if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0) {
-		DPRINTF(("Drive supports LBA.\n"));
+	if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0)
 		wd->sc_flags |= WDF_LBA;
+	
+	if ((wd->sc_flags & WDF_LBA48) != 0) {
+		DPRINTF(("Drive supports LBA48.\n"));
+		wd->sc_capacity =
+		    ((uint64_t)wd->sc_params.atap_max_lba[3] << 48) |
+		    ((uint64_t)wd->sc_params.atap_max_lba[2] << 32) |
+		    ((uint64_t)wd->sc_params.atap_max_lba[1] << 16) |
+		    ((uint64_t)wd->sc_params.atap_max_lba[0] <<  0);
+		DPRINTF(("atap_max_lba = (0x%x, 0x%x, 0x%x, 0x%x)\n",
+		    wd->sc_params.atap_max_lba[3],
+		    wd->sc_params.atap_max_lba[2],
+		    wd->sc_params.atap_max_lba[1],
+		    wd->sc_params.atap_max_lba[0]));
+		wd->sc_capacity28 =
+		    ((uint32_t)wd->sc_params.atap_capacity[1] << 16) |
+		    ((uint32_t)wd->sc_params.atap_capacity[0] <<  0);
+		DPRINTF(("atap_capacity = (0x%x, 0x%x)\n",
+		    wd->sc_params.atap_capacity[1],
+		    wd->sc_params.atap_capacity[0]));
+	} else if ((wd->sc_flags & WDF_LBA) != 0) {
+		DPRINTF(("Drive supports LBA.\n"));
+		wd->sc_capacity = wd->sc_capacity28 =
+		    ((uint32_t)wd->sc_params.atap_capacity[1] << 16) |
+		    ((uint32_t)wd->sc_params.atap_capacity[0] <<  0);
+	} else {
+		DPRINTF(("Drive doesn't support LBA; using CHS.\n"));
+		wd->sc_capacity = wd->sc_capacity28 =
+		    wd->sc_params.atap_cylinders *
+		    wd->sc_params.atap_heads *
+		    wd->sc_params.atap_sectors;
 	}
+	DPRINTF(("wd->sc_capacity = %ld, wd->sc_capacity28 = %d.\n",
+	    (u_long)wd->sc_capacity, wd->sc_capacity28));
 
 	return 0;
 }
@@ -173,7 +200,7 @@
 	}
 
 	DPRINTF(("label info: d_secsize %d, d_nsectors %d, d_ncylinders %d,"
-	    "d_ntracks %d, d_secpercyl %d\n",
+	    " d_ntracks %d, d_secpercyl %d\n",
 	    wd->sc_label.d_secsize,
 	    wd->sc_label.d_nsectors,
 	    wd->sc_label.d_ncylinders,

Index: src/sys/arch/cobalt/stand/boot/wdc.c
diff -u src/sys/arch/cobalt/stand/boot/wdc.c:1.11 src/sys/arch/cobalt/stand/boot/wdc.c:1.12
--- src/sys/arch/cobalt/stand/boot/wdc.c:1.11	Mon Apr 28 20:23:16 2008
+++ src/sys/arch/cobalt/stand/boot/wdc.c	Sun Jan 10 16:20:45 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: wdc.c,v 1.11 2008/04/28 20:23:16 martin Exp $	*/
+/*	$NetBSD: wdc.c,v 1.12 2010/01/10 16:20:45 tsutsui Exp $	*/
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -229,7 +229,7 @@
 	    wd_c->r_precomp));
 #endif
 
-	WDC_WRITE_REG(chp, wd_precomp, wd_c->r_precomp);
+	WDC_WRITE_REG(chp, wd_features, wd_c->r_features);
 	WDC_WRITE_REG(chp, wd_seccnt, wd_c->r_count);
 	WDC_WRITE_REG(chp, wd_sector, wd_c->r_sector);
 	WDC_WRITE_REG(chp, wd_cyl_lo, wd_c->r_cyl);
@@ -258,6 +258,12 @@
 {
 	struct wdc_channel *chp = &wd->sc_channel;
 
+#if 0
+	DPRINTF(("%s(%d, %x, %ld, %d)\n", __func__,
+	    wd_c->drive, wd_c->r_command,
+	    (u_long)wd_c->r_blkno, wd_c->r_count));
+#endif
+
 	/* Select drive, head, and addressing mode. */
 	WDC_WRITE_REG(chp, wd_sdh, (wd_c->drive << 4) | WDSD_LBA);
 
@@ -320,20 +326,37 @@
 {
 	int error;
 	struct wdc_command wd_c;
+	bool lba, lba48;
 
 	memset(&wd_c, 0, sizeof(wd_c));
+	lba   = false;
+	lba48 = false;
+
+	wd_c.data = data;
+	wd_c.r_count = 1;
+	wd_c.r_features = 0;
+	wd_c.drive = wd->sc_unit;
+	wd_c.bcount = wd->sc_label.d_secsize;
+
+	if ((wd->sc_flags & WDF_LBA48) != 0 && blkno > wd->sc_capacity28)
+		lba48 = true;
+	else if ((wd->sc_flags & WDF_LBA) != 0)
+		lba = true;
 
-	if (wd->sc_flags & WDF_LBA48) {
+	if (lba48) {
 		/* LBA48 */
+		wd_c.r_command = atacmd_to48(cmd);
 		wd_c.r_blkno = blkno;
-	} else if (wd->sc_flags & WDF_LBA) {
+	} else if (lba) {
 		/* LBA */
+		wd_c.r_command = cmd;
 		wd_c.r_sector = (blkno >> 0) & 0xff;
 		wd_c.r_cyl = (blkno >> 8) & 0xffff;
 		wd_c.r_head = (blkno >> 24) & 0x0f;
 		wd_c.r_head |= WDSD_LBA;
 	} else {
-		/* LHS */
+		/* CHS */
+		wd_c.r_command = cmd;
 		wd_c.r_sector = blkno % wd->sc_label.d_nsectors;
 		wd_c.r_sector++;    /* Sectors begin with 1, not 0. */
 		blkno /= wd->sc_label.d_nsectors;
@@ -343,13 +366,7 @@
 		wd_c.r_head |= WDSD_CHS;
 	}
 
-	wd_c.data = data;
-	wd_c.r_count = 1;
-	wd_c.drive = wd->sc_unit;
-	wd_c.r_command = cmd;
-	wd_c.bcount = wd->sc_label.d_secsize;
-
-	if (wd->sc_flags & WDF_LBA48)
+	if (lba48)
 		error = wdccommandext(wd, &wd_c);
 	else
 		error = wdccommand(wd, &wd_c);

Index: src/sys/arch/cobalt/stand/boot/wdvar.h
diff -u src/sys/arch/cobalt/stand/boot/wdvar.h:1.8 src/sys/arch/cobalt/stand/boot/wdvar.h:1.9
--- src/sys/arch/cobalt/stand/boot/wdvar.h:1.8	Wed Oct 17 19:54:10 2007
+++ src/sys/arch/cobalt/stand/boot/wdvar.h	Sun Jan 10 16:20:45 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: wdvar.h,v 1.8 2007/10/17 19:54:10 garbled Exp $	*/
+/*	$NetBSD: wdvar.h,v 1.9 2010/01/10 16:20:45 tsutsui Exp $	*/
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -72,6 +72,7 @@
 	u_int sc_unit;
 
 	uint64_t sc_capacity;
+	uint32_t sc_capacity28;
 
 	struct ataparams sc_params;
 	struct disklabel sc_label;
@@ -86,7 +87,7 @@
 	uint16_t r_cyl;
 	uint8_t r_sector;
 	uint8_t r_count;
-	uint8_t r_precomp;
+	uint8_t r_features;
 
 	uint16_t bcount;
 	void *data;

Reply via email to