Deleted Added
full compact
if_wi.c (53356) if_wi.c (53702)
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

--- 15 unchanged lines hidden (view full) ---

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 *
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

--- 15 unchanged lines hidden (view full) ---

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 * $FreeBSD: head/sys/dev/wi/if_wi.c 53356 1999-11-18 08:39:02Z peter $
32 * $FreeBSD: head/sys/dev/wi/if_wi.c 53702 1999-11-25 20:45:49Z wpaul $
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

--- 20 unchanged lines hidden (view full) ---

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. */
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

--- 20 unchanged lines hidden (view full) ---

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#define WICACHE /* turn on signal strength cache code */
69
70
70#include "card.h"
71#undef NCARD
72#define NCARD 0
73#include "wi.h"
74
75#include <sys/param.h>
76#include <sys/systm.h>
71#include <sys/param.h>
72#include <sys/systm.h>
77#include <sys/eventhandler.h>
78#include <sys/sockio.h>
79#include <sys/mbuf.h>
80#include <sys/malloc.h>
81#include <sys/kernel.h>
82#include <sys/socket.h>
73#include <sys/sockio.h>
74#include <sys/mbuf.h>
75#include <sys/malloc.h>
76#include <sys/kernel.h>
77#include <sys/socket.h>
78#include <sys/module.h>
79#include <sys/bus.h>
80#include <sys/syslog.h>
81#include <sys/sysctl.h>
83
82
83#include <machine/bus.h>
84#include <machine/resource.h>
85#include <machine/clock.h>
86#include <machine/md_var.h>
87#include <machine/bus_pio.h>
88#include <sys/rman.h>
89
84#include <net/if.h>
85#include <net/if_arp.h>
86#include <net/ethernet.h>
87#include <net/if_dl.h>
88#include <net/if_media.h>
89#include <net/if_types.h>
90
90#include <net/if.h>
91#include <net/if_arp.h>
92#include <net/ethernet.h>
93#include <net/if_dl.h>
94#include <net/if_media.h>
95#include <net/if_types.h>
96
91#ifdef INET
92#include <netinet/in.h>
93#include <netinet/in_systm.h>
94#include <netinet/in_var.h>
95#include <netinet/ip.h>
96#include <netinet/if_ether.h>
97#include <netinet/in.h>
98#include <netinet/in_systm.h>
99#include <netinet/in_var.h>
100#include <netinet/ip.h>
101#include <netinet/if_ether.h>
97#endif
98
99#include <net/bpf.h>
100
102
103#include <net/bpf.h>
104
101#include <machine/clock.h>
102#include <machine/md_var.h>
103#include <machine/bus_pio.h>
104#include <machine/bus.h>
105
106#include <i386/isa/isa_device.h>
107#include <i386/isa/icu.h>
108#include <i386/isa/if_wireg.h>
109#include <machine/if_wavelan_ieee.h>
105#include <machine/if_wavelan_ieee.h>
106#include <i386/isa/if_wireg.h>
110
107
111#if NCARD > 0
112#include <sys/select.h>
113#include <pccard/cardinfo.h>
114#include <pccard/slot.h>
115#endif
116
117#if !defined(lint)
118static const char rcsid[] =
108#if !defined(lint)
109static const char rcsid[] =
119 "$FreeBSD: head/sys/dev/wi/if_wi.c 53356 1999-11-18 08:39:02Z peter $";
110 "$FreeBSD: head/sys/dev/wi/if_wi.c 53702 1999-11-25 20:45:49Z wpaul $";
120#endif
121
111#endif
112
122static struct wi_softc wi_softc[NWI];
123
124#ifdef foo
125static u_int8_t wi_mcast_addr[6] = { 0x01, 0x60, 0x1D, 0x00, 0x01, 0x00 };
126#endif
127
113#ifdef foo
114static u_int8_t wi_mcast_addr[6] = { 0x01, 0x60, 0x1D, 0x00, 0x01, 0x00 };
115#endif
116
128static int wi_probe __P((struct isa_device *));
129static int wi_attach __P((struct isa_device *));
130ointhand2_t wi_intr;
117static void wi_intr __P((void *));
131static void wi_reset __P((struct wi_softc *));
132static int wi_ioctl __P((struct ifnet *, u_long, caddr_t));
133static void wi_init __P((void *));
134static void wi_start __P((struct ifnet *));
135static void wi_stop __P((struct wi_softc *));
136static void wi_watchdog __P((struct ifnet *));
118static void wi_reset __P((struct wi_softc *));
119static int wi_ioctl __P((struct ifnet *, u_long, caddr_t));
120static void wi_init __P((void *));
121static void wi_start __P((struct ifnet *));
122static void wi_stop __P((struct wi_softc *));
123static void wi_watchdog __P((struct ifnet *));
137static void wi_shutdown __P((void *, int));
138static void wi_rxeof __P((struct wi_softc *));
139static void wi_txeof __P((struct wi_softc *, int));
140static void wi_update_stats __P((struct wi_softc *));
141static void wi_setmulti __P((struct wi_softc *));
142
143static int wi_cmd __P((struct wi_softc *, int, int));
144static int wi_read_record __P((struct wi_softc *, struct wi_ltv_gen *));
145static int wi_write_record __P((struct wi_softc *, struct wi_ltv_gen *));
146static int wi_read_data __P((struct wi_softc *, int,
147 int, caddr_t, int));
148static int wi_write_data __P((struct wi_softc *, int,
149 int, caddr_t, int));
150static int wi_seek __P((struct wi_softc *, int, int, int));
151static int wi_alloc_nicmem __P((struct wi_softc *, int, int *));
152static void wi_inquire __P((void *));
153static void wi_setdef __P((struct wi_softc *, struct wi_req *));
154static int wi_mgmt_xmit __P((struct wi_softc *, caddr_t, int));
155
124static void wi_rxeof __P((struct wi_softc *));
125static void wi_txeof __P((struct wi_softc *, int));
126static void wi_update_stats __P((struct wi_softc *));
127static void wi_setmulti __P((struct wi_softc *));
128
129static int wi_cmd __P((struct wi_softc *, int, int));
130static int wi_read_record __P((struct wi_softc *, struct wi_ltv_gen *));
131static int wi_write_record __P((struct wi_softc *, struct wi_ltv_gen *));
132static int wi_read_data __P((struct wi_softc *, int,
133 int, caddr_t, int));
134static int wi_write_data __P((struct wi_softc *, int,
135 int, caddr_t, int));
136static int wi_seek __P((struct wi_softc *, int, int, int));
137static int wi_alloc_nicmem __P((struct wi_softc *, int, int *));
138static void wi_inquire __P((void *));
139static void wi_setdef __P((struct wi_softc *, struct wi_req *));
140static int wi_mgmt_xmit __P((struct wi_softc *, caddr_t, int));
141
156struct isa_driver widriver = {
157 wi_probe,
158 wi_attach,
159 "wi",
160 1
161};
142#ifdef WICACHE
143static
144void wi_cache_store __P((struct wi_softc *, struct ether_header *,
145 struct mbuf *, unsigned short));
146#endif
162
147
163#if NCARD > 0
164static int wi_pccard_init __P((struct pccard_devinfo *));
165static void wi_pccard_unload __P((struct pccard_devinfo *));
166static int wi_pccard_intr __P((struct pccard_devinfo *));
148static int wi_pccard_probe __P((device_t));
149static int wi_pccard_attach __P((device_t));
150static int wi_pccard_detach __P((device_t));
151static void wi_shutdown __P((device_t));
167
152
168#ifdef PCCARD_MODULE
169PCCARD_MODULE(wi, wi_pccard_init, wi_pccard_unload,
170 wi_pccard_intr, 0, net_imask);
171#else
172static struct pccard_device wi_info = {
153static int wi_alloc __P((device_t));
154static void wi_free __P((device_t));
155
156static device_method_t wi_pccard_methods[] = {
157 /* Device interface */
158 DEVMETHOD(device_probe, wi_pccard_probe),
159 DEVMETHOD(device_attach, wi_pccard_attach),
160 DEVMETHOD(device_detach, wi_pccard_detach),
161 DEVMETHOD(device_shutdown, wi_shutdown),
162
163 { 0, 0 }
164};
165
166static driver_t wi_pccard_driver = {
173 "wi",
167 "wi",
174 wi_pccard_init,
175 wi_pccard_unload,
176 wi_pccard_intr,
177 0, /* Attributes - presently unused */
178 &net_imask /* Interrupt mask for device */
179 /* XXX - Should this also include net_imask? */
168 wi_pccard_methods,
169 sizeof(struct wi_softc)
180};
181
170};
171
182DATA_SET(pccarddrv_set, wi_info);
183#endif
172static devclass_t wi_pccard_devclass;
184
173
185/* Initialize the PCCARD. */
186static int wi_pccard_init(sc_p)
187 struct pccard_devinfo *sc_p;
174DRIVER_MODULE(if_wi, pccard, wi_pccard_driver, wi_pccard_devclass, 0, 0);
175
176static int wi_pccard_probe(dev)
177 device_t dev;
188{
178{
189 struct wi_softc *sc;
190 int i;
191 u_int32_t irq;
179 struct wi_softc *sc;
180 int error;
192
181
193 if (sc_p->isahd.id_unit >= NWI)
194 return(ENODEV);
195
196 sc = &wi_softc[sc_p->isahd.id_unit];
182 sc = device_get_softc(dev);
197 sc->wi_gone = 0;
183 sc->wi_gone = 0;
198 sc->wi_unit = sc_p->isahd.id_unit;
199 sc->wi_bhandle = sc_p->isahd.id_iobase;
200 sc->wi_btag = I386_BUS_SPACE_IO;
201
184
185 error = wi_alloc(dev);
186 if (error)
187 return (error);
188
189 device_set_desc(dev, "WaveLAN/IEEE 802.11");
190 wi_free(dev);
191
202 /* Make sure interrupts are disabled. */
203 CSR_WRITE_2(sc, WI_INT_EN, 0);
204 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
205
192 /* Make sure interrupts are disabled. */
193 CSR_WRITE_2(sc, WI_INT_EN, 0);
194 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
195
206 /* Grr. IRQ is encoded as a bitmask. */
207 irq = sc_p->isahd.id_irq;
208 for (i = 0; i < 32; i++) {
209 if (irq & 0x1)
210 break;
211 irq >>= 1;
212 }
213
214 /*
215 * Print a nice probe message to let the operator
216 * know something interesting is happening.
217 */
218 printf("wi%d: <WaveLAN/IEEE 802.11> at 0x%x-0x%x irq %d on isa\n",
219 sc_p->isahd.id_unit, sc_p->isahd.id_iobase,
220 sc_p->isahd.id_iobase + WI_IOSIZ - 1, i);
221
222 if (wi_attach(&sc_p->isahd))
223 return(ENXIO);
224
225 return(0);
196 return (0);
226}
227
197}
198
228static void wi_pccard_unload(sc_p)
229 struct pccard_devinfo *sc_p;
199static int wi_pccard_detach(dev)
200 device_t dev;
230{
231 struct wi_softc *sc;
232 struct ifnet *ifp;
201{
202 struct wi_softc *sc;
203 struct ifnet *ifp;
204 int s;
233
205
234 sc = &wi_softc[sc_p->isahd.id_unit];
206 s = splimp();
207
208 sc = device_get_softc(dev);
235 ifp = &sc->arpcom.ac_if;
236
237 if (sc->wi_gone) {
209 ifp = &sc->arpcom.ac_if;
210
211 if (sc->wi_gone) {
238 printf("wi%d: already unloaded\n", sc_p->isahd.id_unit);
239 return;
212 device_printf(dev, "already unloaded\n");
213 return(ENODEV);
240 }
241
214 }
215
242 ifp->if_flags &= ~IFF_RUNNING;
243 if_down(ifp);
216 wi_stop(sc);
217 if_detach(ifp);
218 bus_teardown_intr(dev, sc->irq, &sc->wi_intrhand);
219 wi_free(dev);
244 sc->wi_gone = 1;
220 sc->wi_gone = 1;
245 printf("wi%d: unloaded\n", sc_p->isahd.id_unit);
246
221
247 return;
248}
222 splx(s);
223 device_printf(dev, "unload\n");
249
224
250static int wi_pccard_intr(sc_p)
251 struct pccard_devinfo *sc_p;
252{
253 wi_intr(sc_p->isahd.id_unit);
254 return(1);
255}
256#endif
257
258static int wi_probe(isa_dev)
259 struct isa_device *isa_dev;
260{
261 /*
262 * The ISA WaveLAN/IEEE card is actually not an ISA card:
263 * it's a PCMCIA card plugged into a PCMCIA bridge adapter
264 * that fits into an ISA slot. Consequently, we will always
265 * be using the pccard support to probe and attach these
266 * devices, so we can never actually probe one from here.
267 */
268 return(0);
269}
270
225 return(0);
226}
227
271static int wi_attach(isa_dev)
272 struct isa_device *isa_dev;
228static int wi_pccard_attach(device_t dev)
273{
274 struct wi_softc *sc;
275 struct wi_ltv_macaddr mac;
276 struct wi_ltv_gen gen;
277 struct ifnet *ifp;
229{
230 struct wi_softc *sc;
231 struct wi_ltv_macaddr mac;
232 struct wi_ltv_gen gen;
233 struct ifnet *ifp;
278 char ifname[IFNAMSIZ];
234 int error;
279
235
280#ifdef PCCARD_MODULE
281 isa_dev->id_ointr = wi_intr;
282#endif
283 sc = &wi_softc[isa_dev->id_unit];
236 sc = device_get_softc(dev);
284 ifp = &sc->arpcom.ac_if;
285
237 ifp = &sc->arpcom.ac_if;
238
239 error = wi_alloc(dev);
240 if (error) {
241 device_printf(dev, "wi_alloc() failed! (%d)\n", error);
242 return (error);
243 }
244
245 error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,
246 wi_intr, sc, &sc->wi_intrhand);
247
248 if (error) {
249 device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
250 wi_free(dev);
251 return (error);
252 }
253
286 /* Reset the NIC. */
287 wi_reset(sc);
288
289 /* Read the station address. */
290 mac.wi_type = WI_RID_MAC_NODE;
291 mac.wi_len = 4;
292 wi_read_record(sc, (struct wi_ltv_gen *)&mac);
293 bcopy((char *)&mac.wi_mac_addr,
294 (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
295
254 /* Reset the NIC. */
255 wi_reset(sc);
256
257 /* Read the station address. */
258 mac.wi_type = WI_RID_MAC_NODE;
259 mac.wi_len = 4;
260 wi_read_record(sc, (struct wi_ltv_gen *)&mac);
261 bcopy((char *)&mac.wi_mac_addr,
262 (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
263
296 printf("wi%d: Ethernet address: %6D\n", sc->wi_unit,
264 device_printf(dev, "Ethernet address: %6D\n",
297 sc->arpcom.ac_enaddr, ":");
298
299 ifp->if_softc = sc;
300 ifp->if_unit = sc->wi_unit;
301 ifp->if_name = "wi";
302 ifp->if_mtu = ETHERMTU;
303 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
304 ifp->if_ioctl = wi_ioctl;

--- 38 unchanged lines hidden (view full) ---

343 sc->wi_channel = gen.wi_val;
344
345 bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
346
347 wi_init(sc);
348 wi_stop(sc);
349
350 /*
265 sc->arpcom.ac_enaddr, ":");
266
267 ifp->if_softc = sc;
268 ifp->if_unit = sc->wi_unit;
269 ifp->if_name = "wi";
270 ifp->if_mtu = ETHERMTU;
271 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
272 ifp->if_ioctl = wi_ioctl;

--- 38 unchanged lines hidden (view full) ---

311 sc->wi_channel = gen.wi_val;
312
313 bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
314
315 wi_init(sc);
316 wi_stop(sc);
317
318 /*
351 * If this logical interface has already been attached,
352 * don't attach it again or chaos will ensue.
319 * Call MI attach routines.
353 */
320 */
354 sprintf(ifname, "wi%d", sc->wi_unit);
321 if_attach(ifp);
322 ether_ifattach(ifp);
323 callout_handle_init(&sc->wi_stat_ch);
324 bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
355
325
356 if (ifunit(ifname) == NULL) {
357 callout_handle_init(&sc->wi_stat_ch);
358 /*
359 * Call MI attach routines.
360 */
361 if_attach(ifp);
362 ether_ifattach(ifp);
363
364 bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
365
366 EVENTHANDLER_REGISTER(shutdown_post_sync, wi_shutdown, sc,
367 SHUTDOWN_PRI_DEFAULT);
368 }
369
370 return(0);
371}
372
373static void wi_rxeof(sc)
374 struct wi_softc *sc;
375{
376 struct ifnet *ifp;
377 struct ether_header *eh;

--- 30 unchanged lines hidden (view full) ---

408
409 eh = mtod(m, struct ether_header *);
410 m->m_pkthdr.rcvif = ifp;
411
412 if (rx_frame.wi_status == WI_STAT_1042 ||
413 rx_frame.wi_status == WI_STAT_TUNNEL ||
414 rx_frame.wi_status == WI_STAT_WMP_MSG) {
415 if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES) {
326 return(0);
327}
328
329static void wi_rxeof(sc)
330 struct wi_softc *sc;
331{
332 struct ifnet *ifp;
333 struct ether_header *eh;

--- 30 unchanged lines hidden (view full) ---

364
365 eh = mtod(m, struct ether_header *);
366 m->m_pkthdr.rcvif = ifp;
367
368 if (rx_frame.wi_status == WI_STAT_1042 ||
369 rx_frame.wi_status == WI_STAT_TUNNEL ||
370 rx_frame.wi_status == WI_STAT_WMP_MSG) {
371 if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES) {
416 printf("wi%d: oversized packet received "
417 "(wi_dat_len=%d, wi_status=0x%x)\n", sc->wi_unit,
372 device_printf(sc->dev, "oversized packet received "
373 "(wi_dat_len=%d, wi_status=0x%x)\n",
418 rx_frame.wi_dat_len, rx_frame.wi_status);
419 m_freem(m);
420 ifp->if_ierrors++;
421 return;
422 }
423 m->m_pkthdr.len = m->m_len =
424 rx_frame.wi_dat_len + WI_SNAPHDR_LEN;
425

--- 9 unchanged lines hidden (view full) ---

435 m->m_len + 2)) {
436 m_freem(m);
437 ifp->if_ierrors++;
438 return;
439 }
440 } else {
441 if((rx_frame.wi_dat_len +
442 sizeof(struct ether_header)) > MCLBYTES) {
374 rx_frame.wi_dat_len, rx_frame.wi_status);
375 m_freem(m);
376 ifp->if_ierrors++;
377 return;
378 }
379 m->m_pkthdr.len = m->m_len =
380 rx_frame.wi_dat_len + WI_SNAPHDR_LEN;
381

--- 9 unchanged lines hidden (view full) ---

391 m->m_len + 2)) {
392 m_freem(m);
393 ifp->if_ierrors++;
394 return;
395 }
396 } else {
397 if((rx_frame.wi_dat_len +
398 sizeof(struct ether_header)) > MCLBYTES) {
443 printf("wi%d: oversized packet received "
444 "(wi_dat_len=%d, wi_status=0x%x)\n", sc->wi_unit,
399 device_printf(sc->dev, "oversized packet received "
400 "(wi_dat_len=%d, wi_status=0x%x)\n",
445 rx_frame.wi_dat_len, rx_frame.wi_status);
446 m_freem(m);
447 ifp->if_ierrors++;
448 return;
449 }
450 m->m_pkthdr.len = m->m_len =
451 rx_frame.wi_dat_len + sizeof(struct ether_header);
452

--- 15 unchanged lines hidden (view full) ---

468 ETHER_ADDR_LEN) && (eh->ether_dhost[0] & 1) == 0)) {
469 m_freem(m);
470 return;
471 }
472 }
473
474 /* Receive packet. */
475 m_adj(m, sizeof(struct ether_header));
401 rx_frame.wi_dat_len, rx_frame.wi_status);
402 m_freem(m);
403 ifp->if_ierrors++;
404 return;
405 }
406 m->m_pkthdr.len = m->m_len =
407 rx_frame.wi_dat_len + sizeof(struct ether_header);
408

