Oleg -- Comments in line below.
Quoting Oleg Verych <[EMAIL PROTECTED]>: > pp-by: Oleg Verych > --- > drivers/usb/serial/ti_usb_3410_5052.c | 148 > +++++++++++++++++++++------------- > drivers/usb/serial/ti_usb_3410_5052.h | 27 +++--- > 2 files changed, 109 insertions(+), 66 deletions(-) > > Index: linux-2.6.21-rc1/drivers/usb/serial/ti_usb_3410_5052.h > =================================================================== > --- linux-2.6.21-rc1.orig/drivers/usb/serial/ti_usb_3410_5052.h > 2007-02-23 > 02:19:57.950025000 +0100 > +++ linux-2.6.21-rc1/drivers/usb/serial/ti_usb_3410_5052.h 2007-02-23 > 04:02:08.977190250 +0100 > @@ -21,8 +21,8 @@ > #define _TI_3410_5052_H_ > > /* Configuration ids */ > -#define TI_BOOT_CONFIG 1 > -#define TI_ACTIVE_CONFIG 2 > +#define TI_BOOT_CONFIG 1 /* boot config to get > firmware */ > +#define TI_ACTIVE_CONFIG 2 /* actual working device config */ > > /* Vendor and product ids */ > #define TI_VENDOR_ID 0x0451 > @@ -206,19 +206,24 @@ > #define TI_CODE_DATA_ERROR 0x03 > #define TI_CODE_MODEM_STATUS 0x04 > > -/* Download firmware max packet size */ > -#define TI_DOWNLOAD_MAX_PACKET_SIZE 64 > - > -/* Firmware image header */ > -struct ti_firmware_header { > - __le16 wLength; > - __u8 bCheckSum; > -} __attribute__((packed)); These came from reading the TI bootloader firmware sources. The TI_DOWNLOAD_MAX_PACKET_SIZE is a constraint of the bootloader. The header structure also matches the TI bootloader firmware. I do not want to change these. > - > /* UART addresses */ > #define TI_UART1_BASE_ADDR 0xFFA0 /* UART 1 base address */ > #define TI_UART2_BASE_ADDR 0xFFB0 /* UART 2 base address */ > #define TI_UART_OFFSET_LCR 0x0002 /* UART MCR register offset */ > #define TI_UART_OFFSET_MCR 0x0004 /* UART MCR register offset */ > > +/* Firmware */ > +#define TI_FW_PACKET_SIZE 64 > +#define TI_MAX_FIRMWARE_SIZE 16284 > + > +#define ti_fw_file_3410 "umpf3410.i51" > +#define ti_fw_file_5052 "umpf5052.i51" These are not the right names for the firmware files. Please see my patch at http://www.brimson.com/downloads/ti_usb_multitech-1.1.tgz for the firmware files names we are using. These names are specific to just one device. > + > +typedef union { > + __le32 a; /* all */ > + struct { > + __le32 sz : 16, cs : 8; > + } d; > +} ti_firmware_header_t; The header is 24 bits, not 32. Why use a union here? > + > #endif /* _TI_3410_5052_H_ */ > Index: linux-2.6.21-rc1/drivers/usb/serial/ti_usb_3410_5052.c > =================================================================== > --- linux-2.6.21-rc1.orig/drivers/usb/serial/ti_usb_3410_5052.c > 2007-02-23 > 02:20:04.314422750 +0100 > +++ linux-2.6.21-rc1/drivers/usb/serial/ti_usb_3410_5052.c 2007-02-23 > 05:00:54.477096862 +0100 > @@ -33,20 +33,15 @@ > #include <asm/semaphore.h> > #include <linux/usb.h> > #include <linux/usb/serial.h> > - > +#include <linux/firmware.h> > #include "ti_usb_3410_5052.h" > -#include "ti_fw_3410.h" /* firmware image for 3410 */ > -#include "ti_fw_5052.h" /* firmware image for 5052 */ No. This will break the driver for any user who upgrades the kernel and does not have the firmware files. We talked about this before--I do not want to do that. I want to keep the firmware in the driver--we can load firmware if a firmware file is found, but if not, we need to fall back to the firmware image in the driver. Again see my patch at http://www.brimson.com/downloads/ti_usb_multitech-1.1.tgz to see how I want this done. I will submit this patch myself in a few days. > - > > /* Defines */ > > -#define TI_DRIVER_VERSION "v0.9" > +#define TI_DRIVER_VERSION "v0.92" > #define TI_DRIVER_AUTHOR "Al Borchers <[EMAIL PROTECTED]>" > #define TI_DRIVER_DESC "TI USB 3410/5052 Serial Driver" > > -#define TI_FIRMWARE_BUF_SIZE 16284 > - > #define TI_WRITE_BUF_SIZE 1024 > > #define TI_TRANSFER_TIMEOUT 2 > @@ -143,8 +138,7 @@ > static int ti_write_byte(struct ti_device *tdev, unsigned long addr, > __u8 mask, __u8 byte); > > -static int ti_download_firmware(struct ti_device *tdev, > - unsigned char *firmware, unsigned int firmware_size); > +static int ti_fw_change(struct ti_device *tdev, const char *filename); > > /* circular buffer */ > static struct circ_buf *ti_buf_alloc(void); > @@ -384,13 +378,8 @@ > > /* if we have only 1 configuration, download firmware */ > if (dev->descriptor.bNumConfigurations == 1) { > - > - if (tdev->td_is_3410) > - status = ti_download_firmware(tdev, ti_fw_3410, > - sizeof(ti_fw_3410)); > - else > - status = ti_download_firmware(tdev, ti_fw_5052, > - sizeof(ti_fw_5052)); > + status = ti_fw_change(tdev, tdev->td_is_3410 ? > + ti_fw_file_3410 : ti_fw_file_5052); > if (status) > goto free_tdev; > > @@ -1595,57 +1584,106 @@ > } > > > -static int ti_download_firmware(struct ti_device *tdev, > - unsigned char *firmware, unsigned int firmware_size) > +static int ti_fw_change(struct ti_device *tdev, const char *filename) > { > - int status = 0; > - int buffer_size; > - int pos; > - int len; > - int done; > - __u8 cs = 0; > - __u8 *buffer; > - struct usb_device *dev = tdev->td_serial->dev; > - struct ti_firmware_header *header; > - unsigned int pipe = usb_sndbulkpipe(dev, > - tdev->td_serial->port[0]->bulk_out_endpointAddress); > +#define udev (tdev->td_serial->dev) > +#define fw_endpoint (tdev->td_serial->port[0]->bulk_out_endpointAddress) I much prefer a local variable to a #define for this. > > + const struct firmware *fw_data_ptr; > + size_t size; > + int w; > > - buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header); > - buffer = kmalloc(buffer_size, GFP_KERNEL); > - if (!buffer) { > - dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__); > - return -ENOMEM; > + dbg("%s() start; requesting firmware from userspace.",__FUNCTION__); > + > + w = request_firmware(&fw_data_ptr, filename, &udev->dev); > + if (w) { > + dev_err(&udev->dev, "userspace firmware helper failed.\n"); > + return w; > } > > - memcpy(buffer, firmware, firmware_size); > - memset(buffer+firmware_size, 0xff, buffer_size-firmware_size); > + size = fw_data_ptr->size; > > - for(pos = sizeof(struct ti_firmware_header); pos < buffer_size; pos++) > - cs = (__u8)(cs + buffer[pos]); > + if (likely(size <= TI_MAX_FIRMWARE_SIZE)) { > + ti_firmware_header_t h; > > - header = (struct ti_firmware_header *)buffer; > - header->wLength = cpu_to_le16((__u16)(buffer_size - sizeof(struct > ti_firmware_header))); > - header->bCheckSum = cs; > - > - dbg("%s - downloading firmware", __FUNCTION__); > - for (pos = 0; pos < buffer_size; pos += done) { > - len = min(buffer_size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE); > - status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, 1000); > - if (status) > - break; > + if (size % TI_FW_PACKET_SIZE) { > + dev_err(&udev->dev, "firmware size isn't %u modulo.\n" > + "Care to provide one.\n", TI_FW_PACKET_SIZE); > + return -EIO; > + } > + > + /* constructing header: size_LSB size_MSB CRCB */ > + h.a = 0x000000; > + h.d.sz = cpu_to_le16(size); > + > + /* w is zero here and used as index */ > + do { > + h.d.cs += fw_data_ptr->data[w++]; > + } while (w < size); > + > + /* using `w' as buffer */ > + w = (int) h.a; > + dbg("cs: %#x; w: %#x", h.d.cs, w); > + } else { > + dev_err(&udev->dev,"firmware is too big.\n"); > + return -EFBIG; > } > > - kfree(buffer); > + dbg("starting downloading %#zx bytes of firmware.", size); > > - if (status) { > - dev_err(&dev->dev, "%s - error downloading firmware, %d\n", > __FUNCTION__, > status); > - return status; > - } > + do { > + u8 *fw; > + int gone; > + unsigned int pipe = usb_sndbulkpipe(udev, fw_endpoint); > + > + /* XXX implement retry? */ > + w = usb_bulk_msg(udev, pipe, &w, 3, &gone, 1024); > + if (gone != 3) { > + if (!w) > + w = -EIO; > + break; > + } > > - dbg("%s - download successful", __FUNCTION__); > + /* > + * 3-4 12-bit pages, this is not much for kmalloc(), > + * why request_firmware() doesn't allocate with it? > + */ > + fw = kmalloc(size, GFP_KERNEL); > + if (!fw) { > + w = -ENOMEM; > + break; > + } > > - return 0; > + memcpy(fw, fw_data_ptr->data, size); > + > + size /= TI_FW_PACKET_SIZE; > + > + do { > + w = usb_bulk_msg(udev, pipe, fw, TI_FW_PACKET_SIZE, > + &gone, 1024); > + if (gone != TI_FW_PACKET_SIZE) { > + /* > + * unless bulk_msg can be sent partially, > + * `if' above can be removed > + */ > + if (!w) > + w = -EIO; > + break; > + } else { > + fw += TI_FW_PACKET_SIZE; > + } > + } while (--size); > + > + kfree(fw); > + } while (0); > + > + release_firmware(fw_data_ptr); > + > + dbg("%s() done with result %#x.\n",__FUNCTION__, w); > + > + return w; > +#undef fw_endpoint > +#undef dev > } > > > > -- > > ------------------------------------------------------------------------- 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 _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel