summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMatthew Dempsky <matthew@cvs.openbsd.org>2010-07-27 04:41:57 +0000
committerMatthew Dempsky <matthew@cvs.openbsd.org>2010-07-27 04:41:57 +0000
commitcb13e3a366f7b8d6d41ebc02956fab5846ba7c16 (patch)
tree8e964cadcb0d3f0688cc20ff520515ea6bdf72c1 /sys
parentb749a540a9a87f13988fde7c3cbd674c28fee631 (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.c24
-rw-r--r--sys/scsi/scsi_base.c39
-rw-r--r--sys/scsi/scsiconf.h7
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, &sector_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 */