--- 15 unchanged lines hidden (view full) ---

424 ETHER_ADDR_LEN) && (eh->ether_dhost[0] & 1) == 0)) {
425 m_freem(m);
426 return;
427 }
428 }
429
430 /* Receive packet. */
431 m_adj(m, sizeof(struct ether_header));
432#ifdef WICACHE
433 wi_cache_store(sc, eh, m, rx_frame.wi_q_info);
434#endif
476 ether_input(ifp, eh, m);
477
478 return;
479}
480
481static void wi_txeof(sc, status)
482 struct wi_softc *sc;
483 int status;

--- 66 unchanged lines hidden (view full) ---

550
551 ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
552 sc->wi_stats.wi_tx_multi_retries +
553 sc->wi_stats.wi_tx_retry_limit;
554
555 return;
556}
557
435 ether_input(ifp, eh, m);
436
437 return;
438}
439
440static void wi_txeof(sc, status)
441 struct wi_softc *sc;
442 int status;

--- 66 unchanged lines hidden (view full) ---

509
510 ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
511 sc->wi_stats.wi_tx_multi_retries +
512 sc->wi_stats.wi_tx_retry_limit;
513
514 return;
515}
516
558void wi_intr(unit)
559 int unit;
517static void wi_intr(xsc)
518 void *xsc;
560{
519{
561 struct wi_softc *sc;
520 struct wi_softc *sc = xsc;
562 struct ifnet *ifp;
563 u_int16_t status;
564
521 struct ifnet *ifp;
522 u_int16_t status;
523
565 sc = &wi_softc[unit];
566 ifp = &sc->arpcom.ac_if;
567
568 if (!(ifp->if_flags & IFF_UP)) {
569 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
570 CSR_WRITE_2(sc, WI_INT_EN, 0);
571 return;
572 }
573

--- 78 unchanged lines hidden (view full) ---

652 return(ETIMEDOUT);
653
654 return(0);
655}
656
657static void wi_reset(sc)
658 struct wi_softc *sc;
659{
524 ifp = &sc->arpcom.ac_if;
525
526 if (!(ifp->if_flags & IFF_UP)) {
527 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
528 CSR_WRITE_2(sc, WI_INT_EN, 0);
529 return;
530 }
531

--- 78 unchanged lines hidden (view full) ---

610 return(ETIMEDOUT);
611
612 return(0);
613}
614
615static void wi_reset(sc)
616 struct wi_softc *sc;
617{
618 wi_cmd(sc, WI_CMD_INI, 0);
619 DELAY(100000);
620 wi_cmd(sc, WI_CMD_INI, 0);
621 DELAY(100000);
622#ifdef foo
660 if (wi_cmd(sc, WI_CMD_INI, 0))
623 if (wi_cmd(sc, WI_CMD_INI, 0))
661 printf("wi%d: init failed\n", sc->wi_unit);
624 device_printf(sc->dev, "init failed\n");
662 CSR_WRITE_2(sc, WI_INT_EN, 0);
663 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
664
665 /* Calibrate timer. */
666 WI_SETVAL(WI_RID_TICK_TIME, 8);
625 CSR_WRITE_2(sc, WI_INT_EN, 0);
626 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
627
628 /* Calibrate timer. */
629 WI_SETVAL(WI_RID_TICK_TIME, 8);
667
630#endif
668 return;
669}
670
671/*
672 * Read an LTV record from the NIC.
673 */
674static int wi_read_record(sc, ltv)
675 struct wi_softc *sc;

--- 71 unchanged lines hidden (view full) ---

747 selreg = WI_SEL0;
748 offreg = WI_OFF0;
749 break;
750 case WI_BAP1:
751 selreg = WI_SEL1;
752 offreg = WI_OFF1;
753 break;
754 default:
631 return;
632}
633
634/*
635 * Read an LTV record from the NIC.
636 */
637static int wi_read_record(sc, ltv)
638 struct wi_softc *sc;

