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
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel