]> git.hungrycats.org Git - linux/commitdiff
[PATCH] make SCSI understand REQ_BLOCK_PC
authorJens Axboe <axboe@suse.de>
Fri, 18 Oct 2002 03:50:34 +0000 (20:50 -0700)
committerJens Axboe <axboe@suse.de>
Fri, 18 Oct 2002 03:50:34 +0000 (20:50 -0700)
Make SCSI layer understand REQ_BLOCK_PC requests

drivers/scsi/scsi_lib.c
drivers/scsi/scsi_merge.c
drivers/scsi/sd.c
drivers/scsi/sr.c

index a73a677e68180886998f61b303b3de432a66243e..dfa18e0c0eb9db6092acb3a72be832467b2c52b1 100644 (file)
@@ -857,7 +857,7 @@ void scsi_request_fn(request_queue_t * q)
                                scsi_init_cmd_from_req(SCpnt, SRpnt);
                        }
 
-               } else if (req->flags & REQ_CMD) {
+               } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
                        SRpnt = NULL;
                        STpnt = scsi_get_request_dev(req);
                        if (!STpnt) {
@@ -919,7 +919,7 @@ void scsi_request_fn(request_queue_t * q)
                req = NULL;
                spin_unlock_irq(q->queue_lock);
 
-               if (SCpnt->request->flags & REQ_CMD) {
+               if (SCpnt->request->flags & (REQ_CMD | REQ_BLOCK_PC)) {
                        /*
                         * This will do a couple of things:
                         *  1) Fill in the actual SCSI command.
index 980d7047e6e92a52a48e1a7f8b1ba9678dde6abb..ac79b081270cfde1fda69f173bd07479f548069b 100644 (file)
@@ -62,16 +62,28 @@ int scsi_init_io(Scsi_Cmnd *SCpnt)
        int count, gfp_mask;
 
        /*
-        * First we need to know how many scatter gather segments are needed.
+        * non-sg block request. FIXME: check bouncing for isa hosts!
         */
-       count = req->nr_phys_segments;
+       if ((req->flags & REQ_BLOCK_PC) && !req->bio) {
+               /*
+                * FIXME: isa bouncing
+                */
+               if (SCpnt->host->unchecked_isa_dma)
+                       goto fail;
+
+               SCpnt->request_bufflen = req->data_len;
+               SCpnt->request_buffer = req->data;
+               req->buffer = req->data;
+               SCpnt->use_sg = 0;
+               return 1;
+       }
 
        /*
         * we used to not use scatter-gather for single segment request,
         * but now we do (it makes highmem I/O easier to support without
         * kmapping pages)
         */
-       SCpnt->use_sg = count;
+       SCpnt->use_sg = req->nr_phys_segments;
 
        gfp_mask = GFP_NOIO;
        if (in_interrupt()) {
@@ -111,6 +123,7 @@ int scsi_init_io(Scsi_Cmnd *SCpnt)
        /*
         * kill it. there should be no leftover blocks in this request
         */
+fail:
        SCpnt = scsi_end_request(SCpnt, 0, req->nr_sectors);
        BUG_ON(SCpnt);
        return 0;
index 1b7abd00b167f3ccd44848e4ca21f2b5c463f919..17a5cddf66b614d7367e7d0349201b54bbde92ff 100644 (file)
@@ -193,6 +193,7 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
        Scsi_Device * sdp;
        int diskinfo[4];
        int dsk_nr = DEVICE_NR(dev);
+       int error;
     
        SCSI_LOG_IOCTL(1, printk("sd_ioctl: dsk_nr=%d, cmd=0x%x\n",
                       dsk_nr, cmd));
@@ -209,6 +210,10 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
        if( !scsi_block_when_processing_errors(sdp) )
                return -ENODEV;
 
+       error = scsi_cmd_ioctl(inode->i_bdev, cmd, arg);
+       if (error != -ENOTTY)
+               return error;
+
        switch (cmd) 
        {
                case HDIO_GETGEO:   /* Return BIOS disk parameters */
@@ -299,14 +304,43 @@ static struct gendisk **sd_disks;
  **/
 static int sd_init_command(Scsi_Cmnd * SCpnt)
 {
-       int dsk_nr, part_nr, this_count;
+       int dsk_nr, part_nr, this_count, timeout;
        sector_t block;
-       Scsi_Device *sdp;
+       Scsi_Device *sdp = SCpnt->device;
 #if CONFIG_SCSI_LOGGING
        char nbuff[6];
 #endif
+
+       timeout = SD_TIMEOUT;
+       if (SCpnt->device->type != TYPE_DISK)
+               timeout = SD_MOD_TIMEOUT;
+
+       /*
+        * these are already setup, just copy cdb basically
+        */
+       if (SCpnt->request->flags & REQ_BLOCK_PC) {
+               struct request *rq = SCpnt->request;
+
+               if (sizeof(rq->cmd) > sizeof(SCpnt->cmnd))
+                       return 0;
+
+               memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
+               if (rq_data_dir(rq) == WRITE)
+                       SCpnt->sc_data_direction = SCSI_DATA_WRITE;
+               else if (rq->data_len)
+                       SCpnt->sc_data_direction = SCSI_DATA_READ;
+               else
+                       SCpnt->sc_data_direction = SCSI_DATA_NONE;
+
+               this_count = rq->data_len;
+               if (rq->timeout)
+                       timeout = rq->timeout;
+
+               goto queue;
+       }
+
        /*
-        * don't support specials for nwo
+        * we only do REQ_CMD and REQ_BLOCK_PC
         */
        if (!(SCpnt->request->flags & REQ_CMD))
                return 0;
@@ -320,7 +354,6 @@ static int sd_init_command(Scsi_Cmnd * SCpnt)
        SCSI_LOG_HLQUEUE(1, printk("sd_command_init: dsk_nr=%d, block=%llu, "
                            "count=%d\n", dsk_nr, (unsigned long long)block, this_count));
 
-       sdp = SCpnt->device;
        /* >>>>> the "(part_nr & 0xf)" excludes 15th partition, why?? */
        /* >>>>> this change is not in the lk 2.5 series */
        if (part_nr >= (sd_template.dev_max << 4) || (part_nr & 0xf) ||
@@ -433,12 +466,12 @@ static int sd_init_command(Scsi_Cmnd * SCpnt)
         * host adapter, it's safe to assume that we can at least transfer
         * this many bytes between each connect / disconnect.
         */
+queue:
        SCpnt->transfersize = sdp->sector_size;
        SCpnt->underflow = this_count << 9;
 
        SCpnt->allowed = MAX_RETRIES;
-       SCpnt->timeout_per_command = (SCpnt->device->type == TYPE_DISK ?
-                                     SD_TIMEOUT : SD_MOD_TIMEOUT);
+       SCpnt->timeout_per_command = timeout;
 
        /*
         * This is the completion routine we use.  This is matched in terms
index 39af5cce16f03c7bb2d93d7c4787c18c3114146c..56ca2d216b3f61c5bc8db341af0b53374fb9a403 100644 (file)
@@ -262,7 +262,7 @@ static request_queue_t *sr_find_queue(kdev_t dev)
 
 static int sr_init_command(Scsi_Cmnd * SCpnt)
 {
-       int dev, devm, block=0, this_count, s_size;
+       int dev, devm, block=0, this_count, s_size, timeout = SR_TIMEOUT;
        Scsi_CD *cd;
 
        devm = minor(SCpnt->request->rq_dev);
@@ -285,6 +285,30 @@ static int sr_init_command(Scsi_Cmnd * SCpnt)
                return 0;
        }
 
+       /*
+        * these are already setup, just copy cdb basically
+        */
+       if (SCpnt->request->flags & REQ_BLOCK_PC) {
+               struct request *rq = SCpnt->request;
+
+               if (sizeof(rq->cmd) > sizeof(SCpnt->cmnd))
+                       return 0;
+
+               memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
+               if (rq_data_dir(rq) == WRITE)
+                       SCpnt->sc_data_direction = SCSI_DATA_WRITE;
+               else if (rq->data_len)
+                       SCpnt->sc_data_direction = SCSI_DATA_READ;
+               else
+                       SCpnt->sc_data_direction = SCSI_DATA_NONE;
+
+               this_count = rq->data_len;
+               if (rq->timeout)
+                       timeout = rq->timeout;
+
+               goto queue;
+       }
+
        if (!(SCpnt->request->flags & REQ_CMD)) {
                blk_dump_rq_flags(SCpnt->request, "sr unsup command");
                return 0;
@@ -357,11 +381,12 @@ static int sr_init_command(Scsi_Cmnd * SCpnt)
         * host adapter, it's safe to assume that we can at least transfer
         * this many bytes between each connect / disconnect.
         */
+queue:
        SCpnt->transfersize = cd->device->sector_size;
        SCpnt->underflow = this_count << 9;
 
        SCpnt->allowed = MAX_RETRIES;
-       SCpnt->timeout_per_command = SR_TIMEOUT;
+       SCpnt->timeout_per_command = timeout;
 
        /*
         * This is the completion routine we use.  This is matched in terms