--- 71 unchanged lines hidden (view full) ---

710 selreg = WI_SEL0;
711 offreg = WI_OFF0;
712 break;
713 case WI_BAP1:
714 selreg = WI_SEL1;
715 offreg = WI_OFF1;
716 break;
717 default:
755 printf("wi%d: invalid data path: %x\n", sc->wi_unit, chan);
718 device_printf(sc->dev, "invalid data path: %x\n", chan);
756 return(EIO);
757 }
758
759 CSR_WRITE_2(sc, selreg, id);
760 CSR_WRITE_2(sc, offreg, off);
761
762 for (i = 0; i < WI_TIMEOUT; i++) {
763 if (!(CSR_READ_2(sc, offreg) & (WI_OFF_BUSY|WI_OFF_ERR)))

--- 79 unchanged lines hidden (view full) ---

843static int wi_alloc_nicmem(sc, len, id)
844 struct wi_softc *sc;
845 int len;
846 int *id;
847{
848 int i;
849
850 if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) {
719 return(EIO);
720 }
721
722 CSR_WRITE_2(sc, selreg, id);
723 CSR_WRITE_2(sc, offreg, off);
724
725 for (i = 0; i < WI_TIMEOUT; i++) {
726 if (!(CSR_READ_2(sc, offreg) & (WI_OFF_BUSY|WI_OFF_ERR)))

--- 79 unchanged lines hidden (view full) ---

806static int wi_alloc_nicmem(sc, len, id)
807 struct wi_softc *sc;
808 int len;
809 int *id;
810{
811 int i;
812
813 if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) {
851 printf("wi%d: failed to allocate %d bytes on NIC\n",
852 sc->wi_unit, len);
814 device_printf(sc->dev, "failed to allocate %d bytes on NIC\n", len);
853 return(ENOMEM);
854 }
855
856 for (i = 0; i < WI_TIMEOUT; i++) {
857 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
858 break;
859 }
860

--- 171 unchanged lines hidden (view full) ---

1032 case SIOCGWAVELAN:
1033 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1034 if (error)
1035 break;
1036 if (wreq.wi_type == WI_RID_IFACE_STATS) {
1037 bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
1038 sizeof(sc->wi_stats));
1039 wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
815 return(ENOMEM);
816 }
817
818 for (i = 0; i < WI_TIMEOUT; i++) {
819 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
820 break;
821 }
822

--- 171 unchanged lines hidden (view full) ---

994 case SIOCGWAVELAN:
995 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
996 if (error)
997 break;
998 if (wreq.wi_type == WI_RID_IFACE_STATS) {
999 bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
1000 sizeof(sc->wi_stats));
1001 wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1040 } else {
1002 }
1003#ifdef WICACHE
1004 else if (wreq.wi_type == WI_RID_ZERO_CACHE) {
1005 sc->wi_sigitems = sc->wi_nextitem = 0;
1006 } else if (wreq.wi_type == WI_RID_READ_CACHE) {
1007 char *pt = (char *)&wreq.wi_val;
1008 bcopy((char *)&sc->wi_sigitems,
1009 (char *)pt, sizeof(int));
1010 pt += (sizeof (int));
1011 wreq.wi_len = sizeof(int) / 2;
1012 bcopy((char *)&sc->wi_sigcache, (char *)pt,
1013 sizeof(struct wi_sigcache) * sc->wi_sigitems);
1014 wreq.wi_len += ((sizeof(struct wi_sigcache) *
1015 sc->wi_sigitems) / 2) + 1;
1016 }
1017#endif
1018 else {
1041 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) {
1042 error = EINVAL;
1043 break;
1044 }
1045 }
1046 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1047 break;
1048 case SIOCSWAVELAN:

