TRIM support
[dragonfly.git] / sys / dev / disk / ahci / ahci_cam.c
index a18328b..8e61fbf 100644 (file)
@@ -1,4 +1,6 @@
 /*
 /*
+ * (MPSAFE)
+ *
  * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
  *
  * This code is derived from software contributed to The DragonFly Project
  * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
  *
  * This code is derived from software contributed to The DragonFly Project
@@ -78,6 +80,7 @@ static void ahci_ata_atapi_sense(struct ata_fis_d2h *rfis,
 
 static int ahci_cam_probe_disk(struct ahci_port *ap, struct ata_port *at);
 static int ahci_cam_probe_atapi(struct ahci_port *ap, struct ata_port *at);
 
 static int ahci_cam_probe_disk(struct ahci_port *ap, struct ata_port *at);
 static int ahci_cam_probe_atapi(struct ahci_port *ap, struct ata_port *at);
+static int ahci_set_xfer(struct ahci_port *ap, struct ata_port *atx);
 static void ahci_ata_dummy_done(struct ata_xfer *xa);
 static void ata_fix_identify(struct ata_identify *id);
 static void ahci_cam_rescan(struct ahci_port *ap);
 static void ahci_ata_dummy_done(struct ata_xfer *xa);
 static void ata_fix_identify(struct ata_identify *id);
 static void ahci_cam_rescan(struct ahci_port *ap);
@@ -103,15 +106,23 @@ ahci_cam_attach(struct ahci_port *ap)
        if (devq == NULL) {
                return (ENOMEM);
        }
        if (devq == NULL) {
                return (ENOMEM);
        }
+
+       /*
+        * Give the devq enough room to run with 32 max_dev_transactions,
+        * but set the overall max tags to 1 until NCQ is negotiated.
+        */
        sim = cam_sim_alloc(ahci_xpt_action, ahci_xpt_poll, "ahci",
        sim = cam_sim_alloc(ahci_xpt_action, ahci_xpt_poll, "ahci",
-                          (void *)ap, unit, &sim_mplock, 1, 1, devq);
+                          (void *)ap, unit, &ap->ap_sim_lock,
+                          32, 1, devq);
        cam_simq_release(devq);
        if (sim == NULL) {
                return (ENOMEM);
        }
        ap->ap_sim = sim;
        ahci_os_unlock_port(ap);
        cam_simq_release(devq);
        if (sim == NULL) {
                return (ENOMEM);
        }
        ap->ap_sim = sim;
        ahci_os_unlock_port(ap);
+       lockmgr(&ap->ap_sim_lock, LK_EXCLUSIVE);
        error = xpt_bus_register(ap->ap_sim, ap->ap_num);
        error = xpt_bus_register(ap->ap_sim, ap->ap_num);
+       lockmgr(&ap->ap_sim_lock, LK_RELEASE);
        ahci_os_lock_port(ap);
        if (error != CAM_SUCCESS) {
                ahci_cam_detach(ap);
        ahci_os_lock_port(ap);
        if (error != CAM_SUCCESS) {
                ahci_cam_detach(ap);
@@ -189,7 +200,7 @@ ahci_cam_detach(struct ahci_port *ap)
 
        if ((ap->ap_flags & AP_F_CAM_ATTACHED) == 0)
                return;
 
        if ((ap->ap_flags & AP_F_CAM_ATTACHED) == 0)
                return;
-       get_mplock();
+       lockmgr(&ap->ap_sim_lock, LK_EXCLUSIVE);
        if (ap->ap_sim) {
                xpt_freeze_simq(ap->ap_sim, 1);
        }
        if (ap->ap_sim) {
                xpt_freeze_simq(ap->ap_sim, 1);
        }
@@ -202,7 +213,7 @@ ahci_cam_detach(struct ahci_port *ap)
                cam_sim_free(ap->ap_sim);
                ap->ap_sim = NULL;
        }
                cam_sim_free(ap->ap_sim);
                ap->ap_sim = NULL;
        }
-       rel_mplock();
+       lockmgr(&ap->ap_sim_lock, LK_RELEASE);
        ap->ap_flags &= ~AP_F_CAM_ATTACHED;
 }
 
        ap->ap_flags &= ~AP_F_CAM_ATTACHED;
 }
 
