]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] forward port of the various scsi fixes from 2.4
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Sat, 12 Oct 2002 10:19:13 +0000 (03:19 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Sat, 12 Oct 2002 10:19:13 +0000 (03:19 -0700)
drivers/scsi/scsi.c
drivers/scsi/scsi.h
drivers/scsi/scsi_error.c
drivers/scsi/scsi_ioctl.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_syms.c
drivers/scsi/sd.c
drivers/scsi/sr.c
drivers/scsi/sr.h
drivers/scsi/sr_ioctl.c
drivers/scsi/sr_vendor.c

index 5e6a2db44da5654002c66bede3713dcba1d95b37..1ba787fcad2efb1570755b36276a7e7cc720a35e 100644 (file)
@@ -1399,14 +1399,10 @@ static void scsi_softirq(struct softirq_action *h)
  */
 int scsi_retry_command(Scsi_Cmnd * SCpnt)
 {
-       memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
-              sizeof(SCpnt->data_cmnd));
-       SCpnt->request_buffer = SCpnt->buffer;
-       SCpnt->request_bufflen = SCpnt->bufflen;
-       SCpnt->use_sg = SCpnt->old_use_sg;
-       SCpnt->cmd_len = SCpnt->old_cmd_len;
-       SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
-       SCpnt->underflow = SCpnt->old_underflow;
+       /*
+        * Restore the SCSI command state.
+        */
+       scsi_setup_cmd_retry(SCpnt);
 
         /*
          * Zero the sense information from the last time we tried
index 128b1e5e73357825ddef211177b2a25cb8744e6d..36e18809fca9c5881cc9b2328a0f173dd2bdc129 100644 (file)
@@ -467,6 +467,7 @@ extern Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate,
                                   int sectors);
 extern struct Scsi_Device_Template *scsi_get_request_dev(struct request *);
 extern int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt);
+extern void scsi_setup_cmd_retry(Scsi_Cmnd *SCpnt);
 extern int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int);
 extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
                               int block_sectors);
@@ -597,9 +598,10 @@ struct scsi_device {
        unsigned changed:1;     /* Data invalid due to media change */
        unsigned busy:1;        /* Used to prevent races */
        unsigned lockable:1;    /* Able to prevent media removal */
+       unsigned locked:1;      /* Media removal disabled */
        unsigned borken:1;      /* Tell the Seagate driver to be 
                                 * painfully slow on this device */
-//     unsigned disconnect:1;  /* can disconnect */
+       unsigned disconnect:1;  /* can disconnect */
        unsigned soft_reset:1;  /* Uses soft reset option */
        unsigned sdtr:1;        /* Device supports SDTR messages */
        unsigned wdtr:1;        /* Device supports WDTR messages */
index 7e5d1594ae60256eec2d4776a995070cea77f298..386857db783d7755cff7d80a4b374ed81a75b11f 100644 (file)
@@ -8,6 +8,10 @@
  *
  *     Restructured scsi_unjam_host and associated functions.
  *     September 04, 2002 Mike Anderson (andmike@us.ibm.com)
+ *
+ *     Forward port of Russell King's (rmk@arm.linux.org.uk) changes and
+ *     minor  cleanups.
+ *     September 30, 2002 Mike Anderson (andmike@us.ibm.com)
  */
 
 #include <linux/module.h>
@@ -35,6 +39,8 @@
 #include "scsi.h"
 #include "hosts.h"
 
+#include <scsi/scsi_ioctl.h> /* grr */
+
 /*
  * We must always allow SHUTDOWN_SIGS.  Even if we are not a module,
  * the host drivers that we are using may be loaded as modules, and
@@ -59,7 +65,7 @@
  * These should *probably* be handled by the host itself.
  * Since it is allowed to sleep, it probably should.
  */
-#define BUS_RESET_SETTLE_TIME   5*HZ
+#define BUS_RESET_SETTLE_TIME   10*HZ
 #define HOST_RESET_SETTLE_TIME  10*HZ
 
 /**
@@ -91,9 +97,9 @@ void scsi_add_timer(Scsi_Cmnd *scmd, int timeout, void (*complete)
        scmd->eh_timeout.expires = jiffies + timeout;
        scmd->eh_timeout.function = (void (*)(unsigned long)) complete;
 
-       SCSI_LOG_ERROR_RECOVERY(5, printk("Adding timer for command %p at"
-                                         "%d (%p)\n", scmd, timeout,
-                                         complete));
+       SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p, time:"
+                                         " %d, (%p)\n", __FUNCTION__,
+                                         scmd, timeout, complete));
 
        add_timer(&scmd->eh_timeout);
 
@@ -116,8 +122,9 @@ int scsi_delete_timer(Scsi_Cmnd *scmd)
 
        rtn = del_timer(&scmd->eh_timeout);
 
-       SCSI_LOG_ERROR_RECOVERY(5, printk("Clearing timer for command %p"
-                                        " %d\n", scmd, rtn));
+       SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p,"
+                                        " rtn: %d\n", __FUNCTION__,
+                                        scmd, rtn));
 
        scmd->eh_timeout.data = (unsigned long) NULL;
        scmd->eh_timeout.function = NULL;
@@ -150,7 +157,7 @@ void scsi_times_out(Scsi_Cmnd *scmd)
        scsi_host_failed_inc_and_test(scmd->host);
 
        SCSI_LOG_TIMEOUT(3, printk("Command timed out active=%d busy=%d "
-                                  "failed=%d\n",
+                                  " failed=%d\n",
                                   atomic_read(&scmd->host->host_active),
                                   scmd->host->host_busy,
                                   scmd->host->host_failed));
@@ -173,7 +180,7 @@ int scsi_block_when_processing_errors(Scsi_Device *sdev)
 
        SCSI_SLEEP(&sdev->host->host_wait, sdev->host->in_recovery);
 
-       SCSI_LOG_ERROR_RECOVERY(5, printk("Open returning %d\n",
+       SCSI_LOG_ERROR_RECOVERY(5, printk("%s: rtn: %d\n", __FUNCTION__,
                                          sdev->online));
 
        return sdev->online;
@@ -209,10 +216,10 @@ static void scsi_eh_prt_fail_stats(Scsi_Cmnd *sc_list, struct Scsi_Host *shost)
 
                if (cmd_timed_out || cmd_failed) {
                        SCSI_LOG_ERROR_RECOVERY(3,
-                               printk("scsi_eh: %d:%d:%d:%d cmds failed: %d,"
-                                      "timedout: %d\n",
-                                      shost->host_no, sdev->channel,
-                                      sdev->id, sdev->lun,
+                               printk("%s: %d:%d:%d:%d cmds failed: %d,"
+                                      " timedout: %d\n",
+                                      __FUNCTION__, shost->host_no,
+                                      sdev->channel, sdev->id, sdev->lun,
                                       cmd_failed, cmd_timed_out));
                        cmd_timed_out = 0;
                        cmd_failed = 0;
@@ -220,8 +227,8 @@ static void scsi_eh_prt_fail_stats(Scsi_Cmnd *sc_list, struct Scsi_Host *shost)
                }
        }
 
-       SCSI_LOG_ERROR_RECOVERY(2, printk("Total of %d commands on %d "
-                                         "devices require eh work\n",
+       SCSI_LOG_ERROR_RECOVERY(2, printk("Total of %d commands on %d"
+                                         " devices require eh work\n",
                                  total_failures, devices_failed));
 }
 #endif
@@ -265,10 +272,10 @@ static void scsi_eh_get_failed(Scsi_Cmnd **sc_list, struct Scsi_Host *shost)
                                 * queued and will be finished along the
                                 * way.
                                 */
-                               SCSI_LOG_ERROR_RECOVERY(1, printk("Error hdlr "
-                                                         "prematurely woken "
-                                                         "cmds still active "
-                                                         "(%p %x %d)\n",
+                               SCSI_LOG_ERROR_RECOVERY(1, printk("Error hdlr"
+                                                         " prematurely woken"
+                                                         " cmds still active"
+                                                         " (%p %x %d)\n",
                                               scmd, scmd->state,
                                               scmd->target));
                                }
@@ -278,12 +285,17 @@ static void scsi_eh_get_failed(Scsi_Cmnd **sc_list, struct Scsi_Host *shost)
 
        SCSI_LOG_ERROR_RECOVERY(1, scsi_eh_prt_fail_stats(*sc_list, shost));
 
-       BUG_ON(shost->host_failed != found);
+       if (shost->host_failed != found)
+               printk(KERN_ERR "%s: host_failed: %d != found: %d\n", 
+                      __FUNCTION__, shost->host_failed, found);
 }
 
 /**
  * scsi_check_sense - Examine scsi cmd sense
  * @scmd:      Cmd to have sense checked.
+ *
+ * Return value:
+ *     SUCCESS or FAILED or NEEDS_RETRY
  **/
 static int scsi_check_sense(Scsi_Cmnd *scmd)
 {
@@ -353,7 +365,6 @@ static int scsi_check_sense(Scsi_Cmnd *scmd)
  **/
 static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
 {
-       int rtn;
 
        /*
         * first check the host byte, to see if there is anything in there
@@ -369,7 +380,7 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
                         * SUCCESS.
                         */
                        scmd->flags &= ~IS_RESETTING;
-                       goto maybe_retry;
+                       return NEEDS_RETRY;
                }
                /*
                 * rats.  we are already in the error handler, so we now
@@ -377,10 +388,7 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
                 * is valid, we have a pretty good idea of what to do.
                 * if not, we mark it as FAILED.
                 */
-               rtn = scsi_check_sense(scmd);
-               if (rtn == NEEDS_RETRY)
-                       goto maybe_retry;
-               return rtn;
+               return scsi_check_sense(scmd);
        }
        if (host_byte(scmd->result) != DID_OK) {
                return FAILED;
@@ -400,10 +408,7 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
        case COMMAND_TERMINATED:
                return SUCCESS;
        case CHECK_CONDITION:
-               rtn = scsi_check_sense(scmd);
-               if (rtn == NEEDS_RETRY)
-                       goto maybe_retry;
-               return rtn;
+               return scsi_check_sense(scmd);
        case CONDITION_GOOD:
        case INTERMEDIATE_GOOD:
        case INTERMEDIATE_C_GOOD:
@@ -418,14 +423,6 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
                return FAILED;
        }
        return FAILED;
-
- maybe_retry:
-       if ((++scmd->retries) < scmd->allowed) {
-               return NEEDS_RETRY;
-       } else {
-               /* no more retries - report this one back to upper level */
-               return SUCCESS;
-       }
 }
 
 /**
@@ -440,12 +437,13 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
 static void scsi_eh_times_out(Scsi_Cmnd *scmd)
 {
        scsi_eh_eflags_set(scmd, SCSI_EH_REC_TIMEOUT);
-       SCSI_LOG_ERROR_RECOVERY(3, printk("in scsi_eh_times_out %p\n", scmd));
+       SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd:%p\n", __FUNCTION__,
+                                         scmd));
 
        if (scmd->host->eh_action != NULL)
                up(scmd->host->eh_action);
        else
-               printk("missing scsi error handler thread\n");
+               printk("%s: eh_action NULL\n", __FUNCTION__);
 }
 
 /**
@@ -471,8 +469,8 @@ static void scsi_eh_done(Scsi_Cmnd *scmd)
 
        scmd->owner = SCSI_OWNER_ERROR_HANDLER;
 
-       SCSI_LOG_ERROR_RECOVERY(3, printk("in eh_done %p result:%x\n", scmd,
-                                         scmd->result));
+       SCSI_LOG_ERROR_RECOVERY(3, printk("%s scmd: %p result: %x\n",
+                                         __FUNCTION__, scmd, scmd->result));
 
        if (scmd->host->eh_action != NULL)
                up(scmd->host->eh_action);
@@ -488,7 +486,7 @@ static void scsi_eh_done(Scsi_Cmnd *scmd)
  *    this case, and furthermore, there is a different completion handler
  *    vs scsi_dispatch_cmd.
  * Return value:
- *    SUCCESS/FAILED
+ *    SUCCESS or FAILED or NEEDS_RETRY
  **/
 static int scsi_send_eh_cmnd(Scsi_Cmnd *scmd, int timeout)
 {
@@ -498,7 +496,6 @@ static int scsi_send_eh_cmnd(Scsi_Cmnd *scmd, int timeout)
 
        ASSERT_LOCK(host->host_lock, 0);
 
-retry:
        /*
         * we will use a queued command if possible, otherwise we will
         * emulate the queuing and calling of completion function ourselves.
@@ -552,9 +549,8 @@ retry:
                        
                        rtn = FAILED;
                }
-               SCSI_LOG_ERROR_RECOVERY(3, printk("%s: %p rtn:%x\n",
-                                                 __FUNCTION__, scmd,
-                                                 rtn));
+               SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd: %p, rtn:%x\n",
+                                                 __FUNCTION__, scmd, rtn));
        } else {
                int temp;
 
@@ -576,16 +572,15 @@ retry:
         * actually did complete normally.
         */
        if (rtn == SUCCESS) {
-               int ret = scsi_eh_completed_normally(scmd);
+               int rtn = scsi_eh_completed_normally(scmd);
                SCSI_LOG_ERROR_RECOVERY(3,
                        printk("%s: scsi_eh_completed_normally %x\n",
-                              __FUNCTION__, ret));
-               switch (ret) {
+                              __FUNCTION__, rtn));
+               switch (rtn) {
                case SUCCESS:
-                       break;
                case NEEDS_RETRY:
-                       goto retry;
                case FAILED:
+                       break;
                default:
                        rtn = FAILED;
                        break;
@@ -622,7 +617,7 @@ static int scsi_request_sense(Scsi_Cmnd *scmd)
            ? &scsi_result0[0] : kmalloc(512, GFP_ATOMIC | GFP_DMA);
 
        if (scsi_result == NULL) {
-               printk("cannot allocate scsi_result in scsi_request_sense.\n");
+               printk("%s: cannot allocate scsi_result.\n", __FUNCTION__);
                return FAILED;
        }
        /*
@@ -657,15 +652,8 @@ static int scsi_request_sense(Scsi_Cmnd *scmd)
         * when we eventually call scsi_finish, we really wish to complete
         * the original request, so let's restore the original data. (db)
         */
-       memcpy((void *) scmd->cmnd, (void *) scmd->data_cmnd,
-              sizeof(scmd->data_cmnd));
+       scsi_setup_cmd_retry(scmd);
        scmd->result = saved_result;
-       scmd->request_buffer = scmd->buffer;
-       scmd->request_bufflen = scmd->bufflen;
-       scmd->use_sg = scmd->old_use_sg;
-       scmd->cmd_len = scmd->old_cmd_len;
-       scmd->sc_data_direction = scmd->sc_old_data_direction;
-       scmd->underflow = scmd->old_underflow;
 
        /*
         * hey, we are done.  let's look to see what happened.
@@ -683,16 +671,16 @@ static int scsi_request_sense(Scsi_Cmnd *scmd)
  **/
 static int scsi_eh_retry_cmd(Scsi_Cmnd *scmd)
 {
-       memcpy((void *) scmd->cmnd, (void *) scmd->data_cmnd,
-              sizeof(scmd->data_cmnd));
-       scmd->request_buffer = scmd->buffer;
-       scmd->request_bufflen = scmd->bufflen;
-       scmd->use_sg = scmd->old_use_sg;
-       scmd->cmd_len = scmd->old_cmd_len;
-       scmd->sc_data_direction = scmd->sc_old_data_direction;
-       scmd->underflow = scmd->old_underflow;
-
-       return scsi_send_eh_cmnd(scmd, scmd->timeout_per_command);
+       int rtn = SUCCESS;
+
+       for (; scmd->retries < scmd->allowed; scmd->retries++) {
+               scsi_setup_cmd_retry(scmd);
+               rtn = scsi_send_eh_cmnd(scmd, scmd->timeout_per_command);
+               if (rtn != NEEDS_RETRY)
+                       break;
+       }
+
+       return rtn;
 }
 
 /**
@@ -717,9 +705,7 @@ static void scsi_eh_finish_cmd(Scsi_Cmnd *scmd, struct Scsi_Host *shost)
         * set this back so that the upper level can correctly free up
         * things.
         */
-       scmd->use_sg = scmd->old_use_sg;
-       scmd->sc_data_direction = scmd->sc_old_data_direction;
-       scmd->underflow = scmd->old_underflow;
+       scsi_setup_cmd_retry(scmd);
 }
 
 /**
@@ -758,14 +744,14 @@ static int scsi_eh_get_sense(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
                        continue;
 
                SCSI_LOG_ERROR_RECOVERY(2, printk("%s: requesting sense"
-                                                 "for %d\n", __FUNCTION__,
-                                                 scmd->target));
+                                                 " for tgt: %d\n",
+                                                 __FUNCTION__, scmd->target));
                rtn = scsi_request_sense(scmd);
                if (rtn != SUCCESS)
                        continue;
 
                SCSI_LOG_ERROR_RECOVERY(3, printk("sense requested for %p"
-                                                 "- result %x\n", scmd,
+                                                 " result %x\n", scmd,
                                                  scmd->result));
                SCSI_LOG_ERROR_RECOVERY(3, print_sense("bh", scmd));
 
@@ -847,7 +833,9 @@ static int scsi_eh_tur(Scsi_Cmnd *scmd)
        static unsigned char tur_command[6] =
        {TEST_UNIT_READY, 0, 0, 0, 0, 0};
        int rtn;
+       int retry_cnt = 1;
 
+retry_tur:
        memcpy((void *) scmd->cmnd, (void *) tur_command,
               sizeof(tur_command));
 
@@ -873,32 +861,18 @@ static int scsi_eh_tur(Scsi_Cmnd *scmd)
         * when we eventually call scsi_finish, we really wish to complete
         * the original request, so let's restore the original data. (db)
         */
-       memcpy((void *) scmd->cmnd, (void *) scmd->data_cmnd,
-              sizeof(scmd->data_cmnd));
-       scmd->request_buffer = scmd->buffer;
-       scmd->request_bufflen = scmd->bufflen;
-       scmd->use_sg = scmd->old_use_sg;
-       scmd->cmd_len = scmd->old_cmd_len;
-       scmd->sc_data_direction = scmd->sc_old_data_direction;
-       scmd->underflow = scmd->old_underflow;
+       scsi_setup_cmd_retry(scmd);
 
        /*
         * hey, we are done.  let's look to see what happened.
         */
-       SCSI_LOG_ERROR_RECOVERY(3,
-               printk("%s: scmd %p rtn %x\n",
+       SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
                __FUNCTION__, scmd, rtn));
-       if ((rtn == SUCCESS) && scmd->result) {
-               if (((driver_byte(scmd->result) & DRIVER_SENSE) ||
-                    (status_byte(scmd->result) & CHECK_CONDITION)) &&
-                   (SCSI_SENSE_VALID(scmd))) {
-                       if (((scmd->sense_buffer[2] & 0xf) != NOT_READY) &&
-                           ((scmd->sense_buffer[2] & 0xf) != UNIT_ATTENTION) &&
-                           ((scmd->sense_buffer[2] & 0xf) != ILLEGAL_REQUEST)) {
-                               return 0;
-                       }
-               }
-       }
+       if (rtn == SUCCESS)
+               return 0;
+       else if (rtn == NEEDS_RETRY)
+               if (retry_cnt--)
+                       goto retry_tur;
        return 1;
 }
 
