]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/isa/if_wi.c
Clean up after removing sys/eventhandler.h from sys/systm.h at the last
[FreeBSD/FreeBSD.git] / sys / i386 / isa / if_wi.c
1 /*
2  * Copyright (c) 1997, 1998, 1999
3  *      Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Bill Paul.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30  * THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  *      $Id: if_wi.c,v 1.9 1999/08/21 06:24:15 msmith Exp $
33  */
34
35 /*
36  * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for FreeBSD.
37  *
38  * Written by Bill Paul <wpaul@ctr.columbia.edu>
39  * Electrical Engineering Department
40  * Columbia University, New York City
41  */
42
43 /*
44  * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
45  * from Lucent. Unlike the older cards, the new ones are programmed
46  * entirely via a firmware-driven controller called the Hermes.
47  * Unfortunately, Lucent will not release the Hermes programming manual
48  * without an NDA (if at all). What they do release is an API library
49  * called the HCF (Hardware Control Functions) which is supposed to
50  * do the device-specific operations of a device driver for you. The
51  * publically available version of the HCF library (the 'HCF Light') is 
52  * a) extremely gross, b) lacks certain features, particularly support
53  * for 802.11 frames, and c) is contaminated by the GNU Public License.
54  *
55  * This driver does not use the HCF or HCF Light at all. Instead, it
56  * programs the Hermes controller directly, using information gleaned
57  * from the HCF Light code and corresponding documentation.
58  *
59  * This driver supports both the PCMCIA and ISA versions of the
60  * WaveLAN/IEEE cards. Note however that the ISA card isn't really
61  * anything of the sort: it's actually a PCMCIA bridge adapter
62  * that fits into an ISA slot, into which a PCMCIA WaveLAN card is
63  * inserted. Consequently, you need to use the pccard support for
64  * both the ISA and PCMCIA adapters.
65  */
66
67 #define WI_HERMES_AUTOINC_WAR   /* Work around data write autoinc bug. */
68 #define WI_HERMES_STATS_WAR     /* Work around stats counter bug. */
69
70 #include "bpf.h"
71 #include "card.h"
72 #include "wi.h"
73
74 #include <sys/param.h>
75 #include <sys/systm.h>
76 #include <sys/eventhandler.h>
77 #include <sys/sockio.h>
78 #include <sys/mbuf.h>
79 #include <sys/malloc.h>
80 #include <sys/kernel.h>
81 #include <sys/socket.h>
82
83 #include <net/if.h>
84 #include <net/if_arp.h>
85 #include <net/ethernet.h>
86 #include <net/if_dl.h>
87 #include <net/if_media.h>
88 #include <net/if_types.h>
89
90 #ifdef INET
91 #include <netinet/in.h>
92 #include <netinet/in_systm.h>
93 #include <netinet/in_var.h>
94 #include <netinet/ip.h>
95 #include <netinet/if_ether.h>
96 #endif
97
98 #if NBPF > 0
99 #include <net/bpf.h>
100 #endif
101
102 #include <machine/clock.h>
103 #include <machine/md_var.h>
104 #include <machine/bus_pio.h>
105 #include <machine/bus.h>
106
107 #include <i386/isa/isa_device.h>
108 #include <i386/isa/icu.h>
109 #include <i386/isa/if_wireg.h>
110 #include <machine/if_wavelan_ieee.h>
111
112 #if NCARD > 0
113 #include <sys/select.h>
114 #include <pccard/cardinfo.h>
115 #include <pccard/slot.h>
116 #endif
117
118 #if !defined(lint)
119 static const char rcsid[] =
120         "$Id: if_wi.c,v 1.9 1999/08/21 06:24:15 msmith Exp $";
121 #endif
122
123 static struct wi_softc wi_softc[NWI];
124
125 #ifdef foo
126 static u_int8_t wi_mcast_addr[6] = { 0x01, 0x60, 0x1D, 0x00, 0x01, 0x00 };
127 #endif
128
129 static int wi_probe             __P((struct isa_device *));
130 static int wi_attach            __P((struct isa_device *));
131 #ifdef PCCARD_MODULE
132 static ointhand2_t              wi_intr;
133 #endif
134 static void wi_reset            __P((struct wi_softc *));
135 static int wi_ioctl             __P((struct ifnet *, u_long, caddr_t));
136 static void wi_init             __P((void *));
137 static void wi_start            __P((struct ifnet *));
138 static void wi_stop             __P((struct wi_softc *));
139 static void wi_watchdog         __P((struct ifnet *));
140 static void wi_shutdown         __P((void *, int));
141 static void wi_rxeof            __P((struct wi_softc *));
142 static void wi_txeof            __P((struct wi_softc *, int));
143 static void wi_update_stats     __P((struct wi_softc *));
144 static void wi_setmulti         __P((struct wi_softc *));
145
146 static int wi_cmd               __P((struct wi_softc *, int, int));
147 static int wi_read_record       __P((struct wi_softc *, struct wi_ltv_gen *));
148 static int wi_write_record      __P((struct wi_softc *, struct wi_ltv_gen *));
149 static int wi_read_data         __P((struct wi_softc *, int,
150                                         int, caddr_t, int));
151 static int wi_write_data        __P((struct wi_softc *, int,
152                                         int, caddr_t, int));
153 static int wi_seek              __P((struct wi_softc *, int, int, int));
154 static int wi_alloc_nicmem      __P((struct wi_softc *, int, int *));
155 static void wi_inquire          __P((void *));
156 static void wi_setdef           __P((struct wi_softc *, struct wi_req *));
157 static int wi_mgmt_xmit         __P((struct wi_softc *, caddr_t, int));
158
159 struct isa_driver widriver = {
160         wi_probe,
161         wi_attach,
162         "wi",
163         1
164 };
165
166 #if NCARD > 0
167 static int wi_pccard_init       __P((struct pccard_devinfo *));
168 static void wi_pccard_unload    __P((struct pccard_devinfo *));
169 static int wi_pccard_intr       __P((struct pccard_devinfo *));
170
171 #ifdef PCCARD_MODULE
172 PCCARD_MODULE(wi, wi_pccard_init, wi_pccard_unload,
173                 wi_pccard_intr, 0, net_imask);
174 #else
175 static struct pccard_device wi_info = {
176         "wi",
177         wi_pccard_init,
178         wi_pccard_unload,
179         wi_pccard_intr,
180         0,                      /* Attributes - presently unused */
181         &net_imask              /* Interrupt mask for device */
182                                 /* XXX - Should this also include net_imask? */
183 };
184
185 DATA_SET(pccarddrv_set, wi_info);
186 #endif
187
188 /* Initialize the PCCARD. */
189 static int wi_pccard_init(sc_p)
190         struct pccard_devinfo   *sc_p;
191 {
192         struct wi_softc         *sc;
193         int                     i;
194         u_int32_t               irq;
195
196         if (sc_p->isahd.id_unit >= NWI)
197                 return(ENODEV);
198
199         sc = &wi_softc[sc_p->isahd.id_unit];
200         sc->wi_gone = 0;
201         sc->wi_unit = sc_p->isahd.id_unit;
202         sc->wi_bhandle = sc_p->isahd.id_iobase;
203         sc->wi_btag = I386_BUS_SPACE_IO;
204
205         /* Make sure interrupts are disabled. */
206         CSR_WRITE_2(sc, WI_INT_EN, 0);
207         CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
208
209         /* Grr. IRQ is encoded as a bitmask. */
210         irq = sc_p->isahd.id_irq;
211         for (i = 0; i < 32; i++) {
212                 if (irq & 0x1)
213                         break;
214                 irq >>= 1;
215         }
216
217         /*
218          * Print a nice probe message to let the operator
219          * know something interesting is happening.
220          */
221         printf("wi%d: <WaveLAN/IEEE 802.11> at 0x%x-0x%x irq %d on isa\n",
222             sc_p->isahd.id_unit, sc_p->isahd.id_iobase,
223             sc_p->isahd.id_iobase + WI_IOSIZ - 1, i);
224
225         if (wi_attach(&sc_p->isahd))
226                 return(ENXIO);
227
228         return(0);
229 }
230
231 static void wi_pccard_unload(sc_p)
232         struct pccard_devinfo   *sc_p;
233 {
234         struct wi_softc         *sc;
235         struct ifnet            *ifp;
236
237         sc = &wi_softc[sc_p->isahd.id_unit];
238         ifp = &sc->arpcom.ac_if;
239
240         if (sc->wi_gone) {
241                 printf("wi%d: already unloaded\n", sc_p->isahd.id_unit);
242                 return;
243         }
244
245         ifp->if_flags &= ~IFF_RUNNING;
246         if_down(ifp);
247         sc->wi_gone = 1;
248         printf("wi%d: unloaded\n", sc_p->isahd.id_unit);
249
250         return;
251 }
252
253 static int wi_pccard_intr(sc_p)
254         struct pccard_devinfo   *sc_p;
255 {
256         wi_intr(sc_p->isahd.id_unit);
257         return(1);
258 }
259 #endif
260
261 static int wi_probe(isa_dev)
262         struct isa_device       *isa_dev;
263 {
264         /*
265          * The ISA WaveLAN/IEEE card is actually not an ISA card:
266          * it's a PCMCIA card plugged into a PCMCIA bridge adapter
267          * that fits into an ISA slot. Consequently, we will always
268          * be using the pccard support to probe and attach these
269          * devices, so we can never actually probe one from here.
270          */
271         return(0);
272 }
273
274 static int wi_attach(isa_dev)
275         struct isa_device       *isa_dev;
276 {
277         struct wi_softc         *sc;
278         struct wi_ltv_macaddr   mac;
279         struct wi_ltv_gen       gen;
280         struct ifnet            *ifp;
281         char                    ifname[IFNAMSIZ];
282
283 #ifdef PCCARD_MODULE
284         isa_dev->id_ointr = wi_intr;
285 #endif
286         sc = &wi_softc[isa_dev->id_unit];
287         ifp = &sc->arpcom.ac_if;
288
289         /* Reset the NIC. */
290         wi_reset(sc);
291
292         /* Read the station address. */
293         mac.wi_type = WI_RID_MAC_NODE;
294         mac.wi_len = 4;
295         wi_read_record(sc, (struct wi_ltv_gen *)&mac);
296         bcopy((char *)&mac.wi_mac_addr,
297            (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
298
299         printf("wi%d: Ethernet address: %6D\n", sc->wi_unit,
300             sc->arpcom.ac_enaddr, ":");
301
302         ifp->if_softc = sc;
303         ifp->if_unit = sc->wi_unit;
304         ifp->if_name = "wi";
305         ifp->if_mtu = ETHERMTU;
306         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
307         ifp->if_ioctl = wi_ioctl;
308         ifp->if_output = ether_output;
309         ifp->if_start = wi_start;
310         ifp->if_watchdog = wi_watchdog;
311         ifp->if_init = wi_init;
312         ifp->if_baudrate = 10000000;
313         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
314
315         bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
316         bcopy(WI_DEFAULT_NODENAME, sc->wi_node_name,
317             sizeof(WI_DEFAULT_NODENAME) - 1);
318
319         bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
320         bcopy(WI_DEFAULT_NETNAME, sc->wi_net_name,
321             sizeof(WI_DEFAULT_NETNAME) - 1);
322
323         bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
324         bcopy(WI_DEFAULT_IBSS, sc->wi_ibss_name,
325             sizeof(WI_DEFAULT_IBSS) - 1);
326
327         sc->wi_portnum = WI_DEFAULT_PORT;
328         sc->wi_ptype = WI_PORTTYPE_ADHOC;
329         sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
330         sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
331         sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
332         sc->wi_max_data_len = WI_DEFAULT_DATALEN;
333         sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
334         sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
335         sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
336
337         /*
338          * Read the default channel from the NIC. This may vary
339          * depending on the country where the NIC was purchased, so
340          * we can't hard-code a default and expect it to work for
341          * everyone.
342          */
343         gen.wi_type = WI_RID_OWN_CHNL;
344         gen.wi_len = 2;
345         wi_read_record(sc, &gen);
346         sc->wi_channel = gen.wi_val;
347
348         bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
349
350         wi_init(sc);
351         wi_stop(sc);
352
353         /*
354          * If this logical interface has already been attached,
355          * don't attach it again or chaos will ensue.
356          */
357         sprintf(ifname, "wi%d", sc->wi_unit);
358
359         if (ifunit(ifname) == NULL) {
360                 callout_handle_init(&sc->wi_stat_ch);
361                 /*
362                  * Call MI attach routines.
363                  */
364                 if_attach(ifp);
365                 ether_ifattach(ifp);
366
367 #if NBPF > 0
368                 bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
369 #endif
370
371                 EVENTHANDLER_REGISTER(shutdown_post_sync, wi_shutdown, sc,
372                                       SHUTDOWN_PRI_DEFAULT);
373         }
374
375         return(0);
376 }
377
378 static void wi_rxeof(sc)
379         struct wi_softc         *sc;
380 {
381         struct ifnet            *ifp;
382         struct ether_header     *eh;
383         struct wi_frame         rx_frame;
384         struct mbuf             *m;
385         int                     id;
386
387         ifp = &sc->arpcom.ac_if;
388
389         id = CSR_READ_2(sc, WI_RX_FID);
390
391         /* First read in the frame header */
392         if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) {
393                 ifp->if_ierrors++;
394                 return;
395         }
396
397         if (rx_frame.wi_status & WI_STAT_ERRSTAT) {
398                 ifp->if_ierrors++;
399                 return;
400         }
401
402         MGETHDR(m, M_DONTWAIT, MT_DATA);
403         if (m == NULL) {
404                 ifp->if_ierrors++;
405                 return;
406         }
407         MCLGET(m, M_DONTWAIT);
408         if (!(m->m_flags & M_EXT)) {
409                 m_freem(m);
410                 ifp->if_ierrors++;
411                 return;
412         }
413
414         eh = mtod(m, struct ether_header *);
415         m->m_pkthdr.rcvif = ifp;
416
417         if (rx_frame.wi_status == WI_STAT_1042 ||
418             rx_frame.wi_status == WI_STAT_TUNNEL ||
419             rx_frame.wi_status == WI_STAT_WMP_MSG) {
420                 if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES) {
421                         printf("wi%d: oversized packet received "
422                             "(wi_dat_len=%d, wi_status=0x%x)\n", sc->wi_unit,
423                             rx_frame.wi_dat_len, rx_frame.wi_status);
424                         m_freem(m);
425                         ifp->if_ierrors++;
426                         return;
427                 }
428                 m->m_pkthdr.len = m->m_len =
429                     rx_frame.wi_dat_len + WI_SNAPHDR_LEN;
430
431                 bcopy((char *)&rx_frame.wi_addr1,
432                     (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
433                 bcopy((char *)&rx_frame.wi_addr2,
434                     (char *)&eh->ether_shost, ETHER_ADDR_LEN);
435                 bcopy((char *)&rx_frame.wi_type,
436                     (char *)&eh->ether_type, sizeof(u_int16_t));
437
438                 if (wi_read_data(sc, id, WI_802_11_OFFSET,
439                     mtod(m, caddr_t) + sizeof(struct ether_header),
440                     m->m_len + 2)) {
441                         m_freem(m);
442                         ifp->if_ierrors++;
443                         return;
444                 }
445         } else {
446                 if((rx_frame.wi_dat_len +
447                     sizeof(struct ether_header)) > MCLBYTES) {
448                         printf("wi%d: oversized packet received "
449                             "(wi_dat_len=%d, wi_status=0x%x)\n", sc->wi_unit,
450                             rx_frame.wi_dat_len, rx_frame.wi_status);
451                         m_freem(m);
452                         ifp->if_ierrors++;
453                         return;
454                 }
455                 m->m_pkthdr.len = m->m_len =
456                     rx_frame.wi_dat_len + sizeof(struct ether_header);
457
458                 if (wi_read_data(sc, id, WI_802_3_OFFSET,
459                     mtod(m, caddr_t), m->m_len + 2)) {
460                         m_freem(m);
461                         ifp->if_ierrors++;
462                         return;
463                 }
464         }
465
466         ifp->if_ipackets++;
467
468 #if NBPF > 0
469         /* Handle BPF listeners. */
470         if (ifp->if_bpf) {
471                 bpf_mtap(ifp, m);
472                 if (ifp->if_flags & IFF_PROMISC &&
473                     (bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
474                     ETHER_ADDR_LEN) && (eh->ether_dhost[0] & 1) == 0)) {
475                         m_freem(m);
476                         return;
477                 }
478         }
479 #endif
480
481         /* Receive packet. */
482         m_adj(m, sizeof(struct ether_header));
483         ether_input(ifp, eh, m);
484
485         return;
486 }
487
488 static void wi_txeof(sc, status)
489         struct wi_softc         *sc;
490         int                     status;
491 {
492         struct ifnet            *ifp;
493
494         ifp = &sc->arpcom.ac_if;
495
496         ifp->if_timer = 0;
497         ifp->if_flags &= ~IFF_OACTIVE;
498
499         if (status & WI_EV_TX_EXC)
500                 ifp->if_oerrors++;
501         else
502                 ifp->if_opackets++;
503
504         return;
505 }
506
507 void wi_inquire(xsc)
508         void                    *xsc;
509 {
510         struct wi_softc         *sc;
511         struct ifnet            *ifp;
512
513         sc = xsc;
514         ifp = &sc->arpcom.ac_if;
515
516         sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);
517
518         /* Don't do this while we're transmitting */
519         if (ifp->if_flags & IFF_OACTIVE)
520                 return;
521
522         wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS);
523
524         return;
525 }
526
527 void wi_update_stats(sc)
528         struct wi_softc         *sc;
529 {
530         struct wi_ltv_gen       gen;
531         u_int16_t               id;
532         struct ifnet            *ifp;
533         u_int32_t               *ptr;
534         int                     i;
535         u_int16_t               t;
536
537         ifp = &sc->arpcom.ac_if;
538
539         id = CSR_READ_2(sc, WI_INFO_FID);
540
541         wi_read_data(sc, id, 0, (char *)&gen, 4);
542
543         if (gen.wi_type != WI_INFO_COUNTERS ||
544             gen.wi_len > (sizeof(sc->wi_stats) / 4) + 1)
545                 return;
546
547         ptr = (u_int32_t *)&sc->wi_stats;
548
549         for (i = 0; i < gen.wi_len - 1; i++) {
550                 t = CSR_READ_2(sc, WI_DATA1);
551 #ifdef WI_HERMES_STATS_WAR
552                 if (t > 0xF000)
553                         t = ~t & 0xFFFF;
554 #endif
555                 ptr[i] += t;
556         }
557
558         ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
559             sc->wi_stats.wi_tx_multi_retries +
560             sc->wi_stats.wi_tx_retry_limit;
561
562         return;
563 }
564
565 void wi_intr(unit)
566         int                     unit;
567 {
568         struct wi_softc         *sc;
569         struct ifnet            *ifp;
570         u_int16_t               status;
571
572         sc = &wi_softc[unit];
573         ifp = &sc->arpcom.ac_if;
574
575         if (!(ifp->if_flags & IFF_UP)) {
576                 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
577                 CSR_WRITE_2(sc, WI_INT_EN, 0);
578                 return;
579         }
580
581         /* Disable interrupts. */
582         CSR_WRITE_2(sc, WI_INT_EN, 0);
583
584         status = CSR_READ_2(sc, WI_EVENT_STAT);
585         CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
586
587         if (status & WI_EV_RX) {
588                 wi_rxeof(sc);
589                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
590         }
591
592         if (status & WI_EV_TX) {
593                 wi_txeof(sc, status);
594                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
595         }
596
597         if (status & WI_EV_ALLOC) {
598                 int                     id;
599                 id = CSR_READ_2(sc, WI_ALLOC_FID);
600                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
601                 if (id == sc->wi_tx_data_id)
602                         wi_txeof(sc, status);
603         }
604
605         if (status & WI_EV_INFO) {
606                 wi_update_stats(sc);
607                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
608         }
609
610         if (status & WI_EV_TX_EXC) {
611                 wi_txeof(sc, status);
612                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
613         }
614
615         if (status & WI_EV_INFO_DROP) {
616                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
617         }
618
619         /* Re-enable interrupts. */
620         CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
621
622         if (ifp->if_snd.ifq_head != NULL)
623                 wi_start(ifp);
624
625         return;
626 }
627
628 static int wi_cmd(sc, cmd, val)
629         struct wi_softc         *sc;
630         int                     cmd;
631         int                     val;
632 {
633         int                     i, s = 0;
634
635         CSR_WRITE_2(sc, WI_PARAM0, val);
636         CSR_WRITE_2(sc, WI_COMMAND, cmd);
637
638         for (i = 0; i < WI_TIMEOUT; i++) {
639                 /*
640                  * Wait for 'command complete' bit to be
641                  * set in the event status register.
642                  */
643                 s = CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD;
644                 if (s) {
645                         /* Ack the event and read result code. */
646                         s = CSR_READ_2(sc, WI_STATUS);
647                         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
648 #ifdef foo
649                         if ((s & WI_CMD_CODE_MASK) != (cmd & WI_CMD_CODE_MASK))
650                                 return(EIO);
651 #endif
652                         if (s & WI_STAT_CMD_RESULT)
653                                 return(EIO);
654                         break;
655                 }
656         }
657
658         if (i == WI_TIMEOUT)
659                 return(ETIMEDOUT);
660
661         return(0);
662 }
663
664 static void wi_reset(sc)
665         struct wi_softc         *sc;
666 {
667         if (wi_cmd(sc, WI_CMD_INI, 0))
668                 printf("wi%d: init failed\n", sc->wi_unit);
669         CSR_WRITE_2(sc, WI_INT_EN, 0);
670         CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
671
672         /* Calibrate timer. */
673         WI_SETVAL(WI_RID_TICK_TIME, 8);
674
675         return;
676 }
677
678 /*
679  * Read an LTV record from the NIC.
680  */
681 static int wi_read_record(sc, ltv)
682         struct wi_softc         *sc;
683         struct wi_ltv_gen       *ltv;
684 {
685         u_int16_t               *ptr;
686         int                     i, len, code;
687
688         /* Tell the NIC to enter record read mode. */
689         if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type))
690                 return(EIO);
691
692         /* Seek to the record. */
693         if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
694                 return(EIO);
695
696         /*
697          * Read the length and record type and make sure they
698          * match what we expect (this verifies that we have enough
699          * room to hold all of the returned data).
700          */
701         len = CSR_READ_2(sc, WI_DATA1);
702         if (len > ltv->wi_len)
703                 return(ENOSPC);
704         code = CSR_READ_2(sc, WI_DATA1);
705         if (code != ltv->wi_type)
706                 return(EIO);
707
708         ltv->wi_len = len;
709         ltv->wi_type = code;
710
711         /* Now read the data. */
712         ptr = &ltv->wi_val;
713         for (i = 0; i < ltv->wi_len - 1; i++)
714                 ptr[i] = CSR_READ_2(sc, WI_DATA1);
715
716         return(0);
717 }
718
719 /*
720  * Same as read, except we inject data instead of reading it.
721  */
722 static int wi_write_record(sc, ltv)
723         struct wi_softc         *sc;
724         struct wi_ltv_gen       *ltv;
725 {
726         u_int16_t               *ptr;
727         int                     i;
728
729         if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
730                 return(EIO);
731
732         CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
733         CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
734
735         ptr = &ltv->wi_val;
736         for (i = 0; i < ltv->wi_len - 1; i++)
737                 CSR_WRITE_2(sc, WI_DATA1, ptr[i]);
738
739         if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type))
740                 return(EIO);
741
742         return(0);
743 }
744
745 static int wi_seek(sc, id, off, chan)
746         struct wi_softc         *sc;
747         int                     id, off, chan;
748 {
749         int                     i;
750         int                     selreg, offreg;
751
752         switch (chan) {
753         case WI_BAP0:
754                 selreg = WI_SEL0;
755                 offreg = WI_OFF0;
756                 break;
757         case WI_BAP1:
758                 selreg = WI_SEL1;
759                 offreg = WI_OFF1;
760                 break;
761         default:
762                 printf("wi%d: invalid data path: %x\n", sc->wi_unit, chan);
763                 return(EIO);
764         }
765
766         CSR_WRITE_2(sc, selreg, id);
767         CSR_WRITE_2(sc, offreg, off);
768
769         for (i = 0; i < WI_TIMEOUT; i++) {
770                 if (!(CSR_READ_2(sc, offreg) & (WI_OFF_BUSY|WI_OFF_ERR)))
771                         break;
772         }
773
774         if (i == WI_TIMEOUT)
775                 return(ETIMEDOUT);
776
777         return(0);
778 }
779
780 static int wi_read_data(sc, id, off, buf, len)
781         struct wi_softc         *sc;
782         int                     id, off;
783         caddr_t                 buf;
784         int                     len;
785 {
786         int                     i;
787         u_int16_t               *ptr;
788
789         if (wi_seek(sc, id, off, WI_BAP1))
790                 return(EIO);
791
792         ptr = (u_int16_t *)buf;
793         for (i = 0; i < len / 2; i++)
794                 ptr[i] = CSR_READ_2(sc, WI_DATA1);
795
796         return(0);
797 }
798
799 /*
800  * According to the comments in the HCF Light code, there is a bug in
801  * the Hermes (or possibly in certain Hermes firmware revisions) where
802  * the chip's internal autoincrement counter gets thrown off during
803  * data writes: the autoincrement is missed, causing one data word to
804  * be overwritten and subsequent words to be written to the wrong memory
805  * locations. The end result is that we could end up transmitting bogus
806  * frames without realizing it. The workaround for this is to write a
807  * couple of extra guard words after the end of the transfer, then
808  * attempt to read then back. If we fail to locate the guard words where
809  * we expect them, we preform the transfer over again.
810  */
811 static int wi_write_data(sc, id, off, buf, len)
812         struct wi_softc         *sc;
813         int                     id, off;
814         caddr_t                 buf;
815         int                     len;
816 {
817         int                     i;
818         u_int16_t               *ptr;
819
820 #ifdef WI_HERMES_AUTOINC_WAR
821 again:
822 #endif
823
824         if (wi_seek(sc, id, off, WI_BAP0))
825                 return(EIO);
826
827         ptr = (u_int16_t *)buf;
828         for (i = 0; i < (len / 2); i++)
829                 CSR_WRITE_2(sc, WI_DATA0, ptr[i]);
830
831 #ifdef WI_HERMES_AUTOINC_WAR
832         CSR_WRITE_2(sc, WI_DATA0, 0x1234);
833         CSR_WRITE_2(sc, WI_DATA0, 0x5678);
834
835         if (wi_seek(sc, id, off + len, WI_BAP0))
836                 return(EIO);
837
838         if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
839             CSR_READ_2(sc, WI_DATA0) != 0x5678)
840                 goto again;
841 #endif
842
843         return(0);
844 }
845
846 /*
847  * Allocate a region of memory inside the NIC and zero
848  * it out.
849  */
850 static int wi_alloc_nicmem(sc, len, id)
851         struct wi_softc         *sc;
852         int                     len;
853         int                     *id;
854 {
855         int                     i;
856
857         if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) {
858                 printf("wi%d: failed to allocate %d bytes on NIC\n",
859                     sc->wi_unit, len);
860                 return(ENOMEM);
861         }
862
863         for (i = 0; i < WI_TIMEOUT; i++) {
864                 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
865                         break;
866         }
867
868         if (i == WI_TIMEOUT)
869                 return(ETIMEDOUT);
870
871         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
872         *id = CSR_READ_2(sc, WI_ALLOC_FID);
873
874         if (wi_seek(sc, *id, 0, WI_BAP0))
875                 return(EIO);
876
877         for (i = 0; i < len / 2; i++)
878                 CSR_WRITE_2(sc, WI_DATA0, 0);
879
880         return(0);
881 }
882
883 static void wi_setmulti(sc)
884         struct wi_softc         *sc;
885 {
886         struct ifnet            *ifp;
887         int                     i = 0;
888         struct ifmultiaddr      *ifma;
889         struct wi_ltv_mcast     mcast;
890
891         ifp = &sc->arpcom.ac_if;
892
893         bzero((char *)&mcast, sizeof(mcast));
894
895         mcast.wi_type = WI_RID_MCAST;
896         mcast.wi_len = (3 * 16) + 1;
897
898         if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
899                 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
900                 return;
901         }
902
903         for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL;
904                                 ifma = ifma->ifma_link.le_next) {
905                 if (ifma->ifma_addr->sa_family != AF_LINK)
906                         continue;
907                 if (i < 16) {
908                         bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
909                             (char *)&mcast.wi_mcast[i], ETHER_ADDR_LEN);
910                         i++;
911                 } else {
912                         bzero((char *)&mcast, sizeof(mcast));
913                         break;
914                 }
915         }
916
917         mcast.wi_len = (i * 3) + 1;
918         wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
919
920         return;
921 }
922
923 static void wi_setdef(sc, wreq)
924         struct wi_softc         *sc;
925         struct wi_req           *wreq;
926 {
927         struct sockaddr_dl      *sdl;
928         struct ifaddr           *ifa;
929         struct ifnet            *ifp;
930
931         ifp = &sc->arpcom.ac_if;
932
933         switch(wreq->wi_type) {
934         case WI_RID_MAC_NODE:
935                 ifa = ifnet_addrs[ifp->if_index - 1];
936                 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
937                 bcopy((char *)&wreq->wi_val, (char *)&sc->arpcom.ac_enaddr,
938                    ETHER_ADDR_LEN);
939                 bcopy((char *)&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
940                 break;
941         case WI_RID_PORTTYPE:
942                 sc->wi_ptype = wreq->wi_val[0];
943                 break;
944         case WI_RID_TX_RATE:
945                 sc->wi_tx_rate = wreq->wi_val[0];
946                 break;
947         case WI_RID_MAX_DATALEN:
948                 sc->wi_max_data_len = wreq->wi_val[0];
949                 break;
950         case WI_RID_RTS_THRESH:
951                 sc->wi_rts_thresh = wreq->wi_val[0];
952                 break;
953         case WI_RID_SYSTEM_SCALE:
954                 sc->wi_ap_density = wreq->wi_val[0];
955                 break;
956         case WI_RID_CREATE_IBSS:
957                 sc->wi_create_ibss = wreq->wi_val[0];
958                 break;
959         case WI_RID_OWN_CHNL:
960                 sc->wi_channel = wreq->wi_val[0];
961                 break;
962         case WI_RID_NODENAME:
963                 bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
964                 bcopy((char *)&wreq->wi_val[1], sc->wi_node_name, 30);
965                 break;
966         case WI_RID_DESIRED_SSID:
967                 bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
968                 bcopy((char *)&wreq->wi_val[1], sc->wi_net_name, 30);
969                 break;
970         case WI_RID_OWN_SSID:
971                 bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
972                 bcopy((char *)&wreq->wi_val[1], sc->wi_ibss_name, 30);
973                 break;
974         case WI_RID_PM_ENABLED:
975                 sc->wi_pm_enabled = wreq->wi_val[0];
976                 break;
977         case WI_RID_MAX_SLEEP:
978                 sc->wi_max_sleep = wreq->wi_val[0];
979                 break;
980         default:
981                 break;
982         }
983
984         /* Reinitialize WaveLAN. */
985         wi_init(sc);
986
987         return;
988 }
989
990 static int wi_ioctl(ifp, command, data)
991         struct ifnet            *ifp;
992         u_long                  command;
993         caddr_t                 data;
994 {
995         int                     s, error = 0;
996         struct wi_softc         *sc;
997         struct wi_req           wreq;
998         struct ifreq            *ifr;
999
1000         s = splimp();
1001
1002         sc = ifp->if_softc;
1003         ifr = (struct ifreq *)data;
1004
1005         if (sc->wi_gone)
1006                 return(ENODEV);
1007
1008         switch(command) {
1009         case SIOCSIFADDR:
1010         case SIOCGIFADDR:
1011         case SIOCSIFMTU:
1012                 error = ether_ioctl(ifp, command, data);
1013                 break;
1014         case SIOCSIFFLAGS:
1015                 if (ifp->if_flags & IFF_UP) {
1016                         if (ifp->if_flags & IFF_RUNNING &&
1017                             ifp->if_flags & IFF_PROMISC &&
1018                             !(sc->wi_if_flags & IFF_PROMISC)) {
1019                                 WI_SETVAL(WI_RID_PROMISC, 1);
1020                         } else if (ifp->if_flags & IFF_RUNNING &&
1021                             !(ifp->if_flags & IFF_PROMISC) &&
1022                             sc->wi_if_flags & IFF_PROMISC) {
1023                                 WI_SETVAL(WI_RID_PROMISC, 0);
1024                         } else
1025                                 wi_init(sc);
1026                 } else {
1027                         if (ifp->if_flags & IFF_RUNNING) {
1028                                 wi_stop(sc);
1029                         }
1030                 }
1031                 sc->wi_if_flags = ifp->if_flags;
1032                 error = 0;
1033                 break;
1034         case SIOCADDMULTI:
1035         case SIOCDELMULTI:
1036                 wi_setmulti(sc);
1037                 error = 0;
1038                 break;
1039         case SIOCGWAVELAN:
1040                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1041                 if (error)
1042                         break;
1043                 if (wreq.wi_type == WI_RID_IFACE_STATS) {
1044                         bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
1045                             sizeof(sc->wi_stats));
1046                         wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1047                 } else {
1048                         if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) {
1049                                 error = EINVAL;
1050                                 break;
1051                         }
1052                 }
1053                 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1054                 break;
1055         case SIOCSWAVELAN:
1056                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1057                 if (error)
1058                         break;
1059                 if (wreq.wi_type == WI_RID_IFACE_STATS) {
1060                         error = EINVAL;
1061                         break;
1062                 } else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
1063                         error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
1064                             wreq.wi_len);
1065                 } else {
1066                         error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
1067                         if (!error)
1068                                 wi_setdef(sc, &wreq);
1069                 }
1070                 break;
1071         default:
1072                 error = EINVAL;
1073                 break;
1074         }
1075
1076         splx(s);
1077
1078         return(error);
1079 }
1080
1081 static void wi_init(xsc)
1082         void                    *xsc;
1083 {
1084         struct wi_softc         *sc = xsc;
1085         struct ifnet            *ifp = &sc->arpcom.ac_if;
1086         int                     s;
1087         struct wi_ltv_macaddr   mac;
1088         int                     id = 0;
1089
1090         if (sc->wi_gone)
1091                 return;
1092
1093         s = splimp();
1094
1095         if (ifp->if_flags & IFF_RUNNING)
1096                 wi_stop(sc);
1097
1098         wi_reset(sc);
1099
1100         /* Program max data length. */
1101         WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
1102
1103         /* Enable/disable IBSS creation. */
1104         WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
1105
1106         /* Set the port type. */
1107         WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
1108
1109         /* Program the RTS/CTS threshold. */
1110         WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
1111
1112         /* Program the TX rate */
1113         WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
1114
1115         /* Access point density */
1116         WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
1117
1118         /* Power Management Enabled */
1119         WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
1120
1121         /* Power Managment Max Sleep */
1122         WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
1123
1124         /* Specify the IBSS name */
1125         WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name);
1126
1127         /* Specify the network name */
1128         WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
1129
1130         /* Specify the frequency to use */
1131         WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
1132
1133         /* Program the nodename. */
1134         WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name);
1135
1136         /* Set our MAC address. */
1137         mac.wi_len = 4;
1138         mac.wi_type = WI_RID_MAC_NODE;
1139         bcopy((char *)&sc->arpcom.ac_enaddr,
1140            (char *)&mac.wi_mac_addr, ETHER_ADDR_LEN);
1141         wi_write_record(sc, (struct wi_ltv_gen *)&mac);
1142
1143         /* Initialize promisc mode. */
1144         if (ifp->if_flags & IFF_PROMISC) {
1145                 WI_SETVAL(WI_RID_PROMISC, 1);
1146         } else {
1147                 WI_SETVAL(WI_RID_PROMISC, 0);
1148         }
1149
1150         /* Set multicast filter. */
1151         wi_setmulti(sc);
1152
1153         /* Enable desired port */
1154         wi_cmd(sc, WI_CMD_ENABLE|sc->wi_portnum, 0);
1155
1156         if (wi_alloc_nicmem(sc, 1518 + sizeof(struct wi_frame) + 8, &id))
1157                 printf("wi%d: tx buffer allocation failed\n", sc->wi_unit);
1158         sc->wi_tx_data_id = id;
1159
1160         if (wi_alloc_nicmem(sc, 1518 + sizeof(struct wi_frame) + 8, &id))
1161                 printf("wi%d: mgmt. buffer allocation failed\n", sc->wi_unit);
1162         sc->wi_tx_mgmt_id = id;
1163
1164         /* enable interrupts */
1165         CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
1166
1167         splx(s);
1168
1169         ifp->if_flags |= IFF_RUNNING;
1170         ifp->if_flags &= ~IFF_OACTIVE;
1171
1172         sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);
1173
1174         return;
1175 }
1176
1177 static void wi_start(ifp)
1178         struct ifnet            *ifp;
1179 {
1180         struct wi_softc         *sc;
1181         struct mbuf             *m0;
1182         struct wi_frame         tx_frame;
1183         struct ether_header     *eh;
1184         int                     id;
1185
1186         sc = ifp->if_softc;
1187
1188         if (sc->wi_gone)
1189                 return;
1190
1191         if (ifp->if_flags & IFF_OACTIVE)
1192                 return;
1193
1194         IF_DEQUEUE(&ifp->if_snd, m0);
1195         if (m0 == NULL)
1196                 return;
1197
1198         bzero((char *)&tx_frame, sizeof(tx_frame));
1199         id = sc->wi_tx_data_id;
1200         eh = mtod(m0, struct ether_header *);
1201
1202         /*
1203          * Use RFC1042 encoding for IP and ARP datagrams,
1204          * 802.3 for anything else.
1205          */
1206         if (ntohs(eh->ether_type) == ETHERTYPE_IP ||
1207             ntohs(eh->ether_type) == ETHERTYPE_ARP ||
1208             ntohs(eh->ether_type) == ETHERTYPE_REVARP) {
1209                 bcopy((char *)&eh->ether_dhost,
1210                     (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
1211                 bcopy((char *)&eh->ether_shost,
1212                     (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
1213                 bcopy((char *)&eh->ether_dhost,
1214                     (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
1215                 bcopy((char *)&eh->ether_shost,
1216                     (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN);
1217
1218                 tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
1219                 tx_frame.wi_frame_ctl = WI_FTYPE_DATA;
1220                 tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
1221                 tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
1222                 tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
1223                 tx_frame.wi_type = eh->ether_type;
1224
1225                 m_copydata(m0, sizeof(struct ether_header),
1226                     m0->m_pkthdr.len - sizeof(struct ether_header),
1227                     (caddr_t)&sc->wi_txbuf);
1228
1229                 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
1230                     sizeof(struct wi_frame));
1231                 wi_write_data(sc, id, WI_802_11_OFFSET, (caddr_t)&sc->wi_txbuf,
1232                     (m0->m_pkthdr.len - sizeof(struct ether_header)) + 2);
1233         } else {
1234                 tx_frame.wi_dat_len = m0->m_pkthdr.len;
1235
1236                 m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&sc->wi_txbuf);
1237
1238                 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
1239                     sizeof(struct wi_frame));
1240                 wi_write_data(sc, id, WI_802_3_OFFSET, (caddr_t)&sc->wi_txbuf,
1241                     m0->m_pkthdr.len + 2);
1242         }
1243
1244 #if NBPF > 0
1245         /*
1246          * If there's a BPF listner, bounce a copy of
1247          * this frame to him.
1248          */
1249         if (ifp->if_bpf)
1250                 bpf_mtap(ifp, m0);
1251 #endif
1252
1253         m_freem(m0);
1254
1255         if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id))
1256                 printf("wi%d: xmit failed\n", sc->wi_unit);
1257
1258         ifp->if_flags |= IFF_OACTIVE;
1259
1260         /*
1261          * Set a timeout in case the chip goes out to lunch.
1262          */
1263         ifp->if_timer = 5;
1264
1265         return;
1266 }
1267
1268 static int wi_mgmt_xmit(sc, data, len)
1269         struct wi_softc         *sc;
1270         caddr_t                 data;
1271         int                     len;
1272 {
1273         struct wi_frame         tx_frame;
1274         int                     id;
1275         struct wi_80211_hdr     *hdr;
1276         caddr_t                 dptr;
1277
1278         if (sc->wi_gone)
1279                 return(ENODEV);
1280
1281         hdr = (struct wi_80211_hdr *)data;
1282         dptr = data + sizeof(struct wi_80211_hdr);
1283
1284         bzero((char *)&tx_frame, sizeof(tx_frame));
1285         id = sc->wi_tx_mgmt_id;
1286
1287         bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl,
1288            sizeof(struct wi_80211_hdr));
1289
1290         tx_frame.wi_dat_len = len - WI_SNAPHDR_LEN;
1291         tx_frame.wi_len = htons(len - WI_SNAPHDR_LEN);
1292
1293         wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
1294         wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
1295             (len - sizeof(struct wi_80211_hdr)) + 2);
1296
1297         if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) {
1298                 printf("wi%d: xmit failed\n", sc->wi_unit);
1299                 return(EIO);
1300         }
1301
1302         return(0);
1303 }
1304
1305 static void wi_stop(sc)
1306         struct wi_softc         *sc;
1307 {
1308         struct ifnet            *ifp;
1309
1310         if (sc->wi_gone)
1311                 return;
1312
1313         ifp = &sc->arpcom.ac_if;
1314
1315         CSR_WRITE_2(sc, WI_INT_EN, 0);
1316         wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0);
1317
1318         untimeout(wi_inquire, sc, sc->wi_stat_ch);
1319
1320         ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
1321
1322         return;
1323 }
1324
1325 static void wi_watchdog(ifp)
1326         struct ifnet            *ifp;
1327 {
1328         struct wi_softc         *sc;
1329
1330         sc = ifp->if_softc;
1331
1332         printf("wi%d: device timeout\n", sc->wi_unit);
1333
1334         wi_init(sc);
1335
1336         ifp->if_oerrors++;
1337
1338         return;
1339 }
1340
1341 static void wi_shutdown(arg, howto)
1342         void                    *arg;
1343         int                     howto;
1344 {
1345         struct wi_softc         *sc;
1346
1347         sc = arg;
1348         wi_stop(sc);
1349
1350         return;
1351 }