summaryrefslogtreecommitdiff
path: root/at76c503.c
diff options
context:
space:
mode:
Diffstat (limited to 'at76c503.c')
-rw-r--r--at76c503.c83
1 files changed, 76 insertions, 7 deletions
diff --git a/at76c503.c b/at76c503.c
index 2001586..d5aea50 100644
--- a/at76c503.c
+++ b/at76c503.c
@@ -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 */