diff options
author | Matthew Dempsky <matthew@cvs.openbsd.org> | 2010-07-27 04:41:57 +0000 |
---|---|---|
committer | Matthew Dempsky <matthew@cvs.openbsd.org> | 2010-07-27 04:41:57 +0000 |
commit | cb13e3a366f7b8d6d41ebc02956fab5846ba7c16 (patch) | |
tree | 8e964cadcb0d3f0688cc20ff520515ea6bdf72c1 /sys | |
parent | b749a540a9a87f13988fde7c3cbd674c28fee631 (diff) |
Add scsi_cmd_rw_decode() for decoding any SCSI READ or WRITE command,
and update atascsi(4) to make use of it. (Other HBAs will be updated
post-release.) Should allow for use of SATA drives with >2^32 LBAs.
ok deraadt@, dlg@, krw@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ata/atascsi.c | 24 | ||||
-rw-r--r-- | sys/scsi/scsi_base.c | 39 | ||||
-rw-r--r-- | sys/scsi/scsiconf.h | 7 |
3 files changed, 55 insertions, 15 deletions
diff --git a/sys/dev/ata/atascsi.c b/sys/dev/ata/atascsi.c index 690a0211bf7..9c46baf37f4 100644 --- a/sys/dev/ata/atascsi.c +++ b/sys/dev/ata/atascsi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: atascsi.c,v 1.89 2010/07/20 01:06:54 deraadt Exp $ */ +/* $OpenBSD: atascsi.c,v 1.90 2010/07/27 04:41:56 matthew Exp $ */ /* * Copyright (c) 2007 David Gwynne <dlg@openbsd.org> @@ -372,19 +372,21 @@ atascsi_disk_cmd(struct scsi_xfer *xs) struct atascsi_port *ap = as->as_ports[link->target]; struct ata_xfer *xa = xs->io; int flags = 0; - struct scsi_rw *rw; - struct scsi_rw_big *rwb; struct ata_fis_h2d *fis; u_int64_t lba; u_int32_t sector_count; switch (xs->cmd->opcode) { - case READ_BIG: case READ_COMMAND: + case READ_BIG: + case READ_12: + case READ_16: flags = ATA_F_READ; break; - case WRITE_BIG: case WRITE_COMMAND: + case WRITE_BIG: + case WRITE_12: + case WRITE_16: flags = ATA_F_WRITE; /* deal with io outside the switch */ break; @@ -427,14 +429,10 @@ atascsi_disk_cmd(struct scsi_xfer *xs) } xa->flags = flags; - if (xs->cmdlen == 6) { - rw = (struct scsi_rw *)xs->cmd; - lba = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff); - sector_count = rw->length ? rw->length : 0x100; - } else { - rwb = (struct scsi_rw_big *)xs->cmd; - lba = _4btol(rwb->addr); - sector_count = _2btol(rwb->length); + scsi_cmd_rw_decode(xs->cmd, &lba, §or_count); + if ((lba >> 48) != 0 || (sector_count >> 16) != 0) { + atascsi_done(xs, XS_DRIVER_STUFFUP); + return; } fis = xa->fis; diff --git a/sys/scsi/scsi_base.c b/sys/scsi/scsi_base.c index cf51b9fa588..e3632f2a60d 100644 --- a/sys/scsi/scsi_base.c +++ b/sys/scsi/scsi_base.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scsi_base.c,v 1.188 2010/07/27 04:17:10 dlg Exp $ */ +/* $OpenBSD: scsi_base.c,v 1.189 2010/07/27 04:41:56 matthew Exp $ */ /* $NetBSD: scsi_base.c,v 1.43 1997/04/02 02:29:36 mycroft Exp $ */ /* @@ -2353,3 +2353,40 @@ scsi_show_mem(u_char *address, int num) } #endif /* SCSIDEBUG */ +void +scsi_cmd_rw_decode(struct scsi_generic *cmd, u_int64_t *blkno, + u_int32_t *nblks) +{ + switch (cmd->opcode) { + case READ_COMMAND: + case WRITE_COMMAND: { + struct scsi_rw *rw = (struct scsi_rw *)cmd; + *blkno = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff); + *nblks = rw->length ? rw->length : 0x100; + break; + } + case READ_BIG: + case WRITE_BIG: { + struct scsi_rw_big *rwb = (struct scsi_rw_big *)cmd; + *blkno = _4btol(rwb->addr); + *nblks = _2btol(rwb->length); + break; + } + case READ_12: + case WRITE_12: { + struct scsi_rw_12 *rw12 = (struct scsi_rw_12 *)cmd; + *blkno = _4btol(rw12->addr); + *nblks = _4btol(rw12->length); + break; + } + case READ_16: + case WRITE_16: { + struct scsi_rw_16 *rw16 = (struct scsi_rw_16 *)cmd; + *blkno = _8btol(rw16->addr); + *nblks = _4btol(rw16->length); + break; + } + default: + panic("scsi_cmd_rw_decode: bad opcode 0x%02x", cmd->opcode); + } +} diff --git a/sys/scsi/scsiconf.h b/sys/scsi/scsiconf.h index 0fc267fccb1..ed462cb840a 100644 --- a/sys/scsi/scsiconf.h +++ b/sys/scsi/scsiconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: scsiconf.h,v 1.134 2010/07/27 04:17:10 dlg Exp $ */ +/* $OpenBSD: scsiconf.h,v 1.135 2010/07/27 04:41:56 matthew Exp $ */ /* $NetBSD: scsiconf.h,v 1.35 1997/04/02 02:29:38 mycroft Exp $ */ /* @@ -631,5 +631,10 @@ int mpath_path_detach(struct scsi_link *, int); void mpath_path_activate(struct scsi_link *); void mpath_path_deactivate(struct scsi_link *); +/* + * Utility functions for SCSI HBA emulation. + */ +void scsi_cmd_rw_decode(struct scsi_generic *, u_int64_t *, u_int32_t *); + #endif /* _KERNEL */ #endif /* SCSI_SCSICONF_H */ |