2000-02-20 14:56:17 +00:00
/*
* Copyright ( C ) 2000
* Dr . Duncan McLennan Barclay , dmlb @ ragnet . demon . co . uk .
*
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. Neither the name of the author nor the names of any co - contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY DUNCAN BARCLAY AND CONTRIBUTORS ` ` AS IS ' ' AND
* ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL DUNCAN BARCLAY OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
* DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
* LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE .
*
2000-03-08 23:28:06 +00:00
* $ Id : if_ray . c , v 1.8 2000 / 03 / 08 08 : 53 : 36 dmlb Exp $
2000-02-20 14:56:17 +00:00
*
*/
2000-03-08 23:28:06 +00:00
/* $NetBSD: if_ray.c,v 1.12 2000/02/07 09:36:27 augustss Exp $ */
/*
* Copyright ( c ) 2000 Christian E . Hopps
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. Neither the name of the author nor the names of any co - contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ` ` AS IS ' ' AND
* ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
* DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
* LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE .
*/
2000-03-05 14:39:23 +00:00
/*
*
* Card configuration
* = = = = = = = = = = = = = = = = = =
*
* This card is unusual in that it uses both common and attribute
* memory whilst working . The - stable versions of FreeBSD have a real
* problem managing and setting up the correct memory maps . This
* driver should reset the memory maps correctly under PAO and non - PAO
* - stable systems . Work is in hand to fix these problems for - current .
*
* So , if you want to use this driver make sure that
* options RAY_NEED_CM_FIXUP
* options RAY_NEED_CM_REMAPPING
* are in your kernel configuration file .
*
* The first fixes the brain deadness of pccardd ( where it reads the
* CIS for common memory , sets it all up and then throws it all away
2000-03-05 22:24:30 +00:00
* assuming the card is an ed driver . . . ) . Note that this could be
* dangerous ( because it doesn ' t interact with pccardd ) if you
* use other memory mapped cards at the same time .
2000-03-05 14:39:23 +00:00
*
* The second option ensures that common memory is remapped whenever
* we are going to access it ( we can ' t just do it once , as something
* like pccardd may have read the attribute memory and pccard . c
* doesn ' t re - map the last active window - it remaps the last
* non - active window . . . ) .
*
*
* Ad - hoc and infra - structure modes
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*
* At present only the ad - hoc mode is being worked on .
*
* Apart from just writing the code for infrastructure mode I have a
* few concerns about both the Linux and NetBSD drivers in this area .
* They don ' t seem to differentiate between the MAC address of the AP
* and the BSS_ID of the network . I presume this is handled when
* joining a managed n / w and the network parameters are updated , but
* I ' m not sure . How does this interact with ARP ? For mobility we want
* to be able to move around without worrying about which AP we are
* actually talking to - we should always talk to the BSS_ID .
*
* The Linux driver also seems to have the capability to act as an AP .
* I wonder what facilities the " AP " can provide within a driver ? We can
* probably use the BRIDGE code to form an ESS but I don ' t think
* power saving etc . is easy .
*
*
* Packet translation / encapsulation
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*
* Currently we only support the Webgear encapsulation
* 802.11 header < net / if_ieee80211 . h > struct ieee80211_header
* 802.3 header < net / ethernet . h > struct ether_header
* 802.2 LLC header
* 802.2 SNAP header
*
* We should support whatever packet types the following drivers have
* if_wi . c FreeBSD , RFC1042
* if_ray . c NetBSD Webgear , RFC1042
* rayctl . c Linux Webgear , RFC1042
* also whatever we can divine from the NDC Access points and Kanda ' s boxes .
*
* Most drivers appear to have a RFC1042 translation . The incoming packet is
* 802.11 header < net / if_ieee80211 . h > struct ieee80211_header
* 802.2 LLC header
* 802.2 SNAP header
*
* This is translated to
* 802.3 header < net / ethernet . h > struct ether_header
* 802.2 LLC header
* 802.2 SNAP header
*
* Linux seems to look at the SNAP org_code and do some translations
* for IPX and APPLEARP on that . This just may be how Linux does IPX
* and NETATALK . Need to see how FreeBSD does these .
*
* Translation should be selected via if_media stuff or link types .
*/
/*
* TODO
*
2000-03-05 22:24:30 +00:00
* _stop - mostly done
2000-03-08 23:28:06 +00:00
* would be nice to understand shutdown / or power save to prevent RX
2000-03-05 22:24:30 +00:00
* _reset - done
* just needs calling in the right places
2000-03-08 23:28:06 +00:00
* converted panics to resets - when tx packets are the wrong length
2000-03-05 22:24:30 +00:00
* may be needed in a couple of other places when I do more commands
* havenet - mostly done
* i think i ' ve got all the places to set it right , but not so sure
* we reset it in all the right places
* _unload - done
* recreated most of stop but as card is unplugged don ' t try and
2000-03-09 21:34:47 +00:00
* access it to turn it off
2000-03-08 23:28:06 +00:00
* TX bpf - done
* RX bpf - done
* I would much prefer to have the complete 802.11 packet dropped to
* the bpf tap and then have a user land program parse the headers
* as needed . This way , tcpdump - w can be used to grab the raw data . If
* needed the 802.11 aware program can " translate " the .11 to ethernet
* for tcpdump - r
2000-03-09 21:34:47 +00:00
* use std timeout code for download - done
* was mainly moving a call and removing a load of stuff in
* download_done as it duplicates check_ccs and ccs_done
* promisoius - done
2000-03-12 22:54:29 +00:00
* add the start_join_net - done
* i needed it anyway
* remove startccs and startcmd - done
* as those were used for the NetBSD start timeout
* multicast - done but UNTESTED
* I don ' t have the ability / facilty to test this
* rxlevel - done
* stats reported via raycontrol
* getparams ioctl - done
* reported via raycontrol
* start_join_done needs a restart in download_done - done
* now use netbsd style start up
2000-03-21 14:27:46 +00:00
* ioctls - done
* use raycontrol
* translation , BSS_ID , countrycode , changing mode
2000-03-08 23:28:06 +00:00
*
* shutdown
2000-03-05 14:39:23 +00:00
* ifp - > if_hdr length
2000-03-12 22:54:29 +00:00
* _reset - check where needed
2000-03-05 14:39:23 +00:00
* apm
* faster TX routine
* more translations
2000-03-08 23:28:06 +00:00
* infrastructure mode - maybe need some of the old stuff for checking ?
2000-03-05 14:39:23 +00:00
* differeniate between parameters set in attach and init
* spinning in ray_issue_cmd
2000-03-08 23:28:06 +00:00
* fix the XXX code in start_join_done
* make RAY_DEBUG a knob somehow - either sysctl or IFF_DEBUG
2000-03-21 14:27:46 +00:00
* ray_update_params_done needs work
* do an rx level and antenna cache , the antenna can be used to set c_antenna
* for tx
* callout handles need rationalising . can probably remove timerh and
* use ccs_timerh for download and sj_timerh
2000-03-05 14:39:23 +00:00
*/
2000-02-27 19:52:29 +00:00
# define XXX 0
2000-03-08 23:28:06 +00:00
# define XXX_NETBSDTX 0
# define XXX_PROM 0
2000-02-20 14:56:17 +00:00
2000-02-26 14:49:24 +00:00
/*
* XXX build options - move to LINT
*/
2000-03-05 14:39:23 +00:00
/*
* RAY_DEBUG settings
*
* 2 Recoverable error ' s
* 6 Subroutine entry
* 11 Startup CM dump
2000-03-11 13:25:33 +00:00
* 16 State transitions for start / join
2000-03-05 14:39:23 +00:00
* 21 CCS info
* 31 IOCTL calls
* 51 MBUFs dumped / packet types reported
*/
2000-03-08 08:53:36 +00:00
# ifndef RAY_DEBUG
2000-03-12 22:54:29 +00:00
# define RAY_DEBUG 2
2000-03-08 08:53:36 +00:00
# endif
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
# define RAY_CCS_TIMEOUT (hz / 2) /* Timeout for CCS commands */
# define RAY_CHECK_SCHED_TIMEOUT (hz) /* Time to wait until command retry, should be > RAY_CCS_TIMEOUT */
2000-03-05 14:39:23 +00:00
2000-02-27 19:52:29 +00:00
# define RAY_NEED_STARTJOIN_TIMO 0 /* Might be needed with build 4 */
# define RAY_SJ_TIMEOUT (90*hz) /* Timeout for failing STARTJOIN commands - only used with RAY_NEED_STARTJOIN_TIMO */
2000-03-05 14:39:23 +00:00
# define RAY_NEED_CM_FIXUP 1 /* Needed until pccardd hacks for ed drivers are removed (pccardd forces 16bit memory and 0x4000 size) THIS IS A DANGEROUS THING TO USE IF YOU USE OTHER MEMORY MAPPED PCCARDS */
2000-02-27 19:52:29 +00:00
# define RAY_NEED_CM_REMAPPING 1 /* Needed until pccard maps more than one memory area */
2000-03-05 14:39:23 +00:00
2000-03-05 22:24:30 +00:00
# define RAY_RESET_TIMEOUT (5*hz) /* Timeout for resetting the card */
2000-03-08 23:28:06 +00:00
# define RAY_USE_CALLOUT_STOP 0 /* Set for kernels with callout_stop function - 3.3 and above */
2000-03-05 22:24:30 +00:00
# define RAY_SIMPLE_TX 1 /* Simple TX routine */
# define RAY_DECENT_TX 0 /* Decent TX routine - tbd */
2000-02-26 14:49:24 +00:00
/*
* XXX build options - move to LINT
*/
/*
* Debugging odds and odds
*/
2000-02-20 14:56:17 +00:00
# ifndef RAY_DEBUG
2000-02-26 14:49:24 +00:00
# define RAY_DEBUG 0
2000-02-20 14:56:17 +00:00
# endif /* RAY_DEBUG */
2000-02-26 14:49:24 +00:00
# if RAY_DEBUG > 0
2000-02-27 19:52:29 +00:00
2000-03-05 14:39:23 +00:00
/* XXX This macro assumes that common memory is mapped into kernel space and
* XXX does not indirect through SRAM macros - it should
*/
2000-02-26 14:49:24 +00:00
# define RAY_DHEX8(p, l) do { if (RAY_DEBUG > 10) { \
2000-02-20 14:56:17 +00:00
u_int8_t * i ; \
2000-02-26 14:49:24 +00:00
for ( i = p ; i < ( u_int8_t * ) ( p + l ) ; i + = 8 ) \
printf ( " 0x%08lx %8D \n " , \
( unsigned long ) i , ( unsigned char * ) i , " " ) ; \
} } while ( 0 )
2000-02-27 19:52:29 +00:00
2000-03-05 14:39:23 +00:00
# define RAY_DPRINTFN(l, x) do { if (RAY_DEBUG > l) { \
2000-02-26 14:49:24 +00:00
printf x ; \
2000-02-27 19:52:29 +00:00
} } while ( 0 )
2000-03-21 14:39:36 +00:00
# define RAY_DNET_DUMP(sc, s) do { if (RAY_DEBUG > 15) { \
2000-03-11 13:25:33 +00:00
printf ( " ray%d: Current network parameters%s \n " , ( sc ) - > unit , ( s ) ) ; \
printf ( " bss_id %6D \n " , ( sc ) - > sc_c . np_bss_id , " : " ) ; \
printf ( " inited 0x%02x \n " , ( sc ) - > sc_c . np_inited ) ; \
printf ( " def_txrate 0x%02x \n " , ( sc ) - > sc_c . np_def_txrate ) ; \
printf ( " encrypt 0x%02x \n " , ( sc ) - > sc_c . np_encrypt ) ; \
printf ( " net_type 0x%02x \n " , ( sc ) - > sc_c . np_net_type ) ; \
printf ( " ssid \" %.32s \" \n " , ( sc ) - > sc_c . np_ssid ) ; \
2000-03-11 13:34:13 +00:00
printf ( " %8D \n " , ( sc ) - > sc_c . np_ssid , " " ) ; \
printf ( " %8D \n " , ( sc ) - > sc_c . np_ssid + 8 , " " ) ; \
printf ( " %8D \n " , ( sc ) - > sc_c . np_ssid + 16 , " " ) ; \
printf ( " %8D \n " , ( sc ) - > sc_c . np_ssid + 24 , " " ) ; \
2000-03-11 13:25:33 +00:00
printf ( " priv_start 0x%02x \n " , ( sc ) - > sc_c . np_priv_start ) ; \
printf ( " priv_join 0x%02x \n " , ( sc ) - > sc_c . np_priv_join ) ; \
printf ( " ray%d: Desired network parameters%s \n " , ( sc ) - > unit , ( s ) ) ; \
printf ( " bss_id %6D \n " , ( sc ) - > sc_d . np_bss_id , " : " ) ; \
printf ( " inited 0x%02x \n " , ( sc ) - > sc_d . np_inited ) ; \
printf ( " def_txrate 0x%02x \n " , ( sc ) - > sc_d . np_def_txrate ) ; \
printf ( " encrypt 0x%02x \n " , ( sc ) - > sc_d . np_encrypt ) ; \
printf ( " net_type 0x%02x \n " , ( sc ) - > sc_d . np_net_type ) ; \
printf ( " ssid \" %.32s \" \n " , ( sc ) - > sc_d . np_ssid ) ; \
2000-03-11 13:34:13 +00:00
printf ( " %8D \n " , ( sc ) - > sc_c . np_ssid , " " ) ; \
printf ( " %8D \n " , ( sc ) - > sc_c . np_ssid + 8 , " " ) ; \
printf ( " %8D \n " , ( sc ) - > sc_c . np_ssid + 16 , " " ) ; \
printf ( " %8D \n " , ( sc ) - > sc_c . np_ssid + 24 , " " ) ; \
2000-03-11 13:25:33 +00:00
printf ( " priv_start 0x%02x \n " , ( sc ) - > sc_d . np_priv_start ) ; \
printf ( " priv_join 0x%02x \n " , ( sc ) - > sc_d . np_priv_join ) ; \
2000-02-27 19:52:29 +00:00
} } while ( 0 )
2000-02-26 14:49:24 +00:00
# else
2000-03-05 14:39:23 +00:00
# define RAY_DHEX8(p, l)
# define RAY_DPRINTFN(l,x)
2000-02-27 19:52:29 +00:00
# define RAY_DNET_DUMP(sc, s)
# endif /* RAY_DEBUG > 0 */
2000-03-05 14:39:23 +00:00
# if RAY_DEBUG > 50
2000-02-27 19:52:29 +00:00
# define RAY_DMBUF_DUMP(sc, m, s) ray_dump_mbuf((sc), (m), (s))
# else
# define RAY_DMBUF_DUMP(sc, m, s)
# endif /* RAY_DEBUG > 10 */
2000-02-20 14:56:17 +00:00
# include "ray.h"
# include "card.h"
# include "apm.h"
# include "bpfilter.h"
# if NRAY > 0
# include <sys/param.h>
# include <sys/cdefs.h>
# include <sys/conf.h>
# include <sys/errno.h>
# include <sys/kernel.h>
# include <sys/malloc.h>
# include <sys/mbuf.h>
2000-03-08 23:28:06 +00:00
# include <sys/callout.h>
2000-02-20 14:56:17 +00:00
# include <sys/select.h>
# include <sys/socket.h>
# include <sys/sockio.h>
# include <sys/systm.h>
2000-03-08 23:28:06 +00:00
# include <sys/sysctl.h>
2000-02-20 14:56:17 +00:00
# include <sys/uio.h>
2000-02-26 14:49:24 +00:00
# include <sys/proc.h>
# include <sys/ucred.h>
2000-02-20 14:56:17 +00:00
# include <net/if.h>
# include <net/if_arp.h>
# include <net/ethernet.h>
# include <net/if_dl.h>
# include <net/if_media.h>
2000-02-26 14:49:24 +00:00
# include <net/if_mib.h>
2000-02-20 14:56:17 +00:00
# if NBPFILTER > 0
# include <net/bpf.h>
# endif /* NBPFILTER */
# include <machine/clock.h>
# include <machine/md_var.h>
# include <machine/bus_pio.h>
# include <machine/bus.h>
# include <i386/isa/isa.h>
# include <i386/isa/isa_device.h>
2000-03-11 13:25:33 +00:00
# include <i386/isa/if_ieee80211.h>
2000-02-20 14:56:17 +00:00
# include <i386/isa/if_rayreg.h>
2000-02-26 14:49:24 +00:00
# include <i386/isa/if_raymib.h>
2000-02-20 14:56:17 +00:00
# if NCARD > 0
# include <pccard/cardinfo.h>
# include <pccard/cis.h>
# include <pccard/driver.h>
# include <pccard/slot.h>
# endif /* NCARD */
# if NAPM > 0
# include <machine/apm_bios.h>
# endif /* NAPM */
2000-03-08 23:28:06 +00:00
/*
* Sysctl knobs
*/
static int ray_debug = RAY_DEBUG ;
SYSCTL_NODE ( _hw , OID_AUTO , ray , CTLFLAG_RW , 0 , " Raylink Driver " ) ;
SYSCTL_INT ( _hw_ray , OID_AUTO , debug , CTLFLAG_RW , & ray_debug , RAY_DEBUG , " " ) ;
2000-03-11 13:25:33 +00:00
/*
* Network parameters , used twice in sotfc to store what we want and what
* we have .
*
* XXX promisc in here too ?
* XXX sc_station_addr in here too ( for changing mac address )
*/
struct ray_nw_param {
struct ray_cmd_net p_1 ;
u_int8_t np_ap_status ;
struct ray_net_params \
p_2 ;
u_int8_t np_countrycode ;
} ;
# define np_upd_param p_1.c_upd_param
# define np_bss_id p_1.c_bss_id
# define np_inited p_1.c_inited
# define np_def_txrate p_1.c_def_txrate
# define np_encrypt p_1.c_encrypt
# define np_net_type p_2.p_net_type
# define np_ssid p_2.p_ssid
# define np_priv_start p_2.p_privacy_must_start
# define np_priv_join p_2.p_privacy_can_join
2000-02-20 14:56:17 +00:00
/*
* One of these structures per allocated device
*/
struct ray_softc {
2000-02-27 19:52:29 +00:00
struct arpcom arpcom ; /* Ethernet common */
struct ifmedia ifmedia ; /* Ifnet common */
2000-03-08 23:28:06 +00:00
struct callout_handle \
ccs_timerh ; /* Handle for ccs timeouts */
2000-03-12 22:54:29 +00:00
struct callout_handle \
reset_timerh ; /* Handle for reset timer */
struct callout_handle \
start_timerh ; /* Handle for start timer */
2000-02-27 19:52:29 +00:00
# if RAY_NEED_STARTJOIN_TIMO
2000-02-26 14:49:24 +00:00
struct callout_handle \
2000-02-27 19:52:29 +00:00
sj_timerh ; /* Handle for start_join timer */
# endif /* RAY_NEED_STARTJOIN_TIMO */
char * card_type ; /* Card model name */
char * vendor ; /* Card manufacturer */
2000-02-26 14:49:24 +00:00
2000-02-27 19:52:29 +00:00
int unit ; /* Unit number */
u_char gone ; /* 1 = Card bailed out */
caddr_t maddr ; /* Shared RAM Address */
2000-03-05 14:39:23 +00:00
int flags ; /* Start up flags */
2000-02-26 14:49:24 +00:00
2000-02-27 19:52:29 +00:00
int translation ; /* Packet translation types */
2000-03-05 14:39:23 +00:00
# if (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP)
2000-02-27 19:52:29 +00:00
int slotnum ; /* Slot number */
struct mem_desc md ; /* Map info for common memory */
2000-03-05 14:39:23 +00:00
# endif /* (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP) */
2000-02-26 14:49:24 +00:00
2000-02-27 19:52:29 +00:00
struct ray_ecf_startup_v5 \
sc_ecf_startup ; /* Startup info from card */
2000-02-26 14:49:24 +00:00
2000-03-11 13:25:33 +00:00
struct ray_nw_param sc_c ; /* current network params */
struct ray_nw_param sc_d ; /* desired network params */
2000-03-08 23:28:06 +00:00
int sc_havenet ; /* true if we have a network */
int sc_promisc ; /* current set value */
int sc_running ; /* things we are doing */
int sc_scheduled ; /* things we need to do */
int sc_timoneed ; /* set if timeout is sched */
int sc_timocheck ; /* set if timeout is sched */
u_int8_t sc_ccsinuse [ 64 ] ; /* ccss' in use -- not for tx */
int sc_checkcounters ;
u_int64_t sc_rxoverflow ; /* Number of rx overflows */
u_int64_t sc_rxcksum ; /* Number of checksum errors */
u_int64_t sc_rxhcksum ; /* Number of header checksum errors */
u_int8_t sc_rxnoise ; /* Average receiver level */
struct ray_param_req \
* sc_repreq ; /* used to return values */
struct ray_param_req \
* sc_updreq ; /* to the user */
2000-02-20 14:56:17 +00:00
} ;
static struct ray_softc ray_softc [ NRAY ] ;
2000-02-26 14:49:24 +00:00
# define sc_station_addr sc_ecf_startup.e_station_addr
2000-02-20 14:56:17 +00:00
# define sc_version sc_ecf_startup.e_fw_build_string
2000-02-26 14:49:24 +00:00
# define sc_tibsize sc_ecf_startup.e_tibsize
/* Commands -- priority given to LSB */
# define SCP_FIRST 0x0001
# define SCP_UPDATESUBCMD 0x0001
# define SCP_STARTASSOC 0x0002
# define SCP_REPORTPARAMS 0x0004
# define SCP_IFSTART 0x0008
/* Update sub commands -- issues are serialized priority to LSB */
# define SCP_UPD_FIRST 0x0100
# define SCP_UPD_STARTUP 0x0100
# define SCP_UPD_STARTJOIN 0x0200
# define SCP_UPD_PROMISC 0x0400
# define SCP_UPD_MCAST 0x0800
# define SCP_UPD_UPDATEPARAMS 0x1000
# define SCP_UPD_SHIFT 8
# define SCP_UPD_MASK 0xff00
/* These command (a subset of the update set) require timeout checking */
# define SCP_TIMOCHECK_CMD_MASK \
( SCP_UPD_UPDATEPARAMS | SCP_UPD_STARTUP | SCP_UPD_MCAST | \
SCP_UPD_PROMISC )
2000-03-05 14:39:23 +00:00
/*
* Translation types
*/
2000-02-27 19:52:29 +00:00
/* XXX maybe better as part of the if structure? */
# define SC_TRANSLATE_WEBGEAR 0
2000-02-20 14:56:17 +00:00
/*
2000-03-08 23:28:06 +00:00
* Prototyping
2000-02-26 14:49:24 +00:00
*/
2000-03-08 23:28:06 +00:00
static int ray_attach __P ( ( struct isa_device * dev ) ) ;
2000-02-26 14:49:24 +00:00
static int ray_alloc_ccs __P ( ( struct ray_softc * sc , size_t * ccsp , u_int cmd , u_int track ) ) ;
static void ray_ccs_done __P ( ( struct ray_softc * sc , size_t ccs ) ) ;
2000-03-08 23:28:06 +00:00
static void ray_check_ccs __P ( ( void * arg ) ) ;
static void ray_check_scheduled __P ( ( void * arg ) ) ;
static void ray_cmd_cancel __P ( ( struct ray_softc * sc , int cmdf ) ) ;
static void ray_cmd_done __P ( ( struct ray_softc * sc , int cmdf ) ) ;
static int ray_cmd_is_running __P ( ( struct ray_softc * sc , int cmdf ) ) ;
static int ray_cmd_is_scheduled __P ( ( struct ray_softc * sc , int cmdf ) ) ;
static void ray_cmd_ran __P ( ( struct ray_softc * sc , int cmdf ) ) ;
static void ray_cmd_schedule __P ( ( struct ray_softc * sc , int cmdf ) ) ;
2000-03-09 21:34:47 +00:00
static void ray_download_done __P ( ( struct ray_softc * sc ) ) ;
2000-02-26 14:49:24 +00:00
static void ray_download_params __P ( ( struct ray_softc * sc ) ) ;
2000-03-08 23:28:06 +00:00
# if RAY_DEBUG > 50
static void ray_dump_mbuf __P ( ( struct ray_softc * sc , struct mbuf * m , char * s ) ) ;
# endif /* RAY_DEBUG > 50 */
2000-02-26 14:49:24 +00:00
static u_int8_t ray_free_ccs __P ( ( struct ray_softc * sc , size_t ccs ) ) ;
2000-03-08 23:28:06 +00:00
# if XXX_NETBSDTX
static void ray_free_ccs_chain __P ( ( struct ray_softc * sc , u_int ni ) ) ;
# endif /* XXX_NETBSDTX */
static int ray_intr __P ( ( struct pccard_devinfo * dev_p ) ) ;
static int ray_ioctl __P ( ( struct ifnet * ifp , u_long command , caddr_t data ) ) ;
static void ray_init __P ( ( void * xsc ) ) ;
2000-02-26 14:49:24 +00:00
static int ray_issue_cmd __P ( ( struct ray_softc * sc , size_t ccs , u_int track ) ) ;
2000-03-08 23:28:06 +00:00
static int ray_pccard_init __P ( ( struct pccard_devinfo * dev_p ) ) ;
static int ray_pccard_intr __P ( ( struct pccard_devinfo * dev_p ) ) ;
static void ray_pccard_unload __P ( ( struct pccard_devinfo * dev_p ) ) ;
static int ray_probe __P ( ( struct isa_device * dev ) ) ;
static void ray_rcs_intr __P ( ( struct ray_softc * sc , size_t ccs ) ) ;
static void ray_report_params __P ( ( struct ray_softc * sc ) ) ;
2000-03-05 22:24:30 +00:00
static void ray_reset __P ( ( struct ray_softc * sc ) ) ;
static void ray_reset_timo __P ( ( void * xsc ) ) ;
2000-02-27 19:52:29 +00:00
static void ray_rx __P ( ( struct ray_softc * sc , size_t rcs ) ) ;
2000-03-08 23:28:06 +00:00
static void ray_set_pending __P ( ( struct ray_softc * sc , u_int cmdf ) ) ;
static int ray_simple_cmd __P ( ( struct ray_softc * sc , u_int cmd , u_int track ) ) ;
static void ray_start __P ( ( struct ifnet * ifp ) ) ;
static void ray_start_assoc __P ( ( struct ray_softc * sc ) ) ;
2000-03-05 14:39:23 +00:00
static void ray_start_done __P ( ( struct ray_softc * sc , size_t ccs , u_int8_t status ) ) ;
2000-03-08 23:28:06 +00:00
static void ray_start_sc __P ( ( struct ray_softc * sc ) ) ;
2000-03-05 14:39:23 +00:00
static void ray_start_timo __P ( ( void * xsc ) ) ;
static size_t ray_start_wrhdr __P ( ( struct ray_softc * sc , struct ether_header * eh , size_t bufp ) ) ;
2000-02-27 19:52:29 +00:00
static void ray_start_join_done __P ( ( struct ray_softc * sc , size_t ccs , u_int8_t status ) ) ;
2000-03-08 23:28:06 +00:00
static void ray_start_join_net __P ( ( struct ray_softc * sc ) ) ;
2000-02-27 19:52:29 +00:00
# if RAY_NEED_STARTJOIN_TIMO
2000-02-26 14:49:24 +00:00
static void ray_start_join_timo __P ( ( void * xsc ) ) ;
2000-02-27 19:52:29 +00:00
# endif /* RAY_NEED_STARTJOIN_TIMO */
2000-03-08 23:28:06 +00:00
static void ray_stop __P ( ( struct ray_softc * sc ) ) ;
static void ray_update_error_counters \
__P ( ( struct ray_softc * sc ) ) ;
static void ray_update_mcast __P ( ( struct ray_softc * sc ) ) ;
static void ray_update_params __P ( ( struct ray_softc * sc ) ) ;
static void ray_update_params_done __P ( ( struct ray_softc * sc , size_t ccs , u_int stat ) ) ;
static void ray_update_promisc __P ( ( struct ray_softc * sc ) ) ;
static void ray_update_subcmd __P ( ( struct ray_softc * sc ) ) ;
static int ray_user_update_params __P ( ( struct ray_softc * sc , struct ray_param_req * pr ) ) ;
static int ray_user_report_params __P ( ( struct ray_softc * sc , struct ray_param_req * pr ) ) ;
2000-03-12 22:54:29 +00:00
static int ray_user_report_stats __P ( ( struct ray_softc * sc , struct ray_stats_req * sr ) ) ;
2000-03-08 23:28:06 +00:00
static void ray_watchdog __P ( ( struct ifnet * ifp ) ) ;
/*
* PCMCIA driver definition
*/
PCCARD_MODULE ( ray , ray_pccard_init , ray_pccard_unload , ray_pccard_intr , 0 , net_imask ) ;
/*
* ISA driver definition
*/
struct isa_driver raydriver = {
ray_probe ,
ray_attach ,
" ray " ,
1
} ;
/*
* Command function tables - based on bit index in SCP_xx
*/
typedef void ( * ray_cmd_func_t ) ( struct ray_softc * ) ;
static ray_cmd_func_t ray_cmdtab [ ] = {
ray_update_subcmd , /* SCP_UPDATESUBCMD */
ray_start_assoc , /* SCP_STARTASSOC */
ray_report_params , /* SCP_REPORTPARAMS */
ray_start_sc /* SCP_IFSTART */
} ;
static int ray_ncmdtab = sizeof ( ray_cmdtab ) / sizeof ( * ray_cmdtab ) ;
static ray_cmd_func_t ray_subcmdtab [ ] = {
ray_download_params , /* SCP_UPD_STARTUP */
ray_start_join_net , /* SCP_UPD_STARTJOIN */
ray_update_promisc , /* SCP_UPD_PROMISC */
ray_update_mcast , /* SCP_UPD_MCAST */
ray_update_params /* SCP_UPD_UPDATEPARAMS */
} ;
static int ray_nsubcmdtab = sizeof ( ray_subcmdtab ) / sizeof ( * ray_subcmdtab ) ;
2000-02-27 19:52:29 +00:00
2000-02-26 14:49:24 +00:00
/*
* Indirections for reading / writing shared memory - from NetBSD / if_ray . c
*/
# ifndef offsetof
# define offsetof(type, member) \
( ( size_t ) ( & ( ( type * ) 0 ) - > member ) )
# endif /* offsetof */
# define SRAM_READ_1(sc, off) \
( u_int8_t ) * ( ( sc ) - > maddr + ( off ) )
/* ((u_int8_t)bus_space_read_1((sc)->sc_memt, (sc)->sc_memh, (off))) */
# define SRAM_READ_FIELD_1(sc, off, s, f) \
SRAM_READ_1 ( sc , ( off ) + offsetof ( struct s , f ) )
# define SRAM_READ_FIELD_2(sc, off, s, f) \
( ( ( ( u_int16_t ) SRAM_READ_1 ( sc , ( off ) + offsetof ( struct s , f ) ) < < 8 ) \
| ( SRAM_READ_1 ( sc , ( off ) + 1 + offsetof ( struct s , f ) ) ) ) )
# define SRAM_READ_FIELD_N(sc, off, s, f, p, n) \
ray_read_region ( sc , ( off ) + offsetof ( struct s , f ) , ( p ) , ( n ) )
# define ray_read_region(sc, off, vp, n) \
bcopy ( ( sc ) - > maddr + ( off ) , ( vp ) , ( n ) )
# define SRAM_WRITE_1(sc, off, val) \
* ( ( sc ) - > maddr + ( off ) ) = ( val )
/* bus_space_write_1((sc)->sc_memt, (sc)->sc_memh, (off), (val)) */
# define SRAM_WRITE_FIELD_1(sc, off, s, f, v) \
SRAM_WRITE_1 ( sc , ( off ) + offsetof ( struct s , f ) , ( v ) )
# define SRAM_WRITE_FIELD_2(sc, off, s, f, v) do { \
SRAM_WRITE_1 ( sc , ( off ) + offsetof ( struct s , f ) , ( ( ( v ) > > 8 ) & 0xff ) ) ; \
SRAM_WRITE_1 ( sc , ( off ) + 1 + offsetof ( struct s , f ) , ( ( v ) & 0xff ) ) ; \
} while ( 0 )
# define SRAM_WRITE_FIELD_N(sc, off, s, f, p, n) \
ray_write_region ( sc , ( off ) + offsetof ( struct s , f ) , ( p ) , ( n ) )
# define ray_write_region(sc, off, vp, n) \
bcopy ( ( vp ) , ( sc ) - > maddr + ( off ) , ( n ) )
/*
2000-03-05 22:24:30 +00:00
* Macro ' s and constants
2000-02-20 14:56:17 +00:00
*/
2000-03-08 23:28:06 +00:00
# ifndef RAY_CCS_TIMEOUT
# define RAY_CCS_TIMEOUT (hz / 2)
# endif
# ifndef RAY_CHECK_SCHED_TIMEOUT
# define RAY_CHECK_SCHED_TIMEOUT (hz)
# endif
2000-03-05 22:24:30 +00:00
# ifndef RAY_RESET_TIMEOUT
# define RAY_RESET_TIMEOUT (10 * hz)
# endif
2000-03-08 23:28:06 +00:00
# ifndef RAY_START_TIMEOUT
# define RAY_START_TIMEOUT (hz / 2)
# endif
2000-03-05 22:24:30 +00:00
# if RAY_SIMPLE_TX
# define RAY_IFQ_MAXLEN (2)
# else if RAY_DECENT_TX
# define RAY_IFQ_MAXLEN (RAY_CCS_TX_LAST+1)
# endif
2000-03-05 14:39:23 +00:00
# define RAY_CCS_FREE(sc, ccs) \
SRAM_WRITE_FIELD_1 ( ( sc ) , ( ccs ) , ray_cmd , c_status , RAY_CCS_STATUS_FREE )
2000-02-27 19:52:29 +00:00
# define RAY_ECF_READY(sc) (!(ray_read_reg(sc, RAY_ECFIR) & RAY_ECFIR_IRQ))
2000-02-26 14:49:24 +00:00
# define RAY_ECF_START_CMD(sc) ray_attr_write((sc), RAY_ECFIR, RAY_ECFIR_IRQ)
# define RAY_HCS_CLEAR_INTR(sc) ray_attr_write((sc), RAY_HCSIR, 0)
2000-02-27 19:52:29 +00:00
# define RAY_HCS_INTR(sc) (ray_read_reg(sc, RAY_HCSIR) & RAY_HCSIR_IRQ)
2000-02-20 14:56:17 +00:00
/*
* As described in if_xe . c . . .
*
2000-02-26 14:49:24 +00:00
* Horrid stuff for accessing CIS tuples and remapping common memory . . .
2000-02-20 14:56:17 +00:00
*/
# define CARD_MAJOR 50
2000-02-26 14:49:24 +00:00
static int ray_attr_write __P ( ( struct ray_softc * sc , off_t offset , u_int8_t byte ) ) ;
static int ray_attr_read __P ( ( struct ray_softc * sc , off_t offset , u_int8_t * buf , int size ) ) ;
2000-02-27 19:52:29 +00:00
static u_int8_t ray_read_reg __P ( ( struct ray_softc * sc , off_t reg ) ) ;
2000-03-05 14:39:23 +00:00
# if (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP)
2000-02-27 19:52:29 +00:00
static void ray_attr_getmap __P ( ( struct ray_softc * sc ) ) ;
static void ray_attr_cm __P ( ( struct ray_softc * sc ) ) ;
2000-02-26 14:49:24 +00:00
# define RAY_MAP_CM(sc) ray_attr_cm(sc)
2000-02-27 19:52:29 +00:00
# else
# define RAY_MAP_CM(sc)
2000-03-05 14:39:23 +00:00
# endif /* (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP) */
2000-02-20 14:56:17 +00:00
/*
* PCCard initialise .
*/
static int
2000-02-26 14:49:24 +00:00
ray_pccard_init ( dev_p )
2000-02-20 14:56:17 +00:00
struct pccard_devinfo * dev_p ;
{
struct ray_softc * sc ;
2000-03-05 14:39:23 +00:00
int doRemap ;
2000-02-20 14:56:17 +00:00
2000-03-05 14:39:23 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: PCCard probe \n " , dev_p - > isahd . id_unit ) ) ;
2000-02-20 14:56:17 +00:00
if ( dev_p - > isahd . id_unit > = NRAY )
2000-03-08 23:28:06 +00:00
return ( ENODEV ) ;
2000-02-20 14:56:17 +00:00
sc = & ray_softc [ dev_p - > isahd . id_unit ] ;
2000-03-05 14:39:23 +00:00
# if (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP)
sc - > slotnum = dev_p - > slt - > slotnum ;
ray_attr_getmap ( sc ) ;
RAY_DPRINTFN ( 1 , ( " ray%d: Memory window flags 0x%02x, start %p, size 0x%x, card address 0x%lx \n " , sc - > unit , sc - > md . flags , sc - > md . start , sc - > md . size , sc - > md . card ) ) ;
# endif /* (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP) */
# if RAY_NEED_CM_FIXUP
doRemap = 0 ;
2000-03-08 08:53:36 +00:00
if ( sc - > md . start = = 0x0 ) {
2000-03-05 22:24:30 +00:00
printf ( " ray%d: pccardd did not map CM - giving up \n " , sc - > unit ) ;
2000-03-08 23:28:06 +00:00
return ( ENXIO ) ;
2000-03-05 22:24:30 +00:00
}
2000-03-05 14:39:23 +00:00
if ( sc - > md . flags ! = MDF_ACTIVE ) {
printf ( " ray%d: Fixing up CM flags from 0x%x to 0x40 \n " ,
sc - > unit , sc - > md . flags ) ;
doRemap = 1 ;
sc - > md . flags = MDF_ACTIVE ;
2000-02-20 14:56:17 +00:00
}
2000-03-05 14:39:23 +00:00
if ( sc - > md . size ! = 0xc000 ) {
printf ( " ray%d: Fixing up CM size from 0x%x to 0xc000 \n " ,
sc - > unit , sc - > md . size ) ;
doRemap = 1 ;
sc - > md . size = 0xc000 ;
dev_p - > isahd . id_msize = sc - > md . size ;
}
if ( sc - > md . card ! = 0 ) {
printf ( " ray%d: Fixing up CM card address from 0x%lx to 0x0 \n " ,
sc - > unit , sc - > md . card ) ;
doRemap = 1 ;
sc - > md . card = 0 ;
}
if ( doRemap )
ray_attr_cm ( sc ) ;
# endif /* RAY_NEED_CM_FIXUP */
2000-02-20 14:56:17 +00:00
2000-03-05 14:39:23 +00:00
sc - > gone = 0 ;
sc - > unit = dev_p - > isahd . id_unit ;
sc - > maddr = dev_p - > isahd . id_maddr ;
sc - > flags = dev_p - > isahd . id_flags ;
2000-02-20 14:56:17 +00:00
2000-03-08 08:53:36 +00:00
printf ( " ray%d: <Raylink/IEEE 802.11> maddr %p msize 0x%x irq %d flags 0x%x on isa (PC-Card slot %d) \n " ,
2000-03-05 14:39:23 +00:00
sc - > unit ,
2000-03-08 08:53:36 +00:00
sc - > maddr ,
2000-03-05 14:39:23 +00:00
dev_p - > isahd . id_msize ,
ffs ( dev_p - > isahd . id_irq ) - 1 ,
sc - > flags ,
sc - > slotnum ) ;
2000-02-26 14:49:24 +00:00
2000-02-20 14:56:17 +00:00
if ( ray_attach ( & dev_p - > isahd ) )
2000-03-08 23:28:06 +00:00
return ( ENXIO ) ;
2000-02-20 14:56:17 +00:00
2000-03-08 23:28:06 +00:00
return ( 0 ) ;
2000-02-20 14:56:17 +00:00
}
/*
* PCCard unload .
*/
static void
2000-02-26 14:49:24 +00:00
ray_pccard_unload ( dev_p )
2000-02-20 14:56:17 +00:00
struct pccard_devinfo * dev_p ;
{
struct ray_softc * sc ;
struct ifnet * ifp ;
2000-03-05 14:39:23 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: PCCard unload \n " , dev_p - > isahd . id_unit ) ) ;
2000-02-20 14:56:17 +00:00
sc = & ray_softc [ dev_p - > isahd . id_unit ] ;
2000-03-05 22:24:30 +00:00
ifp = & sc - > arpcom . ac_if ;
2000-02-20 14:56:17 +00:00
if ( sc - > gone ) {
printf ( " ray%d: already unloaded \n " , sc - > unit ) ;
return ;
}
2000-03-05 22:24:30 +00:00
/*
* Clear out timers and sort out driver state
2000-03-08 23:28:06 +00:00
*
* We use callout_stop to unconditionally kill the ccs and general
* timers as they are used with multiple arguments .
2000-03-05 22:24:30 +00:00
*/
2000-03-08 23:28:06 +00:00
# if RAY_USE_CALLOUT_STOP
callout_stop ( sc - > ccs_timerh ) ;
2000-03-12 22:54:29 +00:00
callout_stop ( sc - > reset_timerh ) ;
2000-03-08 23:28:06 +00:00
# else
untimeout ( ray_check_ccs , sc , sc - > ccs_timerh ) ;
untimeout ( ray_check_scheduled , sc , sc - > ccs_timerh ) ;
2000-03-12 22:54:29 +00:00
untimeout ( ray_reset_timo , sc , sc - > reset_timerh ) ;
2000-03-08 23:28:06 +00:00
# endif /* RAY_USE_CALLOUT_STOP */
2000-03-05 22:24:30 +00:00
# if RAY_NEED_STARTJOIN_TIMO
untimeout ( ray_start_join_timo , sc , sc - > sj_timerh ) ;
# endif /* RAY_NEED_STARTJOIN_TIMO */
untimeout ( ray_start_timo , sc , sc - > start_timerh ) ;
sc - > sc_havenet = 0 ;
/*
* Mark as not running
*/
ifp - > if_flags & = ~ IFF_RUNNING ;
ifp - > if_flags & = ~ IFF_OACTIVE ;
/*
* Cleardown interface
*/
if_down ( ifp ) ; /* XXX should be if_detach for -current */
2000-02-20 14:56:17 +00:00
2000-03-05 22:24:30 +00:00
/*
* Mark card as gone
*/
2000-02-20 14:56:17 +00:00
sc - > gone = 1 ;
printf ( " ray%d: unloaded \n " , sc - > unit ) ;
return ;
}
/*
2000-03-08 23:28:06 +00:00
* process an interrupt
2000-02-20 14:56:17 +00:00
*/
static int
2000-02-26 14:49:24 +00:00
ray_pccard_intr ( dev_p )
2000-02-20 14:56:17 +00:00
struct pccard_devinfo * dev_p ;
{
2000-03-08 23:28:06 +00:00
return ( ray_intr ( dev_p ) ) ;
2000-02-20 14:56:17 +00:00
}
/*
* ISA probe routine .
*/
static int
2000-02-26 14:49:24 +00:00
ray_probe ( dev_p )
2000-02-20 14:56:17 +00:00
struct isa_device * dev_p ;
{
2000-03-05 14:39:23 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ISA probe \n " , dev_p - > id_unit ) ) ;
2000-02-20 14:56:17 +00:00
2000-03-08 23:28:06 +00:00
return ( 0 ) ;
2000-02-20 14:56:17 +00:00
}
/*
* ISA / PCCard attach .
*/
static int
2000-02-26 14:49:24 +00:00
ray_attach ( dev_p )
2000-02-20 14:56:17 +00:00
struct isa_device * dev_p ;
{
struct ray_softc * sc ;
struct ray_ecf_startup_v5 * ep ;
struct ifnet * ifp ;
2000-02-26 14:49:24 +00:00
char ifname [ IFNAMSIZ ] ;
2000-02-20 14:56:17 +00:00
2000-03-05 14:39:23 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ISA/PCCard attach \n " , dev_p - > id_unit ) ) ;
2000-02-20 14:56:17 +00:00
sc = & ray_softc [ dev_p - > id_unit ] ;
2000-02-26 14:49:24 +00:00
RAY_MAP_CM ( sc ) ;
2000-02-20 14:56:17 +00:00
if ( sc - > gone ) {
printf ( " ray%d: unloaded before attach! \n " , sc - > unit ) ;
2000-03-08 23:28:06 +00:00
return ( 1 ) ;
2000-02-20 14:56:17 +00:00
}
/*
* Read startup results , check the card is okay and work out what
* version we are using .
*/
ep = & sc - > sc_ecf_startup ;
2000-02-26 14:49:24 +00:00
ray_read_region ( sc , RAY_ECF_TO_HOST_BASE , ep , sizeof ( sc - > sc_ecf_startup ) ) ;
2000-02-20 14:56:17 +00:00
if ( ep - > e_status ! = RAY_ECFS_CARD_OK ) {
2000-02-26 14:49:24 +00:00
printf ( " ray%d: card failed self test: status 0x%b \n " , sc - > unit ,
ep - > e_status ,
" \020 " /* print in hex */
" \001 RESERVED0 "
" \002 PROC_SELF_TEST "
" \003 PROG_MEM_CHECKSUM "
" \004 DATA_MEM_TEST "
" \005 RX_CALIBRATION "
" \006 FW_VERSION_COMPAT "
" \007 RERSERVED1 "
" \00 8TEST_COMPLETE "
) ;
2000-03-08 23:28:06 +00:00
return ( 1 ) ;
2000-02-20 14:56:17 +00:00
}
2000-02-26 14:49:24 +00:00
if ( sc - > sc_version ! = RAY_ECFS_BUILD_4 & &
sc - > sc_version ! = RAY_ECFS_BUILD_5
) {
2000-02-20 14:56:17 +00:00
printf ( " ray%d: unsupported firmware version 0x%0x \n " , sc - > unit ,
ep - > e_fw_build_string ) ;
2000-03-08 23:28:06 +00:00
return ( 1 ) ;
2000-02-20 14:56:17 +00:00
}
2000-02-26 14:49:24 +00:00
if ( bootverbose | | RAY_DEBUG ) {
printf ( " ray%d: Start Up Results \n " , sc - > unit ) ;
if ( sc - > sc_version = = RAY_ECFS_BUILD_4 )
printf ( " Firmware version 4 \n " ) ;
else
printf ( " Firmware version 5 \n " ) ;
printf ( " Status 0x%x \n " , ep - > e_status ) ;
printf ( " Ether address %6D \n " , ep - > e_station_addr , " : " ) ;
if ( sc - > sc_version = = RAY_ECFS_BUILD_4 ) {
printf ( " Program checksum %0x \n " , ep - > e_resv0 ) ;
printf ( " CIS checksum %0x \n " , ep - > e_rates [ 0 ] ) ;
} else {
printf ( " (reserved word) %0x \n " , ep - > e_resv0 ) ;
printf ( " Supported rates %8D \n " , ep - > e_rates , " : " ) ;
}
printf ( " Japan call sign %12D \n " , ep - > e_japan_callsign , " : " ) ;
if ( sc - > sc_version = = RAY_ECFS_BUILD_5 ) {
printf ( " Program checksum %0x \n " , ep - > e_prg_cksum ) ;
printf ( " CIS checksum %0x \n " , ep - > e_cis_cksum ) ;
printf ( " Firmware version %0x \n " , ep - > e_fw_build_string ) ;
printf ( " Firmware revision %0x \n " , ep - > e_fw_build ) ;
printf ( " (reserved word) %0x \n " , ep - > e_fw_resv ) ;
printf ( " ASIC version %0x \n " , ep - > e_asic_version ) ;
printf ( " TIB size %0x \n " , ep - > e_tibsize ) ;
}
2000-02-20 14:56:17 +00:00
}
2000-02-26 14:49:24 +00:00
/* Reset any pending interrupts */
RAY_HCS_CLEAR_INTR ( sc ) ;
2000-02-20 14:56:17 +00:00
/*
2000-02-26 14:49:24 +00:00
* Set the parameters that will survive stop / init
2000-02-27 19:52:29 +00:00
*
* Do not update these in ray_init ' s parameter setup
2000-02-20 14:56:17 +00:00
*/
2000-02-26 14:49:24 +00:00
# if XXX
2000-03-05 14:39:23 +00:00
see the ray_init section for stuff to move
2000-02-20 14:56:17 +00:00
# endif
2000-03-11 13:25:33 +00:00
bzero ( & sc - > sc_d , sizeof ( struct ray_nw_param ) ) ;
bzero ( & sc - > sc_c , sizeof ( struct ray_nw_param ) ) ;
2000-02-20 14:56:17 +00:00
/*
* Initialise the network interface structure
*/
2000-02-26 14:49:24 +00:00
bcopy ( ( char * ) & ep - > e_station_addr ,
( char * ) & sc - > arpcom . ac_enaddr , ETHER_ADDR_LEN ) ;
2000-02-20 14:56:17 +00:00
ifp = & sc - > arpcom . ac_if ;
ifp - > if_softc = sc ;
ifp - > if_name = " ray " ;
ifp - > if_unit = sc - > unit ;
ifp - > if_timer = 0 ;
2000-03-12 22:54:29 +00:00
ifp - > if_flags = ( IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST ) ;
2000-02-20 14:56:17 +00:00
# if XXX
2000-02-26 14:49:24 +00:00
ifp - > if_hdr = . . . ; make this big enough to hold the .11 and .3 headers
# endif
2000-03-05 14:39:23 +00:00
ifp - > if_baudrate = 1000000 ; /* Is this baud or bps ;-) */
2000-02-20 14:56:17 +00:00
ifp - > if_output = ether_output ;
ifp - > if_start = ray_start ;
ifp - > if_ioctl = ray_ioctl ;
ifp - > if_watchdog = ray_watchdog ;
ifp - > if_init = ray_init ;
2000-03-05 22:24:30 +00:00
ifp - > if_snd . ifq_maxlen = RAY_IFQ_MAXLEN ;
2000-02-20 14:56:17 +00:00
2000-02-26 14:49:24 +00:00
/*
* If this logical interface has already been attached ,
* don ' t attach it again or chaos will ensue .
*/
sprintf ( ifname , " ray%d " , sc - > unit ) ;
if ( ifunit ( ifname ) = = NULL ) {
2000-03-08 23:28:06 +00:00
callout_handle_init ( & sc - > ccs_timerh ) ;
2000-03-12 22:54:29 +00:00
callout_handle_init ( & sc - > reset_timerh ) ;
2000-02-27 19:52:29 +00:00
# if RAY_NEED_STARTJOIN_TIMO
2000-02-26 14:49:24 +00:00
callout_handle_init ( & sc - > sj_timerh ) ;
2000-02-27 19:52:29 +00:00
# endif /* RAY_NEED_STARTJOIN_TIMO */
2000-03-05 14:39:23 +00:00
callout_handle_init ( & sc - > start_timerh ) ;
2000-02-26 14:49:24 +00:00
if_attach ( ifp ) ;
ether_ifattach ( ifp ) ;
# if NBPFILTER > 0
bpfattach ( ifp , DLT_EN10MB , sizeof ( struct ether_header ) ) ;
# endif /* NBFFILTER */
2000-02-20 14:56:17 +00:00
2000-02-26 14:49:24 +00:00
# if XXX
this looks like a good idea
at_shutdown ( ray_shutdown , sc , SHUTDOWN_POST_SYNC ) ;
2000-02-20 14:56:17 +00:00
# endif /* XXX */
2000-02-26 14:49:24 +00:00
}
2000-02-20 14:56:17 +00:00
2000-03-08 23:28:06 +00:00
return ( 0 ) ;
2000-02-20 14:56:17 +00:00
}
/*
2000-03-08 23:28:06 +00:00
* Network initialisation .
2000-02-20 14:56:17 +00:00
*
2000-03-08 23:28:06 +00:00
* Start up flow is as follows .
* The kernel calls ray_init when the interface is assigned an address .
*
* ray_init does a bit of house keeping before calling ray_download_params .
2000-03-05 14:39:23 +00:00
*
2000-03-08 23:28:06 +00:00
* ray_download_params fills the startup parameter structure out and
2000-03-09 21:34:47 +00:00
* sends it to the card . The download command simply completes , so we
* use the timeout code in ray_check_ccs instead of spin locking . The
* passes flow to the standard ccs handler and we eventually end up in
* ray_download_done .
2000-03-08 23:28:06 +00:00
*
2000-03-09 21:34:47 +00:00
* ray_download_done tells the card to start an adhoc network or join
* a managed network . This should complete via the interrupt
* mechanism , but the NetBSD driver includes a timeout for some buggy
* stuff somewhere - I ' ve left the hooks in but don ' t use them . The
* interrupt handler passes control to ray_start_join_done - the ccs
* is handled by the interrupt mechanism .
2000-03-08 23:28:06 +00:00
*
* Once ray_start_join_done has checked the ccs and uploaded / updated
* the network parameters we are ready to process packets . It is then
* safe to call ray_start which is done by the interrupt handler .
2000-02-20 14:56:17 +00:00
*/
static void
2000-03-08 23:28:06 +00:00
ray_init ( xsc )
void * xsc ;
2000-02-20 14:56:17 +00:00
{
2000-03-08 23:28:06 +00:00
struct ray_softc * sc = xsc ;
struct ray_ecf_startup_v5 * ep ;
struct ifnet * ifp ;
size_t ccs ;
int i ;
2000-02-20 14:56:17 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: Network init \n " , sc - > unit ) ) ;
2000-02-26 14:49:24 +00:00
RAY_MAP_CM ( sc ) ;
2000-02-20 14:56:17 +00:00
if ( sc - > gone ) {
2000-03-08 23:28:06 +00:00
printf ( " ray%d: unloaded before init! \n " , sc - > unit ) ;
2000-02-20 14:56:17 +00:00
return ;
}
2000-03-08 23:28:06 +00:00
ifp = & sc - > arpcom . ac_if ;
if ( ( ifp - > if_flags & IFF_RUNNING ) )
ray_stop ( sc ) ;
2000-03-03 17:07:42 +00:00
2000-03-05 14:39:23 +00:00
/*
2000-03-08 23:28:06 +00:00
* Reset instance variables
2000-03-05 14:39:23 +00:00
*
2000-03-11 13:25:33 +00:00
* The first set are network parameters that are read back when
* the card starts or joins the network .
2000-03-05 14:39:23 +00:00
*
2000-03-08 23:28:06 +00:00
* The second set are network parameters that are downloaded to
* the card .
2000-03-05 14:39:23 +00:00
*
2000-03-08 23:28:06 +00:00
* The third set are driver parameters .
*
* All of the variables in these sets can be updated by the card or ioctls .
2000-03-05 14:39:23 +00:00
*/
2000-03-08 23:28:06 +00:00
# if XXX
see the ray_attach section for stuff to move
# endif
2000-03-11 13:25:33 +00:00
sc - > sc_d . np_upd_param = 0 ;
2000-03-21 14:27:46 +00:00
bzero ( sc - > sc_d . np_bss_id , ETHER_ADDR_LEN ) ;
2000-03-11 13:25:33 +00:00
sc - > sc_d . np_inited = 0 ;
2000-03-21 14:27:46 +00:00
sc - > sc_d . np_def_txrate = RAY_MIB_BASIC_RATE_SET_DEFAULT ;
2000-03-11 13:25:33 +00:00
sc - > sc_d . np_encrypt = 0 ;
sc - > sc_d . np_ap_status = RAY_MIB_AP_STATUS_DEFAULT ;
sc - > sc_d . np_net_type = RAY_MIB_NET_TYPE_DEFAULT ;
bzero ( sc - > sc_d . np_ssid , IEEE80211_NWID_LEN ) ;
strncpy ( sc - > sc_d . np_ssid , RAY_MIB_SSID_DEFAULT , IEEE80211_NWID_LEN ) ;
sc - > sc_d . np_priv_start = RAY_MIB_PRIVACY_MUST_START_DEFAULT ;
sc - > sc_d . np_priv_join = RAY_MIB_PRIVACY_CAN_JOIN_DEFAULT ;
2000-03-08 23:28:06 +00:00
sc - > sc_promisc = ! ! ( ifp - > if_flags & ( IFF_PROMISC | IFF_ALLMULTI ) ) ;
sc - > sc_havenet = 0 ;
sc - > translation = SC_TRANSLATE_WEBGEAR ;
/* Set all ccs to be free */
bzero ( sc - > sc_ccsinuse , sizeof ( sc - > sc_ccsinuse ) ) ;
ccs = RAY_CCS_ADDRESS ( 0 ) ;
for ( i = 0 ; i < RAY_CCS_LAST ; ccs + = RAY_CCS_SIZE , i + + )
RAY_CCS_FREE ( sc , ccs ) ;
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
/* Clear any pending interrupts */
RAY_HCS_CLEAR_INTR ( sc ) ;
# if XXX
Not sure why I really need this - maybe best to deal with
this when resets are requested by me ?
# endif /* XXX */
2000-03-05 14:39:23 +00:00
/*
2000-03-08 23:28:06 +00:00
* Get startup results - the card may have been reset
2000-03-05 14:39:23 +00:00
*/
2000-03-08 23:28:06 +00:00
ep = & sc - > sc_ecf_startup ;
ray_read_region ( sc , RAY_ECF_TO_HOST_BASE , ep , sizeof ( sc - > sc_ecf_startup ) ) ;
if ( ep - > e_status ! = RAY_ECFS_CARD_OK ) {
printf ( " ray%d: card failed self test: status 0x%b \n " , sc - > unit ,
ep - > e_status ,
" \020 " /* print in hex */
" \001 RESERVED0 "
" \002 PROC_SELF_TEST "
" \003 PROG_MEM_CHECKSUM "
" \004 DATA_MEM_TEST "
" \005 RX_CALIBRATION "
" \006 FW_VERSION_COMPAT "
" \007 RERSERVED1 "
" \00 8TEST_COMPLETE "
) ;
return ; /* XXX This doesn't mark the interface as down */
2000-03-05 14:39:23 +00:00
}
/*
2000-03-08 23:28:06 +00:00
* Fixup tib size to be correct - on build 4 it is garbage
2000-03-05 14:39:23 +00:00
*/
2000-03-08 23:28:06 +00:00
if ( sc - > sc_version = = RAY_ECFS_BUILD_4 & & sc - > sc_tibsize = = 0x55 )
sc - > sc_tibsize = sizeof ( struct ray_tx_tib ) ;
2000-03-05 14:39:23 +00:00
/*
2000-03-08 23:28:06 +00:00
* We are now up and running . Next we have to download network
* configuration into the card . We are busy until download is done .
2000-03-05 14:39:23 +00:00
*/
2000-03-08 23:28:06 +00:00
ifp - > if_flags | = IFF_RUNNING | IFF_OACTIVE ;
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
ray_download_params ( sc ) ;
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
return ;
}
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
/*
* Network stop .
*
* Assumes that a ray_init is used to restart the card .
*
*/
static void
ray_stop ( sc )
struct ray_softc * sc ;
{
struct ifnet * ifp ;
int s ;
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: Network stop \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
if ( sc - > gone ) {
printf ( " ray%d: unloaded before stop! \n " , sc - > unit ) ;
2000-03-05 14:39:23 +00:00
return ;
}
2000-03-08 23:28:06 +00:00
ifp = & sc - > arpcom . ac_if ;
2000-03-05 14:39:23 +00:00
/*
2000-03-08 23:28:06 +00:00
* Clear out timers and sort out driver state
2000-03-05 14:39:23 +00:00
*/
2000-03-09 21:34:47 +00:00
# if RAY_USE_CALLOUT_STOP
callout_stop ( sc - > ccs_timerh ) ;
2000-03-12 22:54:29 +00:00
callout_stop ( sc - > reset_timerh ) ;
2000-03-09 21:34:47 +00:00
# else
untimeout ( ray_check_ccs , sc , sc - > ccs_timerh ) ;
untimeout ( ray_check_scheduled , sc , sc - > ccs_timerh ) ;
2000-03-12 22:54:29 +00:00
untimeout ( ray_reset_timo , sc , sc - > reset_timerh ) ;
2000-03-09 21:34:47 +00:00
# endif /* RAY_USE_CALLOUT_STOP */
2000-03-08 23:28:06 +00:00
# if RAY_NEED_STARTJOIN_TIMO
untimeout ( ray_start_join_timo , sc , sc - > sj_timerh ) ;
# endif /* RAY_NEED_STARTJOIN_TIMO */
untimeout ( ray_start_timo , sc , sc - > start_timerh ) ;
sc - > sc_havenet = 0 ;
2000-03-12 22:54:29 +00:00
sc - > sc_rxoverflow = 0 ;
sc - > sc_rxcksum = 0 ;
sc - > sc_rxhcksum = 0 ;
sc - > sc_rxnoise = 0 ;
2000-03-05 14:39:23 +00:00
/*
2000-03-08 23:28:06 +00:00
* Inhibit card - if we can ' t prevent reception then do not worry ;
* stopping a NIC only guarantees no TX .
2000-03-05 14:39:23 +00:00
*/
2000-03-08 23:28:06 +00:00
s = splimp ( ) ;
/* XXX what does the SHUTDOWN command do? Or power saving in COR */
splx ( s ) ;
2000-03-03 17:07:42 +00:00
2000-03-08 23:28:06 +00:00
/*
* Mark as not running
*/
ifp - > if_flags & = ~ IFF_RUNNING ;
ifp - > if_flags & = ~ IFF_OACTIVE ;
2000-03-05 14:39:23 +00:00
return ;
}
2000-03-03 17:07:42 +00:00
2000-03-05 14:39:23 +00:00
/*
2000-03-08 23:28:06 +00:00
* Reset the card
2000-03-05 14:39:23 +00:00
*
2000-03-08 23:28:06 +00:00
* I ' m using the soft reset command in the COR register . I ' m not sure
* if the sequence is right but it does seem to do the right thing . A
* nano second after reset is written the flashing light goes out , and
* a few seconds after the default is written the main card light goes
* out . We wait a while and then re - init the card .
2000-03-05 14:39:23 +00:00
*/
static void
2000-03-08 23:28:06 +00:00
ray_reset ( sc )
2000-03-05 14:39:23 +00:00
struct ray_softc * sc ;
{
struct ifnet * ifp ;
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_reset \n " , sc - > unit ) ) ;
2000-03-05 14:39:23 +00:00
RAY_MAP_CM ( sc ) ;
ifp = & sc - > arpcom . ac_if ;
2000-03-08 23:28:06 +00:00
if ( ifp - > if_flags & IFF_RUNNING )
ray_stop ( sc ) ;
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
printf ( " ray%d: resetting card \n " , sc - > unit ) ;
ray_attr_write ( ( sc ) , RAY_COR , RAY_COR_RESET ) ;
ray_attr_write ( ( sc ) , RAY_COR , RAY_COR_DEFAULT ) ;
2000-03-12 22:54:29 +00:00
sc - > reset_timerh = timeout ( ray_reset_timo , sc , RAY_RESET_TIMEOUT ) ;
2000-03-05 14:39:23 +00:00
2000-02-20 14:56:17 +00:00
return ;
}
2000-03-05 14:39:23 +00:00
/*
2000-03-08 23:28:06 +00:00
* Finishing resetting and restarting the card
2000-03-05 14:39:23 +00:00
*/
static void
2000-03-08 23:28:06 +00:00
ray_reset_timo ( xsc )
2000-03-05 14:39:23 +00:00
void * xsc ;
{
struct ray_softc * sc = xsc ;
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_reset_timo \n " , sc - > unit ) ) ;
2000-03-05 14:39:23 +00:00
RAY_MAP_CM ( sc ) ;
2000-03-08 23:28:06 +00:00
if ( ! RAY_ECF_READY ( sc ) ) {
RAY_DPRINTFN ( 1 , ( " ray%d: ray_reset_timo still busy, re-schedule \n " ,
sc - > unit ) ) ;
2000-03-12 22:54:29 +00:00
sc - > reset_timerh = timeout ( ray_reset_timo , sc , RAY_RESET_TIMEOUT ) ;
2000-03-08 23:28:06 +00:00
return ;
2000-03-05 14:39:23 +00:00
}
2000-03-08 23:28:06 +00:00
RAY_HCS_CLEAR_INTR ( sc ) ;
ray_init ( sc ) ;
2000-03-05 14:39:23 +00:00
return ;
}
2000-03-08 23:28:06 +00:00
static void
ray_watchdog ( ifp )
register struct ifnet * ifp ;
2000-03-05 14:39:23 +00:00
{
2000-03-08 23:28:06 +00:00
struct ray_softc * sc ;
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: Network watchdog \n " , ifp - > if_unit ) ) ;
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
sc = ifp - > if_softc ;
RAY_MAP_CM ( sc ) ;
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
if ( sc - > gone ) {
printf ( " ray%d: unloaded before watchdog! \n " , sc - > unit ) ;
return ;
}
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
printf ( " ray%d: watchdog timeout \n " , sc - > unit ) ;
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
/* XXX may need to have remedial action here
for example
ray_reset
ray_stop
. . .
ray_init
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
do we only use on TX ?
if so then we should clear OACTIVE etc .
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
*/
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
return ;
2000-03-05 14:39:23 +00:00
}
2000-02-20 14:56:17 +00:00
/*
* Network ioctl request .
*/
static int
ray_ioctl ( ifp , command , data )
register struct ifnet * ifp ;
u_long command ;
caddr_t data ;
{
struct ray_softc * sc ;
2000-03-12 22:54:29 +00:00
struct ray_param_req pr ;
struct ray_stats_req sr ;
struct ifreq * ifr ;
int s , error , error2 ;
2000-02-20 14:56:17 +00:00
2000-03-05 14:39:23 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: Network ioctl \n " , ifp - > if_unit ) ) ;
2000-02-20 14:56:17 +00:00
sc = ifp - > if_softc ;
2000-02-26 14:49:24 +00:00
RAY_MAP_CM ( sc ) ;
2000-02-20 14:56:17 +00:00
if ( sc - > gone ) {
printf ( " ray%d: unloaded before ioctl! \n " , sc - > unit ) ;
ifp - > if_flags & = ~ IFF_RUNNING ;
2000-03-08 23:28:06 +00:00
return ( ENXIO ) ;
2000-02-20 14:56:17 +00:00
}
2000-03-12 22:54:29 +00:00
ifr = ( struct ifreq * ) data ;
error = 0 ;
error2 = 0 ;
2000-02-20 14:56:17 +00:00
s = splimp ( ) ;
switch ( command ) {
case SIOCSIFADDR :
case SIOCGIFADDR :
case SIOCSIFMTU :
2000-03-05 14:39:23 +00:00
RAY_DPRINTFN ( 30 , ( " ray%d: ioctl SIFADDR/GIFADDR/SIFMTU \n " , sc - > unit ) ) ;
2000-02-20 14:56:17 +00:00
error = ether_ioctl ( ifp , command , data ) ;
break ;
case SIOCSIFFLAGS :
2000-03-05 14:39:23 +00:00
RAY_DPRINTFN ( 30 , ( " ray%d: for SIFFLAGS \n " , sc - > unit ) ) ;
2000-02-20 14:56:17 +00:00
/*
* If the interface is marked up and stopped , then start
* it . If it is marked down and running , then stop it .
*/
if ( ifp - > if_flags & IFF_UP ) {
if ( ! ( ifp - > if_flags & IFF_RUNNING ) )
ray_init ( sc ) ;
2000-03-08 23:28:06 +00:00
ray_update_promisc ( sc ) ;
2000-02-20 14:56:17 +00:00
} else {
if ( ifp - > if_flags & IFF_RUNNING )
ray_stop ( sc ) ;
}
2000-03-08 23:28:06 +00:00
/* XXX DROP THROUGH or not? */
2000-02-20 14:56:17 +00:00
case SIOCADDMULTI :
case SIOCDELMULTI :
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 30 , ( " ray%d: ioctl called for ADDMULTI/DELMULTI \n " , sc - > unit ) ) ;
2000-03-12 22:54:29 +00:00
ray_update_mcast ( sc ) ;
2000-02-20 14:56:17 +00:00
error = 0 ;
break ;
2000-03-12 22:54:29 +00:00
case SIOCSRAYPARAM :
RAY_DPRINTFN ( 30 , ( " ray%d: ioctl called for SRAYPARAM \n " , sc - > unit ) ) ;
2000-03-21 14:27:46 +00:00
if ( ( error = copyin ( ifr - > ifr_data , & pr , sizeof ( pr ) ) ) )
break ;
error = ray_user_update_params ( sc , & pr ) ;
error2 = copyout ( & pr , ifr - > ifr_data , sizeof ( pr ) ) ;
error = error2 ? error2 : error ;
2000-03-12 22:54:29 +00:00
break ;
case SIOCGRAYPARAM :
RAY_DPRINTFN ( 30 , ( " ray%d: ioctl called for GRAYPARAM \n " , sc - > unit ) ) ;
if ( ( error = copyin ( ifr - > ifr_data , & pr , sizeof ( pr ) ) ) )
break ;
error = ray_user_report_params ( sc , & pr ) ;
error2 = copyout ( & pr , ifr - > ifr_data , sizeof ( pr ) ) ;
error = error2 ? error2 : error ;
break ;
case SIOCGRAYSTATS :
RAY_DPRINTFN ( 30 , ( " ray%d: ioctl called for GRAYSTATS \n " , sc - > unit ) ) ;
error = ray_user_report_stats ( sc , & sr ) ;
error2 = copyout ( & sr , ifr - > ifr_data , sizeof ( sr ) ) ;
error = error2 ? error2 : error ;
break ;
2000-03-11 13:25:33 +00:00
case SIOCGIFFLAGS :
RAY_DPRINTFN ( 30 , ( " ray%d: ioctl called for GIFFLAGS \n " , sc - > unit ) ) ;
error = EINVAL ;
break ;
case SIOCGIFMETRIC :
RAY_DPRINTFN ( 30 , ( " ray%d: ioctl called for GIFMETRIC \n " , sc - > unit ) ) ;
error = EINVAL ;
break ;
case SIOCGIFMTU :
RAY_DPRINTFN ( 30 , ( " ray%d: ioctl called for GIFMTU \n " , sc - > unit ) ) ;
error = EINVAL ;
break ;
case SIOCGIFPHYS :
RAY_DPRINTFN ( 30 , ( " ray%d: ioctl called for GIFPYHS \n " , sc - > unit ) ) ;
error = EINVAL ;
break ;
case SIOCSIFMEDIA :
RAY_DPRINTFN ( 30 , ( " ray%d: ioctl called for SIFMEDIA \n " , sc - > unit ) ) ;
error = EINVAL ;
break ;
case SIOCGIFMEDIA :
RAY_DPRINTFN ( 30 , ( " ray%d: ioctl called for GIFMEDIA \n " , sc - > unit ) ) ;
error = EINVAL ;
break ;
2000-02-26 14:49:24 +00:00
2000-02-20 14:56:17 +00:00
default :
error = EINVAL ;
}
2000-03-05 14:39:23 +00:00
splx ( s ) ;
2000-02-20 14:56:17 +00:00
2000-03-08 23:28:06 +00:00
return ( error ) ;
2000-02-20 14:56:17 +00:00
}
2000-03-08 23:28:06 +00:00
/*
* Network start .
*
* Start sending a packet .
*
* We make two assumptions here :
* 1 ) That the current priority is set to splimp _before_ this code
* is called * and * is returned to the appropriate priority after
* return
* 2 ) That the IFF_OACTIVE flag is checked before this code is called
* ( i . e . that the output part of the interface is idle )
*/
2000-02-20 14:56:17 +00:00
static void
2000-03-08 23:28:06 +00:00
ray_start ( ifp )
struct ifnet * ifp ;
2000-02-20 14:56:17 +00:00
{
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_start \n " , ifp - > if_unit ) ) ;
2000-02-20 14:56:17 +00:00
2000-03-08 23:28:06 +00:00
ray_start_sc ( ifp - > if_softc ) ;
2000-02-20 14:56:17 +00:00
}
static void
2000-03-08 23:28:06 +00:00
ray_start_sc ( sc )
struct ray_softc * sc ;
2000-02-20 14:56:17 +00:00
{
2000-02-26 14:49:24 +00:00
struct ifnet * ifp ;
2000-03-08 23:28:06 +00:00
struct mbuf * m0 , * m ;
struct ether_header * eh ;
size_t ccs , bufp ;
int i , pktlen , len ;
u_int8_t status ;
2000-02-20 14:56:17 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_start_sc \n " , sc - > unit ) ) ;
2000-02-26 14:49:24 +00:00
RAY_MAP_CM ( sc ) ;
2000-02-20 14:56:17 +00:00
2000-03-08 23:28:06 +00:00
ifp = & sc - > arpcom . ac_if ;
/*
* Some simple checks first
*/
2000-02-20 14:56:17 +00:00
if ( sc - > gone ) {
2000-03-08 23:28:06 +00:00
printf ( " ray%d: unloaded before start! \n " , sc - > unit ) ;
2000-02-20 14:56:17 +00:00
return ;
}
2000-03-08 23:28:06 +00:00
if ( ( ifp - > if_flags & IFF_RUNNING ) = = 0 | | ! sc - > sc_havenet )
return ;
if ( ! RAY_ECF_READY ( sc ) ) {
RAY_DPRINTFN ( 1 , ( " ray%d: ray_start busy, schedule a timeout \n " ,
sc - > unit ) ) ;
sc - > start_timerh = timeout ( ray_start_timo , sc , RAY_START_TIMEOUT ) ;
return ;
} else
untimeout ( ray_start_timo , sc , sc - > start_timerh ) ;
2000-02-27 19:52:29 +00:00
2000-02-26 14:49:24 +00:00
/*
2000-03-08 23:28:06 +00:00
* Simple one packet at a time TX routine - probably appaling performance
* and we certainly chew CPU . However bing to windows boxes shows
* a reliance on the far end too :
2000-02-27 19:52:29 +00:00
*
2000-03-08 23:28:06 +00:00
* 1500 k default rate
2000-02-27 19:52:29 +00:00
*
2000-03-08 23:28:06 +00:00
* Libretto 50 CT ( 75 MHz Pentium ) with FreeBSD - 3.1 to
* Nonname box Windows 95 C ( 133 MHz AMD 5 x86 ) 996109 bps
* AST J30 Windows 95 A ( 100 MHz Pentium ) 1307791 bps
2000-02-27 19:52:29 +00:00
*
2000-03-08 23:28:06 +00:00
* 2000 k default rate
2000-03-05 14:39:23 +00:00
*
2000-03-08 23:28:06 +00:00
* Libretto 50 CT ( 75 MHz Pentium ) with FreeBSD - 3.1 to
* Nonname box Windows 95 C ( 133 MHz AMD 5 x86 ) 1087049 bps
* AST J30 Windows 95 A ( 100 MHz Pentium ) 1307791 bps
*
* Flow is
* get a ccs
* build the packet
* set IFF_OACTIVE
* interrupt the card to send the packet
* exit
*
* wait for interrupt telling us the packet has been sent
* clear IFF_OACTIVE
* get called by the interrupt routine if any packets left
2000-02-26 14:49:24 +00:00
*/
2000-02-27 19:52:29 +00:00
2000-02-26 14:49:24 +00:00
/*
2000-03-08 23:28:06 +00:00
* Find a free ccs ; if none available wave good bye and exit .
*
* We find a ccs before we process the mbuf so that we are sure it
* is worthwhile processing the packet . All errors in the mbuf
* processing are either errors in the mbuf or gross configuration
* errors and the packet wouldn ' t get through anyway .
*
* Don ' t forget to clear the ccs on errors .
2000-02-26 14:49:24 +00:00
*/
2000-03-08 23:28:06 +00:00
i = RAY_CCS_TX_FIRST ;
do {
status = SRAM_READ_FIELD_1 ( sc , RAY_CCS_ADDRESS ( i ) , ray_cmd , c_status ) ;
if ( status = = RAY_CCS_STATUS_FREE )
break ;
i + + ;
} while ( i < = RAY_CCS_TX_LAST ) ;
if ( i > RAY_CCS_TX_LAST ) {
ifp - > if_flags | = IFF_OACTIVE ;
return ;
}
RAY_DPRINTFN ( 20 , ( " ray%d: ray_start using ccs 0x%02x \n " , sc - > unit , i ) ) ;
/*
* Reserve and fill the ccs - must do the length later .
*
* Even though build 4 and build 5 have different fields all these
2000-03-21 14:27:46 +00:00
* are common apart from tx_rate . Neither the NetBSD driver or Linux
* driver bother to overwrite this for build 4 cards .
2000-03-08 23:28:06 +00:00
*/
ccs = RAY_CCS_ADDRESS ( i ) ;
bufp = RAY_TX_BASE + i * RAY_TX_BUF_SIZE ;
bufp + = sc - > sc_tibsize ;
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd_tx , c_status , RAY_CCS_STATUS_BUSY ) ;
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd_tx , c_cmd , RAY_CMD_TX_REQ ) ;
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd_tx , c_link , RAY_CCS_LINK_NULL ) ;
SRAM_WRITE_FIELD_2 ( sc , ccs , ray_cmd_tx , c_bufp , bufp ) ;
2000-03-11 13:25:33 +00:00
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd_tx , c_tx_rate , sc - > sc_c . np_def_txrate ) ;
2000-03-21 14:27:46 +00:00
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd_tx , c_apm_mode , 0 ) ; /* XXX */
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd_tx , c_antenna , 0 ) ; /* XXX */
2000-03-08 23:28:06 +00:00
bufp + = sizeof ( struct ray_tx_phy_header ) ;
/*
* Get the mbuf and process it - we have to remember to free the
* ccs if there are any errors
*/
IF_DEQUEUE ( & ifp - > if_snd , m0 ) ;
if ( m0 = = NULL ) {
RAY_CCS_FREE ( sc , ccs ) ;
return ;
}
for ( pktlen = 0 , m = m0 ; m ! = NULL ; m = m - > m_next ) {
pktlen + = m - > m_len ;
}
if ( pktlen > ETHER_MAX_LEN - ETHER_CRC_LEN ) {
RAY_DPRINTFN ( 1 , ( " ray%d: mbuf too long %d \n " , sc - > unit , pktlen ) ) ;
RAY_CCS_FREE ( sc , ccs ) ;
ifp - > if_oerrors + + ;
m_freem ( m0 ) ;
return ;
}
/* XXX
* I would much prefer to have the complete 802.11 packet dropped to
* the bpf tap and then have a user land program parse the headers
* as needed . This way , tcpdump - w can be used to grab the raw data . If
* needed the 802.11 aware program can " translate " the .11 to ethernet
* for tcpdump - r .
*/
# if NBPFILTER > 0
if ( ifp - > if_bpf )
bpf_mtap ( ifp , m0 ) ;
# endif /* NBPFILTER */
/*
* Translation - capability as described earlier
*
* Each case must write the 802.11 header using ray_start_wrhdr ,
* passing a pointer to the ethernet header in and getting a new
* tc buffer pointer . Next remove / modify / addto the 802.3 and 802.2
* headers as needed .
*
* We ' ve pulled up the mbuf for you .
*
*/
if ( m0 - > m_len < sizeof ( struct ether_header ) )
m = m_pullup ( m , sizeof ( struct ether_header ) ) ;
if ( m0 = = NULL ) {
RAY_DPRINTFN ( 1 , ( " ray%d: ray_start could not pullup ether \n " , sc - > unit ) ) ;
RAY_CCS_FREE ( sc , ccs ) ;
ifp - > if_oerrors + + ;
return ;
}
eh = mtod ( m0 , struct ether_header * ) ;
switch ( sc - > translation ) {
case SC_TRANSLATE_WEBGEAR :
bufp = ray_start_wrhdr ( sc , eh , bufp ) ;
break ;
default :
printf ( " ray%d: ray_start unknown translation type 0x%x - why? \n " ,
sc - > unit , sc - > translation ) ;
RAY_CCS_FREE ( sc , ccs ) ;
ifp - > if_oerrors + + ;
m0 = m_free ( m0 ) ;
return ;
}
if ( m0 = = NULL ) {
RAY_DPRINTFN ( 1 , ( " ray%d: ray_start could not translate mbuf \n " , sc - > unit ) ) ;
RAY_CCS_FREE ( sc , ccs ) ;
ifp - > if_oerrors + + ;
return ;
}
pktlen = sizeof ( struct ieee80211_header ) ;
/*
* Copy the mbuf to the buffer in common memory
*
* We panic and don ' t bother wrapping as ethernet packets are 1518
* bytes , we checked the mbuf earlier , and our TX buffers are 2048
* bytes . We don ' t have 530 bytes of headers etc . so something
* must be fubar .
*/
for ( m = m0 ; m ! = NULL ; m = m - > m_next ) {
pktlen + = m - > m_len ;
if ( ( len = m - > m_len ) = = 0 )
continue ;
if ( ( bufp + len ) < RAY_TX_END )
ray_write_region ( sc , bufp , mtod ( m , u_int8_t * ) , len ) ;
else
panic ( " ray%d: ray_start tx buffer overflow \n " , sc - > unit ) ;
bufp + = len ;
}
RAY_DMBUF_DUMP ( sc , m0 , " ray_start " ) ;
m_free ( m0 ) ;
/*
* Fill in a few loose ends and kick the card to send the packet
*/
if ( ! RAY_ECF_READY ( sc ) ) {
/*
* From NetBSD code :
*
* If this can really happen perhaps we need to save
* the chain and use it later . I think this might
* be a confused state though because we check above
* and don ' t issue any commands between .
*/
printf ( " ray%d: ray_tx device busy \n " , sc - > unit ) ;
RAY_CCS_FREE ( sc , ccs ) ;
ifp - > if_oerrors + + ;
return ;
}
SRAM_WRITE_FIELD_2 ( sc , ccs , ray_cmd_tx , c_len , pktlen ) ;
SRAM_WRITE_1 ( sc , RAY_SCB_CCSI , ccs ) ;
ifp - > if_opackets + + ;
ifp - > if_flags | = IFF_OACTIVE ;
RAY_ECF_START_CMD ( sc ) ;
return ;
}
# if XXX_NETBSDTX
netbsd
driver uses a loop
repeat
get a ccs
get a mbuf
translate and send packet to shared ram
until ( no more ccs ' s ) | | ( no more mbuf ' s )
send ccs chain to card
exit
Linux
driver is simple single shot packet ( with a lot of spinlocks ! )
general
the tx space is 0x7000 = 28 kB , and TX buffer size is 2048 so there
can be 14 requests at 2 kB each
from this 2 k we have to remove the TIB - whatever that is - for data
netbsd :
we need to call _start after receiveing a packet to see
if any packets were queued whilst in the interrupt
there is a potential race in obtaining ccss for the tx , in that
we might be in _start synchronously and then an rx interrupt
occurs . the rx will call _start and steal tx ccs from underneath
the interrupted entry .
toptions
dont call _start from rx interrupt
find a safe way of locking
find a better way of obtaining ccs using next free avilable ?
look at other drivers
use tsleep / wakeup
some form of ring to hold ccs
free lsit
rework calling
# endif XXX_NETBSDTX
/*
* TX completion routine .
*
* Clear ccs and network flags .
*/
static void
ray_start_done ( sc , ccs , status )
struct ray_softc * sc ;
size_t ccs ;
u_int8_t status ;
{
struct ifnet * ifp ;
char * status_string [ ] = RAY_CCS_STATUS_STRINGS ;
RAY_DPRINTFN ( 5 , ( " ray%d: ray_start_done \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
ifp = & sc - > arpcom . ac_if ;
if ( status ! = RAY_CCS_STATUS_COMPLETE ) {
printf ( " ray%d: ray_start tx completed but status is %s. \n " ,
sc - > unit , status_string [ status ] ) ;
ifp - > if_oerrors + + ;
}
RAY_CCS_FREE ( sc , ccs ) ;
ifp - > if_timer = 0 ;
if ( ifp - > if_flags & IFF_OACTIVE )
ifp - > if_flags & = ~ IFF_OACTIVE ;
return ;
}
/*
* Start timeout routine .
*
* Used when card was busy but we needed to send a packet .
*/
static void
ray_start_timo ( xsc )
void * xsc ;
{
struct ray_softc * sc = xsc ;
struct ifnet * ifp ;
int s ;
RAY_DPRINTFN ( 5 , ( " ray%d: ray_start_timo \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
ifp = & sc - > arpcom . ac_if ;
if ( ! ( ifp - > if_flags & IFF_OACTIVE ) & & ( ifp - > if_snd . ifq_head ! = NULL ) ) {
s = splimp ( ) ;
ray_start ( ifp ) ;
splx ( s ) ;
}
return ;
}
/*
* Write an 802.11 header into the TX buffer and return the
* adjusted buffer pointer .
*/
static size_t
ray_start_wrhdr ( sc , eh , bufp )
struct ray_softc * sc ;
struct ether_header * eh ;
size_t bufp ;
{
struct ieee80211_header header ;
RAY_DPRINTFN ( 5 , ( " ray%d: ray_start_wrhdr \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
bzero ( & header , sizeof ( struct ieee80211_header ) ) ;
header . i_fc [ 0 ] = ( IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA ) ;
2000-03-11 13:25:33 +00:00
if ( sc - > sc_c . np_net_type = = RAY_MIB_NET_TYPE_ADHOC ) {
2000-03-08 23:28:06 +00:00
header . i_fc [ 1 ] = IEEE80211_FC1_STA_TO_STA ;
bcopy ( eh - > ether_dhost , header . i_addr1 , ETHER_ADDR_LEN ) ;
bcopy ( eh - > ether_shost , header . i_addr2 , ETHER_ADDR_LEN ) ;
2000-03-11 13:25:33 +00:00
bcopy ( sc - > sc_c . np_bss_id , header . i_addr3 , ETHER_ADDR_LEN ) ;
2000-03-08 23:28:06 +00:00
} else {
2000-03-11 13:25:33 +00:00
if ( sc - > sc_c . np_ap_status = = RAY_MIB_AP_STATUS_TERMINAL ) {
2000-03-08 23:28:06 +00:00
header . i_fc [ 1 ] = IEEE80211_FC1_STA_TO_AP ;
2000-03-11 13:25:33 +00:00
bcopy ( sc - > sc_c . np_bss_id , header . i_addr1 , ETHER_ADDR_LEN ) ;
2000-03-08 23:28:06 +00:00
bcopy ( eh - > ether_shost , header . i_addr2 , ETHER_ADDR_LEN ) ;
bcopy ( eh - > ether_dhost , header . i_addr3 , ETHER_ADDR_LEN ) ;
} else
printf ( " ray%d: ray_start can't be an AP yet \n " , sc - > unit ) ;
2000-02-26 14:49:24 +00:00
}
2000-03-08 23:28:06 +00:00
ray_write_region ( sc , bufp , ( u_int8_t * ) & header ,
sizeof ( struct ieee80211_header ) ) ;
return ( bufp + sizeof ( struct ieee80211_header ) ) ;
}
/*
2000-03-21 14:27:46 +00:00
* receive a packet from the card
2000-03-08 23:28:06 +00:00
*/
static void
ray_rx ( sc , rcs )
struct ray_softc * sc ;
size_t rcs ;
{
struct ieee80211_header * header ;
struct ether_header * eh ;
struct ifnet * ifp ;
struct mbuf * m0 ;
size_t pktlen , fraglen , readlen , tmplen ;
size_t bufp , ebufp ;
u_int8_t * dst , * src ;
u_int8_t fc ;
u_int first , ni , i ;
RAY_DPRINTFN ( 5 , ( " ray%d: ray_rx \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
RAY_DPRINTFN ( 20 , ( " ray%d: rcs chain - using rcs 0x%x \n " , sc - > unit , rcs ) ) ;
ifp = & sc - > arpcom . ac_if ;
m0 = NULL ;
readlen = 0 ;
2000-02-26 14:49:24 +00:00
/*
2000-03-08 23:28:06 +00:00
* Get first part of packet and the length . Do some sanity checks
* and get a mbuf .
2000-02-26 14:49:24 +00:00
*/
2000-03-08 23:28:06 +00:00
first = RAY_CCS_INDEX ( rcs ) ;
pktlen = SRAM_READ_FIELD_2 ( sc , rcs , ray_cmd_rx , c_pktlen ) ;
if ( ( pktlen > MCLBYTES ) | | ( pktlen < sizeof ( struct ieee80211_header ) ) ) {
RAY_DPRINTFN ( 1 , ( " ray%d: ray_rx packet is too big or too small \n " ,
sc - > unit ) ) ;
ifp - > if_ierrors + + ;
goto skip_read ;
}
MGETHDR ( m0 , M_DONTWAIT , MT_DATA ) ;
if ( m0 = = NULL ) {
RAY_DPRINTFN ( 1 , ( " ray%d: ray_rx MGETHDR failed \n " , sc - > unit ) ) ;
ifp - > if_ierrors + + ;
goto skip_read ;
}
if ( pktlen > MHLEN ) {
MCLGET ( m0 , M_DONTWAIT ) ;
if ( ( m0 - > m_flags & M_EXT ) = = 0 ) {
RAY_DPRINTFN ( 1 , ( " ray%d: ray_rx MCLGET failed \n " , sc - > unit ) ) ;
ifp - > if_ierrors + + ;
m_freem ( m0 ) ;
m0 = NULL ;
goto skip_read ;
}
}
m0 - > m_pkthdr . rcvif = ifp ;
m0 - > m_pkthdr . len = pktlen ;
m0 - > m_len = pktlen ;
dst = mtod ( m0 , u_int8_t * ) ;
2000-02-26 14:49:24 +00:00
/*
2000-03-08 23:28:06 +00:00
* Walk the fragment chain to build the complete packet .
*
* The use of two index variables removes a race with the
* hardware . If one index were used the clearing of the CCS would
* happen before reading the next pointer and the hardware can get in .
* Not my idea but verbatim from the NetBSD driver .
2000-02-26 14:49:24 +00:00
*/
2000-03-08 23:28:06 +00:00
i = ni = first ;
while ( ( i = ni ) & & ( i ! = RAY_CCS_LINK_NULL ) ) {
rcs = RAY_CCS_ADDRESS ( i ) ;
ni = SRAM_READ_FIELD_1 ( sc , rcs , ray_cmd_rx , c_nextfrag ) ;
bufp = SRAM_READ_FIELD_2 ( sc , rcs , ray_cmd_rx , c_bufp ) ;
fraglen = SRAM_READ_FIELD_2 ( sc , rcs , ray_cmd_rx , c_len ) ;
RAY_DPRINTFN ( 50 , ( " ray%d: ray_rx frag index %d len %d bufp 0x%x ni %d \n " ,
sc - > unit , i , fraglen , ( int ) bufp , ni ) ) ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
if ( fraglen + readlen > pktlen ) {
RAY_DPRINTFN ( 1 , ( " ray%d: ray_rx bad length current 0x%x pktlen 0x%x \n " ,
sc - > unit , fraglen + readlen , pktlen ) ) ;
ifp - > if_ierrors + + ;
m_freem ( m0 ) ;
m0 = NULL ;
goto skip_read ;
}
if ( ( i < RAY_RCS_FIRST ) | | ( i > RAY_RCS_LAST ) ) {
printf ( " ray%d: ray_rx bad rcs index 0x%x \n " , sc - > unit , i ) ;
ifp - > if_ierrors + + ;
m_freem ( m0 ) ;
m0 = NULL ;
goto skip_read ;
}
ebufp = bufp + fraglen ;
if ( ebufp < = RAY_RX_END )
ray_read_region ( sc , bufp , dst , fraglen ) ;
else {
ray_read_region ( sc , bufp , dst , ( tmplen = RAY_RX_END - bufp ) ) ;
ray_read_region ( sc , RAY_RX_BASE , dst + tmplen , ebufp - RAY_RX_END ) ;
}
dst + = fraglen ;
readlen + = fraglen ;
}
skip_read :
/*
* Walk the chain again to free the rcss .
*/
i = ni = first ;
while ( ( i = ni ) & & ( i ! = RAY_CCS_LINK_NULL ) ) {
rcs = RAY_CCS_ADDRESS ( i ) ;
ni = SRAM_READ_FIELD_1 ( sc , rcs , ray_cmd_rx , c_nextfrag ) ;
RAY_CCS_FREE ( sc , rcs ) ;
}
if ( m0 = = NULL )
return ;
RAY_DMBUF_DUMP ( sc , m0 , " ray_rx " ) ;
/*
* Check the 802.11 packet type and obtain the .11 src addresses .
*
* XXX CTL and MGT packets will have separate functions , DATA with here
*
* XXX This needs some work for INFRA mode
*/
header = mtod ( m0 , struct ieee80211_header * ) ;
fc = header - > i_fc [ 0 ] ;
if ( ( fc & IEEE80211_FC0_VERSION_MASK ) ! = IEEE80211_FC0_VERSION_0 ) {
RAY_DPRINTFN ( 1 , ( " ray%d: header not version 0 fc 0x%x \n " , sc - > unit , fc ) ) ;
ifp - > if_ierrors + + ;
m_freem ( m0 ) ;
return ;
}
switch ( fc & IEEE80211_FC0_TYPE_MASK ) {
case IEEE80211_FC0_TYPE_MGT :
printf ( " ray%d: ray_rx got a MGT packet - why? \n " , sc - > unit ) ;
ifp - > if_ierrors + + ;
m_freem ( m0 ) ;
return ;
case IEEE80211_FC0_TYPE_CTL :
printf ( " ray%d: ray_rx got a CTL packet - why? \n " , sc - > unit ) ;
ifp - > if_ierrors + + ;
m_freem ( m0 ) ;
return ;
case IEEE80211_FC0_TYPE_DATA :
RAY_DPRINTFN ( 50 , ( " ray%d: ray_rx got a DATA packet \n " , sc - > unit ) ) ;
break ;
default :
printf ( " ray%d: ray_rx got a unknown packet fc0 0x%x - why? \n " ,
sc - > unit , fc ) ;
ifp - > if_ierrors + + ;
m_freem ( m0 ) ;
return ;
}
fc = header - > i_fc [ 1 ] ;
switch ( fc & IEEE80211_FC1_DS_MASK ) {
case IEEE80211_FC1_STA_TO_STA :
src = header - > i_addr2 ;
RAY_DPRINTFN ( 50 , ( " ray%d: ray_rx packet from sta %6D \n " ,
sc - > unit , src , " : " ) ) ;
break ;
case IEEE80211_FC1_STA_TO_AP :
RAY_DPRINTFN ( 1 , ( " ray%d: ray_rx packet from sta %6D to ap %6D \n " ,
sc - > unit ,
header - > i_addr2 , " : " , header - > i_addr3 , " : " ) ) ;
ifp - > if_ierrors + + ;
m_freem ( m0 ) ;
break ;
case IEEE80211_FC1_AP_TO_STA :
RAY_DPRINTFN ( 1 , ( " ray%d: ray_rx packet from ap %6D \n " ,
sc - > unit ,
header - > i_addr3 , " : " ) ) ;
ifp - > if_ierrors + + ;
m_freem ( m0 ) ;
break ;
case IEEE80211_FC1_AP_TO_AP :
RAY_DPRINTFN ( 1 , ( " ray%d: ray_rx saw packet between aps %6D %6D \n " ,
sc - > unit ,
header - > i_addr1 , " : " , header - > i_addr2 , " : " ) ) ;
ifp - > if_ierrors + + ;
m_freem ( m0 ) ;
return ;
default :
printf ( " ray%d: ray_rx packet type unknown fc1 0x%x - why? \n " ,
sc - > unit , fc ) ;
ifp - > if_ierrors + + ;
m_freem ( m0 ) ;
return ;
}
/*
* Translation - capability as described earlier
*
* Each case must remove the 802.11 header and leave an 802.3
* header in the mbuf copy addresses as needed .
*/
switch ( sc - > translation ) {
case SC_TRANSLATE_WEBGEAR :
/* Nice and easy - just trim the 802.11 header */
m_adj ( m0 , sizeof ( struct ieee80211_header ) ) ;
break ;
default :
printf ( " ray%d: ray_rx unknown translation type 0x%x - why? \n " ,
sc - > unit , sc - > translation ) ;
ifp - > if_ierrors + + ;
m_freem ( m0 ) ;
return ;
}
/*
* Finally , do a bit of house keeping before sending the packet
* up the stack .
*/
ifp - > if_ipackets + + ;
# if NBPFILTER > 0
if ( ifp - > if_bpf )
bpf_mtap ( ifp , m0 ) ;
# endif /* NBPFILTER */
# if XXX_PROM
if_wi . c - might be needed if we hear our own broadcasts in promiscuous mode
but will not be if we dont see them
if ( ( ifp - > if_flags & IFF_PROMISC ) & &
( bcmp ( eh - > ether_shost , sc - > arpcom . ac_enaddr , ETHER_ADDR_LEN ) & &
( eh - > ether_dhost [ 0 ] & 1 ) = = 0 )
) {
m_freem ( m0 ) ;
return ;
}
# endif /* XXX_PROM */
eh = mtod ( m0 , struct ether_header * ) ;
m_adj ( m0 , sizeof ( struct ether_header ) ) ;
ether_input ( ifp , eh , m0 ) ;
2000-02-20 14:56:17 +00:00
return ;
}
2000-03-08 23:28:06 +00:00
/******************************************************************************
* XXX NOT KNF FROM HERE UP
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-02-20 14:56:17 +00:00
/*
2000-03-08 23:28:06 +00:00
* an update params command has completed lookup which command and
* the status
2000-03-05 22:24:30 +00:00
*
2000-03-08 23:28:06 +00:00
* XXX this isn ' t finished yet , we need to grok the command used
2000-02-20 14:56:17 +00:00
*/
static void
2000-03-08 23:28:06 +00:00
ray_update_params_done ( struct ray_softc * sc , size_t ccs , u_int stat )
2000-02-20 14:56:17 +00:00
{
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_update_params_done \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
2000-03-05 22:24:30 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 20 , ( " ray%d: ray_update_params_done stat %d \n " ,
sc - > unit , stat ) ) ;
2000-02-20 14:56:17 +00:00
2000-03-08 23:28:06 +00:00
/* this will get more complex as we add commands */
if ( stat = = RAY_CCS_STATUS_FAIL ) {
printf ( " ray%d: failed to update a promisc \n " , sc - > unit ) ;
/* XXX should probably reset */
/* rcmd = ray_reset; */
}
2000-03-05 22:24:30 +00:00
2000-03-08 23:28:06 +00:00
if ( sc - > sc_running & SCP_UPD_PROMISC ) {
ray_cmd_done ( sc , SCP_UPD_PROMISC ) ;
sc - > sc_promisc = SRAM_READ_1 ( sc , RAY_HOST_TO_ECF_BASE ) ;
RAY_DPRINTFN ( 20 , ( " ray%d: new promisc value %d \n " , sc - > unit ,
sc - > sc_promisc ) ) ;
} else if ( sc - > sc_updreq ) {
ray_cmd_done ( sc , SCP_UPD_UPDATEPARAMS ) ;
/* get the update parameter */
sc - > sc_updreq - > r_failcause =
SRAM_READ_FIELD_1 ( sc , ccs , ray_cmd_update , c_failcause ) ;
sc - > sc_updreq = 0 ;
wakeup ( ray_update_params ) ;
ray_start_join_net ( sc ) ;
}
2000-03-05 22:24:30 +00:00
}
/*
2000-03-08 23:28:06 +00:00
* check too see if we have any pending commands .
2000-03-05 22:24:30 +00:00
*/
static void
2000-03-08 23:28:06 +00:00
ray_check_scheduled ( void * arg )
2000-03-05 22:24:30 +00:00
{
2000-03-08 23:28:06 +00:00
struct ray_softc * sc ;
int s , i , mask ;
2000-03-05 22:24:30 +00:00
2000-03-08 23:28:06 +00:00
s = splnet ( ) ;
sc = arg ;
2000-03-05 22:24:30 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_check_scheduled \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
2000-03-05 22:24:30 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 20 , (
" ray%d: ray_check_scheduled schd 0x%x running 0x%x ready %d \n " ,
sc - > unit , sc - > sc_scheduled , sc - > sc_running , RAY_ECF_READY ( sc ) ) ) ;
2000-03-05 22:24:30 +00:00
2000-03-08 23:28:06 +00:00
if ( sc - > sc_timoneed ) {
untimeout ( ray_check_scheduled , sc , sc - > ccs_timerh ) ;
sc - > sc_timoneed = 0 ;
}
2000-03-05 22:24:30 +00:00
2000-03-08 23:28:06 +00:00
/* if update subcmd is running -- clear it in scheduled */
if ( sc - > sc_running & SCP_UPDATESUBCMD )
sc - > sc_scheduled & = ~ SCP_UPDATESUBCMD ;
mask = SCP_FIRST ;
for ( i = 0 ; i < ray_ncmdtab ; mask < < = 1 , i + + ) {
if ( ( sc - > sc_scheduled & ~ SCP_UPD_MASK ) = = 0 )
break ;
if ( ! RAY_ECF_READY ( sc ) )
break ;
if ( sc - > sc_scheduled & mask )
( * ray_cmdtab [ i ] ) ( sc ) ;
}
RAY_DPRINTFN ( 20 , (
" ray%d: ray_check_scheduled sched 0x%x running 0x%x ready %d \n " ,
sc - > unit , sc - > sc_scheduled , sc - > sc_running , RAY_ECF_READY ( sc ) ) ) ;
if ( sc - > sc_scheduled & ~ SCP_UPD_MASK )
ray_set_pending ( sc , sc - > sc_scheduled ) ;
splx ( s ) ;
2000-03-05 22:24:30 +00:00
}
/*
2000-03-08 23:28:06 +00:00
* check for unreported returns
*
* this routine is coded to only expect one outstanding request for the
* timed out requests at a time , but thats all that can be outstanding
* per hardware limitations
2000-03-05 22:24:30 +00:00
*/
static void
2000-03-08 23:28:06 +00:00
ray_check_ccs ( void * arg )
2000-03-05 22:24:30 +00:00
{
2000-03-08 23:28:06 +00:00
struct ray_softc * sc ;
u_int i , cmd , stat ;
size_t ccs ;
int s ;
s = splnet ( ) ;
sc = arg ;
RAY_DPRINTFN ( 5 , ( " ray%d: ray_check_ccs \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
ccs = 0 ;
stat = RAY_CCS_STATUS_FAIL ;
sc - > sc_timocheck = 0 ;
for ( i = RAY_CCS_CMD_FIRST ; i < = RAY_CCS_CMD_LAST ; i + + ) {
if ( ! sc - > sc_ccsinuse [ i ] )
continue ;
ccs = RAY_CCS_ADDRESS ( i ) ;
cmd = SRAM_READ_FIELD_1 ( sc , ccs , ray_cmd , c_cmd ) ;
switch ( cmd ) {
case RAY_CMD_START_PARAMS :
case RAY_CMD_UPDATE_MCAST :
case RAY_CMD_UPDATE_PARAMS :
stat = SRAM_READ_FIELD_1 ( sc , ccs , ray_cmd , c_status ) ;
RAY_DPRINTFN ( 20 , ( " ray%d: check ccs idx %d ccs 0x%x "
" cmd 0x%x stat %d \n " , sc - > unit , i ,
ccs , cmd , stat ) ) ;
goto breakout ;
}
}
breakout :
/* see if we got one of the commands we are looking for */
if ( i > RAY_CCS_CMD_LAST )
; /* nothign */
else if ( stat = = RAY_CCS_STATUS_FREE ) {
stat = RAY_CCS_STATUS_COMPLETE ;
ray_ccs_done ( sc , ccs ) ;
} else if ( stat ! = RAY_CCS_STATUS_BUSY ) {
if ( sc - > sc_ccsinuse [ i ] = = 1 ) {
/* give a chance for the interrupt to occur */
sc - > sc_ccsinuse [ i ] = 2 ;
if ( ! sc - > sc_timocheck ) {
sc - > ccs_timerh = timeout ( ray_check_ccs , sc , 1 ) ;
sc - > sc_timocheck = 1 ;
}
} else
ray_ccs_done ( sc , ccs ) ;
} else {
sc - > ccs_timerh = timeout ( ray_check_ccs , sc , RAY_CCS_TIMEOUT ) ;
sc - > sc_timocheck = 1 ;
}
splx ( s ) ;
}
2000-03-05 22:24:30 +00:00
2000-03-08 23:28:06 +00:00
/*
* read the counters , the card implements the following protocol
* to keep the values from being changed while read : It checks
* the ` own ' bit and if zero writes the current internal counter
* value , it then sets the ` own ' bit to 1. If the ` own ' bit was 1 it
* incremenets its internal counter . The user thus reads the counter
* if the ` own ' bit is one and then sets the own bit to 0.
*/
static void
ray_update_error_counters ( struct ray_softc * sc )
{
size_t csc ;
2000-03-05 22:24:30 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_update_error_counters \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
/* try and update the error counters */
csc = RAY_STATUS_BASE ;
if ( SRAM_READ_FIELD_1 ( sc , csc , ray_csc , csc_mrxo_own ) ) {
sc - > sc_rxoverflow + =
SRAM_READ_FIELD_2 ( sc , csc , ray_csc , csc_mrx_overflow ) ;
SRAM_WRITE_FIELD_1 ( sc , csc , ray_csc , csc_mrxo_own , 0 ) ;
}
if ( SRAM_READ_FIELD_1 ( sc , csc , ray_csc , csc_mrxc_own ) ) {
sc - > sc_rxcksum + =
SRAM_READ_FIELD_2 ( sc , csc , ray_csc , csc_mrx_overflow ) ;
SRAM_WRITE_FIELD_1 ( sc , csc , ray_csc , csc_mrxc_own , 0 ) ;
}
if ( SRAM_READ_FIELD_1 ( sc , csc , ray_csc , csc_rxhc_own ) ) {
sc - > sc_rxhcksum + =
SRAM_READ_FIELD_2 ( sc , csc , ray_csc , csc_rx_hcksum ) ;
SRAM_WRITE_FIELD_1 ( sc , csc , ray_csc , csc_rxhc_own , 0 ) ;
}
sc - > sc_rxnoise = SRAM_READ_FIELD_1 ( sc , csc , ray_csc , csc_rx_noise ) ;
2000-02-26 14:49:24 +00:00
}
/*
* Process CCS command completion - called from ray_intr
*/
static void
2000-03-12 22:54:29 +00:00
ray_ccs_done ( struct ray_softc * sc , size_t ccs )
2000-02-26 14:49:24 +00:00
{
2000-03-12 22:54:29 +00:00
u_int cmd , stat ;
2000-02-26 14:49:24 +00:00
2000-03-12 22:54:29 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_ccs_done \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
cmd = SRAM_READ_FIELD_1 ( sc , ccs , ray_cmd , c_cmd ) ;
stat = SRAM_READ_FIELD_1 ( sc , ccs , ray_cmd , c_status ) ;
2000-02-26 14:49:24 +00:00
2000-03-12 22:54:29 +00:00
RAY_DPRINTFN ( 20 , ( " ray%d: ccs idx %d ccs 0x%x cmd 0x%x status %d \n " ,
sc - > unit , RAY_CCS_INDEX ( ccs ) , ccs , cmd , stat ) ) ;
2000-03-08 23:28:06 +00:00
2000-03-12 22:54:29 +00:00
switch ( cmd ) {
2000-02-26 14:49:24 +00:00
case RAY_CMD_START_PARAMS :
2000-03-12 22:54:29 +00:00
RAY_DPRINTFN ( 20 , ( " ray%d: ray_ccs_done got START_PARAMS \n " ,
sc - > unit ) ) ;
ray_download_done ( sc ) ;
break ;
2000-02-26 14:49:24 +00:00
case RAY_CMD_UPDATE_PARAMS :
2000-03-12 22:54:29 +00:00
RAY_DPRINTFN ( 20 , ( " ray%d: ray_ccs_done got UPDATE_PARAMS \n " ,
2000-03-05 14:39:23 +00:00
sc - > unit ) ) ;
2000-03-12 22:54:29 +00:00
ray_update_params_done ( sc , ccs , stat ) ;
break ;
2000-02-26 14:49:24 +00:00
case RAY_CMD_REPORT_PARAMS :
2000-03-12 22:54:29 +00:00
RAY_DPRINTFN ( 20 , ( " ray%d: ray_ccs_done got REPORT_PARAMS \n " ,
2000-03-05 14:39:23 +00:00
sc - > unit ) ) ;
2000-03-12 22:54:29 +00:00
/* get the reported parameters */
ray_cmd_done ( sc , SCP_REPORTPARAMS ) ;
if ( ! sc - > sc_repreq )
break ;
sc - > sc_repreq - > r_failcause =
SRAM_READ_FIELD_1 ( sc , ccs , ray_cmd_report , c_failcause ) ;
sc - > sc_repreq - > r_len =
SRAM_READ_FIELD_1 ( sc , ccs , ray_cmd_report , c_len ) ;
ray_read_region ( sc , RAY_ECF_TO_HOST_BASE , sc - > sc_repreq - > r_data ,
sc - > sc_repreq - > r_len ) ;
sc - > sc_repreq = 0 ;
wakeup ( ray_report_params ) ;
break ;
2000-02-26 14:49:24 +00:00
case RAY_CMD_UPDATE_MCAST :
2000-03-12 22:54:29 +00:00
RAY_DPRINTFN ( 20 , ( " ray%d: ray_ccs_done got UPDATE_MCAST \n " ,
2000-03-05 14:39:23 +00:00
sc - > unit ) ) ;
2000-03-12 22:54:29 +00:00
ray_cmd_done ( sc , SCP_UPD_MCAST ) ;
if ( stat = = RAY_CCS_STATUS_FAIL )
ray_reset ( sc ) ;
break ;
2000-02-26 14:49:24 +00:00
case RAY_CMD_START_NET :
case RAY_CMD_JOIN_NET :
2000-03-12 22:54:29 +00:00
RAY_DPRINTFN ( 20 , ( " ray%d: ray_ccs_done got START|JOIN_NET \n " ,
2000-03-05 14:39:23 +00:00
sc - > unit ) ) ;
2000-03-12 22:54:29 +00:00
ray_start_join_done ( sc , ccs , stat ) ;
break ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
case RAY_CMD_TX_REQ :
2000-03-12 22:54:29 +00:00
RAY_DPRINTFN ( 20 , ( " ray%d: ray_ccs_done got TX_REQ \n " ,
2000-03-08 23:28:06 +00:00
sc - > unit ) ) ;
2000-03-12 22:54:29 +00:00
ray_start_done ( sc , ccs , stat ) ;
goto done ;
2000-03-08 23:28:06 +00:00
2000-02-26 14:49:24 +00:00
case RAY_CMD_START_ASSOC :
2000-03-12 22:54:29 +00:00
RAY_DPRINTFN ( 20 , ( " ray%d: ray_ccs_done got START_ASSOC \n " ,
2000-03-05 14:39:23 +00:00
sc - > unit ) ) ;
2000-03-12 22:54:29 +00:00
ray_cmd_done ( sc , SCP_STARTASSOC ) ;
if ( stat = = RAY_CCS_STATUS_FAIL )
ray_start_join_net ( sc ) ; /* XXX check */
else {
sc - > sc_havenet = 1 ;
}
break ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
case RAY_CMD_UPDATE_APM :
2000-03-12 22:54:29 +00:00
RAY_DPRINTFN ( 20 , ( " ray%d: ray_ccs_done got UPDATE_APM \n " ,
2000-03-05 14:39:23 +00:00
sc - > unit ) ) ;
2000-03-12 22:54:29 +00:00
XXX ;
break ;
2000-02-26 14:49:24 +00:00
case RAY_CMD_TEST_MEM :
2000-03-12 22:54:29 +00:00
printf ( " ray%d: ray_ccs_done got TEST_MEM - why? \n " , sc - > unit ) ;
break ;
2000-02-26 14:49:24 +00:00
case RAY_CMD_SHUTDOWN :
2000-03-12 22:54:29 +00:00
printf ( " ray%d: ray_ccs_done got SHUTDOWN - why? \n " , sc - > unit ) ;
break ;
2000-02-26 14:49:24 +00:00
case RAY_CMD_DUMP_MEM :
2000-03-12 22:54:29 +00:00
printf ( " ray%d: ray_ccs_done got DUMP_MEM - why? \n " , sc - > unit ) ;
break ;
2000-02-26 14:49:24 +00:00
case RAY_CMD_START_TIMER :
2000-03-12 22:54:29 +00:00
printf ( " ray%d: ray_ccs_done got START_TIMER - why? \n " ,
sc - > unit ) ;
break ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
default :
2000-03-12 22:54:29 +00:00
printf ( " ray%d: ray_ccs_done unknown command 0x%x \n " ,
sc - > unit , cmd ) ;
break ;
}
2000-03-08 23:28:06 +00:00
2000-03-12 22:54:29 +00:00
ray_free_ccs ( sc , ccs ) ;
2000-03-08 23:28:06 +00:00
done :
2000-03-12 22:54:29 +00:00
/*
* see if needed things can be done now that a command
* has completed
*/
ray_check_scheduled ( sc ) ;
2000-03-08 23:28:06 +00:00
}
/*
* Process ECF command request - called from ray_intr
*/
static void
2000-03-11 13:25:33 +00:00
ray_rcs_intr ( struct ray_softc * sc , size_t rcs )
2000-03-08 23:28:06 +00:00
{
2000-03-11 13:25:33 +00:00
struct ifnet * ifp ;
u_int cmd , status ;
2000-03-08 23:28:06 +00:00
2000-03-11 13:25:33 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_rcs_intr \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
2000-03-08 23:28:06 +00:00
2000-03-11 13:25:33 +00:00
ifp = & sc - > arpcom . ac_if ;
2000-03-08 23:28:06 +00:00
2000-03-11 13:25:33 +00:00
cmd = SRAM_READ_FIELD_1 ( sc , rcs , ray_cmd , c_cmd ) ;
status = SRAM_READ_FIELD_1 ( sc , rcs , ray_cmd , c_status ) ;
RAY_DPRINTFN ( 20 , ( " ray%d: rcs idx %d rcs 0x%x cmd 0x%x status %d \n " ,
sc - > unit , RAY_CCS_INDEX ( rcs ) , rcs , cmd , status ) ) ;
switch ( cmd ) {
2000-03-08 23:28:06 +00:00
case RAY_ECMD_RX_DONE :
2000-03-11 13:25:33 +00:00
RAY_DPRINTFN ( 20 , ( " ray%d: ray_rcs_intr got RX_DONE \n " ,
sc - > unit ) ) ;
ray_rx ( sc , rcs ) ;
break ;
2000-03-08 23:28:06 +00:00
case RAY_ECMD_REJOIN_DONE :
2000-03-11 13:25:33 +00:00
RAY_DPRINTFN ( 20 , ( " ray%d: ray_rcs_intr got REJOIN_DONE \n " ,
2000-03-08 23:28:06 +00:00
sc - > unit ) ) ;
2000-03-11 13:25:33 +00:00
sc - > sc_havenet = 1 ; /* Should not be here but in function */
XXX ;
break ;
2000-03-08 23:28:06 +00:00
case RAY_ECMD_ROAM_START :
2000-03-11 13:25:33 +00:00
RAY_DPRINTFN ( 20 , ( " ray%d: ray_rcs_intr got ROAM_START \n " ,
2000-03-08 23:28:06 +00:00
sc - > unit ) ) ;
2000-03-11 13:25:33 +00:00
sc - > sc_havenet = 0 ; /* Should not be here but in function */
XXX ;
break ;
2000-03-08 23:28:06 +00:00
case RAY_ECMD_JAPAN_CALL_SIGNAL :
2000-03-11 13:25:33 +00:00
printf ( " ray%d: ray_rcs_intr got JAPAN_CALL_SIGNAL - why? \n " ,
2000-03-08 23:28:06 +00:00
sc - > unit ) ;
2000-03-11 13:25:33 +00:00
break ;
2000-03-08 23:28:06 +00:00
default :
2000-03-11 13:25:33 +00:00
printf ( " ray%d: ray_rcs_intr unknown command 0x%x \n " ,
sc - > unit , cmd ) ;
break ;
}
2000-03-08 23:28:06 +00:00
2000-03-11 13:25:33 +00:00
RAY_CCS_FREE ( sc , rcs ) ;
2000-03-08 23:28:06 +00:00
}
/*
* process an interrupt
*/
static int
ray_intr ( struct pccard_devinfo * dev_p )
{
struct ray_softc * sc ;
struct ifnet * ifp ;
int i , count ;
sc = & ray_softc [ dev_p - > isahd . id_unit ] ;
RAY_DPRINTFN ( 5 , ( " ray%d: ray_intr \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
ifp = & sc - > arpcom . ac_if ;
if ( sc - > gone ) {
printf ( " ray%d: unloaded before interrupt! \n " , sc - > unit ) ;
return ( 0 ) ;
}
if ( ( + + sc - > sc_checkcounters % 32 ) = = 0 )
ray_update_error_counters ( sc ) ;
/*
* Check that the interrupt was for us , if so get the rcs / ccs
* and vector on the command contained within it .
*/
if ( ! RAY_HCS_INTR ( sc ) )
count = 0 ;
else {
count = 1 ;
i = SRAM_READ_1 ( sc , RAY_SCB_RCSI ) ;
if ( i < = RAY_CCS_LAST )
ray_ccs_done ( sc , RAY_CCS_ADDRESS ( i ) ) ;
else if ( i < = RAY_RCS_LAST )
ray_rcs_intr ( sc , RAY_CCS_ADDRESS ( i ) ) ;
else
printf ( " ray%d: ray_intr bad ccs index %d \n " , sc - > unit , i ) ;
}
if ( count )
RAY_HCS_CLEAR_INTR ( sc ) ;
RAY_DPRINTFN ( 10 , ( " ray%d: interrupt %s handled \n " ,
sc - > unit , count ? " was " : " not " ) ) ;
/* Send any packets lying around */
if ( ! ( ifp - > if_flags & IFF_OACTIVE ) & & ( ifp - > if_snd . ifq_head ! = NULL ) )
ray_start ( ifp ) ;
return ( count ) ;
}
/*
* Generic CCS handling
*/
# if XXX_NETBSDTX
/*
* free the chain of descriptors - - used for freeing allocated tx chains
*/
static void
ray_free_ccs_chain ( struct ray_softc * sc , u_int ni )
{
u_int i ;
RAY_DPRINTFN ( 5 , ( " ray%d: ray_free_ccs_chain \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
while ( ( i = ni ) ! = RAY_CCS_LINK_NULL ) {
ni = SRAM_READ_FIELD_1 ( sc , RAY_CCS_ADDRESS ( i ) , ray_cmd , c_link ) ;
RAY_CCS_FREE ( sc , RAY_CCS_ADDRESS ( i ) ) ;
}
}
# endif XXX_NETBSDTX
/*
* free up a cmd and return the old status .
* this routine is only used for commands .
*/
static u_int8_t
ray_free_ccs ( struct ray_softc * sc , size_t ccs )
{
u_int8_t stat ;
RAY_DPRINTFN ( 5 , ( " ray%d: ray_free_ccs \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
stat = SRAM_READ_FIELD_1 ( sc , ccs , ray_cmd , c_status ) ;
RAY_CCS_FREE ( sc , ccs ) ;
if ( ccs < = RAY_CCS_ADDRESS ( RAY_CCS_LAST ) )
sc - > sc_ccsinuse [ RAY_CCS_INDEX ( ccs ) ] = 0 ;
RAY_DPRINTFN ( 20 , ( " ray%d: ray_free_ccs freed 0x%02x \n " ,
sc - > unit , RAY_CCS_INDEX ( ccs ) ) ) ;
return ( stat ) ;
}
/*
* Obtain a free ccs buffer .
*
* returns 1 and in ` ccsp ' the bus offset of the free ccs
* or 0 if none are free
*
* If ` track ' is not zero , handles tracking this command
* possibly indicating a callback is needed and setting a timeout
* also if ECF isn ' t ready we terminate earlier to avoid overhead .
*
* this routine is only used for commands
*/
static int
ray_alloc_ccs ( struct ray_softc * sc , size_t * ccsp , u_int cmd , u_int track )
{
size_t ccs ;
u_int i ;
RAY_DPRINTFN ( 5 , ( " ray%d: ray_alloc_ccs \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
/* for tracked commands, if not ready just set pending */
if ( track & & ! RAY_ECF_READY ( sc ) ) {
ray_cmd_schedule ( sc , track ) ;
return ( 0 ) ;
}
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
for ( i = RAY_CCS_CMD_FIRST ; i < = RAY_CCS_CMD_LAST ; i + + ) {
/* probe here to make the card go */
( void ) SRAM_READ_FIELD_1 ( sc , RAY_CCS_ADDRESS ( i ) , ray_cmd ,
c_status ) ;
if ( ! sc - > sc_ccsinuse [ i ] )
break ;
}
if ( i > RAY_CCS_CMD_LAST ) {
if ( track )
ray_cmd_schedule ( sc , track ) ;
return ( 0 ) ;
}
sc - > sc_ccsinuse [ i ] = 1 ;
ccs = RAY_CCS_ADDRESS ( i ) ;
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd , c_status , RAY_CCS_STATUS_BUSY ) ;
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd , c_cmd , cmd ) ;
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd , c_link , RAY_CCS_LINK_NULL ) ;
* ccsp = ccs ;
return ( 1 ) ;
2000-02-26 14:49:24 +00:00
}
/*
2000-03-08 23:28:06 +00:00
* this function sets the pending bit for the command given in ' need '
* and schedules a timeout if none is scheduled already . Any command
* that uses the ` host to ecf ' region must be serialized .
2000-02-26 14:49:24 +00:00
*/
static void
2000-03-08 23:28:06 +00:00
ray_set_pending ( struct ray_softc * sc , u_int cmdf )
2000-02-26 14:49:24 +00:00
{
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_set_pending \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
RAY_DPRINTFN ( 20 , ( " ray%d: ray_set_pending 0x%0x \n " , sc - > unit , cmdf ) ) ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
sc - > sc_scheduled | = cmdf ;
if ( ! sc - > sc_timoneed ) {
RAY_DPRINTFN ( 20 , ( " ray%d: ray_set_pending new timo \n " ,
2000-03-05 14:39:23 +00:00
sc - > unit ) ) ;
2000-03-08 23:28:06 +00:00
sc - > ccs_timerh = timeout ( ray_check_scheduled , sc ,
RAY_CHECK_SCHED_TIMEOUT ) ;
sc - > sc_timoneed = 1 ;
}
2000-02-26 14:49:24 +00:00
}
2000-02-27 19:52:29 +00:00
/*
2000-03-08 23:28:06 +00:00
* schedule the ` cmdf ' for completion later
2000-02-27 19:52:29 +00:00
*/
static void
2000-03-08 23:28:06 +00:00
ray_cmd_schedule ( struct ray_softc * sc , int cmdf )
2000-02-27 19:52:29 +00:00
{
2000-03-08 23:28:06 +00:00
int track ;
RAY_DPRINTFN ( 5 , ( " ray%d: ray_cmd_schedule \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
RAY_DPRINTFN ( 20 , ( " ray%d: ray_cmd_schedule 0x%x \n " , sc - > unit , cmdf ) ) ;
track = cmdf ;
if ( ( cmdf & SCP_UPD_MASK ) = = 0 )
ray_set_pending ( sc , track ) ;
else if ( ray_cmd_is_running ( sc , SCP_UPDATESUBCMD ) ) {
/* don't do timeout mechaniscm if subcmd already going */
sc - > sc_scheduled | = cmdf ;
} else
ray_set_pending ( sc , cmdf | SCP_UPDATESUBCMD ) ;
}
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
/*
* check to see if ` cmdf ' has been scheduled
*/
static int
ray_cmd_is_scheduled ( struct ray_softc * sc , int cmdf )
{
RAY_DPRINTFN ( 5 , ( " ray%d: ray_cmd_is_scheduled \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
RAY_DPRINTFN ( 20 , ( " ray%d: ray_cmd_is_scheduled 0x%x \n " ,
sc - > unit , cmdf ) ) ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
return ( ( sc - > sc_scheduled & cmdf ) ? 1 : 0 ) ;
}
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
/*
* cancel a scheduled command ( not a running one though ! )
*/
static void
ray_cmd_cancel ( struct ray_softc * sc , int cmdf )
{
RAY_DPRINTFN ( 5 , ( " ray%d: ray_cmd_cancel \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
RAY_DPRINTFN ( 20 , ( " ray%d: ray_cmd_cancel 0x%x \n " , sc - > unit , cmdf ) ) ;
sc - > sc_scheduled & = ~ cmdf ;
if ( ( cmdf & SCP_UPD_MASK ) & & ( sc - > sc_scheduled & SCP_UPD_MASK ) = = 0 )
sc - > sc_scheduled & = ~ SCP_UPDATESUBCMD ;
/* if nothing else needed cancel the timer */
if ( sc - > sc_scheduled = = 0 & & sc - > sc_timoneed ) {
untimeout ( ray_check_scheduled , sc , sc - > ccs_timerh ) ;
sc - > sc_timoneed = 0 ;
2000-02-27 19:52:29 +00:00
}
2000-03-08 23:28:06 +00:00
}
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
/*
* called to indicate the ' cmdf ' has been issued
*/
static void
ray_cmd_ran ( struct ray_softc * sc , int cmdf )
{
RAY_DPRINTFN ( 5 , ( " ray%d: ray_cmd_ran \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
RAY_DPRINTFN ( 20 , ( " ray%d: ray_cmd_ran 0x%x \n " , sc - > unit , cmdf ) ) ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
if ( cmdf & SCP_UPD_MASK )
sc - > sc_running | = cmdf | SCP_UPDATESUBCMD ;
else
sc - > sc_running | = cmdf ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
if ( ( cmdf & SCP_TIMOCHECK_CMD_MASK ) & & ! sc - > sc_timocheck ) {
sc - > ccs_timerh = timeout ( ray_check_ccs , sc , RAY_CCS_TIMEOUT ) ;
sc - > sc_timocheck = 1 ;
2000-02-27 19:52:29 +00:00
}
2000-03-08 23:28:06 +00:00
}
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
/*
* check to see if ` cmdf ' has been issued
*/
static int
ray_cmd_is_running ( struct ray_softc * sc , int cmdf )
{
RAY_DPRINTFN ( 5 , ( " ray%d: ray_cmd_is_running \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
RAY_DPRINTFN ( 20 , ( " ray%d: ray_cmd_is_running 0x%x \n " , sc - > unit , cmdf ) ) ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
return ( ( sc - > sc_running & cmdf ) ? 1 : 0 ) ;
}
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
/*
* the given ` cmdf ' that was issued has completed
*/
static void
ray_cmd_done ( struct ray_softc * sc , int cmdf )
{
RAY_DPRINTFN ( 5 , ( " ray%d: ray_cmd_done \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
RAY_DPRINTFN ( 20 , ( " ray%d: ray_cmd_done 0x%x \n " , sc - > unit , cmdf ) ) ;
sc - > sc_running & = ~ cmdf ;
if ( cmdf & SCP_UPD_MASK ) {
sc - > sc_running & = ~ SCP_UPDATESUBCMD ;
if ( sc - > sc_scheduled & SCP_UPD_MASK )
ray_cmd_schedule ( sc , sc - > sc_scheduled & SCP_UPD_MASK ) ;
}
if ( ( sc - > sc_running & SCP_TIMOCHECK_CMD_MASK ) = = 0 & & sc - > sc_timocheck ) {
untimeout ( ray_check_ccs , sc , sc - > ccs_timerh ) ;
sc - > sc_timocheck = 0 ;
}
}
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
/*
* issue the command
* only used for commands not tx
*/
static int
ray_issue_cmd ( struct ray_softc * sc , size_t ccs , u_int track )
{
u_int i ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_cmd_issue \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
/*
* XXX other drivers did this , but I think
* what we really want to do is just make sure we don ' t
* get here or that spinning is ok
*/
i = 0 ;
while ( ! RAY_ECF_READY ( sc ) )
if ( + + i > 50 ) {
printf ( " \n " ) ;
( void ) ray_free_ccs ( sc , ccs ) ;
if ( track )
ray_cmd_schedule ( sc , track ) ;
return ( 0 ) ;
} else if ( i = = 1 )
printf ( " ray%d: ray_issue_cmd spinning " , sc - > unit ) ;
else
printf ( " . " ) ;
SRAM_WRITE_1 ( sc , RAY_SCB_CCSI , RAY_CCS_INDEX ( ccs ) ) ;
RAY_ECF_START_CMD ( sc ) ;
ray_cmd_ran ( sc , track ) ;
return ( 1 ) ;
}
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
/*
* send a simple command if we can
*/
static int
ray_simple_cmd ( struct ray_softc * sc , u_int cmd , u_int track )
{
size_t ccs ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_simple_cmd \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
return ( ray_alloc_ccs ( sc , & ccs , cmd , track ) & &
ray_issue_cmd ( sc , ccs , track ) ) ;
}
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
/*
* Functions based on CCS commands
*/
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
/*
* run a update subcommand
*/
static void
ray_update_subcmd ( struct ray_softc * sc )
{
struct ifnet * ifp ;
int submask , i ;
RAY_DPRINTFN ( 5 , ( " ray%d: ray_update_subcmd \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
ray_cmd_cancel ( sc , SCP_UPDATESUBCMD ) ;
ifp = & sc - > arpcom . ac_if ;
if ( ( ifp - > if_flags & IFF_RUNNING ) = = 0 )
return ;
submask = SCP_UPD_FIRST ;
for ( i = 0 ; i < ray_nsubcmdtab ; submask < < = 1 , i + + ) {
if ( ( sc - > sc_scheduled & SCP_UPD_MASK ) = = 0 )
break ;
/* when done the next command will be scheduled */
if ( ray_cmd_is_running ( sc , SCP_UPDATESUBCMD ) )
break ;
if ( ! RAY_ECF_READY ( sc ) )
break ;
/*
* give priority to LSB - - e . g . , if previous loop reschuled
* doing this command after calling the function won ' t catch
* if a later command sets an earlier bit
*/
if ( sc - > sc_scheduled & ( ( submask - 1 ) & SCP_UPD_MASK ) )
break ;
if ( sc - > sc_scheduled & submask )
( * ray_subcmdtab [ i ] ) ( sc ) ;
}
}
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
/*
* report a parameter
*/
static void
ray_report_params ( struct ray_softc * sc )
{
struct ifnet * ifp ;
size_t ccs ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_report_params \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
2000-03-05 14:39:23 +00:00
2000-03-08 23:28:06 +00:00
ray_cmd_cancel ( sc , SCP_REPORTPARAMS ) ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
ifp = & sc - > arpcom . ac_if ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
if ( ! sc - > sc_repreq )
return ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
/* do the issue check before equality check */
if ( ( ifp - > if_flags & IFF_RUNNING ) = = 0 )
return ;
else if ( ray_cmd_is_running ( sc , SCP_REPORTPARAMS ) ) {
ray_cmd_schedule ( sc , SCP_REPORTPARAMS ) ;
return ;
} else if ( ! ray_alloc_ccs ( sc , & ccs , RAY_CMD_REPORT_PARAMS ,
SCP_REPORTPARAMS ) )
return ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd_report , c_paramid ,
sc - > sc_repreq - > r_paramid ) ;
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd_report , c_nparam , 1 ) ;
( void ) ray_issue_cmd ( sc , ccs , SCP_REPORTPARAMS ) ;
}
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
/*
* start an association
*/
static void
ray_start_assoc ( struct ray_softc * sc )
{
struct ifnet * ifp ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_start_assoc \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
ifp = & sc - > arpcom . ac_if ;
ray_cmd_cancel ( sc , SCP_STARTASSOC ) ;
if ( ( ifp - > if_flags & IFF_RUNNING ) = = 0 )
return ;
else if ( ray_cmd_is_running ( sc , SCP_STARTASSOC ) )
return ;
( void ) ray_simple_cmd ( sc , RAY_CMD_START_ASSOC , SCP_STARTASSOC ) ;
2000-02-27 19:52:29 +00:00
}
2000-03-08 23:28:06 +00:00
/******************************************************************************
* XXX NOT KNF FROM HERE DOWN *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Subcommand functions that use the SCP_UPDATESUBCMD command
* ( and are serialized with respect to other update sub commands
*/
2000-02-26 14:49:24 +00:00
/*
* Download start up structures to card .
*
* Part of ray_init , download , startjoin control flow .
*/
static void
ray_download_params ( sc )
struct ray_softc * sc ;
{
struct ray_mib_4 ray_mib_4_default ;
struct ray_mib_5 ray_mib_5_default ;
2000-03-05 14:39:23 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: Downloading startup parameters \n " , sc - > unit ) ) ;
2000-02-26 14:49:24 +00:00
RAY_MAP_CM ( sc ) ;
ray_cmd_cancel ( sc , SCP_UPD_STARTUP ) ;
# define MIB4(m) ray_mib_4_default.##m
# define MIB5(m) ray_mib_5_default.##m
# define PUT2(p, v) \
do { ( p ) [ 0 ] = ( ( v > > 8 ) & 0xff ) ; ( p ) [ 1 ] = ( v & 0xff ) ; } while ( 0 )
/*
* Firmware version 4 defaults - see if_raymib . h for details
*/
2000-03-11 13:25:33 +00:00
MIB4 ( mib_net_type ) = sc - > sc_d . np_net_type ;
MIB4 ( mib_ap_status ) = sc - > sc_d . np_ap_status ;
bcopy ( sc - > sc_d . np_ssid , MIB4 ( mib_ssid ) , IEEE80211_NWID_LEN ) ;
2000-02-26 14:49:24 +00:00
MIB4 ( mib_scan_mode ) = RAY_MIB_SCAN_MODE_DEFAULT ;
MIB4 ( mib_apm_mode ) = RAY_MIB_APM_MODE_DEFAULT ;
bcopy ( sc - > sc_station_addr , MIB4 ( mib_mac_addr ) , ETHER_ADDR_LEN ) ;
PUT2 ( MIB4 ( mib_frag_thresh ) , RAY_MIB_FRAG_THRESH_DEFAULT ) ;
PUT2 ( MIB4 ( mib_dwell_time ) , RAY_MIB_DWELL_TIME_V4 ) ;
PUT2 ( MIB4 ( mib_beacon_period ) , RAY_MIB_BEACON_PERIOD_V4 ) ;
MIB4 ( mib_dtim_interval ) = RAY_MIB_DTIM_INTERVAL_DEFAULT ;
MIB4 ( mib_max_retry ) = RAY_MIB_MAX_RETRY_DEFAULT ;
MIB4 ( mib_ack_timo ) = RAY_MIB_ACK_TIMO_DEFAULT ;
MIB4 ( mib_sifs ) = RAY_MIB_SIFS_DEFAULT ;
MIB4 ( mib_difs ) = RAY_MIB_DIFS_DEFAULT ;
MIB4 ( mib_pifs ) = RAY_MIB_PIFS_V4 ;
PUT2 ( MIB4 ( mib_rts_thresh ) , RAY_MIB_RTS_THRESH_DEFAULT ) ;
PUT2 ( MIB4 ( mib_scan_dwell ) , RAY_MIB_SCAN_DWELL_V4 ) ;
PUT2 ( MIB4 ( mib_scan_max_dwell ) , RAY_MIB_SCAN_MAX_DWELL_V4 ) ;
MIB4 ( mib_assoc_timo ) = RAY_MIB_ASSOC_TIMO_DEFAULT ;
MIB4 ( mib_adhoc_scan_cycle ) = RAY_MIB_ADHOC_SCAN_CYCLE_DEFAULT ;
MIB4 ( mib_infra_scan_cycle ) = RAY_MIB_INFRA_SCAN_CYCLE_DEFAULT ;
MIB4 ( mib_infra_super_scan_cycle ) = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_DEFAULT ;
MIB4 ( mib_promisc ) = RAY_MIB_PROMISC_DEFAULT ;
PUT2 ( MIB4 ( mib_uniq_word ) , RAY_MIB_UNIQ_WORD_DEFAULT ) ;
MIB4 ( mib_slot_time ) = RAY_MIB_SLOT_TIME_V4 ;
MIB4 ( mib_roam_low_snr_thresh ) = RAY_MIB_ROAM_LOW_SNR_THRESH_DEFAULT ;
MIB4 ( mib_low_snr_count ) = RAY_MIB_LOW_SNR_COUNT_DEFAULT ;
MIB4 ( mib_infra_missed_beacon_count ) = RAY_MIB_INFRA_MISSED_BEACON_COUNT_DEFAULT ;
MIB4 ( mib_adhoc_missed_beacon_count ) = RAY_MIB_ADHOC_MISSED_BEACON_COUNT_DEFAULT ;
MIB4 ( mib_country_code ) = RAY_MIB_COUNTRY_CODE_DEFAULT ;
MIB4 ( mib_hop_seq ) = RAY_MIB_HOP_SEQ_DEFAULT ;
MIB4 ( mib_hop_seq_len ) = RAY_MIB_HOP_SEQ_LEN_V4 ;
MIB4 ( mib_cw_max ) = RAY_MIB_CW_MAX_V4 ;
MIB4 ( mib_cw_min ) = RAY_MIB_CW_MIN_V4 ;
MIB4 ( mib_noise_filter_gain ) = RAY_MIB_NOISE_FILTER_GAIN_DEFAULT ;
MIB4 ( mib_noise_limit_offset ) = RAY_MIB_NOISE_LIMIT_OFFSET_DEFAULT ;
MIB4 ( mib_rssi_thresh_offset ) = RAY_MIB_RSSI_THRESH_OFFSET_DEFAULT ;
MIB4 ( mib_busy_thresh_offset ) = RAY_MIB_BUSY_THRESH_OFFSET_DEFAULT ;
MIB4 ( mib_sync_thresh ) = RAY_MIB_SYNC_THRESH_DEFAULT ;
MIB4 ( mib_test_mode ) = RAY_MIB_TEST_MODE_DEFAULT ;
MIB4 ( mib_test_min_chan ) = RAY_MIB_TEST_MIN_CHAN_DEFAULT ;
MIB4 ( mib_test_max_chan ) = RAY_MIB_TEST_MAX_CHAN_DEFAULT ;
/*
* Firmware version 5 defaults - see if_raymib . h for details
*/
2000-03-11 13:25:33 +00:00
MIB5 ( mib_net_type ) = sc - > sc_d . np_net_type ;
MIB4 ( mib_ap_status ) = sc - > sc_d . np_ap_status ;
bcopy ( sc - > sc_d . np_ssid , MIB5 ( mib_ssid ) , IEEE80211_NWID_LEN ) ;
2000-02-26 14:49:24 +00:00
MIB5 ( mib_scan_mode ) = RAY_MIB_SCAN_MODE_DEFAULT ;
MIB5 ( mib_apm_mode ) = RAY_MIB_APM_MODE_DEFAULT ;
bcopy ( sc - > sc_station_addr , MIB5 ( mib_mac_addr ) , ETHER_ADDR_LEN ) ;
PUT2 ( MIB5 ( mib_frag_thresh ) , RAY_MIB_FRAG_THRESH_DEFAULT ) ;
PUT2 ( MIB5 ( mib_dwell_time ) , RAY_MIB_DWELL_TIME_V5 ) ;
PUT2 ( MIB5 ( mib_beacon_period ) , RAY_MIB_BEACON_PERIOD_V5 ) ;
MIB5 ( mib_dtim_interval ) = RAY_MIB_DTIM_INTERVAL_DEFAULT ;
MIB5 ( mib_max_retry ) = RAY_MIB_MAX_RETRY_DEFAULT ;
MIB5 ( mib_ack_timo ) = RAY_MIB_ACK_TIMO_DEFAULT ;
MIB5 ( mib_sifs ) = RAY_MIB_SIFS_DEFAULT ;
MIB5 ( mib_difs ) = RAY_MIB_DIFS_DEFAULT ;
MIB5 ( mib_pifs ) = RAY_MIB_PIFS_V5 ;
PUT2 ( MIB5 ( mib_rts_thresh ) , RAY_MIB_RTS_THRESH_DEFAULT ) ;
PUT2 ( MIB5 ( mib_scan_dwell ) , RAY_MIB_SCAN_DWELL_V5 ) ;
PUT2 ( MIB5 ( mib_scan_max_dwell ) , RAY_MIB_SCAN_MAX_DWELL_V5 ) ;
MIB5 ( mib_assoc_timo ) = RAY_MIB_ASSOC_TIMO_DEFAULT ;
MIB5 ( mib_adhoc_scan_cycle ) = RAY_MIB_ADHOC_SCAN_CYCLE_DEFAULT ;
MIB5 ( mib_infra_scan_cycle ) = RAY_MIB_INFRA_SCAN_CYCLE_DEFAULT ;
MIB5 ( mib_infra_super_scan_cycle ) = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_DEFAULT ;
MIB5 ( mib_promisc ) = RAY_MIB_PROMISC_DEFAULT ;
PUT2 ( MIB5 ( mib_uniq_word ) , RAY_MIB_UNIQ_WORD_DEFAULT ) ;
MIB5 ( mib_slot_time ) = RAY_MIB_SLOT_TIME_V5 ;
MIB5 ( mib_roam_low_snr_thresh ) = RAY_MIB_ROAM_LOW_SNR_THRESH_DEFAULT ;
MIB5 ( mib_low_snr_count ) = RAY_MIB_LOW_SNR_COUNT_DEFAULT ;
MIB5 ( mib_infra_missed_beacon_count ) = RAY_MIB_INFRA_MISSED_BEACON_COUNT_DEFAULT ;
MIB5 ( mib_adhoc_missed_beacon_count ) = RAY_MIB_ADHOC_MISSED_BEACON_COUNT_DEFAULT ;
MIB5 ( mib_country_code ) = RAY_MIB_COUNTRY_CODE_DEFAULT ;
MIB5 ( mib_hop_seq ) = RAY_MIB_HOP_SEQ_DEFAULT ;
MIB5 ( mib_hop_seq_len ) = RAY_MIB_HOP_SEQ_LEN_V5 ;
PUT2 ( MIB5 ( mib_cw_max ) , RAY_MIB_CW_MAX_V5 ) ;
PUT2 ( MIB5 ( mib_cw_min ) , RAY_MIB_CW_MIN_V5 ) ;
MIB5 ( mib_noise_filter_gain ) = RAY_MIB_NOISE_FILTER_GAIN_DEFAULT ;
MIB5 ( mib_noise_limit_offset ) = RAY_MIB_NOISE_LIMIT_OFFSET_DEFAULT ;
MIB5 ( mib_rssi_thresh_offset ) = RAY_MIB_RSSI_THRESH_OFFSET_DEFAULT ;
MIB5 ( mib_busy_thresh_offset ) = RAY_MIB_BUSY_THRESH_OFFSET_DEFAULT ;
MIB5 ( mib_sync_thresh ) = RAY_MIB_SYNC_THRESH_DEFAULT ;
MIB5 ( mib_test_mode ) = RAY_MIB_TEST_MODE_DEFAULT ;
MIB5 ( mib_test_min_chan ) = RAY_MIB_TEST_MIN_CHAN_DEFAULT ;
MIB5 ( mib_test_max_chan ) = RAY_MIB_TEST_MAX_CHAN_DEFAULT ;
MIB5 ( mib_allow_probe_resp ) = RAY_MIB_ALLOW_PROBE_RESP_DEFAULT ;
2000-03-21 14:27:46 +00:00
MIB5 ( mib_privacy_must_start ) = sc - > sc_d . np_priv_start ;
MIB5 ( mib_privacy_can_join ) = sc - > sc_d . np_priv_join ;
MIB5 ( mib_basic_rate_set [ 0 ] ) = sc - > sc_d . np_def_txrate ;
2000-02-26 14:49:24 +00:00
2000-03-05 22:24:30 +00:00
if ( ! RAY_ECF_READY ( sc ) ) {
printf ( " ray%d: ray_download_params something is already happening \n " ,
2000-02-26 14:49:24 +00:00
sc - > unit ) ;
2000-03-05 22:24:30 +00:00
ray_reset ( sc ) ;
}
2000-02-26 14:49:24 +00:00
if ( sc - > sc_version = = RAY_ECFS_BUILD_4 )
ray_write_region ( sc , RAY_HOST_TO_ECF_BASE ,
& ray_mib_4_default , sizeof ( ray_mib_4_default ) ) ;
else
ray_write_region ( sc , RAY_HOST_TO_ECF_BASE ,
& ray_mib_5_default , sizeof ( ray_mib_5_default ) ) ;
2000-03-08 23:28:06 +00:00
if ( ! ray_simple_cmd ( sc , RAY_CMD_START_PARAMS , SCP_UPD_STARTUP ) )
printf ( " ray%d: ray_download_params can't issue command \n " , sc - > unit ) ;
2000-02-26 14:49:24 +00:00
2000-03-09 21:34:47 +00:00
RAY_DPRINTFN ( 15 , ( " ray%d: Download now awaiting completion \n " , sc - > unit ) ) ;
2000-02-26 14:49:24 +00:00
return ;
}
/*
2000-03-09 21:34:47 +00:00
* Download completion routine .
2000-02-26 14:49:24 +00:00
*
* Part of ray_init , download , start_join control flow .
2000-03-09 21:34:47 +00:00
*
* As START_PARAMS is an update command ray_check_ccs has checked the
* ccs status and re - scheduled timeouts if needed .
2000-02-26 14:49:24 +00:00
*/
static void
2000-03-09 21:34:47 +00:00
ray_download_done ( sc )
struct ray_softc * sc ;
2000-02-26 14:49:24 +00:00
{
2000-03-09 21:34:47 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_download_done \n " , sc - > unit ) ) ;
2000-02-26 14:49:24 +00:00
RAY_MAP_CM ( sc ) ;
2000-03-09 21:34:47 +00:00
ray_cmd_done ( sc , SCP_UPD_STARTUP ) ;
2000-02-26 14:49:24 +00:00
2000-03-11 13:25:33 +00:00
/*
* Fake the current network parameter settings so start_join_net
* will not bother updating them to the card ( we would need to
* zero these anyway , so we might as well copy ) .
*/
sc - > sc_c . np_net_type = sc - > sc_d . np_net_type ;
bcopy ( sc - > sc_d . np_ssid , sc - > sc_c . np_ssid , IEEE80211_NWID_LEN ) ;
2000-03-09 21:34:47 +00:00
2000-03-11 13:25:33 +00:00
ray_start_join_net ( sc ) ;
2000-02-20 14:56:17 +00:00
}
2000-03-08 23:28:06 +00:00
/*
* start or join a network
*/
static void
2000-03-11 13:25:33 +00:00
ray_start_join_net ( struct ray_softc * sc )
2000-03-08 23:28:06 +00:00
{
struct ray_net_params np ;
struct ifnet * ifp ;
size_t ccs ;
2000-03-11 13:25:33 +00:00
int cmd , update ;
2000-03-11 13:34:13 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_start_join_net \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
ifp = & sc - > arpcom . ac_if ;
ray_cmd_cancel ( sc , SCP_UPD_STARTJOIN ) ;
if ( ( ifp - > if_flags & IFF_RUNNING ) = = 0 )
return ;
/* XXX check we may not want to re-issue */
if ( ray_cmd_is_running ( sc , SCP_UPDATESUBCMD ) ) {
ray_cmd_schedule ( sc , SCP_UPD_STARTJOIN ) ;
return ;
}
2000-03-11 13:25:33 +00:00
if ( sc - > sc_d . np_net_type = = RAY_MIB_NET_TYPE_ADHOC )
2000-03-08 23:28:06 +00:00
cmd = RAY_CMD_START_NET ;
else
cmd = RAY_CMD_JOIN_NET ;
2000-03-11 13:25:33 +00:00
if ( ! ray_alloc_ccs ( sc , & ccs , cmd , SCP_UPD_STARTJOIN ) ) {
printf ( " ray%d: ray_start_join_net can't get a CCS \n " , sc - > unit ) ;
ray_reset ( sc ) ;
}
update = 0 ;
if ( bcmp ( sc - > sc_c . np_ssid , sc - > sc_d . np_ssid , IEEE80211_NWID_LEN ) )
update + + ;
if ( sc - > sc_c . np_net_type ! = sc - > sc_d . np_net_type )
update + + ;
if ( update ) {
2000-03-08 23:28:06 +00:00
sc - > sc_havenet = 0 ;
2000-03-11 13:25:33 +00:00
bzero ( & np , sizeof ( np ) ) ;
np . p_net_type = sc - > sc_d . np_net_type ;
bcopy ( sc - > sc_d . np_ssid , np . p_ssid , IEEE80211_NWID_LEN ) ;
np . p_privacy_must_start = sc - > sc_d . np_priv_start ;
np . p_privacy_can_join = sc - > sc_d . np_priv_join ;
2000-03-08 23:28:06 +00:00
ray_write_region ( sc , RAY_HOST_TO_ECF_BASE , & np , sizeof ( np ) ) ;
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd_net , c_upd_param , 1 ) ;
2000-03-11 13:25:33 +00:00
} else
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd_net , c_upd_param , 0 ) ;
RAY_DPRINTFN ( 15 , ( " ray%d: ray_start_join_net %s updating nw params \n " ,
sc - > unit , update ? " is " : " not " ) ) ;
if ( ! ray_issue_cmd ( sc , ccs , SCP_UPD_STARTJOIN ) ) {
printf ( " ray%d: ray_start_join_net can't issue cmd \n " , sc - > unit ) ;
ray_reset ( sc ) ;
2000-03-08 23:28:06 +00:00
}
2000-03-11 13:25:33 +00:00
# if RAY_NEED_STARTJOIN_TIMO
sc - > sj_timerh = timeout ( ray_start_join_timo , sc , RAY_SJ_TIMEOUT ) ;
# endif /* RAY_NEED_STARTJOIN_TIMO */
2000-03-08 23:28:06 +00:00
}
# if RAY_NEED_STARTJOIN_TIMO
/*
* Back stop catcher for start_join command . The NetBSD driver
* suggests that they need it to catch a bug in the firmware or the
* parameters they use - they are not sure . I ' ll just panic as I seem
* to get interrupts back fine and I have version 4 firmware .
*/
static void
ray_start_join_timo ( xsc )
void * xsc ;
{
struct ray_softc * sc = xsc ;
RAY_DPRINTFN ( 5 , ( " ray%d: ray_start_join_timo \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
panic ( " ray%d: ray-start_join_timo occured \n " , sc - > unit ) ;
return ;
}
# endif /* RAY_NEED_STARTJOIN_TIMO */
2000-02-27 19:52:29 +00:00
/*
* Complete start or join command .
*
* Part of ray_init , download , start_join control flow .
*/
static void
ray_start_join_done ( sc , ccs , status )
struct ray_softc * sc ;
size_t ccs ;
u_int8_t status ;
{
2000-03-05 14:39:23 +00:00
struct ifnet * ifp ;
2000-02-27 19:52:29 +00:00
u_int8_t o_net_type ;
2000-03-05 14:39:23 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_start_join_done \n " , sc - > unit ) ) ;
2000-02-27 19:52:29 +00:00
RAY_MAP_CM ( sc ) ;
2000-03-05 14:39:23 +00:00
ifp = & sc - > arpcom . ac_if ;
2000-02-27 19:52:29 +00:00
# if RAY_NEED_STARTJOIN_TIMO
untimeout ( ray_start_join_timo , sc , sc - > sj_timerh ) ;
# endif /* RAY_NEED_STARTJOIN_TIMO */
ray_cmd_done ( sc , SCP_UPD_STARTJOIN ) ;
2000-03-05 22:24:30 +00:00
/*
* XXX This switch and the following test are badly done . I
* XXX need to take remedial action in each case branch and
* XXX return from there . Then remove the test .
* XXX FAIL comment
* XXX if we fired the start command we successfully set the card up
* XXX so just restart ray_start_join sequence and dont reset the card
* XXX may need to split download_done for this
* XXX FREE
* XXX not sure
* XXX BUSY
* XXX maybe timeout but why would we get an interrupt when
* XXX the card is not finished ?
*/
2000-02-27 19:52:29 +00:00
switch ( status ) {
case RAY_CCS_STATUS_FREE :
case RAY_CCS_STATUS_BUSY :
printf ( " ray%d: ray_start_join_done status is FREE/BUSY - why? \n " ,
sc - > unit ) ;
break ;
case RAY_CCS_STATUS_COMPLETE :
break ;
case RAY_CCS_STATUS_FAIL :
printf ( " ray%d: ray_start_join_done status is FAIL - why? \n " ,
sc - > unit ) ;
2000-03-03 17:07:42 +00:00
sc - > sc_havenet = 0 ;
2000-02-27 19:52:29 +00:00
break ;
default :
printf ( " ray%d: ray_start_join_done unknown status 0x%x \n " ,
sc - > unit , status ) ;
break ;
}
2000-03-03 17:07:42 +00:00
if ( status ! = RAY_CCS_STATUS_COMPLETE )
return ;
2000-02-27 19:52:29 +00:00
/*
* If the command completed correctly , get a few network parameters
2000-03-03 17:07:42 +00:00
* from the ccs and active the network .
2000-02-27 19:52:29 +00:00
*/
2000-03-11 13:25:33 +00:00
ray_read_region ( sc , ccs , & sc - > sc_c . p_1 , sizeof ( struct ray_cmd_net ) ) ;
2000-02-27 19:52:29 +00:00
2000-03-03 17:07:42 +00:00
/* adjust values for buggy build 4 */
2000-03-11 13:25:33 +00:00
if ( sc - > sc_c . np_def_txrate = = 0x55 )
sc - > sc_c . np_def_txrate = sc - > sc_d . np_def_txrate ;
if ( sc - > sc_c . np_encrypt = = 0x55 )
sc - > sc_c . np_encrypt = sc - > sc_d . np_encrypt ;
2000-02-27 19:52:29 +00:00
2000-03-03 17:07:42 +00:00
/* card is telling us to update the network parameters */
2000-03-11 13:25:33 +00:00
if ( sc - > sc_c . np_upd_param ) {
2000-03-05 14:39:23 +00:00
RAY_DPRINTFN ( 1 , ( " ray%d: sj_done card updating parameters - why? \n " ,
2000-03-03 17:07:42 +00:00
sc - > unit ) ) ;
2000-03-11 13:25:33 +00:00
o_net_type = sc - > sc_c . np_net_type ; /* XXX this may be wrong? */
2000-03-03 17:07:42 +00:00
ray_read_region ( sc , RAY_HOST_TO_ECF_BASE ,
2000-03-11 13:25:33 +00:00
& sc - > sc_c . p_2 , sizeof ( struct ray_net_params ) ) ;
if ( sc - > sc_c . np_net_type ! = o_net_type ) {
2000-03-03 17:07:42 +00:00
printf ( " ray%d: sj_done card changing network type - why? \n " ,
sc - > unit ) ;
2000-02-27 19:52:29 +00:00
# if XXX
2000-03-05 14:39:23 +00:00
restart ray_start_join sequence
2000-03-09 21:34:47 +00:00
may need to split download_done for this
2000-02-27 19:52:29 +00:00
# endif
}
2000-03-03 17:07:42 +00:00
}
RAY_DNET_DUMP ( sc , " after start/join network completed. " ) ;
2000-02-27 19:52:29 +00:00
2000-03-03 17:07:42 +00:00
/*
2000-03-05 14:39:23 +00:00
* Hurrah ! The network is now active .
*
* Clearing IFF_OACTIVE will ensure that the system will queue packets .
* Just before we return from the interrupt context we check to
* see if packets have been queued .
2000-03-03 17:07:42 +00:00
*/
ray_cmd_schedule ( sc , SCP_UPD_MCAST | SCP_UPD_PROMISC ) ;
2000-03-12 22:54:29 +00:00
2000-03-03 17:07:42 +00:00
if ( SRAM_READ_FIELD_1 ( sc , ccs , ray_cmd , c_cmd ) = = RAY_CMD_JOIN_NET )
ray_start_assoc ( sc ) ;
else {
2000-03-05 14:39:23 +00:00
sc - > sc_havenet = 1 ;
ifp - > if_flags & = ~ IFF_OACTIVE ;
2000-02-27 19:52:29 +00:00
}
return ;
2000-03-03 17:07:42 +00:00
}
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
/******************************************************************************
* XXX NOT KNF FROM HERE UP
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-02-26 14:49:24 +00:00
/*
2000-03-08 23:28:06 +00:00
* set the card in / out of promiscuous mode
2000-02-26 14:49:24 +00:00
*/
static void
2000-03-08 23:28:06 +00:00
ray_update_promisc ( struct ray_softc * sc )
2000-02-26 14:49:24 +00:00
{
2000-03-08 23:28:06 +00:00
struct ifnet * ifp ;
size_t ccs ;
int promisc ;
RAY_DPRINTFN ( 5 , ( " ray%d: ray_update_promisc \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
ifp = & sc - > arpcom . ac_if ;
ray_cmd_cancel ( sc , SCP_UPD_PROMISC ) ;
/* do the issue check before equality check */
promisc = ! ! ( ifp - > if_flags & ( IFF_PROMISC | IFF_ALLMULTI ) ) ;
if ( ( ifp - > if_flags & IFF_RUNNING ) = = 0 )
return ;
else if ( ray_cmd_is_running ( sc , SCP_UPDATESUBCMD ) ) {
ray_cmd_schedule ( sc , SCP_UPD_PROMISC ) ;
return ;
} else if ( promisc = = sc - > sc_promisc )
return ;
else if ( ! ray_alloc_ccs ( sc , & ccs , RAY_CMD_UPDATE_PARAMS , SCP_UPD_PROMISC ) )
return ;
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd_update , c_paramid , RAY_MIB_PROMISC ) ;
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd_update , c_nparam , 1 ) ;
SRAM_WRITE_1 ( sc , RAY_HOST_TO_ECF_BASE , promisc ) ;
( void ) ray_issue_cmd ( sc , ccs , SCP_UPD_PROMISC ) ;
2000-02-26 14:49:24 +00:00
}
/*
2000-03-08 23:28:06 +00:00
* update the parameter based on what the user passed in
2000-02-26 14:49:24 +00:00
*/
2000-03-08 23:28:06 +00:00
static void
ray_update_params ( struct ray_softc * sc )
2000-02-26 14:49:24 +00:00
{
2000-03-08 23:28:06 +00:00
struct ifnet * ifp ;
size_t ccs ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_update_params \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
ifp = & sc - > arpcom . ac_if ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
ray_cmd_cancel ( sc , SCP_UPD_UPDATEPARAMS ) ;
if ( ! sc - > sc_updreq ) {
/* XXX do we need to wakeup here? */
return ;
}
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
/* do the issue check before equality check */
if ( ( ifp - > if_flags & IFF_RUNNING ) = = 0 )
return ;
else if ( ray_cmd_is_running ( sc , SCP_UPDATESUBCMD ) ) {
ray_cmd_schedule ( sc , SCP_UPD_UPDATEPARAMS ) ;
return ;
} else if ( ! ray_alloc_ccs ( sc , & ccs , RAY_CMD_UPDATE_PARAMS ,
SCP_UPD_UPDATEPARAMS ) )
return ;
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd_update , c_paramid ,
sc - > sc_updreq - > r_paramid ) ;
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd_update , c_nparam , 1 ) ;
ray_write_region ( sc , RAY_HOST_TO_ECF_BASE , sc - > sc_updreq - > r_data ,
sc - > sc_updreq - > r_len ) ;
( void ) ray_issue_cmd ( sc , ccs , SCP_UPD_UPDATEPARAMS ) ;
2000-02-26 14:49:24 +00:00
}
/*
2000-03-08 23:28:06 +00:00
* set the multicast filter list
2000-02-26 14:49:24 +00:00
*/
2000-03-08 23:28:06 +00:00
static void
ray_update_mcast ( struct ray_softc * sc )
2000-02-26 14:49:24 +00:00
{
2000-03-12 22:54:29 +00:00
struct ifnet * ifp ;
struct ifmultiaddr * ifma ;
size_t ccs , bufp ;
2000-03-08 23:28:06 +00:00
int count ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_update_mcast \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
2000-03-12 22:54:29 +00:00
ifp = & sc - > arpcom . ac_if ;
2000-03-08 23:28:06 +00:00
ray_cmd_cancel ( sc , SCP_UPD_MCAST ) ;
2000-03-12 22:54:29 +00:00
for ( ifma = ifp - > if_multiaddrs . lh_first , count = 0 ; ifma ! = NULL ;
ifma = ifma - > ifma_link . le_next , count + + )
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
/* track this stuff even when not running */
if ( count > 16 ) {
2000-03-12 22:54:29 +00:00
ifp - > if_flags | = IFF_ALLMULTI ;
2000-03-08 23:28:06 +00:00
ray_update_promisc ( sc ) ;
return ;
2000-03-12 22:54:29 +00:00
} else if ( ifp - > if_flags & IFF_ALLMULTI ) {
ifp - > if_flags & = ~ IFF_ALLMULTI ;
2000-03-08 23:28:06 +00:00
ray_update_promisc ( sc ) ;
}
2000-02-26 14:49:24 +00:00
2000-03-12 22:54:29 +00:00
if ( ( ifp - > if_flags & IFF_RUNNING ) = = 0 )
2000-03-08 23:28:06 +00:00
return ;
else if ( ray_cmd_is_running ( sc , SCP_UPDATESUBCMD ) ) {
ray_cmd_schedule ( sc , SCP_UPD_MCAST ) ;
return ;
} else if ( ! ray_alloc_ccs ( sc , & ccs , RAY_CMD_UPDATE_MCAST , SCP_UPD_MCAST ) )
return ;
SRAM_WRITE_FIELD_1 ( sc , ccs , ray_cmd_update_mcast , c_nmcast , count ) ;
bufp = RAY_HOST_TO_ECF_BASE ;
2000-03-12 22:54:29 +00:00
for ( ifma = ifp - > if_multiaddrs . lh_first ; ifma ! = NULL ;
ifma = ifma - > ifma_link . le_next ) {
ray_write_region (
sc ,
bufp ,
LLADDR ( ( struct sockaddr_dl * ) ifma - > ifma_addr ) ,
ETHER_ADDR_LEN
) ;
2000-03-08 23:28:06 +00:00
bufp + = ETHER_ADDR_LEN ;
}
( void ) ray_issue_cmd ( sc , ccs , SCP_UPD_MCAST ) ;
2000-02-26 14:49:24 +00:00
}
/*
2000-03-08 23:28:06 +00:00
* User issued commands
*/
/*
* issue a update params
*
* expected to be called in sleapable context - - intended for user stuff
2000-02-26 14:49:24 +00:00
*/
static int
2000-03-08 23:28:06 +00:00
ray_user_update_params ( struct ray_softc * sc , struct ray_param_req * pr )
2000-02-26 14:49:24 +00:00
{
2000-03-08 23:28:06 +00:00
struct ifnet * ifp ;
int rv ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_user_update_params \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
ifp = & sc - > arpcom . ac_if ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
if ( ( ifp - > if_flags & IFF_RUNNING ) = = 0 ) {
pr - > r_failcause = RAY_FAILCAUSE_EDEVSTOP ;
return ( EIO ) ;
}
2000-03-21 14:27:46 +00:00
if ( pr - > r_paramid > RAY_MIB_MAX ) {
return ( EINVAL ) ;
}
/*
* Handle certain parameters specially
*/
switch ( pr - > r_paramid ) {
case RAY_MIB_NET_TYPE :
if ( sc - > sc_c . np_net_type = = * pr - > r_data )
return ( 0 ) ;
sc - > sc_d . np_net_type = * pr - > r_data ;
if ( ifp - > if_flags & IFF_RUNNING )
ray_start_join_net ( sc ) ;
return ( 0 ) ;
case RAY_MIB_SSID :
if ( ! bcmp ( sc - > sc_c . np_ssid , pr - > r_data , IEEE80211_NWID_LEN ) )
return ( 0 ) ;
bcopy ( pr - > r_data , sc - > sc_d . np_ssid , IEEE80211_NWID_LEN ) ;
if ( ifp - > if_flags & IFF_RUNNING )
ray_start_join_net ( sc ) ;
return ( 0 ) ;
case RAY_MIB_BASIC_RATE_SET :
sc - > sc_d . np_def_txrate = * pr - > r_data ;
break ;
case RAY_MIB_AP_STATUS : /* Unsupported */
case RAY_MIB_MAC_ADDR : /* XXX Need interface up */
case RAY_MIB_PROMISC : /* BPF */
return ( EINVAL ) ;
break ;
default :
break ;
}
if ( pr - > r_paramid > RAY_MIB_LASTUSER ) {
return ( EINVAL ) ;
}
2000-03-08 23:28:06 +00:00
/* wait to be able to issue the command */
rv = 0 ;
while ( ray_cmd_is_running ( sc , SCP_UPD_UPDATEPARAMS ) | |
ray_cmd_is_scheduled ( sc , SCP_UPD_UPDATEPARAMS ) ) {
rv = tsleep ( ray_update_params , 0 | PCATCH , " cmd in use " , 0 ) ;
if ( rv )
return ( rv ) ;
if ( ( ifp - > if_flags & IFF_RUNNING ) = = 0 ) {
pr - > r_failcause = RAY_FAILCAUSE_EDEVSTOP ;
return ( EIO ) ;
}
}
pr - > r_failcause = RAY_FAILCAUSE_WAITING ;
sc - > sc_updreq = pr ;
ray_cmd_schedule ( sc , SCP_UPD_UPDATEPARAMS ) ;
ray_check_scheduled ( sc ) ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
while ( pr - > r_failcause = = RAY_FAILCAUSE_WAITING )
( void ) tsleep ( ray_update_params , 0 , " waiting cmd " , 0 ) ;
wakeup ( ray_update_params ) ;
return ( 0 ) ;
2000-02-26 14:49:24 +00:00
}
2000-03-08 23:28:06 +00:00
/*
* issue a report params
*
* expected to be called in sleapable context - - intended for user stuff
*/
static int
ray_user_report_params ( struct ray_softc * sc , struct ray_param_req * pr )
2000-02-27 19:52:29 +00:00
{
2000-03-08 23:28:06 +00:00
struct ifnet * ifp ;
2000-03-21 14:27:46 +00:00
int mib_sizes [ ] = RAY_MIB_SIZES ;
2000-03-08 23:28:06 +00:00
int rv ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: ray_user_report_params \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
2000-02-27 19:52:29 +00:00
2000-03-08 23:28:06 +00:00
ifp = & sc - > arpcom . ac_if ;
if ( ( ifp - > if_flags & IFF_RUNNING ) = = 0 ) {
pr - > r_failcause = RAY_FAILCAUSE_EDEVSTOP ;
return ( EIO ) ;
2000-02-27 19:52:29 +00:00
}
2000-03-08 23:28:06 +00:00
2000-03-21 14:27:46 +00:00
/* test for illegal values or immediate responses */
if ( pr - > r_paramid > RAY_MIB_LASTUSER ) {
switch ( pr - > r_paramid ) {
case RAY_MIB_VERSION :
if ( sc - > sc_version = = RAY_ECFS_BUILD_4 )
* pr - > r_data = 4 ;
else
* pr - > r_data = 5 ;
break ;
case RAY_MIB_CUR_BSSID :
bcopy ( sc - > sc_c . np_bss_id , pr - > r_data , ETHER_ADDR_LEN ) ;
break ;
case RAY_MIB_CUR_INITED :
* pr - > r_data = sc - > sc_c . np_inited ;
break ;
case RAY_MIB_CUR_DEF_TXRATE :
* pr - > r_data = sc - > sc_c . np_def_txrate ;
break ;
case RAY_MIB_CUR_ENCRYPT :
* pr - > r_data = sc - > sc_c . np_encrypt ;
break ;
case RAY_MIB_CUR_NET_TYPE :
* pr - > r_data = sc - > sc_c . np_net_type ;
break ;
case RAY_MIB_CUR_SSID :
bcopy ( sc - > sc_c . np_ssid , pr - > r_data , IEEE80211_NWID_LEN ) ;
break ;
case RAY_MIB_CUR_PRIV_START :
* pr - > r_data = sc - > sc_c . np_priv_start ;
break ;
case RAY_MIB_CUR_PRIV_JOIN :
* pr - > r_data = sc - > sc_c . np_priv_join ;
break ;
case RAY_MIB_DES_BSSID :
bcopy ( sc - > sc_d . np_bss_id , pr - > r_data , ETHER_ADDR_LEN ) ;
break ;
case RAY_MIB_DES_INITED :
* pr - > r_data = sc - > sc_d . np_inited ;
break ;
case RAY_MIB_DES_DEF_TXRATE :
* pr - > r_data = sc - > sc_d . np_def_txrate ;
break ;
case RAY_MIB_DES_ENCRYPT :
* pr - > r_data = sc - > sc_d . np_encrypt ;
break ;
case RAY_MIB_DES_NET_TYPE :
* pr - > r_data = sc - > sc_d . np_net_type ;
break ;
case RAY_MIB_DES_SSID :
bcopy ( sc - > sc_d . np_ssid , pr - > r_data , IEEE80211_NWID_LEN ) ;
break ;
case RAY_MIB_DES_PRIV_START :
* pr - > r_data = sc - > sc_d . np_priv_start ;
break ;
case RAY_MIB_DES_PRIV_JOIN :
* pr - > r_data = sc - > sc_d . np_priv_join ;
break ;
default :
return ( EINVAL ) ;
break ;
}
pr - > r_failcause = 0 ;
pr - > r_len = mib_sizes [ pr - > r_paramid ] ;
return ( 0 ) ;
}
2000-03-08 23:28:06 +00:00
/* wait to be able to issue the command */
rv = 0 ;
while ( ray_cmd_is_running ( sc , SCP_REPORTPARAMS )
| | ray_cmd_is_scheduled ( sc , SCP_REPORTPARAMS ) ) {
rv = tsleep ( ray_report_params , 0 | PCATCH , " cmd in use " , 0 ) ;
if ( rv )
return ( rv ) ;
if ( ( ifp - > if_flags & IFF_RUNNING ) = = 0 ) {
pr - > r_failcause = RAY_FAILCAUSE_EDEVSTOP ;
return ( EIO ) ;
}
}
pr - > r_failcause = RAY_FAILCAUSE_WAITING ;
sc - > sc_repreq = pr ;
ray_cmd_schedule ( sc , SCP_REPORTPARAMS ) ;
ray_check_scheduled ( sc ) ;
while ( pr - > r_failcause = = RAY_FAILCAUSE_WAITING )
( void ) tsleep ( ray_report_params , 0 , " waiting cmd " , 0 ) ;
wakeup ( ray_report_params ) ;
return ( 0 ) ;
2000-02-27 19:52:29 +00:00
}
2000-03-08 23:28:06 +00:00
2000-03-12 22:54:29 +00:00
/*
* return the error counters
*/
static int
ray_user_report_stats ( struct ray_softc * sc , struct ray_stats_req * sr )
{
struct ifnet * ifp ;
RAY_DPRINTFN ( 5 , ( " ray%d: ray_user_report_stats \n " , sc - > unit ) ) ;
RAY_MAP_CM ( sc ) ;
ifp = & sc - > arpcom . ac_if ;
if ( ( ifp - > if_flags & IFF_RUNNING ) = = 0 ) {
return ( EIO ) ;
}
sr - > rxoverflow = sc - > sc_rxoverflow ;
sr - > rxcksum = sc - > sc_rxcksum ;
sr - > rxhcksum = sc - > sc_rxhcksum ;
sr - > rxnoise = sc - > sc_rxnoise ;
return ( 0 ) ;
}
2000-03-08 23:28:06 +00:00
/******************************************************************************
* XXX NOT KNF FROM HERE DOWN
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-02-27 19:52:29 +00:00
2000-02-20 14:56:17 +00:00
/*
2000-02-27 19:52:29 +00:00
* Routines to read from / write to the attribute memory .
2000-02-20 14:56:17 +00:00
*
* Taken from if_xe . c .
*
* Until there is a real way of accessing the attribute memory from a driver
* these have to stay .
*
2000-02-26 14:49:24 +00:00
* The hack to use the crdread / crdwrite device functions causes the attribute
* memory to be remapped into the controller and looses the mapping of
* the common memory .
*
* We cheat by using PIOCSMEM and assume that the common memory window
* is in window 0 of the card structure .
*
* Also
* pccard / pcic . c / crdread does mark the unmapped window as inactive
* pccard / pccard . c / map_mem toggles the mapping of a window on
* successive calls
*
2000-02-20 14:56:17 +00:00
*/
2000-03-05 14:39:23 +00:00
# if (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP)
2000-02-26 14:49:24 +00:00
static void
ray_attr_getmap ( struct ray_softc * sc )
{
2000-03-05 14:39:23 +00:00
struct ucred uc ;
struct pcred pc ;
struct proc p ;
int result ;
2000-02-26 14:49:24 +00:00
2000-03-05 14:39:23 +00:00
RAY_DPRINTFN ( 5 , ( " ray%d: attempting to get map for common memory \n " ,
sc - > unit ) ) ;
2000-02-26 14:49:24 +00:00
sc - > md . window = 0 ;
p . p_cred = & pc ;
p . p_cred - > pc_ucred = & uc ;
p . p_cred - > pc_ucred - > cr_uid = 0 ;
2000-03-05 14:39:23 +00:00
result = cdevsw [ CARD_MAJOR ] - > d_ioctl ( makedev ( CARD_MAJOR , sc - > slotnum ) , PIOCGMEM , ( caddr_t ) & sc - > md , 0 , & p ) ;
2000-02-26 14:49:24 +00:00
return ;
}
static void
ray_attr_cm ( struct ray_softc * sc )
{
struct ucred uc ;
struct pcred pc ;
struct proc p ;
2000-03-05 14:39:23 +00:00
RAY_DPRINTFN ( 100 , ( " ray%d: attempting to remap common memory \n " , sc - > unit ) ) ;
2000-02-26 14:49:24 +00:00
p . p_cred = & pc ;
p . p_cred - > pc_ucred = & uc ;
p . p_cred - > pc_ucred - > cr_uid = 0 ;
cdevsw [ CARD_MAJOR ] - > d_ioctl ( makedev ( CARD_MAJOR , sc - > slotnum ) , PIOCSMEM , ( caddr_t ) & sc - > md , 0 , & p ) ;
return ;
}
2000-03-05 14:39:23 +00:00
# endif /* (RAY_NEED_CM_REMAPPING | RAY_NEED_CM_FIXUP) */
2000-02-26 14:49:24 +00:00
2000-02-20 14:56:17 +00:00
static int
2000-02-26 14:49:24 +00:00
ray_attr_write ( struct ray_softc * sc , off_t offset , u_int8_t byte )
2000-02-20 14:56:17 +00:00
{
struct iovec iov ;
struct uio uios ;
2000-02-26 14:49:24 +00:00
int err ;
2000-02-20 14:56:17 +00:00
iov . iov_base = & byte ;
iov . iov_len = sizeof ( byte ) ;
uios . uio_iov = & iov ;
uios . uio_iovcnt = 1 ;
uios . uio_offset = offset ;
uios . uio_resid = sizeof ( byte ) ;
uios . uio_segflg = UIO_SYSSPACE ;
uios . uio_rw = UIO_WRITE ;
uios . uio_procp = 0 ;
2000-02-26 14:49:24 +00:00
err = cdevsw [ CARD_MAJOR ] - > d_write ( makedev ( CARD_MAJOR , sc - > slotnum ) , & uios , 0 ) ;
2000-02-27 19:52:29 +00:00
# if RAY_NEED_CM_REMAPPING
2000-02-26 14:49:24 +00:00
ray_attr_cm ( sc ) ;
2000-02-27 19:52:29 +00:00
# endif /* RAY_NEED_CM_REMAPPING */
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
return ( err ) ;
2000-02-20 14:56:17 +00:00
}
static int
2000-02-26 14:49:24 +00:00
ray_attr_read ( struct ray_softc * sc , off_t offset , u_int8_t * buf , int size )
2000-02-20 14:56:17 +00:00
{
struct iovec iov ;
struct uio uios ;
2000-02-26 14:49:24 +00:00
int err ;
2000-02-20 14:56:17 +00:00
iov . iov_base = buf ;
iov . iov_len = size ;
uios . uio_iov = & iov ;
uios . uio_iovcnt = 1 ;
uios . uio_offset = offset ;
uios . uio_resid = size ;
uios . uio_segflg = UIO_SYSSPACE ;
uios . uio_rw = UIO_READ ;
uios . uio_procp = 0 ;
2000-02-26 14:49:24 +00:00
err = cdevsw [ CARD_MAJOR ] - > d_read ( makedev ( CARD_MAJOR , sc - > slotnum ) , & uios , 0 ) ;
2000-02-27 19:52:29 +00:00
# if RAY_NEED_CM_REMAPPING
2000-02-26 14:49:24 +00:00
ray_attr_cm ( sc ) ;
2000-02-27 19:52:29 +00:00
# endif /* RAY_NEED_CM_REMAPPING */
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
return ( err ) ;
2000-02-20 14:56:17 +00:00
}
2000-02-26 14:49:24 +00:00
static u_int8_t
2000-02-27 19:52:29 +00:00
ray_read_reg ( sc , reg )
struct ray_softc * sc ;
off_t reg ;
2000-02-26 14:49:24 +00:00
{
u_int8_t byte ;
2000-02-27 19:52:29 +00:00
ray_attr_read ( sc , reg , & byte , 1 ) ;
2000-02-26 14:49:24 +00:00
2000-03-08 23:28:06 +00:00
return ( byte ) ;
}
# if RAY_DEBUG > 50
static void
ray_dump_mbuf ( sc , m , s )
struct ray_softc * sc ;
struct mbuf * m ;
char * s ;
{
u_int8_t * d , * ed ;
u_int i ;
char p [ 17 ] ;
printf ( " ray%d: %s mbuf dump: " , sc - > unit , s ) ;
i = 0 ;
bzero ( p , 17 ) ;
for ( ; m ; m = m - > m_next ) {
d = mtod ( m , u_int8_t * ) ;
ed = d + m - > m_len ;
for ( ; d < ed ; i + + , d + + ) {
if ( ( i % 16 ) = = 0 ) {
printf ( " %s \n \t " , p ) ;
} else if ( ( i % 8 ) = = 0 )
printf ( " " ) ;
printf ( " %02x " , * d ) ;
p [ i % 16 ] = ( ( * d > = 0x20 ) & & ( * d < 0x80 ) ) ? * d : ' . ' ;
}
}
if ( ( i - 1 ) % 16 )
printf ( " %s \n " , p ) ;
2000-02-26 14:49:24 +00:00
}
2000-03-08 23:28:06 +00:00
# endif /* RAY_DEBUG > 50 */
2000-02-26 14:49:24 +00:00
2000-03-05 22:24:30 +00:00
# endif /* NRAY */