1 /* $OpenBSD: an.c,v 1.34 2003/10/21 18:58:48 jmc Exp $ */
2
3 /*
4 * Copyright (c) 1997, 1998, 1999
5 * Bill Paul <wpaul@ctr.columbia.edu>. 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, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Bill Paul.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 * $FreeBSD: src/sys/dev/an/if_an.c,v 1.21 2001/09/10 02:05:09 brooks Exp $
35 */
36
37 /*
38 * Aironet 4500/4800 802.11 PCMCIA/ISA/PCI driver for FreeBSD.
39 *
40 * Written by Bill Paul <wpaul@ctr.columbia.edu>
41 * Electrical Engineering Department
42 * Columbia University, New York City
43 */
44
45 /*
46 * The Aironet 4500/4800 series cards some in PCMCIA, ISA and PCI form.
47 * This driver supports all three device types (PCI devices are supported
48 * through an extra PCI shim: /sys/pci/if_an_p.c). ISA devices can be
49 * supported either using hard-coded IO port/IRQ settings or via Plug
50 * and Play. The 4500 series devices support 1Mbps and 2Mbps data rates.
51 * The 4800 devices support 1, 2, 5.5 and 11Mbps rates.
52 *
53 * Like the WaveLAN/IEEE cards, the Aironet NICs are all essentially
54 * PCMCIA devices. The ISA and PCI cards are a combination of a PCMCIA
55 * device and a PCMCIA to ISA or PCMCIA to PCI adapter card. There are
56 * a couple of important differences though:
57 *
58 * - Lucent doesn't currently offer a PCI card, however Aironet does
59 * - Lucent ISA card looks to the host like a PCMCIA controller with
60 * a PCMCIA WaveLAN card inserted. This means that even desktop
61 * machines need to be configured with PCMCIA support in order to
62 * use WaveLAN/IEEE ISA cards. The Aironet cards on the other hand
63 * actually look like normal ISA and PCI devices to the host, so
64 * no PCMCIA controller support is needed
65 *
66 * The latter point results in a small gotcha. The Aironet PCMCIA
67 * cards can be configured for one of two operating modes depending
68 * on how the Vpp1 and Vpp2 programming voltages are set when the
69 * card is activated. In order to put the card in proper PCMCIA
70 * operation (where the CIS table is visible and the interface is
71 * programmed for PCMCIA operation), both Vpp1 and Vpp2 have to be
72 * set to 5 volts. FreeBSD by default doesn't set the Vpp voltages,
73 * which leaves the card in ISA/PCI mode, which prevents it from
74 * being activated as an PCMCIA device. Consequently, /sys/pccard/pccard.c
75 * has to be patched slightly in order to enable the Vpp voltages in
76 * order to make the Aironet PCMCIA cards work.
77 *
78 * Note that some PCMCIA controller software packages for Windows NT
79 * fail to set the voltages as well.
80 *
81 * The Aironet devices can operate in both station mode and access point
82 * mode. Typically, when programmed for station mode, the card can be set
83 * to automatically perform encapsulation/decapsulation of Ethernet II
84 * and 802.3 frames within 802.11 frames so that the host doesn't have
85 * to do it itself. This driver doesn't program the card that way: the
86 * driver handles all of the encapsulation/decapsulation itself.
87 */
88
89 #ifdef INET
90 #define ANCACHE /* enable signal strength cache */
91 #endif
92
93 #include <sys/param.h>
94 #include <sys/systm.h>
95 #include <sys/device.h>
96 #include <sys/sockio.h>
97 #include <sys/mbuf.h>
98 #include <sys/malloc.h>
99 #include <sys/kernel.h>
100 #include <sys/proc.h>
101 #include <sys/socket.h>
102 #include <sys/timeout.h>
103 #ifdef ANCACHE
104 #include <sys/syslog.h>
105 #include <sys/sysctl.h>
106 #endif
107
108 #include <net/if.h>
109 #include <net/if_dl.h>
110 #include <net/if_media.h>
111 #include <net/if_types.h>
112
113 #ifdef INET
114 #include <netinet/in.h>
115 #include <netinet/in_systm.h>
116 #include <netinet/in_var.h>
117 #include <netinet/ip.h>
118 #include <netinet/if_ether.h>
119 #endif
120
121 #include "bpfilter.h"
122 #if NBPFILTER > 0
123 #include <net/bpf.h>
124 #endif
125
126 #include <machine/bus.h>
127
128 #include <dev/ic/anvar.h>
129 #include <dev/ic/anreg.h>
130
131 #define TIMEOUT(handle,func,sc,time) timeout_add(&(handle), (time))
132 #define UNTIMEOUT(func,sc,handle) timeout_del(&(handle))
133 #define BPF_MTAP(if,mbuf) bpf_mtap((if)->if_bpf, (mbuf))
134 #define BPFATTACH(if_bpf,if,dlt,sz)
135
136 struct cfdriver an_cd = {
137 NULL, "an", DV_IFNET
138 };
139
140 void an_reset(struct an_softc *);
141 int an_ioctl(struct ifnet *, u_long, caddr_t);
142 int an_init_tx_ring(struct an_softc *);
143 void an_start(struct ifnet *);
144 void an_watchdog(struct ifnet *);
145 void an_rxeof(struct an_softc *);
146 void an_txeof(struct an_softc *, int);
147
148 void an_promisc(struct an_softc *, int);
149 int an_cmd(struct an_softc *, int, int);
150 int an_read_record(struct an_softc *, struct an_ltv_gen *);
151 int an_write_record(struct an_softc *, struct an_ltv_gen *);
152 int an_read_data(struct an_softc *, int,
153 int, caddr_t, int);
154 int an_write_data(struct an_softc *, int,
155 int, caddr_t, int);
156 int an_seek(struct an_softc *, int, int, int);
157 int an_alloc_nicmem(struct an_softc *, int, int *);
158 void an_stats_update(void *);
159 void an_setdef(struct an_softc *, struct an_req *);
160 #ifdef ANCACHE
161 void an_cache_store(struct an_softc *, struct ether_header *,
162 struct mbuf *, unsigned short);
163 #endif
164 int an_media_change(struct ifnet *);
165 void an_media_status(struct ifnet *, struct ifmediareq *);
166
167 static __inline void
an_swap16(u_int16_t * p,int cnt)168 an_swap16(u_int16_t *p, int cnt)
169 {
170 for (; cnt--; p++)
171 *p = swap16(*p);
172 }
173
174 int
an_attach(sc)175 an_attach(sc)
176 struct an_softc *sc;
177 {
178 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
179
180 sc->an_gone = 0;
181 sc->an_associated = 0;
182
183 /* disable interrupts */
184 CSR_WRITE_2(sc, AN_INT_EN, 0);
185 CSR_WRITE_2(sc, AN_EVENT_ACK, 0xffff);
186
187 /* Reset the NIC. */
188 an_reset(sc);
189
190 /* Load factory config */
191 if (an_cmd(sc, AN_CMD_READCFG, 0)) {
192 printf("%s: failed to load config data\n", ifp->if_xname);
193 return(EIO);
194 }
195
196 /* Read the current configuration */
197 sc->an_config.an_type = AN_RID_GENCONFIG;
198 sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
199 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_config)) {
200 printf("%s: read record failed\n", ifp->if_xname);
201 return(EIO);
202 }
203
204 /* Read the card capabilities */
205 sc->an_caps.an_type = AN_RID_CAPABILITIES;
206 sc->an_caps.an_len = sizeof(struct an_ltv_caps);
207 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_caps)) {
208 printf("%s: read record failed\n", ifp->if_xname);
209 return(EIO);
210 }
211
212 /* Read ssid list */
213 sc->an_ssidlist.an_type = AN_RID_SSIDLIST;
214 sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist);
215 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) {
216 printf("%s: read record failed\n", ifp->if_xname);
217 return(EIO);
218 }
219
220 /* Read AP list */
221 sc->an_aplist.an_type = AN_RID_APLIST;
222 sc->an_aplist.an_len = sizeof(struct an_ltv_aplist);
223 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) {
224 printf("%s: read record failed\n", ifp->if_xname);
225 return(EIO);
226 }
227
228 bcopy((char *)&sc->an_caps.an_oemaddr,
229 (char *)&sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
230
231 printf(": address %6s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
232
233 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
234 ifp->if_softc = sc;
235 ifp->if_mtu = ETHERMTU;
236 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
237 ifp->if_ioctl = an_ioctl;
238 ifp->if_start = an_start;
239 ifp->if_watchdog = an_watchdog;
240 ifp->if_baudrate = 10000000;
241 IFQ_SET_READY(&ifp->if_snd);
242
243 bzero(sc->an_config.an_nodename, sizeof(sc->an_config.an_nodename));
244 strlcpy(sc->an_config.an_nodename, AN_DEFAULT_NODENAME,
245 sizeof(sc->an_config.an_nodename));
246
247 bzero(sc->an_ssidlist.an_ssid1, sizeof(sc->an_ssidlist.an_ssid1));
248 strlcpy(sc->an_ssidlist.an_ssid1, AN_DEFAULT_NETNAME,
249 sizeof(sc->an_ssidlist.an_ssid1));
250 sc->an_ssidlist.an_ssid1_len = strlen(sc->an_ssidlist.an_ssid1);
251
252 sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION;
253
254 sc->an_tx_rate = 0;
255 bzero((char *)&sc->an_stats, sizeof(sc->an_stats));
256 #ifdef ANCACHE
257 sc->an_sigitems = sc->an_nextitem = 0;
258 #endif
259
260 ifmedia_init(&sc->an_ifmedia, 0, an_media_change, an_media_status);
261 #define ADD(m, c) ifmedia_add(&sc->an_ifmedia, (m), (c), NULL)
262 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
263 IFM_IEEE80211_ADHOC, 0), 0);
264 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
265 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
266 IFM_IEEE80211_ADHOC, 0), 0);
267 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
268 if (sc->an_caps.an_rates[2] == AN_RATE_5_5MBPS) {
269 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
270 IFM_IEEE80211_ADHOC, 0), 0);
271 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
272 }
273 if (sc->an_caps.an_rates[3] == AN_RATE_11MBPS) {
274 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
275 IFM_IEEE80211_ADHOC, 0), 0);
276 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
277 }
278 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
279 IFM_IEEE80211_ADHOC, 0), 0);
280 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
281 #undef ADD
282 ifmedia_set(&sc->an_ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
283 0, 0));
284
285 /*
286 * Call MI attach routines.
287 */
288 if_attach(ifp);
289 ether_ifattach(ifp);
290 timeout_set(&sc->an_stat_ch, an_stats_update, sc);
291 #if NBPFILTER > 0
292 BPFATTACH(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB,
293 sizeof(struct ether_header));
294 #endif
295
296 shutdownhook_establish(an_shutdown, sc);
297
298 an_reset(sc);
299 an_init(sc);
300
301 return(0);
302 }
303
304 void
an_rxeof(sc)305 an_rxeof(sc)
306 struct an_softc *sc;
307 {
308 struct ifnet *ifp;
309 struct ether_header *eh;
310 #ifdef ANCACHE
311 struct an_rxframe rx_frame;
312 #endif
313 struct an_rxframe_802_3 rx_frame_802_3;
314 struct mbuf *m;
315 int id, error = 0;
316
317 ifp = &sc->sc_arpcom.ac_if;
318
319 id = CSR_READ_2(sc, AN_RX_FID);
320
321 MGETHDR(m, M_DONTWAIT, MT_DATA);
322 if (m == NULL) {
323 ifp->if_ierrors++;
324 return;
325 }
326 MCLGET(m, M_DONTWAIT);
327 if (!(m->m_flags & M_EXT)) {
328 m_freem(m);
329 ifp->if_ierrors++;
330 return;
331 }
332
333 m->m_pkthdr.rcvif = ifp;
334
335 eh = mtod(m, struct ether_header *);
336
337 #ifdef ANCACHE
338 /* Read NIC frame header */
339 if (an_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) {
340 ifp->if_ierrors++;
341 return;
342 }
343 #endif
344 /* Read in the 802_3 frame header */
345 if (an_read_data(sc, id, 0x34, (caddr_t)&rx_frame_802_3,
346 sizeof(rx_frame_802_3))) {
347 ifp->if_ierrors++;
348 return;
349 }
350
351 if (rx_frame_802_3.an_rx_802_3_status != 0) {
352 ifp->if_ierrors++;
353 return;
354 }
355
356 /* Check for insane frame length */
357 if (letoh16(rx_frame_802_3.an_rx_802_3_payload_len) > MCLBYTES) {
358 ifp->if_ierrors++;
359 return;
360 }
361
362 m->m_pkthdr.len = m->m_len =
363 letoh16(rx_frame_802_3.an_rx_802_3_payload_len) + 12;
364
365 bcopy((char *)&rx_frame_802_3.an_rx_dst_addr,
366 (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
367 bcopy((char *)&rx_frame_802_3.an_rx_src_addr,
368 (char *)&eh->ether_shost, ETHER_ADDR_LEN);
369
370 /* in mbuf header type is just before payload */
371 error = an_read_data(sc, id, 0x44, (caddr_t)&(eh->ether_type),
372 letoh16(rx_frame_802_3.an_rx_802_3_payload_len));
373 if (error) {
374 m_freem(m);
375 ifp->if_ierrors++;
376 return;
377 }
378
379 ifp->if_ipackets++;
380
381 #if NBPFILTER > 0
382 /* Handle BPF listeners. */
383 if (ifp->if_bpf)
384 BPF_MTAP(ifp, m);
385 #endif
386
387 /* Receive packet. */
388 #ifdef ANCACHE
389 an_cache_store(sc, eh, m, rx_frame.an_rx_signal_strength);
390 #endif
391 ether_input_mbuf(ifp, m);
392 }
393
394 void
an_txeof(sc,status)395 an_txeof(sc, status)
396 struct an_softc *sc;
397 int status;
398 {
399 struct ifnet *ifp;
400 int id;
401
402 ifp = &sc->sc_arpcom.ac_if;
403
404 ifp->if_timer = 0;
405 ifp->if_flags &= ~IFF_OACTIVE;
406
407 id = CSR_READ_2(sc, AN_TX_CMP_FID);
408
409 if (status & AN_EV_TX_EXC)
410 ifp->if_oerrors++;
411 else
412 ifp->if_opackets++;
413
414 if (id != sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons])
415 printf("%s: id mismatch: expected %x, got %x\n", ifp->if_xname,
416 sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons], id);
417
418 sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons] = 0;
419 AN_INC(sc->an_rdata.an_tx_cons, AN_TX_RING_CNT);
420 }
421
422 /*
423 * We abuse the stats updater to check the current NIC status. This
424 * is important because we don't want to allow transmissions until
425 * the NIC has synchronized to the current cell (either as the master
426 * in an ad-hoc group, or as a station connected to an access point).
427 */
428 void
an_stats_update(xsc)429 an_stats_update(xsc)
430 void *xsc;
431 {
432 struct an_softc *sc;
433 struct ifnet *ifp;
434 int s;
435
436 s = splimp();
437
438 sc = xsc;
439 ifp = &sc->sc_arpcom.ac_if;
440
441 sc->an_status.an_type = AN_RID_STATUS;
442 sc->an_status.an_len = sizeof(struct an_ltv_status);
443 an_read_record(sc, (struct an_ltv_gen *)&sc->an_status);
444
445 if (sc->an_status.an_opmode & AN_STATUS_OPMODE_IN_SYNC)
446 sc->an_associated = 1;
447 else
448 sc->an_associated = 0;
449
450 /* Don't do this while we're transmitting */
451 if (!(ifp->if_flags & IFF_OACTIVE)) {
452 sc->an_stats.an_len = sizeof(struct an_ltv_stats);
453 sc->an_stats.an_type = AN_RID_32BITS_CUM;
454 an_read_record(sc, (struct an_ltv_gen *)&sc->an_stats.an_len);
455 }
456
457 splx(s);
458 TIMEOUT(sc->an_stat_ch, an_stats_update, sc, hz);
459 }
460
461 int
an_intr(xsc)462 an_intr(xsc)
463 void *xsc;
464 {
465 struct an_softc *sc;
466 struct ifnet *ifp;
467 u_int16_t status;
468
469 sc = (struct an_softc*)xsc;
470
471 if (sc->an_gone)
472 return 0;
473
474 ifp = &sc->sc_arpcom.ac_if;
475
476 if (!(ifp->if_flags & IFF_UP)) {
477 CSR_WRITE_2(sc, AN_EVENT_ACK, 0xFFFF);
478 CSR_WRITE_2(sc, AN_INT_EN, 0);
479 return 0;
480 }
481
482 /* Disable interrupts. */
483 CSR_WRITE_2(sc, AN_INT_EN, 0);
484
485 status = CSR_READ_2(sc, AN_EVENT_STAT);
486 CSR_WRITE_2(sc, AN_EVENT_ACK, ~AN_INTRS);
487
488 if (status & AN_EV_AWAKE) {
489 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_AWAKE);
490 }
491
492 if (status & AN_EV_LINKSTAT) {
493 if (CSR_READ_2(sc, AN_LINKSTAT) == AN_LINKSTAT_ASSOCIATED)
494 sc->an_associated = 1;
495 else
496 sc->an_associated = 0;
497 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT);
498 }
499
500 if (status & AN_EV_RX) {
501 an_rxeof(sc);
502 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
503 }
504
505 if (status & AN_EV_TX) {
506 an_txeof(sc, status);
507 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX);
508 }
509
510 if (status & AN_EV_TX_EXC) {
511 an_txeof(sc, status);
512 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX_EXC);
513 }
514
515 if (status & AN_EV_ALLOC)
516 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC);
517
518 /* Re-enable interrupts. */
519 CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS);
520
521 if (!IFQ_IS_EMPTY(&ifp->if_snd))
522 an_start(ifp);
523
524 return 1;
525 }
526
527 int
an_cmd(sc,cmd,val)528 an_cmd(sc, cmd, val)
529 struct an_softc *sc;
530 int cmd;
531 int val;
532 {
533 int i, stat;
534
535 /* make sure previous command completed */
536 if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) {
537 printf("%s: command busy\n", sc->sc_dev.dv_xname);
538 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY);
539 }
540
541 CSR_WRITE_2(sc, AN_PARAM0, val);
542 CSR_WRITE_2(sc, AN_PARAM1, 0);
543 CSR_WRITE_2(sc, AN_PARAM2, 0);
544 DELAY(10);
545 CSR_WRITE_2(sc, AN_COMMAND, cmd);
546 DELAY(10);
547
548 for (i = AN_TIMEOUT; i--; DELAY(10)) {
549 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD)
550 break;
551 else {
552 if (CSR_READ_2(sc, AN_COMMAND) == cmd) {
553 DELAY(10);
554 CSR_WRITE_2(sc, AN_COMMAND, cmd);
555 }
556 }
557 }
558
559 stat = CSR_READ_2(sc, AN_STATUS);
560
561 /* clear stuck command busy if needed */
562 if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) {
563 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY);
564 }
565
566 /* Ack the command */
567 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD);
568
569 if (i <= 0)
570 return(ETIMEDOUT);
571
572 if (stat & AN_STAT_CMD_RESULT)
573 return(EIO);
574
575 return(0);
576 }
577
578 /*
579 * This reset sequence may look a little strange, but this is the
580 * most reliable method I've found to really kick the NIC in the
581 * head and force it to reboot correctly.
582 */
583 void
an_reset(sc)584 an_reset(sc)
585 struct an_softc *sc;
586 {
587 if (sc->an_gone)
588 return;
589 /*printf("ena ");*/
590 an_cmd(sc, AN_CMD_ENABLE, 0);
591 /* printf("rst ");*/
592 an_cmd(sc, AN_CMD_FW_RESTART, 0);
593 /*printf("nop ");*/
594 an_cmd(sc, AN_CMD_NOOP2, 0);
595
596 if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT)
597 printf("%s: reset failed\n", sc->sc_dev.dv_xname);
598
599 an_cmd(sc, AN_CMD_DISABLE, 0);
600 }
601
602 /*
603 * Read an LTV record from the NIC.
604 */
605 int
an_read_record(sc,ltv)606 an_read_record(sc, ltv)
607 struct an_softc *sc;
608 struct an_ltv_gen *ltv;
609 {
610 u_int16_t *ptr, len, rlen, ltv_data_length;
611 volatile u_int16_t v;
612 int i;
613
614 if (ltv->an_len < 4 || ltv->an_type == 0)
615 return(EINVAL);
616
617 /* Tell the NIC to enter record read mode. */
618 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) {
619 printf("%s: RID 0x%04x access failed\n",
620 sc->sc_dev.dv_xname, ltv->an_type);
621 return(EIO);
622 }
623
624 /* Seek to the record. */
625 if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) {
626 printf("%s: RID 0x%04x seek to record failed\n",
627 sc->sc_dev.dv_xname, ltv->an_type);
628 return(EIO);
629 }
630
631 /*
632 * Read the length to make sure it
633 * matches what we expect (this verifies that we have enough
634 * room to hold all of the returned data).
635 */
636 rlen = len = CSR_READ_2(sc, AN_DATA1);
637
638 /*
639 * Work out record's data length, which is struct length - type word
640 * as we have just read the length.
641 */
642 ltv_data_length = ltv->an_len - sizeof(u_int16_t);
643
644 if (rlen > ltv_data_length)
645 rlen = ltv_data_length;
646
647 /* Now read the data. */
648 len -= 2; rlen -= 2; /* skip the type */
649 ptr = ltv->an_val;
650 for (i = 0; (rlen - i) > 1; i += 2)
651 *ptr++ = CSR_READ_2(sc, AN_DATA1);
652 if (rlen - i == 1)
653 *(u_int8_t *)ptr = CSR_READ_1(sc, AN_DATA1);
654 for (; i < len; i++)
655 v = CSR_READ_1(sc, AN_DATA1);
656
657 #if BYTE_ORDER == BIG_ENDIAN
658 switch (ltv->an_type) {
659 case AN_RID_GENCONFIG:
660 case AN_RID_ACTUALCFG:
661 an_swap16(<v->an_val[4], 7); /* an_macaddr, an_rates */
662 an_swap16(<v->an_val[63], 8); /* an_nodename */
663 break;
664 case AN_RID_SSIDLIST:
665 an_swap16(<v->an_val[1], 16); /* an_ssid1 */
666 an_swap16(<v->an_val[18], 16); /* an_ssid2 */
667 an_swap16(<v->an_val[35], 16); /* an_ssid3 */
668 break;
669 case AN_RID_APLIST:
670 an_swap16(ltv->an_val, 12);
671 break;
672 case AN_RID_DRVNAME:
673 an_swap16(ltv->an_val, 8);
674 break;
675 case AN_RID_CAPABILITIES:
676 an_swap16(ltv->an_val, 2); /* an_oui */
677 an_swap16(<v->an_val[3], 34); /* an_manufname .. an_aironetaddr */
678 an_swap16(<v->an_val[39], 8); /* an_callid .. an_tx_diversity */
679 break;
680 case AN_RID_STATUS:
681 an_swap16(<v->an_val[0], 3); /* an_macaddr */
682 an_swap16(<v->an_val[7], 36); /* an_ssid .. an_prev_bssid3 */
683 an_swap16(<v->an_val[0x74/2], 2); /* an_ap_ip_addr */
684 break;
685 case AN_RID_WEP_VOLATILE:
686 case AN_RID_WEP_PERMANENT:
687 an_swap16(<v->an_val[1], 3); /* an_mac_addr */
688 an_swap16(<v->an_val[5], 6);
689 break;
690 case AN_RID_32BITS_CUM:
691 for (i = 0x60; i--; ) {
692 u_int16_t t = ltv->an_val[i * 2] ^ ltv->an_val[i * 2 + 1];
693 ltv->an_val[i * 2] ^= t;
694 ltv->an_val[i * 2 + 1] ^= t;
695 }
696 break;
697 }
698 #endif
699 return(0);
700 }
701
702 /*
703 * Same as read, except we inject data instead of reading it.
704 */
705 int
an_write_record(sc,ltv)706 an_write_record(sc, ltv)
707 struct an_softc *sc;
708 struct an_ltv_gen *ltv;
709 {
710 u_int16_t *ptr;
711 int i;
712
713 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type))
714 return(EIO);
715
716 if (an_seek(sc, ltv->an_type, 0, AN_BAP1))
717 return(EIO);
718
719 #if BYTE_ORDER == BIG_ENDIAN
720 switch (ltv->an_type) {
721 case AN_RID_GENCONFIG:
722 case AN_RID_ACTUALCFG:
723 an_swap16(<v->an_val[4], 7); /* an_macaddr, an_rates */
724 an_swap16(<v->an_val[63], 8); /* an_nodename */
725 break;
726 case AN_RID_SSIDLIST:
727 an_swap16(<v->an_val[1], 16); /* an_ssid1 */
728 an_swap16(<v->an_val[18], 16); /* an_ssid2 */
729 an_swap16(<v->an_val[35], 16); /* an_ssid3 */
730 break;
731 case AN_RID_APLIST:
732 an_swap16(ltv->an_val, 12);
733 break;
734 case AN_RID_DRVNAME:
735 an_swap16(ltv->an_val, 8);
736 break;
737 case AN_RID_CAPABILITIES:
738 an_swap16(ltv->an_val, 2); /* an_oui */
739 an_swap16(<v->an_val[3], 34); /* an_manufname .. an_aironetaddr */
740 an_swap16(<v->an_val[39], 8); /* an_callid .. an_tx_diversity */
741 break;
742 case AN_RID_STATUS:
743 an_swap16(<v->an_val[0], 3); /* an_macaddr */
744 an_swap16(<v->an_val[7], 36); /* an_ssid .. an_prev_bssid3 */
745 an_swap16(<v->an_val[0x74/2], 2); /* an_ap_ip_addr */
746 break;
747 case AN_RID_WEP_VOLATILE:
748 case AN_RID_WEP_PERMANENT:
749 an_swap16(<v->an_val[1], 3); /* an_mac_addr */
750 an_swap16(<v->an_val[5], 6);
751 break;
752 }
753 #endif
754
755 CSR_WRITE_2(sc, AN_DATA1, ltv->an_len);
756
757 ptr = ltv->an_val;
758 for (i = 0; i < (ltv->an_len - 1) >> 1; i++)
759 CSR_WRITE_2(sc, AN_DATA1, ptr[i]);
760
761 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_WRITE, ltv->an_type))
762 return(EIO);
763
764 return(0);
765 }
766
767 int
an_seek(sc,id,off,chan)768 an_seek(sc, id, off, chan)
769 struct an_softc *sc;
770 int id, off, chan;
771 {
772 int i;
773 int selreg, offreg;
774
775 switch (chan) {
776 case AN_BAP0:
777 selreg = AN_SEL0;
778 offreg = AN_OFF0;
779 break;
780 case AN_BAP1:
781 selreg = AN_SEL1;
782 offreg = AN_OFF1;
783 break;
784 default:
785 printf("%s: invalid data path: %x\n",
786 sc->sc_dev.dv_xname, chan);
787 return (EIO);
788 }
789
790 CSR_WRITE_2(sc, selreg, id);
791 CSR_WRITE_2(sc, offreg, off);
792
793 for (i = AN_TIMEOUT; i--; DELAY(10)) {
794 if (!(CSR_READ_2(sc, offreg) & (AN_OFF_BUSY|AN_OFF_ERR)))
795 break;
796 }
797
798 if (i <= 0)
799 return(ETIMEDOUT);
800
801 return (0);
802 }
803
804 int
an_read_data(sc,id,off,buf,len)805 an_read_data(sc, id, off, buf, len)
806 struct an_softc *sc;
807 int id, off;
808 caddr_t buf;
809 int len;
810 {
811 if (off != -1 && an_seek(sc, id, off, AN_BAP1))
812 return(EIO);
813
814 bus_space_read_raw_multi_2(sc->an_btag, sc->an_bhandle,
815 AN_DATA1, buf, len & ~1);
816 if (len & 1)
817 ((u_int8_t *)buf)[len - 1] = CSR_READ_1(sc, AN_DATA1);
818
819 return (0);
820 }
821
822 int
an_write_data(sc,id,off,buf,len)823 an_write_data(sc, id, off, buf, len)
824 struct an_softc *sc;
825 int id, off;
826 caddr_t buf;
827 int len;
828 {
829 if (off != -1 && an_seek(sc, id, off, AN_BAP0))
830 return(EIO);
831
832 bus_space_write_raw_multi_2(sc->an_btag, sc->an_bhandle,
833 AN_DATA0, buf, len & ~1);
834 if (len & 1)
835 CSR_WRITE_1(sc, AN_DATA0, ((u_int8_t *)buf)[len - 1]);
836
837 return (0);
838 }
839
840 /*
841 * Allocate a region of memory inside the NIC and zero
842 * it out.
843 */
844 int
an_alloc_nicmem(sc,len,id)845 an_alloc_nicmem(sc, len, id)
846 struct an_softc *sc;
847 int len;
848 int *id;
849 {
850 int i;
851
852 if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) {
853 printf("%s: failed to allocate %d bytes on NIC\n",
854 sc->sc_dev.dv_xname, len);
855 return(ENOMEM);
856 }
857
858 for (i = AN_TIMEOUT; i--; DELAY(10)) {
859 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC)
860 break;
861 }
862
863 if (i <= 0)
864 return(ETIMEDOUT);
865
866 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC);
867 *id = CSR_READ_2(sc, AN_ALLOC_FID);
868
869 if (an_seek(sc, *id, 0, AN_BAP0))
870 return(EIO);
871
872 bus_space_set_multi_2(sc->an_btag, sc->an_bhandle,
873 AN_DATA0, 0, len / 2);
874 CSR_WRITE_1(sc, AN_DATA0, 0);
875
876 return(0);
877 }
878
879 void
an_setdef(sc,areq)880 an_setdef(sc, areq)
881 struct an_softc *sc;
882 struct an_req *areq;
883 {
884 struct ifnet *ifp;
885 struct an_ltv_genconfig *cfg;
886 struct an_ltv_ssidlist *ssid;
887 struct an_ltv_aplist *ap;
888 struct an_ltv_gen *sp;
889
890 ifp = &sc->sc_arpcom.ac_if;
891
892 switch (areq->an_type) {
893 case AN_RID_GENCONFIG:
894 cfg = (struct an_ltv_genconfig *)areq;
895 bcopy((char *)&cfg->an_macaddr,
896 (char *)&sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
897 bcopy((char *)&cfg->an_macaddr, LLADDR(ifp->if_sadl),
898 ETHER_ADDR_LEN);
899
900 bcopy((char *)cfg, (char *)&sc->an_config,
901 sizeof(struct an_ltv_genconfig));
902 break;
903 case AN_RID_SSIDLIST:
904 ssid = (struct an_ltv_ssidlist *)areq;
905 bcopy((char *)ssid, (char *)&sc->an_ssidlist,
906 sizeof(struct an_ltv_ssidlist));
907 break;
908 case AN_RID_APLIST:
909 ap = (struct an_ltv_aplist *)areq;
910 bcopy((char *)ap, (char *)&sc->an_aplist,
911 sizeof(struct an_ltv_aplist));
912 break;
913 case AN_RID_TX_SPEED:
914 sp = (struct an_ltv_gen *)areq;
915 sc->an_tx_rate = sp->an_val[0];
916 break;
917 case AN_RID_WEP_VOLATILE:
918 /* Disable the MAC */
919 an_cmd(sc, AN_CMD_DISABLE, 0);
920
921 /* Just write the key, we dont' want to save it */
922 an_write_record(sc, (struct an_ltv_gen *)areq);
923
924 /* Turn the MAC back on */
925 an_cmd(sc, AN_CMD_ENABLE, 0);
926
927 break;
928 case AN_RID_WEP_PERMANENT:
929 /* Disable the MAC */
930 an_cmd(sc, AN_CMD_DISABLE, 0);
931
932 /* Just write the key, the card will save it in this mode */
933 an_write_record(sc, (struct an_ltv_gen *)areq);
934
935 /* Turn the MAC back on */
936 an_cmd(sc, AN_CMD_ENABLE, 0);
937
938 break;
939 default:
940 printf("%s: unknown RID: %x\n",
941 sc->sc_dev.dv_xname, areq->an_type);
942 return;
943 }
944
945 /* Reinitialize the card. */
946 if (ifp->if_flags & IFF_UP)
947 an_init(sc);
948 }
949
950 /*
951 * We can't change the NIC configuration while the MAC is enabled,
952 * so in order to turn on RX monitor mode, we have to turn the MAC
953 * off first.
954 */
955 void
an_promisc(sc,promisc)956 an_promisc(sc, promisc)
957 struct an_softc *sc;
958 int promisc;
959 {
960 struct an_ltv_genconfig genconf;
961
962 /* Disable the MAC. */
963 an_cmd(sc, AN_CMD_DISABLE, 0);
964
965 /* Set RX mode. */
966 if (promisc &&
967 !(sc->an_config.an_rxmode & AN_RXMODE_LAN_MONITOR_CURBSS) ) {
968 sc->an_rxmode = sc->an_config.an_rxmode;
969 sc->an_config.an_rxmode |=
970 AN_RXMODE_LAN_MONITOR_CURBSS;
971 } else {
972 sc->an_config.an_rxmode = sc->an_rxmode;
973 }
974
975 /* Transfer the configuration to the NIC */
976 genconf = sc->an_config;
977 genconf.an_len = sizeof(struct an_ltv_genconfig);
978 genconf.an_type = AN_RID_GENCONFIG;
979 if (an_write_record(sc, (struct an_ltv_gen *)&genconf)) {
980 printf("%s: failed to set configuration\n",
981 sc->sc_dev.dv_xname);
982 return;
983 }
984 /* Turn the MAC back on. */
985 an_cmd(sc, AN_CMD_ENABLE, 0);
986 }
987
988 int
an_ioctl(ifp,command,data)989 an_ioctl(ifp, command, data)
990 struct ifnet *ifp;
991 u_long command;
992 caddr_t data;
993 {
994 int s, error = 0;
995 struct an_softc *sc;
996 struct an_req areq;
997 struct ifreq *ifr;
998 struct proc *p = curproc;
999 struct ifaddr *ifa = (struct ifaddr *)data;
1000
1001 s = splimp();
1002
1003 sc = ifp->if_softc;
1004 ifr = (struct ifreq *)data;
1005
1006 if (sc->an_gone) {
1007 splx(s);
1008 return(ENODEV);
1009 }
1010
1011 if ((error = ether_ioctl(ifp, &sc->sc_arpcom, command, data)) > 0) {
1012 splx(s);
1013 return error;
1014 }
1015
1016 switch(command) {
1017 case SIOCSIFADDR:
1018 ifp->if_flags |= IFF_UP;
1019 switch (ifa->ifa_addr->sa_family) {
1020 #ifdef INET
1021 case AF_INET:
1022 an_init(sc);
1023 arp_ifinit(&sc->sc_arpcom, ifa);
1024 break;
1025 #endif
1026 default:
1027 an_init(sc);
1028 break;
1029 }
1030 break;
1031 case SIOCSIFFLAGS:
1032 if (ifp->if_flags & IFF_UP) {
1033 if (ifp->if_flags & IFF_RUNNING &&
1034 ifp->if_flags & IFF_PROMISC &&
1035 !(sc->an_if_flags & IFF_PROMISC)) {
1036 an_promisc(sc, 1);
1037 } else if (ifp->if_flags & IFF_RUNNING &&
1038 !(ifp->if_flags & IFF_PROMISC) &&
1039 sc->an_if_flags & IFF_PROMISC) {
1040 an_promisc(sc, 0);
1041 an_reset(sc);
1042 }
1043 an_init(sc);
1044 } else {
1045 if (ifp->if_flags & IFF_RUNNING)
1046 an_stop(sc);
1047 }
1048 sc->an_if_flags = ifp->if_flags;
1049 error = 0;
1050 break;
1051 case SIOCSIFMEDIA:
1052 case SIOCGIFMEDIA:
1053 error = ifmedia_ioctl(ifp, ifr, &sc->an_ifmedia, command);
1054 break;
1055 case SIOCADDMULTI:
1056 case SIOCDELMULTI:
1057 /* The Aironet has no multicast filter. */
1058 error = 0;
1059 break;
1060 case SIOCGAIRONET:
1061 error = copyin(ifr->ifr_data, &areq, sizeof(areq));
1062 if (error)
1063 break;
1064 #ifdef ANCACHE
1065 if (areq.an_type == AN_RID_ZERO_CACHE) {
1066 error = suser(p, 0);
1067 if (error)
1068 break;
1069 sc->an_sigitems = sc->an_nextitem = 0;
1070 break;
1071 } else if (areq.an_type == AN_RID_READ_CACHE) {
1072 char *pt = (char *)&areq.an_val;
1073 bcopy((char *)&sc->an_sigitems, (char *)pt,
1074 sizeof(int));
1075 pt += sizeof(int);
1076 areq.an_len = sizeof(int) / 2;
1077 bcopy((char *)&sc->an_sigcache, (char *)pt,
1078 sizeof(struct an_sigcache) * sc->an_sigitems);
1079 areq.an_len += ((sizeof(struct an_sigcache) *
1080 sc->an_sigitems) / 2) + 1;
1081 } else
1082 #endif
1083 if (an_read_record(sc, (struct an_ltv_gen *)&areq)) {
1084 error = EINVAL;
1085 break;
1086 }
1087 error = copyout(&areq, ifr->ifr_data, sizeof(areq));
1088 break;
1089 case SIOCSAIRONET:
1090 error = suser(p, 0);
1091 if (error)
1092 break;
1093 error = copyin(ifr->ifr_data, &areq, sizeof(areq));
1094 if (error)
1095 break;
1096 an_setdef(sc, &areq);
1097 break;
1098 default:
1099 error = EINVAL;
1100 break;
1101 }
1102
1103 splx(s);
1104
1105 return(error);
1106 }
1107
1108 int
an_init_tx_ring(sc)1109 an_init_tx_ring(sc)
1110 struct an_softc *sc;
1111 {
1112 int i;
1113 int id;
1114
1115 if (sc->an_gone)
1116 return (0);
1117
1118 for (i = 0; i < AN_TX_RING_CNT; i++) {
1119 if (an_alloc_nicmem(sc, 1518 + 0x44, &id))
1120 return(ENOMEM);
1121 sc->an_rdata.an_tx_fids[i] = id;
1122 sc->an_rdata.an_tx_ring[i] = 0;
1123 }
1124
1125 sc->an_rdata.an_tx_prod = 0;
1126 sc->an_rdata.an_tx_cons = 0;
1127
1128 return(0);
1129 }
1130
1131 void
an_init(sc)1132 an_init(sc)
1133 struct an_softc *sc;
1134 {
1135 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1136 struct an_ltv_ssidlist ssid;
1137 struct an_ltv_aplist aplist;
1138 struct an_ltv_genconfig genconf;
1139 int s;
1140
1141 if (sc->an_gone)
1142 return;
1143
1144 s = splimp();
1145
1146 if (ifp->if_flags & IFF_RUNNING)
1147 an_stop(sc);
1148
1149 sc->an_associated = 0;
1150
1151 /* Allocate the TX buffers */
1152 if (an_init_tx_ring(sc)) {
1153 printf("%s: tx buffer allocation failed\n",
1154 sc->sc_dev.dv_xname);
1155 splx(s);
1156 return;
1157 }
1158
1159 /* Set our MAC address. */
1160 bcopy((char *)&sc->sc_arpcom.ac_enaddr,
1161 (char *)&sc->an_config.an_macaddr, ETHER_ADDR_LEN);
1162
1163 if (ifp->if_flags & IFF_BROADCAST)
1164 sc->an_config.an_rxmode = AN_RXMODE_BC_ADDR;
1165 else
1166 sc->an_config.an_rxmode = AN_RXMODE_ADDR;
1167
1168 if (ifp->if_flags & IFF_MULTICAST)
1169 sc->an_config.an_rxmode = AN_RXMODE_BC_MC_ADDR;
1170
1171 /* Initialize promisc mode. */
1172 if (ifp->if_flags & IFF_PROMISC)
1173 sc->an_config.an_rxmode |= AN_RXMODE_LAN_MONITOR_CURBSS;
1174
1175 sc->an_rxmode = sc->an_config.an_rxmode;
1176
1177 /* Set the ssid list */
1178 ssid = sc->an_ssidlist;
1179 ssid.an_type = AN_RID_SSIDLIST;
1180 ssid.an_len = sizeof(struct an_ltv_ssidlist);
1181 if (an_write_record(sc, (struct an_ltv_gen *)&ssid)) {
1182 printf("%s: failed to set ssid list\n", sc->sc_dev.dv_xname);
1183 splx(s);
1184 return;
1185 }
1186
1187 /* Set the AP list */
1188 aplist = sc->an_aplist;
1189 aplist.an_type = AN_RID_APLIST;
1190 aplist.an_len = sizeof(struct an_ltv_aplist);
1191 if (an_write_record(sc, (struct an_ltv_gen *)&aplist)) {
1192 printf("%s: failed to set AP list\n", sc->sc_dev.dv_xname);
1193 splx(s);
1194 return;
1195 }
1196
1197 /* Set the configuration in the NIC */
1198 genconf = sc->an_config;
1199 genconf.an_len = sizeof(struct an_ltv_genconfig);
1200 genconf.an_type = AN_RID_GENCONFIG;
1201 if (an_write_record(sc, (struct an_ltv_gen *)&genconf)) {
1202 printf("%s: failed to set configuration\n",
1203 sc->sc_dev.dv_xname);
1204 splx(s);
1205 return;
1206 }
1207
1208 /* Enable the MAC */
1209 if (an_cmd(sc, AN_CMD_ENABLE, 0)) {
1210 printf("%s: failed to enable MAC\n", sc->sc_dev.dv_xname);
1211 splx(s);
1212 return;
1213 }
1214
1215 /* enable interrupts */
1216 CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS);
1217
1218 splx(s);
1219
1220 ifp->if_flags |= IFF_RUNNING;
1221 ifp->if_flags &= ~IFF_OACTIVE;
1222
1223 TIMEOUT(sc->an_stat_ch, an_stats_update, sc, hz);
1224 }
1225
1226 void
an_start(ifp)1227 an_start(ifp)
1228 struct ifnet *ifp;
1229 {
1230 struct an_softc *sc;
1231 struct mbuf *m0 = NULL;
1232 struct an_txframe_802_3 tx_frame_802_3;
1233 struct ether_header *eh;
1234 u_int16_t len;
1235 int id;
1236 int idx;
1237 unsigned char txcontrol;
1238 int pkts = 0;
1239
1240 sc = ifp->if_softc;
1241
1242 if (sc->an_gone)
1243 return;
1244
1245 if (ifp->if_flags & IFF_OACTIVE)
1246 return;
1247
1248 if (!sc->an_associated)
1249 return;
1250
1251 idx = sc->an_rdata.an_tx_prod;
1252 bzero((char *)&tx_frame_802_3, sizeof(tx_frame_802_3));
1253
1254 while(sc->an_rdata.an_tx_ring[idx] == 0) {
1255 IFQ_DEQUEUE(&ifp->if_snd, m0);
1256 if (m0 == NULL)
1257 break;
1258
1259 pkts++;
1260 id = sc->an_rdata.an_tx_fids[idx];
1261 eh = mtod(m0, struct ether_header *);
1262
1263 bcopy((char *)&eh->ether_dhost,
1264 (char *)&tx_frame_802_3.an_tx_dst_addr, ETHER_ADDR_LEN);
1265 bcopy((char *)&eh->ether_shost,
1266 (char *)&tx_frame_802_3.an_tx_src_addr, ETHER_ADDR_LEN);
1267
1268 len = m0->m_pkthdr.len - 12; /* minus src/dest mac & type */
1269 tx_frame_802_3.an_tx_802_3_payload_len = htole16(len);
1270
1271 m_copydata(m0, sizeof(struct ether_header) - 2, len,
1272 (caddr_t)&sc->an_txbuf);
1273
1274 txcontrol=AN_TXCTL_8023;
1275 /* write the txcontrol only */
1276 an_write_data(sc, id, 0x08, (caddr_t)&txcontrol,
1277 sizeof(txcontrol));
1278
1279 /* 802_3 header */
1280 an_write_data(sc, id, 0x34, (caddr_t)&tx_frame_802_3,
1281 sizeof(struct an_txframe_802_3));
1282
1283 /* in mbuf header type is just before payload */
1284 an_write_data(sc, id, 0x44, (caddr_t)&sc->an_txbuf, len);
1285
1286 /*
1287 * If there's a BPF listener, bounce a copy of
1288 * this frame to him.
1289 */
1290 #if NBPFILTER > 0
1291 if (ifp->if_bpf)
1292 BPF_MTAP(ifp, m0);
1293 #endif
1294
1295 m_freem(m0);
1296 m0 = NULL;
1297
1298 sc->an_rdata.an_tx_ring[idx] = id;
1299 if (an_cmd(sc, AN_CMD_TX, id))
1300 printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
1301
1302 AN_INC(idx, AN_TX_RING_CNT);
1303 }
1304 if (pkts == 0)
1305 return;
1306
1307 if (m0 != NULL)
1308 ifp->if_flags |= IFF_OACTIVE;
1309
1310 sc->an_rdata.an_tx_prod = idx;
1311
1312 /*
1313 * Set a timeout in case the chip goes out to lunch.
1314 */
1315 ifp->if_timer = 5;
1316 }
1317
1318 void
an_stop(sc)1319 an_stop(sc)
1320 struct an_softc *sc;
1321 {
1322 struct ifnet *ifp;
1323 int i;
1324
1325 if (sc->an_gone)
1326 return;
1327
1328 ifp = &sc->sc_arpcom.ac_if;
1329
1330 an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0);
1331 CSR_WRITE_2(sc, AN_INT_EN, 0);
1332 an_cmd(sc, AN_CMD_DISABLE, 0);
1333
1334 for (i = 0; i < AN_TX_RING_CNT; i++)
1335 an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->an_rdata.an_tx_fids[i]);
1336
1337 UNTIMEOUT(an_stats_update, sc, sc->an_stat_ch);
1338
1339 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
1340 }
1341
1342 void
an_watchdog(ifp)1343 an_watchdog(ifp)
1344 struct ifnet *ifp;
1345 {
1346 struct an_softc *sc;
1347
1348 sc = ifp->if_softc;
1349
1350 if (sc->an_gone)
1351 return;
1352
1353 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
1354
1355 an_reset(sc);
1356 an_init(sc);
1357
1358 ifp->if_oerrors++;
1359 }
1360
1361 void
an_shutdown(self)1362 an_shutdown(self)
1363 void *self;
1364 {
1365 an_stop(self);
1366 }
1367
1368 #ifdef ANCACHE
1369 /* Aironet signal strength cache code.
1370 * store signal/noise/quality on per MAC src basis in
1371 * a small fixed cache. The cache wraps if > MAX slots
1372 * used. The cache may be zeroed out to start over.
1373 * Two simple filters exist to reduce computation:
1374 * 1. ip only (literally 0x800) which may be used
1375 * to ignore some packets. It defaults to ip only.
1376 * it could be used to focus on broadcast, non-IP 802.11 beacons.
1377 * 2. multicast/broadcast only. This may be used to
1378 * ignore unicast packets and only cache signal strength
1379 * for multicast/broadcast packets (beacons); e.g., Mobile-IP
1380 * beacons and not unicast traffic.
1381 *
1382 * The cache stores (MAC src(index), IP src (major clue), signal,
1383 * quality, noise)
1384 *
1385 * No apologies for storing IP src here. It's easy and saves much
1386 * trouble elsewhere. The cache is assumed to be INET dependent,
1387 * although it need not be.
1388 *
1389 * Note: the Aironet only has a single byte of signal strength value
1390 * in the rx frame header, and it's not scaled to anything sensible.
1391 * This is kind of lame, but it's all we've got.
1392 */
1393
1394 #ifdef documentation
1395
1396 int an_sigitems; /* number of cached entries */
1397 struct an_sigcache an_sigcache[MAXANCACHE]; /* array of cache entries */
1398 int an_nextitem; /* index/# of entries */
1399
1400
1401 #endif
1402
1403 /* control variables for cache filtering. Basic idea is
1404 * to reduce cost (e.g., to only Mobile-IP agent beacons
1405 * which are broadcast or multicast). Still you might
1406 * want to measure signal strength anth unicast ping packets
1407 * on a pt. to pt. ant. setup.
1408 */
1409 /* set true if you want to limit cache items to broadcast/mcast
1410 * only packets (not unicast). Useful for mobile-ip beacons which
1411 * are broadcast/multicast at network layer. Default is all packets
1412 * so ping/unicast anll work say anth pt. to pt. antennae setup.
1413 */
1414 #if 0
1415 static int an_cache_mcastonly = 0;
1416 SYSCTL_INT(_machdep, OID_AUTO, an_cache_mcastonly, CTLFLAG_RW,
1417 &an_cache_mcastonly, 0, "");
1418
1419 /* set true if you want to limit cache items to IP packets only
1420 */
1421 static int an_cache_iponly = 1;
1422 SYSCTL_INT(_machdep, OID_AUTO, an_cache_iponly, CTLFLAG_RW,
1423 &an_cache_iponly, 0, "");
1424 #endif
1425
1426 /*
1427 * an_cache_store, per rx packet store signal
1428 * strength in MAC (src) indexed cache.
1429 */
1430 void
an_cache_store(sc,eh,m,rx_quality)1431 an_cache_store (sc, eh, m, rx_quality)
1432 struct an_softc *sc;
1433 struct ether_header *eh;
1434 struct mbuf *m;
1435 unsigned short rx_quality;
1436 {
1437 struct ip *ip = 0;
1438 int i;
1439 static int cache_slot = 0; /* use this cache entry */
1440 static int wrapindex = 0; /* next "free" cache entry */
1441 int saanp=0;
1442
1443 /* filters:
1444 * 1. ip only
1445 * 2. configurable filter to throw out unicast packets,
1446 * keep multicast only.
1447 */
1448
1449 if ((ntohs(eh->ether_type) == 0x800))
1450 saanp = 1;
1451
1452 /* filter for ip packets only
1453 */
1454 if (sc->an_cache_iponly && !saanp)
1455 return;
1456
1457 /* filter for broadcast/multicast only */
1458 if (sc->an_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0))
1459 return;
1460
1461 #ifdef SIGDEBUG
1462 printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n",
1463 rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff);
1464 #endif
1465
1466 /* find the ip header. we want to store the ip_src address */
1467 if (saanp)
1468 ip = (struct ip *)(mtod(m, char *) + sizeof(struct ether_header));
1469
1470 /* do a linear search for a matching MAC address
1471 * in the cache table
1472 * . MAC address is 6 bytes,
1473 * . var w_nextitem holds total number of entries already cached
1474 */
1475 for(i = 0; i < sc->an_nextitem; i++)
1476 if (!bcmp(eh->ether_shost , sc->an_sigcache[i].macsrc, 6))
1477 /* Match!,
1478 * so we already have this entry, update the data
1479 */
1480 break;
1481
1482 /* did we find a matching mac address?
1483 * if yes, then overwrite a previously existing cache entry
1484 */
1485 if (i < sc->an_nextitem )
1486 cache_slot = i;
1487
1488 /* else, have a new address entry,so
1489 * add this new entry,
1490 * if table full, then we need to replace LRU entry
1491 */
1492 else {
1493
1494 /* check for space in cache table
1495 * note: an_nextitem also holds number of entries
1496 * added in the cache table
1497 */
1498 if ( sc->an_nextitem < MAXANCACHE ) {
1499 cache_slot = sc->an_nextitem;
1500 sc->an_nextitem++;
1501 sc->an_sigitems = sc->an_nextitem;
1502 }
1503 /* no space found, so simply wrap anth wrap index
1504 * and "zap" the next entry
1505 */
1506 else {
1507 if (wrapindex == MAXANCACHE)
1508 wrapindex = 0;
1509 cache_slot = wrapindex++;
1510 }
1511 }
1512
1513 /* invariant: cache_slot now points at some slot
1514 * in cache.
1515 */
1516 if (cache_slot < 0 || cache_slot >= MAXANCACHE) {
1517 log(LOG_ERR, "an_cache_store, bad index: %d of "
1518 "[0..%d], gross cache error\n",
1519 cache_slot, MAXANCACHE);
1520 return;
1521 }
1522
1523 /* store items in cache
1524 * .ip source address
1525 * .mac src
1526 * .signal, etc.
1527 */
1528 if (saanp)
1529 sc->an_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr;
1530 bcopy( eh->ether_shost, sc->an_sigcache[cache_slot].macsrc, 6);
1531
1532 sc->an_sigcache[cache_slot].signal = rx_quality;
1533 }
1534 #endif
1535
1536 int
an_media_change(ifp)1537 an_media_change(ifp)
1538 struct ifnet *ifp;
1539 {
1540 struct an_softc *sc = ifp->if_softc;
1541 int otype = sc->an_config.an_opmode;
1542 int orate = sc->an_tx_rate;
1543
1544 if ((sc->an_ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0)
1545 sc->an_config.an_opmode = AN_OPMODE_IBSS_ADHOC;
1546 else
1547 sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION;
1548
1549 switch (IFM_SUBTYPE(sc->an_ifmedia.ifm_cur->ifm_media)) {
1550 case IFM_IEEE80211_DS1:
1551 sc->an_tx_rate = AN_RATE_1MBPS;
1552 break;
1553 case IFM_IEEE80211_DS2:
1554 sc->an_tx_rate = AN_RATE_2MBPS;
1555 break;
1556 case IFM_IEEE80211_DS5:
1557 sc->an_tx_rate = AN_RATE_5_5MBPS;
1558 break;
1559 case IFM_IEEE80211_DS11:
1560 sc->an_tx_rate = AN_RATE_11MBPS;
1561 break;
1562 case IFM_AUTO:
1563 sc->an_tx_rate = 0;
1564 break;
1565 }
1566
1567 if (otype != sc->an_config.an_opmode ||
1568 orate != sc->an_tx_rate)
1569 an_init(sc);
1570
1571 return(0);
1572 }
1573
1574 void
an_media_status(ifp,imr)1575 an_media_status(ifp, imr)
1576 struct ifnet *ifp;
1577 struct ifmediareq *imr;
1578 {
1579 struct an_ltv_status status;
1580 struct an_softc *sc = ifp->if_softc;
1581
1582 status.an_len = sizeof(status);
1583 status.an_type = AN_RID_STATUS;
1584 if (an_read_record(sc, (struct an_ltv_gen *)&status)) {
1585 /* If the status read fails, just lie. */
1586 imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media;
1587 imr->ifm_status = IFM_AVALID|IFM_ACTIVE;
1588 }
1589
1590 if (sc->an_tx_rate == 0) {
1591 imr->ifm_active = IFM_IEEE80211|IFM_AUTO;
1592 if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC)
1593 imr->ifm_active |= IFM_IEEE80211_ADHOC;
1594 switch (status.an_current_tx_rate) {
1595 case AN_RATE_1MBPS:
1596 imr->ifm_active |= IFM_IEEE80211_DS1;
1597 break;
1598 case AN_RATE_2MBPS:
1599 imr->ifm_active |= IFM_IEEE80211_DS2;
1600 break;
1601 case AN_RATE_5_5MBPS:
1602 imr->ifm_active |= IFM_IEEE80211_DS5;
1603 break;
1604 case AN_RATE_11MBPS:
1605 imr->ifm_active |= IFM_IEEE80211_DS11;
1606 break;
1607 }
1608 } else {
1609 imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media;
1610 }
1611
1612 imr->ifm_status = IFM_AVALID;
1613 if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC)
1614 imr->ifm_status |= IFM_ACTIVE;
1615 else if (status.an_opmode & AN_STATUS_OPMODE_ASSOCIATED)
1616 imr->ifm_status |= IFM_ACTIVE;
1617 }
1618