@@ -929,7 +903,7 @@ static int scsi_eh_abort_cmd(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
 
                rtn = scsi_try_to_abort_cmd(scmd);
                if (rtn == SUCCESS) {
-                       if (scsi_eh_tur(scmd)) {
+                       if (!scsi_eh_tur(scmd)) {
                                rtn = scsi_eh_retry_cmd(scmd);
                                if (rtn == SUCCESS)
                                        scsi_eh_finish_cmd(scmd, shost);
@@ -963,6 +937,11 @@ static int scsi_try_bus_device_reset(Scsi_Cmnd *scmd)
        rtn = scmd->host->hostt->eh_device_reset_handler(scmd);
        spin_unlock_irqrestore(scmd->host->host_lock, flags);
 
+       if (rtn == SUCCESS) {
+               scmd->device->was_reset = 1;
+               scmd->device->expecting_cc_ua = 1;
+       }
+
        return rtn;
 }
 
@@ -999,7 +978,7 @@ static int scsi_eh_bus_device_reset(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
                 * a bus device reset to it.
                 */
                rtn = scsi_try_bus_device_reset(scmd);
-               if ((rtn == SUCCESS) && (scsi_eh_tur(scmd)))
+               if ((rtn == SUCCESS) && (!scsi_eh_tur(scmd)))
                                for (scmd = sc_todo; scmd; scmd = scmd->bh_next)
                                        if ((scmd->device == sdev) &&
                                            scsi_eh_eflags_chk(scmd, SCSI_EH_CMD_ERR)) {
@@ -1141,7 +1120,7 @@ static int scsi_eh_bus_host_reset(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
                                if (!scsi_eh_eflags_chk(scmd, SCSI_EH_CMD_ERR)
                                    || channel != scmd->channel)
                                        continue;
-                               if (scsi_eh_tur(scmd)) {
+                               if (!scsi_eh_tur(scmd)) {
                                        rtn = scsi_eh_retry_cmd(scmd);
 
                                        if (rtn == SUCCESS)
@@ -1168,10 +1147,10 @@ static void scsi_eh_offline_sdevs(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
                if (!scsi_eh_eflags_chk(scmd, SCSI_EH_CMD_ERR))
                        continue;
 
-               printk(KERN_INFO "%s: Device set offline - not"
-                               "ready or command retry failed"
-                               "after error recovery: host"
-                               "%d channel %d id %d lun %d\n",
+               printk(KERN_INFO "%s: Device offlined - not"
+                               " ready or command retry failed"
+                               " after error recovery: host"
+                               " %d channel %d id %d lun %d\n",
                                __FUNCTION__, shost->host_no,
                                scmd->device->channel,
                                scmd->device->id,
@@ -1243,7 +1222,7 @@ int scsi_decide_disposition(Scsi_Cmnd *scmd)
         */
        if (scmd->device->online == FALSE) {
                SCSI_LOG_ERROR_RECOVERY(5, printk("%s: device offline - report"
-                                                 "as SUCCESS\n",
+                                                 " as SUCCESS\n",
                                                  __FUNCTION__));
                return SUCCESS;
        }
@@ -1367,7 +1346,7 @@ int scsi_decide_disposition(Scsi_Cmnd *scmd)
                return SUCCESS;
 
        case RESERVATION_CONFLICT:
-               printk("scsi%d (%d,%d,%d) : reservation conflict\n", 
+               printk("scsi%d (%d,%d,%d) : reservation conflict\n",
                       scmd->host->host_no, scmd->channel,
                       scmd->device->id, scmd->device->lun);
                return SUCCESS; /* causes immediate i/o error */
@@ -1388,6 +1367,75 @@ int scsi_decide_disposition(Scsi_Cmnd *scmd)
        }
 }
 
+/**
+ * scsi_eh_lock_done - done function for eh door lock request
+ * @scmd:      SCSI command block for the door lock request
+ *
+ * Notes:
+ *     We completed the asynchronous door lock request, and it has either
+ *     locked the door or failed.  We must free the command structures
+ *     associated with this request.
+ **/
+static void scsi_eh_lock_done(struct scsi_cmnd *scmd)
+{
+       struct scsi_request *sreq = scmd->sc_request;
+
+       scmd->sc_request = NULL;
+       sreq->sr_command = NULL;
+
+       scsi_release_command(scmd);
+       scsi_release_request(sreq);
+}
+
+
+/**
+ * scsi_eh_lock_door - Prevent medium removal for the specified device
+ * @sdev:      SCSI device to prevent medium removal
+ *
+ * Locking:
+ *     We must be called from process context; scsi_allocate_request()
+ *     may sleep.
+ *
+ * Notes:
+ *     We queue up an asynchronous "ALLOW MEDIUM REMOVAL" request on the
+ *     head of the devices request queue, and continue.
+ *
+ * Bugs:
+ *     scsi_allocate_request() may sleep waiting for existing requests to
+ *     be processed.  However, since we haven't kicked off any request
+ *     processing for this host, this may deadlock.
+ *
+ *     If scsi_allocate_request() fails for what ever reason, we
+ *     completely forget to lock the door.
+ **/
+static void scsi_eh_lock_door(struct scsi_device *sdev)
+{
+       struct scsi_request *sreq = scsi_allocate_request(sdev);
+
+       if (sreq == NULL) {
+               printk(KERN_ERR "%s: request allocate failed,"
+                      "prevent media removal cmd not sent", __FUNCTION__);
+               return;
+       }
+
+       sreq->sr_cmnd[0] = ALLOW_MEDIUM_REMOVAL;
+       sreq->sr_cmnd[1] = (sdev->scsi_level <= SCSI_2) ? (sdev->lun << 5) : 0;
+       sreq->sr_cmnd[2] = 0;
+       sreq->sr_cmnd[3] = 0;
+       sreq->sr_cmnd[4] = SCSI_REMOVAL_PREVENT;
+       sreq->sr_cmnd[5] = 0;
+       sreq->sr_data_direction = SCSI_DATA_NONE;
+       sreq->sr_bufflen = 0;
+       sreq->sr_buffer = NULL;
+       sreq->sr_allowed = 5;
+       sreq->sr_done = scsi_eh_lock_done;
+       sreq->sr_timeout_per_command = 10 * HZ;
+       sreq->sr_cmd_len = COMMAND_SIZE(sreq->sr_cmnd[0]);
+
+       scsi_insert_special_req(sreq, 1);
+}
+
+
 /**
  * scsi_restart_operations - restart io operations to the specified host.
  * @shost:     Host we are restarting.
@@ -1403,6 +1451,15 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
 
        ASSERT_LOCK(shost->host_lock, 0);
 
+       /*
+        * If the door was locked, we need to insert a door lock request
+        * onto the head of the SCSI request queue for the device.  There
+        * is no point trying to lock the door of an off-line device.
+        */
+       for (sdev = shost->host_queue; sdev; sdev = sdev->next)
+               if (sdev->online && sdev->locked)
+                       scsi_eh_lock_door(sdev);
+
        /*
         * next free up anything directly waiting upon the host.  this
         * will be requests for character device operations, and also for
@@ -1426,8 +1483,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
                if ((shost->can_queue > 0 &&
                     (shost->host_busy >= shost->can_queue))
                    || (shost->host_blocked)
-                   || (shost->host_self_blocked)
-                   || (sdev->device_blocked)) {
+                   || (shost->host_self_blocked)) {
                        break;
                }
 
@@ -1475,7 +1531,7 @@ static void scsi_unjam_host(struct Scsi_Host *shost)
        if (scsi_eh_get_sense(sc_todo, shost))
                if (scsi_eh_abort_cmd(sc_todo, shost))
                        if (scsi_eh_bus_device_reset(sc_todo, shost))
-                               if(scsi_eh_bus_host_reset(sc_todo, shost))
+                               if (scsi_eh_bus_host_reset(sc_todo, shost))
                                        scsi_eh_offline_sdevs(sc_todo, shost);
 
        BUG_ON(shost->host_failed);
@@ -1563,8 +1619,7 @@ void scsi_error_handler(void *data)
        /*
         * Wake up the thread that created us.
         */
-       SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent %d\n",
-                                         shost->eh_notify->count.counter));
+       SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent \n"));
 
        up(shost->eh_notify);
 
index 80f23e46a9e4ff8005a73fee12c0848deb1a7276..d1c431cc4017cb8b24f4aa1bcb2130d02073b020 100644 (file)
@@ -151,6 +151,29 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd,
        return result;
 }
 
+int scsi_set_medium_removal(Scsi_Device *dev, char state)
+{
+       char scsi_cmd[MAX_COMMAND_SIZE];
+       int ret;
+
+       if (!dev->removable || !dev->lockable)
+              return 0;
+
+       scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
+       scsi_cmd[1] = (dev->scsi_level <= SCSI_2) ? (dev->lun << 5) : 0;
+       scsi_cmd[2] = 0;
+       scsi_cmd[3] = 0;
+       scsi_cmd[4] = state;
+       scsi_cmd[5] = 0;
+
+       ret = ioctl_internal_command(dev, scsi_cmd, IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
+
+       if (ret == 0)
+               dev->locked = state == SCSI_REMOVAL_PREVENT;
+
+       return ret;
+}
+
 /*
  * This interface is deprecated - users should use the scsi generic (sg)
  * interface instead, as this is a more flexible approach to performing
@@ -456,24 +479,9 @@ int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg)
                return scsi_ioctl_send_command((Scsi_Device *) dev,
                                             (Scsi_Ioctl_Command *) arg);
        case SCSI_IOCTL_DOORLOCK:
-               if (!dev->removable || !dev->lockable)
-                       return 0;
-               scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
-               scsi_cmd[1] = cmd_byte1;
-               scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
-               scsi_cmd[4] = SCSI_REMOVAL_PREVENT;
-               return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
-                                  IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
-               break;
+               return scsi_set_medium_removal(dev, SCSI_REMOVAL_PREVENT);
        case SCSI_IOCTL_DOORUNLOCK:
-               if (!dev->removable || !dev->lockable)
-                       return 0;
-               scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
-               scsi_cmd[1] = cmd_byte1;
-               scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
-               scsi_cmd[4] = SCSI_REMOVAL_ALLOW;
-               return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
-                                  IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
+               return scsi_set_medium_removal(dev, SCSI_REMOVAL_ALLOW);
        case SCSI_IOCTL_TEST_UNIT_READY:
                scsi_cmd[0] = TEST_UNIT_READY;
                scsi_cmd[1] = cmd_byte1;
index e06c020ad0725f917077dd36aa2a1615405e4876..a73a677e68180886998f61b303b3de432a66243e 100644 (file)
@@ -159,6 +159,30 @@ int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt)
        return 1;
 }
 
+/*
+ * Function:   scsi_setup_cmd_retry()
+ *
+ * Purpose:    Restore the command state for a retry
+ *
+ * Arguments:  SCpnt   - command to be restored
+ *
+ * Returns:    Nothing
+ *
+ * Notes:      Immediately prior to retrying a command, we need
+ *             to restore certain fields that we saved above.
+ */
+void scsi_setup_cmd_retry(Scsi_Cmnd *SCpnt)
+{
+       memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
+               sizeof(SCpnt->data_cmnd));
+       SCpnt->request_buffer = SCpnt->buffer;
+       SCpnt->request_bufflen = SCpnt->bufflen;
+       SCpnt->use_sg = SCpnt->old_use_sg;
+       SCpnt->cmd_len = SCpnt->old_cmd_len;
+       SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
+       SCpnt->underflow = SCpnt->old_underflow;
+}
+
 /*
  * Function:    scsi_queue_next_request()
  *
@@ -614,7 +638,7 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
                        printk("scsi%d: ERROR on channel %d, id %d, lun %d, CDB: ",
                               SCpnt->host->host_no, (int) SCpnt->channel,
                               (int) SCpnt->target, (int) SCpnt->lun);
-                       print_command(SCpnt->cmnd);
+                       print_command(SCpnt->data_cmnd);
                        print_sense("sd", SCpnt);
                        SCpnt = scsi_end_request(SCpnt, 0, block_sectors);
                        return;
@@ -798,33 +822,6 @@ void scsi_request_fn(request_queue_t * q)
                        SDpnt->starved = 0;
                }
 
-               /*
-                * FIXME(eric)
-                * I am not sure where the best place to do this is.  We need
-                * to hook in a place where we are likely to come if in user
-                * space.   Technically the error handling thread should be
-                * doing this crap, but the error handler isn't used by
-                * most hosts.
-                */
-               if (SDpnt->was_reset) {
-                       /*
-                        * We need to relock the door, but we might
-                        * be in an interrupt handler.  Only do this
-                        * from user space, since we do not want to
-                        * sleep from an interrupt.
-                        *
-                        * FIXME(eric) - have the error handler thread do
-                        * this work.
-                        */
-                       SDpnt->was_reset = 0;
-                       if (SDpnt->removable && !in_interrupt()) {
-                               spin_unlock_irq(q->queue_lock);
-                               scsi_ioctl(SDpnt, SCSI_IOCTL_DOORLOCK, 0);
-                               spin_lock_irq(q->queue_lock);
-                               continue;
-                       }
-               }
-
                /*
                 * If we couldn't find a request that could be queued, then we
                 * can also quit.
index adaad88679f2ffe27e5fd79af152c2d830715fec..e85aeca9d8e6dc6beb48fd4f56dec6a7e1ee1c2e 100644 (file)
@@ -54,6 +54,7 @@ EXPORT_SYMBOL(scsi_release_command);
 EXPORT_SYMBOL(print_Scsi_Cmnd);
 EXPORT_SYMBOL(scsi_block_when_processing_errors);
 EXPORT_SYMBOL(scsi_ioctl_send_command);
+EXPORT_SYMBOL(scsi_set_medium_removal);
 #if defined(CONFIG_SCSI_LOGGING)       /* { */
 EXPORT_SYMBOL(scsi_logging_level);
 #endif
index 4e6bddf4803be18633240dd2acb3e73bf21fea50..bc5909c98ee30309d725b8a6b26d2db74ea1d7e0 100644 (file)
@@ -529,7 +529,7 @@ static int sd_open(struct inode *inode, struct file *filp)
        if (sdp->removable)
                if (sdp->access_count==1)
                        if (scsi_block_when_processing_errors(sdp))
-                               scsi_ioctl(sdp, SCSI_IOCTL_DOORLOCK, NULL);
+                               scsi_set_medium_removal(sdp, SCSI_REMOVAL_PREVENT);
 
        return 0;
 
@@ -573,7 +573,7 @@ static int sd_release(struct inode *inode, struct file *filp)
        if (sdp->removable) {
                if (!sdp->access_count)
                        if (scsi_block_when_processing_errors(sdp))
-                               scsi_ioctl(sdp, SCSI_IOCTL_DOORUNLOCK, NULL);
+                               scsi_set_medium_removal(sdp, SCSI_REMOVAL_ALLOW);
        }
        if (sdp->host->hostt->module)
                __MOD_DEC_USE_COUNT(sdp->host->hostt->module);
@@ -1623,7 +1623,6 @@ static int sd_synchronize_cache(int index, int verbose)
        }
 
        the_result = SRpnt->sr_result;
-       scsi_release_request(SRpnt);
        if(verbose) {
                if(the_result != 0) {
                        printk("FAILED\n  status = %x, message = %02x, host = %d, driver = %02x\n  ",
@@ -1636,6 +1635,7 @@ static int sd_synchronize_cache(int index, int verbose)
 
                }
        }
+       scsi_release_request(SRpnt);
        return (the_result == 0);
 }
 
index f909295227d5ff4ebb68862cc07cd6d82b3c7656..ab50575b899ceb3b1435d7b188a34fe7c167c244 100644 (file)
@@ -575,7 +575,7 @@ Enomem:
 
 void get_capabilities(Scsi_CD *cd)
 {
-       unsigned char cmd[6];
+       struct cdrom_generic_command cgc;
        unsigned char *buffer;
        int rc, n;
 
@@ -597,13 +597,18 @@ void get_capabilities(Scsi_CD *cd)
                printk(KERN_ERR "sr: out of memory.\n");
                return;
        }
-       cmd[0] = MODE_SENSE;
-       cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                ((cd->device->lun << 5) & 0xe0) : 0;
-       cmd[2] = 0x2a;
-       cmd[4] = 128;
-       cmd[3] = cmd[5] = 0;
-       rc = sr_do_ioctl(cd, cmd, buffer, 128, 1, SCSI_DATA_READ, NULL);
+       memset(&cgc, 0, sizeof(struct cdrom_generic_command));
+       cgc.cmd[0] = MODE_SENSE;
+       cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                    ((cd->device->lun << 5) & 0xe0) : 0;
+       cgc.cmd[2] = 0x2a;
+       cgc.cmd[4] = 128;
+       cgc.buffer = buffer;
+       cgc.buflen = 128;
+       cgc.quiet = 1;
+       cgc.data_direction = SCSI_DATA_READ;
+       cgc.timeout = SR_TIMEOUT;
+       rc = sr_do_ioctl(cd, &cgc);
 
        if (rc) {
                /* failed, drive doesn't have capabilities mode page */
@@ -680,7 +685,10 @@ static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command
        if (device->scsi_level <= SCSI_2)
                cgc->cmd[1] |= device->lun << 5;
 
-       cgc->stat = sr_do_ioctl(cdi->handle, cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense);
+       if (cgc->timeout <= 0)
+               cgc->timeout = IOCTL_TIMEOUT;
+
+       sr_do_ioctl(cdi->handle, cgc);
 
        return cgc->stat;
 }
index 3c3ec71656903fa2bdac98990f127270e8b52319..815b95e8c41c36066695d9ceaab8ef6bc0be3cf7 100644 (file)
 #include "scsi.h"
 #include <linux/genhd.h>
 
+/* The CDROM is fairly slow, so we need a little extra time */
+/* In fact, it is very slow if it has to spin up first */
+#define IOCTL_TIMEOUT 30*HZ
+
 typedef struct {
        unsigned capacity;      /* size in blocks                       */
        Scsi_Device *device;
@@ -34,7 +38,7 @@ typedef struct {
        struct gendisk *disk;
 } Scsi_CD;
 
-int sr_do_ioctl(Scsi_CD *, unsigned char *, void *, unsigned, int, int, struct request_sense *);
+int sr_do_ioctl(Scsi_CD *, struct cdrom_generic_command *);
 
 int sr_lock_door(struct cdrom_device_info *, int);
 int sr_tray_move(struct cdrom_device_info *, int);
index 797034b58e7ff8c5a8faaa53e427529ed2bd56b8..82c0f0c52a867f1beb424f8c330c1f673df37515 100644 (file)
@@ -25,9 +25,6 @@
 static int xa_test = 0;
 
 #define IOCTL_RETRIES 3
-/* The CDROM is fairly slow, so we need a little extra time */
-/* In fact, it is very slow if it has to spin up first */
-#define IOCTL_TIMEOUT 30*HZ
 
 /* ATAPI drives don't have a SCMD_PLAYAUDIO_TI command.  When these drives
    are emulating a SCSI device via the idescsi module, they need to have
@@ -37,7 +34,7 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
 {
        struct cdrom_tocentry trk0_te, trk1_te;
        struct cdrom_tochdr tochdr;
-       u_char sr_cmd[10];
+       struct cdrom_generic_command cgc;
        int ntracks, ret;
 
        if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &tochdr)))
@@ -59,22 +56,25 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
                return ret;
        if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk1_te)))
                return ret;
-       
-       sr_cmd[0] = GPCMD_PLAY_AUDIO_MSF;
-       sr_cmd[3] = trk0_te.cdte_addr.msf.minute;
-       sr_cmd[4] = trk0_te.cdte_addr.msf.second;
-       sr_cmd[5] = trk0_te.cdte_addr.msf.frame;
-       sr_cmd[6] = trk1_te.cdte_addr.msf.minute;
-       sr_cmd[7] = trk1_te.cdte_addr.msf.second;
-       sr_cmd[8] = trk1_te.cdte_addr.msf.frame;
-       return sr_do_ioctl(cdi->handle, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
+
+       memset(&cgc, 0, sizeof(struct cdrom_generic_command));
+       cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
+       cgc.cmd[3] = trk0_te.cdte_addr.msf.minute;
+       cgc.cmd[4] = trk0_te.cdte_addr.msf.second;
+       cgc.cmd[5] = trk0_te.cdte_addr.msf.frame;
+       cgc.cmd[6] = trk1_te.cdte_addr.msf.minute;
+       cgc.cmd[7] = trk1_te.cdte_addr.msf.second;
+       cgc.cmd[8] = trk1_te.cdte_addr.msf.frame;
+       cgc.data_direction = SCSI_DATA_NONE;
+       cgc.timeout = IOCTL_TIMEOUT;
+       return sr_do_ioctl(cdi->handle, &cgc);
 }
 
 /* We do our own retries because we want to know what the specific
    error code is.  Normally the UNIT_ATTENTION code will automatically
    clear after one error */
 
-int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned buflength, int quiet, int readwrite, struct request_sense *sense)
+int sr_do_ioctl(Scsi_CD *cd, struct cdrom_generic_command *cgc)
 {
        Scsi_Request *SRpnt;
        Scsi_Device *SDev;
@@ -86,29 +86,32 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
        SRpnt = scsi_allocate_request(SDev);
         if (!SRpnt) {
                 printk("Unable to allocate SCSI request in sr_do_ioctl");
-                return -ENOMEM;
+               err = -ENOMEM;
+               goto out;
         }
-       SRpnt->sr_data_direction = readwrite;
+       SRpnt->sr_data_direction = cgc->data_direction;
 
        /* use ISA DMA buffer if necessary */
-       SRpnt->sr_request->buffer = buffer;
-       if (buffer && SRpnt->sr_host->unchecked_isa_dma &&
-           (virt_to_phys(buffer) + buflength - 1 > ISA_DMA_THRESHOLD)) {
-               bounce_buffer = (char *) kmalloc(buflength, GFP_DMA);
+       SRpnt->sr_request->buffer = cgc->buffer;
+       if (cgc->buffer && SRpnt->sr_host->unchecked_isa_dma &&
+           (virt_to_phys(cgc->buffer) + cgc->buflen - 1 > ISA_DMA_THRESHOLD)) {
+               bounce_buffer = (char *) kmalloc(cgc->buflen, GFP_DMA);
                if (bounce_buffer == NULL) {
                        printk("SCSI DMA pool exhausted.");
-                       return -ENOMEM;
+                       err = -ENOMEM;
+                       goto out;
                }
-               memcpy(bounce_buffer, (char *) buffer, buflength);
-               buffer = bounce_buffer;
+               memcpy(bounce_buffer, cgc->buffer, cgc->buflen);
+               cgc->buffer = bounce_buffer;
        }
       retry:
-       if (!scsi_block_when_processing_errors(SDev))
-               return -ENODEV;
-
+       if (!scsi_block_when_processing_errors(SDev)) {
+               err = -ENODEV;
+               goto out;
+       }
 
-       scsi_wait_req(SRpnt, (void *) sr_cmd, (void *) buffer, buflength,
-                     IOCTL_TIMEOUT, IOCTL_RETRIES);
+       scsi_wait_req(SRpnt, cgc->cmd, cgc->buffer, cgc->buflen,
+                     cgc->timeout, IOCTL_RETRIES);
 
        req = SRpnt->sr_request;
        if (SRpnt->sr_buffer && req->buffer && SRpnt->sr_buffer != req->buffer) {
@@ -124,7 +127,7 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
                switch (SRpnt->sr_sense_buffer[2] & 0xf) {
                case UNIT_ATTENTION:
                        SDev->changed = 1;
-                       if (!quiet)
+                       if (!cgc->quiet)
                                printk(KERN_INFO "%s: disc change detected.\n", cd->cdi.name);
                        if (retries++ < 10)
                                goto retry;
@@ -134,7 +137,7 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
                        if (SRpnt->sr_sense_buffer[12] == 0x04 &&
                            SRpnt->sr_sense_buffer[13] == 0x01) {
                                /* sense: Logical unit is in process of becoming ready */
-                               if (!quiet)
+                               if (!cgc->quiet)
                                        printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name);
                                if (retries++ < 10) {
                                        /* sleep 2 sec and try again */
@@ -146,7 +149,7 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
                                        break;
                                }
                        }
-                       if (!quiet)
+                       if (!cgc->quiet)
                                printk(KERN_INFO "%s: CDROM not ready.  Make sure there is a disc in the drive.\n", cd->cdi.name);
 #ifdef DEBUG
                        print_req_sense("sr", SRpnt);
@@ -154,7 +157,7 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
                        err = -ENOMEDIUM;
                        break;
                case ILLEGAL_REQUEST:
-                       if (!quiet)
+                       if (!cgc->quiet)
                                printk(KERN_ERR "%s: CDROM (ioctl) reports ILLEGAL "
                                       "REQUEST.\n", cd->cdi.name);
                        if (SRpnt->sr_sense_buffer[12] == 0x20 &&
@@ -165,24 +168,26 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
                                err = -EINVAL;
                        }
 #ifdef DEBUG
-                       print_command(sr_cmd);
+                       print_command(cgc->cmd);
                        print_req_sense("sr", SRpnt);
 #endif
                        break;
                default:
                        printk(KERN_ERR "%s: CDROM (ioctl) error, command: ", cd->cdi.name);
-                       print_command(sr_cmd);
+                       print_command(cgc->cmd);
                        print_req_sense("sr", SRpnt);
                        err = -EIO;
                }
        }
 
-       if (sense)
-               memcpy(sense, SRpnt->sr_sense_buffer, sizeof(*sense));
+       if (cgc->sense)
+               memcpy(cgc->sense, SRpnt->sr_sense_buffer, sizeof(*cgc->sense));
 
        /* Wake up a process waiting for device */
        scsi_release_request(SRpnt);
        SRpnt = NULL;
+      out:
+       cgc->stat = err;
        return err;
 }
 
@@ -191,35 +196,39 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
 
 static int test_unit_ready(Scsi_CD *cd)
 {
-       u_char sr_cmd[10];
-
-       sr_cmd[0] = GPCMD_TEST_UNIT_READY;
-       sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                   ((cd->device->lun) << 5) : 0;
-       sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
-       return sr_do_ioctl(cd, sr_cmd, NULL, 0, 1, SCSI_DATA_NONE, NULL);
+       struct cdrom_generic_command cgc;
+
+       memset(&cgc, 0, sizeof(struct cdrom_generic_command));
+       cgc.cmd[0] = GPCMD_TEST_UNIT_READY;
+       cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                    ((cd->device->lun) << 5) : 0;
+       cgc.quiet = 1;
+       cgc.data_direction = SCSI_DATA_NONE;
+       cgc.timeout = IOCTL_TIMEOUT;
+       return sr_do_ioctl(cd, &cgc);
 }
 
 int sr_tray_move(struct cdrom_device_info *cdi, int pos)
 {
        Scsi_CD *cd = cdi->handle;
-       u_char sr_cmd[10];
-
-       sr_cmd[0] = GPCMD_START_STOP_UNIT;
-       sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                   ((cd->device->lun) << 5) : 0;
-       sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
-       sr_cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */ ;
-
-       return sr_do_ioctl(cd, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
+       struct cdrom_generic_command cgc;
+
+       memset(&cgc, 0, sizeof(struct cdrom_generic_command));
+       cgc.cmd[0] = GPCMD_START_STOP_UNIT;
+       cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                    ((cd->device->lun) << 5) : 0;
+       cgc.cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */ ;
+       cgc.data_direction = SCSI_DATA_NONE;
+       cgc.timeout = IOCTL_TIMEOUT;
+       return sr_do_ioctl(cd, &cgc);
 }
 
 int sr_lock_door(struct cdrom_device_info *cdi, int lock)
 {
        Scsi_CD *cd = cdi->handle;
 
-       return scsi_ioctl(cd->device, lock ? SCSI_IOCTL_DOORLOCK :
-                       SCSI_IOCTL_DOORUNLOCK, 0);
+       return scsi_set_medium_removal(cd->device, lock ?
+                      SCSI_REMOVAL_PREVENT : SCSI_REMOVAL_ALLOW);
 }
 
 int sr_drive_status(struct cdrom_device_info *cdi, int slot)
@@ -278,22 +287,22 @@ int sr_get_last_session(struct cdrom_device_info *cdi,
 int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
 {
        Scsi_CD *cd = cdi->handle;
-       u_char sr_cmd[10];
+       struct cdrom_generic_command cgc;
        char buffer[32];
        int result;
 
-       sr_cmd[0] = GPCMD_READ_SUBCHANNEL;
-       sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                   ((cd->device->lun) << 5) : 0;
-       sr_cmd[2] = 0x40;       /* I do want the subchannel info */
-       sr_cmd[3] = 0x02;       /* Give me medium catalog number info */
-       sr_cmd[4] = sr_cmd[5] = 0;
-       sr_cmd[6] = 0;
-       sr_cmd[7] = 0;
-       sr_cmd[8] = 24;
-       sr_cmd[9] = 0;
-
-       result = sr_do_ioctl(cd, sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL);
+       memset(&cgc, 0, sizeof(struct cdrom_generic_command));
+       cgc.cmd[0] = GPCMD_READ_SUBCHANNEL;
+       cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                    ((cd->device->lun) << 5) : 0;
+       cgc.cmd[2] = 0x40;      /* I do want the subchannel info */
+       cgc.cmd[3] = 0x02;      /* Give me medium catalog number info */
+       cgc.cmd[8] = 24;
+       cgc.buffer = buffer;
+       cgc.buflen = 24;
+       cgc.data_direction = SCSI_DATA_READ;
+       cgc.timeout = IOCTL_TIMEOUT;
+       result = sr_do_ioctl(cd, &cgc);
 
        memcpy(mcn->medium_catalog_number, buffer + 9, 13);
        mcn->medium_catalog_number[13] = 0;
@@ -309,21 +318,23 @@ int sr_reset(struct cdrom_device_info *cdi)
 int sr_select_speed(struct cdrom_device_info *cdi, int speed)
 {
        Scsi_CD *cd = cdi->handle;
-       u_char sr_cmd[MAX_COMMAND_SIZE];
+       struct cdrom_generic_command cgc;
 
        if (speed == 0)
                speed = 0xffff; /* set to max */
        else
                speed *= 177;   /* Nx to kbyte/s */
 
-       memset(sr_cmd, 0, MAX_COMMAND_SIZE);
-       sr_cmd[0] = GPCMD_SET_SPEED;    /* SET CD SPEED */
-       sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                   ((cd->device->lun) << 5) : 0;
-       sr_cmd[2] = (speed >> 8) & 0xff;        /* MSB for speed (in kbytes/sec) */
-       sr_cmd[3] = speed & 0xff;       /* LSB */
+       memset(&cgc, 0, sizeof(struct cdrom_generic_command));
+       cgc.cmd[0] = GPCMD_SET_SPEED;   /* SET CD SPEED */
+       cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                    ((cd->device->lun) << 5) : 0;
+       cgc.cmd[2] = (speed >> 8) & 0xff;       /* MSB for speed (in kbytes/sec) */
+       cgc.cmd[3] = speed & 0xff;      /* LSB */
+       cgc.data_direction = SCSI_DATA_NONE;
+       cgc.timeout = IOCTL_TIMEOUT;
 
-       if (sr_do_ioctl(cd, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL))
+       if (sr_do_ioctl(cd, &cgc))
                return -EIO;
        return 0;
 }
@@ -337,24 +348,28 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed)
 int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
 {
        Scsi_CD *cd = cdi->handle;
-       u_char sr_cmd[10];
+       struct cdrom_generic_command cgc;
        int result;
        unsigned char buffer[32];
 
-       memset(sr_cmd, 0, sizeof(sr_cmd));
+       memset(&cgc, 0, sizeof(struct cdrom_generic_command));
+       cgc.timeout = IOCTL_TIMEOUT;
 
        switch (cmd) {
        case CDROMREADTOCHDR:
                {
                        struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
 
-                       sr_cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
-                       sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                                   ((cd->device->lun) << 5) : 0;
-                       sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
-                       sr_cmd[8] = 12;         /* LSB of length */
+                       cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
+                       cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                                    ((cd->device->lun) << 5) : 0;
+                       cgc.cmd[8] = 12;                /* LSB of length */
+                       cgc.buffer = buffer;
+                       cgc.buflen = 12;
+                       cgc.quiet = 1;
+                       cgc.data_direction = SCSI_DATA_READ;
 
-                       result = sr_do_ioctl(cd, sr_cmd, buffer, 12, 1, SCSI_DATA_READ, NULL);
+                       result = sr_do_ioctl(cd, &cgc);
 
                        tochdr->cdth_trk0 = buffer[2];
                        tochdr->cdth_trk1 = buffer[3];
@@ -366,15 +381,17 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
                {
                        struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg;
 
-                       sr_cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
-                       sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                                   ((cd->device->lun) << 5) : 0;
-                       sr_cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
-                       sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
-                       sr_cmd[6] = tocentry->cdte_track;
-                       sr_cmd[8] = 12;         /* LSB of length */
+                       cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
+                       cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                                    ((cd->device->lun) << 5) : 0;
+                       cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
+                       cgc.cmd[6] = tocentry->cdte_track;
+                       cgc.cmd[8] = 12;                /* LSB of length */
+                       cgc.buffer = buffer;
+                       cgc.buflen = 12;
+                       cgc.data_direction = SCSI_DATA_READ;
 
-                       result = sr_do_ioctl(cd, sr_cmd, buffer, 12, 0, SCSI_DATA_READ, NULL);
+                       result = sr_do_ioctl(cd, &cgc);
 
                        tocentry->cdte_ctrl = buffer[5] & 0xf;
                        tocentry->cdte_adr = buffer[5] >> 4;
@@ -393,15 +410,16 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
        case CDROMPLAYTRKIND: {
                struct cdrom_ti* ti = (struct cdrom_ti*)arg;
 
-               sr_cmd[0] = GPCMD_PLAYAUDIO_TI;
-               sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                           (cd->device->lun << 5) : 0;
-               sr_cmd[4] = ti->cdti_trk0;
-               sr_cmd[5] = ti->cdti_ind0;
-               sr_cmd[7] = ti->cdti_trk1;
-               sr_cmd[8] = ti->cdti_ind1;
+               cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;
+               cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                            (cd->device->lun << 5) : 0;
+               cgc.cmd[4] = ti->cdti_trk0;
+               cgc.cmd[5] = ti->cdti_ind0;
+               cgc.cmd[7] = ti->cdti_trk1;
+               cgc.cmd[8] = ti->cdti_ind1;
+               cgc.data_direction = SCSI_DATA_NONE;
 
-               result = sr_do_ioctl(cd, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
+               result = sr_do_ioctl(cd, &cgc);
                if (result == -EDRIVE_CANT_DO_THIS)
                        result = sr_fake_playtrkind(cdi, ti);
 
@@ -436,38 +454,42 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
 
 static int sr_read_cd(Scsi_CD *cd, unsigned char *dest, int lba, int format, int blksize)
 {
-       unsigned char cmd[MAX_COMMAND_SIZE];
+       struct cdrom_generic_command cgc;
 
 #ifdef DEBUG
        printk("%s: sr_read_cd lba=%d format=%d blksize=%d\n",
               cd->cdi.name, lba, format, blksize);
 #endif
 
-       memset(cmd, 0, MAX_COMMAND_SIZE);
-       cmd[0] = GPCMD_READ_CD; /* READ_CD */
-       cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                (cd->device->lun << 5) : 0;
-       cmd[1] |= ((format & 7) << 2);
-       cmd[2] = (unsigned char) (lba >> 24) & 0xff;
-       cmd[3] = (unsigned char) (lba >> 16) & 0xff;
-       cmd[4] = (unsigned char) (lba >> 8) & 0xff;
-       cmd[5] = (unsigned char) lba & 0xff;
-       cmd[8] = 1;
+       memset(&cgc, 0, sizeof(struct cdrom_generic_command));
+       cgc.cmd[0] = GPCMD_READ_CD;     /* READ_CD */
+       cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                    (cd->device->lun << 5) : 0;
+       cgc.cmd[1] |= ((format & 7) << 2);
+       cgc.cmd[2] = (unsigned char) (lba >> 24) & 0xff;
+       cgc.cmd[3] = (unsigned char) (lba >> 16) & 0xff;
+       cgc.cmd[4] = (unsigned char) (lba >> 8) & 0xff;
+       cgc.cmd[5] = (unsigned char) lba & 0xff;
+       cgc.cmd[8] = 1;
        switch (blksize) {
        case 2336:
-               cmd[9] = 0x58;
+               cgc.cmd[9] = 0x58;
                break;
        case 2340:
-               cmd[9] = 0x78;
+               cgc.cmd[9] = 0x78;
                break;
        case 2352:
-               cmd[9] = 0xf8;
+               cgc.cmd[9] = 0xf8;
                break;
        default:
-               cmd[9] = 0x10;
+               cgc.cmd[9] = 0x10;
                break;
        }
-       return sr_do_ioctl(cd, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL);
+       cgc.buffer = dest;
+       cgc.buflen = blksize;
+       cgc.data_direction = SCSI_DATA_READ;
+       cgc.timeout = IOCTL_TIMEOUT;
+       return sr_do_ioctl(cd, &cgc);
 }
 
 /*
@@ -476,7 +498,7 @@ static int sr_read_cd(Scsi_CD *cd, unsigned char *dest, int lba, int format, int
 
 static int sr_read_sector(Scsi_CD *cd, int lba, int blksize, unsigned char *dest)
 {
-       unsigned char cmd[MAX_COMMAND_SIZE];    /* the scsi-command */
+       struct cdrom_generic_command cgc;
        int rc;
 
        /* we try the READ CD command first... */
@@ -497,16 +519,20 @@ static int sr_read_sector(Scsi_CD *cd, int lba, int blksize, unsigned char *dest
        printk("%s: sr_read_sector lba=%d blksize=%d\n", cd->cdi.name, lba, blksize);
 #endif
 
-       memset(cmd, 0, MAX_COMMAND_SIZE);
-       cmd[0] = GPCMD_READ_10;
-       cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                (cd->device->lun << 5) : 0;
-       cmd[2] = (unsigned char) (lba >> 24) & 0xff;
-       cmd[3] = (unsigned char) (lba >> 16) & 0xff;
-       cmd[4] = (unsigned char) (lba >> 8) & 0xff;
-       cmd[5] = (unsigned char) lba & 0xff;
-       cmd[8] = 1;
-       rc = sr_do_ioctl(cd, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL);
+       memset(&cgc, 0, sizeof(struct cdrom_generic_command));
+       cgc.cmd[0] = GPCMD_READ_10;
+       cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                    (cd->device->lun << 5) : 0;
+       cgc.cmd[2] = (unsigned char) (lba >> 24) & 0xff;
+       cgc.cmd[3] = (unsigned char) (lba >> 16) & 0xff;
+       cgc.cmd[4] = (unsigned char) (lba >> 8) & 0xff;
+       cgc.cmd[5] = (unsigned char) lba & 0xff;
+       cgc.cmd[8] = 1;
+       cgc.buffer = dest;
+       cgc.buflen = blksize;
+       cgc.data_direction = SCSI_DATA_READ;
+       cgc.timeout = IOCTL_TIMEOUT;
+       rc = sr_do_ioctl(cd, &cgc);
 
        return rc;
 }
@@ -562,7 +588,6 @@ int sr_dev_ioctl(struct cdrom_device_info *cdi,
  * c-label-offset: -4
  * c-continued-statement-offset: 4
  * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
  * tab-width: 8
  * End:
  */
index b7000df8b52077e6814969486f81c09779f4a775..6803d45c7b2603d36f582edf9984d3807f217ad7 100644 (file)
@@ -58,6 +58,8 @@
 #define VENDOR_TOSHIBA         3
 #define VENDOR_WRITER          4       /* pre-scsi3 writers */
 
+#define VENDOR_TIMEOUT 30*HZ
+
 void sr_vendor_init(Scsi_CD *cd)
 {
 #ifndef CONFIG_BLK_DEV_SR_VENDOR
@@ -104,7 +106,7 @@ void sr_vendor_init(Scsi_CD *cd)
 int sr_set_blocklength(Scsi_CD *cd, int blocklength)
 {
        unsigned char *buffer;  /* the buffer for the ioctl */
-       unsigned char cmd[MAX_COMMAND_SIZE];    /* the scsi-command */
+       struct cdrom_generic_command cgc;
        struct ccs_modesel_head *modesel;
        int rc, density = 0;
 
@@ -120,19 +122,23 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength)
 #ifdef DEBUG
        printk("%s: MODE SELECT 0x%x/%d\n", cd->cdi.name, density, blocklength);
 #endif
-       memset(cmd, 0, MAX_COMMAND_SIZE);
-       cmd[0] = MODE_SELECT;
-       cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                (cd->device->lun << 5) : 0;
-       cmd[1] |= (1 << 4);
-       cmd[4] = 12;
+       memset(&cgc, 0, sizeof(struct cdrom_generic_command));
+       cgc.cmd[0] = MODE_SELECT;
+       cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                    (cd->device->lun << 5) : 0;
+       cgc.cmd[1] |= (1 << 4);
+       cgc.cmd[4] = 12;
        modesel = (struct ccs_modesel_head *) buffer;
        memset(modesel, 0, sizeof(*modesel));
        modesel->block_desc_length = 0x08;
        modesel->density = density;
        modesel->block_length_med = (blocklength >> 8) & 0xff;
        modesel->block_length_lo = blocklength & 0xff;
-       if (0 == (rc = sr_do_ioctl(cd, cmd, buffer, sizeof(*modesel), 0, SCSI_DATA_WRITE, NULL))) {
+       cgc.buffer = buffer;
+       cgc.buflen = sizeof(*modesel);
+       cgc.data_direction = SCSI_DATA_WRITE;
+       cgc.timeout = VENDOR_TIMEOUT;
+       if (0 == (rc = sr_do_ioctl(cd, &cgc))) {
                cd->device->sector_size = blocklength;
        }
 #ifdef DEBUG
@@ -154,7 +160,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
        Scsi_CD *cd = cdi->handle;
        unsigned long sector;
        unsigned char *buffer;  /* the buffer for the ioctl */
-       unsigned char cmd[MAX_COMMAND_SIZE];    /* the scsi-command */
+       struct cdrom_generic_command cgc;
        int rc, no_multi;
 
        if (cd->cdi.mask & CDC_MULTI_SESSION)
@@ -168,16 +174,22 @@ int sr_cd_check(struct cdrom_device_info *cdi)
        no_multi = 0;           /* flag: the drive can't handle multisession */
        rc = 0;
 
+       memset(&cgc, 0, sizeof(struct cdrom_generic_command));
+
        switch (cd->vendor) {
 
        case VENDOR_SCSI3:
-               memset(cmd, 0, MAX_COMMAND_SIZE);
-               cmd[0] = READ_TOC;
-               cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                        (cd->device->lun << 5) : 0;
-               cmd[8] = 12;
-               cmd[9] = 0x40;
-               rc = sr_do_ioctl(cd, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL);
+               cgc.cmd[0] = READ_TOC;
+               cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                            (cd->device->lun << 5) : 0;
+               cgc.cmd[8] = 12;
+               cgc.cmd[9] = 0x40;
+               cgc.buffer = buffer;
+               cgc.buflen = 12;
+               cgc.quiet = 1;
+               cgc.data_direction = SCSI_DATA_READ;
+               cgc.timeout = VENDOR_TIMEOUT;
+               rc = sr_do_ioctl(cd, &cgc);
                if (rc != 0)
                        break;
                if ((buffer[0] << 8) + buffer[1] < 0x0a) {
@@ -197,13 +209,17 @@ int sr_cd_check(struct cdrom_device_info *cdi)
 #ifdef CONFIG_BLK_DEV_SR_VENDOR
        case VENDOR_NEC:{
                        unsigned long min, sec, frame;
-                       memset(cmd, 0, MAX_COMMAND_SIZE);
-                       cmd[0] = 0xde;
-                       cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                                (cd->device->lun << 5) : 0;
-                       cmd[1] |= 0x03;
-                       cmd[2] = 0xb0;
-                       rc = sr_do_ioctl(cd, cmd, buffer, 0x16, 1, SCSI_DATA_READ, NULL);
+                       cgc.cmd[0] = 0xde;
+                       cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                                    (cd->device->lun << 5) : 0;
+                       cgc.cmd[1] |= 0x03;
+                       cgc.cmd[2] = 0xb0;
+                       cgc.buffer = buffer;
+                       cgc.buflen = 0x16;
+                       cgc.quiet = 1;
+                       cgc.data_direction = SCSI_DATA_READ;
+                       cgc.timeout = VENDOR_TIMEOUT;
+                       rc = sr_do_ioctl(cd, &cgc);
                        if (rc != 0)
                                break;
                        if (buffer[14] != 0 && buffer[14] != 0xb0) {
@@ -225,12 +241,16 @@ int sr_cd_check(struct cdrom_device_info *cdi)
 
                        /* we request some disc information (is it a XA-CD ?,
                         * where starts the last session ?) */
-                       memset(cmd, 0, MAX_COMMAND_SIZE);
-                       cmd[0] = 0xc7;
-                       cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                                (cd->device->lun << 5) : 0;
-                       cmd[1] |= 0x03;
-                       rc = sr_do_ioctl(cd, cmd, buffer, 4, 1, SCSI_DATA_READ, NULL);
+                       cgc.cmd[0] = 0xc7;
+                       cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                                    (cd->device->lun << 5) : 0;
+                       cgc.cmd[1] |= 0x03;
+                       cgc.buffer = buffer;
+                       cgc.buflen = 4;
+                       cgc.quiet = 1;
+                       cgc.data_direction = SCSI_DATA_READ;
+                       cgc.timeout = VENDOR_TIMEOUT;
+                       rc = sr_do_ioctl(cd, &cgc);
                        if (rc == -EINVAL) {
                                printk(KERN_INFO "%s: Hmm, seems the drive "
                                       "doesn't support multisession CD's\n",
@@ -251,13 +271,17 @@ int sr_cd_check(struct cdrom_device_info *cdi)
                }
 
        case VENDOR_WRITER:
-               memset(cmd, 0, MAX_COMMAND_SIZE);
-               cmd[0] = READ_TOC;
-               cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                        (cd->device->lun << 5) : 0;
-               cmd[8] = 0x04;
-               cmd[9] = 0x40;
-               rc = sr_do_ioctl(cd, cmd, buffer, 0x04, 1, SCSI_DATA_READ, NULL);
+               cgc.cmd[0] = READ_TOC;
+               cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                            (cd->device->lun << 5) : 0;
+               cgc.cmd[8] = 0x04;
+               cgc.cmd[9] = 0x40;
+               cgc.buffer = buffer;
+               cgc.buflen = 0x04;
+               cgc.quiet = 1;
+               cgc.data_direction = SCSI_DATA_READ;
+               cgc.timeout = VENDOR_TIMEOUT;
+               rc = sr_do_ioctl(cd, &cgc);
                if (rc != 0) {
                        break;
                }
@@ -266,13 +290,18 @@ int sr_cd_check(struct cdrom_device_info *cdi)
                               "%s: No finished session\n", cd->cdi.name);
                        break;
                }
-               cmd[0] = READ_TOC;      /* Read TOC */
-               cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
-                        (cd->device->lun << 5) : 0;
-               cmd[6] = rc & 0x7f;     /* number of last session */
-               cmd[8] = 0x0c;
-               cmd[9] = 0x40;
-               rc = sr_do_ioctl(cd, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL);
+               cgc.cmd[0] = READ_TOC;  /* Read TOC */
+               cgc.cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+                            (cd->device->lun << 5) : 0;
+               cgc.cmd[6] = rc & 0x7f; /* number of last session */
+               cgc.cmd[8] = 0x0c;
+               cgc.cmd[9] = 0x40;
+               cgc.buffer = buffer;
+               cgc.buflen = 12;
+               cgc.quiet = 1;
+               cgc.data_direction = SCSI_DATA_READ;
+               cgc.timeout = VENDOR_TIMEOUT;
+               rc = sr_do_ioctl(cd, &cgc);
                if (rc != 0) {
                        break;
                }