subr_ndis.c revision 124122
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 124122 2004-01-04 07:47:33Z 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> 66124122Swpaul#include <sys/queue.h> 67124122Swpaul#include <sys/taskqueue.h> 68123474Swpaul 69123474Swpaul#include <net/if.h> 70123474Swpaul#include <net/if_arp.h> 71123474Swpaul#include <net/ethernet.h> 72123474Swpaul#include <net/if_dl.h> 73123474Swpaul#include <net/if_media.h> 74123474Swpaul 75123474Swpaul#include <machine/bus_memio.h> 76123474Swpaul#include <machine/bus_pio.h> 77123474Swpaul#include <machine/bus.h> 78123474Swpaul#include <machine/resource.h> 79123474Swpaul 80123474Swpaul#include <sys/bus.h> 81123474Swpaul#include <sys/rman.h> 82123474Swpaul 83123474Swpaul#include <machine/stdarg.h> 84123474Swpaul 85123695Swpaul#include <net80211/ieee80211_var.h> 86123695Swpaul#include <net80211/ieee80211_ioctl.h> 87123695Swpaul 88123474Swpaul#include <dev/pci/pcireg.h> 89123474Swpaul#include <dev/pci/pcivar.h> 90123474Swpaul 91123474Swpaul#include <compat/ndis/pe_var.h> 92123474Swpaul#include <compat/ndis/resource_var.h> 93123512Swpaul#include <compat/ndis/ntoskrnl_var.h> 94123474Swpaul#include <compat/ndis/ndis_var.h> 95123474Swpaul#include <compat/ndis/cfg_var.h> 96123474Swpaul#include <dev/if_ndis/if_ndisvar.h> 97123474Swpaul 98123474Swpaul#define __stdcall __attribute__((__stdcall__)) 99123474Swpaul#define FUNC void(*)(void) 100123474Swpaul 101123474Swpaulstatic struct mtx ndis_interlock; 102123474Swpaul 103123474Swpaul__stdcall static void ndis_initwrap(ndis_handle, 104123474Swpaul ndis_driver_object *, void *, void *); 105123474Swpaul__stdcall static ndis_status ndis_register_miniport(ndis_handle, 106123474Swpaul ndis_miniport_characteristics *, int); 107123474Swpaul__stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t); 108123474Swpaul__stdcall static ndis_status ndis_malloc(void **, 109123474Swpaul uint32_t, uint32_t, ndis_physaddr); 110123474Swpaul__stdcall static void ndis_free(void *, uint32_t, uint32_t); 111123474Swpaul__stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle, 112123474Swpaul uint32_t, uint32_t, ndis_interface_type); 113123474Swpaul__stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle); 114123526Swpaul__stdcall static void ndis_open_cfgbyidx(ndis_status *, ndis_handle, 115123526Swpaul uint32_t, ndis_unicode_string *, ndis_handle *); 116123526Swpaul__stdcall static void ndis_open_cfgbyname(ndis_status *, ndis_handle, 117123526Swpaul ndis_unicode_string *, ndis_handle *); 118123474Swpaulstatic ndis_status ndis_encode_parm(ndis_miniport_block *, 119123474Swpaul struct sysctl_oid *, ndis_parm_type, ndis_config_parm **); 120123526Swpaulstatic ndis_status ndis_decode_parm(ndis_miniport_block *, 121123526Swpaul ndis_config_parm *, char *); 122123474Swpaul__stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **, 123123474Swpaul ndis_handle, ndis_unicode_string *, ndis_parm_type); 124123526Swpaul__stdcall static void ndis_write_cfg(ndis_status *, ndis_handle, 125123526Swpaul ndis_unicode_string *, ndis_config_parm *); 126123474Swpaul__stdcall static void ndis_close_cfg(ndis_handle); 127123474Swpaul__stdcall static void ndis_create_lock(ndis_spin_lock *); 128123474Swpaul__stdcall static void ndis_destroy_lock(ndis_spin_lock *); 129123474Swpaul__stdcall static void ndis_lock(ndis_spin_lock *); 130123474Swpaul__stdcall static void ndis_unlock(ndis_spin_lock *); 131123474Swpaul__stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t, 132123474Swpaul uint32_t, void *, uint32_t); 133123474Swpaul__stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t, 134123474Swpaul uint32_t, void *, uint32_t); 135123474Swpaulstatic void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...); 136123474Swpaulstatic void ndis_map_cb(void *, bus_dma_segment_t *, int, int); 137123474Swpaul__stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *, 138123474Swpaul uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *); 139123474Swpaul__stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t); 140123474Swpaul__stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle *, 141123474Swpaul ndis_timer_function, void *); 142123474Swpaulstatic void ndis_timercall(void *); 143123474Swpaul__stdcall static void ndis_set_timer(ndis_miniport_timer *, uint32_t); 144123474Swpaulstatic void ndis_tick(void *); 145123474Swpaul__stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t); 146123474Swpaul__stdcall static void ndis_cancel_timer(ndis_miniport_timer *, uint8_t *); 147123474Swpaul__stdcall static void ndis_query_resources(ndis_status *, ndis_handle, 148123474Swpaul ndis_resource_list *, uint32_t *); 149123474Swpaul__stdcall static ndis_status ndis_register_ioport(void **, 150123474Swpaul ndis_handle, uint32_t, uint32_t); 151123474Swpaul__stdcall static void ndis_deregister_ioport(ndis_handle, 152123474Swpaul uint32_t, uint32_t, void *); 153123474Swpaul__stdcall static void ndis_read_netaddr(ndis_status *, void **, 154123474Swpaul uint32_t *, ndis_handle); 155123848Swpaul__stdcall static ndis_status ndis_mapreg_cnt(uint32_t, uint32_t *); 156123474Swpaul__stdcall static ndis_status ndis_alloc_mapreg(ndis_handle, 157123474Swpaul uint32_t, uint8_t, uint32_t, uint32_t); 158123474Swpaul__stdcall static void ndis_free_mapreg(ndis_handle); 159123474Swpaulstatic void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int); 160123474Swpaul__stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t, 161123474Swpaul uint8_t, void **, ndis_physaddr *); 162123474Swpaul__stdcall static void ndis_alloc_sharedmem_async(ndis_handle, 163123474Swpaul uint32_t, uint8_t, void *); 164123474Swpaul__stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t, 165123474Swpaul uint8_t, void *, ndis_physaddr); 166123474Swpaul__stdcall static ndis_status ndis_map_iospace(void **, ndis_handle, 167123474Swpaul ndis_physaddr, uint32_t); 168123474Swpaul__stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t); 169123474Swpaul__stdcall static uint32_t ndis_cachefill(void); 170123474Swpaul__stdcall static uint32_t ndis_dma_align(ndis_handle); 171123474Swpaul__stdcall static ndis_status ndis_init_sc_dma(ndis_handle, 172123474Swpaul uint8_t, uint32_t); 173123474Swpaul__stdcall static void ndis_alloc_packetpool(ndis_status *, 174123474Swpaul ndis_handle *, uint32_t, uint32_t); 175123474Swpaul__stdcall static void ndis_ex_alloc_packetpool(ndis_status *, 176123474Swpaul ndis_handle *, uint32_t, uint32_t, uint32_t); 177123474Swpaul__stdcall static uint32_t ndis_packetpool_use(ndis_handle); 178123474Swpaul__stdcall static void ndis_free_packetpool(ndis_handle); 179123474Swpaul__stdcall static void ndis_alloc_packet(ndis_status *, 180123474Swpaul ndis_packet **, ndis_handle); 181123474Swpaul__stdcall static void ndis_release_packet(ndis_packet *); 182123474Swpaul__stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **); 183123721Swpaul__stdcall static void ndis_unchain_tailbuf(ndis_packet *, ndis_buffer **); 184123474Swpaul__stdcall static void ndis_alloc_bufpool(ndis_status *, 185123474Swpaul ndis_handle *, uint32_t); 186123474Swpaul__stdcall static void ndis_free_bufpool(ndis_handle); 187123474Swpaul__stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **, 188123474Swpaul ndis_handle, void *, uint32_t); 189123474Swpaul__stdcall static void ndis_release_buf(ndis_buffer *); 190124100Swpaul__stdcall static uint32_t ndis_buflen(ndis_buffer *); 191123474Swpaul__stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *); 192123474Swpaul__stdcall static void ndis_query_buf_safe(ndis_buffer *, void **, 193123474Swpaul uint32_t *, uint32_t); 194123474Swpaul__stdcall static void ndis_adjust_buflen(ndis_buffer *, int); 195123474Swpaul__stdcall static uint32_t ndis_interlock_inc(uint32_t *); 196123474Swpaul__stdcall static uint32_t ndis_interlock_dec(uint32_t *); 197123474Swpaul__stdcall static void ndis_init_event(ndis_event *); 198123474Swpaul__stdcall static void ndis_set_event(ndis_event *); 199123474Swpaul__stdcall static void ndis_reset_event(ndis_event *); 200123474Swpaul__stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t); 201123474Swpaul__stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *, 202123474Swpaul ndis_unicode_string *); 203123526Swpaul__stdcall static ndis_status ndis_ansi2unicode(ndis_unicode_string *, 204123526Swpaul ndis_ansi_string *); 205123474Swpaul__stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle, 206123474Swpaul uint32_t, ndis_resource_list **); 207123474Swpaul__stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *, 208123474Swpaul ndis_handle, uint32_t, uint32_t, uint8_t, 209123474Swpaul uint8_t, ndis_interrupt_mode); 210123474Swpaul__stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *); 211123474Swpaul__stdcall static void ndis_register_shutdown(ndis_handle, void *, 212123474Swpaul ndis_shutdown_handler); 213123474Swpaul__stdcall static void ndis_deregister_shutdown(ndis_handle); 214123474Swpaul__stdcall static uint32_t ndis_numpages(ndis_buffer *); 215123573Swpaul__stdcall static void ndis_buf_physpages(ndis_buffer *, uint32_t *); 216123474Swpaul__stdcall static void ndis_query_bufoffset(ndis_buffer *, 217123474Swpaul uint32_t *, uint32_t *); 218123474Swpaul__stdcall static void ndis_sleep(uint32_t); 219123474Swpaul__stdcall static uint32_t ndis_read_pccard_amem(ndis_handle, 220123474Swpaul uint32_t, void *, uint32_t); 221123474Swpaul__stdcall static uint32_t ndis_write_pccard_amem(ndis_handle, 222123474Swpaul uint32_t, void *, uint32_t); 223123474Swpaul__stdcall static ndis_list_entry *ndis_insert_head(ndis_list_entry *, 224123474Swpaul ndis_list_entry *, ndis_spin_lock *); 225123474Swpaul__stdcall static ndis_list_entry *ndis_remove_head(ndis_list_entry *, 226123474Swpaul ndis_spin_lock *); 227123474Swpaul__stdcall static ndis_list_entry *ndis_insert_tail(ndis_list_entry *, 228123474Swpaul ndis_list_entry *, ndis_spin_lock *); 229123474Swpaul__stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *, 230123474Swpaul void *, void *); 231123504Swpaul__stdcall static void ndis_time(uint64_t *); 232123822Swpaul__stdcall static void ndis_uptime(uint32_t *); 233124100Swpaul__stdcall static void ndis_init_string(ndis_unicode_string *, char *); 234123526Swpaul__stdcall static void ndis_init_ansi_string(ndis_ansi_string *, char *); 235123941Swpaul__stdcall static void ndis_init_unicode_string(ndis_unicode_string *, 236123941Swpaul uint16_t *); 237123507Swpaul__stdcall static void ndis_free_string(ndis_unicode_string *); 238123507Swpaul__stdcall static ndis_status ndis_remove_miniport(ndis_handle *); 239123526Swpaul__stdcall static void ndis_termwrap(ndis_handle, void *); 240123526Swpaul__stdcall static void ndis_get_devprop(ndis_handle, void *, void *, 241123526Swpaul void *, cm_resource_list *, cm_resource_list *); 242123721Swpaul__stdcall static void ndis_firstbuf(ndis_packet *, ndis_buffer **, 243123721Swpaul void **, uint32_t *, uint32_t *); 244123721Swpaul__stdcall static void ndis_firstbuf_safe(ndis_packet *, ndis_buffer **, 245123721Swpaul void **, uint32_t *, uint32_t *, uint32_t); 246123822Swpaul__stdcall static void ndis_open_file(ndis_status *, ndis_handle *, uint32_t *, 247123822Swpaul ndis_unicode_string *, ndis_physaddr); 248123822Swpaul__stdcall static void ndis_map_file(ndis_status *, void **, ndis_handle); 249123822Swpaul__stdcall static void ndis_unmap_file(ndis_handle); 250123822Swpaul__stdcall static void ndis_close_file(ndis_handle); 251123848Swpaul__stdcall static u_int8_t ndis_cpu_cnt(void); 252124116Swpaul__stdcall static void ndis_ind_statusdone(ndis_handle); 253124116Swpaul__stdcall static void ndis_ind_status(ndis_handle, ndis_status, 254124116Swpaul void *, uint32_t); 255124122Swpaulstatic void ndis_workfunc(void *, int); 256124122Swpaul__stdcall static ndis_status ndis_sched_workitem(ndis_work_item *); 257123474Swpaul__stdcall static void dummy(void); 258123474Swpaul 259124116Swpaul/* 260124116Swpaul * Some really old drivers do not properly check the return value 261124116Swpaul * from NdisAllocatePacket() and NdisAllocateBuffer() and will 262124116Swpaul * sometimes allocate few more buffers/packets that they originally 263124116Swpaul * requested when they created the pool. To prevent this from being 264124116Swpaul * a problem, we allocate a few extra buffers/packets beyond what 265124116Swpaul * the driver asks for. This #define controls how many. 266124116Swpaul */ 267124116Swpaul#define NDIS_POOL_EXTRA 16 268123474Swpaul 269123474Swpaulint 270123474Swpaulndis_libinit() 271123474Swpaul{ 272123474Swpaul mtx_init(&ndis_interlock, "ndislock", MTX_NETWORK_LOCK, 273123474Swpaul MTX_DEF | MTX_RECURSE | MTX_DUPOK); 274123474Swpaul 275123474Swpaul return(0); 276123474Swpaul} 277123474Swpaul 278123474Swpaulint 279123474Swpaulndis_libfini() 280123474Swpaul{ 281123474Swpaul mtx_destroy(&ndis_interlock); 282123474Swpaul return(0); 283123474Swpaul} 284123474Swpaul 285123474Swpaul/* 286123474Swpaul * NDIS deals with strings in unicode format, so we have 287123474Swpaul * do deal with them that way too. For now, we only handle 288123474Swpaul * conversion between unicode and ASCII since that's all 289123474Swpaul * that device drivers care about. 290123474Swpaul */ 291123474Swpaul 292123474Swpaulint 293123474Swpaulndis_ascii_to_unicode(ascii, unicode) 294123474Swpaul char *ascii; 295123474Swpaul uint16_t **unicode; 296123474Swpaul{ 297123474Swpaul uint16_t *ustr; 298123474Swpaul int i; 299123474Swpaul 300123474Swpaul if (*unicode == NULL) 301123474Swpaul *unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK); 302123474Swpaul 303123474Swpaul if (*unicode == NULL) 304123474Swpaul return(ENOMEM); 305123474Swpaul ustr = *unicode; 306123474Swpaul for (i = 0; i < strlen(ascii); i++) { 307123474Swpaul *ustr = (uint16_t)ascii[i]; 308123474Swpaul ustr++; 309123474Swpaul } 310123474Swpaul 311123474Swpaul return(0); 312123474Swpaul} 313123474Swpaul 314123474Swpaulint 315123474Swpaulndis_unicode_to_ascii(unicode, ulen, ascii) 316123474Swpaul uint16_t *unicode; 317123474Swpaul int ulen; 318123474Swpaul char **ascii; 319123474Swpaul{ 320123474Swpaul uint8_t *astr; 321123474Swpaul int i; 322123474Swpaul 323123474Swpaul if (*ascii == NULL) 324124100Swpaul *ascii = malloc((ulen / 2) + 1, M_DEVBUF, M_WAITOK|M_ZERO); 325123474Swpaul if (*ascii == NULL) 326123474Swpaul return(ENOMEM); 327123474Swpaul astr = *ascii; 328124100Swpaul for (i = 0; i < ulen / 2; i++) { 329123474Swpaul *astr = (uint8_t)unicode[i]; 330123474Swpaul astr++; 331123474Swpaul } 332123474Swpaul 333123474Swpaul return(0); 334123474Swpaul} 335123474Swpaul 336123474Swpaul__stdcall static void 337123474Swpaulndis_initwrap(wrapper, drv_obj, path, unused) 338123474Swpaul ndis_handle wrapper; 339123474Swpaul ndis_driver_object *drv_obj; 340123474Swpaul void *path; 341123474Swpaul void *unused; 342123474Swpaul{ 343123474Swpaul ndis_driver_object **drv; 344123474Swpaul 345123474Swpaul drv = wrapper; 346123474Swpaul *drv = drv_obj; 347123474Swpaul 348123474Swpaul return; 349123474Swpaul} 350123474Swpaul 351123526Swpaul__stdcall static void 352123526Swpaulndis_termwrap(handle, syspec) 353123526Swpaul ndis_handle handle; 354123526Swpaul void *syspec; 355123526Swpaul{ 356123526Swpaul return; 357123526Swpaul} 358123526Swpaul 359123474Swpaul__stdcall static ndis_status 360123474Swpaulndis_register_miniport(handle, characteristics, len) 361123474Swpaul ndis_handle handle; 362123474Swpaul ndis_miniport_characteristics *characteristics; 363123474Swpaul int len; 364123474Swpaul{ 365123474Swpaul ndis_driver_object *drv; 366123474Swpaul 367123474Swpaul drv = handle; 368123474Swpaul bcopy((char *)characteristics, (char *)&drv->ndo_chars, 369123474Swpaul sizeof(ndis_miniport_characteristics)); 370123474Swpaul return(NDIS_STATUS_SUCCESS); 371123474Swpaul} 372123474Swpaul 373123474Swpaul__stdcall static ndis_status 374123474Swpaulndis_malloc_withtag(vaddr, len, tag) 375123474Swpaul void **vaddr; 376123474Swpaul uint32_t len; 377123474Swpaul uint32_t tag; 378123474Swpaul{ 379123474Swpaul void *mem; 380123474Swpaul 381123474Swpaul mem = malloc(len, M_DEVBUF, M_NOWAIT); 382123474Swpaul if (mem == NULL) 383123474Swpaul return(NDIS_STATUS_RESOURCES); 384123474Swpaul *vaddr = mem; 385123474Swpaul 386123474Swpaul return(NDIS_STATUS_SUCCESS); 387123474Swpaul} 388123474Swpaul 389123474Swpaul__stdcall static ndis_status 390123474Swpaulndis_malloc(vaddr, len, flags, highaddr) 391123474Swpaul void **vaddr; 392123474Swpaul uint32_t len; 393123474Swpaul uint32_t flags; 394123474Swpaul ndis_physaddr highaddr; 395123474Swpaul{ 396123474Swpaul void *mem; 397123474Swpaul 398123474Swpaul mem = malloc(len, M_DEVBUF, M_NOWAIT); 399123474Swpaul if (mem == NULL) 400123474Swpaul return(NDIS_STATUS_RESOURCES); 401123474Swpaul *vaddr = mem; 402123474Swpaul 403123474Swpaul return(NDIS_STATUS_SUCCESS); 404123474Swpaul} 405123474Swpaul 406123474Swpaul__stdcall static void 407123474Swpaulndis_free(vaddr, len, flags) 408123474Swpaul void *vaddr; 409123474Swpaul uint32_t len; 410123474Swpaul uint32_t flags; 411123474Swpaul{ 412123474Swpaul if (len == 0) 413123474Swpaul return; 414123474Swpaul free(vaddr, M_DEVBUF); 415123474Swpaul return; 416123474Swpaul} 417123474Swpaul 418123474Swpaul__stdcall static ndis_status 419123474Swpaulndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs, 420123474Swpaul flags, iftype) 421123474Swpaul ndis_handle adapter_handle; 422123474Swpaul ndis_handle adapter_ctx; 423123474Swpaul uint32_t hangsecs; 424123474Swpaul uint32_t flags; 425123474Swpaul ndis_interface_type iftype; 426123474Swpaul{ 427123474Swpaul ndis_miniport_block *block; 428123474Swpaul 429123474Swpaul /* 430123474Swpaul * Save the adapter context, we need it for calling 431123474Swpaul * the driver's internal functions. 432123474Swpaul */ 433123474Swpaul block = (ndis_miniport_block *)adapter_handle; 434123474Swpaul block->nmb_miniportadapterctx = adapter_ctx; 435123474Swpaul block->nmb_checkforhangsecs = hangsecs; 436123474Swpaul 437123474Swpaul return(NDIS_STATUS_SUCCESS); 438123474Swpaul} 439123474Swpaul 440123474Swpaul__stdcall static void 441123474Swpaulndis_open_cfg(status, cfg, wrapctx) 442123474Swpaul ndis_status *status; 443123474Swpaul ndis_handle *cfg; 444123474Swpaul ndis_handle wrapctx; 445123474Swpaul{ 446123474Swpaul *cfg = wrapctx; 447123474Swpaul *status = NDIS_STATUS_SUCCESS; 448123474Swpaul return; 449123474Swpaul} 450123474Swpaul 451123526Swpaul__stdcall static void 452123526Swpaulndis_open_cfgbyname(status, cfg, subkey, subhandle) 453123526Swpaul ndis_status *status; 454123526Swpaul ndis_handle cfg; 455123526Swpaul ndis_unicode_string *subkey; 456123526Swpaul ndis_handle *subhandle; 457123526Swpaul{ 458123526Swpaul *subhandle = cfg; 459123526Swpaul *status = NDIS_STATUS_SUCCESS; 460123526Swpaul return; 461123526Swpaul} 462123526Swpaul 463123526Swpaul__stdcall static void 464123526Swpaulndis_open_cfgbyidx(status, cfg, idx, subkey, subhandle) 465123526Swpaul ndis_status *status; 466123526Swpaul ndis_handle cfg; 467123526Swpaul uint32_t idx; 468123526Swpaul ndis_unicode_string *subkey; 469123526Swpaul ndis_handle *subhandle; 470123526Swpaul{ 471123526Swpaul *status = NDIS_STATUS_FAILURE; 472123526Swpaul return; 473123526Swpaul} 474123526Swpaul 475123474Swpaulstatic ndis_status 476123474Swpaulndis_encode_parm(block, oid, type, parm) 477123474Swpaul ndis_miniport_block *block; 478123474Swpaul struct sysctl_oid *oid; 479123474Swpaul ndis_parm_type type; 480123474Swpaul ndis_config_parm **parm; 481123474Swpaul{ 482123474Swpaul uint16_t *unicode; 483123474Swpaul ndis_unicode_string *ustr; 484123474Swpaul 485123474Swpaul unicode = (uint16_t *)&block->nmb_dummybuf; 486123474Swpaul 487123474Swpaul switch(type) { 488123474Swpaul case ndis_parm_string: 489123474Swpaul ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode); 490123474Swpaul (*parm)->ncp_type = ndis_parm_string; 491123474Swpaul ustr = &(*parm)->ncp_parmdata.ncp_stringdata; 492123474Swpaul ustr->nus_len = strlen((char *)oid->oid_arg1) * 2; 493123474Swpaul ustr->nus_buf = unicode; 494123474Swpaul break; 495123474Swpaul case ndis_parm_int: 496123474Swpaul (*parm)->ncp_type = ndis_parm_int; 497123474Swpaul (*parm)->ncp_parmdata.ncp_intdata = 498123474Swpaul strtol((char *)oid->oid_arg1, NULL, 10); 499123474Swpaul break; 500123474Swpaul case ndis_parm_hexint: 501123474Swpaul (*parm)->ncp_type = ndis_parm_hexint; 502123474Swpaul (*parm)->ncp_parmdata.ncp_intdata = 503123474Swpaul strtoul((char *)oid->oid_arg1, NULL, 16); 504123474Swpaul break; 505123474Swpaul default: 506123474Swpaul return(NDIS_STATUS_FAILURE); 507123474Swpaul break; 508123474Swpaul } 509123474Swpaul 510123474Swpaul return(NDIS_STATUS_SUCCESS); 511123474Swpaul} 512123474Swpaul 513123474Swpaul__stdcall static void 514123474Swpaulndis_read_cfg(status, parm, cfg, key, type) 515123474Swpaul ndis_status *status; 516123474Swpaul ndis_config_parm **parm; 517123474Swpaul ndis_handle cfg; 518123474Swpaul ndis_unicode_string *key; 519123474Swpaul ndis_parm_type type; 520123474Swpaul{ 521123474Swpaul char *keystr = NULL; 522123474Swpaul uint16_t *unicode; 523123474Swpaul ndis_miniport_block *block; 524123474Swpaul struct ndis_softc *sc; 525123474Swpaul struct sysctl_oid *oidp; 526123474Swpaul struct sysctl_ctx_entry *e; 527123474Swpaul 528123474Swpaul block = (ndis_miniport_block *)cfg; 529123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 530123474Swpaul 531124100Swpaul if (key->nus_len == 0 || key->nus_buf == NULL) { 532124100Swpaul *status = NDIS_STATUS_FAILURE; 533124100Swpaul return; 534124100Swpaul } 535124100Swpaul 536123474Swpaul ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr); 537123474Swpaul 538123474Swpaul *parm = &block->nmb_replyparm; 539123474Swpaul bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm)); 540123474Swpaul unicode = (uint16_t *)&block->nmb_dummybuf; 541123474Swpaul 542123474Swpaul /* 543123474Swpaul * See if registry key is already in a list of known keys 544123474Swpaul * included with the driver. 545123474Swpaul */ 546123474Swpaul TAILQ_FOREACH(e, &sc->ndis_ctx, link) { 547123474Swpaul oidp = e->entry; 548123474Swpaul if (strcmp(oidp->oid_name, keystr) == 0) { 549123488Swpaul if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) { 550123488Swpaul free(keystr, M_DEVBUF); 551123488Swpaul *status = NDIS_STATUS_FAILURE; 552123488Swpaul return; 553123488Swpaul } 554123474Swpaul *status = ndis_encode_parm(block, oidp, type, parm); 555123474Swpaul free(keystr, M_DEVBUF); 556123474Swpaul return; 557123474Swpaul } 558123474Swpaul } 559123474Swpaul 560123474Swpaul /* 561123474Swpaul * If the key didn't match, add it to the list of dynamically 562123474Swpaul * created ones. Sometimes, drivers refer to registry keys 563123474Swpaul * that aren't documented in their .INF files. These keys 564123474Swpaul * are supposed to be created by some sort of utility or 565123474Swpaul * control panel snap-in that comes with the driver software. 566123474Swpaul * Sometimes it's useful to be able to manipulate these. 567123474Swpaul * If the driver requests the key in the form of a string, 568123474Swpaul * make its default value an empty string, otherwise default 569123474Swpaul * it to "0". 570123474Swpaul */ 571123474Swpaul 572123474Swpaul if (type == ndis_parm_int || type == ndis_parm_hexint) 573123488Swpaul ndis_add_sysctl(sc, keystr, "(dynamic integer key)", 574123488Swpaul "UNSET", CTLFLAG_RW); 575123474Swpaul else 576123488Swpaul ndis_add_sysctl(sc, keystr, "(dynamic string key)", 577123488Swpaul "UNSET", CTLFLAG_RW); 578123474Swpaul 579123474Swpaul free(keystr, M_DEVBUF); 580123474Swpaul *status = NDIS_STATUS_FAILURE; 581123474Swpaul return; 582123474Swpaul} 583123474Swpaul 584123526Swpaulstatic ndis_status 585123526Swpaulndis_decode_parm(block, parm, val) 586123526Swpaul ndis_miniport_block *block; 587123526Swpaul ndis_config_parm *parm; 588123526Swpaul char *val; 589123526Swpaul{ 590123526Swpaul uint16_t *unicode; 591123526Swpaul ndis_unicode_string *ustr; 592123526Swpaul 593123526Swpaul unicode = (uint16_t *)&block->nmb_dummybuf; 594123526Swpaul 595123526Swpaul switch(parm->ncp_type) { 596123526Swpaul case ndis_parm_string: 597123526Swpaul ustr = &parm->ncp_parmdata.ncp_stringdata; 598123526Swpaul ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &val); 599123526Swpaul break; 600123526Swpaul case ndis_parm_int: 601123526Swpaul sprintf(val, "%ul", parm->ncp_parmdata.ncp_intdata); 602123526Swpaul break; 603123526Swpaul case ndis_parm_hexint: 604123526Swpaul sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata); 605123526Swpaul break; 606123526Swpaul default: 607123526Swpaul return(NDIS_STATUS_FAILURE); 608123526Swpaul break; 609123526Swpaul } 610123526Swpaul return(NDIS_STATUS_SUCCESS); 611123526Swpaul} 612123526Swpaul 613123474Swpaul__stdcall static void 614123526Swpaulndis_write_cfg(status, cfg, key, parm) 615123526Swpaul ndis_status *status; 616123526Swpaul ndis_handle cfg; 617123526Swpaul ndis_unicode_string *key; 618123526Swpaul ndis_config_parm *parm; 619123526Swpaul{ 620123526Swpaul char *keystr = NULL; 621123526Swpaul ndis_miniport_block *block; 622123526Swpaul struct ndis_softc *sc; 623123526Swpaul struct sysctl_oid *oidp; 624123526Swpaul struct sysctl_ctx_entry *e; 625123526Swpaul char val[256]; 626123526Swpaul 627123526Swpaul block = (ndis_miniport_block *)cfg; 628123526Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 629123526Swpaul 630123526Swpaul ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr); 631123526Swpaul 632123526Swpaul /* Decode the parameter into a string. */ 633123526Swpaul *status = ndis_decode_parm(block, parm, val); 634123526Swpaul if (*status != NDIS_STATUS_SUCCESS) { 635123526Swpaul free(keystr, M_DEVBUF); 636123526Swpaul return; 637123526Swpaul } 638123526Swpaul 639123526Swpaul /* See if the key already exists. */ 640123526Swpaul 641123526Swpaul TAILQ_FOREACH(e, &sc->ndis_ctx, link) { 642123526Swpaul oidp = e->entry; 643123526Swpaul if (strcmp(oidp->oid_name, keystr) == 0) { 644123526Swpaul /* Found it, set the value. */ 645123526Swpaul strcpy((char *)oidp->oid_arg1, val); 646123526Swpaul free(keystr, M_DEVBUF); 647123526Swpaul return; 648123526Swpaul } 649123526Swpaul } 650123526Swpaul 651123526Swpaul /* Not found, add a new key with the specified value. */ 652123526Swpaul ndis_add_sysctl(sc, keystr, "(dynamically set key)", 653123526Swpaul val, CTLFLAG_RW); 654123526Swpaul 655123526Swpaul free(keystr, M_DEVBUF); 656123526Swpaul *status = NDIS_STATUS_SUCCESS; 657123526Swpaul return; 658123526Swpaul} 659123526Swpaul 660123526Swpaul__stdcall static void 661123474Swpaulndis_close_cfg(cfg) 662123474Swpaul ndis_handle cfg; 663123474Swpaul{ 664123474Swpaul return; 665123474Swpaul} 666123474Swpaul 667123474Swpaul__stdcall static void 668123474Swpaulndis_create_lock(lock) 669123474Swpaul ndis_spin_lock *lock; 670123474Swpaul{ 671123474Swpaul struct mtx *mtx; 672123474Swpaul 673123474Swpaul mtx = malloc(sizeof(struct mtx), M_DEVBUF, M_NOWAIT|M_ZERO); 674123474Swpaul if (mtx == NULL) 675123474Swpaul return; 676123695Swpaul mtx_init(mtx, "ndislock", "ndis spin lock", 677123474Swpaul MTX_DEF | MTX_RECURSE | MTX_DUPOK); 678123474Swpaul lock->nsl_spinlock = (ndis_kspin_lock)mtx; 679123474Swpaul 680123474Swpaul return; 681123474Swpaul} 682123474Swpaul 683123474Swpaul__stdcall static void 684123474Swpaulndis_destroy_lock(lock) 685123474Swpaul ndis_spin_lock *lock; 686123474Swpaul{ 687123474Swpaul struct mtx *ndis_mtx; 688123474Swpaul 689123474Swpaul ndis_mtx = (struct mtx *)lock->nsl_spinlock; 690123474Swpaul mtx_destroy(ndis_mtx); 691123474Swpaul free(ndis_mtx, M_DEVBUF); 692124100Swpaul lock->nsl_spinlock = 0xdeadf00d; /* XXX */ 693123474Swpaul 694123474Swpaul return; 695123474Swpaul} 696123474Swpaul 697123474Swpaul__stdcall static void 698123474Swpaulndis_lock(lock) 699123474Swpaul ndis_spin_lock *lock; 700123474Swpaul{ 701123474Swpaul if (lock == NULL) 702123474Swpaul return; 703124100Swpaul /* 704124100Swpaul * Workaround for certain broken NDIS drivers. I have 705124100Swpaul * encountered one case where a driver creates a spinlock 706124100Swpaul * within its DriverEntry() routine, which is then destroyed 707124100Swpaul * in its MiniportHalt() routine. This is a bug, because 708124100Swpaul * MiniportHalt() is meant to only destroy what MiniportInit() 709124100Swpaul * creates. This leads to the following problem: 710124100Swpaul * DriverEntry() <- spinlock created 711124100Swpaul * MiniportInit() <- NIC initialized 712124100Swpaul * MiniportHalt() <- NIC halted, spinlock destroyed 713124100Swpaul * MiniportInit() <- NIC initialized, spinlock not recreated 714124100Swpaul * NdisAcquireSpinLock(boguslock) <- panic 715124100Swpaul * To work around this, we poison the spinlock on destroy, and 716124100Swpaul * if we try to re-acquire the poison pill^Wspinlock, we init 717124100Swpaul * it again so subsequent calls will work. 718124100Swpaul * 719124100Swpaul * Drivers that behave in this way are likely not officially 720124100Swpaul * certified by Microsoft, since their I would expect the 721124100Swpaul * Microsoft NDIS test tool to catch mistakes like this. 722124100Swpaul */ 723124100Swpaul if (lock->nsl_spinlock == 0xdeadf00d) 724124100Swpaul ndis_create_lock(lock); 725123474Swpaul mtx_lock((struct mtx *)lock->nsl_spinlock); 726123474Swpaul 727123474Swpaul return; 728123474Swpaul} 729123474Swpaul 730123474Swpaul__stdcall static void 731123474Swpaulndis_unlock(lock) 732123474Swpaul ndis_spin_lock *lock; 733123474Swpaul{ 734123474Swpaul if (lock == NULL) 735123474Swpaul return; 736123474Swpaul mtx_unlock((struct mtx *)lock->nsl_spinlock); 737123474Swpaul 738123474Swpaul return; 739123474Swpaul} 740123474Swpaul 741123474Swpaul__stdcall static uint32_t 742123474Swpaulndis_read_pci(adapter, slot, offset, buf, len) 743123474Swpaul ndis_handle adapter; 744123474Swpaul uint32_t slot; 745123474Swpaul uint32_t offset; 746123474Swpaul void *buf; 747123474Swpaul uint32_t len; 748123474Swpaul{ 749123474Swpaul ndis_miniport_block *block; 750123474Swpaul int i; 751123474Swpaul char *dest; 752123474Swpaul 753123474Swpaul block = (ndis_miniport_block *)adapter; 754123474Swpaul dest = buf; 755123474Swpaul if (block == NULL || block->nmb_dev == NULL) 756123474Swpaul return(0); 757123474Swpaul 758123474Swpaul for (i = 0; i < len; i++) 759123474Swpaul dest[i] = pci_read_config(block->nmb_dev, i + offset, 1); 760123474Swpaul 761123474Swpaul return(len); 762123474Swpaul} 763123474Swpaul 764123474Swpaul__stdcall static uint32_t 765123474Swpaulndis_write_pci(adapter, slot, offset, buf, len) 766123474Swpaul ndis_handle adapter; 767123474Swpaul uint32_t slot; 768123474Swpaul uint32_t offset; 769123474Swpaul void *buf; 770123474Swpaul uint32_t len; 771123474Swpaul{ 772123474Swpaul ndis_miniport_block *block; 773123474Swpaul int i; 774123474Swpaul char *dest; 775123474Swpaul 776123474Swpaul block = (ndis_miniport_block *)adapter; 777123474Swpaul dest = buf; 778123474Swpaul 779123474Swpaul if (block == NULL || block->nmb_dev == NULL) 780123474Swpaul return(0); 781123474Swpaul 782123474Swpaul for (i = 0; i < len; i++) 783123474Swpaul pci_write_config(block->nmb_dev, i + offset, dest[i], 1); 784123474Swpaul 785123474Swpaul return(len); 786123474Swpaul} 787123474Swpaul 788123474Swpaul/* 789123474Swpaul * The errorlog routine uses a variable argument list, so we 790123474Swpaul * have to declare it this way. 791123474Swpaul */ 792123474Swpaulstatic void 793123474Swpaulndis_syslog(ndis_handle adapter, ndis_error_code code, 794123474Swpaul uint32_t numerrors, ...) 795123474Swpaul{ 796123474Swpaul ndis_miniport_block *block; 797123474Swpaul va_list ap; 798123474Swpaul int i; 799123474Swpaul 800123474Swpaul block = (ndis_miniport_block *)adapter; 801123474Swpaul 802124060Swpaul device_printf (block->nmb_dev, "NDIS ERROR: %x\n", code); 803124060Swpaul device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors); 804123474Swpaul 805123474Swpaul va_start(ap, numerrors); 806123474Swpaul for (i = 0; i < numerrors; i++) 807124060Swpaul device_printf (block->nmb_dev, "argptr: %p\n", 808124060Swpaul va_arg(ap, void *)); 809123474Swpaul va_end(ap); 810123474Swpaul 811123474Swpaul return; 812123474Swpaul} 813123474Swpaul 814123474Swpaulstatic void 815123474Swpaulndis_map_cb(arg, segs, nseg, error) 816123474Swpaul void *arg; 817123474Swpaul bus_dma_segment_t *segs; 818123474Swpaul int nseg; 819123474Swpaul int error; 820123474Swpaul{ 821123474Swpaul struct ndis_map_arg *ctx; 822123474Swpaul int i; 823123474Swpaul 824123474Swpaul if (error) 825123474Swpaul return; 826123474Swpaul 827123474Swpaul ctx = arg; 828123474Swpaul 829123474Swpaul for (i = 0; i < nseg; i++) { 830123474Swpaul ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr; 831123474Swpaul ctx->nma_fraglist[i].npu_len = segs[i].ds_len; 832123474Swpaul } 833123474Swpaul 834123474Swpaul ctx->nma_cnt = nseg; 835123474Swpaul 836123474Swpaul return; 837123474Swpaul} 838123474Swpaul 839123474Swpaul__stdcall static void 840123474Swpaulndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize) 841123474Swpaul ndis_handle adapter; 842123474Swpaul ndis_buffer *buf; 843123474Swpaul uint32_t mapreg; 844123474Swpaul uint8_t writedev; 845123474Swpaul ndis_paddr_unit *addrarray; 846123474Swpaul uint32_t *arraysize; 847123474Swpaul{ 848123474Swpaul ndis_miniport_block *block; 849123474Swpaul struct ndis_softc *sc; 850123474Swpaul struct ndis_map_arg nma; 851123474Swpaul bus_dmamap_t map; 852123474Swpaul int error; 853123474Swpaul 854123474Swpaul if (adapter == NULL) 855123474Swpaul return; 856123474Swpaul 857123474Swpaul block = (ndis_miniport_block *)adapter; 858123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 859123474Swpaul 860123474Swpaul if (mapreg > sc->ndis_mmapcnt) 861123474Swpaul return; 862123474Swpaul 863123474Swpaul map = sc->ndis_mmaps[mapreg]; 864123474Swpaul nma.nma_fraglist = addrarray; 865123474Swpaul 866123474Swpaul error = bus_dmamap_load(sc->ndis_mtag, map, 867123757Swpaul MDL_VA(buf), buf->nb_bytecount, ndis_map_cb, 868123474Swpaul (void *)&nma, BUS_DMA_NOWAIT); 869123474Swpaul 870123474Swpaul if (error) 871123474Swpaul return; 872123474Swpaul 873123474Swpaul bus_dmamap_sync(sc->ndis_mtag, map, 874123474Swpaul writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD); 875123474Swpaul 876123474Swpaul *arraysize = nma.nma_cnt; 877123474Swpaul 878123474Swpaul return; 879123474Swpaul} 880123474Swpaul 881123474Swpaul__stdcall static void 882123474Swpaulndis_vtophys_unload(adapter, buf, mapreg) 883123474Swpaul ndis_handle adapter; 884123474Swpaul ndis_buffer *buf; 885123474Swpaul uint32_t mapreg; 886123474Swpaul{ 887123474Swpaul ndis_miniport_block *block; 888123474Swpaul struct ndis_softc *sc; 889123474Swpaul bus_dmamap_t map; 890123474Swpaul 891123474Swpaul if (adapter == NULL) 892123474Swpaul return; 893123474Swpaul 894123474Swpaul block = (ndis_miniport_block *)adapter; 895123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 896123474Swpaul 897123474Swpaul if (mapreg > sc->ndis_mmapcnt) 898123474Swpaul return; 899123474Swpaul 900123474Swpaul map = sc->ndis_mmaps[mapreg]; 901123474Swpaul 902123474Swpaul bus_dmamap_sync(sc->ndis_mtag, map, 903123474Swpaul BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 904123474Swpaul 905123474Swpaul bus_dmamap_unload(sc->ndis_mtag, map); 906123474Swpaul 907123474Swpaul return; 908123474Swpaul} 909123474Swpaul 910123474Swpaul__stdcall static void 911123474Swpaulndis_create_timer(timer, handle, func, ctx) 912123474Swpaul ndis_miniport_timer *timer; 913123474Swpaul ndis_handle *handle; 914123474Swpaul ndis_timer_function func; 915123474Swpaul void *ctx; 916123474Swpaul{ 917123821Swpaul struct ndis_timer_entry *ne = NULL; 918123821Swpaul ndis_miniport_block *block; 919123821Swpaul block = (ndis_miniport_block *)handle; 920123474Swpaul 921123821Swpaul ne = malloc(sizeof(struct ndis_timer_entry), M_DEVBUF, M_NOWAIT); 922123832Swpaul callout_init(&ne->nte_ch, CALLOUT_MPSAFE); 923123821Swpaul TAILQ_INSERT_TAIL(&block->nmb_timerlist, ne, link); 924123821Swpaul ne->nte_timer = timer; 925123821Swpaul 926123821Swpaul timer->nmt_ktimer.nk_header.dh_sigstate = TRUE; 927123821Swpaul timer->nmt_dpc.nk_deferredctx = &ne->nte_ch; 928123474Swpaul timer->nmt_timerfunc = func; 929123474Swpaul timer->nmt_timerctx = ctx; 930123474Swpaul 931123474Swpaul return; 932123474Swpaul} 933123474Swpaul 934123474Swpaul/* 935123474Swpaul * The driver's timer callout is __stdcall function, so we need this 936123474Swpaul * intermediate step. 937123474Swpaul */ 938123474Swpaul 939123474Swpaulstatic void 940123474Swpaulndis_timercall(arg) 941123474Swpaul void *arg; 942123474Swpaul{ 943123474Swpaul ndis_miniport_timer *timer; 944123474Swpaul __stdcall ndis_timer_function timerfunc; 945123474Swpaul 946123474Swpaul timer = arg; 947123474Swpaul 948123821Swpaul timer->nmt_ktimer.nk_header.dh_sigstate = FALSE; 949123474Swpaul timerfunc = timer->nmt_timerfunc; 950123474Swpaul timerfunc(NULL, timer->nmt_timerctx, NULL, NULL); 951123474Swpaul 952123474Swpaul return; 953123474Swpaul} 954123474Swpaul 955123474Swpaul/* 956123474Swpaul * Windows specifies timeouts in milliseconds. We specify timeouts 957123474Swpaul * in hz. Trying to compute a tenth of a second based on hz is tricky. 958123474Swpaul * so we approximate. Note that we abuse the dpc portion of the 959123474Swpaul * miniport timer structure to hold the UNIX callout handle. 960123474Swpaul */ 961123474Swpaul__stdcall static void 962123474Swpaulndis_set_timer(timer, msecs) 963123474Swpaul ndis_miniport_timer *timer; 964123474Swpaul uint32_t msecs; 965123474Swpaul{ 966123832Swpaul struct callout *ch; 967123474Swpaul struct timeval tv; 968123474Swpaul 969123474Swpaul tv.tv_sec = 0; 970123474Swpaul tv.tv_usec = msecs * 1000; 971123474Swpaul 972123821Swpaul ch = timer->nmt_dpc.nk_deferredctx; 973123474Swpaul timer->nmt_dpc.nk_sysarg2 = ndis_timercall; 974123821Swpaul timer->nmt_ktimer.nk_header.dh_sigstate = TRUE; 975123832Swpaul callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer); 976123474Swpaul 977123474Swpaul return; 978123474Swpaul} 979123474Swpaul 980123474Swpaulstatic void 981123474Swpaulndis_tick(arg) 982123474Swpaul void *arg; 983123474Swpaul{ 984123474Swpaul ndis_miniport_timer *timer; 985123832Swpaul struct callout *ch; 986123474Swpaul __stdcall ndis_timer_function timerfunc; 987123474Swpaul struct timeval tv; 988123474Swpaul 989123474Swpaul timer = arg; 990123474Swpaul 991123821Swpaul timer->nmt_ktimer.nk_header.dh_sigstate = FALSE; 992123474Swpaul timerfunc = timer->nmt_timerfunc; 993123474Swpaul timerfunc(NULL, timer->nmt_timerctx, NULL, NULL); 994123474Swpaul 995123474Swpaul /* Automatically reload timer. */ 996123474Swpaul 997123474Swpaul tv.tv_sec = 0; 998123474Swpaul tv.tv_usec = timer->nmt_ktimer.nk_period * 1000; 999123821Swpaul ch = timer->nmt_dpc.nk_deferredctx; 1000123821Swpaul timer->nmt_ktimer.nk_header.dh_sigstate = TRUE; 1001123474Swpaul timer->nmt_dpc.nk_sysarg2 = ndis_tick; 1002123832Swpaul callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer); 1003123474Swpaul 1004123474Swpaul return; 1005123474Swpaul} 1006123474Swpaul 1007123474Swpaul__stdcall static void 1008123474Swpaulndis_set_periodic_timer(timer, msecs) 1009123474Swpaul ndis_miniport_timer *timer; 1010123474Swpaul uint32_t msecs; 1011123474Swpaul{ 1012123832Swpaul struct callout *ch; 1013123474Swpaul struct timeval tv; 1014123474Swpaul 1015123474Swpaul tv.tv_sec = 0; 1016123474Swpaul tv.tv_usec = msecs * 1000; 1017123474Swpaul 1018123474Swpaul timer->nmt_ktimer.nk_period = msecs; 1019123821Swpaul ch = timer->nmt_dpc.nk_deferredctx; 1020123474Swpaul timer->nmt_dpc.nk_sysarg2 = ndis_tick; 1021123821Swpaul timer->nmt_ktimer.nk_header.dh_sigstate = TRUE; 1022123832Swpaul callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer); 1023123474Swpaul 1024123474Swpaul return; 1025123474Swpaul} 1026123474Swpaul 1027123474Swpaul__stdcall static void 1028123474Swpaulndis_cancel_timer(timer, cancelled) 1029123474Swpaul ndis_miniport_timer *timer; 1030123474Swpaul uint8_t *cancelled; 1031123474Swpaul{ 1032123832Swpaul struct callout *ch; 1033123474Swpaul 1034124097Swpaul if (timer == NULL) 1035124097Swpaul return; 1036123821Swpaul ch = timer->nmt_dpc.nk_deferredctx; 1037124097Swpaul if (ch == NULL) 1038124097Swpaul return; 1039123832Swpaul callout_stop(ch); 1040123821Swpaul *cancelled = timer->nmt_ktimer.nk_header.dh_sigstate; 1041123474Swpaul 1042123474Swpaul return; 1043123474Swpaul} 1044123474Swpaul 1045123474Swpaul__stdcall static void 1046123474Swpaulndis_query_resources(status, adapter, list, buflen) 1047123474Swpaul ndis_status *status; 1048123474Swpaul ndis_handle adapter; 1049123474Swpaul ndis_resource_list *list; 1050123474Swpaul uint32_t *buflen; 1051123474Swpaul{ 1052123474Swpaul ndis_miniport_block *block; 1053123474Swpaul struct ndis_softc *sc; 1054124094Swpaul int rsclen; 1055123474Swpaul 1056123474Swpaul block = (ndis_miniport_block *)adapter; 1057123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1058124094Swpaul 1059124094Swpaul rsclen = sizeof(ndis_resource_list) + 1060123474Swpaul (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)); 1061124094Swpaul if (*buflen < rsclen) { 1062124094Swpaul *buflen = rsclen; 1063124094Swpaul *status = NDIS_STATUS_INVALID_LENGTH; 1064124094Swpaul return; 1065124094Swpaul } 1066123474Swpaul 1067123474Swpaul bcopy((char *)block->nmb_rlist, (char *)list, *buflen); 1068123474Swpaul *status = NDIS_STATUS_SUCCESS; 1069123474Swpaul return; 1070123474Swpaul} 1071123474Swpaul 1072123474Swpaul__stdcall static ndis_status 1073123474Swpaulndis_register_ioport(offset, adapter, port, numports) 1074123474Swpaul void **offset; 1075123474Swpaul ndis_handle adapter; 1076123474Swpaul uint32_t port; 1077123474Swpaul uint32_t numports; 1078123474Swpaul{ 1079123474Swpaul struct ndis_miniport_block *block; 1080123474Swpaul struct ndis_softc *sc; 1081123474Swpaul 1082123474Swpaul if (adapter == NULL) 1083123474Swpaul return(NDIS_STATUS_FAILURE); 1084123474Swpaul 1085123474Swpaul block = (ndis_miniport_block *)adapter; 1086123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 1087123474Swpaul 1088123474Swpaul if (sc->ndis_res_io == NULL) 1089123474Swpaul return(NDIS_STATUS_FAILURE); 1090123474Swpaul 1091123474Swpaul if (rman_get_size(sc->ndis_res_io) != numports) 1092123474Swpaul return(NDIS_STATUS_INVALID_LENGTH); 1093123474Swpaul 1094123474Swpaul *offset = (void *)rman_get_start(sc->ndis_res_io); 1095123474Swpaul 1096123474Swpaul return(NDIS_STATUS_SUCCESS); 1097123474Swpaul} 1098123474Swpaul 1099123474Swpaul__stdcall static void 1100123474Swpaulndis_deregister_ioport(adapter, port, numports, offset) 1101123474Swpaul ndis_handle adapter; 1102123474Swpaul uint32_t port; 1103123474Swpaul uint32_t numports; 1104123474Swpaul void *offset; 1105123474Swpaul{ 1106123474Swpaul return; 1107123474Swpaul} 1108123474Swpaul 1109123474Swpaul__stdcall static void 1110123474Swpaulndis_read_netaddr(status, addr, addrlen, adapter) 1111123474Swpaul ndis_status *status; 1112123474Swpaul void **addr; 1113123474Swpaul uint32_t *addrlen; 1114123474Swpaul ndis_handle adapter; 1115123474Swpaul{ 1116123474Swpaul struct ndis_softc *sc; 1117123474Swpaul ndis_miniport_block *block; 1118123474Swpaul uint8_t empty[] = { 0, 0, 0, 0, 0, 0 }; 1119123474Swpaul 1120123474Swpaul block = (ndis_miniport_block *)adapter; 1121123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1122123474Swpaul 1123123474Swpaul if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0) 1124123474Swpaul *status = NDIS_STATUS_FAILURE; 1125123474Swpaul else { 1126123474Swpaul *addr = sc->arpcom.ac_enaddr; 1127123474Swpaul *addrlen = ETHER_ADDR_LEN; 1128123474Swpaul *status = NDIS_STATUS_SUCCESS; 1129123474Swpaul } 1130123474Swpaul 1131123474Swpaul return; 1132123474Swpaul} 1133123474Swpaul 1134123474Swpaul__stdcall static ndis_status 1135123848Swpaulndis_mapreg_cnt(bustype, cnt) 1136123848Swpaul uint32_t bustype; 1137123848Swpaul uint32_t *cnt; 1138123848Swpaul{ 1139124097Swpaul *cnt = 8192; 1140123848Swpaul return(NDIS_STATUS_SUCCESS); 1141123848Swpaul} 1142123848Swpaul 1143123848Swpaul__stdcall static ndis_status 1144123474Swpaulndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap) 1145123474Swpaul ndis_handle adapter; 1146123474Swpaul uint32_t dmachannel; 1147123474Swpaul uint8_t dmasize; 1148123474Swpaul uint32_t physmapneeded; 1149123474Swpaul uint32_t maxmap; 1150123474Swpaul{ 1151123474Swpaul struct ndis_softc *sc; 1152123474Swpaul ndis_miniport_block *block; 1153123474Swpaul int error, i, nseg = NDIS_MAXSEG; 1154123474Swpaul 1155123474Swpaul block = (ndis_miniport_block *)adapter; 1156123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1157123474Swpaul 1158123474Swpaul sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded, 1159123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 1160123474Swpaul 1161123474Swpaul if (sc->ndis_mmaps == NULL) 1162123474Swpaul return(NDIS_STATUS_RESOURCES); 1163123474Swpaul 1164123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 1165123474Swpaul BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, 1166123474Swpaul NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW, 1167123474Swpaul NULL, NULL, &sc->ndis_mtag); 1168123474Swpaul 1169123474Swpaul if (error) { 1170123474Swpaul free(sc->ndis_mmaps, M_DEVBUF); 1171123474Swpaul return(NDIS_STATUS_RESOURCES); 1172123474Swpaul } 1173123474Swpaul 1174123474Swpaul for (i = 0; i < physmapneeded; i++) 1175123474Swpaul bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]); 1176123474Swpaul 1177123474Swpaul sc->ndis_mmapcnt = physmapneeded; 1178123474Swpaul 1179123474Swpaul return(NDIS_STATUS_SUCCESS); 1180123474Swpaul} 1181123474Swpaul 1182123474Swpaul__stdcall static void 1183123474Swpaulndis_free_mapreg(adapter) 1184123474Swpaul ndis_handle adapter; 1185123474Swpaul{ 1186123474Swpaul struct ndis_softc *sc; 1187123474Swpaul ndis_miniport_block *block; 1188123474Swpaul int i; 1189123474Swpaul 1190123474Swpaul block = (ndis_miniport_block *)adapter; 1191123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1192123474Swpaul 1193123474Swpaul for (i = 0; i < sc->ndis_mmapcnt; i++) 1194123474Swpaul bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]); 1195123474Swpaul 1196123474Swpaul free(sc->ndis_mmaps, M_DEVBUF); 1197123474Swpaul 1198123474Swpaul bus_dma_tag_destroy(sc->ndis_mtag); 1199123474Swpaul 1200123474Swpaul return; 1201123474Swpaul} 1202123474Swpaul 1203123474Swpaulstatic void 1204123474Swpaulndis_mapshared_cb(arg, segs, nseg, error) 1205123474Swpaul void *arg; 1206123474Swpaul bus_dma_segment_t *segs; 1207123474Swpaul int nseg; 1208123474Swpaul int error; 1209123474Swpaul{ 1210123474Swpaul ndis_physaddr *p; 1211123474Swpaul 1212123474Swpaul if (error || nseg > 1) 1213123474Swpaul return; 1214123474Swpaul 1215123474Swpaul p = arg; 1216123474Swpaul 1217123474Swpaul p->np_quad = segs[0].ds_addr; 1218123474Swpaul 1219123474Swpaul return; 1220123474Swpaul} 1221123474Swpaul 1222123474Swpaul/* 1223123474Swpaul * This maps to bus_dmamem_alloc(). 1224123474Swpaul */ 1225123474Swpaul__stdcall static void 1226123474Swpaulndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr) 1227123474Swpaul ndis_handle adapter; 1228123474Swpaul uint32_t len; 1229123474Swpaul uint8_t cached; 1230123474Swpaul void **vaddr; 1231123474Swpaul ndis_physaddr *paddr; 1232123474Swpaul{ 1233123474Swpaul ndis_miniport_block *block; 1234123474Swpaul struct ndis_softc *sc; 1235123474Swpaul struct ndis_shmem *sh; 1236123474Swpaul int error; 1237123474Swpaul 1238123474Swpaul if (adapter == NULL) 1239123474Swpaul return; 1240123474Swpaul 1241123474Swpaul block = (ndis_miniport_block *)adapter; 1242123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 1243123474Swpaul 1244123474Swpaul sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO); 1245123474Swpaul if (sh == NULL) 1246123474Swpaul return; 1247123474Swpaul 1248123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, 64, 1249123474Swpaul 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, 1250123474Swpaul NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL, 1251123474Swpaul &sh->ndis_stag); 1252123474Swpaul 1253123474Swpaul if (error) { 1254123474Swpaul free(sh, M_DEVBUF); 1255123474Swpaul return; 1256123474Swpaul } 1257123474Swpaul 1258123474Swpaul error = bus_dmamem_alloc(sh->ndis_stag, vaddr, 1259123474Swpaul BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap); 1260123474Swpaul 1261123474Swpaul if (error) { 1262123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1263123474Swpaul free(sh, M_DEVBUF); 1264123474Swpaul return; 1265123474Swpaul } 1266123474Swpaul 1267123474Swpaul error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr, 1268123474Swpaul len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT); 1269123474Swpaul 1270123474Swpaul if (error) { 1271123474Swpaul bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap); 1272123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1273123474Swpaul free(sh, M_DEVBUF); 1274123474Swpaul return; 1275123474Swpaul } 1276123474Swpaul 1277123474Swpaul sh->ndis_saddr = *vaddr; 1278123474Swpaul sh->ndis_next = sc->ndis_shlist; 1279123474Swpaul sc->ndis_shlist = sh; 1280123474Swpaul 1281123474Swpaul return; 1282123474Swpaul} 1283123474Swpaul 1284123474Swpaul__stdcall static void 1285123474Swpaulndis_alloc_sharedmem_async(adapter, len, cached, ctx) 1286123474Swpaul ndis_handle adapter; 1287123474Swpaul uint32_t len; 1288123474Swpaul uint8_t cached; 1289123474Swpaul void *ctx; 1290123474Swpaul{ 1291123474Swpaul ndis_miniport_block *block; 1292123474Swpaul struct ndis_softc *sc; 1293123474Swpaul void *vaddr; 1294123474Swpaul ndis_physaddr paddr; 1295123474Swpaul __stdcall ndis_allocdone_handler donefunc; 1296123474Swpaul 1297123474Swpaul if (adapter == NULL) 1298123474Swpaul return; 1299123474Swpaul 1300123474Swpaul block = (ndis_miniport_block *)adapter; 1301123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 1302123474Swpaul donefunc = sc->ndis_chars.nmc_allocate_complete_func; 1303123474Swpaul 1304123474Swpaul ndis_alloc_sharedmem(adapter, len, cached, &vaddr, &paddr); 1305123474Swpaul donefunc(adapter, vaddr, &paddr, len, ctx); 1306123474Swpaul 1307123474Swpaul return; 1308123474Swpaul} 1309123474Swpaul 1310123474Swpaul__stdcall static void 1311123474Swpaulndis_free_sharedmem(adapter, len, cached, vaddr, paddr) 1312123474Swpaul ndis_handle adapter; 1313123474Swpaul uint32_t len; 1314123474Swpaul uint8_t cached; 1315123474Swpaul void *vaddr; 1316123474Swpaul ndis_physaddr paddr; 1317123474Swpaul{ 1318123474Swpaul ndis_miniport_block *block; 1319123474Swpaul struct ndis_softc *sc; 1320123474Swpaul struct ndis_shmem *sh, *prev; 1321123474Swpaul 1322123474Swpaul if (vaddr == NULL || adapter == NULL) 1323123474Swpaul return; 1324123474Swpaul 1325123474Swpaul block = (ndis_miniport_block *)adapter; 1326123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 1327123474Swpaul sh = prev = sc->ndis_shlist; 1328123474Swpaul 1329123474Swpaul while (sh) { 1330123474Swpaul if (sh->ndis_saddr == vaddr) 1331123474Swpaul break; 1332123474Swpaul prev = sh; 1333123474Swpaul sh = sh->ndis_next; 1334123474Swpaul } 1335123474Swpaul 1336123474Swpaul bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap); 1337123474Swpaul bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap); 1338123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1339123474Swpaul 1340123474Swpaul if (sh == sc->ndis_shlist) 1341123474Swpaul sc->ndis_shlist = sh->ndis_next; 1342123474Swpaul else 1343123474Swpaul prev->ndis_next = sh->ndis_next; 1344123474Swpaul 1345123474Swpaul free(sh, M_DEVBUF); 1346123474Swpaul 1347123474Swpaul return; 1348123474Swpaul} 1349123474Swpaul 1350123474Swpaul__stdcall static ndis_status 1351123474Swpaulndis_map_iospace(vaddr, adapter, paddr, len) 1352123474Swpaul void **vaddr; 1353123474Swpaul ndis_handle adapter; 1354123474Swpaul ndis_physaddr paddr; 1355123474Swpaul uint32_t len; 1356123474Swpaul{ 1357123474Swpaul ndis_miniport_block *block; 1358123474Swpaul struct ndis_softc *sc; 1359123474Swpaul 1360123474Swpaul if (adapter == NULL) 1361123474Swpaul return(NDIS_STATUS_FAILURE); 1362123474Swpaul 1363123474Swpaul block = (ndis_miniport_block *)adapter; 1364123474Swpaul sc = (struct ndis_softc *)(block->nmb_ifp); 1365123474Swpaul 1366123474Swpaul if (sc->ndis_res_mem == NULL) 1367123474Swpaul return(NDIS_STATUS_FAILURE); 1368123474Swpaul 1369123474Swpaul *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem); 1370123474Swpaul 1371123474Swpaul return(NDIS_STATUS_SUCCESS); 1372123474Swpaul} 1373123474Swpaul 1374123474Swpaul__stdcall static void 1375123474Swpaulndis_unmap_iospace(adapter, vaddr, len) 1376123474Swpaul ndis_handle adapter; 1377123474Swpaul void *vaddr; 1378123474Swpaul uint32_t len; 1379123474Swpaul{ 1380123474Swpaul return; 1381123474Swpaul} 1382123474Swpaul 1383123474Swpaul__stdcall static uint32_t 1384123474Swpaulndis_cachefill(void) 1385123474Swpaul{ 1386123474Swpaul return(128); 1387123474Swpaul} 1388123474Swpaul 1389123474Swpaul__stdcall static uint32_t 1390123474Swpaulndis_dma_align(handle) 1391123474Swpaul ndis_handle handle; 1392123474Swpaul{ 1393123474Swpaul return(128); 1394123474Swpaul} 1395123474Swpaul 1396123474Swpaul/* 1397123474Swpaul * NDIS has two methods for dealing with NICs that support DMA. 1398123474Swpaul * One is to just pass packets to the driver and let it call 1399123474Swpaul * NdisMStartBufferPhysicalMapping() to map each buffer in the packet 1400123474Swpaul * all by itself, and the other is to let the NDIS library handle the 1401123474Swpaul * buffer mapping internally, and hand the driver an already populated 1402123474Swpaul * scatter/gather fragment list. If the driver calls 1403123474Swpaul * NdisMInitializeScatterGatherDma(), it wants to use the latter 1404123474Swpaul * method. 1405123474Swpaul */ 1406123474Swpaul 1407123474Swpaul__stdcall static ndis_status 1408123474Swpaulndis_init_sc_dma(adapter, is64, maxphysmap) 1409123474Swpaul ndis_handle adapter; 1410123474Swpaul uint8_t is64; 1411123474Swpaul uint32_t maxphysmap; 1412123474Swpaul{ 1413123474Swpaul struct ndis_softc *sc; 1414123474Swpaul ndis_miniport_block *block; 1415123474Swpaul int error; 1416123474Swpaul 1417123474Swpaul if (adapter == NULL) 1418123474Swpaul return(NDIS_STATUS_FAILURE); 1419123474Swpaul block = (ndis_miniport_block *)adapter; 1420123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1421123474Swpaul 1422123474Swpaul /* Don't do this twice. */ 1423123474Swpaul if (sc->ndis_sc == 1) 1424123474Swpaul return(NDIS_STATUS_SUCCESS); 1425123474Swpaul 1426123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 1427123474Swpaul BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 1428123474Swpaul MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW, 1429123474Swpaul NULL, NULL, &sc->ndis_ttag); 1430123474Swpaul 1431123474Swpaul sc->ndis_sc = 1; 1432123474Swpaul 1433123474Swpaul return(NDIS_STATUS_SUCCESS); 1434123474Swpaul} 1435123474Swpaul 1436123474Swpaul__stdcall static void 1437123474Swpaulndis_alloc_packetpool(status, pool, descnum, protrsvdlen) 1438123474Swpaul ndis_status *status; 1439123474Swpaul ndis_handle *pool; 1440123474Swpaul uint32_t descnum; 1441123474Swpaul uint32_t protrsvdlen; 1442123474Swpaul{ 1443123474Swpaul ndis_packet *cur; 1444123474Swpaul int i; 1445123474Swpaul 1446124116Swpaul *pool = malloc(sizeof(ndis_packet) * 1447124116Swpaul ((descnum + NDIS_POOL_EXTRA) + 1), 1448123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 1449123474Swpaul 1450123474Swpaul if (pool == NULL) { 1451123474Swpaul *status = NDIS_STATUS_RESOURCES; 1452123474Swpaul return; 1453123474Swpaul } 1454123474Swpaul 1455123474Swpaul cur = (ndis_packet *)*pool; 1456123474Swpaul cur->np_private.npp_flags = 0x1; /* mark the head of the list */ 1457124116Swpaul for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) { 1458123474Swpaul cur->np_private.npp_head = (ndis_handle)(cur + 1); 1459123474Swpaul cur++; 1460123474Swpaul } 1461123474Swpaul 1462123474Swpaul *status = NDIS_STATUS_SUCCESS; 1463123474Swpaul return; 1464123474Swpaul} 1465123474Swpaul 1466123474Swpaul__stdcall static void 1467123474Swpaulndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen) 1468123474Swpaul ndis_status *status; 1469123474Swpaul ndis_handle *pool; 1470123474Swpaul uint32_t descnum; 1471123474Swpaul uint32_t oflowdescnum; 1472123474Swpaul uint32_t protrsvdlen; 1473123474Swpaul{ 1474123474Swpaul return(ndis_alloc_packetpool(status, pool, 1475123474Swpaul descnum + oflowdescnum, protrsvdlen)); 1476123474Swpaul} 1477123474Swpaul 1478123474Swpaul__stdcall static uint32_t 1479123474Swpaulndis_packetpool_use(pool) 1480123474Swpaul ndis_handle pool; 1481123474Swpaul{ 1482123474Swpaul ndis_packet *head; 1483123474Swpaul 1484123474Swpaul head = (ndis_packet *)pool; 1485123474Swpaul 1486123474Swpaul return(head->np_private.npp_count); 1487123474Swpaul} 1488123474Swpaul 1489123474Swpaul__stdcall static void 1490123474Swpaulndis_free_packetpool(pool) 1491123474Swpaul ndis_handle pool; 1492123474Swpaul{ 1493123474Swpaul free(pool, M_DEVBUF); 1494123474Swpaul return; 1495123474Swpaul} 1496123474Swpaul 1497123474Swpaul__stdcall static void 1498123474Swpaulndis_alloc_packet(status, packet, pool) 1499123474Swpaul ndis_status *status; 1500123474Swpaul ndis_packet **packet; 1501123474Swpaul ndis_handle pool; 1502123474Swpaul{ 1503123474Swpaul ndis_packet *head, *pkt; 1504123474Swpaul 1505123474Swpaul head = (ndis_packet *)pool; 1506123474Swpaul 1507123474Swpaul if (head->np_private.npp_flags != 0x1) { 1508123474Swpaul *status = NDIS_STATUS_FAILURE; 1509123474Swpaul return; 1510123474Swpaul } 1511123474Swpaul 1512123474Swpaul pkt = (ndis_packet *)head->np_private.npp_head; 1513123474Swpaul 1514123474Swpaul if (pkt == NULL) { 1515123474Swpaul *status = NDIS_STATUS_RESOURCES; 1516123474Swpaul return; 1517123474Swpaul } 1518123474Swpaul 1519123474Swpaul head->np_private.npp_head = pkt->np_private.npp_head; 1520123474Swpaul 1521123474Swpaul pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL; 1522123474Swpaul /* Save pointer to the pool. */ 1523123474Swpaul pkt->np_private.npp_pool = head; 1524123474Swpaul 1525123474Swpaul /* Set the oob offset pointer. Lots of things expect this. */ 1526123474Swpaul pkt->np_private.npp_packetooboffset = 1527123474Swpaul offsetof(ndis_packet, np_oob); 1528123474Swpaul 1529123474Swpaul *packet = pkt; 1530123474Swpaul 1531123474Swpaul head->np_private.npp_count++; 1532123474Swpaul *status = NDIS_STATUS_SUCCESS; 1533123474Swpaul return; 1534123474Swpaul} 1535123474Swpaul 1536123848Swpaul__stdcall static void 1537123848Swpaulndis_release_packet(packet) 1538123474Swpaul ndis_packet *packet; 1539123474Swpaul{ 1540123474Swpaul ndis_packet *head; 1541123474Swpaul 1542123474Swpaul if (packet == NULL || packet->np_private.npp_pool == NULL) 1543123474Swpaul return; 1544123474Swpaul 1545123474Swpaul head = packet->np_private.npp_pool; 1546123474Swpaul if (head->np_private.npp_flags != 0x1) 1547123474Swpaul return; 1548123474Swpaul 1549123474Swpaul packet->np_private.npp_head = head->np_private.npp_head; 1550123474Swpaul head->np_private.npp_head = (ndis_buffer *)packet; 1551123474Swpaul head->np_private.npp_count--; 1552123474Swpaul 1553123474Swpaul return; 1554123474Swpaul} 1555123474Swpaul 1556123474Swpaul__stdcall static void 1557123474Swpaulndis_unchain_headbuf(packet, buf) 1558123474Swpaul ndis_packet *packet; 1559123474Swpaul ndis_buffer **buf; 1560123474Swpaul{ 1561123474Swpaul ndis_packet_private *priv; 1562123474Swpaul 1563123474Swpaul if (packet == NULL || buf == NULL) 1564123474Swpaul return; 1565123474Swpaul 1566123474Swpaul priv = &packet->np_private; 1567123474Swpaul 1568123474Swpaul priv->npp_validcounts = FALSE; 1569123474Swpaul 1570123474Swpaul if (priv->npp_head == priv->npp_tail) { 1571123474Swpaul *buf = priv->npp_head; 1572123474Swpaul priv->npp_head = priv->npp_tail = NULL; 1573123474Swpaul } else { 1574123474Swpaul *buf = priv->npp_head; 1575123474Swpaul priv->npp_head = (*buf)->nb_next; 1576123474Swpaul } 1577123474Swpaul 1578123474Swpaul return; 1579123474Swpaul} 1580123474Swpaul 1581123721Swpaul__stdcall static void 1582123721Swpaulndis_unchain_tailbuf(packet, buf) 1583123721Swpaul ndis_packet *packet; 1584123721Swpaul ndis_buffer **buf; 1585123721Swpaul{ 1586123721Swpaul ndis_packet_private *priv; 1587123721Swpaul ndis_buffer *tmp; 1588123721Swpaul 1589123721Swpaul if (packet == NULL || buf == NULL) 1590123721Swpaul return; 1591123721Swpaul 1592123721Swpaul priv = &packet->np_private; 1593123721Swpaul 1594123721Swpaul priv->npp_validcounts = FALSE; 1595123721Swpaul 1596123721Swpaul if (priv->npp_head == priv->npp_tail) { 1597123721Swpaul *buf = priv->npp_head; 1598123721Swpaul priv->npp_head = priv->npp_tail = NULL; 1599123721Swpaul } else { 1600123721Swpaul *buf = priv->npp_tail; 1601123721Swpaul tmp = priv->npp_head; 1602123721Swpaul while (tmp->nb_next != priv->npp_tail) 1603123721Swpaul tmp = tmp->nb_next; 1604123721Swpaul priv->npp_tail = tmp; 1605123721Swpaul tmp->nb_next = NULL; 1606123721Swpaul } 1607123721Swpaul 1608123721Swpaul return; 1609123721Swpaul} 1610123721Swpaul 1611123474Swpaul/* 1612123474Swpaul * The NDIS "buffer" manipulation functions are somewhat misnamed. 1613123474Swpaul * They don't really allocate buffers: they allocate buffer mappings. 1614123474Swpaul * The idea is you reserve a chunk of DMA-able memory using 1615123474Swpaul * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer() 1616123474Swpaul * to obtain the virtual address of the DMA-able region. 1617123474Swpaul * ndis_alloc_bufpool() is analagous to bus_dma_tag_create(). 1618123474Swpaul */ 1619123474Swpaul 1620123474Swpaul__stdcall static void 1621123474Swpaulndis_alloc_bufpool(status, pool, descnum) 1622123474Swpaul ndis_status *status; 1623123474Swpaul ndis_handle *pool; 1624123474Swpaul uint32_t descnum; 1625123474Swpaul{ 1626123474Swpaul ndis_buffer *cur; 1627123474Swpaul int i; 1628123474Swpaul 1629124116Swpaul *pool = malloc(sizeof(ndis_buffer) * 1630124116Swpaul ((descnum + NDIS_POOL_EXTRA) + 1), 1631123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 1632123474Swpaul 1633123474Swpaul if (pool == NULL) { 1634123474Swpaul *status = NDIS_STATUS_RESOURCES; 1635123474Swpaul return; 1636123474Swpaul } 1637123474Swpaul 1638123474Swpaul cur = (ndis_buffer *)*pool; 1639123474Swpaul cur->nb_flags = 0x1; /* mark the head of the list */ 1640124116Swpaul for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) { 1641123474Swpaul cur->nb_next = cur + 1; 1642123474Swpaul cur++; 1643123474Swpaul } 1644123474Swpaul 1645123474Swpaul *status = NDIS_STATUS_SUCCESS; 1646123474Swpaul return; 1647123474Swpaul} 1648123474Swpaul 1649123474Swpaul__stdcall static void 1650123474Swpaulndis_free_bufpool(pool) 1651123474Swpaul ndis_handle pool; 1652123474Swpaul{ 1653123474Swpaul free(pool, M_DEVBUF); 1654123474Swpaul return; 1655123474Swpaul} 1656123474Swpaul 1657123474Swpaul/* 1658123474Swpaul * This maps to a bus_dmamap_create() and bus_dmamap_load(). 1659123474Swpaul */ 1660123474Swpaul__stdcall static void 1661123474Swpaulndis_alloc_buf(status, buffer, pool, vaddr, len) 1662123474Swpaul ndis_status *status; 1663123474Swpaul ndis_buffer **buffer; 1664123474Swpaul ndis_handle pool; 1665123474Swpaul void *vaddr; 1666123474Swpaul uint32_t len; 1667123474Swpaul{ 1668123474Swpaul ndis_buffer *head, *buf; 1669123474Swpaul 1670123474Swpaul head = (ndis_buffer *)pool; 1671123474Swpaul if (head->nb_flags != 0x1) { 1672123474Swpaul *status = NDIS_STATUS_FAILURE; 1673123474Swpaul return; 1674123474Swpaul } 1675123474Swpaul 1676123474Swpaul buf = head->nb_next; 1677123474Swpaul 1678123474Swpaul if (buf == NULL) { 1679123474Swpaul *status = NDIS_STATUS_RESOURCES; 1680123474Swpaul return; 1681123474Swpaul } 1682123474Swpaul 1683123474Swpaul head->nb_next = buf->nb_next; 1684123474Swpaul 1685123474Swpaul /* Save pointer to the pool. */ 1686123474Swpaul buf->nb_process = head; 1687123474Swpaul 1688123757Swpaul MDL_INIT(buf, vaddr, len); 1689123474Swpaul 1690123474Swpaul *buffer = buf; 1691123474Swpaul 1692123474Swpaul *status = NDIS_STATUS_SUCCESS; 1693123474Swpaul return; 1694123474Swpaul} 1695123474Swpaul 1696123848Swpaul__stdcall static void 1697123848Swpaulndis_release_buf(buf) 1698123474Swpaul ndis_buffer *buf; 1699123474Swpaul{ 1700123474Swpaul ndis_buffer *head; 1701123474Swpaul 1702123474Swpaul if (buf == NULL || buf->nb_process == NULL) 1703123474Swpaul return; 1704123474Swpaul 1705123474Swpaul head = buf->nb_process; 1706123474Swpaul 1707123474Swpaul if (head->nb_flags != 0x1) 1708123474Swpaul return; 1709123474Swpaul 1710123474Swpaul buf->nb_next = head->nb_next; 1711123474Swpaul head->nb_next = buf; 1712123474Swpaul 1713123474Swpaul return; 1714123474Swpaul} 1715123474Swpaul 1716124100Swpaul/* Aw c'mon. */ 1717124100Swpaul 1718124100Swpaul__stdcall static uint32_t 1719124100Swpaulndis_buflen(buf) 1720124100Swpaul ndis_buffer *buf; 1721124100Swpaul{ 1722124100Swpaul return(buf->nb_bytecount); 1723124100Swpaul} 1724124100Swpaul 1725123723Swpaul/* 1726123723Swpaul * Get the virtual address and length of a buffer. 1727123723Swpaul * Note: the vaddr argument is optional. 1728123723Swpaul */ 1729123474Swpaul 1730123474Swpaul__stdcall static void 1731123474Swpaulndis_query_buf(buf, vaddr, len) 1732123474Swpaul ndis_buffer *buf; 1733123474Swpaul void **vaddr; 1734123474Swpaul uint32_t *len; 1735123474Swpaul{ 1736123723Swpaul if (vaddr != NULL) 1737123757Swpaul *vaddr = MDL_VA(buf); 1738123474Swpaul *len = buf->nb_bytecount; 1739123474Swpaul 1740123474Swpaul return; 1741123474Swpaul} 1742123474Swpaul 1743123474Swpaul/* Same as above -- we don't care about the priority. */ 1744123474Swpaul 1745123474Swpaul__stdcall static void 1746123474Swpaulndis_query_buf_safe(buf, vaddr, len, prio) 1747123474Swpaul ndis_buffer *buf; 1748123474Swpaul void **vaddr; 1749123474Swpaul uint32_t *len; 1750123474Swpaul uint32_t prio; 1751123474Swpaul{ 1752123723Swpaul if (vaddr != NULL) 1753123757Swpaul *vaddr = MDL_VA(buf); 1754123474Swpaul *len = buf->nb_bytecount; 1755123474Swpaul 1756123474Swpaul return; 1757123474Swpaul} 1758123474Swpaul 1759123474Swpaul__stdcall static void 1760123474Swpaulndis_adjust_buflen(buf, len) 1761123474Swpaul ndis_buffer *buf; 1762123474Swpaul int len; 1763123474Swpaul{ 1764123474Swpaul buf->nb_bytecount = len; 1765123474Swpaul 1766123474Swpaul return; 1767123474Swpaul} 1768123474Swpaul 1769123474Swpaul__stdcall static uint32_t 1770123474Swpaulndis_interlock_inc(addend) 1771123474Swpaul uint32_t *addend; 1772123474Swpaul{ 1773123474Swpaul mtx_lock(&ndis_interlock); 1774123474Swpaul *addend++; 1775123474Swpaul mtx_unlock(&ndis_interlock); 1776123474Swpaul return(*addend); 1777123474Swpaul} 1778123474Swpaul 1779123474Swpaul__stdcall static uint32_t 1780123474Swpaulndis_interlock_dec(addend) 1781123474Swpaul uint32_t *addend; 1782123474Swpaul{ 1783123474Swpaul mtx_lock(&ndis_interlock); 1784123474Swpaul *addend--; 1785123474Swpaul mtx_unlock(&ndis_interlock); 1786123474Swpaul return(*addend); 1787123474Swpaul} 1788123474Swpaul 1789123474Swpaul__stdcall static void 1790123474Swpaulndis_init_event(event) 1791123474Swpaul ndis_event *event; 1792123474Swpaul{ 1793123474Swpaul event->ne_event.nk_header.dh_sigstate = FALSE; 1794123474Swpaul return; 1795123474Swpaul} 1796123474Swpaul 1797123474Swpaul__stdcall static void 1798123474Swpaulndis_set_event(event) 1799123474Swpaul ndis_event *event; 1800123474Swpaul{ 1801123474Swpaul event->ne_event.nk_header.dh_sigstate = TRUE; 1802123474Swpaul wakeup(event); 1803123474Swpaul return; 1804123474Swpaul} 1805123474Swpaul 1806123474Swpaul__stdcall static void 1807123474Swpaulndis_reset_event(event) 1808123474Swpaul ndis_event *event; 1809123474Swpaul{ 1810123474Swpaul event->ne_event.nk_header.dh_sigstate = FALSE; 1811123474Swpaul wakeup(event); 1812123474Swpaul return; 1813123474Swpaul} 1814123474Swpaul 1815123474Swpaul__stdcall static uint8_t 1816123474Swpaulndis_wait_event(event, msecs) 1817123474Swpaul ndis_event *event; 1818123474Swpaul uint32_t msecs; 1819123474Swpaul{ 1820123474Swpaul int error; 1821123474Swpaul struct timeval tv; 1822123474Swpaul 1823123474Swpaul if (event->ne_event.nk_header.dh_sigstate == TRUE) 1824123474Swpaul return(TRUE); 1825123474Swpaul 1826123474Swpaul tv.tv_sec = 0; 1827123474Swpaul tv.tv_usec = msecs * 1000; 1828123474Swpaul 1829123474Swpaul error = tsleep(event, PPAUSE|PCATCH, "ndis", tvtohz(&tv)); 1830123474Swpaul 1831123474Swpaul return(event->ne_event.nk_header.dh_sigstate); 1832123474Swpaul} 1833123474Swpaul 1834123474Swpaul__stdcall static ndis_status 1835123474Swpaulndis_unicode2ansi(dstr, sstr) 1836123526Swpaul ndis_ansi_string *dstr; 1837123526Swpaul ndis_unicode_string *sstr; 1838123474Swpaul{ 1839123526Swpaul if (dstr == NULL || sstr == NULL) 1840123526Swpaul return(NDIS_STATUS_FAILURE); 1841123526Swpaul if (ndis_unicode_to_ascii(sstr->nus_buf, 1842123526Swpaul sstr->nus_len, &dstr->nas_buf)) 1843123526Swpaul return(NDIS_STATUS_FAILURE); 1844123526Swpaul dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf); 1845123474Swpaul return (NDIS_STATUS_SUCCESS); 1846123474Swpaul} 1847123474Swpaul 1848123474Swpaul__stdcall static ndis_status 1849123526Swpaulndis_ansi2unicode(dstr, sstr) 1850123526Swpaul ndis_unicode_string *dstr; 1851123526Swpaul ndis_ansi_string *sstr; 1852123526Swpaul{ 1853123526Swpaul char *str; 1854123526Swpaul if (dstr == NULL || sstr == NULL) 1855123526Swpaul return(NDIS_STATUS_FAILURE); 1856123526Swpaul str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT); 1857123526Swpaul if (str == NULL) 1858123526Swpaul return(NDIS_STATUS_FAILURE); 1859123526Swpaul strncpy(str, sstr->nas_buf, sstr->nas_len); 1860123526Swpaul *(str + sstr->nas_len) = '\0'; 1861123526Swpaul if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) { 1862123526Swpaul free(str, M_DEVBUF); 1863123526Swpaul return(NDIS_STATUS_FAILURE); 1864123526Swpaul } 1865123526Swpaul dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2; 1866123526Swpaul free(str, M_DEVBUF); 1867123526Swpaul return (NDIS_STATUS_SUCCESS); 1868123526Swpaul} 1869123526Swpaul 1870123526Swpaul__stdcall static ndis_status 1871123474Swpaulndis_assign_pcirsrc(adapter, slot, list) 1872123474Swpaul ndis_handle adapter; 1873123474Swpaul uint32_t slot; 1874123474Swpaul ndis_resource_list **list; 1875123474Swpaul{ 1876123474Swpaul ndis_miniport_block *block; 1877123474Swpaul 1878123474Swpaul if (adapter == NULL || list == NULL) 1879123474Swpaul return (NDIS_STATUS_FAILURE); 1880123474Swpaul 1881123474Swpaul block = (ndis_miniport_block *)adapter; 1882123474Swpaul *list = block->nmb_rlist; 1883123474Swpaul 1884123474Swpaul return (NDIS_STATUS_SUCCESS); 1885123474Swpaul} 1886123474Swpaul 1887123474Swpaul__stdcall static ndis_status 1888123474Swpaulndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode) 1889123474Swpaul ndis_miniport_interrupt *intr; 1890123474Swpaul ndis_handle adapter; 1891123474Swpaul uint32_t ivec; 1892123474Swpaul uint32_t ilevel; 1893123474Swpaul uint8_t reqisr; 1894123474Swpaul uint8_t shared; 1895123474Swpaul ndis_interrupt_mode imode; 1896123474Swpaul{ 1897123474Swpaul 1898123474Swpaul return(NDIS_STATUS_SUCCESS); 1899123474Swpaul} 1900123474Swpaul 1901123474Swpaul__stdcall static void 1902123474Swpaulndis_deregister_intr(intr) 1903123474Swpaul ndis_miniport_interrupt *intr; 1904123474Swpaul{ 1905123474Swpaul return; 1906123474Swpaul} 1907123474Swpaul 1908123474Swpaul__stdcall static void 1909123474Swpaulndis_register_shutdown(adapter, shutdownctx, shutdownfunc) 1910123474Swpaul ndis_handle adapter; 1911123474Swpaul void *shutdownctx; 1912123474Swpaul ndis_shutdown_handler shutdownfunc; 1913123474Swpaul{ 1914123474Swpaul ndis_miniport_block *block; 1915123474Swpaul ndis_miniport_characteristics *chars; 1916123474Swpaul struct ndis_softc *sc; 1917123474Swpaul 1918123474Swpaul if (adapter == NULL) 1919123474Swpaul return; 1920123474Swpaul 1921123474Swpaul block = (ndis_miniport_block *)adapter; 1922123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1923123474Swpaul chars = &sc->ndis_chars; 1924123474Swpaul 1925123474Swpaul chars->nmc_shutdown_handler = shutdownfunc; 1926123474Swpaul chars->nmc_rsvd0 = shutdownctx; 1927123474Swpaul 1928123474Swpaul return; 1929123474Swpaul} 1930123474Swpaul 1931123474Swpaul__stdcall static void 1932123474Swpaulndis_deregister_shutdown(adapter) 1933123474Swpaul ndis_handle adapter; 1934123474Swpaul{ 1935123474Swpaul ndis_miniport_block *block; 1936123474Swpaul ndis_miniport_characteristics *chars; 1937123474Swpaul struct ndis_softc *sc; 1938123474Swpaul 1939123474Swpaul if (adapter == NULL) 1940123474Swpaul return; 1941123474Swpaul 1942123474Swpaul block = (ndis_miniport_block *)adapter; 1943123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 1944123474Swpaul chars = &sc->ndis_chars; 1945123474Swpaul 1946123474Swpaul chars->nmc_shutdown_handler = NULL; 1947123474Swpaul chars->nmc_rsvd0 = NULL; 1948123474Swpaul 1949123474Swpaul return; 1950123474Swpaul} 1951123474Swpaul 1952123474Swpaul__stdcall static uint32_t 1953123474Swpaulndis_numpages(buf) 1954123474Swpaul ndis_buffer *buf; 1955123474Swpaul{ 1956123757Swpaul if (buf == NULL) 1957123757Swpaul return(0); 1958123512Swpaul if (buf->nb_bytecount == 0) 1959123512Swpaul return(1); 1960123757Swpaul return(SPAN_PAGES(MDL_VA(buf), buf->nb_bytecount)); 1961123474Swpaul} 1962123474Swpaul 1963123474Swpaul__stdcall static void 1964123573Swpaulndis_buf_physpages(buf, pages) 1965123573Swpaul ndis_buffer *buf; 1966123573Swpaul uint32_t *pages; 1967123573Swpaul{ 1968123757Swpaul if (buf == NULL) 1969123757Swpaul return; 1970123757Swpaul 1971123573Swpaul *pages = ndis_numpages(buf); 1972123573Swpaul return; 1973123573Swpaul} 1974123573Swpaul 1975123573Swpaul__stdcall static void 1976123474Swpaulndis_query_bufoffset(buf, off, len) 1977123474Swpaul ndis_buffer *buf; 1978123474Swpaul uint32_t *off; 1979123474Swpaul uint32_t *len; 1980123474Swpaul{ 1981123757Swpaul if (buf == NULL) 1982123757Swpaul return; 1983123757Swpaul 1984123757Swpaul *off = buf->nb_byteoffset; 1985123474Swpaul *len = buf->nb_bytecount; 1986123474Swpaul 1987123474Swpaul return; 1988123474Swpaul} 1989123474Swpaul 1990123474Swpaul__stdcall static void 1991123474Swpaulndis_sleep(usecs) 1992123474Swpaul uint32_t usecs; 1993123474Swpaul{ 1994123474Swpaul struct timeval tv; 1995123474Swpaul uint32_t dummy; 1996123474Swpaul 1997123474Swpaul tv.tv_sec = 0; 1998123474Swpaul tv.tv_usec = usecs; 1999123474Swpaul 2000123474Swpaul tsleep(&dummy, PPAUSE|PCATCH, "ndis", tvtohz(&tv)); 2001124100Swpaul 2002123474Swpaul return; 2003123474Swpaul} 2004123474Swpaul 2005123474Swpaul__stdcall static uint32_t 2006123474Swpaulndis_read_pccard_amem(handle, offset, buf, len) 2007123474Swpaul ndis_handle handle; 2008123474Swpaul uint32_t offset; 2009123474Swpaul void *buf; 2010123474Swpaul uint32_t len; 2011123474Swpaul{ 2012123474Swpaul struct ndis_softc *sc; 2013123474Swpaul ndis_miniport_block *block; 2014123474Swpaul bus_space_handle_t bh; 2015123474Swpaul bus_space_tag_t bt; 2016123474Swpaul char *dest; 2017123474Swpaul int i; 2018123474Swpaul 2019123474Swpaul if (handle == NULL) 2020123474Swpaul return(0); 2021123474Swpaul 2022123474Swpaul block = (ndis_miniport_block *)handle; 2023123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 2024123474Swpaul dest = buf; 2025123474Swpaul 2026123474Swpaul bh = rman_get_bushandle(sc->ndis_res_am); 2027123474Swpaul bt = rman_get_bustag(sc->ndis_res_am); 2028123474Swpaul 2029123474Swpaul for (i = 0; i < len; i++) 2030123474Swpaul dest[i] = bus_space_read_1(bt, bh, (offset * 2) + (i * 2)); 2031123474Swpaul 2032123474Swpaul return(i); 2033123474Swpaul} 2034123474Swpaul 2035123474Swpaul__stdcall static uint32_t 2036123474Swpaulndis_write_pccard_amem(handle, offset, buf, len) 2037123474Swpaul ndis_handle handle; 2038123474Swpaul uint32_t offset; 2039123474Swpaul void *buf; 2040123474Swpaul uint32_t len; 2041123474Swpaul{ 2042123474Swpaul struct ndis_softc *sc; 2043123474Swpaul ndis_miniport_block *block; 2044123474Swpaul bus_space_handle_t bh; 2045123474Swpaul bus_space_tag_t bt; 2046123474Swpaul char *src; 2047123474Swpaul int i; 2048123474Swpaul 2049123474Swpaul if (handle == NULL) 2050123474Swpaul return(0); 2051123474Swpaul 2052123474Swpaul block = (ndis_miniport_block *)handle; 2053123474Swpaul sc = (struct ndis_softc *)block->nmb_ifp; 2054123474Swpaul src = buf; 2055123474Swpaul 2056123474Swpaul bh = rman_get_bushandle(sc->ndis_res_am); 2057123474Swpaul bt = rman_get_bustag(sc->ndis_res_am); 2058123474Swpaul 2059123474Swpaul for (i = 0; i < len; i++) 2060123474Swpaul bus_space_write_1(bt, bh, (offset * 2) + (i * 2), src[i]); 2061123474Swpaul 2062123474Swpaul return(i); 2063123474Swpaul} 2064123474Swpaul 2065123474Swpaul__stdcall static ndis_list_entry * 2066123474Swpaulndis_insert_head(head, entry, lock) 2067123474Swpaul ndis_list_entry *head; 2068123474Swpaul ndis_list_entry *entry; 2069123474Swpaul ndis_spin_lock *lock; 2070123474Swpaul{ 2071123474Swpaul ndis_list_entry *flink; 2072123474Swpaul 2073123474Swpaul mtx_lock_spin((struct mtx *)lock->nsl_spinlock); 2074123474Swpaul flink = head->nle_flink; 2075123474Swpaul entry->nle_flink = flink; 2076123474Swpaul entry->nle_blink = head; 2077123474Swpaul flink->nle_blink = entry; 2078123474Swpaul head->nle_flink = entry; 2079123474Swpaul mtx_unlock_spin((struct mtx *)lock->nsl_spinlock); 2080123474Swpaul 2081123474Swpaul return(flink); 2082123474Swpaul} 2083123474Swpaul 2084123474Swpaul__stdcall static ndis_list_entry * 2085123474Swpaulndis_remove_head(head, lock) 2086123474Swpaul ndis_list_entry *head; 2087123474Swpaul ndis_spin_lock *lock; 2088123474Swpaul{ 2089123474Swpaul ndis_list_entry *flink; 2090123474Swpaul ndis_list_entry *entry; 2091123474Swpaul 2092123474Swpaul mtx_lock_spin((struct mtx *)lock->nsl_spinlock); 2093123474Swpaul entry = head->nle_flink; 2094123474Swpaul flink = entry->nle_flink; 2095123474Swpaul head->nle_flink = flink; 2096123474Swpaul flink->nle_blink = head; 2097123474Swpaul mtx_unlock_spin((struct mtx *)lock->nsl_spinlock); 2098123474Swpaul 2099123474Swpaul return(entry); 2100123474Swpaul} 2101123474Swpaul 2102123474Swpaul__stdcall static ndis_list_entry * 2103123474Swpaulndis_insert_tail(head, entry, lock) 2104123474Swpaul ndis_list_entry *head; 2105123474Swpaul ndis_list_entry *entry; 2106123474Swpaul ndis_spin_lock *lock; 2107123474Swpaul{ 2108123474Swpaul ndis_list_entry *blink; 2109123474Swpaul 2110123474Swpaul mtx_lock_spin((struct mtx *)lock->nsl_spinlock); 2111123474Swpaul blink = head->nle_blink; 2112123474Swpaul entry->nle_flink = head; 2113123474Swpaul entry->nle_blink = blink; 2114123474Swpaul blink->nle_flink = entry; 2115123474Swpaul head->nle_blink = entry; 2116123474Swpaul mtx_unlock_spin((struct mtx *)lock->nsl_spinlock); 2117123474Swpaul 2118123474Swpaul return(blink); 2119123474Swpaul} 2120123474Swpaul 2121123474Swpaul__stdcall static uint8_t 2122123474Swpaulndis_sync_with_intr(intr, syncfunc, syncctx) 2123123474Swpaul ndis_miniport_interrupt *intr; 2124123474Swpaul void *syncfunc; 2125123474Swpaul void *syncctx; 2126123474Swpaul{ 2127123474Swpaul __stdcall uint8_t (*sync)(void *); 2128123474Swpaul 2129123474Swpaul if (syncfunc == NULL || syncctx == NULL) 2130123474Swpaul return(0); 2131123474Swpaul 2132123474Swpaul sync = syncfunc; 2133123474Swpaul return(sync(syncctx)); 2134123474Swpaul} 2135123474Swpaul 2136123504Swpaul/* 2137123504Swpaul * Return the number of 100 nanosecond intervals since 2138123504Swpaul * January 1, 1601. (?!?!) 2139123504Swpaul */ 2140123474Swpaul__stdcall static void 2141123504Swpaulndis_time(tval) 2142123504Swpaul uint64_t *tval; 2143123504Swpaul{ 2144123504Swpaul struct timespec ts; 2145123822Swpaul 2146123504Swpaul nanotime(&ts); 2147123822Swpaul *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 + 2148123822Swpaul 11644473600; 2149123504Swpaul} 2150123504Swpaul 2151123822Swpaul/* 2152123822Swpaul * Return the number of milliseconds since the system booted. 2153123822Swpaul */ 2154123504Swpaul__stdcall static void 2155123822Swpaulndis_uptime(tval) 2156123822Swpaul uint32_t *tval; 2157123822Swpaul{ 2158123822Swpaul struct timespec ts; 2159123822Swpaul 2160123822Swpaul nanouptime(&ts); 2161123822Swpaul *tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000; 2162123822Swpaul} 2163123822Swpaul 2164123822Swpaul__stdcall static void 2165123507Swpaulndis_init_string(dst, src) 2166124100Swpaul ndis_unicode_string *dst; 2167123507Swpaul char *src; 2168123507Swpaul{ 2169123507Swpaul ndis_unicode_string *u; 2170123507Swpaul 2171124100Swpaul u = dst; 2172124116Swpaul u->nus_buf = NULL; 2173124100Swpaul if (ndis_ascii_to_unicode(src, &u->nus_buf)) 2174123507Swpaul return; 2175123507Swpaul u->nus_len = u->nus_maxlen = strlen(src) * 2; 2176123507Swpaul return; 2177123507Swpaul} 2178123507Swpaul 2179123507Swpaul__stdcall static void 2180123507Swpaulndis_free_string(str) 2181123507Swpaul ndis_unicode_string *str; 2182123507Swpaul{ 2183123507Swpaul if (str == NULL) 2184123507Swpaul return; 2185123507Swpaul if (str->nus_buf != NULL) 2186123507Swpaul free(str->nus_buf, M_DEVBUF); 2187123507Swpaul free(str, M_DEVBUF); 2188123507Swpaul return; 2189123507Swpaul} 2190123507Swpaul 2191123507Swpaul__stdcall static ndis_status 2192123507Swpaulndis_remove_miniport(adapter) 2193123507Swpaul ndis_handle *adapter; 2194123507Swpaul{ 2195123507Swpaul return(NDIS_STATUS_SUCCESS); 2196123507Swpaul} 2197123507Swpaul 2198123507Swpaul__stdcall static void 2199123526Swpaulndis_init_ansi_string(dst, src) 2200123526Swpaul ndis_ansi_string *dst; 2201123526Swpaul char *src; 2202123526Swpaul{ 2203123526Swpaul ndis_ansi_string *a; 2204123526Swpaul 2205123526Swpaul a = dst; 2206123526Swpaul if (a == NULL) 2207123526Swpaul return; 2208123526Swpaul if (src == NULL) { 2209123526Swpaul a->nas_len = a->nas_maxlen = 0; 2210123526Swpaul a->nas_buf = NULL; 2211123526Swpaul } else { 2212123526Swpaul a->nas_buf = src; 2213123526Swpaul a->nas_len = a->nas_maxlen = strlen(src); 2214123526Swpaul } 2215123526Swpaul 2216123526Swpaul return; 2217123526Swpaul} 2218123526Swpaul 2219123941Swpaul__stdcall static void 2220123941Swpaulndis_init_unicode_string(dst, src) 2221123941Swpaul ndis_unicode_string *dst; 2222123941Swpaul uint16_t *src; 2223123941Swpaul{ 2224123941Swpaul ndis_unicode_string *u; 2225123941Swpaul int i; 2226123941Swpaul 2227123941Swpaul u = dst; 2228123941Swpaul if (u == NULL) 2229123941Swpaul return; 2230123941Swpaul if (src == NULL) { 2231123941Swpaul u->nus_len = u->nus_maxlen = 0; 2232123941Swpaul u->nus_buf = NULL; 2233123941Swpaul } else { 2234123941Swpaul i = 0; 2235123941Swpaul while(src[i] != 0) 2236123941Swpaul i++; 2237123941Swpaul u->nus_buf = src; 2238123941Swpaul u->nus_len = u->nus_maxlen = i * 2; 2239123941Swpaul } 2240123941Swpaul 2241123941Swpaul return; 2242123941Swpaul} 2243123941Swpaul 2244123526Swpaul__stdcall static void ndis_get_devprop(adapter, phydevobj, 2245123526Swpaul funcdevobj, nextdevobj, resources, transresources) 2246123526Swpaul ndis_handle adapter; 2247123526Swpaul void *phydevobj; 2248123526Swpaul void *funcdevobj; 2249123526Swpaul void *nextdevobj; 2250123526Swpaul cm_resource_list *resources; 2251123526Swpaul cm_resource_list *transresources; 2252123526Swpaul{ 2253123526Swpaul return; 2254123526Swpaul} 2255123526Swpaul 2256123526Swpaul__stdcall static void 2257123721Swpaulndis_firstbuf(packet, buf, firstva, firstlen, totlen) 2258123721Swpaul ndis_packet *packet; 2259123721Swpaul ndis_buffer **buf; 2260123721Swpaul void **firstva; 2261123721Swpaul uint32_t *firstlen; 2262123721Swpaul uint32_t *totlen; 2263123721Swpaul{ 2264123721Swpaul ndis_buffer *tmp; 2265123721Swpaul 2266123721Swpaul tmp = packet->np_private.npp_head; 2267123721Swpaul *buf = tmp; 2268123721Swpaul if (tmp == NULL) { 2269123721Swpaul *firstva = NULL; 2270123721Swpaul *firstlen = *totlen = 0; 2271123721Swpaul } else { 2272123757Swpaul *firstva = MDL_VA(tmp); 2273123721Swpaul *firstlen = *totlen = tmp->nb_bytecount; 2274123721Swpaul for (tmp = tmp->nb_next; tmp != NULL; tmp = tmp->nb_next) 2275123721Swpaul *totlen += tmp->nb_bytecount; 2276123721Swpaul } 2277123721Swpaul 2278123721Swpaul return; 2279123721Swpaul} 2280123721Swpaul 2281123721Swpaul__stdcall static void 2282123721Swpaulndis_firstbuf_safe(packet, buf, firstva, firstlen, totlen, prio) 2283123721Swpaul ndis_packet *packet; 2284123721Swpaul ndis_buffer **buf; 2285123721Swpaul void **firstva; 2286123721Swpaul uint32_t *firstlen; 2287123721Swpaul uint32_t *totlen; 2288123721Swpaul uint32_t prio; 2289123721Swpaul{ 2290123721Swpaul ndis_firstbuf(packet, buf, firstva, firstlen, totlen); 2291123721Swpaul} 2292123721Swpaul 2293123822Swpaul/* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */ 2294123721Swpaul__stdcall static void 2295123822Swpaulndis_open_file(status, filehandle, filelength, filename, highestaddr) 2296123822Swpaul ndis_status *status; 2297123822Swpaul ndis_handle *filehandle; 2298123822Swpaul uint32_t *filelength; 2299123822Swpaul ndis_unicode_string *filename; 2300123822Swpaul ndis_physaddr highestaddr; 2301123822Swpaul{ 2302123822Swpaul char *afilename = NULL; 2303123822Swpaul 2304123822Swpaul ndis_unicode_to_ascii(filename->nus_buf, filename->nus_len, &afilename); 2305123822Swpaul printf("ndis_open_file(\"%s\", %ju)\n", afilename, 2306123822Swpaul highestaddr.np_quad); 2307123822Swpaul free(afilename, M_DEVBUF); 2308123822Swpaul *status = NDIS_STATUS_FILE_NOT_FOUND; 2309123822Swpaul return; 2310123822Swpaul} 2311123822Swpaul 2312123822Swpaul__stdcall static void 2313123822Swpaulndis_map_file(status, mappedbuffer, filehandle) 2314123822Swpaul ndis_status *status; 2315123822Swpaul void **mappedbuffer; 2316123822Swpaul ndis_handle filehandle; 2317123822Swpaul{ 2318123822Swpaul 2319123822Swpaul *status = NDIS_STATUS_ALREADY_MAPPED; 2320123822Swpaul return; 2321123822Swpaul} 2322123822Swpaul 2323123822Swpaul__stdcall static void 2324123822Swpaulndis_unmap_file(filehandle) 2325123822Swpaul ndis_handle filehandle; 2326123822Swpaul{ 2327123822Swpaul return; 2328123822Swpaul} 2329123822Swpaul 2330123822Swpaul__stdcall static void 2331123822Swpaulndis_close_file(filehandle) 2332123822Swpaul ndis_handle filehandle; 2333123822Swpaul{ 2334123822Swpaul return; 2335123822Swpaul} 2336123822Swpaul 2337123848Swpaul__stdcall static uint8_t 2338123848Swpaulndis_cpu_cnt() 2339123848Swpaul{ 2340123848Swpaul#ifdef SMP 2341123848Swpaul return(mp_ncpus); 2342123848Swpaul#else 2343123848Swpaul return(1); 2344123848Swpaul#endif 2345123848Swpaul}; 2346123848Swpaul 2347124116Swpaultypedef void (*ndis_statusdone_handler)(ndis_handle); 2348124116Swpaultypedef void (*ndis_status_handler)(ndis_handle, ndis_status, 2349124116Swpaul void *, uint32_t); 2350124116Swpaul 2351123822Swpaul__stdcall static void 2352124116Swpaulndis_ind_statusdone(adapter) 2353124116Swpaul ndis_handle adapter; 2354124116Swpaul{ 2355124116Swpaul ndis_miniport_block *block; 2356124116Swpaul __stdcall ndis_statusdone_handler statusdonefunc; 2357124116Swpaul 2358124116Swpaul block = (ndis_miniport_block *)adapter; 2359124116Swpaul statusdonefunc = block->nmb_statusdone_func; 2360124116Swpaul 2361124116Swpaul statusdonefunc(adapter); 2362124116Swpaul return; 2363124116Swpaul} 2364124116Swpaul 2365124116Swpaul__stdcall static void 2366124116Swpaulndis_ind_status(adapter, status, sbuf, slen) 2367124116Swpaul ndis_handle adapter; 2368124116Swpaul ndis_status status; 2369124116Swpaul void *sbuf; 2370124116Swpaul uint32_t slen; 2371124116Swpaul{ 2372124116Swpaul ndis_miniport_block *block; 2373124116Swpaul __stdcall ndis_status_handler statusfunc; 2374124116Swpaul 2375124116Swpaul block = (ndis_miniport_block *)adapter; 2376124116Swpaul statusfunc = block->nmb_status_func; 2377124116Swpaul 2378124116Swpaul statusfunc(adapter, status, sbuf, slen); 2379124116Swpaul return; 2380124116Swpaul} 2381124116Swpaul 2382124122Swpaulstatic void 2383124122Swpaulndis_workfunc(ctx, pending) 2384124122Swpaul void *ctx; 2385124122Swpaul int pending; 2386124122Swpaul{ 2387124122Swpaul ndis_work_item *work; 2388124122Swpaul __stdcall ndis_proc workfunc; 2389124122Swpaul 2390124122Swpaul work = ctx; 2391124122Swpaul workfunc = work->nwi_func; 2392124122Swpaul workfunc(work, work->nwi_ctx); 2393124122Swpaul return; 2394124122Swpaul} 2395124122Swpaul 2396124122Swpaul__stdcall static ndis_status 2397124122Swpaulndis_sched_workitem(work) 2398124122Swpaul ndis_work_item *work; 2399124122Swpaul{ 2400124122Swpaul struct task *t; 2401124122Swpaul 2402124122Swpaul t = (struct task *)&work->nwi_wraprsvd; 2403124122Swpaul TASK_INIT(t, 0, ndis_workfunc, work); 2404124122Swpaul taskqueue_enqueue(taskqueue_swi, t); 2405124122Swpaul return(NDIS_STATUS_SUCCESS); 2406124122Swpaul} 2407124122Swpaul 2408124116Swpaul__stdcall static void 2409123474Swpauldummy() 2410123474Swpaul{ 2411123474Swpaul printf ("NDIS dummy called...\n"); 2412123474Swpaul return; 2413123474Swpaul} 2414123474Swpaul 2415123474Swpaulimage_patch_table ndis_functbl[] = { 2416124122Swpaul { "NdisScheduleWorkItem", (FUNC)ndis_sched_workitem }, 2417124116Swpaul { "NdisMIndicateStatusComplete", (FUNC)ndis_ind_statusdone }, 2418124116Swpaul { "NdisMIndicateStatus", (FUNC)ndis_ind_status }, 2419123848Swpaul { "NdisSystemProcessorCount", (FUNC)ndis_cpu_cnt }, 2420123721Swpaul { "NdisUnchainBufferAtBack", (FUNC)ndis_unchain_tailbuf, }, 2421123721Swpaul { "NdisGetFirstBufferFromPacket", (FUNC)ndis_firstbuf }, 2422123721Swpaul { "NdisGetFirstBufferFromPacketSafe", (FUNC)ndis_firstbuf_safe }, 2423123573Swpaul { "NdisGetBufferPhysicalArraySize", (FUNC)ndis_buf_physpages }, 2424123526Swpaul { "NdisMGetDeviceProperty", (FUNC)ndis_get_devprop }, 2425123526Swpaul { "NdisInitAnsiString", (FUNC)ndis_init_ansi_string }, 2426123941Swpaul { "NdisInitUnicodeString", (FUNC)ndis_init_unicode_string }, 2427123526Swpaul { "NdisWriteConfiguration", (FUNC)ndis_write_cfg }, 2428123526Swpaul { "NdisAnsiStringToUnicodeString", (FUNC)ndis_ansi2unicode }, 2429123526Swpaul { "NdisTerminateWrapper", (FUNC)ndis_termwrap }, 2430123526Swpaul { "NdisOpenConfigurationKeyByName", (FUNC)ndis_open_cfgbyname }, 2431123526Swpaul { "NdisOpenConfigurationKeyByIndex", (FUNC)ndis_open_cfgbyidx }, 2432123507Swpaul { "NdisMRemoveMiniport", (FUNC)ndis_remove_miniport }, 2433123507Swpaul { "NdisInitializeString", (FUNC)ndis_init_string }, 2434123507Swpaul { "NdisFreeString", (FUNC)ndis_free_string }, 2435123504Swpaul { "NdisGetCurrentSystemTime", (FUNC)ndis_time }, 2436123822Swpaul { "NdisGetSystemUpTime", (FUNC)ndis_uptime }, 2437123474Swpaul { "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr }, 2438123474Swpaul { "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async }, 2439123474Swpaul { "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head }, 2440123474Swpaul { "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail }, 2441123474Swpaul { "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head }, 2442123474Swpaul { "NdisInitializeWrapper", (FUNC)ndis_initwrap }, 2443123474Swpaul { "NdisMRegisterMiniport", (FUNC)ndis_register_miniport }, 2444123474Swpaul { "NdisAllocateMemoryWithTag", (FUNC)ndis_malloc_withtag }, 2445123474Swpaul { "NdisAllocateMemory", (FUNC)ndis_malloc }, 2446123474Swpaul { "NdisMSetAttributesEx", (FUNC)ndis_setattr_ex }, 2447123474Swpaul { "NdisCloseConfiguration", (FUNC)ndis_close_cfg }, 2448123474Swpaul { "NdisReadConfiguration", (FUNC)ndis_read_cfg }, 2449123474Swpaul { "NdisOpenConfiguration", (FUNC)ndis_open_cfg }, 2450123474Swpaul { "NdisReleaseSpinLock", (FUNC)ndis_unlock }, 2451123474Swpaul { "NdisDprAcquireSpinLock", (FUNC)ndis_lock }, 2452123474Swpaul { "NdisDprReleaseSpinLock", (FUNC)ndis_unlock }, 2453123474Swpaul { "NdisAcquireSpinLock", (FUNC)ndis_lock }, 2454123474Swpaul { "NdisAllocateSpinLock", (FUNC)ndis_create_lock }, 2455123474Swpaul { "NdisFreeSpinLock", (FUNC)ndis_destroy_lock }, 2456123474Swpaul { "NdisFreeMemory", (FUNC)ndis_free }, 2457123474Swpaul { "NdisReadPciSlotInformation", (FUNC)ndis_read_pci }, 2458123474Swpaul { "NdisWritePciSlotInformation",(FUNC)ndis_write_pci }, 2459124100Swpaul { "NdisImmediateReadPciSlotInformation", (FUNC)ndis_read_pci }, 2460124100Swpaul { "NdisImmediateWritePciSlotInformation", (FUNC)ndis_write_pci }, 2461123474Swpaul { "NdisWriteErrorLogEntry", (FUNC)ndis_syslog }, 2462123474Swpaul { "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load }, 2463123474Swpaul { "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload }, 2464123474Swpaul { "NdisMInitializeTimer", (FUNC)ndis_create_timer }, 2465123474Swpaul { "NdisSetTimer", (FUNC)ndis_set_timer }, 2466123474Swpaul { "NdisMCancelTimer", (FUNC)ndis_cancel_timer }, 2467123474Swpaul { "NdisMSetPeriodicTimer", (FUNC)ndis_set_periodic_timer }, 2468123474Swpaul { "NdisMQueryAdapterResources", (FUNC)ndis_query_resources }, 2469123474Swpaul { "NdisMRegisterIoPortRange", (FUNC)ndis_register_ioport }, 2470123474Swpaul { "NdisMDeregisterIoPortRange", (FUNC)ndis_deregister_ioport }, 2471123474Swpaul { "NdisReadNetworkAddress", (FUNC)ndis_read_netaddr }, 2472123848Swpaul { "NdisQueryMapRegisterCount", (FUNC)ndis_mapreg_cnt }, 2473123474Swpaul { "NdisMAllocateMapRegisters", (FUNC)ndis_alloc_mapreg }, 2474123848Swpaul { "NdisMFreeMapRegisters", (FUNC)ndis_free_mapreg }, 2475123474Swpaul { "NdisMAllocateSharedMemory", (FUNC)ndis_alloc_sharedmem }, 2476123474Swpaul { "NdisMMapIoSpace", (FUNC)ndis_map_iospace }, 2477123474Swpaul { "NdisMUnmapIoSpace", (FUNC)ndis_unmap_iospace }, 2478123474Swpaul { "NdisGetCacheFillSize", (FUNC)ndis_cachefill }, 2479123474Swpaul { "NdisMGetDmaAlignment", (FUNC)ndis_dma_align }, 2480123474Swpaul { "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma }, 2481123474Swpaul { "NdisAllocatePacketPool", (FUNC)ndis_alloc_packetpool }, 2482123474Swpaul { "NdisAllocatePacketPoolEx", (FUNC)ndis_ex_alloc_packetpool }, 2483123474Swpaul { "NdisAllocatePacket", (FUNC)ndis_alloc_packet }, 2484123474Swpaul { "NdisFreePacket", (FUNC)ndis_release_packet }, 2485123474Swpaul { "NdisFreePacketPool", (FUNC)ndis_free_packetpool }, 2486124097Swpaul { "NdisDprAllocatePacket", (FUNC)ndis_alloc_packet }, 2487124097Swpaul { "NdisDprFreePacket", (FUNC)ndis_release_packet }, 2488123474Swpaul { "NdisAllocateBufferPool", (FUNC)ndis_alloc_bufpool }, 2489123474Swpaul { "NdisAllocateBuffer", (FUNC)ndis_alloc_buf }, 2490123474Swpaul { "NdisQueryBuffer", (FUNC)ndis_query_buf }, 2491123474Swpaul { "NdisQueryBufferSafe", (FUNC)ndis_query_buf_safe }, 2492124100Swpaul { "NdisBufferLength", (FUNC)ndis_buflen }, 2493123474Swpaul { "NdisFreeBuffer", (FUNC)ndis_release_buf }, 2494123474Swpaul { "NdisFreeBufferPool", (FUNC)ndis_free_bufpool }, 2495123474Swpaul { "NdisInterlockedIncrement", (FUNC)ndis_interlock_inc }, 2496123474Swpaul { "NdisInterlockedDecrement", (FUNC)ndis_interlock_dec }, 2497123474Swpaul { "NdisInitializeEvent", (FUNC)ndis_init_event }, 2498123474Swpaul { "NdisSetEvent", (FUNC)ndis_set_event }, 2499123474Swpaul { "NdisResetEvent", (FUNC)ndis_reset_event }, 2500123474Swpaul { "NdisWaitEvent", (FUNC)ndis_wait_event }, 2501123474Swpaul { "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi }, 2502123474Swpaul { "NdisMPciAssignResources", (FUNC)ndis_assign_pcirsrc }, 2503123474Swpaul { "NdisMFreeSharedMemory", (FUNC)ndis_free_sharedmem }, 2504123474Swpaul { "NdisMRegisterInterrupt", (FUNC)ndis_register_intr }, 2505123474Swpaul { "NdisMDeregisterInterrupt", (FUNC)ndis_deregister_intr }, 2506123474Swpaul { "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown }, 2507123474Swpaul { "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown }, 2508123474Swpaul { "NDIS_BUFFER_TO_SPAN_PAGES", (FUNC)ndis_numpages }, 2509123474Swpaul { "NdisQueryBufferOffset", (FUNC)ndis_query_bufoffset }, 2510123474Swpaul { "NdisAdjustBufferLength", (FUNC)ndis_adjust_buflen }, 2511123474Swpaul { "NdisPacketPoolUsage", (FUNC)ndis_packetpool_use }, 2512123474Swpaul { "NdisMSleep", (FUNC)ndis_sleep }, 2513123474Swpaul { "NdisUnchainBufferAtFront", (FUNC)ndis_unchain_headbuf }, 2514123474Swpaul { "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem }, 2515123474Swpaul { "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem }, 2516123822Swpaul { "NdisOpenFile", (FUNC)ndis_open_file }, 2517123822Swpaul { "NdisMapFile", (FUNC)ndis_map_file }, 2518123822Swpaul { "NdisUnmapFile", (FUNC)ndis_unmap_file }, 2519123822Swpaul { "NdisCloseFile", (FUNC)ndis_close_file }, 2520123474Swpaul 2521123474Swpaul /* 2522123474Swpaul * This last entry is a catch-all for any function we haven't 2523123474Swpaul * implemented yet. The PE import list patching routine will 2524123474Swpaul * use it for any function that doesn't have an explicit match 2525123474Swpaul * in this table. 2526123474Swpaul */ 2527123474Swpaul 2528123474Swpaul { NULL, (FUNC)dummy }, 2529123474Swpaul 2530123474Swpaul /* End of list. */ 2531123474Swpaul 2532123474Swpaul { NULL, NULL }, 2533123474Swpaul}; 2534