--- 93 unchanged lines hidden (view full) ---

1142
1143 /* Set multicast filter. */
1144 wi_setmulti(sc);
1145
1146 /* Enable desired port */
1147 wi_cmd(sc, WI_CMD_ENABLE|sc->wi_portnum, 0);
1148
1149 if (wi_alloc_nicmem(sc, 1518 + sizeof(struct wi_frame) + 8, &id))
1019 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) {
1020 error = EINVAL;
1021 break;
1022 }
1023 }
1024 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1025 break;
1026 case SIOCSWAVELAN:

--- 93 unchanged lines hidden (view full) ---

1120
1121 /* Set multicast filter. */
1122 wi_setmulti(sc);
1123
1124 /* Enable desired port */
1125 wi_cmd(sc, WI_CMD_ENABLE|sc->wi_portnum, 0);
1126
1127 if (wi_alloc_nicmem(sc, 1518 + sizeof(struct wi_frame) + 8, &id))
1150 printf("wi%d: tx buffer allocation failed\n", sc->wi_unit);
1128 device_printf(sc->dev, "tx buffer allocation failed\n");
1151 sc->wi_tx_data_id = id;
1152
1153 if (wi_alloc_nicmem(sc, 1518 + sizeof(struct wi_frame) + 8, &id))
1129 sc->wi_tx_data_id = id;
1130
1131 if (wi_alloc_nicmem(sc, 1518 + sizeof(struct wi_frame) + 8, &id))
1154 printf("wi%d: mgmt. buffer allocation failed\n", sc->wi_unit);
1132 device_printf(sc->dev, "mgmt. buffer allocation failed\n");
1155 sc->wi_tx_mgmt_id = id;
1156
1157 /* enable interrupts */
1158 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
1159
1160 splx(s);
1161
1162 ifp->if_flags |= IFF_RUNNING;

