[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[cdi-devel] [PATCH] No STALL



From: Max Reitz <max@xxxxxxxxxx>

* Stall problem removed, hopefully more correct
  msc driver code.

Signed-off-by: Max Reitz <max@xxxxxxxxxx>
---
 usb/include/usb.h |   19 +++---
 usb/main.c        |    3 +
 usb/msd.c         |  180 +++++++++++++++++++++++++----------------------------
 3 files changed, 98 insertions(+), 104 deletions(-)

diff --git a/usb/include/usb.h b/usb/include/usb.h
index b6ff391..584f31f 100644
--- a/usb/include/usb.h
+++ b/usb/include/usb.h
@@ -93,15 +93,16 @@ enum usb_packet_type {
 #define DESC_OTHER_SPEED_CONFIGURATION 7
 #define DESC_INTERFACE_POWER           8
 
-#define USB_NO_ERROR                   0x00
-#define USB_STALLED                    0x01
-#define USB_BUFFER_ERROR               0x02
-#define USB_BABBLE                     0x04
-#define USB_NAK                        0x08
-#define USB_CRC                        0x10
-#define USB_TIMEOUT                    0x20
-#define USB_BITSTUFF                   0x40
-#define USB_TRIVIAL_ERROR              0x80
+#define USB_NO_ERROR                   0x0000
+#define USB_STALLED                    0x0001
+#define USB_BUFFER_ERROR               0x0002
+#define USB_BABBLE                     0x0004
+#define USB_NAK                        0x0008
+#define USB_CRC                        0x0010
+#define USB_TIMEOUT                    0x0020
+#define USB_BITSTUFF                   0x0040
+#define USB_TRIVIAL_ERROR              0x0080
+#define USB_STATUS_ERROR               0x0100
 
 #define USB_TOD_SETUP                  0x0001
 #define USB_TOD_SETUP_DATA_IN          0x0002
diff --git a/usb/main.c b/usb/main.c
index 878aefe..9eb20d8 100644
--- a/usb/main.c
+++ b/usb/main.c
@@ -126,6 +126,9 @@ int usb_do_packet(struct usb_device* device, struct usb_packet* packet)
     }
     while (error == USB_NAK) {
         error = device->hci->do_packet(device, packet);
+        if (error == USB_NAK) {
+            cdi_sleep_ms(5);
+        }
     }
     if (error == USB_STALLED) {
         printf("[usb] ENDPOINT %i DES GERÃ?TS %i STALLED!\n", packet->endpoint,
diff --git a/usb/msd.c b/usb/msd.c
index ad6f362..471856a 100644
--- a/usb/msd.c
+++ b/usb/msd.c
@@ -169,13 +169,15 @@ void register_msd(struct usb_device* usbdev)
     for (i = 0; i < usbdev->interface->num_endpoints; i++) {
         ep_desc = address;
         if ((ep_desc->endpoint_address & 0x80) &&
-            (ep_desc->attributes == 0x02) && (msc->bulk_ep_in == NULL))                                                             //BULK-IN
+            (ep_desc->attributes == 0x02) && (msc->bulk_ep_in == NULL))
         {
+            //BULK-IN
             msc->bulk_ep_in = ep_desc;
         } else if (!(ep_desc->endpoint_address & 0x80) &&
                    (ep_desc->attributes == 0x02) &&
-                   (msc->bulk_ep_out == NULL))                                                                                             //BULK-OUT
+                   (msc->bulk_ep_out == NULL))
         {
+            //BULK-OUT
             msc->bulk_ep_out = ep_desc;
         }
         address += sizeof(struct endpoint_desc);
@@ -252,7 +254,7 @@ static int read_status(struct usb_device* usbdev, uint32_t expected_tag)
     struct command_status_wrapper* csw;
     int error;
 
-    if (cdi_alloc_phys_mem(sizeof(struct command_status_wrapper), (void**) &csw,
+    if (cdi_alloc_phys_mem(sizeof(*csw), (void**) &csw,
             (void**) &pcsw) == -1)
     {
         return USB_TRIVIAL_ERROR;
@@ -274,9 +276,11 @@ static int read_status(struct usb_device* usbdev, uint32_t expected_tag)
     if ((csw->csw_signature != CSW_SIGNATURE) ||
         (csw->csw_tag != expected_tag) || csw->csw_status)
     {
-        return USB_CRC;         //Watt weiÃ? denn ich
-
+        dprintf("0x%08X %i==%i 0x%08X\n", csw->csw_signature, csw->csw_tag,
+            expected_tag, csw->csw_status);
+        return USB_STATUS_ERROR;
     }
+
     return USB_NO_ERROR;
 }
 
@@ -358,9 +362,9 @@ static int msd_ready(struct usb_device* usbdev)
     cbw->cbw_signature = CBW_SIGNATURE;
     cbw->cbw_tag = (expected_tag = cbw_tag++);
     cbw->cbw_data_transfer_length = 0;
-    cbw->cbw_flags = 0x80;      //IN
-    cbw->cbw_lun = 0;           //Was weiÃ? ich, wie viele LUNs datt Dingens hat?
-    cbw->cbw_cb_length = 12;    //Alles null, also "Test unit ready"
+    cbw->cbw_flags = 0x80; //IN
+    cbw->cbw_lun = 0; //Was weiÃ? ich, wie viele LUNs datt Dingens hat?
+    cbw->cbw_cb_length = 12; //Alles null, also "Test unit ready"
 
     if (write_cmd(usbdev, pcbw) != USB_NO_ERROR) {
         return 0;
@@ -395,14 +399,13 @@ static int msd_cdi_read(struct cdi_storage_device* strgdev, uint64_t start,
     uintptr_t pb;
     int bs = strgdev->block_size, error;
 #ifdef WAIT_FOR_MSD_READY
-    int j;
+    int i;
 #endif
-//    uint32_t i;
     struct usb_device* usbdev = ((struct cdi_msd*) strgdev)->usb_device;
 
     fdprintf("read(%i, %i)\n", (int) start, (int) count);
     start += ((struct cdi_msd*) strgdev)->offset;
-    if (cdi_alloc_phys_mem(bs, &vb, (void**) &pb) == -1) {
+    if (cdi_alloc_phys_mem(count * bs, &vb, (void**) &pb) == -1) {
         dprintf("Blockspeicher konnte nicht allociert werden.\n");
         return -1;
     }
@@ -415,22 +418,19 @@ static int msd_cdi_read(struct cdi_storage_device* strgdev, uint64_t start,
         __asm__ __volatile__ ("hlt");
 #endif
     }
-    /*for (i = 0; i < count; i++)
-       {*/
 #ifdef WAIT_FOR_MSD_READY
-    for (j = 0; !msd_ready(usbdev) && (j < 10); j++) {
+    for (i = 0; !msd_ready(usbdev) && (i < 10); i++) {
         cdi_sleep_ms(20);
     }
 
 #endif
-    error = msd_read(usbdev, start /* + i*/, count, pb, bs);
+    error = msd_read(usbdev, start, count, pb, count * bs);
     if (error != USB_NO_ERROR) {
-        dprintf("Lesefehler 0x%X bei Block %i.\n", error, 0);
+        dprintf("Lesefehler 0x%X bei Block %i.\n", error, start);
         usbdev->locked = 0;
         return -1;
     }
-    memcpy(buffer /* + i * bs*/, vb, count * bs);
-    //}
+    memcpy(buffer, vb, count * bs);
     usbdev->locked = 0;
     return 0;
 }
@@ -458,11 +458,11 @@ static uint32_t msd_read(struct usb_device* usbdev, uint32_t lba,
     cbw->cbw_signature = CBW_SIGNATURE;
     cbw->cbw_tag = (expected_tag = cbw_tag++);
     cbw->cbw_data_transfer_length = length;
-    cbw->cbw_flags = 0x80;      //IN
-    cbw->cbw_lun = 0;           //Was weiÃ? ich, wie viele LUNs datt Dingens hat?
+    cbw->cbw_flags = 0x80; //IN
+    cbw->cbw_lun = 0; //Was weiÃ? ich, wie viele LUNs datt Dingens hat?
     cbw->cbw_cb_length = 12;
     cbw->cbw_cb[0] = MSC_CMD_READ10;
-    cbw->cbw_cb[1] = 0;         //LUN: 0
+    cbw->cbw_cb[1] = 0; //LUN: 0
     cbw->cbw_cb[2] = (lba & 0xFF000000) >> 24;
     cbw->cbw_cb[3] = (lba & 0x00FF0000) >> 16;
     cbw->cbw_cb[4] = (lba & 0x0000FF00) >> 8;
@@ -484,7 +484,6 @@ static uint32_t msd_read(struct usb_device* usbdev, uint32_t lba,
         .type_of_data = USB_TOD_DATA_IN,
     };
 
-    //Transaktionen eintragen
     ep_size = msc->bulk_ep_in->max_packet_size;
     for (i = 0; i < length; i += ep_size) {
         in_packet.length = (length - i > ep_size) ? ep_size : length - i;
@@ -496,12 +495,6 @@ static uint32_t msd_read(struct usb_device* usbdev, uint32_t lba,
         in_packet.datatoggle ^= 1;
     }
 
-    /*//Auf deren Ende warten
-       for (i = 0; i < length; i += ep_size)
-       {
-
-       }*/
-
     error = read_status(usbdev, expected_tag);
     if (error != USB_NO_ERROR) {
         return error;
@@ -561,71 +554,69 @@ static uint32_t msd_write(struct usb_device* usbdev, uint32_t lba,
     uint16_t sectors, uintptr_t phys_buffer,
     size_t length)
 {
-    /*struct msclass_data *msc;
-       struct command_block_wrapper *cbw;
-       struct command_status_wrapper *csw;
-       uintptr_t pcbw, pcsw;
-       uint32_t expected_tag;
-       int error;
-
-       if (cdi_alloc_phys_mem(sizeof(struct command_block_wrapper), (void **)&cbw, (void **)&pcbw) == -1)
-       {
-       return USB_TRIVIAL_ERROR;
-       }
-       if (cdi_alloc_phys_mem(sizeof(struct command_status_wrapper), (void **)&csw, (void **)&pcsw) == -1)
-       {
-       return USB_TRIVIAL_ERROR;
-       }
-       if (!phys_buffer || !length)
-       {
-       return USB_TRIVIAL_ERROR;
-       }
-       msc = (struct msclass_data *)usbdev->classd;
-       memset(cbw, 0, 0x1F);
-       cbw->cbw_signature = CBW_SIGNATURE;
-       cbw->cbw_tag = (expected_tag = cbw_tag++);
-       cbw->cbw_data_transfer_length = length;
-       cbw->cbw_flags = 0x00;       //OUT
-       cbw->cbw_lun = 0;            //Was weiÃ? ich, wie viele LUNs datt Dingens hat?
-       cbw->cbw_cb_length = 12;
-       cbw->cbw_cb[0] = MSC_CMD_WRITE10;
-       cbw->cbw_cb[1] = 0;          //LUN: 0
-       cbw->cbw_cb[2] = (lba & 0xFF000000) >> 24;
-       cbw->cbw_cb[3] = (lba & 0x00FF0000) >> 16;
-       cbw->cbw_cb[4] = (lba & 0x0000FF00) >> 8;
-       cbw->cbw_cb[5] = lba & 0x000000FF;
-       cbw->cbw_cb[7] = (sectors & 0x0000FF00) >> 8;
-       cbw->cbw_cb[8] = sectors & 0x000000FF;
-
-       error = write_cmd(usbdev, pcbw);
-       if (error != USB_NO_ERROR)
-       {
-       return error;
-       }
-
-       struct usb_packet out_packet = {
-       .type = PACKET_OUT,
-       .endpoint = msc->bulk_ep_out->endpoint_address,
-       .phys_data = phys_buffer,
-       .length = length,
-       .datatoggle = 0,
-       .type_of_data = USB_TOD_DATA_OUT,
-       };
-
-       error = usb_do_packet(usbdev, &out_packet);
-       if (error != USB_NO_ERROR)
-       {
-       return error;
-       }
-
-       error = read_status(usbdev, expected_tag);
-       if (error != USB_NO_ERROR)
-       {
-       return error;
-       }
-
-       return USB_NO_ERROR;*/
-    return USB_STALLED;
+    struct msclass_data* msc;
+    struct command_block_wrapper* cbw;
+    uintptr_t pcbw;
+    uint32_t expected_tag;
+    int error, i, ep_size;
+
+    if (cdi_alloc_phys_mem(sizeof(*cbw), (void**) &cbw,
+            (void**) &pcbw) == -1)
+    {
+        return USB_TRIVIAL_ERROR;
+    }
+    if (!phys_buffer || !length) {
+        return USB_TRIVIAL_ERROR;
+    }
+    msc = (struct msclass_data*) usbdev->classd;
+    memset(cbw, 0, 0x1F);
+    cbw->cbw_signature = CBW_SIGNATURE;
+    cbw->cbw_tag = (expected_tag = cbw_tag++);
+    cbw->cbw_data_transfer_length = length;
+    cbw->cbw_flags = 0x00; //OUT
+    cbw->cbw_lun = 0; //Was weiÃ? ich, wie viele LUNs datt Dingens hat?
+    cbw->cbw_cb_length = 12;
+    cbw->cbw_cb[0] = MSC_CMD_WRITE10;
+    cbw->cbw_cb[1] = 0; //LUN: 0
+    cbw->cbw_cb[2] = (lba & 0xFF000000) >> 24;
+    cbw->cbw_cb[3] = (lba & 0x00FF0000) >> 16;
+    cbw->cbw_cb[4] = (lba & 0x0000FF00) >> 8;
+    cbw->cbw_cb[5] = lba & 0x000000FF;
+    cbw->cbw_cb[7] = (sectors & 0x0000FF00) >> 8;
+    cbw->cbw_cb[8] = sectors & 0x000000FF;
+
+    error = write_cmd(usbdev, pcbw);
+    if (error != USB_NO_ERROR) {
+        return error;
+    }
+
+    struct usb_packet out_packet = {
+        .type         = PACKET_OUT,
+        .endpoint     = msc->bulk_ep_out->endpoint_address,
+        .phys_data    = phys_buffer,
+        .length       = 0,
+        .datatoggle   = 0,
+        .type_of_data = USB_TOD_DATA_OUT,
+    };
+
+    //Transaktionen eintragen
+    ep_size = msc->bulk_ep_out->max_packet_size;
+    for (i = 0; i < length; i += ep_size) {
+        out_packet.length = (length - i > ep_size) ? ep_size : length - i;
+        error = usb_do_packet(usbdev, &out_packet);
+        if (error != USB_NO_ERROR) {
+            return error;
+        }
+        out_packet.phys_data += ep_size;
+        out_packet.datatoggle ^= 1;
+    }
+
+    error = read_status(usbdev, expected_tag);
+    if (error != USB_NO_ERROR) {
+        return error;
+    }
+
+    return USB_NO_ERROR;
 }
 
 static void get_partitions(struct cdi_storage_device* cdistrg)
@@ -662,8 +653,7 @@ static void get_partitions(struct cdi_storage_device* cdistrg)
                 break;
             }
             sprintf((char*) cdimsd->cdi_device.dev.name, "%sp%i",
-                cdistrg->dev.name,
-                j++);
+                cdistrg->dev.name, j++);
             cdimsd->cdi_device.block_size = base_cdimsd->cdi_device.block_size;
             cdimsd->cdi_device.block_count = partition[i].size;
             _dprintf(" %s", cdimsd->cdi_device.dev.name);
-- 
1.6.3.3