@@ -251,7 +262,7 @@ ahci_cam_probe(struct ahci_port *ap, struct ata_port *atx)
         * an (at) pointing to target 0.
         */
        if (atx == NULL) {
         * an (at) pointing to target 0.
         */
        if (atx == NULL) {
-               at = ap->ap_ata;        /* direct attached - device 0 */
+               at = ap->ap_ata[0];     /* direct attached - device 0 */
                if (ap->ap_type == ATA_PORT_T_PM) {
                        kprintf("%s: Found Port Multiplier\n",
                                ATANAME(ap, atx));
                if (ap->ap_type == ATA_PORT_T_PM) {
                        kprintf("%s: Found Port Multiplier\n",
                                ATANAME(ap, atx));
@@ -367,8 +378,8 @@ ahci_cam_probe(struct ahci_port *ap, struct ata_port *atx)
                                }
                        }
                        if (at->at_ncqdepth >= ap->ap_sc->sc_ncmds) {
                                }
                        }
                        if (at->at_ncqdepth >= ap->ap_sc->sc_ncmds) {
-                               cam_devq_resize(ap->ap_sim->devq,
-                                               at->at_ncqdepth - 1);
+                               cam_sim_set_max_tags(ap->ap_sim,
+                                                    at->at_ncqdepth - 1);
                        }
                }
        } else {
                        }
                }
        } else {
@@ -492,7 +503,12 @@ ahci_cam_probe_disk(struct ahci_port *ap, struct ata_port *atx)
        struct ata_port *at;
        struct ata_xfer *xa;
 
        struct ata_port *at;
        struct ata_xfer *xa;
 
-       at = atx ? atx : ap->ap_ata;
+       at = atx ? atx : ap->ap_ata[0];
+
+       /*
+        * Set dummy xfer mode
+        */
+       ahci_set_xfer(ap, atx);
 
        /*
         * Enable write cache if supported
 
        /*
         * Enable write cache if supported
@@ -509,11 +525,11 @@ ahci_cam_probe_disk(struct ahci_port *ap, struct ata_port *atx)
                xa = ahci_ata_get_xfer(ap, atx);
                xa->complete = ahci_ata_dummy_done;
                xa->fis->command = ATA_C_SET_FEATURES;
                xa = ahci_ata_get_xfer(ap, atx);
                xa->complete = ahci_ata_dummy_done;
                xa->fis->command = ATA_C_SET_FEATURES;
-               /*xa->fis->features = ATA_SF_WRITECACHE_EN;*/
-               xa->fis->features = ATA_SF_LOOKAHEAD_EN;
+               xa->fis->features = ATA_SF_WRITECACHE_EN;
+               /* xa->fis->features = ATA_SF_LOOKAHEAD_EN; */
                xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
                xa->fis->device = 0;
                xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
                xa->fis->device = 0;
-               xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
+               xa->flags = ATA_F_PIO | ATA_F_POLL;
                xa->timeout = 1000;
                xa->datalen = 0;
                if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
                xa->timeout = 1000;
                xa->datalen = 0;
                if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
@@ -535,7 +551,7 @@ ahci_cam_probe_disk(struct ahci_port *ap, struct ata_port *atx)
                xa->fis->features = ATA_SF_LOOKAHEAD_EN;
                xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
                xa->fis->device = 0;
                xa->fis->features = ATA_SF_LOOKAHEAD_EN;
                xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
                xa->fis->device = 0;
-               xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
+               xa->flags = ATA_F_PIO | ATA_F_POLL;
                xa->timeout = 1000;
                xa->datalen = 0;
                if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
                xa->timeout = 1000;
                xa->datalen = 0;
                if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
@@ -560,7 +576,7 @@ ahci_cam_probe_disk(struct ahci_port *ap, struct ata_port *atx)
                xa->complete = ahci_ata_dummy_done;
                xa->fis->command = ATA_C_SEC_FREEZE_LOCK;
                xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
                xa->complete = ahci_ata_dummy_done;
                xa->fis->command = ATA_C_SEC_FREEZE_LOCK;
                xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
-               xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
+               xa->flags = ATA_F_PIO | ATA_F_POLL;
                xa->timeout = 1000;
                xa->datalen = 0;
                if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
                xa->timeout = 1000;
                xa->datalen = 0;
                if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
@@ -580,6 +596,68 @@ ahci_cam_probe_disk(struct ahci_port *ap, struct ata_port *atx)
 static int
 ahci_cam_probe_atapi(struct ahci_port *ap, struct ata_port *atx)
 {
 static int
 ahci_cam_probe_atapi(struct ahci_port *ap, struct ata_port *atx)
 {
+       ahci_set_xfer(ap, atx);
+       return(0);
+}
+
+/*
+ * Setting the transfer mode is irrelevant for the SATA transport
+ * but some (atapi) devices seem to need it anyway.  In addition
+ * if we are running through a SATA->PATA converter for some reason
+ * beyond my comprehension we might have to set the mode.
+ *
+ * We only support DMA modes for SATA attached devices, so don't bother
+ * with legacy modes.
+ */
+static int
+ahci_set_xfer(struct ahci_port *ap, struct ata_port *atx)
+{
+       struct ata_port *at;
+       struct ata_xfer *xa;
+       u_int16_t mode;
+       u_int16_t mask;
+
+       at = atx ? atx : ap->ap_ata[0];
+
+       /*
+        * Figure out the supported UDMA mode.  Ignore other legacy modes.
+        */
+       mask = le16toh(at->at_identify.ultradma);
+       if ((mask & 0xFF) == 0 || mask == 0xFFFF)
+               return(0);
+       mask &= 0xFF;
+       mode = 0x4F;
+       while ((mask & 0x8000) == 0) {
+               mask <<= 1;
+               --mode;
+       }
+
+       /*
+        * SATA atapi devices often still report a dma mode, even though
+        * it is irrelevant for SATA transport.  It is also possible that
+        * we are running through a SATA->PATA converter and seeing the
+        * PATA dma mode.
+        *
+        * In this case the device may require a (dummy) SETXFER to be
+        * sent before it will work properly.
+        */
+       xa = ahci_ata_get_xfer(ap, atx);
+       xa->complete = ahci_ata_dummy_done;
+       xa->fis->command = ATA_C_SET_FEATURES;
+       xa->fis->features = ATA_SF_SETXFER;
+       xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
+       xa->fis->sector_count = mode;
+       xa->flags = ATA_F_PIO | ATA_F_POLL;
+       xa->timeout = 1000;
+       xa->datalen = 0;
+       if (ahci_ata_cmd(xa) != ATA_S_COMPLETE) {
+               kprintf("%s: Unable to set dummy xfer mode \n",
+                       ATANAME(ap, atx));
+       } else if (bootverbose) {
+               kprintf("%s: Set dummy xfer mode to %02x\n",
+                       ATANAME(ap, atx), mode);
+       }
+       ahci_ata_put_xfer(xa);
        return(0);
 }
 
        return(0);
 }
 
@@ -651,7 +729,7 @@ ahci_cam_rescan(struct ahci_port *ap)
        }
        ap->ap_flags |= AP_F_SCAN_RUNNING;
        for (i = 0; i < AHCI_MAX_PMPORTS; ++i) {
        }
        ap->ap_flags |= AP_F_SCAN_RUNNING;
        for (i = 0; i < AHCI_MAX_PMPORTS; ++i) {
-               ap->ap_ata[i].at_features |= ATA_PORT_F_RESCAN;
+               ap->ap_ata[i]->at_features |= ATA_PORT_F_RESCAN;
        }
 
        status = xpt_create_path(&path, xpt_periph, cam_sim_path(ap->ap_sim),
        }
 
        status = xpt_create_path(&path, xpt_periph, cam_sim_path(ap->ap_sim),
@@ -703,7 +781,6 @@ ahci_xpt_action(struct cam_sim *sim, union ccb *ccb)
 
        /* XXX lock */
        ap = cam_sim_softc(sim);
 
        /* XXX lock */
        ap = cam_sim_softc(sim);
-       at = ap->ap_ata;
        atx = NULL;
        KKASSERT(ap != NULL);
        ccbh = &ccb->ccb_h;
        atx = NULL;
        KKASSERT(ap != NULL);
        ccbh = &ccb->ccb_h;
@@ -738,7 +815,7 @@ ahci_xpt_action(struct cam_sim *sim, union ccb *ccb)
                        xpt_done(ccb);
                        return;
                }
                        xpt_done(ccb);
                        return;
                }
