Author: arekm Date: Mon Jan 16 07:25:34 2006 GMT Module: SOURCES Tag: LINUX_2_6_14 ---- Log message: - ueagle driver from 2.6.15
---- Files affected: SOURCES: linux-2.6-ueagle.patch (NONE -> 1.1.2.1) (NEW) ---- Diffs: ================================================================ Index: SOURCES/linux-2.6-ueagle.patch diff -u /dev/null SOURCES/linux-2.6-ueagle.patch:1.1.2.1 --- /dev/null Mon Jan 16 08:25:34 2006 +++ SOURCES/linux-2.6-ueagle.patch Mon Jan 16 08:25:29 2006 @@ -0,0 +1,1900 @@ +From: matthieu castet <[EMAIL PROTECTED]> +Date: Mon, 7 Nov 2005 22:27:13 +0000 (+0100) +Subject: [PATCH] USB: Eagle and ADI 930 usb adsl modem driver +X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=b72458a80c75cab832248f536412f386e20a93a0 + +[PATCH] USB: Eagle and ADI 930 usb adsl modem driver + +A driver for USB ADSL modems based on the ADI eagle chipset using the +usb_atm infrastructure. + +The managing part was taken from bsd ueagle driver, other parts were +written from scratch. + +The driver uses the in-kernel firmware loader : +- to load a first usb firmware when the modem is in pre-firmware state +- to load the dsp firmware that are swapped in host memory. +- to load CMV (configuration and management variables) when the modem +boot. (We can't use options or sysfs for this as there many possible +values. See +https://mail.gna.org/public/eagleusb-dev/2005-04/msg00031.html for a +description of some) +- to load fpga code for 930 chipset. + +The device had 4 endpoints : +* 2 for data (use by usbatm). The incoming +endpoint could be iso or bulk. The modem seems buggy and produce lot's +of atm errors when using it in bulk mode for speed > 3Mbps, so iso +endpoint is need for speed > 3Mbps. At the moment iso endpoint need a +patched usbatm library and for this reason is not included in this patch. + +* One bulk endpoint for uploading dsp firmware + +* One irq endpoint that notices the driver + - if we need to upload a page of the dsp firmware + - an ack for read or write CMV and the value (for the read case). + +If order to make the driver cleaner, we design synchronous +(read|write)_cmv : +-send a synchronous control message to the modem +-wait for an ack or a timeout +-return the value if needed. + +In order to run these synchronous usb messages we need a kernel thread. + +The driver has been tested with sagem fast 800 modems with different +eagle chipset revision and with ADI 930 since April 2005. + +Signed-off-by: Matthieu CASTET <[EMAIL PROTECTED]> +Signed-off-by: Andrew Morton <[EMAIL PROTECTED]> +Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]> +--- + +--- a/drivers/usb/atm/Kconfig ++++ b/drivers/usb/atm/Kconfig +@@ -44,6 +44,19 @@ config USB_CXACRU + To compile this driver as a module, choose M here: the + module will be called cxacru. + ++config USB_UEAGLEATM ++ tristate "ADI 930 and eagle USB DSL modem" ++ depends on USB_ATM ++ select FW_LOADER ++ help ++ Say Y here if you have an ADSL USB modem based on the ADI 930 ++ or eagle chipset. In order to use your modem you will need to ++ install firmwares and CMV (Command Management Variables); see ++ <https://gna.org/projects/ueagleatm/> for details. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called ueagle-atm. ++ + config USB_XUSBATM + tristate "Other USB DSL modem support" + depends on USB_ATM +--- a/drivers/usb/atm/Makefile ++++ b/drivers/usb/atm/Makefile +@@ -4,6 +4,7 @@ + + obj-$(CONFIG_USB_CXACRU) += cxacru.o + obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o ++obj-$(CONFIG_USB_UEAGLEATM) += ueagle-atm.o + obj-$(CONFIG_USB_ATM) += usbatm.o + obj-$(CONFIG_USB_XUSBATM) += xusbatm.o + +--- /dev/null ++++ b/drivers/usb/atm/ueagle-atm.c +@@ -0,0 +1,1813 @@ ++/*- ++ * Copyright (c) 2003, 2004 ++ * Damien Bergamini <[EMAIL PROTECTED]>. All rights reserved. ++ * ++ * Copyright (c) 2005 Matthieu Castet <[EMAIL PROTECTED]> ++ * ++ * This software is available to you under a choice of one of two ++ * licenses. You may choose to be licensed under the terms of the GNU ++ * General Public License (GPL) Version 2, available from the file ++ * COPYING in the main directory of this source tree, or the ++ * BSD license below: ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice unmodified, this list of conditions, and the following ++ * disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * GPL license : ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ * HISTORY : some part of the code was base on ueagle 1.3 BSD driver, ++ * Damien Bergamini agree to put his code under a DUAL GPL/BSD license. ++ * ++ * The rest of the code was was rewritten from scratch. ++ */ ++ ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/init.h> ++#include <linux/crc32.h> ++#include <linux/usb.h> ++#include <linux/firmware.h> ++#include <linux/ctype.h> ++#include <linux/kthread.h> ++#include <linux/version.h> ++#include <asm/unaligned.h> ++ ++#include "usbatm.h" ++ ++#define EAGLEUSBVERSION "ueagle 1.1" ++ ++ ++/* ++ * Debug macros ++ */ ++#define uea_dbg(usb_dev, format, args...) \ ++ do { \ ++ if (debug >= 1) \ ++ dev_dbg(&(usb_dev)->dev, \ ++ "[ueagle-atm dbg] %s: " format, \ ++ __FUNCTION__, ##args); \ ++ } while (0) ++ ++#define uea_vdbg(usb_dev, format, args...) \ ++ do { \ ++ if (debug >= 2) \ ++ dev_dbg(&(usb_dev)->dev, \ ++ "[ueagle-atm vdbg] " format, ##args); \ ++ } while (0) ++ ++#define uea_enters(usb_dev) \ ++ uea_vdbg(usb_dev, "entering %s\n", __FUNCTION__) ++ ++#define uea_leaves(usb_dev) \ ++ uea_vdbg(usb_dev, "leaving %s\n", __FUNCTION__) ++ ++#define uea_err(usb_dev, format,args...) \ ++ dev_err(&(usb_dev)->dev ,"[UEAGLE-ATM] " format , ##args) ++ ++#define uea_warn(usb_dev, format,args...) \ ++ dev_warn(&(usb_dev)->dev ,"[Ueagle-atm] " format, ##args) ++ ++#define uea_info(usb_dev, format,args...) \ ++ dev_info(&(usb_dev)->dev ,"[ueagle-atm] " format, ##args) ++ ++struct uea_cmvs { ++ u32 address; ++ u16 offset; ++ u32 data; ++} __attribute__ ((packed)); ++ ++struct uea_softc { ++ struct usb_device *usb_dev; ++ struct usbatm_data *usbatm; ++ ++ int modem_index; ++ unsigned int driver_info; ++ ++ int booting; ++ int reset; ++ ++ wait_queue_head_t sync_q; ++ ++ struct task_struct *kthread; ++ u32 data; ++ wait_queue_head_t cmv_ack_wait; ++ int cmv_ack; ++ ++ struct work_struct task; ++ u16 pageno; ++ u16 ovl; ++ ++ const struct firmware *dsp_firm; ++ struct urb *urb_int; ++ ++ u8 cmv_function; ++ u16 cmv_idx; ++ u32 cmv_address; ++ u16 cmv_offset; ++ ++ /* keep in sync with eaglectl */ ++ struct uea_stats { ++ struct { ++ u32 state; ++ u32 flags; ++ u32 mflags; ++ u32 vidcpe; ++ u32 vidco; ++ u32 dsrate; ++ u32 usrate; ++ u32 dsunc; ++ u32 usunc; ++ u32 dscorr; ++ u32 uscorr; ++ u32 txflow; ++ u32 rxflow; ++ u32 usattenuation; ++ u32 dsattenuation; ++ u32 dsmargin; ++ u32 usmargin; ++ u32 firmid; ++ } phy; ++ } stats; ++}; ++ ++/* ++ * Elsa IDs ++ */ ++#define ELSA_VID 0x05CC ++#define ELSA_PID_PSTFIRM 0x3350 ++#define ELSA_PID_PREFIRM 0x3351 ++ ++/* ++ * Sagem USB IDs ++ */ ++#define EAGLE_VID 0x1110 ++#define EAGLE_I_PID_PREFIRM 0x9010 /* Eagle I */ ++#define EAGLE_I_PID_PSTFIRM 0x900F /* Eagle I */ ++ ++#define EAGLE_IIC_PID_PREFIRM 0x9024 /* Eagle IIC */ ++#define EAGLE_IIC_PID_PSTFIRM 0x9023 /* Eagle IIC */ ++ ++#define EAGLE_II_PID_PREFIRM 0x9022 /* Eagle II */ ++#define EAGLE_II_PID_PSTFIRM 0x9021 /* Eagle II */ ++ ++/* ++ * Eagle III Pid ++ */ ++#define EAGLE_III_PID_PREFIRM 0x9032 /* Eagle III */ ++#define EAGLE_III_PID_PSTFIRM 0x9031 /* Eagle III */ ++ ++/* ++ * USR USB IDs ++ */ ++#define USR_VID 0x0BAF ++#define MILLER_A_PID_PREFIRM 0x00F2 ++#define MILLER_A_PID_PSTFIRM 0x00F1 ++#define MILLER_B_PID_PREFIRM 0x00FA ++#define MILLER_B_PID_PSTFIRM 0x00F9 ++#define HEINEKEN_A_PID_PREFIRM 0x00F6 ++#define HEINEKEN_A_PID_PSTFIRM 0x00F5 ++#define HEINEKEN_B_PID_PREFIRM 0x00F8 ++#define HEINEKEN_B_PID_PSTFIRM 0x00F7 ++ ++#define PREFIRM 0 ++#define PSTFIRM (1<<7) ++enum { ++ ADI930 = 0, ++ EAGLE_I, ++ EAGLE_II, ++ EAGLE_III ++}; ++ ++/* macros for both struct usb_device_id and struct uea_softc */ ++#define UEA_IS_PREFIRM(x) \ ++ (!((x)->driver_info & PSTFIRM)) ++#define UEA_CHIP_VERSION(x) \ ++ ((x)->driver_info & 0xf) ++ ++#define IS_ISDN(sc) \ ++ (le16_to_cpu(sc->usb_dev->descriptor.bcdDevice) & 0x80) ++ ++#define INS_TO_USBDEV(ins) ins->usb_dev ++ ++#define GET_STATUS(data) \ ++ ((data >> 8) & 0xf) ++#define IS_OPERATIONAL(sc) \ ++ (GET_STATUS(sc->stats.phy.state) == 2) ++ ++/* ++ * Set of macros to handle unaligned data in the firmware blob. ++ * The FW_GET_BYTE() macro is provided only for consistency. ++ */ ++ ++#define FW_GET_BYTE(p) *((__u8 *) (p)) ++#define FW_GET_WORD(p) le16_to_cpu(get_unaligned((__le16 *) (p))) ++#define FW_GET_LONG(p) le32_to_cpu(get_unaligned((__le32 *) (p))) ++ ++#define FW_DIR "ueagle-atm/" ++#define NB_MODEM 4 ++ ++#define BULK_TIMEOUT 300 ++#define CTRL_TIMEOUT 1000 ++ ++#define ACK_TIMEOUT msecs_to_jiffies(1500) ++ ++#define UEA_INTR_IFACE_NO 0 ++#define UEA_US_IFACE_NO 1 ++#define UEA_DS_IFACE_NO 2 ++ ++#define FASTEST_ISO_INTF 8 ++ ++#define UEA_BULK_DATA_PIPE 0x02 ++#define UEA_IDMA_PIPE 0x04 ++#define UEA_INTR_PIPE 0x04 ++#define UEA_ISO_DATA_PIPE 0x08 ++ ++#define UEA_SET_BLOCK 0x0001 ++#define UEA_SET_MODE 0x0003 ++#define UEA_SET_2183_DATA 0x0004 ++#define UEA_SET_TIMEOUT 0x0011 ++ ++#define UEA_LOOPBACK_OFF 0x0002 ++#define UEA_LOOPBACK_ON 0x0003 ++#define UEA_BOOT_IDMA 0x0006 ++#define UEA_START_RESET 0x0007 ++#define UEA_END_RESET 0x0008 ++ ++#define UEA_SWAP_MAILBOX (0x3fcd | 0x4000) ++#define UEA_MPTX_START (0x3fce | 0x4000) ++#define UEA_MPTX_MAILBOX (0x3fd6 | 0x4000) ++#define UEA_MPRX_MAILBOX (0x3fdf | 0x4000) ++ ++/* structure describing a block within a DSP page */ ++struct block_info { ++ __le16 wHdr; ++#define UEA_BIHDR 0xabcd ++ __le16 wAddress; ++ __le16 wSize; ++ __le16 wOvlOffset; ++ __le16 wOvl; /* overlay */ ++ __le16 wLast; ++} __attribute__ ((packed)); ++#define BLOCK_INFO_SIZE 12 ++ ++/* structure representing a CMV (Configuration and Management Variable) */ ++struct cmv { ++ __le16 wPreamble; ++#define PREAMBLE 0x535c ++ __u8 bDirection; ++#define MODEMTOHOST 0x01 ++#define HOSTTOMODEM 0x10 ++ __u8 bFunction; ++#define FUNCTION_TYPE(f) ((f) >> 4) ++#define MEMACCESS 0x1 ++#define ADSLDIRECTIVE 0x7 ++ ++#define FUNCTION_SUBTYPE(f) ((f) & 0x0f) ++/* for MEMACCESS */ ++#define REQUESTREAD 0x0 ++#define REQUESTWRITE 0x1 ++#define REPLYREAD 0x2 ++#define REPLYWRITE 0x3 ++/* for ADSLDIRECTIVE */ ++#define KERNELREADY 0x0 ++#define MODEMREADY 0x1 ++ ++#define MAKEFUNCTION(t, s) (((t) & 0xf) << 4 | ((s) & 0xf)) ++ __le16 wIndex; ++ __le32 dwSymbolicAddress; ++#define MAKESA(a, b, c, d) \ ++ (((c) & 0xff) << 24 | \ ++ ((d) & 0xff) << 16 | \ ++ ((a) & 0xff) << 8 | \ ++ ((b) & 0xff)) ++ ++#define SA_CNTL MAKESA('C', 'N', 'T', 'L') ++#define SA_DIAG MAKESA('D', 'I', 'A', 'G') ++#define SA_INFO MAKESA('I', 'N', 'F', 'O') ++#define SA_OPTN MAKESA('O', 'P', 'T', 'N') ++#define SA_RATE MAKESA('R', 'A', 'T', 'E') ++#define SA_STAT MAKESA('S', 'T', 'A', 'T') ++ __le16 wOffsetAddress; ++ __le32 dwData; ++} __attribute__ ((packed)); ++#define CMV_SIZE 16 ++ ++/* structure representing swap information */ ++struct swap_info { ++ __u8 bSwapPageNo; ++ __u8 bOvl; /* overlay */ ++} __attribute__ ((packed)); ++ ++/* structure representing interrupt data */ ++struct intr_pkt { ++ __u8 bType; ++ __u8 bNotification; ++ __le16 wValue; ++ __le16 wIndex; ++ __le16 wLength; ++ __le16 wInterrupt; ++#define INT_LOADSWAPPAGE 0x0001 ++#define INT_INCOMINGCMV 0x0002 ++ union { ++ struct { ++ struct swap_info swapinfo; ++ __le16 wDataSize; ++ } __attribute__ ((packed)) s1; ++ ++ struct { ++ struct cmv cmv; ++ __le16 wDataSize; ++ } __attribute__ ((packed)) s2; ++ } __attribute__ ((packed)) u; ++#define bSwapPageNo u.s1.swapinfo.bSwapPageNo ++#define bOvl u.s1.swapinfo.bOvl ++} __attribute__ ((packed)); ++#define INTR_PKT_SIZE 28 ++ ++static struct usb_driver uea_driver; ++static DECLARE_MUTEX(uea_semaphore); ++static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III"}; ++ ++static int modem_index; ++static unsigned int debug; ++static int sync_wait[NB_MODEM]; ++static char *cmv_file[NB_MODEM]; ++ ++module_param(debug, uint, 0644); ++MODULE_PARM_DESC(debug, "module debug level (0=off,1=on,2=verbose)"); ++module_param_array(sync_wait, bool, NULL, 0644); ++MODULE_PARM_DESC(sync_wait, "wait the synchronisation before starting ATM"); ++module_param_array(cmv_file, charp, NULL, 0644); ++MODULE_PARM_DESC(cmv_file, ++ "file name with configuration and management variables"); ++ ++#define UPDATE_ATM_STAT(type, val) \ ++ do { \ ++ if (sc->usbatm->atm_dev) \ ++ sc->usbatm->atm_dev->type = val; \ ++ } while (0) ++ ++/* Firmware loading */ ++#define LOAD_INTERNAL 0xA0 ++#define F8051_USBCS 0x7f92 ++ ++/** ++ * uea_send_modem_cmd - Send a command for pre-firmware devices. ++ */ ++static int uea_send_modem_cmd(struct usb_device *usb, ++ u16 addr, u16 size, u8 * buff) ++{ ++ int ret = -ENOMEM; ++ u8 *xfer_buff; ++ ++ xfer_buff = kmalloc(size, GFP_KERNEL); ++ if (xfer_buff) { ++ memcpy(xfer_buff, buff, size); ++ ret = usb_control_msg(usb, ++ usb_sndctrlpipe(usb, 0), ++ LOAD_INTERNAL, ++ USB_DIR_OUT | USB_TYPE_VENDOR | ++ USB_RECIP_DEVICE, addr, 0, xfer_buff, ++ size, CTRL_TIMEOUT); ++ kfree(xfer_buff); ++ } ++ ++ if (ret < 0) ++ return ret; ++ ++ return (ret == size) ? 0 : -EIO; ++} ++ ++static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *context) ++{ ++ struct usb_device *usb = context; ++ u8 *pfw, value; ++ u32 crc = 0; ++ int ret, size; ++ ++ uea_enters(usb); ++ if (!fw_entry) { ++ uea_err(usb, "firmware is not available\n"); ++ goto err; ++ } ++ ++ pfw = fw_entry->data; ++ size = fw_entry->size; ++ ++ crc = FW_GET_LONG(pfw); ++ pfw += 4; ++ size -= 4; ++ if (crc32_be(0, pfw, size) != crc) { ++ uea_err(usb, "firmware is corrupted\n"); ++ goto err; ++ } ++ ++ /* ++ * Start to upload formware : send reset ++ */ ++ value = 1; ++ ret = uea_send_modem_cmd(usb, F8051_USBCS, sizeof(value), &value); ++ ++ if (ret < 0) { ++ uea_err(usb, "modem reset failed with error %d\n", ret); ++ goto err; ++ } ++ ++ while (size > 0) { ++ u8 len = FW_GET_BYTE(pfw); ++ u16 add = FW_GET_WORD(pfw + 1); ++ ret = uea_send_modem_cmd(usb, add, len, pfw + 3); ++ if (ret < 0) { ++ uea_err(usb, "uploading firmware data failed " ++ "with error %d\n", ret); ++ goto err; ++ } ++ pfw += len + 3; ++ size -= len + 3; ++ } ++ ++ /* ++ * Tell the modem we finish : de-assert reset ++ */ ++ value = 0; ++ ret = uea_send_modem_cmd(usb, F8051_USBCS, 1, &value); ++ if (ret < 0) ++ uea_err(usb, "modem de-assert failed with error %d\n", ret); ++ else ++ uea_info(usb, "firmware uploaded\n"); ++ ++err: ++ uea_leaves(usb); ++} ++ ++/** ++ * uea_load_firmware - Load usb firmware for pre-firmware devices. ++ */ ++static int uea_load_firmware(struct usb_device *usb, unsigned int ver) ++{ ++ int ret; ++ char *fw_name = FW_DIR "eagle.fw"; ++ ++ uea_enters(usb); ++ uea_info(usb, "pre-firmware device, uploading firmware\n"); ++ ++ switch (ver) { ++ case ADI930: ++ fw_name = FW_DIR "adi930.fw"; ++ break; ++ case EAGLE_I: ++ fw_name = FW_DIR "eagleI.fw"; ++ break; ++ case EAGLE_II: ++ fw_name = FW_DIR "eagleII.fw"; ++ break; ++ case EAGLE_III: ++ fw_name = FW_DIR "eagleIII.fw"; ++ break; ++ } ++ ++ ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, usb, uea_upload_pre_firmware); ++ if (ret) ++ uea_err(usb, "firmware %s is not available\n", fw_name); <<Diff was trimmed, longer than 597 lines>> _______________________________________________ pld-cvs-commit mailing list [email protected] http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit
