Commit Graph

237 Commits

Author SHA1 Message Date
Coleman Kane
d9cacbcf4f Replace use of ic->ic_flags with vap->iv_flags to operate on per-vap flags
for ndis 802.11 work.

Submitted by:	Paul B. Mahol <onemda@gmail.com>
2009-06-18 11:12:10 +00:00
Andrew Thompson
a593f6b8de s/usb2_/usb_|usbd_/ on all function names for the USB stack. 2009-06-15 01:02:43 +00:00
Coleman Kane
badff0e4d8 Fix an LOR
Submitted by:	Paul B. Mahol <onemda@gmail.com>
MFC after:	1 week
2009-06-10 18:00:10 +00:00
Andrew Thompson
5cdee58296 Commit missed driver_info to driver_ivar change in usb_attach_args.
Pointed out by:	kib
2009-06-08 19:56:23 +00:00
Sam Leffler
e6c3129877 fix setting of ni_txrate
Submitted by:	"Paul B. Mahol" <onemda@gmail.com>
2009-06-02 20:32:13 +00:00
Andrew Thompson
e0a69b51ac s/usb2_/usb_/ on all typedefs for the USB stack. 2009-05-29 18:46:57 +00:00
Andrew Thompson
760bc48e7e s/usb2_/usb_/ on all C structs for the USB stack. 2009-05-28 17:36:36 +00:00
Andrew Thompson
fadc970b77 Fix a few variable renames of usb2_mode outside dev/usb. 2009-05-21 02:09:12 +00:00
Sam Leffler
74904f7d58 update for net80211 rx api change 2009-05-20 23:33:40 +00:00
Andrew Thompson
5efea30f03 Create a taskqueue for each wireless interface which provides a serialised
sleepable context for net80211 driver callbacks. This removes the need for USB
and firmware based drivers to roll their own code to defer the chip programming
for state changes, scan requests, channel changes and mcast/promisc updates.
When a driver callback completes the hardware state is now guaranteed to have
been updated and is in sync with net80211 layer.

This nukes around 1300 lines of code from the wireless device drivers making
them more readable and less race prone.

The net80211 layer has been updated as follows
 - all state/channel changes are serialised on the taskqueue.
 - ieee80211_new_state() always queues and can now be called from any context
 - scanning runs from a single taskq function and executes to completion. driver
   callbacks are synchronous so the channel, phy mode and rx filters are
   guaranteed to be set in hardware before probe request frames are
   transmitted.

Help and contributions from Sam Leffler.

Reviewed by:	sam
2009-05-02 15:14:18 +00:00
Andrew Thompson
a0c4317cc2 Only call ieee80211_start_all() if its a 80211 device.
Submitted by:	Paul B. Mahol
2009-04-16 23:42:00 +00:00
Sam Leffler
9fb0fccb89 o add a capability for drivers that require 802.3 encapsulation of
frames passed down through the transmit path
o mark ndis requiring 802.3 encap'd frames

Reviewed by:	"Paul B. Mahol" <onemda@gmail.com>, thompsa
2009-04-08 16:19:50 +00:00
Sam Leffler
29aca94080 Eliminate ic_myaddr so changing the mac address of a device works correctly:
o remove ic_myaddr from ieee80211com
o change ieee80211_ifattach to take the mac address of the physical device
  and use that to setup the lladdr.
o replace all references to ic_myaddr in drivers by IF_LLADDR
o related cleanups (e.g. kill dead code)

PR:		kern/133178
Reviewed by:	thompsa, rpaulo
2009-03-29 17:59:14 +00:00
Weongyo Jeong
c4f82f895d set NULL after free to avoid duplicate free.
Tested by:	Ganbold <ganbold_at_micom.mng.net>
2009-03-24 04:20:17 +00:00
Weongyo Jeong
577b9fa3f8 Some NDIS USB drivers try to call URB funcs like URB_FUNCTION_VENDOR_xxx
or URB_FUNCTION_CLASS_xxx with HAL preemption lock that means it's
non-sleepable during USB requests though usb2_do_request() requires a
sleep so it needs to send queries to the default pipe without those
interfaces to avoid sleep.
2009-03-18 02:38:35 +00:00
Weongyo Jeong
2c964f43b6 o change a lock model based on HAL preemption lock to a normal mtx.
Based on the HAL preemption lock there is a problem on SMP machines
  and causes a panic.
o When a device detached the current tactic to detach NDIS USB driver is
  to call SURPRISE_REMOVED event.  So it don't need to call
  ndis_halt_nic() again.  This fixes some page faults when some drivers
  work abnormal.
o it assumes now that URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER is in
  DISPATCH_LEVEL (non-sleepable) and as further work
  URB_FUNCTION_VENDOR_XXX and URB_FUNCTION_CLASS_XXX should be.

Reviewed by:	Hans Petter Selasky <hselasky_at_freebsd.org>
Tested by:	Paul B. Mahol <onemda_at_gmail.com>
2009-03-12 02:51:55 +00:00
Warner Losh
155a83e87a remove now-redunant cardbus attachment. 2009-03-09 13:23:54 +00:00
Sam Leffler
f11fe89814 Fix TXPMGT handling:
o correct dBm<->mW conversion logic
o set net80211 TXPMGT capability only if driver reports it is capable

PR:		kern/132342
Submitted by:	"Paul B. Mahol" <onemda@gmail.com>
2009-03-09 02:37:52 +00:00
Weongyo Jeong
6affafd098 o port NDIS USB support from USB1 to the new usb(USB2).
o implement URB_FUNCTION_ABORT_PIPE handling.
o remove unused code related with canceling the timer list for USB
  drivers.
o whitespace cleanup and style(9)

Obtained from:	hps's original patch
2009-03-07 07:26:22 +00:00
Andrew Thompson
3975e3a1ea Move usb to a graveyard location under sys/legacy/dev, it is intended that the
new USB2 stack will fully replace this for 8.0.

Remove kernel modules, a subsequent commit will update conf/files. Unhook
usbdevs from the build.
2009-02-23 18:16:17 +00:00
Andrew Thompson
1e736167a5 Provide a NDIS tx power level converstion to/from net80211, this uses a loookup
table to approximate mW<->dBM.

Submitted by:	Paul B. Mahol
2009-01-12 17:15:09 +00:00
Weongyo Jeong
c862b05ba7 fix a typo to set the 48Mbps data rate.
PR:		kern/130189
Submitted by:	Paul B. Mahol <onemda_at_gmail.com>
Reviewed by:	sam
MFC after:	3 weeks
2009-01-09 02:31:51 +00:00
Weongyo Jeong
b3974c00b5 Integrate the NDIS USB support code to CURRENT.
Now the NDISulator supports NDIS USB drivers that it've tested with
devices as follows:

  - Anygate XM-142 (Conexant)
  - Netgear WG111v2 (Realtek)
  - U-Khan UW-2054u (Marvell)
  - Shuttle XPC Accessory PN20 (Realtek)
  - ipTIME G054U2 (Ralink)
  - UNiCORN WL-54G (ZyDAS)
  - ZyXEL G-200v2 (ZyDAS)

All of them succeeded to attach and worked though there are still some
problems that it's expected to be solved.