-               at += ccbh->target_id;
+               at = ap->ap_ata[ccbh->target_id];
                if (ap->ap_type == ATA_PORT_T_PM)
                        atx = at;
 
                if (ap->ap_type == ATA_PORT_T_PM)
                        atx = at;
 
@@ -747,6 +824,8 @@ ahci_xpt_action(struct cam_sim *sim, union ccb *ccb)
                        xpt_done(ccb);
                        return;
                }
                        xpt_done(ccb);
                        return;
                }
+       } else {
+               at = ap->ap_ata[0];
        }
 
        /*
        }
 
        /*
@@ -803,6 +882,9 @@ ahci_xpt_action(struct cam_sim *sim, union ccb *ccb)
                        case AHCI_PREG_SSTS_SPD_GEN2:
                                ccb->cpi.base_transfer_speed = 300000;
                                break;
                        case AHCI_PREG_SSTS_SPD_GEN2:
                                ccb->cpi.base_transfer_speed = 300000;
                                break;
+                       case AHCI_PREG_SSTS_SPD_GEN3:
+                               ccb->cpi.base_transfer_speed = 600000;
+                               break;
                        default:
                                /* unknown */
                                ccb->cpi.base_transfer_speed = 1000;
                        default:
                                /* unknown */
                                ccb->cpi.base_transfer_speed = 1000;
