if_ipw.c revision 1.8
1/*	$Id: if_ipw.c,v 1.8 2004/10/27 21:17:18 damien Exp $  */
2
3/*-
4 * Copyright (c) 2004
5 *      Damien Bergamini <damien.bergamini@free.fr>. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice unmodified, this list of conditions, and the following
12 *    disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30/*-
31 * Intel(R) PRO/Wireless 2100 MiniPCI driver
32 * www.intel.com/network/connectivity/products/wireless/prowireless_mobile.htm
33 */
34
35#include "bpfilter.h"
36
37#include <sys/param.h>
38#include <sys/sockio.h>
39#include <sys/sysctl.h>
40#include <sys/mbuf.h>
41#include <sys/kernel.h>
42#include <sys/socket.h>
43#include <sys/systm.h>
44#include <sys/malloc.h>
45#include <sys/conf.h>
46
47#include <machine/bus.h>
48#include <machine/endian.h>
49#include <machine/intr.h>
50
51#include <dev/pci/pcireg.h>
52#include <dev/pci/pcivar.h>
53#include <dev/pci/pcidevs.h>
54
55#if NBPFILTER > 0
56#include <net/bpf.h>
57#endif
58#include <net/if.h>
59#include <net/if_arp.h>
60#include <net/if_dl.h>
61#include <net/if_media.h>
62#include <net/if_types.h>
63
64#include <netinet/in.h>
65#include <netinet/in_systm.h>
66#include <netinet/in_var.h>
67#include <netinet/if_ether.h>
68#include <netinet/ip.h>
69
70#include <net80211/ieee80211_var.h>
71#include <net80211/ieee80211_radiotap.h>
72
73#include <dev/pci/if_ipwreg.h>
74#include <dev/pci/if_ipwvar.h>
75
76static const struct ieee80211_rateset ipw_rateset_11b =
77	{ 4, { 2, 4, 11, 22 } };
78
79int ipw_match(struct device *, void *, void *);
80void ipw_attach(struct device *, struct device *, void *);
81int ipw_detach(struct device *, int);
82int ipw_media_change(struct ifnet *);
83int ipw_newstate(struct ieee80211com *, enum ieee80211_state, int);
84void ipw_command_intr(struct ipw_softc *, struct ipw_soft_buf *);
85void ipw_newstate_intr(struct ipw_softc *, struct ipw_soft_buf *);
86void ipw_data_intr(struct ipw_softc *, struct ipw_status *,
87    struct ipw_soft_bd *, struct ipw_soft_buf *);
88void ipw_notification_intr(struct ipw_softc *, struct ipw_soft_buf *);
89void ipw_rx_intr(struct ipw_softc *);
90void ipw_release_sbd(struct ipw_softc *, struct ipw_soft_bd *);
91void ipw_tx_intr(struct ipw_softc *);
92int ipw_intr(void *);
93int ipw_cmd(struct ipw_softc *, u_int32_t, void *, u_int32_t);
94int ipw_tx_start(struct ifnet *, struct mbuf *, struct ieee80211_node *);
95void ipw_start(struct ifnet *);
96void ipw_watchdog(struct ifnet *);
97int ipw_get_table1(struct ipw_softc *, u_int32_t *);
98int ipw_get_radio(struct ipw_softc *, int *);
99int ipw_ioctl(struct ifnet *, u_long, caddr_t);
100u_int32_t ipw_read_table1(struct ipw_softc *, u_int32_t);
101void ipw_write_table1(struct ipw_softc *, u_int32_t, u_int32_t);
102int ipw_read_table2(struct ipw_softc *, u_int32_t, void *, u_int32_t *);
103int ipw_tx_init(struct ipw_softc *);
104void ipw_tx_stop(struct ipw_softc *);
105int ipw_rx_init(struct ipw_softc *);
106void ipw_rx_stop(struct ipw_softc *);
107void ipw_reset(struct ipw_softc *);
108int ipw_clock_sync(struct ipw_softc *);
109int ipw_load_ucode(struct ipw_softc *, u_char *, int);
110int ipw_load_firmware(struct ipw_softc *, u_char *, int);
111int ipw_firmware_init(struct ipw_softc *, u_char *);
112int ipw_config(struct ipw_softc *);
113int ipw_init(struct ifnet *);
114void ipw_stop(struct ifnet *, int);
115void ipw_read_mem_1(struct ipw_softc *, bus_size_t, u_int8_t *, bus_size_t);
116void ipw_write_mem_1(struct ipw_softc *, bus_size_t, u_int8_t *, bus_size_t);
117void ipw_zero_mem_4(struct ipw_softc *, bus_size_t, bus_size_t);
118
119static __inline u_int8_t MEM_READ_1(struct ipw_softc *sc, u_int32_t addr)
120{
121	CSR_WRITE_4(sc, IPW_CSR_INDIRECT_ADDR, addr);
122	return CSR_READ_1(sc, IPW_CSR_INDIRECT_DATA);
123}
124
125static __inline u_int32_t MEM_READ_4(struct ipw_softc *sc, u_int32_t addr)
126{
127	CSR_WRITE_4(sc, IPW_CSR_INDIRECT_ADDR, addr);
128	return CSR_READ_4(sc, IPW_CSR_INDIRECT_DATA);
129}
130
131#ifdef IPW_DEBUG
132#define DPRINTF(x)	if (ipw_debug > 0) printf x
133#define DPRINTFN(n, x)	if (ipw_debug >= (n)) printf x
134int ipw_debug = 0;
135#else
136#define DPRINTF(x)
137#define DPRINTFN(n, x)
138#endif
139
140struct cfattach ipw_ca = {
141	sizeof (struct ipw_softc), ipw_match, ipw_attach, ipw_detach
142};
143
144int
145ipw_match(struct device *parent, void *match, void *aux)
146{
147	struct pci_attach_args *pa = aux;
148
149	if (PCI_VENDOR (pa->pa_id) == PCI_VENDOR_INTEL &&
150	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PRO_2100_3B)
151		return 1;
152
153	return 0;
154}
155
156/* Base Address Register */
157#define IPW_PCI_BAR0	0x10
158
159void
160ipw_attach(struct device *parent, struct device *self, void *aux)
161{
162	struct ipw_softc *sc = (struct ipw_softc *)self;
163	struct ieee80211com *ic = &sc->sc_ic;
164	struct ifnet *ifp = &ic->ic_if;
165	struct pci_attach_args *pa = aux;
166	const char *intrstr;
167	bus_space_tag_t memt;
168	bus_space_handle_t memh;
169	bus_addr_t base;
170	pci_intr_handle_t ih;
171	u_int32_t data;
172	int error, i;
173
174	sc->sc_pct = pa->pa_pc;
175
176	/* enable bus-mastering */
177	data = pci_conf_read(sc->sc_pct, pa->pa_tag, PCI_COMMAND_STATUS_REG);
178	data |= PCI_COMMAND_MASTER_ENABLE;
179	pci_conf_write(sc->sc_pct, pa->pa_tag, PCI_COMMAND_STATUS_REG, data);
180
181	/* map the register window */
182	error = pci_mapreg_map(pa, IPW_PCI_BAR0, PCI_MAPREG_TYPE_MEM |
183	    PCI_MAPREG_MEM_TYPE_32BIT, 0, &memt, &memh, &base, &sc->sc_sz, 0);
184	if (error != 0) {
185		printf(": could not map memory space\n");
186		return;
187	}
188
189	sc->sc_st = memt;
190	sc->sc_sh = memh;
191	sc->sc_dmat = pa->pa_dmat;
192
193	/* disable interrupts */
194	CSR_WRITE_4(sc, IPW_CSR_INTR_MASK, 0);
195
196	if (pci_intr_map(pa, &ih) != 0) {
197		printf(": could not map interrupt\n");
198		return;
199	}
200
201	intrstr = pci_intr_string(sc->sc_pct, ih);
202	sc->sc_ih = pci_intr_establish(sc->sc_pct, ih, IPL_NET, ipw_intr, sc,
203	    sc->sc_dev.dv_xname);
204	if (sc->sc_ih == NULL) {
205		printf(": could not establish interrupt");
206		if (intrstr != NULL)
207			printf(" at %s", intrstr);
208		printf("\n");
209		return;
210	}
211	printf(": %s\n", intrstr);
212
213	ic->ic_phytype = IEEE80211_T_DS;
214	ic->ic_opmode = IEEE80211_M_STA;
215	ic->ic_state = IEEE80211_S_INIT;
216
217	/* set device capabilities */
218	ic->ic_caps =  IEEE80211_C_IBSS | IEEE80211_C_MONITOR |
219	    IEEE80211_C_PMGT | IEEE80211_C_TXPMGT | IEEE80211_C_WEP;
220
221	/* set supported .11b rates */
222	ic->ic_sup_rates[IEEE80211_MODE_11B] = ipw_rateset_11b;
223
224	/* set supported .11b channels (1 through 14) */
225	for (i = 1; i <= 14; i++) {
226		ic->ic_channels[i].ic_freq =
227		    ieee80211_ieee2mhz(i, IEEE80211_CHAN_B);
228		ic->ic_channels[i].ic_flags = IEEE80211_CHAN_B;
229	}
230
231	/* default to authmode OPEN */
232	sc->authmode = IEEE80211_AUTH_OPEN;
233
234	/* IBSS channel undefined for now */
235	ic->ic_ibss_chan = &ic->ic_channels[0];
236
237	ifp->if_softc = sc;
238	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
239	ifp->if_init = ipw_init;
240	ifp->if_ioctl = ipw_ioctl;
241	ifp->if_start = ipw_start;
242	ifp->if_watchdog = ipw_watchdog;
243	IFQ_SET_READY(&ifp->if_snd);
244	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
245
246	if_attach(ifp);
247	ieee80211_ifattach(ifp);
248	/* override state transition machine */
249	sc->sc_newstate = ic->ic_newstate;
250	ic->ic_newstate = ipw_newstate;
251	ieee80211_media_init(ifp, ipw_media_change, ieee80211_media_status);
252
253#if NBPFILTER > 0
254	bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
255	    sizeof (struct ieee80211_frame) + 64);
256
257	sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
258	sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
259	sc->sc_rxtap.wr_ihdr.it_present = htole32(IPW_RX_RADIOTAP_PRESENT);
260
261	sc->sc_txtap_len = sizeof sc->sc_txtapu;
262	sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
263	sc->sc_txtap.wt_ihdr.it_present = htole32(IPW_TX_RADIOTAP_PRESENT);
264#endif
265}
266
267int
268ipw_detach(struct device* self, int flags)
269{
270	struct ipw_softc *sc = (struct ipw_softc *)self;
271	struct ifnet *ifp = &sc->sc_ic.ic_if;
272
273	ipw_reset(sc);
274
275#if NBPFILTER > 0
276	bpfdetach(ifp);
277#endif
278	ieee80211_ifdetach(ifp);
279	if_detach(ifp);
280
281	if (sc->sc_ih != NULL) {
282		pci_intr_disestablish(sc->sc_pct, sc->sc_ih);
283		sc->sc_ih = NULL;
284	}
285
286	bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz);
287
288	return 0;
289}
290
291int
292ipw_media_change(struct ifnet *ifp)
293{
294	int error;
295
296	error = ieee80211_media_change(ifp);
297	if (error != ENETRESET)
298		return error;
299
300	if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
301		ipw_init(ifp);
302
303	return 0;
304}
305
306int
307ipw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
308{
309	struct ipw_softc *sc = ic->ic_softc;
310	struct ieee80211_node *ni = ic->ic_bss;
311	u_int32_t val, len;
312
313	switch (nstate) {
314	case IEEE80211_S_RUN:
315		len = IEEE80211_NWID_LEN;
316		ipw_read_table2(sc, IPW_INFO_CURRENT_SSID, ni->ni_essid, &len);
317		ni->ni_esslen = len;
318
319		val = ipw_read_table1(sc, IPW_INFO_CURRENT_CHANNEL);
320		ni->ni_chan = &ic->ic_channels[val];
321
322		DELAY(100); /* firmware needs a short delay here */
323
324		len = IEEE80211_ADDR_LEN;
325		ipw_read_table2(sc, IPW_INFO_CURRENT_BSSID, ni->ni_bssid, &len);
326		break;
327
328	case IEEE80211_S_INIT:
329	case IEEE80211_S_SCAN:
330	case IEEE80211_S_AUTH:
331	case IEEE80211_S_ASSOC:
332		break;
333	}
334
335	ic->ic_state = nstate;
336	return 0;
337}
338
339void
340ipw_command_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
341{
342	struct ipw_cmd *cmd;
343
344	bus_dmamap_sync(sc->sc_dmat, sbuf->map, 0, sizeof (struct ipw_cmd),
345	    BUS_DMASYNC_POSTREAD);
346
347	cmd = mtod(sbuf->m, struct ipw_cmd *);
348
349	DPRINTFN(2, ("RX!CMD!%u!%u!%u!%u!%u\n",
350	    letoh32(cmd->type), letoh32(cmd->subtype), letoh32(cmd->seq),
351	    letoh32(cmd->len), letoh32(cmd->status)));
352
353	/*
354	 * Wake up processes waiting for command ack. In the case of the
355	 * IPW_CMD_DISABLE command, wake up the process only when the adapter
356	 * enters the IPW_STATE_DISABLED state. This is notified in
357	 * ipw_newstate_intr().
358	 */
359	if (letoh32(cmd->type) != IPW_CMD_DISABLE)
360		wakeup(sc->cmd);
361}
362
363void
364ipw_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
365{
366	struct ieee80211com *ic = &sc->sc_ic;
367	u_int32_t state;
368
369	bus_dmamap_sync(sc->sc_dmat, sbuf->map, 0, sizeof state,
370	    BUS_DMASYNC_POSTREAD);
371
372	state = letoh32(*mtod(sbuf->m, u_int32_t *));
373
374	DPRINTFN(2, ("RX!NEWSTATE!%u\n", state));
375
376	switch (state) {
377	case IPW_STATE_ASSOCIATED:
378		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
379		break;
380
381	case IPW_STATE_SCANNING:
382		ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
383		break;
384
385	case IPW_STATE_ASSOCIATION_LOST:
386		ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
387		break;
388
389	case IPW_STATE_DISABLED:
390		wakeup(sc->cmd);
391		break;
392
393	case IPW_STATE_RADIO_DISABLED:
394		/* XXX should turn the interface down */
395		break;
396	}
397}
398
399void
400ipw_data_intr(struct ipw_softc *sc, struct ipw_status *status,
401    struct ipw_soft_bd *sbd, struct ipw_soft_buf *sbuf)
402{
403	struct ieee80211com *ic = &sc->sc_ic;
404	struct ifnet *ifp = &ic->ic_if;
405	struct mbuf *m;
406	struct ieee80211_frame *wh;
407	struct ieee80211_node *ni;
408	int error;
409
410	DPRINTFN(5, ("RX!DATA!%u!%u\n", letoh32(status->len), status->rssi));
411
412	bus_dmamap_sync(sc->sc_dmat, sbuf->map, 0, letoh32(status->len),
413	    BUS_DMASYNC_POSTREAD);
414
415	bus_dmamap_unload(sc->sc_dmat, sbuf->map);
416
417	/* Finalize mbuf */
418	m = sbuf->m;
419	m->m_pkthdr.rcvif = ifp;
420	m->m_pkthdr.len = m->m_len = letoh32(status->len);
421
422#if NBPFILTER > 0
423	if (sc->sc_drvbpf != NULL) {
424		struct mbuf mb;
425		struct ipw_rx_radiotap_header *tap = &sc->sc_rxtap;
426
427		tap->wr_flags = 0;
428		tap->wr_antsignal = status->rssi;
429		tap->wr_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
430		tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
431
432		M_DUP_PKTHDR(&mb, m);
433		mb.m_data = (caddr_t)tap;
434		mb.m_len = sc->sc_rxtap_len;
435		mb.m_next = m;
436		mb.m_pkthdr.len += mb.m_len;
437		bpf_mtap(sc->sc_drvbpf, &mb);
438	}
439#endif
440
441	wh = mtod(m, struct ieee80211_frame *);
442
443	ni = ieee80211_find_rxnode(ic, wh);
444
445	/* Send it up to the upper layer */
446	ieee80211_input(ifp, m, ni, status->rssi, 0);
447
448	if (ni == ic->ic_bss)
449		ieee80211_unref_node(&ni);
450	else
451		ieee80211_free_node(ic, ni);
452
453	MGETHDR(m, M_DONTWAIT, MT_DATA);
454	if (m == NULL) {
455		printf("%s: could not allocate rx mbuf\n",
456		    sc->sc_dev.dv_xname);
457		return;
458	}
459	MCLGET(m, M_DONTWAIT);
460	if (!(m->m_flags & M_EXT)) {
461		m_freem(m);
462		printf("%s: could not allocate rx mbuf cluster\n",
463		    sc->sc_dev.dv_xname);
464		return;
465	}
466
467	error = bus_dmamap_load(sc->sc_dmat, sbuf->map, mtod(m, void *),
468	    MCLBYTES, NULL, BUS_DMA_NOWAIT);
469	if (error != 0) {
470		printf("%s: could not map rxbuf dma memory\n",
471		    sc->sc_dev.dv_xname);
472		m_freem(m);
473		return;
474	}
475
476	sbuf->m = m;
477	sbd->bd->physaddr = htole32(sbuf->map->dm_segs[0].ds_addr);
478}
479
480void
481ipw_notification_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
482{
483	DPRINTFN(2, ("RX!NOTIFICATION\n"));
484}
485
486void
487ipw_rx_intr(struct ipw_softc *sc)
488{
489	struct ipw_status *status;
490	struct ipw_soft_bd *sbd;
491	struct ipw_soft_buf *sbuf;
492	u_int32_t r, i;
493
494	r = CSR_READ_4(sc, IPW_CSR_RX_READ_INDEX);
495
496	for (i = (sc->rxcur + 1) % IPW_NRBD; i != r; i = (i + 1) % IPW_NRBD) {
497
498		bus_dmamap_sync(sc->sc_dmat, sc->rbd_map,
499		    i * sizeof (struct ipw_bd), sizeof (struct ipw_bd),
500		    BUS_DMASYNC_POSTREAD);
501
502		bus_dmamap_sync(sc->sc_dmat, sc->status_map,
503		    i * sizeof (struct ipw_status), sizeof (struct ipw_status),
504		    BUS_DMASYNC_POSTREAD);
505
506		status = &sc->status_list[i];
507		sbd = &sc->srbd_list[i];
508		sbuf = sbd->priv;
509
510		switch (letoh16(status->code) & 0xf) {
511		case IPW_STATUS_CODE_COMMAND:
512			ipw_command_intr(sc, sbuf);
513			break;
514
515		case IPW_STATUS_CODE_NEWSTATE:
516			ipw_newstate_intr(sc, sbuf);
517			break;
518
519		case IPW_STATUS_CODE_DATA_802_3:
520		case IPW_STATUS_CODE_DATA_802_11:
521			ipw_data_intr(sc, status, sbd, sbuf);
522			break;
523
524		case IPW_STATUS_CODE_NOTIFICATION:
525			ipw_notification_intr(sc, sbuf);
526			break;
527
528		default:
529			printf("%s: unknown status code %u\n",
530			    sc->sc_dev.dv_xname, letoh16(status->code));
531		}
532		sbd->bd->flags = 0;
533
534		bus_dmamap_sync(sc->sc_dmat, sc->rbd_map,
535		    i * sizeof (struct ipw_bd), sizeof (struct ipw_bd),
536		    BUS_DMASYNC_PREWRITE);
537	}
538
539	/* Tell the firmware what we have processed */
540	sc->rxcur = (r == 0) ? IPW_NRBD - 1 : r - 1;
541	CSR_WRITE_4(sc, IPW_CSR_RX_WRITE_INDEX, sc->rxcur);
542}
543
544void
545ipw_release_sbd(struct ipw_softc *sc, struct ipw_soft_bd *sbd)
546{
547	struct ieee80211com *ic;
548	struct ipw_soft_hdr *shdr;
549	struct ipw_soft_buf *sbuf;
550
551	switch (sbd->type) {
552	case IPW_SBD_TYPE_COMMAND:
553		bus_dmamap_unload(sc->sc_dmat, sc->cmd_map);
554		break;
555
556	case IPW_SBD_TYPE_HEADER:
557		shdr = sbd->priv;
558		bus_dmamap_unload(sc->sc_dmat, shdr->map);
559		TAILQ_INSERT_TAIL(&sc->sc_free_shdr, shdr, next);
560		break;
561
562	case IPW_SBD_TYPE_DATA:
563		ic = &sc->sc_ic;
564		sbuf = sbd->priv;
565		bus_dmamap_unload(sc->sc_dmat, sbuf->map);
566		m_freem(sbuf->m);
567		if (sbuf->ni != NULL && sbuf->ni != ic->ic_bss)
568			ieee80211_free_node(ic, sbuf->ni);
569		/* kill watchdog timer */
570		sc->sc_tx_timer = 0;
571		TAILQ_INSERT_TAIL(&sc->sc_free_sbuf, sbuf, next);
572		break;
573	}
574	sbd->type = IPW_SBD_TYPE_NOASSOC;
575}
576
577void
578ipw_tx_intr(struct ipw_softc *sc)
579{
580	struct ifnet *ifp = &sc->sc_ic.ic_if;
581	u_int32_t r, i;
582
583	r = CSR_READ_4(sc, IPW_CSR_TX_READ_INDEX);
584
585	for (i = (sc->txold + 1) % IPW_NTBD; i != r; i = (i + 1) % IPW_NTBD)
586		ipw_release_sbd(sc, &sc->stbd_list[i]);
587
588	/* Remember what the firmware has processed */
589	sc->txold = (r == 0) ? IPW_NTBD - 1 : r - 1;
590
591	/* Call start() since some buffer descriptors have been released */
592	ifp->if_flags &= ~IFF_OACTIVE;
593	(*ifp->if_start)(ifp);
594}
595
596int
597ipw_intr(void *arg)
598{
599	struct ipw_softc *sc = arg;
600	u_int32_t r;
601
602	if ((r = CSR_READ_4(sc, IPW_CSR_INTR)) == 0)
603		return 0;
604
605	/* Disable interrupts */
606	CSR_WRITE_4(sc, IPW_CSR_INTR_MASK, 0);
607
608	DPRINTFN(8, ("INTR!0x%08x\n", r));
609
610	if (r & IPW_INTR_RX_TRANSFER)
611		ipw_rx_intr(sc);
612
613	if (r & IPW_INTR_TX_TRANSFER)
614		ipw_tx_intr(sc);
615
616	if (r & IPW_INTR_FW_INIT_DONE) {
617		if (!(r & (IPW_INTR_FATAL_ERROR | IPW_INTR_PARITY_ERROR)))
618			wakeup(sc);
619	}
620
621	/* Acknowledge interrupts */
622	CSR_WRITE_4(sc, IPW_CSR_INTR, r);
623
624	/* Re-enable interrupts */
625	CSR_WRITE_4(sc, IPW_CSR_INTR_MASK, IPW_INTR_MASK);
626
627	return 0;
628}
629
630int
631ipw_cmd(struct ipw_softc *sc, u_int32_t type, void *data, u_int32_t len)
632{
633	struct ipw_soft_bd *sbd;
634	int error;
635
636	sbd = &sc->stbd_list[sc->txcur];
637
638	error = bus_dmamap_load(sc->sc_dmat, sc->cmd_map, sc->cmd,
639	    sizeof (struct ipw_cmd), NULL, BUS_DMA_NOWAIT);
640	if (error != 0) {
641		printf("%s: could not map cmd dma memory\n",
642		    sc->sc_dev.dv_xname);
643		return error;
644	}
645
646	sc->cmd->type = htole32(type);
647	sc->cmd->subtype = htole32(0);
648	sc->cmd->len = htole32(len);
649	sc->cmd->seq = htole32(0);
650	if (data != NULL)
651		bcopy(data, sc->cmd->data, len);
652
653	sbd->type = IPW_SBD_TYPE_COMMAND;
654	sbd->bd->physaddr = htole32(sc->cmd_map->dm_segs[0].ds_addr);
655	sbd->bd->len = htole32(sizeof (struct ipw_cmd));
656	sbd->bd->nfrag = 1;
657	sbd->bd->flags = IPW_BD_FLAG_TX_FRAME_COMMAND |
658			 IPW_BD_FLAG_TX_LAST_FRAGMENT;
659
660	bus_dmamap_sync(sc->sc_dmat, sc->cmd_map, 0, sizeof (struct ipw_cmd),
661	    BUS_DMASYNC_PREWRITE);
662
663	bus_dmamap_sync(sc->sc_dmat, sc->tbd_map,
664	    sc->txcur * sizeof (struct ipw_bd), sizeof (struct ipw_bd),
665	    BUS_DMASYNC_PREWRITE);
666
667	sc->txcur = (sc->txcur + 1) % IPW_NTBD;
668	CSR_WRITE_4(sc, IPW_CSR_TX_WRITE_INDEX, sc->txcur);
669
670	DPRINTFN(2, ("TX!CMD!%u!%u!%u!%u\n", type, 0, 0, len));
671
672	/* Wait at most one second for command to complete */
673	return tsleep(sc->cmd, 0, "ipwcmd", hz);
674}
675
676int
677ipw_tx_start(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni)
678{
679	struct ipw_softc *sc = ifp->if_softc;
680	struct ieee80211com *ic = &sc->sc_ic;
681	struct ieee80211_frame *wh;
682	struct ipw_soft_bd *sbd;
683	struct ipw_soft_hdr *shdr;
684	struct ipw_soft_buf *sbuf;
685	int error, i;
686
687	if (ic->ic_flags & IEEE80211_F_WEPON) {
688		m = ieee80211_wep_crypt(ifp, m, 1);
689		if (m == NULL)
690			return ENOBUFS;
691	}
692
693#if NBPFILTER > 0
694	if (sc->sc_drvbpf != NULL) {
695		struct mbuf mb;
696		struct ipw_tx_radiotap_header *tap = &sc->sc_txtap;
697
698		tap->wt_flags = 0;
699		tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
700		tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
701
702		M_DUP_PKTHDR(&mb, m);
703		mb.m_data = (caddr_t)tap;
704		mb.m_len = sc->sc_txtap_len;
705		mb.m_next = m;
706		mb.m_pkthdr.len += mb.m_len;
707		bpf_mtap(sc->sc_drvbpf, &mb);
708	}
709#endif
710
711	wh = mtod(m, struct ieee80211_frame *);
712
713	shdr = TAILQ_FIRST(&sc->sc_free_shdr);
714	sbuf = TAILQ_FIRST(&sc->sc_free_sbuf);
715
716	shdr->hdr.type = htole32(IPW_HDR_TYPE_SEND);
717	shdr->hdr.subtype = htole32(0);
718	shdr->hdr.encrypted = (wh->i_fc[1] & IEEE80211_FC1_WEP) ? 1 : 0;
719	shdr->hdr.encrypt = 0;
720	shdr->hdr.keyidx = 0;
721	shdr->hdr.keysz = 0;
722	shdr->hdr.fragmentsz = htole16(0);
723	IEEE80211_ADDR_COPY(shdr->hdr.src_addr, wh->i_addr2);
724	if (ic->ic_opmode == IEEE80211_M_STA)
725		IEEE80211_ADDR_COPY(shdr->hdr.dst_addr, wh->i_addr3);
726	else
727		IEEE80211_ADDR_COPY(shdr->hdr.dst_addr, wh->i_addr1);
728
729	/* trim IEEE802.11 header */
730	m_adj(m, sizeof (struct ieee80211_frame));
731
732	/*
733	 * We need to map the mbuf first to know how many buffer descriptors
734	 * are needed for this transfer.
735	 */
736	error = bus_dmamap_load_mbuf(sc->sc_dmat, sbuf->map, m, BUS_DMA_NOWAIT);
737	if (error != 0) {
738		printf("%s: could not map mbuf (error %d)\n",
739		    sc->sc_dev.dv_xname, error);
740		m_freem(m);
741		return error;
742	}
743
744	error = bus_dmamap_load(sc->sc_dmat, shdr->map, &shdr->hdr,
745	    sizeof (struct ipw_hdr), NULL, BUS_DMA_NOWAIT);
746	if (error != 0) {
747		printf("%s: could not map header (error %d)\n",
748		    sc->sc_dev.dv_xname, error);
749		bus_dmamap_unload(sc->sc_dmat, sbuf->map);
750		m_freem(m);
751		return error;
752	}
753
754	TAILQ_REMOVE(&sc->sc_free_sbuf, sbuf, next);
755	TAILQ_REMOVE(&sc->sc_free_shdr, shdr, next);
756
757	sbd = &sc->stbd_list[sc->txcur];
758	sbd->type = IPW_SBD_TYPE_HEADER;
759	sbd->priv = shdr;
760	sbd->bd->physaddr = htole32(shdr->map->dm_segs[0].ds_addr);
761	sbd->bd->len = htole32(sizeof (struct ipw_hdr));
762	sbd->bd->nfrag = 1 + sbuf->map->dm_nsegs;
763	sbd->bd->flags = IPW_BD_FLAG_TX_FRAME_802_3 |
764			 IPW_BD_FLAG_TX_NOT_LAST_FRAGMENT;
765
766	DPRINTFN(5, ("TX!HDR!%u!%u!%u!%u", shdr->hdr.type, shdr->hdr.subtype,
767	    shdr->hdr.encrypted, shdr->hdr.encrypt));
768	DPRINTFN(5, ("!%s", ether_sprintf(shdr->hdr.src_addr)));
769	DPRINTFN(5, ("!%s\n", ether_sprintf(shdr->hdr.dst_addr)));
770
771	bus_dmamap_sync(sc->sc_dmat, sc->tbd_map,
772	    sc->txcur * sizeof (struct ipw_bd),
773	    sizeof (struct ipw_bd), BUS_DMASYNC_PREWRITE);
774
775	sc->txcur = (sc->txcur + 1) % IPW_NTBD;
776
777	sbuf->m = m;
778	sbuf->ni = ni;
779
780	for (i = 0; i < sbuf->map->dm_nsegs; i++) {
781		sbd = &sc->stbd_list[sc->txcur];
782		sbd->bd->physaddr = htole32(sbuf->map->dm_segs[i].ds_addr);
783		sbd->bd->len = htole32(sbuf->map->dm_segs[i].ds_len);
784		sbd->bd->nfrag = 0; /* used only in first bd */
785		sbd->bd->flags = IPW_BD_FLAG_TX_FRAME_802_3;
786		if (i == sbuf->map->dm_nsegs - 1) {
787			sbd->type = IPW_SBD_TYPE_DATA;
788			sbd->priv = sbuf;
789			sbd->bd->flags |= IPW_BD_FLAG_TX_LAST_FRAGMENT;
790		} else {
791			sbd->type = IPW_SBD_TYPE_NOASSOC;
792			sbd->bd->flags |= IPW_BD_FLAG_TX_NOT_LAST_FRAGMENT;
793		}
794
795		DPRINTFN(5, ("TX!FRAG!%d!%d\n", i,
796		    sbuf->map->dm_segs[i].ds_len));
797
798		bus_dmamap_sync(sc->sc_dmat, sc->tbd_map,
799		    sc->txcur * sizeof (struct ipw_bd),
800		    sizeof (struct ipw_bd), BUS_DMASYNC_PREWRITE);
801
802		sc->txcur = (sc->txcur + 1) % IPW_NTBD;
803	}
804
805	bus_dmamap_sync(sc->sc_dmat, shdr->map, 0, sizeof (struct ipw_hdr),
806	    BUS_DMASYNC_PREWRITE);
807
808	bus_dmamap_sync(sc->sc_dmat, sbuf->map, 0, MCLBYTES,
809	    BUS_DMASYNC_PREWRITE);
810
811	/* Inform firmware about this new packet */
812	CSR_WRITE_4(sc, IPW_CSR_TX_WRITE_INDEX, sc->txcur);
813
814	return 0;
815}
816
817void
818ipw_start(struct ifnet *ifp)
819{
820	struct ipw_softc *sc = ifp->if_softc;
821	struct ieee80211com *ic = &sc->sc_ic;
822	struct mbuf *m;
823	struct ieee80211_node *ni;
824
825	for (;;) {
826		IF_DEQUEUE(&ifp->if_snd, m);
827		if (m == NULL)
828			break;
829
830#if NBPFILTER > 0
831		if (ifp->if_bpf != NULL)
832			bpf_mtap(ifp->if_bpf, m);
833#endif
834
835		m = ieee80211_encap(ifp, m, &ni);
836		if (m == NULL)
837			continue;
838
839#if NBPFILTER > 0
840		if (ic->ic_rawbpf != NULL)
841			bpf_mtap(ic->ic_rawbpf, m);
842#endif
843
844		if (ipw_tx_start(ifp, m, ni) != 0) {
845			if (ni != NULL && ni != ic->ic_bss)
846				ieee80211_free_node(ic, ni);
847			break;
848		}
849
850		/* start watchdog timer */
851		sc->sc_tx_timer = 5;
852		ifp->if_timer = 1;
853	}
854}
855
856void
857ipw_watchdog(struct ifnet *ifp)
858{
859	struct ipw_softc *sc = ifp->if_softc;
860
861	ifp->if_timer = 0;
862
863	if (sc->sc_tx_timer > 0) {
864		if (--sc->sc_tx_timer == 0) {
865			printf("%s: device timeout\n", sc->sc_dev.dv_xname);
866#ifdef notyet
867			ipw_init(ifp);
868#endif
869			return;
870		}
871		ifp->if_timer = 1;
872	}
873
874	ieee80211_watchdog(ifp);
875}
876
877int
878ipw_get_table1(struct ipw_softc *sc, u_int32_t *tbl)
879{
880	u_int32_t i, size, buf[256];
881
882	if (!(sc->flags & IPW_FLAG_FW_INITED))
883		return ENOTTY;
884
885	CSR_WRITE_4(sc, IPW_CSR_AUTOINC_ADDR, sc->table1_base);
886
887	size = CSR_READ_4(sc, IPW_CSR_AUTOINC_DATA);
888	for (i = 1; i < size; i++)
889		buf[i] = MEM_READ_4(sc, CSR_READ_4(sc, IPW_CSR_AUTOINC_DATA));
890
891	return copyout(buf, tbl, size * sizeof (u_int32_t));
892}
893
894int
895ipw_get_radio(struct ipw_softc *sc, int *ret)
896{
897	int val;
898
899	if (!(sc->flags & IPW_FLAG_FW_INITED))
900		return ENOTTY;
901
902	val = (CSR_READ_4(sc, IPW_CSR_IO) & IPW_IO_RADIO_DISABLED) ? 0 : 1;
903	return copyout(&val, ret, sizeof val);
904}
905
906int
907ipw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
908{
909	struct ipw_softc *sc = ifp->if_softc;
910	struct ifreq *ifr;
911	struct ifaddr *ifa;
912	int s, error = 0;
913
914	s = splnet();
915
916	switch (cmd) {
917	case SIOCSIFADDR:
918		ifa = (struct ifaddr *) data;
919		ifp->if_flags |= IFF_UP;
920		switch (ifa->ifa_addr->sa_family) {
921#ifdef INET
922		case AF_INET:
923			arp_ifinit(&sc->sc_ic.ic_ac, ifa);
924			ipw_init(ifp);
925			break;
926#endif
927		default:
928			ipw_init(ifp);
929		}
930		break;
931
932	case SIOCSIFFLAGS:
933		if (ifp->if_flags & IFF_UP) {
934			if (!(ifp->if_flags & IFF_RUNNING))
935				ipw_init(ifp);
936		} else {
937			if (ifp->if_flags & IFF_RUNNING)
938				ipw_stop(ifp, 1);
939		}
940		break;
941
942	case SIOCGTABLE1:
943		ifr = (struct ifreq *)data;
944		error = ipw_get_table1(sc, (u_int32_t *)ifr->ifr_data);
945		break;
946
947	case SIOCGRADIO:
948		ifr = (struct ifreq *)data;
949		error = ipw_get_radio(sc, (int *)ifr->ifr_data);
950		break;
951
952	case SIOCSLOADFW:
953		/* only super-user can do that! */
954		if ((error = suser(curproc, 0)) != 0)
955			break;
956
957		ifr = (struct ifreq *)data;
958		error = ipw_firmware_init(sc, (u_char *)ifr->ifr_data);
959		break;
960
961	case SIOCSKILLFW:
962		/* only super-user can do that! */
963		if ((error = suser(curproc, 0)) != 0)
964			break;
965
966		ipw_reset(sc);
967		break;
968
969	case SIOCG80211AUTH:
970		((struct ieee80211_auth *)data)->i_authtype = sc->authmode;
971		break;
972
973	case SIOCS80211AUTH:
974		/* only super-user can do that! */
975		if ((error = suser(curproc, 0)) != 0)
976			break;
977
978		sc->authmode = ((struct ieee80211_auth *)data)->i_authtype;
979		break;
980
981	default:
982		error = ieee80211_ioctl(ifp, cmd, data);
983	}
984
985	if (error == ENETRESET && cmd != SIOCADDMULTI) {
986		if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
987		    (IFF_UP | IFF_RUNNING))
988			ipw_init(ifp);
989		error = 0;
990	}
991
992	splx(s);
993	return error;
994}
995
996u_int32_t
997ipw_read_table1(struct ipw_softc *sc, u_int32_t off)
998{
999	return MEM_READ_4(sc, MEM_READ_4(sc, sc->table1_base + off));
1000}
1001
1002void
1003ipw_write_table1(struct ipw_softc *sc, u_int32_t off, u_int32_t info)
1004{
1005	MEM_WRITE_4(sc, MEM_READ_4(sc, sc->table1_base + off), info);
1006}
1007
1008int
1009ipw_read_table2(struct ipw_softc *sc, u_int32_t off, void *buf, u_int32_t *len)
1010{
1011	u_int32_t addr, info;
1012	u_int16_t count, size;
1013	u_int32_t total;
1014
1015	/* addr[4] + count[2] + size[2] */
1016	addr = MEM_READ_4(sc, sc->table2_base + off);
1017	info = MEM_READ_4(sc, sc->table2_base + off + 4);
1018
1019	count = info >> 16;
1020	size = info & 0xffff;
1021	total = count * size;
1022
1023	if (total > *len) {
1024		*len = total;
1025		return EINVAL;
1026	}
1027
1028	*len = total;
1029	ipw_read_mem_1(sc, addr, buf, total);
1030
1031	return 0;
1032}
1033
1034int
1035ipw_tx_init(struct ipw_softc *sc)
1036{
1037	char *errmsg;
1038	struct ipw_bd *bd;
1039	struct ipw_soft_bd *sbd;
1040	struct ipw_soft_hdr *shdr;
1041	struct ipw_soft_buf *sbuf;
1042	int error, i, nsegs;
1043
1044	/* Allocate transmission buffer descriptors */
1045	error = bus_dmamap_create(sc->sc_dmat, IPW_TBD_SZ, 1, IPW_TBD_SZ, 0,
1046	    BUS_DMA_NOWAIT, &sc->tbd_map);
1047	if (error != 0) {
1048		errmsg = "could not create tbd dma map";
1049		goto fail;
1050	}
1051
1052	error = bus_dmamem_alloc(sc->sc_dmat, IPW_TBD_SZ, PAGE_SIZE, 0,
1053	    &sc->tbd_seg, 1, &nsegs, BUS_DMA_NOWAIT);
1054	if (error != 0) {
1055		errmsg = "could not allocate tbd dma memory";
1056		goto fail;
1057	}
1058
1059	error = bus_dmamem_map(sc->sc_dmat, &sc->tbd_seg, nsegs, IPW_TBD_SZ,
1060	    (caddr_t *)&sc->tbd_list, BUS_DMA_NOWAIT);
1061	if (error != 0) {
1062		errmsg = "could not map tbd dma memory";
1063		goto fail;
1064	}
1065
1066	error = bus_dmamap_load(sc->sc_dmat, sc->tbd_map, sc->tbd_list,
1067	    IPW_TBD_SZ, NULL, BUS_DMA_NOWAIT);
1068	if (error != 0) {
1069		errmsg = "could not load tbd dma memory";
1070		goto fail;
1071	}
1072
1073	sc->stbd_list = malloc(IPW_NTBD * sizeof (struct ipw_soft_bd),
1074	    M_DEVBUF, M_NOWAIT);
1075	if (sc->stbd_list == NULL) {
1076		errmsg = "could not allocate soft tbd";
1077		error = ENOMEM;
1078		goto fail;
1079	}
1080	sbd = sc->stbd_list;
1081	bd = sc->tbd_list;
1082	for (i = 0; i < IPW_NTBD; i++, sbd++, bd++) {
1083		sbd->type = IPW_SBD_TYPE_NOASSOC;
1084		sbd->bd = bd;
1085	}
1086
1087	CSR_WRITE_4(sc, IPW_CSR_TX_BD_BASE, sc->tbd_map->dm_segs[0].ds_addr);
1088	CSR_WRITE_4(sc, IPW_CSR_TX_BD_SIZE, IPW_NTBD);
1089	CSR_WRITE_4(sc, IPW_CSR_TX_READ_INDEX, 0);
1090	CSR_WRITE_4(sc, IPW_CSR_TX_WRITE_INDEX, 0);
1091	sc->txold = IPW_NTBD - 1; /* latest bd index ack'ed by firmware */
1092	sc->txcur = 0; /* bd index to write to */
1093
1094	/* Allocate a DMA-able command */
1095	error = bus_dmamap_create(sc->sc_dmat, sizeof (struct ipw_cmd), 1,
1096	    sizeof (struct ipw_cmd), 0, BUS_DMA_NOWAIT, &sc->cmd_map);
1097	if (error != 0) {
1098		errmsg = "could not create cmd dma map";
1099		goto fail;
1100	}
1101
1102	error = bus_dmamem_alloc(sc->sc_dmat, sizeof (struct ipw_cmd),
1103	    PAGE_SIZE, 0, &sc->cmd_seg, 1, &nsegs, BUS_DMA_NOWAIT);
1104	if (error != 0) {
1105		errmsg = "could not allocate cmd dma memory";
1106		goto fail;
1107	}
1108
1109	error = bus_dmamem_map(sc->sc_dmat, &sc->cmd_seg, nsegs,
1110	    sizeof (struct ipw_cmd), (caddr_t *)&sc->cmd, BUS_DMA_NOWAIT);
1111	if (error != 0) {
1112		errmsg = "could not map cmd dma memory";
1113		goto fail;
1114	}
1115
1116	/* Allocate a pool of DMA-able headers */
1117	sc->shdr_list = malloc(IPW_NDATA * sizeof (struct ipw_soft_hdr),
1118	    M_DEVBUF, M_NOWAIT);
1119	if (sc->shdr_list == NULL) {
1120		errmsg = "could not allocate soft hdr";
1121		error = ENOMEM;
1122		goto fail;
1123	}
1124	TAILQ_INIT(&sc->sc_free_shdr);
1125	for (i = 0, shdr = sc->shdr_list; i < IPW_NDATA; i++, shdr++) {
1126		error = bus_dmamap_create(sc->sc_dmat,
1127		    sizeof (struct ipw_soft_hdr), 1,
1128	 	    sizeof (struct ipw_soft_hdr), 0, BUS_DMA_NOWAIT,
1129		    &shdr->map);
1130		if (error != 0) {
1131			errmsg = "could not create hdr dma map";
1132			goto fail;
1133		}
1134		TAILQ_INSERT_TAIL(&sc->sc_free_shdr, shdr, next);
1135	}
1136
1137	/* Allocate a pool of DMA-able buffers */
1138	sc->tx_sbuf_list = malloc(IPW_NDATA * sizeof (struct ipw_soft_buf),
1139	    M_DEVBUF, M_NOWAIT);
1140	if (sc->tx_sbuf_list == NULL) {
1141		errmsg = "could not allocate soft txbuf";
1142		error = ENOMEM;
1143		goto fail;
1144	}
1145	TAILQ_INIT(&sc->sc_free_sbuf);
1146	for (i = 0, sbuf = sc->tx_sbuf_list; i < IPW_NDATA; i++, sbuf++) {
1147		error = bus_dmamap_create(sc->sc_dmat, IPW_NDATA * MCLBYTES,
1148		    IPW_NDATA, MCLBYTES, 0, BUS_DMA_NOWAIT, &sbuf->map);
1149		if (error != 0) {
1150			errmsg = "could not create txbuf dma map";
1151			goto fail;
1152		}
1153		TAILQ_INSERT_TAIL(&sc->sc_free_sbuf, sbuf, next);
1154	}
1155
1156	return 0;
1157
1158fail:	printf("%s: %s\n", sc->sc_dev.dv_xname, errmsg);
1159	ipw_tx_stop(sc);
1160
1161	return error;
1162}
1163
1164void
1165ipw_tx_stop(struct ipw_softc *sc)
1166{
1167	struct ipw_soft_hdr *shdr;
1168	struct ipw_soft_buf *sbuf;
1169	int i;
1170
1171	if (sc->tbd_map != NULL) {
1172		if (sc->tbd_list != NULL) {
1173			bus_dmamap_unload(sc->sc_dmat, sc->tbd_map);
1174			bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->tbd_list,
1175			    IPW_TBD_SZ);
1176			bus_dmamem_free(sc->sc_dmat, &sc->tbd_seg, 1);
1177			sc->tbd_list = NULL;
1178		}
1179		bus_dmamap_destroy(sc->sc_dmat, sc->tbd_map);
1180		sc->tbd_map = NULL;
1181	}
1182
1183	if (sc->stbd_list != NULL) {
1184		for (i = 0; i < IPW_NTBD; i++)
1185			ipw_release_sbd(sc, &sc->stbd_list[i]);
1186		free(sc->stbd_list, M_DEVBUF);
1187		sc->stbd_list = NULL;
1188	}
1189
1190	if (sc->cmd_map != NULL) {
1191		if (sc->cmd != NULL) {
1192			bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->cmd,
1193			    sizeof (struct ipw_cmd));
1194			bus_dmamem_free(sc->sc_dmat, &sc->cmd_seg, 1);
1195			sc->cmd = NULL;
1196		}
1197		bus_dmamap_destroy(sc->sc_dmat, sc->cmd_map);
1198		sc->cmd_map = NULL;
1199	}
1200
1201	if (sc->shdr_list != NULL) {
1202		TAILQ_FOREACH(shdr, &sc->sc_free_shdr, next)
1203			bus_dmamap_destroy(sc->sc_dmat, shdr->map);
1204		free(sc->shdr_list, M_DEVBUF);
1205		sc->shdr_list = NULL;
1206	}
1207
1208
1209	if (sc->tx_sbuf_list != NULL) {
1210		TAILQ_FOREACH(sbuf, &sc->sc_free_sbuf, next)
1211			bus_dmamap_destroy(sc->sc_dmat, sbuf->map);
1212		free(sc->tx_sbuf_list, M_DEVBUF);
1213		sc->tx_sbuf_list = NULL;
1214	}
1215}
1216
1217int
1218ipw_rx_init(struct ipw_softc *sc)
1219{
1220	char *errmsg;
1221	struct ipw_bd *bd;
1222	struct ipw_soft_bd *sbd;
1223	struct ipw_soft_buf *sbuf;
1224	int error, i, nsegs;
1225
1226	/* Allocate reception buffer descriptors */
1227	error = bus_dmamap_create(sc->sc_dmat, IPW_RBD_SZ, 1, IPW_RBD_SZ, 0,
1228	    BUS_DMA_NOWAIT, &sc->rbd_map);
1229	if (error != 0) {
1230		errmsg = "could not create rbd dma map";
1231		goto fail;
1232	}
1233
1234	error = bus_dmamem_alloc(sc->sc_dmat, IPW_RBD_SZ, PAGE_SIZE, 0,
1235	    &sc->rbd_seg, 1, &nsegs, BUS_DMA_NOWAIT);
1236	if (error != 0) {
1237		errmsg = "could not allocate rbd dma memory";
1238		goto fail;
1239	}
1240
1241	error = bus_dmamem_map(sc->sc_dmat, &sc->rbd_seg, nsegs, IPW_RBD_SZ,
1242	    (caddr_t *)&sc->rbd_list, BUS_DMA_NOWAIT);
1243	if (error != 0) {
1244		errmsg = "could not map rbd dma memory";
1245		goto fail;
1246	}
1247
1248	error = bus_dmamap_load(sc->sc_dmat, sc->rbd_map, sc->rbd_list,
1249	    IPW_RBD_SZ, NULL, BUS_DMA_NOWAIT);
1250	if (error != 0) {
1251		errmsg = "could not load rbd dma memory";
1252		goto fail;
1253	}
1254
1255	sc->srbd_list = malloc(IPW_NRBD * sizeof (struct ipw_soft_bd),
1256	    M_DEVBUF, M_NOWAIT);
1257	if (sc->srbd_list == NULL) {
1258		errmsg = "could not allocate soft rbd";
1259		error = ENOMEM;
1260		goto fail;
1261	}
1262	sbd = sc->srbd_list;
1263	bd = sc->rbd_list;
1264	for (i = 0; i < IPW_NRBD; i++, sbd++, bd++) {
1265		sbd->type = IPW_SBD_TYPE_NOASSOC;
1266		sbd->bd = bd;
1267	}
1268
1269	CSR_WRITE_4(sc, IPW_CSR_RX_BD_BASE, sc->rbd_map->dm_segs[0].ds_addr);
1270	CSR_WRITE_4(sc, IPW_CSR_RX_BD_SIZE, IPW_NRBD);
1271	CSR_WRITE_4(sc, IPW_CSR_RX_READ_INDEX, 0);
1272	CSR_WRITE_4(sc, IPW_CSR_RX_WRITE_INDEX, IPW_NRBD - 1);
1273	sc->rxcur = IPW_NRBD - 1; /* latest bd index I've read */
1274
1275	/* Allocate status descriptors */
1276	error = bus_dmamap_create(sc->sc_dmat, IPW_STATUS_SZ, 1, IPW_STATUS_SZ,
1277	    0, BUS_DMA_NOWAIT, &sc->status_map);
1278	if (error != 0) {
1279		errmsg = "could not create status dma map";
1280		goto fail;
1281	}
1282
1283	error = bus_dmamem_alloc(sc->sc_dmat, IPW_STATUS_SZ, PAGE_SIZE, 0,
1284	    &sc->status_seg, 1, &nsegs, BUS_DMA_NOWAIT);
1285	if (error != 0) {
1286		errmsg = "could not allocate status dma memory";
1287		goto fail;
1288	}
1289
1290	error = bus_dmamem_map(sc->sc_dmat, &sc->status_seg, nsegs,
1291	    IPW_STATUS_SZ, (caddr_t *)&sc->status_list, BUS_DMA_NOWAIT);
1292	if (error != 0) {
1293		errmsg = "could not map status dma memory";
1294		goto fail;
1295	}
1296
1297	error = bus_dmamap_load(sc->sc_dmat, sc->status_map, sc->status_list,
1298	    IPW_STATUS_SZ, NULL, BUS_DMA_NOWAIT);
1299	if (error != 0) {
1300		errmsg = "could not load status dma memory";
1301		goto fail;
1302	}
1303
1304	CSR_WRITE_4(sc, IPW_CSR_RX_STATUS_BASE,
1305	    sc->status_map->dm_segs[0].ds_addr);
1306
1307	sc->rx_sbuf_list = malloc(IPW_NRBD * sizeof (struct ipw_soft_buf),
1308	    M_DEVBUF, M_NOWAIT);
1309	if (sc->rx_sbuf_list == NULL) {
1310		errmsg = "could not allocate soft rxbuf";
1311		error = ENOMEM;
1312		goto fail;
1313	}
1314
1315	sbuf = sc->rx_sbuf_list;
1316	sbd = sc->srbd_list;
1317	for (i = 0; i < IPW_NRBD; i++, sbuf++, sbd++) {
1318
1319		MGETHDR(sbuf->m, M_DONTWAIT, MT_DATA);
1320		if (sbuf->m == NULL) {
1321			errmsg = "could not allocate rx mbuf";
1322			error = ENOMEM;
1323			goto fail;
1324		}
1325		MCLGET(sbuf->m, M_DONTWAIT);
1326		if (!(sbuf->m->m_flags & M_EXT)) {
1327			m_freem(sbuf->m);
1328			errmsg = "could not allocate rx mbuf cluster";
1329			error = ENOMEM;
1330			goto fail;
1331		}
1332
1333		error = bus_dmamap_create(sc->sc_dmat, IPW_NRBD * MCLBYTES,
1334		    IPW_NRBD, MCLBYTES, 0, BUS_DMA_NOWAIT, &sbuf->map);
1335		if (error != 0) {
1336			m_freem(sbuf->m);
1337			errmsg = "could not create rxbuf dma map";
1338			goto fail;
1339		}
1340		error = bus_dmamap_load(sc->sc_dmat, sbuf->map,
1341		    mtod(sbuf->m, void *), MCLBYTES, NULL, BUS_DMA_NOWAIT);
1342		if (error != 0) {
1343			bus_dmamap_destroy(sc->sc_dmat, sbuf->map);
1344			m_freem(sbuf->m);
1345			errmsg = "could not map rxbuf dma memory";
1346			goto fail;
1347		}
1348		sbd->type = IPW_SBD_TYPE_DATA;
1349		sbd->priv = sbuf;
1350		sbd->bd->physaddr = htole32(sbuf->map->dm_segs[0].ds_addr);
1351		sbd->bd->len = htole32(MCLBYTES);
1352	}
1353
1354	return 0;
1355
1356fail:	printf("%s: %s\n", sc->sc_dev.dv_xname, errmsg);
1357	ipw_rx_stop(sc);
1358
1359	return error;
1360}
1361
1362void
1363ipw_rx_stop(struct ipw_softc *sc)
1364{
1365	struct ipw_soft_bd *sbd;
1366	struct ipw_soft_buf *sbuf;
1367	int i;
1368
1369	if (sc->rbd_map != NULL) {
1370		if (sc->rbd_list != NULL) {
1371			bus_dmamap_unload(sc->sc_dmat, sc->rbd_map);
1372			bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->rbd_list,
1373			    IPW_RBD_SZ);
1374			bus_dmamem_free(sc->sc_dmat, &sc->rbd_seg, 1);
1375			sc->rbd_list = NULL;
1376		}
1377		bus_dmamap_destroy(sc->sc_dmat, sc->rbd_map);
1378		sc->rbd_map = NULL;
1379	}
1380
1381	if (sc->status_map != NULL) {
1382		if (sc->status_list != NULL) {
1383			bus_dmamap_unload(sc->sc_dmat, sc->status_map);
1384			bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->status_list,
1385			    IPW_STATUS_SZ);
1386			bus_dmamem_free(sc->sc_dmat, &sc->status_seg, 1);
1387			sc->status_list = NULL;
1388		}
1389		bus_dmamap_destroy(sc->sc_dmat, sc->status_map);
1390		sc->status_map = NULL;
1391	}
1392
1393	if (sc->srbd_list != NULL) {
1394		for (i = 0, sbd = sc->srbd_list; i < IPW_NRBD; i++, sbd++) {
1395			if (sbd->type == IPW_SBD_TYPE_NOASSOC)
1396				continue;
1397
1398			sbuf = sbd->priv;
1399			bus_dmamap_unload(sc->sc_dmat, sbuf->map);
1400			bus_dmamap_destroy(sc->sc_dmat, sbuf->map);
1401			m_freem(sbuf->m);
1402		}
1403		free(sc->srbd_list, M_DEVBUF);
1404		sc->srbd_list = NULL;
1405	}
1406
1407	if (sc->rx_sbuf_list != NULL) {
1408		free(sc->rx_sbuf_list, M_DEVBUF);
1409		sc->rx_sbuf_list = NULL;
1410	}
1411}
1412
1413void
1414ipw_reset(struct ipw_softc *sc)
1415{
1416	struct ifnet *ifp = &sc->sc_ic.ic_if;
1417	int ntries;
1418
1419	ipw_stop(ifp, 1);
1420
1421	if (sc->flags & IPW_FLAG_FW_INITED) {
1422		ipw_cmd(sc, IPW_CMD_DISABLE_PHY, NULL, 0);
1423		ipw_cmd(sc, IPW_CMD_PREPARE_POWER_DOWN, NULL, 0);
1424
1425		sc->flags &= ~IPW_FLAG_FW_INITED;
1426	}
1427
1428	/* Disable interrupts */
1429	CSR_WRITE_4(sc, IPW_CSR_INTR_MASK, 0);
1430
1431	CSR_WRITE_4(sc, IPW_CSR_RST, IPW_RST_STOP_MASTER);
1432	for (ntries = 0; ntries < 5; ntries++) {
1433		if (CSR_READ_4(sc, IPW_CSR_RST) & IPW_RST_MASTER_DISABLED)
1434			break;
1435		DELAY(10);
1436	}
1437
1438	CSR_WRITE_4(sc, IPW_CSR_RST, IPW_RST_SW_RESET);
1439
1440	ipw_rx_stop(sc);
1441	ipw_tx_stop(sc);
1442
1443	ifp->if_flags &= ~IFF_UP;
1444}
1445
1446int
1447ipw_clock_sync(struct ipw_softc *sc)
1448{
1449	int ntries;
1450	u_int32_t r;
1451
1452	CSR_WRITE_4(sc, IPW_CSR_RST, IPW_RST_SW_RESET);
1453	for (ntries = 0; ntries < 1000; ntries++) {
1454		if (CSR_READ_4(sc, IPW_CSR_RST) & IPW_RST_PRINCETON_RESET)
1455			break;
1456		DELAY(10);
1457	}
1458	if (ntries == 1000)
1459		return EIO;
1460
1461	CSR_WRITE_4(sc, IPW_CSR_CTL, IPW_CTL_INIT);
1462	for (ntries = 0; ntries < 1000; ntries++) {
1463		if ((r = CSR_READ_4(sc, IPW_CSR_CTL)) & IPW_CTL_CLOCK_READY)
1464			break;
1465		DELAY(200);
1466	}
1467	if (ntries == 1000)
1468		return EIO;
1469
1470	CSR_WRITE_4(sc, IPW_CSR_CTL, r | IPW_CTL_ALLOW_STANDBY);
1471
1472	return 0;
1473}
1474
1475int
1476ipw_load_ucode(struct ipw_softc *sc, u_char *uc, int size)
1477{
1478	int ntries;
1479
1480	MEM_WRITE_2(sc, 0x220000, 0x0703);
1481	MEM_WRITE_2(sc, 0x220000, 0x0707);
1482
1483	MEM_WRITE_1(sc, 0x210014, 0x72);
1484	MEM_WRITE_1(sc, 0x210014, 0x72);
1485
1486	MEM_WRITE_1(sc, 0x210000, 0x40);
1487	MEM_WRITE_1(sc, 0x210000, 0x00);
1488	MEM_WRITE_1(sc, 0x210000, 0x40);
1489
1490	MEM_WRITE_MULTI_1(sc, 0x210010, uc, size);
1491
1492	MEM_WRITE_1(sc, 0x210000, 0x00);
1493	MEM_WRITE_1(sc, 0x210000, 0x00);
1494	MEM_WRITE_1(sc, 0x210000, 0x80);
1495
1496	MEM_WRITE_2(sc, 0x220000, 0x0703);
1497	MEM_WRITE_2(sc, 0x220000, 0x0707);
1498
1499	MEM_WRITE_1(sc, 0x210014, 0x72);
1500	MEM_WRITE_1(sc, 0x210014, 0x72);
1501
1502	MEM_WRITE_1(sc, 0x210000, 0x00);
1503	MEM_WRITE_1(sc, 0x210000, 0x80);
1504
1505	for (ntries = 0; ntries < 10; ntries++) {
1506		if (MEM_READ_1(sc, 0x210000) & 1)
1507			break;
1508		DELAY(10);
1509	}
1510	if (ntries == 10)
1511		return EIO;
1512
1513	return 0;
1514}
1515
1516/* set of macros to handle unaligned little endian data in firmware image */
1517#define GETLE32(p) ((p)[0] | (p)[1] << 8 | (p)[2] << 16 | (p)[3] << 24)
1518#define GETLE16(p) ((p)[0] | (p)[1] << 8)
1519int
1520ipw_load_firmware(struct ipw_softc *sc, u_char *fw, int size)
1521{
1522	u_char *p, *end;
1523	u_int32_t dst;
1524	u_int16_t len;
1525
1526	p = fw;
1527	end = fw + size;
1528	while (p < end) {
1529		if (p + 6 > end)
1530			return EINVAL;
1531
1532		dst = GETLE32(p); p += 4;
1533		len = GETLE16(p); p += 2;
1534
1535		if (p + len > end)
1536			return EINVAL;
1537
1538		ipw_write_mem_1(sc, dst, p, len);
1539		p += len;
1540	}
1541	return 0;
1542}
1543
1544int
1545ipw_firmware_init(struct ipw_softc *sc, u_char *data)
1546{
1547	struct ieee80211com *ic = &sc->sc_ic;
1548	struct ifnet *ifp = &ic->ic_if;
1549	struct ipw_fw_hdr hdr;
1550	u_int32_t r, len, fw_size, uc_size;
1551	u_char *fw, *uc;
1552	int error;
1553
1554	ipw_reset(sc);
1555
1556	if ((error = copyin(data, &hdr, sizeof hdr)) != 0)
1557		goto fail1;
1558
1559	fw_size = letoh32(hdr.fw_size);
1560	uc_size = letoh32(hdr.uc_size);
1561	data += sizeof hdr;
1562
1563	if ((fw = malloc(fw_size, M_DEVBUF, M_NOWAIT)) == NULL) {
1564		error = ENOMEM;
1565		goto fail1;
1566	}
1567
1568	if ((error = copyin(data, fw, fw_size)) != 0)
1569		goto fail2;
1570
1571	data += fw_size;
1572
1573	if ((uc = malloc(uc_size, M_DEVBUF, M_NOWAIT)) == NULL) {
1574		error = ENOMEM;
1575		goto fail2;
1576	}
1577
1578	if ((error = copyin(data, uc, uc_size)) != 0)
1579		goto fail3;
1580
1581	if ((error = ipw_clock_sync(sc)) != 0) {
1582		printf("%s: clock synchronization failed\n",
1583		    sc->sc_dev.dv_xname);
1584		goto fail3;
1585	}
1586
1587	MEM_WRITE_4(sc, 0x003000e0, 0x80000000);
1588
1589	CSR_WRITE_4(sc, IPW_CSR_RST, 0);
1590
1591	if ((error = ipw_load_ucode(sc, uc, uc_size)) != 0) {
1592		printf("%s: could not load microcode\n", sc->sc_dev.dv_xname);
1593		goto fail3;
1594	}
1595
1596	MEM_WRITE_4(sc, 0x003000e0, 0);
1597
1598	if ((error = ipw_clock_sync(sc)) != 0) {
1599		printf("%s: clock synchronization failed\n",
1600		    sc->sc_dev.dv_xname);
1601		goto fail3;
1602	}
1603
1604	if ((error = ipw_load_firmware(sc, fw, fw_size))) {
1605		printf("%s: could not load firmware\n", sc->sc_dev.dv_xname);
1606		goto fail3;
1607	}
1608
1609	ipw_zero_mem_4(sc, 0x0002f200, 196);
1610	ipw_zero_mem_4(sc, 0x0002f610, 8);
1611	ipw_zero_mem_4(sc, 0x0002fa00, 8);
1612	ipw_zero_mem_4(sc, 0x0002fc00, 4);
1613	ipw_zero_mem_4(sc, 0x0002ff80, 32);
1614
1615	if ((error = ipw_rx_init(sc)) != 0) {
1616		printf("%s: could not initialize rx queue\n",
1617		    sc->sc_dev.dv_xname);
1618		goto fail3;
1619	}
1620
1621	if ((error = ipw_tx_init(sc)) != 0) {
1622		printf("%s: could not initialize tx queue\n",
1623		    sc->sc_dev.dv_xname);
1624		goto fail3;
1625	}
1626
1627	CSR_WRITE_4(sc, IPW_CSR_IO, IPW_IO_GPIO1_ENABLE | IPW_IO_GPIO3_MASK |
1628	    IPW_IO_LED_OFF);
1629
1630	/* Allow interrupts so we know when the firmware is inited */
1631	CSR_WRITE_4(sc, IPW_CSR_INTR_MASK, IPW_INTR_MASK);
1632
1633	/* Tell the adapter to initialize the firmware */
1634	CSR_WRITE_4(sc, IPW_CSR_RST, 0);
1635
1636	/* Wait at most one second for firmware initialization to complete */
1637	if ((error = tsleep(sc, 0, "ipwinit", hz)) != 0) {
1638		printf("%s: timeout waiting for firmware initialization to "
1639		    "complete\n", sc->sc_dev.dv_xname);
1640		goto fail3;
1641	}
1642
1643	/* Firmware initialization completed */
1644	sc->flags |= IPW_FLAG_FW_INITED;
1645
1646	free(uc, M_DEVBUF);
1647	free(fw, M_DEVBUF);
1648
1649	r = CSR_READ_4(sc, IPW_CSR_IO);
1650	CSR_WRITE_4(sc, IPW_CSR_IO, r | IPW_IO_GPIO1_MASK | IPW_IO_GPIO3_MASK);
1651
1652	/* Retrieve information tables base addresses */
1653	sc->table1_base = CSR_READ_4(sc, IPW_CSR_TABLE1_BASE);
1654	sc->table2_base = CSR_READ_4(sc, IPW_CSR_TABLE2_BASE);
1655
1656	ipw_write_table1(sc, IPW_INFO_LOCK, 0);
1657
1658	/* Retrieve adapter MAC address */
1659	len = IEEE80211_ADDR_LEN;
1660	ipw_read_table2(sc, IPW_INFO_ADAPTER_MAC, ic->ic_myaddr, &len);
1661
1662	IEEE80211_ADDR_COPY(LLADDR(ifp->if_sadl), ic->ic_myaddr);
1663
1664	return 0;
1665
1666fail3:	free(uc, M_DEVBUF);
1667fail2:	free(fw, M_DEVBUF);
1668fail1:	ipw_reset(sc);
1669
1670	return error;
1671}
1672
1673int
1674ipw_config(struct ipw_softc *sc)
1675{
1676	struct ieee80211com *ic = &sc->sc_ic;
1677	struct ifnet *ifp = &ic->ic_if;
1678	struct ipw_security security;
1679	struct ieee80211_wepkey *k;
1680	struct ipw_wep_key wepkey;
1681	struct ipw_scan_options options;
1682	struct ipw_configuration config;
1683	u_int32_t data;
1684	int error, i;
1685
1686	switch (ic->ic_opmode) {
1687	case IEEE80211_M_STA:
1688	case IEEE80211_M_HOSTAP:
1689		data = htole32(IPW_MODE_BSS);
1690		break;
1691
1692	case IEEE80211_M_IBSS:
1693	case IEEE80211_M_AHDEMO:
1694		data = htole32(IPW_MODE_IBSS);
1695		break;
1696
1697	case IEEE80211_M_MONITOR:
1698		data = htole32(IPW_MODE_MONITOR);
1699		break;
1700	}
1701	DPRINTF(("Setting adapter mode to %u\n", data));
1702	error = ipw_cmd(sc, IPW_CMD_SET_MODE, &data, sizeof data);
1703	if (error != 0)
1704		return error;
1705
1706	if (ic->ic_opmode == IEEE80211_M_IBSS ||
1707	    ic->ic_opmode == IEEE80211_M_MONITOR) {
1708		data = htole32(ieee80211_chan2ieee(ic, ic->ic_ibss_chan));
1709		DPRINTF(("Setting adapter channel to %u\n", data));
1710		error = ipw_cmd(sc, IPW_CMD_SET_CHANNEL, &data, sizeof data);
1711		if (error != 0)
1712			return error;
1713	}
1714
1715	if (ic->ic_opmode == IEEE80211_M_MONITOR) {
1716		DPRINTF(("Enabling adapter\n"));
1717		return ipw_cmd(sc, IPW_CMD_ENABLE, NULL, 0);
1718	}
1719
1720	DPRINTF(("Setting adapter MAC to %s\n", ether_sprintf(ic->ic_myaddr)));
1721	IEEE80211_ADDR_COPY(((struct arpcom *)ifp)->ac_enaddr, ic->ic_myaddr);
1722	IEEE80211_ADDR_COPY(LLADDR(ifp->if_sadl), ic->ic_myaddr);
1723	error = ipw_cmd(sc, IPW_CMD_SET_MAC_ADDRESS, ic->ic_myaddr,
1724	    IEEE80211_ADDR_LEN);
1725	if (error != 0)
1726		return error;
1727
1728	config.flags = htole32(IPW_CFG_BSS_MASK | IPW_CFG_IBSS_MASK |
1729			       IPW_CFG_PREAMBLE_LEN | IPW_CFG_802_1x_ENABLE);
1730	if (ic->ic_opmode == IEEE80211_M_IBSS)
1731		config.flags |= htole32(IPW_CFG_IBSS_AUTO_START);
1732	if (ifp->if_flags & IFF_PROMISC)
1733		config.flags |= htole32(IPW_CFG_PROMISCUOUS);
1734	config.channels = htole32(0x3fff); /* channels 1-14 */
1735	config.ibss_chan = htole32(0x7ff);
1736	DPRINTF(("Setting adapter configuration 0x%08x\n", config.flags));
1737	error = ipw_cmd(sc, IPW_CMD_SET_CONFIGURATION, &config, sizeof config);
1738	if (error != 0)
1739		return error;
1740
1741	data = htole32(0x3); /* 1, 2 */
1742	DPRINTF(("Setting adapter basic tx rates to 0x%x\n", data));
1743	error = ipw_cmd(sc, IPW_CMD_SET_BASIC_TX_RATES, &data, sizeof data);
1744	if (error != 0)
1745		return error;
1746
1747	data = htole32(0xf); /* 1, 2, 5.5, 11 */
1748	DPRINTF(("Setting adapter tx rates to 0x%x\n", data));
1749	error = ipw_cmd(sc, IPW_CMD_SET_TX_RATES, &data, sizeof data);
1750	if (error != 0)
1751		return error;
1752
1753	data = htole32(IPW_POWER_MODE_CAM);
1754	DPRINTF(("Setting adapter power mode to %u\n", data));
1755	error = ipw_cmd(sc, IPW_CMD_SET_POWER_MODE, &data, sizeof data);
1756	if (error != 0)
1757		return error;
1758
1759	if (ic->ic_opmode == IEEE80211_M_IBSS) {
1760		data = htole32(ic->ic_txpower);
1761		DPRINTF(("Setting adapter tx power index to %u\n", data));
1762		error = ipw_cmd(sc, IPW_CMD_SET_TX_POWER_INDEX, &data,
1763		    sizeof data);
1764		if (error != 0)
1765			return error;
1766	}
1767
1768	data = htole32(ic->ic_rtsthreshold);
1769	DPRINTF(("Setting adapter RTS threshold to %u\n", data));
1770	error = ipw_cmd(sc, IPW_CMD_SET_RTS_THRESHOLD, &data, sizeof data);
1771	if (error != 0)
1772		return error;
1773
1774	data = htole32(ic->ic_fragthreshold);
1775	DPRINTF(("Setting adapter frag threshold to %u\n", data));
1776	error = ipw_cmd(sc, IPW_CMD_SET_FRAG_THRESHOLD, &data, sizeof data);
1777	if (error != 0)
1778		return error;
1779
1780#ifdef IPW_DEBUG
1781	if (ipw_debug > 0) {
1782		printf("Setting adapter ESSID to ");
1783		ieee80211_print_essid(ic->ic_des_essid, ic->ic_des_esslen);
1784		printf("\n");
1785	}
1786#endif
1787	error = ipw_cmd(sc, IPW_CMD_SET_ESSID, ic->ic_des_essid,
1788	    ic->ic_des_esslen);
1789	if (error != 0)
1790		return error;
1791
1792	/* no mandatory BSSID */
1793	error = ipw_cmd(sc, IPW_CMD_SET_MANDATORY_BSSID, NULL, 0);
1794	if (error != 0)
1795		return error;
1796
1797	if (ic->ic_flags & IEEE80211_F_DESBSSID) {
1798		DPRINTF(("Setting adapter desired BSSID to %s\n",
1799		    ether_sprintf(ic->ic_des_bssid)));
1800		error = ipw_cmd(sc, IPW_CMD_SET_DESIRED_BSSID,
1801		    ic->ic_des_bssid, IEEE80211_ADDR_LEN);
1802		if (error != 0)
1803			return error;
1804	}
1805
1806	security.authmode = (sc->authmode == IEEE80211_AUTH_SHARED) ?
1807	    IPW_AUTH_SHARED : IPW_AUTH_OPEN;
1808	security.ciphers = htole32(IPW_CIPHER_NONE);
1809	security.version = htole16(0);
1810	security.replay_counters_number = 0;
1811	security.unicast_using_group = 0;
1812	DPRINTF(("Setting adapter authmode to %u\n", security.authmode));
1813	error = ipw_cmd(sc, IPW_CMD_SET_SECURITY_INFORMATION, &security,
1814	    sizeof security);
1815	if (error != 0)
1816		return error;
1817
1818	if (ic->ic_flags & IEEE80211_F_WEPON) {
1819		k = ic->ic_nw_keys;
1820		for (i = 0; i < IEEE80211_WEP_NKID; i++, k++) {
1821			if (k->wk_len == 0)
1822				continue;
1823
1824			wepkey.idx = i;
1825			wepkey.len = k->wk_len;
1826			bzero(wepkey.key, sizeof wepkey.key);
1827			bcopy(k->wk_key, wepkey.key, k->wk_len);
1828			DPRINTF(("Setting wep key index %d len %d\n",
1829			    wepkey.idx, wepkey.len));
1830			error = ipw_cmd(sc, IPW_CMD_SET_WEP_KEY, &wepkey,
1831			    sizeof wepkey);
1832			if (error != 0)
1833				return error;
1834		}
1835
1836		data = htole32(ic->ic_wep_txkey);
1837		DPRINTF(("Setting adapter tx key index to %u\n", data));
1838		error = ipw_cmd(sc, IPW_CMD_SET_WEP_KEY_INDEX, &data,
1839		    sizeof data);
1840		if (error != 0)
1841			return error;
1842	}
1843
1844	data = htole32((sc->sc_ic.ic_flags & IEEE80211_F_WEPON) ? 0x8 : 0);
1845	DPRINTF(("Setting adapter wep flags to 0x%x\n", data));
1846	error = ipw_cmd(sc, IPW_CMD_SET_WEP_FLAGS, &data, sizeof data);
1847	if (error != 0)
1848		return error;
1849
1850	if (ic->ic_opmode == IEEE80211_M_IBSS ||
1851	    ic->ic_opmode == IEEE80211_M_HOSTAP) {
1852		data = htole32(ic->ic_lintval);
1853		DPRINTF(("Setting adapter beacon interval to %u\n", data));
1854		error = ipw_cmd(sc, IPW_CMD_SET_BEACON_INTERVAL, &data,
1855		    sizeof data);
1856		if (error != 0)
1857			return error;
1858	}
1859
1860	options.flags = htole32(0);
1861	options.channels = htole32(0x3fff); /* scan channels 1-14 */
1862	error = ipw_cmd(sc, IPW_CMD_SET_SCAN_OPTIONS, &options, sizeof options);
1863	if (error != 0)
1864		return error;
1865
1866	/* finally, enable adapter (start scanning for an access point) */
1867	DPRINTF(("Enabling adapter\n"));
1868	return ipw_cmd(sc, IPW_CMD_ENABLE, NULL, 0);
1869}
1870
1871int
1872ipw_init(struct ifnet *ifp)
1873{
1874	struct ipw_softc *sc = ifp->if_softc;
1875
1876	/* exit immediately if firmware has not been ioctl'd */
1877	if (!(sc->flags & IPW_FLAG_FW_INITED)) {
1878		ifp->if_flags &= ~IFF_UP;
1879		return EIO;
1880	}
1881
1882	ipw_stop(ifp, 0);
1883
1884	if (ipw_config(sc) != 0) {
1885		printf("%s: device configuration failed\n",
1886		    sc->sc_dev.dv_xname);
1887		goto fail;
1888	}
1889
1890	ifp->if_flags &= ~IFF_OACTIVE;
1891	ifp->if_flags |= IFF_RUNNING;
1892
1893	return 0;
1894
1895fail:	ipw_stop(ifp, 0);
1896
1897	return EIO;
1898}
1899
1900void
1901ipw_stop(struct ifnet *ifp, int disable)
1902{
1903	struct ipw_softc *sc = ifp->if_softc;
1904	struct ieee80211com *ic = &sc->sc_ic;
1905
1906	if (ifp->if_flags & IFF_RUNNING) {
1907		DPRINTF(("Disabling adapter\n"));
1908		ipw_cmd(sc, IPW_CMD_DISABLE, NULL, 0);
1909	}
1910
1911	ifp->if_timer = 0;
1912	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1913
1914	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
1915}
1916
1917void
1918ipw_read_mem_1(struct ipw_softc *sc, bus_size_t offset, u_int8_t *datap,
1919    bus_size_t count)
1920{
1921	for (; count > 0; offset++, datap++, count--) {
1922		CSR_WRITE_4(sc, IPW_CSR_INDIRECT_ADDR, offset & ~3);
1923		*datap = CSR_READ_1(sc, IPW_CSR_INDIRECT_DATA + (offset & 3));
1924	}
1925}
1926
1927void
1928ipw_write_mem_1(struct ipw_softc *sc, bus_size_t offset, u_int8_t *datap,
1929    bus_size_t count)
1930{
1931	for (; count > 0; offset++, datap++, count--) {
1932		CSR_WRITE_4(sc, IPW_CSR_INDIRECT_ADDR, offset & ~3);
1933		CSR_WRITE_1(sc, IPW_CSR_INDIRECT_DATA + (offset & 3), *datap);
1934	}
1935}
1936
1937void
1938ipw_zero_mem_4(struct ipw_softc *sc, bus_size_t offset, bus_size_t count)
1939{
1940	CSR_WRITE_4(sc, IPW_CSR_AUTOINC_ADDR, offset);
1941	while (count-- > 0)
1942		CSR_WRITE_4(sc, IPW_CSR_AUTOINC_DATA, 0);
1943}
1944
1945struct cfdriver ipw_cd = {
1946	0, "ipw", DV_IFNET
1947};
1948