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