@@ -876,6 +958,17 @@ ahci_xpt_action(struct cam_sim *sim, union ccb *ccb)
                        break;
                }
                break;
                        break;
                }
                break;
+       case XPT_TRIM:
+       {
+               scsi_cdb_t cdb;
+               struct ccb_scsiio *csio;
+               csio = &ccb->csio;
+               cdb = (void *)((ccbh->flags & CAM_CDB_POINTER) ?
+                   csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes);
+               cdb->generic.opcode = TRIM;
+               ahci_xpt_scsi_disk_io(ap, atx, ccb);
+               break;
+       }
        default:
                ccbh->status = CAM_REQ_INVALID;
                xpt_done(ccb);
        default:
                ccbh->status = CAM_REQ_INVALID;
                xpt_done(ccb);
@@ -922,6 +1015,8 @@ ahci_xpt_scsi_disk_io(struct ahci_port *ap, struct ata_port *atx,
        struct ata_xfer *xa;
        struct ata_port *at;
        struct ata_fis_h2d *fis;
        struct ata_xfer *xa;
        struct ata_port *at;
        struct ata_fis_h2d *fis;
+       struct ata_pass_12 *atp12;
+       struct ata_pass_16 *atp16;
        scsi_cdb_t cdb;
        union scsi_data *rdata;
        int rdata_len;
        scsi_cdb_t cdb;
        union scsi_data *rdata;
        int rdata_len;
@@ -931,7 +1026,7 @@ ahci_xpt_scsi_disk_io(struct ahci_port *ap, struct ata_port *atx,
 
        ccbh = &ccb->csio.ccb_h;
        csio = &ccb->csio;
 
        ccbh = &ccb->csio.ccb_h;
        csio = &ccb->csio;
-       at = atx ? atx : &ap->ap_ata[0];
+       at = atx ? atx : ap->ap_ata[0];
 
        /*
         * XXX not passing NULL at for direct attach!
 
        /*
         * XXX not passing NULL at for direct attach!
@@ -983,6 +1078,17 @@ ahci_xpt_scsi_disk_io(struct ahci_port *ap, struct ata_port *atx,
                              sizeof(rdata->inquiry_data.revision));
                        ccbh->status = CAM_REQ_CMP;
                }
                              sizeof(rdata->inquiry_data.revision));
                        ccbh->status = CAM_REQ_CMP;
                }
+               
+               /*
+                * Use the vendor specific area to set the TRIM status
+                * for scsi_da
+                */
+               if (at->at_identify.support_dsm) {
+                       rdata->inquiry_data.vendor_specific1[0] =
+                           at->at_identify.support_dsm &ATA_SUPPORT_DSM_TRIM;
+                       rdata->inquiry_data.vendor_specific1[1] = 
+                           at->at_identify.max_dsm_blocks;
+               }
                break;
        case READ_CAPACITY_16:
                if (cdb->read_capacity_16.service_action != SRC16_SERVICE_ACTION) {
                break;
        case READ_CAPACITY_16:
                if (cdb->read_capacity_16.service_action != SRC16_SERVICE_ACTION) {
@@ -1032,9 +1138,39 @@ ahci_xpt_scsi_disk_io(struct ahci_port *ap, struct ata_port *atx,
                if (xa->timeout < 45000)
                        xa->timeout = 45000;
                xa->datalen = 0;
                if (xa->timeout < 45000)
                        xa->timeout = 45000;
                xa->datalen = 0;
-               xa->flags = ATA_F_READ;
+               xa->flags = 0;
                xa->complete = ahci_ata_complete_disk_synchronize_cache;
                break;
                xa->complete = ahci_ata_complete_disk_synchronize_cache;
                break;
+       case TRIM:
+               fis = xa->fis;
+               fis->command = ATA_C_DATA_SET_MANAGEMENT;
+               fis->features = (u_int8_t)ATA_SF_DSM_TRIM;
+               fis->features_exp = (u_int8_t)(ATA_SF_DSM_TRIM>> 8);
+
+               xa->flags = ATA_F_WRITE;
+               fis->flags = ATA_H2D_FLAGS_CMD;
+
+               xa->data = csio->data_ptr;
+               xa->datalen = csio->dxfer_len;
+               xa->timeout = ccbh->timeout*50; /* milliseconds */
+
+               fis->sector_count =(u_int8_t)(xa->datalen/512);
+               fis->sector_count_exp =(u_int8_t)((xa->datalen/512)>>8);
+
+               lba = 0;
+               fis->lba_low = (u_int8_t)lba;
+               fis->lba_mid = (u_int8_t)(lba >> 8);
+               fis->lba_high = (u_int8_t)(lba >> 16);
+               fis->lba_low_exp = (u_int8_t)(lba >> 24);
+               fis->lba_mid_exp = (u_int8_t)(lba >> 32);
+               fis->lba_high_exp = (u_int8_t)(lba >> 40);
+                  
+               fis->device = ATA_H2D_DEVICE_LBA;
+               xa->data = csio->data_ptr;
+
+               xa->complete = ahci_ata_complete_disk_rw;
+               ccbh->status = CAM_REQ_INPROG;
+               break;
        case TEST_UNIT_READY:
        case START_STOP_UNIT:
        case PREVENT_ALLOW:
        case TEST_UNIT_READY:
        case START_STOP_UNIT:
        case PREVENT_ALLOW:
@@ -1045,11 +1181,92 @@ ahci_xpt_scsi_disk_io(struct ahci_port *ap, struct ata_port *atx,
                rdata_len = 0;
                break;
        case ATA_PASS_12:
                rdata_len = 0;
                break;
        case ATA_PASS_12:
+               atp12 = &cdb->ata_pass_12;
+               fis = xa->fis;
+               /*
+                * Figure out the flags to be used, depending on the direction of the
+                * CAM request.
+                */
+               switch (ccbh->flags & CAM_DIR_MASK) {
+               case CAM_DIR_IN:
+                       xa->flags = ATA_F_READ;
+                       break;
+               case CAM_DIR_OUT:
+                       xa->flags = ATA_F_WRITE;
+                       break;
+               default:
+                       xa->flags = 0;
+               }
+               xa->flags |= ATA_F_POLL | ATA_F_EXCLUSIVE;
+               xa->data = csio->data_ptr;
+               xa->datalen = csio->dxfer_len;
+               xa->complete = ahci_ata_complete_disk_rw;
+               xa->timeout = ccbh->timeout;
+
+               /*
+                * Populate the fis from the information we received through CAM
+                * ATA passthrough.
+                */
+               fis->flags = ATA_H2D_FLAGS_CMD; /* maybe also atp12->flags ? */
+               fis->features = atp12->features;
+               fis->sector_count = atp12->sector_count;
+               fis->lba_low = atp12->lba_low;
+               fis->lba_mid = atp12->lba_mid;
+               fis->lba_high = atp12->lba_high;
+               fis->device = atp12->device;    /* maybe always 0? */
+               fis->command = atp12->command;
+               fis->control = atp12->control;
+
+               /*
+                * Mark as in progress so it is sent to the device.
+                */
+               ccbh->status = CAM_REQ_INPROG;
+               break;
        case ATA_PASS_16:
        case ATA_PASS_16:
+               atp16 = &cdb->ata_pass_16;
+               fis = xa->fis;
                /*
                /*
-                * XXX implement pass-through
+                * Figure out the flags to be used, depending on the direction of the
+                * CAM request.
                 */
                 */
-               ccbh->status = CAM_FUNC_NOTAVAIL;
+               switch (ccbh->flags & CAM_DIR_MASK) {
+               case CAM_DIR_IN:
+                       xa->flags = ATA_F_READ;
+                       break;
+               case CAM_DIR_OUT:
+                       xa->flags = ATA_F_WRITE;
+                       break;
+               default:
+                       xa->flags = 0;
+               }
+               xa->flags |= ATA_F_POLL | ATA_F_EXCLUSIVE;
+               xa->data = csio->data_ptr;
+               xa->datalen = csio->dxfer_len;
+               xa->complete = ahci_ata_complete_disk_rw;
+               xa->timeout = ccbh->timeout;
+
+               /*
+                * Populate the fis from the information we received through CAM
+                * ATA passthrough.
+                */
+               fis->flags = ATA_H2D_FLAGS_CMD; /* maybe also atp16->flags ? */
+               fis->features = atp16->features;
+               fis->features_exp = atp16->features_ext;
+               fis->sector_count = atp16->sector_count;
+               fis->sector_count_exp = atp16->sector_count_ext;
+               fis->lba_low = atp16->lba_low;
+               fis->lba_low_exp = atp16->lba_low_ext;
+               fis->lba_mid = atp16->lba_mid;
+               fis->lba_mid_exp = atp16->lba_mid_ext;
+               fis->lba_high = atp16->lba_high;
+               fis->lba_mid_exp = atp16->lba_mid_ext;
+               fis->device = atp16->device;    /* maybe always 0? */
+               fis->command = atp16->command;
+
+               /*
+                * Mark as in progress so it is sent to the device.
+                */
+               ccbh->status = CAM_REQ_INPROG;
                break;
        default:
                switch(cdb->generic.opcode) {
                break;
        default:
                switch(cdb->generic.opcode) {
@@ -1204,7 +1421,7 @@ ahci_xpt_scsi_atapi_io(struct ahci_port *ap, struct ata_port *atx,
 
        ccbh = &ccb->csio.ccb_h;
        csio = &ccb->csio;
 
        ccbh = &ccb->csio.ccb_h;
        csio = &ccb->csio;
-       at = atx ? atx : &ap->ap_ata[0];
+       at = atx ? atx : ap->ap_ata[0];
 
        switch (ccbh->flags & CAM_DIR_MASK) {
        case CAM_DIR_IN:
 
        switch (ccbh->flags & CAM_DIR_MASK) {
        case CAM_DIR_IN:
@@ -1277,10 +1494,14 @@ ahci_xpt_scsi_atapi_io(struct ahci_port *ap, struct ata_port *atx,
        /*
         * Copy the cdb to the packetcmd buffer in the FIS using a
         * convenient pointer in the xa.
        /*
         * Copy the cdb to the packetcmd buffer in the FIS using a
         * convenient pointer in the xa.
+        *
+        * Zero-out any trailing bytes in case the ATAPI device cares.
         */
        cdbs = (void *)((ccbh->flags & CAM_CDB_POINTER) ?
                        csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes);
        bcopy(cdbs, xa->packetcmd, csio->cdb_len);
         */
        cdbs = (void *)((ccbh->flags & CAM_CDB_POINTER) ?
                        csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes);
        bcopy(cdbs, xa->packetcmd, csio->cdb_len);
+       if (csio->cdb_len < 16)
+               bzero(xa->packetcmd + csio->cdb_len, 16 - csio->cdb_len);
 
 #if 0
        kprintf("opcode %d cdb_len %d dxfer_len %d\n",
 
 #if 0
        kprintf("opcode %d cdb_len %d dxfer_len %d\n",
@@ -1301,8 +1522,10 @@ ahci_xpt_scsi_atapi_io(struct ahci_port *ap, struct ata_port *atx,
                 * It is unclear if this is needed or not.
                 */
                if (cdbd->sense.length == SSD_FULL_SIZE) {
                 * It is unclear if this is needed or not.
                 */
                if (cdbd->sense.length == SSD_FULL_SIZE) {
-                       kprintf("%s: Shortening sense request\n",
-                               PORTNAME(ap));
+                       if (bootverbose) {
+                               kprintf("%s: Shortening sense request\n",
+                                       PORTNAME(ap));
+                       }
                        cdbd->sense.length = offsetof(struct scsi_sense_data,
                                                      extra_bytes[0]);
                }
                        cdbd->sense.length = offsetof(struct scsi_sense_data,
                                                      extra_bytes[0]);
                }