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

diff -urp -X dontdiff linux-2.6.11-rc2/drivers/block/ub.c 
linux-2.6.11-rc2-lem/drivers/block/ub.c
--- linux-2.6.11-rc2/drivers/block/ub.c 2005-01-22 14:54:09.000000000 -0800
+++ linux-2.6.11-rc2-lem/drivers/block/ub.c     2005-01-26 23:48:06.000000000 
-0800
@@ -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(s
  * 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_
                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_
                 */
                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_
        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_
        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_
 {
        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_
                (*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 *i
 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);
 }
 
 /*


-------------------------------------------------------
This SF.Net email is sponsored by: IntelliVIEW -- Interactive Reporting
Tool for open source databases. Create drag-&-drop reports. Save time
by over 75%! Publish reports on the web. Export to DOC, XLS, RTF, etc.
Download a FREE copy at http://www.intelliview.com/go/osdn_nl
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to