summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2002-08-15 07:13:17 +0000
committerWarner Losh <imp@FreeBSD.org>2002-08-15 07:13:17 +0000
commit6f6efa5165971625e295067ad6d1e81169b3c49d (patch)
treece84034800c168a808a6c7d79c6ca011158dc4a3
parentba05755c4bec41856fb396e1fb9421685425df01 (diff)
Notes
-rw-r--r--sys/dev/wi/if_wavelan_ieee.h17
-rw-r--r--sys/dev/wi/if_wi.c142
-rw-r--r--sys/dev/wi/if_wi_pccard.c149
-rw-r--r--sys/dev/wi/if_wivar.h1
4 files changed, 161 insertions, 148 deletions
diff --git a/sys/dev/wi/if_wavelan_ieee.h b/sys/dev/wi/if_wavelan_ieee.h
index 0af03a625d64..e350c32febcb 100644
--- a/sys/dev/wi/if_wavelan_ieee.h
+++ b/sys/dev/wi/if_wavelan_ieee.h
@@ -75,6 +75,7 @@ struct wi_req {
#define WI_RID_MGMT_XMIT 0x0200
#define WI_RID_ZERO_CACHE 0x0300
#define WI_RID_READ_CACHE 0x0400
+#define WI_RID_FWDOWNLOAD 0x0500
struct wi_80211_hdr {
u_int16_t frame_ctl;
@@ -147,6 +148,22 @@ struct wi_sigcache {
int quality; /* quality of the packet */
};
+/*
+ * Firmware downloading API. We support downloading into RAM and into
+ * flash. We copy the entire .hex file for both the primary and secondary
+ * firmware into the kernel, which is minorly gross, but matches the
+ * format of the compiled in firmware.
+ */
+struct wi_fwdownload {
+ int type; /* What type of download. */
+#define WI_FW_RAM 1
+#define WI_FW_FLASH 2
+ size_t pri_len; /* Primary firmware length */
+ size_t sec_len; /* Secondary firmware length */
+ caddr_t pri_data; /* Pointer (user) to primary data */
+ caddr_t sec_data; /* Pointer (user) to secondary data */
+};
+
#ifndef _KERNEL
struct wi_counters {
u_int32_t wi_tx_unicast_frames;
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index b3a3db1a6cd5..c2175644459b 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -142,6 +142,11 @@ static void wi_media_status(struct ifnet *, struct ifmediareq *);
static int wi_get_debug(struct wi_softc *, struct wi_req *);
static int wi_set_debug(struct wi_softc *, struct wi_req *);
+/* support to download firmware for symbol CF card */
+static int wi_symbol_write_firm(struct wi_softc *, const void *, int,
+ const void *, int);
+static int wi_symbol_set_hcr(struct wi_softc *, int);
+
devclass_t wi_devclass;
struct wi_card_ident wi_card_ident[] = {
@@ -3109,3 +3114,140 @@ wi_set_debug(sc, wreq)
return (error);
}
+
+/*
+ * Special routines to download firmware for Symbol CF card.
+ * XXX: This should be modified generic into any PRISM-2 based card.
+ */
+
+#define WI_SBCF_PDIADDR 0x3100
+
+/* unaligned load little endian */
+#define GETLE32(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
+#define GETLE16(p) ((p)[0] | ((p)[1]<<8))
+
+int
+wi_symbol_load_firm(struct wi_softc *sc, const void *primsym, int primlen,
+ const void *secsym, int seclen)
+{
+ uint8_t ebuf[256];
+ int i;
+
+ /* load primary code and run it */
+ wi_symbol_set_hcr(sc, WI_HCR_EEHOLD);
+ if (wi_symbol_write_firm(sc, primsym, primlen, NULL, 0))
+ return EIO;
+ wi_symbol_set_hcr(sc, WI_HCR_RUN);
+ for (i = 0; ; i++) {
+ if (i == 10)
+ return ETIMEDOUT;
+ tsleep(sc, PWAIT, "wiinit", 1);
+ if (CSR_READ_2(sc, WI_CNTL) == WI_CNTL_AUX_ENA_STAT)
+ break;
+ /* write the magic key value to unlock aux port */
+ CSR_WRITE_2(sc, WI_PARAM0, WI_AUX_KEY0);
+ CSR_WRITE_2(sc, WI_PARAM1, WI_AUX_KEY1);
+ CSR_WRITE_2(sc, WI_PARAM2, WI_AUX_KEY2);
+ CSR_WRITE_2(sc, WI_CNTL, WI_CNTL_AUX_ENA_CNTL);
+ }
+
+ /* issue read EEPROM command: XXX copied from wi_cmd() */
+ CSR_WRITE_2(sc, WI_PARAM0, 0);
+ CSR_WRITE_2(sc, WI_PARAM1, 0);
+ CSR_WRITE_2(sc, WI_PARAM2, 0);
+ CSR_WRITE_2(sc, WI_COMMAND, WI_CMD_READEE);
+ for (i = 0; i < WI_TIMEOUT; i++) {
+ if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
+ break;
+ DELAY(1);
+ }
+ CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
+
+ CSR_WRITE_2(sc, WI_AUX_PAGE, WI_SBCF_PDIADDR / WI_AUX_PGSZ);
+ CSR_WRITE_2(sc, WI_AUX_OFFSET, WI_SBCF_PDIADDR % WI_AUX_PGSZ);
+ CSR_READ_MULTI_STREAM_2(sc, WI_AUX_DATA,
+ (uint16_t *)ebuf, sizeof(ebuf) / 2);
+ if (GETLE16(ebuf) > sizeof(ebuf))
+ return EIO;
+ if (wi_symbol_write_firm(sc, secsym, seclen, ebuf + 4, GETLE16(ebuf)))
+ return EIO;
+ return 0;
+}
+
+static int
+wi_symbol_write_firm(struct wi_softc *sc, const void *buf, int buflen,
+ const void *ebuf, int ebuflen)
+{
+ const uint8_t *p, *ep, *q, *eq;
+ char *tp;
+ uint32_t addr, id, eid;
+ int i, len, elen, nblk, pdrlen;
+
+ /*
+ * Parse the header of the firmware image.
+ */
+ p = buf;
+ ep = p + buflen;
+ while (p < ep && *p++ != ' '); /* FILE: */
+ while (p < ep && *p++ != ' '); /* filename */
+ while (p < ep && *p++ != ' '); /* type of the firmware */
+ nblk = strtoul(p, &tp, 10);
+ p = tp;
+ pdrlen = strtoul(p + 1, &tp, 10);
+ p = tp;
+ while (p < ep && *p++ != 0x1a); /* skip rest of header */
+
+ /*
+ * Block records: address[4], length[2], data[length];
+ */
+ for (i = 0; i < nblk; i++) {
+ addr = GETLE32(p); p += 4;
+ len = GETLE16(p); p += 2;
+ CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
+ CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
+ CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
+ (const uint16_t *)p, len / 2);
+ p += len;
+ }
+
+ /*
+ * PDR: id[4], address[4], length[4];
+ */
+ for (i = 0; i < pdrlen; ) {
+ id = GETLE32(p); p += 4; i += 4;
+ addr = GETLE32(p); p += 4; i += 4;
+ len = GETLE32(p); p += 4; i += 4;
+ /* replace PDR entry with the values from EEPROM, if any */
+ for (q = ebuf, eq = q + ebuflen; q < eq; q += elen * 2) {
+ elen = GETLE16(q); q += 2;
+ eid = GETLE16(q); q += 2;
+ elen--; /* elen includes eid */
+ if (eid == 0)
+ break;
+ if (eid != id)
+ continue;
+ CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
+ CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
+ CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
+ (const uint16_t *)q, len / 2);
+ break;
+ }
+ }
+ return 0;
+}
+
+static int
+wi_symbol_set_hcr(struct wi_softc *sc, int mode)
+{
+ uint16_t hcr;
+
+ CSR_WRITE_2(sc, WI_COR, WI_COR_RESET);
+ tsleep(sc, PWAIT, "wiinit", 1);
+ hcr = CSR_READ_2(sc, WI_HCR);
+ hcr = (hcr & WI_HCR_4WIRE) | (mode & ~WI_HCR_4WIRE);
+ CSR_WRITE_2(sc, WI_HCR, hcr);
+ tsleep(sc, PWAIT, "wiinit", 1);
+ CSR_WRITE_2(sc, WI_COR, WI_COR_IOMODE);
+ tsleep(sc, PWAIT, "wiinit", 1);
+ return 0;
+}
diff --git a/sys/dev/wi/if_wi_pccard.c b/sys/dev/wi/if_wi_pccard.c
index 51550689abe5..755eb97004bd 100644
--- a/sys/dev/wi/if_wi_pccard.c
+++ b/sys/dev/wi/if_wi_pccard.c
@@ -82,13 +82,6 @@ static const char rcsid[] =
static int wi_pccard_probe(device_t);
static int wi_pccard_attach(device_t);
-#ifdef WI_SYMBOL_FIRMWARE
-/* support to download firmware for symbol CF card */
-static int wi_pcmcia_load_firm(struct wi_softc *, const void *, int, const void *, int);
-static int wi_pcmcia_write_firm(struct wi_softc *, const void *, int, const void *, int);
-static int wi_pcmcia_set_hcr(struct wi_softc *, int);
-#endif
-
#if __FreeBSD_version < 500000
static device_method_t wi_pccard_methods[] = {
/* Device interface */
@@ -235,7 +228,7 @@ wi_pccard_attach(device_t dev)
if (vendor == PCMCIA_VENDOR_SYMBOL &&
product == PCMCIA_PRODUCT_SYMBOL_LA4100) {
#ifdef WI_SYMBOL_FIRMWARE
- if (wi_pcmcia_load_firm(sc,
+ if (wi_symbol_load_firm(sc,
spectrum24t_primsym, sizeof(spectrum24t_primsym),
spectrum24t_secsym, sizeof(spectrum24t_secsym))) {
device_printf(dev, "couldn't load firmware\n");
@@ -249,143 +242,3 @@ wi_pccard_attach(device_t dev)
return (wi_generic_attach(dev));
}
-
-#ifdef WI_SYMBOL_FIRMWARE
-
-/*
- * Special routines to download firmware for Symbol CF card.
- * XXX: This should be modified generic into any PRISM-2 based card.
- */
-
-#define WI_SBCF_PDIADDR 0x3100
-
-/* unaligned load little endian */
-#define GETLE32(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
-#define GETLE16(p) ((p)[0] | ((p)[1]<<8))
-
-static int
-wi_pcmcia_load_firm(struct wi_softc *sc, const void *primsym, int primlen,
- const void *secsym, int seclen)
-{
- uint8_t ebuf[256];
- int i;
-
- /* load primary code and run it */
- wi_pcmcia_set_hcr(sc, WI_HCR_EEHOLD);
- if (wi_pcmcia_write_firm(sc, primsym, primlen, NULL, 0))
- return EIO;
- wi_pcmcia_set_hcr(sc, WI_HCR_RUN);
- for (i = 0; ; i++) {
- if (i == 10)
- return ETIMEDOUT;
- tsleep(sc, PWAIT, "wiinit", 1);
- if (CSR_READ_2(sc, WI_CNTL) == WI_CNTL_AUX_ENA_STAT)
- break;
- /* write the magic key value to unlock aux port */
- CSR_WRITE_2(sc, WI_PARAM0, WI_AUX_KEY0);
- CSR_WRITE_2(sc, WI_PARAM1, WI_AUX_KEY1);
- CSR_WRITE_2(sc, WI_PARAM2, WI_AUX_KEY2);
- CSR_WRITE_2(sc, WI_CNTL, WI_CNTL_AUX_ENA_CNTL);
- }
-
- /* issue read EEPROM command: XXX copied from wi_cmd() */
- CSR_WRITE_2(sc, WI_PARAM0, 0);
- CSR_WRITE_2(sc, WI_PARAM1, 0);
- CSR_WRITE_2(sc, WI_PARAM2, 0);
- CSR_WRITE_2(sc, WI_COMMAND, WI_CMD_READEE);
- for (i = 0; i < WI_TIMEOUT; i++) {
- if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
- break;
- DELAY(1);
- }
- CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
-
- CSR_WRITE_2(sc, WI_AUX_PAGE, WI_SBCF_PDIADDR / WI_AUX_PGSZ);
- CSR_WRITE_2(sc, WI_AUX_OFFSET, WI_SBCF_PDIADDR % WI_AUX_PGSZ);
- CSR_READ_MULTI_STREAM_2(sc, WI_AUX_DATA,
- (uint16_t *)ebuf, sizeof(ebuf) / 2);
- if (GETLE16(ebuf) > sizeof(ebuf))
- return EIO;
- if (wi_pcmcia_write_firm(sc, secsym, seclen, ebuf + 4, GETLE16(ebuf)))
- return EIO;
- return 0;
-}
-
-static int
-wi_pcmcia_write_firm(struct wi_softc *sc, const void *buf, int buflen,
- const void *ebuf, int ebuflen)
-{
- const uint8_t *p, *ep, *q, *eq;
- char *tp;
- uint32_t addr, id, eid;
- int i, len, elen, nblk, pdrlen;
-
- /*
- * Parse the header of the firmware image.
- */
- p = buf;
- ep = p + buflen;
- while (p < ep && *p++ != ' '); /* FILE: */
- while (p < ep && *p++ != ' '); /* filename */
- while (p < ep && *p++ != ' '); /* type of the firmware */
- nblk = strtoul(p, &tp, 10);
- p = tp;
- pdrlen = strtoul(p + 1, &tp, 10);
- p = tp;
- while (p < ep && *p++ != 0x1a); /* skip rest of header */
-
- /*
- * Block records: address[4], length[2], data[length];
- */
- for (i = 0; i < nblk; i++) {
- addr = GETLE32(p); p += 4;
- len = GETLE16(p); p += 2;
- CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
- CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
- CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
- (const uint16_t *)p, len / 2);
- p += len;
- }
-
- /*
- * PDR: id[4], address[4], length[4];
- */
- for (i = 0; i < pdrlen; ) {
- id = GETLE32(p); p += 4; i += 4;
- addr = GETLE32(p); p += 4; i += 4;
- len = GETLE32(p); p += 4; i += 4;
- /* replace PDR entry with the values from EEPROM, if any */
- for (q = ebuf, eq = q + ebuflen; q < eq; q += elen * 2) {
- elen = GETLE16(q); q += 2;
- eid = GETLE16(q); q += 2;
- elen--; /* elen includes eid */
- if (eid == 0)
- break;
- if (eid != id)
- continue;
- CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
- CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
- CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
- (const uint16_t *)q, len / 2);
- break;
- }
- }
- return 0;
-}
-
-static int
-wi_pcmcia_set_hcr(struct wi_softc *sc, int mode)
-{
- uint16_t hcr;
-
- CSR_WRITE_2(sc, WI_COR, WI_COR_RESET);
- tsleep(sc, PWAIT, "wiinit", 1);
- hcr = CSR_READ_2(sc, WI_HCR);
- hcr = (hcr & WI_HCR_4WIRE) | (mode & ~WI_HCR_4WIRE);
- CSR_WRITE_2(sc, WI_HCR, hcr);
- tsleep(sc, PWAIT, "wiinit", 1);
- CSR_WRITE_2(sc, WI_COR, WI_COR_IOMODE);
- tsleep(sc, PWAIT, "wiinit", 1);
- return 0;
-}
-#endif
diff --git a/sys/dev/wi/if_wivar.h b/sys/dev/wi/if_wivar.h
index 3db8acd7a993..e615e0b125f7 100644
--- a/sys/dev/wi/if_wivar.h
+++ b/sys/dev/wi/if_wivar.h
@@ -222,3 +222,4 @@ int wi_alloc(device_t, int);
void wi_free(device_t);
extern devclass_t wi_devclass;
int wi_mgmt_xmit(struct wi_softc *, caddr_t, int);
+int wi_symbol_load_firm(struct wi_softc *, const void *, int, const void *, int);