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