--- 76 unchanged lines hidden (view full) ---

1239 * this frame to him.
1240 */
1241 if (ifp->if_bpf)
1242 bpf_mtap(ifp, m0);
1243
1244 m_freem(m0);
1245
1246 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id))
1133 sc->wi_tx_mgmt_id = id;
1134
1135 /* enable interrupts */
1136 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
1137
1138 splx(s);
1139
1140 ifp->if_flags |= IFF_RUNNING;

--- 76 unchanged lines hidden (view full) ---

1217 * this frame to him.
1218 */
1219 if (ifp->if_bpf)
1220 bpf_mtap(ifp, m0);
1221
1222 m_freem(m0);
1223
1224 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id))
1247 printf("wi%d: xmit failed\n", sc->wi_unit);
1225 device_printf(sc->dev, "xmit failed\n");
1248
1249 ifp->if_flags |= IFF_OACTIVE;
1250
1251 /*
1252 * Set a timeout in case the chip goes out to lunch.
1253 */
1254 ifp->if_timer = 5;
1255

--- 25 unchanged lines hidden (view full) ---

1281 tx_frame.wi_dat_len = len - WI_SNAPHDR_LEN;
1282 tx_frame.wi_len = htons(len - WI_SNAPHDR_LEN);
1283
1284 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
1285 wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
1286 (len - sizeof(struct wi_80211_hdr)) + 2);
1287
1288 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) {
1226
1227 ifp->if_flags |= IFF_OACTIVE;
1228
1229 /*
1230 * Set a timeout in case the chip goes out to lunch.
1231 */
1232 ifp->if_timer = 5;
1233

--- 25 unchanged lines hidden (view full) ---

1259 tx_frame.wi_dat_len = len - WI_SNAPHDR_LEN;
1260 tx_frame.wi_len = htons(len - WI_SNAPHDR_LEN);
1261
1262 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
1263 wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
1264 (len - sizeof(struct wi_80211_hdr)) + 2);
1265
1266 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) {
1289 printf("wi%d: xmit failed\n", sc->wi_unit);
1267 device_printf(sc->dev, "xmit failed\n");
1290 return(EIO);
1291 }
1292
1293 return(0);
1294}
1295
1296static void wi_stop(sc)
1297 struct wi_softc *sc;

