diff options
author | Marcus Glocker <mglocker@cvs.openbsd.org> | 2007-05-28 13:51:10 +0000 |
---|---|---|
committer | Marcus Glocker <mglocker@cvs.openbsd.org> | 2007-05-28 13:51:10 +0000 |
commit | 8968ee9d819198c892377b9a35f405b81f51bca0 (patch) | |
tree | efa797cde61959e32575d08f329905db075de2d7 /sys/dev/pcmcia | |
parent | 67902ee5c1ad7fb57141c675e37c58c7ddacd0a1 (diff) |
Add a bunch of new firmware commands to configure MAC/PHY/RF, and do so.
Simplify command interface.
Diffstat (limited to 'sys/dev/pcmcia')
-rw-r--r-- | sys/dev/pcmcia/if_malo.c | 339 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_maloreg.h | 27 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_malovar.h | 37 |
3 files changed, 347 insertions, 56 deletions
diff --git a/sys/dev/pcmcia/if_malo.c b/sys/dev/pcmcia/if_malo.c index 4d15d20a6bb..3f1fb570c24 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.7 2007/05/27 15:44:27 mglocker Exp $ */ +/* $OpenBSD: if_malo.c,v 1.8 2007/05/28 13:51:09 mglocker Exp $ */ /* * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> @@ -76,7 +76,15 @@ void cmalo_hexdump(void *, int); int cmalo_cmd_get_hwspec(struct malo_softc *); int cmalo_cmd_rsp_hwspec(struct malo_softc *); int cmalo_cmd_set_reset(struct malo_softc *); +int cmalo_cmd_get_status(struct malo_softc *); +int cmalo_cmd_rsp_status(struct malo_softc *); +int cmalo_cmd_set_radio(struct malo_softc *, uint16_t); int cmalo_cmd_set_channel(struct malo_softc *, uint16_t); +int cmalo_cmd_set_txpower(struct malo_softc *, int16_t); +int cmalo_cmd_set_antenna(struct malo_softc *, uint16_t); +int cmalo_cmd_set_macctrl(struct malo_softc *); +int cmalo_cmd_set_macaddr(struct malo_softc *); +int cmalo_cmd_request(struct malo_softc *, uint16_t, int); int cmalo_cmd_response(struct malo_softc *); /* @@ -515,6 +523,18 @@ cmalo_init(struct ifnet *ifp) /* setup device */ if (cmalo_cmd_set_channel(sc, 1) != 0) return (EIO); + if (cmalo_cmd_set_antenna(sc, 1) != 0) + return (EIO); + if (cmalo_cmd_set_antenna(sc, 2) != 0) + return (EIO); + if (cmalo_cmd_set_radio(sc, 1) != 0) + return (EIO); + if (cmalo_cmd_set_txpower(sc, 15) != 0) + return (EIO); + if (cmalo_cmd_set_macctrl(sc) != 0) + return (EIO); + if (cmalo_cmd_set_macaddr(sc) != 0) + return (EIO); /* device up */ ifp->if_flags |= IFF_RUNNING; @@ -578,10 +598,9 @@ cmalo_intr(void *arg) DPRINTF(2, "%s: interrupt handler called (intr = 0x%04x)\n", sc->sc_dev.dv_xname, intr); - if (intr & MALO_VAL_HOST_INTR_CMD) { + if (intr & MALO_VAL_HOST_INTR_CMD) /* command response */ sc->sc_cmd_running = 0; - } /* acknowledge interrupt */ intr &= MALO_VAL_HOST_INTR_MASK_ON; @@ -636,13 +655,12 @@ cmalo_cmd_get_hwspec(struct malo_softc *sc) { struct malo_cmd_header *hdr = sc->sc_cmd; struct malo_cmd_body_spec *body; - uint16_t psize, *uc; - int i; + uint16_t psize; bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE); psize = sizeof(*hdr) + sizeof(*body); - hdr->cmd = htole16(MALO_VAL_CMD_HWSPEC); + hdr->cmd = htole16(MALO_CMD_HWSPEC); hdr->size = htole16(sizeof(*body)); hdr->seqnum = htole16(1); hdr->result = 0; @@ -651,28 +669,9 @@ cmalo_cmd_get_hwspec(struct malo_softc *sc) /* set all bits for MAC address, otherwise we won't get one back */ memset(body->macaddr, 0xff, ETHER_ADDR_LEN); - cmalo_hexdump(sc->sc_cmd, psize); - - /* send command request */ - MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, psize); - uc = (uint16_t *)hdr; - for (i = 0; i < psize / 2; i++) - MALO_WRITE_2(sc, MALO_REG_CMD_WRITE, htole16(uc[i])); - MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_DNLD_OVER); - MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_DNLD_OVER); - - /* wait for the command response */ - sc->sc_cmd_running = 1; - for (i = 0; i < 10; i++) { - if (sc->sc_cmd_running == 0) - break; - tsleep(sc, 0, "malocmd", 1); - } - if (sc->sc_cmd_running) { - printf("%s: timeout while waiting for cmd response!\n", - sc->sc_dev.dv_xname); + /* process command request */ + if (cmalo_cmd_request(sc, psize, 0) != 0) return (EIO); - } /* process command repsonse */ cmalo_cmd_response(sc); @@ -701,24 +700,90 @@ int cmalo_cmd_set_reset(struct malo_softc *sc) { struct malo_cmd_header *hdr = sc->sc_cmd; - uint16_t psize, *uc; - int i; + uint16_t psize; bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE); psize = sizeof(*hdr); - hdr->cmd = htole16(MALO_VAL_CMD_RESET); + hdr->cmd = htole16(MALO_CMD_RESET); hdr->size = 0; hdr->seqnum = htole16(1); hdr->result = 0; - /* send command request */ - MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, psize); - uc = (uint16_t *)hdr; - for (i = 0; i < psize / 2; i++) - MALO_WRITE_2(sc, MALO_REG_CMD_WRITE, htole16(uc[i])); - MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_DNLD_OVER); - MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_DNLD_OVER); + /* process command request */ + if (cmalo_cmd_request(sc, psize, 1) != 0) + return (EIO); + + return (0); +} + +int +cmalo_cmd_get_status(struct malo_softc *sc) +{ + struct malo_cmd_header *hdr = sc->sc_cmd; + uint16_t psize; + + bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE); + psize = sizeof(*hdr); + + hdr->cmd = htole16(MALO_CMD_STATUS); + hdr->size = 0; + hdr->seqnum = htole16(1); + hdr->result = 0; + + /* process command request */ + if (cmalo_cmd_request(sc, psize, 0) != 0) + return (EIO); + + /* process command repsonse */ + cmalo_cmd_response(sc); + + return (0); +} + +int +cmalo_cmd_rsp_status(struct malo_softc *sc) +{ + struct malo_cmd_header *hdr = sc->sc_cmd; + struct malo_cmd_body_status *body; + + body = (struct malo_cmd_body_status *)(hdr + 1); + + printf("%s: FW status = 0x%04x, MAC status = 0x%04x\n", + body->fw_status, body->mac_status); + + return (0); +} + +int +cmalo_cmd_set_radio(struct malo_softc *sc, uint16_t control) +{ + struct malo_cmd_header *hdr = sc->sc_cmd; + struct malo_cmd_body_radio *body; + uint16_t psize; + + bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE); + psize = sizeof(*hdr) + sizeof(*body); + + hdr->cmd = htole16(MALO_CMD_RADIO); + hdr->size = htole16(sizeof(*body)); + hdr->seqnum = htole16(1); + hdr->result = 0; + body = (struct malo_cmd_body_radio *)(hdr + 1); + + body->action = htole16(1); + + if (control) { + body->control = htole16(MALO_CMD_RADIO_ON); + body->control |= htole16(MALO_CMD_RADIO_AUTO_P); + } + + /* process command request */ + if (cmalo_cmd_request(sc, psize, 0) != 0) + return (EIO); + + /* process command repsonse */ + cmalo_cmd_response(sc); return (0); } @@ -728,13 +793,12 @@ cmalo_cmd_set_channel(struct malo_softc *sc, uint16_t channel) { struct malo_cmd_header *hdr = sc->sc_cmd; struct malo_cmd_body_channel *body; - uint16_t psize, *uc; - int i; + uint16_t psize; bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE); psize = sizeof(*hdr) + sizeof(*body); - hdr->cmd = htole16(MALO_VAL_CMD_CHANNEL); + hdr->cmd = htole16(MALO_CMD_CHANNEL); hdr->size = htole16(sizeof(*body)); hdr->seqnum = htole16(1); hdr->result = 0; @@ -743,16 +807,164 @@ cmalo_cmd_set_channel(struct malo_softc *sc, uint16_t channel) body->action = htole16(1); body->channel = htole16(channel); + /* process command request */ + if (cmalo_cmd_request(sc, psize, 0) != 0) + return (EIO); + + /* process command repsonse */ + cmalo_cmd_response(sc); + + return (0); +} + + +int +cmalo_cmd_set_txpower(struct malo_softc *sc, int16_t txpower) +{ + struct malo_cmd_header *hdr = sc->sc_cmd; + struct malo_cmd_body_txpower *body; + uint16_t psize; + + bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE); + psize = sizeof(*hdr) + sizeof(*body); + + hdr->cmd = htole16(MALO_CMD_TXPOWER); + hdr->size = htole16(sizeof(*body)); + hdr->seqnum = htole16(1); + hdr->result = 0; + body = (struct malo_cmd_body_txpower *)(hdr + 1); + + body->action = htole16(1); + body->txpower = htole16(txpower); + + /* process command request */ + if (cmalo_cmd_request(sc, psize, 0) != 0) + return (EIO); + + /* process command repsonse */ + cmalo_cmd_response(sc); + + return (0); +} + +int +cmalo_cmd_set_antenna(struct malo_softc *sc, uint16_t action) +{ + struct malo_cmd_header *hdr = sc->sc_cmd; + struct malo_cmd_body_antenna *body; + uint16_t psize; + + bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE); + psize = sizeof(*hdr) + sizeof(*body); + + hdr->cmd = htole16(MALO_CMD_ANTENNA); + hdr->size = htole16(sizeof(*body)); + hdr->seqnum = htole16(1); + hdr->result = 0; + body = (struct malo_cmd_body_antenna *)(hdr + 1); + + /* 1 = set RX, 2 = set TX */ + body->action = htole16(action); + + if (action == 1) + /* set RX antenna */ + body->antenna_mode = htole16(0xffff); /* diversity */ + if (action == 2) + /* set TX antenna */ + body->antenna_mode = htole16(2); + + /* process command request */ + if (cmalo_cmd_request(sc, psize, 0) != 0) + return (EIO); + + /* process command repsonse */ + cmalo_cmd_response(sc); + + return (0); +} + +int +cmalo_cmd_set_macctrl(struct malo_softc *sc) +{ + struct malo_cmd_header *hdr = sc->sc_cmd; + struct malo_cmd_body_macctrl *body; + uint16_t psize; + + bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE); + psize = sizeof(*hdr) + sizeof(*body); + + hdr->cmd = htole16(MALO_CMD_MACCTRL); + hdr->size = htole16(sizeof(*body)); + hdr->seqnum = htole16(1); + hdr->result = 0; + body = (struct malo_cmd_body_macctrl *)(hdr + 1); + + body->action = htole16(MALO_CMD_MACCTRL_RX_ON); + body->action |= htole16(MALO_CMD_MACCTRL_TX_ON); + + /* process command request */ + if (cmalo_cmd_request(sc, psize, 0) != 0) + return (EIO); + + /* process command repsonse */ + cmalo_cmd_response(sc); + + return (0); +} + +int +cmalo_cmd_set_macaddr(struct malo_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct malo_cmd_header *hdr = sc->sc_cmd; + struct malo_cmd_body_macaddr *body; + uint16_t psize; + int i; + + bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE); + psize = sizeof(*hdr) + sizeof(*body); + + hdr->cmd = htole16(MALO_CMD_MACADDR); + hdr->size = htole16(sizeof(*body)); + hdr->seqnum = htole16(1); + hdr->result = 0; + body = (struct malo_cmd_body_macaddr *)(hdr + 1); + + body->action = htole16(1); + + for (i = 0; i < ETHER_ADDR_LEN; i++) + body->macaddr[i] = ic->ic_myaddr[i]; + + /* process command request */ + if (cmalo_cmd_request(sc, psize, 0) != 0) + return (EIO); + + /* process command repsonse */ + cmalo_cmd_response(sc); + + return (0); +} + +int +cmalo_cmd_request(struct malo_softc *sc, uint16_t psize, int no_response) +{ + uint16_t *uc; + int i; + cmalo_hexdump(sc->sc_cmd, psize); /* send command request */ MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, psize); - uc = (uint16_t *)hdr; + uc = (uint16_t *)sc->sc_cmd; for (i = 0; i < psize / 2; i++) MALO_WRITE_2(sc, MALO_REG_CMD_WRITE, htole16(uc[i])); MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_DNLD_OVER); MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_DNLD_OVER); + if (no_response) + /* we don't expect a response */ + return (0); + /* wait for the command response */ sc->sc_cmd_running = 1; for (i = 0; i < 10; i++) { @@ -766,9 +978,6 @@ cmalo_cmd_set_channel(struct malo_softc *sc, uint16_t channel) return (EIO); } - /* process command repsonse */ - cmalo_cmd_response(sc); - return (0); } @@ -801,26 +1010,58 @@ cmalo_cmd_response(struct malo_softc *sc) hdr->result = letoh16(hdr->result); /* check for a valid command response */ - if (!(hdr->cmd & MALO_VAL_CMD_RESP)) { + if (!(hdr->cmd & MALO_CMD_RESP)) { printf("%s: got invalid command response (0x%04x)!\n", sc->sc_dev.dv_xname, hdr->cmd); return (EIO); } - hdr->cmd &= ~MALO_VAL_CMD_RESP; + hdr->cmd &= ~MALO_CMD_RESP; /* to which command does the response belong */ switch (hdr->cmd) { - case MALO_VAL_CMD_HWSPEC: + case MALO_CMD_HWSPEC: + DPRINTF(1, "%s: got hwspec cmd response\n", + sc->sc_dev.dv_xname); cmalo_cmd_rsp_hwspec(sc); break; - case MALO_VAL_CMD_RESET: + case MALO_CMD_RESET: /* reset will not send back a response */ break; - case MALO_VAL_CMD_CHANNEL: + case MALO_CMD_STATUS: + DPRINTF(1, "%s: got status cmd response\n", + sc->sc_dev.dv_xname); + cmalo_cmd_rsp_status(sc); + break; + case MALO_CMD_RADIO: + /* do nothing */ + DPRINTF(1, "%s: got radio cmd response\n", + sc->sc_dev.dv_xname); + break; + case MALO_CMD_CHANNEL: /* do nothing */ DPRINTF(1, "%s: got channel cmd response\n", sc->sc_dev.dv_xname); break; + case MALO_CMD_TXPOWER: + /* do nothing */ + DPRINTF(1, "%s: got txpower cmd response\n", + sc->sc_dev.dv_xname); + break; + case MALO_CMD_ANTENNA: + /* do nothing */ + DPRINTF(1, "%s: got antenna cmd response\n", + sc->sc_dev.dv_xname); + break; + case MALO_CMD_MACCTRL: + /* do nothing */ + DPRINTF(1, "%s: got macctrl cmd response\n", + sc->sc_dev.dv_xname); + break; + case MALO_CMD_MACADDR: + /* do nothing */ + DPRINTF(1, "%s: got macaddr cmd response\n", + sc->sc_dev.dv_xname); + break; default: printf("%s: got unknown cmd response (0x%04x)!\n", sc->sc_dev.dv_xname, hdr->cmd); diff --git a/sys/dev/pcmcia/if_maloreg.h b/sys/dev/pcmcia/if_maloreg.h index 495f3eddbcb..eac3cdfa99b 100644 --- a/sys/dev/pcmcia/if_maloreg.h +++ b/sys/dev/pcmcia/if_maloreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_maloreg.h,v 1.3 2007/05/26 11:11:54 mglocker Exp $ */ +/* $OpenBSD: if_maloreg.h,v 1.4 2007/05/28 13:51:09 mglocker Exp $ */ /* * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> @@ -30,7 +30,7 @@ #define MALO_REG_SCRATCH 0x3f #define MALO_REG_CARD_INTR_MASK 0x44 -/* register values */ +/* I/O register values */ #define MALO_VAL_SCRATCH_READY 0x00 #define MALO_VAL_SCRATCH_FW_LOADED 0x5a #define MALO_VAL_HOST_INTR_MASK_ON 0x001f @@ -41,7 +41,22 @@ #define MALO_VAL_HOST_INTR_CMD (1 << 3) /* FW commands */ -#define MALO_VAL_CMD_RESP 0x8000 -#define MALO_VAL_CMD_HWSPEC 0x0003 -#define MALO_VAL_CMD_RESET 0x0005 -#define MALO_VAL_CMD_CHANNEL 0x001d +#define MALO_CMD_RESP 0x8000 +#define MALO_CMD_HWSPEC 0x0003 +#define MALO_CMD_RESET 0x0005 +#define MALO_CMD_STATUS 0x000a +#define MALO_CMD_RADIO 0x001c +#define MALO_CMD_CHANNEL 0x001d +#define MALO_CMD_TXPOWER 0x001e +#define MALO_CMD_ANTENNA 0x0020 +#define MALO_CMD_MACCTRL 0x0028 +#define MALO_CMD_MACADDR 0x004d + +/* FW command values */ +#define MALO_CMD_RADIO_OFF 0x0000 +#define MALO_CMD_RADIO_ON 0x0001 +#define MALO_CMD_RADIO_LONG_P 0x0000 +#define MALO_CMD_RADIO_SHORT_P 0x0002 +#define MALO_CMD_RADIO_AUTO_P 0x0004 +#define MALO_CMD_MACCTRL_RX_ON 0x0001 +#define MALO_CMD_MACCTRL_TX_ON 0x0002 diff --git a/sys/dev/pcmcia/if_malovar.h b/sys/dev/pcmcia/if_malovar.h index 59f18c1382b..2235e3edec0 100644 --- a/sys/dev/pcmcia/if_malovar.h +++ b/sys/dev/pcmcia/if_malovar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_malovar.h,v 1.4 2007/05/26 21:16:03 mglocker Exp $ */ +/* $OpenBSD: if_malovar.h,v 1.5 2007/05/28 13:51:09 mglocker Exp $ */ /* * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> @@ -66,6 +66,21 @@ struct malo_cmd_body_spec { uint32_t fw_capinfo; } __packed; +struct malo_cmd_body_status { + uint16_t fw_status; + uint16_t mac_status; + uint16_t rf_status; + uint16_t current_channel; + uint8_t ap_mac[ETHER_ADDR_LEN]; + uint16_t reserved; + uint32_t max_linkspeed; +} __packed; + +struct malo_cmd_body_radio { + uint16_t action; + uint16_t control; +} __packed; + struct malo_cmd_body_channel { uint16_t action; uint16_t channel; @@ -74,6 +89,26 @@ struct malo_cmd_body_channel { uint8_t channel_list[32]; } __packed; +struct malo_cmd_body_txpower { + uint16_t action; + int16_t txpower; +} __packed; + +struct malo_cmd_body_antenna { + uint16_t action; + uint16_t antenna_mode; +} __packed; + +struct malo_cmd_body_macctrl { + uint16_t action; + uint16_t reserved; +} __packed; + +struct malo_cmd_body_macaddr { + uint16_t action; + uint8_t macaddr[ETHER_ADDR_LEN]; +} __packed; + struct malo_softc { struct device sc_dev; struct ieee80211com sc_ic; |