subr_ndis.c revision 124097
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 124097 2004-01-03 09:20:48Z 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> 65123848Swpaul#include <sys/smp.h> 66123474Swpaul 67123474Swpaul#include <net/if.h> 68123474Swpaul#include <net/if_arp.h> 69123474Swpaul#include <net/ethernet.h> 70123474Swpaul#include <net/if_dl.h> 71123474Swpaul#include <net/if_media.h> 72123474Swpaul 73123474Swpaul#include <machine/bus_memio.h> 74123474Swpaul#include <machine/bus_pio.h> 75123474Swpaul#include <machine/bus.h> 76123474Swpaul#include <machine/resource.h> 77123474Swpaul 78123474Swpaul#include <sys/bus.h> 79123474Swpaul#include <sys/rman.h> 80123474Swpaul 81123474Swpaul#include <machine/stdarg.h> 82123474Swpaul 83123695Swpaul#include <net80211/ieee80211_var.h> 84123695Swpaul#include <net80211/ieee80211_ioctl.h> 85123695Swpaul 86123474Swpaul#include <dev/pci/pcireg.h> 87123474Swpaul#include <dev/pci/pcivar.h> 88123474Swpaul 89123474Swpaul#include <compat/ndis/pe_var.h> 90123474Swpaul#include <compat/ndis/resource_var.h> 91123512Swpaul#include <compat/ndis/ntoskrnl_var.h> 92123474Swpaul#include <compat/ndis/ndis_var.h> 93123474Swpaul#include <compat/ndis/cfg_var.h> 94123474Swpaul#include <dev/if_ndis/if_ndisvar.h> 95123474Swpaul 96123474Swpaul#define __stdcall __attribute__((__stdcall__)) 97123474Swpaul#define FUNC void(*)(void) 98123474Swpaul 99123474Swpaulstatic struct mtx ndis_interlock; 100123474Swpaulstatic int ndis_inits = 0; 101123474Swpaul 102123474Swpaul__stdcall static void ndis_initwrap(ndis_handle, 103123474Swpaul ndis_driver_object *, void *, void *); 104123474Swpaul__stdcall static ndis_status ndis_register_miniport(ndis_handle, 105123474Swpaul ndis_miniport_characteristics *, int); 106123474Swpaul__stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t); 107123474Swpaul__stdcall static ndis_status ndis_malloc(void **, 108123474Swpaul uint32_t, uint32_t, ndis_physaddr); 109123474Swpaul__stdcall static void ndis_free(void *, uint32_t, uint32_t); 110123474Swpaul__stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle, 111123474Swpaul uint32_t, uint32_t, ndis_interface_type); 112123474Swpaul__stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle); 113123526Swpaul__stdcall static void ndis_open_cfgbyidx(ndis_status *, ndis_handle, 114123526Swpaul uint32_t, ndis_unicode_string *, ndis_handle *); 115123526Swpaul__stdcall static void ndis_open_cfgbyname(ndis_status *, ndis_handle, 116123526Swpaul ndis_unicode_string *, ndis_handle *); 117123474Swpaulstatic ndis_status ndis_encode_parm(ndis_miniport_block *, 118123474Swpaul struct sysctl_oid *, ndis_parm_type, ndis_config_parm **); 119123526Swpaulstatic ndis_status ndis_decode_parm(ndis_miniport_block *, 120123526Swpaul ndis_config_parm *, char *); 121123474Swpaul__stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **, 122123474Swpaul ndis_handle, ndis_unicode_string *, ndis_parm_type); 123123526Swpaul__stdcall static void ndis_write_cfg(ndis_status *, ndis_handle, 124123526Swpaul ndis_unicode_string *, ndis_config_parm *); 125123474Swpaul__stdcall static void ndis_close_cfg(ndis_handle); 126123474Swpaul__stdcall static void ndis_create_lock(ndis_spin_lock *); 127123474Swpaul__stdcall static void ndis_destroy_lock(ndis_spin_lock *); 128123474Swpaul__stdcall static void ndis_lock(ndis_spin_lock *); 129123474Swpaul__stdcall static void ndis_unlock(ndis_spin_lock *); 130123474Swpaul__stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t, 131123474Swpaul uint32_t, void *, uint32_t); 132123474Swpaul__stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t, 133123474Swpaul uint32_t, void *, uint32_t); 134123474Swpaulstatic void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...); 135123474Swpaulstatic void ndis_map_cb(void *, bus_dma_segment_t *, int, int); 136123474Swpaul__stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *, 137123474Swpaul uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *); 138123474Swpaul__stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t); 139123474Swpaul__stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle *, 140123474Swpaul ndis_timer_function, void *); 141123474Swpaulstatic void ndis_timercall(void *); 142123474Swpaul__stdcall static void ndis_set_timer(ndis_miniport_timer *, uint32_t); 143123474Swpaulstatic void ndis_tick(void *); 144123474Swpaul__stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t); 145123474Swpaul__stdcall static void ndis_cancel_timer(ndis_miniport_timer *, uint8_t *); 146123474Swpaul__stdcall static void ndis_query_resources(ndis_status *, ndis_handle, 147123474Swpaul ndis_resource_list *, uint32_t *); 148123474Swpaul__stdcall static ndis_status ndis_register_ioport(void **, 149123474Swpaul ndis_handle, uint32_t, uint32_t); 150123474Swpaul__stdcall static void ndis_deregister_ioport(ndis_handle, 151123474Swpaul uint32_t, uint32_t, void *); 152123474Swpaul__stdcall static void ndis_read_netaddr(ndis_status *, void **, 153123474Swpaul uint32_t *, ndis_handle); 154123848Swpaul__stdcall static ndis_status ndis_mapreg_cnt(uint32_t, uint32_t *); 155123474Swpaul__stdcall static ndis_status ndis_alloc_mapreg(ndis_handle, 156123474Swpaul uint32_t, uint8_t, uint32_t, uint32_t); 157123474Swpaul__stdcall static void ndis_free_mapreg(ndis_handle); 158123474Swpaulstatic void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int); 159123474Swpaul__stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t, 160123474Swpaul uint8_t, void **, ndis_physaddr *); 161123474Swpaul__stdcall static void ndis_alloc_sharedmem_async(ndis_handle, 162123474Swpaul uint32_t, uint8_t, void *); 163123474Swpaul__stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t, 164123474Swpaul uint8_t, void *, ndis_physaddr); 165123474Swpaul__stdcall static ndis_status ndis_map_iospace(void **, ndis_handle, 166123474Swpaul ndis_physaddr, uint32_t); 167123474Swpaul__stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t); 168123474Swpaul__stdcall static uint32_t ndis_cachefill(void); 169123474Swpaul__stdcall static uint32_t ndis_dma_align(ndis_handle); 170123474Swpaul__stdcall static ndis_status ndis_init_sc_dma(ndis_handle, 171123474Swpaul uint8_t, uint32_t); 172123474Swpaul__stdcall static void ndis_alloc_packetpool(ndis_status *, 173123474Swpaul ndis_handle *, uint32_t, uint32_t); 174123474Swpaul__stdcall static void ndis_ex_alloc_packetpool(ndis_status *, 175123474Swpaul ndis_handle *, uint32_t, uint32_t, uint32_t); 176123474Swpaul__stdcall static uint32_t ndis_packetpool_use(ndis_handle); 177123474Swpaul__stdcall static void ndis_free_packetpool(ndis_handle); 178123474Swpaul__stdcall static void ndis_alloc_packet(ndis_status *, 179123474Swpaul ndis_packet **, ndis_handle); 180123474Swpaul__stdcall static void ndis_release_packet(ndis_packet *); 181123474Swpaul__stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **); 182123721Swpaul__stdcall static void ndis_unchain_tailbuf(ndis_packet *, ndis_buffer **); 183123474Swpaul__stdcall static void ndis_alloc_bufpool(ndis_status *, 184123474Swpaul ndis_handle *, uint32_t); 185123474Swpaul__stdcall static void ndis_free_bufpool(ndis_handle); 186123474Swpaul__stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **, 187123474Swpaul ndis_handle, void *, uint32_t); 188123474Swpaul__stdcall static void ndis_release_buf(ndis_buffer *); 189123474Swpaul__stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *); 190123474Swpaul__stdcall static void ndis_query_buf_safe(ndis_buffer *, void **, 191123474Swpaul uint32_t *, uint32_t); 192123474Swpaul__stdcall static void ndis_adjust_buflen(ndis_buffer *, int); 193123474Swpaul__stdcall static uint32_t ndis_interlock_inc(uint32_t *); 194123474Swpaul__stdcall static uint32_t ndis_interlock_dec(uint32_t *); 195123474Swpaul__stdcall static void ndis_init_event(ndis_event *); 196123474Swpaul__stdcall static void ndis_set_event(ndis_event *); 197123474Swpaul__stdcall static void ndis_reset_event(ndis_event *); 198123474Swpaul__stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t); 199123474Swpaul__stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *, 200123474Swpaul ndis_unicode_string *); 201123526Swpaul__stdcall static ndis_status ndis_ansi2unicode(ndis_unicode_string *, 202123526Swpaul ndis_ansi_string *); 203123474Swpaul__stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle, 204123474Swpaul uint32_t, ndis_resource_list **); 205123474Swpaul__stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *, 206123474Swpaul ndis_handle, uint32_t, uint32_t, uint8_t, 207123474Swpaul uint8_t, ndis_interrupt_mode); 208123474Swpaul__stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *); 209123474Swpaul__stdcall static void ndis_register_shutdown(ndis_handle, void *, 210123474Swpaul ndis_shutdown_handler); 211123474Swpaul__stdcall static void ndis_deregister_shutdown(ndis_handle); 212123474Swpaul__stdcall static uint32_t ndis_numpages(ndis_buffer *); 213123573Swpaul__stdcall static void ndis_buf_physpages(ndis_buffer *, uint32_t *); 214123474Swpaul__stdcall static void ndis_query_bufoffset(ndis_buffer *, 215123474Swpaul uint32_t *, uint32_t *); 216123474Swpaul__stdcall static void ndis_sleep(uint32_t); 217123474Swpaul__stdcall static uint32_t ndis_read_pccard_amem(ndis_handle, 218123474Swpaul uint32_t, void *, uint32_t); 219123474Swpaul__stdcall static uint32_t ndis_write_pccard_amem(ndis_handle, 220123474Swpaul uint32_t, void *, uint32_t); 221123474Swpaul__stdcall static ndis_list_entry *ndis_insert_head(ndis_list_entry *, 222123474Swpaul ndis_list_entry *, ndis_spin_lock *); 223123474Swpaul__stdcall static ndis_list_entry *ndis_remove_head(ndis_list_entry *, 224123474Swpaul ndis_spin_lock *); 225123474Swpaul__stdcall static ndis_list_entry *ndis_insert_tail(ndis_list_entry *, 226123474Swpaul ndis_list_entry *, ndis_spin_lock *); 227123474Swpaul__stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *, 228123474Swpaul void *, void *); 229123504Swpaul__stdcall static void ndis_time(uint64_t *); 230123822Swpaul__stdcall static void ndis_uptime(uint32_t *); 231123507Swpaul__stdcall static void ndis_init_string(ndis_unicode_string **, char *); 232123526Swpaul__stdcall static void ndis_init_ansi_string(ndis_ansi_string *, char *); 233123941Swpaul__stdcall static void ndis_init_unicode_string(ndis_unicode_string *, 234123941Swpaul uint16_t *); 235123507Swpaul__stdcall static void ndis_free_string(ndis_unicode_string *); 236123507Swpaul__stdcall static ndis_status ndis_remove_miniport(ndis_handle *); 237123526Swpaul__stdcall static void ndis_termwrap(ndis_handle, void *); 238123526Swpaul__stdcall static void ndis_get_devprop(ndis_handle, void *, void *, 239123526Swpaul void *, cm_resource_list *, cm_resource_list *); 240123721Swpaul__stdcall static void ndis_firstbuf(ndis_packet *, ndis_buffer **, 241123721Swpaul void **, uint32_t *, uint32_t *); 242123721Swpaul__stdcall static void ndis_firstbuf_safe(ndis_packet *, ndis_buffer **, 243123721Swpaul void **, uint32_t *, uint32_t *, uint32_t); 244123822Swpaul__stdcall static void ndis_open_file(ndis_status *, ndis_handle *, uint32_t *, 245123822Swpaul ndis_unicode_string *, ndis_physaddr); 246123822Swpaul__stdcall static void ndis_map_file(ndis_status *, void **, ndis_handle); 247123822Swpaul__stdcall static void ndis_unmap_file(ndis_handle); 248123822Swpaul__stdcall static void ndis_close_file(ndis_handle); 249123848Swpaul__stdcall static u_int8_t ndis_cpu_cnt(void); 250123474Swpaul__stdcall static void dummy(void); 251123474Swpaul 252123474Swpaul 253123474Swpaulint 254123474Swpaulndis_libinit() 255123474Swpaul{ 256123474Swpaul if (ndis_inits) { 257123474Swpaul ndis_inits++; 258123474Swpaul return(0); 259123474Swpaul } 260123474Swpaul 261123474Swpaul mtx_init(&ndis_interlock, "ndislock", MTX_NETWORK_LOCK, 262123474Swpaul MTX_DEF | MTX_RECURSE | MTX_DUPOK); 263123474Swpaul 264123474Swpaul ndis_inits++; 265123474Swpaul return(0); 266123474Swpaul} 267123474Swpaul 268123474Swpaulint 269123474Swpaulndis_libfini() 270123474Swpaul{ 271123474Swpaul if (ndis_inits != 1) { 272123474Swpaul ndis_inits--; 273123474Swpaul return(0); 274123474Swpaul } 275123474Swpaul 276123474Swpaul mtx_destroy(&ndis_interlock); 277123474Swpaul ndis_inits--; 278123474Swpaul 279123474Swpaul return(0); 280123474Swpaul} 281123474Swpaul 282123474Swpaul/* 283123474Swpaul * NDIS deals with strings in unicode format, so we have 284123474Swpaul * do deal with them that way too. For now, we only handle 285123474Swpaul * conversion between unicode and ASCII since that's all 286123474Swpaul * that device drivers care about. 287123474Swpaul */ 288123474Swpaul 289123474Swpaulint 290123474Swpaulndis_ascii_to_unicode(ascii, unicode) 291123474Swpaul char *ascii; 292123474Swpaul uint16_t **unicode; 293123474Swpaul{ 294123474Swpaul uint16_t *ustr; 295123474Swpaul int i; 296123474Swpaul 297123474Swpaul if (*unicode == NULL) 298123474Swpaul *unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK); 299123474Swpaul 300123474Swpaul if (*unicode == NULL) 301123474Swpaul return(ENOMEM); 302123474Swpaul ustr = *unicode; 303123474Swpaul for (i = 0; i < strlen(ascii); i++) { 304123474Swpaul *ustr = (uint16_t)ascii[i]; 305123474Swpaul ustr++; 306123474Swpaul } 307123474Swpaul 308123474Swpaul return(0); 309123474Swpaul} 310123474Swpaul 311123474Swpaulint 312123474Swpaulndis_unicode_to_ascii(unicode, ulen, ascii) 313123474Swpaul uint16_t *unicode; 314123474Swpaul int ulen; 315123474Swpaul char **ascii; 316123474Swpaul{ 317123474Swpaul uint8_t *astr; 318123474Swpaul int i; 319123474Swpaul 320123474Swpaul if (*ascii == NULL) 321123474Swpaul *ascii = malloc(ulen, M_DEVBUF, M_WAITOK); 322123474Swpaul 323123474Swpaul if (*ascii == NULL) 324123474Swpaul return(ENOMEM); 325123474Swpaul astr = *ascii; 326123474Swpaul for (i = 0; i < ulen; i++) { 327123474Swpaul *astr = (uint8_t)unicode[i]; 328123474Swpaul astr++; 329123474Swpaul } 330123474Swpaul 331123474Swpaul return(0); 332123474Swpaul} 333123474Swpaul 334123474Swpaul__stdcall static void 335123474Swpaulndis_initwrap(wrapper, drv_obj, path, unused) 336123474Swpaul ndis_handle wrapper; 337123474Swpaul ndis_driver_object *drv_obj; 338123474Swpaul void *path; 339123474Swpaul void *unused; 340123474Swpaul{ 341123474Swpaul ndis_driver_object **drv; 342123474Swpaul 343123474Swpaul drv = wrapper; 344123474Swpaul *drv = drv_obj; 345123474Swpaul 346123474Swpaul return; 347123474Swpaul} 348123474Swpaul 349123526Swpaul__stdcall static void 350123526Swpaulndis_termwrap(handle, syspec) 351123526Swpaul ndis_handle handle; 352123526Swpaul void *syspec; 353123526Swpaul{ 354123526Swpaul return; 355123526Swpaul} 356123526Swpaul 357123474Swpaul__stdcall static ndis_status 358123474Swpaulndis_register_miniport(handle, characteristics, len) 359123474Swpaul ndis_handle handle; 360123474Swpaul ndis_miniport_characteristics *characteristics; 361123474Swpaul int len; 362123474Swpaul{ 363123474Swpaul ndis_driver_object *drv; 364123474Swpaul 365123474Swpaul drv = handle; 366123474Swpaul bcopy((char *)characteristics, (char *)&drv->ndo_chars, 367123474Swpaul sizeof(ndis_miniport_characteristics)); 368123474Swpaul return(NDIS_STATUS_SUCCESS); 369123474Swpaul} 370123474Swpaul 371123474Swpaul__stdcall static ndis_status 372123474Swpaulndis_malloc_withtag(vaddr, len, tag) 373123474Swpaul void **vaddr; 374123474Swpaul uint32_t len; 375123474Swpaul uint32_t tag; 376123474Swpaul{ 377123474Swpaul void *mem; 378123474Swpaul 379123474Swpaul mem = malloc(len, M_DEVBUF, M_NOWAIT); 380123474Swpaul if (mem == NULL) 381123474Swpaul return(NDIS_STATUS_RESOURCES); 382123474Swpaul *vaddr = mem; 383123474Swpaul 384123474Swpaul return(NDIS_STATUS_SUCCESS); 385123474Swpaul} 386123474Swpaul 387123474Swpaul__stdcall static ndis_status 388123474Swpaulndis_malloc(vaddr, len, flags, highaddr) 389123474Swpaul void **vaddr; 390123474Swpaul uint32_t len; 391123474Swpaul uint32_t flags; 392123474Swpaul ndis_physaddr highaddr; 393123474Swpaul{ 394123474Swpaul void *mem; 395123474Swpaul 396123474Swpaul mem = malloc(len, M_DEVBUF, M_NOWAIT); 397123474Swpaul if (mem == NULL) 398123474Swpaul return(NDIS_STATUS_RESOURCES); 399123474Swpaul *vaddr = mem; 400123474Swpaul 401123474Swpaul return(NDIS_STATUS_SUCCESS); 402123474Swpaul} 403123474Swpaul 404123474Swpaul__stdcall static void 405123474Swpaulndis_free(vaddr, len, flags) 406123474Swpaul void *vaddr; 407123474Swpaul uint32_t len; 408123474Swpaul uint32_t flags; 409123474Swpaul{ 410123474Swpaul if (len == 0) 411123474Swpaul return; 412123474Swpaul free(vaddr, M_DEVBUF); 413123474Swpaul return; 414123474Swpaul} 415123474Swpaul 416123474Swpaul__stdcall static ndis_status 417123474Swpaulndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs, 418123474Swpaul flags, iftype) 419123474Swpaul ndis_handle adapter_handle; 420123474Swpaul ndis_handle adapter_ctx; 421123474Swpaul uint32_t hangsecs; 422123474Swpaul uint32_t flags; 423123474Swpaul ndis_interface_type iftype; 424123474Swpaul{ 425123474Swpaul ndis_miniport_block *block; 426123474Swpaul 427123474Swpaul /* 428123474Swpaul * Save the adapter context, we need it for calling 429123474Swpaul * the driver's internal functions. 430123474Swpaul */ 431123474Swpaul block = (ndis_miniport_block *)adapter_handle; 432123474Swpaul block->nmb_miniportadapterctx = adapter_ctx; 433123474Swpaul block->nmb_checkforhangsecs = hangsecs; 434123474Swpaul 435123474Swpaul return(NDIS_STATUS_SUCCESS); 436123474Swpaul} 437123474Swpaul 438123474Swpaul__stdcall static void 439123474Swpaulndis_open_cfg(status, cfg, wrapctx) 440123474Swpaul ndis_status *status; 441123474Swpaul ndis_handle *cfg; 442123474Swpaul ndis_handle wrapctx; 443123474Swpaul{ 444123474Swpaul *cfg = wrapctx; 445123474Swpaul *status = NDIS_STATUS_SUCCESS; 446123474Swpaul return; 447123474Swpaul} 448123474Swpaul 449123526Swpaul__stdcall static void 450123526Swpaulndis_open_cfgbyname(status, cfg, subkey, subhandle) 451123526Swpaul ndis_status *status; 452123526Swpaul ndis_handle cfg; 453123526Swpaul ndis_unicode_string *subkey; 454123526Swpaul ndis_handle *subhandle; 455123526Swpaul{ 456123526Swpaul *subhandle = cfg; 457123526Swpaul *status = NDIS_STATUS_SUCCESS; 458123526Swpaul return; 459123526Swpaul} 460123526Swpaul 461123526Swpaul__stdcall static void 462123526Swpaulndis_open_cfgbyidx(status, cfg, idx, subkey, subhandle) 463123526Swpaul ndis_status *status; 464123526Swpaul ndis_handle cfg; 465123526Swpaul uint32_t idx; 466123526Swpaul ndis_unicode_string *subkey; 467123526Swpaul ndis_handle *subhandle; 468123526Swpaul{ 469123526Swpaul *status = NDIS_STATUS_FAILURE; 470123526Swpaul return; 471123526Swpaul} 472123526Swpaul 473123474Swpaulstatic ndis_status 474123474Swpaulndis_encode_parm(block, oid, type, parm) 475123474Swpaul ndis_miniport_block *block; 476123474Swpaul struct sysctl_oid *oid; 477123474Swpaul ndis_parm_type type; 478123474Swpaul ndis_config_parm **parm; 479123474Swpaul{ 480123474Swpaul uint16_t *unicode; 481123474Swpaul ndis_unicode_string *ustr; 482123474Swpaul 483123474Swpaul unicode = (uint16_t *)&block->nmb_dummybuf; 484123474Swpaul 485123474Swpaul switch(type) { 486123474Swpaul case ndis_parm_string: 487123474Swpaul ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode); 488123474Swpaul (*parm)->ncp_type = ndis_parm_string; 489123474Swpaul ustr = &(*parm)->ncp_parmdata.ncp_stringdata; 490123474Swpaul ustr->nus_len = strlen((char *)oid->oid_arg1) * 2; 491123474Swpaul ustr->nus_buf = unicode; 492123474Swpaul break; 493123474Swpaul case ndis_parm_int: 494123474Swpaul (*parm)->ncp_type = ndis_parm_int; 495123474Swpaul (*parm)->ncp_parmdata.ncp_intdata = 496123474Swpaul strtol((char *)oid->oid_arg1, NULL, 10); 497123474Swpaul break; 498123474Swpaul case ndis_parm_hexint: 499123474Swpaul (*parm)->ncp_type = ndis_parm_hexint; 500123474Swpaul (*parm)->ncp_parmdata.ncp_intdata = 501123474Swpaul strtoul((char *)oid->oid_arg1, NULL, 16); 502123474Swpaul break; 503123474Swpaul default: 504123474Swpaul return(NDIS_STATUS_FAILURE); 505123474Swpaul break; 506123474Swpaul } 507123474Swpaul 508123474Swpaul return(NDIS_STATUS_SUCCESS); 509123474Swpaul} 510123474Swpaul 511123474Swpaul__stdcall static void 512123474Swpaulndis_read_cfg(status, parm, cfg, key, type) 513123474Swpaul ndis_status *status; 514123474Swpaul ndis_config_parm **parm; 515123474Swpaul ndis_handle cfg; 516123474Swpaul ndis_unicode_string *key; 517123474Swpaul ndis_parm_type type; 518123474Swpaul{ 519123474Swpaul char *keystr = NULL; 520123474Swpaul uint16_t *unicode; 521123474Swpaul ndis_miniport_block *block; 522123474Swpaul struct ndis_softc *sc; 523123474Swpaul struct sysctl_oid *oidp; 524123474Swpaul struct sysctl_ctx_entry *e; 525123474Swpaul 526123474Swpaul block = (ndis_miniport_block *)cfg; 527123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 528123474Swpaul 529123474Swpaul ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr); 530123474Swpaul 531123474Swpaul *parm = &block->nmb_replyparm; 532123474Swpaul bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm)); 533123474Swpaul unicode = (uint16_t *)&block->nmb_dummybuf; 534123474Swpaul 535123474Swpaul /* 536123474Swpaul * See if registry key is already in a list of known keys 537123474Swpaul * included with the driver. 538123474Swpaul */ 539123474Swpaul TAILQ_FOREACH(e, &sc->ndis_ctx, link) { 540123474Swpaul oidp = e->entry; 541123474Swpaul if (strcmp(oidp->oid_name, keystr) == 0) { 542123488Swpaul if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) { 543123488Swpaul free(keystr, M_DEVBUF); 544123488Swpaul *status = NDIS_STATUS_FAILURE; 545123488Swpaul return; 546123488Swpaul } 547123474Swpaul *status = ndis_encode_parm(block, oidp, type, parm); 548123474Swpaul free(keystr, M_DEVBUF); 549123474Swpaul return; 550123474Swpaul } 551123474Swpaul } 552123474Swpaul 553123474Swpaul /* 554123474Swpaul * If the key didn't match, add it to the list of dynamically 555123474Swpaul * created ones. Sometimes, drivers refer to registry keys 556123474Swpaul * that aren't documented in their .INF files. These keys 557123474Swpaul * are supposed to be created by some sort of utility or 558123474Swpaul * control panel snap-in that comes with the driver software. 559123474Swpaul * Sometimes it's useful to be able to manipulate these. 560123474Swpaul * If the driver requests the key in the form of a string, 561123474Swpaul * make its default value an empty string, otherwise default 562123474Swpaul * it to "0". 563123474Swpaul */ 564123474Swpaul 565123474Swpaul if (type == ndis_parm_int || type == ndis_parm_hexint) 566123488Swpaul ndis_add_sysctl(sc, keystr, "(dynamic integer key)", 567123488Swpaul "UNSET", CTLFLAG_RW); 568123474Swpaul else 569123488Swpaul ndis_add_sysctl(sc, keystr, "(dynamic string key)", 570123488Swpaul "UNSET", CTLFLAG_RW); 571123474Swpaul 572123474Swpaul free(keystr, M_DEVBUF); 573123474Swpaul *status = NDIS_STATUS_FAILURE; 574123474Swpaul return; 575123474Swpaul} 576123474Swpaul 577123526Swpaulstatic ndis_status 578123526Swpaulndis_decode_parm(block, parm, val) 579123526Swpaul ndis_miniport_block *block; 580123526Swpaul ndis_config_parm *parm; 581123526Swpaul char *val; 582123526Swpaul{ 583123526Swpaul uint16_t *unicode; 584123526Swpaul ndis_unicode_string *ustr; 585123526Swpaul 586123526Swpaul unicode = (uint16_t *)&block->nmb_dummybuf; 587123526Swpaul 588123526Swpaul switch(parm->ncp_type) { 589123526Swpaul case ndis_parm_string: 590123526Swpaul ustr = &parm->ncp_parmdata.ncp_stringdata; 591123526Swpaul ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &val); 592123526Swpaul break; 593123526Swpaul case ndis_parm_int: 594123526Swpaul sprintf(val, "%ul", parm->ncp_parmdata.ncp_intdata); 595123526Swpaul break; 596123526Swpaul case ndis_parm_hexint: 597123526Swpaul sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata); 598123526Swpaul break; 599123526Swpaul default: 600123526Swpaul return(NDIS_STATUS_FAILURE); 601123526Swpaul break; 602123526Swpaul } 603123526Swpaul return(NDIS_STATUS_SUCCESS); 604123526Swpaul} 605123526Swpaul 606123474Swpaul__stdcall static void 607123526Swpaulndis_write_cfg(status, cfg, key, parm) 608123526Swpaul ndis_status *status; 609123526Swpaul ndis_handle cfg; 610123526Swpaul ndis_unicode_string *key; 611123526Swpaul ndis_config_parm *parm; 612123526Swpaul{ 613123526Swpaul char *keystr = NULL; 614123526Swpaul ndis_miniport_block *block; 615123526Swpaul struct ndis_softc *sc; 616123526Swpaul struct sysctl_oid *oidp; 617123526Swpaul struct sysctl_ctx_entry *e; 618123526Swpaul char val[256]; 619123526Swpaul 620123526Swpaul block = (ndis_miniport_block *)cfg; 621123526Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 622123526Swpaul 623123526Swpaul ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr); 624123526Swpaul 625123526Swpaul /* Decode the parameter into a string. */ 626123526Swpaul *status = ndis_decode_parm(block, parm, val); 627123526Swpaul if (*status != NDIS_STATUS_SUCCESS) { 628123526Swpaul free(keystr, M_DEVBUF); 629123526Swpaul return; 630123526Swpaul } 631123526Swpaul 632123526Swpaul /* See if the key already exists. */ 633123526Swpaul 634123526Swpaul TAILQ_FOREACH(e, &sc->ndis_ctx, link) { 635123526Swpaul oidp = e->entry; 636123526Swpaul if (strcmp(oidp->oid_name, keystr) == 0) { 637123526Swpaul /* Found it, set the value. */ 638123526Swpaul strcpy((char *)oidp->oid_arg1, val); 639123526Swpaul free(keystr, M_DEVBUF); 640123526Swpaul return; 641123526Swpaul } 642123526Swpaul } 643123526Swpaul 644123526Swpaul /* Not found, add a new key with the specified value. */ 645123526Swpaul ndis_add_sysctl(sc, keystr, "(dynamically set key)", 646123526Swpaul val, CTLFLAG_RW); 647123526Swpaul 648123526Swpaul free(keystr, M_DEVBUF); 649123526Swpaul *status = NDIS_STATUS_SUCCESS; 650123526Swpaul return; 651123526Swpaul} 652123526Swpaul 653123526Swpaul__stdcall static void 654123474Swpaulndis_close_cfg(cfg) 655123474Swpaul ndis_handle cfg; 656123474Swpaul{ 657123474Swpaul return; 658123474Swpaul} 659123474Swpaul 660123474Swpaul__stdcall static void 661123474Swpaulndis_create_lock(lock) 662123474Swpaul ndis_spin_lock *lock; 663123474Swpaul{ 664123474Swpaul struct mtx *mtx; 665123474Swpaul 666123474Swpaul mtx = malloc(sizeof(struct mtx), M_DEVBUF, M_NOWAIT|M_ZERO); 667123474Swpaul if (mtx == NULL) 668123474Swpaul return; 669123695Swpaul mtx_init(mtx, "ndislock", "ndis spin lock", 670123474Swpaul MTX_DEF | MTX_RECURSE | MTX_DUPOK); 671123474Swpaul lock->nsl_spinlock = (ndis_kspin_lock)mtx; 672123474Swpaul 673123474Swpaul return; 674123474Swpaul} 675123474Swpaul 676123474Swpaul__stdcall static void 677123474Swpaulndis_destroy_lock(lock) 678123474Swpaul ndis_spin_lock *lock; 679123474Swpaul{ 680123474Swpaul struct mtx *ndis_mtx; 681123474Swpaul 682123474Swpaul ndis_mtx = (struct mtx *)lock->nsl_spinlock; 683123474Swpaul mtx_destroy(ndis_mtx); 684123474Swpaul free(ndis_mtx, M_DEVBUF); 685123474Swpaul 686123474Swpaul return; 687123474Swpaul} 688123474Swpaul 689123474Swpaul__stdcall static void 690123474Swpaulndis_lock(lock) 691123474Swpaul ndis_spin_lock *lock; 692123474Swpaul{ 693123474Swpaul if (lock == NULL) 694123474Swpaul return; 695123474Swpaul mtx_lock((struct mtx *)lock->nsl_spinlock); 696123474Swpaul 697123474Swpaul return; 698123474Swpaul} 699123474Swpaul 700123474Swpaul__stdcall static void 701123474Swpaulndis_unlock(lock) 702123474Swpaul ndis_spin_lock *lock; 703123474Swpaul{ 704123474Swpaul if (lock == NULL) 705123474Swpaul return; 706123474Swpaul mtx_unlock((struct mtx *)lock->nsl_spinlock); 707123474Swpaul 708123474Swpaul return; 709123474Swpaul} 710123474Swpaul 711123474Swpaul__stdcall static uint32_t 712123474Swpaulndis_read_pci(adapter, slot, offset, buf, len) 713123474Swpaul ndis_handle adapter; 714123474Swpaul uint32_t slot; 715123474Swpaul uint32_t offset; 716123474Swpaul void *buf; 717123474Swpaul uint32_t len; 718123474Swpaul{ 719123474Swpaul ndis_miniport_block *block; 720123474Swpaul int i; 721123474Swpaul char *dest; 722123474Swpaul 723123474Swpaul block = (ndis_miniport_block *)adapter; 724123474Swpaul dest = buf; 725123474Swpaul if (block == NULL || block->nmb_dev == NULL) 726123474Swpaul return(0); 727123474Swpaul 728123474Swpaul for (i = 0; i < len; i++) 729123474Swpaul dest[i] = pci_read_config(block->nmb_dev, i + offset, 1); 730123474Swpaul 731123474Swpaul return(len); 732123474Swpaul} 733123474Swpaul 734123474Swpaul__stdcall static uint32_t 735123474Swpaulndis_write_pci(adapter, slot, offset, buf, len) 736123474Swpaul ndis_handle adapter; 737123474Swpaul uint32_t slot; 738123474Swpaul uint32_t offset; 739123474Swpaul void *buf; 740123474Swpaul uint32_t len; 741123474Swpaul{ 742123474Swpaul ndis_miniport_block *block; 743123474Swpaul int i; 744123474Swpaul char *dest; 745123474Swpaul 746123474Swpaul block = (ndis_miniport_block *)adapter; 747123474Swpaul dest = buf; 748123474Swpaul 749123474Swpaul if (block == NULL || block->nmb_dev == NULL) 750123474Swpaul return(0); 751123474Swpaul 752123474Swpaul for (i = 0; i < len; i++) 753123474Swpaul pci_write_config(block->nmb_dev, i + offset, dest[i], 1); 754123474Swpaul 755123474Swpaul return(len); 756123474Swpaul} 757123474Swpaul 758123474Swpaul/* 759123474Swpaul * The errorlog routine uses a variable argument list, so we 760123474Swpaul * have to declare it this way. 761123474Swpaul */ 762123474Swpaulstatic void 763123474Swpaulndis_syslog(ndis_handle adapter, ndis_error_code code, 764123474Swpaul uint32_t numerrors, ...) 765123474Swpaul{ 766123474Swpaul ndis_miniport_block *block; 767123474Swpaul va_list ap; 768123474Swpaul int i; 769123474Swpaul 770123474Swpaul block = (ndis_miniport_block *)adapter; 771123474Swpaul 772124060Swpaul device_printf (block->nmb_dev, "NDIS ERROR: %x\n", code); 773124060Swpaul device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors); 774123474Swpaul 775123474Swpaul va_start(ap, numerrors); 776123474Swpaul for (i = 0; i < numerrors; i++) 777124060Swpaul device_printf (block->nmb_dev, "argptr: %p\n", 778124060Swpaul va_arg(ap, void *)); 779123474Swpaul va_end(ap); 780123474Swpaul 781123474Swpaul return; 782123474Swpaul} 783123474Swpaul 784123474Swpaulstatic void 785123474Swpaulndis_map_cb(arg, segs, nseg, error) 786123474Swpaul void *arg; 787123474Swpaul bus_dma_segment_t *segs; 788123474Swpaul int nseg; 789123474Swpaul int error; 790123474Swpaul{ 791123474Swpaul struct ndis_map_arg *ctx; 792123474Swpaul int i; 793123474Swpaul 794123474Swpaul if (error) 795123474Swpaul return; 796123474Swpaul 797123474Swpaul ctx = arg; 798123474Swpaul 799123474Swpaul for (i = 0; i < nseg; i++) { 800123474Swpaul ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr; 801123474Swpaul ctx->nma_fraglist[i].npu_len = segs[i].ds_len; 802123474Swpaul } 803123474Swpaul 804123474Swpaul ctx->nma_cnt = nseg; 805123474Swpaul 806123474Swpaul return; 807123474Swpaul} 808123474Swpaul 809123474Swpaul__stdcall static void 810123474Swpaulndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize) 811123474Swpaul ndis_handle adapter; 812123474Swpaul ndis_buffer *buf; 813123474Swpaul uint32_t mapreg; 814123474Swpaul uint8_t writedev; 815123474Swpaul ndis_paddr_unit *addrarray; 816123474Swpaul uint32_t *arraysize; 817123474Swpaul{ 818123474Swpaul ndis_miniport_block *block; 819123474Swpaul struct ndis_softc *sc; 820123474Swpaul struct ndis_map_arg nma; 821123474Swpaul bus_dmamap_t map; 822123474Swpaul int error; 823123474Swpaul 824123474Swpaul if (adapter == NULL) 825123474Swpaul return; 826123474Swpaul 827123474Swpaul block = (ndis_miniport_block *)adapter; 828123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 829123474Swpaul 830123474Swpaul if (mapreg > sc->ndis_mmapcnt) 831123474Swpaul return; 832123474Swpaul 833123474Swpaul map = sc->ndis_mmaps[mapreg]; 834123474Swpaul nma.nma_fraglist = addrarray; 835123474Swpaul 836123474Swpaul error = bus_dmamap_load(sc->ndis_mtag, map, 837123757Swpaul MDL_VA(buf), buf->nb_bytecount, ndis_map_cb, 838123474Swpaul (void *)&nma, BUS_DMA_NOWAIT); 839123474Swpaul 840123474Swpaul if (error) 841123474Swpaul return; 842123474Swpaul 843123474Swpaul bus_dmamap_sync(sc->ndis_mtag, map, 844123474Swpaul writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD); 845123474Swpaul 846123474Swpaul *arraysize = nma.nma_cnt; 847123474Swpaul 848123474Swpaul return; 849123474Swpaul} 850123474Swpaul 851123474Swpaul__stdcall static void 852123474Swpaulndis_vtophys_unload(adapter, buf, mapreg) 853123474Swpaul ndis_handle adapter; 854123474Swpaul ndis_buffer *buf; 855123474Swpaul uint32_t mapreg; 856123474Swpaul{ 857123474Swpaul ndis_miniport_block *block; 858123474Swpaul struct ndis_softc *sc; 859123474Swpaul bus_dmamap_t map; 860123474Swpaul 861123474Swpaul if (adapter == NULL) 862123474Swpaul return; 863123474Swpaul 864123474Swpaul block = (ndis_miniport_block *)adapter; 865123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 866123474Swpaul 867123474Swpaul if (mapreg > sc->ndis_mmapcnt) 868123474Swpaul return; 869123474Swpaul 870123474Swpaul map = sc->ndis_mmaps[mapreg]; 871123474Swpaul 872123474Swpaul bus_dmamap_sync(sc->ndis_mtag, map, 873123474Swpaul BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 874123474Swpaul 875123474Swpaul bus_dmamap_unload(sc->ndis_mtag, map); 876123474Swpaul 877123474Swpaul return; 878123474Swpaul} 879123474Swpaul 880123474Swpaul__stdcall static void 881123474Swpaulndis_create_timer(timer, handle, func, ctx) 882123474Swpaul ndis_miniport_timer *timer; 883123474Swpaul ndis_handle *handle; 884123474Swpaul ndis_timer_function func; 885123474Swpaul void *ctx; 886123474Swpaul{ 887123821Swpaul struct ndis_timer_entry *ne = NULL; 888123821Swpaul ndis_miniport_block *block; 889123821Swpaul block = (ndis_miniport_block *)handle; 890123474Swpaul 891123821Swpaul ne = malloc(sizeof(struct ndis_timer_entry), M_DEVBUF, M_NOWAIT); 892123832Swpaul callout_init(&ne->nte_ch, CALLOUT_MPSAFE); 893123821Swpaul TAILQ_INSERT_TAIL(&block->nmb_timerlist, ne, link); 894123821Swpaul ne->nte_timer = timer; 895123821Swpaul 896123821Swpaul timer->nmt_ktimer.nk_header.dh_sigstate = TRUE; 897123821Swpaul timer->nmt_dpc.nk_deferredctx = &ne->nte_ch; 898123474Swpaul timer->nmt_timerfunc = func; 899123474Swpaul timer->nmt_timerctx = ctx; 900123474Swpaul 901123474Swpaul return; 902123474Swpaul} 903123474Swpaul 904123474Swpaul/* 905123474Swpaul * The driver's timer callout is __stdcall function, so we need this 906123474Swpaul * intermediate step. 907123474Swpaul */ 908123474Swpaul 909123474Swpaulstatic void 910123474Swpaulndis_timercall(arg) 911123474Swpaul void *arg; 912123474Swpaul{ 913123474Swpaul ndis_miniport_timer *timer; 914123474Swpaul __stdcall ndis_timer_function timerfunc; 915123474Swpaul 916123474Swpaul timer = arg; 917123474Swpaul 918123821Swpaul timer->nmt_ktimer.nk_header.dh_sigstate = FALSE; 919123474Swpaul timerfunc = timer->nmt_timerfunc; 920123474Swpaul timerfunc(NULL, timer->nmt_timerctx, NULL, NULL); 921123474Swpaul 922123474Swpaul return; 923123474Swpaul} 924123474Swpaul 925123474Swpaul/* 926123474Swpaul * Windows specifies timeouts in milliseconds. We specify timeouts 927123474Swpaul * in hz. Trying to compute a tenth of a second based on hz is tricky. 928123474Swpaul * so we approximate. Note that we abuse the dpc portion of the 929123474Swpaul * miniport timer structure to hold the UNIX callout handle. 930123474Swpaul */ 931123474Swpaul__stdcall static void 932123474Swpaulndis_set_timer(timer, msecs) 933123474Swpaul ndis_miniport_timer *timer; 934123474Swpaul uint32_t msecs; 935123474Swpaul{ 936123832Swpaul struct callout *ch; 937123474Swpaul struct timeval tv; 938123474Swpaul 939123474Swpaul tv.tv_sec = 0; 940123474Swpaul tv.tv_usec = msecs * 1000; 941123474Swpaul 942123821Swpaul ch = timer->nmt_dpc.nk_deferredctx; 943123474Swpaul timer->nmt_dpc.nk_sysarg2 = ndis_timercall; 944123821Swpaul timer->nmt_ktimer.nk_header.dh_sigstate = TRUE; 945123832Swpaul callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer); 946123474Swpaul 947123474Swpaul return; 948123474Swpaul} 949123474Swpaul 950123474Swpaulstatic void 951123474Swpaulndis_tick(arg) 952123474Swpaul void *arg; 953123474Swpaul{ 954123474Swpaul ndis_miniport_timer *timer; 955123832Swpaul struct callout *ch; 956123474Swpaul __stdcall ndis_timer_function timerfunc; 957123474Swpaul struct timeval tv; 958123474Swpaul 959123474Swpaul timer = arg; 960123474Swpaul 961123821Swpaul timer->nmt_ktimer.nk_header.dh_sigstate = FALSE; 962123474Swpaul timerfunc = timer->nmt_timerfunc; 963123474Swpaul timerfunc(NULL, timer->nmt_timerctx, NULL, NULL); 964123474Swpaul 965123474Swpaul /* Automatically reload timer. */ 966123474Swpaul 967123474Swpaul tv.tv_sec = 0; 968123474Swpaul tv.tv_usec = timer->nmt_ktimer.nk_period * 1000; 969123821Swpaul ch = timer->nmt_dpc.nk_deferredctx; 970123821Swpaul timer->nmt_ktimer.nk_header.dh_sigstate = TRUE; 971123474Swpaul timer->nmt_dpc.nk_sysarg2 = ndis_tick; 972123832Swpaul callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer); 973123474Swpaul 974123474Swpaul return; 975123474Swpaul} 976123474Swpaul 977123474Swpaul__stdcall static void 978123474Swpaulndis_set_periodic_timer(timer, msecs) 979123474Swpaul ndis_miniport_timer *timer; 980123474Swpaul uint32_t msecs; 981123474Swpaul{ 982123832Swpaul struct callout *ch; 983123474Swpaul struct timeval tv; 984123474Swpaul 985123474Swpaul tv.tv_sec = 0; 986123474Swpaul tv.tv_usec = msecs * 1000; 987123474Swpaul 988123474Swpaul timer->nmt_ktimer.nk_period = msecs; 989123821Swpaul ch = timer->nmt_dpc.nk_deferredctx; 990123474Swpaul timer->nmt_dpc.nk_sysarg2 = ndis_tick; 991123821Swpaul timer->nmt_ktimer.nk_header.dh_sigstate = TRUE; 992123832Swpaul callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer); 993123474Swpaul 994123474Swpaul return; 995123474Swpaul} 996123474Swpaul 997123474Swpaul__stdcall static void 998123474Swpaulndis_cancel_timer(timer, cancelled) 999123474Swpaul ndis_miniport_timer *timer; 1000123474Swpaul uint8_t *cancelled; 1001123474Swpaul{ 1002123832Swpaul struct callout *ch; 1003123474Swpaul 1004124097Swpaul if (timer == NULL) 1005124097Swpaul return; 1006123821Swpaul ch = timer->nmt_dpc.nk_deferredctx; 1007124097Swpaul if (ch == NULL) 1008124097Swpaul return; 1009123832Swpaul callout_stop(ch); 1010123821Swpaul *cancelled = timer->nmt_ktimer.nk_header.dh_sigstate; 1011123474Swpaul 1012123474Swpaul return; 1013123474Swpaul} 1014123474Swpaul 1015123474Swpaul__stdcall static void 1016123474Swpaulndis_query_resources(status, adapter, list, buflen) 1017123474Swpaul ndis_status *status; 1018123474Swpaul ndis_handle adapter; 1019123474Swpaul ndis_resource_list *list; 1020123474Swpaul uint32_t *buflen; 1021123474Swpaul{ 1022123474Swpaul ndis_miniport_block *block; 1023123474Swpaul struct ndis_softc *sc; 1024124094Swpaul int rsclen; 1025123474Swpaul 1026123474Swpaul block = (ndis_miniport_block *)adapter; 1027123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1028124094Swpaul 1029124094Swpaul rsclen = sizeof(ndis_resource_list) + 1030123474Swpaul (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)); 1031124094Swpaul if (*buflen < rsclen) { 1032124094Swpaul *buflen = rsclen; 1033124094Swpaul *status = NDIS_STATUS_INVALID_LENGTH; 1034124094Swpaul return; 1035124094Swpaul } 1036123474Swpaul 1037123474Swpaul bcopy((char *)block->nmb_rlist, (char *)list, *buflen); 1038123474Swpaul *status = NDIS_STATUS_SUCCESS; 1039123474Swpaul return; 1040123474Swpaul} 1041123474Swpaul 1042123474Swpaul__stdcall static ndis_status 1043123474Swpaulndis_register_ioport(offset, adapter, port, numports) 1044123474Swpaul void **offset; 1045123474Swpaul ndis_handle adapter; 1046123474Swpaul uint32_t port; 1047123474Swpaul uint32_t numports; 1048123474Swpaul{ 1049123474Swpaul struct ndis_miniport_block *block; 1050123474Swpaul struct ndis_softc *sc; 1051123474Swpaul 1052123474Swpaul if (adapter == NULL) 1053123474Swpaul return(NDIS_STATUS_FAILURE); 1054123474Swpaul 1055123474Swpaul block = (ndis_miniport_block *)adapter; 1056123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 1057123474Swpaul 1058123474Swpaul if (sc->ndis_res_io == NULL) 1059123474Swpaul return(NDIS_STATUS_FAILURE); 1060123474Swpaul 1061123474Swpaul if (rman_get_size(sc->ndis_res_io) != numports) 1062123474Swpaul return(NDIS_STATUS_INVALID_LENGTH); 1063123474Swpaul 1064123474Swpaul *offset = (void *)rman_get_start(sc->ndis_res_io); 1065123474Swpaul 1066123474Swpaul return(NDIS_STATUS_SUCCESS); 1067123474Swpaul} 1068123474Swpaul 1069123474Swpaul__stdcall static void 1070123474Swpaulndis_deregister_ioport(adapter, port, numports, offset) 1071123474Swpaul ndis_handle adapter; 1072123474Swpaul uint32_t port; 1073123474Swpaul uint32_t numports; 1074123474Swpaul void *offset; 1075123474Swpaul{ 1076123474Swpaul return; 1077123474Swpaul} 1078123474Swpaul 1079123474Swpaul__stdcall static void 1080123474Swpaulndis_read_netaddr(status, addr, addrlen, adapter) 1081123474Swpaul ndis_status *status; 1082123474Swpaul void **addr; 1083123474Swpaul uint32_t *addrlen; 1084123474Swpaul ndis_handle adapter; 1085123474Swpaul{ 1086123474Swpaul struct ndis_softc *sc; 1087123474Swpaul ndis_miniport_block *block; 1088123474Swpaul uint8_t empty[] = { 0, 0, 0, 0, 0, 0 }; 1089123474Swpaul 1090123474Swpaul block = (ndis_miniport_block *)adapter; 1091123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1092123474Swpaul 1093123474Swpaul if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0) 1094123474Swpaul *status = NDIS_STATUS_FAILURE; 1095123474Swpaul else { 1096123474Swpaul *addr = sc->arpcom.ac_enaddr; 1097123474Swpaul *addrlen = ETHER_ADDR_LEN; 1098123474Swpaul *status = NDIS_STATUS_SUCCESS; 1099123474Swpaul } 1100123474Swpaul 1101123474Swpaul return; 1102123474Swpaul} 1103123474Swpaul 1104123474Swpaul__stdcall static ndis_status 1105123848Swpaulndis_mapreg_cnt(bustype, cnt) 1106123848Swpaul uint32_t bustype; 1107123848Swpaul uint32_t *cnt; 1108123848Swpaul{ 1109124097Swpaul *cnt = 8192; 1110123848Swpaul return(NDIS_STATUS_SUCCESS); 1111123848Swpaul} 1112123848Swpaul 1113123848Swpaul__stdcall static ndis_status 1114123474Swpaulndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap) 1115123474Swpaul ndis_handle adapter; 1116123474Swpaul uint32_t dmachannel; 1117123474Swpaul uint8_t dmasize; 1118123474Swpaul uint32_t physmapneeded; 1119123474Swpaul uint32_t maxmap; 1120123474Swpaul{ 1121123474Swpaul struct ndis_softc *sc; 1122123474Swpaul ndis_miniport_block *block; 1123123474Swpaul int error, i, nseg = NDIS_MAXSEG; 1124123474Swpaul 1125123474Swpaul block = (ndis_miniport_block *)adapter; 1126123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1127123474Swpaul 1128123474Swpaul sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded, 1129123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 1130123474Swpaul 1131123474Swpaul if (sc->ndis_mmaps == NULL) 1132123474Swpaul return(NDIS_STATUS_RESOURCES); 1133123474Swpaul 1134123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 1135123474Swpaul BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, 1136123474Swpaul NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW, 1137123474Swpaul NULL, NULL, &sc->ndis_mtag); 1138123474Swpaul 1139123474Swpaul if (error) { 1140123474Swpaul free(sc->ndis_mmaps, M_DEVBUF); 1141123474Swpaul return(NDIS_STATUS_RESOURCES); 1142123474Swpaul } 1143123474Swpaul 1144123474Swpaul for (i = 0; i < physmapneeded; i++) 1145123474Swpaul bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]); 1146123474Swpaul 1147123474Swpaul sc->ndis_mmapcnt = physmapneeded; 1148123474Swpaul 1149123474Swpaul return(NDIS_STATUS_SUCCESS); 1150123474Swpaul} 1151123474Swpaul 1152123474Swpaul__stdcall static void 1153123474Swpaulndis_free_mapreg(adapter) 1154123474Swpaul ndis_handle adapter; 1155123474Swpaul{ 1156123474Swpaul struct ndis_softc *sc; 1157123474Swpaul ndis_miniport_block *block; 1158123474Swpaul int i; 1159123474Swpaul 1160123474Swpaul block = (ndis_miniport_block *)adapter; 1161123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1162123474Swpaul 1163123474Swpaul for (i = 0; i < sc->ndis_mmapcnt; i++) 1164123474Swpaul bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]); 1165123474Swpaul 1166123474Swpaul free(sc->ndis_mmaps, M_DEVBUF); 1167123474Swpaul 1168123474Swpaul bus_dma_tag_destroy(sc->ndis_mtag); 1169123474Swpaul 1170123474Swpaul return; 1171123474Swpaul} 1172123474Swpaul 1173123474Swpaulstatic void 1174123474Swpaulndis_mapshared_cb(arg, segs, nseg, error) 1175123474Swpaul void *arg; 1176123474Swpaul bus_dma_segment_t *segs; 1177123474Swpaul int nseg; 1178123474Swpaul int error; 1179123474Swpaul{ 1180123474Swpaul ndis_physaddr *p; 1181123474Swpaul 1182123474Swpaul if (error || nseg > 1) 1183123474Swpaul return; 1184123474Swpaul 1185123474Swpaul p = arg; 1186123474Swpaul 1187123474Swpaul p->np_quad = segs[0].ds_addr; 1188123474Swpaul 1189123474Swpaul return; 1190123474Swpaul} 1191123474Swpaul 1192123474Swpaul/* 1193123474Swpaul * This maps to bus_dmamem_alloc(). 1194123474Swpaul */ 1195123474Swpaul__stdcall static void 1196123474Swpaulndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr) 1197123474Swpaul ndis_handle adapter; 1198123474Swpaul uint32_t len; 1199123474Swpaul uint8_t cached; 1200123474Swpaul void **vaddr; 1201123474Swpaul ndis_physaddr *paddr; 1202123474Swpaul{ 1203123474Swpaul ndis_miniport_block *block; 1204123474Swpaul struct ndis_softc *sc; 1205123474Swpaul struct ndis_shmem *sh; 1206123474Swpaul int error; 1207123474Swpaul 1208123474Swpaul if (adapter == NULL) 1209123474Swpaul return; 1210123474Swpaul 1211123474Swpaul block = (ndis_miniport_block *)adapter; 1212123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 1213123474Swpaul 1214123474Swpaul sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO); 1215123474Swpaul if (sh == NULL) 1216123474Swpaul return; 1217123474Swpaul 1218123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, 64, 1219123474Swpaul 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, 1220123474Swpaul NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL, 1221123474Swpaul &sh->ndis_stag); 1222123474Swpaul 1223123474Swpaul if (error) { 1224123474Swpaul free(sh, M_DEVBUF); 1225123474Swpaul return; 1226123474Swpaul } 1227123474Swpaul 1228123474Swpaul error = bus_dmamem_alloc(sh->ndis_stag, vaddr, 1229123474Swpaul BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap); 1230123474Swpaul 1231123474Swpaul if (error) { 1232123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1233123474Swpaul free(sh, M_DEVBUF); 1234123474Swpaul return; 1235123474Swpaul } 1236123474Swpaul 1237123474Swpaul error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr, 1238123474Swpaul len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT); 1239123474Swpaul 1240123474Swpaul if (error) { 1241123474Swpaul bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap); 1242123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1243123474Swpaul free(sh, M_DEVBUF); 1244123474Swpaul return; 1245123474Swpaul } 1246123474Swpaul 1247123474Swpaul sh->ndis_saddr = *vaddr; 1248123474Swpaul sh->ndis_next = sc->ndis_shlist; 1249123474Swpaul sc->ndis_shlist = sh; 1250123474Swpaul 1251123474Swpaul return; 1252123474Swpaul} 1253123474Swpaul 1254123474Swpaul__stdcall static void 1255123474Swpaulndis_alloc_sharedmem_async(adapter, len, cached, ctx) 1256123474Swpaul ndis_handle adapter; 1257123474Swpaul uint32_t len; 1258123474Swpaul uint8_t cached; 1259123474Swpaul void *ctx; 1260123474Swpaul{ 1261123474Swpaul ndis_miniport_block *block; 1262123474Swpaul struct ndis_softc *sc; 1263123474Swpaul void *vaddr; 1264123474Swpaul ndis_physaddr paddr; 1265123474Swpaul __stdcall ndis_allocdone_handler donefunc; 1266123474Swpaul 1267123474Swpaul if (adapter == NULL) 1268123474Swpaul return; 1269123474Swpaul 1270123474Swpaul block = (ndis_miniport_block *)adapter; 1271123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 1272123474Swpaul donefunc = sc->ndis_chars.nmc_allocate_complete_func; 1273123474Swpaul 1274123474Swpaul ndis_alloc_sharedmem(adapter, len, cached, &vaddr, &paddr); 1275123474Swpaul donefunc(adapter, vaddr, &paddr, len, ctx); 1276123474Swpaul 1277123474Swpaul return; 1278123474Swpaul} 1279123474Swpaul 1280123474Swpaul__stdcall static void 1281123474Swpaulndis_free_sharedmem(adapter, len, cached, vaddr, paddr) 1282123474Swpaul ndis_handle adapter; 1283123474Swpaul uint32_t len; 1284123474Swpaul uint8_t cached; 1285123474Swpaul void *vaddr; 1286123474Swpaul ndis_physaddr paddr; 1287123474Swpaul{ 1288123474Swpaul ndis_miniport_block *block; 1289123474Swpaul struct ndis_softc *sc; 1290123474Swpaul struct ndis_shmem *sh, *prev; 1291123474Swpaul 1292123474Swpaul if (vaddr == NULL || adapter == NULL) 1293123474Swpaul return; 1294123474Swpaul 1295123474Swpaul block = (ndis_miniport_block *)adapter; 1296123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 1297123474Swpaul sh = prev = sc->ndis_shlist; 1298123474Swpaul 1299123474Swpaul while (sh) { 1300123474Swpaul if (sh->ndis_saddr == vaddr) 1301123474Swpaul break; 1302123474Swpaul prev = sh; 1303123474Swpaul sh = sh->ndis_next; 1304123474Swpaul } 1305123474Swpaul 1306123474Swpaul bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap); 1307123474Swpaul bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap); 1308123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1309123474Swpaul 1310123474Swpaul if (sh == sc->ndis_shlist) 1311123474Swpaul sc->ndis_shlist = sh->ndis_next; 1312123474Swpaul else 1313123474Swpaul prev->ndis_next = sh->ndis_next; 1314123474Swpaul 1315123474Swpaul free(sh, M_DEVBUF); 1316123474Swpaul 1317123474Swpaul return; 1318123474Swpaul} 1319123474Swpaul 1320123474Swpaul__stdcall static ndis_status 1321123474Swpaulndis_map_iospace(vaddr, adapter, paddr, len) 1322123474Swpaul void **vaddr; 1323123474Swpaul ndis_handle adapter; 1324123474Swpaul ndis_physaddr paddr; 1325123474Swpaul uint32_t len; 1326123474Swpaul{ 1327123474Swpaul ndis_miniport_block *block; 1328123474Swpaul struct ndis_softc *sc; 1329123474Swpaul 1330123474Swpaul if (adapter == NULL) 1331123474Swpaul return(NDIS_STATUS_FAILURE); 1332123474Swpaul 1333123474Swpaul block = (ndis_miniport_block *)adapter; 1334123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 1335123474Swpaul 1336123474Swpaul if (sc->ndis_res_mem == NULL) 1337123474Swpaul return(NDIS_STATUS_FAILURE); 1338123474Swpaul 1339123474Swpaul *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem); 1340123474Swpaul 1341123474Swpaul return(NDIS_STATUS_SUCCESS); 1342123474Swpaul} 1343123474Swpaul 1344123474Swpaul__stdcall static void 1345123474Swpaulndis_unmap_iospace(adapter, vaddr, len) 1346123474Swpaul ndis_handle adapter; 1347123474Swpaul void *vaddr; 1348123474Swpaul uint32_t len; 1349123474Swpaul{ 1350123474Swpaul return; 1351123474Swpaul} 1352123474Swpaul 1353123474Swpaul__stdcall static uint32_t 1354123474Swpaulndis_cachefill(void) 1355123474Swpaul{ 1356123474Swpaul return(128); 1357123474Swpaul} 1358123474Swpaul 1359123474Swpaul__stdcall static uint32_t 1360123474Swpaulndis_dma_align(handle) 1361123474Swpaul ndis_handle handle; 1362123474Swpaul{ 1363123474Swpaul return(128); 1364123474Swpaul} 1365123474Swpaul 1366123474Swpaul/* 1367123474Swpaul * NDIS has two methods for dealing with NICs that support DMA. 1368123474Swpaul * One is to just pass packets to the driver and let it call 1369123474Swpaul * NdisMStartBufferPhysicalMapping() to map each buffer in the packet 1370123474Swpaul * all by itself, and the other is to let the NDIS library handle the 1371123474Swpaul * buffer mapping internally, and hand the driver an already populated 1372123474Swpaul * scatter/gather fragment list. If the driver calls 1373123474Swpaul * NdisMInitializeScatterGatherDma(), it wants to use the latter 1374123474Swpaul * method. 1375123474Swpaul */ 1376123474Swpaul 1377123474Swpaul__stdcall static ndis_status 1378123474Swpaulndis_init_sc_dma(adapter, is64, maxphysmap) 1379123474Swpaul ndis_handle adapter; 1380123474Swpaul uint8_t is64; 1381123474Swpaul uint32_t maxphysmap; 1382123474Swpaul{ 1383123474Swpaul struct ndis_softc *sc; 1384123474Swpaul ndis_miniport_block *block; 1385123474Swpaul int error; 1386123474Swpaul 1387123474Swpaul if (adapter == NULL) 1388123474Swpaul return(NDIS_STATUS_FAILURE); 1389123474Swpaul block = (ndis_miniport_block *)adapter; 1390123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1391123474Swpaul 1392123474Swpaul /* Don't do this twice. */ 1393123474Swpaul if (sc->ndis_sc == 1) 1394123474Swpaul return(NDIS_STATUS_SUCCESS); 1395123474Swpaul 1396123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 1397123474Swpaul BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 1398123474Swpaul MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW, 1399123474Swpaul NULL, NULL, &sc->ndis_ttag); 1400123474Swpaul 1401123474Swpaul sc->ndis_sc = 1; 1402123474Swpaul 1403123474Swpaul return(NDIS_STATUS_SUCCESS); 1404123474Swpaul} 1405123474Swpaul 1406123474Swpaul__stdcall static void 1407123474Swpaulndis_alloc_packetpool(status, pool, descnum, protrsvdlen) 1408123474Swpaul ndis_status *status; 1409123474Swpaul ndis_handle *pool; 1410123474Swpaul uint32_t descnum; 1411123474Swpaul uint32_t protrsvdlen; 1412123474Swpaul{ 1413123474Swpaul ndis_packet *cur; 1414123474Swpaul int i; 1415123474Swpaul 1416123474Swpaul *pool = malloc(sizeof(ndis_packet) * (descnum + 1), 1417123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 1418123474Swpaul 1419123474Swpaul if (pool == NULL) { 1420123474Swpaul *status = NDIS_STATUS_RESOURCES; 1421123474Swpaul return; 1422123474Swpaul } 1423123474Swpaul 1424123474Swpaul cur = (ndis_packet *)*pool; 1425123474Swpaul cur->np_private.npp_flags = 0x1; /* mark the head of the list */ 1426123474Swpaul for (i = 0; i < descnum; i++) { 1427123474Swpaul cur->np_private.npp_head = (ndis_handle)(cur + 1); 1428123474Swpaul cur++; 1429123474Swpaul } 1430123474Swpaul 1431123474Swpaul *status = NDIS_STATUS_SUCCESS; 1432123474Swpaul return; 1433123474Swpaul} 1434123474Swpaul 1435123474Swpaul__stdcall static void 1436123474Swpaulndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen) 1437123474Swpaul ndis_status *status; 1438123474Swpaul ndis_handle *pool; 1439123474Swpaul uint32_t descnum; 1440123474Swpaul uint32_t oflowdescnum; 1441123474Swpaul uint32_t protrsvdlen; 1442123474Swpaul{ 1443123474Swpaul return(ndis_alloc_packetpool(status, pool, 1444123474Swpaul descnum + oflowdescnum, protrsvdlen)); 1445123474Swpaul} 1446123474Swpaul 1447123474Swpaul__stdcall static uint32_t 1448123474Swpaulndis_packetpool_use(pool) 1449123474Swpaul ndis_handle pool; 1450123474Swpaul{ 1451123474Swpaul ndis_packet *head; 1452123474Swpaul 1453123474Swpaul head = (ndis_packet *)pool; 1454123474Swpaul 1455123474Swpaul return(head->np_private.npp_count); 1456123474Swpaul} 1457123474Swpaul 1458123474Swpaul__stdcall static void 1459123474Swpaulndis_free_packetpool(pool) 1460123474Swpaul ndis_handle pool; 1461123474Swpaul{ 1462123474Swpaul free(pool, M_DEVBUF); 1463123474Swpaul return; 1464123474Swpaul} 1465123474Swpaul 1466123474Swpaul__stdcall static void 1467123474Swpaulndis_alloc_packet(status, packet, pool) 1468123474Swpaul ndis_status *status; 1469123474Swpaul ndis_packet **packet; 1470123474Swpaul ndis_handle pool; 1471123474Swpaul{ 1472123474Swpaul ndis_packet *head, *pkt; 1473123474Swpaul 1474123474Swpaul head = (ndis_packet *)pool; 1475123474Swpaul 1476123474Swpaul if (head->np_private.npp_flags != 0x1) { 1477123474Swpaul *status = NDIS_STATUS_FAILURE; 1478123474Swpaul return; 1479123474Swpaul } 1480123474Swpaul 1481123474Swpaul pkt = (ndis_packet *)head->np_private.npp_head; 1482123474Swpaul 1483123474Swpaul if (pkt == NULL) { 1484123474Swpaul *status = NDIS_STATUS_RESOURCES; 1485123474Swpaul return; 1486123474Swpaul } 1487123474Swpaul 1488123474Swpaul head->np_private.npp_head = pkt->np_private.npp_head; 1489123474Swpaul 1490123474Swpaul pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL; 1491123474Swpaul /* Save pointer to the pool. */ 1492123474Swpaul pkt->np_private.npp_pool = head; 1493123474Swpaul 1494123474Swpaul /* Set the oob offset pointer. Lots of things expect this. */ 1495123474Swpaul pkt->np_private.npp_packetooboffset = 1496123474Swpaul offsetof(ndis_packet, np_oob); 1497123474Swpaul 1498123474Swpaul *packet = pkt; 1499123474Swpaul 1500123474Swpaul head->np_private.npp_count++; 1501123474Swpaul *status = NDIS_STATUS_SUCCESS; 1502123474Swpaul return; 1503123474Swpaul} 1504123474Swpaul 1505123848Swpaul__stdcall static void 1506123848Swpaulndis_release_packet(packet) 1507123474Swpaul ndis_packet *packet; 1508123474Swpaul{ 1509123474Swpaul ndis_packet *head; 1510123474Swpaul 1511123474Swpaul if (packet == NULL || packet->np_private.npp_pool == NULL) 1512123474Swpaul return; 1513123474Swpaul 1514123474Swpaul head = packet->np_private.npp_pool; 1515123474Swpaul if (head->np_private.npp_flags != 0x1) 1516123474Swpaul return; 1517123474Swpaul 1518123474Swpaul packet->np_private.npp_head = head->np_private.npp_head; 1519123474Swpaul head->np_private.npp_head = (ndis_buffer *)packet; 1520123474Swpaul head->np_private.npp_count--; 1521123474Swpaul 1522123474Swpaul return; 1523123474Swpaul} 1524123474Swpaul 1525123474Swpaul__stdcall static void 1526123474Swpaulndis_unchain_headbuf(packet, buf) 1527123474Swpaul ndis_packet *packet; 1528123474Swpaul ndis_buffer **buf; 1529123474Swpaul{ 1530123474Swpaul ndis_packet_private *priv; 1531123474Swpaul 1532123474Swpaul if (packet == NULL || buf == NULL) 1533123474Swpaul return; 1534123474Swpaul 1535123474Swpaul priv = &packet->np_private; 1536123474Swpaul 1537123474Swpaul priv->npp_validcounts = FALSE; 1538123474Swpaul 1539123474Swpaul if (priv->npp_head == priv->npp_tail) { 1540123474Swpaul *buf = priv->npp_head; 1541123474Swpaul priv->npp_head = priv->npp_tail = NULL; 1542123474Swpaul } else { 1543123474Swpaul *buf = priv->npp_head; 1544123474Swpaul priv->npp_head = (*buf)->nb_next; 1545123474Swpaul } 1546123474Swpaul 1547123474Swpaul return; 1548123474Swpaul} 1549123474Swpaul 1550123721Swpaul__stdcall static void 1551123721Swpaulndis_unchain_tailbuf(packet, buf) 1552123721Swpaul ndis_packet *packet; 1553123721Swpaul ndis_buffer **buf; 1554123721Swpaul{ 1555123721Swpaul ndis_packet_private *priv; 1556123721Swpaul ndis_buffer *tmp; 1557123721Swpaul 1558123721Swpaul if (packet == NULL || buf == NULL) 1559123721Swpaul return; 1560123721Swpaul 1561123721Swpaul priv = &packet->np_private; 1562123721Swpaul 1563123721Swpaul priv->npp_validcounts = FALSE; 1564123721Swpaul 1565123721Swpaul if (priv->npp_head == priv->npp_tail) { 1566123721Swpaul *buf = priv->npp_head; 1567123721Swpaul priv->npp_head = priv->npp_tail = NULL; 1568123721Swpaul } else { 1569123721Swpaul *buf = priv->npp_tail; 1570123721Swpaul tmp = priv->npp_head; 1571123721Swpaul while (tmp->nb_next != priv->npp_tail) 1572123721Swpaul tmp = tmp->nb_next; 1573123721Swpaul priv->npp_tail = tmp; 1574123721Swpaul tmp->nb_next = NULL; 1575123721Swpaul } 1576123721Swpaul 1577123721Swpaul return; 1578123721Swpaul} 1579123721Swpaul 1580123474Swpaul/* 1581123474Swpaul * The NDIS "buffer" manipulation functions are somewhat misnamed. 1582123474Swpaul * They don't really allocate buffers: they allocate buffer mappings. 1583123474Swpaul * The idea is you reserve a chunk of DMA-able memory using 1584123474Swpaul * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer() 1585123474Swpaul * to obtain the virtual address of the DMA-able region. 1586123474Swpaul * ndis_alloc_bufpool() is analagous to bus_dma_tag_create(). 1587123474Swpaul */ 1588123474Swpaul 1589123474Swpaul__stdcall static void 1590123474Swpaulndis_alloc_bufpool(status, pool, descnum) 1591123474Swpaul ndis_status *status; 1592123474Swpaul ndis_handle *pool; 1593123474Swpaul uint32_t descnum; 1594123474Swpaul{ 1595123474Swpaul ndis_buffer *cur; 1596123474Swpaul int i; 1597123474Swpaul 1598123474Swpaul *pool = malloc(sizeof(ndis_buffer) * (descnum + 1), 1599123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 1600123474Swpaul 1601123474Swpaul if (pool == NULL) { 1602123474Swpaul *status = NDIS_STATUS_RESOURCES; 1603123474Swpaul return; 1604123474Swpaul } 1605123474Swpaul 1606123474Swpaul cur = (ndis_buffer *)*pool; 1607123474Swpaul cur->nb_flags = 0x1; /* mark the head of the list */ 1608123474Swpaul for (i = 0; i < descnum; i++) { 1609123474Swpaul cur->nb_next = cur + 1; 1610123474Swpaul cur++; 1611123474Swpaul } 1612123474Swpaul 1613123474Swpaul *status = NDIS_STATUS_SUCCESS; 1614123474Swpaul return; 1615123474Swpaul} 1616123474Swpaul 1617123474Swpaul__stdcall static void 1618123474Swpaulndis_free_bufpool(pool) 1619123474Swpaul ndis_handle pool; 1620123474Swpaul{ 1621123474Swpaul free(pool, M_DEVBUF); 1622123474Swpaul return; 1623123474Swpaul} 1624123474Swpaul 1625123474Swpaul/* 1626123474Swpaul * This maps to a bus_dmamap_create() and bus_dmamap_load(). 1627123474Swpaul */ 1628123474Swpaul__stdcall static void 1629123474Swpaulndis_alloc_buf(status, buffer, pool, vaddr, len) 1630123474Swpaul ndis_status *status; 1631123474Swpaul ndis_buffer **buffer; 1632123474Swpaul ndis_handle pool; 1633123474Swpaul void *vaddr; 1634123474Swpaul uint32_t len; 1635123474Swpaul{ 1636123474Swpaul ndis_buffer *head, *buf; 1637123474Swpaul 1638123474Swpaul head = (ndis_buffer *)pool; 1639123474Swpaul if (head->nb_flags != 0x1) { 1640123474Swpaul *status = NDIS_STATUS_FAILURE; 1641123474Swpaul return; 1642123474Swpaul } 1643123474Swpaul 1644123474Swpaul buf = head->nb_next; 1645123474Swpaul 1646123474Swpaul if (buf == NULL) { 1647123474Swpaul *status = NDIS_STATUS_RESOURCES; 1648123474Swpaul return; 1649123474Swpaul } 1650123474Swpaul 1651123474Swpaul head->nb_next = buf->nb_next; 1652123474Swpaul 1653123474Swpaul /* Save pointer to the pool. */ 1654123474Swpaul buf->nb_process = head; 1655123474Swpaul 1656123757Swpaul MDL_INIT(buf, vaddr, len); 1657123474Swpaul 1658123474Swpaul *buffer = buf; 1659123474Swpaul 1660123474Swpaul *status = NDIS_STATUS_SUCCESS; 1661123474Swpaul return; 1662123474Swpaul} 1663123474Swpaul 1664123848Swpaul__stdcall static void 1665123848Swpaulndis_release_buf(buf) 1666123474Swpaul ndis_buffer *buf; 1667123474Swpaul{ 1668123474Swpaul ndis_buffer *head; 1669123474Swpaul 1670123474Swpaul if (buf == NULL || buf->nb_process == NULL) 1671123474Swpaul return; 1672123474Swpaul 1673123474Swpaul head = buf->nb_process; 1674123474Swpaul 1675123474Swpaul if (head->nb_flags != 0x1) 1676123474Swpaul return; 1677123474Swpaul 1678123474Swpaul buf->nb_next = head->nb_next; 1679123474Swpaul head->nb_next = buf; 1680123474Swpaul 1681123474Swpaul return; 1682123474Swpaul} 1683123474Swpaul 1684123723Swpaul/* 1685123723Swpaul * Get the virtual address and length of a buffer. 1686123723Swpaul * Note: the vaddr argument is optional. 1687123723Swpaul */ 1688123474Swpaul 1689123474Swpaul__stdcall static void 1690123474Swpaulndis_query_buf(buf, vaddr, len) 1691123474Swpaul ndis_buffer *buf; 1692123474Swpaul void **vaddr; 1693123474Swpaul uint32_t *len; 1694123474Swpaul{ 1695123723Swpaul if (vaddr != NULL) 1696123757Swpaul *vaddr = MDL_VA(buf); 1697123474Swpaul *len = buf->nb_bytecount; 1698123474Swpaul 1699123474Swpaul return; 1700123474Swpaul} 1701123474Swpaul 1702123474Swpaul/* Same as above -- we don't care about the priority. */ 1703123474Swpaul 1704123474Swpaul__stdcall static void 1705123474Swpaulndis_query_buf_safe(buf, vaddr, len, prio) 1706123474Swpaul ndis_buffer *buf; 1707123474Swpaul void **vaddr; 1708123474Swpaul uint32_t *len; 1709123474Swpaul uint32_t prio; 1710123474Swpaul{ 1711123723Swpaul if (vaddr != NULL) 1712123757Swpaul *vaddr = MDL_VA(buf); 1713123474Swpaul *len = buf->nb_bytecount; 1714123474Swpaul 1715123474Swpaul return; 1716123474Swpaul} 1717123474Swpaul 1718123474Swpaul__stdcall static void 1719123474Swpaulndis_adjust_buflen(buf, len) 1720123474Swpaul ndis_buffer *buf; 1721123474Swpaul int len; 1722123474Swpaul{ 1723123474Swpaul buf->nb_bytecount = len; 1724123474Swpaul 1725123474Swpaul return; 1726123474Swpaul} 1727123474Swpaul 1728123474Swpaul__stdcall static uint32_t 1729123474Swpaulndis_interlock_inc(addend) 1730123474Swpaul uint32_t *addend; 1731123474Swpaul{ 1732123474Swpaul mtx_lock(&ndis_interlock); 1733123474Swpaul *addend++; 1734123474Swpaul mtx_unlock(&ndis_interlock); 1735123474Swpaul return(*addend); 1736123474Swpaul} 1737123474Swpaul 1738123474Swpaul__stdcall static uint32_t 1739123474Swpaulndis_interlock_dec(addend) 1740123474Swpaul uint32_t *addend; 1741123474Swpaul{ 1742123474Swpaul mtx_lock(&ndis_interlock); 1743123474Swpaul *addend--; 1744123474Swpaul mtx_unlock(&ndis_interlock); 1745123474Swpaul return(*addend); 1746123474Swpaul} 1747123474Swpaul 1748123474Swpaul__stdcall static void 1749123474Swpaulndis_init_event(event) 1750123474Swpaul ndis_event *event; 1751123474Swpaul{ 1752123474Swpaul event->ne_event.nk_header.dh_sigstate = FALSE; 1753123474Swpaul return; 1754123474Swpaul} 1755123474Swpaul 1756123474Swpaul__stdcall static void 1757123474Swpaulndis_set_event(event) 1758123474Swpaul ndis_event *event; 1759123474Swpaul{ 1760123474Swpaul event->ne_event.nk_header.dh_sigstate = TRUE; 1761123474Swpaul wakeup(event); 1762123474Swpaul return; 1763123474Swpaul} 1764123474Swpaul 1765123474Swpaul__stdcall static void 1766123474Swpaulndis_reset_event(event) 1767123474Swpaul ndis_event *event; 1768123474Swpaul{ 1769123474Swpaul event->ne_event.nk_header.dh_sigstate = FALSE; 1770123474Swpaul wakeup(event); 1771123474Swpaul return; 1772123474Swpaul} 1773123474Swpaul 1774123474Swpaul__stdcall static uint8_t 1775123474Swpaulndis_wait_event(event, msecs) 1776123474Swpaul ndis_event *event; 1777123474Swpaul uint32_t msecs; 1778123474Swpaul{ 1779123474Swpaul int error; 1780123474Swpaul struct timeval tv; 1781123474Swpaul 1782123474Swpaul if (event->ne_event.nk_header.dh_sigstate == TRUE) 1783123474Swpaul return(TRUE); 1784123474Swpaul 1785123474Swpaul tv.tv_sec = 0; 1786123474Swpaul tv.tv_usec = msecs * 1000; 1787123474Swpaul 1788123474Swpaul error = tsleep(event, PPAUSE|PCATCH, "ndis", tvtohz(&tv)); 1789123474Swpaul 1790123474Swpaul return(event->ne_event.nk_header.dh_sigstate); 1791123474Swpaul} 1792123474Swpaul 1793123474Swpaul__stdcall static ndis_status 1794123474Swpaulndis_unicode2ansi(dstr, sstr) 1795123526Swpaul ndis_ansi_string *dstr; 1796123526Swpaul ndis_unicode_string *sstr; 1797123474Swpaul{ 1798123526Swpaul if (dstr == NULL || sstr == NULL) 1799123526Swpaul return(NDIS_STATUS_FAILURE); 1800123526Swpaul if (ndis_unicode_to_ascii(sstr->nus_buf, 1801123526Swpaul sstr->nus_len, &dstr->nas_buf)) 1802123526Swpaul return(NDIS_STATUS_FAILURE); 1803123526Swpaul dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf); 1804123474Swpaul return (NDIS_STATUS_SUCCESS); 1805123474Swpaul} 1806123474Swpaul 1807123474Swpaul__stdcall static ndis_status 1808123526Swpaulndis_ansi2unicode(dstr, sstr) 1809123526Swpaul ndis_unicode_string *dstr; 1810123526Swpaul ndis_ansi_string *sstr; 1811123526Swpaul{ 1812123526Swpaul char *str; 1813123526Swpaul if (dstr == NULL || sstr == NULL) 1814123526Swpaul return(NDIS_STATUS_FAILURE); 1815123526Swpaul str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT); 1816123526Swpaul if (str == NULL) 1817123526Swpaul return(NDIS_STATUS_FAILURE); 1818123526Swpaul strncpy(str, sstr->nas_buf, sstr->nas_len); 1819123526Swpaul *(str + sstr->nas_len) = '\0'; 1820123526Swpaul if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) { 1821123526Swpaul free(str, M_DEVBUF); 1822123526Swpaul return(NDIS_STATUS_FAILURE); 1823123526Swpaul } 1824123526Swpaul dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2; 1825123526Swpaul free(str, M_DEVBUF); 1826123526Swpaul return (NDIS_STATUS_SUCCESS); 1827123526Swpaul} 1828123526Swpaul 1829123526Swpaul__stdcall static ndis_status 1830123474Swpaulndis_assign_pcirsrc(adapter, slot, list) 1831123474Swpaul ndis_handle adapter; 1832123474Swpaul uint32_t slot; 1833123474Swpaul ndis_resource_list **list; 1834123474Swpaul{ 1835123474Swpaul ndis_miniport_block *block; 1836123474Swpaul 1837123474Swpaul if (adapter == NULL || list == NULL) 1838123474Swpaul return (NDIS_STATUS_FAILURE); 1839123474Swpaul 1840123474Swpaul block = (ndis_miniport_block *)adapter; 1841123474Swpaul *list = block->nmb_rlist; 1842123474Swpaul 1843124060Swpaul device_printf (block->nmb_dev, "assign PCI resources...\n"); 1844123474Swpaul return (NDIS_STATUS_SUCCESS); 1845123474Swpaul} 1846123474Swpaul 1847123474Swpaul__stdcall static ndis_status 1848123474Swpaulndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode) 1849123474Swpaul ndis_miniport_interrupt *intr; 1850123474Swpaul ndis_handle adapter; 1851123474Swpaul uint32_t ivec; 1852123474Swpaul uint32_t ilevel; 1853123474Swpaul uint8_t reqisr; 1854123474Swpaul uint8_t shared; 1855123474Swpaul ndis_interrupt_mode imode; 1856123474Swpaul{ 1857123474Swpaul 1858123474Swpaul return(NDIS_STATUS_SUCCESS); 1859123474Swpaul} 1860123474Swpaul 1861123474Swpaul__stdcall static void 1862123474Swpaulndis_deregister_intr(intr) 1863123474Swpaul ndis_miniport_interrupt *intr; 1864123474Swpaul{ 1865123474Swpaul return; 1866123474Swpaul} 1867123474Swpaul 1868123474Swpaul__stdcall static void 1869123474Swpaulndis_register_shutdown(adapter, shutdownctx, shutdownfunc) 1870123474Swpaul ndis_handle adapter; 1871123474Swpaul void *shutdownctx; 1872123474Swpaul ndis_shutdown_handler shutdownfunc; 1873123474Swpaul{ 1874123474Swpaul ndis_miniport_block *block; 1875123474Swpaul ndis_miniport_characteristics *chars; 1876123474Swpaul struct ndis_softc *sc; 1877123474Swpaul 1878123474Swpaul if (adapter == NULL) 1879123474Swpaul return; 1880123474Swpaul 1881123474Swpaul block = (ndis_miniport_block *)adapter; 1882123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1883123474Swpaul chars = &sc->ndis_chars; 1884123474Swpaul 1885123474Swpaul chars->nmc_shutdown_handler = shutdownfunc; 1886123474Swpaul chars->nmc_rsvd0 = shutdownctx; 1887123474Swpaul 1888123474Swpaul return; 1889123474Swpaul} 1890123474Swpaul 1891123474Swpaul__stdcall static void 1892123474Swpaulndis_deregister_shutdown(adapter) 1893123474Swpaul ndis_handle adapter; 1894123474Swpaul{ 1895123474Swpaul ndis_miniport_block *block; 1896123474Swpaul ndis_miniport_characteristics *chars; 1897123474Swpaul struct ndis_softc *sc; 1898123474Swpaul 1899123474Swpaul if (adapter == NULL) 1900123474Swpaul return; 1901123474Swpaul 1902123474Swpaul block = (ndis_miniport_block *)adapter; 1903123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1904123474Swpaul chars = &sc->ndis_chars; 1905123474Swpaul 1906123474Swpaul chars->nmc_shutdown_handler = NULL; 1907123474Swpaul chars->nmc_rsvd0 = NULL; 1908123474Swpaul 1909123474Swpaul return; 1910123474Swpaul} 1911123474Swpaul 1912123474Swpaul__stdcall static uint32_t 1913123474Swpaulndis_numpages(buf) 1914123474Swpaul ndis_buffer *buf; 1915123474Swpaul{ 1916123757Swpaul if (buf == NULL) 1917123757Swpaul return(0); 1918123512Swpaul if (buf->nb_bytecount == 0) 1919123512Swpaul return(1); 1920123757Swpaul return(SPAN_PAGES(MDL_VA(buf), buf->nb_bytecount)); 1921123474Swpaul} 1922123474Swpaul 1923123474Swpaul__stdcall static void 1924123573Swpaulndis_buf_physpages(buf, pages) 1925123573Swpaul ndis_buffer *buf; 1926123573Swpaul uint32_t *pages; 1927123573Swpaul{ 1928123757Swpaul if (buf == NULL) 1929123757Swpaul return; 1930123757Swpaul 1931123573Swpaul *pages = ndis_numpages(buf); 1932123573Swpaul return; 1933123573Swpaul} 1934123573Swpaul 1935123573Swpaul__stdcall static void 1936123474Swpaulndis_query_bufoffset(buf, off, len) 1937123474Swpaul ndis_buffer *buf; 1938123474Swpaul uint32_t *off; 1939123474Swpaul uint32_t *len; 1940123474Swpaul{ 1941123757Swpaul if (buf == NULL) 1942123757Swpaul return; 1943123757Swpaul 1944123757Swpaul *off = buf->nb_byteoffset; 1945123474Swpaul *len = buf->nb_bytecount; 1946123474Swpaul 1947123474Swpaul return; 1948123474Swpaul} 1949123474Swpaul 1950123474Swpaul__stdcall static void 1951123474Swpaulndis_sleep(usecs) 1952123474Swpaul uint32_t usecs; 1953123474Swpaul{ 1954123474Swpaul struct timeval tv; 1955123474Swpaul uint32_t dummy; 1956123474Swpaul 1957123474Swpaul tv.tv_sec = 0; 1958123474Swpaul tv.tv_usec = usecs; 1959123474Swpaul 1960123474Swpaul tsleep(&dummy, PPAUSE|PCATCH, "ndis", tvtohz(&tv)); 1961123474Swpaul return; 1962123474Swpaul} 1963123474Swpaul 1964123474Swpaul__stdcall static uint32_t 1965123474Swpaulndis_read_pccard_amem(handle, offset, buf, len) 1966123474Swpaul ndis_handle handle; 1967123474Swpaul uint32_t offset; 1968123474Swpaul void *buf; 1969123474Swpaul uint32_t len; 1970123474Swpaul{ 1971123474Swpaul struct ndis_softc *sc; 1972123474Swpaul ndis_miniport_block *block; 1973123474Swpaul bus_space_handle_t bh; 1974123474Swpaul bus_space_tag_t bt; 1975123474Swpaul char *dest; 1976123474Swpaul int i; 1977123474Swpaul 1978123474Swpaul if (handle == NULL) 1979123474Swpaul return(0); 1980123474Swpaul 1981123474Swpaul block = (ndis_miniport_block *)handle; 1982123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1983123474Swpaul dest = buf; 1984123474Swpaul 1985123474Swpaul bh = rman_get_bushandle(sc->ndis_res_am); 1986123474Swpaul bt = rman_get_bustag(sc->ndis_res_am); 1987123474Swpaul 1988123474Swpaul for (i = 0; i < len; i++) 1989123474Swpaul dest[i] = bus_space_read_1(bt, bh, (offset * 2) + (i * 2)); 1990123474Swpaul 1991123474Swpaul return(i); 1992123474Swpaul} 1993123474Swpaul 1994123474Swpaul__stdcall static uint32_t 1995123474Swpaulndis_write_pccard_amem(handle, offset, buf, len) 1996123474Swpaul ndis_handle handle; 1997123474Swpaul uint32_t offset; 1998123474Swpaul void *buf; 1999123474Swpaul uint32_t len; 2000123474Swpaul{ 2001123474Swpaul struct ndis_softc *sc; 2002123474Swpaul ndis_miniport_block *block; 2003123474Swpaul bus_space_handle_t bh; 2004123474Swpaul bus_space_tag_t bt; 2005123474Swpaul char *src; 2006123474Swpaul int i; 2007123474Swpaul 2008123474Swpaul if (handle == NULL) 2009123474Swpaul return(0); 2010123474Swpaul 2011123474Swpaul block = (ndis_miniport_block *)handle; 2012123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 2013123474Swpaul src = buf; 2014123474Swpaul 2015123474Swpaul bh = rman_get_bushandle(sc->ndis_res_am); 2016123474Swpaul bt = rman_get_bustag(sc->ndis_res_am); 2017123474Swpaul 2018123474Swpaul for (i = 0; i < len; i++) 2019123474Swpaul bus_space_write_1(bt, bh, (offset * 2) + (i * 2), src[i]); 2020123474Swpaul 2021123474Swpaul return(i); 2022123474Swpaul} 2023123474Swpaul 2024123474Swpaul__stdcall static ndis_list_entry * 2025123474Swpaulndis_insert_head(head, entry, lock) 2026123474Swpaul ndis_list_entry *head; 2027123474Swpaul ndis_list_entry *entry; 2028123474Swpaul ndis_spin_lock *lock; 2029123474Swpaul{ 2030123474Swpaul ndis_list_entry *flink; 2031123474Swpaul 2032123474Swpaul mtx_lock_spin((struct mtx *)lock->nsl_spinlock); 2033123474Swpaul flink = head->nle_flink; 2034123474Swpaul entry->nle_flink = flink; 2035123474Swpaul entry->nle_blink = head; 2036123474Swpaul flink->nle_blink = entry; 2037123474Swpaul head->nle_flink = entry; 2038123474Swpaul mtx_unlock_spin((struct mtx *)lock->nsl_spinlock); 2039123474Swpaul 2040123474Swpaul return(flink); 2041123474Swpaul} 2042123474Swpaul 2043123474Swpaul__stdcall static ndis_list_entry * 2044123474Swpaulndis_remove_head(head, lock) 2045123474Swpaul ndis_list_entry *head; 2046123474Swpaul ndis_spin_lock *lock; 2047123474Swpaul{ 2048123474Swpaul ndis_list_entry *flink; 2049123474Swpaul ndis_list_entry *entry; 2050123474Swpaul 2051123474Swpaul mtx_lock_spin((struct mtx *)lock->nsl_spinlock); 2052123474Swpaul entry = head->nle_flink; 2053123474Swpaul flink = entry->nle_flink; 2054123474Swpaul head->nle_flink = flink; 2055123474Swpaul flink->nle_blink = head; 2056123474Swpaul mtx_unlock_spin((struct mtx *)lock->nsl_spinlock); 2057123474Swpaul 2058123474Swpaul return(entry); 2059123474Swpaul} 2060123474Swpaul 2061123474Swpaul__stdcall static ndis_list_entry * 2062123474Swpaulndis_insert_tail(head, entry, lock) 2063123474Swpaul ndis_list_entry *head; 2064123474Swpaul ndis_list_entry *entry; 2065123474Swpaul ndis_spin_lock *lock; 2066123474Swpaul{ 2067123474Swpaul ndis_list_entry *blink; 2068123474Swpaul 2069123474Swpaul mtx_lock_spin((struct mtx *)lock->nsl_spinlock); 2070123474Swpaul blink = head->nle_blink; 2071123474Swpaul entry->nle_flink = head; 2072123474Swpaul entry->nle_blink = blink; 2073123474Swpaul blink->nle_flink = entry; 2074123474Swpaul head->nle_blink = entry; 2075123474Swpaul mtx_unlock_spin((struct mtx *)lock->nsl_spinlock); 2076123474Swpaul 2077123474Swpaul return(blink); 2078123474Swpaul} 2079123474Swpaul 2080123474Swpaul__stdcall static uint8_t 2081123474Swpaulndis_sync_with_intr(intr, syncfunc, syncctx) 2082123474Swpaul ndis_miniport_interrupt *intr; 2083123474Swpaul void *syncfunc; 2084123474Swpaul void *syncctx; 2085123474Swpaul{ 2086123474Swpaul __stdcall uint8_t (*sync)(void *); 2087123474Swpaul 2088123474Swpaul if (syncfunc == NULL || syncctx == NULL) 2089123474Swpaul return(0); 2090123474Swpaul 2091123474Swpaul sync = syncfunc; 2092123474Swpaul return(sync(syncctx)); 2093123474Swpaul} 2094123474Swpaul 2095123504Swpaul/* 2096123504Swpaul * Return the number of 100 nanosecond intervals since 2097123504Swpaul * January 1, 1601. (?!?!) 2098123504Swpaul */ 2099123474Swpaul__stdcall static void 2100123504Swpaulndis_time(tval) 2101123504Swpaul uint64_t *tval; 2102123504Swpaul{ 2103123504Swpaul struct timespec ts; 2104123822Swpaul 2105123504Swpaul nanotime(&ts); 2106123822Swpaul *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 + 2107123822Swpaul 11644473600; 2108123504Swpaul} 2109123504Swpaul 2110123822Swpaul/* 2111123822Swpaul * Return the number of milliseconds since the system booted. 2112123822Swpaul */ 2113123504Swpaul__stdcall static void 2114123822Swpaulndis_uptime(tval) 2115123822Swpaul uint32_t *tval; 2116123822Swpaul{ 2117123822Swpaul struct timespec ts; 2118123822Swpaul 2119123822Swpaul nanouptime(&ts); 2120123822Swpaul *tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000; 2121123822Swpaul} 2122123822Swpaul 2123123822Swpaul__stdcall static void 2124123507Swpaulndis_init_string(dst, src) 2125123507Swpaul ndis_unicode_string **dst; 2126123507Swpaul char *src; 2127123507Swpaul{ 2128123507Swpaul ndis_unicode_string *u; 2129123507Swpaul 2130123507Swpaul u = malloc(sizeof(ndis_unicode_string), M_DEVBUF, M_NOWAIT); 2131123507Swpaul if (u == NULL) 2132123507Swpaul return; 2133123507Swpaul u->nus_buf = NULL; 2134123507Swpaul if (ndis_ascii_to_unicode(src, &u->nus_buf)) { 2135123507Swpaul free(u, M_DEVBUF); 2136123507Swpaul return; 2137123507Swpaul } 2138123507Swpaul u->nus_len = u->nus_maxlen = strlen(src) * 2; 2139123507Swpaul return; 2140123507Swpaul} 2141123507Swpaul 2142123507Swpaul__stdcall static void 2143123507Swpaulndis_free_string(str) 2144123507Swpaul ndis_unicode_string *str; 2145123507Swpaul{ 2146123507Swpaul if (str == NULL) 2147123507Swpaul return; 2148123507Swpaul if (str->nus_buf != NULL) 2149123507Swpaul free(str->nus_buf, M_DEVBUF); 2150123507Swpaul free(str, M_DEVBUF); 2151123507Swpaul return; 2152123507Swpaul} 2153123507Swpaul 2154123507Swpaul__stdcall static ndis_status 2155123507Swpaulndis_remove_miniport(adapter) 2156123507Swpaul ndis_handle *adapter; 2157123507Swpaul{ 2158123507Swpaul return(NDIS_STATUS_SUCCESS); 2159123507Swpaul} 2160123507Swpaul 2161123507Swpaul__stdcall static void 2162123526Swpaulndis_init_ansi_string(dst, src) 2163123526Swpaul ndis_ansi_string *dst; 2164123526Swpaul char *src; 2165123526Swpaul{ 2166123526Swpaul ndis_ansi_string *a; 2167123526Swpaul 2168123526Swpaul a = dst; 2169123526Swpaul if (a == NULL) 2170123526Swpaul return; 2171123526Swpaul if (src == NULL) { 2172123526Swpaul a->nas_len = a->nas_maxlen = 0; 2173123526Swpaul a->nas_buf = NULL; 2174123526Swpaul } else { 2175123526Swpaul a->nas_buf = src; 2176123526Swpaul a->nas_len = a->nas_maxlen = strlen(src); 2177123526Swpaul } 2178123526Swpaul 2179123526Swpaul return; 2180123526Swpaul} 2181123526Swpaul 2182123941Swpaul__stdcall static void 2183123941Swpaulndis_init_unicode_string(dst, src) 2184123941Swpaul ndis_unicode_string *dst; 2185123941Swpaul uint16_t *src; 2186123941Swpaul{ 2187123941Swpaul ndis_unicode_string *u; 2188123941Swpaul int i; 2189123941Swpaul 2190123941Swpaul u = dst; 2191123941Swpaul if (u == NULL) 2192123941Swpaul return; 2193123941Swpaul if (src == NULL) { 2194123941Swpaul u->nus_len = u->nus_maxlen = 0; 2195123941Swpaul u->nus_buf = NULL; 2196123941Swpaul } else { 2197123941Swpaul i = 0; 2198123941Swpaul while(src[i] != 0) 2199123941Swpaul i++; 2200123941Swpaul u->nus_buf = src; 2201123941Swpaul u->nus_len = u->nus_maxlen = i * 2; 2202123941Swpaul } 2203123941Swpaul 2204123941Swpaul return; 2205123941Swpaul} 2206123941Swpaul 2207123526Swpaul__stdcall static void ndis_get_devprop(adapter, phydevobj, 2208123526Swpaul funcdevobj, nextdevobj, resources, transresources) 2209123526Swpaul ndis_handle adapter; 2210123526Swpaul void *phydevobj; 2211123526Swpaul void *funcdevobj; 2212123526Swpaul void *nextdevobj; 2213123526Swpaul cm_resource_list *resources; 2214123526Swpaul cm_resource_list *transresources; 2215123526Swpaul{ 2216123526Swpaul return; 2217123526Swpaul} 2218123526Swpaul 2219123526Swpaul__stdcall static void 2220123721Swpaulndis_firstbuf(packet, buf, firstva, firstlen, totlen) 2221123721Swpaul ndis_packet *packet; 2222123721Swpaul ndis_buffer **buf; 2223123721Swpaul void **firstva; 2224123721Swpaul uint32_t *firstlen; 2225123721Swpaul uint32_t *totlen; 2226123721Swpaul{ 2227123721Swpaul ndis_buffer *tmp; 2228123721Swpaul 2229123721Swpaul tmp = packet->np_private.npp_head; 2230123721Swpaul *buf = tmp; 2231123721Swpaul if (tmp == NULL) { 2232123721Swpaul *firstva = NULL; 2233123721Swpaul *firstlen = *totlen = 0; 2234123721Swpaul } else { 2235123757Swpaul *firstva = MDL_VA(tmp); 2236123721Swpaul *firstlen = *totlen = tmp->nb_bytecount; 2237123721Swpaul for (tmp = tmp->nb_next; tmp != NULL; tmp = tmp->nb_next) 2238123721Swpaul *totlen += tmp->nb_bytecount; 2239123721Swpaul } 2240123721Swpaul 2241123721Swpaul return; 2242123721Swpaul} 2243123721Swpaul 2244123721Swpaul__stdcall static void 2245123721Swpaulndis_firstbuf_safe(packet, buf, firstva, firstlen, totlen, prio) 2246123721Swpaul ndis_packet *packet; 2247123721Swpaul ndis_buffer **buf; 2248123721Swpaul void **firstva; 2249123721Swpaul uint32_t *firstlen; 2250123721Swpaul uint32_t *totlen; 2251123721Swpaul uint32_t prio; 2252123721Swpaul{ 2253123721Swpaul ndis_firstbuf(packet, buf, firstva, firstlen, totlen); 2254123721Swpaul} 2255123721Swpaul 2256123822Swpaul/* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */ 2257123721Swpaul__stdcall static void 2258123822Swpaulndis_open_file(status, filehandle, filelength, filename, highestaddr) 2259123822Swpaul ndis_status *status; 2260123822Swpaul ndis_handle *filehandle; 2261123822Swpaul uint32_t *filelength; 2262123822Swpaul ndis_unicode_string *filename; 2263123822Swpaul ndis_physaddr highestaddr; 2264123822Swpaul{ 2265123822Swpaul char *afilename = NULL; 2266123822Swpaul 2267123822Swpaul ndis_unicode_to_ascii(filename->nus_buf, filename->nus_len, &afilename); 2268123822Swpaul printf("ndis_open_file(\"%s\", %ju)\n", afilename, 2269123822Swpaul highestaddr.np_quad); 2270123822Swpaul free(afilename, M_DEVBUF); 2271123822Swpaul *status = NDIS_STATUS_FILE_NOT_FOUND; 2272123822Swpaul return; 2273123822Swpaul} 2274123822Swpaul 2275123822Swpaul__stdcall static void 2276123822Swpaulndis_map_file(status, mappedbuffer, filehandle) 2277123822Swpaul ndis_status *status; 2278123822Swpaul void **mappedbuffer; 2279123822Swpaul ndis_handle filehandle; 2280123822Swpaul{ 2281123822Swpaul 2282123822Swpaul *status = NDIS_STATUS_ALREADY_MAPPED; 2283123822Swpaul return; 2284123822Swpaul} 2285123822Swpaul 2286123822Swpaul__stdcall static void 2287123822Swpaulndis_unmap_file(filehandle) 2288123822Swpaul ndis_handle filehandle; 2289123822Swpaul{ 2290123822Swpaul return; 2291123822Swpaul} 2292123822Swpaul 2293123822Swpaul__stdcall static void 2294123822Swpaulndis_close_file(filehandle) 2295123822Swpaul ndis_handle filehandle; 2296123822Swpaul{ 2297123822Swpaul return; 2298123822Swpaul} 2299123822Swpaul 2300123848Swpaul__stdcall static uint8_t 2301123848Swpaulndis_cpu_cnt() 2302123848Swpaul{ 2303123848Swpaul#ifdef SMP 2304123848Swpaul return(mp_ncpus); 2305123848Swpaul#else 2306123848Swpaul return(1); 2307123848Swpaul#endif 2308123848Swpaul}; 2309123848Swpaul 2310123822Swpaul__stdcall static void 2311123474Swpauldummy() 2312123474Swpaul{ 2313123474Swpaul printf ("NDIS dummy called...\n"); 2314123474Swpaul return; 2315123474Swpaul} 2316123474Swpaul 2317123474Swpaulimage_patch_table ndis_functbl[] = { 2318123848Swpaul { "NdisSystemProcessorCount", (FUNC)ndis_cpu_cnt }, 2319123721Swpaul { "NdisUnchainBufferAtBack", (FUNC)ndis_unchain_tailbuf, }, 2320123721Swpaul { "NdisGetFirstBufferFromPacket", (FUNC)ndis_firstbuf }, 2321123721Swpaul { "NdisGetFirstBufferFromPacketSafe", (FUNC)ndis_firstbuf_safe }, 2322123573Swpaul { "NdisGetBufferPhysicalArraySize", (FUNC)ndis_buf_physpages }, 2323123526Swpaul { "NdisMGetDeviceProperty", (FUNC)ndis_get_devprop }, 2324123526Swpaul { "NdisInitAnsiString", (FUNC)ndis_init_ansi_string }, 2325123941Swpaul { "NdisInitUnicodeString", (FUNC)ndis_init_unicode_string }, 2326123526Swpaul { "NdisWriteConfiguration", (FUNC)ndis_write_cfg }, 2327123526Swpaul { "NdisAnsiStringToUnicodeString", (FUNC)ndis_ansi2unicode }, 2328123526Swpaul { "NdisTerminateWrapper", (FUNC)ndis_termwrap }, 2329123526Swpaul { "NdisOpenConfigurationKeyByName", (FUNC)ndis_open_cfgbyname }, 2330123526Swpaul { "NdisOpenConfigurationKeyByIndex", (FUNC)ndis_open_cfgbyidx }, 2331123507Swpaul { "NdisMRemoveMiniport", (FUNC)ndis_remove_miniport }, 2332123507Swpaul { "NdisInitializeString", (FUNC)ndis_init_string }, 2333123507Swpaul { "NdisFreeString", (FUNC)ndis_free_string }, 2334123504Swpaul { "NdisGetCurrentSystemTime", (FUNC)ndis_time }, 2335123822Swpaul { "NdisGetSystemUpTime", (FUNC)ndis_uptime }, 2336123474Swpaul { "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr }, 2337123474Swpaul { "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async }, 2338123474Swpaul { "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head }, 2339123474Swpaul { "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail }, 2340123474Swpaul { "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head }, 2341123474Swpaul { "NdisInitializeWrapper", (FUNC)ndis_initwrap }, 2342123474Swpaul { "NdisMRegisterMiniport", (FUNC)ndis_register_miniport }, 2343123474Swpaul { "NdisAllocateMemoryWithTag", (FUNC)ndis_malloc_withtag }, 2344123474Swpaul { "NdisAllocateMemory", (FUNC)ndis_malloc }, 2345123474Swpaul { "NdisMSetAttributesEx", (FUNC)ndis_setattr_ex }, 2346123474Swpaul { "NdisCloseConfiguration", (FUNC)ndis_close_cfg }, 2347123474Swpaul { "NdisReadConfiguration", (FUNC)ndis_read_cfg }, 2348123474Swpaul { "NdisOpenConfiguration", (FUNC)ndis_open_cfg }, 2349123474Swpaul { "NdisReleaseSpinLock", (FUNC)ndis_unlock }, 2350123474Swpaul { "NdisDprAcquireSpinLock", (FUNC)ndis_lock }, 2351123474Swpaul { "NdisDprReleaseSpinLock", (FUNC)ndis_unlock }, 2352123474Swpaul { "NdisAcquireSpinLock", (FUNC)ndis_lock }, 2353123474Swpaul { "NdisAllocateSpinLock", (FUNC)ndis_create_lock }, 2354123474Swpaul { "NdisFreeSpinLock", (FUNC)ndis_destroy_lock }, 2355123474Swpaul { "NdisFreeMemory", (FUNC)ndis_free }, 2356123474Swpaul { "NdisReadPciSlotInformation", (FUNC)ndis_read_pci }, 2357123474Swpaul { "NdisWritePciSlotInformation",(FUNC)ndis_write_pci }, 2358123474Swpaul { "NdisWriteErrorLogEntry", (FUNC)ndis_syslog }, 2359123474Swpaul { "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load }, 2360123474Swpaul { "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload }, 2361123474Swpaul { "NdisMInitializeTimer", (FUNC)ndis_create_timer }, 2362123474Swpaul { "NdisSetTimer", (FUNC)ndis_set_timer }, 2363123474Swpaul { "NdisMCancelTimer", (FUNC)ndis_cancel_timer }, 2364123474Swpaul { "NdisMSetPeriodicTimer", (FUNC)ndis_set_periodic_timer }, 2365123474Swpaul { "NdisMQueryAdapterResources", (FUNC)ndis_query_resources }, 2366123474Swpaul { "NdisMRegisterIoPortRange", (FUNC)ndis_register_ioport }, 2367123474Swpaul { "NdisMDeregisterIoPortRange", (FUNC)ndis_deregister_ioport }, 2368123474Swpaul { "NdisReadNetworkAddress", (FUNC)ndis_read_netaddr }, 2369123848Swpaul { "NdisQueryMapRegisterCount", (FUNC)ndis_mapreg_cnt }, 2370123474Swpaul { "NdisMAllocateMapRegisters", (FUNC)ndis_alloc_mapreg }, 2371123848Swpaul { "NdisMFreeMapRegisters", (FUNC)ndis_free_mapreg }, 2372123474Swpaul { "NdisMAllocateSharedMemory", (FUNC)ndis_alloc_sharedmem }, 2373123474Swpaul { "NdisMMapIoSpace", (FUNC)ndis_map_iospace }, 2374123474Swpaul { "NdisMUnmapIoSpace", (FUNC)ndis_unmap_iospace }, 2375123474Swpaul { "NdisGetCacheFillSize", (FUNC)ndis_cachefill }, 2376123474Swpaul { "NdisMGetDmaAlignment", (FUNC)ndis_dma_align }, 2377123474Swpaul { "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma }, 2378123474Swpaul { "NdisAllocatePacketPool", (FUNC)ndis_alloc_packetpool }, 2379123474Swpaul { "NdisAllocatePacketPoolEx", (FUNC)ndis_ex_alloc_packetpool }, 2380123474Swpaul { "NdisAllocatePacket", (FUNC)ndis_alloc_packet }, 2381123474Swpaul { "NdisFreePacket", (FUNC)ndis_release_packet }, 2382123474Swpaul { "NdisFreePacketPool", (FUNC)ndis_free_packetpool }, 2383124097Swpaul { "NdisDprAllocatePacket", (FUNC)ndis_alloc_packet }, 2384124097Swpaul { "NdisDprFreePacket", (FUNC)ndis_release_packet }, 2385123474Swpaul { "NdisAllocateBufferPool", (FUNC)ndis_alloc_bufpool }, 2386123474Swpaul { "NdisAllocateBuffer", (FUNC)ndis_alloc_buf }, 2387123474Swpaul { "NdisQueryBuffer", (FUNC)ndis_query_buf }, 2388123474Swpaul { "NdisQueryBufferSafe", (FUNC)ndis_query_buf_safe }, 2389123474Swpaul { "NdisFreeBuffer", (FUNC)ndis_release_buf }, 2390123474Swpaul { "NdisFreeBufferPool", (FUNC)ndis_free_bufpool }, 2391123474Swpaul { "NdisInterlockedIncrement", (FUNC)ndis_interlock_inc }, 2392123474Swpaul { "NdisInterlockedDecrement", (FUNC)ndis_interlock_dec }, 2393123474Swpaul { "NdisInitializeEvent", (FUNC)ndis_init_event }, 2394123474Swpaul { "NdisSetEvent", (FUNC)ndis_set_event }, 2395123474Swpaul { "NdisResetEvent", (FUNC)ndis_reset_event }, 2396123474Swpaul { "NdisWaitEvent", (FUNC)ndis_wait_event }, 2397123474Swpaul { "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi }, 2398123474Swpaul { "NdisMPciAssignResources", (FUNC)ndis_assign_pcirsrc }, 2399123474Swpaul { "NdisMFreeSharedMemory", (FUNC)ndis_free_sharedmem }, 2400123474Swpaul { "NdisMRegisterInterrupt", (FUNC)ndis_register_intr }, 2401123474Swpaul { "NdisMDeregisterInterrupt", (FUNC)ndis_deregister_intr }, 2402123474Swpaul { "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown }, 2403123474Swpaul { "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown }, 2404123474Swpaul { "NDIS_BUFFER_TO_SPAN_PAGES", (FUNC)ndis_numpages }, 2405123474Swpaul { "NdisQueryBufferOffset", (FUNC)ndis_query_bufoffset }, 2406123474Swpaul { "NdisAdjustBufferLength", (FUNC)ndis_adjust_buflen }, 2407123474Swpaul { "NdisPacketPoolUsage", (FUNC)ndis_packetpool_use }, 2408123474Swpaul { "NdisMSleep", (FUNC)ndis_sleep }, 2409123474Swpaul { "NdisUnchainBufferAtFront", (FUNC)ndis_unchain_headbuf }, 2410123474Swpaul { "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem }, 2411123474Swpaul { "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem }, 2412123822Swpaul { "NdisOpenFile", (FUNC)ndis_open_file }, 2413123822Swpaul { "NdisMapFile", (FUNC)ndis_map_file }, 2414123822Swpaul { "NdisUnmapFile", (FUNC)ndis_unmap_file }, 2415123822Swpaul { "NdisCloseFile", (FUNC)ndis_close_file }, 2416123474Swpaul 2417123474Swpaul /* 2418123474Swpaul * This last entry is a catch-all for any function we haven't 2419123474Swpaul * implemented yet. The PE import list patching routine will 2420123474Swpaul * use it for any function that doesn't have an explicit match 2421123474Swpaul * in this table. 2422123474Swpaul */ 2423123474Swpaul 2424123474Swpaul { NULL, (FUNC)dummy }, 2425123474Swpaul 2426123474Swpaul /* End of list. */ 2427123474Swpaul 2428123474Swpaul { NULL, NULL }, 2429123474Swpaul}; 2430