summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/bwi.c190
-rw-r--r--sys/dev/ic/bwivar.h10
2 files changed, 108 insertions, 92 deletions
diff --git a/sys/dev/ic/bwi.c b/sys/dev/ic/bwi.c
index 329ac855f71..f9dde32b343 100644
--- a/sys/dev/ic/bwi.c
+++ b/sys/dev/ic/bwi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bwi.c,v 1.23 2007/09/15 15:08:07 jsg Exp $ */
+/* $OpenBSD: bwi.c,v 1.24 2007/09/15 22:47:14 mglocker Exp $ */
/*
* Copyright (c) 2007 The DragonFly Project. All rights reserved.
@@ -153,7 +153,7 @@ int bwi_get_firmware(const char *, const uint8_t *, size_t,
int bwi_mac_fw_load(struct bwi_mac *);
int bwi_mac_gpio_init(struct bwi_mac *);
int bwi_mac_gpio_fini(struct bwi_mac *);
-int bwi_mac_fw_load_iv(struct bwi_mac *, const struct fw_image *);
+int bwi_mac_fw_load_iv(struct bwi_mac *, uint8_t *, int);
int bwi_mac_fw_init(struct bwi_mac *);
void bwi_mac_opmode_init(struct bwi_mac *);
void bwi_mac_hostflags_init(struct bwi_mac *);
@@ -1012,12 +1012,12 @@ bwi_mac_init(struct bwi_mac *mac)
if (error)
return (error);
- return (0);
-
error = bwi_mac_fw_init(mac);
if (error)
return (error);
+ return (0);
+
/*
* Turn on RF
*/
@@ -1877,111 +1877,129 @@ bwi_mac_gpio_fini(struct bwi_mac *mac)
}
int
-bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct fw_image *fw)
+bwi_mac_fw_load_iv(struct bwi_mac *mac, uint8_t *fw_image, int fw_len)
{
- DPRINTF(1, "%s\n", __func__);
-#if 0
struct bwi_softc *sc = mac->mac_sc;
- struct ifnet *ifp = &sc->sc_ic.ic_if;
- const struct bwi_fwhdr *hdr;
const struct bwi_fw_iv *iv;
- int n, i, iv_img_size;
+ uint16_t offset, size;
+ uint32_t val;
+ int len, i;
/* Get the number of IVs in the IV image */
- hdr = (const struct bwi_fwhdr *)fw->fw_image;
- n = betoh32(hdr->fw_iv_cnt);
- DPRINTF(1, "%s: IV count %d\n", sc->sc_dev.dv_xname, n);
-
- /* Calculate the IV image size, for later sanity check */
- iv_img_size = fw->fw_imglen - sizeof(*hdr);
+ len = fw_len / sizeof(struct bwi_fw_iv);
+ DPRINTF(1, "%s: IV count %d\n", sc->sc_dev.dv_xname, len);
/* Locate the first IV */
- iv = (const struct bwi_fw_iv *)
- ((const uint8_t *)fw->fw_image + sizeof(*hdr));
-
- for (i = 0; i < n; ++i) {
- uint16_t iv_ofs, ofs;
- int sz = 0;
-
- if (iv_img_size < sizeof(iv->iv_ofs)) {
- DPRINTF(1, "%s: invalid IV image, ofs\n",
- sc->sc_dev.dv_xname);
- return (EINVAL);
- }
- iv_img_size -= sizeof(iv->iv_ofs);
- sz += sizeof(iv->iv_ofs);
+ iv = (const struct bwi_fw_iv *)fw_image;
+
+ for (i = 0; i < len; i++, iv++) {
+ offset = betoh16(iv->offset);
+ size = betoh16(iv->size);
+ val = betoh32(iv->val);
+
+ if (offset >= 0x1000)
+ goto error;
+
+ if (size == sizeof(uint16_t)) {
+ if (val & 0xffff0000)
+ goto error;
+ CSR_WRITE_2(sc, offset, (uint16_t)val);
+ } else if (size == sizeof(uint32_t))
+ CSR_WRITE_4(sc, offset, val);
+ else
+ goto error;
+ }
- iv_ofs = betoh16(iv->iv_ofs);
+ return (0);
- ofs = __SHIFTOUT(iv_ofs, BWI_FW_IV_OFS_MASK);
- if (ofs >= 0x1000) {
- DPRINTF(1, "%s: invalid ofs (0x%04x) for %dth iv\n",
- sc->sc_dev.dv_xname, ofs, i);
- return (EINVAL);
- }
+error:
+ printf("%s: bad IV format!\n", sc->sc_dev.dv_xname);
+ return (1);
+}
- if (iv_ofs & BWI_FW_IV_IS_32BIT) {
- uint32_t val32;
+int
+bwi_mac_fw_init(struct bwi_mac *mac)
+{
+ struct bwi_softc *sc = mac->mac_sc;
+ char *name = "bwi-airforce";
+ char fwname[64];
+ uint8_t *ucode;
+ size_t size_ucode, size_iv, off_iv;
+ int idx, error;
- if (iv_img_size < sizeof(iv->iv_val.val32)) {
- DPRINTF(1, "%s: invalid IV image, val32\n",
- sc->sc_dev.dv_xname);
- return (EINVAL);
- }
- iv_img_size -= sizeof(iv->iv_val.val32);
- sz += sizeof(iv->iv_val.val32);
+ /*
+ * Load FW file
+ */
+ if ((error = loadfirmware(name, &ucode, &size_ucode)) != 0) {
+ printf("%s: error %d, could not read microcode %s!\n",
+ sc->sc_dev.dv_xname, error, name);
+ return (EIO);
+ }
+ DPRINTF(1, "%s: successfully read %s\n", sc->sc_dev.dv_xname, name);
- val32 = betoh32(iv->iv_val.val32);
- CSR_WRITE_4(sc, ofs, val32);
- } else {
- uint16_t val16;
+ /*
+ * Load IV
+ *
+ * TODO: 11A
+ */
+ if (mac->mac_rev == 2 || mac->mac_rev == 4) {
+ idx = 2;
+ } else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) {
+ idx = 5;
+ } else {
+ printf("%s: no suitable IV for MAC rev %d\n",
+ sc->sc_dev.dv_xname, mac->mac_rev);
+ return (ENODEV);
+ }
+ snprintf(fwname, sizeof(fwname), "bcm43xx_initval%02d.fw", idx);
- if (iv_img_size < sizeof(iv->iv_val.val16)) {
- DPRINTF(1, "%s: invalid IV image, val16\n",
- sc->sc_dev.dv_xname);
- return (EINVAL);
- }
- iv_img_size -= sizeof(iv->iv_val.val16);
- sz += sizeof(iv->iv_val.val16);
+ DPRINTF(1, "%s: IV image is %s\n", sc->sc_dev.dv_xname, fwname);
- val16 = betoh16(iv->iv_val.val16);
- CSR_WRITE_2(sc, ofs, val16);
- }
+ if (bwi_get_firmware(fwname, ucode, size_ucode, &size_iv, &off_iv)) {
+ printf("%s: IV image %s not found!\n",
+ sc->sc_dev.dv_xname, fwname);
+ return (ENOMEM);
+ }
- iv = (const struct bwi_fw_iv *)((const uint8_t *)iv + sz);
+ error = bwi_mac_fw_load_iv(mac, (ucode + off_iv), size_iv);
+ if (error) {
+ printf("%s: load IV failed!\n", sc->sc_dev.dv_xname);
+ return (error);
}
- if (iv_img_size != 0) {
- DPRINTF(1, "%s: invalid IV image, size left %d\n",
- sc->sc_dev.dv_xname, iv_img_size);
- return (EINVAL);
+ /*
+ * Load extended IV
+ *
+ * TODO: 11A
+ */
+ if (mac->mac_rev == 2 || mac->mac_rev == 4 || mac->mac_rev >= 11) {
+ /* No extended IV */
+ goto back;
+ } else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) {
+ idx = 5;
+ } else {
+ printf("%s: no suitable extended IV for MAC rev %d\n",
+ sc->sc_dev.dv_xname, mac->mac_rev);
+ return (ENODEV);
}
+ snprintf(fwname, sizeof(fwname), "bcm43xx_initval%02d.fw", idx);
- return (0);
-#endif
- return (0);
-}
+ DPRINTF(1, "%s: extended IV image is %s\n",
+ sc->sc_dev.dv_xname, fwname);
-int
-bwi_mac_fw_init(struct bwi_mac *mac)
-{
- struct bwi_softc *sc;
- int error;
+ if (bwi_get_firmware(fwname, ucode, size_ucode, &size_iv, &off_iv)) {
+ printf("%s: extended IV image %s not found!\n",
+ sc->sc_dev.dv_xname, fwname);
+ return (ENOMEM);
+ }
- sc = mac->mac_sc;
+ error = bwi_mac_fw_load_iv(mac, (ucode + off_iv), size_iv);
+ if (error)
+ printf("%s: load extended IV failed!\n", sc->sc_dev.dv_xname);
- error = bwi_mac_fw_load_iv(mac, mac->mac_iv);
- if (error) {
- DPRINTF(1, "%s: load IV failed\n", sc->sc_dev.dv_xname);
- return (error);
- }
+back:
+ free(ucode, M_DEVBUF);
- if (mac->mac_iv_ext != NULL) {
- error = bwi_mac_fw_load_iv(mac, mac->mac_iv_ext);
- if (error)
- DPRINTF(1, "%s: load ExtIV failed\n",
- sc->sc_dev.dv_xname);
- }
return (error);
}
diff --git a/sys/dev/ic/bwivar.h b/sys/dev/ic/bwivar.h
index fec3603edc0..7768c5779c6 100644
--- a/sys/dev/ic/bwivar.h
+++ b/sys/dev/ic/bwivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bwivar.h,v 1.8 2007/09/15 13:38:22 jsg Exp $ */
+/* $OpenBSD: bwivar.h,v 1.9 2007/09/15 22:47:14 mglocker Exp $ */
/*
* Copyright (c) 2007 The DragonFly Project. All rights reserved.
@@ -256,11 +256,9 @@ struct bwi_fwhdr {
struct bwi_fw_iv {
/* Big endian */
- uint16_t iv_ofs;
- union {
- uint32_t val32;
- uint16_t val16;
- } iv_val;
+ uint16_t offset;
+ uint16_t size;
+ uint32_t val;
} __packed;
#define BWI_FW_IV_OFS_MASK __BITS(14, 0)