cvs commit: src/sys/compat/ndis kern_ndis.c kern_windrv.c ndis_var.h ntoskrnl_var.h subr_hal.c subr_ndis.c subr_ntoskrnl.c winx32_wrap.S src/sys/dev/if_ndis if_ndis.c if_ndisvar.h

Bill Paul wpaul at FreeBSD.org
Mon Oct 10 09:46:40 PDT 2005


wpaul       2005-10-10 16:46:39 UTC

  FreeBSD src repository

  Modified files:
    sys/compat/ndis      kern_ndis.c kern_windrv.c ndis_var.h 
                         ntoskrnl_var.h subr_hal.c subr_ndis.c 
                         subr_ntoskrnl.c winx32_wrap.S 
    sys/dev/if_ndis      if_ndis.c if_ndisvar.h 
  Log:
  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.
  
  Revision  Changes    Path
  1.86      +72 -70    src/sys/compat/ndis/kern_ndis.c
  1.12      +29 -27    src/sys/compat/ndis/kern_windrv.c
  1.42      +109 -10   src/sys/compat/ndis/ndis_var.h
  1.37      +105 -37   src/sys/compat/ndis/ntoskrnl_var.h
  1.25      +88 -20    src/sys/compat/ndis/subr_hal.c
  1.95      +330 -225  src/sys/compat/ndis/subr_ndis.c
  1.72      +935 -351  src/sys/compat/ndis/subr_ntoskrnl.c
  1.3       +20 -4     src/sys/compat/ndis/winx32_wrap.S
  1.104     +770 -474  src/sys/dev/if_ndis/if_ndis.c
  1.24      +79 -9     src/sys/dev/if_ndis/if_ndisvar.h


More information about the cvs-src mailing list