Hi,

Daniel Drake wrote:

> Matthieu CASTET wrote:
>
>> Waiting for a clean solution I found a way to solve my problem : I read the
>> start of the firmware in order to see if it is already loaded.
>
>
>
> This approach looks acceptable (although the actual implementation needs 
> cleaning a little) - thanks for investigating!

Here a more clean patch.
There still a problem if a wrong firmware was loaded by another driver (windows 
or vendor driver) : we won't reload the one supported by our driver.

>
> Have you been able to tell why the vendor driver does not suffer the same 
> problem? It would be good if we had more than one approach to choose from :)

The vendor driver doesn't recover a rmmod of the rw driver.


Matthieu

Signed-off-by: Matthieu CASTET <[EMAIL PROTECTED]>



Index: zd1211_2006-09-20/zd_chip.h
===================================================================
--- zd1211_2006-09-20.orig/zd_chip.h    2006-09-24 16:45:50.000000000 +0200
+++ zd1211_2006-09-20/zd_chip.h 2006-09-24 16:48:30.000000000 +0200
@@ -645,7 +645,9 @@
        FW_BASE_ADDR_OFFSET             = FW_START_OFFSET + 0x1d,
        EEPROM_START_OFFSET             = 0xf800,
        EEPROM_SIZE                     = 0x800, /* words */
+       LOAD_CODE_START_OFFSET  = 0xffe9,
        LOAD_CODE_SIZE                  = 0xe, /* words */
+       LOAD_VECT_START_OFFSET  = 0xfff7,
        LOAD_VECT_SIZE                  = 0x10000 - 0xfff7, /* words */
        EEPROM_REGS_OFFSET              = LOAD_CODE_SIZE + LOAD_VECT_SIZE,
        EEPROM_REGS_SIZE                = 0x7e, /* words */
Index: zd1211_2006-09-20/zd_usb.c
===================================================================
--- zd1211_2006-09-20.orig/zd_usb.c     2006-09-24 16:48:52.000000000 +0200
+++ zd1211_2006-09-20/zd_usb.c  2006-09-24 17:19:32.000000000 +0200
@@ -366,6 +366,27 @@
        return r;
 }
 
+static int is_firmware_loaded(struct usb_device *udev)
+{
+       int r;
+       u16 reset_vector;
+
+       r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                       USB_REQ_FIRMWARE_READ_DATA,
+                       USB_DIR_IN | USB_TYPE_VENDOR,
+                       LOAD_VECT_START_OFFSET, 0, &reset_vector, 
sizeof(reset_vector), 5000 /* ms */);
+       if (r != sizeof(reset_vector)) {
+               dev_err(&udev->dev,
+                               "control request firmeware read."
+                               " Return value %d\n", r);
+               if (r >= 0)
+                       return -ENODEV;
+       }
+       /* If a firware is loaded the reset_vector is the start of the
+        * firmware */
+       return reset_vector == FW_START_OFFSET;
+}
+
 static void disable_read_regs_int(struct zd_usb *usb)
 {
        struct zd_usb_interrupt *intr = &usb->intr;
@@ -1036,18 +1057,31 @@
                goto error;
        }
 
-       r = upload_firmware(udev, id->driver_info);
-       if (r) {
+       r = is_firmware_loaded(udev);
+       if (r < 0) {
                dev_err(&intf->dev,
-                      "couldn't load firmware. Error number %d\n", r);
+                               "you should unplug/replug your device");
                goto error;
        }
+       /* TODO if the firmware was already loaded, upload new firmware here
+        * hangs. We should reload the firmware in a latter stage after a
+        * FW_SOFT_RESET because the current firmware could different from
+        * the one we wanted.
+        */
+       if (r == 0) {
+               r = upload_firmware(udev, id->driver_info);
+               if (r) {
+                       dev_err(&intf->dev,
+                                       "couldn't load firmware. Error number 
%d\n", r);
+                       goto error;
+               }
 
-       r = usb_reset_configuration(udev);
-       if (r) {
-               dev_dbg_f(&intf->dev,
-                       "couldn't reset configuration. Error number %d\n", r);
-               goto error;
+               r = usb_reset_configuration(udev);
+               if (r) {
+                       dev_dbg_f(&intf->dev,
+                                       "couldn't reset configuration. Error 
number %d\n", r);
+                       goto error;
+               }
        }
 
        /* At this point the interrupt endpoint is not generally enabled. We
@@ -1073,7 +1107,6 @@
        dev_info(&intf->dev,"%s\n", netdev->name);
        return 0;
 error:
-       usb_reset_device(interface_to_usbdev(intf));
        zd_netdev_free(netdev);
        return r;
 }
@@ -1097,13 +1130,6 @@
        zd_usb_disable_rx(usb);
        zd_usb_disable_int(usb);
 
-       /* If the disconnect has been caused by a removal of the
-        * driver module, the reset allows reloading of the driver. If the
-        * reset will not be executed here, the upload of the firmware in the
-        * probe function caused by the reloading of the driver will fail.
-        */
-       usb_reset_device(interface_to_usbdev(intf));
-
        zd_netdev_free(netdev);
        dev_dbg(&intf->dev, "disconnected\n");
 }


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Zd1211-devs mailing list - http://zd1211.ath.cx/
Unsubscribe: https://lists.sourceforge.net/lists/listinfo/zd1211-devs

Reply via email to