Hi.

Here is a patch for test11 which modifies the datafab driver according to my understanding of the datafab device. I completely removed the lun detection but left this work up to the operating system, namely sd_mod.ko. sd_mod can decide which lun is available by means of checking the media presence flag which is reported from the datafab_id_device function. Now the driver works with _my_ datafab device.

But there is still a glitch in the driver. If I rmmod and insmod the usb-storage module, the insmod hangs. If I disconnect the datafab device, rmmod the driver, connect the device, insmod the usb-storage module it works. Strange. I can't track down if the error is in the datafab source file or somewhere else. My current feeling says it is somewhere else, maybe due to the complex deregistering path.

The problem is that all requests to the device time out:

Dec 9 23:20:47 kernel: usb-storage: Command TEST_UNIT_READY (6 bytes)
Dec 9 23:20:47 kernel: usb-storage: 00 00 00 00 00 00
Dec 9 23:20:47 kernel: usb-storage: datafab_transport: TEST_UNIT_READY.
Dec 9 23:20:47 kernel: usb-storage: datafab_bulk_write: len = 8
Dec 9 23:20:47 kernel: usb-storage: usb_stor_bulk_transfer_buf: xfer 8 bytes
Dec 9 23:21:17 kernel: usb-storage: command_abort called
Dec 9 23:21:17 kernel: usb-storage: usb_stor_stop_transport called
Dec 9 23:21:17 kernel: usb-storage: -- cancelling URB
Dec 9 23:21:17 kernel: usb-storage: Status code -104; transferred 0/8
Dec 9 23:21:17 kernel: usb-storage: -- transfer cancelled
Dec 9 23:21:17 kernel: usb-storage: -- command was aborted
Dec 9 23:21:17 kernel: usb-storage: scsi command aborted


But aside from that i'd like to see the new code in the kernel. Comments?

