Annotation of sys/dev/ic/malo.c, Revision 1.1.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);
2278:
2279: return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
2280: }
2281:
2282: int
2283: malo_cmd_set_txpower(struct malo_softc *sc, unsigned int powerlevel)
2284: {
2285: struct malo_cmdheader *hdr = sc->sc_cmd_mem;
2286: struct malo_cmd_txpower *body;
2287:
2288: hdr->cmd = htole16(MALO_CMD_SET_TXPOWER);
2289: hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
2290: hdr->seqnum = 1;
2291: hdr->result = 0;
2292: body = (struct malo_cmd_txpower *)(hdr + 1);
2293:
2294: bzero(body, sizeof(*body));
2295: body->action = htole16(1);
2296: if (powerlevel >= 0 && powerlevel < 30)
2297: body->supportpowerlvl = htole16(5); /* LOW */
2298: else if (powerlevel >= 30 && powerlevel < 60)
2299: body->supportpowerlvl = htole16(10); /* MEDIUM */
2300: else
2301: body->supportpowerlvl = htole16(15); /* HIGH */
2302:
2303: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
2304: BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
2305:
2306: return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
2307: }
2308:
2309: int
2310: malo_cmd_set_rts(struct malo_softc *sc, uint32_t threshold)
2311: {
2312: struct malo_cmdheader *hdr = sc->sc_cmd_mem;
2313:
2314: hdr->cmd = htole16(MALO_CMD_SET_RTS);
2315: hdr->size = htole16(sizeof(*hdr) + sizeof(threshold));
2316: hdr->seqnum = 1;
2317: hdr->result = 0;
2318:
2319: *(uint32_t *)(hdr + 1) = htole32(threshold);
2320:
2321: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
2322: BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
2323:
2324: return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
2325: }
2326:
2327: int
2328: malo_cmd_set_slot(struct malo_softc *sc, uint8_t slot)
2329: {
2330: struct malo_cmdheader *hdr = sc->sc_cmd_mem;
2331: struct malo_cmd_slot *body;
2332:
2333: hdr->cmd = htole16(MALO_CMD_SET_SLOT);
2334: hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
2335: hdr->seqnum = 1;
2336: hdr->result = 0;
2337: body = (struct malo_cmd_slot *)(hdr + 1);
2338:
2339: bzero(body, sizeof(*body));
2340: body->action = htole16(1);
2341: body->slot = slot;
2342:
2343: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
2344: BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
2345:
2346: return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
2347: }
2348:
2349: int
2350: malo_cmd_set_rate(struct malo_softc *sc, uint8_t rate)
2351: {
2352: struct ieee80211com *ic = &sc->sc_ic;
2353: struct malo_cmdheader *hdr = sc->sc_cmd_mem;
2354: struct malo_cmd_rate *body;
2355: int i;
2356:
2357: hdr->cmd = htole16(MALO_CMD_SET_RATE);
2358: hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
2359: hdr->seqnum = 1;
2360: hdr->result = 0;
2361: body = (struct malo_cmd_rate *)(hdr + 1);
2362:
2363: bzero(body, sizeof(*body));
2364:
2365: if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
2366: /* TODO */
2367: } else {
2368: body->aprates[0] = 2;
2369: body->aprates[1] = 4;
2370: body->aprates[2] = 11;
2371: body->aprates[3] = 22;
2372: if (ic->ic_curmode == IEEE80211_MODE_11G) {
2373: body->aprates[4] = 0;
2374: body->aprates[5] = 12;
2375: body->aprates[6] = 18;
2376: body->aprates[7] = 24;
2377: body->aprates[8] = 36;
2378: body->aprates[9] = 48;
2379: body->aprates[10] = 72;
2380: body->aprates[11] = 96;
2381: body->aprates[12] = 108;
2382: }
2383: }
2384:
2385: if (rate != 0) {
2386: /* fixed rate */
2387: for (i = 0; i < 13; i++) {
2388: if (body->aprates[i] == rate) {
2389: body->rateindex = i;
2390: body->dataratetype = 1;
2391: break;
2392: }
2393: }
2394: }
2395:
2396: bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
2397: BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
2398:
2399: return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
2400: }
CVSweb