📄 main.c
字号:
spin_unlock(&dev->wl->irq_lock); return ret;}static void b43legacy_release_firmware(struct b43legacy_wldev *dev){ release_firmware(dev->fw.ucode); dev->fw.ucode = NULL; release_firmware(dev->fw.pcm); dev->fw.pcm = NULL; release_firmware(dev->fw.initvals); dev->fw.initvals = NULL; release_firmware(dev->fw.initvals_band); dev->fw.initvals_band = NULL;}static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl){ b43legacyerr(wl, "You must go to http://linuxwireless.org/en/users/" "Drivers/b43#devicefirmware " "and download the correct firmware (version 3).\n");}static int do_request_fw(struct b43legacy_wldev *dev, const char *name, const struct firmware **fw){ char path[sizeof(modparam_fwpostfix) + 32]; struct b43legacy_fw_header *hdr; u32 size; int err; if (!name) return 0; snprintf(path, ARRAY_SIZE(path), "b43legacy%s/%s.fw", modparam_fwpostfix, name); err = request_firmware(fw, path, dev->dev->dev); if (err) { b43legacyerr(dev->wl, "Firmware file \"%s\" not found " "or load failed.\n", path); return err; } if ((*fw)->size < sizeof(struct b43legacy_fw_header)) goto err_format; hdr = (struct b43legacy_fw_header *)((*fw)->data); switch (hdr->type) { case B43legacy_FW_TYPE_UCODE: case B43legacy_FW_TYPE_PCM: size = be32_to_cpu(hdr->size); if (size != (*fw)->size - sizeof(struct b43legacy_fw_header)) goto err_format; /* fallthrough */ case B43legacy_FW_TYPE_IV: if (hdr->ver != 1) goto err_format; break; default: goto err_format; } return err;err_format: b43legacyerr(dev->wl, "Firmware file \"%s\" format error.\n", path); return -EPROTO;}static int b43legacy_request_firmware(struct b43legacy_wldev *dev){ struct b43legacy_firmware *fw = &dev->fw; const u8 rev = dev->dev->id.revision; const char *filename; u32 tmshigh; int err; tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH); if (!fw->ucode) { if (rev == 2) filename = "ucode2"; else if (rev == 4) filename = "ucode4"; else filename = "ucode5"; err = do_request_fw(dev, filename, &fw->ucode); if (err) goto err_load; } if (!fw->pcm) { if (rev < 5) filename = "pcm4"; else filename = "pcm5"; err = do_request_fw(dev, filename, &fw->pcm); if (err) goto err_load; } if (!fw->initvals) { switch (dev->phy.type) { case B43legacy_PHYTYPE_G: if ((rev >= 5) && (rev <= 10)) filename = "b0g0initvals5"; else if (rev == 2 || rev == 4) filename = "b0g0initvals2"; else goto err_no_initvals; break; default: goto err_no_initvals; } err = do_request_fw(dev, filename, &fw->initvals); if (err) goto err_load; } if (!fw->initvals_band) { switch (dev->phy.type) { case B43legacy_PHYTYPE_G: if ((rev >= 5) && (rev <= 10)) filename = "b0g0bsinitvals5"; else if (rev >= 11) filename = NULL; else if (rev == 2 || rev == 4) filename = NULL; else goto err_no_initvals; break; default: goto err_no_initvals; } err = do_request_fw(dev, filename, &fw->initvals_band); if (err) goto err_load; } return 0;err_load: b43legacy_print_fw_helptext(dev->wl); goto error;err_no_initvals: err = -ENODEV; b43legacyerr(dev->wl, "No Initial Values firmware file for PHY %u, " "core rev %u\n", dev->phy.type, rev); goto error;error: b43legacy_release_firmware(dev); return err;}static int b43legacy_upload_microcode(struct b43legacy_wldev *dev){ const size_t hdr_len = sizeof(struct b43legacy_fw_header); const __be32 *data; unsigned int i; unsigned int len; u16 fwrev; u16 fwpatch; u16 fwdate; u16 fwtime; u32 tmp; int err = 0; /* Upload Microcode. */ data = (__be32 *) (dev->fw.ucode->data + hdr_len); len = (dev->fw.ucode->size - hdr_len) / sizeof(__be32); b43legacy_shm_control_word(dev, B43legacy_SHM_UCODE | B43legacy_SHM_AUTOINC_W, 0x0000); for (i = 0; i < len; i++) { b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA, be32_to_cpu(data[i])); udelay(10); } if (dev->fw.pcm) { /* Upload PCM data. */ data = (__be32 *) (dev->fw.pcm->data + hdr_len); len = (dev->fw.pcm->size - hdr_len) / sizeof(__be32); b43legacy_shm_control_word(dev, B43legacy_SHM_HW, 0x01EA); b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA, 0x00004000); /* No need for autoinc bit in SHM_HW */ b43legacy_shm_control_word(dev, B43legacy_SHM_HW, 0x01EB); for (i = 0; i < len; i++) { b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA, be32_to_cpu(data[i])); udelay(10); } } b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_ALL); b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0x00020402); /* Wait for the microcode to load and respond */ i = 0; while (1) { tmp = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); if (tmp == B43legacy_IRQ_MAC_SUSPENDED) break; i++; if (i >= B43legacy_IRQWAIT_MAX_RETRIES) { b43legacyerr(dev->wl, "Microcode not responding\n"); b43legacy_print_fw_helptext(dev->wl); err = -ENODEV; goto out; } udelay(10); } /* dummy read follows */ b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); /* Get and check the revisions. */ fwrev = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, B43legacy_SHM_SH_UCODEREV); fwpatch = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, B43legacy_SHM_SH_UCODEPATCH); fwdate = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, B43legacy_SHM_SH_UCODEDATE); fwtime = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, B43legacy_SHM_SH_UCODETIME); if (fwrev > 0x128) { b43legacyerr(dev->wl, "YOU ARE TRYING TO LOAD V4 FIRMWARE." " Only firmware from binary drivers version 3.x" " is supported. You must change your firmware" " files.\n"); b43legacy_print_fw_helptext(dev->wl); b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0); err = -EOPNOTSUPP; goto out; } b43legacydbg(dev->wl, "Loading firmware version 0x%X, patch level %u " "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch, (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F); dev->fw.rev = fwrev; dev->fw.patch = fwpatch;out: return err;}static int b43legacy_write_initvals(struct b43legacy_wldev *dev, const struct b43legacy_iv *ivals, size_t count, size_t array_size){ const struct b43legacy_iv *iv; u16 offset; size_t i; bool bit32; BUILD_BUG_ON(sizeof(struct b43legacy_iv) != 6); iv = ivals; for (i = 0; i < count; i++) { if (array_size < sizeof(iv->offset_size)) goto err_format; array_size -= sizeof(iv->offset_size); offset = be16_to_cpu(iv->offset_size); bit32 = !!(offset & B43legacy_IV_32BIT); offset &= B43legacy_IV_OFFSET_MASK; if (offset >= 0x1000) goto err_format; if (bit32) { u32 value; if (array_size < sizeof(iv->data.d32)) goto err_format; array_size -= sizeof(iv->data.d32); value = be32_to_cpu(get_unaligned(&iv->data.d32)); b43legacy_write32(dev, offset, value); iv = (const struct b43legacy_iv *)((const uint8_t *)iv + sizeof(__be16) + sizeof(__be32)); } else { u16 value; if (array_size < sizeof(iv->data.d16)) goto err_format; array_size -= sizeof(iv->data.d16); value = be16_to_cpu(iv->data.d16); b43legacy_write16(dev, offset, value); iv = (const struct b43legacy_iv *)((const uint8_t *)iv + sizeof(__be16) + sizeof(__be16)); } } if (array_size) goto err_format; return 0;err_format: b43legacyerr(dev->wl, "Initial Values Firmware file-format error.\n"); b43legacy_print_fw_helptext(dev->wl); return -EPROTO;}static int b43legacy_upload_initvals(struct b43legacy_wldev *dev){ const size_t hdr_len = sizeof(struct b43legacy_fw_header); const struct b43legacy_fw_header *hdr; struct b43legacy_firmware *fw = &dev->fw; const struct b43legacy_iv *ivals; size_t count; int err; hdr = (const struct b43legacy_fw_header *)(fw->initvals->data); ivals = (const struct b43legacy_iv *)(fw->initvals->data + hdr_len); count = be32_to_cpu(hdr->size); err = b43legacy_write_initvals(dev, ivals, count, fw->initvals->size - hdr_len); if (err) goto out; if (fw->initvals_band) { hdr = (const struct b43legacy_fw_header *) (fw->initvals_band->data); ivals = (const struct b43legacy_iv *)(fw->initvals_band->data + hdr_len); count = be32_to_cpu(hdr->size); err = b43legacy_write_initvals(dev, ivals, count, fw->initvals_band->size - hdr_len); if (err) goto out; }out: return err;}/* Initialize the GPIOs * http://bcm-specs.sipsolutions.net/GPIO */static int b43legacy_gpio_init(struct b43legacy_wldev *dev){ struct ssb_bus *bus = dev->dev->bus; struct ssb_device *gpiodev, *pcidev = NULL; u32 mask; u32 set; b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD) & 0xFFFF3FFF); b43legacy_leds_switch_all(dev, 0); b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK, b43legacy_read16(dev, B43legacy_MMIO_GPIO_MASK) | 0x000F); mask = 0x0000001F; set = 0x0000000F; if (dev->dev->bus->chip_id == 0x4301) { mask |= 0x0060; set |= 0x0060; } if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_PACTRL) { b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK, b43legacy_read16(dev, B43legacy_MMIO_GPIO_MASK) | 0x0200); mask |= 0x0200; set |= 0x0200; } if (dev->dev->id.revision >= 2) mask |= 0x0010; /* FIXME: This is redundant. */#ifdef CONFIG_SSB_DRIVER_PCICORE pcidev = bus->pcicore.dev;#endif gpiodev = bus->chipco.dev ? : pcidev; if (!gpiodev) return 0; ssb_write32(gpiodev, B43legacy_GPIO_CONTROL, (ssb_read32(gpiodev, B43legacy_GPIO_CONTROL) & mask) | set); return 0;}/* Turn off all GPIO stuff. Call this on module unload, for example. */static void b43legacy_gpio_cleanup(struct b43legacy_wldev *dev){ struct ssb_bus *bus = dev->dev->bus; struct ssb_device *gpiodev, *pcidev = NULL;#ifdef CONFIG_SSB_DRIVER_PCICORE pcidev = bus->pcicore.dev;#endif gpiodev = bus->chipco.dev ? : pcidev; if (!gpiodev) return; ssb_write32(gpiodev, B43legacy_GPIO_CONTROL, 0);}/* http://bcm-specs.sipsolutions.net/EnableMac */void b43legacy_mac_enable(struct b43legacy_wldev *dev){ dev->mac_suspended--; B43legacy_WARN_ON(dev->mac_suspended < 0); if (dev->mac_suspended == 0) { b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD) | B43legacy_SBF_MAC_ENABLED); b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_MAC_SUSPENDED); /* the next two are dummy reads */ b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); b43legacy_power_saving_ctl_bits(dev, -1, -1); }}/* http://bcm-specs.sipsolutions.net/SuspendMAC */void b43legacy_mac_suspend(struct b43legacy_wldev *dev){ int i; u32 tmp; B43legacy_WARN_ON(dev->mac_suspended < 0); if (dev->mac_suspended == 0) { b43legacy_power_saving_ctl_bits(dev, -1, 1); b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD) & ~B43legacy_SBF_MAC_ENABLED); b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); for (i = 10000; i; i--) { tmp = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); if (tmp & B43legacy_IRQ_MAC_SUSPENDED) goto out; udelay(1); } b43legacyerr(dev->wl, "MAC suspend failed\n"); }out: dev->mac_suspended++;}static void b43legacy_adjust_opmode(struct b43legacy_wldev *dev){ struct b43legacy_wl *wl = dev->wl; u32 ctl; u16 cfp_pretbtt; ctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); /* Reset status to STA infrastructure mode. */ ctl &= ~B43legacy_MACCTL_AP; ctl &= ~B43legacy_MACCTL_KEEP_CTL; ctl &= ~B43legacy_MACCTL_KEEP_BADPLCP; ctl &= ~B43legacy_MACCTL_KEEP_BAD; ctl &= ~B43legacy_MACCTL_PROMISC; ctl &= ~B43legacy_MACCTL_BEACPROMISC;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -