Annotation of sys/dev/ic/malo.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: malo.c,v 1.72 2007/07/18 18:10:31 damien Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
! 5: * Copyright (c) 2006 Marcus Glocker <mglocker@openbsd.org>
! 6: *
! 7: * Permission to use, copy, modify, and distribute this software for any
! 8: * purpose with or without fee is hereby granted, provided that the above
! 9: * copyright notice and this permission notice appear in all copies.
! 10: *
! 11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 15: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 16: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 17: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 18: */
! 19:
! 20: #include "bpfilter.h"
! 21:
! 22: #include <sys/cdefs.h>
! 23: #include <sys/param.h>
! 24: #include <sys/types.h>
! 25:
! 26: #include <sys/device.h>
! 27: #include <sys/kernel.h>
! 28: #include <sys/malloc.h>
! 29: #include <sys/mbuf.h>
! 30: #include <sys/proc.h>
! 31: #include <sys/socket.h>
! 32: #include <sys/sockio.h>
! 33: #include <sys/systm.h>
! 34:
! 35: #include <machine/bus.h>
! 36: #include <machine/endian.h>
! 37: #include <machine/intr.h>
! 38:
! 39: #include <net/if.h>
! 40: #include <net/if_media.h>
! 41:
! 42: #if NBPFILTER > 0
! 43: #include <net/bpf.h>
! 44: #endif
! 45:
! 46: #include <netinet/in.h>
! 47: #include <netinet/in_systm.h>
! 48: #include <netinet/if_ether.h>
! 49:
! 50: #include <net80211/ieee80211_var.h>
! 51: #include <net80211/ieee80211_radiotap.h>
! 52:
! 53: #include <dev/ic/malo.h>
! 54:
! 55: #ifdef MALO_DEBUG
! 56: #define DPRINTF(x) do { if (malo_debug > 0) printf x; } while (0)
! 57: #define DPRINTFN(n, x) do { if (malo_debug >= (n)) printf x; } while (0)
! 58: int malo_debug = 1;
! 59: #else
! 60: #define DPRINTF(x)
! 61: #define DPRINTFN(n, x)
! 62: #endif
! 63:
! 64: /* internal structures and defines */
! 65: struct malo_node {
! 66: struct ieee80211_node ni;
! 67: };
! 68:
! 69: struct malo_rx_data {
! 70: bus_dmamap_t map;
! 71: struct mbuf *m;
! 72: };
! 73:
! 74: struct malo_tx_data {
! 75: bus_dmamap_t map;
! 76: struct mbuf *m;
! 77: uint32_t softstat;
! 78: struct ieee80211_node *ni;
! 79: };
! 80:
! 81: /* RX descriptor used by HW */
! 82: struct malo_rx_desc {
! 83: uint8_t rxctrl;
! 84: uint8_t rssi;
! 85: uint8_t status;
! 86: uint8_t channel;
! 87: uint16_t len;
! 88: uint8_t reserved1; /* actually unused */
! 89: uint8_t datarate;
! 90: uint32_t physdata; /* DMA address of data */
! 91: uint32_t physnext; /* DMA address of next control block */
! 92: uint16_t qosctrl;
! 93: uint16_t reserved2;
! 94: } __packed;
! 95:
! 96: /* TX descriptor used by HW */
! 97: struct malo_tx_desc {
! 98: uint32_t status;
! 99: uint8_t datarate;
! 100: uint8_t txpriority;
! 101: uint16_t qosctrl;
! 102: uint32_t physdata; /* DMA address of data */
! 103: uint16_t len;
! 104: uint8_t destaddr[6];
! 105: uint32_t physnext; /* DMA address of next control block */
! 106: uint32_t reserved1; /* SAP packet info ??? */
! 107: uint32_t reserved2;
! 108: } __packed;
! 109:
! 110: #define MALO_RX_RING_COUNT 256
! 111: #define MALO_TX_RING_COUNT 256
! 112: #define MALO_MAX_SCATTER 8 /* XXX unknown, wild guess */
! 113:
! 114: /*
! 115: * Firmware commands
! 116: */
! 117: #define MALO_CMD_GET_HW_SPEC 0x0003
! 118: #define MALO_CMD_SET_WEPKEY 0x0013
! 119: #define MALO_CMD_SET_RADIO 0x001c
! 120: #define MALO_CMD_SET_AID 0x010d
! 121: #define MALO_CMD_SET_TXPOWER 0x001e
! 122: #define MALO_CMD_SET_ANTENNA 0x0020
! 123: #define MALO_CMD_SET_PRESCAN 0x0107
! 124: #define MALO_CMD_SET_POSTSCAN 0x0108
! 125: #define MALO_CMD_SET_RATE 0x0110
! 126: #define MALO_CMD_SET_CHANNEL 0x010a
! 127: #define MALO_CMD_SET_RTS 0x0113
! 128: #define MALO_CMD_SET_SLOT 0x0114
! 129: #define MALO_CMD_RESPONSE 0x8000
! 130:
! 131: #define MALO_CMD_RESULT_OK 0x0000 /* everything is fine */
! 132: #define MALO_CMD_RESULT_ERROR 0x0001 /* general error */
! 133: #define MALO_CMD_RESULT_NOSUPPORT 0x0002 /* command not valid */
! 134: #define MALO_CMD_RESULT_PENDING 0x0003 /* will be processed */
! 135: #define MALO_CMD_RESULT_BUSY 0x0004 /* command ignored */
! 136: #define MALO_CMD_RESULT_PARTIALDATA 0x0005 /* buffer too small */
! 137:
! 138: struct malo_cmdheader {
! 139: uint16_t cmd;
! 140: uint16_t size; /* size of the command, incl. header */
! 141: uint16_t seqnum; /* seems not to matter that much */
! 142: uint16_t result; /* set to 0 on request */
! 143: /* following the data payload, up to 256 bytes */
! 144: };
! 145:
! 146: struct malo_hw_spec {
! 147: uint16_t HwVersion;
! 148: uint16_t NumOfWCB;
! 149: uint16_t NumOfMCastAdr;
! 150: uint8_t PermanentAddress[6];
! 151: uint16_t RegionCode;
! 152: uint16_t NumberOfAntenna;
! 153: uint32_t FWReleaseNumber;
! 154: uint32_t WcbBase0;
! 155: uint32_t RxPdWrPtr;
! 156: uint32_t RxPdRdPtr;
! 157: uint32_t CookiePtr;
! 158: uint32_t WcbBase1;
! 159: uint32_t WcbBase2;
! 160: uint32_t WcbBase3;
! 161: } __packed;
! 162:
! 163: struct malo_cmd_wepkey {
! 164: uint16_t action;
! 165: uint8_t len;
! 166: uint8_t flags;
! 167: uint16_t index;
! 168: uint8_t value[IEEE80211_KEYBUF_SIZE];
! 169: uint8_t txmickey[IEEE80211_WEP_MICLEN];
! 170: uint8_t rxmickey[IEEE80211_WEP_MICLEN];
! 171: uint64_t rxseqctr;
! 172: uint64_t txseqctr;
! 173: } __packed;
! 174:
! 175: struct malo_cmd_radio {
! 176: uint16_t action;
! 177: uint16_t preamble_mode;
! 178: uint16_t enable;
! 179: } __packed;
! 180:
! 181: struct malo_cmd_aid {
! 182: uint16_t associd;
! 183: uint8_t macaddr[6];
! 184: uint32_t gprotection;
! 185: uint8_t aprates[14];
! 186: } __packed;
! 187:
! 188: struct malo_cmd_txpower {
! 189: uint16_t action;
! 190: uint16_t supportpowerlvl;
! 191: uint16_t currentpowerlvl;
! 192: uint16_t reserved;
! 193: uint16_t powerlvllist[8];
! 194: } __packed;
! 195:
! 196: struct malo_cmd_antenna {
! 197: uint16_t action;
! 198: uint16_t mode;
! 199: } __packed;
! 200:
! 201: struct malo_cmd_postscan {
! 202: uint32_t isibss;
! 203: uint8_t bssid[6];
! 204: } __packed;
! 205:
! 206: struct malo_cmd_channel {
! 207: uint16_t action;
! 208: uint8_t channel;
! 209: } __packed;
! 210:
! 211: struct malo_cmd_rate {
! 212: uint8_t dataratetype;
! 213: uint8_t rateindex;
! 214: uint8_t aprates[14];
! 215: } __packed;
! 216:
! 217: struct malo_cmd_slot {
! 218: uint16_t action;
! 219: uint8_t slot;
! 220: } __packed;
! 221:
! 222: #define malo_mem_write4(sc, off, x) \
! 223: bus_space_write_4((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, (off), (x))
! 224: #define malo_mem_write2(sc, off, x) \
! 225: bus_space_write_2((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, (off), (x))
! 226: #define malo_mem_write1(sc, off, x) \
! 227: bus_space_write_1((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, (off), (x))
! 228:
! 229: #define malo_mem_read4(sc, off) \
! 230: bus_space_read_4((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, (off))
! 231: #define malo_mem_read1(sc, off) \
! 232: bus_space_read_1((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, (off))
! 233:
! 234: #define malo_ctl_write4(sc, off, x) \
! 235: bus_space_write_4((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off), (x))
! 236: #define malo_ctl_read4(sc, off) \
! 237: bus_space_read_4((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off))
! 238: #define malo_ctl_read1(sc, off) \
! 239: bus_space_read_1((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off))
! 240:
! 241: #define malo_ctl_barrier(sc, t) \
! 242: bus_space_barrier((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, 0x0c00, 0xff, (t))
! 243:
! 244: struct cfdriver malo_cd = {
! 245: NULL, "malo", DV_IFNET
! 246: };
! 247:
! 248: int malo_alloc_cmd(struct malo_softc *sc);
! 249: void malo_free_cmd(struct malo_softc *sc);
! 250: void malo_send_cmd(struct malo_softc *sc, bus_addr_t addr);
! 251: int malo_send_cmd_dma(struct malo_softc *sc, bus_addr_t addr);
! 252: int malo_alloc_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring,
! 253: int count);
! 254: void malo_reset_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring);
! 255: void malo_free_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring);
! 256: int malo_alloc_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring,
! 257: int count);
! 258: void malo_reset_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring);
! 259: void malo_free_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring);
! 260: int malo_init(struct ifnet *ifp);
! 261: int malo_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
! 262: void malo_start(struct ifnet *ifp);
! 263: void malo_stop(struct malo_softc *sc);
! 264: void malo_watchdog(struct ifnet *ifp);
! 265: int malo_newstate(struct ieee80211com *ic, enum ieee80211_state nstate,
! 266: int arg);
! 267: void malo_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni,
! 268: int isnew);
! 269: struct ieee80211_node *
! 270: malo_node_alloc(struct ieee80211com *ic);
! 271: int malo_media_change(struct ifnet *ifp);
! 272: void malo_media_status(struct ifnet *ifp, struct ifmediareq *imr);
! 273: int malo_chip2rate(int chip_rate);
! 274: int malo_fix2rate(int fix_rate);
! 275: void malo_next_scan(void *arg);
! 276: void malo_tx_intr(struct malo_softc *sc);
! 277: int malo_tx_mgt(struct malo_softc *sc, struct mbuf *m0,
! 278: struct ieee80211_node *ni);
! 279: int malo_tx_data(struct malo_softc *sc, struct mbuf *m0,
! 280: struct ieee80211_node *ni);
! 281: void malo_tx_setup_desc(struct malo_softc *sc, struct malo_tx_desc *desc,
! 282: int len, int rate, const bus_dma_segment_t *segs, int nsegs);
! 283: void malo_rx_intr(struct malo_softc *sc);
! 284: int malo_load_bootimg(struct malo_softc *sc);
! 285: int malo_load_firmware(struct malo_softc *sc);
! 286:
! 287: int malo_set_wepkey(struct malo_softc *sc);
! 288: int malo_set_slot(struct malo_softc *sc);
! 289: void malo_update_slot(struct ieee80211com *ic);
! 290: #ifdef MALO_DEBUG
! 291: void malo_hexdump(void *buf, int len);
! 292: #endif
! 293: static char *
! 294: malo_cmd_string(uint16_t cmd);
! 295: static char *
! 296: malo_cmd_string_result(uint16_t result);
! 297: int malo_cmd_get_spec(struct malo_softc *sc);
! 298: int malo_cmd_set_wepkey(struct malo_softc *sc, struct ieee80211_key *k,
! 299: uint16_t k_index);
! 300: int malo_cmd_set_prescan(struct malo_softc *sc);
! 301: int malo_cmd_set_postscan(struct malo_softc *sc, uint8_t *macaddr,
! 302: uint8_t ibsson);
! 303: int malo_cmd_set_channel(struct malo_softc *sc, uint8_t channel);
! 304: int malo_cmd_set_antenna(struct malo_softc *sc, uint16_t antenna_type);
! 305: int malo_cmd_set_radio(struct malo_softc *sc, uint16_t mode,
! 306: uint16_t preamble);
! 307: int malo_cmd_set_aid(struct malo_softc *sc, uint8_t *bssid,
! 308: uint16_t associd);
! 309: int malo_cmd_set_txpower(struct malo_softc *sc, unsigned int powerlevel);
! 310: int malo_cmd_set_rts(struct malo_softc *sc, uint32_t threshold);
! 311: int malo_cmd_set_slot(struct malo_softc *sc, uint8_t slot);
! 312: int malo_cmd_set_rate(struct malo_softc *sc, uint8_t rate);
! 313:
! 314: int
! 315: malo_intr(void *arg)
! 316: {
! 317: struct malo_softc *sc = arg;
! 318: uint32_t status;
! 319:
! 320: status = malo_ctl_read4(sc, 0x0c30);
! 321: if (status == 0xffffffff || status == 0)
! 322: /* not for us */
! 323: return (0);
! 324:
! 325: if (status & 0x1)
! 326: malo_tx_intr(sc);
! 327: if (status & 0x2)
! 328: malo_rx_intr(sc);
! 329: if (status & 0x4) {
! 330: struct malo_cmdheader *hdr = sc->sc_cmd_mem;
! 331:
! 332: if (letoh16(hdr->result) != MALO_CMD_RESULT_OK) {
! 333: printf("%s: firmware cmd %s failed with %s\n",
! 334: sc->sc_dev.dv_xname,
! 335: malo_cmd_string(hdr->cmd),
! 336: malo_cmd_string_result(hdr->result));
! 337: }
! 338: #ifdef MALO_DEBUG
! 339: printf("%s: cmd answer for %s=%s\n",
! 340: sc->sc_dev.dv_xname,
! 341: malo_cmd_string(hdr->cmd),
! 342: malo_cmd_string_result(hdr->result));
! 343: if (malo_debug > 2)
! 344: malo_hexdump(hdr, letoh16(hdr->size));
! 345: #endif
! 346: }
! 347:
! 348: if (status & ~0x7)
! 349: DPRINTF(("%s: unkown interrupt %x\n", sc->sc_dev.dv_xname,
! 350: status));
! 351:
! 352: /* just ack the interrupt */
! 353: malo_ctl_write4(sc, 0x0c30, 0);
! 354:
! 355: return (1);
! 356: }
! 357:
! 358: int
! 359: malo_attach(struct malo_softc *sc)
! 360: {
! 361: struct ieee80211com *ic = &sc->sc_ic;
! 362: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 363: int i;
! 364:
! 365: /* initialize channel scanning timer */
! 366: timeout_set(&sc->sc_scan_to, malo_next_scan, sc);
! 367:
! 368: /* allocate DMA structures */
! 369: malo_alloc_cmd(sc);
! 370: malo_alloc_rx_ring(sc, &sc->sc_rxring, MALO_RX_RING_COUNT);
! 371: malo_alloc_tx_ring(sc, &sc->sc_txring, MALO_TX_RING_COUNT);
! 372:
! 373: /* setup interface */
! 374: ifp->if_softc = sc;
! 375: ifp->if_init = malo_init;
! 376: ifp->if_ioctl = malo_ioctl;
! 377: ifp->if_start = malo_start;
! 378: ifp->if_watchdog = malo_watchdog;
! 379: ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
! 380: strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
! 381: IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
! 382: IFQ_SET_READY(&ifp->if_snd);
! 383:
! 384: /* set supported rates */
! 385: ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
! 386: ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
! 387: sc->sc_last_txrate = -1;
! 388:
! 389: /* set channels */
! 390: for (i = 1; i <= 14; i++) {
! 391: ic->ic_channels[i].ic_freq =
! 392: ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
! 393: ic->ic_channels[i].ic_flags =
! 394: IEEE80211_CHAN_PUREG |
! 395: IEEE80211_CHAN_B |
! 396: IEEE80211_CHAN_G;
! 397: }
! 398:
! 399: /* set the rest */
! 400: ic->ic_caps =
! 401: IEEE80211_C_IBSS |
! 402: IEEE80211_C_MONITOR |
! 403: IEEE80211_C_SHPREAMBLE |
! 404: IEEE80211_C_SHSLOT |
! 405: IEEE80211_C_WEP;
! 406: ic->ic_opmode = IEEE80211_M_STA;
! 407: ic->ic_state = IEEE80211_S_INIT;
! 408: ic->ic_max_rssi = 75;
! 409: for (i = 0; i < 6; i++)
! 410: ic->ic_myaddr[i] = malo_ctl_read1(sc, 0xa528 + i);
! 411:
! 412: /* show our mac address */
! 413: printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
! 414:
! 415: /* attach interface */
! 416: if_attach(ifp);
! 417: ieee80211_ifattach(ifp);
! 418:
! 419: /* post attach vector functions */
! 420: sc->sc_newstate = ic->ic_newstate;
! 421: ic->ic_newstate = malo_newstate;
! 422: ic->ic_newassoc = malo_newassoc;
! 423: ic->ic_node_alloc = malo_node_alloc;
! 424: ic->ic_updateslot = malo_update_slot;
! 425:
! 426: ieee80211_media_init(ifp, malo_media_change, malo_media_status);
! 427:
! 428: #if NBPFILTER > 0
! 429: bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
! 430: sizeof(struct ieee80211_frame) + 64);
! 431:
! 432: sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
! 433: sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
! 434: sc->sc_rxtap.wr_ihdr.it_present = htole32(MALO_RX_RADIOTAP_PRESENT);
! 435:
! 436: sc->sc_txtap_len = sizeof(sc->sc_txtapu);
! 437: sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
! 438: sc->sc_txtap.wt_ihdr.it_present = htole32(MALO_TX_RADIOTAP_PRESENT);
! 439: #endif
! 440:
! 441: return (0);
! 442: }
! 443:
! 444: int
! 445: malo_detach(void *arg)
! 446: {
! 447: struct malo_softc *sc = arg;
! 448: struct ieee80211com *ic = &sc->sc_ic;
! 449: struct ifnet *ifp = &ic->ic_if;
! 450:
! 451: /* remove channel scanning timer */
! 452: timeout_del(&sc->sc_scan_to);
! 453:
! 454: malo_stop(sc);
! 455: ieee80211_ifdetach(ifp);
! 456: if_detach(ifp);
! 457: malo_free_cmd(sc);
! 458: malo_free_rx_ring(sc, &sc->sc_rxring);
! 459: malo_free_tx_ring(sc, &sc->sc_txring);
! 460:
! 461: return (0);
! 462: }
! 463:
! 464: int
! 465: malo_alloc_cmd(struct malo_softc *sc)
! 466: {
! 467: int error, nsegs;
! 468:
! 469: error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1,
! 470: PAGE_SIZE, 0, BUS_DMA_ALLOCNOW, &sc->sc_cmd_dmam);
! 471: if (error != 0) {
! 472: printf("%s: can not create DMA tag\n", sc->sc_dev.dv_xname);
! 473: return (-1);
! 474: }
! 475:
! 476: error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE,
! 477: 0, &sc->sc_cmd_dmas, 1, &nsegs, BUS_DMA_WAITOK);
! 478: if (error != 0) {
! 479: printf("%s: error alloc dma memory\n", sc->sc_dev.dv_xname);
! 480: return (-1);
! 481: }
! 482:
! 483: error = bus_dmamem_map(sc->sc_dmat, &sc->sc_cmd_dmas, nsegs,
! 484: PAGE_SIZE, (caddr_t *)&sc->sc_cmd_mem, BUS_DMA_WAITOK);
! 485: if (error != 0) {
! 486: printf("%s: error map dma memory\n", sc->sc_dev.dv_xname);
! 487: return (-1);
! 488: }
! 489:
! 490: error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmd_dmam,
! 491: sc->sc_cmd_mem, PAGE_SIZE, NULL, BUS_DMA_NOWAIT);
! 492: if (error != 0) {
! 493: printf("%s: error load dma memory\n", sc->sc_dev.dv_xname);
! 494: bus_dmamem_free(sc->sc_dmat, &sc->sc_cmd_dmas, nsegs);
! 495: return (-1);
! 496: }
! 497:
! 498: sc->sc_cookie = sc->sc_cmd_mem;
! 499: *sc->sc_cookie = htole32(0xaa55aa55);
! 500: sc->sc_cmd_mem = sc->sc_cmd_mem + sizeof(uint32_t);
! 501: sc->sc_cookie_dmaaddr = sc->sc_cmd_dmam->dm_segs[0].ds_addr;
! 502: sc->sc_cmd_dmaaddr = sc->sc_cmd_dmam->dm_segs[0].ds_addr +
! 503: sizeof(uint32_t);
! 504:
! 505: return (0);
! 506: }
! 507:
! 508: void
! 509: malo_free_cmd(struct malo_softc *sc)
! 510: {
! 511: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
! 512: BUS_DMASYNC_POSTWRITE);
! 513: bus_dmamap_unload(sc->sc_dmat, sc->sc_cmd_dmam);
! 514: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_cookie, PAGE_SIZE);
! 515: bus_dmamem_free(sc->sc_dmat, &sc->sc_cmd_dmas, 1);
! 516: }
! 517:
! 518: void
! 519: malo_send_cmd(struct malo_softc *sc, bus_addr_t addr)
! 520: {
! 521: malo_ctl_write4(sc, 0x0c10, (uint32_t)addr);
! 522: malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
! 523: malo_ctl_write4(sc, 0x0c18, 2); /* CPU_TRANSFER_CMD */
! 524: malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
! 525: }
! 526:
! 527: int
! 528: malo_send_cmd_dma(struct malo_softc *sc, bus_addr_t addr)
! 529: {
! 530: int i;
! 531: struct malo_cmdheader *hdr = sc->sc_cmd_mem;
! 532:
! 533: malo_ctl_write4(sc, 0x0c10, (uint32_t)addr);
! 534: malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
! 535: malo_ctl_write4(sc, 0x0c18, 2); /* CPU_TRANSFER_CMD */
! 536: malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
! 537:
! 538: for (i = 0; i < 10; i++) {
! 539: delay(100);
! 540: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
! 541: BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
! 542: if (hdr->cmd & htole16(0x8000))
! 543: break;
! 544: }
! 545:
! 546: if (i == 10)
! 547: return (ETIMEDOUT);
! 548:
! 549: return (0);
! 550: }
! 551:
! 552: int
! 553: malo_alloc_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring, int count)
! 554: {
! 555: struct malo_rx_desc *desc;
! 556: struct malo_rx_data *data;
! 557: int i, nsegs, error;
! 558:
! 559: ring->count = count;
! 560: ring->cur = ring->next = 0;
! 561:
! 562: error = bus_dmamap_create(sc->sc_dmat,
! 563: count * sizeof(struct malo_rx_desc), 1,
! 564: count * sizeof(struct malo_rx_desc), 0,
! 565: BUS_DMA_NOWAIT, &ring->map);
! 566: if (error != 0) {
! 567: printf("%s: could not create desc DMA map\n",
! 568: sc->sc_dev.dv_xname);
! 569: goto fail;
! 570: }
! 571:
! 572: error = bus_dmamem_alloc(sc->sc_dmat,
! 573: count * sizeof(struct malo_rx_desc),
! 574: PAGE_SIZE, 0, &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT);
! 575: if (error != 0) {
! 576: printf("%s: could not allocate DMA memory\n",
! 577: sc->sc_dev.dv_xname);
! 578: goto fail;
! 579: }
! 580:
! 581: error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs,
! 582: count * sizeof(struct malo_rx_desc), (caddr_t *)&ring->desc,
! 583: BUS_DMA_NOWAIT);
! 584: if (error != 0) {
! 585: printf("%s: could not map desc DMA memory\n",
! 586: sc->sc_dev.dv_xname);
! 587: goto fail;
! 588: }
! 589:
! 590: error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->desc,
! 591: count * sizeof(struct malo_rx_desc), NULL, BUS_DMA_NOWAIT);
! 592: if (error != 0) {
! 593: printf("%s: could not load desc DMA map\n",
! 594: sc->sc_dev.dv_xname);
! 595: goto fail;
! 596: }
! 597:
! 598: bzero(ring->desc, count * sizeof(struct malo_rx_desc));
! 599: ring->physaddr = ring->map->dm_segs->ds_addr;
! 600:
! 601: ring->data = malloc(count * sizeof (struct malo_rx_data), M_DEVBUF,
! 602: M_NOWAIT);
! 603: if (ring->data == NULL) {
! 604: printf("%s: could not allocate soft data\n",
! 605: sc->sc_dev.dv_xname);
! 606: error = ENOMEM;
! 607: goto fail;
! 608: }
! 609:
! 610: /*
! 611: * Pre-allocate Rx buffers and populate Rx ring.
! 612: */
! 613: bzero(ring->data, count * sizeof (struct malo_rx_data));
! 614: for (i = 0; i < count; i++) {
! 615: desc = &ring->desc[i];
! 616: data = &ring->data[i];
! 617:
! 618: error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
! 619: 0, BUS_DMA_NOWAIT, &data->map);
! 620: if (error != 0) {
! 621: printf("%s: could not create DMA map\n",
! 622: sc->sc_dev.dv_xname);
! 623: goto fail;
! 624: }
! 625:
! 626: MGETHDR(data->m, M_DONTWAIT, MT_DATA);
! 627: if (data->m == NULL) {
! 628: printf("%s: could not allocate rx mbuf\n",
! 629: sc->sc_dev.dv_xname);
! 630: error = ENOMEM;
! 631: goto fail;
! 632: }
! 633:
! 634: MCLGET(data->m, M_DONTWAIT);
! 635: if (!(data->m->m_flags & M_EXT)) {
! 636: printf("%s: could not allocate rx mbuf cluster\n",
! 637: sc->sc_dev.dv_xname);
! 638: error = ENOMEM;
! 639: goto fail;
! 640: }
! 641:
! 642: error = bus_dmamap_load(sc->sc_dmat, data->map,
! 643: mtod(data->m, void *), MCLBYTES, NULL, BUS_DMA_NOWAIT);
! 644: if (error != 0) {
! 645: printf("%s: could not load rx buf DMA map",
! 646: sc->sc_dev.dv_xname);
! 647: goto fail;
! 648: }
! 649:
! 650: desc->status = htole16(1);
! 651: desc->physdata = htole32(data->map->dm_segs->ds_addr);
! 652: desc->physnext = htole32(ring->physaddr +
! 653: (i + 1) % count * sizeof(struct malo_rx_desc));
! 654: }
! 655:
! 656: bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
! 657: BUS_DMASYNC_PREWRITE);
! 658:
! 659: return (0);
! 660:
! 661: fail: malo_free_rx_ring(sc, ring);
! 662: return (error);
! 663: }
! 664:
! 665: void
! 666: malo_reset_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring)
! 667: {
! 668: int i;
! 669:
! 670: for (i = 0; i < ring->count; i++)
! 671: ring->desc[i].status = 0;
! 672:
! 673: bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
! 674: BUS_DMASYNC_PREWRITE);
! 675:
! 676: ring->cur = ring->next = 0;
! 677: }
! 678:
! 679: void
! 680: malo_free_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring)
! 681: {
! 682: struct malo_rx_data *data;
! 683: int i;
! 684:
! 685: if (ring->desc != NULL) {
! 686: bus_dmamap_sync(sc->sc_dmat, ring->map, 0,
! 687: ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 688: bus_dmamap_unload(sc->sc_dmat, ring->map);
! 689: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc,
! 690: ring->count * sizeof(struct malo_rx_desc));
! 691: bus_dmamem_free(sc->sc_dmat, &ring->seg, 1);
! 692: }
! 693:
! 694: if (ring->data != NULL) {
! 695: for (i = 0; i < ring->count; i++) {
! 696: data = &ring->data[i];
! 697:
! 698: if (data->m != NULL) {
! 699: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 700: data->map->dm_mapsize,
! 701: BUS_DMASYNC_POSTREAD);
! 702: bus_dmamap_unload(sc->sc_dmat, data->map);
! 703: m_freem(data->m);
! 704: }
! 705:
! 706: if (data->map != NULL)
! 707: bus_dmamap_destroy(sc->sc_dmat, data->map);
! 708: }
! 709: free(ring->data, M_DEVBUF);
! 710: }
! 711: }
! 712:
! 713: int
! 714: malo_alloc_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring,
! 715: int count)
! 716: {
! 717: int i, nsegs, error;
! 718:
! 719: ring->count = count;
! 720: ring->queued = 0;
! 721: ring->cur = ring->next = ring->stat = 0;
! 722:
! 723: error = bus_dmamap_create(sc->sc_dmat,
! 724: count * sizeof(struct malo_tx_desc), 1,
! 725: count * sizeof(struct malo_tx_desc), 0, BUS_DMA_NOWAIT, &ring->map);
! 726: if (error != 0) {
! 727: printf("%s: could not create desc DMA map\n",
! 728: sc->sc_dev.dv_xname);
! 729: goto fail;
! 730: }
! 731:
! 732: error = bus_dmamem_alloc(sc->sc_dmat,
! 733: count * sizeof(struct malo_tx_desc),
! 734: PAGE_SIZE, 0, &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT);
! 735: if (error != 0) {
! 736: printf("%s: could not allocate DMA memory\n",
! 737: sc->sc_dev.dv_xname);
! 738: goto fail;
! 739: }
! 740:
! 741: error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs,
! 742: count * sizeof(struct malo_tx_desc), (caddr_t *)&ring->desc,
! 743: BUS_DMA_NOWAIT);
! 744: if (error != 0) {
! 745: printf("%s: could not map desc DMA memory\n",
! 746: sc->sc_dev.dv_xname);
! 747: goto fail;
! 748: }
! 749:
! 750: error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->desc,
! 751: count * sizeof(struct malo_tx_desc), NULL, BUS_DMA_NOWAIT);
! 752: if (error != 0) {
! 753: printf("%s: could not load desc DMA map\n",
! 754: sc->sc_dev.dv_xname);
! 755: goto fail;
! 756: }
! 757:
! 758: memset(ring->desc, 0, count * sizeof(struct malo_tx_desc));
! 759: ring->physaddr = ring->map->dm_segs->ds_addr;
! 760:
! 761: ring->data = malloc(count * sizeof(struct malo_tx_data), M_DEVBUF,
! 762: M_NOWAIT);
! 763: if (ring->data == NULL) {
! 764: printf("%s: could not allocate soft data\n",
! 765: sc->sc_dev.dv_xname);
! 766: error = ENOMEM;
! 767: goto fail;
! 768: }
! 769:
! 770: memset(ring->data, 0, count * sizeof(struct malo_tx_data));
! 771: for (i = 0; i < count; i++) {
! 772: error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
! 773: MALO_MAX_SCATTER, MCLBYTES, 0, BUS_DMA_NOWAIT,
! 774: &ring->data[i].map);
! 775: if (error != 0) {
! 776: printf("%s: could not create DMA map\n",
! 777: sc->sc_dev.dv_xname);
! 778: goto fail;
! 779: }
! 780: ring->desc[i].physnext = htole32(ring->physaddr +
! 781: (i + 1) % count * sizeof(struct malo_tx_desc));
! 782: }
! 783:
! 784: return (0);
! 785:
! 786: fail: malo_free_tx_ring(sc, ring);
! 787: return (error);
! 788: }
! 789:
! 790: void
! 791: malo_reset_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring)
! 792: {
! 793: struct malo_tx_desc *desc;
! 794: struct malo_tx_data *data;
! 795: int i;
! 796:
! 797: for (i = 0; i < ring->count; i++) {
! 798: desc = &ring->desc[i];
! 799: data = &ring->data[i];
! 800:
! 801: if (data->m != NULL) {
! 802: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 803: data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 804: bus_dmamap_unload(sc->sc_dmat, data->map);
! 805: m_freem(data->m);
! 806: data->m = NULL;
! 807: }
! 808:
! 809: /*
! 810: * The node has already been freed at that point so don't call
! 811: * ieee80211_release_node() here.
! 812: */
! 813: data->ni = NULL;
! 814:
! 815: desc->status = 0;
! 816: }
! 817:
! 818: bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
! 819: BUS_DMASYNC_PREWRITE);
! 820:
! 821: ring->queued = 0;
! 822: ring->cur = ring->next = ring->stat = 0;
! 823: }
! 824:
! 825: void
! 826: malo_free_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring)
! 827: {
! 828: struct malo_tx_data *data;
! 829: int i;
! 830:
! 831: if (ring->desc != NULL) {
! 832: bus_dmamap_sync(sc->sc_dmat, ring->map, 0,
! 833: ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 834: bus_dmamap_unload(sc->sc_dmat, ring->map);
! 835: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc,
! 836: ring->count * sizeof(struct malo_tx_desc));
! 837: bus_dmamem_free(sc->sc_dmat, &ring->seg, 1);
! 838: }
! 839:
! 840: if (ring->data != NULL) {
! 841: for (i = 0; i < ring->count; i++) {
! 842: data = &ring->data[i];
! 843:
! 844: if (data->m != NULL) {
! 845: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 846: data->map->dm_mapsize,
! 847: BUS_DMASYNC_POSTWRITE);
! 848: bus_dmamap_unload(sc->sc_dmat, data->map);
! 849: m_freem(data->m);
! 850: }
! 851:
! 852: /*
! 853: * The node has already been freed at that point so
! 854: * don't call ieee80211_release_node() here.
! 855: */
! 856: data->ni = NULL;
! 857:
! 858: if (data->map != NULL)
! 859: bus_dmamap_destroy(sc->sc_dmat, data->map);
! 860: }
! 861: free(ring->data, M_DEVBUF);
! 862: }
! 863: }
! 864:
! 865: int
! 866: malo_init(struct ifnet *ifp)
! 867: {
! 868: struct malo_softc *sc = ifp->if_softc;
! 869: struct ieee80211com *ic = &sc->sc_ic;
! 870: uint8_t chan;
! 871: int error;
! 872:
! 873: DPRINTF(("%s: %s\n", ifp->if_xname, __func__));
! 874:
! 875: /* if interface already runs stop it first */
! 876: if (ifp->if_flags & IFF_RUNNING)
! 877: malo_stop(sc);
! 878:
! 879: /* power on cardbus socket */
! 880: if (sc->sc_enable)
! 881: sc->sc_enable(sc);
! 882:
! 883: /* disable interrupts */
! 884: malo_ctl_read4(sc, 0x0c30);
! 885: malo_ctl_write4(sc, 0x0c30, 0);
! 886: malo_ctl_write4(sc, 0x0c34, 0);
! 887: malo_ctl_write4(sc, 0x0c3c, 0);
! 888:
! 889: /* load firmware */
! 890: if ((error = malo_load_bootimg(sc)))
! 891: goto fail;
! 892: if ((error = malo_load_firmware(sc)))
! 893: goto fail;
! 894:
! 895: /* enable interrupts */
! 896: malo_ctl_write4(sc, 0x0c34, 0x1f);
! 897: malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
! 898: malo_ctl_write4(sc, 0x0c3c, 0x1f);
! 899: malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
! 900:
! 901: if ((error = malo_cmd_get_spec(sc)))
! 902: goto fail;
! 903:
! 904: /* select default channel */
! 905: ic->ic_bss->ni_chan = ic->ic_ibss_chan;
! 906: chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
! 907:
! 908: /* initialize hardware */
! 909: if ((error = malo_cmd_set_channel(sc, chan))) {
! 910: printf("%s: setting channel failed!\n",
! 911: sc->sc_dev.dv_xname);
! 912: goto fail;
! 913: }
! 914: if ((error = malo_cmd_set_antenna(sc, 1))) {
! 915: printf("%s: setting RX antenna failed!\n",
! 916: sc->sc_dev.dv_xname);
! 917: goto fail;
! 918: }
! 919: if ((error = malo_cmd_set_antenna(sc, 2))) {
! 920: printf("%s: setting TX antenna failed!\n",
! 921: sc->sc_dev.dv_xname);
! 922: goto fail;
! 923: }
! 924: if ((error = malo_cmd_set_radio(sc, 1, 5))) {
! 925: printf("%s: turn radio on failed!\n",
! 926: sc->sc_dev.dv_xname);
! 927: goto fail;
! 928: }
! 929: if ((error = malo_cmd_set_txpower(sc, 100))) {
! 930: printf("%s: setting TX power failed!\n",
! 931: sc->sc_dev.dv_xname);
! 932: goto fail;
! 933: }
! 934: if ((error = malo_cmd_set_rts(sc, IEEE80211_RTS_MAX))) {
! 935: printf("%s: setting RTS failed!\n",
! 936: sc->sc_dev.dv_xname);
! 937: goto fail;
! 938: }
! 939:
! 940: /* WEP */
! 941: if (sc->sc_ic.ic_flags & IEEE80211_F_WEPON) {
! 942: /* set key */
! 943: if (malo_set_wepkey(sc)) {
! 944: printf("%s: setting WEP key failed!\n",
! 945: sc->sc_dev.dv_xname);
! 946: goto fail;
! 947: }
! 948: }
! 949:
! 950: ifp->if_flags |= IFF_RUNNING;
! 951:
! 952: if (ic->ic_opmode != IEEE80211_M_MONITOR)
! 953: /* start background scanning */
! 954: ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
! 955: else
! 956: /* in monitor mode change directly into run state */
! 957: ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
! 958:
! 959: return (0);
! 960:
! 961: fail:
! 962: /* reset adapter */
! 963: DPRINTF(("%s: malo_init failed, reseting card\n",
! 964: sc->sc_dev.dv_xname));
! 965: malo_ctl_write4(sc, 0x0c18, (1 << 15));
! 966: return (error);
! 967: }
! 968:
! 969: int
! 970: malo_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
! 971: {
! 972: struct malo_softc *sc = ifp->if_softc;
! 973: struct ieee80211com *ic = &sc->sc_ic;
! 974: struct ifaddr *ifa;
! 975: struct ifreq *ifr;
! 976: int s, error = 0;
! 977: uint8_t chan;
! 978:
! 979: s = splnet();
! 980:
! 981: switch (cmd) {
! 982: case SIOCSIFADDR:
! 983: ifa = (struct ifaddr *)data;
! 984: ifp->if_flags |= IFF_UP;
! 985: #ifdef INET
! 986: if (ifa->ifa_addr->sa_family == AF_INET)
! 987: arp_ifinit(&ic->ic_ac, ifa);
! 988: #endif
! 989: /* FALLTHROUGH */
! 990: case SIOCSIFFLAGS:
! 991: if (ifp->if_flags & IFF_UP) {
! 992: if ((ifp->if_flags & IFF_RUNNING) == 0)
! 993: malo_init(ifp);
! 994: } else {
! 995: if (ifp->if_flags & IFF_RUNNING)
! 996: malo_stop(sc);
! 997: }
! 998: break;
! 999: case SIOCADDMULTI:
! 1000: case SIOCDELMULTI:
! 1001: ifr = (struct ifreq *)data;
! 1002: error = (cmd == SIOCADDMULTI) ?
! 1003: ether_addmulti(ifr, &ic->ic_ac) :
! 1004: ether_delmulti(ifr, &ic->ic_ac);
! 1005:
! 1006: if (error == ENETRESET)
! 1007: error = 0;
! 1008: break;
! 1009: case SIOCS80211CHANNEL:
! 1010: /* allow fast channel switching in monitor mode */
! 1011: error = ieee80211_ioctl(ifp, cmd, data);
! 1012: if (error == ENETRESET &&
! 1013: ic->ic_opmode == IEEE80211_M_MONITOR) {
! 1014: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
! 1015: (IFF_UP | IFF_RUNNING)) {
! 1016: ic->ic_bss->ni_chan = ic->ic_ibss_chan;
! 1017: chan = ieee80211_chan2ieee(ic,
! 1018: ic->ic_bss->ni_chan);
! 1019: malo_cmd_set_channel(sc, chan);
! 1020: }
! 1021: error = 0;
! 1022: }
! 1023: break;
! 1024: default:
! 1025: error = ieee80211_ioctl(ifp, cmd, data);
! 1026: break;
! 1027: }
! 1028:
! 1029: if (error == ENETRESET) {
! 1030: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
! 1031: (IFF_UP | IFF_RUNNING))
! 1032: malo_init(ifp);
! 1033: error = 0;
! 1034: }
! 1035:
! 1036: splx(s);
! 1037:
! 1038: return (error);
! 1039: }
! 1040:
! 1041: void
! 1042: malo_start(struct ifnet *ifp)
! 1043: {
! 1044: struct malo_softc *sc = ifp->if_softc;
! 1045: struct ieee80211com *ic = &sc->sc_ic;
! 1046: struct mbuf *m0;
! 1047: struct ieee80211_node *ni;
! 1048:
! 1049: DPRINTFN(2, ("%s: %s\n", sc->sc_dev.dv_xname, __func__));
! 1050:
! 1051: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
! 1052: return;
! 1053:
! 1054: for (;;) {
! 1055: IF_POLL(&ic->ic_mgtq, m0);
! 1056: if (m0 != NULL) {
! 1057: if (sc->sc_txring.queued >= MALO_TX_RING_COUNT) {
! 1058: ifp->if_flags |= IFF_OACTIVE;
! 1059: break;
! 1060: }
! 1061: IF_DEQUEUE(&ic->ic_mgtq, m0);
! 1062:
! 1063: ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
! 1064: m0->m_pkthdr.rcvif = NULL;
! 1065: #if NBPFILTER > 0
! 1066: if (ic->ic_rawbpf != NULL)
! 1067: bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
! 1068: #endif
! 1069: if (malo_tx_mgt(sc, m0, ni) != 0)
! 1070: break;
! 1071: } else {
! 1072: if (ic->ic_state != IEEE80211_S_RUN)
! 1073: break;
! 1074: IFQ_POLL(&ifp->if_snd, m0);
! 1075: if (m0 == NULL)
! 1076: break;
! 1077: if (sc->sc_txring.queued >= MALO_TX_RING_COUNT - 1) {
! 1078: ifp->if_flags |= IFF_OACTIVE;
! 1079: break;
! 1080: }
! 1081: IFQ_DEQUEUE(&ifp->if_snd, m0);
! 1082: #if NBPFILTER > 0
! 1083: if (ifp->if_bpf != NULL)
! 1084: bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
! 1085: #endif
! 1086: m0 = ieee80211_encap(ifp, m0, &ni);
! 1087: if (m0 == NULL)
! 1088: continue;
! 1089: #if NBPFILTER > 0
! 1090: if (ic->ic_rawbpf != NULL)
! 1091: bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
! 1092: #endif
! 1093: if (malo_tx_data(sc, m0, ni) != 0) {
! 1094: if (ni != NULL)
! 1095: ieee80211_release_node(ic, ni);
! 1096: ifp->if_oerrors++;
! 1097: break;
! 1098: }
! 1099: }
! 1100: }
! 1101: }
! 1102:
! 1103: void
! 1104: malo_stop(struct malo_softc *sc)
! 1105: {
! 1106: struct ieee80211com *ic = &sc->sc_ic;
! 1107: struct ifnet *ifp = &ic->ic_if;
! 1108:
! 1109: DPRINTF(("%s: %s\n", ifp->if_xname, __func__));
! 1110:
! 1111: /* reset adapter */
! 1112: if (ifp->if_flags & IFF_RUNNING)
! 1113: malo_ctl_write4(sc, 0x0c18, (1 << 15));
! 1114:
! 1115: /* device is not running anymore */
! 1116: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 1117:
! 1118: /* change back to initial state */
! 1119: ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
! 1120:
! 1121: /* reset RX / TX rings */
! 1122: malo_reset_tx_ring(sc, &sc->sc_txring);
! 1123: malo_reset_rx_ring(sc, &sc->sc_rxring);
! 1124:
! 1125: /* set initial rate */
! 1126: sc->sc_last_txrate = -1;
! 1127:
! 1128: /* power off cardbus socket */
! 1129: if (sc->sc_disable)
! 1130: sc->sc_disable(sc);
! 1131: }
! 1132:
! 1133: void
! 1134: malo_watchdog(struct ifnet *ifp)
! 1135: {
! 1136:
! 1137: }
! 1138:
! 1139: int
! 1140: malo_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
! 1141: {
! 1142: struct malo_softc *sc = ic->ic_if.if_softc;
! 1143: enum ieee80211_state ostate;
! 1144: uint8_t chan;
! 1145: int rate;
! 1146:
! 1147: DPRINTFN(2, ("%s: %s\n", sc->sc_dev.dv_xname, __func__));
! 1148:
! 1149: ostate = ic->ic_state;
! 1150: timeout_del(&sc->sc_scan_to);
! 1151:
! 1152: switch (nstate) {
! 1153: case IEEE80211_S_INIT:
! 1154: break;
! 1155: case IEEE80211_S_SCAN:
! 1156: if (ostate == IEEE80211_S_INIT) {
! 1157: if (malo_cmd_set_prescan(sc) != 0)
! 1158: DPRINTF(("%s: can't set prescan\n",
! 1159: sc->sc_dev.dv_xname));
! 1160: } else {
! 1161: chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
! 1162:
! 1163: malo_cmd_set_channel(sc, chan);
! 1164: }
! 1165: timeout_add(&sc->sc_scan_to, hz / 2);
! 1166: break;
! 1167: case IEEE80211_S_AUTH:
! 1168: DPRINTF(("newstate AUTH\n"));
! 1169: malo_cmd_set_postscan(sc, ic->ic_myaddr, 1);
! 1170: chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
! 1171: malo_cmd_set_channel(sc, chan);
! 1172: break;
! 1173: case IEEE80211_S_ASSOC:
! 1174: DPRINTF(("newstate ASSOC\n"));
! 1175: if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
! 1176: malo_cmd_set_radio(sc, 1, 3); /* short preamble */
! 1177: else
! 1178: malo_cmd_set_radio(sc, 1, 1); /* long preamble */
! 1179:
! 1180: malo_cmd_set_aid(sc, ic->ic_bss->ni_bssid,
! 1181: ic->ic_bss->ni_associd);
! 1182:
! 1183: if (ic->ic_fixed_rate == -1)
! 1184: /* automatic rate adaption */
! 1185: malo_cmd_set_rate(sc, 0);
! 1186: else {
! 1187: /* fixed rate */
! 1188: rate = malo_fix2rate(ic->ic_fixed_rate);
! 1189: malo_cmd_set_rate(sc, rate);
! 1190: }
! 1191:
! 1192: malo_set_slot(sc);
! 1193: break;
! 1194: case IEEE80211_S_RUN:
! 1195: DPRINTF(("newstate RUN\n"));
! 1196: break;
! 1197: default:
! 1198: break;
! 1199: }
! 1200:
! 1201: return (sc->sc_newstate(ic, nstate, arg));
! 1202: }
! 1203:
! 1204: void
! 1205: malo_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
! 1206: {
! 1207:
! 1208: }
! 1209:
! 1210: struct ieee80211_node *
! 1211: malo_node_alloc(struct ieee80211com *ic)
! 1212: {
! 1213: struct malo_node *wn;
! 1214:
! 1215: wn = malloc(sizeof(struct malo_node), M_DEVBUF, M_NOWAIT);
! 1216: if (wn == NULL)
! 1217: return (NULL);
! 1218:
! 1219: bzero(wn, sizeof(struct malo_node));
! 1220:
! 1221: return ((struct ieee80211_node *)wn);
! 1222: }
! 1223:
! 1224: int
! 1225: malo_media_change(struct ifnet *ifp)
! 1226: {
! 1227: int error;
! 1228:
! 1229: DPRINTF(("%s: %s\n", ifp->if_xname, __func__));
! 1230:
! 1231: error = ieee80211_media_change(ifp);
! 1232: if (error != ENETRESET)
! 1233: return (error);
! 1234:
! 1235: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
! 1236: malo_init(ifp);
! 1237:
! 1238: return (0);
! 1239: }
! 1240:
! 1241: void
! 1242: malo_media_status(struct ifnet *ifp, struct ifmediareq *imr)
! 1243: {
! 1244: struct malo_softc *sc = ifp->if_softc;
! 1245: struct ieee80211com *ic = &sc->sc_ic;
! 1246:
! 1247: imr->ifm_status = IFM_AVALID;
! 1248: imr->ifm_active = IFM_IEEE80211;
! 1249: if (ic->ic_state == IEEE80211_S_RUN)
! 1250: imr->ifm_status |= IFM_ACTIVE;
! 1251:
! 1252: /* report last TX rate used by chip */
! 1253: imr->ifm_active |= ieee80211_rate2media(ic, sc->sc_last_txrate,
! 1254: ic->ic_curmode);
! 1255:
! 1256: switch (ic->ic_opmode) {
! 1257: case IEEE80211_M_STA:
! 1258: break;
! 1259: case IEEE80211_M_IBSS:
! 1260: imr->ifm_active |= IFM_IEEE80211_ADHOC;
! 1261: break;
! 1262: case IEEE80211_M_MONITOR:
! 1263: imr->ifm_active |= IFM_IEEE80211_MONITOR;
! 1264: break;
! 1265: case IEEE80211_M_AHDEMO:
! 1266: break;
! 1267: case IEEE80211_M_HOSTAP:
! 1268: break;
! 1269: }
! 1270:
! 1271: switch (ic->ic_curmode) {
! 1272: case IEEE80211_MODE_11B:
! 1273: imr->ifm_active |= IFM_IEEE80211_11B;
! 1274: break;
! 1275: case IEEE80211_MODE_11G:
! 1276: imr->ifm_active |= IFM_IEEE80211_11G;
! 1277: break;
! 1278: }
! 1279: }
! 1280:
! 1281: int
! 1282: malo_chip2rate(int chip_rate)
! 1283: {
! 1284: switch (chip_rate) {
! 1285: /* CCK rates */
! 1286: case 0: return (2);
! 1287: case 1: return (4);
! 1288: case 2: return (11);
! 1289: case 3: return (22);
! 1290:
! 1291: /* OFDM rates */
! 1292: case 4: return (0); /* reserved */
! 1293: case 5: return (12);
! 1294: case 6: return (18);
! 1295: case 7: return (24);
! 1296: case 8: return (36);
! 1297: case 9: return (48);
! 1298: case 10: return (72);
! 1299: case 11: return (96);
! 1300: case 12: return (108);
! 1301:
! 1302: /* no rate select yet or unknown rate */
! 1303: default: return (-1);
! 1304: }
! 1305: }
! 1306:
! 1307: int
! 1308: malo_fix2rate(int fix_rate)
! 1309: {
! 1310: switch (fix_rate) {
! 1311: /* CCK rates */
! 1312: case 0: return (2);
! 1313: case 1: return (4);
! 1314: case 2: return (11);
! 1315: case 3: return (22);
! 1316:
! 1317: /* OFDM rates */
! 1318: case 4: return (12);
! 1319: case 5: return (18);
! 1320: case 6: return (24);
! 1321: case 7: return (36);
! 1322: case 8: return (48);
! 1323: case 9: return (72);
! 1324: case 10: return (96);
! 1325: case 11: return (108);
! 1326:
! 1327: /* unknown rate: should not happen */
! 1328: default: return (0);
! 1329: }
! 1330: }
! 1331:
! 1332: void
! 1333: malo_next_scan(void *arg)
! 1334: {
! 1335: struct malo_softc *sc = arg;
! 1336: struct ieee80211com *ic = &sc->sc_ic;
! 1337: struct ifnet *ifp = &ic->ic_if;
! 1338: int s;
! 1339:
! 1340: DPRINTF(("%s: %s\n", ifp->if_xname, __func__));
! 1341:
! 1342: s = splnet();
! 1343:
! 1344: if (ic->ic_state == IEEE80211_S_SCAN)
! 1345: ieee80211_next_scan(ifp);
! 1346:
! 1347: splx(s);
! 1348: }
! 1349:
! 1350: void
! 1351: malo_tx_intr(struct malo_softc *sc)
! 1352: {
! 1353: struct ieee80211com *ic = &sc->sc_ic;
! 1354: struct ifnet *ifp = &ic->ic_if;
! 1355: struct malo_tx_desc *desc;
! 1356: struct malo_tx_data *data;
! 1357: struct malo_node *rn;
! 1358: int stat;
! 1359:
! 1360: DPRINTFN(2, ("%s: %s\n", sc->sc_dev.dv_xname, __func__));
! 1361:
! 1362: stat = sc->sc_txring.stat;
! 1363: for (;;) {
! 1364: desc = &sc->sc_txring.desc[sc->sc_txring.stat];
! 1365: data = &sc->sc_txring.data[sc->sc_txring.stat];
! 1366: rn = (struct malo_node *)data->ni;
! 1367:
! 1368: /* check if TX descriptor is not owned by FW anymore */
! 1369: if ((letoh32(desc->status) & 0x80000000) ||
! 1370: !(letoh32(data->softstat) & 0x80))
! 1371: break;
! 1372:
! 1373: /* if no frame has been sent, ignore */
! 1374: if (rn == NULL)
! 1375: goto next;
! 1376:
! 1377: /* check TX state */
! 1378: switch (letoh32(desc->status) & 0x1) {
! 1379: case 0x1:
! 1380: DPRINTFN(2, ("data frame was sent successfully\n"));
! 1381: ifp->if_opackets++;
! 1382: break;
! 1383: default:
! 1384: DPRINTF(("data frame sending error\n"));
! 1385: ifp->if_oerrors++;
! 1386: break;
! 1387: }
! 1388:
! 1389: /* save last used TX rate */
! 1390: sc->sc_last_txrate = malo_chip2rate(desc->datarate);
! 1391:
! 1392: /* cleanup TX data and TX descritpor */
! 1393: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 1394: data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 1395: bus_dmamap_unload(sc->sc_dmat, data->map);
! 1396: m_freem(data->m);
! 1397: ieee80211_release_node(ic, data->ni);
! 1398: data->m = NULL;
! 1399: data->ni = NULL;
! 1400: data->softstat &= htole32(~0x80);
! 1401: desc->status = 0;
! 1402: desc->len = 0;
! 1403:
! 1404: DPRINTFN(2, ("tx done idx=%u\n", sc->sc_txring.stat));
! 1405:
! 1406: sc->sc_txring.queued--;
! 1407: next:
! 1408: if (++sc->sc_txring.stat >= sc->sc_txring.count)
! 1409: sc->sc_txring.stat = 0;
! 1410: if (sc->sc_txring.stat == stat)
! 1411: break;
! 1412: }
! 1413:
! 1414: sc->sc_tx_timer = 0;
! 1415: ifp->if_flags &= ~IFF_OACTIVE;
! 1416: malo_start(ifp);
! 1417: }
! 1418:
! 1419: int
! 1420: malo_tx_mgt(struct malo_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
! 1421: {
! 1422: struct ieee80211com *ic = &sc->sc_ic;
! 1423: struct ifnet *ifp = &ic->ic_if;
! 1424: struct malo_tx_desc *desc;
! 1425: struct malo_tx_data *data;
! 1426: struct ieee80211_frame *wh;
! 1427: int error;
! 1428:
! 1429: DPRINTFN(2, ("%s: %s\n", sc->sc_dev.dv_xname, __func__));
! 1430:
! 1431: desc = &sc->sc_txring.desc[sc->sc_txring.cur];
! 1432: data = &sc->sc_txring.data[sc->sc_txring.cur];
! 1433:
! 1434: if (m0->m_len < sizeof(struct ieee80211_frame)) {
! 1435: m0 = m_pullup(m0, sizeof(struct ieee80211_frame));
! 1436: if (m0 == NULL) {
! 1437: ifp->if_ierrors++;
! 1438: return (ENOBUFS);
! 1439: }
! 1440: }
! 1441: wh = mtod(m0, struct ieee80211_frame *);
! 1442:
! 1443: if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
! 1444: m0 = ieee80211_wep_crypt(ifp, m0, 1);
! 1445: if (m0 == NULL)
! 1446: return (ENOBUFS);
! 1447:
! 1448: /* packet header may have moved, reset our local pointer */
! 1449: wh = mtod(m0, struct ieee80211_frame *);
! 1450: }
! 1451:
! 1452: #if NBPFILTER > 0
! 1453: if (sc->sc_drvbpf != NULL) {
! 1454: struct mbuf mb;
! 1455: struct malo_tx_radiotap_hdr *tap = &sc->sc_txtap;
! 1456:
! 1457: tap->wt_flags = 0;
! 1458: tap->wt_rate = sc->sc_last_txrate;
! 1459: tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
! 1460: tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
! 1461:
! 1462: mb.m_data = (caddr_t)tap;
! 1463: mb.m_len = sc->sc_txtap_len;
! 1464: mb.m_next = m0;
! 1465: mb.m_nextpkt = NULL;
! 1466: mb.m_type = 0;
! 1467: mb.m_flags = 0;
! 1468: bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
! 1469: }
! 1470: #endif
! 1471: /*
! 1472: * inject FW specific fields into the 802.11 frame
! 1473: *
! 1474: * 2 bytes FW len (inject)
! 1475: * 24 bytes 802.11 frame header
! 1476: * 6 bytes addr4 (inject)
! 1477: * n bytes 802.11 frame body
! 1478: */
! 1479: if (M_LEADINGSPACE(m0) < 8) {
! 1480: if (M_TRAILINGSPACE(m0) < 8)
! 1481: panic("%s: not enough space for mbuf dance",
! 1482: sc->sc_dev.dv_xname);
! 1483: bcopy(m0->m_data, m0->m_data + 8, m0->m_len);
! 1484: m0->m_data += 8;
! 1485: }
! 1486:
! 1487: /* move frame header */
! 1488: bcopy(m0->m_data, m0->m_data - 6, sizeof(*wh));
! 1489: m0->m_data -= 8;
! 1490: m0->m_len += 8;
! 1491: m0->m_pkthdr.len += 8;
! 1492: *mtod(m0, uint16_t *) = htole16(m0->m_len - 32); /* FW len */
! 1493:
! 1494: error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
! 1495: BUS_DMA_NOWAIT);
! 1496: if (error != 0) {
! 1497: printf("%s: could not map mbuf (error %d)\n",
! 1498: sc->sc_dev.dv_xname, error);
! 1499: m_freem(m0);
! 1500: return (error);
! 1501: }
! 1502:
! 1503: data->m = m0;
! 1504: data->ni = ni;
! 1505: data->softstat |= htole32(0x80);
! 1506:
! 1507: malo_tx_setup_desc(sc, desc, m0->m_pkthdr.len, 0,
! 1508: data->map->dm_segs, data->map->dm_nsegs);
! 1509:
! 1510: bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
! 1511: BUS_DMASYNC_PREWRITE);
! 1512: bus_dmamap_sync(sc->sc_dmat, sc->sc_txring.map,
! 1513: sc->sc_txring.cur * sizeof(struct malo_tx_desc),
! 1514: sizeof(struct malo_tx_desc), BUS_DMASYNC_PREWRITE);
! 1515:
! 1516: DPRINTFN(2, ("%s: sending mgmt frame, pktlen=%u, idx=%u\n",
! 1517: sc->sc_dev.dv_xname, m0->m_pkthdr.len, sc->sc_txring.cur));
! 1518:
! 1519: sc->sc_txring.queued++;
! 1520: sc->sc_txring.cur = (sc->sc_txring.cur + 1) % MALO_TX_RING_COUNT;
! 1521:
! 1522: /* kick mgmt TX */
! 1523: malo_ctl_write4(sc, 0x0c18, 1);
! 1524: malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
! 1525:
! 1526: return (0);
! 1527: }
! 1528:
! 1529: int
! 1530: malo_tx_data(struct malo_softc *sc, struct mbuf *m0,
! 1531: struct ieee80211_node *ni)
! 1532: {
! 1533: struct ieee80211com *ic = &sc->sc_ic;
! 1534: struct ifnet *ifp = &ic->ic_if;
! 1535: struct malo_tx_desc *desc;
! 1536: struct malo_tx_data *data;
! 1537: struct ieee80211_frame *wh;
! 1538: struct mbuf *mnew;
! 1539: int error;
! 1540:
! 1541: DPRINTFN(2, ("%s: %s\n", sc->sc_dev.dv_xname, __func__));
! 1542:
! 1543: desc = &sc->sc_txring.desc[sc->sc_txring.cur];
! 1544: data = &sc->sc_txring.data[sc->sc_txring.cur];
! 1545:
! 1546: if (m0->m_len < sizeof(struct ieee80211_frame)) {
! 1547: m0 = m_pullup(m0, sizeof(struct ieee80211_frame));
! 1548: if (m0 == NULL) {
! 1549: ifp->if_ierrors++;
! 1550: return (ENOBUFS);
! 1551: }
! 1552: }
! 1553: wh = mtod(m0, struct ieee80211_frame *);
! 1554:
! 1555: if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
! 1556: m0 = ieee80211_wep_crypt(ifp, m0, 1);
! 1557: if (m0 == NULL)
! 1558: return (ENOBUFS);
! 1559:
! 1560: /* packet header may have moved, reset our local pointer */
! 1561: wh = mtod(m0, struct ieee80211_frame *);
! 1562: }
! 1563:
! 1564: #if NBPFILTER > 0
! 1565: if (sc->sc_drvbpf != NULL) {
! 1566: struct mbuf mb;
! 1567: struct malo_tx_radiotap_hdr *tap = &sc->sc_txtap;
! 1568:
! 1569: tap->wt_flags = 0;
! 1570: tap->wt_rate = sc->sc_last_txrate;
! 1571: tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
! 1572: tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
! 1573:
! 1574: mb.m_data = (caddr_t)tap;
! 1575: mb.m_len = sc->sc_txtap_len;
! 1576: mb.m_next = m0;
! 1577: mb.m_nextpkt = NULL;
! 1578: mb.m_type = 0;
! 1579: mb.m_flags = 0;
! 1580: bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
! 1581: }
! 1582: #endif
! 1583:
! 1584: /*
! 1585: * inject FW specific fields into the 802.11 frame
! 1586: *
! 1587: * 2 bytes FW len (inject)
! 1588: * 24 bytes 802.11 frame header
! 1589: * 6 bytes addr4 (inject)
! 1590: * n bytes 802.11 frame body
! 1591: *
! 1592: * For now copy all into a new mcluster.
! 1593: */
! 1594: MGETHDR(mnew, M_DONTWAIT, MT_DATA);
! 1595: if (mnew == NULL)
! 1596: return (ENOBUFS);
! 1597: MCLGET(mnew, M_DONTWAIT);
! 1598: if (!(mnew->m_flags & M_EXT)) {
! 1599: m_free(mnew);
! 1600: return (ENOBUFS);
! 1601: }
! 1602:
! 1603: *mtod(mnew, uint16_t *) = htole16(m0->m_pkthdr.len - 24); /* FW len */
! 1604: bcopy(wh, mtod(mnew, caddr_t) + 2, sizeof(*wh));
! 1605: bzero(mtod(mnew, caddr_t) + 26, 6);
! 1606: m_copydata(m0, sizeof(*wh), m0->m_pkthdr.len - sizeof(*wh),
! 1607: mtod(mnew, caddr_t) + 32);
! 1608: mnew->m_pkthdr.len = mnew->m_len = m0->m_pkthdr.len + 8;
! 1609: m_freem(m0);
! 1610: m0 = mnew;
! 1611:
! 1612: error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
! 1613: BUS_DMA_NOWAIT);
! 1614: if (error != 0) {
! 1615: printf("%s: could not map mbuf (error %d)\n",
! 1616: sc->sc_dev.dv_xname, error);
! 1617: m_freem(m0);
! 1618: return (error);
! 1619: }
! 1620:
! 1621: data->m = m0;
! 1622: data->ni = ni;
! 1623: data->softstat |= htole32(0x80);
! 1624:
! 1625: malo_tx_setup_desc(sc, desc, m0->m_pkthdr.len, 1,
! 1626: data->map->dm_segs, data->map->dm_nsegs);
! 1627:
! 1628: bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
! 1629: BUS_DMASYNC_PREWRITE);
! 1630: bus_dmamap_sync(sc->sc_dmat, sc->sc_txring.map,
! 1631: sc->sc_txring.cur * sizeof(struct malo_tx_desc),
! 1632: sizeof(struct malo_tx_desc), BUS_DMASYNC_PREWRITE);
! 1633:
! 1634: DPRINTFN(2, ("%s: sending data frame, pktlen=%u, idx=%u\n",
! 1635: sc->sc_dev.dv_xname, m0->m_pkthdr.len, sc->sc_txring.cur));
! 1636:
! 1637: sc->sc_txring.queued++;
! 1638: sc->sc_txring.cur = (sc->sc_txring.cur + 1) % MALO_TX_RING_COUNT;
! 1639:
! 1640: /* kick data TX */
! 1641: malo_ctl_write4(sc, 0x0c18, 1);
! 1642: malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
! 1643:
! 1644: return (0);
! 1645: }
! 1646:
! 1647: void
! 1648: malo_tx_setup_desc(struct malo_softc *sc, struct malo_tx_desc *desc,
! 1649: int len, int rate, const bus_dma_segment_t *segs, int nsegs)
! 1650: {
! 1651: desc->len = htole16(segs[0].ds_len);
! 1652: desc->datarate = rate; /* 0 = mgmt frame, 1 = data frame */
! 1653: desc->physdata = htole32(segs[0].ds_addr);
! 1654: desc->status = htole32(0x00000001 | 0x80000000);
! 1655: }
! 1656:
! 1657: void
! 1658: malo_rx_intr(struct malo_softc *sc)
! 1659: {
! 1660: struct ieee80211com *ic = &sc->sc_ic;
! 1661: struct ifnet *ifp = &ic->ic_if;
! 1662: struct malo_rx_desc *desc;
! 1663: struct malo_rx_data *data;
! 1664: struct ieee80211_frame *wh;
! 1665: struct ieee80211_node *ni;
! 1666: struct mbuf *mnew, *m;
! 1667: uint32_t rxRdPtr, rxWrPtr;
! 1668: int error, i;
! 1669:
! 1670: rxRdPtr = malo_mem_read4(sc, sc->sc_RxPdRdPtr);
! 1671: rxWrPtr = malo_mem_read4(sc, sc->sc_RxPdWrPtr);
! 1672:
! 1673: for (i = 0; i < MALO_RX_RING_COUNT && rxRdPtr != rxWrPtr; i++) {
! 1674: desc = &sc->sc_rxring.desc[sc->sc_rxring.cur];
! 1675: data = &sc->sc_rxring.data[sc->sc_rxring.cur];
! 1676:
! 1677: bus_dmamap_sync(sc->sc_dmat, sc->sc_rxring.map,
! 1678: sc->sc_rxring.cur * sizeof(struct malo_rx_desc),
! 1679: sizeof(struct malo_rx_desc), BUS_DMASYNC_POSTREAD);
! 1680:
! 1681: DPRINTFN(3, ("rx intr idx=%d, rxctrl=0x%02x, rssi=%d, "
! 1682: "status=0x%02x, channel=%d, len=%d, res1=%02x, rate=%d, "
! 1683: "physdata=0x%04x, physnext=0x%04x, qosctrl=%02x, res2=%d\n",
! 1684: sc->sc_rxring.cur, desc->rxctrl, desc->rssi, desc->status,
! 1685: desc->channel, letoh16(desc->len), desc->reserved1,
! 1686: desc->datarate, letoh32(desc->physdata),
! 1687: letoh32(desc->physnext), desc->qosctrl, desc->reserved2));
! 1688:
! 1689: if ((desc->rxctrl & 0x80) == 0)
! 1690: break;
! 1691:
! 1692: MGETHDR(mnew, M_DONTWAIT, MT_DATA);
! 1693: if (mnew == NULL) {
! 1694: ifp->if_ierrors++;
! 1695: goto skip;
! 1696: }
! 1697:
! 1698: MCLGET(mnew, M_DONTWAIT);
! 1699: if (!(mnew->m_flags & M_EXT)) {
! 1700: m_freem(mnew);
! 1701: ifp->if_ierrors++;
! 1702: goto skip;
! 1703: }
! 1704:
! 1705: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 1706: data->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
! 1707: bus_dmamap_unload(sc->sc_dmat, data->map);
! 1708:
! 1709: error = bus_dmamap_load(sc->sc_dmat, data->map,
! 1710: mtod(mnew, void *), MCLBYTES, NULL, BUS_DMA_NOWAIT);
! 1711: if (error != 0) {
! 1712: m_freem(mnew);
! 1713:
! 1714: error = bus_dmamap_load(sc->sc_dmat, data->map,
! 1715: mtod(data->m, void *), MCLBYTES, NULL,
! 1716: BUS_DMA_NOWAIT);
! 1717: if (error != 0) {
! 1718: panic("%s: could not load old rx mbuf",
! 1719: sc->sc_dev.dv_xname);
! 1720: }
! 1721: ifp->if_ierrors++;
! 1722: goto skip;
! 1723: }
! 1724:
! 1725: /*
! 1726: * New mbuf mbuf successfully loaded
! 1727: */
! 1728: m = data->m;
! 1729: data->m = mnew;
! 1730: desc->physdata = htole32(data->map->dm_segs->ds_addr);
! 1731:
! 1732: /* finalize mbuf */
! 1733: m->m_pkthdr.rcvif = ifp;
! 1734: m->m_pkthdr.len = m->m_len = letoh16(desc->len);
! 1735:
! 1736: /*
! 1737: * cut out FW specific fields from the 802.11 frame
! 1738: *
! 1739: * 2 bytes FW len (cut out)
! 1740: * 24 bytes 802.11 frame header
! 1741: * 6 bytes addr4 (cut out)
! 1742: * n bytes 802.11 frame data
! 1743: */
! 1744: bcopy(m->m_data, m->m_data + 6, 26);
! 1745: m_adj(m, 8);
! 1746:
! 1747: #if NBPFILTER > 0
! 1748: if (sc->sc_drvbpf != NULL) {
! 1749: struct mbuf mb;
! 1750: struct malo_rx_radiotap_hdr *tap = &sc->sc_rxtap;
! 1751:
! 1752: tap->wr_flags = 0;
! 1753: tap->wr_chan_freq =
! 1754: htole16(ic->ic_bss->ni_chan->ic_freq);
! 1755: tap->wr_chan_flags =
! 1756: htole16(ic->ic_bss->ni_chan->ic_flags);
! 1757: tap->wr_rssi = desc->rssi;
! 1758: tap->wr_max_rssi = ic->ic_max_rssi;
! 1759:
! 1760: mb.m_data = (caddr_t)tap;
! 1761: mb.m_len = sc->sc_rxtap_len;
! 1762: mb.m_next = m;
! 1763: mb.m_nextpkt = NULL;
! 1764: mb.m_type = 0;
! 1765: mb.m_flags = 0;
! 1766: bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
! 1767: }
! 1768: #endif
! 1769:
! 1770: wh = mtod(m, struct ieee80211_frame *);
! 1771: ni = ieee80211_find_rxnode(ic, wh);
! 1772:
! 1773: /* send the frame to the 802.11 layer */
! 1774: ieee80211_input(ifp, m, ni, desc->rssi, 0);
! 1775:
! 1776: /* node is no longer needed */
! 1777: ieee80211_release_node(ic, ni);
! 1778:
! 1779: skip:
! 1780: desc->rxctrl = 0;
! 1781: rxRdPtr = letoh32(desc->physnext);
! 1782:
! 1783: bus_dmamap_sync(sc->sc_dmat, sc->sc_rxring.map,
! 1784: sc->sc_rxring.cur * sizeof(struct malo_rx_desc),
! 1785: sizeof(struct malo_rx_desc), BUS_DMASYNC_PREWRITE);
! 1786:
! 1787: sc->sc_rxring.cur = (sc->sc_rxring.cur + 1) %
! 1788: MALO_RX_RING_COUNT;
! 1789: }
! 1790:
! 1791: malo_mem_write4(sc, sc->sc_RxPdRdPtr, rxRdPtr);
! 1792:
! 1793: /*
! 1794: * In HostAP mode, ieee80211_input() will enqueue packets in if_snd
! 1795: * without calling if_start().
! 1796: */
! 1797: if (!IFQ_IS_EMPTY(&ifp->if_snd) && !(ifp->if_flags & IFF_OACTIVE))
! 1798: (*ifp->if_start)(ifp);
! 1799: }
! 1800:
! 1801: int
! 1802: malo_load_bootimg(struct malo_softc *sc)
! 1803: {
! 1804: char *name = "malo8335-h";
! 1805: uint8_t *ucode;
! 1806: size_t size;
! 1807: int error, i;
! 1808:
! 1809: /* load boot firmware */
! 1810: if ((error = loadfirmware(name, &ucode, &size)) != 0) {
! 1811: printf("%s: error %d, could not read microcode %s!\n",
! 1812: sc->sc_dev.dv_xname, error, name);
! 1813: return (EIO);
! 1814: }
! 1815:
! 1816: /*
! 1817: * It seems we are putting this code directly onto the stack of
! 1818: * the ARM cpu. I don't know why we need to instruct the DMA
! 1819: * engine to move the code. This is a big riddle without docu.
! 1820: */
! 1821: DPRINTF(("%s: loading boot firmware\n", sc->sc_dev.dv_xname));
! 1822: malo_mem_write2(sc, 0xbef8, 0x001);
! 1823: malo_mem_write2(sc, 0xbefa, size);
! 1824: malo_mem_write4(sc, 0xbefc, 0);
! 1825:
! 1826: bus_space_write_region_1(sc->sc_mem1_bt, sc->sc_mem1_bh, 0xbf00,
! 1827: ucode, size);
! 1828:
! 1829: /*
! 1830: * we loaded the firmware into card memory now tell the CPU
! 1831: * to fetch the code and execute it. The memory mapped via the
! 1832: * first bar is internaly mapped to 0xc0000000.
! 1833: */
! 1834: malo_send_cmd(sc, 0xc000bef8);
! 1835:
! 1836: /* wait for the device to go into FW loading mode */
! 1837: for (i = 0; i < 10; i++) {
! 1838: delay(50);
! 1839: malo_ctl_barrier(sc, BUS_SPACE_BARRIER_READ);
! 1840: if (malo_ctl_read4(sc, 0x0c14) == 0x5)
! 1841: break;
! 1842: }
! 1843: if (i == 10) {
! 1844: printf("%s: timeout at boot firmware load!\n",
! 1845: sc->sc_dev.dv_xname);
! 1846: free(ucode, M_DEVBUF);
! 1847: return (ETIMEDOUT);
! 1848: }
! 1849: free(ucode, M_DEVBUF);
! 1850:
! 1851: /* tell the card we're done and... */
! 1852: malo_mem_write2(sc, 0xbef8, 0x001);
! 1853: malo_mem_write2(sc, 0xbefa, 0);
! 1854: malo_mem_write4(sc, 0xbefc, 0);
! 1855: malo_send_cmd(sc, 0xc000bef8);
! 1856:
! 1857: DPRINTF(("%s: boot firmware loaded\n", sc->sc_dev.dv_xname));
! 1858:
! 1859: return (0);
! 1860: }
! 1861:
! 1862: int
! 1863: malo_load_firmware(struct malo_softc *sc)
! 1864: {
! 1865: struct malo_cmdheader *hdr;
! 1866: char *name = "malo8335-m";
! 1867: void *data;
! 1868: uint8_t *ucode;
! 1869: size_t size, count, bsize;
! 1870: int i, sn, error;
! 1871:
! 1872: /* load real firmware now */
! 1873: if ((error = loadfirmware(name, &ucode, &size)) != 0) {
! 1874: printf("%s: error %d, could not read microcode %s!\n",
! 1875: sc->sc_dev.dv_xname, error, name);
! 1876: return (EIO);
! 1877: }
! 1878:
! 1879: DPRINTF(("%s: uploading firmware\n", sc->sc_dev.dv_xname));
! 1880:
! 1881: hdr = sc->sc_cmd_mem;
! 1882: data = hdr + 1;
! 1883: sn = 1;
! 1884: for (count = 0; count < size; count += bsize) {
! 1885: bsize = MIN(256, size - count);
! 1886:
! 1887: hdr->cmd = htole16(0x0001);
! 1888: hdr->size = htole16(bsize);
! 1889: hdr->seqnum = htole16(sn++);
! 1890: hdr->result = 0;
! 1891:
! 1892: bcopy(ucode + count, data, bsize);
! 1893:
! 1894: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
! 1895: BUS_DMASYNC_PREWRITE);
! 1896: malo_send_cmd(sc, sc->sc_cmd_dmaaddr);
! 1897: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
! 1898: BUS_DMASYNC_POSTWRITE);
! 1899: delay(500);
! 1900: }
! 1901: free(ucode, M_DEVBUF);
! 1902:
! 1903: DPRINTF(("%s: firmware upload finished\n", sc->sc_dev.dv_xname));
! 1904:
! 1905: /*
! 1906: * send a command with size 0 to tell that the firmware has been
! 1907: * uploaded
! 1908: */
! 1909: hdr->cmd = htole16(0x0001);
! 1910: hdr->size = 0;
! 1911: hdr->seqnum = htole16(sn++);
! 1912: hdr->result = 0;
! 1913:
! 1914: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
! 1915: BUS_DMASYNC_PREWRITE);
! 1916: malo_send_cmd(sc, sc->sc_cmd_dmaaddr);
! 1917: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
! 1918: BUS_DMASYNC_POSTWRITE);
! 1919: delay(100);
! 1920:
! 1921: DPRINTF(("%s: loading firmware\n", sc->sc_dev.dv_xname));
! 1922:
! 1923: /* wait until firmware has been loaded */
! 1924: for (i = 0; i < 200; i++) {
! 1925: malo_ctl_write4(sc, 0x0c10, 0x5a);
! 1926: delay(500);
! 1927: malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE |
! 1928: BUS_SPACE_BARRIER_READ);
! 1929: if (malo_ctl_read4(sc, 0x0c14) == 0xf0f1f2f4)
! 1930: break;
! 1931: }
! 1932: if (i == 200) {
! 1933: printf("%s: timeout at firmware load!\n", sc->sc_dev.dv_xname);
! 1934: return (ETIMEDOUT);
! 1935: }
! 1936:
! 1937: DPRINTF(("%s: firmware loaded\n", sc->sc_dev.dv_xname));
! 1938:
! 1939: return (0);
! 1940: }
! 1941:
! 1942: int
! 1943: malo_set_wepkey(struct malo_softc *sc)
! 1944: {
! 1945: struct ieee80211com *ic = &sc->sc_ic;
! 1946: int i;
! 1947:
! 1948: for (i = 0; i < IEEE80211_WEP_NKID; i++) {
! 1949: struct ieee80211_key *k = &ic->ic_nw_keys[i];
! 1950:
! 1951: if (k->k_len == 0)
! 1952: continue;
! 1953:
! 1954: if (malo_cmd_set_wepkey(sc, k, i))
! 1955: return (ENXIO);
! 1956: }
! 1957:
! 1958: return (0);
! 1959: }
! 1960:
! 1961: int
! 1962: malo_set_slot(struct malo_softc *sc)
! 1963: {
! 1964: struct ieee80211com *ic = &sc->sc_ic;
! 1965:
! 1966: if (ic->ic_flags & IEEE80211_F_SHSLOT) {
! 1967: /* set short slot */
! 1968: if (malo_cmd_set_slot(sc, 1)) {
! 1969: printf("%s: setting short slot failed\n",
! 1970: sc->sc_dev.dv_xname);
! 1971: return (ENXIO);
! 1972: }
! 1973: } else {
! 1974: /* set long slot */
! 1975: if (malo_cmd_set_slot(sc, 0)) {
! 1976: printf("%s: setting long slot failed\n",
! 1977: sc->sc_dev.dv_xname);
! 1978: return (ENXIO);
! 1979: }
! 1980: }
! 1981:
! 1982: return (0);
! 1983: }
! 1984:
! 1985: void
! 1986: malo_update_slot(struct ieee80211com *ic)
! 1987: {
! 1988: struct malo_softc *sc = ic->ic_if.if_softc;
! 1989:
! 1990: malo_set_slot(sc);
! 1991:
! 1992: if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
! 1993: /* TODO */
! 1994: }
! 1995: }
! 1996:
! 1997: #ifdef MALO_DEBUG
! 1998: void
! 1999: malo_hexdump(void *buf, int len)
! 2000: {
! 2001: u_char b[16];
! 2002: int i, j, l;
! 2003:
! 2004: for (i = 0; i < len; i += l) {
! 2005: printf("%4i:", i);
! 2006: l = min(sizeof(b), len - i);
! 2007: bcopy(buf + i, b, l);
! 2008:
! 2009: for (j = 0; j < sizeof(b); j++) {
! 2010: if (j % 2 == 0)
! 2011: printf(" ");
! 2012: if (j % 8 == 0)
! 2013: printf(" ");
! 2014: if (j < l)
! 2015: printf("%02x", (int)b[j]);
! 2016: else
! 2017: printf(" ");
! 2018: }
! 2019: printf(" |");
! 2020: for (j = 0; j < l; j++) {
! 2021: if (b[j] >= 0x20 && b[j] <= 0x7e)
! 2022: printf("%c", b[j]);
! 2023: else
! 2024: printf(".");
! 2025: }
! 2026: printf("|\n");
! 2027: }
! 2028: }
! 2029: #endif
! 2030:
! 2031: static char *
! 2032: malo_cmd_string(uint16_t cmd)
! 2033: {
! 2034: int i;
! 2035: static char cmd_buf[16];
! 2036: static const struct {
! 2037: uint16_t cmd_code;
! 2038: char *cmd_string;
! 2039: } cmds[] = {
! 2040: { MALO_CMD_GET_HW_SPEC, "GetHwSpecifications" },
! 2041: { MALO_CMD_SET_RADIO, "SetRadio" },
! 2042: { MALO_CMD_SET_TXPOWER, "SetTxPower" },
! 2043: { MALO_CMD_SET_ANTENNA, "SetAntenna" },
! 2044: { MALO_CMD_SET_PRESCAN, "SetPrescan" },
! 2045: { MALO_CMD_SET_POSTSCAN, "SetPostscan" },
! 2046: { MALO_CMD_SET_CHANNEL, "SetChannel" },
! 2047: { MALO_CMD_SET_RTS, "SetRTS" },
! 2048: };
! 2049:
! 2050: for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++)
! 2051: if ((letoh16(cmd) & 0x7fff) == cmds[i].cmd_code)
! 2052: return (cmds[i].cmd_string);
! 2053:
! 2054: snprintf(cmd_buf, sizeof(cmd_buf), "unknown %#x", cmd);
! 2055: return (cmd_buf);
! 2056: }
! 2057:
! 2058: static char *
! 2059: malo_cmd_string_result(uint16_t result)
! 2060: {
! 2061: int i;
! 2062: static const struct {
! 2063: uint16_t result_code;
! 2064: char *result_string;
! 2065: } results[] = {
! 2066: { MALO_CMD_RESULT_OK, "OK" },
! 2067: { MALO_CMD_RESULT_ERROR, "general error" },
! 2068: { MALO_CMD_RESULT_NOSUPPORT, "not supported" },
! 2069: { MALO_CMD_RESULT_PENDING, "pending" },
! 2070: { MALO_CMD_RESULT_BUSY, "ignored" },
! 2071: { MALO_CMD_RESULT_PARTIALDATA, "incomplete" },
! 2072: };
! 2073:
! 2074: for (i = 0; i < sizeof(results) / sizeof(results[0]); i++)
! 2075: if (letoh16(result) == results[i].result_code)
! 2076: return (results[i].result_string);
! 2077:
! 2078: return ("unknown");
! 2079: }
! 2080:
! 2081: int
! 2082: malo_cmd_get_spec(struct malo_softc *sc)
! 2083: {
! 2084: struct malo_cmdheader *hdr = sc->sc_cmd_mem;
! 2085: struct malo_hw_spec *spec;
! 2086:
! 2087: hdr->cmd = htole16(MALO_CMD_GET_HW_SPEC);
! 2088: hdr->size = htole16(sizeof(*hdr) + sizeof(*spec));
! 2089: hdr->seqnum = htole16(42); /* the one and only */
! 2090: hdr->result = 0;
! 2091: spec = (struct malo_hw_spec *)(hdr + 1);
! 2092:
! 2093: bzero(spec, sizeof(*spec));
! 2094: memset(spec->PermanentAddress, 0xff, ETHER_ADDR_LEN);
! 2095: spec->CookiePtr = htole32(sc->sc_cookie_dmaaddr);
! 2096:
! 2097: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
! 2098: BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
! 2099:
! 2100: if (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr) != 0)
! 2101: return (ETIMEDOUT);
! 2102:
! 2103: /* XXX get the data from the buffer and feed it to ieee80211 */
! 2104: DPRINTF(("%s: get_hw_spec: V%x R%x, #WCB %d, #Mcast %d, Regcode %d, "
! 2105: "#Ant %d\n", sc->sc_dev.dv_xname, htole16(spec->HwVersion),
! 2106: htole32(spec->FWReleaseNumber), htole16(spec->NumOfWCB),
! 2107: htole16(spec->NumOfMCastAdr), htole16(spec->RegionCode),
! 2108: htole16(spec->NumberOfAntenna)));
! 2109:
! 2110: /* tell the DMA engine where our rings are */
! 2111: malo_mem_write4(sc, letoh32(spec->RxPdRdPtr) & 0xffff,
! 2112: sc->sc_rxring.physaddr);
! 2113: malo_mem_write4(sc, letoh32(spec->RxPdWrPtr) & 0xffff,
! 2114: sc->sc_rxring.physaddr);
! 2115: malo_mem_write4(sc, letoh32(spec->WcbBase0) & 0xffff,
! 2116: sc->sc_txring.physaddr);
! 2117:
! 2118: /* save DMA RX pointers for later use */
! 2119: sc->sc_RxPdRdPtr = letoh32(spec->RxPdRdPtr) & 0xffff;
! 2120: sc->sc_RxPdWrPtr = letoh32(spec->RxPdWrPtr) & 0xffff;
! 2121:
! 2122: return (0);
! 2123: }
! 2124:
! 2125: int
! 2126: malo_cmd_set_wepkey(struct malo_softc *sc, struct ieee80211_key *k,
! 2127: uint16_t k_index)
! 2128: {
! 2129: struct malo_cmdheader *hdr = sc->sc_cmd_mem;
! 2130: struct malo_cmd_wepkey *body;
! 2131:
! 2132: hdr->cmd = htole16(MALO_CMD_SET_WEPKEY);
! 2133: hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
! 2134: hdr->seqnum = 1;
! 2135: hdr->result = 0;
! 2136: body = (struct malo_cmd_wepkey *)(hdr + 1);
! 2137:
! 2138: bzero(body, sizeof(*body));
! 2139: body->action = htole16(1);
! 2140: body->flags = 0;
! 2141: body->index = k_index;
! 2142: body->len = k->k_len;
! 2143: memcpy(body->value, k->k_key, k->k_len);
! 2144:
! 2145: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
! 2146: BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
! 2147:
! 2148: return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
! 2149: }
! 2150:
! 2151: int
! 2152: malo_cmd_set_prescan(struct malo_softc *sc)
! 2153: {
! 2154: struct malo_cmdheader *hdr = sc->sc_cmd_mem;
! 2155:
! 2156: hdr->cmd = htole16(MALO_CMD_SET_PRESCAN);
! 2157: hdr->size = htole16(sizeof(*hdr));
! 2158: hdr->seqnum = 1;
! 2159: hdr->result = 0;
! 2160:
! 2161: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
! 2162: BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
! 2163:
! 2164: return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
! 2165: }
! 2166:
! 2167: int
! 2168: malo_cmd_set_postscan(struct malo_softc *sc, uint8_t *macaddr, uint8_t ibsson)
! 2169: {
! 2170: struct malo_cmdheader *hdr = sc->sc_cmd_mem;
! 2171: struct malo_cmd_postscan *body;
! 2172:
! 2173: hdr->cmd = htole16(MALO_CMD_SET_POSTSCAN);
! 2174: hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
! 2175: hdr->seqnum = 1;
! 2176: hdr->result = 0;
! 2177: body = (struct malo_cmd_postscan *)(hdr + 1);
! 2178:
! 2179: bzero(body, sizeof(*body));
! 2180: memcpy(&body->bssid, macaddr, ETHER_ADDR_LEN);
! 2181: body->isibss = htole32(ibsson);
! 2182:
! 2183: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
! 2184: BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
! 2185:
! 2186: return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
! 2187: }
! 2188:
! 2189: int
! 2190: malo_cmd_set_channel(struct malo_softc *sc, uint8_t channel)
! 2191: {
! 2192: struct malo_cmdheader *hdr = sc->sc_cmd_mem;
! 2193: struct malo_cmd_channel *body;
! 2194:
! 2195: hdr->cmd = htole16(MALO_CMD_SET_CHANNEL);
! 2196: hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
! 2197: hdr->seqnum = 1;
! 2198: hdr->result = 0;
! 2199: body = (struct malo_cmd_channel *)(hdr + 1);
! 2200:
! 2201: bzero(body, sizeof(*body));
! 2202: body->action = htole16(1);
! 2203: body->channel = channel;
! 2204:
! 2205: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
! 2206: BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
! 2207:
! 2208: return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
! 2209: }
! 2210:
! 2211: int
! 2212: malo_cmd_set_antenna(struct malo_softc *sc, uint16_t antenna)
! 2213: {
! 2214: struct malo_cmdheader *hdr = sc->sc_cmd_mem;
! 2215: struct malo_cmd_antenna *body;
! 2216:
! 2217: hdr->cmd = htole16(MALO_CMD_SET_ANTENNA);
! 2218: hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
! 2219: hdr->seqnum = 1;
! 2220: hdr->result = 0;
! 2221: body = (struct malo_cmd_antenna *)(hdr + 1);
! 2222:
! 2223: bzero(body, sizeof(*body));
! 2224: body->action = htole16(antenna);
! 2225: if (antenna == 1)
! 2226: body->mode = htole16(0xffff);
! 2227: else
! 2228: body->mode = htole16(2);
! 2229:
! 2230: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
! 2231: BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
! 2232:
! 2233: return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
! 2234: }
! 2235:
! 2236: int
! 2237: malo_cmd_set_radio(struct malo_softc *sc, uint16_t enable,
! 2238: uint16_t preamble_mode)
! 2239: {
! 2240: struct malo_cmdheader *hdr = sc->sc_cmd_mem;
! 2241: struct malo_cmd_radio *body;
! 2242:
! 2243: hdr->cmd = htole16(MALO_CMD_SET_RADIO);
! 2244: hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
! 2245: hdr->seqnum = 1;
! 2246: hdr->result = 0;
! 2247: body = (struct malo_cmd_radio *)(hdr + 1);
! 2248:
! 2249: bzero(body, sizeof(*body));
! 2250: body->action = htole16(1);
! 2251: body->preamble_mode = htole16(preamble_mode);
! 2252: body->enable = htole16(enable);
! 2253:
! 2254: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
! 2255: BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
! 2256:
! 2257: return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
! 2258: }
! 2259:
! 2260: int
! 2261: malo_cmd_set_aid(struct malo_softc *sc, uint8_t *bssid, uint16_t associd)
! 2262: {
! 2263: struct malo_cmdheader *hdr = sc->sc_cmd_mem;
! 2264: struct malo_cmd_aid *body;
! 2265:
! 2266: hdr->cmd = htole16(MALO_CMD_SET_AID);
! 2267: hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
! 2268: hdr->seqnum = 1;
! 2269: hdr->result = 0;
! 2270: body = (struct malo_cmd_aid *)(hdr + 1);
! 2271:
! 2272: bzero(body, sizeof(*body));
! 2273: body->associd = htole16(associd);
! 2274: memcpy(&body->macaddr[0], bssid, IEEE80211_ADDR_LEN);
! 2275:
! 2276: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
! 2277: BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
CVSweb