--- 17 unchanged lines hidden (view full) ---

1315
1316static void wi_watchdog(ifp)
1317 struct ifnet *ifp;
1318{
1319 struct wi_softc *sc;
1320
1321 sc = ifp->if_softc;
1322
1268 return(EIO);
1269 }
1270
1271 return(0);
1272}
1273
1274static void wi_stop(sc)
1275 struct wi_softc *sc;

--- 17 unchanged lines hidden (view full) ---

1293
1294static void wi_watchdog(ifp)
1295 struct ifnet *ifp;
1296{
1297 struct wi_softc *sc;
1298
1299 sc = ifp->if_softc;
1300
1323 printf("wi%d: device timeout\n", sc->wi_unit);
1301 device_printf(sc->dev,"device timeout\n");
1324
1325 wi_init(sc);
1326
1327 ifp->if_oerrors++;
1328
1329 return;
1330}
1331
1302
1303 wi_init(sc);
1304
1305 ifp->if_oerrors++;
1306
1307 return;
1308}
1309
1332static void wi_shutdown(arg, howto)
1333 void *arg;
1334 int howto;
1310static int wi_alloc(dev)
1311 device_t dev;
1335{
1312{
1313 struct wi_softc *sc = device_get_softc(dev);
1314 int rid;
1315
1316 rid = 0;
1317 sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
1318 0, ~0, 1, RF_ACTIVE);
1319 if (!sc->iobase) {
1320 device_printf(dev, "No I/O space?!\n");
1321 return (ENXIO);
1322 }
1323
1324 rid = 0;
1325 sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
1326 0, ~0, 1, RF_ACTIVE);
1327 if (!sc->irq) {
1328 device_printf(dev, "No irq?!\n");
1329 return (ENXIO);
1330 }
1331
1332 sc->dev = dev;
1333 sc->wi_unit = device_get_unit(dev);
1334 sc->wi_io_addr = rman_get_start(sc->iobase);
1335 sc->wi_btag = rman_get_bustag(sc->iobase);
1336 sc->wi_bhandle = rman_get_bushandle(sc->iobase);
1337
1338 return (0);
1339}
1340
1341static void wi_free(dev)
1342 device_t dev;
1343{
1344 struct wi_softc *sc = device_get_softc(dev);
1345
1346 if (sc->iobase != NULL)
1347 bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->iobase);
1348 if (sc->irq != NULL)
1349 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
1350
1351 return;
1352}
1353
1354static void wi_shutdown(dev)
1355 device_t dev;
1356{
1336 struct wi_softc *sc;
1337
1357 struct wi_softc *sc;
1358
1338 sc = arg;
1359 sc = device_get_softc(dev);
1339 wi_stop(sc);
1340
1341 return;
1342}
1360 wi_stop(sc);
1361
1362 return;
1363}
1364
1365#ifdef WICACHE
1366/* wavelan signal strength cache code.
1367 * store signal/noise/quality on per MAC src basis in
1368 * a small fixed cache. The cache wraps if > MAX slots
1369 * used. The cache may be zeroed out to start over.
1370 * Two simple filters exist to reduce computation:
1371 * 1. ip only (literally 0x800) which may be used
1372 * to ignore some packets. It defaults to ip only.
1373 * it could be used to focus on broadcast, non-IP 802.11 beacons.
1374 * 2. multicast/broadcast only. This may be used to
1375 * ignore unicast packets and only cache signal strength
1376 * for multicast/broadcast packets (beacons); e.g., Mobile-IP
1377 * beacons and not unicast traffic.
1378 *
1379 * The cache stores (MAC src(index), IP src (major clue), signal,
1380 * quality, noise)
1381 *
1382 * No apologies for storing IP src here. It's easy and saves much
1383 * trouble elsewhere. The cache is assumed to be INET dependent,
1384 * although it need not be.
1385 */
1386
1387#ifdef documentation
1388
1389int wi_sigitems; /* number of cached entries */
1390struct wi_sigcache wi_sigcache[MAXWICACHE]; /* array of cache entries */
1391int wi_nextitem; /* index/# of entries */
1392
1393
1394#endif
1395
1396/* control variables for cache filtering. Basic idea is
1397 * to reduce cost (e.g., to only Mobile-IP agent beacons
1398 * which are broadcast or multicast). Still you might
1399 * want to measure signal strength with unicast ping packets
1400 * on a pt. to pt. ant. setup.
1401 */
1402/* set true if you want to limit cache items to broadcast/mcast
1403 * only packets (not unicast). Useful for mobile-ip beacons which
1404 * are broadcast/multicast at network layer. Default is all packets
1405 * so ping/unicast will work say with pt. to pt. antennae setup.
1406 */
1407static int wi_cache_mcastonly = 0;
1408SYSCTL_INT(_machdep, OID_AUTO, wi_cache_mcastonly, CTLFLAG_RW,
1409 &wi_cache_mcastonly, 0, "");
1410
1411/* set true if you want to limit cache items to IP packets only
1412*/
1413static int wi_cache_iponly = 1;
1414SYSCTL_INT(_machdep, OID_AUTO, wi_cache_iponly, CTLFLAG_RW,
1415 &wi_cache_iponly, 0, "");
1416
1417/*
1418 * Original comments:
1419 * -----------------
1420 * wi_cache_store, per rx packet store signal
1421 * strength in MAC (src) indexed cache.
1422 *
1423 * follows linux driver in how signal strength is computed.
1424 * In ad hoc mode, we use the rx_quality field.
1425 * signal and noise are trimmed to fit in the range from 47..138.
1426 * rx_quality field MSB is signal strength.
1427 * rx_quality field LSB is noise.
1428 * "quality" is (signal - noise) as is log value.
1429 * note: quality CAN be negative.
1430 *
1431 * In BSS mode, we use the RID for communication quality.
1432 * TBD: BSS mode is currently untested.
1433 *
1434 * Bill's comments:
1435 * ---------------
1436 * Actually, we use the rx_quality field all the time for both "ad-hoc"
1437 * and BSS modes. Why? Because reading an RID is really, really expensive:
1438 * there's a bunch of PIO operations that have to be done to read a record
1439 * from the NIC, and reading the comms quality RID each time a packet is
1440 * received can really hurt performance. We don't have to do this anyway:
1441 * the comms quality field only reflects the values in the rx_quality field
1442 * anyway. The comms quality RID is only meaningful in infrastructure mode,
1443 * but the values it contains are updated based on the rx_quality from
1444 * frames received from the access point.
1445 *
1446 * Also, according to Lucent, the signal strength and noise level values
1447 * can be converted to dBms by subtracting 149, so I've modified the code
1448 * to do that instead of the scaling it did originally.
1449 */
1450static
1451void wi_cache_store (struct wi_softc *sc, struct ether_header *eh,
1452 struct mbuf *m, unsigned short rx_quality)
1453{
1454 struct ip *ip = 0;
1455 int i;
1456 static int cache_slot = 0; /* use this cache entry */
1457 static int wrapindex = 0; /* next "free" cache entry */
1458 int sig, noise;
1459 int sawip=0;
1460
1461 /* filters:
1462 * 1. ip only
1463 * 2. configurable filter to throw out unicast packets,
1464 * keep multicast only.
1465 */
1466
1467 if ((ntohs(eh->ether_type) == 0x800)) {
1468 sawip = 1;
1469 }
1470
1471 /* filter for ip packets only
1472 */
1473 if (wi_cache_iponly && !sawip) {
1474 return;
1475 }
1476
1477 /* filter for broadcast/multicast only
1478 */
1479 if (wi_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
1480 return;
1481 }
1482
1483#ifdef SIGDEBUG
1484 printf("wi%d: q value %x (MSB=0x%x, LSB=0x%x) \n", sc->wi_unit,
1485 rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff);
1486#endif
1487
1488 /* find the ip header. we want to store the ip_src
1489 * address.
1490 */
1491 if (sawip) {
1492 ip = mtod(m, struct ip *);
1493 }
1494
1495 /* do a linear search for a matching MAC address
1496 * in the cache table
1497 * . MAC address is 6 bytes,
1498 * . var w_nextitem holds total number of entries already cached
1499 */
1500 for(i = 0; i < sc->wi_nextitem; i++) {
1501 if (! bcmp(eh->ether_shost , sc->wi_sigcache[i].macsrc, 6 )) {
1502 /* Match!,
1503 * so we already have this entry,
1504 * update the data
1505 */
1506 break;
1507 }
1508 }
1509
1510 /* did we find a matching mac address?
1511 * if yes, then overwrite a previously existing cache entry
1512 */
1513 if (i < sc->wi_nextitem ) {
1514 cache_slot = i;
1515 }
1516 /* else, have a new address entry,so
1517 * add this new entry,
1518 * if table full, then we need to replace LRU entry
1519 */
1520 else {
1521
1522 /* check for space in cache table
1523 * note: wi_nextitem also holds number of entries
1524 * added in the cache table
1525 */
1526 if ( sc->wi_nextitem < MAXWICACHE ) {
1527 cache_slot = sc->wi_nextitem;
1528 sc->wi_nextitem++;
1529 sc->wi_sigitems = sc->wi_nextitem;
1530 }
1531 /* no space found, so simply wrap with wrap index
1532 * and "zap" the next entry
1533 */
1534 else {
1535 if (wrapindex == MAXWICACHE) {
1536 wrapindex = 0;
1537 }
1538 cache_slot = wrapindex++;
1539 }
1540 }
1541
1542 /* invariant: cache_slot now points at some slot
1543 * in cache.
1544 */
1545 if (cache_slot < 0 || cache_slot >= MAXWICACHE) {
1546 log(LOG_ERR, "wi_cache_store, bad index: %d of "
1547 "[0..%d], gross cache error\n",
1548 cache_slot, MAXWICACHE);
1549 return;
1550 }
1551
1552 /* store items in cache
1553 * .ip source address
1554 * .mac src
1555 * .signal, etc.
1556 */
1557 if (sawip) {
1558 sc->wi_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr;
1559 }
1560 bcopy( eh->ether_shost, sc->wi_sigcache[cache_slot].macsrc, 6);
1561
1562 sig = (rx_quality >> 8) & 0xFF;
1563 noise = rx_quality & 0xFF;
1564 sc->wi_sigcache[cache_slot].signal = sig - 149;
1565 sc->wi_sigcache[cache_slot].noise = noise - 149;
1566 sc->wi_sigcache[cache_slot].quality = sig - noise;
1567
1568 return;
1569}
1570#endif