Add scsi_cmd_rw_decode() for decoding any SCSI READ or WRITE command,
authormatthew <matthew@openbsd.org>
Tue, 27 Jul 2010 04:41:56 +0000 (04:41 +0000)
committermatthew <matthew@openbsd.org>
Tue, 27 Jul 2010 04:41:56 +0000 (04:41 +0000)
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@

sys/dev/ata/atascsi.c
sys/scsi/scsi_base.c
sys/scsi/scsiconf.h

index 690a021..9c46baf 100644 (file)
@@ -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;
index cf51b9f..e3632f2 100644 (file)
@@ -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);
+       }
+}
index 0fc267f..ed462cb 100644 (file)
@@ -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 */