]> git.hungrycats.org Git - linux/commitdiff
[PATCH] USB: Add ioctls to ub
authorPete Zaitcev <zaitcev@redhat.com>
Thu, 17 Feb 2005 03:56:54 +0000 (19:56 -0800)
committerGreg Kroah-Hartman <gregkh@kernel.bkbits.net>
Thu, 17 Feb 2005 03:56:54 +0000 (19:56 -0800)
This patch adds support for ioctls to ub, with the help of scsi_ioctl_cmd().
Now ub can eject CDs. But do not try to burn CDs yet, it's not tested.

Original patch from Peter Jones (aka deviant-).

Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
drivers/block/ub.c

index 84991b28a9bc83abc2b9645ef84becbcb2a3eab5..4384d6a2486699495a3f198027120e3baa6e1b86 100644 (file)
@@ -300,6 +300,11 @@ struct ub_dev {
 
 /*
  */
+static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq);
+static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
+    struct request *rq);
+static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
+    struct request *rq);
 static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
 static void ub_end_rq(struct request *rq, int uptodate);
 static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
@@ -591,40 +596,73 @@ static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc)
  * The request function is our main entry point
  */
 
-static inline int ub_bd_rq_fn_1(request_queue_t *q)
+static void ub_bd_rq_fn(request_queue_t *q)
 {
-#if 0
-       int writing = 0, pci_dir, i, n_elem;
-       u32 tmp;
-       unsigned int msg_size;
-#endif
        struct ub_dev *sc = q->queuedata;
        struct request *rq;
-#if 0 /* We use rq->buffer for now */
-       struct scatterlist *sg;
-       int n_elem;
-#endif
+
+       while ((rq = elv_next_request(q)) != NULL) {
+               if (ub_bd_rq_fn_1(sc, rq) != 0) {
+                       blk_stop_queue(q);
+                       break;
+               }
+       }
+}
+
+static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq)
+{
        struct ub_scsi_cmd *cmd;
-       int ub_dir;
-       unsigned int block, nblks;
        int rc;
 
-       if ((rq = elv_next_request(q)) == NULL)
-               return 1;
-
        if (atomic_read(&sc->poison) || sc->changed) {
                blkdev_dequeue_request(rq);
                ub_end_rq(rq, 0);
                return 0;
        }
 
-       if ((cmd = ub_get_cmd(sc)) == NULL) {
-               blk_stop_queue(q);
-               return 1;
-       }
+       if ((cmd = ub_get_cmd(sc)) == NULL)
+               return -1;
+       memset(cmd, 0, sizeof(struct ub_scsi_cmd));
 
        blkdev_dequeue_request(rq);
 
+       if (blk_pc_request(rq)) {
+               rc = ub_cmd_build_packet(sc, cmd, rq);
+       } else {
+               rc = ub_cmd_build_block(sc, cmd, rq);
+       }
+       if (rc != 0) {
+               ub_put_cmd(sc, cmd);
+               ub_end_rq(rq, 0);
+               blk_start_queue(sc->disk->queue);
+               return 0;
+       }
+
+       cmd->state = UB_CMDST_INIT;
+       cmd->done = ub_rw_cmd_done;
+       cmd->back = rq;
+
+       cmd->tag = sc->tagcnt++;
+       if ((rc = ub_submit_scsi(sc, cmd)) != 0) {
+               ub_put_cmd(sc, cmd);
+               ub_end_rq(rq, 0);
+               blk_start_queue(sc->disk->queue);
+               return 0;
+       }
+
+       return 0;
+}
+
+static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
+    struct request *rq)
+{
+       int ub_dir;
+#if 0 /* We use rq->buffer for now */
+       struct scatterlist *sg;
+       int n_elem;
+#endif
+       unsigned int block, nblks;
+
        if (rq_data_dir(rq) == WRITE)
                ub_dir = UB_DIR_WRITE;
        else
@@ -652,6 +690,7 @@ static inline int ub_bd_rq_fn_1(request_queue_t *q)
                return 0;
        }
 #endif
+
        /*
         * XXX Unfortunately, this check does not work. It is quite possible
         * to get bogus non-null rq->buffer if you allow sg by mistake.
@@ -663,13 +702,12 @@ static inline int ub_bd_rq_fn_1(request_queue_t *q)
                 */
                static int do_print = 1;
                if (do_print) {
-                       printk(KERN_WARNING "%s: unmapped request\n", sc->name);
+                       printk(KERN_WARNING "%s: unmapped block request"
+                           " flags 0x%lx sectors %lu\n",
+                           sc->name, rq->flags, rq->nr_sectors);
                        do_print = 0;
                }
