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