3 * Dr. Duncan McLennan Barclay, dmlb@ragnet.demon.co.uk.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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. Neither the name of the author nor the names of any co-contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY DUNCAN BARCLAY AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL DUNCAN BARCLAY OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * $FreeBSD: src/sys/dev/ray/if_ray.c,v 1.47.2.4 2001/08/14 22:54:05 dmlb Exp $
32 * $DragonFly: src/sys/dev/netif/ray/Attic/if_ray.c,v 1.31 2006/12/22 23:26:21 swildner Exp $
36 /* $NetBSD: if_ray.c,v 1.12 2000/02/07 09:36:27 augustss Exp $ */
38 * Copyright (c) 2000 Christian E. Hopps
39 * All rights reserved.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. Neither the name of the author nor the names of any co-contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
53 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70 * This card is unusual in that it uses both common and attribute
71 * memory whilst working. It should use common memory and an IO port.
73 * The bus resource allocations need to work around the brain deadness
74 * of pccardd (where it reads the CIS for common memory, sets it all
75 * up and then throws it all away assuming the card is an ed
76 * driver...). Note that this could be dangerous (because it doesn't
77 * interact with pccardd) if you use other memory mapped cards in the
78 * same pccard slot as currently old mappings are not cleaned up very well
79 * by the bus_release_resource methods or pccardd.
81 * There is no support for running this driver on 4.0.
83 * Ad-hoc and infra-structure modes
84 * ================================
86 * The driver supports ad-hoc mode for V4 firmware and infrastructure
87 * mode for V5 firmware. V5 firmware in ad-hoc mode is untested and should
90 * The Linux driver also seems to have the capability to act as an AP.
91 * I wonder what facilities the "AP" can provide within a driver? We can
92 * probably use the BRIDGE code to form an ESS but I don't think
93 * power saving etc. is easy.
96 * Packet framing/encapsulation/translation
97 * ========================================
99 * Currently we support the Webgear encapsulation:
100 * 802.11 header <net/if_ieee80211.h>struct ieee80211_frame
101 * 802.3 header <net/ethernet.h>struct ether_header
104 * and RFC1042 encapsulation of IP datagrams (translation):
105 * 802.11 header <net/if_ieee80211.h>struct ieee80211_frame
111 * Framing should be selected via if_media stuff or link types but
112 * is currently hardcoded to:
120 * 802.11 provides two authentication mechanisms. The first is a very
121 * simple host based mechanism (like xhost) called Open System and the
122 * second is a more complex challenge/response called Shared Key built
125 * This driver only supports Open System and does not implement any
126 * host based control lists. In otherwords authentication is always
127 * granted to hosts wanting to authenticate with this station. This is
128 * the only sensible behaviour as the Open System mechanism uses MAC
129 * addresses to identify hosts. Send me patches if you need it!
133 * ***check all XXX_INFRA code - reassoc not done well at all!
134 * ***watchdog to catch screwed up removals?
135 * ***error handling of RAY_COM_RUNQ
136 * ***error handling of ECF command completions
137 * ***can't seem to create a n/w that Win95 wants to see.
138 * ***remove panic in ray_com_ecf by re-quing or timeout
139 * ***use new ioctl stuff - probably need to change RAY_COM_FCHKRUNNING things?
140 * consider user doing:
141 * ifconfig ray0 192.168.200.38 -bssid "freed"
142 * ifconfig ray0 192.168.200.38 -bssid "fred"
143 * here the second one would be missed in this code
144 * check that v5 needs timeouts on ecf commands
145 * write up driver structure in comments above
146 * UPDATE_PARAMS seems to return via an interrupt - maybe the timeout
147 * is needed for wrong values?
148 * proper setting of mib_hop_seq_len with country code for v4 firmware
149 * best done with raycontrol?
150 * countrycode setting is broken I think
151 * userupdate should trap and do via startjoin etc.
152 * fragmentation when rx level drops?
153 * v5 might not need download
154 * defaults are as documented apart from hop_seq_length
155 * settings are sane for ad-hoc not infra
158 * most state is implied by the sequence of commands in the runq
159 * but in fact any of the rx and tx path that uses variables
160 * in the sc_c are potentially going to get screwed?
163 * proper handling of the basic rate set - see the manual
164 * all ray_sj, ray_assoc sequencues need a "nicer" solution as we
165 * remember association and authentication
166 * need to consider WEP
167 * acting as ap - should be able to get working from the manual
168 * need to finish RAY_ECMD_REJOIN_DONE
169 * finish authenitcation code, it doesn't handle errors/timeouts/
173 * promisc in here too? - done
174 * should be able to update the parameters before we download to the
175 * device. This means we must attach a desired struct to the
176 * runq entry and maybe have another big case statement to
177 * move these desired into current when not running.
178 * init must then use the current settings (pre-loaded
179 * in attach now!) and pass to download. But we can't access
180 * current nw params outside of the runq - ahhh
181 * differeniate between parameters set in attach and init
182 * sc_station_addr in here too (for changing mac address)
183 * move desired into the command structure?
184 * take downloaded MIB from a complete nw_param?
185 * longer term need to attach a desired nw params to the runq entry
188 * RAY_COM_RUNQ errors
190 * if sleeping in ccs_alloc with eintr/erestart/enxio/enodev
191 * erestart try again from the top
192 * XXX do not malloc more comqs
193 * XXX ccs allocation hard
194 * eintr clean up and return
195 * enxio clean up and return - done in macro
197 * if sleeping in runq_arr itself with eintr/erestart/enxio/enodev
198 * erestart try again from the top
199 * XXX do not malloc more comqs
200 * XXX ccs allocation hard
201 * XXX reinsert comqs at head of list
202 * eintr clean up and return
203 * enxio clean up and return - done in macro
207 #define XXX_ACTING_AP 0
209 #define RAY_DEBUG ( \
210 /* RAY_DBG_AUTH | */ \
211 /* RAY_DBG_SUBR | */ \
212 /* RAY_DBG_BOOTPARAM | */ \
213 /* RAY_DBG_STARTJOIN | */ \
214 /* RAY_DBG_CCS | */ \
215 /* RAY_DBG_IOCTL | */ \
216 /* RAY_DBG_MBUF | */ \
219 /* RAY_DBG_COM | */ \
220 /* RAY_DBG_STOP | */ \
221 /* RAY_DBG_CTL | */ \
222 /* RAY_DBG_MGT | */ \
224 /* RAY_DBG_DCOM | */ \
229 * XXX build options - move to LINT
231 #define RAY_CM_RID 0 /* pccardd abuses windows 0 and 1 */
232 #define RAY_AM_RID 3 /* pccardd abuses windows 0 and 1 */
233 #define RAY_COM_TIMEOUT (hz/2) /* Timeout for CCS commands */
234 #define RAY_TX_TIMEOUT (hz/2) /* Timeout for rescheduling TX */
235 #define RAY_ECF_SPIN_DELAY 1000 /* Wait 1ms before checking ECF ready */
236 #define RAY_ECF_SPIN_TRIES 10 /* Wait this many times for ECF ready */
238 * XXX build options - move to LINT
242 #define RAY_DEBUG 0x0000
243 #endif /* RAY_DEBUG */
245 #include <sys/param.h>
246 #include <sys/systm.h>
247 #include <sys/malloc.h>
248 #include <sys/kernel.h>
249 #include <sys/thread2.h>
251 #include <sys/rman.h>
252 #include <sys/mbuf.h>
253 #include <sys/socket.h>
254 #include <sys/sockio.h>
256 #include <machine/clock.h>
259 #include <net/ethernet.h>
261 #include <net/ifq_var.h>
262 #include <net/if_arp.h>
263 #include <net/if_dl.h>
264 #include <net/if_llc.h>
266 #include <netproto/802_11/ieee80211.h>
267 #include <netproto/802_11/ieee80211_ioctl.h>
269 #include <machine/limits.h>
271 #include <bus/pccard/pccardvar.h>
274 #include "if_rayreg.h"
275 #include "if_raymib.h"
276 #include "if_raydbg.h"
277 #include "if_rayvar.h"
282 static int ray_attach (device_t
);
283 static int ray_ccs_alloc (struct ray_softc
*sc
, size_t *ccsp
, char *wmesg
);
284 static void ray_ccs_fill (struct ray_softc
*sc
, size_t ccs
, u_int cmd
);
285 static void ray_ccs_free (struct ray_softc
*sc
, size_t ccs
);
286 static int ray_ccs_tx (struct ray_softc
*sc
, size_t *ccsp
, size_t *bufpp
);
287 static void ray_com_ecf (struct ray_softc
*sc
, struct ray_comq_entry
*com
);
288 static void ray_com_ecf_done (struct ray_softc
*sc
);
289 static void ray_com_ecf_timo (void *xsc
);
290 static struct ray_comq_entry
*
291 ray_com_init (struct ray_comq_entry
*com
, ray_comqfn_t function
, int flags
, char *mesg
);
292 static struct ray_comq_entry
*
293 ray_com_malloc (ray_comqfn_t function
, int flags
, char *mesg
);
294 static void ray_com_runq (struct ray_softc
*sc
);
295 static int ray_com_runq_add (struct ray_softc
*sc
, struct ray_comq_entry
*com
[], int ncom
, char *wmesg
);
296 static void ray_com_runq_done (struct ray_softc
*sc
);
297 static int ray_detach (device_t
);
298 static void ray_init (void *xsc
);
299 static int ray_init_user (struct ray_softc
*sc
);
300 static void ray_init_assoc (struct ray_softc
*sc
, struct ray_comq_entry
*com
);
301 static void ray_init_assoc_done (struct ray_softc
*sc
, u_int8_t status
, size_t ccs
);
302 static void ray_init_auth (struct ray_softc
*sc
, struct ray_comq_entry
*com
);
303 static int ray_init_auth_send (struct ray_softc
*sc
, u_int8_t
*dst
, int sequence
);
304 static void ray_init_auth_done (struct ray_softc
*sc
, u_int8_t status
);
305 static void ray_init_download (struct ray_softc
*sc
, struct ray_comq_entry
*com
);
306 static void ray_init_download_done (struct ray_softc
*sc
, u_int8_t status
, size_t ccs
);
307 static void ray_init_download_v4 (struct ray_softc
*sc
, struct ray_comq_entry
*com
);
308 static void ray_init_download_v5 (struct ray_softc
*sc
, struct ray_comq_entry
*com
);
309 static void ray_init_mcast (struct ray_softc
*sc
, struct ray_comq_entry
*com
);
310 static void ray_init_sj (struct ray_softc
*sc
, struct ray_comq_entry
*com
);
311 static void ray_init_sj_done (struct ray_softc
*sc
, u_int8_t status
, size_t ccs
);
312 static void ray_intr (void *xsc
);
313 static void ray_intr_ccs (struct ray_softc
*sc
, u_int8_t cmd
, u_int8_t status
, size_t ccs
);
314 static void ray_intr_rcs (struct ray_softc
*sc
, u_int8_t cmd
, size_t ccs
);
315 static void ray_intr_updt_errcntrs (struct ray_softc
*sc
);
316 static int ray_ioctl (struct ifnet
*ifp
, u_long command
, caddr_t data
, struct ucred
*cr
);
317 static void ray_mcast (struct ray_softc
*sc
, struct ray_comq_entry
*com
);
318 static void ray_mcast_done (struct ray_softc
*sc
, u_int8_t status
, size_t ccs
);
319 static int ray_mcast_user (struct ray_softc
*sc
);
320 static int ray_probe (device_t
);
321 static void ray_promisc (struct ray_softc
*sc
, struct ray_comq_entry
*com
);
322 static void ray_repparams (struct ray_softc
*sc
, struct ray_comq_entry
*com
);
323 static void ray_repparams_done (struct ray_softc
*sc
, u_int8_t status
, size_t ccs
);
324 static int ray_repparams_user (struct ray_softc
*sc
, struct ray_param_req
*pr
);
325 static int ray_repstats_user (struct ray_softc
*sc
, struct ray_stats_req
*sr
);
326 static int ray_res_alloc_am (struct ray_softc
*sc
);
327 static int ray_res_alloc_cm (struct ray_softc
*sc
);
328 static int ray_res_alloc_irq (struct ray_softc
*sc
);
329 static void ray_res_release (struct ray_softc
*sc
);
330 static void ray_rx (struct ray_softc
*sc
, size_t rcs
);
331 static void ray_rx_ctl (struct ray_softc
*sc
, struct mbuf
*m0
);
332 static void ray_rx_data (struct ray_softc
*sc
, struct mbuf
*m0
, u_int8_t siglev
, u_int8_t antenna
);
333 static void ray_rx_mgt (struct ray_softc
*sc
, struct mbuf
*m0
);
334 static void ray_rx_mgt_auth (struct ray_softc
*sc
, struct mbuf
*m0
);
335 static void ray_rx_mgt_beacon (struct ray_softc
*sc
, struct mbuf
*m0
);
336 static void ray_rx_mgt_info (struct ray_softc
*sc
, struct mbuf
*m0
,
337 union ieee80211_information
*elements
);
338 static void ray_rx_update_cache (struct ray_softc
*sc
, u_int8_t
*src
, u_int8_t siglev
, u_int8_t antenna
);
339 static void ray_stop (struct ray_softc
*sc
, struct ray_comq_entry
*com
);
340 static int ray_stop_user (struct ray_softc
*sc
);
341 static void ray_tx (struct ifnet
*ifp
);
342 static void ray_tx_done (struct ray_softc
*sc
, u_int8_t status
, size_t ccs
);
343 static void ray_tx_timo (void *xsc
);
344 static int ray_tx_send (struct ray_softc
*sc
, size_t ccs
, int pktlen
, u_int8_t
*dst
);
345 static size_t ray_tx_wrhdr (struct ray_softc
*sc
, size_t bufp
, u_int8_t type
, u_int8_t fc1
, u_int8_t
*addr1
, u_int8_t
*addr2
, u_int8_t
*addr3
);
346 static void ray_upparams (struct ray_softc
*sc
, struct ray_comq_entry
*com
);
347 static void ray_upparams_done (struct ray_softc
*sc
, u_int8_t status
, size_t ccs
);
348 static int ray_upparams_user (struct ray_softc
*sc
, struct ray_param_req
*pr
);
349 static void ray_watchdog (struct ifnet
*ifp
);
350 static u_int8_t
ray_tx_best_antenna (struct ray_softc
*sc
, u_int8_t
*dst
);
352 #if RAY_DEBUG & RAY_DBG_COM
353 static void ray_com_ecf_check (struct ray_softc
*sc
, size_t ccs
, char *mesg
);
354 #endif /* RAY_DEBUG & RAY_DBG_COM */
355 #if RAY_DEBUG & RAY_DBG_MBUF
356 static void ray_dump_mbuf (struct ray_softc
*sc
, struct mbuf
*m
, char *s
);
357 #endif /* RAY_DEBUG & RAY_DBG_MBUF */
360 * PC-Card (PCMCIA) driver definition
362 static device_method_t ray_methods
[] = {
363 /* Device interface */
364 DEVMETHOD(device_probe
, ray_probe
),
365 DEVMETHOD(device_attach
, ray_attach
),
366 DEVMETHOD(device_detach
, ray_detach
),
371 static driver_t ray_driver
= {
374 sizeof(struct ray_softc
)
377 static devclass_t ray_devclass
;
379 DECLARE_DUMMY_MODULE(if_ray
);
380 DRIVER_MODULE(if_ray
, pccard
, ray_driver
, ray_devclass
, 0, 0);
383 * Probe for the card by checking its startup results.
385 * Fixup any bugs/quirks for different firmware.
388 ray_probe(device_t dev
)
390 struct ray_softc
*sc
= device_get_softc(dev
);
391 struct ray_ecf_startup_v5
*ep
= &sc
->sc_ecf_startup
;
395 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
398 * Read startup results from the card.
400 error
= ray_res_alloc_cm(sc
);
403 error
= ray_res_alloc_am(sc
);
409 SRAM_READ_REGION(sc
, RAY_ECF_TO_HOST_BASE
, ep
,
410 sizeof(sc
->sc_ecf_startup
));
414 * Check the card is okay and work out what version we are using.
416 if (ep
->e_status
!= RAY_ECFS_CARD_OK
) {
417 RAY_PRINTF(sc
, "card failed self test 0x%b",
418 ep
->e_status
, RAY_ECFS_PRINTFB
);
421 if (sc
->sc_version
!= RAY_ECFS_BUILD_4
&&
422 sc
->sc_version
!= RAY_ECFS_BUILD_5
) {
423 RAY_PRINTF(sc
, "unsupported firmware version 0x%0x",
424 ep
->e_fw_build_string
);
427 RAY_DPRINTF(sc
, RAY_DBG_BOOTPARAM
, "found a card");
431 * Fixup tib size to be correct - on build 4 it is garbage
433 if (sc
->sc_version
== RAY_ECFS_BUILD_4
&& sc
->sc_tibsize
== 0x55)
434 sc
->sc_tibsize
= sizeof(struct ray_tx_tib
);
440 * Attach the card into the kernel
443 ray_attach(device_t dev
)
445 struct ray_softc
*sc
= device_get_softc(dev
);
446 struct ray_ecf_startup_v5
*ep
= &sc
->sc_ecf_startup
;
447 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
451 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
453 if ((sc
== NULL
) || (sc
->sc_gone
))
457 * Grab the resources I need
459 error
= ray_res_alloc_cm(sc
);
462 error
= ray_res_alloc_am(sc
);
469 * Reset any pending interrupts
471 RAY_HCS_CLEAR_INTR(sc
);
474 * Set the parameters that will survive stop/init and
475 * reset a few things on the card.
477 * Do not update these in ray_init_download's parameter setup
479 * XXX see the ray_init_download section for stuff to move
482 bzero(&sc
->sc_d
, sizeof(struct ray_nw_param
));
483 bzero(&sc
->sc_c
, sizeof(struct ray_nw_param
));
485 /* Clear statistics counters */
486 sc
->sc_rxoverflow
= 0;
491 /* Clear signal and antenna cache */
492 bzero(sc
->sc_siglevs
, sizeof(sc
->sc_siglevs
));
494 /* Set all ccs to be free */
495 bzero(sc
->sc_ccsinuse
, sizeof(sc
->sc_ccsinuse
));
496 ccs
= RAY_CCS_ADDRESS(0);
497 for (i
= 0; i
< RAY_CCS_LAST
; ccs
+= RAY_CCS_SIZE
, i
++)
498 RAY_CCS_FREE(sc
, ccs
);
501 * Initialise the network interface structure
503 if_initname(ifp
, "ray", device_get_unit(dev
));
506 ifp
->if_flags
= (IFF_BROADCAST
| IFF_SIMPLEX
| IFF_MULTICAST
);
507 ifp
->if_hdrlen
= sizeof(struct ieee80211_frame
) +
508 sizeof(struct ether_header
);
509 ifp
->if_baudrate
= 1000000; /* Is this baud or bps ;-) */
510 ifp
->if_start
= ray_tx
;
511 ifp
->if_ioctl
= ray_ioctl
;
512 ifp
->if_watchdog
= ray_watchdog
;
513 ifp
->if_init
= ray_init
;
514 ifq_set_maxlen(&ifp
->if_snd
, IFQ_MAXLEN
);
515 ifq_set_ready(&ifp
->if_snd
);
518 * Initialise the timers and driver
520 callout_init(&sc
->com_timer
);
521 callout_init(&sc
->tx_timer
);
522 TAILQ_INIT(&sc
->sc_comq
);
524 ether_ifattach(ifp
, ep
->e_station_addr
, NULL
);
526 error
= ray_res_alloc_irq(sc
);
533 * Print out some useful information
535 if (bootverbose
|| (RAY_DEBUG
& RAY_DBG_BOOTPARAM
)) {
536 RAY_PRINTF(sc
, "start up results");
537 if (sc
->sc_version
== RAY_ECFS_BUILD_4
)
538 kprintf(". Firmware version 4\n");
540 kprintf(". Firmware version 5\n");
541 kprintf(". Status 0x%b\n", ep
->e_status
, RAY_ECFS_PRINTFB
);
542 if (sc
->sc_version
== RAY_ECFS_BUILD_4
) {
543 kprintf(". Program checksum %0x\n", ep
->e_resv0
);
544 kprintf(". CIS checksum %0x\n", ep
->e_rates
[0]);
546 kprintf(". (reserved word) %0x\n", ep
->e_resv0
);
547 kprintf(". Supported rates %8D\n", ep
->e_rates
, ":");
549 kprintf(". Japan call sign %12D\n", ep
->e_japan_callsign
, ":");
550 if (sc
->sc_version
== RAY_ECFS_BUILD_5
) {
551 kprintf(". Program checksum %0x\n", ep
->e_prg_cksum
);
552 kprintf(". CIS checksum %0x\n", ep
->e_cis_cksum
);
553 kprintf(". Firmware version %0x\n",
554 ep
->e_fw_build_string
);
555 kprintf(". Firmware revision %0x\n", ep
->e_fw_build
);
556 kprintf(". (reserved word) %0x\n", ep
->e_fw_resv
);
557 kprintf(". ASIC version %0x\n", ep
->e_asic_version
);
558 kprintf(". TIB size %0x\n", ep
->e_tibsize
);
568 * This is usually called when the card is ejected, but
569 * can be caused by a modunload of a controller driver.
570 * The idea is to reset the driver's view of the device
571 * and ensure that any driver entry points such as
572 * read and write do not hang.
575 ray_detach(device_t dev
)
577 struct ray_softc
*sc
= device_get_softc(dev
);
578 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
579 struct ray_comq_entry
*com
;
581 lwkt_serialize_enter(ifp
->if_serializer
);
583 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STOP
, "");
585 if ((sc
== NULL
) || (sc
->sc_gone
)) {
586 lwkt_serialize_exit(ifp
->if_serializer
);
591 * Mark as not running and detach the interface.
593 * N.B. if_detach can trigger ioctls so we do it first and
594 * then clean the runq.
597 sc
->sc_c
.np_havenet
= 0;
598 ifp
->if_flags
&= ~(IFF_RUNNING
| IFF_OACTIVE
);
601 * Stop the runq and wake up anyone sleeping for us.
603 callout_stop(&sc
->com_timer
);
604 callout_stop(&sc
->tx_timer
);
605 com
= TAILQ_FIRST(&sc
->sc_comq
);
606 for (com
= TAILQ_FIRST(&sc
->sc_comq
); com
!= NULL
;
607 com
= TAILQ_NEXT(com
, c_chain
)) {
608 com
->c_flags
|= RAY_COM_FDETACHED
;
610 RAY_DPRINTF(sc
, RAY_DBG_STOP
, "looking at com %p %b",
611 com
, com
->c_flags
, RAY_COM_FLAGS_PRINTFB
);
612 if (com
->c_flags
& RAY_COM_FWOK
) {
613 RAY_DPRINTF(sc
, RAY_DBG_STOP
, "waking com %p", com
);
614 wakeup(com
->c_wakeup
);
618 lwkt_serialize_exit(ifp
->if_serializer
);
626 RAY_DPRINTF(sc
, RAY_DBG_STOP
, "unloading complete");
632 * Network ioctl request.
635 ray_ioctl(struct ifnet
*ifp
, u_long command
, caddr_t data
, struct ucred
*cr
)
637 struct ray_softc
*sc
= ifp
->if_softc
;
638 struct ray_param_req pr
;
639 struct ray_stats_req sr
;
640 struct ifreq
*ifr
= (struct ifreq
*)data
;
643 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_IOCTL
, "");
645 if ((sc
== NULL
) || (sc
->sc_gone
))
652 RAY_DPRINTF(sc
, RAY_DBG_IOCTL
, "SIFFLAGS 0x%0x", ifp
->if_flags
);
654 * If the interface is marked up we call ray_init_user.
655 * This will deal with mcast and promisc flags as well as
656 * initialising the hardware if it needs it.
658 if (ifp
->if_flags
& IFF_UP
)
659 error
= ray_init_user(sc
);
661 error
= ray_stop_user(sc
);
666 RAY_DPRINTF(sc
, RAY_DBG_IOCTL
, "ADDMULTI/DELMULTI");
667 error
= ray_mcast_user(sc
);
671 RAY_DPRINTF(sc
, RAY_DBG_IOCTL
, "SRAYPARAM");
672 if ((error
= copyin(ifr
->ifr_data
, &pr
, sizeof(pr
))))
674 error
= ray_upparams_user(sc
, &pr
);
675 error2
= copyout(&pr
, ifr
->ifr_data
, sizeof(pr
));
676 error
= error2
? error2
: error
;
680 RAY_DPRINTF(sc
, RAY_DBG_IOCTL
, "GRAYPARAM");
681 if ((error
= copyin(ifr
->ifr_data
, &pr
, sizeof(pr
))))
683 error
= ray_repparams_user(sc
, &pr
);
684 error2
= copyout(&pr
, ifr
->ifr_data
, sizeof(pr
));
685 error
= error2
? error2
: error
;
689 RAY_DPRINTF(sc
, RAY_DBG_IOCTL
, "GRAYSTATS");
690 error
= ray_repstats_user(sc
, &sr
);
691 error2
= copyout(&sr
, ifr
->ifr_data
, sizeof(sr
));
692 error
= error2
? error2
: error
;
696 RAY_DPRINTF(sc
, RAY_DBG_IOCTL
, "GRAYSIGLEV");
697 error
= copyout(sc
->sc_siglevs
, ifr
->ifr_data
,
698 sizeof(sc
->sc_siglevs
));
702 RAY_DPRINTF(sc
, RAY_DBG_IOCTL
, "GIFFLAGS");
707 RAY_DPRINTF(sc
, RAY_DBG_IOCTL
, "GIFMETRIC");
712 RAY_DPRINTF(sc
, RAY_DBG_IOCTL
, "GIFMTU");
717 RAY_DPRINTF(sc
, RAY_DBG_IOCTL
, "GIFPYHS");
722 RAY_DPRINTF(sc
, RAY_DBG_IOCTL
, "SIFMEDIA");
727 RAY_DPRINTF(sc
, RAY_DBG_IOCTL
, "GIFMEDIA");
732 error
= ether_ioctl(ifp
, command
, data
);
740 * Ethernet layer entry to ray_init - discard errors
745 struct ray_softc
*sc
= (struct ray_softc
*)xsc
;
751 * User land entry to network initialisation and changes in interface flags.
753 * We do a very little work here, just creating runq entries to
754 * processes the actions needed to cope with interface flags. We do it
755 * this way in case there are runq entries outstanding from earlier
756 * ioctls that modify the interface flags.
758 * Returns values are either 0 for success, a varity of resource allocation
759 * failures or errors in the command sent to the card.
761 * Note, IFF_RUNNING is eventually set by init_sj_done or init_assoc_done
764 ray_init_user(struct ray_softc
*sc
)
766 struct ray_comq_entry
*com
[6];
769 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STARTJOIN
, "");
772 * Create the following runq entries to bring the card up.
774 * init_download - download the network to the card
775 * init_mcast - reset multicast list
776 * init_sj - find or start a BSS
777 * init_auth - authenticate with a ESSID if needed
778 * init_assoc - associate with a ESSID if needed
780 * They are only actually executed if the card is not running.
781 * We may enter this routine from a simple change of IP
782 * address and do not need to get the card to do these things.
783 * However, we cannot perform the check here as there may be
784 * commands in the runq that change the IFF_RUNNING state of
788 com
[ncom
++] = RAY_COM_MALLOC(ray_init_download
, RAY_COM_FCHKRUNNING
);
789 com
[ncom
++] = RAY_COM_MALLOC(ray_init_mcast
, RAY_COM_FCHKRUNNING
);
790 com
[ncom
++] = RAY_COM_MALLOC(ray_init_sj
, RAY_COM_FCHKRUNNING
);
791 com
[ncom
++] = RAY_COM_MALLOC(ray_init_auth
, RAY_COM_FCHKRUNNING
);
792 com
[ncom
++] = RAY_COM_MALLOC(ray_init_assoc
, RAY_COM_FCHKRUNNING
);
795 * Create runq entries to process flags
797 * promisc - set/reset PROMISC and ALLMULTI flags
799 * They are only actually executed if the card is running
801 com
[ncom
++] = RAY_COM_MALLOC(ray_promisc
, 0);
803 RAY_COM_RUNQ(sc
, com
, ncom
, "rayinit", error
);
805 /* XXX no real error processing from anything yet! */
807 RAY_COM_FREE(com
, ncom
);
813 * Runq entry for resetting driver and downloading start up structures to card
816 ray_init_download(struct ray_softc
*sc
, struct ray_comq_entry
*com
)
818 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
820 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STARTJOIN
, "");
822 /* If the card already running we might not need to download */
823 RAY_COM_CHKRUNNING(sc
, com
, ifp
);
826 * Reset instance variables
828 * The first set are network parameters that are read back when
829 * the card starts or joins the network.
831 * The second set are network parameters that are downloaded to
834 * The third set are driver parameters.
836 * All of the variables in these sets can be updated by the
839 * XXX see the ray_attach section for stuff to move
841 sc
->sc_d
.np_upd_param
= 0;
842 bzero(sc
->sc_d
.np_bss_id
, ETHER_ADDR_LEN
);
843 sc
->sc_d
.np_inited
= 0;
844 sc
->sc_d
.np_def_txrate
= RAY_MIB_BASIC_RATE_SET_DEFAULT
;
845 sc
->sc_d
.np_encrypt
= 0;
847 bzero(sc
->sc_d
.np_ssid
, IEEE80211_NWID_LEN
);
848 if (sc
->sc_version
== RAY_ECFS_BUILD_4
) {
849 sc
->sc_d
.np_net_type
= RAY_MIB_NET_TYPE_V4
;
850 strncpy(sc
->sc_d
.np_ssid
, RAY_MIB_SSID_V4
, IEEE80211_NWID_LEN
);
851 sc
->sc_d
.np_ap_status
= RAY_MIB_AP_STATUS_V4
;
852 sc
->sc_d
.np_framing
= RAY_FRAMING_ENCAPSULATION
;
854 sc
->sc_d
.np_net_type
= RAY_MIB_NET_TYPE_V5
;
855 strncpy(sc
->sc_d
.np_ssid
, RAY_MIB_SSID_V5
, IEEE80211_NWID_LEN
);
856 sc
->sc_d
.np_ap_status
= RAY_MIB_AP_STATUS_V5
;
857 sc
->sc_d
.np_framing
= RAY_FRAMING_TRANSLATION
;
859 sc
->sc_d
.np_priv_start
= RAY_MIB_PRIVACY_MUST_START_DEFAULT
;
860 sc
->sc_d
.np_priv_join
= RAY_MIB_PRIVACY_CAN_JOIN_DEFAULT
;
861 sc
->sc_d
.np_promisc
= !!(ifp
->if_flags
& (IFF_PROMISC
| IFF_ALLMULTI
));
863 /* XXX this is a hack whilst I transition the code. The instance
864 * XXX variables above should be set somewhere else. This is needed for
866 bcopy(&sc
->sc_d
, &com
->c_desired
, sizeof(struct ray_nw_param
));
869 * Download the right firmware defaults
871 if (sc
->sc_version
== RAY_ECFS_BUILD_4
)
872 ray_init_download_v4(sc
, com
);
874 ray_init_download_v5(sc
, com
);
879 ray_ccs_fill(sc
, com
->c_ccs
, RAY_CMD_DOWNLOAD_PARAMS
);
880 ray_com_ecf(sc
, com
);
884 do { (p)[0] = ((v >> 8) & 0xff); (p)[1] = (v & 0xff); } while(0)
886 * Firmware version 4 defaults - see if_raymib.h for details
889 ray_init_download_v4(struct ray_softc
*sc
, struct ray_comq_entry
*com
)
891 struct ray_mib_4 ray_mib_4_default
;
893 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STARTJOIN
, "");
896 #define MIB4(m) ray_mib_4_default.m
898 MIB4(mib_net_type
) = com
->c_desired
.np_net_type
;
899 MIB4(mib_ap_status
) = com
->c_desired
.np_ap_status
;
900 bcopy(com
->c_desired
.np_ssid
, MIB4(mib_ssid
), IEEE80211_NWID_LEN
);
901 MIB4(mib_scan_mode
) = RAY_MIB_SCAN_MODE_V4
;
902 MIB4(mib_apm_mode
) = RAY_MIB_APM_MODE_V4
;
903 bcopy(sc
->sc_station_addr
, MIB4(mib_mac_addr
), ETHER_ADDR_LEN
);
904 PUT2(MIB4(mib_frag_thresh
), RAY_MIB_FRAG_THRESH_V4
);
905 PUT2(MIB4(mib_dwell_time
), RAY_MIB_DWELL_TIME_V4
);
906 PUT2(MIB4(mib_beacon_period
), RAY_MIB_BEACON_PERIOD_V4
);
907 MIB4(mib_dtim_interval
) = RAY_MIB_DTIM_INTERVAL_V4
;
908 MIB4(mib_max_retry
) = RAY_MIB_MAX_RETRY_V4
;
909 MIB4(mib_ack_timo
) = RAY_MIB_ACK_TIMO_V4
;
910 MIB4(mib_sifs
) = RAY_MIB_SIFS_V4
;
911 MIB4(mib_difs
) = RAY_MIB_DIFS_V4
;
912 MIB4(mib_pifs
) = RAY_MIB_PIFS_V4
;
913 PUT2(MIB4(mib_rts_thresh
), RAY_MIB_RTS_THRESH_V4
);
914 PUT2(MIB4(mib_scan_dwell
), RAY_MIB_SCAN_DWELL_V4
);
915 PUT2(MIB4(mib_scan_max_dwell
), RAY_MIB_SCAN_MAX_DWELL_V4
);
916 MIB4(mib_assoc_timo
) = RAY_MIB_ASSOC_TIMO_V4
;
917 MIB4(mib_adhoc_scan_cycle
) = RAY_MIB_ADHOC_SCAN_CYCLE_V4
;
918 MIB4(mib_infra_scan_cycle
) = RAY_MIB_INFRA_SCAN_CYCLE_V4
;
919 MIB4(mib_infra_super_scan_cycle
)
920 = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_V4
;
921 MIB4(mib_promisc
) = com
->c_desired
.np_promisc
;
922 PUT2(MIB4(mib_uniq_word
), RAY_MIB_UNIQ_WORD_V4
);
923 MIB4(mib_slot_time
) = RAY_MIB_SLOT_TIME_V4
;
924 MIB4(mib_roam_low_snr_thresh
) = RAY_MIB_ROAM_LOW_SNR_THRESH_V4
;
925 MIB4(mib_low_snr_count
) = RAY_MIB_LOW_SNR_COUNT_V4
;
926 MIB4(mib_infra_missed_beacon_count
)
927 = RAY_MIB_INFRA_MISSED_BEACON_COUNT_V4
;
928 MIB4(mib_adhoc_missed_beacon_count
)
929 = RAY_MIB_ADHOC_MISSED_BEACON_COUNT_V4
;
930 MIB4(mib_country_code
) = RAY_MIB_COUNTRY_CODE_V4
;
931 MIB4(mib_hop_seq
) = RAY_MIB_HOP_SEQ_V4
;
932 MIB4(mib_hop_seq_len
) = RAY_MIB_HOP_SEQ_LEN_V4
;
933 MIB4(mib_cw_max
) = RAY_MIB_CW_MAX_V4
;
934 MIB4(mib_cw_min
) = RAY_MIB_CW_MIN_V4
;
935 MIB4(mib_noise_filter_gain
) = RAY_MIB_NOISE_FILTER_GAIN_DEFAULT
;
936 MIB4(mib_noise_limit_offset
) = RAY_MIB_NOISE_LIMIT_OFFSET_DEFAULT
;
937 MIB4(mib_rssi_thresh_offset
) = RAY_MIB_RSSI_THRESH_OFFSET_DEFAULT
;
938 MIB4(mib_busy_thresh_offset
) = RAY_MIB_BUSY_THRESH_OFFSET_DEFAULT
;
939 MIB4(mib_sync_thresh
) = RAY_MIB_SYNC_THRESH_DEFAULT
;
940 MIB4(mib_test_mode
) = RAY_MIB_TEST_MODE_DEFAULT
;
941 MIB4(mib_test_min_chan
) = RAY_MIB_TEST_MIN_CHAN_DEFAULT
;
942 MIB4(mib_test_max_chan
) = RAY_MIB_TEST_MAX_CHAN_DEFAULT
;
945 SRAM_WRITE_REGION(sc
, RAY_HOST_TO_ECF_BASE
,
946 &ray_mib_4_default
, sizeof(ray_mib_4_default
));
950 * Firmware version 5 defaults - see if_raymib.h for details
953 ray_init_download_v5(struct ray_softc
*sc
, struct ray_comq_entry
*com
)
955 struct ray_mib_5 ray_mib_5_default
;
957 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STARTJOIN
, "");
960 #define MIB5(m) ray_mib_5_default.m
961 MIB5(mib_net_type
) = com
->c_desired
.np_net_type
;
962 MIB5(mib_ap_status
) = com
->c_desired
.np_ap_status
;
963 bcopy(com
->c_desired
.np_ssid
, MIB5(mib_ssid
), IEEE80211_NWID_LEN
);
964 MIB5(mib_scan_mode
) = RAY_MIB_SCAN_MODE_V5
;
965 MIB5(mib_apm_mode
) = RAY_MIB_APM_MODE_V5
;
966 bcopy(sc
->sc_station_addr
, MIB5(mib_mac_addr
), ETHER_ADDR_LEN
);
967 PUT2(MIB5(mib_frag_thresh
), RAY_MIB_FRAG_THRESH_V5
);
968 PUT2(MIB5(mib_dwell_time
), RAY_MIB_DWELL_TIME_V5
);
969 PUT2(MIB5(mib_beacon_period
), RAY_MIB_BEACON_PERIOD_V5
);
970 MIB5(mib_dtim_interval
) = RAY_MIB_DTIM_INTERVAL_V5
;
971 MIB5(mib_max_retry
) = RAY_MIB_MAX_RETRY_V5
;
972 MIB5(mib_ack_timo
) = RAY_MIB_ACK_TIMO_V5
;
973 MIB5(mib_sifs
) = RAY_MIB_SIFS_V5
;
974 MIB5(mib_difs
) = RAY_MIB_DIFS_V5
;
975 MIB5(mib_pifs
) = RAY_MIB_PIFS_V5
;
976 PUT2(MIB5(mib_rts_thresh
), RAY_MIB_RTS_THRESH_V5
);
977 PUT2(MIB5(mib_scan_dwell
), RAY_MIB_SCAN_DWELL_V5
);
978 PUT2(MIB5(mib_scan_max_dwell
), RAY_MIB_SCAN_MAX_DWELL_V5
);
979 MIB5(mib_assoc_timo
) = RAY_MIB_ASSOC_TIMO_V5
;
980 MIB5(mib_adhoc_scan_cycle
) = RAY_MIB_ADHOC_SCAN_CYCLE_V5
;
981 MIB5(mib_infra_scan_cycle
) = RAY_MIB_INFRA_SCAN_CYCLE_V5
;
982 MIB5(mib_infra_super_scan_cycle
)
983 = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_V5
;
984 MIB5(mib_promisc
) = com
->c_desired
.np_promisc
;
985 PUT2(MIB5(mib_uniq_word
), RAY_MIB_UNIQ_WORD_V5
);
986 MIB5(mib_slot_time
) = RAY_MIB_SLOT_TIME_V5
;
987 MIB5(mib_roam_low_snr_thresh
) = RAY_MIB_ROAM_LOW_SNR_THRESH_V5
;
988 MIB5(mib_low_snr_count
) = RAY_MIB_LOW_SNR_COUNT_V5
;
989 MIB5(mib_infra_missed_beacon_count
)
990 = RAY_MIB_INFRA_MISSED_BEACON_COUNT_V5
;
991 MIB5(mib_adhoc_missed_beacon_count
)
992 = RAY_MIB_ADHOC_MISSED_BEACON_COUNT_V5
;
993 MIB5(mib_country_code
) = RAY_MIB_COUNTRY_CODE_V5
;
994 MIB5(mib_hop_seq
) = RAY_MIB_HOP_SEQ_V5
;
995 MIB5(mib_hop_seq_len
) = RAY_MIB_HOP_SEQ_LEN_V5
;
996 PUT2(MIB5(mib_cw_max
), RAY_MIB_CW_MAX_V5
);
997 PUT2(MIB5(mib_cw_min
), RAY_MIB_CW_MIN_V5
);
998 MIB5(mib_noise_filter_gain
) = RAY_MIB_NOISE_FILTER_GAIN_DEFAULT
;
999 MIB5(mib_noise_limit_offset
) = RAY_MIB_NOISE_LIMIT_OFFSET_DEFAULT
;
1000 MIB5(mib_rssi_thresh_offset
) = RAY_MIB_RSSI_THRESH_OFFSET_DEFAULT
;
1001 MIB5(mib_busy_thresh_offset
) = RAY_MIB_BUSY_THRESH_OFFSET_DEFAULT
;
1002 MIB5(mib_sync_thresh
) = RAY_MIB_SYNC_THRESH_DEFAULT
;
1003 MIB5(mib_test_mode
) = RAY_MIB_TEST_MODE_DEFAULT
;
1004 MIB5(mib_test_min_chan
) = RAY_MIB_TEST_MIN_CHAN_DEFAULT
;
1005 MIB5(mib_test_max_chan
) = RAY_MIB_TEST_MAX_CHAN_DEFAULT
;
1006 MIB5(mib_allow_probe_resp
) = RAY_MIB_ALLOW_PROBE_RESP_DEFAULT
;
1007 MIB5(mib_privacy_must_start
) = com
->c_desired
.np_priv_start
;
1008 MIB5(mib_privacy_can_join
) = com
->c_desired
.np_priv_join
;
1009 MIB5(mib_basic_rate_set
[0]) = com
->c_desired
.np_def_txrate
;
1012 SRAM_WRITE_REGION(sc
, RAY_HOST_TO_ECF_BASE
,
1013 &ray_mib_5_default
, sizeof(ray_mib_5_default
));
1018 * Download completion routine
1021 ray_init_download_done(struct ray_softc
*sc
, u_int8_t status
, size_t ccs
)
1023 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STARTJOIN
, "");
1024 RAY_COM_CHECK(sc
, ccs
);
1026 RAY_CCSERR(sc
, status
, if_oerrors
); /* XXX error counter */
1028 ray_com_ecf_done(sc
);
1032 * Runq entry to empty the multicast filter list
1035 ray_init_mcast(struct ray_softc
*sc
, struct ray_comq_entry
*com
)
1037 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1039 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STARTJOIN
, "");
1042 /* If the card already running we might not need to reset the list */
1043 RAY_COM_CHKRUNNING(sc
, com
, ifp
);
1048 ray_ccs_fill(sc
, com
->c_ccs
, RAY_CMD_UPDATE_MCAST
);
1049 SRAM_WRITE_FIELD_1(sc
, com
->c_ccs
, ray_cmd_update_mcast
, c_nmcast
, 0);
1051 ray_com_ecf(sc
, com
);
1055 * Runq entry to starting or joining a network
1058 ray_init_sj(struct ray_softc
*sc
, struct ray_comq_entry
*com
)
1060 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1061 struct ray_net_params np
;
1064 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STARTJOIN
, "");
1067 /* If the card already running we might not need to start the n/w */
1068 RAY_COM_CHKRUNNING(sc
, com
, ifp
);
1071 * Set up the right start or join command and determine
1072 * whether we should tell the card about a change in operating
1075 sc
->sc_c
.np_havenet
= 0;
1076 if (sc
->sc_d
.np_net_type
== RAY_MIB_NET_TYPE_ADHOC
)
1077 ray_ccs_fill(sc
, com
->c_ccs
, RAY_CMD_START_NET
);
1079 ray_ccs_fill(sc
, com
->c_ccs
, RAY_CMD_JOIN_NET
);
1082 if (sc
->sc_c
.np_net_type
!= sc
->sc_d
.np_net_type
)
1084 if (bcmp(sc
->sc_c
.np_ssid
, sc
->sc_d
.np_ssid
, IEEE80211_NWID_LEN
))
1086 if (sc
->sc_c
.np_priv_join
!= sc
->sc_d
.np_priv_join
)
1088 if (sc
->sc_c
.np_priv_start
!= sc
->sc_d
.np_priv_start
)
1090 RAY_DPRINTF(sc
, RAY_DBG_STARTJOIN
,
1091 "%s updating nw params", update
?"is":"not");
1093 bzero(&np
, sizeof(np
));
1094 np
.p_net_type
= sc
->sc_d
.np_net_type
;
1095 bcopy(sc
->sc_d
.np_ssid
, np
.p_ssid
, IEEE80211_NWID_LEN
);
1096 np
.p_privacy_must_start
= sc
->sc_d
.np_priv_start
;
1097 np
.p_privacy_can_join
= sc
->sc_d
.np_priv_join
;
1098 SRAM_WRITE_REGION(sc
, RAY_HOST_TO_ECF_BASE
, &np
, sizeof(np
));
1099 SRAM_WRITE_FIELD_1(sc
, com
->c_ccs
, ray_cmd_net
, c_upd_param
, 1);
1101 SRAM_WRITE_FIELD_1(sc
, com
->c_ccs
, ray_cmd_net
, c_upd_param
, 0);
1106 ray_com_ecf(sc
, com
);
1110 * Complete start command or intermediate step in assoc command
1113 ray_init_sj_done(struct ray_softc
*sc
, u_int8_t status
, size_t ccs
)
1115 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1117 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STARTJOIN
, "");
1119 RAY_COM_CHECK(sc
, ccs
);
1121 RAY_CCSERR(sc
, status
, if_oerrors
); /* XXX error counter */
1124 * Read back network parameters that the ECF sets
1126 SRAM_READ_REGION(sc
, ccs
, &sc
->sc_c
.p_1
, sizeof(struct ray_cmd_net
));
1128 /* Adjust values for buggy firmware */
1129 if (sc
->sc_c
.np_inited
== 0x55)
1130 sc
->sc_c
.np_inited
= 0;
1131 if (sc
->sc_c
.np_def_txrate
== 0x55)
1132 sc
->sc_c
.np_def_txrate
= sc
->sc_d
.np_def_txrate
;
1133 if (sc
->sc_c
.np_encrypt
== 0x55)
1134 sc
->sc_c
.np_encrypt
= sc
->sc_d
.np_encrypt
;
1137 * Update our local state if we updated the network parameters
1138 * when the START_NET or JOIN_NET was issued.
1140 if (sc
->sc_c
.np_upd_param
) {
1141 RAY_DPRINTF(sc
, RAY_DBG_STARTJOIN
, "updated parameters");
1142 SRAM_READ_REGION(sc
, RAY_HOST_TO_ECF_BASE
,
1143 &sc
->sc_c
.p_2
, sizeof(struct ray_net_params
));
1147 * Hurrah! The network is now active.
1149 * Clearing IFF_OACTIVE will ensure that the system will send us
1150 * packets. Just before we return from the interrupt context
1151 * we check to see if packets have been queued.
1153 if (SRAM_READ_FIELD_1(sc
, ccs
, ray_cmd
, c_cmd
) == RAY_CMD_START_NET
) {
1154 sc
->sc_c
.np_havenet
= 1;
1155 sc
->sc_c
.np_framing
= sc
->sc_d
.np_framing
;
1156 ifp
->if_flags
|= IFF_RUNNING
;
1157 ifp
->if_flags
&= ~IFF_OACTIVE
;
1160 ray_com_ecf_done(sc
);
1164 * Runq entry to authenticate with an access point or another station
1167 ray_init_auth(struct ray_softc
*sc
, struct ray_comq_entry
*com
)
1169 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1171 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STARTJOIN
| RAY_DBG_AUTH
, "");
1173 /* If card already running we might not need to authenticate */
1174 RAY_COM_CHKRUNNING(sc
, com
, ifp
);
1177 * XXX Don't do anything if we are not in a managed network
1179 * XXX V4 adhoc does not need this, V5 adhoc unknown
1181 if (sc
->sc_c
.np_net_type
!= RAY_MIB_NET_TYPE_INFRA
) {
1182 ray_com_runq_done(sc
);
1187 * XXX_AUTH need to think of run queue when doing auths from request i.e. would
1188 * XXX_AUTH need to have auth at top of runq?
1189 * XXX_AUTH ditto for sending any auth response packets...what about timeouts?
1195 /* XXX_AUTH check exit status and retry or fail as we can't associate without this */
1196 ray_init_auth_send(sc
, sc
->sc_c
.np_bss_id
, IEEE80211_AUTH_OPEN_REQUEST
);
1200 * Build and send an authentication packet
1202 * If an error occurs, returns 1 else returns 0.
1205 ray_init_auth_send(struct ray_softc
*sc
, u_int8_t
*dst
, int sequence
)
1210 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STARTJOIN
| RAY_DBG_AUTH
, "");
1212 /* Get a control block */
1213 if (ray_ccs_tx(sc
, &ccs
, &bufp
)) {
1214 RAY_RECERR(sc
, "could not obtain a ccs");
1218 /* Fill the header in */
1219 bufp
= ray_tx_wrhdr(sc
, bufp
,
1220 IEEE80211_FC0_TYPE_MGT
| IEEE80211_FC0_SUBTYPE_AUTH
,
1221 IEEE80211_FC1_DIR_NODS
,
1223 sc
->arpcom
.ac_enaddr
,
1224 sc
->sc_c
.np_bss_id
);
1226 /* Add algorithm number */
1227 SRAM_WRITE_1(sc
, bufp
+ pktlen
++, IEEE80211_AUTH_ALG_OPEN
);
1228 SRAM_WRITE_1(sc
, bufp
+ pktlen
++, 0);
1230 /* Add sequence number */
1231 SRAM_WRITE_1(sc
, bufp
+ pktlen
++, sequence
);
1232 SRAM_WRITE_1(sc
, bufp
+ pktlen
++, 0);
1234 /* Add status code */
1235 SRAM_WRITE_1(sc
, bufp
+ pktlen
++, 0);
1236 SRAM_WRITE_1(sc
, bufp
+ pktlen
++, 0);
1237 pktlen
+= sizeof(struct ieee80211_frame
);
1239 return (ray_tx_send(sc
, ccs
, pktlen
, dst
));
1243 * Complete authentication runq
1246 ray_init_auth_done(struct ray_softc
*sc
, u_int8_t status
)
1248 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STARTJOIN
| RAY_DBG_AUTH
, "");
1250 if (status
!= IEEE80211_STATUS_SUCCESS
)
1251 RAY_RECERR(sc
, "authentication failed with status %d", status
);
1253 * XXX_AUTH retry? if not just recall ray_init_auth_send and dont clear runq?
1254 * XXX_AUTH association requires that authenitcation is successful
1255 * XXX_AUTH before we associate, and the runq is the only way to halt the
1256 * XXX_AUTH progress of associate.
1257 * XXX_AUTH In this case I might not need the RAY_AUTH_NEEDED state
1259 ray_com_runq_done(sc
);
1263 * Runq entry to starting an association with an access point
1266 ray_init_assoc(struct ray_softc
*sc
, struct ray_comq_entry
*com
)
1268 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1270 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STARTJOIN
, "");
1272 /* If the card already running we might not need to associate */
1273 RAY_COM_CHKRUNNING(sc
, com
, ifp
);
1276 * Don't do anything if we are not in a managed network
1278 if (sc
->sc_c
.np_net_type
!= RAY_MIB_NET_TYPE_INFRA
) {
1279 ray_com_runq_done(sc
);
1286 ray_ccs_fill(sc
, com
->c_ccs
, RAY_CMD_START_ASSOC
);
1287 ray_com_ecf(sc
, com
);
1291 * Complete association
1294 ray_init_assoc_done(struct ray_softc
*sc
, u_int8_t status
, size_t ccs
)
1296 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1298 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STARTJOIN
, "");
1299 RAY_COM_CHECK(sc
, ccs
);
1301 RAY_CCSERR(sc
, status
, if_oerrors
); /* XXX error counter */
1304 * Hurrah! The network is now active.
1306 * Clearing IFF_OACTIVE will ensure that the system will send us
1307 * packets. Just before we return from the interrupt context
1308 * we check to see if packets have been queued.
1310 sc
->sc_c
.np_havenet
= 1;
1311 sc
->sc_c
.np_framing
= sc
->sc_d
.np_framing
;
1312 ifp
->if_flags
|= IFF_RUNNING
;
1313 ifp
->if_flags
&= ~IFF_OACTIVE
;
1315 ray_com_ecf_done(sc
);
1321 * Inhibit card - if we can't prevent reception then do not worry;
1322 * stopping a NIC only guarantees no TX.
1324 * The change to the interface flags is done via the runq so that any
1325 * existing commands can execute normally.
1328 ray_stop_user(struct ray_softc
*sc
)
1330 struct ray_comq_entry
*com
[1];
1333 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STOP
, "");
1336 * Schedule the real stop routine
1339 com
[ncom
++] = RAY_COM_MALLOC(ray_stop
, 0);
1341 RAY_COM_RUNQ(sc
, com
, ncom
, "raystop", error
);
1343 /* XXX no real error processing from anything yet! */
1345 RAY_COM_FREE(com
, ncom
);
1351 * Runq entry for stopping the interface activity
1354 ray_stop(struct ray_softc
*sc
, struct ray_comq_entry
*com
)
1356 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1358 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STOP
, "");
1361 * Mark as not running and drain output queue
1363 ifp
->if_flags
&= ~(IFF_RUNNING
| IFF_OACTIVE
);
1365 ifq_purge(&ifp
->if_snd
);
1366 ray_com_runq_done(sc
);
1370 ray_watchdog(struct ifnet
*ifp
)
1372 struct ray_softc
*sc
= ifp
->if_softc
;
1374 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
1377 if ((sc
== NULL
) || (sc
->sc_gone
))
1380 RAY_PRINTF(sc
, "watchdog timeout");
1384 * Transmit packet handling
1390 * We make one assumptions here:
1391 * - That the IFF_OACTIVE flag is checked before this code is called
1392 * (i.e. that the output part of the interface is idle)
1394 * A simple one packet at a time TX routine is used - we don't bother
1395 * chaining TX buffers. Performance is sufficient to max out the
1396 * wireless link on a P75.
1398 * AST J30 Windows 95A (100MHz Pentium) to
1399 * Libretto 50CT FreeBSD-3.1 (75MHz Pentium) 167.37kB/s
1400 * Nonname box FreeBSD-3.4 (233MHz AMD K6) 161.82kB/s
1402 * Libretto 50CT FreeBSD-3.1 (75MHz Pentium) to
1403 * AST J30 Windows 95A (100MHz Pentium) 167.37kB/s
1404 * Nonname box FreeBSD-3.4 (233MHz AMD K6) 161.38kB/s
1406 * Given that 160kB/s is saturating the 2Mb/s wireless link we
1409 * In short I'm happy that the added complexity of chaining TX
1410 * packets together isn't worth it for my machines.
1413 ray_tx(struct ifnet
*ifp
)
1415 struct ray_softc
*sc
= ifp
->if_softc
;
1416 struct mbuf
*m0
, *m
;
1417 struct ether_header
*eh
;
1422 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_TX
, "");
1426 * Some simple checks first - some are overkill
1428 if ((sc
== NULL
) || (sc
->sc_gone
))
1430 if (!(ifp
->if_flags
& IFF_RUNNING
)) {
1431 RAY_RECERR(sc
, "cannot transmit - not running");
1434 if (!sc
->sc_c
.np_havenet
) {
1435 RAY_RECERR(sc
, "cannot transmit - no network");
1438 if (!RAY_ECF_READY(sc
)) {
1439 /* Can't assume that the ECF is busy because of this driver */
1440 if (!callout_active(&sc
->tx_timer
)) {
1441 callout_reset(&sc
->tx_timer
, RAY_TX_TIMEOUT
,
1446 callout_stop(&sc
->tx_timer
);
1449 * We find a ccs before we process the mbuf so that we are sure it
1450 * is worthwhile processing the packet. All errors in the mbuf
1451 * processing are either errors in the mbuf or gross configuration
1452 * errors and the packet wouldn't get through anyway.
1454 if (ray_ccs_tx(sc
, &ccs
, &bufp
)) {
1455 ifp
->if_flags
|= IFF_OACTIVE
;
1460 * Get the mbuf and process it - we have to remember to free the
1461 * ccs if there are any errors.
1463 m0
= ifq_dequeue(&ifp
->if_snd
, NULL
);
1465 RAY_CCS_FREE(sc
, ccs
);
1469 pktlen
= m0
->m_pkthdr
.len
;
1470 if (pktlen
> ETHER_MAX_LEN
- ETHER_CRC_LEN
) {
1471 RAY_RECERR(sc
, "mbuf too long %d", pktlen
);
1472 RAY_CCS_FREE(sc
, ccs
);
1478 m0
= m_pullup(m0
, sizeof(struct ether_header
));
1480 RAY_RECERR(sc
, "could not pullup ether");
1481 RAY_CCS_FREE(sc
, ccs
);
1485 eh
= mtod(m0
, struct ether_header
*);
1488 * Write the 802.11 header according to network type etc.
1490 if (sc
->sc_c
.np_net_type
== RAY_MIB_NET_TYPE_ADHOC
)
1491 bufp
= ray_tx_wrhdr(sc
, bufp
,
1492 IEEE80211_FC0_TYPE_DATA
,
1493 IEEE80211_FC1_DIR_NODS
,
1496 sc
->sc_c
.np_bss_id
);
1498 if (sc
->sc_c
.np_ap_status
== RAY_MIB_AP_STATUS_TERMINAL
)
1499 bufp
= ray_tx_wrhdr(sc
, bufp
,
1500 IEEE80211_FC0_TYPE_DATA
,
1501 IEEE80211_FC1_DIR_TODS
,
1506 bufp
= ray_tx_wrhdr(sc
, bufp
,
1507 IEEE80211_FC0_TYPE_DATA
,
1508 IEEE80211_FC1_DIR_FROMDS
,
1518 switch (sc
->sc_c
.np_framing
) {
1520 case RAY_FRAMING_ENCAPSULATION
:
1521 /* Nice and easy - nothing! (just add an 802.11 header) */
1524 case RAY_FRAMING_TRANSLATION
:
1526 * Drop the first address in the ethernet header and
1527 * write an LLC and SNAP header over the second.
1529 m_adj(m0
, ETHER_ADDR_LEN
);
1531 RAY_RECERR(sc
, "could not get space for 802.2 header");
1532 RAY_CCS_FREE(sc
, ccs
);
1536 llc
= mtod(m0
, struct llc
*);
1537 llc
->llc_dsap
= LLC_SNAP_LSAP
;
1538 llc
->llc_ssap
= LLC_SNAP_LSAP
;
1539 llc
->llc_control
= LLC_UI
;
1540 llc
->llc_un
.type_snap
.org_code
[0] = 0;
1541 llc
->llc_un
.type_snap
.org_code
[1] = 0;
1542 llc
->llc_un
.type_snap
.org_code
[2] = 0;
1546 RAY_RECERR(sc
, "unknown framing type %d", sc
->sc_c
.np_framing
);
1547 RAY_CCS_FREE(sc
, ccs
);
1554 RAY_RECERR(sc
, "could not frame packet");
1555 RAY_CCS_FREE(sc
, ccs
);
1559 RAY_MBUF_DUMP(sc
, RAY_DBG_TX
, m0
, "framed packet");
1562 * Copy the mbuf to the buffer in common memory
1564 * We drop and don't bother wrapping as Ethernet packets are 1518
1565 * bytes, we checked the mbuf earlier, and our TX buffers are 2048
1566 * bytes. We don't have 530 bytes of headers etc. so something
1569 pktlen
= sizeof(struct ieee80211_frame
);
1570 for (m
= m0
; m
!= NULL
; m
= m
->m_next
) {
1572 if ((len
= m
->m_len
) == 0)
1574 if ((bufp
+ len
) < RAY_TX_END
)
1575 SRAM_WRITE_REGION(sc
, bufp
, mtod(m
, u_int8_t
*), len
);
1577 RAY_RECERR(sc
, "tx buffer overflow");
1578 RAY_CCS_FREE(sc
, ccs
);
1589 if (ray_tx_send(sc
, ccs
, pktlen
, eh
->ether_dhost
))
1597 * Start timeout routine.
1599 * Used when card was busy but we needed to send a packet.
1602 ray_tx_timo(void *xsc
)
1604 struct ray_softc
*sc
= (struct ray_softc
*)xsc
;
1605 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1607 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
1609 lwkt_serialize_enter(ifp
->if_serializer
);
1610 if ((ifp
->if_flags
& IFF_OACTIVE
) == 0 && !ifq_is_empty(&ifp
->if_snd
)) {
1613 lwkt_serialize_exit(ifp
->if_serializer
);
1617 * Write an 802.11 header into the Tx buffer space and return the
1618 * adjusted buffer pointer.
1621 ray_tx_wrhdr(struct ray_softc
*sc
, size_t bufp
, u_int8_t type
, u_int8_t fc1
, u_int8_t
*addr1
, u_int8_t
*addr2
, u_int8_t
*addr3
)
1623 struct ieee80211_frame header
;
1625 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_TX
, "");
1628 bzero(&header
, sizeof(struct ieee80211_frame
));
1629 header
.i_fc
[0] = (IEEE80211_FC0_VERSION_0
| type
);
1630 header
.i_fc
[1] = fc1
;
1631 bcopy(addr1
, header
.i_addr1
, ETHER_ADDR_LEN
);
1632 bcopy(addr2
, header
.i_addr2
, ETHER_ADDR_LEN
);
1633 bcopy(addr3
, header
.i_addr3
, ETHER_ADDR_LEN
);
1635 SRAM_WRITE_REGION(sc
, bufp
, (u_int8_t
*)&header
,
1636 sizeof(struct ieee80211_frame
));
1638 return (bufp
+ sizeof(struct ieee80211_frame
));
1642 * Fill in a few loose ends and kick the card to send the packet
1644 * Returns 0 on success, 1 on failure
1647 ray_tx_send(struct ray_softc
*sc
, size_t ccs
, int pktlen
, u_int8_t
*dst
)
1651 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_TX
, "");
1654 while (!RAY_ECF_READY(sc
)) {
1655 DELAY(RAY_ECF_SPIN_DELAY
);
1656 if (++i
> RAY_ECF_SPIN_TRIES
) {
1657 RAY_RECERR(sc
, "ECF busy, dropping packet");
1658 RAY_CCS_FREE(sc
, ccs
);
1663 RAY_RECERR(sc
, "spun %d times", i
);
1665 SRAM_WRITE_FIELD_2(sc
, ccs
, ray_cmd_tx
, c_len
, pktlen
);
1666 SRAM_WRITE_FIELD_1(sc
, ccs
, ray_cmd_tx
, c_antenna
,
1667 ray_tx_best_antenna(sc
, dst
));
1668 SRAM_WRITE_1(sc
, RAY_SCB_CCSI
, RAY_CCS_INDEX(ccs
));
1669 RAY_ECF_START_CMD(sc
);
1675 * Determine best antenna to use from rx level and antenna cache
1678 ray_tx_best_antenna(struct ray_softc
*sc
, u_int8_t
*dst
)
1680 struct ray_siglev
*sl
;
1684 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_TX
, "");
1686 if (sc
->sc_version
== RAY_ECFS_BUILD_4
)
1689 /* try to find host */
1690 for (i
= 0; i
< RAY_NSIGLEVRECS
; i
++) {
1691 sl
= &sc
->sc_siglevs
[i
];
1692 if (bcmp(sl
->rsl_host
, dst
, ETHER_ADDR_LEN
) == 0)
1695 /* not found, return default setting */
1699 /* This is a simple thresholding scheme that takes the mean
1700 * of the best antenna history. This is okay but as it is a
1701 * filter, it adds a bit of lag in situations where the
1702 * best antenna swaps from one side to the other slowly. Don't know
1703 * how likely this is given the horrible fading though.
1706 for (i
= 0; i
< RAY_NANTENNA
; i
++) {
1707 antenna
+= sl
->rsl_antennas
[i
];
1710 return (antenna
> (RAY_NANTENNA
>> 1));
1714 * Transmit now complete so clear ccs and network flags.
1717 ray_tx_done(struct ray_softc
*sc
, u_int8_t status
, size_t ccs
)
1719 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1721 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_TX
, "");
1723 RAY_CCSERR(sc
, status
, if_oerrors
);
1725 RAY_CCS_FREE(sc
, ccs
);
1727 if (ifp
->if_flags
& IFF_OACTIVE
)
1728 ifp
->if_flags
&= ~IFF_OACTIVE
;
1732 * Receiver packet handling
1736 * Receive a packet from the card
1739 ray_rx(struct ray_softc
*sc
, size_t rcs
)
1741 struct ieee80211_frame
*header
;
1742 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1744 size_t pktlen
, fraglen
, readlen
, tmplen
;
1746 u_int8_t siglev
, antenna
;
1750 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
1753 RAY_DPRINTF(sc
, RAY_DBG_CCS
, "using rcs 0x%x", rcs
);
1759 * Get first part of packet and the length. Do some sanity checks
1762 first
= RAY_CCS_INDEX(rcs
);
1763 pktlen
= SRAM_READ_FIELD_2(sc
, rcs
, ray_cmd_rx
, c_pktlen
);
1764 siglev
= SRAM_READ_FIELD_1(sc
, rcs
, ray_cmd_rx
, c_siglev
);
1765 antenna
= SRAM_READ_FIELD_1(sc
, rcs
, ray_cmd_rx
, c_antenna
);
1767 if ((pktlen
> MCLBYTES
) || (pktlen
< sizeof(struct ieee80211_frame
))) {
1768 RAY_RECERR(sc
, "packet too big or too small");
1773 MGETHDR(m0
, MB_DONTWAIT
, MT_DATA
);
1775 RAY_RECERR(sc
, "MGETHDR failed");
1779 if (pktlen
> MHLEN
) {
1780 MCLGET(m0
, MB_DONTWAIT
);
1781 if (!(m0
->m_flags
& M_EXT
)) {
1782 RAY_RECERR(sc
, "MCLGET failed");
1789 m0
->m_pkthdr
.rcvif
= ifp
;
1790 m0
->m_pkthdr
.len
= pktlen
;
1792 mp
= mtod(m0
, u_int8_t
*);
1795 * Walk the fragment chain to build the complete packet.
1797 * The use of two index variables removes a race with the
1798 * hardware. If one index were used the clearing of the CCS would
1799 * happen before reading the next pointer and the hardware can get in.
1800 * Not my idea but verbatim from the NetBSD driver.
1803 while ((i
= ni
) && (i
!= RAY_CCS_LINK_NULL
)) {
1804 rcs
= RAY_CCS_ADDRESS(i
);
1805 ni
= SRAM_READ_FIELD_1(sc
, rcs
, ray_cmd_rx
, c_nextfrag
);
1806 bufp
= SRAM_READ_FIELD_2(sc
, rcs
, ray_cmd_rx
, c_bufp
);
1807 fraglen
= SRAM_READ_FIELD_2(sc
, rcs
, ray_cmd_rx
, c_len
);
1808 if (fraglen
+ readlen
> pktlen
) {
1809 RAY_RECERR(sc
, "bad length current 0x%x pktlen 0x%x",
1810 fraglen
+ readlen
, pktlen
);
1816 if ((i
< RAY_RCS_FIRST
) || (i
> RAY_RCS_LAST
)) {
1817 RAY_RECERR(sc
, "bad rcs index 0x%x", i
);
1824 ebufp
= bufp
+ fraglen
;
1825 if (ebufp
<= RAY_RX_END
)
1826 SRAM_READ_REGION(sc
, bufp
, mp
, fraglen
);
1828 SRAM_READ_REGION(sc
, bufp
, mp
,
1829 (tmplen
= RAY_RX_END
- bufp
));
1830 SRAM_READ_REGION(sc
, RAY_RX_BASE
, mp
+ tmplen
,
1831 ebufp
- RAY_RX_END
);
1840 * Walk the chain again to free the rcss.
1843 while ((i
= ni
) && (i
!= RAY_CCS_LINK_NULL
)) {
1844 rcs
= RAY_CCS_ADDRESS(i
);
1845 ni
= SRAM_READ_FIELD_1(sc
, rcs
, ray_cmd_rx
, c_nextfrag
);
1846 RAY_CCS_FREE(sc
, rcs
);
1853 * Check the 802.11 packet type and hand off to
1854 * appropriate functions.
1856 header
= mtod(m0
, struct ieee80211_frame
*);
1857 if ((header
->i_fc
[0] & IEEE80211_FC0_VERSION_MASK
)
1858 != IEEE80211_FC0_VERSION_0
) {
1859 RAY_RECERR(sc
, "header not version 0 fc0 0x%x",
1865 switch (header
->i_fc
[0] & IEEE80211_FC0_TYPE_MASK
) {
1867 case IEEE80211_FC0_TYPE_DATA
:
1868 ray_rx_data(sc
, m0
, siglev
, antenna
);
1871 case IEEE80211_FC0_TYPE_MGT
:
1875 case IEEE80211_FC0_TYPE_CTL
:
1880 RAY_RECERR(sc
, "unknown packet fc0 0x%x", header
->i_fc
[0]);
1887 * Deal with DATA packet types
1890 ray_rx_data(struct ray_softc
*sc
, struct mbuf
*m0
, u_int8_t siglev
, u_int8_t antenna
)
1892 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
1893 struct ieee80211_frame
*header
= mtod(m0
, struct ieee80211_frame
*);
1894 struct ether_header
*eh
;
1896 u_int8_t
*sa
= NULL
, *da
= NULL
, *ra
= NULL
, *ta
= NULL
;
1899 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_RX
, "");
1902 * Check the the data packet subtype, some packets have
1903 * nothing in them so we will drop them here.
1905 switch (header
->i_fc
[0] & IEEE80211_FC0_SUBTYPE_MASK
) {
1907 case IEEE80211_FC0_SUBTYPE_DATA
:
1908 case IEEE80211_FC0_SUBTYPE_CF_ACK
:
1909 case IEEE80211_FC0_SUBTYPE_CF_POLL
:
1910 case IEEE80211_FC0_SUBTYPE_CF_ACPL
:
1911 RAY_DPRINTF(sc
, RAY_DBG_RX
, "DATA packet");
1914 case IEEE80211_FC0_SUBTYPE_NODATA
:
1915 case IEEE80211_FC0_SUBTYPE_CFACK
:
1916 case IEEE80211_FC0_SUBTYPE_CFPOLL
:
1917 case IEEE80211_FC0_SUBTYPE_CF_ACK_CF_ACK
:
1918 RAY_DPRINTF(sc
, RAY_DBG_RX
, "NULL packet");
1924 RAY_RECERR(sc
, "reserved DATA packet subtype 0x%x",
1925 header
->i_fc
[0] & IEEE80211_FC0_SUBTYPE_MASK
);
1932 * Parse the To DS and From DS fields to determine the length
1933 * of the 802.11 header for use later on.
1935 * Additionally, furtle out the right destination and
1936 * source MAC addresses for the packet. Packets may come via
1937 * APs so the MAC addresses of the immediate node may be
1938 * different from the node that actually sent us the packet.
1940 * da destination address of final recipient
1941 * sa source address of orginator
1942 * ra receiver address of immediate recipient
1943 * ta transmitter address of immediate orginator
1945 * Address matching is performed on da or sa with the AP or
1946 * BSSID in ra and ta.
1948 RAY_MBUF_DUMP(sc
, RAY_DBG_RX
, m0
, "(1) packet before framing");
1949 switch (header
->i_fc
[1] & IEEE80211_FC1_DIR_MASK
) {
1951 case IEEE80211_FC1_DIR_NODS
:
1952 da
= ra
= header
->i_addr1
;
1953 sa
= ta
= header
->i_addr2
;
1954 trim
= sizeof(struct ieee80211_frame
);
1955 RAY_DPRINTF(sc
, RAY_DBG_RX
, "from %6D to %6D",
1959 case IEEE80211_FC1_DIR_FROMDS
:
1960 da
= ra
= header
->i_addr1
;
1961 ta
= header
->i_addr2
;
1962 sa
= header
->i_addr3
;
1963 trim
= sizeof(struct ieee80211_frame
);
1964 RAY_DPRINTF(sc
, RAY_DBG_RX
, "ap %6D from %6D to %6D",
1965 ta
, ":", sa
, ":", da
, ":");
1968 case IEEE80211_FC1_DIR_TODS
:
1969 ra
= header
->i_addr1
;
1970 sa
= ta
= header
->i_addr2
;
1971 da
= header
->i_addr3
;
1972 trim
= sizeof(struct ieee80211_frame
);
1973 RAY_DPRINTF(sc
, RAY_DBG_RX
, "from %6D to %6D ap %6D",
1974 sa
, ":", da
, ":", ra
, ":");
1977 case IEEE80211_FC1_DIR_DSTODS
:
1978 ra
= header
->i_addr1
;
1979 ta
= header
->i_addr2
;
1980 da
= header
->i_addr3
;
1981 sa
= (u_int8_t
*)header
+1;
1982 trim
= sizeof(struct ieee80211_frame
) + ETHER_ADDR_LEN
;
1983 RAY_DPRINTF(sc
, RAY_DBG_RX
, "from %6D to %6D ap %6D to %6D",
1984 sa
, ":", da
, ":", ta
, ":", ra
, ":");
1991 * Each case must leave an Ethernet header and adjust trim.
1993 switch (sc
->sc_c
.np_framing
) {
1995 case RAY_FRAMING_ENCAPSULATION
:
1996 /* A NOP as the Ethernet header is in the packet */
1999 case RAY_FRAMING_TRANSLATION
:
2000 /* Check that we have an LLC and SNAP sequence */
2001 llc
= (struct llc
*)((u_int8_t
*)header
+ trim
);
2002 if (llc
->llc_dsap
== LLC_SNAP_LSAP
&&
2003 llc
->llc_ssap
== LLC_SNAP_LSAP
&&
2004 llc
->llc_control
== LLC_UI
&&
2005 llc
->llc_un
.type_snap
.org_code
[0] == 0 &&
2006 llc
->llc_un
.type_snap
.org_code
[1] == 0 &&
2007 llc
->llc_un
.type_snap
.org_code
[2] == 0) {
2009 * This is not magic. RFC1042 header is 8
2010 * bytes, with the last two bytes being the
2011 * ether type. So all we need is another
2012 * ETHER_ADDR_LEN bytes to write the
2015 trim
-= ETHER_ADDR_LEN
;
2016 eh
= (struct ether_header
*)((u_int8_t
*)header
+ trim
);
2019 * Copy carefully to avoid mashing the MAC
2020 * addresses. The address layout in the .11 header
2021 * does make sense, honest, but it is a pain.
2023 * NODS da sa no risk
2024 * FROMDS da ta sa sa then da
2025 * DSTODS ra ta da sa sa then da
2026 * TODS ra sa da da then sa
2030 bcopy(sa
, eh
->ether_shost
, ETHER_ADDR_LEN
);
2031 bcopy(da
, eh
->ether_dhost
, ETHER_ADDR_LEN
);
2034 bcopy(da
, eh
->ether_dhost
, ETHER_ADDR_LEN
);
2035 bcopy(sa
, eh
->ether_shost
, ETHER_ADDR_LEN
);
2040 /* Assume RAY_FRAMING_ENCAPSULATION */
2042 "got encapsulated packet but in translation mode");
2048 RAY_RECERR(sc
, "unknown framing type %d", sc
->sc_c
.np_framing
);
2053 RAY_MBUF_DUMP(sc
, RAY_DBG_RX
, m0
, "(2) packet after framing");
2056 * Finally, do a bit of house keeping before sending the packet
2060 RAY_MBUF_DUMP(sc
, RAY_DBG_RX
, m0
, "(3) packet after trimming");
2062 ray_rx_update_cache(sc
, header
->i_addr2
, siglev
, antenna
);
2063 ifp
->if_input(ifp
, m0
);
2067 * Deal with MGT packet types
2070 ray_rx_mgt(struct ray_softc
*sc
, struct mbuf
*m0
)
2072 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
2073 struct ieee80211_frame
*header
= mtod(m0
, struct ieee80211_frame
*);
2075 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_MGT
, "");
2077 if ((header
->i_fc
[1] & IEEE80211_FC1_DIR_MASK
) !=
2078 IEEE80211_FC1_DIR_NODS
) {
2079 RAY_RECERR(sc
, "MGT TODS/FROMDS wrong fc1 0x%x",
2080 header
->i_fc
[1] & IEEE80211_FC1_DIR_MASK
);
2087 * Check the the mgt packet subtype, some packets should be
2088 * dropped depending on the mode the station is in. See pg
2091 * P - proccess, J - Junk, E - ECF deals with, I - Illegal
2093 * AHDOC procces or junk
2094 * INFRA STA process or junk
2095 * INFRA AP process or jumk
2097 * +PPP IEEE80211_FC0_SUBTYPE_BEACON
2098 * +EEE IEEE80211_FC0_SUBTYPE_PROBE_REQ
2099 * +EEE IEEE80211_FC0_SUBTYPE_PROBE_RESP
2100 * PPP IEEE80211_FC0_SUBTYPE_AUTH
2101 * PPP IEEE80211_FC0_SUBTYPE_DEAUTH
2102 * JJP IEEE80211_FC0_SUBTYPE_ASSOC_REQ
2103 * JPJ IEEE80211_FC0_SUBTYPE_ASSOC_RESP
2104 * JPP IEEE80211_FC0_SUBTYPE_DISASSOC
2105 * JJP IEEE80211_FC0_SUBTYPE_REASSOC_REQ
2106 * JPJ IEEE80211_FC0_SUBTYPE_REASSOC_RESP
2107 * +EEE IEEE80211_FC0_SUBTYPE_ATIM
2109 RAY_MBUF_DUMP(sc
, RAY_DBG_MGT
, m0
, "MGT packet");
2110 switch (header
->i_fc
[0] & IEEE80211_FC0_SUBTYPE_MASK
) {
2112 case IEEE80211_FC0_SUBTYPE_BEACON
:
2113 RAY_DPRINTF(sc
, RAY_DBG_MGT
, "BEACON MGT packet");
2114 ray_rx_mgt_beacon(sc
, m0
);
2117 case IEEE80211_FC0_SUBTYPE_AUTH
:
2118 RAY_DPRINTF(sc
, RAY_DBG_MGT
, "AUTH MGT packet");
2119 ray_rx_mgt_auth(sc
, m0
);
2122 case IEEE80211_FC0_SUBTYPE_DEAUTH
:
2123 RAY_DPRINTF(sc
, RAY_DBG_MGT
, "DEAUTH MGT packet");
2124 /* XXX ray_rx_mgt_deauth(sc, m0); */
2127 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ
:
2128 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ
:
2129 RAY_DPRINTF(sc
, RAY_DBG_MGT
, "(RE)ASSOC_REQ MGT packet");
2130 if ((sc
->sc_c
.np_net_type
== RAY_MIB_NET_TYPE_INFRA
) &&
2131 (sc
->sc_c
.np_ap_status
== RAY_MIB_AP_STATUS_AP
))
2132 RAY_RECERR(sc
, "can't be an AP yet"); /* XXX_ACTING_AP */
2135 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP
:
2136 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP
:
2137 RAY_DPRINTF(sc
, RAY_DBG_MGT
, "(RE)ASSOC_RESP MGT packet");
2138 if ((sc
->sc_c
.np_net_type
== RAY_MIB_NET_TYPE_INFRA
) &&
2139 (sc
->sc_c
.np_ap_status
== RAY_MIB_AP_STATUS_TERMINAL
))
2140 RAY_RECERR(sc
, "can't be in INFRA yet"); /* XXX_INFRA */
2143 case IEEE80211_FC0_SUBTYPE_DISASSOC
:
2144 RAY_DPRINTF(sc
, RAY_DBG_MGT
, "DISASSOC MGT packet");
2145 if (sc
->sc_c
.np_net_type
== RAY_MIB_NET_TYPE_INFRA
)
2146 RAY_RECERR(sc
, "can't be in INFRA yet"); /* XXX_INFRA */
2149 case IEEE80211_FC0_SUBTYPE_PROBE_REQ
:
2150 case IEEE80211_FC0_SUBTYPE_PROBE_RESP
:
2151 case IEEE80211_FC0_SUBTYPE_ATIM
:
2152 RAY_RECERR(sc
, "unexpected MGT packet subtype 0x%0x",
2153 header
->i_fc
[0] & IEEE80211_FC0_SUBTYPE_MASK
);
2158 RAY_RECERR(sc
, "reserved MGT packet subtype 0x%x",
2159 header
->i_fc
[0] & IEEE80211_FC0_SUBTYPE_MASK
);
2167 * Deal with BEACON management packet types
2168 * XXX furtle anything interesting out
2169 * XXX Note that there are rules governing what beacons to read
2170 * XXX see 8802 S7.2.3, S11.1.2.3
2171 * XXX is this actually useful?
2174 ray_rx_mgt_beacon(struct ray_softc
*sc
, struct mbuf
*m0
)
2176 struct ieee80211_frame
*header
= mtod(m0
, struct ieee80211_frame
*);
2177 ieee80211_mgt_beacon_t beacon
= (u_int8_t
*)(header
+1);
2178 union ieee80211_information elements
;
2180 u_int64_t
*timestamp
;
2182 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_MGT
, "");
2184 timestamp
= (u_int64_t
*)beacon
;
2186 RAY_DPRINTF(sc
, RAY_DBG_MGT
, "timestamp\t0x%x", *timestamp
);
2187 RAY_DPRINTF(sc
, RAY_DBG_MGT
, "interval\t\t0x%x", IEEE80211_BEACON_INTERVAL(beacon
));
2188 RAY_DPRINTF(sc
, RAY_DBG_MGT
, "capability\t0x%x", IEEE80211_BEACON_CAPABILITY(beacon
));
2190 ray_rx_mgt_info(sc
, m0
, &elements
);
2195 ray_rx_mgt_info(struct ray_softc
*sc
, struct mbuf
*m0
,
2196 union ieee80211_information
*elements
)
2198 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
2199 struct ieee80211_frame
*header
= mtod(m0
, struct ieee80211_frame
*);
2200 ieee80211_mgt_beacon_t beacon
= (u_int8_t
*)(header
+1);
2201 ieee80211_mgt_beacon_t bp
, be
;
2204 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_MGT
, "");
2207 be
= mtod(m0
, u_int8_t
*) + m0
->m_len
;
2211 RAY_DPRINTF(sc
, RAY_DBG_MGT
, "id 0x%02x length %d", *bp
, len
);
2215 case IEEE80211_ELEMID_SSID
:
2216 if (len
> IEEE80211_NWID_LEN
) {
2217 RAY_RECERR(sc
, "bad SSD length: %d from %6D",
2218 len
, header
->i_addr2
, ":");
2220 strncpy(elements
->ssid
, bp
+ 2, len
);
2221 elements
->ssid
[len
] = 0;
2222 RAY_DPRINTF(sc
, RAY_DBG_MGT
,
2223 "beacon ssid %s", elements
->ssid
);
2226 case IEEE80211_ELEMID_RATES
:
2227 RAY_DPRINTF(sc
, RAY_DBG_MGT
, "rates");
2230 case IEEE80211_ELEMID_FHPARMS
:
2231 elements
->fh
.dwell
= bp
[2] + (bp
[3] << 8);
2232 elements
->fh
.set
= bp
[4];
2233 elements
->fh
.pattern
= bp
[5];
2234 elements
->fh
.index
= bp
[6];
2235 RAY_DPRINTF(sc
, RAY_DBG_MGT
,
2236 "fhparams dwell\t0x%04x", elements
->fh
.dwell
);
2237 RAY_DPRINTF(sc
, RAY_DBG_MGT
,
2238 "fhparams set\t0x%02x", elements
->fh
.set
);
2239 RAY_DPRINTF(sc
, RAY_DBG_MGT
,
2240 "fhparams pattern\t0x%02x", elements
->fh
.pattern
);
2241 RAY_DPRINTF(sc
, RAY_DBG_MGT
,
2242 "fhparams index\t0x%02x", elements
->fh
.index
);
2245 case IEEE80211_ELEMID_DSPARMS
:
2246 RAY_RECERR(sc
, "got direct sequence params!");
2249 case IEEE80211_ELEMID_CFPARMS
:
2250 RAY_DPRINTF(sc
, RAY_DBG_MGT
, "cfparams");
2253 case IEEE80211_ELEMID_TIM
:
2254 elements
->tim
.count
= bp
[2];
2255 elements
->tim
.period
= bp
[3];
2256 elements
->tim
.bitctl
= bp
[4];
2257 RAY_DPRINTF(sc
, RAY_DBG_MGT
,
2258 "tim count\t0x%02x", elements
->tim
.count
);
2259 RAY_DPRINTF(sc
, RAY_DBG_MGT
,
2260 "tim period\t0x%02x", elements
->tim
.period
);
2261 RAY_DPRINTF(sc
, RAY_DBG_MGT
,
2262 "tim bitctl\t0x%02x", elements
->tim
.bitctl
);
2263 #if RAY_DEBUG & RAY_DBG_MGT
2266 for (i
= 5; i
< len
+ 1; i
++)
2267 RAY_DPRINTF(sc
, RAY_DBG_MGT
,
2268 "tim pvt[%03d]\t0x%02x", i
-5, bp
[i
]);
2273 case IEEE80211_ELEMID_IBSSPARMS
:
2274 elements
->ibss
.atim
= bp
[2] + (bp
[3] << 8);
2275 RAY_DPRINTF(sc
, RAY_DBG_MGT
,
2276 "ibssparams atim\t0x%02x", elements
->ibss
.atim
);
2279 case IEEE80211_ELEMID_CHALLENGE
:
2280 RAY_DPRINTF(sc
, RAY_DBG_MGT
, "challenge");
2284 RAY_RECERR(sc
, "reserved MGT element id 0x%x", *bp
);
2285 ifp
->if_ierrors
++;break;
2292 * Deal with AUTH management packet types
2295 ray_rx_mgt_auth(struct ray_softc
*sc
, struct mbuf
*m0
)
2297 struct ieee80211_frame
*header
= mtod(m0
, struct ieee80211_frame
*);
2298 ieee80211_mgt_auth_t auth
= (u_int8_t
*)(header
+1);
2300 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_AUTH
, "");
2302 switch (IEEE80211_AUTH_ALGORITHM(auth
)) {
2304 case IEEE80211_AUTH_ALG_OPEN
:
2305 RAY_DPRINTF(sc
, RAY_DBG_AUTH
,
2306 "open system authentication sequence number %d",
2307 IEEE80211_AUTH_TRANSACTION(auth
));
2308 if (IEEE80211_AUTH_TRANSACTION(auth
) ==
2309 IEEE80211_AUTH_OPEN_REQUEST
) {
2311 /* XXX_AUTH use ray_init_auth_send */
2313 } else if (IEEE80211_AUTH_TRANSACTION(auth
) ==
2314 IEEE80211_AUTH_OPEN_RESPONSE
)
2315 ray_init_auth_done(sc
, IEEE80211_AUTH_STATUS(auth
));
2318 case IEEE80211_AUTH_ALG_SHARED
:
2320 "shared key authentication sequence number %d",
2321 IEEE80211_AUTH_TRANSACTION(auth
));
2326 "reserved authentication subtype 0x%04hx",
2327 IEEE80211_AUTH_ALGORITHM(auth
));
2333 * Deal with CTL packet types
2336 ray_rx_ctl(struct ray_softc
*sc
, struct mbuf
*m0
)
2338 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
2339 struct ieee80211_frame
*header
= mtod(m0
, struct ieee80211_frame
*);
2341 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_CTL
, "");
2343 if ((header
->i_fc
[1] & IEEE80211_FC1_DIR_MASK
) !=
2344 IEEE80211_FC1_DIR_NODS
) {
2345 RAY_RECERR(sc
, "CTL TODS/FROMDS wrong fc1 0x%x",
2346 header
->i_fc
[1] & IEEE80211_FC1_DIR_MASK
);
2353 * Check the the ctl packet subtype, some packets should be
2354 * dropped depending on the mode the station is in. The ECF
2355 * should deal with everything but the power save poll to an
2356 * AP. See pg 52(60) of docs.
2358 RAY_MBUF_DUMP(sc
, RAY_DBG_CTL
, m0
, "CTL packet");
2359 switch (header
->i_fc
[0] & IEEE80211_FC0_SUBTYPE_MASK
) {
2361 case IEEE80211_FC0_SUBTYPE_PS_POLL
:
2362 RAY_DPRINTF(sc
, RAY_DBG_CTL
, "PS_POLL CTL packet");
2363 if ((sc
->sc_d
.np_net_type
== RAY_MIB_NET_TYPE_INFRA
) &&
2364 (sc
->sc_c
.np_ap_status
== RAY_MIB_AP_STATUS_AP
))
2365 RAY_RECERR(sc
, "can't be an AP yet"); /* XXX_ACTING_AP */
2368 case IEEE80211_FC0_SUBTYPE_RTS
:
2369 case IEEE80211_FC0_SUBTYPE_CTS
:
2370 case IEEE80211_FC0_SUBTYPE_ACK
:
2371 case IEEE80211_FC0_SUBTYPE_CF_END
:
2372 case IEEE80211_FC0_SUBTYPE_CF_END_ACK
:
2373 RAY_RECERR(sc
, "unexpected CTL packet subtype 0x%0x",
2374 header
->i_fc
[0] & IEEE80211_FC0_SUBTYPE_MASK
);
2379 RAY_RECERR(sc
, "reserved CTL packet subtype 0x%x",
2380 header
->i_fc
[0] & IEEE80211_FC0_SUBTYPE_MASK
);
2388 * Update rx level and antenna cache
2391 ray_rx_update_cache(struct ray_softc
*sc
, u_int8_t
*src
, u_int8_t siglev
, u_int8_t antenna
)
2393 struct timeval mint
;
2394 struct ray_siglev
*sl
;
2397 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
2399 /* Try to find host */
2400 for (i
= 0; i
< RAY_NSIGLEVRECS
; i
++) {
2401 sl
= &sc
->sc_siglevs
[i
];
2402 if (bcmp(sl
->rsl_host
, src
, ETHER_ADDR_LEN
) == 0)
2405 /* Not found, find oldest slot */
2407 mint
.tv_sec
= LONG_MAX
;
2409 for (i
= 0; i
< RAY_NSIGLEVRECS
; i
++) {
2410 sl
= &sc
->sc_siglevs
[i
];
2411 if (timevalcmp(&sl
->rsl_time
, &mint
, <)) {
2413 mint
= sl
->rsl_time
;
2416 sl
= &sc
->sc_siglevs
[mini
];
2417 bzero(sl
->rsl_siglevs
, RAY_NSIGLEV
);
2418 bzero(sl
->rsl_antennas
, RAY_NANTENNA
);
2419 bcopy(src
, sl
->rsl_host
, ETHER_ADDR_LEN
);
2422 microtime(&sl
->rsl_time
);
2423 bcopy(sl
->rsl_siglevs
, &sl
->rsl_siglevs
[1], RAY_NSIGLEV
-1);
2424 sl
->rsl_siglevs
[0] = siglev
;
2425 if (sc
->sc_version
!= RAY_ECFS_BUILD_4
) {
2426 bcopy(sl
->rsl_antennas
, &sl
->rsl_antennas
[1], RAY_NANTENNA
-1);
2427 sl
->rsl_antennas
[0] = antenna
;
2432 * Interrupt handling
2436 * Process an interrupt
2441 struct ray_softc
*sc
= (struct ray_softc
*)xsc
;
2442 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
2444 u_int8_t cmd
, status
;
2447 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
2450 if ((sc
== NULL
) || (sc
->sc_gone
))
2454 * Check that the interrupt was for us, if so get the rcs/ccs
2455 * and vector on the command contained within it.
2457 if (RAY_HCS_INTR(sc
)) {
2458 ccsi
= SRAM_READ_1(sc
, RAY_SCB_RCSI
);
2459 ccs
= RAY_CCS_ADDRESS(ccsi
);
2460 cmd
= SRAM_READ_FIELD_1(sc
, ccs
, ray_cmd
, c_cmd
);
2461 status
= SRAM_READ_FIELD_1(sc
, ccs
, ray_cmd
, c_status
);
2462 if (ccsi
<= RAY_CCS_LAST
)
2463 ray_intr_ccs(sc
, cmd
, status
, ccs
);
2464 else if (ccsi
<= RAY_RCS_LAST
)
2465 ray_intr_rcs(sc
, cmd
, ccs
);
2467 RAY_RECERR(sc
, "bad ccs index 0x%x", ccsi
);
2468 RAY_HCS_CLEAR_INTR(sc
);
2471 /* Send any packets lying around and update error counters */
2472 if ((ifp
->if_flags
& IFF_OACTIVE
) == 0 && !ifq_is_empty(&ifp
->if_snd
))
2474 if ((++sc
->sc_checkcounters
% 32) == 0)
2475 ray_intr_updt_errcntrs(sc
);
2479 * Read the error counters.
2482 ray_intr_updt_errcntrs(struct ray_softc
*sc
)
2486 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
2490 * The card implements the following protocol to keep the
2491 * values from being changed while read: It checks the `own'
2492 * bit and if zero writes the current internal counter value,
2493 * it then sets the `own' bit to 1. If the `own' bit was 1 it
2494 * incremenets its internal counter. The user thus reads the
2495 * counter if the `own' bit is one and then sets the own bit
2498 csc
= RAY_STATUS_BASE
;
2499 if (SRAM_READ_FIELD_1(sc
, csc
, ray_csc
, csc_mrxo_own
)) {
2500 sc
->sc_rxoverflow
+=
2501 SRAM_READ_FIELD_2(sc
, csc
, ray_csc
, csc_mrx_overflow
);
2502 SRAM_WRITE_FIELD_1(sc
, csc
, ray_csc
, csc_mrxo_own
, 0);
2504 if (SRAM_READ_FIELD_1(sc
, csc
, ray_csc
, csc_mrxc_own
)) {
2506 SRAM_READ_FIELD_2(sc
, csc
, ray_csc
, csc_mrx_overflow
);
2507 SRAM_WRITE_FIELD_1(sc
, csc
, ray_csc
, csc_mrxc_own
, 0);
2509 if (SRAM_READ_FIELD_1(sc
, csc
, ray_csc
, csc_rxhc_own
)) {
2511 SRAM_READ_FIELD_2(sc
, csc
, ray_csc
, csc_rx_hcksum
);
2512 SRAM_WRITE_FIELD_1(sc
, csc
, ray_csc
, csc_rxhc_own
, 0);
2514 sc
->sc_rxnoise
= SRAM_READ_FIELD_1(sc
, csc
, ray_csc
, csc_rx_noise
);
2518 * Process CCS command completion
2521 ray_intr_ccs(struct ray_softc
*sc
, u_int8_t cmd
, u_int8_t status
, size_t ccs
)
2523 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
2527 case RAY_CMD_DOWNLOAD_PARAMS
:
2528 RAY_DPRINTF(sc
, RAY_DBG_COM
, "START_PARAMS");
2529 ray_init_download_done(sc
, status
, ccs
);
2532 case RAY_CMD_UPDATE_PARAMS
:
2533 RAY_DPRINTF(sc
, RAY_DBG_COM
, "UPDATE_PARAMS");
2534 ray_upparams_done(sc
, status
, ccs
);
2537 case RAY_CMD_REPORT_PARAMS
:
2538 RAY_DPRINTF(sc
, RAY_DBG_COM
, "REPORT_PARAMS");
2539 ray_repparams_done(sc
, status
, ccs
);
2542 case RAY_CMD_UPDATE_MCAST
:
2543 RAY_DPRINTF(sc
, RAY_DBG_COM
, "UPDATE_MCAST");
2544 ray_mcast_done(sc
, status
, ccs
);
2547 case RAY_CMD_START_NET
:
2548 case RAY_CMD_JOIN_NET
:
2549 RAY_DPRINTF(sc
, RAY_DBG_COM
, "START|JOIN_NET");
2550 ray_init_sj_done(sc
, status
, ccs
);
2553 case RAY_CMD_TX_REQ
:
2554 RAY_DPRINTF(sc
, RAY_DBG_COM
, "TX_REQ");
2555 ray_tx_done(sc
, status
, ccs
);
2558 case RAY_CMD_START_ASSOC
:
2559 RAY_DPRINTF(sc
, RAY_DBG_COM
, "START_ASSOC");
2560 ray_init_assoc_done(sc
, status
, ccs
);
2563 case RAY_CMD_UPDATE_APM
:
2564 RAY_RECERR(sc
, "unexpected UPDATE_APM");
2567 case RAY_CMD_TEST_MEM
:
2568 RAY_RECERR(sc
, "unexpected TEST_MEM");
2571 case RAY_CMD_SHUTDOWN
:
2572 RAY_RECERR(sc
, "unexpected SHUTDOWN");
2575 case RAY_CMD_DUMP_MEM
:
2576 RAY_RECERR(sc
, "unexpected DUMP_MEM");
2579 case RAY_CMD_START_TIMER
:
2580 RAY_RECERR(sc
, "unexpected START_TIMER");
2584 RAY_RECERR(sc
, "unknown command 0x%x", cmd
);
2590 * Process ECF command request
2593 ray_intr_rcs(struct ray_softc
*sc
, u_int8_t cmd
, size_t rcs
)
2595 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
2599 case RAY_ECMD_RX_DONE
:
2600 RAY_DPRINTF(sc
, RAY_DBG_RX
, "RX_DONE");
2604 case RAY_ECMD_REJOIN_DONE
:
2605 RAY_DPRINTF(sc
, RAY_DBG_RX
, "REJOIN_DONE");
2606 sc
->sc_c
.np_havenet
= 1; /* XXX Should not be here but in function */
2609 case RAY_ECMD_ROAM_START
:
2610 RAY_DPRINTF(sc
, RAY_DBG_RX
, "ROAM_START");
2611 sc
->sc_c
.np_havenet
= 0; /* XXX Should not be here but in function */
2614 case RAY_ECMD_JAPAN_CALL_SIGNAL
:
2615 RAY_RECERR(sc
, "unexpected JAPAN_CALL_SIGNAL");
2619 RAY_RECERR(sc
, "unknown command 0x%x", cmd
);
2623 RAY_CCS_FREE(sc
, rcs
);
2627 * User land entry to multicast list changes
2630 ray_mcast_user(struct ray_softc
*sc
)
2632 struct ray_comq_entry
*com
[2];
2635 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
2638 * Do all checking in the runq to preserve ordering.
2640 * We run promisc to pick up changes to the ALL_MULTI
2644 com
[ncom
++] = RAY_COM_MALLOC(ray_mcast
, 0);
2645 com
[ncom
++] = RAY_COM_MALLOC(ray_promisc
, 0);
2647 RAY_COM_RUNQ(sc
, com
, ncom
, "raymcast", error
);
2649 /* XXX no real error processing from anything yet! */
2651 RAY_COM_FREE(com
, ncom
);
2657 * Runq entry to setting the multicast filter list
2659 * MUST always be followed by a call to ray_promisc to pick up changes
2663 ray_mcast(struct ray_softc
*sc
, struct ray_comq_entry
*com
)
2665 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
2666 struct ifmultiaddr
*ifma
;
2670 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
2674 * If card is not running we don't need to update this.
2676 if (!(ifp
->if_flags
& IFF_RUNNING
)) {
2677 RAY_DPRINTF(sc
, RAY_DBG_IOCTL
, "not running");
2678 ray_com_runq_done(sc
);
2683 * The multicast list is only 16 items long so use promiscuous
2684 * mode and don't bother updating the multicast list.
2686 LIST_FOREACH(ifma
, &ifp
->if_multiaddrs
, ifma_link
)
2689 ray_com_runq_done(sc
);
2691 } else if (count
> 16) {
2692 ifp
->if_flags
|= IFF_ALLMULTI
;
2693 ray_com_runq_done(sc
);
2695 } else if (ifp
->if_flags
& IFF_ALLMULTI
)
2696 ifp
->if_flags
&= ~IFF_ALLMULTI
;
2701 ray_ccs_fill(sc
, com
->c_ccs
, RAY_CMD_UPDATE_MCAST
);
2702 SRAM_WRITE_FIELD_1(sc
, com
->c_ccs
,
2703 ray_cmd_update_mcast
, c_nmcast
, count
);
2704 bufp
= RAY_HOST_TO_ECF_BASE
;
2705 LIST_FOREACH(ifma
, &ifp
->if_multiaddrs
, ifma_link
) {
2709 LLADDR((struct sockaddr_dl
*)ifma
->ifma_addr
),
2712 bufp
+= ETHER_ADDR_LEN
;
2715 ray_com_ecf(sc
, com
);
2719 * Complete the multicast filter list update
2722 ray_mcast_done(struct ray_softc
*sc
, u_int8_t status
, size_t ccs
)
2724 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_STARTJOIN
, "");
2725 RAY_COM_CHECK(sc
, ccs
);
2727 RAY_CCSERR(sc
, status
, if_oerrors
); /* XXX error counter */
2729 ray_com_ecf_done(sc
);
2733 * Runq entry to set/reset promiscuous mode
2736 ray_promisc(struct ray_softc
*sc
, struct ray_comq_entry
*com
)
2738 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
2740 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
2744 * If card not running or we already have the right flags
2745 * we don't need to update this
2747 sc
->sc_d
.np_promisc
= !!(ifp
->if_flags
& (IFF_PROMISC
| IFF_ALLMULTI
));
2748 if (!(ifp
->if_flags
& IFF_RUNNING
) ||
2749 (sc
->sc_c
.np_promisc
== sc
->sc_d
.np_promisc
)) {
2750 ray_com_runq_done(sc
);
2757 ray_ccs_fill(sc
, com
->c_ccs
, RAY_CMD_UPDATE_PARAMS
);
2758 SRAM_WRITE_FIELD_1(sc
, com
->c_ccs
,
2759 ray_cmd_update
, c_paramid
, RAY_MIB_PROMISC
);
2760 SRAM_WRITE_FIELD_1(sc
, com
->c_ccs
, ray_cmd_update
, c_nparam
, 1);
2761 SRAM_WRITE_1(sc
, RAY_HOST_TO_ECF_BASE
, sc
->sc_d
.np_promisc
);
2763 ray_com_ecf(sc
, com
);
2767 * User land entry to parameter reporting
2769 * As we by pass the runq to report current parameters this function
2770 * only provides a snap shot of the driver's state.
2773 ray_repparams_user(struct ray_softc
*sc
, struct ray_param_req
*pr
)
2775 struct ray_comq_entry
*com
[1];
2778 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
2781 * Test for illegal values or immediate responses
2783 if (pr
->r_paramid
> RAY_MIB_MAX
)
2785 if ((sc
->sc_version
== RAY_ECFS_BUILD_4
) &&
2786 !(mib_info
[pr
->r_paramid
][0] & RAY_V4
))
2788 if ((sc
->sc_version
== RAY_ECFS_BUILD_5
) &&
2789 !(mib_info
[pr
->r_paramid
][0] & RAY_V5
))
2791 if (pr
->r_paramid
> RAY_MIB_LASTUSER
) {
2792 switch (pr
->r_paramid
) {
2794 case RAY_MIB_VERSION
:
2795 if (sc
->sc_version
== RAY_ECFS_BUILD_4
)
2796 *pr
->r_data
= RAY_V4
;
2798 *pr
->r_data
= RAY_V5
;
2800 case RAY_MIB_CUR_BSSID
:
2801 bcopy(sc
->sc_c
.np_bss_id
, pr
->r_data
, ETHER_ADDR_LEN
);
2803 case RAY_MIB_CUR_INITED
:
2804 *pr
->r_data
= sc
->sc_c
.np_inited
;
2806 case RAY_MIB_CUR_DEF_TXRATE
:
2807 *pr
->r_data
= sc
->sc_c
.np_def_txrate
;
2809 case RAY_MIB_CUR_ENCRYPT
:
2810 *pr
->r_data
= sc
->sc_c
.np_encrypt
;
2812 case RAY_MIB_CUR_NET_TYPE
:
2813 *pr
->r_data
= sc
->sc_c
.np_net_type
;
2815 case RAY_MIB_CUR_SSID
:
2816 bcopy(sc
->sc_c
.np_ssid
, pr
->r_data
, IEEE80211_NWID_LEN
);
2818 case RAY_MIB_CUR_PRIV_START
:
2819 *pr
->r_data
= sc
->sc_c
.np_priv_start
;
2821 case RAY_MIB_CUR_PRIV_JOIN
:
2822 *pr
->r_data
= sc
->sc_c
.np_priv_join
;
2824 case RAY_MIB_DES_BSSID
:
2825 bcopy(sc
->sc_d
.np_bss_id
, pr
->r_data
, ETHER_ADDR_LEN
);
2827 case RAY_MIB_DES_INITED
:
2828 *pr
->r_data
= sc
->sc_d
.np_inited
;
2830 case RAY_MIB_DES_DEF_TXRATE
:
2831 *pr
->r_data
= sc
->sc_d
.np_def_txrate
;
2833 case RAY_MIB_DES_ENCRYPT
:
2834 *pr
->r_data
= sc
->sc_d
.np_encrypt
;
2836 case RAY_MIB_DES_NET_TYPE
:
2837 *pr
->r_data
= sc
->sc_d
.np_net_type
;
2839 case RAY_MIB_DES_SSID
:
2840 bcopy(sc
->sc_d
.np_ssid
, pr
->r_data
, IEEE80211_NWID_LEN
);
2842 case RAY_MIB_DES_PRIV_START
:
2843 *pr
->r_data
= sc
->sc_d
.np_priv_start
;
2845 case RAY_MIB_DES_PRIV_JOIN
:
2846 *pr
->r_data
= sc
->sc_d
.np_priv_join
;
2848 case RAY_MIB_CUR_AP_STATUS
:
2849 *pr
->r_data
= sc
->sc_c
.np_ap_status
;
2851 case RAY_MIB_CUR_PROMISC
:
2852 *pr
->r_data
= sc
->sc_c
.np_promisc
;
2854 case RAY_MIB_DES_AP_STATUS
:
2855 *pr
->r_data
= sc
->sc_d
.np_ap_status
;
2857 case RAY_MIB_DES_PROMISC
:
2858 *pr
->r_data
= sc
->sc_d
.np_promisc
;
2860 case RAY_MIB_CUR_FRAMING
:
2861 *pr
->r_data
= sc
->sc_c
.np_framing
;
2863 case RAY_MIB_DES_FRAMING
:
2864 *pr
->r_data
= sc
->sc_d
.np_framing
;
2871 pr
->r_failcause
= 0;
2872 if (sc
->sc_version
== RAY_ECFS_BUILD_4
)
2873 pr
->r_len
= mib_info
[pr
->r_paramid
][RAY_MIB_INFO_SIZ4
];
2874 else if (sc
->sc_version
== RAY_ECFS_BUILD_5
)
2875 pr
->r_len
= mib_info
[pr
->r_paramid
][RAY_MIB_INFO_SIZ5
];
2879 pr
->r_failcause
= 0;
2881 com
[ncom
++] = RAY_COM_MALLOC(ray_repparams
, RAY_COM_FWOK
);
2882 com
[ncom
-1]->c_pr
= pr
;
2884 RAY_COM_RUNQ(sc
, com
, ncom
, "rayrparm", error
);
2886 /* XXX no real error processing from anything yet! */
2887 if (!com
[0]->c_retval
&& pr
->r_failcause
)
2890 RAY_COM_FREE(com
, ncom
);
2896 * Runq entry to read the required parameter
2898 * The card and driver are happy for parameters to be read
2899 * whenever the card is plugged in
2902 ray_repparams(struct ray_softc
*sc
, struct ray_comq_entry
*com
)
2904 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
2910 ray_ccs_fill(sc
, com
->c_ccs
, RAY_CMD_REPORT_PARAMS
);
2911 SRAM_WRITE_FIELD_1(sc
, com
->c_ccs
,
2912 ray_cmd_report
, c_paramid
, com
->c_pr
->r_paramid
);
2913 SRAM_WRITE_FIELD_1(sc
, com
->c_ccs
, ray_cmd_report
, c_nparam
, 1);
2915 ray_com_ecf(sc
, com
);
2919 * Complete the parameter reporting
2922 ray_repparams_done(struct ray_softc
*sc
, u_int8_t status
, size_t ccs
)
2924 struct ray_comq_entry
*com
;
2926 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
2928 RAY_COM_CHECK(sc
, ccs
);
2930 RAY_CCSERR(sc
, status
, if_oerrors
); /* XXX error counter */
2932 com
= TAILQ_FIRST(&sc
->sc_comq
);
2933 com
->c_pr
->r_failcause
=
2934 SRAM_READ_FIELD_1(sc
, ccs
, ray_cmd_report
, c_failcause
);
2936 SRAM_READ_FIELD_1(sc
, ccs
, ray_cmd_report
, c_len
);
2937 SRAM_READ_REGION(sc
, RAY_ECF_TO_HOST_BASE
,
2938 com
->c_pr
->r_data
, com
->c_pr
->r_len
);
2940 ray_com_ecf_done(sc
);
2944 * User land entry (and exit) to the error counters
2947 ray_repstats_user(struct ray_softc
*sc
, struct ray_stats_req
*sr
)
2949 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
2951 sr
->rxoverflow
= sc
->sc_rxoverflow
;
2952 sr
->rxcksum
= sc
->sc_rxcksum
;
2953 sr
->rxhcksum
= sc
->sc_rxhcksum
;
2954 sr
->rxnoise
= sc
->sc_rxnoise
;
2960 * User land entry to parameter update changes
2962 * As a parameter change can cause the network parameters to be
2963 * invalid we have to re-start/join.
2966 ray_upparams_user(struct ray_softc
*sc
, struct ray_param_req
*pr
)
2968 struct ray_comq_entry
*com
[4];
2969 int error
, ncom
, todo
;
2970 #define RAY_UPP_SJ 0x1
2971 #define RAY_UPP_PARAMS 0x2
2973 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
2976 * Check that the parameter is available based on firmware version
2978 pr
->r_failcause
= 0;
2979 if (pr
->r_paramid
> RAY_MIB_LASTUSER
)
2981 if ((sc
->sc_version
== RAY_ECFS_BUILD_4
) &&
2982 !(mib_info
[pr
->r_paramid
][0] & RAY_V4
))
2984 if ((sc
->sc_version
== RAY_ECFS_BUILD_5
) &&
2985 !(mib_info
[pr
->r_paramid
][0] & RAY_V5
))
2989 * Handle certain parameters specially
2992 switch (pr
->r_paramid
) {
2993 case RAY_MIB_NET_TYPE
: /* Updated via START_NET JOIN_NET */
2994 sc
->sc_d
.np_net_type
= *pr
->r_data
;
2998 case RAY_MIB_SSID
: /* Updated via START_NET JOIN_NET */
2999 bcopy(pr
->r_data
, sc
->sc_d
.np_ssid
, IEEE80211_NWID_LEN
);
3003 case RAY_MIB_PRIVACY_MUST_START
:/* Updated via START_NET */
3004 if (sc
->sc_c
.np_net_type
!= RAY_MIB_NET_TYPE_ADHOC
)
3006 sc
->sc_d
.np_priv_start
= *pr
->r_data
;
3010 case RAY_MIB_PRIVACY_CAN_JOIN
: /* Updated via START_NET JOIN_NET */
3011 sc
->sc_d
.np_priv_join
= *pr
->r_data
;
3015 case RAY_MIB_BASIC_RATE_SET
:
3016 sc
->sc_d
.np_def_txrate
= *pr
->r_data
;
3017 todo
|= RAY_UPP_PARAMS
;
3020 case RAY_MIB_AP_STATUS
: /* Unsupported */
3021 case RAY_MIB_MAC_ADDR
: /* XXX Need interface up but could be done */
3022 case RAY_MIB_PROMISC
: /* BPF */
3027 todo
|= RAY_UPP_PARAMS
;
3033 * Generate the runq entries as needed
3036 if (todo
& RAY_UPP_PARAMS
) {
3037 com
[ncom
++] = RAY_COM_MALLOC(ray_upparams
, 0);
3038 com
[ncom
-1]->c_pr
= pr
;
3040 if (todo
& RAY_UPP_SJ
) {
3041 com
[ncom
++] = RAY_COM_MALLOC(ray_init_sj
, 0);
3042 com
[ncom
++] = RAY_COM_MALLOC(ray_init_auth
, 0);
3043 com
[ncom
++] = RAY_COM_MALLOC(ray_init_assoc
, 0);
3046 RAY_COM_RUNQ(sc
, com
, ncom
, "rayuparam", error
);
3048 /* XXX no real error processing from anything yet! */
3049 if (!com
[0]->c_retval
&& pr
->r_failcause
)
3052 RAY_COM_FREE(com
, ncom
);
3058 * Runq entry to update a parameter
3060 * The card and driver are happy for parameters to be updated
3061 * whenever the card is plugged in
3063 * XXX the above is a little bit of a lie until _download is sorted out and we
3064 * XXX keep local copies of things
3067 ray_upparams(struct ray_softc
*sc
, struct ray_comq_entry
*com
)
3069 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
3072 ray_ccs_fill(sc
, com
->c_ccs
, RAY_CMD_UPDATE_PARAMS
);
3074 SRAM_WRITE_FIELD_1(sc
, com
->c_ccs
,
3075 ray_cmd_update
, c_paramid
, com
->c_pr
->r_paramid
);
3076 SRAM_WRITE_FIELD_1(sc
, com
->c_ccs
, ray_cmd_update
, c_nparam
, 1);
3077 SRAM_WRITE_REGION(sc
, RAY_HOST_TO_ECF_BASE
,
3078 com
->c_pr
->r_data
, com
->c_pr
->r_len
);
3080 ray_com_ecf(sc
, com
);
3084 * Complete the parameter update, note that promisc finishes up here too
3087 ray_upparams_done(struct ray_softc
*sc
, u_int8_t status
, size_t ccs
)
3089 struct ray_comq_entry
*com
;
3091 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
3093 RAY_COM_CHECK(sc
, ccs
);
3095 RAY_CCSERR(sc
, status
, if_oerrors
); /* XXX error counter */
3097 com
= TAILQ_FIRST(&sc
->sc_comq
);
3099 switch (SRAM_READ_FIELD_1(sc
, ccs
, ray_cmd_update
, c_paramid
)) {
3101 case RAY_MIB_PROMISC
:
3102 sc
->sc_c
.np_promisc
= SRAM_READ_1(sc
, RAY_HOST_TO_ECF_BASE
);
3103 RAY_DPRINTF(sc
, RAY_DBG_IOCTL
,
3104 "promisc value %d", sc
->sc_c
.np_promisc
);
3108 com
->c_pr
->r_failcause
=
3109 SRAM_READ_FIELD_1(sc
, ccs
, ray_cmd_update
, c_failcause
);
3114 ray_com_ecf_done(sc
);
3118 * Command queuing and execution
3122 * Set up a comq entry struct
3124 static struct ray_comq_entry
*
3125 ray_com_init(struct ray_comq_entry
*com
, ray_comqfn_t function
, int flags
, char *mesg
)
3127 com
->c_function
= function
;
3128 com
->c_flags
= flags
;
3131 com
->c_wakeup
= NULL
;
3139 * Malloc and set up a comq entry struct
3141 static struct ray_comq_entry
*
3142 ray_com_malloc(ray_comqfn_t function
, int flags
, char *mesg
)
3144 struct ray_comq_entry
*com
;
3146 MALLOC(com
, struct ray_comq_entry
*,
3147 sizeof(struct ray_comq_entry
), M_RAYCOM
, M_WAITOK
);
3149 return (ray_com_init(com
, function
, flags
, mesg
));
3153 * Add an array of commands to the runq, get some ccs's for them and
3154 * then run, waiting on the last command.
3156 * We add the commands to the queue first to preserve ioctl ordering.
3158 * On recoverable errors, this routine removes the entries from the
3159 * runq. A caller can requeue the commands (and still preserve its own
3160 * processes ioctl ordering) but doesn't have to. When the card is
3161 * detached we get out quickly to prevent panics and don't bother
3165 ray_com_runq_add(struct ray_softc
*sc
, struct ray_comq_entry
*com
[], int ncom
, char *wmesg
)
3169 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_COM
, "");
3173 * Add the commands to the runq but don't let it run until
3174 * the ccs's are allocated successfully
3176 com
[0]->c_flags
|= RAY_COM_FWAIT
;
3177 for (i
= 0; i
< ncom
; i
++) {
3178 com
[i
]->c_wakeup
= com
[ncom
-1];
3179 RAY_DPRINTF(sc
, RAY_DBG_COM
, "adding %p", com
[i
]);
3180 RAY_DCOM(sc
, RAY_DBG_DCOM
, com
[i
], "adding");
3181 TAILQ_INSERT_TAIL(&sc
->sc_comq
, com
[i
], c_chain
);
3183 com
[ncom
-1]->c_flags
|= RAY_COM_FWOK
;
3186 * Allocate ccs's for each command.
3188 for (i
= 0; i
< ncom
; i
++) {
3189 error
= ray_ccs_alloc(sc
, &com
[i
]->c_ccs
, wmesg
);
3197 * Allow the queue to run and sleep if needed.
3199 * Iff the FDETACHED flag is set in the com entry we waited on
3200 * the driver is in a zombie state! The softc structure has been
3201 * freed by the generic bus detach methods - eek. We tread very
3204 com
[0]->c_flags
&= ~RAY_COM_FWAIT
;
3206 if (TAILQ_FIRST(&sc
->sc_comq
) != NULL
) {
3207 RAY_DPRINTF(sc
, RAY_DBG_COM
, "sleeping");
3208 error
= tsleep(com
[ncom
-1], PCATCH
, wmesg
, 0);
3209 if (com
[ncom
-1]->c_flags
& RAY_COM_FDETACHED
)
3211 RAY_DPRINTF(sc
, RAY_DBG_COM
,
3212 "awakened, tsleep returned 0x%x", error
);
3218 * Only clean the queue on real errors - we don't care about it
3219 * when we detach as the queue entries are freed by the callers.
3221 if (error
&& (error
!= ENXIO
))
3222 for (i
= 0; i
< ncom
; i
++)
3223 if (!(com
[i
]->c_flags
& RAY_COM_FCOMPLETED
)) {
3224 RAY_DPRINTF(sc
, RAY_DBG_COM
, "removing %p",
3226 RAY_DCOM(sc
, RAY_DBG_DCOM
, com
[i
], "removing");
3227 TAILQ_REMOVE(&sc
->sc_comq
, com
[i
], c_chain
);
3228 ray_ccs_free(sc
, com
[i
]->c_ccs
);
3229 com
[i
]->c_ccs
= NULL
;
3236 * Run the command at the head of the queue (if not already running)
3239 ray_com_runq(struct ray_softc
*sc
)
3241 struct ray_comq_entry
*com
;
3243 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_COM
, "");
3245 com
= TAILQ_FIRST(&sc
->sc_comq
);
3246 if ((com
== NULL
) ||
3247 (com
->c_flags
& RAY_COM_FRUNNING
) ||
3248 (com
->c_flags
& RAY_COM_FWAIT
) ||
3249 (com
->c_flags
& RAY_COM_FDETACHED
))
3252 com
->c_flags
|= RAY_COM_FRUNNING
;
3253 RAY_DPRINTF(sc
, RAY_DBG_COM
, "running %p", com
);
3254 RAY_DCOM(sc
, RAY_DBG_DCOM
, com
, "running");
3255 com
->c_function(sc
, com
);
3259 * Remove run command, free ccs and wakeup caller.
3261 * Minimal checks are done here as we ensure that the com and command
3262 * handler were matched up earlier. Must be called at splnet or higher
3263 * so that entries on the command queue are correctly removed.
3265 * Remove the com from the comq, and wakeup the caller if it requested
3266 * to be woken. This is used for ensuring a sequence of commands
3267 * completes. Finally, re-run the queue.
3270 ray_com_runq_done(struct ray_softc
*sc
)
3272 struct ray_comq_entry
*com
;
3274 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_COM
, "");
3276 com
= TAILQ_FIRST(&sc
->sc_comq
); /* XXX shall we check this as below */
3277 RAY_DPRINTF(sc
, RAY_DBG_COM
, "removing %p", com
);
3278 RAY_DCOM(sc
, RAY_DBG_DCOM
, com
, "removing");
3279 TAILQ_REMOVE(&sc
->sc_comq
, com
, c_chain
);
3281 com
->c_flags
&= ~RAY_COM_FRUNNING
;
3282 com
->c_flags
|= RAY_COM_FCOMPLETED
;
3284 ray_ccs_free(sc
, com
->c_ccs
);
3287 if (com
->c_flags
& RAY_COM_FWOK
)
3288 wakeup(com
->c_wakeup
);
3292 /* XXX what about error on completion then? deal with when i fix
3293 * XXX the status checking
3295 * XXX all the runq_done calls from IFF_RUNNING checks in runq
3296 * XXX routines should return EIO but shouldn't abort the runq
3301 * Send a command to the ECF.
3304 ray_com_ecf(struct ray_softc
*sc
, struct ray_comq_entry
*com
)
3308 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_COM
, "");
3311 while (!RAY_ECF_READY(sc
)) {
3312 DELAY(RAY_ECF_SPIN_DELAY
);
3313 if (++i
> RAY_ECF_SPIN_TRIES
)
3314 RAY_PANIC(sc
, "spun too long");
3317 RAY_RECERR(sc
, "spun %d times", i
);
3319 RAY_DPRINTF(sc
, RAY_DBG_COM
, "sending %p", com
);
3320 RAY_DCOM(sc
, RAY_DBG_DCOM
, com
, "sending");
3321 SRAM_WRITE_1(sc
, RAY_SCB_CCSI
, RAY_CCS_INDEX(com
->c_ccs
));
3322 RAY_ECF_START_CMD(sc
);
3324 if (RAY_COM_NEEDS_TIMO(
3325 SRAM_READ_FIELD_1(sc
, com
->c_ccs
, ray_cmd
, c_cmd
))) {
3326 RAY_DPRINTF(sc
, RAY_DBG_COM
, "adding timeout");
3327 callout_reset(&sc
->com_timer
, RAY_COM_TIMEOUT
,
3328 ray_com_ecf_timo
, sc
);
3333 * Deal with commands that require a timeout to test completion.
3335 * This routine is coded to only expect one outstanding request for the
3336 * timed out requests at a time, but thats all that can be outstanding
3337 * per hardware limitations and all that we issue anyway.
3339 * We don't do any fancy testing of the command currently issued as we
3340 * know it must be a timeout based one...unless I've got this wrong!
3343 ray_com_ecf_timo(void *xsc
)
3345 struct ray_softc
*sc
= (struct ray_softc
*)xsc
;
3346 struct ray_comq_entry
*com
;
3347 u_int8_t cmd
, status
;
3349 lwkt_serialize_enter(sc
->arpcom
.ac_if
.if_serializer
);
3350 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_COM
, "");
3353 com
= TAILQ_FIRST(&sc
->sc_comq
);
3355 cmd
= SRAM_READ_FIELD_1(sc
, com
->c_ccs
, ray_cmd
, c_cmd
);
3356 status
= SRAM_READ_FIELD_1(sc
, com
->c_ccs
, ray_cmd
, c_status
);
3359 case RAY_CCS_STATUS_COMPLETE
:
3360 case RAY_CCS_STATUS_FREE
: /* Buggy firmware */
3361 ray_intr_ccs(sc
, cmd
, status
, com
->c_ccs
);
3364 case RAY_CCS_STATUS_BUSY
:
3365 callout_reset(&sc
->com_timer
, RAY_COM_TIMEOUT
,
3366 ray_com_ecf_timo
, sc
);
3369 default: /* Replicates NetBSD */
3370 if (sc
->sc_ccsinuse
[RAY_CCS_INDEX(com
->c_ccs
)] == 1) {
3371 /* give a chance for the interrupt to occur */
3372 sc
->sc_ccsinuse
[RAY_CCS_INDEX(com
->c_ccs
)] = 2;
3373 callout_reset(&sc
->com_timer
, RAY_COM_TIMEOUT
,
3374 ray_com_ecf_timo
, sc
);
3376 ray_intr_ccs(sc
, cmd
, status
, com
->c_ccs
);
3380 lwkt_serialize_exit(sc
->arpcom
.ac_if
.if_serializer
);
3384 * Called when interrupt handler for the command has done all it
3385 * needs to. Will be called at splnet.
3388 ray_com_ecf_done(struct ray_softc
*sc
)
3390 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_COM
, "");
3392 callout_stop(&sc
->com_timer
);
3394 ray_com_runq_done(sc
);
3397 #if RAY_DEBUG & RAY_DBG_COM
3399 * Process completed ECF commands that probably came from the command queue
3401 * This routine is called after vectoring the completed ECF command
3402 * to the appropriate _done routine. It helps check everything is okay.
3405 ray_com_ecf_check(struct ray_softc
*sc
, size_t ccs
, char *mesg
)
3407 struct ray_comq_entry
*com
;
3409 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_COM
, "%s", mesg
);
3411 com
= TAILQ_FIRST(&sc
->sc_comq
);
3414 RAY_PANIC(sc
, "no command queue");
3415 if (com
->c_ccs
!= ccs
)
3416 RAY_PANIC(sc
, "ccs's don't match");
3418 #endif /* RAY_DEBUG & RAY_DBG_COM */
3425 * Obtain a ccs for a commmand
3427 * Returns 0 and in `ccsp' the bus offset of the free ccs. Will block
3428 * awaiting free ccs if needed - if the sleep is interrupted
3429 * EINTR/ERESTART is returned, if the card is ejected we return ENXIO.
3432 ray_ccs_alloc(struct ray_softc
*sc
, size_t *ccsp
, char *wmesg
)
3438 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_CCS
, "");
3442 for (i
= RAY_CCS_CMD_FIRST
; i
<= RAY_CCS_CMD_LAST
; i
++) {
3443 /* we probe here to make the card go */
3444 SRAM_READ_FIELD_1(sc
, RAY_CCS_ADDRESS(i
), ray_cmd
,
3446 if (!sc
->sc_ccsinuse
[i
])
3449 if (i
> RAY_CCS_CMD_LAST
) {
3450 RAY_DPRINTF(sc
, RAY_DBG_CCS
, "sleeping");
3451 error
= tsleep(ray_ccs_alloc
, PCATCH
, wmesg
, 0);
3452 if ((sc
== NULL
) || (sc
->sc_gone
))
3454 RAY_DPRINTF(sc
, RAY_DBG_CCS
,
3455 "awakened, tsleep returned 0x%x", error
);
3461 RAY_DPRINTF(sc
, RAY_DBG_CCS
, "allocated 0x%02x", i
);
3462 sc
->sc_ccsinuse
[i
] = 1;
3463 ccs
= RAY_CCS_ADDRESS(i
);
3470 * Fill the easy bits in of a pre-allocated CCS
3473 ray_ccs_fill(struct ray_softc
*sc
, size_t ccs
, u_int cmd
)
3475 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_CCS
, "");
3479 RAY_PANIC(sc
, "ccs not allocated");
3481 SRAM_WRITE_FIELD_1(sc
, ccs
, ray_cmd
, c_status
, RAY_CCS_STATUS_BUSY
);
3482 SRAM_WRITE_FIELD_1(sc
, ccs
, ray_cmd
, c_cmd
, cmd
);
3483 SRAM_WRITE_FIELD_1(sc
, ccs
, ray_cmd
, c_link
, RAY_CCS_LINK_NULL
);
3487 * Free up a ccs allocated via ray_ccs_alloc
3489 * Return the old status. This routine is only used for ccs allocated via
3490 * ray_ccs_alloc (not tx, rx or ECF command requests).
3493 ray_ccs_free(struct ray_softc
*sc
, size_t ccs
)
3495 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_CCS
, "");
3498 #if 1 | (RAY_DEBUG & RAY_DBG_CCS)
3499 if (!sc
->sc_ccsinuse
[RAY_CCS_INDEX(ccs
)])
3500 RAY_RECERR(sc
, "freeing free ccs 0x%02x", RAY_CCS_INDEX(ccs
));
3501 #endif /* RAY_DEBUG & RAY_DBG_CCS */
3503 RAY_CCS_FREE(sc
, ccs
);
3504 sc
->sc_ccsinuse
[RAY_CCS_INDEX(ccs
)] = 0;
3505 RAY_DPRINTF(sc
, RAY_DBG_CCS
, "freed 0x%02x", RAY_CCS_INDEX(ccs
));
3506 wakeup(ray_ccs_alloc
);
3510 * Obtain a ccs and tx buffer to transmit with and fill them in.
3512 * Returns 0 and in `ccsp' the bus offset of the free ccs. Will not block
3513 * and if none available and will returns EAGAIN.
3515 * The caller must fill in the length later.
3516 * The caller must clear the ccs on errors.
3519 ray_ccs_tx(struct ray_softc
*sc
, size_t *ccsp
, size_t *bufpp
)
3525 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_CCS
, "");
3528 i
= RAY_CCS_TX_FIRST
;
3530 status
= SRAM_READ_FIELD_1(sc
, RAY_CCS_ADDRESS(i
),
3532 if (status
== RAY_CCS_STATUS_FREE
)
3535 } while (i
<= RAY_CCS_TX_LAST
);
3536 if (i
> RAY_CCS_TX_LAST
) {
3539 RAY_DPRINTF(sc
, RAY_DBG_CCS
, "allocated 0x%02x", i
);
3542 * Reserve and fill the ccs - must do the length later.
3544 * Even though build 4 and build 5 have different fields all these
3545 * are common apart from tx_rate. Neither the NetBSD driver or Linux
3546 * driver bother to overwrite this for build 4 cards.
3548 * The start of the buffer must be aligned to a 256 byte boundary
3549 * (least significant byte of address = 0x00).
3551 ccs
= RAY_CCS_ADDRESS(i
);
3552 bufp
= RAY_TX_BASE
+ i
* RAY_TX_BUF_SIZE
;
3553 bufp
+= sc
->sc_tibsize
;
3554 SRAM_WRITE_FIELD_1(sc
, ccs
, ray_cmd_tx
, c_status
, RAY_CCS_STATUS_BUSY
);
3555 SRAM_WRITE_FIELD_1(sc
, ccs
, ray_cmd_tx
, c_cmd
, RAY_CMD_TX_REQ
);
3556 SRAM_WRITE_FIELD_1(sc
, ccs
, ray_cmd_tx
, c_link
, RAY_CCS_LINK_NULL
);
3557 SRAM_WRITE_FIELD_2(sc
, ccs
, ray_cmd_tx
, c_bufp
, bufp
);
3558 SRAM_WRITE_FIELD_1(sc
,
3559 ccs
, ray_cmd_tx
, c_tx_rate
, sc
->sc_c
.np_def_txrate
);
3560 SRAM_WRITE_FIELD_1(sc
, ccs
, ray_cmd_tx
, c_apm_mode
, 0);
3561 bufp
+= sizeof(struct ray_tx_phy_header
);
3569 * Routines to obtain resources for the card
3573 * Allocate the attribute memory on the card
3575 * The attribute memory space is abused by these devices as IO space. As such
3576 * the OS card services don't have a chance of knowing that they need to keep
3577 * the attribute space mapped. We have to do it manually.
3580 ray_res_alloc_am(struct ray_softc
*sc
)
3584 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_CM
, "");
3586 sc
->am_rid
= RAY_AM_RID
;
3587 sc
->am_res
= bus_alloc_resource(sc
->dev
, SYS_RES_MEMORY
,
3588 &sc
->am_rid
, 0UL, ~0UL, 0x1000, RF_ACTIVE
);
3590 RAY_PRINTF(sc
, "Cannot allocate attribute memory");
3593 error
= CARD_SET_MEMORY_OFFSET(device_get_parent(sc
->dev
), sc
->dev
,
3594 sc
->am_rid
, 0, NULL
);
3596 RAY_PRINTF(sc
, "CARD_SET_MEMORY_OFFSET returned 0x%0x", error
);
3599 error
= CARD_SET_RES_FLAGS(device_get_parent(sc
->dev
), sc
->dev
,
3600 SYS_RES_MEMORY
, sc
->am_rid
, PCCARD_A_MEM_ATTR
);
3602 RAY_PRINTF(sc
, "CARD_SET_RES_FLAGS returned 0x%0x", error
);
3605 error
= CARD_SET_RES_FLAGS(device_get_parent(sc
->dev
), sc
->dev
,
3606 SYS_RES_MEMORY
, sc
->am_rid
, PCCARD_A_MEM_8BIT
);
3608 RAY_PRINTF(sc
, "CARD_SET_RES_FLAGS returned 0x%0x", error
);
3611 sc
->am_bsh
= rman_get_bushandle(sc
->am_res
);
3612 sc
->am_bst
= rman_get_bustag(sc
->am_res
);
3614 #if RAY_DEBUG & (RAY_DBG_CM | RAY_DBG_BOOTPARAM)
3618 CARD_GET_RES_FLAGS(device_get_parent(sc
->dev
), sc
->dev
,
3619 SYS_RES_MEMORY
, sc
->am_rid
, &flags
);
3620 CARD_GET_MEMORY_OFFSET(device_get_parent(sc
->dev
), sc
->dev
,
3621 sc
->am_rid
, &offset
);
3622 RAY_PRINTF(sc
, "allocated attribute memory:\n"
3623 ". start 0x%0lx count 0x%0lx flags 0x%0lx offset 0x%0x",
3624 bus_get_resource_start(sc
->dev
, SYS_RES_MEMORY
, sc
->am_rid
),
3625 bus_get_resource_count(sc
->dev
, SYS_RES_MEMORY
, sc
->am_rid
),
3628 #endif /* RAY_DEBUG & (RAY_DBG_CM | RAY_DBG_BOOTPARAM) */
3634 * Allocate the common memory on the card
3636 * As this memory is described in the CIS, the OS card services should
3637 * have set the map up okay, but the card uses 8 bit RAM. This is not
3638 * described in the CIS.
3641 ray_res_alloc_cm(struct ray_softc
*sc
)
3643 u_long start
, count
, end
;
3646 RAY_DPRINTF(sc
, RAY_DBG_SUBR
| RAY_DBG_CM
, "");
3648 RAY_DPRINTF(sc
,RAY_DBG_CM
| RAY_DBG_BOOTPARAM
,
3649 "cm start 0x%0lx count 0x%0lx",
3650 bus_get_resource_start(sc
->dev
, SYS_RES_MEMORY
, RAY_CM_RID
),
3651 bus_get_resource_count(sc
->dev
, SYS_RES_MEMORY
, RAY_CM_RID
));
3653 sc
->cm_rid
= RAY_CM_RID
;
3654 start
= bus_get_resource_start(sc
->dev
, SYS_RES_MEMORY
, sc
->cm_rid
);
3655 count
= bus_get_resource_count(sc
->dev
, SYS_RES_MEMORY
, sc
->cm_rid
);
3656 end
= start
+ count
- 1;
3657 sc
->cm_res
= bus_alloc_resource(sc
->dev
, SYS_RES_MEMORY
,
3658 &sc
->cm_rid
, start
, end
, count
, RF_ACTIVE
);
3660 RAY_PRINTF(sc
, "Cannot allocate common memory");
3663 error
= CARD_SET_MEMORY_OFFSET(device_get_parent(sc
->dev
), sc
->dev
,
3664 sc
->cm_rid
, 0, NULL
);
3666 RAY_PRINTF(sc
, "CARD_SET_MEMORY_OFFSET returned 0x%0x", error
);
3669 error
= CARD_SET_RES_FLAGS(device_get_parent(sc
->dev
), sc
->dev
,
3670 SYS_RES_MEMORY
, sc
->cm_rid
, PCCARD_A_MEM_COM
);
3672 RAY_PRINTF(sc
, "CARD_SET_RES_FLAGS returned 0x%0x", error
);
3675 error
= CARD_SET_RES_FLAGS(device_get_parent(sc
->dev
), sc
->dev
,
3676 SYS_RES_MEMORY
, sc
->cm_rid
, PCCARD_A_MEM_8BIT
);
3678 RAY_PRINTF(sc
, "CARD_SET_RES_FLAGS returned 0x%0x", error
);
3681 sc
->cm_bsh
= rman_get_bushandle(sc
->cm_res
);
3682 sc
->cm_bst
= rman_get_bustag(sc
->cm_res
);
3684 #if RAY_DEBUG & (RAY_DBG_CM | RAY_DBG_BOOTPARAM)
3688 CARD_GET_RES_FLAGS(device_get_parent(sc
->dev
), sc
->dev
,
3689 SYS_RES_MEMORY
, sc
->cm_rid
, &flags
);
3690 CARD_GET_MEMORY_OFFSET(device_get_parent(sc
->dev
), sc
->dev
,
3691 sc
->cm_rid
, &offset
);
3692 RAY_PRINTF(sc
, "allocated common memory:\n"
3693 ". start 0x%0lx count 0x%0lx flags 0x%0lx offset 0x%0x",
3694 bus_get_resource_start(sc
->dev
, SYS_RES_MEMORY
, sc
->cm_rid
),
3695 bus_get_resource_count(sc
->dev
, SYS_RES_MEMORY
, sc
->cm_rid
),
3698 #endif /* RAY_DEBUG & (RAY_DBG_CM | RAY_DBG_BOOTPARAM) */
3704 * Get an irq and attach it to the bus
3707 ray_res_alloc_irq(struct ray_softc
*sc
)
3711 RAY_DPRINTF(sc
, RAY_DBG_SUBR
, "");
3713 RAY_DPRINTF(sc
,RAY_DBG_CM
| RAY_DBG_BOOTPARAM
,
3714 "irq start 0x%0lx count 0x%0lx",
3715 bus_get_resource_start(sc
->dev
, SYS_RES_IRQ
, 0),
3716 bus_get_resource_count(sc
->dev
, SYS_RES_IRQ
, 0));
3719 sc
->irq_res
= bus_alloc_resource_any(sc
->dev
, SYS_RES_IRQ
,
3720 &sc
->irq_rid
, RF_ACTIVE
);
3722 RAY_PRINTF(sc
, "Cannot allocate irq");
3725 error
= bus_setup_intr(sc
->dev
, sc
->irq_res
, INTR_NETSAFE
,
3726 ray_intr
, sc
, &sc
->irq_handle
,
3727 sc
->arpcom
.ac_if
.if_serializer
);
3729 RAY_PRINTF(sc
, "Failed to setup irq");
3732 RAY_DPRINTF(sc
, RAY_DBG_CM
| RAY_DBG_BOOTPARAM
, "allocated irq:\n"
3733 ". start 0x%0lx count 0x%0lx",
3734 bus_get_resource_start(sc
->dev
, SYS_RES_IRQ
, sc
->irq_rid
),
3735 bus_get_resource_count(sc
->dev
, SYS_RES_IRQ
, sc
->irq_rid
));
3741 * Release all of the card's resources
3744 ray_res_release(struct ray_softc
*sc
)
3746 if (sc
->irq_res
!= 0) {
3747 bus_teardown_intr(sc
->dev
, sc
->irq_res
, sc
->irq_handle
);
3748 bus_release_resource(sc
->dev
, SYS_RES_IRQ
,
3749 sc
->irq_rid
, sc
->irq_res
);
3752 if (sc
->am_res
!= 0) {
3753 bus_release_resource(sc
->dev
, SYS_RES_MEMORY
,
3754 sc
->am_rid
, sc
->am_res
);
3757 if (sc
->cm_res
!= 0) {
3758 bus_release_resource(sc
->dev
, SYS_RES_MEMORY
,
3759 sc
->cm_rid
, sc
->cm_res
);
3767 #if RAY_DEBUG & RAY_DBG_MBUF
3769 ray_dump_mbuf(struct ray_softc
*sc
, struct mbuf
*m
, char *s
)
3775 RAY_PRINTF(sc
, "%s", s
);
3776 RAY_PRINTF(sc
, "\nm0->data\t0x%p\nm_pkthdr.len\t%d\nm_len\t%d",
3777 mtod(m
, u_int8_t
*), m
->m_pkthdr
.len
, m
->m_len
);
3780 for (; m
; m
= m
->m_next
) {
3781 d
= mtod(m
, u_int8_t
*);
3784 for (; d
< ed
; i
++, d
++) {
3785 if ((i
% 16) == 0) {
3786 kprintf(" %s\n\t", p
);
3787 } else if ((i
% 8) == 0)
3789 kprintf(" %02x", *d
);
3790 p
[i
% 16] = ((*d
>= 0x20) && (*d
< 0x80)) ? *d
: '.';
3794 kprintf(" %s\n", p
);
3796 #endif /* RAY_DEBUG & RAY_DBG_MBUF */