bye,
eduard.
--- linux-2.6.0-test11/drivers/usb/storage/datafab.c.orig       2003-10-25 
20:44:53.000000000 +0200
+++ linux-2.6.0-test11/drivers/usb/storage/datafab.c    2003-12-09 23:16:16.000000000 
+0100
@@ -61,10 +61,6 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 
-static int datafab_determine_lun(struct us_data *us,
-                                struct datafab_info *info);
-
-
 static inline int
 datafab_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) {
        if (len == 0)
@@ -89,6 +85,7 @@
 
 static int datafab_read_data(struct us_data *us,
                             struct datafab_info *info,
+                            char lun,
                             u32 sector,
                             u32 sectors, 
                             unsigned char *dest, 
@@ -100,7 +97,6 @@
        unsigned char  thistime;
        int totallen, len, result;
        int sg_idx = 0, sg_offset = 0;
-       int rc;
 
        // we're working in LBA mode.  according to the ATA spec, 
        // we can support up to 28-bit addressing.  I don't know if Datafab
@@ -110,12 +106,6 @@
        if (sectors > 0x0FFFFFFF)
                return USB_STOR_TRANSPORT_ERROR;
 
-       if (info->lun == -1) {
-               rc = datafab_determine_lun(us, info);
-               if (rc != USB_STOR_TRANSPORT_GOOD)
-                       return rc;
-       }
-
        totallen = sectors * info->ssize;
 
        do {
@@ -136,7 +126,7 @@
                command[3] = (sector >> 8) & 0xFF;
                command[4] = (sector >> 16) & 0xFF;
        
-               command[5] = 0xE0 + (info->lun << 4);
+               command[5] = 0xE0 + (lun << 4);
                command[5] |= (sector >> 24) & 0x0F;
                command[6] = 0x20;
                command[7] = 0x01;
@@ -176,6 +166,7 @@
 
 static int datafab_write_data(struct us_data *us,
                              struct datafab_info *info,
+                             char lun,
                              u32 sector,
                              u32 sectors, 
                              unsigned char *src, 
@@ -186,7 +177,7 @@
        unsigned char *buffer = NULL;
        unsigned char *ptr;
        unsigned char thistime;
-       int totallen, len, result, rc;
+       int totallen, len, result;
        int sg_idx = 0, sg_offset = 0;
 
        // we're working in LBA mode.  according to the ATA spec, 
@@ -197,12 +188,6 @@
        if (sectors > 0x0FFFFFFF)
                return USB_STOR_TRANSPORT_ERROR;
 
-       if (info->lun == -1) {
-               rc = datafab_determine_lun(us, info);
-               if (rc != USB_STOR_TRANSPORT_GOOD)
-                       return rc;
-       }
-
        // If we're using scatter-gather, we have to create a new
        // buffer to read all of the data in first, since a
        // scatter-gather buffer could in theory start in the middle
@@ -236,7 +221,7 @@
                command[3] = (sector >> 8) & 0xFF;
                command[4] = (sector >> 16) & 0xFF;
 
-               command[5] = 0xE0 + (info->lun << 4);
+               command[5] = 0xE0 + (lun << 4);
                command[5] |= (sector >> 24) & 0x0F;
                command[6] = 0x30;
                command[7] = 0x02;
@@ -284,75 +269,9 @@
 }
 
 
-static int datafab_determine_lun(struct us_data *us,
-                                struct datafab_info *info)
-{
-       // Dual-slot readers can be thought of as dual-LUN devices.
-       // We need to determine which card slot is being used.
-       // We'll send an IDENTIFY DEVICE command and see which LUN responds...
-       //
-       // There might be a better way of doing this?
-
-       static unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
-       unsigned char *command = us->iobuf;
-       unsigned char *buf;
-       int count = 0, rc;
-
-       if (!us || !info)
-               return USB_STOR_TRANSPORT_ERROR;
-
-       memcpy(command, scommand, 8);
-       buf = kmalloc(512, GFP_NOIO);
-       if (!buf)
-               return USB_STOR_TRANSPORT_ERROR;
-
-       US_DEBUGP("datafab_determine_lun:  locating...\n");
-
-       // we'll try 3 times before giving up...
-       //
-       while (count++ < 3) {
-               command[5] = 0xa0;
-
-               rc = datafab_bulk_write(us, command, 8);
-               if (rc != USB_STOR_XFER_GOOD) {
-                       rc = USB_STOR_TRANSPORT_ERROR;
-                       goto leave;
-               }
-
-               rc = datafab_bulk_read(us, buf, 512);
-               if (rc == USB_STOR_XFER_GOOD) {
-                       info->lun = 0;
-                       rc = USB_STOR_TRANSPORT_GOOD;
-                       goto leave;
-               }
-
-               command[5] = 0xb0;
-
-               rc = datafab_bulk_write(us, command, 8);
-               if (rc != USB_STOR_XFER_GOOD) {
-                       rc = USB_STOR_TRANSPORT_ERROR;
-                       goto leave;
-               }
-
-               rc = datafab_bulk_read(us, buf, 512);
-               if (rc == USB_STOR_XFER_GOOD) {
-                       info->lun = 1;
-                       rc = USB_STOR_TRANSPORT_GOOD;
-                       goto leave;
-               }
-
-               wait_ms(20);
-       }
-
-       rc = USB_STOR_TRANSPORT_ERROR;
-
- leave:
-       kfree(buf);
-       return rc;
-}
-
 static int datafab_id_device(struct us_data *us,
-                            struct datafab_info *info)
+                            struct datafab_info *info,
+                            char lun)
 {
        // this is a variation of the ATA "IDENTIFY DEVICE" command...according
        // to the ATA spec, 'Sector Count' isn't used but the Windows driver
@@ -366,18 +285,12 @@
        if (!us || !info)
                return USB_STOR_TRANSPORT_ERROR;
 
-       if (info->lun == -1) {
-               rc = datafab_determine_lun(us, info);
-               if (rc != USB_STOR_TRANSPORT_GOOD)
-                       return rc;
-       }
-
        memcpy(command, scommand, 8);
        reply = kmalloc(512, GFP_NOIO);
        if (!reply)
                return USB_STOR_TRANSPORT_ERROR;
 
-       command[5] += (info->lun << 4);
+       command[5] += (lun << 4);
 
        rc = datafab_bulk_write(us, command, 8);
        if (rc != USB_STOR_XFER_GOOD) {
@@ -387,7 +300,7 @@
 
        // we'll go ahead and extract the media capacity while we're here...
        //
-       rc = datafab_bulk_read(us, reply, sizeof(reply));
+       rc = datafab_bulk_read(us, reply, 512);
        if (rc == USB_STOR_XFER_GOOD) {
                // capacity is at word offset 57-58
                //
@@ -396,6 +309,17 @@
                                ((u32)(reply[115]) <<  8) | 
                                ((u32)(reply[114])      );
                rc = USB_STOR_TRANSPORT_GOOD;
+               // delete old sense information
+               info->sense_key = NO_SENSE;
+               info->sense_asc = 0;
+               goto leave;
+       }
+
+       // we get a short transfer on empty medium slot
+       if (rc == USB_STOR_XFER_SHORT) {
+               rc = USB_STOR_TRANSPORT_FAILED;
+               info->sense_key = UNIT_ATTENTION;
+               info->sense_asc = 0x3A;
                goto leave;
        }
 
@@ -560,7 +484,6 @@
                }
                memset(us->extra, 0, sizeof(struct datafab_info));
                us->extra_destructor = datafab_info_destructor;
-               ((struct datafab_info *)us->extra)->lun = -1;
        }
 
        info = (struct datafab_info *) (us->extra);
@@ -575,7 +498,7 @@
 
        if (srb->cmnd[0] == READ_CAPACITY) {
                info->ssize = 0x200;  // hard coded 512 byte sectors as per ATA spec
-               rc = datafab_id_device(us, info);
+               rc = datafab_id_device(us, info, srb->device->lun);
                if (rc != USB_STOR_TRANSPORT_GOOD)
                        return rc;
 
@@ -611,7 +534,7 @@
                blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
 
                US_DEBUGP("datafab_transport:  READ_10: read block 0x%04lx  count 
%ld\n", block, blocks);
-               return datafab_read_data(us, info, block, blocks, ptr, srb->use_sg);
+               return datafab_read_data(us, info, srb->device->lun, block, blocks, 
ptr, srb->use_sg);
        }
 
        if (srb->cmnd[0] == READ_12) {
@@ -624,7 +547,7 @@
                         ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9]));
 
                US_DEBUGP("datafab_transport:  READ_12: read block 0x%04lx  count 
%ld\n", block, blocks);
-               return datafab_read_data(us, info, block, blocks, ptr, srb->use_sg);
+               return datafab_read_data(us, info, srb->device->lun, block, blocks, 
ptr, srb->use_sg);
        }
 
        if (srb->cmnd[0] == WRITE_10) {
@@ -634,7 +557,7 @@
                blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
 
                US_DEBUGP("datafab_transport:  WRITE_10: write block 0x%04lx  count 
%ld\n", block, blocks);
-               return datafab_write_data(us, info, block, blocks, ptr, srb->use_sg);
+               return datafab_write_data(us, info, srb->device->lun, block, blocks, 
ptr, srb->use_sg);
        }
 
        if (srb->cmnd[0] == WRITE_12) {
@@ -647,12 +570,12 @@
                         ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9]));
 
                US_DEBUGP("datafab_transport:  WRITE_12: write block 0x%04lx  count 
%ld\n", block, blocks);
-               return datafab_write_data(us, info, block, blocks, ptr, srb->use_sg);
+               return datafab_write_data(us, info, srb->device->lun, block, blocks, 
ptr, srb->use_sg);
        }
 
        if (srb->cmnd[0] == TEST_UNIT_READY) {
                US_DEBUGP("datafab_transport:  TEST_UNIT_READY.\n");
-               return datafab_id_device(us, info);
+               return datafab_id_device(us, info, srb->device->lun);
        }
 
        if (srb->cmnd[0] == REQUEST_SENSE) {
@@ -694,7 +617,7 @@
                US_DEBUGP("datafab_transport:  START_STOP.\n");
                /* the first datafab_id_device after a media change returns
                   an error (determined experimentally) */
-               rc = datafab_id_device(us, info);
+               rc = datafab_id_device(us, info, srb->device->lun);
                if (rc == USB_STOR_TRANSPORT_GOOD) {
                        info->sense_key = NO_SENSE;
                        srb->result = SUCCESS;
--- linux-2.6.0-test11/drivers/usb/storage/datafab.h.orig       2003-10-25 
20:44:14.000000000 +0200
+++ linux-2.6.0-test11/drivers/usb/storage/datafab.h    2003-12-09 22:58:26.000000000 
+0100
@@ -29,7 +29,6 @@
 struct datafab_info {
        unsigned long   sectors;        // total sector count
        unsigned long   ssize;          // sector size in bytes
-       char            lun;            // used for dual-slot readers
        
        // the following aren't used yet
        unsigned char   sense_key;

Reply via email to