-               ub_put_cmd(sc, cmd);
-               ub_end_rq(rq, 0);
-               blk_start_queue(q);
-               return 0;
+               return -1;
        }
 
        /*
@@ -681,7 +719,6 @@ static inline int ub_bd_rq_fn_1(request_queue_t *q)
        block = rq->sector >> sc->capacity.bshift;
        nblks = rq->nr_sectors >> sc->capacity.bshift;
 
-       memset(cmd, 0, sizeof(struct ub_scsi_cmd));
        cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10;
        /* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */
        cmd->cdb[2] = block >> 24;
@@ -691,27 +728,44 @@ static inline int ub_bd_rq_fn_1(request_queue_t *q)
        cmd->cdb[7] = nblks >> 8;
        cmd->cdb[8] = nblks;
        cmd->cdb_len = 10;
+
        cmd->dir = ub_dir;
-       cmd->state = UB_CMDST_INIT;
        cmd->data = rq->buffer;
        cmd->len = rq->nr_sectors * 512;
-       cmd->done = ub_rw_cmd_done;
-       cmd->back = rq;
-
-       cmd->tag = sc->tagcnt++;
-       if ((rc = ub_submit_scsi(sc, cmd)) != 0) {
-               ub_put_cmd(sc, cmd);
-               ub_end_rq(rq, 0);
-               blk_start_queue(q);
-               return 0;
-       }
 
        return 0;
 }
 
-static void ub_bd_rq_fn(request_queue_t *q)
+static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
+    struct request *rq)
 {
-       do { } while (ub_bd_rq_fn_1(q) == 0);
+
+       if (rq->data_len != 0 && rq->data == NULL) {
+               static int do_print = 1;
+               if (do_print) {
+                       printk(KERN_WARNING "%s: unmapped packet request"
+                           " flags 0x%lx length %d\n",
+                           sc->name, rq->flags, rq->data_len);
+                       do_print = 0;
+               }
+               return -1;
+       }
+
+       memcpy(&cmd->cdb, rq->cmd, rq->cmd_len);
+       cmd->cdb_len = rq->cmd_len;
+
+       if (rq->data_len == 0) {
+               cmd->dir = UB_DIR_NONE;
+       } else {
+               if (rq_data_dir(rq) == WRITE)
+                       cmd->dir = UB_DIR_WRITE;
+               else
+                       cmd->dir = UB_DIR_READ;
+       }
+       cmd->data = rq->data;
+       cmd->len = rq->data_len;
+
+       return 0;
 }
 
 static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
@@ -884,6 +938,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 {
        struct urb *urb = &sc->work_urb;
        struct bulk_cs_wrap *bcs;
+       struct request *rq = cmd->back;
        int pipe;
        int rc;
 
@@ -1137,6 +1192,13 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                (*cmd->done)(sc, cmd);
 
        } else if (cmd->state == UB_CMDST_SENSE) {
+               if (blk_pc_request(rq)) {
+                       /*
+                        * UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE
+                        */
+                       memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE);
+                       rq->sense_len = UB_SENSE_SIZE;
+               }
                ub_state_done(sc, cmd, -EIO);
 
        } else {
@@ -1495,30 +1557,10 @@ static int ub_bd_release(struct inode *inode, struct file *filp)
 static int ub_bd_ioctl(struct inode *inode, struct file *filp,
     unsigned int cmd, unsigned long arg)
 {
-// void __user *usermem = (void *) arg;
-// struct carm_port *port = ino->i_bdev->bd_disk->private_data;
-// struct hd_geometry geom;
-
-#if 0
-       switch (cmd) {
-       case HDIO_GETGEO:
-               if (usermem == NULL)            // XXX Bizzare. Why?
-                       return -EINVAL;
-
-               geom.heads = (u8) port->dev_geom_head;
-               geom.sectors = (u8) port->dev_geom_sect;
-               geom.cylinders = port->dev_geom_cyl;
-               geom.start = get_start_sect(ino->i_bdev);
-
-               if (copy_to_user(usermem, &geom, sizeof(geom)))
-                       return -EFAULT;
-               return 0;
-
-       default: ;
-       }
-#endif
+       struct gendisk *disk = inode->i_bdev->bd_disk;
+       void __user *usermem = (void __user *) arg;
 
-       return -ENOTTY;
+       return scsi_cmd_ioctl(filp, disk, cmd, usermem);
 }
 
 /*