subr_ndis.c revision 123504
1123474Swpaul/* 2123474Swpaul * Copyright (c) 2003 3123474Swpaul * Bill Paul <wpaul@windriver.com>. All rights reserved. 4123474Swpaul * 5123474Swpaul * Redistribution and use in source and binary forms, with or without 6123474Swpaul * modification, are permitted provided that the following conditions 7123474Swpaul * are met: 8123474Swpaul * 1. Redistributions of source code must retain the above copyright 9123474Swpaul * notice, this list of conditions and the following disclaimer. 10123474Swpaul * 2. Redistributions in binary form must reproduce the above copyright 11123474Swpaul * notice, this list of conditions and the following disclaimer in the 12123474Swpaul * documentation and/or other materials provided with the distribution. 13123474Swpaul * 3. All advertising materials mentioning features or use of this software 14123474Swpaul * must display the following acknowledgement: 15123474Swpaul * This product includes software developed by Bill Paul. 16123474Swpaul * 4. Neither the name of the author nor the names of any co-contributors 17123474Swpaul * may be used to endorse or promote products derived from this software 18123474Swpaul * without specific prior written permission. 19123474Swpaul * 20123474Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21123474Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22123474Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23123474Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24123474Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25123474Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26123474Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27123474Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28123474Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29123474Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30123474Swpaul * THE POSSIBILITY OF SUCH DAMAGE. 31123474Swpaul */ 32123474Swpaul 33123474Swpaul#include <sys/cdefs.h> 34123474Swpaul__FBSDID("$FreeBSD: head/sys/compat/ndis/subr_ndis.c 123504 2003-12-12 22:35:13Z wpaul $"); 35123474Swpaul 36123474Swpaul/* 37123474Swpaul * This file implements a translation layer between the BSD networking 38123474Swpaul * infrasturcture and Windows(R) NDIS network driver modules. A Windows 39123474Swpaul * NDIS driver calls into several functions in the NDIS.SYS Windows 40123474Swpaul * kernel module and exports a table of functions designed to be called 41123474Swpaul * by the NDIS subsystem. Using the PE loader, we can patch our own 42123474Swpaul * versions of the NDIS routines into a given Windows driver module and 43123474Swpaul * convince the driver that it is in fact running on Windows. 44123474Swpaul * 45123474Swpaul * We provide a table of all our implemented NDIS routines which is patched 46123474Swpaul * into the driver object code. All our exported routines must use the 47123474Swpaul * _stdcall calling convention, since that's what the Windows object code 48123474Swpaul * expects. 49123474Swpaul */ 50123474Swpaul 51123474Swpaul 52123474Swpaul#include <sys/param.h> 53123474Swpaul#include <sys/types.h> 54123474Swpaul#include <sys/errno.h> 55123474Swpaul 56123474Swpaul#include <sys/callout.h> 57123474Swpaul#include <sys/kernel.h> 58123474Swpaul#include <sys/systm.h> 59123474Swpaul#include <sys/malloc.h> 60123474Swpaul#include <sys/lock.h> 61123474Swpaul#include <sys/mutex.h> 62123474Swpaul#include <sys/socket.h> 63123474Swpaul#include <sys/sysctl.h> 64123504Swpaul#include <sys/timespec.h> 65123474Swpaul 66123474Swpaul#include <net/if.h> 67123474Swpaul#include <net/if_arp.h> 68123474Swpaul#include <net/ethernet.h> 69123474Swpaul#include <net/if_dl.h> 70123474Swpaul#include <net/if_media.h> 71123474Swpaul 72123474Swpaul#include <machine/bus_memio.h> 73123474Swpaul#include <machine/bus_pio.h> 74123474Swpaul#include <machine/bus.h> 75123474Swpaul#include <machine/resource.h> 76123474Swpaul 77123474Swpaul#include <sys/bus.h> 78123474Swpaul#include <sys/rman.h> 79123474Swpaul 80123474Swpaul#include <machine/stdarg.h> 81123474Swpaul 82123474Swpaul#include <dev/pci/pcireg.h> 83123474Swpaul#include <dev/pci/pcivar.h> 84123474Swpaul 85123474Swpaul#include <compat/ndis/pe_var.h> 86123474Swpaul#include <compat/ndis/resource_var.h> 87123474Swpaul#include <compat/ndis/ndis_var.h> 88123474Swpaul#include <compat/ndis/cfg_var.h> 89123474Swpaul#include <dev/if_ndis/if_ndisvar.h> 90123474Swpaul 91123474Swpaul#define __stdcall __attribute__((__stdcall__)) 92123474Swpaul#define FUNC void(*)(void) 93123474Swpaul 94123474Swpaulstatic struct mtx ndis_interlock; 95123474Swpaulstatic int ndis_inits = 0; 96123474Swpaul 97123474Swpaul__stdcall static void ndis_initwrap(ndis_handle, 98123474Swpaul ndis_driver_object *, void *, void *); 99123474Swpaul__stdcall static ndis_status ndis_register_miniport(ndis_handle, 100123474Swpaul ndis_miniport_characteristics *, int); 101123474Swpaul__stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t); 102123474Swpaul__stdcall static ndis_status ndis_malloc(void **, 103123474Swpaul uint32_t, uint32_t, ndis_physaddr); 104123474Swpaul__stdcall static void ndis_free(void *, uint32_t, uint32_t); 105123474Swpaul__stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle, 106123474Swpaul uint32_t, uint32_t, ndis_interface_type); 107123474Swpaul__stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle); 108123474Swpaulstatic ndis_status ndis_encode_parm(ndis_miniport_block *, 109123474Swpaul struct sysctl_oid *, ndis_parm_type, ndis_config_parm **); 110123474Swpaul__stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **, 111123474Swpaul ndis_handle, ndis_unicode_string *, ndis_parm_type); 112123474Swpaul__stdcall static void ndis_close_cfg(ndis_handle); 113123474Swpaul__stdcall static void ndis_create_lock(ndis_spin_lock *); 114123474Swpaul__stdcall static void ndis_destroy_lock(ndis_spin_lock *); 115123474Swpaul__stdcall static void ndis_lock(ndis_spin_lock *); 116123474Swpaul__stdcall static void ndis_unlock(ndis_spin_lock *); 117123474Swpaul__stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t, 118123474Swpaul uint32_t, void *, uint32_t); 119123474Swpaul__stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t, 120123474Swpaul uint32_t, void *, uint32_t); 121123474Swpaulstatic void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...); 122123474Swpaulstatic void ndis_map_cb(void *, bus_dma_segment_t *, int, int); 123123474Swpaul__stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *, 124123474Swpaul uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *); 125123474Swpaul__stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t); 126123474Swpaul__stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle *, 127123474Swpaul ndis_timer_function, void *); 128123474Swpaulstatic void ndis_timercall(void *); 129123474Swpaul__stdcall static void ndis_set_timer(ndis_miniport_timer *, uint32_t); 130123474Swpaulstatic void ndis_tick(void *); 131123474Swpaul__stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t); 132123474Swpaul__stdcall static void ndis_cancel_timer(ndis_miniport_timer *, uint8_t *); 133123474Swpaul__stdcall static void ndis_query_resources(ndis_status *, ndis_handle, 134123474Swpaul ndis_resource_list *, uint32_t *); 135123474Swpaul__stdcall static ndis_status ndis_register_ioport(void **, 136123474Swpaul ndis_handle, uint32_t, uint32_t); 137123474Swpaul__stdcall static void ndis_deregister_ioport(ndis_handle, 138123474Swpaul uint32_t, uint32_t, void *); 139123474Swpaul__stdcall static void ndis_read_netaddr(ndis_status *, void **, 140123474Swpaul uint32_t *, ndis_handle); 141123474Swpaul__stdcall static ndis_status ndis_alloc_mapreg(ndis_handle, 142123474Swpaul uint32_t, uint8_t, uint32_t, uint32_t); 143123474Swpaul__stdcall static void ndis_free_mapreg(ndis_handle); 144123474Swpaulstatic void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int); 145123474Swpaul__stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t, 146123474Swpaul uint8_t, void **, ndis_physaddr *); 147123474Swpaul__stdcall static void ndis_alloc_sharedmem_async(ndis_handle, 148123474Swpaul uint32_t, uint8_t, void *); 149123474Swpaul__stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t, 150123474Swpaul uint8_t, void *, ndis_physaddr); 151123474Swpaul__stdcall static ndis_status ndis_map_iospace(void **, ndis_handle, 152123474Swpaul ndis_physaddr, uint32_t); 153123474Swpaul__stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t); 154123474Swpaul__stdcall static uint32_t ndis_cachefill(void); 155123474Swpaul__stdcall static uint32_t ndis_dma_align(ndis_handle); 156123474Swpaul__stdcall static ndis_status ndis_init_sc_dma(ndis_handle, 157123474Swpaul uint8_t, uint32_t); 158123474Swpaul__stdcall static void ndis_alloc_packetpool(ndis_status *, 159123474Swpaul ndis_handle *, uint32_t, uint32_t); 160123474Swpaul__stdcall static void ndis_ex_alloc_packetpool(ndis_status *, 161123474Swpaul ndis_handle *, uint32_t, uint32_t, uint32_t); 162123474Swpaul__stdcall static uint32_t ndis_packetpool_use(ndis_handle); 163123474Swpaul__stdcall static void ndis_free_packetpool(ndis_handle); 164123474Swpaul__stdcall static void ndis_alloc_packet(ndis_status *, 165123474Swpaul ndis_packet **, ndis_handle); 166123474Swpaul__stdcall static void ndis_release_packet(ndis_packet *); 167123474Swpaul__stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **); 168123474Swpaul__stdcall static void ndis_alloc_bufpool(ndis_status *, 169123474Swpaul ndis_handle *, uint32_t); 170123474Swpaul__stdcall static void ndis_free_bufpool(ndis_handle); 171123474Swpaul__stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **, 172123474Swpaul ndis_handle, void *, uint32_t); 173123474Swpaul__stdcall static void ndis_release_buf(ndis_buffer *); 174123474Swpaul__stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *); 175123474Swpaul__stdcall static void ndis_query_buf_safe(ndis_buffer *, void **, 176123474Swpaul uint32_t *, uint32_t); 177123474Swpaul__stdcall static void ndis_adjust_buflen(ndis_buffer *, int); 178123474Swpaul__stdcall static uint32_t ndis_interlock_inc(uint32_t *); 179123474Swpaul__stdcall static uint32_t ndis_interlock_dec(uint32_t *); 180123474Swpaul__stdcall static void ndis_init_event(ndis_event *); 181123474Swpaul__stdcall static void ndis_set_event(ndis_event *); 182123474Swpaul__stdcall static void ndis_reset_event(ndis_event *); 183123474Swpaul__stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t); 184123474Swpaul__stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *, 185123474Swpaul ndis_unicode_string *); 186123474Swpaul__stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle, 187123474Swpaul uint32_t, ndis_resource_list **); 188123474Swpaul__stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *, 189123474Swpaul ndis_handle, uint32_t, uint32_t, uint8_t, 190123474Swpaul uint8_t, ndis_interrupt_mode); 191123474Swpaul__stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *); 192123474Swpaul__stdcall static void ndis_register_shutdown(ndis_handle, void *, 193123474Swpaul ndis_shutdown_handler); 194123474Swpaul__stdcall static void ndis_deregister_shutdown(ndis_handle); 195123474Swpaul__stdcall static uint32_t ndis_numpages(ndis_buffer *); 196123474Swpaul__stdcall static void ndis_query_bufoffset(ndis_buffer *, 197123474Swpaul uint32_t *, uint32_t *); 198123474Swpaul__stdcall static void ndis_sleep(uint32_t); 199123474Swpaul__stdcall static uint32_t ndis_read_pccard_amem(ndis_handle, 200123474Swpaul uint32_t, void *, uint32_t); 201123474Swpaul__stdcall static uint32_t ndis_write_pccard_amem(ndis_handle, 202123474Swpaul uint32_t, void *, uint32_t); 203123474Swpaul__stdcall static ndis_list_entry *ndis_insert_head(ndis_list_entry *, 204123474Swpaul ndis_list_entry *, ndis_spin_lock *); 205123474Swpaul__stdcall static ndis_list_entry *ndis_remove_head(ndis_list_entry *, 206123474Swpaul ndis_spin_lock *); 207123474Swpaul__stdcall static ndis_list_entry *ndis_insert_tail(ndis_list_entry *, 208123474Swpaul ndis_list_entry *, ndis_spin_lock *); 209123474Swpaul__stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *, 210123474Swpaul void *, void *); 211123504Swpaul__stdcall static void ndis_time(uint64_t *); 212123474Swpaul__stdcall static void dummy(void); 213123474Swpaul 214123474Swpaul 215123474Swpaulint 216123474Swpaulndis_libinit() 217123474Swpaul{ 218123474Swpaul if (ndis_inits) { 219123474Swpaul ndis_inits++; 220123474Swpaul return(0); 221123474Swpaul } 222123474Swpaul 223123474Swpaul mtx_init(&ndis_interlock, "ndislock", MTX_NETWORK_LOCK, 224123474Swpaul MTX_DEF | MTX_RECURSE | MTX_DUPOK); 225123474Swpaul 226123474Swpaul ndis_inits++; 227123474Swpaul return(0); 228123474Swpaul} 229123474Swpaul 230123474Swpaulint 231123474Swpaulndis_libfini() 232123474Swpaul{ 233123474Swpaul if (ndis_inits != 1) { 234123474Swpaul ndis_inits--; 235123474Swpaul return(0); 236123474Swpaul } 237123474Swpaul 238123474Swpaul mtx_destroy(&ndis_interlock); 239123474Swpaul ndis_inits--; 240123474Swpaul 241123474Swpaul return(0); 242123474Swpaul} 243123474Swpaul 244123474Swpaul/* 245123474Swpaul * NDIS deals with strings in unicode format, so we have 246123474Swpaul * do deal with them that way too. For now, we only handle 247123474Swpaul * conversion between unicode and ASCII since that's all 248123474Swpaul * that device drivers care about. 249123474Swpaul */ 250123474Swpaul 251123474Swpaulint 252123474Swpaulndis_ascii_to_unicode(ascii, unicode) 253123474Swpaul char *ascii; 254123474Swpaul uint16_t **unicode; 255123474Swpaul{ 256123474Swpaul uint16_t *ustr; 257123474Swpaul int i; 258123474Swpaul 259123474Swpaul if (*unicode == NULL) 260123474Swpaul *unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK); 261123474Swpaul 262123474Swpaul if (*unicode == NULL) 263123474Swpaul return(ENOMEM); 264123474Swpaul ustr = *unicode; 265123474Swpaul for (i = 0; i < strlen(ascii); i++) { 266123474Swpaul *ustr = (uint16_t)ascii[i]; 267123474Swpaul ustr++; 268123474Swpaul } 269123474Swpaul 270123474Swpaul return(0); 271123474Swpaul} 272123474Swpaul 273123474Swpaulint 274123474Swpaulndis_unicode_to_ascii(unicode, ulen, ascii) 275123474Swpaul uint16_t *unicode; 276123474Swpaul int ulen; 277123474Swpaul char **ascii; 278123474Swpaul{ 279123474Swpaul uint8_t *astr; 280123474Swpaul int i; 281123474Swpaul 282123474Swpaul if (*ascii == NULL) 283123474Swpaul *ascii = malloc(ulen, M_DEVBUF, M_WAITOK); 284123474Swpaul 285123474Swpaul if (*ascii == NULL) 286123474Swpaul return(ENOMEM); 287123474Swpaul astr = *ascii; 288123474Swpaul for (i = 0; i < ulen; i++) { 289123474Swpaul *astr = (uint8_t)unicode[i]; 290123474Swpaul astr++; 291123474Swpaul } 292123474Swpaul 293123474Swpaul return(0); 294123474Swpaul} 295123474Swpaul 296123474Swpaul__stdcall static void 297123474Swpaulndis_initwrap(wrapper, drv_obj, path, unused) 298123474Swpaul ndis_handle wrapper; 299123474Swpaul ndis_driver_object *drv_obj; 300123474Swpaul void *path; 301123474Swpaul void *unused; 302123474Swpaul{ 303123474Swpaul ndis_driver_object **drv; 304123474Swpaul 305123474Swpaul drv = wrapper; 306123474Swpaul *drv = drv_obj; 307123474Swpaul 308123474Swpaul return; 309123474Swpaul} 310123474Swpaul 311123474Swpaul__stdcall static ndis_status 312123474Swpaulndis_register_miniport(handle, characteristics, len) 313123474Swpaul ndis_handle handle; 314123474Swpaul ndis_miniport_characteristics *characteristics; 315123474Swpaul int len; 316123474Swpaul{ 317123474Swpaul ndis_driver_object *drv; 318123474Swpaul 319123474Swpaul drv = handle; 320123474Swpaul bcopy((char *)characteristics, (char *)&drv->ndo_chars, 321123474Swpaul sizeof(ndis_miniport_characteristics)); 322123474Swpaul return(NDIS_STATUS_SUCCESS); 323123474Swpaul} 324123474Swpaul 325123474Swpaul__stdcall static ndis_status 326123474Swpaulndis_malloc_withtag(vaddr, len, tag) 327123474Swpaul void **vaddr; 328123474Swpaul uint32_t len; 329123474Swpaul uint32_t tag; 330123474Swpaul{ 331123474Swpaul void *mem; 332123474Swpaul 333123474Swpaul mem = malloc(len, M_DEVBUF, M_NOWAIT); 334123474Swpaul if (mem == NULL) 335123474Swpaul return(NDIS_STATUS_RESOURCES); 336123474Swpaul *vaddr = mem; 337123474Swpaul 338123474Swpaul return(NDIS_STATUS_SUCCESS); 339123474Swpaul} 340123474Swpaul 341123474Swpaul__stdcall static ndis_status 342123474Swpaulndis_malloc(vaddr, len, flags, highaddr) 343123474Swpaul void **vaddr; 344123474Swpaul uint32_t len; 345123474Swpaul uint32_t flags; 346123474Swpaul ndis_physaddr highaddr; 347123474Swpaul{ 348123474Swpaul void *mem; 349123474Swpaul 350123474Swpaul mem = malloc(len, M_DEVBUF, M_NOWAIT); 351123474Swpaul if (mem == NULL) 352123474Swpaul return(NDIS_STATUS_RESOURCES); 353123474Swpaul *vaddr = mem; 354123474Swpaul 355123474Swpaul return(NDIS_STATUS_SUCCESS); 356123474Swpaul} 357123474Swpaul 358123474Swpaul__stdcall static void 359123474Swpaulndis_free(vaddr, len, flags) 360123474Swpaul void *vaddr; 361123474Swpaul uint32_t len; 362123474Swpaul uint32_t flags; 363123474Swpaul{ 364123474Swpaul if (len == 0) 365123474Swpaul return; 366123474Swpaul free(vaddr, M_DEVBUF); 367123474Swpaul return; 368123474Swpaul} 369123474Swpaul 370123474Swpaul__stdcall static ndis_status 371123474Swpaulndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs, 372123474Swpaul flags, iftype) 373123474Swpaul ndis_handle adapter_handle; 374123474Swpaul ndis_handle adapter_ctx; 375123474Swpaul uint32_t hangsecs; 376123474Swpaul uint32_t flags; 377123474Swpaul ndis_interface_type iftype; 378123474Swpaul{ 379123474Swpaul ndis_miniport_block *block; 380123474Swpaul 381123474Swpaul /* 382123474Swpaul * Save the adapter context, we need it for calling 383123474Swpaul * the driver's internal functions. 384123474Swpaul */ 385123474Swpaul block = (ndis_miniport_block *)adapter_handle; 386123474Swpaul block->nmb_miniportadapterctx = adapter_ctx; 387123474Swpaul block->nmb_checkforhangsecs = hangsecs; 388123474Swpaul 389123474Swpaul return(NDIS_STATUS_SUCCESS); 390123474Swpaul} 391123474Swpaul 392123474Swpaul__stdcall static void 393123474Swpaulndis_open_cfg(status, cfg, wrapctx) 394123474Swpaul ndis_status *status; 395123474Swpaul ndis_handle *cfg; 396123474Swpaul ndis_handle wrapctx; 397123474Swpaul{ 398123474Swpaul *cfg = wrapctx; 399123474Swpaul *status = NDIS_STATUS_SUCCESS; 400123474Swpaul return; 401123474Swpaul} 402123474Swpaul 403123474Swpaulstatic ndis_status 404123474Swpaulndis_encode_parm(block, oid, type, parm) 405123474Swpaul ndis_miniport_block *block; 406123474Swpaul struct sysctl_oid *oid; 407123474Swpaul ndis_parm_type type; 408123474Swpaul ndis_config_parm **parm; 409123474Swpaul{ 410123474Swpaul uint16_t *unicode; 411123474Swpaul ndis_unicode_string *ustr; 412123474Swpaul 413123474Swpaul unicode = (uint16_t *)&block->nmb_dummybuf; 414123474Swpaul 415123474Swpaul switch(type) { 416123474Swpaul case ndis_parm_string: 417123474Swpaul ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode); 418123474Swpaul (*parm)->ncp_type = ndis_parm_string; 419123474Swpaul ustr = &(*parm)->ncp_parmdata.ncp_stringdata; 420123474Swpaul ustr->nus_len = strlen((char *)oid->oid_arg1) * 2; 421123474Swpaul ustr->nus_buf = unicode; 422123474Swpaul break; 423123474Swpaul case ndis_parm_int: 424123474Swpaul (*parm)->ncp_type = ndis_parm_int; 425123474Swpaul (*parm)->ncp_parmdata.ncp_intdata = 426123474Swpaul strtol((char *)oid->oid_arg1, NULL, 10); 427123474Swpaul break; 428123474Swpaul case ndis_parm_hexint: 429123474Swpaul (*parm)->ncp_type = ndis_parm_hexint; 430123474Swpaul (*parm)->ncp_parmdata.ncp_intdata = 431123474Swpaul strtoul((char *)oid->oid_arg1, NULL, 16); 432123474Swpaul break; 433123474Swpaul default: 434123474Swpaul return(NDIS_STATUS_FAILURE); 435123474Swpaul break; 436123474Swpaul } 437123474Swpaul 438123474Swpaul return(NDIS_STATUS_SUCCESS); 439123474Swpaul} 440123474Swpaul 441123474Swpaul__stdcall static void 442123474Swpaulndis_read_cfg(status, parm, cfg, key, type) 443123474Swpaul ndis_status *status; 444123474Swpaul ndis_config_parm **parm; 445123474Swpaul ndis_handle cfg; 446123474Swpaul ndis_unicode_string *key; 447123474Swpaul ndis_parm_type type; 448123474Swpaul{ 449123474Swpaul char *keystr = NULL; 450123474Swpaul uint16_t *unicode; 451123474Swpaul ndis_miniport_block *block; 452123474Swpaul struct ndis_softc *sc; 453123474Swpaul struct sysctl_oid *oidp; 454123474Swpaul struct sysctl_ctx_entry *e; 455123474Swpaul 456123474Swpaul block = (ndis_miniport_block *)cfg; 457123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 458123474Swpaul 459123474Swpaul ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr); 460123474Swpaul 461123474Swpaul *parm = &block->nmb_replyparm; 462123474Swpaul bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm)); 463123474Swpaul unicode = (uint16_t *)&block->nmb_dummybuf; 464123474Swpaul 465123474Swpaul /* 466123474Swpaul * See if registry key is already in a list of known keys 467123474Swpaul * included with the driver. 468123474Swpaul */ 469123474Swpaul TAILQ_FOREACH(e, &sc->ndis_ctx, link) { 470123474Swpaul oidp = e->entry; 471123474Swpaul if (strcmp(oidp->oid_name, keystr) == 0) { 472123488Swpaul if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) { 473123488Swpaul free(keystr, M_DEVBUF); 474123488Swpaul *status = NDIS_STATUS_FAILURE; 475123488Swpaul return; 476123488Swpaul } 477123474Swpaul *status = ndis_encode_parm(block, oidp, type, parm); 478123474Swpaul free(keystr, M_DEVBUF); 479123474Swpaul return; 480123474Swpaul } 481123474Swpaul } 482123474Swpaul 483123474Swpaul /* 484123474Swpaul * If the key didn't match, add it to the list of dynamically 485123474Swpaul * created ones. Sometimes, drivers refer to registry keys 486123474Swpaul * that aren't documented in their .INF files. These keys 487123474Swpaul * are supposed to be created by some sort of utility or 488123474Swpaul * control panel snap-in that comes with the driver software. 489123474Swpaul * Sometimes it's useful to be able to manipulate these. 490123474Swpaul * If the driver requests the key in the form of a string, 491123474Swpaul * make its default value an empty string, otherwise default 492123474Swpaul * it to "0". 493123474Swpaul */ 494123474Swpaul 495123474Swpaul if (type == ndis_parm_int || type == ndis_parm_hexint) 496123488Swpaul ndis_add_sysctl(sc, keystr, "(dynamic integer key)", 497123488Swpaul "UNSET", CTLFLAG_RW); 498123474Swpaul else 499123488Swpaul ndis_add_sysctl(sc, keystr, "(dynamic string key)", 500123488Swpaul "UNSET", CTLFLAG_RW); 501123474Swpaul 502123474Swpaul free(keystr, M_DEVBUF); 503123474Swpaul *status = NDIS_STATUS_FAILURE; 504123474Swpaul return; 505123474Swpaul} 506123474Swpaul 507123474Swpaul__stdcall static void 508123474Swpaulndis_close_cfg(cfg) 509123474Swpaul ndis_handle cfg; 510123474Swpaul{ 511123474Swpaul return; 512123474Swpaul} 513123474Swpaul 514123474Swpaul__stdcall static void 515123474Swpaulndis_create_lock(lock) 516123474Swpaul ndis_spin_lock *lock; 517123474Swpaul{ 518123474Swpaul struct mtx *mtx; 519123474Swpaul 520123474Swpaul mtx = malloc(sizeof(struct mtx), M_DEVBUF, M_NOWAIT|M_ZERO); 521123474Swpaul if (mtx == NULL) 522123474Swpaul return; 523123474Swpaul mtx_init(mtx, "ndislock", MTX_NETWORK_LOCK, 524123474Swpaul MTX_DEF | MTX_RECURSE | MTX_DUPOK); 525123474Swpaul lock->nsl_spinlock = (ndis_kspin_lock)mtx; 526123474Swpaul 527123474Swpaul return; 528123474Swpaul} 529123474Swpaul 530123474Swpaul__stdcall static void 531123474Swpaulndis_destroy_lock(lock) 532123474Swpaul ndis_spin_lock *lock; 533123474Swpaul{ 534123474Swpaul struct mtx *ndis_mtx; 535123474Swpaul 536123474Swpaul ndis_mtx = (struct mtx *)lock->nsl_spinlock; 537123474Swpaul mtx_destroy(ndis_mtx); 538123474Swpaul free(ndis_mtx, M_DEVBUF); 539123474Swpaul 540123474Swpaul return; 541123474Swpaul} 542123474Swpaul 543123474Swpaul__stdcall static void 544123474Swpaulndis_lock(lock) 545123474Swpaul ndis_spin_lock *lock; 546123474Swpaul{ 547123474Swpaul if (lock == NULL) 548123474Swpaul return; 549123474Swpaul mtx_lock((struct mtx *)lock->nsl_spinlock); 550123474Swpaul 551123474Swpaul return; 552123474Swpaul} 553123474Swpaul 554123474Swpaul__stdcall static void 555123474Swpaulndis_unlock(lock) 556123474Swpaul ndis_spin_lock *lock; 557123474Swpaul{ 558123474Swpaul if (lock == NULL) 559123474Swpaul return; 560123474Swpaul mtx_unlock((struct mtx *)lock->nsl_spinlock); 561123474Swpaul 562123474Swpaul return; 563123474Swpaul} 564123474Swpaul 565123474Swpaul__stdcall static uint32_t 566123474Swpaulndis_read_pci(adapter, slot, offset, buf, len) 567123474Swpaul ndis_handle adapter; 568123474Swpaul uint32_t slot; 569123474Swpaul uint32_t offset; 570123474Swpaul void *buf; 571123474Swpaul uint32_t len; 572123474Swpaul{ 573123474Swpaul ndis_miniport_block *block; 574123474Swpaul int i; 575123474Swpaul char *dest; 576123474Swpaul 577123474Swpaul block = (ndis_miniport_block *)adapter; 578123474Swpaul dest = buf; 579123474Swpaul if (block == NULL || block->nmb_dev == NULL) 580123474Swpaul return(0); 581123474Swpaul 582123474Swpaul for (i = 0; i < len; i++) 583123474Swpaul dest[i] = pci_read_config(block->nmb_dev, i + offset, 1); 584123474Swpaul 585123474Swpaul return(len); 586123474Swpaul} 587123474Swpaul 588123474Swpaul__stdcall static uint32_t 589123474Swpaulndis_write_pci(adapter, slot, offset, buf, len) 590123474Swpaul ndis_handle adapter; 591123474Swpaul uint32_t slot; 592123474Swpaul uint32_t offset; 593123474Swpaul void *buf; 594123474Swpaul uint32_t len; 595123474Swpaul{ 596123474Swpaul ndis_miniport_block *block; 597123474Swpaul int i; 598123474Swpaul char *dest; 599123474Swpaul 600123474Swpaul block = (ndis_miniport_block *)adapter; 601123474Swpaul dest = buf; 602123474Swpaul 603123474Swpaul if (block == NULL || block->nmb_dev == NULL) 604123474Swpaul return(0); 605123474Swpaul 606123474Swpaul for (i = 0; i < len; i++) 607123474Swpaul pci_write_config(block->nmb_dev, i + offset, dest[i], 1); 608123474Swpaul 609123474Swpaul return(len); 610123474Swpaul} 611123474Swpaul 612123474Swpaul/* 613123474Swpaul * The errorlog routine uses a variable argument list, so we 614123474Swpaul * have to declare it this way. 615123474Swpaul */ 616123474Swpaulstatic void 617123474Swpaulndis_syslog(ndis_handle adapter, ndis_error_code code, 618123474Swpaul uint32_t numerrors, ...) 619123474Swpaul{ 620123474Swpaul ndis_miniport_block *block; 621123474Swpaul va_list ap; 622123474Swpaul int i; 623123474Swpaul 624123474Swpaul block = (ndis_miniport_block *)adapter; 625123474Swpaul 626123474Swpaul printf ("NDIS ERROR: %x\n", code); 627123474Swpaul printf ("NDIS NUMERRORS: %x\n", numerrors); 628123474Swpaul 629123474Swpaul va_start(ap, numerrors); 630123474Swpaul for (i = 0; i < numerrors; i++) 631123474Swpaul printf ("argptr: %p\n", va_arg(ap, void *)); 632123474Swpaul va_end(ap); 633123474Swpaul 634123474Swpaul return; 635123474Swpaul} 636123474Swpaul 637123474Swpaulstatic void 638123474Swpaulndis_map_cb(arg, segs, nseg, error) 639123474Swpaul void *arg; 640123474Swpaul bus_dma_segment_t *segs; 641123474Swpaul int nseg; 642123474Swpaul int error; 643123474Swpaul{ 644123474Swpaul struct ndis_map_arg *ctx; 645123474Swpaul int i; 646123474Swpaul 647123474Swpaul if (error) 648123474Swpaul return; 649123474Swpaul 650123474Swpaul ctx = arg; 651123474Swpaul 652123474Swpaul for (i = 0; i < nseg; i++) { 653123474Swpaul ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr; 654123474Swpaul ctx->nma_fraglist[i].npu_len = segs[i].ds_len; 655123474Swpaul } 656123474Swpaul 657123474Swpaul ctx->nma_cnt = nseg; 658123474Swpaul 659123474Swpaul return; 660123474Swpaul} 661123474Swpaul 662123474Swpaul__stdcall static void 663123474Swpaulndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize) 664123474Swpaul ndis_handle adapter; 665123474Swpaul ndis_buffer *buf; 666123474Swpaul uint32_t mapreg; 667123474Swpaul uint8_t writedev; 668123474Swpaul ndis_paddr_unit *addrarray; 669123474Swpaul uint32_t *arraysize; 670123474Swpaul{ 671123474Swpaul ndis_miniport_block *block; 672123474Swpaul struct ndis_softc *sc; 673123474Swpaul struct ndis_map_arg nma; 674123474Swpaul bus_dmamap_t map; 675123474Swpaul int error; 676123474Swpaul 677123474Swpaul if (adapter == NULL) 678123474Swpaul return; 679123474Swpaul 680123474Swpaul block = (ndis_miniport_block *)adapter; 681123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 682123474Swpaul 683123474Swpaul if (mapreg > sc->ndis_mmapcnt) 684123474Swpaul return; 685123474Swpaul 686123474Swpaul map = sc->ndis_mmaps[mapreg]; 687123474Swpaul nma.nma_fraglist = addrarray; 688123474Swpaul 689123474Swpaul error = bus_dmamap_load(sc->ndis_mtag, map, 690123474Swpaul buf->nb_mappedsystemva, buf->nb_bytecount, ndis_map_cb, 691123474Swpaul (void *)&nma, BUS_DMA_NOWAIT); 692123474Swpaul 693123474Swpaul if (error) 694123474Swpaul return; 695123474Swpaul 696123474Swpaul bus_dmamap_sync(sc->ndis_mtag, map, 697123474Swpaul writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD); 698123474Swpaul 699123474Swpaul *arraysize = nma.nma_cnt; 700123474Swpaul 701123474Swpaul return; 702123474Swpaul} 703123474Swpaul 704123474Swpaul__stdcall static void 705123474Swpaulndis_vtophys_unload(adapter, buf, mapreg) 706123474Swpaul ndis_handle adapter; 707123474Swpaul ndis_buffer *buf; 708123474Swpaul uint32_t mapreg; 709123474Swpaul{ 710123474Swpaul ndis_miniport_block *block; 711123474Swpaul struct ndis_softc *sc; 712123474Swpaul bus_dmamap_t map; 713123474Swpaul 714123474Swpaul if (adapter == NULL) 715123474Swpaul return; 716123474Swpaul 717123474Swpaul block = (ndis_miniport_block *)adapter; 718123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 719123474Swpaul 720123474Swpaul if (mapreg > sc->ndis_mmapcnt) 721123474Swpaul return; 722123474Swpaul 723123474Swpaul map = sc->ndis_mmaps[mapreg]; 724123474Swpaul 725123474Swpaul bus_dmamap_sync(sc->ndis_mtag, map, 726123474Swpaul BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 727123474Swpaul 728123474Swpaul bus_dmamap_unload(sc->ndis_mtag, map); 729123474Swpaul 730123474Swpaul return; 731123474Swpaul} 732123474Swpaul 733123474Swpaul__stdcall static void 734123474Swpaulndis_create_timer(timer, handle, func, ctx) 735123474Swpaul ndis_miniport_timer *timer; 736123474Swpaul ndis_handle *handle; 737123474Swpaul ndis_timer_function func; 738123474Swpaul void *ctx; 739123474Swpaul{ 740123474Swpaul struct callout_handle *ch; 741123474Swpaul 742123474Swpaul ch = (struct callout_handle *)&timer->nmt_dpc; 743123474Swpaul callout_handle_init(ch); 744123474Swpaul timer->nmt_timerfunc = func; 745123474Swpaul timer->nmt_timerctx = ctx; 746123474Swpaul 747123474Swpaul return; 748123474Swpaul} 749123474Swpaul 750123474Swpaul/* 751123474Swpaul * The driver's timer callout is __stdcall function, so we need this 752123474Swpaul * intermediate step. 753123474Swpaul */ 754123474Swpaul 755123474Swpaulstatic void 756123474Swpaulndis_timercall(arg) 757123474Swpaul void *arg; 758123474Swpaul{ 759123474Swpaul ndis_miniport_timer *timer; 760123474Swpaul __stdcall ndis_timer_function timerfunc; 761123474Swpaul 762123474Swpaul timer = arg; 763123474Swpaul 764123474Swpaul timerfunc = timer->nmt_timerfunc; 765123474Swpaul timerfunc(NULL, timer->nmt_timerctx, NULL, NULL); 766123474Swpaul 767123474Swpaul return; 768123474Swpaul} 769123474Swpaul 770123474Swpaul/* 771123474Swpaul * Windows specifies timeouts in milliseconds. We specify timeouts 772123474Swpaul * in hz. Trying to compute a tenth of a second based on hz is tricky. 773123474Swpaul * so we approximate. Note that we abuse the dpc portion of the 774123474Swpaul * miniport timer structure to hold the UNIX callout handle. 775123474Swpaul */ 776123474Swpaul__stdcall static void 777123474Swpaulndis_set_timer(timer, msecs) 778123474Swpaul ndis_miniport_timer *timer; 779123474Swpaul uint32_t msecs; 780123474Swpaul{ 781123474Swpaul struct callout_handle *ch; 782123474Swpaul struct timeval tv; 783123474Swpaul 784123474Swpaul tv.tv_sec = 0; 785123474Swpaul tv.tv_usec = msecs * 1000; 786123474Swpaul 787123474Swpaul ch = (struct callout_handle *)&timer->nmt_dpc; 788123474Swpaul timer->nmt_dpc.nk_sysarg2 = ndis_timercall; 789123474Swpaul *ch = timeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, (void *)timer, 790123474Swpaul tvtohz(&tv)); 791123474Swpaul 792123474Swpaul return; 793123474Swpaul} 794123474Swpaul 795123474Swpaulstatic void 796123474Swpaulndis_tick(arg) 797123474Swpaul void *arg; 798123474Swpaul{ 799123474Swpaul ndis_miniport_timer *timer; 800123474Swpaul struct callout_handle *ch; 801123474Swpaul __stdcall ndis_timer_function timerfunc; 802123474Swpaul struct timeval tv; 803123474Swpaul 804123474Swpaul timer = arg; 805123474Swpaul 806123474Swpaul timerfunc = timer->nmt_timerfunc; 807123474Swpaul timerfunc(NULL, timer->nmt_timerctx, NULL, NULL); 808123474Swpaul 809123474Swpaul /* Automatically reload timer. */ 810123474Swpaul 811123474Swpaul tv.tv_sec = 0; 812123474Swpaul tv.tv_usec = timer->nmt_ktimer.nk_period * 1000; 813123474Swpaul ch = (struct callout_handle *)&timer->nmt_dpc; 814123474Swpaul timer->nmt_dpc.nk_sysarg2 = ndis_tick; 815123474Swpaul *ch = timeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, timer, 816123474Swpaul tvtohz(&tv)); 817123474Swpaul 818123474Swpaul return; 819123474Swpaul} 820123474Swpaul 821123474Swpaul__stdcall static void 822123474Swpaulndis_set_periodic_timer(timer, msecs) 823123474Swpaul ndis_miniport_timer *timer; 824123474Swpaul uint32_t msecs; 825123474Swpaul{ 826123474Swpaul struct callout_handle *ch; 827123474Swpaul struct timeval tv; 828123474Swpaul 829123474Swpaul tv.tv_sec = 0; 830123474Swpaul tv.tv_usec = msecs * 1000; 831123474Swpaul 832123474Swpaul timer->nmt_ktimer.nk_period = msecs; 833123474Swpaul ch = (struct callout_handle *)&timer->nmt_dpc; 834123474Swpaul timer->nmt_dpc.nk_sysarg2 = ndis_tick; 835123474Swpaul *ch = timeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, timer, 836123474Swpaul tvtohz(&tv)); 837123474Swpaul 838123474Swpaul return; 839123474Swpaul} 840123474Swpaul 841123474Swpaul__stdcall static void 842123474Swpaulndis_cancel_timer(timer, cancelled) 843123474Swpaul ndis_miniport_timer *timer; 844123474Swpaul uint8_t *cancelled; 845123474Swpaul{ 846123474Swpaul struct callout_handle *ch; 847123474Swpaul 848123474Swpaul ch = (struct callout_handle *)&timer->nmt_dpc; 849123474Swpaul untimeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, timer, *ch); 850123474Swpaul 851123474Swpaul return; 852123474Swpaul} 853123474Swpaul 854123474Swpaul__stdcall static void 855123474Swpaulndis_query_resources(status, adapter, list, buflen) 856123474Swpaul ndis_status *status; 857123474Swpaul ndis_handle adapter; 858123474Swpaul ndis_resource_list *list; 859123474Swpaul uint32_t *buflen; 860123474Swpaul{ 861123474Swpaul ndis_miniport_block *block; 862123474Swpaul struct ndis_softc *sc; 863123474Swpaul 864123474Swpaul block = (ndis_miniport_block *)adapter; 865123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 866123474Swpaul 867123474Swpaul *buflen = sizeof(ndis_resource_list) + 868123474Swpaul (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)); 869123474Swpaul 870123474Swpaul bcopy((char *)block->nmb_rlist, (char *)list, *buflen); 871123474Swpaul *status = NDIS_STATUS_SUCCESS; 872123474Swpaul return; 873123474Swpaul} 874123474Swpaul 875123474Swpaul__stdcall static ndis_status 876123474Swpaulndis_register_ioport(offset, adapter, port, numports) 877123474Swpaul void **offset; 878123474Swpaul ndis_handle adapter; 879123474Swpaul uint32_t port; 880123474Swpaul uint32_t numports; 881123474Swpaul{ 882123474Swpaul struct ndis_miniport_block *block; 883123474Swpaul struct ndis_softc *sc; 884123474Swpaul 885123474Swpaul if (adapter == NULL) 886123474Swpaul return(NDIS_STATUS_FAILURE); 887123474Swpaul 888123474Swpaul block = (ndis_miniport_block *)adapter; 889123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 890123474Swpaul 891123474Swpaul if (sc->ndis_res_io == NULL) 892123474Swpaul return(NDIS_STATUS_FAILURE); 893123474Swpaul 894123474Swpaul if (rman_get_size(sc->ndis_res_io) != numports) 895123474Swpaul return(NDIS_STATUS_INVALID_LENGTH); 896123474Swpaul 897123474Swpaul *offset = (void *)rman_get_start(sc->ndis_res_io); 898123474Swpaul 899123474Swpaul return(NDIS_STATUS_SUCCESS); 900123474Swpaul} 901123474Swpaul 902123474Swpaul__stdcall static void 903123474Swpaulndis_deregister_ioport(adapter, port, numports, offset) 904123474Swpaul ndis_handle adapter; 905123474Swpaul uint32_t port; 906123474Swpaul uint32_t numports; 907123474Swpaul void *offset; 908123474Swpaul{ 909123474Swpaul return; 910123474Swpaul} 911123474Swpaul 912123474Swpaul__stdcall static void 913123474Swpaulndis_read_netaddr(status, addr, addrlen, adapter) 914123474Swpaul ndis_status *status; 915123474Swpaul void **addr; 916123474Swpaul uint32_t *addrlen; 917123474Swpaul ndis_handle adapter; 918123474Swpaul{ 919123474Swpaul struct ndis_softc *sc; 920123474Swpaul ndis_miniport_block *block; 921123474Swpaul uint8_t empty[] = { 0, 0, 0, 0, 0, 0 }; 922123474Swpaul 923123474Swpaul block = (ndis_miniport_block *)adapter; 924123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 925123474Swpaul 926123474Swpaul if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0) 927123474Swpaul *status = NDIS_STATUS_FAILURE; 928123474Swpaul else { 929123474Swpaul *addr = sc->arpcom.ac_enaddr; 930123474Swpaul *addrlen = ETHER_ADDR_LEN; 931123474Swpaul *status = NDIS_STATUS_SUCCESS; 932123474Swpaul } 933123474Swpaul 934123474Swpaul return; 935123474Swpaul} 936123474Swpaul 937123474Swpaul__stdcall static ndis_status 938123474Swpaulndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap) 939123474Swpaul ndis_handle adapter; 940123474Swpaul uint32_t dmachannel; 941123474Swpaul uint8_t dmasize; 942123474Swpaul uint32_t physmapneeded; 943123474Swpaul uint32_t maxmap; 944123474Swpaul{ 945123474Swpaul struct ndis_softc *sc; 946123474Swpaul ndis_miniport_block *block; 947123474Swpaul int error, i, nseg = NDIS_MAXSEG; 948123474Swpaul 949123474Swpaul block = (ndis_miniport_block *)adapter; 950123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 951123474Swpaul 952123474Swpaul sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded, 953123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 954123474Swpaul 955123474Swpaul if (sc->ndis_mmaps == NULL) 956123474Swpaul return(NDIS_STATUS_RESOURCES); 957123474Swpaul 958123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 959123474Swpaul BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, 960123474Swpaul NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW, 961123474Swpaul NULL, NULL, &sc->ndis_mtag); 962123474Swpaul 963123474Swpaul if (error) { 964123474Swpaul free(sc->ndis_mmaps, M_DEVBUF); 965123474Swpaul return(NDIS_STATUS_RESOURCES); 966123474Swpaul } 967123474Swpaul 968123474Swpaul for (i = 0; i < physmapneeded; i++) 969123474Swpaul bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]); 970123474Swpaul 971123474Swpaul sc->ndis_mmapcnt = physmapneeded; 972123474Swpaul 973123474Swpaul return(NDIS_STATUS_SUCCESS); 974123474Swpaul} 975123474Swpaul 976123474Swpaul__stdcall static void 977123474Swpaulndis_free_mapreg(adapter) 978123474Swpaul ndis_handle adapter; 979123474Swpaul{ 980123474Swpaul struct ndis_softc *sc; 981123474Swpaul ndis_miniport_block *block; 982123474Swpaul int i; 983123474Swpaul 984123474Swpaul block = (ndis_miniport_block *)adapter; 985123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 986123474Swpaul 987123474Swpaul for (i = 0; i < sc->ndis_mmapcnt; i++) 988123474Swpaul bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]); 989123474Swpaul 990123474Swpaul free(sc->ndis_mmaps, M_DEVBUF); 991123474Swpaul 992123474Swpaul bus_dma_tag_destroy(sc->ndis_mtag); 993123474Swpaul 994123474Swpaul return; 995123474Swpaul} 996123474Swpaul 997123474Swpaulstatic void 998123474Swpaulndis_mapshared_cb(arg, segs, nseg, error) 999123474Swpaul void *arg; 1000123474Swpaul bus_dma_segment_t *segs; 1001123474Swpaul int nseg; 1002123474Swpaul int error; 1003123474Swpaul{ 1004123474Swpaul ndis_physaddr *p; 1005123474Swpaul 1006123474Swpaul if (error || nseg > 1) 1007123474Swpaul return; 1008123474Swpaul 1009123474Swpaul p = arg; 1010123474Swpaul 1011123474Swpaul p->np_quad = segs[0].ds_addr; 1012123474Swpaul 1013123474Swpaul return; 1014123474Swpaul} 1015123474Swpaul 1016123474Swpaul/* 1017123474Swpaul * This maps to bus_dmamem_alloc(). 1018123474Swpaul */ 1019123474Swpaul__stdcall static void 1020123474Swpaulndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr) 1021123474Swpaul ndis_handle adapter; 1022123474Swpaul uint32_t len; 1023123474Swpaul uint8_t cached; 1024123474Swpaul void **vaddr; 1025123474Swpaul ndis_physaddr *paddr; 1026123474Swpaul{ 1027123474Swpaul ndis_miniport_block *block; 1028123474Swpaul struct ndis_softc *sc; 1029123474Swpaul struct ndis_shmem *sh; 1030123474Swpaul int error; 1031123474Swpaul 1032123474Swpaul if (adapter == NULL) 1033123474Swpaul return; 1034123474Swpaul 1035123474Swpaul block = (ndis_miniport_block *)adapter; 1036123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 1037123474Swpaul 1038123474Swpaul sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO); 1039123474Swpaul if (sh == NULL) 1040123474Swpaul return; 1041123474Swpaul 1042123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, 64, 1043123474Swpaul 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, 1044123474Swpaul NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL, 1045123474Swpaul &sh->ndis_stag); 1046123474Swpaul 1047123474Swpaul if (error) { 1048123474Swpaul free(sh, M_DEVBUF); 1049123474Swpaul return; 1050123474Swpaul } 1051123474Swpaul 1052123474Swpaul error = bus_dmamem_alloc(sh->ndis_stag, vaddr, 1053123474Swpaul BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap); 1054123474Swpaul 1055123474Swpaul if (error) { 1056123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1057123474Swpaul free(sh, M_DEVBUF); 1058123474Swpaul return; 1059123474Swpaul } 1060123474Swpaul 1061123474Swpaul error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr, 1062123474Swpaul len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT); 1063123474Swpaul 1064123474Swpaul if (error) { 1065123474Swpaul bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap); 1066123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1067123474Swpaul free(sh, M_DEVBUF); 1068123474Swpaul return; 1069123474Swpaul } 1070123474Swpaul 1071123474Swpaul sh->ndis_saddr = *vaddr; 1072123474Swpaul sh->ndis_next = sc->ndis_shlist; 1073123474Swpaul sc->ndis_shlist = sh; 1074123474Swpaul 1075123474Swpaul return; 1076123474Swpaul} 1077123474Swpaul 1078123474Swpaul__stdcall static void 1079123474Swpaulndis_alloc_sharedmem_async(adapter, len, cached, ctx) 1080123474Swpaul ndis_handle adapter; 1081123474Swpaul uint32_t len; 1082123474Swpaul uint8_t cached; 1083123474Swpaul void *ctx; 1084123474Swpaul{ 1085123474Swpaul ndis_miniport_block *block; 1086123474Swpaul struct ndis_softc *sc; 1087123474Swpaul void *vaddr; 1088123474Swpaul ndis_physaddr paddr; 1089123474Swpaul __stdcall ndis_allocdone_handler donefunc; 1090123474Swpaul 1091123474Swpaul if (adapter == NULL) 1092123474Swpaul return; 1093123474Swpaul 1094123474Swpaul block = (ndis_miniport_block *)adapter; 1095123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 1096123474Swpaul donefunc = sc->ndis_chars.nmc_allocate_complete_func; 1097123474Swpaul 1098123474Swpaul ndis_alloc_sharedmem(adapter, len, cached, &vaddr, &paddr); 1099123474Swpaul donefunc(adapter, vaddr, &paddr, len, ctx); 1100123474Swpaul 1101123474Swpaul return; 1102123474Swpaul} 1103123474Swpaul 1104123474Swpaul__stdcall static void 1105123474Swpaulndis_free_sharedmem(adapter, len, cached, vaddr, paddr) 1106123474Swpaul ndis_handle adapter; 1107123474Swpaul uint32_t len; 1108123474Swpaul uint8_t cached; 1109123474Swpaul void *vaddr; 1110123474Swpaul ndis_physaddr paddr; 1111123474Swpaul{ 1112123474Swpaul ndis_miniport_block *block; 1113123474Swpaul struct ndis_softc *sc; 1114123474Swpaul struct ndis_shmem *sh, *prev; 1115123474Swpaul 1116123474Swpaul if (vaddr == NULL || adapter == NULL) 1117123474Swpaul return; 1118123474Swpaul 1119123474Swpaul block = (ndis_miniport_block *)adapter; 1120123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 1121123474Swpaul sh = prev = sc->ndis_shlist; 1122123474Swpaul 1123123474Swpaul while (sh) { 1124123474Swpaul if (sh->ndis_saddr == vaddr) 1125123474Swpaul break; 1126123474Swpaul prev = sh; 1127123474Swpaul sh = sh->ndis_next; 1128123474Swpaul } 1129123474Swpaul 1130123474Swpaul bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap); 1131123474Swpaul bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap); 1132123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1133123474Swpaul 1134123474Swpaul if (sh == sc->ndis_shlist) 1135123474Swpaul sc->ndis_shlist = sh->ndis_next; 1136123474Swpaul else 1137123474Swpaul prev->ndis_next = sh->ndis_next; 1138123474Swpaul 1139123474Swpaul free(sh, M_DEVBUF); 1140123474Swpaul 1141123474Swpaul return; 1142123474Swpaul} 1143123474Swpaul 1144123474Swpaul__stdcall static ndis_status 1145123474Swpaulndis_map_iospace(vaddr, adapter, paddr, len) 1146123474Swpaul void **vaddr; 1147123474Swpaul ndis_handle adapter; 1148123474Swpaul ndis_physaddr paddr; 1149123474Swpaul uint32_t len; 1150123474Swpaul{ 1151123474Swpaul ndis_miniport_block *block; 1152123474Swpaul struct ndis_softc *sc; 1153123474Swpaul 1154123474Swpaul if (adapter == NULL) 1155123474Swpaul return(NDIS_STATUS_FAILURE); 1156123474Swpaul 1157123474Swpaul block = (ndis_miniport_block *)adapter; 1158123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 1159123474Swpaul 1160123474Swpaul if (sc->ndis_res_mem == NULL) 1161123474Swpaul return(NDIS_STATUS_FAILURE); 1162123474Swpaul 1163123474Swpaul *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem); 1164123474Swpaul 1165123474Swpaul return(NDIS_STATUS_SUCCESS); 1166123474Swpaul} 1167123474Swpaul 1168123474Swpaul__stdcall static void 1169123474Swpaulndis_unmap_iospace(adapter, vaddr, len) 1170123474Swpaul ndis_handle adapter; 1171123474Swpaul void *vaddr; 1172123474Swpaul uint32_t len; 1173123474Swpaul{ 1174123474Swpaul return; 1175123474Swpaul} 1176123474Swpaul 1177123474Swpaul__stdcall static uint32_t 1178123474Swpaulndis_cachefill(void) 1179123474Swpaul{ 1180123474Swpaul return(128); 1181123474Swpaul} 1182123474Swpaul 1183123474Swpaul__stdcall static uint32_t 1184123474Swpaulndis_dma_align(handle) 1185123474Swpaul ndis_handle handle; 1186123474Swpaul{ 1187123474Swpaul return(128); 1188123474Swpaul} 1189123474Swpaul 1190123474Swpaul/* 1191123474Swpaul * NDIS has two methods for dealing with NICs that support DMA. 1192123474Swpaul * One is to just pass packets to the driver and let it call 1193123474Swpaul * NdisMStartBufferPhysicalMapping() to map each buffer in the packet 1194123474Swpaul * all by itself, and the other is to let the NDIS library handle the 1195123474Swpaul * buffer mapping internally, and hand the driver an already populated 1196123474Swpaul * scatter/gather fragment list. If the driver calls 1197123474Swpaul * NdisMInitializeScatterGatherDma(), it wants to use the latter 1198123474Swpaul * method. 1199123474Swpaul */ 1200123474Swpaul 1201123474Swpaul__stdcall static ndis_status 1202123474Swpaulndis_init_sc_dma(adapter, is64, maxphysmap) 1203123474Swpaul ndis_handle adapter; 1204123474Swpaul uint8_t is64; 1205123474Swpaul uint32_t maxphysmap; 1206123474Swpaul{ 1207123474Swpaul struct ndis_softc *sc; 1208123474Swpaul ndis_miniport_block *block; 1209123474Swpaul int error; 1210123474Swpaul 1211123474Swpaul if (adapter == NULL) 1212123474Swpaul return(NDIS_STATUS_FAILURE); 1213123474Swpaul block = (ndis_miniport_block *)adapter; 1214123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1215123474Swpaul 1216123474Swpaul /* Don't do this twice. */ 1217123474Swpaul if (sc->ndis_sc == 1) 1218123474Swpaul return(NDIS_STATUS_SUCCESS); 1219123474Swpaul 1220123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 1221123474Swpaul BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 1222123474Swpaul MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW, 1223123474Swpaul NULL, NULL, &sc->ndis_ttag); 1224123474Swpaul 1225123474Swpaul sc->ndis_sc = 1; 1226123474Swpaul 1227123474Swpaul return(NDIS_STATUS_SUCCESS); 1228123474Swpaul} 1229123474Swpaul 1230123474Swpaul__stdcall static void 1231123474Swpaulndis_alloc_packetpool(status, pool, descnum, protrsvdlen) 1232123474Swpaul ndis_status *status; 1233123474Swpaul ndis_handle *pool; 1234123474Swpaul uint32_t descnum; 1235123474Swpaul uint32_t protrsvdlen; 1236123474Swpaul{ 1237123474Swpaul ndis_packet *cur; 1238123474Swpaul int i; 1239123474Swpaul 1240123474Swpaul *pool = malloc(sizeof(ndis_packet) * (descnum + 1), 1241123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 1242123474Swpaul 1243123474Swpaul if (pool == NULL) { 1244123474Swpaul *status = NDIS_STATUS_RESOURCES; 1245123474Swpaul return; 1246123474Swpaul } 1247123474Swpaul 1248123474Swpaul cur = (ndis_packet *)*pool; 1249123474Swpaul cur->np_private.npp_flags = 0x1; /* mark the head of the list */ 1250123474Swpaul for (i = 0; i < descnum; i++) { 1251123474Swpaul cur->np_private.npp_head = (ndis_handle)(cur + 1); 1252123474Swpaul cur++; 1253123474Swpaul } 1254123474Swpaul 1255123474Swpaul *status = NDIS_STATUS_SUCCESS; 1256123474Swpaul return; 1257123474Swpaul} 1258123474Swpaul 1259123474Swpaul__stdcall static void 1260123474Swpaulndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen) 1261123474Swpaul ndis_status *status; 1262123474Swpaul ndis_handle *pool; 1263123474Swpaul uint32_t descnum; 1264123474Swpaul uint32_t oflowdescnum; 1265123474Swpaul uint32_t protrsvdlen; 1266123474Swpaul{ 1267123474Swpaul return(ndis_alloc_packetpool(status, pool, 1268123474Swpaul descnum + oflowdescnum, protrsvdlen)); 1269123474Swpaul} 1270123474Swpaul 1271123474Swpaul__stdcall static uint32_t 1272123474Swpaulndis_packetpool_use(pool) 1273123474Swpaul ndis_handle pool; 1274123474Swpaul{ 1275123474Swpaul ndis_packet *head; 1276123474Swpaul 1277123474Swpaul head = (ndis_packet *)pool; 1278123474Swpaul 1279123474Swpaul return(head->np_private.npp_count); 1280123474Swpaul} 1281123474Swpaul 1282123474Swpaul__stdcall static void 1283123474Swpaulndis_free_packetpool(pool) 1284123474Swpaul ndis_handle pool; 1285123474Swpaul{ 1286123474Swpaul free(pool, M_DEVBUF); 1287123474Swpaul return; 1288123474Swpaul} 1289123474Swpaul 1290123474Swpaul__stdcall static void 1291123474Swpaulndis_alloc_packet(status, packet, pool) 1292123474Swpaul ndis_status *status; 1293123474Swpaul ndis_packet **packet; 1294123474Swpaul ndis_handle pool; 1295123474Swpaul{ 1296123474Swpaul ndis_packet *head, *pkt; 1297123474Swpaul 1298123474Swpaul head = (ndis_packet *)pool; 1299123474Swpaul 1300123474Swpaul if (head->np_private.npp_flags != 0x1) { 1301123474Swpaul *status = NDIS_STATUS_FAILURE; 1302123474Swpaul return; 1303123474Swpaul } 1304123474Swpaul 1305123474Swpaul pkt = (ndis_packet *)head->np_private.npp_head; 1306123474Swpaul 1307123474Swpaul if (pkt == NULL) { 1308123474Swpaul *status = NDIS_STATUS_RESOURCES; 1309123474Swpaul return; 1310123474Swpaul } 1311123474Swpaul 1312123474Swpaul head->np_private.npp_head = pkt->np_private.npp_head; 1313123474Swpaul 1314123474Swpaul pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL; 1315123474Swpaul /* Save pointer to the pool. */ 1316123474Swpaul pkt->np_private.npp_pool = head; 1317123474Swpaul 1318123474Swpaul /* Set the oob offset pointer. Lots of things expect this. */ 1319123474Swpaul pkt->np_private.npp_packetooboffset = 1320123474Swpaul offsetof(ndis_packet, np_oob); 1321123474Swpaul 1322123474Swpaul *packet = pkt; 1323123474Swpaul 1324123474Swpaul head->np_private.npp_count++; 1325123474Swpaul *status = NDIS_STATUS_SUCCESS; 1326123474Swpaul return; 1327123474Swpaul} 1328123474Swpaul 1329123474Swpaul__stdcall static void 1330123474Swpaulndis_release_packet(packet) 1331123474Swpaul ndis_packet *packet; 1332123474Swpaul{ 1333123474Swpaul ndis_packet *head; 1334123474Swpaul 1335123474Swpaul if (packet == NULL || packet->np_private.npp_pool == NULL) 1336123474Swpaul return; 1337123474Swpaul 1338123474Swpaul head = packet->np_private.npp_pool; 1339123474Swpaul if (head->np_private.npp_flags != 0x1) 1340123474Swpaul return; 1341123474Swpaul 1342123474Swpaul packet->np_private.npp_head = head->np_private.npp_head; 1343123474Swpaul head->np_private.npp_head = (ndis_buffer *)packet; 1344123474Swpaul head->np_private.npp_count--; 1345123474Swpaul 1346123474Swpaul return; 1347123474Swpaul} 1348123474Swpaul 1349123474Swpaul__stdcall static void 1350123474Swpaulndis_unchain_headbuf(packet, buf) 1351123474Swpaul ndis_packet *packet; 1352123474Swpaul ndis_buffer **buf; 1353123474Swpaul{ 1354123474Swpaul ndis_packet_private *priv; 1355123474Swpaul 1356123474Swpaul if (packet == NULL || buf == NULL) 1357123474Swpaul return; 1358123474Swpaul 1359123474Swpaul priv = &packet->np_private; 1360123474Swpaul 1361123474Swpaul priv->npp_validcounts = FALSE; 1362123474Swpaul 1363123474Swpaul if (priv->npp_head == priv->npp_tail) { 1364123474Swpaul *buf = priv->npp_head; 1365123474Swpaul priv->npp_head = priv->npp_tail = NULL; 1366123474Swpaul } else { 1367123474Swpaul *buf = priv->npp_head; 1368123474Swpaul priv->npp_head = (*buf)->nb_next; 1369123474Swpaul } 1370123474Swpaul 1371123474Swpaul return; 1372123474Swpaul} 1373123474Swpaul 1374123474Swpaul/* 1375123474Swpaul * The NDIS "buffer" manipulation functions are somewhat misnamed. 1376123474Swpaul * They don't really allocate buffers: they allocate buffer mappings. 1377123474Swpaul * The idea is you reserve a chunk of DMA-able memory using 1378123474Swpaul * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer() 1379123474Swpaul * to obtain the virtual address of the DMA-able region. 1380123474Swpaul * ndis_alloc_bufpool() is analagous to bus_dma_tag_create(). 1381123474Swpaul */ 1382123474Swpaul 1383123474Swpaul__stdcall static void 1384123474Swpaulndis_alloc_bufpool(status, pool, descnum) 1385123474Swpaul ndis_status *status; 1386123474Swpaul ndis_handle *pool; 1387123474Swpaul uint32_t descnum; 1388123474Swpaul{ 1389123474Swpaul ndis_buffer *cur; 1390123474Swpaul int i; 1391123474Swpaul 1392123474Swpaul *pool = malloc(sizeof(ndis_buffer) * (descnum + 1), 1393123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 1394123474Swpaul 1395123474Swpaul if (pool == NULL) { 1396123474Swpaul *status = NDIS_STATUS_RESOURCES; 1397123474Swpaul return; 1398123474Swpaul } 1399123474Swpaul 1400123474Swpaul cur = (ndis_buffer *)*pool; 1401123474Swpaul cur->nb_flags = 0x1; /* mark the head of the list */ 1402123474Swpaul for (i = 0; i < descnum; i++) { 1403123474Swpaul cur->nb_next = cur + 1; 1404123474Swpaul cur++; 1405123474Swpaul } 1406123474Swpaul 1407123474Swpaul *status = NDIS_STATUS_SUCCESS; 1408123474Swpaul return; 1409123474Swpaul} 1410123474Swpaul 1411123474Swpaul__stdcall static void 1412123474Swpaulndis_free_bufpool(pool) 1413123474Swpaul ndis_handle pool; 1414123474Swpaul{ 1415123474Swpaul free(pool, M_DEVBUF); 1416123474Swpaul return; 1417123474Swpaul} 1418123474Swpaul 1419123474Swpaul/* 1420123474Swpaul * This maps to a bus_dmamap_create() and bus_dmamap_load(). 1421123474Swpaul */ 1422123474Swpaul__stdcall static void 1423123474Swpaulndis_alloc_buf(status, buffer, pool, vaddr, len) 1424123474Swpaul ndis_status *status; 1425123474Swpaul ndis_buffer **buffer; 1426123474Swpaul ndis_handle pool; 1427123474Swpaul void *vaddr; 1428123474Swpaul uint32_t len; 1429123474Swpaul{ 1430123474Swpaul ndis_buffer *head, *buf; 1431123474Swpaul 1432123474Swpaul head = (ndis_buffer *)pool; 1433123474Swpaul if (head->nb_flags != 0x1) { 1434123474Swpaul *status = NDIS_STATUS_FAILURE; 1435123474Swpaul return; 1436123474Swpaul } 1437123474Swpaul 1438123474Swpaul buf = head->nb_next; 1439123474Swpaul 1440123474Swpaul if (buf == NULL) { 1441123474Swpaul *status = NDIS_STATUS_RESOURCES; 1442123474Swpaul return; 1443123474Swpaul } 1444123474Swpaul 1445123474Swpaul head->nb_next = buf->nb_next; 1446123474Swpaul 1447123474Swpaul /* Save pointer to the pool. */ 1448123474Swpaul buf->nb_process = head; 1449123474Swpaul 1450123474Swpaul buf->nb_mappedsystemva = vaddr; 1451123474Swpaul buf->nb_size = len; 1452123474Swpaul buf->nb_next = NULL; 1453123474Swpaul 1454123474Swpaul *buffer = buf; 1455123474Swpaul 1456123474Swpaul *status = NDIS_STATUS_SUCCESS; 1457123474Swpaul return; 1458123474Swpaul} 1459123474Swpaul 1460123474Swpaul__stdcall static void 1461123474Swpaulndis_release_buf(buf) 1462123474Swpaul ndis_buffer *buf; 1463123474Swpaul{ 1464123474Swpaul ndis_buffer *head; 1465123474Swpaul 1466123474Swpaul if (buf == NULL || buf->nb_process == NULL) 1467123474Swpaul return; 1468123474Swpaul 1469123474Swpaul head = buf->nb_process; 1470123474Swpaul 1471123474Swpaul if (head->nb_flags != 0x1) 1472123474Swpaul return; 1473123474Swpaul 1474123474Swpaul buf->nb_next = head->nb_next; 1475123474Swpaul head->nb_next = buf; 1476123474Swpaul 1477123474Swpaul return; 1478123474Swpaul} 1479123474Swpaul 1480123474Swpaul/* Get the virtual address and length of a buffer */ 1481123474Swpaul 1482123474Swpaul__stdcall static void 1483123474Swpaulndis_query_buf(buf, vaddr, len) 1484123474Swpaul ndis_buffer *buf; 1485123474Swpaul void **vaddr; 1486123474Swpaul uint32_t *len; 1487123474Swpaul{ 1488123474Swpaul *vaddr = buf->nb_mappedsystemva; 1489123474Swpaul *len = buf->nb_bytecount; 1490123474Swpaul 1491123474Swpaul return; 1492123474Swpaul} 1493123474Swpaul 1494123474Swpaul/* Same as above -- we don't care about the priority. */ 1495123474Swpaul 1496123474Swpaul__stdcall static void 1497123474Swpaulndis_query_buf_safe(buf, vaddr, len, prio) 1498123474Swpaul ndis_buffer *buf; 1499123474Swpaul void **vaddr; 1500123474Swpaul uint32_t *len; 1501123474Swpaul uint32_t prio; 1502123474Swpaul{ 1503123474Swpaul *vaddr = buf->nb_mappedsystemva; 1504123474Swpaul *len = buf->nb_bytecount; 1505123474Swpaul 1506123474Swpaul return; 1507123474Swpaul} 1508123474Swpaul 1509123474Swpaul__stdcall static void 1510123474Swpaulndis_adjust_buflen(buf, len) 1511123474Swpaul ndis_buffer *buf; 1512123474Swpaul int len; 1513123474Swpaul{ 1514123488Swpaul if (len > buf->nb_size) 1515123474Swpaul return; 1516123474Swpaul buf->nb_bytecount = len; 1517123474Swpaul 1518123474Swpaul return; 1519123474Swpaul} 1520123474Swpaul 1521123474Swpaul__stdcall static uint32_t 1522123474Swpaulndis_interlock_inc(addend) 1523123474Swpaul uint32_t *addend; 1524123474Swpaul{ 1525123474Swpaul mtx_lock(&ndis_interlock); 1526123474Swpaul *addend++; 1527123474Swpaul mtx_unlock(&ndis_interlock); 1528123474Swpaul return(*addend); 1529123474Swpaul} 1530123474Swpaul 1531123474Swpaul__stdcall static uint32_t 1532123474Swpaulndis_interlock_dec(addend) 1533123474Swpaul uint32_t *addend; 1534123474Swpaul{ 1535123474Swpaul mtx_lock(&ndis_interlock); 1536123474Swpaul *addend--; 1537123474Swpaul mtx_unlock(&ndis_interlock); 1538123474Swpaul return(*addend); 1539123474Swpaul} 1540123474Swpaul 1541123474Swpaul__stdcall static void 1542123474Swpaulndis_init_event(event) 1543123474Swpaul ndis_event *event; 1544123474Swpaul{ 1545123474Swpaul event->ne_event.nk_header.dh_sigstate = FALSE; 1546123474Swpaul return; 1547123474Swpaul} 1548123474Swpaul 1549123474Swpaul__stdcall static void 1550123474Swpaulndis_set_event(event) 1551123474Swpaul ndis_event *event; 1552123474Swpaul{ 1553123474Swpaul event->ne_event.nk_header.dh_sigstate = TRUE; 1554123474Swpaul wakeup(event); 1555123474Swpaul return; 1556123474Swpaul} 1557123474Swpaul 1558123474Swpaul__stdcall static void 1559123474Swpaulndis_reset_event(event) 1560123474Swpaul ndis_event *event; 1561123474Swpaul{ 1562123474Swpaul event->ne_event.nk_header.dh_sigstate = FALSE; 1563123474Swpaul wakeup(event); 1564123474Swpaul return; 1565123474Swpaul} 1566123474Swpaul 1567123474Swpaul__stdcall static uint8_t 1568123474Swpaulndis_wait_event(event, msecs) 1569123474Swpaul ndis_event *event; 1570123474Swpaul uint32_t msecs; 1571123474Swpaul{ 1572123474Swpaul int error; 1573123474Swpaul struct timeval tv; 1574123474Swpaul 1575123474Swpaul if (event->ne_event.nk_header.dh_sigstate == TRUE) 1576123474Swpaul return(TRUE); 1577123474Swpaul 1578123474Swpaul tv.tv_sec = 0; 1579123474Swpaul tv.tv_usec = msecs * 1000; 1580123474Swpaul 1581123474Swpaul error = tsleep(event, PPAUSE|PCATCH, "ndis", tvtohz(&tv)); 1582123474Swpaul 1583123474Swpaul return(event->ne_event.nk_header.dh_sigstate); 1584123474Swpaul} 1585123474Swpaul 1586123474Swpaul__stdcall static ndis_status 1587123474Swpaulndis_unicode2ansi(dstr, sstr) 1588123474Swpaul ndis_ansi_string *dstr; 1589123474Swpaul ndis_unicode_string *sstr; 1590123474Swpaul{ 1591123474Swpaul ndis_unicode_to_ascii(sstr->nus_buf, sstr->nus_len, &dstr->nas_buf); 1592123474Swpaul dstr->nas_len = strlen(dstr->nas_buf); 1593123474Swpaul printf ("unicode 2 ansi...\n"); 1594123474Swpaul return (NDIS_STATUS_SUCCESS); 1595123474Swpaul} 1596123474Swpaul 1597123474Swpaul__stdcall static ndis_status 1598123474Swpaulndis_assign_pcirsrc(adapter, slot, list) 1599123474Swpaul ndis_handle adapter; 1600123474Swpaul uint32_t slot; 1601123474Swpaul ndis_resource_list **list; 1602123474Swpaul{ 1603123474Swpaul ndis_miniport_block *block; 1604123474Swpaul 1605123474Swpaul if (adapter == NULL || list == NULL) 1606123474Swpaul return (NDIS_STATUS_FAILURE); 1607123474Swpaul 1608123474Swpaul block = (ndis_miniport_block *)adapter; 1609123474Swpaul *list = block->nmb_rlist; 1610123474Swpaul 1611123474Swpaul printf ("assign PCI resources...\n"); 1612123474Swpaul return (NDIS_STATUS_SUCCESS); 1613123474Swpaul} 1614123474Swpaul 1615123474Swpaul__stdcall static ndis_status 1616123474Swpaulndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode) 1617123474Swpaul ndis_miniport_interrupt *intr; 1618123474Swpaul ndis_handle adapter; 1619123474Swpaul uint32_t ivec; 1620123474Swpaul uint32_t ilevel; 1621123474Swpaul uint8_t reqisr; 1622123474Swpaul uint8_t shared; 1623123474Swpaul ndis_interrupt_mode imode; 1624123474Swpaul{ 1625123474Swpaul 1626123474Swpaul return(NDIS_STATUS_SUCCESS); 1627123474Swpaul} 1628123474Swpaul 1629123474Swpaul__stdcall static void 1630123474Swpaulndis_deregister_intr(intr) 1631123474Swpaul ndis_miniport_interrupt *intr; 1632123474Swpaul{ 1633123474Swpaul return; 1634123474Swpaul} 1635123474Swpaul 1636123474Swpaul__stdcall static void 1637123474Swpaulndis_register_shutdown(adapter, shutdownctx, shutdownfunc) 1638123474Swpaul ndis_handle adapter; 1639123474Swpaul void *shutdownctx; 1640123474Swpaul ndis_shutdown_handler shutdownfunc; 1641123474Swpaul{ 1642123474Swpaul ndis_miniport_block *block; 1643123474Swpaul ndis_miniport_characteristics *chars; 1644123474Swpaul struct ndis_softc *sc; 1645123474Swpaul 1646123474Swpaul if (adapter == NULL) 1647123474Swpaul return; 1648123474Swpaul 1649123474Swpaul block = (ndis_miniport_block *)adapter; 1650123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1651123474Swpaul chars = &sc->ndis_chars; 1652123474Swpaul 1653123474Swpaul chars->nmc_shutdown_handler = shutdownfunc; 1654123474Swpaul chars->nmc_rsvd0 = shutdownctx; 1655123474Swpaul 1656123474Swpaul return; 1657123474Swpaul} 1658123474Swpaul 1659123474Swpaul__stdcall static void 1660123474Swpaulndis_deregister_shutdown(adapter) 1661123474Swpaul ndis_handle adapter; 1662123474Swpaul{ 1663123474Swpaul ndis_miniport_block *block; 1664123474Swpaul ndis_miniport_characteristics *chars; 1665123474Swpaul struct ndis_softc *sc; 1666123474Swpaul 1667123474Swpaul if (adapter == NULL) 1668123474Swpaul return; 1669123474Swpaul 1670123474Swpaul block = (ndis_miniport_block *)adapter; 1671123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1672123474Swpaul chars = &sc->ndis_chars; 1673123474Swpaul 1674123474Swpaul chars->nmc_shutdown_handler = NULL; 1675123474Swpaul chars->nmc_rsvd0 = NULL; 1676123474Swpaul 1677123474Swpaul return; 1678123474Swpaul} 1679123474Swpaul 1680123474Swpaul__stdcall static uint32_t 1681123474Swpaulndis_numpages(buf) 1682123474Swpaul ndis_buffer *buf; 1683123474Swpaul{ 1684123474Swpaul return(howmany(buf->nb_bytecount, PAGE_SIZE)); 1685123474Swpaul} 1686123474Swpaul 1687123474Swpaul__stdcall static void 1688123474Swpaulndis_query_bufoffset(buf, off, len) 1689123474Swpaul ndis_buffer *buf; 1690123474Swpaul uint32_t *off; 1691123474Swpaul uint32_t *len; 1692123474Swpaul{ 1693123474Swpaul *off = (uint32_t)buf->nb_mappedsystemva & (PAGE_SIZE - 1); 1694123474Swpaul *len = buf->nb_bytecount; 1695123474Swpaul 1696123474Swpaul return; 1697123474Swpaul} 1698123474Swpaul 1699123474Swpaul__stdcall static void 1700123474Swpaulndis_sleep(usecs) 1701123474Swpaul uint32_t usecs; 1702123474Swpaul{ 1703123474Swpaul struct timeval tv; 1704123474Swpaul uint32_t dummy; 1705123474Swpaul 1706123474Swpaul tv.tv_sec = 0; 1707123474Swpaul tv.tv_usec = usecs; 1708123474Swpaul 1709123474Swpaul tsleep(&dummy, PPAUSE|PCATCH, "ndis", tvtohz(&tv)); 1710123474Swpaul return; 1711123474Swpaul} 1712123474Swpaul 1713123474Swpaul__stdcall static uint32_t 1714123474Swpaulndis_read_pccard_amem(handle, offset, buf, len) 1715123474Swpaul ndis_handle handle; 1716123474Swpaul uint32_t offset; 1717123474Swpaul void *buf; 1718123474Swpaul uint32_t len; 1719123474Swpaul{ 1720123474Swpaul struct ndis_softc *sc; 1721123474Swpaul ndis_miniport_block *block; 1722123474Swpaul bus_space_handle_t bh; 1723123474Swpaul bus_space_tag_t bt; 1724123474Swpaul char *dest; 1725123474Swpaul int i; 1726123474Swpaul 1727123474Swpaul if (handle == NULL) 1728123474Swpaul return(0); 1729123474Swpaul 1730123474Swpaul block = (ndis_miniport_block *)handle; 1731123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1732123474Swpaul dest = buf; 1733123474Swpaul 1734123474Swpaul bh = rman_get_bushandle(sc->ndis_res_am); 1735123474Swpaul bt = rman_get_bustag(sc->ndis_res_am); 1736123474Swpaul 1737123474Swpaul for (i = 0; i < len; i++) 1738123474Swpaul dest[i] = bus_space_read_1(bt, bh, (offset * 2) + (i * 2)); 1739123474Swpaul 1740123474Swpaul return(i); 1741123474Swpaul} 1742123474Swpaul 1743123474Swpaul__stdcall static uint32_t 1744123474Swpaulndis_write_pccard_amem(handle, offset, buf, len) 1745123474Swpaul ndis_handle handle; 1746123474Swpaul uint32_t offset; 1747123474Swpaul void *buf; 1748123474Swpaul uint32_t len; 1749123474Swpaul{ 1750123474Swpaul struct ndis_softc *sc; 1751123474Swpaul ndis_miniport_block *block; 1752123474Swpaul bus_space_handle_t bh; 1753123474Swpaul bus_space_tag_t bt; 1754123474Swpaul char *src; 1755123474Swpaul int i; 1756123474Swpaul 1757123474Swpaul if (handle == NULL) 1758123474Swpaul return(0); 1759123474Swpaul 1760123474Swpaul block = (ndis_miniport_block *)handle; 1761123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1762123474Swpaul src = buf; 1763123474Swpaul 1764123474Swpaul bh = rman_get_bushandle(sc->ndis_res_am); 1765123474Swpaul bt = rman_get_bustag(sc->ndis_res_am); 1766123474Swpaul 1767123474Swpaul for (i = 0; i < len; i++) 1768123474Swpaul bus_space_write_1(bt, bh, (offset * 2) + (i * 2), src[i]); 1769123474Swpaul 1770123474Swpaul return(i); 1771123474Swpaul} 1772123474Swpaul 1773123474Swpaul__stdcall static ndis_list_entry * 1774123474Swpaulndis_insert_head(head, entry, lock) 1775123474Swpaul ndis_list_entry *head; 1776123474Swpaul ndis_list_entry *entry; 1777123474Swpaul ndis_spin_lock *lock; 1778123474Swpaul{ 1779123474Swpaul ndis_list_entry *flink; 1780123474Swpaul 1781123474Swpaul mtx_lock_spin((struct mtx *)lock->nsl_spinlock); 1782123474Swpaul flink = head->nle_flink; 1783123474Swpaul entry->nle_flink = flink; 1784123474Swpaul entry->nle_blink = head; 1785123474Swpaul flink->nle_blink = entry; 1786123474Swpaul head->nle_flink = entry; 1787123474Swpaul mtx_unlock_spin((struct mtx *)lock->nsl_spinlock); 1788123474Swpaul 1789123474Swpaul return(flink); 1790123474Swpaul} 1791123474Swpaul 1792123474Swpaul__stdcall static ndis_list_entry * 1793123474Swpaulndis_remove_head(head, lock) 1794123474Swpaul ndis_list_entry *head; 1795123474Swpaul ndis_spin_lock *lock; 1796123474Swpaul{ 1797123474Swpaul ndis_list_entry *flink; 1798123474Swpaul ndis_list_entry *entry; 1799123474Swpaul 1800123474Swpaul mtx_lock_spin((struct mtx *)lock->nsl_spinlock); 1801123474Swpaul entry = head->nle_flink; 1802123474Swpaul flink = entry->nle_flink; 1803123474Swpaul head->nle_flink = flink; 1804123474Swpaul flink->nle_blink = head; 1805123474Swpaul mtx_unlock_spin((struct mtx *)lock->nsl_spinlock); 1806123474Swpaul 1807123474Swpaul return(entry); 1808123474Swpaul} 1809123474Swpaul 1810123474Swpaul__stdcall static ndis_list_entry * 1811123474Swpaulndis_insert_tail(head, entry, lock) 1812123474Swpaul ndis_list_entry *head; 1813123474Swpaul ndis_list_entry *entry; 1814123474Swpaul ndis_spin_lock *lock; 1815123474Swpaul{ 1816123474Swpaul ndis_list_entry *blink; 1817123474Swpaul 1818123474Swpaul mtx_lock_spin((struct mtx *)lock->nsl_spinlock); 1819123474Swpaul blink = head->nle_blink; 1820123474Swpaul entry->nle_flink = head; 1821123474Swpaul entry->nle_blink = blink; 1822123474Swpaul blink->nle_flink = entry; 1823123474Swpaul head->nle_blink = entry; 1824123474Swpaul mtx_unlock_spin((struct mtx *)lock->nsl_spinlock); 1825123474Swpaul 1826123474Swpaul return(blink); 1827123474Swpaul} 1828123474Swpaul 1829123474Swpaul__stdcall static uint8_t 1830123474Swpaulndis_sync_with_intr(intr, syncfunc, syncctx) 1831123474Swpaul ndis_miniport_interrupt *intr; 1832123474Swpaul void *syncfunc; 1833123474Swpaul void *syncctx; 1834123474Swpaul{ 1835123474Swpaul __stdcall uint8_t (*sync)(void *); 1836123474Swpaul 1837123474Swpaul if (syncfunc == NULL || syncctx == NULL) 1838123474Swpaul return(0); 1839123474Swpaul 1840123474Swpaul sync = syncfunc; 1841123474Swpaul return(sync(syncctx)); 1842123474Swpaul} 1843123474Swpaul 1844123504Swpaul/* 1845123504Swpaul * Return the number of 100 nanosecond intervals since 1846123504Swpaul * January 1, 1601. (?!?!) 1847123504Swpaul */ 1848123474Swpaul__stdcall static void 1849123504Swpaulndis_time(tval) 1850123504Swpaul uint64_t *tval; 1851123504Swpaul{ 1852123504Swpaul struct timespec ts; 1853123504Swpaul nanotime(&ts); 1854123504Swpaul *tval = (ts.tv_nsec / 100) + (ts.tv_nsec * 10000000); 1855123504Swpaul return; 1856123504Swpaul} 1857123504Swpaul 1858123504Swpaul__stdcall static void 1859123474Swpauldummy() 1860123474Swpaul{ 1861123474Swpaul printf ("NDIS dummy called...\n"); 1862123474Swpaul return; 1863123474Swpaul} 1864123474Swpaul 1865123474Swpaulimage_patch_table ndis_functbl[] = { 1866123504Swpaul { "NdisGetCurrentSystemTime", (FUNC)ndis_time }, 1867123474Swpaul { "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr }, 1868123474Swpaul { "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async }, 1869123474Swpaul { "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head }, 1870123474Swpaul { "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail }, 1871123474Swpaul { "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head }, 1872123474Swpaul { "NdisInitializeWrapper", (FUNC)ndis_initwrap }, 1873123474Swpaul { "NdisMRegisterMiniport", (FUNC)ndis_register_miniport }, 1874123474Swpaul { "NdisAllocateMemoryWithTag", (FUNC)ndis_malloc_withtag }, 1875123474Swpaul { "NdisAllocateMemory", (FUNC)ndis_malloc }, 1876123474Swpaul { "NdisMSetAttributesEx", (FUNC)ndis_setattr_ex }, 1877123474Swpaul { "NdisCloseConfiguration", (FUNC)ndis_close_cfg }, 1878123474Swpaul { "NdisReadConfiguration", (FUNC)ndis_read_cfg }, 1879123474Swpaul { "NdisOpenConfiguration", (FUNC)ndis_open_cfg }, 1880123474Swpaul { "NdisReleaseSpinLock", (FUNC)ndis_unlock }, 1881123474Swpaul { "NdisDprAcquireSpinLock", (FUNC)ndis_lock }, 1882123474Swpaul { "NdisDprReleaseSpinLock", (FUNC)ndis_unlock }, 1883123474Swpaul { "NdisAcquireSpinLock", (FUNC)ndis_lock }, 1884123474Swpaul { "NdisAllocateSpinLock", (FUNC)ndis_create_lock }, 1885123474Swpaul { "NdisFreeSpinLock", (FUNC)ndis_destroy_lock }, 1886123474Swpaul { "NdisFreeMemory", (FUNC)ndis_free }, 1887123474Swpaul { "NdisReadPciSlotInformation", (FUNC)ndis_read_pci }, 1888123474Swpaul { "NdisWritePciSlotInformation",(FUNC)ndis_write_pci }, 1889123474Swpaul { "NdisWriteErrorLogEntry", (FUNC)ndis_syslog }, 1890123474Swpaul { "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load }, 1891123474Swpaul { "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload }, 1892123474Swpaul { "NdisMInitializeTimer", (FUNC)ndis_create_timer }, 1893123474Swpaul { "NdisSetTimer", (FUNC)ndis_set_timer }, 1894123474Swpaul { "NdisMCancelTimer", (FUNC)ndis_cancel_timer }, 1895123474Swpaul { "NdisMSetPeriodicTimer", (FUNC)ndis_set_periodic_timer }, 1896123474Swpaul { "NdisMQueryAdapterResources", (FUNC)ndis_query_resources }, 1897123474Swpaul { "NdisMRegisterIoPortRange", (FUNC)ndis_register_ioport }, 1898123474Swpaul { "NdisMDeregisterIoPortRange", (FUNC)ndis_deregister_ioport }, 1899123474Swpaul { "NdisReadNetworkAddress", (FUNC)ndis_read_netaddr }, 1900123474Swpaul { "NdisMAllocateMapRegisters", (FUNC)ndis_alloc_mapreg }, 1901123474Swpaul { "NdisMFreeMapRegisters", (FUNC)ndis_free_mapreg }, 1902123474Swpaul { "NdisMAllocateSharedMemory", (FUNC)ndis_alloc_sharedmem }, 1903123474Swpaul { "NdisMMapIoSpace", (FUNC)ndis_map_iospace }, 1904123474Swpaul { "NdisMUnmapIoSpace", (FUNC)ndis_unmap_iospace }, 1905123474Swpaul { "NdisGetCacheFillSize", (FUNC)ndis_cachefill }, 1906123474Swpaul { "NdisMGetDmaAlignment", (FUNC)ndis_dma_align }, 1907123474Swpaul { "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma }, 1908123474Swpaul { "NdisAllocatePacketPool", (FUNC)ndis_alloc_packetpool }, 1909123474Swpaul { "NdisAllocatePacketPoolEx", (FUNC)ndis_ex_alloc_packetpool }, 1910123474Swpaul { "NdisAllocatePacket", (FUNC)ndis_alloc_packet }, 1911123474Swpaul { "NdisFreePacket", (FUNC)ndis_release_packet }, 1912123474Swpaul { "NdisFreePacketPool", (FUNC)ndis_free_packetpool }, 1913123474Swpaul { "NdisAllocateBufferPool", (FUNC)ndis_alloc_bufpool }, 1914123474Swpaul { "NdisAllocateBuffer", (FUNC)ndis_alloc_buf }, 1915123474Swpaul { "NdisQueryBuffer", (FUNC)ndis_query_buf }, 1916123474Swpaul { "NdisQueryBufferSafe", (FUNC)ndis_query_buf_safe }, 1917123474Swpaul { "NdisFreeBuffer", (FUNC)ndis_release_buf }, 1918123474Swpaul { "NdisFreeBufferPool", (FUNC)ndis_free_bufpool }, 1919123474Swpaul { "NdisInterlockedIncrement", (FUNC)ndis_interlock_inc }, 1920123474Swpaul { "NdisInterlockedDecrement", (FUNC)ndis_interlock_dec }, 1921123474Swpaul { "NdisInitializeEvent", (FUNC)ndis_init_event }, 1922123474Swpaul { "NdisSetEvent", (FUNC)ndis_set_event }, 1923123474Swpaul { "NdisResetEvent", (FUNC)ndis_reset_event }, 1924123474Swpaul { "NdisWaitEvent", (FUNC)ndis_wait_event }, 1925123474Swpaul { "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi }, 1926123474Swpaul { "NdisMPciAssignResources", (FUNC)ndis_assign_pcirsrc }, 1927123474Swpaul { "NdisMFreeSharedMemory", (FUNC)ndis_free_sharedmem }, 1928123474Swpaul { "NdisMRegisterInterrupt", (FUNC)ndis_register_intr }, 1929123474Swpaul { "NdisMDeregisterInterrupt", (FUNC)ndis_deregister_intr }, 1930123474Swpaul { "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown }, 1931123474Swpaul { "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown }, 1932123474Swpaul { "NDIS_BUFFER_TO_SPAN_PAGES", (FUNC)ndis_numpages }, 1933123474Swpaul { "NdisQueryBufferOffset", (FUNC)ndis_query_bufoffset }, 1934123474Swpaul { "NdisAdjustBufferLength", (FUNC)ndis_adjust_buflen }, 1935123474Swpaul { "NdisPacketPoolUsage", (FUNC)ndis_packetpool_use }, 1936123474Swpaul { "NdisMSleep", (FUNC)ndis_sleep }, 1937123474Swpaul { "NdisUnchainBufferAtFront", (FUNC)ndis_unchain_headbuf }, 1938123474Swpaul { "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem }, 1939123474Swpaul { "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem }, 1940123474Swpaul 1941123474Swpaul /* 1942123474Swpaul * This last entry is a catch-all for any function we haven't 1943123474Swpaul * implemented yet. The PE import list patching routine will 1944123474Swpaul * use it for any function that doesn't have an explicit match 1945123474Swpaul * in this table. 1946123474Swpaul */ 1947123474Swpaul 1948123474Swpaul { NULL, (FUNC)dummy }, 1949123474Swpaul 1950123474Swpaul /* End of list. */ 1951123474Swpaul 1952123474Swpaul { NULL, NULL }, 1953123474Swpaul}; 1954123474Swpaul 1955