📄 hostap_download.c
字号:
static int prism2_download_genesis(local_info_t *local, struct prism2_download_data *param){ struct net_device *dev = local->dev; int ram16 = 0, i; int ret = 0; if (local->hw_downloading) { printk(KERN_WARNING "%s: Already downloading - aborting new " "request\n", dev->name); return -EBUSY; } if (!local->func->genesis_reset || !local->func->cor_sreset) { printk(KERN_INFO "%s: Genesis mode downloading not supported " "with this hwmodel\n", dev->name); return -EOPNOTSUPP; } local->hw_downloading = 1; if (prism2_enable_aux_port(dev, 1)) { printk(KERN_DEBUG "%s: failed to enable AUX port\n", dev->name); ret = -EIO; goto out; } if (local->sram_type == -1) { /* 0x1F for x8 SRAM or 0x0F for x16 SRAM */ if (prism2_enable_genesis(local, 0x1f) == 0) { ram16 = 0; PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x8 " "SRAM\n", dev->name); } else if (prism2_enable_genesis(local, 0x0f) == 0) { ram16 = 1; PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x16 " "SRAM\n", dev->name); } else { printk(KERN_DEBUG "%s: Could not initiate genesis " "mode\n", dev->name); ret = -EIO; goto out; } } else { if (prism2_enable_genesis(local, local->sram_type == 8 ? 0x1f : 0x0f)) { printk(KERN_DEBUG "%s: Failed to set Genesis " "mode (sram_type=%d)\n", dev->name, local->sram_type); ret = -EIO; goto out; } ram16 = local->sram_type != 8; } for (i = 0; i < param->num_areas; i++) { PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n", dev->name, param->data[i].len, param->data[i].addr); if (hfa384x_to_aux(dev, param->data[i].addr, param->data[i].len, param->data[i].data)) { printk(KERN_WARNING "%s: RAM download at 0x%08x " "(len=%d) failed\n", dev->name, param->data[i].addr, param->data[i].len); ret = -EIO; goto out; } } PDEBUG(DEBUG_EXTRA2, "Disable genesis mode\n"); local->func->genesis_reset(local, ram16 ? 0x07 : 0x17); if (prism2_enable_aux_port(dev, 0)) { printk(KERN_DEBUG "%s: Failed to disable AUX port\n", dev->name); } mdelay(5); local->hw_downloading = 0; PDEBUG(DEBUG_EXTRA2, "Trying to initialize card\n"); /* Make sure the INIT command does not generate a command completion * event by disabling interrupts. */ hfa384x_disable_interrupts(dev); if (prism2_hw_init(dev, 1)) { printk(KERN_DEBUG "%s: Initialization after genesis mode " "download failed\n", dev->name); ret = -EIO; goto out; } PDEBUG(DEBUG_EXTRA2, "Card initialized - running PRI only\n"); if (prism2_hw_init2(dev, 1)) { printk(KERN_DEBUG "%s: Initialization(2) after genesis mode " "download failed\n", dev->name); ret = -EIO; goto out; } out: local->hw_downloading = 0; return ret;}#ifdef PRISM2_NON_VOLATILE_DOWNLOAD/* Note! Non-volatile downloading functionality has not yet been tested * thoroughly and it may corrupt flash image and effectively kill the card that * is being updated. You have been warned. */static inline int prism2_download_block(struct net_device *dev, u32 addr, u8 *data, u32 bufaddr, int rest_len){ u16 param0, param1; int block_len; block_len = rest_len < 4096 ? rest_len : 4096; param0 = addr & 0xffff; param1 = addr >> 16; HFA384X_OUTW(block_len, HFA384X_PARAM2_OFF); HFA384X_OUTW(param1, HFA384X_PARAM1_OFF); if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD | (HFA384X_PROGMODE_ENABLE_NON_VOLATILE << 8), param0)) { printk(KERN_WARNING "%s: Flash download command execution " "failed\n", dev->name); return -1; } if (hfa384x_to_aux(dev, bufaddr, block_len, data)) { printk(KERN_WARNING "%s: flash download at 0x%08x " "(len=%d) failed\n", dev->name, addr, block_len); return -1; } HFA384X_OUTW(0, HFA384X_PARAM2_OFF); HFA384X_OUTW(0, HFA384X_PARAM1_OFF); if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD | (HFA384X_PROGMODE_PROGRAM_NON_VOLATILE << 8), 0)) { printk(KERN_WARNING "%s: Flash write command execution " "failed\n", dev->name); return -1; } return block_len;}static int prism2_download_nonvolatile(local_info_t *local, struct prism2_download_data *dl){ struct net_device *dev = local->dev; int ret = 0, i; struct { u16 page; u16 offset; u16 len; } dlbuffer; u32 bufaddr; if (local->hw_downloading) { printk(KERN_WARNING "%s: Already downloading - aborting new " "request\n", dev->name); return -1; } ret = local->func->get_rid(dev, HFA384X_RID_DOWNLOADBUFFER, &dlbuffer, 6, 0); if (ret < 0) { printk(KERN_WARNING "%s: Could not read download buffer " "parameters\n", dev->name); goto out; } dlbuffer.page = le16_to_cpu(dlbuffer.page); dlbuffer.offset = le16_to_cpu(dlbuffer.offset); dlbuffer.len = le16_to_cpu(dlbuffer.len); printk(KERN_DEBUG "Download buffer: %d bytes at 0x%04x:0x%04x\n", dlbuffer.len, dlbuffer.page, dlbuffer.offset); bufaddr = (dlbuffer.page << 7) + dlbuffer.offset; local->hw_downloading = 1; if (!local->pri_only) { prism2_hw_shutdown(dev, 0); if (prism2_hw_init(dev, 0)) { printk(KERN_WARNING "%s: Could not initialize card for" " download\n", dev->name); ret = -1; goto out; } } hfa384x_disable_interrupts(dev); if (prism2_enable_aux_port(dev, 1)) { printk(KERN_WARNING "%s: Could not enable AUX port\n", dev->name); ret = -1; goto out; } printk(KERN_DEBUG "%s: starting flash download\n", dev->name); for (i = 0; i < dl->num_areas; i++) { int rest_len = dl->data[i].len; int data_off = 0; while (rest_len > 0) { int block_len; block_len = prism2_download_block( dev, dl->data[i].addr + data_off, dl->data[i].data + data_off, bufaddr, rest_len); if (block_len < 0) { ret = -1; goto out; } rest_len -= block_len; data_off += block_len; } } HFA384X_OUTW(0, HFA384X_PARAM1_OFF); HFA384X_OUTW(0, HFA384X_PARAM2_OFF); if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD | (HFA384X_PROGMODE_DISABLE << 8), 0)) { printk(KERN_WARNING "%s: Download command execution failed\n", dev->name); ret = -1; goto out; } if (prism2_enable_aux_port(dev, 0)) { printk(KERN_DEBUG "%s: Disabling AUX port failed\n", dev->name); /* continue anyway.. restart should have taken care of this */ } mdelay(5); local->func->hw_reset(dev); local->hw_downloading = 0; if (prism2_hw_config(dev, 2)) { printk(KERN_WARNING "%s: Card configuration after flash " "download failed\n", dev->name); ret = -1; } else { printk(KERN_INFO "%s: Card initialized successfully after " "flash download\n", dev->name); } out: local->hw_downloading = 0; return ret;}#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */static void prism2_download_free_data(struct prism2_download_data *dl){ int i; if (dl == NULL) return; for (i = 0; i < dl->num_areas; i++) kfree(dl->data[i].data); kfree(dl);}static int prism2_download(local_info_t *local, struct prism2_download_param *param){ int ret = 0; int i; u32 total_len = 0; struct prism2_download_data *dl = NULL; printk(KERN_DEBUG "prism2_download: dl_cmd=%d start_addr=0x%08x " "num_areas=%d\n", param->dl_cmd, param->start_addr, param->num_areas); if (param->num_areas > 100) { ret = -EINVAL; goto out; } dl = kmalloc(sizeof(*dl) + param->num_areas * sizeof(struct prism2_download_data_area), GFP_KERNEL); if (dl == NULL) { ret = -ENOMEM; goto out; } memset(dl, 0, sizeof(*dl) + param->num_areas * sizeof(struct prism2_download_data_area)); dl->dl_cmd = param->dl_cmd; dl->start_addr = param->start_addr; dl->num_areas = param->num_areas; for (i = 0; i < param->num_areas; i++) { PDEBUG(DEBUG_EXTRA2, " area %d: addr=0x%08x len=%d ptr=0x%p\n", i, param->data[i].addr, param->data[i].len, param->data[i].ptr); dl->data[i].addr = param->data[i].addr; dl->data[i].len = param->data[i].len; total_len += param->data[i].len; if (param->data[i].len > PRISM2_MAX_DOWNLOAD_AREA_LEN || total_len > PRISM2_MAX_DOWNLOAD_LEN) { ret = -E2BIG; goto out; } dl->data[i].data = kmalloc(dl->data[i].len, GFP_KERNEL); if (dl->data[i].data == NULL) { ret = -ENOMEM; goto out; } if (copy_from_user(dl->data[i].data, param->data[i].ptr, param->data[i].len)) { ret = -EFAULT; goto out; } } switch (param->dl_cmd) { case PRISM2_DOWNLOAD_VOLATILE: case PRISM2_DOWNLOAD_VOLATILE_PERSISTENT: ret = prism2_download_volatile(local, dl); break; case PRISM2_DOWNLOAD_VOLATILE_GENESIS: case PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT: ret = prism2_download_genesis(local, dl); break; case PRISM2_DOWNLOAD_NON_VOLATILE:#ifdef PRISM2_NON_VOLATILE_DOWNLOAD ret = prism2_download_nonvolatile(local, dl);#else /* PRISM2_NON_VOLATILE_DOWNLOAD */ printk(KERN_INFO "%s: non-volatile downloading not enabled\n", local->dev->name); ret = -EOPNOTSUPP;#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */ break; default: printk(KERN_DEBUG "%s: unsupported download command %d\n", local->dev->name, param->dl_cmd); ret = -EINVAL; break; }; out: if (ret == 0 && dl && param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT) { prism2_download_free_data(local->dl_pri); local->dl_pri = dl; } else if (ret == 0 && dl && param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_PERSISTENT) { prism2_download_free_data(local->dl_sec); local->dl_sec = dl; } else prism2_download_free_data(dl); return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -