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