diff options
Diffstat (limited to 'at76c503.c')
-rw-r--r-- | at76c503.c | 83 |
1 files changed, 76 insertions, 7 deletions
@@ -1,6 +1,6 @@ /* -*- linux-c -*- */ /* - * USB at76c503 driver + * USB at76c503/at76c505 driver * * Copyright (c) 2002 - 2003 Oliver Kurth <oku@masqmail.cx> * @@ -139,7 +139,7 @@ static int debug; /* Version Information */ #define DRIVER_AUTHOR "Oliver Kurth <oku@masqmail.cx>, Joerg Albert <joerg.albert@gmx.de>" -#define DRIVER_DESC "Atmel at76c503 Wireless LAN Driver" +#define DRIVER_DESC "Generic Atmel at76c503/at76c505 routines" /* Module paramaters */ MODULE_PARM(debug, "i"); @@ -392,7 +392,7 @@ int load_ext_fw_block(struct usb_device *udev, } static inline -int get_hw_cfg(struct usb_device *udev, +int get_hw_cfg_rfmd(struct usb_device *udev, unsigned char *buf, int buf_size) { return usb_control_msg(udev, usb_rcvctrlpipe(udev,0), @@ -401,6 +401,73 @@ int get_hw_cfg(struct usb_device *udev, buf, buf_size, HZ); } +/* Intersil boards use a different "value" for GetHWConfig requests */ +static inline +int get_hw_cfg_intersil(struct usb_device *udev, + unsigned char *buf, int buf_size) +{ + return usb_control_msg(udev, usb_rcvctrlpipe(udev,0), + 0x33, INTERFACE_VENDOR_REQUEST_IN, + ((0x09 << 8) | 0x02), 0, + buf, buf_size, HZ); +} + +/* Get the hardware configuration for the adapter and place the appropriate + * data in the appropriate fields of 'dev' (the GetHWConfig request and + * interpretation of the result depends on the type of board we're dealing + * with) */ +static int get_hw_config(struct at76c503 *dev) +{ + int ret; + union { + struct hwcfg_intersil i; + struct hwcfg_rfmd r3; + struct hwcfg_r505 r5; + } hwcfg; + + switch (dev->board_type) { + case BOARDTYPE_INTERSIL: + ret = get_hw_cfg_intersil(dev->udev, (unsigned char *)&hwcfg.i, sizeof(hwcfg.i)); + if (ret) break; + memcpy(dev->mac_addr, hwcfg.i.mac_addr, ETH_ALEN); + memcpy(dev->cr31_values, hwcfg.i.cr31_values, 14); + memcpy(dev->cr58_values, hwcfg.i.cr58_values, 14); + memcpy(dev->pidvid, hwcfg.i.pidvid, 4); + dev->regulatory_domain = hwcfg.i.regulatory_domain; + break; + case BOARDTYPE_RFMD: + ret = get_hw_cfg_rfmd(dev->udev, (unsigned char *)&hwcfg.r3, sizeof(hwcfg.r3)); + if (ret) break; + memcpy(dev->cr20_values, hwcfg.r3.cr20_values, 14); + memcpy(dev->cr21_values, hwcfg.r3.cr21_values, 14); + memcpy(dev->bb_cr, hwcfg.r3.bb_cr, 14); + memcpy(dev->pidvid, hwcfg.r3.pidvid, 4); + memcpy(dev->mac_addr, hwcfg.r3.mac_addr, ETH_ALEN); + dev->regulatory_domain = hwcfg.r3.regulatory_domain; + memcpy(dev->low_power_values, hwcfg.r3.low_power_values, 14); + memcpy(dev->normal_power_values, hwcfg.r3.normal_power_values, 14); + break; + case BOARDTYPE_R505: + ret = get_hw_cfg_rfmd(dev->udev, (unsigned char *)&hwcfg.r5, sizeof(hwcfg.r5)); + if (ret) break; + memcpy(dev->cr39_values, hwcfg.r5.cr39_values, 14); + memcpy(dev->bb_cr, hwcfg.r5.bb_cr, 14); + memcpy(dev->pidvid, hwcfg.r5.pidvid, 4); + memcpy(dev->mac_addr, hwcfg.r5.mac_addr, ETH_ALEN); + dev->regulatory_domain = hwcfg.r5.regulatory_domain; + memcpy(dev->cr15_values, hwcfg.r5.cr15_values, 14); + break; + default: + err("Bad board type set (%d). Unable to get hardware config.", dev->board_type); + return -EINVAL; + } + + if (ret < 0) { + err("Get HW Config failed (%d)", ret); + } + return ret; +} + static inline int get_mib(struct usb_device *udev, u16 mib, u8 *buf, int buf_size) @@ -2842,7 +2909,7 @@ static int at76c503_alloc_urbs(struct at76c503 *dev) return 0; } -struct at76c503 *at76c503_new_device(struct usb_device *udev, const char *netdev_name) +struct at76c503 *at76c503_new_device(struct usb_device *udev, int board_type, const char *netdev_name) { struct net_device *netdev; struct at76c503 *dev = NULL; @@ -2874,6 +2941,8 @@ struct at76c503 *at76c503_new_device(struct usb_device *udev, const char *netdev dev->tasklet.func = rx_tasklet; dev->tasklet.data = (unsigned long)dev; + dev->board_type = board_type; + /* set up the endpoint information */ /* check out the endpoints */ interface = &udev->actconfig->interface[0]; @@ -2897,12 +2966,12 @@ struct at76c503 *at76c503_new_device(struct usb_device *udev, const char *netdev dev->fw_version.patch, dev->fw_version.build); /* MAC address */ - ret = get_hw_cfg(dev->udev, (unsigned char *)&dev->hwcfg.rfmd, sizeof(struct hwcfg_rfmd)); + ret = get_hw_config(dev); if(ret < 0){ - err("could not get MAC: get_hw_cfg() failed, ret = %d", ret); + err("could not get MAC address"); goto error; } - memcpy(netdev->dev_addr, &(dev->hwcfg.rfmd.mac_addr), ETH_ALEN); + memcpy(netdev->dev_addr, dev->mac_addr, ETH_ALEN); info("using MAC %s", mac2str(netdev->dev_addr)); set_mac_address(dev, netdev->dev_addr); /* may have been changed, write back original */ |