📄 ndis.c
字号:
}STDCALL void WRAP_EXPORT(NdisMAllocateSharedMemory) (struct ndis_handle *handle, ULONG size, BOOLEAN cached, void **virt, NDIS_PHY_ADDRESS *phys){ dma_addr_t p; void *v; TRACEENTER3("map count: %d, size: %u, cached: %d", handle->map_count, size, cached);// if (handle->map_dma_addr == NULL)// ERROR("%s: DMA map address is not set!\n", __FUNCTION__); /* FIXME: do USB drivers call this? */ v = PCI_DMA_ALLOC_COHERENT(handle->dev.pci, size, &p); if (!v) { ERROR("Failed to allocate DMA coherent memory. " "Windows driver requested %d bytes of " "%scached memory\n", size, cached ? "" : "un-"); } *virt = v; *phys = p; DBGTRACE3("allocated shared memory: %p", v);}STDCALL NDIS_STATUS WRAP_EXPORT(NdisMAllocateSharedMemoryAsync) (struct ndis_handle *handle, ULONG size, BOOLEAN cached, void *ctx){ struct ndis_work_entry *ndis_work_entry; struct ndis_alloc_mem_work_item *alloc_mem; KIRQL irql; TRACEENTER3("%s", ""); ndis_work_entry = kmalloc(sizeof(*ndis_work_entry), GFP_ATOMIC); if (!ndis_work_entry) return NDIS_STATUS_FAILURE; ndis_work_entry->type = NDIS_ALLOC_MEM_WORK_ITEM; ndis_work_entry->handle = handle; alloc_mem = &ndis_work_entry->entry.alloc_mem_work_item; alloc_mem->size = size; alloc_mem->cached = cached; alloc_mem->ctx = ctx; irql = kspin_lock_irql(&ndis_work_list_lock, DISPATCH_LEVEL); list_add_tail(&ndis_work_entry->list, &ndis_work_list); kspin_unlock_irql(&ndis_work_list_lock, irql); schedule_work(&ndis_work); TRACEEXIT3(return NDIS_STATUS_PENDING);}STDCALL void WRAP_EXPORT(NdisMFreeSharedMemory) (struct ndis_handle *handle, ULONG size, BOOLEAN cached, void *virt, NDIS_PHY_ADDRESS addr){ TRACEENTER3("%s", ""); /* FIXME: do USB drivers call this? */ PCI_DMA_FREE_COHERENT(handle->dev.pci, size, virt, addr); TRACEEXIT3(return);}/* Some drivers allocate NDIS_BUFFER (aka MDL) very often; instead of * allocating and freeing with kernel functions, we chain them into * ndis_buffer_pool. When an MDL is freed, it is added to the list of * free MDLs. When allocated, we first check if there is one in free * list and if so just return it; otherwise, we allocate a new one and * return that. This reduces memory fragmentation. Windows DDK says * that the driver itself shouldn't check what is returned in * pool_handle, presumably because buffer pools are not used in * XP. However, as long as driver follows rest of the semantics - that * it should indicate maximum number of MDLs used with num_descr and * pass the same pool_handle in other buffer functions, this should * work. Sadly, though, NdisFreeBuffer doesn't pass the pool_handle, * so we use 'process' field of MDL to store pool_handle. */STDCALL void WRAP_EXPORT(NdisAllocateBufferPool) (NDIS_STATUS *status, struct ndis_buffer_pool **pool_handle, UINT num_descr){ struct ndis_buffer_pool *pool; TRACEENTER3("buffers: %d", num_descr); pool = kmalloc(sizeof(*pool), GFP_ATOMIC); if (!pool) { *status = NDIS_STATUS_RESOURCES; TRACEEXIT3(return); } kspin_lock_init(&pool->lock); pool->max_descr = num_descr; pool->num_allocated_descr = 0; pool->free_descr = NULL; *pool_handle = pool; *status = NDIS_STATUS_SUCCESS; TRACEEXIT3(return);}STDCALL void WRAP_EXPORT(NdisAllocateBuffer) (NDIS_STATUS *status, ndis_buffer **buffer, struct ndis_buffer_pool *pool, void *virt, UINT length){ ndis_buffer *descr; KIRQL irql; TRACEENTER3("pool: %p, allocated: %d", pool, pool->num_allocated_descr); if (!pool) { *status = NDIS_STATUS_FAILURE; TRACEEXIT4(return); } irql = kspin_lock_irql(&pool->lock, DISPATCH_LEVEL); if (pool->num_allocated_descr < pool->max_descr) { if (pool->free_descr) { descr = pool->free_descr; pool->free_descr = descr->next; memset(descr, 0, sizeof(*descr)); MmInitializeMdl(descr, virt, length); } else descr = allocate_init_mdl(virt, length); } else descr = NULL; if (descr) { /* NdisFreeBuffer doesn't pass pool, so we store pool * in unused field 'process' */ descr->process = pool; pool->num_allocated_descr++; *status = NDIS_STATUS_SUCCESS; DBGTRACE3("allocated buffer %p for %p", descr, virt); } else *status = NDIS_STATUS_FAILURE; *buffer = descr; kspin_unlock_irql(&pool->lock, irql); TRACEEXIT3(return);}STDCALL void WRAP_EXPORT(NdisFreeBuffer) (ndis_buffer *descr){ struct ndis_buffer_pool *pool; KIRQL irql; TRACEENTER3("buffer: %p", descr); pool = descr->process; if (!pool) { ERROR("pool for descriptor %p is invalid", descr); TRACEEXIT3(return); } irql = kspin_lock_irql(&pool->lock, DISPATCH_LEVEL); descr->next = pool->free_descr; pool->free_descr = descr; pool->num_allocated_descr--; kspin_unlock_irql(&pool->lock, irql); TRACEEXIT3(return);}STDCALL void WRAP_EXPORT(NdisFreeBufferPool) (struct ndis_buffer_pool *pool){ ndis_buffer *cur, *prev; KIRQL irql; TRACEENTER3("pool: %p", pool); irql = kspin_lock_irql(&pool->lock, DISPATCH_LEVEL); cur = pool->free_descr; while (cur) { prev = cur; cur = cur->next; prev->process = NULL; free_mdl(prev); } kspin_unlock_irql(&pool->lock, irql); kfree(pool); TRACEEXIT3(return);}STDCALL void WRAP_EXPORT(NdisAdjustBufferLength) (ndis_buffer *buffer, UINT length){ TRACEENTER4("%p", buffer); buffer->bytecount = length;}STDCALL void WRAP_EXPORT(NdisQueryBuffer) (ndis_buffer *buffer, void **virt, UINT *length){ TRACEENTER3("buffer: %p", buffer); if (virt) *virt = MmGetMdlVirtualAddress(buffer); if (length) *length = MmGetMdlByteCount(buffer); TRACEEXIT3(return);}STDCALL void WRAP_EXPORT(NdisQueryBufferSafe) (ndis_buffer *buffer, void **virt, UINT *length, enum mm_page_priority priority){ TRACEENTER3("%p, %p, %p", buffer, virt, length); if (virt) *virt = MmGetMdlVirtualAddress(buffer); if (length) *length = MmGetMdlByteCount(buffer);}STDCALL void *WRAP_EXPORT(NdisBufferVirtualAddress) (ndis_buffer *buffer){ TRACEENTER3("%p", buffer); return MmGetMdlVirtualAddress(buffer);}STDCALL ULONG WRAP_EXPORT(NdisBufferLength) (ndis_buffer *buffer){ TRACEENTER3("%p", buffer); return MmGetMdlByteCount(buffer);}STDCALL void WRAP_EXPORT(NdisAllocatePacketPool) (NDIS_STATUS *status, struct ndis_packet_pool **pool_handle, UINT num_descr, UINT rsvlen){ struct ndis_packet_pool *pool; TRACEENTER3("buffers: %d", num_descr); pool = kmalloc(sizeof(*pool), GFP_ATOMIC); if (!pool) { *status = NDIS_STATUS_RESOURCES; TRACEEXIT3(return); } kspin_lock_init(&pool->lock); pool->max_descr = num_descr; pool->num_allocated_descr = 0; pool->free_descr = NULL; *pool_handle = pool; *status = NDIS_STATUS_SUCCESS; TRACEEXIT3(return);}STDCALL void WRAP_EXPORT(NdisAllocatePacketPoolEx) (NDIS_STATUS *status, struct ndis_packet_pool **pool_handle, UINT num_descr, UINT overflowsize, UINT rsvlen){ TRACEENTER3(""); NdisAllocatePacketPool(status, pool_handle, num_descr, rsvlen); TRACEEXIT3(return);}STDCALL UINT WRAP_EXPORT(NdisPacketPoolUsage) (struct ndis_packet_pool *pool){ UINT i; KIRQL irql; irql = kspin_lock_irql(&pool->lock, DISPATCH_LEVEL); i = pool->num_allocated_descr; kspin_unlock_irql(&pool->lock, irql); return i;}struct ndis_packet *allocate_ndis_packet(void){ struct ndis_packet *packet; packet = kmem_cache_alloc(packet_cache, GFP_ATOMIC); if (packet) { memset(packet, 0, sizeof(*packet)); packet->private.oob_offset = offsetof(struct ndis_packet, oob_data); packet->private.packet_flags = fPACKET_ALLOCATED_BY_NDIS; } return packet;}void free_ndis_packet(struct ndis_packet *packet){ kmem_cache_free(packet_cache, packet);}STDCALL void WRAP_EXPORT(NdisAllocatePacket) (NDIS_STATUS *status, struct ndis_packet **packet, struct ndis_packet_pool *pool){ struct ndis_packet *descr; KIRQL irql; TRACEENTER3("pool: %p", pool); if (!pool) { *status = NDIS_STATUS_RESOURCES; TRACEEXIT3(return); } irql = kspin_lock_irql(&pool->lock, DISPATCH_LEVEL); if (pool->num_allocated_descr < pool->max_descr) { if (pool->free_descr) { descr = pool->free_descr; pool->free_descr = descr->next; memset(descr, 0, sizeof(*descr)); descr->private.oob_offset = offsetof(struct ndis_packet, oob_data); descr->private.packet_flags = fPACKET_ALLOCATED_BY_NDIS; } else descr = allocate_ndis_packet(); } else descr = NULL; if (descr) { pool->num_allocated_descr++; descr->private.pool = pool; *status = NDIS_STATUS_SUCCESS; } else *status = NDIS_STATUS_RESOURCES; *packet = descr; kspin_unlock_irql(&pool->lock, irql); DBGTRACE3("packet: %p, pool: %p", descr, pool); TRACEEXIT3(return);}STDCALL void WRAP_EXPORT(NdisDprAllocatePacket) (NDIS_STATUS *status, struct ndis_packet **packet, struct ndis_packet_pool *pool){ NdisAllocatePacket(status, packet, pool);}STDCALL void WRAP_EXPORT(NdisFreePacket) (struct ndis_packet *descr){ struct ndis_packet_pool *pool; KIRQL irql; TRACEENTER3("packet: %p, pool: %p", descr, descr->private.pool); pool = descr->private.pool; if (!pool) { ERROR("pool for descriptor %p is invalid", descr); TRACEEXIT3(return); } irql = kspin_lock_irql(&pool->lock, DISPATCH_LEVEL); descr->next = pool->free_descr; pool->free_descr = descr; pool->num_allocated_descr--; kspin_unlock_irql(&pool->lock, irql); TRACEEXIT3(return);}STDCALL void WRAP_EXPORT(NdisFreePacketPool) (struct ndis_packet_pool *pool){ struct ndis_packet *cur, *prev; KIRQL irql; TRACEENTER3("pool: %p", pool); irql = kspin_lock_irql(&pool->lock, DISPATCH_LEVEL); cur = pool->free_descr; while (cur) { prev = cur; cur = cur->next; free_ndis_packet(prev); } kspin_unlock_irql(&pool->lock, irql); kfree(pool); TRACEEXIT3(return);}STDCALL void WRAP_EXPORT(NdisSend) (NDIS_STATUS *status, struct ndis_handle *handle, struct ndis_packet *packet){ KIRQL irql; struct miniport_char *miniport = &handle->driver->miniport_char; if (miniport->send_packets) { struct ndis_packet *packets[1]; packets[0] = packet; irql = raise_irql(DISPATCH_LEVEL); LIN2WIN3(miniport->send_packets, handle->adapter_ctx, packets, 1); lower_irql(irql); if (test_bit(ATTR_SERIALIZED, &handle->attributes)) { *status = packet->oob_data.status; switch (*status) { case NDIS_STATUS_SUCCESS: sendpacket_done(handle, packet); break; case NDIS_STATUS_PENDING: break; case NDIS_STATUS_RESOURCES: handle->send_ok = 0; break; case NDIS_STATUS_FAILURE: default: break; } } else { *status = NDIS_STATUS_PENDING; } } else { irql = raise_irql(DISPATCH_LEVEL); *status = LIN2WIN3(miniport->send, handle->adapter_ctx, packet, 0); lower_irql(irql); switch (*status) { case NDIS_STATUS_SUCCESS: sendpacket_done(handle, packet); break; case NDIS_STATUS_PENDING: break; case NDIS_STATUS_RESOURCES: handle->send_ok = 0; break; case NDIS_STATUS_FAILURE: break; } } TRACEEXIT3(return);}STDCALL void WRAP_EXPORT(NdisMInitializeTimer) (struct ndis_miniport_timer *timer_handle, struct ndis_handle *handle, void *func, void *ctx){ TRACEENTER4("%s", ""); wrapper_init_timer(&timer_handle->ktimer, handle); init_dpc(&timer_handle->kdpc, func, ctx); wrapper_set_timer_dpc(timer_handle->ktimer.wrapper_timer, &timer_handle->kdpc); TRACEEXIT4(return);}STDCALL void WRAP_EXPORT(NdisInitializeTimer) (struct ndis_timer *timer_handle, void *func, void *ctx){ TRACEENTER4("%p, %p, %p", timer_handle, func, ctx); wrapper_init_timer(&timer_handle->ktimer, NULL); init_dpc(&timer_handle->kdpc, func, ctx); wrapper_set_timer_dpc(timer_handle->ktimer.wrapper_timer, &timer_handle->kdpc); TRACEEXIT4(return);}STDCALL void WRAP_EXPORT(NdisSetTimer) (struct ndis_timer *timer_handle, UINT ms){ unsigned long expires = jiffies + (ms * HZ) / 1000; TRACEENTER4("%p, %u", timer_handle, ms); wrapper_set_timer(timer_handle->ktimer.wrapper_timer, expires, 0, NULL); TRACEEXIT4(return);}STDCALL void WRAP_EXPORT(NdisMSetPeriodicTimer) (struct ndis_miniport_timer *timer_handle, UINT ms){ unsigned long expires = jiffies + (ms * HZ) / 1000; unsigned long repeat = ms * HZ / 1000; TRACEENTER4("%p, %u", timer_handle, ms); wrapper_set_timer(timer_handle->ktimer.wrapper_timer, expires, repeat, NULL); TRACEEXIT4(return);}STDCALL void WRAP_EXPORT(NdisMCancelTimer) (struct ndis_miniport_timer *timer_handle, BOOLEAN *canceled){ TRACEENTER4("%s", ""); wrapper_cancel_timer(timer_handle->ktimer.wrapper_timer, canceled); TRACEEXIT4(return);}STDCALL void WRAP_EXPORT(NdisCancelTimer) (struct ndis_timer *timer_handle, BOOLEAN *canceled){ TRACEENTER4("%s", ""); wrapper_cancel_timer(timer_handle->ktimer.wrapper_timer, canceled); TRACEEXIT4(return);}STDCALL void WRAP_EXPORT(NdisReadNetworkAddress) (NDIS_STATUS *status, void **addr, UINT *len, struct ndis_handle *handle){ struct ndis_config_param *setting; struct unicode_string key; struct ansi_string ansi; int ret;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -