📄 at76c503.c
字号:
} printk ("\n");}int at76c503_remap(struct usb_device *udev){ int ret; ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), 0x0a, INTERFACE_VENDOR_REQUEST_OUT, 0, 0, NULL, 0, HZ); if (ret < 0) return ret; return 0;}static inlineint get_op_mode(struct usb_device *udev){ int ret; u8 op_mode; ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33, INTERFACE_VENDOR_REQUEST_IN, 0x01, 0, &op_mode, 1, HZ); if(ret < 0) return ret; return op_mode;}/* this loads a block of the second part of the firmware */static inlineint load_ext_fw_block(struct usb_device *udev, int i, unsigned char *buf, int bsize){ return usb_control_msg(udev, usb_sndctrlpipe(udev,0), 0x0e, DEVICE_VENDOR_REQUEST_OUT, 0x0802, i, buf, bsize, HZ);}static inlineint get_hw_cfg_rfmd(struct usb_device *udev, unsigned char *buf, int buf_size){ return usb_control_msg(udev, usb_rcvctrlpipe(udev,0), 0x33, INTERFACE_VENDOR_REQUEST_IN, ((0x0a << 8) | 0x02), 0, buf, buf_size, HZ);}/* Intersil boards use a different "value" for GetHWConfig requests */static inlineint 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 = kmalloc(sizeof(*hwcfg), GFP_KERNEL); if (!hwcfg) return -ENOMEM; switch (dev->board_type) { case BOARDTYPE_INTERSIL: ret = get_hw_cfg_intersil(dev->udev, (unsigned char *)&hwcfg->i, sizeof(hwcfg->i)); if (ret < 0) 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 < 0) 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 < 0) 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); ret = -EINVAL; } kfree(hwcfg); if (ret < 0) { err("Get HW Config failed (%d)", ret); } return ret;}/* == PROC getRegDomain == */struct reg_domain const *getRegDomain(u16 code){ static struct reg_domain const fd_tab[] = { {0x10, "FCC (U.S)", 0x7ff}, /* ch 1-11 */ {0x20, "IC (Canada)", 0x7ff}, /* ch 1-11 */ {0x30, "ETSI (Europe - (Spain+France)", 0x1fff}, /* ch 1-13 */ {0x31, "Spain", 0x600}, /* ch 10,11 */ {0x32, "France", 0x1e00}, /* ch 10-13 */ {0x40, "MKK (Japan)", 0x2000}, /* ch 14 */ {0x41, "MKK1 (Japan)", 0x3fff}, /* ch 1-14 */ {0x50, "Israel", 0x3fc}, /* ch 3-9 */ }; static int const tab_len = sizeof(fd_tab) / sizeof(struct reg_domain); /* use this if an unknown code comes in */ static struct reg_domain const unknown = {0, "<unknown>", 0xffffffff}; int i; for(i=0; i < tab_len; i++) if (code == fd_tab[i].code) break; return (i >= tab_len) ? &unknown : &fd_tab[i];} /* getFreqDomain */static inlineint get_mib(struct usb_device *udev, u16 mib, u8 *buf, int buf_size){ return usb_control_msg(udev, usb_rcvctrlpipe(udev,0), 0x33, INTERFACE_VENDOR_REQUEST_IN, mib << 8, 0, buf, buf_size, HZ);}static inlineint get_cmd_status(struct usb_device *udev, u8 cmd, u8 *cmd_status){ return usb_control_msg(udev, usb_rcvctrlpipe(udev,0), 0x22, INTERFACE_VENDOR_REQUEST_IN, cmd, 0, cmd_status, 40, HZ);}#define EXT_FW_BLOCK_SIZE 1024int at76c503_download_external_fw(struct usb_device *udev, u8 *buf, int size){ int i = 0, ret = 0; u8 op_mode; u8 *block; if (size < 0) return -EINVAL; if ((size > 0) && (buf == NULL)) return -EFAULT; op_mode = get_op_mode(udev); if (op_mode <= 0) { err("Internal firmware not loaded (%d)", op_mode); return -EPROTO; } if (op_mode == OPMODE_NETCARD) { /* don't need firmware downloaded, it's already ready to go */ return 0; } if (op_mode != OPMODE_NOFLASHNETCARD) { dbg(DBG_DEVSTART, "Unexpected operating mode (%d)." "Attempting to download firmware anyway.", op_mode); } block = kmalloc(EXT_FW_BLOCK_SIZE, GFP_KERNEL); if (block == NULL) return -ENOMEM; dbg(DBG_DEVSTART, "Downloading external firmware..."); while(size > 0){ int bsize = size > EXT_FW_BLOCK_SIZE ? EXT_FW_BLOCK_SIZE : size; memcpy(block, buf, bsize); dbg(DBG_DEVSTART, "ext fw, size left = %5d, bsize = %4d, i = %2d", size, bsize, i); if((ret = load_ext_fw_block(udev, i, block, bsize)) < 0){ err("load_ext_fw_block failed: %d, i = %d", ret, i); goto exit; } buf += bsize; size -= bsize; i++; } /* for fw >= 0.100, the device needs an extra empty block: */ if((ret = load_ext_fw_block(udev, i, block, 0)) < 0){ err("load_ext_fw_block failed: %d, i = %d", ret, i); goto exit; } exit: kfree(block); return ret;}staticint set_card_command(struct usb_device *udev, int cmd, unsigned char *buf, int buf_size){ int ret; struct at76c503_command *cmd_buf = (struct at76c503_command *)kmalloc( sizeof(struct at76c503_command) + buf_size, GFP_KERNEL); if(cmd_buf){ cmd_buf->cmd = cmd; cmd_buf->reserved = 0; cmd_buf->size = cpu_to_le16(buf_size); if(buf_size > 0) memcpy(&(cmd_buf[1]), buf, buf_size); ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), 0x0e, DEVICE_VENDOR_REQUEST_OUT, 0, 0, cmd_buf, sizeof(struct at76c503_command) + buf_size, HZ); kfree(cmd_buf); return ret; } return -ENOMEM;}/* TODO: should timeout */int wait_completion(struct at76c503 *dev, int cmd){ u8 *cmd_status = kmalloc(40, GFP_KERNEL); struct net_device *netdev = dev->netdev; int ret = 0; do{ ret = get_cmd_status(dev->udev, cmd, cmd_status); if(ret < 0){ err("%s: get_cmd_status failed: %d", netdev->name, ret); break; } dbg(DBG_WAIT_COMPLETE, "%s: cmd %d,cmd_status[5] = %d", dev->netdev->name, cmd, cmd_status[5]); if(cmd_status[5] == CMD_STATUS_IN_PROGRESS || cmd_status[5] == CMD_STATUS_IDLE){ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/10); // 100 ms }else break; }while(1); if (ret >= 0) /* if get_cmd_status did not fail, return the status retrieved */ ret = cmd_status[5]; kfree(cmd_status); return ret;}staticint set_mib(struct at76c503 *dev, struct set_mib_buffer *buf){ struct usb_device *udev = dev->udev; int ret; struct at76c503_command *cmd_buf = (struct at76c503_command *)kmalloc( sizeof(struct at76c503_command) + buf->size + 4, GFP_KERNEL); if(cmd_buf){ cmd_buf->cmd = CMD_SET_MIB; cmd_buf->reserved = 0; cmd_buf->size = cpu_to_le16(buf->size + 4); memcpy(&(cmd_buf[1]), buf, buf->size + 4); ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), 0x0e, DEVICE_VENDOR_REQUEST_OUT, 0, 0, cmd_buf, sizeof(struct at76c503_command) + buf->size + 4, HZ); if (ret >= 0) if ((ret=wait_completion(dev, CMD_SET_MIB)) != CMD_STATUS_COMPLETE) { info("%s: set_mib: wait_completion failed with %d", dev->netdev->name, ret); ret = -156; /* ??? */ } kfree(cmd_buf); return ret; } return -ENOMEM;}/* return < 0 on error, == 0 if no command sent, == 1 if cmd sent */staticint set_radio(struct at76c503 *dev, int on_off){ int ret; if(dev->radio_on != on_off){ ret = set_card_command(dev->udev, CMD_RADIO, NULL, 0); if(ret < 0){ err("%s: set_card_command(CMD_RADIO) failed: %d", dev->netdev->name, ret); } else ret = 1; dev->radio_on = on_off; } else ret = 0; return ret;}/* == PROC set_pm_mode == sets power save modi (PM_ACTIVE/PM_SAVE/PM_SMART_SAVE) */static int set_pm_mode(struct at76c503 *dev, u8 mode) __attribute__ ((unused));static int set_pm_mode(struct at76c503 *dev, u8 mode){ int ret = 0; struct set_mib_buffer mib_buf; memset(&mib_buf, 0, sizeof(struct set_mib_buffer)); mib_buf.type = MIB_MAC_MGMT; mib_buf.size = 1; mib_buf.index = POWER_MGMT_MODE_OFFSET; mib_buf.data[0] = mode; ret = set_mib(dev, &mib_buf); if(ret < 0){ err("%s: set_mib (pm_mode) failed: %d", dev->netdev->name, ret); } return ret;}/* == PROC set_associd == sets the assoc id for power save mode */static int set_associd(struct at76c503 *dev, u16 id) __attribute__ ((unused));static int set_associd(struct at76c503 *dev, u16 id){ int ret = 0; struct set_mib_buffer mib_buf; memset(&mib_buf, 0, sizeof(struct set_mib_buffer)); mib_buf.type = MIB_MAC_MGMT; mib_buf.size = 2; mib_buf.index = STATION_ID_OFFSET; mib_buf.data[0] = id & 0xff; mib_buf.data[1] = id >> 8; ret = set_mib(dev, &mib_buf); if(ret < 0){ err("%s: set_mib (associd) failed: %d", dev->netdev->name, ret); } return ret;}/* == PROC set_listen_interval == sets the listen interval for power save mode. really needed, as we have a similar parameter in the assocreq ??? */static int set_listen_interval(struct at76c503 *dev, u16 interval) __attribute__ ((unused));static int set_listen_interval(struct at76c503 *dev, u16 interval){ int ret = 0; struct set_mib_buffer mib_buf; memset(&mib_buf, 0, sizeof(struct set_mib_buffer)); mib_buf.type = MIB_MAC; mib_buf.size = 2; mib_buf.index = STATION_ID_OFFSET; mib_buf.data[0] = interval & 0xff; mib_buf.data[1] = interval >> 8; ret = set_mib(dev, &mib_buf); if(ret < 0){ err("%s: set_mib (listen_interval) failed: %d", dev->netdev->name, ret); } return ret;}staticint set_preamble(struct at76c503 *dev, u8 type){ int ret = 0; struct set_mib_buffer mib_buf; memset(&mib_buf, 0, sizeof(struct set_mib_buffer)); mib_buf.type = MIB_LOCAL; mib_buf.size = 1; mib_buf.index = PREAMBLE_TYPE_OFFSET; mib_buf.data[0] = type; ret = set_mib(dev, &mib_buf); if(ret < 0){ err("%s: set_mib (preamble) failed: %d", dev->netdev->name, ret); } return ret;}staticint set_frag(struct at76c503 *dev, u16 size){ int ret = 0; struct set_mib_buffer mib_buf; memset(&mib_buf, 0, sizeof(struct set_mib_buffer)); mib_buf.type = MIB_MAC; mib_buf.size = 2; mib_buf.index = FRAGMENTATION_OFFSET; *(u16*)mib_buf.data = cpu_to_le16(size); ret = set_mib(dev, &mib_buf); if(ret < 0){ err("%s: set_mib (frag threshold) failed: %d", dev->netdev->name, ret); } return ret;}static
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -