/*
*/
+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);
* 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
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.
*/
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;
}
/*
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;
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)
{
struct urb *urb = &sc->work_urb;
struct bulk_cs_wrap *bcs;
+ struct request *rq = cmd->back;
int pipe;
int rc;
(*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 {
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);
}
/*