summaryrefslogtreecommitdiff
path: root/sys/dev/pcmcia/if_malo.c
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2007-10-09 08:24:18 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2007-10-09 08:24:18 +0000
commit828fcb97b5e6b29f13d9d5736a4fe66719dcff22 (patch)
tree6809b99df6447d6fa0299201e88d7898c1d8bce4 /sys/dev/pcmcia/if_malo.c
parent54cbb3780c19c9c504c4d9578e7606ee26db942f (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.c96
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);