diff options
author | Marcus Glocker <mglocker@cvs.openbsd.org> | 2007-05-25 05:33:52 +0000 |
---|---|---|
committer | Marcus Glocker <mglocker@cvs.openbsd.org> | 2007-05-25 05:33:52 +0000 |
commit | af616b9cc39f0ab0a299bba062425b861834344b (patch) | |
tree | cb4c83eb332b9ae92e3a2e1da277587c2f577e44 /sys/dev/pcmcia | |
parent | c07b718dd1c51a12f60549c721a117b000eb5833 (diff) |
Initial driver stub for the Marvell 88W8385 PCMCIA (CF) device.
Loads firmware, sends first FW command, establish interrupts.
Diffstat (limited to 'sys/dev/pcmcia')
-rw-r--r-- | sys/dev/pcmcia/files.pcmcia | 6 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_malo.c | 665 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_maloreg.h | 44 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_malovar.h | 74 |
4 files changed, 788 insertions, 1 deletions
diff --git a/sys/dev/pcmcia/files.pcmcia b/sys/dev/pcmcia/files.pcmcia index 7dae5f395f6..5190c0f366b 100644 --- a/sys/dev/pcmcia/files.pcmcia +++ b/sys/dev/pcmcia/files.pcmcia @@ -1,4 +1,4 @@ -# $OpenBSD: files.pcmcia,v 1.40 2006/11/28 12:01:27 miod Exp $ +# $OpenBSD: files.pcmcia,v 1.41 2007/05/25 05:33:51 mglocker Exp $ # $NetBSD: files.pcmcia,v 1.9 1998/06/21 18:45:41 christos Exp $ # # Config.new file and device description for machine-independent PCMCIA code. @@ -73,6 +73,10 @@ file dev/pcmcia/if_cnw.c cnw attach wi at pcmcia with wi_pcmcia file dev/pcmcia/if_wi_pcmcia.c wi_pcmcia +# Marvell 88W8385 +attach malo at pcmcia with malo_pcmcia +file dev/pcmcia/if_malo.c malo_pcmcia + # AMD 79c930-based 802.11 cards (including BayStack 650 FH card). device awi: ether, ifnet attach awi at pcmcia with awi_pcmcia diff --git a/sys/dev/pcmcia/if_malo.c b/sys/dev/pcmcia/if_malo.c new file mode 100644 index 00000000000..95412e56603 --- /dev/null +++ b/sys/dev/pcmcia/if_malo.c @@ -0,0 +1,665 @@ +/* $OpenBSD: if_malo.c,v 1.1 2007/05/25 05:33:51 mglocker Exp $ */ + +/* + * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/timeout.h> +#include <sys/socket.h> +#include <sys/tree.h> +#include <sys/malloc.h> +#include <sys/sockio.h> + +#include <net/if.h> +#include <net/if_media.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/if_ether.h> + +#include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_radiotap.h> + +#include <machine/bus.h> + +#include <dev/pcmcia/pcmciareg.h> +#include <dev/pcmcia/pcmciavar.h> +#include <dev/pcmcia/pcmciadevs.h> + +#include <dev/pcmcia/if_malovar.h> +#include <dev/pcmcia/if_maloreg.h> + +/* + * Driver for the Marvell 88W8385 CF chip. + */ + +#ifdef CMALO_DEBUG +int cmalo_d = 1; +#define DPRINTF(l, x...) do { if ((l) <= cmalo_d) printf(x); } while (0) +#else +#define DPRINTF(l, x...) +#endif + +int malo_pcmcia_match(struct device *, void *, void *); +void malo_pcmcia_attach(struct device *, struct device *, void *); +int malo_pcmcia_detach(struct device *, int); +int malo_pcmcia_activate(struct device *, enum devact); + +void cmalo_attach(void *); +int cmalo_ioctl(struct ifnet *, u_long, caddr_t); +int cmalo_fw_load_helper(struct malo_softc *); +int cmalo_fw_load_main(struct malo_softc *); +int cmalo_init(struct ifnet *); +void cmalo_stop(struct malo_softc *); +int cmalo_detach(void *); +int cmalo_intr(void *); +void cmalo_intr_mask(struct malo_softc *sc, int); + +void cmalo_hexdump(void *, int); +int cmalo_cmd_get_hwspec(struct malo_softc *); +int cmalo_cmd_rsp_hwspec(struct malo_softc *); +int cmalo_cmd_response(struct malo_softc *); + +/* + * PCMCIA bus. + */ +struct malo_pcmcia_softc { + struct malo_softc sc_malo; + + struct pcmcia_function *sc_pf; + struct pcmcia_io_handle sc_pcioh; + int sc_io_window; + void *sc_ih; +}; + +struct cfattach malo_pcmcia_ca = { + sizeof(struct malo_pcmcia_softc), + malo_pcmcia_match, + malo_pcmcia_attach, + malo_pcmcia_detach, + malo_pcmcia_activate +}; + +int +malo_pcmcia_match(struct device *parent, void *match, void *aux) +{ + struct pcmcia_attach_args *pa = aux; + + if (pa->manufacturer == PCMCIA_VENDOR_AMBICOM && + pa->product == PCMCIA_PRODUCT_AMBICOM_WL54CF) + return (1); + + return (0); +} + +void +malo_pcmcia_attach(struct device *parent, struct device *self, void *aux) +{ + struct malo_pcmcia_softc *psc = (struct malo_pcmcia_softc *)self; + struct malo_softc *sc = &psc->sc_malo; + struct pcmcia_attach_args *pa = aux; + struct pcmcia_config_entry *cfe; + const char *intrstr = NULL; + + psc->sc_pf = pa->pf; + cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head); + + /* enable card */ + pcmcia_function_init(psc->sc_pf, cfe); + if (pcmcia_function_enable(psc->sc_pf)) { + printf(": can't enable function!\n"); + return; + } + + /* allocate I/O space */ + if (pcmcia_io_alloc(psc->sc_pf, 0, + cfe->iospace[0].length, cfe->iospace[0].length, &psc->sc_pcioh)) { + printf(": can't allocate i/o space!\n"); + pcmcia_function_disable(psc->sc_pf); + return; + } + + /* map I/O space */ + if (pcmcia_io_map(psc->sc_pf, PCMCIA_WIDTH_IO16, 0, + cfe->iospace[0].length, &psc->sc_pcioh, &psc->sc_io_window)) { + printf(": can't map i/o space!\n"); + pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh); + pcmcia_function_disable(psc->sc_pf); + return; + } + sc->sc_iot = psc->sc_pcioh.iot; + sc->sc_ioh = psc->sc_pcioh.ioh; + + printf(" port 0x%x/%d", psc->sc_pcioh.addr, psc->sc_pcioh.size); + + /* establish interrupt */ + psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, cmalo_intr, sc, + sc->sc_dev.dv_xname); + if (psc->sc_ih == NULL) { + printf(": can't establish interrupt!\n"); + return; + } + intrstr = pcmcia_intr_string(psc->sc_pf, psc->sc_ih); + if (intrstr != NULL) { + if (*intrstr != NULL) + printf(", %s", intrstr); + } + printf("\n"); + + /* attach device */ + if (rootvp == NULL) + mountroothook_establish(cmalo_attach, sc); + else + cmalo_attach(sc); +} + +int +malo_pcmcia_detach(struct device *dev, int flags) +{ + struct malo_pcmcia_softc *psc = (struct malo_pcmcia_softc *)dev; + struct malo_softc *sc = &psc->sc_malo; + int error; + + if ((error = cmalo_detach(sc))) + return (error); + + pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window); + pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh); + + return (0); +} + +int +malo_pcmcia_activate(struct device *dev, enum devact act) +{ + struct malo_pcmcia_softc *psc = (struct malo_pcmcia_softc *)dev; + struct malo_softc *sc = &psc->sc_malo; + struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = &ic->ic_if; + int s; + + s = splnet(); + switch (act) { + case DVACT_ACTIVATE: + pcmcia_function_enable(psc->sc_pf); + psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, + cmalo_intr, sc, sc->sc_dev.dv_xname); + cmalo_init(ifp); + break; + case DVACT_DEACTIVATE: + ifp->if_timer = 0; + if (ifp->if_flags & IFF_RUNNING) + cmalo_stop(sc); + pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih); + pcmcia_function_disable(psc->sc_pf); + break; + } + splx(s); + + return (0); +} + +/* + * Driver. + */ +void +cmalo_attach(void *arg) +{ + struct malo_softc *sc = arg; + struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = &sc->sc_ic.ic_if; + int i; + + /* disable interrupts */ + cmalo_intr_mask(sc, 0); + + /* load firmware */ + if (cmalo_fw_load_helper(sc) != 0) + return; + if (cmalo_fw_load_main(sc) != 0) + return; + + /* enable interrupts */ + cmalo_intr_mask(sc, 1); + + /* allocate command buffer */ + sc->sc_cmd = malloc(CMD_BUFFER_SIZE, M_USBDEV, M_WAITOK); + + /* get hardware specs */ + cmalo_cmd_get_hwspec(sc); + delay(1000); /* XXX */ + + /* setup interface */ + ifp->if_softc = sc; + ifp->if_ioctl = cmalo_ioctl; + ifp->if_init = cmalo_init; + //ifp->if_start = cmalo_start; + //ifp->if_watchdog = cmalo_watchdog; + ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; + strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); + + ic->ic_opmode = IEEE80211_M_STA; + ic->ic_state = IEEE80211_S_INIT; + ic->ic_caps = + IEEE80211_C_IBSS | + IEEE80211_C_WEP; + + ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b; + ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g; + + for (i = 0; i <= 14; i++) { + ic->ic_channels[i].ic_freq = + ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); + ic->ic_channels[i].ic_flags = + IEEE80211_CHAN_B | + IEEE80211_CHAN_G; + } + + /* attach interface */ + if_attach(ifp); + ieee80211_ifattach(ifp); + + ieee80211_media_init(ifp, ieee80211_media_change, + ieee80211_media_status); + + /* second attach line */ + printf("%s: address %s\n", + sc->sc_dev.dv_xname, ether_sprintf(ic->ic_myaddr)); +} + +int +cmalo_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +{ + struct malo_softc *sc = ifp->if_softc; + struct ieee80211com *ic = &sc->sc_ic; + struct ifaddr *ifa; + int s, error = 0; + + s = splnet(); + + switch (cmd) { + case SIOCSIFADDR: + ifa = (struct ifaddr *)data; + ifp->if_flags |= IFF_UP; +#ifdef INET + if (ifa->ifa_addr->sa_family == AF_INET) + arp_ifinit(&ic->ic_ac, ifa); +#endif + /* FALLTHROUGH */ + case SIOCSIFFLAGS: + if ((ifp->if_flags & IFF_UP)) { + if (!(ifp->if_flags & IFF_RUNNING)) + cmalo_init(ifp); + } else { + if ((ifp->if_flags & IFF_RUNNING)) + cmalo_stop(sc); + } + break; + default: + error = EINVAL; + break; + } + + splx(s); + + return (error); +} + +int +cmalo_fw_load_helper(struct malo_softc *sc) +{ + const char *name = "mrv8385-h.fw"; + size_t usize; + uint8_t *ucode, val8; + int offset, error, bsize, i; + + /* verify if the card is ready for firmware download */ + val8 = MALO_READ_1(sc, MALO_REG_SCRATCH); + if (val8 == MALO_VAL_SCRATCH_FW_LOADED) + /* firmware already loaded */ + return (0); + if (val8 != MALO_VAL_SCRATCH_READY) { + /* bad register value */ + printf("%s: device not ready for FW download!\n", + sc->sc_dev.dv_xname); + return (EIO); + } + + /* read helper firmware image */ + if ((error = loadfirmware(name, &ucode, &usize)) != 0) { + printf("%s: can't read microcode %s (error %d)!\n", + sc->sc_dev.dv_xname, name, error); + return (EIO); + } + + /* download the helper firmware */ + for (offset = 0; offset < usize; offset += bsize) { + if (usize - offset >= FW_HELPER_BSIZE) + bsize = FW_HELPER_BSIZE; + else + bsize = usize - offset; + + /* send a block in words and confirm it */ + DPRINTF(2, "%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); + MALO_WRITE_MULTI_2(sc, MALO_REG_CMD_WRITE, (ucode + offset), + bsize / 2); + 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); + + /* poll for an acknowledgement */ + for (i = 0; i < 50; i++) { + if (MALO_READ_1(sc, MALO_REG_CARD_STATUS) == + MALO_VAL_DNLD_OVER) + break; + delay(1000); + } + 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); + 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); + DPRINTF(1, "%s: helper FW downloaded\n", sc->sc_dev.dv_xname); + + return (0); +} + +int +cmalo_fw_load_main(struct malo_softc *sc) +{ + const char *name = "mrv8385-m.fw"; + size_t usize; + uint8_t *ucode; + uint16_t val16; + int offset, error, bsize, retry, i; + + /* read main firmware image */ + if ((error = loadfirmware(name, &ucode, &usize)) != 0) { + printf("%s: can't read microcode %s (error %d)!\n", + sc->sc_dev.dv_xname, name, error); + return (EIO); + } + + /* verify if the helper firmware has been loaded correctly */ + for (i = 0; i < 10; i++) { + if (MALO_READ_1(sc, MALO_REG_RBAL) == FW_HELPER_OK) + break; + delay(1000); + } + 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) { + val16 = MALO_READ_2(sc, MALO_REG_RBAL); + /* + * If the helper firmware serves us an odd integer then + * something went wrong and we retry to download the last + * block until we receive a good integer again, or give up. + */ + if (val16 & 0x0001) { + if (retry > FW_MAIN_MAX_RETRY) { + printf("%s: main FW download failed!\n", + sc->sc_dev.dv_xname); + free(ucode, M_DEVBUF); + return (EIO); + } + retry++; + offset -= bsize; + } else { + retry = 0; + bsize = val16; + } + + /* send a block in words and confirm it */ + DPRINTF(2, "%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); + MALO_WRITE_MULTI_2(sc, MALO_REG_CMD_WRITE, (ucode + offset), + bsize / 2); + 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); + + /* poll for an acknowledgement */ + for (i = 0; i < 5000; i++) { + if (MALO_READ_1(sc, MALO_REG_CARD_STATUS) == + MALO_VAL_DNLD_OVER) + break; + } + 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); + + /* verify if the main firmware has been loaded correctly */ + for (i = 0; i < 50; i++) { + if (MALO_READ_1(sc, MALO_REG_SCRATCH) == + MALO_VAL_SCRATCH_FW_LOADED) + break; + delay(1000); + } + if (i == 50) { + printf("%s: main FW not loaded!\n", sc->sc_dev.dv_xname); + return (EIO); + } + + DPRINTF(1, "%s: main FW loaded successfully\n", sc->sc_dev.dv_xname); + + return (0); +} + +int +cmalo_init(struct ifnet *ifp) +{ + //struct malo_softc *sc = ifp->if_softc; + + return (0); +} + +void +cmalo_stop(struct malo_softc *sc) +{ + +} + +int +cmalo_detach(void *arg) +{ + struct malo_softc *sc = arg; + struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = &ic->ic_if; + + /* free command buffer */ + free(sc->sc_cmd, M_DEVBUF); + + /* detach inferface */ + ieee80211_ifdetach(ifp); + if_detach(ifp); + + return (0); +} + +int +cmalo_intr(void *arg) +{ + struct malo_softc *sc = arg; + uint16_t intr; + + intr = MALO_READ_2(sc, MALO_REG_HOST_INTR_CAUSE); + + DPRINTF(2, "%s: interrupt handler called (intr = 0x%04x)\n", + sc->sc_dev.dv_xname, intr); + + if (intr == 0) { + /* interrupt not for us */ + return (0); + } + if (intr == 0xffff) { + /* card has been detached */ + return (0); + } + + if (intr & MALO_VAL_HOST_INTR_CMD) { + /* command response */ + cmalo_cmd_response(sc); + } + + /* acknowledge interrupt */ + intr &= MALO_VAL_HOST_INTR_MASK_ON; + MALO_WRITE_2(sc, MALO_REG_HOST_INTR_CAUSE, intr); + + return (1); +} + +void +cmalo_intr_mask(struct malo_softc *sc, int enable) +{ + uint16_t val16; + + val16 = MALO_READ_2(sc, MALO_REG_HOST_INTR_MASK); + + DPRINTF(1, "%s: intr mask changed from 0x%04x ", + sc->sc_dev.dv_xname, val16); + + if (enable) + MALO_WRITE_2(sc, MALO_REG_HOST_INTR_MASK, + val16 & ~MALO_VAL_HOST_INTR_MASK_ON); + else + MALO_WRITE_2(sc, MALO_REG_HOST_INTR_MASK, + val16 | MALO_VAL_HOST_INTR_MASK_ON); + + val16 = MALO_READ_2(sc, MALO_REG_HOST_INTR_MASK); + + DPRINTF(1, "to 0x%04x\n", val16); +} + +void +cmalo_hexdump(void *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) { + if (i % 16 == 0) + printf("%s%4i:", i ? "\n" : "", i); + if (i % 4 == 0) + printf(" "); + printf("%02x", (int)*((u_char *)buf + i)); + } + + printf("\n"); +} + +int +cmalo_cmd_get_hwspec(struct malo_softc *sc) +{ + struct malo_cmd_header *hdr = sc->sc_cmd; + struct malo_cmd_body_spec *body; + + bzero(sc->sc_cmd, CMD_BUFFER_SIZE); + + hdr->cmd = htole16(MALO_VAL_CMD_HWSPEC); + hdr->size = htole16(sizeof(*hdr) + sizeof(*body)); + hdr->seqnum = htole16(1); + hdr->result = 0; + body = (struct malo_cmd_body_spec *)(hdr + 1); + + /* 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, hdr->size); + + /* send command request */ + MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, hdr->size); + MALO_WRITE_MULTI_2(sc, MALO_REG_CMD_WRITE, hdr, hdr->size / 2); + 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); + + return (0); +} + +int +cmalo_cmd_rsp_hwspec(struct malo_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct malo_cmd_header *hdr = sc->sc_cmd; + struct malo_cmd_body_spec *body; + int i; + + body = (struct malo_cmd_body_spec *)(hdr + 1); + + /* get our MAC address */ + for (i = 0; i < ETHER_ADDR_LEN; i++) + ic->ic_myaddr[i] = body->macaddr[i]; + + return (0); +} + +int +cmalo_cmd_response(struct malo_softc *sc) +{ + struct malo_cmd_header *hdr = sc->sc_cmd; + int len; + + bzero(sc->sc_cmd, CMD_BUFFER_SIZE); + + /* read the whole command answer */ + len = MALO_READ_2(sc, MALO_REG_CMD_READ_LEN); + MALO_READ_MULTI_2(sc, MALO_REG_CMD_READ, sc->sc_cmd, len / 2); + + cmalo_hexdump(sc->sc_cmd, len); + + /* check for a valid command response */ + if (!(hdr->cmd & MALO_VAL_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; + + /* to which command does the response belong */ + switch (hdr->cmd) { + case MALO_VAL_CMD_HWSPEC: + cmalo_cmd_rsp_hwspec(sc); + break; + default: + printf("%s: got unknown command response (0x%04x)!\n", + sc->sc_dev.dv_xname, hdr->cmd); + break; + } + + return (0); +} diff --git a/sys/dev/pcmcia/if_maloreg.h b/sys/dev/pcmcia/if_maloreg.h new file mode 100644 index 00000000000..b5202ad4563 --- /dev/null +++ b/sys/dev/pcmcia/if_maloreg.h @@ -0,0 +1,44 @@ +/* $OpenBSD: if_maloreg.h,v 1.1 2007/05/25 05:33:51 mglocker Exp $ */ + +/* + * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* I/O registers */ +#define MALO_REG_HOST_STATUS 0x00 +#define MALO_REG_CARD_INTR_CAUSE 0x02 +#define MALO_REG_HOST_INTR_MASK 0x04 +#define MALO_REG_CMD_READ 0x12 +#define MALO_REG_CMD_WRITE_LEN 0x18 +#define MALO_REG_CMD_WRITE 0x1a +#define MALO_REG_CARD_STATUS 0x20 +#define MALO_REG_HOST_INTR_CAUSE 0x22 +#define MALO_REG_RBAL 0x28 +#define MALO_REG_CMD_READ_LEN 0x30 +#define MALO_REG_SCRATCH 0x3f +#define MALO_REG_CARD_INTR_MASK 0x44 + +/* register values */ +#define MALO_VAL_SCRATCH_READY 0x00 +#define MALO_VAL_SCRATCH_FW_LOADED 0x5a +#define MALO_VAL_HOST_INTR_MASK_ON 0x001f +#define MALO_VAL_DNLD_OVER (1 << 2) + +/* interrupt reasons */ +#define MALO_VAL_HOST_INTR_CMD (1 << 3) + +/* FW commands */ +#define MALO_VAL_CMD_RESP 0x8000 +#define MALO_VAL_CMD_HWSPEC 0x0003 diff --git a/sys/dev/pcmcia/if_malovar.h b/sys/dev/pcmcia/if_malovar.h new file mode 100644 index 00000000000..5e79ea41483 --- /dev/null +++ b/sys/dev/pcmcia/if_malovar.h @@ -0,0 +1,74 @@ +/* $OpenBSD: if_malovar.h,v 1.1 2007/05/25 05:33:51 mglocker Exp $ */ + +/* + * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* simplify bus space access */ +#define MALO_READ_1(sc, reg) \ + bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (reg)) +#define MALO_READ_2(sc, reg) \ + bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, (reg)) +#define MALO_READ_MULTI_2(sc, reg, off, size) \ + bus_space_read_multi_2((sc)->sc_iot, (sc)->sc_ioh, (reg), (off), \ + (size)) +#define MALO_WRITE_1(sc, reg, val) \ + bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) +#define MALO_WRITE_2(sc, reg, val) \ + bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) +#define MALO_WRITE_MULTI_2(sc, reg, off, size) \ + bus_space_write_multi_2((sc)->sc_iot, (sc)->sc_ioh, (reg), (off), \ + (size)) + +/* miscellaneous */ +#define FW_HELPER_BSIZE 256 /* helper FW block size */ +#define FW_HELPER_OK 0x10 /* helper FW loaded */ +#define FW_MAIN_MAX_RETRY 20 /* main FW block resend max retry */ +#define CMD_BUFFER_SIZE 256 /* cmd buffer */ + +/* FW command header */ +struct malo_cmd_header { + uint16_t cmd; + uint16_t size; + uint16_t seqnum; + uint16_t result; +}; + +/* FW command bodies */ +struct malo_cmd_body_spec { + uint16_t hw_if_version; + uint16_t hw_version; + uint16_t num_of_wcb; + uint16_t num_of_mcast; + uint8_t macaddr[ETHER_ADDR_LEN]; + uint16_t regioncode; + uint16_t num_of_antenna; + uint32_t fw_version; + uint32_t wcbbase; + uint32_t rxpdrdptr; + uint32_t rxpdwrptr; + uint32_t fw_capinfo; +}; + +struct malo_softc { + struct device sc_dev; + + struct ieee80211com sc_ic; + + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + + void *sc_cmd; +}; |