diff options
author | Marcus Glocker <mglocker@cvs.openbsd.org> | 2007-10-09 08:24:18 +0000 |
---|---|---|
committer | Marcus Glocker <mglocker@cvs.openbsd.org> | 2007-10-09 08:24:18 +0000 |
commit | 828fcb97b5e6b29f13d9d5736a4fe66719dcff22 (patch) | |
tree | 6809b99df6447d6fa0299201e88d7898c1d8bce4 /sys/dev/pcmcia/if_malo.c | |
parent | 54cbb3780c19c9c504c4d9578e7606ee26db942f (diff) |
Load the firmware files just one time per device lifecycle (attach time)
instead on every `ifconfig up'.
Diffstat (limited to 'sys/dev/pcmcia/if_malo.c')
-rw-r--r-- | sys/dev/pcmcia/if_malo.c | 96 |
1 files changed, 61 insertions, 35 deletions
diff --git a/sys/dev/pcmcia/if_malo.c b/sys/dev/pcmcia/if_malo.c index 804def0d02d..aa15cd05780 100644 --- a/sys/dev/pcmcia/if_malo.c +++ b/sys/dev/pcmcia/if_malo.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_malo.c,v 1.58 2007/10/08 22:30:16 mglocker Exp $ */ +/* $OpenBSD: if_malo.c,v 1.59 2007/10/09 08:24:17 mglocker Exp $ */ /* * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> @@ -74,6 +74,8 @@ int malo_pcmcia_activate(struct device *, enum devact); void cmalo_attach(void *); int cmalo_ioctl(struct ifnet *, u_long, caddr_t); +int cmalo_fw_alloc(struct malo_softc *); +void cmalo_fw_free(struct malo_softc *); int cmalo_fw_load_helper(struct malo_softc *); int cmalo_fw_load_main(struct malo_softc *); int cmalo_init(struct ifnet *); @@ -272,6 +274,8 @@ cmalo_attach(void *arg) cmalo_intr_mask(sc, 0); /* load firmware */ + if (cmalo_fw_alloc(sc) != 0) + return; if (cmalo_fw_load_helper(sc) != 0) return; if (cmalo_fw_load_main(sc) != 0) @@ -432,13 +436,55 @@ cmalo_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } int +cmalo_fw_alloc(struct malo_softc *sc) +{ + const char *name_h = "malo8385-h"; + const char *name_m = "malo8385-m"; + int error; + + if (sc->sc_fw_h == NULL) { + /* read helper firmware image */ + error = loadfirmware(name_h, &sc->sc_fw_h, &sc->sc_fw_h_size); + if (error != 0) { + printf("%s: error %d, could not read firmware %s\n", + sc->sc_dev.dv_xname, error, name_h); + return (EIO); + } + } + + if (sc->sc_fw_m == NULL) { + /* read main firmware image */ + error = loadfirmware(name_m, &sc->sc_fw_m, &sc->sc_fw_m_size); + if (error != 0) { + printf("%s: error %d, could not read firmware %s\n", + sc->sc_dev.dv_xname, error, name_m); + return (EIO); + } + } + + return (0); +} + +void +cmalo_fw_free(struct malo_softc *sc) +{ + if (sc->sc_fw_h != NULL) { + free(sc->sc_fw_h, M_DEVBUF); + sc->sc_fw_h = NULL; + } + + if (sc->sc_fw_m != NULL) { + free(sc->sc_fw_m, M_DEVBUF); + sc->sc_fw_m = NULL; + } +} + +int cmalo_fw_load_helper(struct malo_softc *sc) { - const char *name = "malo8385-h"; - size_t usize; - uint8_t val8, *ucode; + uint8_t val8; uint16_t bsize, *uc; - int error, offset, i; + int offset, i; /* verify if the card is ready for firmware download */ val8 = MALO_READ_1(sc, MALO_REG_SCRATCH); @@ -452,25 +498,18 @@ cmalo_fw_load_helper(struct malo_softc *sc) return (EIO); } - /* read helper firmware image */ - if ((error = loadfirmware(name, &ucode, &usize)) != 0) { - printf("%s: error %d, could not read firmware %s\n", - sc->sc_dev.dv_xname, error, name); - return (EIO); - } - /* download the helper firmware */ - for (offset = 0; offset < usize; offset += bsize) { - if (usize - offset >= MALO_FW_HELPER_BSIZE) + for (offset = 0; offset < sc->sc_fw_h_size; offset += bsize) { + if (sc->sc_fw_h_size - offset >= MALO_FW_HELPER_BSIZE) bsize = MALO_FW_HELPER_BSIZE; else - bsize = usize - offset; + bsize = sc->sc_fw_h_size - offset; /* send a block in words and confirm it */ DPRINTF(3, "%s: download helper FW block (%d bytes, %d off)\n", sc->sc_dev.dv_xname, bsize, offset); MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, bsize); - uc = (uint16_t *)(ucode + offset); + uc = (uint16_t *)(sc->sc_fw_h + offset); for (i = 0; i < bsize / 2; i++) MALO_WRITE_2(sc, MALO_REG_CMD_WRITE, htole16(uc[i])); MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER); @@ -487,11 +526,9 @@ cmalo_fw_load_helper(struct malo_softc *sc) if (i == 50) { printf("%s: timeout while helper FW block download!\n", sc->sc_dev.dv_xname); - free(ucode, M_DEVBUF); return (EIO); } } - free(ucode, M_DEVBUF); /* helper firmware download done */ MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, 0); @@ -505,18 +542,8 @@ cmalo_fw_load_helper(struct malo_softc *sc) int cmalo_fw_load_main(struct malo_softc *sc) { - const char *name = "malo8385-m"; - size_t usize; - uint8_t *ucode; uint16_t val16, bsize, *uc; - int error, offset, i, retry; - - /* read main firmware image */ - if ((error = loadfirmware(name, &ucode, &usize)) != 0) { - printf("%s: error %d, could not read firmware %s\n", - sc->sc_dev.dv_xname, error, name); - return (EIO); - } + int offset, i, retry; /* verify if the helper firmware has been loaded correctly */ for (i = 0; i < 10; i++) { @@ -526,13 +553,12 @@ cmalo_fw_load_main(struct malo_softc *sc) } if (i == 10) { printf("%s: helper FW not loaded!\n", sc->sc_dev.dv_xname); - free(ucode, M_DEVBUF); return (EIO); } DPRINTF(1, "%s: helper FW loaded successfully\n", sc->sc_dev.dv_xname); /* download the main firmware */ - for (offset = 0; offset < usize; offset += bsize) { + for (offset = 0; offset < sc->sc_fw_m_size; offset += bsize) { val16 = MALO_READ_2(sc, MALO_REG_RBAL); /* * If the helper firmware serves us an odd integer then @@ -543,7 +569,6 @@ cmalo_fw_load_main(struct malo_softc *sc) if (retry > MALO_FW_MAIN_MAXRETRY) { printf("%s: main FW download failed!\n", sc->sc_dev.dv_xname); - free(ucode, M_DEVBUF); return (EIO); } retry++; @@ -557,7 +582,7 @@ cmalo_fw_load_main(struct malo_softc *sc) DPRINTF(3, "%s: download main FW block (%d bytes, %d off)\n", sc->sc_dev.dv_xname, bsize, offset); MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, bsize); - uc = (uint16_t *)(ucode + offset); + uc = (uint16_t *)(sc->sc_fw_m + offset); for (i = 0; i < bsize / 2; i++) MALO_WRITE_2(sc, MALO_REG_CMD_WRITE, htole16(uc[i])); MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER); @@ -573,11 +598,9 @@ cmalo_fw_load_main(struct malo_softc *sc) if (i == 5000) { printf("%s: timeout while main FW block download!\n", sc->sc_dev.dv_xname); - free(ucode, M_DEVBUF); return (EIO); } } - free(ucode, M_DEVBUF); DPRINTF(1, "%s: main FW downloaded\n", sc->sc_dev.dv_xname); @@ -779,6 +802,9 @@ cmalo_detach(void *arg) if (sc->sc_data != NULL) free(sc->sc_data, M_DEVBUF); + /* free firmware */ + cmalo_fw_free(sc); + /* detach inferface */ ieee80211_ifdetach(ifp); if_detach(ifp); |