Deleted Added
sdiff udiff text old ( 125599 ) new ( 125860 )
full compact
1/*
2 * Copyright (c) 2003
3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/compat/ndis/subr_ndis.c 125599 2004-02-08 20:39:35Z wpaul $");
35
36/*
37 * This file implements a translation layer between the BSD networking
38 * infrasturcture and Windows(R) NDIS network driver modules. A Windows
39 * NDIS driver calls into several functions in the NDIS.SYS Windows
40 * kernel module and exports a table of functions designed to be called
41 * by the NDIS subsystem. Using the PE loader, we can patch our own
42 * versions of the NDIS routines into a given Windows driver module and
43 * convince the driver that it is in fact running on Windows.
44 *
45 * We provide a table of all our implemented NDIS routines which is patched
46 * into the driver object code. All our exported routines must use the
47 * _stdcall calling convention, since that's what the Windows object code
48 * expects.
49 */
50
51
52#include <sys/param.h>
53#include <sys/types.h>
54#include <sys/errno.h>
55
56#include <sys/callout.h>
57#include <sys/kernel.h>
58#include <sys/systm.h>
59#include <sys/malloc.h>
60#include <sys/lock.h>
61#include <sys/mutex.h>
62#include <sys/socket.h>
63#include <sys/sysctl.h>
64#include <sys/timespec.h>
65#include <sys/smp.h>
66#include <sys/queue.h>
67#include <sys/proc.h>
68#include <sys/filedesc.h>
69#include <sys/namei.h>
70#include <sys/fcntl.h>
71#include <sys/vnode.h>
72#include <sys/kthread.h>
73
74#include <net/if.h>
75#include <net/if_arp.h>
76#include <net/ethernet.h>
77#include <net/if_dl.h>
78#include <net/if_media.h>
79
80#include <machine/atomic.h>
81#include <machine/bus_memio.h>
82#include <machine/bus_pio.h>
83#include <machine/bus.h>
84#include <machine/resource.h>
85
86#include <sys/bus.h>
87#include <sys/rman.h>
88
89#include <machine/stdarg.h>
90
91#include <net80211/ieee80211_var.h>
92#include <net80211/ieee80211_ioctl.h>
93
94#include <dev/pci/pcireg.h>
95#include <dev/pci/pcivar.h>
96
97#include <compat/ndis/pe_var.h>
98#include <compat/ndis/resource_var.h>
99#include <compat/ndis/ntoskrnl_var.h>
100#include <compat/ndis/ndis_var.h>
101#include <compat/ndis/cfg_var.h>
102#include <dev/if_ndis/if_ndisvar.h>
103
104#define FUNC void(*)(void)
105
106static struct mtx *ndis_interlock;
107static char ndis_filepath[MAXPATHLEN];
108struct mtx_pool *ndis_mtxpool;
109extern struct nd_head ndis_devhead;
110
111SYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath,
112 MAXPATHLEN, "Path used by NdisOpenFile() to search for files");
113
114__stdcall static void ndis_initwrap(ndis_handle *,
115 device_object *, void *, void *);
116__stdcall static ndis_status ndis_register_miniport(ndis_handle,
117 ndis_miniport_characteristics *, int);
118__stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t);
119__stdcall static ndis_status ndis_malloc(void **,
120 uint32_t, uint32_t, ndis_physaddr);
121__stdcall static void ndis_free(void *, uint32_t, uint32_t);
122__stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle,
123 uint32_t, uint32_t, ndis_interface_type);
124__stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle);
125__stdcall static void ndis_open_cfgbyidx(ndis_status *, ndis_handle,
126 uint32_t, ndis_unicode_string *, ndis_handle *);
127__stdcall static void ndis_open_cfgbyname(ndis_status *, ndis_handle,
128 ndis_unicode_string *, ndis_handle *);
129static ndis_status ndis_encode_parm(ndis_miniport_block *,
130 struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
131static ndis_status ndis_decode_parm(ndis_miniport_block *,
132 ndis_config_parm *, char *);
133__stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **,
134 ndis_handle, ndis_unicode_string *, ndis_parm_type);
135__stdcall static void ndis_write_cfg(ndis_status *, ndis_handle,
136 ndis_unicode_string *, ndis_config_parm *);
137__stdcall static void ndis_close_cfg(ndis_handle);
138__stdcall static void ndis_create_lock(ndis_spin_lock *);
139__stdcall static void ndis_destroy_lock(ndis_spin_lock *);
140__stdcall static void ndis_lock(ndis_spin_lock *);
141__stdcall static void ndis_unlock(ndis_spin_lock *);
142__stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t,
143 uint32_t, void *, uint32_t);
144__stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t,
145 uint32_t, void *, uint32_t);
146static void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...);
147static void ndis_map_cb(void *, bus_dma_segment_t *, int, int);
148__stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *,
149 uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *);
150__stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t);
151__stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle *,
152 ndis_timer_function, void *);
153__stdcall static void ndis_init_timer(ndis_timer *,
154 ndis_timer_function, void *);
155static void ndis_timercall(void *);
156__stdcall static void ndis_set_timer(ndis_miniport_timer *, uint32_t);
157static void ndis_tick(void *);
158__stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t);
159__stdcall static void ndis_cancel_timer(ndis_miniport_timer *, uint8_t *);
160__stdcall static void ndis_query_resources(ndis_status *, ndis_handle,
161 ndis_resource_list *, uint32_t *);
162__stdcall static ndis_status ndis_register_ioport(void **,
163 ndis_handle, uint32_t, uint32_t);
164__stdcall static void ndis_deregister_ioport(ndis_handle,
165 uint32_t, uint32_t, void *);
166__stdcall static void ndis_read_netaddr(ndis_status *, void **,
167 uint32_t *, ndis_handle);
168__stdcall static ndis_status ndis_mapreg_cnt(uint32_t, uint32_t *);
169__stdcall static ndis_status ndis_alloc_mapreg(ndis_handle,
170 uint32_t, uint8_t, uint32_t, uint32_t);
171__stdcall static void ndis_free_mapreg(ndis_handle);
172static void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int);
173__stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t,
174 uint8_t, void **, ndis_physaddr *);
175static void ndis_asyncmem_complete(void *);
176__stdcall static ndis_status ndis_alloc_sharedmem_async(ndis_handle,
177 uint32_t, uint8_t, void *);
178__stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t,
179 uint8_t, void *, ndis_physaddr);
180__stdcall static ndis_status ndis_map_iospace(void **, ndis_handle,
181 ndis_physaddr, uint32_t);
182__stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t);
183__stdcall static uint32_t ndis_cachefill(void);
184__stdcall static uint32_t ndis_dma_align(ndis_handle);
185__stdcall static ndis_status ndis_init_sc_dma(ndis_handle,
186 uint8_t, uint32_t);
187__stdcall static void ndis_alloc_packetpool(ndis_status *,
188 ndis_handle *, uint32_t, uint32_t);
189__stdcall static void ndis_ex_alloc_packetpool(ndis_status *,
190 ndis_handle *, uint32_t, uint32_t, uint32_t);
191__stdcall static uint32_t ndis_packetpool_use(ndis_handle);
192__stdcall static void ndis_free_packetpool(ndis_handle);
193__stdcall static void ndis_alloc_packet(ndis_status *,
194 ndis_packet **, ndis_handle);
195__stdcall static void ndis_release_packet(ndis_packet *);
196__stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **);
197__stdcall static void ndis_unchain_tailbuf(ndis_packet *, ndis_buffer **);
198__stdcall static void ndis_alloc_bufpool(ndis_status *,
199 ndis_handle *, uint32_t);
200__stdcall static void ndis_free_bufpool(ndis_handle);
201__stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **,
202 ndis_handle, void *, uint32_t);
203__stdcall static void ndis_release_buf(ndis_buffer *);
204__stdcall static uint32_t ndis_buflen(ndis_buffer *);
205__stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *);
206__stdcall static void ndis_query_buf_safe(ndis_buffer *, void **,
207 uint32_t *, uint32_t);
208__stdcall static void *ndis_buf_vaddr(ndis_buffer *);
209__stdcall static void *ndis_buf_vaddr_safe(ndis_buffer *, uint32_t);
210__stdcall static void ndis_adjust_buflen(ndis_buffer *, int);
211__stdcall static uint32_t ndis_interlock_inc(uint32_t *);
212__stdcall static uint32_t ndis_interlock_dec(uint32_t *);
213__stdcall static void ndis_init_event(ndis_event *);
214__stdcall static void ndis_set_event(ndis_event *);
215__stdcall static void ndis_reset_event(ndis_event *);
216__stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t);
217__stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *,
218 ndis_unicode_string *);
219__stdcall static ndis_status ndis_ansi2unicode(ndis_unicode_string *,
220 ndis_ansi_string *);
221__stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle,
222 uint32_t, ndis_resource_list **);
223__stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *,
224 ndis_handle, uint32_t, uint32_t, uint8_t,
225 uint8_t, ndis_interrupt_mode);
226__stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *);
227__stdcall static void ndis_register_shutdown(ndis_handle, void *,
228 ndis_shutdown_handler);
229__stdcall static void ndis_deregister_shutdown(ndis_handle);
230__stdcall static uint32_t ndis_numpages(ndis_buffer *);
231__stdcall static void ndis_buf_physpages(ndis_buffer *, uint32_t *);
232__stdcall static void ndis_query_bufoffset(ndis_buffer *,
233 uint32_t *, uint32_t *);
234__stdcall static void ndis_sleep(uint32_t);
235__stdcall static uint32_t ndis_read_pccard_amem(ndis_handle,
236 uint32_t, void *, uint32_t);
237__stdcall static uint32_t ndis_write_pccard_amem(ndis_handle,
238 uint32_t, void *, uint32_t);
239__stdcall static list_entry *ndis_insert_head(list_entry *,
240 list_entry *, ndis_spin_lock *);
241__stdcall static list_entry *ndis_remove_head(list_entry *,
242 ndis_spin_lock *);
243__stdcall static list_entry *ndis_insert_tail(list_entry *,
244 list_entry *, ndis_spin_lock *);
245__stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *,
246 void *, void *);
247__stdcall static void ndis_time(uint64_t *);
248__stdcall static void ndis_uptime(uint32_t *);
249__stdcall static void ndis_init_string(ndis_unicode_string *, char *);
250__stdcall static void ndis_init_ansi_string(ndis_ansi_string *, char *);
251__stdcall static void ndis_init_unicode_string(ndis_unicode_string *,
252 uint16_t *);
253__stdcall static void ndis_free_string(ndis_unicode_string *);
254__stdcall static ndis_status ndis_remove_miniport(ndis_handle *);
255__stdcall static void ndis_termwrap(ndis_handle, void *);
256__stdcall static void ndis_get_devprop(ndis_handle, device_object **,
257 device_object **, device_object **, cm_resource_list *,
258 cm_resource_list *);
259__stdcall static void ndis_firstbuf(ndis_packet *, ndis_buffer **,
260 void **, uint32_t *, uint32_t *);
261__stdcall static void ndis_firstbuf_safe(ndis_packet *, ndis_buffer **,
262 void **, uint32_t *, uint32_t *, uint32_t);
263__stdcall static void ndis_open_file(ndis_status *, ndis_handle *, uint32_t *,
264 ndis_unicode_string *, ndis_physaddr);
265__stdcall static void ndis_map_file(ndis_status *, void **, ndis_handle);
266__stdcall static void ndis_unmap_file(ndis_handle);
267__stdcall static void ndis_close_file(ndis_handle);
268__stdcall static u_int8_t ndis_cpu_cnt(void);
269__stdcall static void ndis_ind_statusdone(ndis_handle);
270__stdcall static void ndis_ind_status(ndis_handle, ndis_status,
271 void *, uint32_t);
272static void ndis_workfunc(void *);
273__stdcall static ndis_status ndis_sched_workitem(ndis_work_item *);
274__stdcall static void ndis_pkt_to_pkt(ndis_packet *, uint32_t, uint32_t,
275 ndis_packet *, uint32_t, uint32_t *);
276__stdcall static void ndis_pkt_to_pkt_safe(ndis_packet *, uint32_t, uint32_t,
277 ndis_packet *, uint32_t, uint32_t *, uint32_t);
278__stdcall static ndis_status ndis_register_dev(ndis_handle,
279 ndis_unicode_string *, ndis_unicode_string *, driver_dispatch **,
280 void **, ndis_handle *);
281__stdcall static ndis_status ndis_deregister_dev(ndis_handle);
282__stdcall static ndis_status ndis_query_name(ndis_unicode_string *,
283 ndis_handle);
284__stdcall static void ndis_register_unload(ndis_handle, void *);
285__stdcall static void dummy(void);
286
287/*
288 * Some really old drivers do not properly check the return value
289 * from NdisAllocatePacket() and NdisAllocateBuffer() and will
290 * sometimes allocate few more buffers/packets that they originally
291 * requested when they created the pool. To prevent this from being
292 * a problem, we allocate a few extra buffers/packets beyond what
293 * the driver asks for. This #define controls how many.
294 */
295#define NDIS_POOL_EXTRA 16
296
297int
298ndis_libinit()
299{
300 strcpy(ndis_filepath, "/compat/ndis");
301 ndis_mtxpool = mtx_pool_create("ndis mutex pool",
302 1024, MTX_DEF | MTX_RECURSE | MTX_DUPOK);;
303 ndis_interlock = mtx_pool_alloc(ndis_mtxpool);
304 return(0);
305}
306
307int
308ndis_libfini()
309{
310 mtx_pool_destroy(&ndis_mtxpool);
311 return(0);
312}
313
314/*
315 * NDIS deals with strings in unicode format, so we have
316 * do deal with them that way too. For now, we only handle
317 * conversion between unicode and ASCII since that's all
318 * that device drivers care about.
319 */
320
321int
322ndis_ascii_to_unicode(ascii, unicode)
323 char *ascii;
324 uint16_t **unicode;
325{
326 uint16_t *ustr;
327 int i;
328
329 if (*unicode == NULL)
330 *unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK);
331
332 if (*unicode == NULL)
333 return(ENOMEM);
334 ustr = *unicode;
335 for (i = 0; i < strlen(ascii); i++) {
336 *ustr = (uint16_t)ascii[i];
337 ustr++;
338 }
339
340 return(0);
341}
342
343int
344ndis_unicode_to_ascii(unicode, ulen, ascii)
345 uint16_t *unicode;
346 int ulen;
347 char **ascii;
348{
349 uint8_t *astr;
350 int i;
351
352 if (*ascii == NULL)
353 *ascii = malloc((ulen / 2) + 1, M_DEVBUF, M_WAITOK|M_ZERO);
354 if (*ascii == NULL)
355 return(ENOMEM);
356 astr = *ascii;
357 for (i = 0; i < ulen / 2; i++) {
358 *astr = (uint8_t)unicode[i];
359 astr++;
360 }
361
362 return(0);
363}
364
365__stdcall static void
366ndis_initwrap(wrapper, drv_obj, path, unused)
367 ndis_handle *wrapper;
368 device_object *drv_obj;
369 void *path;
370 void *unused;
371{
372 ndis_miniport_block *block;
373
374 block = drv_obj->do_rsvd;
375 *wrapper = block;
376
377 return;
378}
379
380__stdcall static void
381ndis_termwrap(handle, syspec)
382 ndis_handle handle;
383 void *syspec;
384{
385 return;
386}
387
388__stdcall static ndis_status
389ndis_register_miniport(handle, characteristics, len)
390 ndis_handle handle;
391 ndis_miniport_characteristics *characteristics;
392 int len;
393{
394 ndis_miniport_block *block;
395 struct ndis_softc *sc;
396
397 block = (ndis_miniport_block *)handle;
398 sc = (struct ndis_softc *)block->nmb_ifp;
399 bcopy((char *)characteristics, (char *)&sc->ndis_chars,
400 sizeof(ndis_miniport_characteristics));
401 if (sc->ndis_chars.nmc_version_major < 5 ||
402 sc->ndis_chars.nmc_version_minor < 1) {
403 sc->ndis_chars.nmc_shutdown_handler = NULL;
404 sc->ndis_chars.nmc_canceltxpkts_handler = NULL;
405 sc->ndis_chars.nmc_pnpevent_handler = NULL;
406 }
407
408 return(NDIS_STATUS_SUCCESS);
409}
410
411__stdcall static ndis_status
412ndis_malloc_withtag(vaddr, len, tag)
413 void **vaddr;
414 uint32_t len;
415 uint32_t tag;
416{
417 void *mem;
418
419 mem = malloc(len, M_DEVBUF, M_NOWAIT);
420 if (mem == NULL)
421 return(NDIS_STATUS_RESOURCES);
422 *vaddr = mem;
423
424 return(NDIS_STATUS_SUCCESS);
425}
426
427__stdcall static ndis_status
428ndis_malloc(vaddr, len, flags, highaddr)
429 void **vaddr;
430 uint32_t len;
431 uint32_t flags;
432 ndis_physaddr highaddr;
433{
434 void *mem;
435
436 mem = malloc(len, M_DEVBUF, M_NOWAIT);
437 if (mem == NULL)
438 return(NDIS_STATUS_RESOURCES);
439 *vaddr = mem;
440
441 return(NDIS_STATUS_SUCCESS);
442}
443
444__stdcall static void
445ndis_free(vaddr, len, flags)
446 void *vaddr;
447 uint32_t len;
448 uint32_t flags;
449{
450 if (len == 0)
451 return;
452 free(vaddr, M_DEVBUF);
453
454 return;
455}
456
457__stdcall static ndis_status
458ndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs,
459 flags, iftype)
460 ndis_handle adapter_handle;
461 ndis_handle adapter_ctx;
462 uint32_t hangsecs;
463 uint32_t flags;
464 ndis_interface_type iftype;
465{
466 ndis_miniport_block *block;
467
468 /*
469 * Save the adapter context, we need it for calling
470 * the driver's internal functions.
471 */
472 block = (ndis_miniport_block *)adapter_handle;
473 block->nmb_miniportadapterctx = adapter_ctx;
474 block->nmb_checkforhangsecs = hangsecs;
475
476 return(NDIS_STATUS_SUCCESS);
477}
478
479__stdcall static void
480ndis_open_cfg(status, cfg, wrapctx)
481 ndis_status *status;
482 ndis_handle *cfg;
483 ndis_handle wrapctx;
484{
485 *cfg = wrapctx;
486 *status = NDIS_STATUS_SUCCESS;
487 return;
488}
489
490__stdcall static void
491ndis_open_cfgbyname(status, cfg, subkey, subhandle)
492 ndis_status *status;
493 ndis_handle cfg;
494 ndis_unicode_string *subkey;
495 ndis_handle *subhandle;
496{
497 *subhandle = cfg;
498 *status = NDIS_STATUS_SUCCESS;
499 return;
500}
501
502__stdcall static void
503ndis_open_cfgbyidx(status, cfg, idx, subkey, subhandle)
504 ndis_status *status;
505 ndis_handle cfg;
506 uint32_t idx;
507 ndis_unicode_string *subkey;
508 ndis_handle *subhandle;
509{
510 *status = NDIS_STATUS_FAILURE;
511 return;
512}
513
514static ndis_status
515ndis_encode_parm(block, oid, type, parm)
516 ndis_miniport_block *block;
517 struct sysctl_oid *oid;
518 ndis_parm_type type;
519 ndis_config_parm **parm;
520{
521 uint16_t *unicode;
522 ndis_unicode_string *ustr;
523
524 unicode = (uint16_t *)&block->nmb_dummybuf;
525
526 switch(type) {
527 case ndis_parm_string:
528 ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
529 (*parm)->ncp_type = ndis_parm_string;
530 ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
531 ustr->nus_len = strlen((char *)oid->oid_arg1) * 2;
532 ustr->nus_buf = unicode;
533 break;
534 case ndis_parm_int:
535 (*parm)->ncp_type = ndis_parm_int;
536 (*parm)->ncp_parmdata.ncp_intdata =
537 strtol((char *)oid->oid_arg1, NULL, 10);
538 break;
539 case ndis_parm_hexint:
540 (*parm)->ncp_type = ndis_parm_hexint;
541 (*parm)->ncp_parmdata.ncp_intdata =
542 strtoul((char *)oid->oid_arg1, NULL, 16);
543 break;
544 default:
545 return(NDIS_STATUS_FAILURE);
546 break;
547 }
548
549 return(NDIS_STATUS_SUCCESS);
550}
551
552__stdcall static void
553ndis_read_cfg(status, parm, cfg, key, type)
554 ndis_status *status;
555 ndis_config_parm **parm;
556 ndis_handle cfg;
557 ndis_unicode_string *key;
558 ndis_parm_type type;
559{
560 char *keystr = NULL;
561 uint16_t *unicode;
562 ndis_miniport_block *block;
563 struct ndis_softc *sc;
564 struct sysctl_oid *oidp;
565 struct sysctl_ctx_entry *e;
566
567 block = (ndis_miniport_block *)cfg;
568 sc = (struct ndis_softc *)block->nmb_ifp;
569
570 if (key->nus_len == 0 || key->nus_buf == NULL) {
571 *status = NDIS_STATUS_FAILURE;
572 return;
573 }
574
575 ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
576
577 *parm = &block->nmb_replyparm;
578 bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
579 unicode = (uint16_t *)&block->nmb_dummybuf;
580
581 /*
582 * See if registry key is already in a list of known keys
583 * included with the driver.
584 */
585 TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
586 oidp = e->entry;
587 if (strcmp(oidp->oid_name, keystr) == 0) {
588 if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
589 free(keystr, M_DEVBUF);
590 *status = NDIS_STATUS_FAILURE;
591 return;
592 }
593 *status = ndis_encode_parm(block, oidp, type, parm);
594 free(keystr, M_DEVBUF);
595 return;
596 }
597 }
598
599 /*
600 * If the key didn't match, add it to the list of dynamically
601 * created ones. Sometimes, drivers refer to registry keys
602 * that aren't documented in their .INF files. These keys
603 * are supposed to be created by some sort of utility or
604 * control panel snap-in that comes with the driver software.
605 * Sometimes it's useful to be able to manipulate these.
606 * If the driver requests the key in the form of a string,
607 * make its default value an empty string, otherwise default
608 * it to "0".
609 */
610
611 if (type == ndis_parm_int || type == ndis_parm_hexint)
612 ndis_add_sysctl(sc, keystr, "(dynamic integer key)",
613 "UNSET", CTLFLAG_RW);
614 else
615 ndis_add_sysctl(sc, keystr, "(dynamic string key)",
616 "UNSET", CTLFLAG_RW);
617
618 free(keystr, M_DEVBUF);
619 *status = NDIS_STATUS_FAILURE;
620 return;
621}
622
623static ndis_status
624ndis_decode_parm(block, parm, val)
625 ndis_miniport_block *block;
626 ndis_config_parm *parm;
627 char *val;
628{
629 ndis_unicode_string *ustr;
630 char *astr = NULL;
631
632 switch(parm->ncp_type) {
633 case ndis_parm_string:
634 ustr = &parm->ncp_parmdata.ncp_stringdata;
635 ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &astr);
636 bcopy(astr, val, 254);
637 free(astr, M_DEVBUF);
638 break;
639 case ndis_parm_int:
640 sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata);
641 break;
642 case ndis_parm_hexint:
643 sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata);
644 break;
645 default:
646 return(NDIS_STATUS_FAILURE);
647 break;
648 }
649 return(NDIS_STATUS_SUCCESS);
650}
651
652__stdcall static void
653ndis_write_cfg(status, cfg, key, parm)
654 ndis_status *status;
655 ndis_handle cfg;
656 ndis_unicode_string *key;
657 ndis_config_parm *parm;
658{
659 char *keystr = NULL;
660 ndis_miniport_block *block;
661 struct ndis_softc *sc;
662 struct sysctl_oid *oidp;
663 struct sysctl_ctx_entry *e;
664 char val[256];
665
666 block = (ndis_miniport_block *)cfg;
667 sc = (struct ndis_softc *)block->nmb_ifp;
668
669 ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
670
671 /* Decode the parameter into a string. */
672 bzero(val, sizeof(val));
673 *status = ndis_decode_parm(block, parm, val);
674 if (*status != NDIS_STATUS_SUCCESS) {
675 free(keystr, M_DEVBUF);
676 return;
677 }
678
679 /* See if the key already exists. */
680
681 TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
682 oidp = e->entry;
683 if (strcmp(oidp->oid_name, keystr) == 0) {
684 /* Found it, set the value. */
685 strcpy((char *)oidp->oid_arg1, val);
686 free(keystr, M_DEVBUF);
687 return;
688 }
689 }
690
691 /* Not found, add a new key with the specified value. */
692 ndis_add_sysctl(sc, keystr, "(dynamically set key)",
693 val, CTLFLAG_RW);
694
695 free(keystr, M_DEVBUF);
696 *status = NDIS_STATUS_SUCCESS;
697 return;
698}
699
700__stdcall static void
701ndis_close_cfg(cfg)
702 ndis_handle cfg;
703{
704 return;
705}
706
707__stdcall static void
708ndis_create_lock(lock)
709 ndis_spin_lock *lock;
710{
711 lock->nsl_spinlock = (ndis_kspin_lock)mtx_pool_alloc(ndis_mtxpool);
712 return;
713}
714
715__stdcall static void
716ndis_destroy_lock(lock)
717 ndis_spin_lock *lock;
718{
719 /* We use a mutex pool, so this is a no-op. */
720 return;
721}
722
723__stdcall static void
724ndis_lock(lock)
725 ndis_spin_lock *lock;
726{
727 mtx_pool_lock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
728 return;
729}
730
731__stdcall static void
732ndis_unlock(lock)
733 ndis_spin_lock *lock;
734{
735 mtx_pool_unlock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
736 return;
737}
738
739__stdcall static uint32_t
740ndis_read_pci(adapter, slot, offset, buf, len)
741 ndis_handle adapter;
742 uint32_t slot;
743 uint32_t offset;
744 void *buf;
745 uint32_t len;
746{
747 ndis_miniport_block *block;
748 int i;
749 char *dest;
750
751 block = (ndis_miniport_block *)adapter;
752 dest = buf;
753 if (block == NULL || block->nmb_dev == NULL)
754 return(0);
755
756 for (i = 0; i < len; i++)
757 dest[i] = pci_read_config(block->nmb_dev, i + offset, 1);
758
759 return(len);
760}
761
762__stdcall static uint32_t
763ndis_write_pci(adapter, slot, offset, buf, len)
764 ndis_handle adapter;
765 uint32_t slot;
766 uint32_t offset;
767 void *buf;
768 uint32_t len;
769{
770 ndis_miniport_block *block;
771 int i;
772 char *dest;
773
774 block = (ndis_miniport_block *)adapter;
775 dest = buf;
776
777 if (block == NULL || block->nmb_dev == NULL)
778 return(0);
779
780 for (i = 0; i < len; i++)
781 pci_write_config(block->nmb_dev, i + offset, dest[i], 1);
782
783 return(len);
784}
785
786/*
787 * The errorlog routine uses a variable argument list, so we
788 * have to declare it this way.
789 */
790#define ERRMSGLEN 512
791static void
792ndis_syslog(ndis_handle adapter, ndis_error_code code,
793 uint32_t numerrors, ...)
794{
795 ndis_miniport_block *block;
796 va_list ap;
797 int i, error;
798 char *str = NULL, *ustr = NULL;
799 uint16_t flags;
800 char msgbuf[ERRMSGLEN];
801
802 block = (ndis_miniport_block *)adapter;
803
804 error = pe_get_message(block->nmb_img, code, &str, &i, &flags);
805 if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE) {
806 ustr = msgbuf;
807 ndis_unicode_to_ascii((uint16_t *)str,
808 ((i / 2)) > (ERRMSGLEN - 1) ? ERRMSGLEN : i, &ustr);
809 str = ustr;
810 }
811 device_printf (block->nmb_dev, "NDIS ERROR: %x (%s)\n", code,
812 str == NULL ? "unknown error" : str);
813 device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors);
814
815 va_start(ap, numerrors);
816 for (i = 0; i < numerrors; i++)
817 device_printf (block->nmb_dev, "argptr: %p\n",
818 va_arg(ap, void *));
819 va_end(ap);
820
821 return;
822}
823
824static void
825ndis_map_cb(arg, segs, nseg, error)
826 void *arg;
827 bus_dma_segment_t *segs;
828 int nseg;
829 int error;
830{
831 struct ndis_map_arg *ctx;
832 int i;
833
834 if (error)
835 return;
836
837 ctx = arg;
838
839 for (i = 0; i < nseg; i++) {
840 ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
841 ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
842 }
843
844 ctx->nma_cnt = nseg;
845
846 return;
847}
848
849__stdcall static void
850ndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize)
851 ndis_handle adapter;
852 ndis_buffer *buf;
853 uint32_t mapreg;
854 uint8_t writedev;
855 ndis_paddr_unit *addrarray;
856 uint32_t *arraysize;
857{
858 ndis_miniport_block *block;
859 struct ndis_softc *sc;
860 struct ndis_map_arg nma;
861 bus_dmamap_t map;
862 int error;
863
864 if (adapter == NULL)
865 return;
866
867 block = (ndis_miniport_block *)adapter;
868 sc = (struct ndis_softc *)(block->nmb_ifp);
869
870 if (mapreg > sc->ndis_mmapcnt)
871 return;
872
873 map = sc->ndis_mmaps[mapreg];
874 nma.nma_fraglist = addrarray;
875
876 error = bus_dmamap_load(sc->ndis_mtag, map,
877 MDL_VA(buf), buf->nb_bytecount, ndis_map_cb,
878 (void *)&nma, BUS_DMA_NOWAIT);
879
880 if (error)
881 return;
882
883 bus_dmamap_sync(sc->ndis_mtag, map,
884 writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
885
886 *arraysize = nma.nma_cnt;
887
888 return;
889}
890
891__stdcall static void
892ndis_vtophys_unload(adapter, buf, mapreg)
893 ndis_handle adapter;
894 ndis_buffer *buf;
895 uint32_t mapreg;
896{
897 ndis_miniport_block *block;
898 struct ndis_softc *sc;
899 bus_dmamap_t map;
900
901 if (adapter == NULL)
902 return;
903
904 block = (ndis_miniport_block *)adapter;
905 sc = (struct ndis_softc *)(block->nmb_ifp);
906
907 if (mapreg > sc->ndis_mmapcnt)
908 return;
909
910 map = sc->ndis_mmaps[mapreg];
911
912 bus_dmamap_sync(sc->ndis_mtag, map,
913 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
914
915 bus_dmamap_unload(sc->ndis_mtag, map);
916
917 return;
918}
919
920/*
921 * This is an older pre-miniport timer init routine which doesn't
922 * accept a miniport context handle. The function context (ctx)
923 * is supposed to be a pointer to the adapter handle, which should
924 * have been handed to us via NdisSetAttributesEx(). We use this
925 * function context to track down the corresponding ndis_miniport_block
926 * structure. It's vital that we track down the miniport block structure,
927 * so if we can't do it, we panic. Note that we also play some games
928 * here by treating ndis_timer and ndis_miniport_timer as the same
929 * thing.
930 */
931
932__stdcall static void
933ndis_init_timer(timer, func, ctx)
934 ndis_timer *timer;
935 ndis_timer_function func;
936 void *ctx;
937{
938 struct ndis_timer_entry *ne = NULL;
939 ndis_miniport_block *block = NULL;
940
941 TAILQ_FOREACH(block, &ndis_devhead, link) {
942 if (block->nmb_miniportadapterctx == ctx)
943 break;
944 }
945
946 if (block->nmb_miniportadapterctx != ctx)
947 panic("NDIS driver timer context didn't "
948 "match any adapter contexts");
949
950 ne = malloc(sizeof(struct ndis_timer_entry), M_DEVBUF, M_NOWAIT);
951 callout_init(&ne->nte_ch, CALLOUT_MPSAFE);
952 TAILQ_INSERT_TAIL(&block->nmb_timerlist, ne, link);
953 ne->nte_timer = (ndis_miniport_timer *)timer;
954
955 INIT_LIST_HEAD((&timer->nt_timer.nk_header.dh_waitlisthead));
956 timer->nt_timer.nk_header.dh_sigstate = FALSE;
957 timer->nt_timer.nk_header.dh_type = EVENT_TYPE_NOTIFY;
958 timer->nt_timer.nk_header.dh_size = OTYPE_TIMER;
959 timer->nt_dpc.nk_sysarg1 = &ne->nte_ch;
960 timer->nt_dpc.nk_deferedfunc = (ndis_kdpc_func)func;
961 timer->nt_dpc.nk_deferredctx = ctx;
962
963 return;
964}
965
966__stdcall static void
967ndis_create_timer(timer, handle, func, ctx)
968 ndis_miniport_timer *timer;
969 ndis_handle *handle;
970 ndis_timer_function func;
971 void *ctx;
972{
973 struct ndis_timer_entry *ne = NULL;
974 ndis_miniport_block *block;
975 block = (ndis_miniport_block *)handle;
976
977 ne = malloc(sizeof(struct ndis_timer_entry), M_DEVBUF, M_NOWAIT);
978 callout_init(&ne->nte_ch, CALLOUT_MPSAFE);
979 TAILQ_INSERT_TAIL(&block->nmb_timerlist, ne, link);
980 ne->nte_timer = timer;
981
982 INIT_LIST_HEAD((&timer->nmt_ktimer.nk_header.dh_waitlisthead));
983 timer->nmt_ktimer.nk_header.dh_sigstate = FALSE;
984 timer->nmt_ktimer.nk_header.dh_type = EVENT_TYPE_NOTIFY;
985 timer->nmt_ktimer.nk_header.dh_size = OTYPE_TIMER;
986 timer->nmt_dpc.nk_sysarg1 = &ne->nte_ch;
987 timer->nmt_dpc.nk_deferedfunc = (ndis_kdpc_func)func;
988 timer->nmt_dpc.nk_deferredctx = ctx;
989
990 return;
991}
992
993/*
994 * The driver's timer callout is __stdcall function, so we need this
995 * intermediate step.
996 */
997
998static void
999ndis_timercall(arg)
1000 void *arg;
1001{
1002 ndis_miniport_timer *timer;
1003 __stdcall ndis_timer_function timerfunc;
1004
1005 timer = arg;
1006
1007 timerfunc = (ndis_timer_function)timer->nmt_dpc.nk_deferedfunc;
1008 timerfunc(NULL, timer->nmt_dpc.nk_deferredctx, NULL, NULL);
1009 ntoskrnl_wakeup(&timer->nmt_ktimer.nk_header);
1010
1011 return;
1012}
1013
1014/*
1015 * Windows specifies timeouts in milliseconds. We specify timeouts
1016 * in hz, so some conversion is required.
1017 */
1018__stdcall static void
1019ndis_set_timer(timer, msecs)
1020 ndis_miniport_timer *timer;
1021 uint32_t msecs;
1022{
1023 struct callout *ch;
1024 struct timeval tv;
1025
1026 tv.tv_sec = 0;
1027 tv.tv_usec = msecs * 1000;
1028
1029 ch = timer->nmt_dpc.nk_sysarg1;
1030 timer->nmt_dpc.nk_sysarg2 = ndis_timercall;
1031 timer->nmt_ktimer.nk_header.dh_sigstate = FALSE;
1032 callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
1033
1034 return;
1035}
1036
1037static void
1038ndis_tick(arg)
1039 void *arg;
1040{
1041 ndis_miniport_timer *timer;
1042 struct callout *ch;
1043 __stdcall ndis_timer_function timerfunc;
1044 struct timeval tv;
1045
1046 timer = arg;
1047
1048 timerfunc = (ndis_timer_function)timer->nmt_dpc.nk_deferedfunc;
1049 timerfunc(NULL, timer->nmt_dpc.nk_deferredctx, NULL, NULL);
1050 ntoskrnl_wakeup(&timer->nmt_ktimer.nk_header);
1051
1052 /* Automatically reload timer. */
1053
1054 tv.tv_sec = 0;
1055 tv.tv_usec = timer->nmt_ktimer.nk_period * 1000;
1056 ch = timer->nmt_dpc.nk_sysarg1;
1057 timer->nmt_ktimer.nk_header.dh_sigstate = FALSE;
1058 timer->nmt_dpc.nk_sysarg2 = ndis_tick;
1059 callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
1060
1061 return;
1062}
1063
1064__stdcall static void
1065ndis_set_periodic_timer(timer, msecs)
1066 ndis_miniport_timer *timer;
1067 uint32_t msecs;
1068{
1069 struct callout *ch;
1070 struct timeval tv;
1071
1072 tv.tv_sec = 0;
1073 tv.tv_usec = msecs * 1000;
1074
1075 timer->nmt_ktimer.nk_period = msecs;
1076 ch = timer->nmt_dpc.nk_sysarg1;
1077 timer->nmt_dpc.nk_sysarg2 = ndis_tick;
1078 timer->nmt_ktimer.nk_header.dh_sigstate = FALSE;
1079 callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
1080
1081 return;
1082}
1083
1084__stdcall static void
1085ndis_cancel_timer(timer, cancelled)
1086 ndis_miniport_timer *timer;
1087 uint8_t *cancelled;
1088{
1089 struct callout *ch;
1090
1091 if (timer == NULL)
1092 return;
1093 ch = timer->nmt_dpc.nk_sysarg1;
1094 if (ch == NULL)
1095 return;
1096 callout_stop(ch);
1097 *cancelled = timer->nmt_ktimer.nk_header.dh_sigstate;
1098
1099 return;
1100}
1101
1102__stdcall static void
1103ndis_query_resources(status, adapter, list, buflen)
1104 ndis_status *status;
1105 ndis_handle adapter;
1106 ndis_resource_list *list;
1107 uint32_t *buflen;
1108{
1109 ndis_miniport_block *block;
1110 struct ndis_softc *sc;
1111 int rsclen;
1112
1113 block = (ndis_miniport_block *)adapter;
1114 sc = (struct ndis_softc *)block->nmb_ifp;
1115
1116 rsclen = sizeof(ndis_resource_list) +
1117 (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
1118 if (*buflen < rsclen) {
1119 *buflen = rsclen;
1120 *status = NDIS_STATUS_INVALID_LENGTH;
1121 return;
1122 }
1123
1124 bcopy((char *)block->nmb_rlist, (char *)list, *buflen);
1125 *status = NDIS_STATUS_SUCCESS;
1126 return;
1127}
1128
1129__stdcall static ndis_status
1130ndis_register_ioport(offset, adapter, port, numports)
1131 void **offset;
1132 ndis_handle adapter;
1133 uint32_t port;
1134 uint32_t numports;
1135{
1136 struct ndis_miniport_block *block;
1137 struct ndis_softc *sc;
1138
1139 if (adapter == NULL)
1140 return(NDIS_STATUS_FAILURE);
1141
1142 block = (ndis_miniport_block *)adapter;
1143 sc = (struct ndis_softc *)(block->nmb_ifp);
1144
1145 if (sc->ndis_res_io == NULL)
1146 return(NDIS_STATUS_FAILURE);
1147
1148 /* Don't let the device map more ports than we have. */
1149 if (rman_get_size(sc->ndis_res_io) < numports)
1150 return(NDIS_STATUS_INVALID_LENGTH);
1151
1152 *offset = (void *)rman_get_start(sc->ndis_res_io);
1153
1154 return(NDIS_STATUS_SUCCESS);
1155}
1156
1157__stdcall static void
1158ndis_deregister_ioport(adapter, port, numports, offset)
1159 ndis_handle adapter;
1160 uint32_t port;
1161 uint32_t numports;
1162 void *offset;
1163{
1164 return;
1165}
1166
1167__stdcall static void
1168ndis_read_netaddr(status, addr, addrlen, adapter)
1169 ndis_status *status;
1170 void **addr;
1171 uint32_t *addrlen;
1172 ndis_handle adapter;
1173{
1174 struct ndis_softc *sc;
1175 ndis_miniport_block *block;
1176 uint8_t empty[] = { 0, 0, 0, 0, 0, 0 };
1177
1178 block = (ndis_miniport_block *)adapter;
1179 sc = (struct ndis_softc *)block->nmb_ifp;
1180
1181 if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
1182 *status = NDIS_STATUS_FAILURE;
1183 else {
1184 *addr = sc->arpcom.ac_enaddr;
1185 *addrlen = ETHER_ADDR_LEN;
1186 *status = NDIS_STATUS_SUCCESS;
1187 }
1188
1189 return;
1190}
1191
1192__stdcall static ndis_status
1193ndis_mapreg_cnt(bustype, cnt)
1194 uint32_t bustype;
1195 uint32_t *cnt;
1196{
1197 *cnt = 8192;
1198 return(NDIS_STATUS_SUCCESS);
1199}
1200
1201__stdcall static ndis_status
1202ndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap)
1203 ndis_handle adapter;
1204 uint32_t dmachannel;
1205 uint8_t dmasize;
1206 uint32_t physmapneeded;
1207 uint32_t maxmap;
1208{
1209 struct ndis_softc *sc;
1210 ndis_miniport_block *block;
1211 int error, i, nseg = NDIS_MAXSEG;
1212
1213 block = (ndis_miniport_block *)adapter;
1214 sc = (struct ndis_softc *)block->nmb_ifp;
1215
1216 sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
1217 M_DEVBUF, M_NOWAIT|M_ZERO);
1218
1219 if (sc->ndis_mmaps == NULL)
1220 return(NDIS_STATUS_RESOURCES);
1221
1222 error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1223 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1224 NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
1225 NULL, NULL, &sc->ndis_mtag);
1226
1227 if (error) {
1228 free(sc->ndis_mmaps, M_DEVBUF);
1229 return(NDIS_STATUS_RESOURCES);
1230 }
1231
1232 for (i = 0; i < physmapneeded; i++)
1233 bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
1234
1235 sc->ndis_mmapcnt = physmapneeded;
1236
1237 return(NDIS_STATUS_SUCCESS);
1238}
1239
1240__stdcall static void
1241ndis_free_mapreg(adapter)
1242 ndis_handle adapter;
1243{
1244 struct ndis_softc *sc;
1245 ndis_miniport_block *block;
1246 int i;
1247
1248 block = (ndis_miniport_block *)adapter;
1249 sc = (struct ndis_softc *)block->nmb_ifp;
1250
1251 for (i = 0; i < sc->ndis_mmapcnt; i++)
1252 bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
1253
1254 free(sc->ndis_mmaps, M_DEVBUF);
1255
1256 bus_dma_tag_destroy(sc->ndis_mtag);
1257
1258 return;
1259}
1260
1261static void
1262ndis_mapshared_cb(arg, segs, nseg, error)
1263 void *arg;
1264 bus_dma_segment_t *segs;
1265 int nseg;
1266 int error;
1267{
1268 ndis_physaddr *p;
1269
1270 if (error || nseg > 1)
1271 return;
1272
1273 p = arg;
1274
1275 p->np_quad = segs[0].ds_addr;
1276
1277 return;
1278}
1279
1280/*
1281 * This maps to bus_dmamem_alloc().
1282 */
1283__stdcall static void
1284ndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr)
1285 ndis_handle adapter;
1286 uint32_t len;
1287 uint8_t cached;
1288 void **vaddr;
1289 ndis_physaddr *paddr;
1290{
1291 ndis_miniport_block *block;
1292 struct ndis_softc *sc;
1293 struct ndis_shmem *sh;
1294 int error;
1295
1296 if (adapter == NULL)
1297 return;
1298
1299 block = (ndis_miniport_block *)adapter;
1300 sc = (struct ndis_softc *)(block->nmb_ifp);
1301
1302 sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO);
1303 if (sh == NULL)
1304 return;
1305
1306 error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
1307 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1308 NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL,
1309 &sh->ndis_stag);
1310
1311 if (error) {
1312 free(sh, M_DEVBUF);
1313 return;
1314 }
1315
1316 error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
1317 BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
1318
1319 if (error) {
1320 bus_dma_tag_destroy(sh->ndis_stag);
1321 free(sh, M_DEVBUF);
1322 return;
1323 }
1324
1325 error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
1326 len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
1327
1328 if (error) {
1329 bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
1330 bus_dma_tag_destroy(sh->ndis_stag);
1331 free(sh, M_DEVBUF);
1332 return;
1333 }
1334
1335 sh->ndis_saddr = *vaddr;
1336 sh->ndis_next = sc->ndis_shlist;
1337 sc->ndis_shlist = sh;
1338
1339 return;
1340}
1341
1342struct ndis_allocwork {
1343 ndis_handle na_adapter;
1344 uint32_t na_len;
1345 uint8_t na_cached;
1346 void *na_ctx;
1347};
1348
1349static void
1350ndis_asyncmem_complete(arg)
1351 void *arg;
1352{
1353 ndis_miniport_block *block;
1354 struct ndis_softc *sc;
1355 struct ndis_allocwork *w;
1356 void *vaddr;
1357 ndis_physaddr paddr;
1358 __stdcall ndis_allocdone_handler donefunc;
1359
1360 w = arg;
1361 block = (ndis_miniport_block *)w->na_adapter;
1362 sc = (struct ndis_softc *)(block->nmb_ifp);
1363
1364 vaddr = NULL;
1365 paddr.np_quad = 0;
1366
1367 donefunc = sc->ndis_chars.nmc_allocate_complete_func;
1368 ndis_alloc_sharedmem(w->na_adapter, w->na_len,
1369 w->na_cached, &vaddr, &paddr);
1370 donefunc(w->na_adapter, vaddr, &paddr, w->na_len, w->na_ctx);
1371
1372 free(arg, M_DEVBUF);
1373
1374 return;
1375}
1376
1377__stdcall static ndis_status
1378ndis_alloc_sharedmem_async(adapter, len, cached, ctx)
1379 ndis_handle adapter;
1380 uint32_t len;
1381 uint8_t cached;
1382 void *ctx;
1383{
1384 struct ndis_allocwork *w;
1385
1386 if (adapter == NULL)
1387 return(NDIS_STATUS_FAILURE);
1388
1389 w = malloc(sizeof(struct ndis_allocwork), M_TEMP, M_NOWAIT);
1390
1391 if (w == NULL)
1392 return(NDIS_STATUS_FAILURE);
1393
1394 w->na_adapter = adapter;
1395 w->na_cached = cached;
1396 w->na_len = len;
1397 w->na_ctx = ctx;
1398
1399 /*
1400 * Pawn this work off on the SWI thread instead of the
1401 * taskqueue thread, because sometimes drivers will queue
1402 * up work items on the taskqueue thread that will block,
1403 * which would prevent the memory allocation from completing
1404 * when we need it.
1405 */
1406 ndis_sched(ndis_asyncmem_complete, w, NDIS_SWI);
1407
1408 return(NDIS_STATUS_PENDING);
1409}
1410
1411__stdcall static void
1412ndis_free_sharedmem(adapter, len, cached, vaddr, paddr)
1413 ndis_handle adapter;
1414 uint32_t len;
1415 uint8_t cached;
1416 void *vaddr;
1417 ndis_physaddr paddr;
1418{
1419 ndis_miniport_block *block;
1420 struct ndis_softc *sc;
1421 struct ndis_shmem *sh, *prev;
1422
1423 if (vaddr == NULL || adapter == NULL)
1424 return;
1425
1426 block = (ndis_miniport_block *)adapter;
1427 sc = (struct ndis_softc *)(block->nmb_ifp);
1428 sh = prev = sc->ndis_shlist;
1429
1430 while (sh) {
1431 if (sh->ndis_saddr == vaddr)
1432 break;
1433 prev = sh;
1434 sh = sh->ndis_next;
1435 }
1436
1437 bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
1438 bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap);
1439 bus_dma_tag_destroy(sh->ndis_stag);
1440
1441 if (sh == sc->ndis_shlist)
1442 sc->ndis_shlist = sh->ndis_next;
1443 else
1444 prev->ndis_next = sh->ndis_next;
1445
1446 free(sh, M_DEVBUF);
1447
1448 return;
1449}
1450
1451__stdcall static ndis_status
1452ndis_map_iospace(vaddr, adapter, paddr, len)
1453 void **vaddr;
1454 ndis_handle adapter;
1455 ndis_physaddr paddr;
1456 uint32_t len;
1457{
1458 ndis_miniport_block *block;
1459 struct ndis_softc *sc;
1460
1461 if (adapter == NULL)
1462 return(NDIS_STATUS_FAILURE);
1463
1464 block = (ndis_miniport_block *)adapter;
1465 sc = (struct ndis_softc *)(block->nmb_ifp);
1466
1467 if (sc->ndis_res_mem != NULL &&
1468 paddr.np_quad == rman_get_start(sc->ndis_res_mem))
1469 *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem);
1470 else if (sc->ndis_res_altmem != NULL &&
1471 paddr.np_quad == rman_get_start(sc->ndis_res_altmem))
1472 *vaddr = (void *)rman_get_virtual(sc->ndis_res_altmem);
1473 else
1474 return(NDIS_STATUS_FAILURE);
1475
1476 return(NDIS_STATUS_SUCCESS);
1477}
1478
1479__stdcall static void
1480ndis_unmap_iospace(adapter, vaddr, len)
1481 ndis_handle adapter;
1482 void *vaddr;
1483 uint32_t len;
1484{
1485 return;
1486}
1487
1488__stdcall static uint32_t
1489ndis_cachefill(void)
1490{
1491 return(128);
1492}
1493
1494__stdcall static uint32_t
1495ndis_dma_align(handle)
1496 ndis_handle handle;
1497{
1498 return(128);
1499}
1500
1501/*
1502 * NDIS has two methods for dealing with NICs that support DMA.
1503 * One is to just pass packets to the driver and let it call
1504 * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
1505 * all by itself, and the other is to let the NDIS library handle the
1506 * buffer mapping internally, and hand the driver an already populated
1507 * scatter/gather fragment list. If the driver calls
1508 * NdisMInitializeScatterGatherDma(), it wants to use the latter
1509 * method.
1510 */
1511
1512__stdcall static ndis_status
1513ndis_init_sc_dma(adapter, is64, maxphysmap)
1514 ndis_handle adapter;
1515 uint8_t is64;
1516 uint32_t maxphysmap;
1517{
1518 struct ndis_softc *sc;
1519 ndis_miniport_block *block;
1520 int error;
1521
1522 if (adapter == NULL)
1523 return(NDIS_STATUS_FAILURE);
1524 block = (ndis_miniport_block *)adapter;
1525 sc = (struct ndis_softc *)block->nmb_ifp;
1526
1527 /* Don't do this twice. */
1528 if (sc->ndis_sc == 1)
1529 return(NDIS_STATUS_SUCCESS);
1530
1531 error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1532 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
1533 MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
1534 NULL, NULL, &sc->ndis_ttag);
1535
1536 sc->ndis_sc = 1;
1537
1538 return(NDIS_STATUS_SUCCESS);
1539}
1540
1541__stdcall static void
1542ndis_alloc_packetpool(status, pool, descnum, protrsvdlen)
1543 ndis_status *status;
1544 ndis_handle *pool;
1545 uint32_t descnum;
1546 uint32_t protrsvdlen;
1547{
1548 ndis_packet *cur;
1549 int i;
1550
1551 *pool = malloc(sizeof(ndis_packet) *
1552 ((descnum + NDIS_POOL_EXTRA) + 1),
1553 M_DEVBUF, M_NOWAIT|M_ZERO);
1554
1555 if (pool == NULL) {
1556 *status = NDIS_STATUS_RESOURCES;
1557 return;
1558 }
1559
1560 cur = (ndis_packet *)*pool;
1561 cur->np_private.npp_flags = 0x1; /* mark the head of the list */
1562 for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1563 cur->np_private.npp_head = (ndis_handle)(cur + 1);
1564 cur++;
1565 }
1566
1567 *status = NDIS_STATUS_SUCCESS;
1568 return;
1569}
1570
1571__stdcall static void
1572ndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen)
1573 ndis_status *status;
1574 ndis_handle *pool;
1575 uint32_t descnum;
1576 uint32_t oflowdescnum;
1577 uint32_t protrsvdlen;
1578{
1579 return(ndis_alloc_packetpool(status, pool,
1580 descnum + oflowdescnum, protrsvdlen));
1581}
1582
1583__stdcall static uint32_t
1584ndis_packetpool_use(pool)
1585 ndis_handle pool;
1586{
1587 ndis_packet *head;
1588
1589 head = (ndis_packet *)pool;
1590
1591 return(head->np_private.npp_count);
1592}
1593
1594__stdcall static void
1595ndis_free_packetpool(pool)
1596 ndis_handle pool;
1597{
1598 free(pool, M_DEVBUF);
1599 return;
1600}
1601
1602__stdcall static void
1603ndis_alloc_packet(status, packet, pool)
1604 ndis_status *status;
1605 ndis_packet **packet;
1606 ndis_handle pool;
1607{
1608 ndis_packet *head, *pkt;
1609
1610 head = (ndis_packet *)pool;
1611
1612 if (head->np_private.npp_flags != 0x1) {
1613 *status = NDIS_STATUS_FAILURE;
1614 return;
1615 }
1616
1617 pkt = (ndis_packet *)head->np_private.npp_head;
1618
1619 if (pkt == NULL) {
1620 *status = NDIS_STATUS_RESOURCES;
1621 return;
1622 }
1623
1624 head->np_private.npp_head = pkt->np_private.npp_head;
1625
1626 pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL;
1627 /* Save pointer to the pool. */
1628 pkt->np_private.npp_pool = head;
1629
1630 /* Set the oob offset pointer. Lots of things expect this. */
1631 pkt->np_private.npp_packetooboffset =
1632 offsetof(ndis_packet, np_oob);
1633
1634 /*
1635 * We must initialize the packet flags correctly in order
1636 * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and
1637 * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() to work correctly.
1638 */
1639 pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS;
1640
1641 *packet = pkt;
1642
1643 head->np_private.npp_count++;
1644 *status = NDIS_STATUS_SUCCESS;
1645 return;
1646}
1647
1648__stdcall static void
1649ndis_release_packet(packet)
1650 ndis_packet *packet;
1651{
1652 ndis_packet *head;
1653
1654 if (packet == NULL || packet->np_private.npp_pool == NULL)
1655 return;
1656
1657 head = packet->np_private.npp_pool;
1658 if (head->np_private.npp_flags != 0x1)
1659 return;
1660
1661 packet->np_private.npp_head = head->np_private.npp_head;
1662 head->np_private.npp_head = (ndis_buffer *)packet;
1663 head->np_private.npp_count--;
1664
1665 return;
1666}
1667
1668__stdcall static void
1669ndis_unchain_headbuf(packet, buf)
1670 ndis_packet *packet;
1671 ndis_buffer **buf;
1672{
1673 ndis_packet_private *priv;
1674
1675 if (packet == NULL || buf == NULL)
1676 return;
1677
1678 priv = &packet->np_private;
1679
1680 priv->npp_validcounts = FALSE;
1681
1682 if (priv->npp_head == priv->npp_tail) {
1683 *buf = priv->npp_head;
1684 priv->npp_head = priv->npp_tail = NULL;
1685 } else {
1686 *buf = priv->npp_head;
1687 priv->npp_head = (*buf)->nb_next;
1688 }
1689
1690 return;
1691}
1692
1693__stdcall static void
1694ndis_unchain_tailbuf(packet, buf)
1695 ndis_packet *packet;
1696 ndis_buffer **buf;
1697{
1698 ndis_packet_private *priv;
1699 ndis_buffer *tmp;
1700
1701 if (packet == NULL || buf == NULL)
1702 return;
1703
1704 priv = &packet->np_private;
1705
1706 priv->npp_validcounts = FALSE;
1707
1708 if (priv->npp_head == priv->npp_tail) {
1709 *buf = priv->npp_head;
1710 priv->npp_head = priv->npp_tail = NULL;
1711 } else {
1712 *buf = priv->npp_tail;
1713 tmp = priv->npp_head;
1714 while (tmp->nb_next != priv->npp_tail)
1715 tmp = tmp->nb_next;
1716 priv->npp_tail = tmp;
1717 tmp->nb_next = NULL;
1718 }
1719
1720 return;
1721}
1722
1723/*
1724 * The NDIS "buffer" manipulation functions are somewhat misnamed.
1725 * They don't really allocate buffers: they allocate buffer mappings.
1726 * The idea is you reserve a chunk of DMA-able memory using
1727 * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer()
1728 * to obtain the virtual address of the DMA-able region.
1729 * ndis_alloc_bufpool() is analagous to bus_dma_tag_create().
1730 */
1731
1732__stdcall static void
1733ndis_alloc_bufpool(status, pool, descnum)
1734 ndis_status *status;
1735 ndis_handle *pool;
1736 uint32_t descnum;
1737{
1738 ndis_buffer *cur;
1739 int i;
1740
1741 *pool = malloc(sizeof(ndis_buffer) *
1742 ((descnum + NDIS_POOL_EXTRA) + 1),
1743 M_DEVBUF, M_NOWAIT|M_ZERO);
1744
1745 if (pool == NULL) {
1746 *status = NDIS_STATUS_RESOURCES;
1747 return;
1748 }
1749
1750 cur = (ndis_buffer *)*pool;
1751 cur->nb_flags = 0x1; /* mark the head of the list */
1752 for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1753 cur->nb_next = cur + 1;
1754 cur++;
1755 }
1756
1757 *status = NDIS_STATUS_SUCCESS;
1758 return;
1759}
1760
1761__stdcall static void
1762ndis_free_bufpool(pool)
1763 ndis_handle pool;
1764{
1765 free(pool, M_DEVBUF);
1766 return;
1767}
1768
1769/*
1770 * This maps to a bus_dmamap_create() and bus_dmamap_load().
1771 */
1772__stdcall static void
1773ndis_alloc_buf(status, buffer, pool, vaddr, len)
1774 ndis_status *status;
1775 ndis_buffer **buffer;
1776 ndis_handle pool;
1777 void *vaddr;
1778 uint32_t len;
1779{
1780 ndis_buffer *head, *buf;
1781
1782 head = (ndis_buffer *)pool;
1783 if (head->nb_flags != 0x1) {
1784 *status = NDIS_STATUS_FAILURE;
1785 return;
1786 }
1787
1788 buf = head->nb_next;
1789
1790 if (buf == NULL) {
1791 *status = NDIS_STATUS_RESOURCES;
1792 return;
1793 }
1794
1795 head->nb_next = buf->nb_next;
1796
1797 /* Save pointer to the pool. */
1798 buf->nb_process = head;
1799
1800 MDL_INIT(buf, vaddr, len);
1801
1802 *buffer = buf;
1803
1804 *status = NDIS_STATUS_SUCCESS;
1805 return;
1806}
1807
1808__stdcall static void
1809ndis_release_buf(buf)
1810 ndis_buffer *buf;
1811{
1812 ndis_buffer *head;
1813
1814 if (buf == NULL || buf->nb_process == NULL)
1815 return;
1816
1817 head = buf->nb_process;
1818
1819 if (head->nb_flags != 0x1)
1820 return;
1821
1822 buf->nb_next = head->nb_next;
1823 head->nb_next = buf;
1824
1825 return;
1826}
1827
1828/* Aw c'mon. */
1829
1830__stdcall static uint32_t
1831ndis_buflen(buf)
1832 ndis_buffer *buf;
1833{
1834 return(buf->nb_bytecount);
1835}
1836
1837/*
1838 * Get the virtual address and length of a buffer.
1839 * Note: the vaddr argument is optional.
1840 */
1841
1842__stdcall static void
1843ndis_query_buf(buf, vaddr, len)
1844 ndis_buffer *buf;
1845 void **vaddr;
1846 uint32_t *len;
1847{
1848 if (vaddr != NULL)
1849 *vaddr = MDL_VA(buf);
1850 *len = buf->nb_bytecount;
1851
1852 return;
1853}
1854
1855/* Same as above -- we don't care about the priority. */
1856
1857__stdcall static void
1858ndis_query_buf_safe(buf, vaddr, len, prio)
1859 ndis_buffer *buf;
1860 void **vaddr;
1861 uint32_t *len;
1862 uint32_t prio;
1863{
1864 if (vaddr != NULL)
1865 *vaddr = MDL_VA(buf);
1866 *len = buf->nb_bytecount;
1867
1868 return;
1869}
1870
1871/* Damnit Microsoft!! How many ways can you do the same thing?! */
1872
1873__stdcall static void *
1874ndis_buf_vaddr(buf)
1875 ndis_buffer *buf;
1876{
1877 return(MDL_VA(buf));
1878}
1879
1880__stdcall static void *
1881ndis_buf_vaddr_safe(buf, prio)
1882 ndis_buffer *buf;
1883 uint32_t prio;
1884{
1885 return(MDL_VA(buf));
1886}
1887
1888__stdcall static void
1889ndis_adjust_buflen(buf, len)
1890 ndis_buffer *buf;
1891 int len;
1892{
1893 buf->nb_bytecount = len;
1894
1895 return;
1896}
1897
1898__stdcall static uint32_t
1899ndis_interlock_inc(addend)
1900 uint32_t *addend;
1901{
1902 atomic_add_long((u_long *)addend, 1);
1903 return(*addend);
1904}
1905
1906__stdcall static uint32_t
1907ndis_interlock_dec(addend)
1908 uint32_t *addend;
1909{
1910 atomic_subtract_long((u_long *)addend, 1);
1911 return(*addend);
1912}
1913
1914__stdcall static void
1915ndis_init_event(event)
1916 ndis_event *event;
1917{
1918 event->ne_event.nk_header.dh_sigstate = FALSE;
1919 event->ne_event.nk_header.dh_size = OTYPE_EVENT;
1920 event->ne_event.nk_header.dh_type = EVENT_TYPE_NOTIFY;
1921 INIT_LIST_HEAD((&event->ne_event.nk_header.dh_waitlisthead));
1922 return;
1923}
1924
1925__stdcall static void
1926ndis_set_event(event)
1927 ndis_event *event;
1928{
1929 ntoskrnl_wakeup(event);
1930 return;
1931}
1932
1933__stdcall static void
1934ndis_reset_event(event)
1935 ndis_event *event;
1936{
1937 event->ne_event.nk_header.dh_sigstate = FALSE;
1938 return;
1939}
1940
1941/*
1942 * This is a stripped-down version of KeWaitForSingleObject().
1943 * Maybe it ought to just call ntoskrnl_waitforobj() to reduce
1944 * code duplication.
1945 */
1946
1947__stdcall static uint8_t
1948ndis_wait_event(event, msecs)
1949 ndis_event *event;
1950 uint32_t msecs;
1951{
1952 int error;
1953 struct timeval tv;
1954 wait_block w;
1955 struct thread *td = curthread;
1956
1957 mtx_pool_lock(ndis_mtxpool, ntoskrnl_dispatchlock);
1958
1959 if (event->ne_event.nk_header.dh_sigstate == TRUE) {
1960 mtx_pool_unlock(ndis_mtxpool, ntoskrnl_dispatchlock);
1961 return(TRUE);
1962 }
1963
1964 INSERT_LIST_HEAD((&event->ne_event.nk_header.dh_waitlisthead),
1965 (&w.wb_waitlist));
1966
1967 tv.tv_sec = 0;
1968 tv.tv_usec = msecs * 1000;
1969
1970 w.wb_kthread = td;
1971 w.wb_object = &event->ne_event.nk_header;
1972
1973 mtx_pool_unlock(ndis_mtxpool, ntoskrnl_dispatchlock);
1974
1975 if (td->td_proc->p_flag & P_KTHREAD)
1976 error = kthread_suspend(td->td_proc, tvtohz(&tv));
1977 else
1978 error = tsleep(td, PPAUSE|PCATCH, "ndiswe", tvtohz(&tv));
1979
1980 mtx_pool_lock(ndis_mtxpool, ntoskrnl_dispatchlock);
1981
1982 REMOVE_LIST_ENTRY((&w.wb_waitlist));
1983
1984 mtx_pool_unlock(ndis_mtxpool, ntoskrnl_dispatchlock);
1985
1986 return(event->ne_event.nk_header.dh_sigstate);
1987}
1988
1989__stdcall static ndis_status
1990ndis_unicode2ansi(dstr, sstr)
1991 ndis_ansi_string *dstr;
1992 ndis_unicode_string *sstr;
1993{
1994 if (dstr == NULL || sstr == NULL)
1995 return(NDIS_STATUS_FAILURE);
1996 if (ndis_unicode_to_ascii(sstr->nus_buf,
1997 sstr->nus_len, &dstr->nas_buf))
1998 return(NDIS_STATUS_FAILURE);
1999 dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf);
2000 return (NDIS_STATUS_SUCCESS);
2001}
2002
2003__stdcall static ndis_status
2004ndis_ansi2unicode(dstr, sstr)
2005 ndis_unicode_string *dstr;
2006 ndis_ansi_string *sstr;
2007{
2008 char *str;
2009 if (dstr == NULL || sstr == NULL)
2010 return(NDIS_STATUS_FAILURE);
2011 str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT);
2012 if (str == NULL)
2013 return(NDIS_STATUS_FAILURE);
2014 strncpy(str, sstr->nas_buf, sstr->nas_len);
2015 *(str + sstr->nas_len) = '\0';
2016 if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) {
2017 free(str, M_DEVBUF);
2018 return(NDIS_STATUS_FAILURE);
2019 }
2020 dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2;
2021 free(str, M_DEVBUF);
2022 return (NDIS_STATUS_SUCCESS);
2023}
2024
2025__stdcall static ndis_status
2026ndis_assign_pcirsrc(adapter, slot, list)
2027 ndis_handle adapter;
2028 uint32_t slot;
2029 ndis_resource_list **list;
2030{
2031 ndis_miniport_block *block;
2032
2033 if (adapter == NULL || list == NULL)
2034 return (NDIS_STATUS_FAILURE);
2035
2036 block = (ndis_miniport_block *)adapter;
2037 *list = block->nmb_rlist;
2038
2039 return (NDIS_STATUS_SUCCESS);
2040}
2041
2042__stdcall static ndis_status
2043ndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode)
2044 ndis_miniport_interrupt *intr;
2045 ndis_handle adapter;
2046 uint32_t ivec;
2047 uint32_t ilevel;
2048 uint8_t reqisr;
2049 uint8_t shared;
2050 ndis_interrupt_mode imode;
2051{
2052 ndis_miniport_block *block;
2053
2054 block = adapter;
2055
2056 intr->ni_block = adapter;
2057 intr->ni_isrreq = reqisr;
2058 intr->ni_shared = shared;
2059 block->nmb_interrupt = intr;
2060 return(NDIS_STATUS_SUCCESS);
2061}
2062
2063__stdcall static void
2064ndis_deregister_intr(intr)
2065 ndis_miniport_interrupt *intr;
2066{
2067 return;
2068}
2069
2070__stdcall static void
2071ndis_register_shutdown(adapter, shutdownctx, shutdownfunc)
2072 ndis_handle adapter;
2073 void *shutdownctx;
2074 ndis_shutdown_handler shutdownfunc;
2075{
2076 ndis_miniport_block *block;
2077 ndis_miniport_characteristics *chars;
2078 struct ndis_softc *sc;
2079
2080 if (adapter == NULL)
2081 return;
2082
2083 block = (ndis_miniport_block *)adapter;
2084 sc = (struct ndis_softc *)block->nmb_ifp;
2085 chars = &sc->ndis_chars;
2086
2087 chars->nmc_shutdown_handler = shutdownfunc;
2088 chars->nmc_rsvd0 = shutdownctx;
2089
2090 return;
2091}
2092
2093__stdcall static void
2094ndis_deregister_shutdown(adapter)
2095 ndis_handle adapter;
2096{
2097 ndis_miniport_block *block;
2098 ndis_miniport_characteristics *chars;
2099 struct ndis_softc *sc;
2100
2101 if (adapter == NULL)
2102 return;
2103
2104 block = (ndis_miniport_block *)adapter;
2105 sc = (struct ndis_softc *)block->nmb_ifp;
2106 chars = &sc->ndis_chars;
2107
2108 chars->nmc_shutdown_handler = NULL;
2109 chars->nmc_rsvd0 = NULL;
2110
2111 return;
2112}
2113
2114__stdcall static uint32_t
2115ndis_numpages(buf)
2116 ndis_buffer *buf;
2117{
2118 if (buf == NULL)
2119 return(0);
2120 if (buf->nb_bytecount == 0)
2121 return(1);
2122 return(SPAN_PAGES(MDL_VA(buf), buf->nb_bytecount));
2123}
2124
2125__stdcall static void
2126ndis_buf_physpages(buf, pages)
2127 ndis_buffer *buf;
2128 uint32_t *pages;
2129{
2130 if (buf == NULL)
2131 return;
2132
2133 *pages = ndis_numpages(buf);
2134 return;
2135}
2136
2137__stdcall static void
2138ndis_query_bufoffset(buf, off, len)
2139 ndis_buffer *buf;
2140 uint32_t *off;
2141 uint32_t *len;
2142{
2143 if (buf == NULL)
2144 return;
2145
2146 *off = buf->nb_byteoffset;
2147 *len = buf->nb_bytecount;
2148
2149 return;
2150}
2151
2152__stdcall static void
2153ndis_sleep(usecs)
2154 uint32_t usecs;
2155{
2156 struct timeval tv;
2157 uint32_t dummy;
2158
2159 tv.tv_sec = 0;
2160 tv.tv_usec = usecs;
2161
2162 tsleep(&dummy, PPAUSE|PCATCH, "ndis", tvtohz(&tv));
2163
2164 return;
2165}
2166
2167__stdcall static uint32_t
2168ndis_read_pccard_amem(handle, offset, buf, len)
2169 ndis_handle handle;
2170 uint32_t offset;
2171 void *buf;
2172 uint32_t len;
2173{
2174 struct ndis_softc *sc;
2175 ndis_miniport_block *block;
2176 bus_space_handle_t bh;
2177 bus_space_tag_t bt;
2178 char *dest;
2179 int i;
2180
2181 if (handle == NULL)
2182 return(0);
2183
2184 block = (ndis_miniport_block *)handle;
2185 sc = (struct ndis_softc *)block->nmb_ifp;
2186 dest = buf;
2187
2188 bh = rman_get_bushandle(sc->ndis_res_am);
2189 bt = rman_get_bustag(sc->ndis_res_am);
2190
2191 for (i = 0; i < len; i++)
2192 dest[i] = bus_space_read_1(bt, bh, (offset * 2) + (i * 2));
2193
2194 return(i);
2195}
2196
2197__stdcall static uint32_t
2198ndis_write_pccard_amem(handle, offset, buf, len)
2199 ndis_handle handle;
2200 uint32_t offset;
2201 void *buf;
2202 uint32_t len;
2203{
2204 struct ndis_softc *sc;
2205 ndis_miniport_block *block;
2206 bus_space_handle_t bh;
2207 bus_space_tag_t bt;
2208 char *src;
2209 int i;
2210
2211 if (handle == NULL)
2212 return(0);
2213
2214 block = (ndis_miniport_block *)handle;
2215 sc = (struct ndis_softc *)block->nmb_ifp;
2216 src = buf;
2217
2218 bh = rman_get_bushandle(sc->ndis_res_am);
2219 bt = rman_get_bustag(sc->ndis_res_am);
2220
2221 for (i = 0; i < len; i++)
2222 bus_space_write_1(bt, bh, (offset * 2) + (i * 2), src[i]);
2223
2224 return(i);
2225}
2226
2227__stdcall static list_entry *
2228ndis_insert_head(head, entry, lock)
2229 list_entry *head;
2230 list_entry *entry;
2231 ndis_spin_lock *lock;
2232{
2233 list_entry *flink;
2234
2235 mtx_pool_lock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2236 flink = head->nle_flink;
2237 entry->nle_flink = flink;
2238 entry->nle_blink = head;
2239 flink->nle_blink = entry;
2240 head->nle_flink = entry;
2241 mtx_pool_unlock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2242
2243 return(flink);
2244}
2245
2246__stdcall static list_entry *
2247ndis_remove_head(head, lock)
2248 list_entry *head;
2249 ndis_spin_lock *lock;
2250{
2251 list_entry *flink;
2252 list_entry *entry;
2253
2254 mtx_pool_lock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2255 entry = head->nle_flink;
2256 flink = entry->nle_flink;
2257 head->nle_flink = flink;
2258 flink->nle_blink = head;
2259 mtx_pool_unlock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2260
2261 return(entry);
2262}
2263
2264__stdcall static list_entry *
2265ndis_insert_tail(head, entry, lock)
2266 list_entry *head;
2267 list_entry *entry;
2268 ndis_spin_lock *lock;
2269{
2270 list_entry *blink;
2271
2272 mtx_pool_lock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2273 blink = head->nle_blink;
2274 entry->nle_flink = head;
2275 entry->nle_blink = blink;
2276 blink->nle_flink = entry;
2277 head->nle_blink = entry;
2278 mtx_pool_unlock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2279
2280 return(blink);
2281}
2282
2283__stdcall static uint8_t
2284ndis_sync_with_intr(intr, syncfunc, syncctx)
2285 ndis_miniport_interrupt *intr;
2286 void *syncfunc;
2287 void *syncctx;
2288{
2289 struct ndis_softc *sc;
2290 __stdcall uint8_t (*sync)(void *);
2291 uint8_t rval;
2292
2293 if (syncfunc == NULL || syncctx == NULL)
2294 return(0);
2295
2296 sc = (struct ndis_softc *)intr->ni_block->nmb_ifp;
2297 sync = syncfunc;
2298 mtx_pool_lock(ndis_mtxpool, sc->ndis_intrmtx);
2299 rval = sync(syncctx);
2300 mtx_pool_unlock(ndis_mtxpool, sc->ndis_intrmtx);
2301
2302 return(rval);
2303}
2304
2305/*
2306 * Return the number of 100 nanosecond intervals since
2307 * January 1, 1601. (?!?!)
2308 */
2309__stdcall static void
2310ndis_time(tval)
2311 uint64_t *tval;
2312{
2313 struct timespec ts;
2314
2315 nanotime(&ts);
2316 *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 +
2317 11644473600;
2318
2319 return;
2320}
2321
2322/*
2323 * Return the number of milliseconds since the system booted.
2324 */
2325__stdcall static void
2326ndis_uptime(tval)
2327 uint32_t *tval;
2328{
2329 struct timespec ts;
2330
2331 nanouptime(&ts);
2332 *tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000;
2333
2334 return;
2335}
2336
2337__stdcall static void
2338ndis_init_string(dst, src)
2339 ndis_unicode_string *dst;
2340 char *src;
2341{
2342 ndis_unicode_string *u;
2343
2344 u = dst;
2345 u->nus_buf = NULL;
2346 if (ndis_ascii_to_unicode(src, &u->nus_buf))
2347 return;
2348 u->nus_len = u->nus_maxlen = strlen(src) * 2;
2349 return;
2350}
2351
2352__stdcall static void
2353ndis_free_string(str)
2354 ndis_unicode_string *str;
2355{
2356 if (str == NULL)
2357 return;
2358 if (str->nus_buf != NULL)
2359 free(str->nus_buf, M_DEVBUF);
2360 free(str, M_DEVBUF);
2361 return;
2362}
2363
2364__stdcall static ndis_status
2365ndis_remove_miniport(adapter)
2366 ndis_handle *adapter;
2367{
2368 return(NDIS_STATUS_SUCCESS);
2369}
2370
2371__stdcall static void
2372ndis_init_ansi_string(dst, src)
2373 ndis_ansi_string *dst;
2374 char *src;
2375{
2376 ndis_ansi_string *a;
2377
2378 a = dst;
2379 if (a == NULL)
2380 return;
2381 if (src == NULL) {
2382 a->nas_len = a->nas_maxlen = 0;
2383 a->nas_buf = NULL;
2384 } else {
2385 a->nas_buf = src;
2386 a->nas_len = a->nas_maxlen = strlen(src);
2387 }
2388
2389 return;
2390}
2391
2392__stdcall static void
2393ndis_init_unicode_string(dst, src)
2394 ndis_unicode_string *dst;
2395 uint16_t *src;
2396{
2397 ndis_unicode_string *u;
2398 int i;
2399
2400 u = dst;
2401 if (u == NULL)
2402 return;
2403 if (src == NULL) {
2404 u->nus_len = u->nus_maxlen = 0;
2405 u->nus_buf = NULL;
2406 } else {
2407 i = 0;
2408 while(src[i] != 0)
2409 i++;
2410 u->nus_buf = src;
2411 u->nus_len = u->nus_maxlen = i * 2;
2412 }
2413
2414 return;
2415}
2416
2417__stdcall static void ndis_get_devprop(adapter, phydevobj,
2418 funcdevobj, nextdevobj, resources, transresources)
2419 ndis_handle adapter;
2420 device_object **phydevobj;
2421 device_object **funcdevobj;
2422 device_object **nextdevobj;
2423 cm_resource_list *resources;
2424 cm_resource_list *transresources;
2425{
2426 ndis_miniport_block *block;
2427
2428 block = (ndis_miniport_block *)adapter;
2429
2430 if (phydevobj != NULL)
2431 *phydevobj = &block->nmb_devobj;
2432 if (funcdevobj != NULL)
2433 *funcdevobj = &block->nmb_devobj;
2434
2435 return;
2436}
2437
2438__stdcall static void
2439ndis_firstbuf(packet, buf, firstva, firstlen, totlen)
2440 ndis_packet *packet;
2441 ndis_buffer **buf;
2442 void **firstva;
2443 uint32_t *firstlen;
2444 uint32_t *totlen;
2445{
2446 ndis_buffer *tmp;
2447
2448 tmp = packet->np_private.npp_head;
2449 *buf = tmp;
2450 if (tmp == NULL) {
2451 *firstva = NULL;
2452 *firstlen = *totlen = 0;
2453 } else {
2454 *firstva = MDL_VA(tmp);
2455 *firstlen = *totlen = tmp->nb_bytecount;
2456 for (tmp = tmp->nb_next; tmp != NULL; tmp = tmp->nb_next)
2457 *totlen += tmp->nb_bytecount;
2458 }
2459
2460 return;
2461}
2462
2463__stdcall static void
2464ndis_firstbuf_safe(packet, buf, firstva, firstlen, totlen, prio)
2465 ndis_packet *packet;
2466 ndis_buffer **buf;
2467 void **firstva;
2468 uint32_t *firstlen;
2469 uint32_t *totlen;
2470 uint32_t prio;
2471{
2472 ndis_firstbuf(packet, buf, firstva, firstlen, totlen);
2473}
2474
2475/* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
2476__stdcall static void
2477ndis_open_file(status, filehandle, filelength, filename, highestaddr)
2478 ndis_status *status;
2479 ndis_handle *filehandle;
2480 uint32_t *filelength;
2481 ndis_unicode_string *filename;
2482 ndis_physaddr highestaddr;
2483{
2484 char *afilename = NULL;
2485 struct thread *td = curthread;
2486 struct nameidata nd;
2487 int flags, error;
2488 struct vattr vat;
2489 struct vattr *vap = &vat;
2490 ndis_fh *fh;
2491 char path[MAXPATHLEN];
2492
2493 ndis_unicode_to_ascii(filename->nus_buf,
2494 filename->nus_len, &afilename);
2495
2496 sprintf(path, "%s/%s", ndis_filepath, afilename);
2497 free(afilename, M_DEVBUF);
2498
2499 fh = malloc(sizeof(ndis_fh), M_TEMP, M_NOWAIT);
2500 if (fh == NULL) {
2501 *status = NDIS_STATUS_RESOURCES;
2502 return;
2503 }
2504
2505 mtx_lock(&Giant);
2506
2507 /* Some threads don't have a current working directory. */
2508
2509 if (td->td_proc->p_fd->fd_rdir == NULL)
2510 td->td_proc->p_fd->fd_rdir = rootvnode;
2511 if (td->td_proc->p_fd->fd_cdir == NULL)
2512 td->td_proc->p_fd->fd_cdir = rootvnode;
2513
2514 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td);
2515
2516 flags = FREAD;
2517 error = vn_open(&nd, &flags, 0, -1);
2518 if (error) {
2519 mtx_unlock(&Giant);
2520 *status = NDIS_STATUS_FILE_NOT_FOUND;
2521 free(fh, M_TEMP);
2522 return;
2523 }
2524
2525 NDFREE(&nd, NDF_ONLY_PNBUF);
2526
2527 /* Get the file size. */
2528 VOP_GETATTR(nd.ni_vp, vap, NOCRED, td);
2529 VOP_UNLOCK(nd.ni_vp, 0, td);
2530 mtx_unlock(&Giant);
2531
2532 fh->nf_vp = nd.ni_vp;
2533 fh->nf_map = NULL;
2534 *filehandle = fh;
2535 *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF;
2536 *status = NDIS_STATUS_SUCCESS;
2537 return;
2538}
2539
2540__stdcall static void
2541ndis_map_file(status, mappedbuffer, filehandle)
2542 ndis_status *status;
2543 void **mappedbuffer;
2544 ndis_handle filehandle;
2545{
2546 ndis_fh *fh;
2547 struct thread *td = curthread;
2548 int error, resid;
2549
2550 if (filehandle == NULL) {
2551 *status = NDIS_STATUS_FAILURE;
2552 return;
2553 }
2554
2555 fh = (ndis_fh *)filehandle;
2556
2557 if (fh->nf_vp == NULL) {
2558 *status = NDIS_STATUS_FAILURE;
2559 return;
2560 }
2561
2562 if (fh->nf_map != NULL) {
2563 *status = NDIS_STATUS_ALREADY_MAPPED;
2564 return;
2565 }
2566
2567 fh->nf_map = malloc(fh->nf_maplen, M_DEVBUF, M_NOWAIT);
2568
2569 if (fh->nf_map == NULL) {
2570 *status = NDIS_STATUS_RESOURCES;
2571 return;
2572 }
2573
2574 mtx_lock(&Giant);
2575 error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0,
2576 UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td);
2577 mtx_unlock(&Giant);
2578
2579 if (error)
2580 *status = NDIS_STATUS_FAILURE;
2581 else {
2582 *status = NDIS_STATUS_SUCCESS;
2583 *mappedbuffer = fh->nf_map;
2584 }
2585
2586 return;
2587}
2588
2589__stdcall static void
2590ndis_unmap_file(filehandle)
2591 ndis_handle filehandle;
2592{
2593 ndis_fh *fh;
2594 fh = (ndis_fh *)filehandle;
2595
2596 if (fh->nf_map == NULL)
2597 return;
2598 free(fh->nf_map, M_DEVBUF);
2599 fh->nf_map = NULL;
2600
2601 return;
2602}
2603
2604__stdcall static void
2605ndis_close_file(filehandle)
2606 ndis_handle filehandle;
2607{
2608 struct thread *td = curthread;
2609 ndis_fh *fh;
2610
2611 if (filehandle == NULL)
2612 return;
2613
2614 fh = (ndis_fh *)filehandle;
2615 if (fh->nf_map != NULL) {
2616 free(fh->nf_map, M_DEVBUF);
2617 fh->nf_map = NULL;
2618 }
2619
2620 if (fh->nf_vp == NULL)
2621 return;
2622
2623 mtx_lock(&Giant);
2624 vn_close(fh->nf_vp, FREAD, td->td_ucred, td);
2625 mtx_unlock(&Giant);
2626
2627 fh->nf_vp = NULL;
2628 free(fh, M_DEVBUF);
2629
2630 return;
2631}
2632
2633__stdcall static uint8_t
2634ndis_cpu_cnt()
2635{
2636 return(mp_ncpus);
2637}
2638
2639typedef void (*ndis_statusdone_handler)(ndis_handle);
2640typedef void (*ndis_status_handler)(ndis_handle, ndis_status,
2641 void *, uint32_t);
2642
2643__stdcall static void
2644ndis_ind_statusdone(adapter)
2645 ndis_handle adapter;
2646{
2647 ndis_miniport_block *block;
2648 __stdcall ndis_statusdone_handler statusdonefunc;
2649
2650 block = (ndis_miniport_block *)adapter;
2651 statusdonefunc = block->nmb_statusdone_func;
2652
2653 statusdonefunc(adapter);
2654 return;
2655}
2656
2657__stdcall static void
2658ndis_ind_status(adapter, status, sbuf, slen)
2659 ndis_handle adapter;
2660 ndis_status status;
2661 void *sbuf;
2662 uint32_t slen;
2663{
2664 ndis_miniport_block *block;
2665 __stdcall ndis_status_handler statusfunc;
2666
2667 block = (ndis_miniport_block *)adapter;
2668 statusfunc = block->nmb_status_func;
2669
2670 statusfunc(adapter, status, sbuf, slen);
2671 return;
2672}
2673
2674static void
2675ndis_workfunc(ctx)
2676 void *ctx;
2677{
2678 ndis_work_item *work;
2679 __stdcall ndis_proc workfunc;
2680
2681 work = ctx;
2682 workfunc = work->nwi_func;
2683 workfunc(work, work->nwi_ctx);
2684 return;
2685}
2686
2687__stdcall static ndis_status
2688ndis_sched_workitem(work)
2689 ndis_work_item *work;
2690{
2691 ndis_sched(ndis_workfunc, work, NDIS_TASKQUEUE);
2692 return(NDIS_STATUS_SUCCESS);
2693}
2694
2695__stdcall static void
2696ndis_pkt_to_pkt(dpkt, doff, reqlen, spkt, soff, cpylen)
2697 ndis_packet *dpkt;
2698 uint32_t doff;
2699 uint32_t reqlen;
2700 ndis_packet *spkt;
2701 uint32_t soff;
2702 uint32_t *cpylen;
2703{
2704 ndis_buffer *src, *dst;
2705 char *sptr, *dptr;
2706 int resid, copied, len, scnt, dcnt;
2707
2708 *cpylen = 0;
2709
2710 src = spkt->np_private.npp_head;
2711 dst = dpkt->np_private.npp_head;
2712
2713 sptr = MDL_VA(src);
2714 dptr = MDL_VA(dst);
2715 scnt = src->nb_bytecount;
2716 dcnt = dst->nb_bytecount;
2717
2718 while (soff) {
2719 if (src->nb_bytecount > soff) {
2720 sptr += soff;
2721 scnt = src->nb_bytecount - soff;
2722 break;
2723 }
2724 soff -= src->nb_bytecount;
2725 src = src->nb_next;
2726 if (src == NULL)
2727 return;
2728 sptr = MDL_VA(src);
2729 }
2730
2731 while (doff) {
2732 if (dst->nb_bytecount > doff) {
2733 dptr += doff;
2734 dcnt = dst->nb_bytecount - doff;
2735 break;
2736 }
2737 doff -= dst->nb_bytecount;
2738 dst = dst->nb_next;
2739 if (dst == NULL)
2740 return;
2741 dptr = MDL_VA(dst);
2742 }
2743
2744 resid = reqlen;
2745 copied = 0;
2746
2747 while(1) {
2748 if (resid < scnt)
2749 len = resid;
2750 else
2751 len = scnt;
2752 if (dcnt < len)
2753 len = dcnt;
2754
2755 bcopy(sptr, dptr, len);
2756
2757 copied += len;
2758 resid -= len;
2759 if (resid == 0)
2760 break;
2761
2762 dcnt -= len;
2763 if (dcnt == 0) {
2764 dst = dst->nb_next;
2765 if (dst == NULL)
2766 break;
2767 dptr = MDL_VA(dst);
2768 dcnt = dst->nb_bytecount;
2769 }
2770
2771 scnt -= len;
2772 if (scnt == 0) {
2773 src = src->nb_next;
2774 if (src == NULL)
2775 break;
2776 sptr = MDL_VA(src);
2777 scnt = src->nb_bytecount;
2778 }
2779 }
2780
2781 *cpylen = copied;
2782 return;
2783}
2784
2785__stdcall static void
2786ndis_pkt_to_pkt_safe(dpkt, doff, reqlen, spkt, soff, cpylen, prio)
2787 ndis_packet *dpkt;
2788 uint32_t doff;
2789 uint32_t reqlen;
2790 ndis_packet *spkt;
2791 uint32_t soff;
2792 uint32_t *cpylen;
2793 uint32_t prio;
2794{
2795 ndis_pkt_to_pkt(dpkt, doff, reqlen, spkt, soff, cpylen);
2796 return;
2797}
2798
2799__stdcall static ndis_status
2800ndis_register_dev(handle, devname, symname, majorfuncs, devobj, devhandle)
2801 ndis_handle handle;
2802 ndis_unicode_string *devname;
2803 ndis_unicode_string *symname;
2804 driver_dispatch *majorfuncs[];
2805 void **devobj;
2806 ndis_handle *devhandle;
2807{
2808 ndis_miniport_block *block;
2809
2810 block = (ndis_miniport_block *)handle;
2811 *devobj = &block->nmb_devobj;
2812 *devhandle = handle;
2813
2814 return(NDIS_STATUS_SUCCESS);
2815}
2816
2817__stdcall static ndis_status
2818ndis_deregister_dev(handle)
2819 ndis_handle handle;
2820{
2821 return(NDIS_STATUS_SUCCESS);
2822}
2823
2824__stdcall static ndis_status
2825ndis_query_name(name, handle)
2826 ndis_unicode_string *name;
2827 ndis_handle handle;
2828{
2829 ndis_miniport_block *block;
2830
2831 block = (ndis_miniport_block *)handle;
2832 ndis_ascii_to_unicode(__DECONST(char *,
2833 device_get_nameunit(block->nmb_dev)), &name->nus_buf);
2834 name->nus_len = strlen(device_get_nameunit(block->nmb_dev)) * 2;
2835
2836 return(NDIS_STATUS_SUCCESS);
2837}
2838
2839__stdcall static void
2840ndis_register_unload(handle, func)
2841 ndis_handle handle;
2842 void *func;
2843{
2844 return;
2845}
2846
2847__stdcall static void
2848dummy()
2849{
2850 printf ("NDIS dummy called...\n");
2851 return;
2852}
2853
2854image_patch_table ndis_functbl[] = {
2855 { "NdisCopyFromPacketToPacket", (FUNC)ndis_pkt_to_pkt },
2856 { "NdisCopyFromPacketToPacketSafe", (FUNC)ndis_pkt_to_pkt_safe },
2857 { "NdisScheduleWorkItem", (FUNC)ndis_sched_workitem },
2858 { "NdisMIndicateStatusComplete", (FUNC)ndis_ind_statusdone },
2859 { "NdisMIndicateStatus", (FUNC)ndis_ind_status },
2860 { "NdisSystemProcessorCount", (FUNC)ndis_cpu_cnt },
2861 { "NdisUnchainBufferAtBack", (FUNC)ndis_unchain_tailbuf, },
2862 { "NdisGetFirstBufferFromPacket", (FUNC)ndis_firstbuf },
2863 { "NdisGetFirstBufferFromPacketSafe", (FUNC)ndis_firstbuf_safe },
2864 { "NdisGetBufferPhysicalArraySize", (FUNC)ndis_buf_physpages },
2865 { "NdisMGetDeviceProperty", (FUNC)ndis_get_devprop },
2866 { "NdisInitAnsiString", (FUNC)ndis_init_ansi_string },
2867 { "NdisInitUnicodeString", (FUNC)ndis_init_unicode_string },
2868 { "NdisWriteConfiguration", (FUNC)ndis_write_cfg },
2869 { "NdisAnsiStringToUnicodeString", (FUNC)ndis_ansi2unicode },
2870 { "NdisTerminateWrapper", (FUNC)ndis_termwrap },
2871 { "NdisOpenConfigurationKeyByName", (FUNC)ndis_open_cfgbyname },
2872 { "NdisOpenConfigurationKeyByIndex", (FUNC)ndis_open_cfgbyidx },
2873 { "NdisMRemoveMiniport", (FUNC)ndis_remove_miniport },
2874 { "NdisInitializeString", (FUNC)ndis_init_string },
2875 { "NdisFreeString", (FUNC)ndis_free_string },
2876 { "NdisGetCurrentSystemTime", (FUNC)ndis_time },
2877 { "NdisGetSystemUpTime", (FUNC)ndis_uptime },
2878 { "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr },
2879 { "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async },
2880 { "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head },
2881 { "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail },
2882 { "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head },
2883 { "NdisInitializeWrapper", (FUNC)ndis_initwrap },
2884 { "NdisMRegisterMiniport", (FUNC)ndis_register_miniport },
2885 { "NdisAllocateMemoryWithTag", (FUNC)ndis_malloc_withtag },
2886 { "NdisAllocateMemory", (FUNC)ndis_malloc },
2887 { "NdisMSetAttributesEx", (FUNC)ndis_setattr_ex },
2888 { "NdisCloseConfiguration", (FUNC)ndis_close_cfg },
2889 { "NdisReadConfiguration", (FUNC)ndis_read_cfg },
2890 { "NdisOpenConfiguration", (FUNC)ndis_open_cfg },
2891 { "NdisReleaseSpinLock", (FUNC)ndis_unlock },
2892 { "NdisDprAcquireSpinLock", (FUNC)ndis_lock },
2893 { "NdisDprReleaseSpinLock", (FUNC)ndis_unlock },
2894 { "NdisAcquireSpinLock", (FUNC)ndis_lock },
2895 { "NdisAllocateSpinLock", (FUNC)ndis_create_lock },
2896 { "NdisFreeSpinLock", (FUNC)ndis_destroy_lock },
2897 { "NdisFreeMemory", (FUNC)ndis_free },
2898 { "NdisReadPciSlotInformation", (FUNC)ndis_read_pci },
2899 { "NdisWritePciSlotInformation",(FUNC)ndis_write_pci },
2900 { "NdisImmediateReadPciSlotInformation", (FUNC)ndis_read_pci },
2901 { "NdisImmediateWritePciSlotInformation", (FUNC)ndis_write_pci },
2902 { "NdisWriteErrorLogEntry", (FUNC)ndis_syslog },
2903 { "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load },
2904 { "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload },
2905 { "NdisMInitializeTimer", (FUNC)ndis_create_timer },
2906 { "NdisInitializeTimer", (FUNC)ndis_init_timer },
2907 { "NdisSetTimer", (FUNC)ndis_set_timer },
2908 { "NdisMCancelTimer", (FUNC)ndis_cancel_timer },
2909 { "NdisCancelTimer", (FUNC)ndis_cancel_timer },
2910 { "NdisMSetPeriodicTimer", (FUNC)ndis_set_periodic_timer },
2911 { "NdisMQueryAdapterResources", (FUNC)ndis_query_resources },
2912 { "NdisMRegisterIoPortRange", (FUNC)ndis_register_ioport },
2913 { "NdisMDeregisterIoPortRange", (FUNC)ndis_deregister_ioport },
2914 { "NdisReadNetworkAddress", (FUNC)ndis_read_netaddr },
2915 { "NdisQueryMapRegisterCount", (FUNC)ndis_mapreg_cnt },
2916 { "NdisMAllocateMapRegisters", (FUNC)ndis_alloc_mapreg },
2917 { "NdisMFreeMapRegisters", (FUNC)ndis_free_mapreg },
2918 { "NdisMAllocateSharedMemory", (FUNC)ndis_alloc_sharedmem },
2919 { "NdisMMapIoSpace", (FUNC)ndis_map_iospace },
2920 { "NdisMUnmapIoSpace", (FUNC)ndis_unmap_iospace },
2921 { "NdisGetCacheFillSize", (FUNC)ndis_cachefill },
2922 { "NdisMGetDmaAlignment", (FUNC)ndis_dma_align },
2923 { "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma },
2924 { "NdisAllocatePacketPool", (FUNC)ndis_alloc_packetpool },
2925 { "NdisAllocatePacketPoolEx", (FUNC)ndis_ex_alloc_packetpool },
2926 { "NdisAllocatePacket", (FUNC)ndis_alloc_packet },
2927 { "NdisFreePacket", (FUNC)ndis_release_packet },
2928 { "NdisFreePacketPool", (FUNC)ndis_free_packetpool },
2929 { "NdisDprAllocatePacket", (FUNC)ndis_alloc_packet },
2930 { "NdisDprFreePacket", (FUNC)ndis_release_packet },
2931 { "NdisAllocateBufferPool", (FUNC)ndis_alloc_bufpool },
2932 { "NdisAllocateBuffer", (FUNC)ndis_alloc_buf },
2933 { "NdisQueryBuffer", (FUNC)ndis_query_buf },
2934 { "NdisQueryBufferSafe", (FUNC)ndis_query_buf_safe },
2935 { "NdisBufferVirtualAddress", (FUNC)ndis_buf_vaddr },
2936 { "NdisBufferVirtualAddressSafe", (FUNC)ndis_buf_vaddr_safe },
2937 { "NdisBufferLength", (FUNC)ndis_buflen },
2938 { "NdisFreeBuffer", (FUNC)ndis_release_buf },
2939 { "NdisFreeBufferPool", (FUNC)ndis_free_bufpool },
2940 { "NdisInterlockedIncrement", (FUNC)ndis_interlock_inc },
2941 { "NdisInterlockedDecrement", (FUNC)ndis_interlock_dec },
2942 { "NdisInitializeEvent", (FUNC)ndis_init_event },
2943 { "NdisSetEvent", (FUNC)ndis_set_event },
2944 { "NdisResetEvent", (FUNC)ndis_reset_event },
2945 { "NdisWaitEvent", (FUNC)ndis_wait_event },
2946 { "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi },
2947 { "NdisMPciAssignResources", (FUNC)ndis_assign_pcirsrc },
2948 { "NdisMFreeSharedMemory", (FUNC)ndis_free_sharedmem },
2949 { "NdisMRegisterInterrupt", (FUNC)ndis_register_intr },
2950 { "NdisMDeregisterInterrupt", (FUNC)ndis_deregister_intr },
2951 { "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown },
2952 { "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown },
2953 { "NDIS_BUFFER_TO_SPAN_PAGES", (FUNC)ndis_numpages },
2954 { "NdisQueryBufferOffset", (FUNC)ndis_query_bufoffset },
2955 { "NdisAdjustBufferLength", (FUNC)ndis_adjust_buflen },
2956 { "NdisPacketPoolUsage", (FUNC)ndis_packetpool_use },
2957 { "NdisMSleep", (FUNC)ndis_sleep },
2958 { "NdisUnchainBufferAtFront", (FUNC)ndis_unchain_headbuf },
2959 { "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem },
2960 { "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem },
2961 { "NdisOpenFile", (FUNC)ndis_open_file },
2962 { "NdisMapFile", (FUNC)ndis_map_file },
2963 { "NdisUnmapFile", (FUNC)ndis_unmap_file },
2964 { "NdisCloseFile", (FUNC)ndis_close_file },
2965 { "NdisMRegisterDevice", (FUNC)ndis_register_dev },
2966 { "NdisMDeregisterDevice", (FUNC)ndis_deregister_dev },
2967 { "NdisMQueryAdapterInstanceName", (FUNC)ndis_query_name },
2968 { "NdisMRegisterUnloadHandler", (FUNC)ndis_register_unload },
2969
2970 /*
2971 * This last entry is a catch-all for any function we haven't
2972 * implemented yet. The PE import list patching routine will
2973 * use it for any function that doesn't have an explicit match
2974 * in this table.
2975 */
2976
2977 { NULL, (FUNC)dummy },
2978
2979 /* End of list. */
2980
2981 { NULL, NULL },
2982};