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