Module Name:    src
Committed By:   jakllsch
Date:           Tue Jan 24 20:04:08 UTC 2012

Modified Files:
        src/sys/dev/ata: atavar.h satafis_subr.c satafisreg.h wd.c
        src/sys/dev/ic: mvsata.c wdc.c
        src/sys/sys: ataio.h

Log Message:
Rework struct ata_command to support LBA28 and LBA48-protocol commands.
Implement 28- and 48-bit command issuance and parameter read-back in the
various ATA host drivers. Add LBA28-protocol support to ATAIOCCOMMAND ioctl.


To generate a diff of this commit:
cvs rdiff -u -r1.83 -r1.84 src/sys/dev/ata/atavar.h
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/ata/satafis_subr.c
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/ata/satafisreg.h
cvs rdiff -u -r1.390 -r1.391 src/sys/dev/ata/wd.c
cvs rdiff -u -r1.14 -r1.15 src/sys/dev/ic/mvsata.c
cvs rdiff -u -r1.267 -r1.268 src/sys/dev/ic/wdc.c
cvs rdiff -u -r1.8 -r1.9 src/sys/sys/ataio.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/dev/ata/atavar.h
diff -u src/sys/dev/ata/atavar.h:1.83 src/sys/dev/ata/atavar.h:1.84
--- src/sys/dev/ata/atavar.h:1.83	Sat Oct 29 18:43:58 2011
+++ src/sys/dev/ata/atavar.h	Tue Jan 24 20:04:07 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: atavar.h,v 1.83 2011/10/29 18:43:58 jakllsch Exp $	*/
+/*	$NetBSD: atavar.h,v 1.84 2012/01/24 20:04:07 jakllsch Exp $	*/
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -238,18 +238,24 @@ struct ata_bio {
  * (which need multiple interrupts per commands).
  */
 struct ata_command {
-	u_int8_t r_command;	/* Parameters to upload to registers */
-	u_int8_t r_head;
-	u_int16_t r_cyl;
-	u_int8_t r_sector;
-	u_int8_t r_count;
-	u_int8_t r_features;
-	u_int8_t r_st_bmask;	/* status register mask to wait for before
+	/* ATA parameters */
+	uint64_t r_lba;		/* before & after */
+	uint16_t r_count;	/* before & after */
+	union {
+		uint16_t r_features; /* before */
+		uint8_t r_error; /* after */
+	};
+	union {
+		uint8_t r_command; /* before */
+		uint8_t r_status; /* after */
+	};
+	uint8_t r_device;	/* before & after */
+
+	uint8_t r_st_bmask;	/* status register mask to wait for before
 				   command */
-	u_int8_t r_st_pmask;	/* status register mask to wait for after
+	uint8_t r_st_pmask;	/* status register mask to wait for after
 				   command */
-	u_int8_t r_error;	/* error register after command done */
-	volatile u_int16_t flags;
+	volatile uint16_t flags;
 
 #define AT_READ     0x0001 /* There is data to read */
 #define AT_WRITE    0x0002 /* There is data to write (excl. with AT_READ) */
@@ -263,6 +269,8 @@ struct ata_command {
 #define AT_RESET    0x0400 /* command terminated by channel reset */
 #define AT_GONE     0x0800 /* command terminated because device is gone */
 #define AT_READREG  0x1000 /* Read registers on completion */
+#define AT_LBA      0x2000 /* LBA28 */
+#define AT_LBA48    0x4000 /* LBA48 */
 
 	int timeout;		/* timeout (in ms) */
 	void *data;		/* Data buffer address */

Index: src/sys/dev/ata/satafis_subr.c
diff -u src/sys/dev/ata/satafis_subr.c:1.5 src/sys/dev/ata/satafis_subr.c:1.6
--- src/sys/dev/ata/satafis_subr.c:1.5	Wed Apr  7 17:51:16 2010
+++ src/sys/dev/ata/satafis_subr.c	Tue Jan 24 20:04:07 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: satafis_subr.c,v 1.5 2010/04/07 17:51:16 jakllsch Exp $ */
+/* $NetBSD: satafis_subr.c,v 1.6 2012/01/24 20:04:07 jakllsch Exp $ */
 
 /*-
  * Copyright (c) 2009 Jonathan A. Kollasch.
@@ -51,7 +51,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: satafis_subr.c,v 1.5 2010/04/07 17:51:16 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: satafis_subr.c,v 1.6 2012/01/24 20:04:07 jakllsch Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -69,17 +69,32 @@ __KERNEL_RCSID(0, "$NetBSD: satafis_subr
 void
 satafis_rhd_construct_cmd(struct ata_command *ata_c, uint8_t *fis)
 {
+
 	memset(fis, 0, RHD_FISLEN);
 
 	fis[fis_type] = RHD_FISTYPE;
 	fis[rhd_c] = RHD_C;
 	fis[rhd_command] = ata_c->r_command;
-	fis[rhd_features] = ata_c->r_features;
-	fis[rhd_sector] = ata_c->r_sector;
-	fis[rhd_cyl_lo] = ata_c->r_cyl & 0xff;
-	fis[rhd_cyl_hi] = (ata_c->r_cyl >> 8) & 0xff;
-	fis[rhd_dh] = ata_c->r_head & 0x0f;
-	fis[rhd_seccnt] = ata_c->r_count;
+	fis[rhd_features0] = (ata_c->r_features >> 0) & 0xff;
+
+	fis[rhd_lba0] = (ata_c->r_lba >> 0) & 0xff;
+	fis[rhd_lba1] = (ata_c->r_lba >> 8) & 0xff;
+	fis[rhd_lba2] = (ata_c->r_lba >> 16) & 0xff;
+	if ((ata_c->flags & AT_LBA48) != 0) {
+		fis[rhd_dh] = WDSD_LBA;
+		fis[rhd_lba3] = (ata_c->r_lba >> 24) & 0xff;
+		fis[rhd_lba4] = (ata_c->r_lba >> 32) & 0xff;
+		fis[rhd_lba5] = (ata_c->r_lba >> 40) & 0xff;
+		fis[rhd_features1] = (ata_c->r_features >> 8) & 0xff;
+	} else {
+		fis[rhd_dh] = ((ata_c->r_lba >> 24) & 0x0f) |
+		    (((ata_c->flags & AT_LBA) != 0) ? WDSD_LBA : 0);
+	}
+
+	fis[rhd_count0] = (ata_c->r_count >> 0) & 0xff;
+	if ((ata_c->flags & AT_LBA48) != 0) {
+		fis[rhd_count1] = (ata_c->r_count >> 8) & 0xff;
+	}
 }
 
 void
@@ -101,41 +116,45 @@ satafis_rhd_construct_bio(struct ata_xfe
 		fis[rhd_command] =
 		    (ata_bio->flags & ATA_READ) ? WDCC_READDMA : WDCC_WRITEDMA;
 	}
-	fis[rhd_sector] = ata_bio->blkno & 0xff;
-	fis[rhd_cyl_lo] = (ata_bio->blkno >> 8) & 0xff;
-	fis[rhd_cyl_hi] = (ata_bio->blkno >> 16) & 0xff;
-	if (ata_bio->flags & ATA_LBA48) {
+
+	fis[rhd_lba0] = (ata_bio->blkno >> 0) & 0xff;
+	fis[rhd_lba1] = (ata_bio->blkno >> 8) & 0xff;
+	fis[rhd_lba2] = (ata_bio->blkno >> 16) & 0xff;
+	if ((ata_bio->flags & ATA_LBA48) != 0) {
 		fis[rhd_dh] = WDSD_LBA;
-		fis[rhd_sector_exp] = (ata_bio->blkno >> 24) & 0xff;
-		fis[rhd_cyl_lo_exp] = (ata_bio->blkno >> 32) & 0xff;
-		fis[rhd_cyl_hi_exp] = (ata_bio->blkno >> 40) & 0xff;
+		fis[rhd_lba3] = (ata_bio->blkno >> 24) & 0xff;
+		fis[rhd_lba4] = (ata_bio->blkno >> 32) & 0xff;
+		fis[rhd_lba5] = (ata_bio->blkno >> 40) & 0xff;
 	} else {
-		fis[rhd_dh] = ((ata_bio->blkno >> 24) & 0x0f) | WDSD_LBA;
+		fis[rhd_dh] = ((ata_bio->blkno >> 24) & 0x0f) |
+		    (((ata_bio->flags & ATA_LBA) != 0) ? WDSD_LBA : 0);
+	}
+
+	fis[rhd_count0] = nblks & 0xff;
+	if ((ata_bio->flags & ATA_LBA48) != 0) {
+		fis[rhd_count1] = (nblks >> 8) & 0xff;
 	}
-	fis[rhd_seccnt] = nblks & 0xff;
-	fis[rhd_seccnt_exp] = (ata_bio->flags & ATA_LBA48) ?
-	    ((nblks >> 8) & 0xff) : 0;
 }
 
 #if NATAPIBUS > 0
 void
 satafis_rhd_construct_atapi(struct ata_xfer *xfer, uint8_t *fis)
 {
+
 	memset(fis, 0, RHD_FISLEN);
 
 	fis[fis_type] = RHD_FISTYPE;
 	fis[rhd_c] = RHD_C;
 	fis[rhd_command] = ATAPI_PKT_CMD;
-	fis[rhd_features] = (xfer->c_flags & C_DMA) ?
+	fis[rhd_features0] = (xfer->c_flags & C_DMA) ?
 	    ATAPI_PKT_CMD_FTRE_DMA : 0;
-
-	return;
 }
 #endif /* NATAPIBUS */
 
 void
 satafis_rdh_parse(struct ata_channel *chp, const uint8_t *fis)
 {
+
 	chp->ch_status = fis[rdh_status];
 	chp->ch_error = fis[rdh_error];
 }
@@ -143,11 +162,25 @@ satafis_rdh_parse(struct ata_channel *ch
 void
 satafis_rdh_cmd_readreg(struct ata_command *ata_c, const uint8_t *fis)
 {
-	ata_c->r_command = fis[rdh_status];
-	ata_c->r_features = fis[rdh_error];
+
+	ata_c->r_lba = (uint64_t)fis[rdh_lba0] << 0;
+	ata_c->r_lba |= (uint64_t)fis[rdh_lba1] << 8;
+	ata_c->r_lba |= (uint64_t)fis[rdh_lba2] << 16;
+	if ((ata_c->flags & AT_LBA48) != 0) {
+		ata_c->r_lba |= (uint64_t)fis[rdh_lba3] << 24;
+		ata_c->r_lba |= (uint64_t)fis[rdh_lba4] << 32;
+		ata_c->r_lba |= (uint64_t)fis[rdh_lba5] << 40;
+	} else {
+		ata_c->r_lba |= (uint64_t)(fis[rdh_dh] & 0x0f) << 24;
+	}
+
+	ata_c->r_count = fis[rdh_count0] << 0;
+	if ((ata_c->flags & AT_LBA48) != 0) {
+		ata_c->r_count |= fis[rdh_count1] << 8;
+	}
+
 	ata_c->r_error = fis[rdh_error];
-	ata_c->r_sector = fis[rdh_sector];
-	ata_c->r_cyl = fis[rdh_cyl_hi] << 8 | fis[rdh_cyl_lo];
-	ata_c->r_head = fis[rdh_dh];
-	ata_c->r_count = fis[rdh_seccnt];
+	ata_c->r_status = fis[rdh_status];
+
+	ata_c->r_device = fis[rdh_dh] & 0xf0;
 }

Index: src/sys/dev/ata/satafisreg.h
diff -u src/sys/dev/ata/satafisreg.h:1.3 src/sys/dev/ata/satafisreg.h:1.4
--- src/sys/dev/ata/satafisreg.h:1.3	Wed Nov  2 18:41:58 2011
+++ src/sys/dev/ata/satafisreg.h	Tue Jan 24 20:04:07 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: satafisreg.h,v 1.3 2011/11/02 18:41:58 jakllsch Exp $ */
+/* $NetBSD: satafisreg.h,v 1.4 2012/01/24 20:04:07 jakllsch Exp $ */
 
 /*
  * Copyright (c) 2009, 2010 Jonathan A. Kollasch.
@@ -34,18 +34,18 @@
 #define RHD_FISLEN 20
 #define rhd_c 1 /* Command bit and PM port */
 #define RHD_C 0x80
-#define rhd_command 2 /* wd_command */
-#define rhd_features 3 /* wd_precomp */
-#define rhd_sector 4 /* wd_sector */
-#define rhd_cyl_lo 5 /* wd_cyl_lo */
-#define rhd_cyl_hi 6 /* wd_cyl_hi */
-#define rhd_dh 7 /* wd_sdh */
-#define rhd_sector_exp 8
-#define rhd_cyl_lo_exp 9
-#define rhd_cyl_hi_exp 10
-#define rhd_features_exp 11
-#define rhd_seccnt 12
-#define rhd_seccnt_exp 13
+#define rhd_command 2
+#define rhd_features0 3
+#define rhd_lba0 4
+#define rhd_lba1 5
+#define rhd_lba2 6
+#define rhd_dh 7
+#define rhd_lba3 8
+#define rhd_lba4 9
+#define rhd_lba5 10
+#define rhd_features1 11
+#define rhd_count0 12
+#define rhd_count1 13
 #define rhd_control 15
 
 #define RDH_FISTYPE 0x34
@@ -54,15 +54,15 @@
 #define RDH_I 0x40
 #define rdh_status 2
 #define rdh_error 3
-#define rdh_sector 4 /* wd_sector */
-#define rdh_cyl_lo 5 /* wd_cyl_lo */
-#define rdh_cyl_hi 6 /* wd_cyl_hi */
-#define rdh_dh 7 /* wd_sdh */
-#define rdh_sector_exp 8
-#define rdh_cyl_lo_exp 9
-#define rdh_cyl_hi_exp 10
-#define rdh_seccnt 12
-#define rdh_seccnt_exp 13
+#define rdh_lba0 4
+#define rdh_lba1 5
+#define rdh_lba2 6
+#define rdh_dh 7
+#define rdh_lba3 8
+#define rdh_lba4 9
+#define rdh_lba5 10
+#define rdh_count0 12
+#define rdh_count1 13
 
 #define SDB_FISTYPE 0xA1
 #define SDB_FISLEN 8

Index: src/sys/dev/ata/wd.c
diff -u src/sys/dev/ata/wd.c:1.390 src/sys/dev/ata/wd.c:1.391
--- src/sys/dev/ata/wd.c:1.390	Fri Nov 25 13:55:40 2011
+++ src/sys/dev/ata/wd.c	Tue Jan 24 20:04:07 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: wd.c,v 1.390 2011/11/25 13:55:40 joerg Exp $ */
+/*	$NetBSD: wd.c,v 1.391 2012/01/24 20:04:07 jakllsch Exp $ */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
@@ -54,7 +54,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.390 2011/11/25 13:55:40 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.391 2012/01/24 20:04:07 jakllsch Exp $");
 
 #include "opt_ata.h"
 
@@ -2068,13 +2068,16 @@ wdioctlstrategy(struct buf *bp)
 	if (wi->wi_atareq.flags & ATACMD_READREG)
 		ata_c.flags |= AT_READREG;
 
+	if ((wi->wi_atareq.flags & ATACMD_LBA) != 0)
+		ata_c.flags |= AT_LBA;
+
 	ata_c.flags |= AT_WAIT;
 
 	ata_c.timeout = wi->wi_atareq.timeout;
 	ata_c.r_command = wi->wi_atareq.command;
-	ata_c.r_head = wi->wi_atareq.head & 0x0f;
-	ata_c.r_cyl = wi->wi_atareq.cylinder;
-	ata_c.r_sector = wi->wi_atareq.sec_num;
+	ata_c.r_lba = ((wi->wi_atareq.head & 0x0f) << 24) |
+	    (wi->wi_atareq.cylinder << 8) |
+	    wi->wi_atareq.sec_num;
 	ata_c.r_count = wi->wi_atareq.sec_count;
 	ata_c.r_features = wi->wi_atareq.features;
 	ata_c.r_st_bmask = WDCS_DRDY;
@@ -2099,11 +2102,13 @@ wdioctlstrategy(struct buf *bp)
 	} else {
 		wi->wi_atareq.retsts = ATACMD_OK;
 		if (wi->wi_atareq.flags & ATACMD_READREG) {
-			wi->wi_atareq.head = ata_c.r_head ;
-			wi->wi_atareq.cylinder = ata_c.r_cyl;
-			wi->wi_atareq.sec_num = ata_c.r_sector;
+			wi->wi_atareq.command = ata_c.r_status;
+			wi->wi_atareq.features = ata_c.r_error;
 			wi->wi_atareq.sec_count = ata_c.r_count;
-			wi->wi_atareq.features = ata_c.r_features;
+			wi->wi_atareq.sec_num = ata_c.r_lba & 0xff;
+			wi->wi_atareq.head = (ata_c.r_device & 0xf0) |
+			    ((ata_c.r_lba >> 24) & 0x0f);
+			wi->wi_atareq.cylinder = (ata_c.r_lba >> 8) & 0xffff;
 			wi->wi_atareq.error = ata_c.r_error;
 		}
 	}

Index: src/sys/dev/ic/mvsata.c
diff -u src/sys/dev/ic/mvsata.c:1.14 src/sys/dev/ic/mvsata.c:1.15
--- src/sys/dev/ic/mvsata.c:1.14	Sun Jan 22 16:09:08 2012
+++ src/sys/dev/ic/mvsata.c	Tue Jan 24 20:04:08 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: mvsata.c,v 1.14 2012/01/22 16:09:08 jakllsch Exp $	*/
+/*	$NetBSD: mvsata.c,v 1.15 2012/01/24 20:04:08 jakllsch Exp $	*/
 /*
  * Copyright (c) 2008 KIYOHARA Takashi
  * All rights reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.14 2012/01/22 16:09:08 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.15 2012/01/24 20:04:08 jakllsch Exp $");
 
 #include "opt_mvsata.h"
 
@@ -1543,8 +1543,18 @@ mvsata_wdc_cmd_start(struct ata_channel 
 	if (ata_c->flags & AT_POLL)
 		/* polled command, disable interrupts */
 		MVSATA_WDC_WRITE_1(mvport, SRB_CAS, WDCTL_4BIT | WDCTL_IDS);
-	wdccommand(chp, drive, ata_c->r_command, ata_c->r_cyl, ata_c->r_head,
-	    ata_c->r_sector, ata_c->r_count, ata_c->r_features);
+	if ((ata_c->flags & AT_LBA48) != 0) {
+		wdccommandext(chp, drive, ata_c->r_command,
+		    ata_c->r_lba, ata_c->r_count, ata_c->r_features);
+	} else {
+		wdccommand(chp, drive, ata_c->r_command,
+		    (ata_c->r_lba >> 8) & 0xffff,
+		    (((ata_c->flags & AT_LBA) != 0) ? WDSD_LBA : 0) |
+		    ((ata_c->r_lba >> 24) & 0x0f),
+		    ata_c->r_lba & 0xff,
+		    ata_c->r_count & 0xff,
+		    ata_c->r_features & 0xff);
+	}
 
 	if ((ata_c->flags & AT_POLL) == 0) {
 		chp->ch_flags |= ATACH_IRQ_WAIT; /* wait for interrupt */
@@ -1604,7 +1614,9 @@ again:
 	 * penalty for the extra register write is acceptable,
 	 * wdc_exec_command() isn't called often (mostly for autoconfig)
 	 */
-	MVSATA_WDC_WRITE_1(mvport, SRB_H, WDSD_IBM);
+	if ((xfer->c_flags & C_ATAPI) != 0) {
+		MVSATA_WDC_WRITE_1(mvport, SRB_H, WDSD_IBM);
+	}
 	if ((ata_c->flags & AT_XFDONE) != 0) {
 		/*
 		 * We have completed a data xfer. The drive should now be
@@ -1703,13 +1715,43 @@ mvsata_wdc_cmd_done(struct ata_channel *
 	if ((ata_c->flags & AT_READREG) != 0 &&
 	    device_is_active(atac->atac_dev) &&
 	    (ata_c->flags & (AT_ERROR | AT_DF)) == 0) {
-		ata_c->r_head = MVSATA_WDC_READ_1(mvport, SRB_H);
-		ata_c->r_count = MVSATA_WDC_READ_1(mvport, SRB_SC);
-		ata_c->r_sector = MVSATA_WDC_READ_1(mvport, SRB_LBAL);
-		ata_c->r_cyl = MVSATA_WDC_READ_1(mvport, SRB_LBAM) << 8;
-		ata_c->r_cyl |= MVSATA_WDC_READ_1(mvport, SRB_LBAH);
+		ata_c->r_status = MVSATA_WDC_READ_1(mvport, SRB_CS);
 		ata_c->r_error = MVSATA_WDC_READ_1(mvport, SRB_FE);
-		ata_c->r_features = ata_c->r_error;
+		ata_c->r_count = MVSATA_WDC_READ_1(mvport, SRB_SC);
+		ata_c->r_lba =
+		    (uint64_t)MVSATA_WDC_READ_1(mvport, SRB_LBAL) << 0;
+		ata_c->r_lba |=
+		    (uint64_t)MVSATA_WDC_READ_1(mvport, SRB_LBAM) << 8;
+		ata_c->r_lba |=
+		    (uint64_t)MVSATA_WDC_READ_1(mvport, SRB_LBAH) << 16;
+		ata_c->r_device = MVSATA_WDC_READ_1(mvport, SRB_H);
+		if ((ata_c->flags & AT_LBA48) != 0) {
+			if ((ata_c->flags & AT_POLL) != 0) {
+				MVSATA_WDC_WRITE_1(mvport, SRB_CAS,
+				    WDCTL_HOB|WDCTL_4BIT|WDCTL_IDS);
+			} else {
+				MVSATA_WDC_WRITE_1(mvport, SRB_CAS,
+				    WDCTL_HOB|WDCTL_4BIT);
+			}
+			ata_c->r_count |=
+			    MVSATA_WDC_READ_1(mvport, SRB_SC) << 8;
+			ata_c->r_lba =
+			    (uint64_t)MVSATA_WDC_READ_1(mvport, SRB_LBAL) << 24;
+			ata_c->r_lba |=
+			    (uint64_t)MVSATA_WDC_READ_1(mvport, SRB_LBAM) << 32;
+			ata_c->r_lba |=
+			    (uint64_t)MVSATA_WDC_READ_1(mvport, SRB_LBAH) << 40;
+			if ((ata_c->flags & AT_POLL) != 0) {
+				MVSATA_WDC_WRITE_1(mvport, SRB_CAS,
+				    WDCTL_4BIT|WDCTL_IDS);
+			} else {
+				MVSATA_WDC_WRITE_1(mvport, SRB_CAS,
+				    WDCTL_4BIT);
+			}
+		} else {
+			ata_c->r_lba |=
+			    (uint64_t)(ata_c->r_device & 0x0f) << 24;
+		}
 	}
 	callout_stop(&chp->ch_callout);
 	chp->ch_queue->active_xfer = NULL;

Index: src/sys/dev/ic/wdc.c
diff -u src/sys/dev/ic/wdc.c:1.267 src/sys/dev/ic/wdc.c:1.268
--- src/sys/dev/ic/wdc.c:1.267	Mon Jan  9 01:01:49 2012
+++ src/sys/dev/ic/wdc.c	Tue Jan 24 20:04:08 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: wdc.c,v 1.267 2012/01/09 01:01:49 jakllsch Exp $ */
+/*	$NetBSD: wdc.c,v 1.268 2012/01/24 20:04:08 jakllsch Exp $ */
 
 /*
  * Copyright (c) 1998, 2001, 2003 Manuel Bouyer.  All rights reserved.
@@ -58,7 +58,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.267 2012/01/09 01:01:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.268 2012/01/24 20:04:08 jakllsch Exp $");
 
 #include "opt_ata.h"
 #include "opt_wdc.h"
@@ -1457,8 +1457,19 @@ __wdccommand_start(struct ata_channel *c
 		bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr,
 		    WDCTL_4BIT | WDCTL_IDS);
 	}
-	wdccommand(chp, drive, ata_c->r_command, ata_c->r_cyl, ata_c->r_head,
-	    ata_c->r_sector, ata_c->r_count, ata_c->r_features);
+	if ((ata_c->flags & AT_LBA48) != 0) {
+		wdccommandext(chp, drive, ata_c->r_command,
+		   ata_c->r_lba, ata_c->r_count, ata_c->r_features);
+	} else {
+		wdccommand(chp, drive, ata_c->r_command,
+		    (ata_c->r_lba >> 8) & 0xffff,
+		    WDSD_IBM | (drive << 4) |
+		    (((ata_c->flags & AT_LBA) != 0) ? WDSD_LBA : 0) |
+		    ((ata_c->r_lba >> 24) & 0x0f),
+		    ata_c->r_lba & 0xff,
+		    ata_c->r_count & 0xff,
+		    ata_c->r_features & 0xff);
+	}
 
 	if ((ata_c->flags & AT_POLL) == 0) {
 		chp->ch_flags |= ATACH_IRQ_WAIT; /* wait for interrupt */
@@ -1524,8 +1535,10 @@ __wdccommand_intr(struct ata_channel *ch
 	 * penalty for the extra register write is acceptable,
 	 * wdc_exec_command() isn't called often (mostly for autoconfig)
 	 */
-	bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
-	    WDSD_IBM | (xfer->c_drive << 4));
+	if ((xfer->c_flags & C_ATAPI) != 0) {
+		bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
+		    WDSD_IBM | (xfer->c_drive << 4));
+	}
 	if ((ata_c->flags & AT_XFDONE) != 0) {
 		/*
 		 * We have completed a data xfer. The drive should now be
@@ -1604,20 +1617,48 @@ __wdccommand_done(struct ata_channel *ch
 	if ((ata_c->flags & AT_READREG) != 0 &&
 	    device_is_active(atac->atac_dev) &&
 	    (ata_c->flags & (AT_ERROR | AT_DF)) == 0) {
-		ata_c->r_head = bus_space_read_1(wdr->cmd_iot,
-		    wdr->cmd_iohs[wd_sdh], 0);
-		ata_c->r_count = bus_space_read_1(wdr->cmd_iot,
-		    wdr->cmd_iohs[wd_seccnt], 0);
-		ata_c->r_sector = bus_space_read_1(wdr->cmd_iot,
-		    wdr->cmd_iohs[wd_sector], 0);
-		ata_c->r_cyl = bus_space_read_1(wdr->cmd_iot,
-		    wdr->cmd_iohs[wd_cyl_hi], 0) << 8;
-		ata_c->r_cyl |= bus_space_read_1(wdr->cmd_iot,
-		    wdr->cmd_iohs[wd_cyl_lo], 0);
+		ata_c->r_status = bus_space_read_1(wdr->cmd_iot,
+		    wdr->cmd_iohs[wd_status], 0);
 		ata_c->r_error = bus_space_read_1(wdr->cmd_iot,
 		    wdr->cmd_iohs[wd_error], 0);
-		ata_c->r_features = bus_space_read_1(wdr->cmd_iot,
-		    wdr->cmd_iohs[wd_features], 0);
+		ata_c->r_count = bus_space_read_1(wdr->cmd_iot,
+		    wdr->cmd_iohs[wd_seccnt], 0);
+		ata_c->r_lba = (uint64_t)bus_space_read_1(wdr->cmd_iot,
+		    wdr->cmd_iohs[wd_sector], 0) << 0;
+		ata_c->r_lba |= (uint64_t)bus_space_read_1(wdr->cmd_iot,
+		    wdr->cmd_iohs[wd_cyl_lo], 0) << 8;
+		ata_c->r_lba |= (uint64_t)bus_space_read_1(wdr->cmd_iot,
+		    wdr->cmd_iohs[wd_cyl_hi], 0) << 16;
+		ata_c->r_device = bus_space_read_1(wdr->cmd_iot,
+		    wdr->cmd_iohs[wd_sdh], 0);
+
+		if ((ata_c->flags & AT_LBA48) != 0) {
+			if ((ata_c->flags & AT_POLL) != 0)
+				bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh,
+				    wd_aux_ctlr,
+				    WDCTL_HOB|WDCTL_4BIT|WDCTL_IDS);
+			else
+				bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh,
+				    wd_aux_ctlr, WDCTL_HOB|WDCTL_4BIT);
+			ata_c->r_count |= bus_space_read_1(wdr->cmd_iot,
+			    wdr->cmd_iohs[wd_seccnt], 0) << 8;
+			ata_c->r_lba |= (uint64_t)bus_space_read_1(wdr->cmd_iot,
+			    wdr->cmd_iohs[wd_sector], 0) << 24;
+			ata_c->r_lba |= (uint64_t)bus_space_read_1(wdr->cmd_iot,
+			    wdr->cmd_iohs[wd_cyl_lo], 0) << 32;
+			ata_c->r_lba |= (uint64_t)bus_space_read_1(wdr->cmd_iot,
+			    wdr->cmd_iohs[wd_cyl_hi], 0) << 40;
+			if ((ata_c->flags & AT_POLL) != 0)
+				bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh,
+				    wd_aux_ctlr, WDCTL_4BIT|WDCTL_IDS);
+			else
+				bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh,
+				     wd_aux_ctlr, WDCTL_4BIT);
+		} else {
+			ata_c->r_lba |=
+			    (uint64_t)(ata_c->r_device & 0x0f) << 24;
+		}
+		ata_c->r_device &= 0xf0;
 	}
 	callout_stop(&chp->ch_callout);
 	chp->ch_queue->active_xfer = NULL;

Index: src/sys/sys/ataio.h
diff -u src/sys/sys/ataio.h:1.8 src/sys/sys/ataio.h:1.9
--- src/sys/sys/ataio.h:1.8	Sun Mar  4 06:03:40 2007
+++ src/sys/sys/ataio.h	Tue Jan 24 20:04:07 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: ataio.h,v 1.8 2007/03/04 06:03:40 christos Exp $	*/
+/*	$NetBSD: ataio.h,v 1.9 2012/01/24 20:04:07 jakllsch Exp $	*/
 
 #ifndef _SYS_ATAIO_H_
 #define _SYS_ATAIO_H_
@@ -26,6 +26,7 @@ typedef struct	atareq {
 #define ATACMD_READ		0x00000001
 #define ATACMD_WRITE		0x00000002
 #define ATACMD_READREG		0x00000004
+#define ATACMD_LBA		0x00000008
 
 /* definitions for the return status (retsts) */
 #define ATACMD_OK	0x00

Reply via email to