fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / usb / image / microtek.c
index 230efaf..8ccddf7 100644 (file)
@@ -160,7 +160,6 @@ static void mts_usb_disconnect(struct usb_interface *intf);
 static struct usb_device_id mts_usb_ids [];
 
 static struct usb_driver mts_usb_driver = {
-       .owner =        THIS_MODULE,
        .name =         "microtekX6",
        .probe =        mts_usb_probe,
        .disconnect =   mts_usb_disconnect,
@@ -214,8 +213,8 @@ static struct usb_driver mts_usb_driver = {
 #ifdef MTS_DO_DEBUG
 
 static inline void mts_debug_dump(struct mts_desc* desc) {
-       MTS_DEBUG("desc at 0x%x: halted = %02x%02x, toggle = %02x%02x\n",
-                 (int)desc,(int)desc->usb_dev->halted[1],(int)desc->usb_dev->halted[0],
+       MTS_DEBUG("desc at 0x%x: toggle = %02x%02x\n",
+                 (int)desc,
                  (int)desc->usb_dev->toggle[1],(int)desc->usb_dev->toggle[0]
                );
        MTS_DEBUG("ep_out=%x ep_response=%x ep_image=%x\n",
@@ -226,7 +225,7 @@ static inline void mts_debug_dump(struct mts_desc* desc) {
 }
 
 
-static inline void mts_show_command(Scsi_Cmnd *srb)
+static inline void mts_show_command(struct scsi_cmnd *srb)
 {
        char *what = NULL;
 
@@ -310,7 +309,7 @@ static inline void mts_show_command(Scsi_Cmnd *srb)
 
 #else
 
-static inline void mts_show_command(Scsi_Cmnd * dummy)
+static inline void mts_show_command(struct scsi_cmnd * dummy)
 {
 }
 
@@ -324,10 +323,22 @@ static inline void mts_urb_abort(struct mts_desc* desc) {
        MTS_DEBUG_GOT_HERE();
        mts_debug_dump(desc);
 
-       usb_unlink_urb( desc->urb );
+       usb_kill_urb( desc->urb );
 }
 
-static int mts_scsi_abort (Scsi_Cmnd *srb)
+static int mts_slave_alloc (struct scsi_device *s)
+{
+       s->inquiry_len = 0x24;
+       return 0;
+}
+
+static int mts_slave_configure (struct scsi_device *s)
+{
+       blk_queue_dma_alignment(s->request_queue, (512 - 1));
+       return 0;
+}
+
+static int mts_scsi_abort(struct scsi_cmnd *srb)
 {
        struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
 
@@ -335,28 +346,33 @@ static int mts_scsi_abort (Scsi_Cmnd *srb)
 
        mts_urb_abort(desc);
 
-       return SCSI_ABORT_PENDING;
+       return FAILED;
 }
 
-static int mts_scsi_host_reset (Scsi_Cmnd *srb)
+static int mts_scsi_host_reset(struct scsi_cmnd *srb)
 {
        struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
+       int result, rc;
 
        MTS_DEBUG_GOT_HERE();
        mts_debug_dump(desc);
 
-       usb_reset_device(desc->usb_dev); /*FIXME: untested on new reset code */
-       return 0;  /* RANT why here 0 and not SUCCESS */
+       rc = usb_lock_device_for_reset(desc->usb_dev, desc->usb_intf);
+       if (rc < 0)
+               return FAILED;
+       result = usb_reset_device(desc->usb_dev);
+       if (rc)
+               usb_unlock_device(desc->usb_dev);
+       return result ? FAILED : SUCCESS;
 }
 
-static
-int mts_scsi_queuecommand (Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback );
+static int
+mts_scsi_queuecommand(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback);
 
 static void mts_transfer_cleanup( struct urb *transfer );
-static void mts_do_sg(struct urb * transfer, struct pt_regs *regs);
-
+static void mts_do_sg(struct urb * transfer);
 
-inline static
+static inline
 void mts_int_submit_urb (struct urb* transfer,
                        int pipe,
                        void* data,
@@ -401,12 +417,12 @@ static void mts_transfer_cleanup( struct urb *transfer )
 
 }
 
-static void mts_transfer_done( struct urb *transfer, struct pt_regs *regs )
+static void mts_transfer_done( struct urb *transfer )
 {
        MTS_INT_INIT();
 
        context->srb->result &= MTS_SCSI_ERR_MASK;
-       context->srb->result |= (unsigned)context->status<<1;
+       context->srb->result |= (unsigned)(*context->scsi_status)<<1;
 
        mts_transfer_cleanup(transfer);
 
@@ -422,12 +438,12 @@ static void mts_get_status( struct urb *transfer )
        mts_int_submit_urb(transfer,
                           usb_rcvbulkpipe(context->instance->usb_dev,
                                           context->instance->ep_response),
-                          &context->status,
+                          context->scsi_status,
                           1,
                           mts_transfer_done );
 }
 
-static void mts_data_done( struct urb* transfer, struct pt_regs *regs )
+static void mts_data_done( struct urb* transfer )
 /* Interrupt context! */
 {
        MTS_INT_INIT();
@@ -444,7 +460,7 @@ static void mts_data_done( struct urb* transfer, struct pt_regs *regs )
 }
 
 
-static void mts_command_done( struct urb *transfer, struct pt_regs *regs )
+static void mts_command_done( struct urb *transfer )
 /* Interrupt context! */
 {
        MTS_INT_INIT();
@@ -476,7 +492,7 @@ static void mts_command_done( struct urb *transfer, struct pt_regs *regs )
                                           context->data_pipe,
                                           context->data,
                                           context->data_length,
-                                          context->srb->use_sg ? mts_do_sg : mts_data_done);
+                                          context->srb->use_sg > 1 ? mts_do_sg : mts_data_done);
                } else {
                        mts_get_status(transfer);
                }
@@ -485,7 +501,7 @@ static void mts_command_done( struct urb *transfer, struct pt_regs *regs )
        return;
 }
 
-static void mts_do_sg (struct urb* transfer, struct pt_regs *regs)
+static void mts_do_sg (struct urb* transfer)
 {
        struct scatterlist * sg;
        MTS_INT_INIT();
@@ -497,7 +513,7 @@ static void mts_do_sg (struct urb* transfer, struct pt_regs *regs)
                mts_transfer_cleanup(transfer);
         }
 
-       sg = context->srb->buffer;
+       sg = context->srb->request_buffer;
        context->fragment++;
        mts_int_submit_urb(transfer,
                           context->data_pipe,
@@ -521,7 +537,7 @@ static const unsigned char mts_direction[256/8] = {
 #define MTS_DIRECTION_IS_IN(x) ((mts_direction[x>>3] >> (x & 7)) & 1)
 
 static void
-mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc )
+mts_build_transfer_context(struct scsi_cmnd *srb, struct mts_desc* desc)
 {
        int pipe;
        struct scatterlist * sg;
@@ -533,19 +549,19 @@ mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc )
        desc->context.fragment = 0;
 
        if (!srb->use_sg) {
-               if ( !srb->bufflen ){
+               if ( !srb->request_bufflen ){
                        desc->context.data = NULL;
                        desc->context.data_length = 0;
                        return;
                } else {
-                       desc->context.data = srb->buffer;
-                       desc->context.data_length = srb->bufflen;
+                       desc->context.data = srb->request_buffer;
+                       desc->context.data_length = srb->request_bufflen;
                        MTS_DEBUG("length = %d or %d\n",
                                  srb->request_bufflen, srb->bufflen);
                }
        } else {
                MTS_DEBUG("Using scatter/gather\n");
-               sg = srb->buffer;
+               sg = srb->request_buffer;
                desc->context.data = page_address(sg[0].page) + sg[0].offset;
                desc->context.data_length = sg[0].length;
        }
@@ -572,8 +588,8 @@ mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc )
 }
 
 
-static
-int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback )
+static int
+mts_scsi_queuecommand(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback)
 {
        struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
        int err = 0;
@@ -622,12 +638,11 @@ int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback )
                        callback(srb);
 
        }
-
 out:
        return err;
 }
 