To use NDIS USB support, you should rebuild and install ndiscvt(8) and
if you encounter a problem to attach please set `hw.ndisusb.halt' to
0 then retry.

I expect no changes of the NDIS code for PCI, PCMCIA devices.

Obtained from:  //depot/projects/ndisusb/...
2008-12-27 08:03:32 +00:00
Sam Leffler
e0a11d8bec hookup mcast and promisc callbacks
Submitted by:	"Paul B. Mahol" <onemda@gmail.com>
2008-11-30 20:48:57 +00:00
Andrew Thompson
a1f8daf412 Fake the assoc id so that ndis can work on the latest net80211.
PR:		kern/128750
Submitted by:	Paul B. Mahol
2008-11-11 03:36:15 +00:00
Weongyo Jeong
db102f9a37 sc->ndis_txidx should be cycle between 0 and sc->ndis_maxpkts, not
NDIS_TXPKTS and don't allocate unused extra spaces for sc->ndis_txarray
and sc->ndis_txpool.

PR:		kern/127644
Submitted by:	Antoine Pelisse <apelisse_at_gmail.com>
MFC after:	1 week
2008-10-04 04:15:39 +00:00
Coleman Kane
093d7be50e Fix a mutex LOR introduced by the conversion of if_ndis from spinlocks to
mutexes and replacing the obsolete if_watchdog interface. The ndis_ticktask
function calls into ieee80211_new_state under one condition with NDIS_LOCK
held. The ieee80211_new_state would call into ndis_start in some cases too,
resulting in the occasional case where ndis_start acquires NDIS_LOCK from
inside the NDIS_LOCK held by ndis_ticktask.

Obtained from:	Paul B. Mahol <onemda@gmail.com>
MFC after:	1 week
2008-07-09 00:10:55 +00:00
Coleman Kane
21a6592999 Convert ndis_spinlock to ndis_mtx and start using the sleepable
mtx interface for NDIS_LOCK/UNLOCK. This should result in less
CPU utilization on behalf of the ndis driver. Additionally, this
commit also fixes a potential LOR in the ndis_tick code, by
not locking inside the ndis_tick function, but instead delegating
that work to the helpers called through IoQueueWorkItem. The
way that this is currently set up for NDIS prevents us from
simply implementing a callout_init_mtx mechanism.

However, the helper functions that handle the various timeout
cases implement fine-grained locking using the spinlocks provided
by the NDIS-compat layer, and using the mtx that is added with
this commit. This leaves the following ndis_softc members operated
on in ndis_tick in an unlocked context:

  * ndis_hang_timer - Only modified outside of ndis_tick once, before
                      the first callout_reset to schedule ndis_tick
  * ifp->if_oerrors - Only incremented in two places, which should be
                      an atomic op
  * ndis_tx_timer   - Assigned to 5 (when guaranteed to be 0) or 0
                      (in txeof), to indicate to ndis_tick what to
                      do. This is the only member of which I was
                      suspicious for needing the NDIS_LOCK here. My
                      testing (and another's) have been fine so far.
  * ndis_stat_callout - Only uses a simple set of callout routines,
                        callout_reset only called by ndis_tick after
                        the initial reset, and then callout_drain is
                        used exactly once in shutdown code.

The benefit is that ndis_tick doesn't acquire NDIS_LOCK unless one of
the timeout conditions is flagged, and it still obeys the locking
order semantics that are dictated by the NDIS layer at the moment. I
have been investigating a more thorough s/spinlock/mtx/ of the NDIS
layer, but the simplest naive approach (replace KeAcquireSpinLock
with an mtx implementation) has anti-succeeded for me so far. This
is a good first step though.

Tested by:	onemda@gmail.com
Reviewed by:	current@, jhb, thompsa
Proposed by:	jhb
2008-06-11 13:40:15 +00:00
Coleman Kane
e97f228a10 Update if_ndis to remove the legacy if_watchdog interface and
bring it more up to date. The watchdog timer, and its
associated code, is all collapsed into the ndis_tick function
that was implemented for the NDIS-subsystem watchdog. This
implementation is similar to what numerous other drivers use
to implement the watchdog.

Reviewed by:	thompsa, jhb
MFC after:	2 weeks
2008-06-03 00:55:48 +00:00
Weongyo Jeong
e54b92f37b Fix a panic that it's occurred when NDIS init handler returned a error
by unknown reasons.   In this case, sc->ifp is still NULL so it will
cause a page fault during calling ndis_detach()
2008-05-30 07:17:51 +00:00
Sam Leffler
c43feede8b Minor cleanup of vap create work:
o add IEEE80211_C_STA capability to indicate sta mode is supported
  (was previously assumed) and mark drivers as capable
o add ieee80211_opcap array to map an opmode to the equivalent capability bit
o move IEEE80211_C_OPMODE definition to where capabilities are defined so it's
  clear it should be kept in sync (on future additions)
o check device capabilities in clone create before trying to create a vap;
  this makes driver checks unneeded
o make error codes return on failed clone request unique
o temporarily add console printfs on clone request failures to aid in
  debugging; these will move under DIAGNOSTIC or similar before release
2008-05-12 00:15:30 +00:00
Andrew Thompson
6ba643ce87 - Associate from a taskq as we can deadlock on the ndis hal and the com lock.
- Remove double vap init (ieee80211_start_all)
- Keep ic_curchan in sync with the scan results.
2008-05-10 20:12:43 +00:00
Andrew Thompson
517b468a5d Partially revert the last rev. Do call ndis_setstate_80211() when we up the
interface but break out the associate code into a separate function. This fixes
association with an 11b Apple Airport.

Reported by:	Ted Lindgreen
2008-05-10 20:07:00 +00:00
Andrew Thompson
3fec7550c6 Do not call ndis_setstate_80211() until we are ready to associate, the vap may
not have been created yet and will panic. This requires ndis_scan() to always
set the SSID.

Reported by:	Ben Kaduk
2008-05-01 05:11:33 +00:00
Andrew Thompson
31a8c1edd8 Unify all the wifi *_ioctl routines
- Limit grabbing the lock to SIOCSIFFLAGS.
 - Move ieee80211_start_all() to SIOCSIFFLAGS.
 - Remove SIOCSIFMEDIA as it is not useful.
 - Limit ether_ioctl to only SIOCGIFADDR. SIOCSIFADDR and SIOCSIFMTU have no
   affect as there is no input/output path in the vap parent.  The vap code
   will handle the reinit of the mac address changes.
 - Split off ndis_ioctl_80211 as it was getting too different to wired devices.

This fixes a copyout while locked and a lock recursion.

Reviewed by:		sam
2008-05-01 04:55:00 +00:00
Sam Leffler
b032f27c36 Multi-bss (aka vap) support for 802.11 devices.
Note this includes changes to all drivers and moves some device firmware
loading to use firmware(9) and a separate module (e.g. ral).  Also there
no longer are separate wlan_scan* modules; this functionality is now
bundled into the wlan module.

Supported by:	Hobnob and Marvell
Reviewed by:	many
Obtained from:	Atheros (some bits)
2008-04-20 20:35:46 +00:00
Coleman Kane
12b6a0f87c Change the 1 in callout_init to CALLOUT_MPSAFE. I made the change in my
tree, but never committed it into git before making my patch!

Submitted by:	thompsa
MFC after:	1 month
2008-04-17 22:57:33 +00:00
Coleman Kane
aba7c5b84b Change the timeout(9) usage in if_ndis to a callout(9) implementation,
as the former is becoming deprecated and exhibits some extraneous
Giant-locking. The new callout(9) is declared MPSAFE, so it may
improve concurrency.

Tested by:	matteo
Silence from:	wpaul
MFC after:	1 month
2008-04-17 22:01:38 +00:00
John Baldwin
9a57f6280c Use pause(9) instead of a tsleep() on a stack variable.
MFC after:	1 week
2008-01-17 20:11:58 +00:00
Andrew Thompson
2aec24b515 sc->ndis_tq variable is only initialized when a driver module is for wireless
NICs.

PR:		kern/118439
Submitted by:	Weongyo Jeong
2007-12-09 20:14:01 +00:00
Andrew Thompson
30d9c7698a Preallocate some space to return the scan results, some drivers do not properly
pass back the desired buffer length. This fixes scanning with the Marvell
88W8335 and BCM4328 wireless cards.

PR:		kern/118370
Submitted by:	Weongyo Jeong
Tested by:	Ed Schouten
2007-12-07 10:37:25 +00:00
Wojciech A. Koszek
8b249eccbc Cast address of 'bssid' to uint8_t since printf() expects to get unsigned
argument in %6D case.

Submitted by:	thompsa
Compile-tested:	wkoszek
Reviewed by:	cognet (mentor)
Approved by:	cognet (mentor)
2007-12-04 20:48:32 +00:00
Andrew Thompson
7218dd5f5a Remove compatibilty defines to simplify reading the code, this is around 10% of
the total LOC. These are mostly for the 6.x branch and it will be easier to
cherrypick any changes (if at all).
2007-12-03 21:51:28 +00:00
Andrew Thompson
4d50f65ceb Hide a debug printf, NDIS_DEBUG is always defined and we test the sysctl.
MFC after:	3 days
2007-12-02 09:03:43 +00:00
Julian Elischer
3745c395ec Rename the kthread_xxx (e.g. kthread_create()) calls
to kproc_xxx as they actually make whole processes.
Thos makes way for us to add REAL kthread_create() and friends
that actually make theads. it turns out that most of these
calls actually end up being moved back to the thread version
when it's added. but we need to make this cosmetic change first.

I'd LOVE to do this rename in 7.0  so that we can eventually MFC the
new kthread_xxx() calls.
2007-10-20 23:23:23 +00:00
Andrew Thompson
c4dd9fb67a Fix up ndis interaction with net80211
- make NDIS_DEBUG a sysctl
 - default to IEEE80211_MODE_11B if the card doesnt tell us the channels
 - dont mess with ic_des_chan when we assosciate
 - Allow a directed scan by setting the ESSID before scanning (verified
   with wireshark). Hidden APs probably wouldnt have worked before.
 - Grab the channel type and use it to look up the correct curchan for
   the scan results (mistakenly used 11B before)
 - Fix memory leak in the ndis_scan_results

Tested by:	matteo
Reviewed by:	sam
Approved by:	re (rwatson)
2007-07-26 20:11:16 +00:00
Andrew Thompson
cddce0cb90 Improve the net80211 handling within ndis
- use net80211 for scanning and pass the results back to the scan cache
 - use ieee80211_init_channels to fill our channel list
 - fix up state transitions
 - depreciate the old wicontrol ioctls
 - add some debugging lines (#define NDIS_DEBUG)

Reviewed by:	sam
Approved by:	re (kensmith)
2007-07-12 02:54:05 +00:00
Warner Losh
79d80dc284 finish removing usb_port.h macros.
Use device_foo_t to declare functions
a little de-k&r
2007-06-18 22:24:32 +00:00
Warner Losh
645016c0e4 Expand USB_ATTACH_{ERROR,SUCCESS}_RETURN inline and eliminate from
usb_port.h.  They aren't needed, and are a legacy of this code's past.
2007-06-12 15:37:19 +00:00
Sam Leffler
68e8e04e93 Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
  fully enumerated and uniquely identify the operating characteristics;
  these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
  background scanning and roaming
o move scanning support into loadable modules based on the operating
  mode to enable different policies and reduce the memory footprint
  on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
  mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
  we use a simple algorithm to trigger a roam: we threshold the rssi
  and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
  drivers but is incomplete; it's included now to establish a baseline
  for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
  prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
  encapsulation (note this can be used with any card that can tx+rx
  large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
  authentication and association failures
o enable the addition of sta mode power save support for drivers that need
  net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
  results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
  index into the rate set; this needs to be extended to deal with
  multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing

Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
       dynamic turbo (lightly tested), 11n (sniffing only and needs
       new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
       rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested

This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others.  Much of the scanning work was supported by
Atheros.  The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
Matt Jacob
a443a26379 Initialize irql to something prior to calls that (might) set it.
Whined about: gcc 4.2
2007-05-20 16:59:37 +00:00
Pawel Jakub Dawidek
93caf77f95 Use strcasecmp() from libkern. 2007-04-06 11:21:01 +00:00
Sam Leffler
6dbd16f1cc change ic_modecaps to a bit vector and use setbit, et. al. 2007-03-11 22:37:32 +00:00
Jung-uk Kim
7be240e621 Fix shared authentication mode. 2006-12-28 00:05:40 +00:00
Robert Watson
acd3428b7d Sweep kernel replacing suser(9) calls with priv(9) calls, assigning
specific privilege names to a broad range of privileges.  These may
require some future tweaking.

Sponsored by:           nCircle Network Security, Inc.
Obtained from:          TrustedBSD Project
Discussed on:           arch@
Reviewed (at least in part) by: mlaier, jmg, pjd, bde, ceri,
                        Alex Lyashkov <umka at sevcity dot net>,
                        Skip Ford <skip dot ford at verizon dot net>,
                        Antoine Brodin <antoine dot brodin at laposte dot net>
2006-11-06 13:42:10 +00:00
Matt Jacob
656cedd455 Static -> static. 2006-09-07 06:00:03 +00:00
Tom Rhodes
2ae23ece2d Catch up with USB changes, device_ptr_t was removed, we need device_t here. 2006-09-07 05:34:04 +00:00
Bill Paul
55ad415824 When ndis_attach() runs, it has to very briefly initialize the card
in order to query the underlying Windows driver for the station address
and some other properties. There is a slim chance that the card may
receive a packet and indicate it up to us before ndis_attach() can call
ndis_halt_nic(). This is bad, because both the softc structure and
the ifnet structure aren't fully initialized yet: many pointers are
still NULL, so if we make it into ndis_rxeof(), we will panic.

To fix this, we need to do the following:

- Move the calls to IoAllocateWorkItem() to before the call to ndis_init_nic().
- Move the initialization of the RX DPC and status callback function pointers
  to before ndis_init_nic() as well.
- Modify ndis_rxeof() to check if the IFF_DRV_RUNNING flag is set. If it
  isn't, we return any supplied NDIS_PACKETs to the NIC without processing
  them.

This fixes a crash than can occur when activating a wireless NIC in
close proximity to a very busy wireless network, reported by Ryan
Beasley (ryan%^$!ATgoddamnbastard-****!!!DOTorg.

MFC after:	3 days
2006-02-04 19:42:49 +00:00
Bill Paul
a807264e92 In ndis_rxeof_eth(), avoid acquiring the NDIS miniport block spinlock for
serialized miniports when updating the packet list.

This fixes a deadlock that can occur with the Ralink RT2500 driver
when using wpa_supplicant.
2005-12-16 17:21:28 +00:00
Bill Paul
b5b548a6bc The latest version of the Intel 2200BG/2915ABG driver (9.0.0.3-9) from
Intel's web site requires some minor tweaks to get it to work:

- The driver seems to have been released with full WMI tracing enabled,
  and makes references to some WMI APIs, namely IoWMIRegistrationControl(),
  WmiQueryTraceInformation() and WmiTraceMessage(). Only the first
  one is ever called (during intialization). These have been implemented
  as do-nothing stubs for now. Also added a definition for STATUS_NOT_FOUND
  to ntoskrnl_var.h, which is used as a return code for one of the WMI
  routines.

- The driver references KeRaiseIrqlToDpcLevel() and KeLowerIrql()
  (the latter as a function, which is unusual because normally
  KeLowerIrql() is a macro in the Windows DDK that calls KfLowewIrql()).
  I'm not sure why these are being called since they're not really
  part of WDM. Presumeably they're being used for backwards
  compatibility with old versions of Windows. These have been
  implemented in subr_hal.c. (Note that they're _stdcall routines
  instead of _fastcall.)

- When querying the OID_802_11_BSSID_LIST OID to get a BSSID list,
  you don't know ahead of time how many networks the NIC has found
  during scanning, so you're allowed to pass 0 as the list length.
  This should cause the driver to return an 'insufficient resources'
  error and set the length to indicate how many bytes are actually
  needed. However for some reason, the Intel driver does not honor
  this convention: if you give it a length of 0, it returns some
  other error and doesn't tell you how much space is really needed.
  To get around this, if using a length of 0 yields anything besides
  the expected error case, we arbitrarily assume a length of 64K.
  This is similar to the hack that wpa_supplicant uses when doing
  a BSSID list query.
2005-11-06 19:38:34 +00:00
Bill Paul
a91395a9d0 Tests with my dual Opteron system have shown that it's possible
for code to start out on one CPU when thunking into Windows
mode in ctxsw_utow(), and then be pre-empted and migrated to another
CPU before thunking back to UNIX mode in ctxsw_wtou(). This is
bad, because then we can end up looking at the wrong 'thread environment
block' when trying to come back to UNIX mode. To avoid this, we now
pin ourselves to the current CPU when thunking into Windows code.

Few other cleanups, since I'm here:

- Get rid of the ndis_isr(), ndis_enable_interrupt() and
  ndis_disable_interrupt() wrappers from kern_ndis.c and just invoke
  the miniport's methods directly in the interrupt handling routines
  in subr_ndis.c. We may as well lose the function call overhead,
  since we don't need to export these things outside of ndis.ko
  now anyway.

- Remove call to ndis_enable_interrupt() from ndis_init() in if_ndis.c.
  We don't need to do it there anyway (the miniport init routine handles
  it, if needed).

- Fix the logic in NdisWriteErrorLogEntry() a little.

- Change some NDIS_STATUS_xxx codes in subr_ntoskrnl.c into STATUS_xxx
  codes.

- Handle kthread_create() failure correctly in PsCreateSystemThread().
2005-11-02 18:01:04 +00:00
Bill Paul
068b664206 Fix ndis_getstate_80211() so that it properly reports the authmode
and channel to ifconfig. Also use the SSID and channel info from
the association info that we already have instead of using ndis_get_info()
to ask the driver for it again.
2005-10-29 02:18:27 +00:00
Bill Paul
ef74f2c9c5 Correct some __FreeBSD_version conditionals to use version bumps closer
to the actual dates when code actually changed. Also add special case
link state change handling for RELENG_5, which doesn't have
if_link_state_change(). No actual operational changes are done.
2005-10-25 16:14:34 +00:00
Bill Paul
ac350b125a Do not allow ndis_ticktask() to run after ndis_halt_nic() has been called.
(It may have been queued up in one of the workitem threads, and letting
it fire after the NIC has been halted will cause a crash in some cases.)
2005-10-24 17:47:47 +00:00
Bill Paul
baa6396dc1 Correct the size used to allocate ndis_txarray. It should be
NDIS_TXPKTS now, not ndis_maxpkts.
2005-10-19 03:14:11 +00:00
Bill Paul
a3ced67adf Another round of cleanups and fixes:
- Change ndis_return() from a DPC to a workitem so that it doesn't
  run at DISPATCH_LEVEL (with the dispatcher lock held).

- In if_ndis.c, submit packets to the stack via (*ifp->if_input)() in
  a workitem instead of doing it directly in ndis_rxeof(), because
  ndis_rxeof() runs in a DPC, and hence at DISPATCH_LEVEL. This
  implies that the 'dispatch level' mutex for the current CPU is
  being held, and we don't want to call if_input while holding
  any locks.

- Reimplement IoConnectInterrupt()/IoDisconnectInterrupt(). The original
  approach I used to track down the interrupt resource (by scanning
  the device tree starting at the nexus) is prone to problems when
  two devices share an interrupt. (E.g removing ndis1 might disable
  interrupts for ndis0.) The new approach is to multiplex all the
  NDIS interrupts through a common internal dispatcher (ntoskrnl_intr())
  and allow IoConnectInterrupt()/IoDisconnectInterrupt() to add or
  remove interrupts from the dispatch list.

- Implement KeAcquireInterruptSpinLock() and KeReleaseInterruptSpinLock().

- Change the DPC and workitem threads to use the KeXXXSpinLock
  API instead of mtx_lock_spin()/mtx_unlock_spin().

- Simplify the NdisXXXPacket routines by creating an actual
  packet pool structure and using the InterlockedSList routines
  to manage the packet queue.

- Only honor the value returned by OID_GEN_MAXIMUM_SEND_PACKETS
  for serialized drivers. For deserialized drivers, we now create
  a packet array of 64 entries. (The Microsoft DDK documentation
  says that for deserialized miniports, OID_GEN_MAXIMUM_SEND_PACKETS
  is ignored, and the driver for the Marvell 8335 chip, which is
  a deserialized miniport, returns 1 when queried.)

- Clean up timer handling in subr_ntoskrnl.

- Add the following conditional debugging code:
	NTOSKRNL_DEBUG_TIMERS - add debugging and stats for timers
	NDIS_DEBUG_PACKETS - add extra sanity checking for NdisXXXPacket API
	NTOSKRNL_DEBUG_SPINLOCKS - add test for spinning too long

- In kern_ndis.c, always start the HAL first and shut it down last,
  since Windows spinlocks depend on it. Ntoskrnl should similarly be
  started second and shut down next to last.
2005-10-18 19:52:15 +00:00
Bill Paul
93a08226da Fix build: remove stale KASSERT() for mutex that no longer exists. 2005-10-11 21:31:23 +00:00
Bill Paul
31333e7fcb Grrr. Add one more missing NDIS_UNLOCK(). 2005-10-10 18:41:36 +00:00
Bill Paul
c4095c0551 Add missing NDIS_UNLOCK() in one of the failure cases in SIOCGPRIVATE_0. 2005-10-10 18:17:46 +00:00
Bill Paul
21628ddbd6 This commit makes a big round of updates and fixes many, many things.
First and most importantly, I threw out the thread priority-twiddling
implementation of KeRaiseIrql()/KeLowerIrq()/KeGetCurrentIrql() in
favor of a new scheme that uses sleep mutexes. The old scheme was
really very naughty and sought to provide the same behavior as
Windows spinlocks (i.e. blocking pre-emption) but in a way that
wouldn't raise the ire of WITNESS. The new scheme represents
'DISPATCH_LEVEL' as the acquisition of a per-cpu sleep mutex. If
a thread on cpu0 acquires the 'dispatcher mutex,' it will block
any other thread on the same processor that tries to acquire it,
in effect only allowing one thread on the processor to be at
'DISPATCH_LEVEL' at any given time. It can then do the 'atomic sit
and spin' routine on the spinlock variable itself. If a thread on
cpu1 wants to acquire the same spinlock, it acquires the 'dispatcher
mutex' for cpu1 and then it too does an atomic sit and spin to try
acquiring the spinlock.

Unlike real spinlocks, this does not disable pre-emption of all
threads on the CPU, but it does put any threads involved with
the NDISulator to sleep, which is just as good for our purposes.

This means I can now play nice with WITNESS, and I can safely do
things like call malloc() when I'm at 'DISPATCH_LEVEL,' which
you're allowed to do in Windows.

Next, I completely re-wrote most of the event/timer/mutex handling
and wait code. KeWaitForSingleObject() and KeWaitForMultipleObjects()
have been re-written to use condition variables instead of msleep().
This allows us to use the Windows convention whereby thread A can
tell thread B "wake up with a boosted priority." (With msleep(), you
instead have thread B saying "when I get woken up, I'll use this
priority here," and thread A can't tell it to do otherwise.) The
new KeWaitForMultipleObjects() has been better tested and better
duplicates the semantics of its Windows counterpart.

I also overhauled the IoQueueWorkItem() API and underlying code.
Like KeInsertQueueDpc(), IoQueueWorkItem() must insure that the
same work item isn't put on the queue twice. ExQueueWorkItem(),
which in my implementation is built on top of IoQueueWorkItem(),
was also modified to perform a similar test.

I renamed the doubly-linked list macros to give them the same names
as their Windows counterparts and fixed RemoveListTail() and
RemoveListHead() so they properly return the removed item.

I also corrected the list handling code in ntoskrnl_dpc_thread()
and ntoskrnl_workitem_thread(). I realized that the original logic
did not correctly handle the case where a DPC callout tries to
queue up another DPC. It works correctly now.

I implemented IoConnectInterrupt() and IoDisconnectInterrupt() and
modified NdisMRegisterInterrupt() and NdisMDisconnectInterrupt() to
use them. I also tried to duplicate the interrupt handling scheme
used in Windows. The interrupt handling is now internal to ndis.ko,
and the ndis_intr() function has been removed from if_ndis.c. (In
the USB case, interrupt handling isn't needed in if_ndis.c anyway.)

NdisMSleep() has been rewritten to use a KeWaitForSingleObject()
and a KeTimer, which is how it works in Windows. (This is mainly
to insure that the NDISulator uses the KeTimer API so I can spot
any problems with it that may arise.)

KeCancelTimer() has been changed so that it only cancels timers, and
does not attempt to cancel a DPC if the timer managed to fire and
queue one up before KeCancelTimer() was called. The Windows DDK
documentation seems to imply that KeCantelTimer() will also call
KeRemoveQueueDpc() if necessary, but it really doesn't.

The KeTimer implementation has been rewritten to use the callout API
directly instead of timeout()/untimeout(). I still cheat a little in
that I have to manage my own small callout timer wheel, but the timer
code works more smoothly now. I discovered a race condition using
timeout()/untimeout() with periodic timers where untimeout() fails
to actually cancel a timer. I don't quite understand where the race
is, using callout_init()/callout_reset()/callout_stop() directly
seems to fix it.

I also discovered and fixed a bug in winx32_wrap.S related to
translating _stdcall calls. There are a couple of routines
(i.e. the 64-bit arithmetic intrinsics in subr_ntoskrnl) that
return 64-bit quantities. On the x86 arch, 64-bit values are
returned in the %eax and %edx registers. However, it happens
that the ctxsw_utow() routine uses %edx as a scratch register,
and x86_stdcall_wrap() and x86_stdcall_call() were only preserving
%eax before branching to ctxsw_utow(). This means %edx was getting
clobbered in some cases. Curiously, the most noticeable effect of this
bug is that the driver for the TI AXC110 chipset would constantly drop
and reacquire its link for no apparent reason. Both %eax and %edx
are preserved on the stack now. The _fastcall and _regparm
wrappers already handled everything correctly.

I changed if_ndis to use IoAllocateWorkItem() and IoQueueWorkItem()
instead of the NdisScheduleWorkItem() API. This is to avoid possible
deadlocks with any drivers that use NdisScheduleWorkItem() themselves.

The unicode/ansi conversion handling code has been cleaned up. The
internal routines have been moved to subr_ntoskrnl and the
RtlXXX routines have been exported so that subr_ndis can call them.
This removes the incestuous relationship between the two modules
regarding this code and fixes the implementation so that it honors
the 'maxlen' fields correctly. (Previously it was possible for
NdisUnicodeStringToAnsiString() to possibly clobber memory it didn't
own, which was causing many mysterious crashes in the Marvell 8335
driver.)

The registry handling code (NdisOpen/Close/ReadConfiguration()) has
been fixed to allocate memory for all the parameters it hands out to
callers and delete whem when NdisCloseConfiguration() is called.
(Previously, it would secretly use a single static buffer.)

I also substantially updated if_ndis so that the source can now be
built on FreeBSD 7, 6 and 5 without any changes. On FreeBSD 5, only
WEP support is enabled. On FreeBSD 6 and 7, WPA-PSK support is enabled.

The original WPA code has been updated to fit in more cleanly with
the net80211 API, and to eleminate the use of magic numbers. The
ndis_80211_setstate() routine now sets a default authmode of OPEN
and initializes the RTS threshold and fragmentation threshold.
The WPA routines were changed so that the authentication mode is
always set first, followed by the cipher. Some drivers depend on
the operations being performed in this order.

I also added passthrough ioctls that allow application code to
directly call the MiniportSetInformation()/MiniportQueryInformation()
methods via ndis_set_info() and ndis_get_info(). The ndis_linksts()
routine also caches the last 4 events signalled by the driver via
NdisMIndicateStatus(), and they can be queried by an application via
a separate ioctl. This is done to allow wpa_supplicant to directly
program the various crypto and key management options in the driver,
allowing things like WPA2 support to work.

Whew.
2005-10-10 16:46:39 +00:00
Max Laier
b6de9e91bd Remove bridge(4) from the tree. if_bridge(4) is a full functional
replacement and has additional features which make it superior.

Discussed on:	-arch
Reviewed by:	thompsa
X-MFC-after:	never (RELENG_6 as transition period)
2005-09-27 18:10:43 +00:00
Warner Losh
ad4f426ef6 Make sure that we call if_free(ifp) after bus_teardown_intr. Since we
could get an interrupt after we free the ifp, and the interrupt
handler depended on the ifp being still alive, this could, in theory,
cause a crash.  Eliminate this possibility by moving the if_free to
after the bus_teardown_intr() call.
2005-09-19 03:10:21 +00:00
Robert Watson
13f4c340ae Propagate rename of IFF_OACTIVE and IFF_RUNNING to IFF_DRV_OACTIVE and
IFF_DRV_RUNNING, as well as the move from ifnet.if_flags to
ifnet.if_drv_flags.  Device drivers are now responsible for
synchronizing access to these flags, as they are in if_drv_flags.  This
helps prevent races between the network stack and device driver in
maintaining the interface flags field.

Many __FreeBSD__ and __FreeBSD_version checks maintained and continued;
some less so.

Reviewed by:	pjd, bz
MFC after:	7 days
2005-08-09 10:20:02 +00:00
Robert Watson
13b203d0d7 Modify device drivers supporting multicast addresses to lock if_addr_mtx
over iteration of their multicast address lists when synchronizing the
hardware address filter with the network stack-maintained list.

Problem reported by:	Ed Maste (emaste at phaedrus dot sandvine dot ca>
MFC after:		1 week
2005-08-03 00:18:35 +00:00
Brooks Davis
bc3552517b Move if_alloc() higher in the attach function so sc->ifp is populated
early.  I've moved it all the way to the top rather than part way up as
the submitter did.

Submitted by:	Jung-uk Kim <jkim at niksun dot com>
Reported by:	submitter, le, dougb
Approved by:	re (ifnet blanket)
2005-06-14 17:47:31 +00:00
Brooks Davis
fc74a9f93a Stop embedding struct ifnet at the top of driver softcs. Instead the
struct ifnet or the layer 2 common structure it was embedded in have
been replaced with a struct ifnet pointer to be filled by a call to the
new function, if_alloc(). The layer 2 common structure is also allocated
via if_alloc() based on the interface type. It is hung off the new
struct ifnet member, if_l2com.

This change removes the size of these structures from the kernel ABI and
will allow us to better manage them as interfaces come and go.

Other changes of note:
 - Struct arpcom is no longer referenced in normal interface code.
   Instead the Ethernet address is accessed via the IFP2ENADDR() macro.
   To enforce this ac_enaddr has been renamed to _ac_enaddr.
 - The second argument to ether_ifattach is now always the mac address
   from driver private storage rather than sometimes being ac_enaddr.

Reviewed by:	sobomax, sam
2005-06-10 16:49:24 +00:00
Yoshihiro Takahashi
d4fcf3cba5 Remove bus_{mem,p}io.h and related code for a micro-optimization on i386
and amd64.  The optimization is a trivial on recent machines.

Reviewed by:	-arch (imp, marcel, dfr)
2005-05-29 04:42:30 +00:00
Bill Paul
450a94af7a Deal with a few bootstrap issues:
We can't call KeFlushQueuedDpcs() during bootstrap (cold == 1), since
the flush operation sleeps to wait for completion, and we can't sleep
here (clowns will eat us).

On an i386 SMP system, if we're loaded/probed/attached during bootstrap,
smp_rendezvous() won't run us anywhere except CPU 0 (since the other CPUs
aren't launched until later), which means we won't be able to set up
the GDTs anywhere except CPU 0. To deal with this case, ctxsw_utow()
now checks to see if the TID for the current processor has been properly
initialized and sets up the GTD for the current CPU if not.

Lastly, in if_ndis.c:ndis_shutdown(), do an ndis_stop() to insure we
really halt the NIC and stop interrupts from happening.

Note that loading a driver during bootstrap is, unfortunately, kind of
a hit or miss sort of proposition. In Windows, the expectation is that
by the time a given driver's MiniportInitialize() method is called,
the system is already in 'multiuser' state, i.e. it's up and running
enough to support all the stuff specified in the NDIS API, which includes
the underlying OS-supplied facilities it implicitly depends on, such as
having all CPUs running, having the DPC queues initialized, WorkItem
threads running, etc. But in UNIX, a lot of that stuff won't work during
bootstrap. This causes a problem since we need to call MiniportInitialize()
at least once during ndis_attach() in order to find out what kind of NIC
we have and learn its station address.

What this means is that some cards just plain won't work right if
you try to pre-load the driver along with the kernel: they'll only be
probed/attach correctly if the driver is kldloaded _after_ the system
has reached multiuser. I can't really think of a way around this that
would still preserve the ability to use an NDIS device for diskless
booting.
2005-05-20 04:00:50 +00:00
Bill Paul
cebddbda3b In ndis_halt_nic(), invalidate the miniportadapterctx early to try and
prevent anything from making calls to the NIC while it's being shut down.
This is yet another attempt to stop things like mdnsd from trying to
poke at the card while it's not properly initialized and panicking
the system.

Also, remove unneeded debug message from if_ndis.c.
2005-05-20 02:35:43 +00:00
Bill Paul
02fa4220cd Correct type for workitem routines. 2005-05-16 16:50:52 +00:00
Bill Paul
433d61bb56 Add support for NdisMEthIndicateReceive() and MiniportTransferData().
The Ralink RT2500 driver uses this API instead of NdisMIndicateReceivePacket().

Drivers use NdisMEthIndicateReceive() when they know they support
802.3 media and expect to hand their packets only protocols that want
to deal with that particular media type. With this API, the driver does
not manage its own NDIS_PACKET/NDIS_BUFFER structures. Instead, it
lets bound protocols have a peek at the data, and then they supply
an NDIS_PACKET/NDIS_BUFFER combo to the miniport driver, into which
it copies the packet data.

Drivers use NdisMIndicateReceivePacket() to allow their packets to
be read by any protocol, not just those bound to 802.3 media devices.

To make this work, we need an internal pool of NDIS_PACKETS for
receives. Currently, we check to see if the driver exports a
MiniportTransferData() method in its characteristics structure,
and only allocate the pool for drivers that have this method.

This should allow the RT2500 driver to work correctly, though I
still have to fix ndiscvt(8) to parse its .inf file properly.

Also, change kern_ndis.c:ndis_halt_nic() to reap timers before
acquiring NDIS_LOCK(), since the reaping process might entail sleeping
briefly (and we can't sleep with a lock held).
2005-05-15 04:27:59 +00:00
Bill Paul
239a676456 More fixes for multibus drivers. When calling out to the match
function in if_ndis_pci.c and if_ndis_pccard.c, provide the bustype
too so the stubs can ignore devlists that don't concern them.
2005-05-08 23:19:20 +00:00
Bill Paul
6169e4d097 Fix support for Windows drivers that support both PCI and PCMCIA devices at
the same time.

Fix if_ndis_pccard.c so that it sets sc->ndis_dobj and sc->ndis_regvals.

Correct IMPORT_SFUNC() macros for the READ_PORT_BUFFER_xxx() routines,
which take 3 arguments, not 2.

This fixes it so that the Windows driver for my Cisco Aironet 340 PCMCIA
card works again. (Yes, I know the an(4) driver supports this card natively,
but it's the only PCMCIA device I have with a Windows XP driver.)
2005-05-08 23:07:51 +00:00
Bill Paul
971aba5809 Avoid trying to queue up an interrupt handler DPC if the driver
hasn't called NdisMRegisterInterrupt() yet.
2005-05-08 09:36:16 +00:00
Bill Paul
a6e6c501af Minor correction to the logic for selecting the proper device index. 2005-05-08 02:06:57 +00:00
Bill Paul
eb31d50cc7 Avoid sleeping with mutex held in kern_ndis.c.
Remove unused fields from ndis_miniport_block.

Fix a bug in KeFlushQueuedDpcs() (we weren't calculating the kq pointer
correctly).

In if_ndis.c, clear the IFF_RUNNING flag before calling ndis_halt_nic().

Add some guards in kern_ndis.c to avoid letting anyone invoke ndis_get_info()
or ndis_set_info() if the NIC isn't fully initialized. Apparently, mdnsd
will sometimes try to invoke the ndis_ioctl() routine at exactly the
wrong moment (to futz with its multicast filters) when the interface
comes up, and can trigger a crash unless we guard against it.
2005-05-05 06:14:59 +00:00
Bill Paul
9b307fe2be This commit makes a bunch of changes, some big, some not so big.
- Remove the old task threads from kern_ndis.c and reimplement them in
  subr_ntoskrnl.c, in order to more properly emulate the Windows DPC
  API. Each CPU gets its own DPC queue/thread, and each queue can
  have low, medium and high importance DPCs. New APIs implemented:
  KeSetTargetProcessorDpc(), KeSetImportanceDpc() and KeFlushQueuedDpcs().
  (This is the biggest change.)

- Fix a bug in NdisMInitializeTimer(): the k_dpc pointer in the
  nmt_timer embedded in the ndis_miniport_timer struct must be set
  to point to the DPC, also embedded in the struct. Failing to do
  this breaks dequeueing of DPCs submitted via timers, and in turn
  breaks cancelling timers.

- Fix a bug in KeCancelTimer(): if the timer is interted in the timer
  queue (i.e. the timeout callback is still pending), we have to both
  untimeout() the timer _and_ call KeRemoveQueueDpc() to nuke the DPC
  that might be pending. Failing to do this breaks cancellation of
  periodic timers, which always appear to be inserted in the timer queue.

- Make use of the nmt_nexttimer field in ndis_miniport_timer: keep a
  queue of pending timers and cancel them all in ndis_halt_nic(), prior
  to calling MiniportHalt(). Also call KeFlushQueuedDpcs() to make sure
  any DPCs queued by the timers have expired.

- Modify NdisMAllocateSharedMemory() and NdisMFreeSharedMemory() to keep
  track of both the virtual and physical addresses of the shared memory
  buffers that get handed out. The AirGo MIMO driver appears to have a bug
  in it: for one of the segments is allocates, it returns the wrong
  virtual address. This would confuse NdisMFreeSharedMemory() and cause
  a crash. Why it doesn't crash Windows too I have no idea (from reading
  the documentation for NdisMFreeSharedMemory(), it appears to be a violation
  of the API).

- Implement strstr(), strchr() and MmIsAddressValid().

- Implement IoAllocateWorkItem(), IoFreeWorkItem(), IoQueueWorkItem() and
  ExQueueWorkItem(). (This is the second biggest change.)

- Make NdisScheduleWorkItem() call ExQueueWorkItem(). (Note that the
  ExQueueWorkItem() API is deprecated by Microsoft, but NDIS still uses
  it, since NdisScheduleWorkItem() is incompatible with the IoXXXWorkItem()
  API.)

- Change if_ndis.c to use the NdisScheduleWorkItem() interface for scheduling
  tasks.

With all these changes and fixes, the AirGo MIMO driver for the Belkin
F5D8010 Pre-N card now works. Special thanks to Paul Robinson
(paul dawt robinson at pwermedia dawt net) for the loan of a card
for testing.
2005-05-05 03:56:09 +00:00
Bill Paul
96b50ea387 Throw the switch on the new driver generation/loading mechanism. From
here on in, if_ndis.ko will be pre-built as a module, and can be built
into a static kernel (though it's not part of GENERIC). Drivers are
created using the new ndisgen(8) script, which uses ndiscvt(8) under
the covers, along with a few other tools. The result is a driver module
that can be kldloaded into the kernel.

A driver with foo.inf and foo.sys files will be converted into
foo_sys.ko (and foo_sys.o, for those who want/need to make static
kernels). This module contains all of the necessary info from the
.INF file and the driver binary image, converted into an ELF module.
You can kldload this module (or add it to /boot/loader.conf) to have
it loaded automatically. Any required firmware files can be bundled
into the module as well (or converted/loaded separately).

Also, add a workaround for a problem in NdisMSleep(). During system
bootstrap (cold == 1), msleep() always returns 0 without actually
sleeping. The Intel 2200BG driver uses NdisMSleep() to wait for
the NIC's firmware to come to life, and fails to load if NdisMSleep()
doesn't actually delay. As a workaround, if msleep() (and hence
ndis_thsuspend()) returns 0, use a hard DELAY() to sleep instead).
This is not really the right thing to do, but we can't really do much
else. At the very least, this makes the Intel driver happy.

There are probably other drivers that fail in this way during bootstrap.
Unfortunately, the only workaround for those is to avoid pre-loading
them and kldload them once the system is running instead.
2005-04-24 20:21:22 +00:00
Bill Paul
d365e2f833 Small cleanup of the WPA code additions. The SIOCG80211 and SIOCS80211
ioctls are now handled explicitly, but we can't really do anything
with them unless the NIC is up (trying to get/set a parameter when
the NDIS driver isn't running always yields an error). If something
invokes either of these ioctls and the NIC isn't initialized, punt
to the default ieee80211_ioctl() routine.
2005-04-20 02:17:53 +00:00
Bill Paul
c2ea1490f8 Add preliminary support for WPA-PSK using wpa_supplicant and the
net80211 code, graciously contributed by Arvind Srinivasan.

Submitted by:	Arvind Srinivasan arvind at celar daht us
2005-04-19 15:30:44 +00:00
Bill Paul
d02239a3af Create new i386 windows/bsd thunking layer, similar to the amd64 thunking
layer, but with a twist.

The twist has to do with the fact that Microsoft supports structured
exception handling in kernel mode. On the i386 arch, exception handling
is implemented by hanging an exception registration list off the
Thread Environment Block (TEB), and the TEB is accessed via the %fs
register. The problem is, we use %fs as a pointer to the pcpu stucture,
which means any driver that tries to write through %fs:0 will overwrite
the curthread pointer and make a serious mess of things.

To get around this, Project Evil now creates a special entry in
the GDT on each processor. When we call into Windows code, a context
switch routine will fix up %fs so it points to our new descriptor,
which in turn points to a fake TEB. When the Windows code returns,
or calls out to an external routine, we swap %fs back again. Currently,
Project Evil makes use of GDT slot 7, which is all 0s by default.
I fully expect someone to jump up and say I can't do that, but I
couldn't find any code that makes use of this entry anywhere. Sadly,
this was the only method I could come up with that worked on both
UP and SMP. (Modifying the LDT works on UP, but becomes incredibly
complicated on SMP.) If necessary, the context switching stuff can
be yanked out while preserving the convention calling wrappers.

(Fortunately, it looks like Microsoft uses some special epilog/prolog
code on amd64 to implement exception handling, so the same nastiness
won't be necessary on that arch.)

The advantages are:

- Any driver that uses %fs as though it were a TEB pointer won't
  clobber pcpu.
- All the __stdcall/__fastcall/__regparm stuff that's specific to
  gcc goes away.

Also, while I'm here, switch NdisGetSystemUpTime() back to using
nanouptime() again. It turns out nanouptime() is way more accurate
than just using ticks(). On slower machines, the Atheros drivers
I tested seem to take a long time to associate due to the loss
in accuracy.
2005-04-11 02:02:35 +00:00
Bill Paul
00df63a690 Remove the last vestiges of the "wait for link down event" hack. 2005-03-28 21:48:15 +00:00
Bill Paul
e0c8c9460c Argh. PCI resource list became an STAILQ instead of an SLIST. Try to
deal with this while maintaining backards source compatibility with
stable.
2005-03-27 10:35:07 +00:00
Bill Paul
7c1968ad82 Finally bring an end to the great "make the Atheros NDIS driver
work on SMP" saga. After several weeks and much gnashing of teeth,
I have finally tracked down all the problems, despite their best
efforts to confound and annoy me.

Problem nunmber one: the Atheros windows driver is _NOT_ a de-serialized
miniport! It used to be that NDIS drivers relied on the NDIS library
itself for all their locking and serialization needs. Transmit packet
queues were all handled internally by NDIS, and all calls to
MiniportXXX() routines were guaranteed to be appropriately serialized.
This proved to be a performance problem however, and Microsoft
introduced de-serialized miniports with the NDIS 5.x spec. Microsoft
still supports serialized miniports, but recommends that all new drivers
written for Windows XP and later be deserialized. Apparently Atheros
wasn't listening when they said this.

This means (among other things) that we have to serialize calls to
MiniportSendPackets(). We also have to serialize calls to MiniportTimer()
that are triggered via the NdisMInitializeTimer() routine. It finally
dawned on me why NdisMInitializeTimer() takes a special
NDIS_MINIPORT_TIMER structure and a pointer to the miniport block:
the timer callback must be serialized, and it's only by saving the
miniport block handle that we can get access to the serialization
lock during the timer callback.

Problem number two: haunted hardware. The thing that was _really_
driving me absolutely bonkers for the longest time is that, for some
reason I couldn't understand, my test machine would occasionally freeze
or more frustratingly, reset completely. That's reset and in *pow!*
back to the BIOS startup. No panic, no crashdump, just a reset. This
appeared to happen most often when MiniportReset() was called. (As
to why MiniportReset() was being called, see problem three below.)
I thought maybe I had created some sort of horrible deadlock
condition in the process of adding the serialization, but after three
weeks, at least 6 different locking implementations and heroic efforts
to debug the spinlock code, the machine still kept resetting. Finally,
I started single stepping through the MiniportReset() routine in
the driver using the kernel debugger, and this ultimately led me to
the source of the problem.

One of the last things the Atheros MiniportReset() routine does is
call NdisReadPciSlotInformation() several times to inspect a portion
of the device's PCI config space. It reads the same chunk of config
space repeatedly, in rapid succession. Presumeably, it's polling
the hardware for some sort of event. The reset occurs partway through
this process. I discovered that when I single-stepped through this
portion of the routine, the reset didn't occur. So I inserted a 1
microsecond delay into the read loop in NdisReadPciSlotInformation().
Suddenly, the reset was gone!!

I'm still very puzzled by the whole thing. What I suspect is happening
is that reading the PCI config space so quickly is causing a severe
PCI bus error. My test system is a Sun w2100z dual Opteron system,
and the NIC is a miniPCI card mounted in a miniPCI-to-PCI carrier card,
plugged into a 100Mhz PCI slot. It's possible that this combination of
hardware causes a bus protocol violation in this scenario which leads
to a fatal machine check. This is pure speculation though. Really all I
know for sure is that inserting the delay makes the problem go away.
(To quote Homer Simpson: "I don't know how it works, but fire makes
it good!")

Problem number three: NdisAllocatePacket() needs to make sure to
initialize the npp_validcounts field in the 'private' section of
the NDIS_PACKET structure. The reason if_ndis was calling the
MiniportReset() routine in the first place is that packet transmits
were sometimes hanging. When sending a packet, an NDIS driver will
call NdisQueryPacket() to learn how many physical buffers the packet
resides in. NdisQueryPacket() is actually a macro, which traverses
the NDIS_BUFFER list attached to the NDIS_PACKET and stashes some
of the results in the 'private' section of the NDIS_PACKET. It also
sets the npp_validcounts field to TRUE To indicate that the results are
now valid. The problem is, now that if_ndis creates a pool of transmit
packets via NdisAllocatePacketPool(), it's important that each time
a new packet is allocated via NdisAllocatePacket() that validcounts
be initialized to FALSE. If it isn't, and a previously transmitted
NDIS_PACKET is pulled out of the pool, it may contain stale data
from a previous transmission which won't get updated by NdisQueryPacket().
This would cause the driver to miscompute the number of fragments
for a given packet, and botch the transmission.

Fixing these three problems seems to make the Atheros driver happy
on SMP, which hopefully means other serialized miniports will be
happy too.

And there was much rejoicing.

Other stuff fixed along the way:

- Modified ndis_thsuspend() to take a mutex as an argument. This
  allows KeWaitForSingleObject() and KeWaitForMultipleObjects() to
  avoid any possible race conditions with other routines that
  use the dispatcher lock.

- Fixed KeCancelTimer() so that it returns the correct value for
  'pending' according to the Microsoft documentation

- Modfied NdisGetSystemUpTime() to use ticks and hz rather than
  calling nanouptime(). Also added comment that this routine wraps
  after 49.7 days.

- Added macros for KeAcquireSpinLock()/KeReleaseSpinLock() to hide
  all the MSCALL() goop.

- For x86, KeAcquireSpinLockRaiseToDpc() needs to be a separate
  function. This is because it's supposed to be _stdcall on the x86
  arch, whereas KeAcquireSpinLock() is supposed to be _fastcall.
  On amd64, all routines use the same calling convention so we can
  just map KeAcquireSpinLockRaiseToDpc() directly to KfAcquireSpinLock()
  and it will work. (The _fastcall attribute is a no-op on amd64.)

- Implement and use IoInitializeDpcRequest() and IoRequestDpc() (they're
  just macros) and use them for interrupt handling. This allows us to
  move the ndis_intrtask() routine from if_ndis.c to kern_ndis.c.

- Fix the MmInitializeMdl() macro so that is uses sizeof(vm_offset_t)
  when computing mdl_size instead of uint32_t, so that it matches the
  MmSizeOfMdl() routine.

- Change a could of M_WAITOKs to M_NOWAITs in the unicode routines in
  subr_ndis.c.

- Use the dispatcher lock a little more consistently in subr_ntoskrnl.c.

- Get rid of the "wait for link event" hack in ndis_init(). Now that
  I fixed NdisReadPciSlotInformation(), it seems I don't need it anymore.
  This should fix the witness panic a couple of people have reported.

- Use MSCALL1() when calling the MiniportHangCheck() function in
  ndis_ticktask(). I accidentally missed this one when adding the
  wrapping for amd64.
2005-03-27 10:14:36 +00:00
Maxim Konovalov
c017b3b664 s/SLIST/STAILQ/
Spotted by:	clive
2005-03-19 19:17:17 +00:00
Bill Paul
58a6edd121 When you call MiniportInitialize() for an 802.11 driver, it will
at some point result in a status event being triggered (it should
be a link down event: the Microsoft driver design guide says you
should generate one when the NIC is initialized). Some drivers
generate the event during MiniportInitialize(), such that by the
time MiniportInitialize() completes, the NIC is ready to go. But
some drivers, in particular the ones for Atheros wireless NICs,
don't generate the event until after a device interrupt occurs
at some point after MiniportInitialize() has completed.

The gotcha is that you have to wait until the link status event
occurs one way or the other before you try to fiddle with any
settings (ssid, channel, etc...). For the drivers that set the
event sycnhronously this isn't a problem, but for the others
we have to pause after calling ndis_init_nic() and wait for the event
to arrive before continuing. Failing to wait can cause big trouble:
on my SMP system, calling ndis_setstate_80211() after ndis_init_nic()
completes, but _before_ the link event arrives, will lock up or
reset the system.

What we do now is check to see if a link event arrived while
ndis_init_nic() was running, and if it didn't we msleep() until
it does.

Along the way, I discovered a few other problems:

- Defered procedure calls run at PASSIVE_LEVEL, not DISPATCH_LEVEL.
  ntoskrnl_run_dpc() has been fixed accordingly. (I read the documentation
  wrong.)

- Similarly, the NDIS interrupt handler, which is essentially a
  DPC, also doesn't need to run at DISPATCH_LEVEL. ndis_intrtask()
  has been fixed accordingly.

- MiniportQueryInformation() and MiniportSetInformation() run at
  DISPATCH_LEVEL, and each request must complete before another
  can be submitted. ndis_get_info() and ndis_set_info() have been
  fixed accordingly.

- Turned the sleep lock that guards the NDIS thread job list into
  a spin lock. We never do anything with this lock held except manage
  the job list (no other locks are held), so it's safe to do this,
  and it's possible that ndis_sched() and ndis_unsched() can be
  called from DISPATCH_LEVEL, so using a sleep lock here is
  semantically incorrect. Also updated subr_witness.c to add the
  lock to the order list.
2005-03-07 03:05:31 +00:00
Bill Paul
55fc1315ca Use 0 instead if NULL for vm_offset_t argument to windrv_lookup() to
silence compiler warnings.
2005-02-28 16:47:54 +00:00
Bill Paul
5d7b952561 Correct e-mail address in copyright. 2005-02-25 02:36:23 +00:00
Bill Paul
d80e940c3c Apparently, the probe routine in if_ndis_usb.c can be called twice
for a given device in some circumstances, so move the PDO creation
to the attach routine so we don't end up creating two PDOs.

Also, when we skip the call to ndis_convert_res() in if_ndis.c:ndis_attach(),
initialize sc->ndis_block->nmb_rlist to NULL. We don't explicitly zero
the miniport block, so this will make sure ndis_unload_driver() does
the right thing.
2005-02-24 22:54:15 +00:00
Bill Paul
63ba67b69c - Correct one aspect of the driver_object/device_object/IRP framework:
when we create a PDO, the driver_object associated with it is that
  of the parent driver, not the driver we're trying to attach. For
  example, if we attach a PCI device, the PDO we pass to the NdisAddDevice()
  function should contain a pointer to fake_pci_driver, not to the NDIS
  driver itself. For PCI or PCMCIA devices this doesn't matter because
  the child never needs to talk to the parent bus driver, but for USB,
  the child needs to be able to send IRPs to the parent USB bus driver, and
  for that to work the parent USB bus driver has to be hung off the PDO.

  This involves modifying windrv_lookup() so that we can search for
  bus drivers by name, if necessary. Our fake bus drivers attach themselves
  as "PCI Bus," "PCCARD Bus" and "USB Bus," so we can search for them
  using those names.

  The individual attachment stubs now create and attach PDOs to the
  parent bus drivers instead of hanging them off the NDIS driver's
  object, and in if_ndis.c, we now search for the correct driver
  object depending on the bus type, and use that to find the correct PDO.

  With this fix, I can get my sample USB ethernet driver to deliver
  an IRP to my fake parent USB bus driver's dispatch routines.

- Add stub modules for USB support: subr_usbd.c, usbd_var.h and
  if_ndis_usb.c. The subr_usbd.c module is hooked up the build
  but currently doesn't do very much. It provides the stub USB
  parent driver object and a dispatch routine for
  IRM_MJ_INTERNAL_DEVICE_CONTROL. The only exported function at
  the moment is USBD_GetUSBDIVersion(). The if_ndis_usb.c stub
  compiles, but is not hooked up to the build yet. I'm putting
  these here so I can keep them under source code control as I
  flesh them out.
2005-02-24 21:49:14 +00:00