Commit Graph

167 Commits

Author SHA1 Message Date
thompsa
fc7deb78dc 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
9abe935013 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
0f8825b3f7 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
6b792c2ee0 hookup mcast and promisc callbacks
Submitted by:	"Paul B. Mahol" <onemda@gmail.com>
2008-11-30 20:48:57 +00:00
thompsa
d18d0c02e1 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
37709ec805 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
cokane
798aa25682 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
cokane
185ba1fe2a 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
cokane
a4d47ec275 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
f7fc034d21 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
f663b62128 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
thompsa
a00c8b6db2 - 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
thompsa
8d989f76da 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
thompsa
078d0c4a42 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
thompsa
a96561521e 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
3569e353ca 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
cokane
986a88fe51 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
cokane
ed4c4d169e 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
jhb
bc40648c02 Use pause(9) instead of a tsleep() on a stack variable.
MFC after:	1 week
2008-01-17 20:11:58 +00:00
thompsa
8b2f43475d 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
thompsa
e4ece2b010 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
wkoszek
ec7b100d6f 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
thompsa
6e7c2e0556 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
thompsa
663523e681 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
51d643caa6 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
thompsa
5ee74f3589 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
thompsa
b4a663c82a 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
imp
54ee9439a2 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
imp
d4a700c2dc 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
6a8b18f115 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
mjacob
8141e76829 Initialize irql to something prior to calls that (might) set it.
Whined about: gcc 4.2
2007-05-20 16:59:37 +00:00
pjd
4d6f2c1541 Use strcasecmp() from libkern. 2007-04-06 11:21:01 +00:00
sam
35a6c17cb8 change ic_modecaps to a bit vector and use setbit, et. al. 2007-03-11 22:37:32 +00:00
jkim
ebf5b23a3e Fix shared authentication mode. 2006-12-28 00:05:40 +00:00
rwatson
10d0d9cf47 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
mjacob
161582abd4 Static -> static. 2006-09-07 06:00:03 +00:00
trhodes
8a7125d081 Catch up with USB changes, device_ptr_t was removed, we need device_t here. 2006-09-07 05:34:04 +00:00
wpaul
6861e36921 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
wpaul
2e4c2f73c4 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
wpaul
6daa19f5d4 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
wpaul
c104267c1a 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
wpaul
d00054e968 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
wpaul
24cf3a8a44 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
wpaul
c681179258 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
wpaul
df7513965d 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
wpaul
81737fff08 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
wpaul
cf228658f5 Fix build: remove stale KASSERT() for mutex that no longer exists. 2005-10-11 21:31:23 +00:00
wpaul
e65220d04e Grrr. Add one more missing NDIS_UNLOCK(). 2005-10-10 18:41:36 +00:00
wpaul
81da4ba060 Add missing NDIS_UNLOCK() in one of the failure cases in SIOCGPRIVATE_0. 2005-10-10 18:17:46 +00:00
wpaul
ef07dbe57f 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