-static Scsi_Host_Template mts_scsi_host_template = {
+static struct scsi_host_template mts_scsi_host_template = {
        .module                 = THIS_MODULE,
        .name                   = "microtekX6",
        .proc_name              = "microtekX6",
@@ -640,6 +655,9 @@ static Scsi_Host_Template mts_scsi_host_template = {
        .cmd_per_lun =          1,
        .use_clustering =       1,
        .emulated =             1,
+       .slave_alloc =          mts_slave_alloc,
+       .slave_configure =      mts_slave_configure,
+       .max_sectors=           256, /* 128 K */
 };
 
 struct vendor_product
@@ -656,7 +674,7 @@ struct vendor_product
 
 
 /* These are taken from the msmUSB.inf file on the Windows driver CD */
-const static struct vendor_product mts_supported_products[] =
+static const struct vendor_product mts_supported_products[] =
 {
        { "Phantom 336CX",      mts_sup_unknown},
        { "Phantom 336CX",      mts_sup_unknown},
@@ -697,6 +715,7 @@ static int mts_usb_probe(struct usb_interface *intf,
        int ep_in_set[3]; /* this will break if we have more than three endpoints
                           which is why we check */
        int *ep_in_current = ep_in_set;
+       int err_retval = -ENOMEM;
 
        struct mts_desc * new_desc;
        struct vendor_product const* p;
@@ -709,8 +728,8 @@ static int mts_usb_probe(struct usb_interface *intf,
        MTS_DEBUG( "usb-device descriptor at %x\n", (int)dev );
 
        MTS_DEBUG( "product id = 0x%x, vendor id = 0x%x\n",
-                  (int)dev->descriptor.idProduct,
-                  (int)dev->descriptor.idVendor );
+                  le16_to_cpu(dev->descriptor.idProduct),
+                  le16_to_cpu(dev->descriptor.idVendor) );
 
        MTS_DEBUG_GOT_HERE();
 
@@ -765,18 +784,22 @@ static int mts_usb_probe(struct usb_interface *intf,
                MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" );
                return -ENODEV;
        }
-       
-       
-       new_desc = kmalloc(sizeof(struct mts_desc), GFP_KERNEL);
+
+
+       new_desc = kzalloc(sizeof(struct mts_desc), GFP_KERNEL);
        if (!new_desc)
                goto out;
 
-       memset(new_desc, 0, sizeof(*new_desc));
        new_desc->urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!new_desc->urb)
                goto out_kfree;
 
+       new_desc->context.scsi_status = kmalloc(1, GFP_KERNEL);
+       if (!new_desc->context.scsi_status)
+               goto out_free_urb;
+
        new_desc->usb_dev = dev;
+       new_desc->usb_intf = intf;
        init_MUTEX(&new_desc->lock);
 
        /* endpoints */
@@ -799,21 +822,28 @@ static int mts_usb_probe(struct usb_interface *intf,
        new_desc->host = scsi_host_alloc(&mts_scsi_host_template,
                        sizeof(new_desc));
        if (!new_desc->host)
-               goto out_free_urb;
+               goto out_kfree2;
 
        new_desc->host->hostdata[0] = (unsigned long)new_desc;
-       scsi_add_host(new_desc->host, NULL); /* XXX handle failure */
+       if (scsi_add_host(new_desc->host, NULL)) {
+               err_retval = -EIO;
+               goto out_host_put;
+       }
        scsi_scan_host(new_desc->host);
 
        usb_set_intfdata(intf, new_desc);
        return 0;
 
+ out_host_put:
+       scsi_host_put(new_desc->host);
+ out_kfree2:
+       kfree(new_desc->context.scsi_status);
  out_free_urb:
        usb_free_urb(new_desc->urb);
  out_kfree:
        kfree(new_desc);
  out:
-       return -ENOMEM;
+       return err_retval;
 }
 
 static void mts_usb_disconnect (struct usb_interface *intf)
@@ -822,11 +852,12 @@ static void mts_usb_disconnect (struct usb_interface *intf)
 
        usb_set_intfdata(intf, NULL);
 
+       usb_kill_urb(desc->urb);
        scsi_remove_host(desc->host);
-       usb_unlink_urb(desc->urb);
-       scsi_host_put(desc->host);
 
+       scsi_host_put(desc->host);
        usb_free_urb(desc->urb);
+       kfree(desc->context.scsi_status);
        kfree(desc);
 }
 
@@ -847,5 +878,3 @@ module_exit(microtek_drv_exit);
 MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
 MODULE_LICENSE("GPL");
-
-