📄 ndis.c
字号:
TRACEENTER3("%p, %p %u (%u)", wnd, buf, index, wnd->tx_dma_count); if (wnd->use_sg_dma) WARNING("buffer %p may have been unmapped already", buf); if (index >= wnd->tx_dma_count) { ERROR("invalid map register (%u >= %u)", index, wnd->tx_dma_count); return; } DBGTRACE4("%lx, %d, %d", (unsigned long)wnd->tx_dma_addr[index], MmGetMdlByteCount(buf), index); if (wnd->tx_dma_addr[index] == 0) {// ERROR("map register not used (%lu)", index); return; } PCI_DMA_UNMAP_SINGLE(wnd->wd->pci.pdev, wnd->tx_dma_addr[index], MmGetMdlByteCount(buf), PCI_DMA_TODEVICE); wnd->tx_dma_addr[index] = 0;}wstdcall void WIN_FUNC(NdisMAllocateSharedMemory,5) (struct ndis_miniport_block *nmb, ULONG size, BOOLEAN cached, void **virt, NDIS_PHY_ADDRESS *phys){ dma_addr_t dma_addr; struct wrap_device *wd = nmb->wnd->wd; TRACEENTER3("size: %u, cached: %d", size, cached); *virt = PCI_DMA_ALLOC_COHERENT(wd->pci.pdev, size, &dma_addr); if (!*virt) WARNING("couldn't allocate %d bytes of %scached DMA memory", size, cached ? "" : "un-"); *phys = dma_addr; TRACEEXIT3(return);}wstdcall void WIN_FUNC(NdisMFreeSharedMemory,5) (struct ndis_miniport_block *nmb, ULONG size, BOOLEAN cached, void *virt, NDIS_PHY_ADDRESS addr){ struct wrap_device *wd = nmb->wnd->wd; TRACEENTER3(""); PCI_DMA_FREE_COHERENT(wd->pci.pdev, size, virt, addr); TRACEEXIT3(return);}wstdcall void alloc_shared_memory_async(void *arg1, void *arg2){ struct wrap_ndis_device *wnd; struct alloc_shared_mem *alloc_shared_mem; struct miniport_char *miniport; void *virt; NDIS_PHY_ADDRESS phys; KIRQL irql; wnd = arg1; alloc_shared_mem = arg2; miniport = &wnd->wd->driver->ndis_driver->miniport; NdisMAllocateSharedMemory(wnd->nmb, alloc_shared_mem->size, alloc_shared_mem->cached, &virt, &phys); irql = serialize_lock_irql(wnd); LIN2WIN5(miniport->alloc_complete, wnd->nmb, virt, &phys, alloc_shared_mem->size, alloc_shared_mem->ctx); serialize_unlock_irql(wnd, irql); kfree(alloc_shared_mem);}WIN_FUNC_DECL(alloc_shared_memory_async,2)wstdcall NDIS_STATUS WIN_FUNC(NdisMAllocateSharedMemoryAsync,4) (struct ndis_miniport_block *nmb, ULONG size, BOOLEAN cached, void *ctx){ struct wrap_ndis_device *wnd = nmb->wnd; struct alloc_shared_mem *alloc_shared_mem; TRACEENTER3("wnd: %p", wnd); alloc_shared_mem = kmalloc(sizeof(*alloc_shared_mem), gfp_irql()); if (!alloc_shared_mem) { WARNING("couldn't allocate memory"); return NDIS_STATUS_FAILURE; } alloc_shared_mem->size = size; alloc_shared_mem->cached = cached; alloc_shared_mem->ctx = ctx; if (schedule_ntos_work_item(WIN_FUNC_PTR(alloc_shared_memory_async,2), wnd, alloc_shared_mem)) TRACEEXIT3(return NDIS_STATUS_FAILURE); TRACEEXIT3(return NDIS_STATUS_PENDING);}/* 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. */wstdcall void WIN_FUNC(NdisAllocateBufferPool,3) (NDIS_STATUS *status, struct ndis_buffer_pool **pool_handle, UINT num_descr){ struct ndis_buffer_pool *pool; TRACEENTER1("buffers: %d", num_descr); pool = kmalloc(sizeof(*pool), gfp_irql()); if (!pool) { *status = NDIS_STATUS_RESOURCES; TRACEEXIT3(return); } nt_spin_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; DBGTRACE1("pool: %p, num_descr: %d", pool, num_descr); TRACEEXIT1(return);}wstdcall void WIN_FUNC(NdisAllocateBuffer,5) (NDIS_STATUS *status, ndis_buffer **buffer, struct ndis_buffer_pool *pool, void *virt, UINT length){ ndis_buffer *descr; TRACEENTER4("pool: %p, allocated: %d", pool, pool->num_allocated_descr); if (!pool) { *status = NDIS_STATUS_FAILURE; TRACEEXIT4(return); } DBG_BLOCK(2) { if (pool->num_allocated_descr > pool->max_descr) WARNING("pool %p is full: %d(%d)", pool, pool->num_allocated_descr, pool->max_descr); } descr = atomic_remove_list_head(pool->free_descr, oldhead->next); if (descr) { typeof(descr->flags) flags; flags = descr->flags; MmInitializeMdl(descr, virt, length); if (flags & MDL_CACHE_ALLOCATED) descr->flags = MDL_CACHE_ALLOCATED; descr->flags |= MDL_SOURCE_IS_NONPAGED_POOL; } else { descr = allocate_init_mdl(virt, length); if (!descr) { WARNING("couldn't allocate buffer"); *status = NDIS_STATUS_FAILURE; TRACEEXIT4(return); } DBGTRACE4("allocated buffer %p for %p, %d", descr, virt, length); atomic_inc_var(pool->num_allocated_descr); MmBuildMdlForNonPagedPool(descr); } descr->pool = pool; *buffer = descr; *status = NDIS_STATUS_SUCCESS; DBGTRACE4("buffer: %p", descr); TRACEEXIT4(return);}wstdcall void WIN_FUNC(NdisFreeBuffer,1) (ndis_buffer *descr){ struct ndis_buffer_pool *pool; TRACEENTER4("descr: %p", descr); if (!descr || !descr->pool) { ERROR("invalid buffer"); TRACEEXIT4(return); } pool = descr->pool; if (pool->num_allocated_descr > MAX_ALLOCATED_NDIS_BUFFERS) { /* NB NB NB: set mdl's 'pool' field to NULL before * calling free_mdl; otherwise free_mdl calls * NdisFreeBuffer causing deadlock (for spinlock) */ atomic_dec_var(pool->num_allocated_descr); descr->pool = NULL; free_mdl(descr); } else atomic_insert_list_head(pool->free_descr, descr->next, descr); TRACEEXIT4(return);}wstdcall void WIN_FUNC(NdisFreeBufferPool,1) (struct ndis_buffer_pool *pool){ ndis_buffer *cur, *next; KIRQL irql; DBGTRACE3("pool: %p", pool); if (!pool) { WARNING("invalid pool"); TRACEEXIT3(return); } irql = nt_spin_lock_irql(&pool->lock, DISPATCH_LEVEL); cur = pool->free_descr; while (cur) { next = cur->next; cur->pool = NULL; free_mdl(cur); cur = next; } nt_spin_unlock_irql(&pool->lock, irql); kfree(pool); pool = NULL; TRACEEXIT3(return);}wstdcall void WIN_FUNC(NdisAdjustBufferLength,2) (ndis_buffer *buffer, UINT length){ TRACEENTER4("%p, %d", buffer, length); buffer->bytecount = length;}wstdcall void WIN_FUNC(NdisQueryBuffer,3) (ndis_buffer *buffer, void **virt, UINT *length){ TRACEENTER4("buffer: %p", buffer); if (virt) *virt = MmGetSystemAddressForMdl(buffer); *length = MmGetMdlByteCount(buffer); DBGTRACE4("%u", *length); TRACEEXIT4(return);}wstdcall void WIN_FUNC(NdisQueryBufferSafe,4) (ndis_buffer *buffer, void **virt, UINT *length, enum mm_page_priority priority){ TRACEENTER4("%p, %p, %p, %d", buffer, virt, length, priority); if (virt) *virt = MmGetSystemAddressForMdlSafe(buffer, priority); *length = MmGetMdlByteCount(buffer); DBGTRACE4("%u", *length);}wstdcall void *WIN_FUNC(NdisBufferVirtualAddress,1) (ndis_buffer *buffer){ TRACEENTER3("%p", buffer); return MmGetSystemAddressForMdl(buffer);}wstdcall ULONG WIN_FUNC(NdisBufferLength,1) (ndis_buffer *buffer){ TRACEENTER3("%p", buffer); return MmGetMdlByteCount(buffer);}wstdcall void WIN_FUNC(NdisQueryBufferOffset,3) (ndis_buffer *buffer, UINT *offset, UINT *length){ TRACEENTER3("%p", buffer); *offset = MmGetMdlByteOffset(buffer); *length = MmGetMdlByteCount(buffer); DBGTRACE3("%d, %d", *offset, *length);}wstdcall void WIN_FUNC(NdisUnchainBufferAtBack,2) (struct ndis_packet *packet, ndis_buffer **buffer){ ndis_buffer *b, *btail; TRACEENTER3("%p", packet); b = packet->private.buffer_head; if (!b) { /* no buffer in packet */ *buffer = NULL; TRACEEXIT3(return); } btail = packet->private.buffer_tail; *buffer = btail; if (b == btail) { /* one buffer in packet */ packet->private.buffer_head = NULL; packet->private.buffer_tail = NULL; } else { while (b->next != btail) b = b->next; packet->private.buffer_tail = b; b->next = NULL; } packet->private.valid_counts = FALSE; TRACEEXIT3(return);}wstdcall void WIN_FUNC(NdisUnchainBufferAtFront,2) (struct ndis_packet *packet, ndis_buffer **buffer){ TRACEENTER3("%p", packet); if (packet->private.buffer_head == NULL) { /* no buffer in packet */ *buffer = NULL; TRACEEXIT3(return); } *buffer = packet->private.buffer_head; if (packet->private.buffer_head == packet->private.buffer_tail) { /* one buffer in packet */ packet->private.buffer_head = NULL; packet->private.buffer_tail = NULL; } else packet->private.buffer_head = (*buffer)->next; packet->private.valid_counts = FALSE; TRACEEXIT3(return);}wstdcall void WIN_FUNC(NdisGetFirstBufferFromPacketSafe,6) (struct ndis_packet *packet, ndis_buffer **first_buffer, void **first_buffer_va, UINT *first_buffer_length, UINT *total_buffer_length, enum mm_page_priority priority){ ndis_buffer *b = packet->private.buffer_head; TRACEENTER3("%p(%p)", packet, b); *first_buffer = b; if (b) { *first_buffer_va = MmGetSystemAddressForMdlSafe(b, priority); *first_buffer_length = *total_buffer_length = MmGetMdlByteCount(b); for (b = b->next; b; b = b->next) *total_buffer_length += MmGetMdlByteCount(b); } else { *first_buffer_va = NULL; *first_buffer_length = 0; *total_buffer_length = 0; } DBGTRACE3("%p, %d, %d", *first_buffer_va, *first_buffer_length, *total_buffer_length); TRACEEXIT3(return);}wstdcall void WIN_FUNC(NdisGetFirstBufferFromPacket,6) (struct ndis_packet *packet, ndis_buffer **first_buffer, void **first_buffer_va, UINT *first_buffer_length, UINT *total_buffer_length, enum mm_page_priority priority){ NdisGetFirstBufferFromPacketSafe(packet, first_buffer, first_buffer_va, first_buffer_length, total_buffer_length, NormalPagePriority);}wstdcall void WIN_FUNC(NdisAllocatePacketPoolEx,5) (NDIS_STATUS *status, struct ndis_packet_pool **pool_handle, UINT num_descr, UINT overflowsize, UINT proto_rsvd_length){ struct ndis_packet_pool *pool; TRACEENTER3("buffers: %d, length: %d", num_descr, proto_rsvd_length); pool = kmalloc(sizeof(*pool), gfp_irql()); if (!pool) { *status = NDIS_STATUS_RESOURCES; TRACEEXIT3(return); } memset(pool, 0, sizeof(*pool)); nt_spin_lock_init(&pool->lock); pool->max_descr = num_descr; pool->num_allocated_descr = 0; pool->num_used_descr = 0; pool->free_descr = NULL; pool->proto_rsvd_length = proto_rsvd_length; *pool_handle = pool; *status = NDIS_STATUS_SUCCESS; DBGTRACE3("pool: %p", pool); TRACEEXIT3(return);}wstdcall void WIN_FUNC(NdisAllocatePacketPool,4) (NDIS_STATUS *status, struct ndis_packet_pool **pool_handle, UINT num_descr, UINT proto_rsvd_length){ NdisAllocatePacketPoolEx(status, pool_handle, num_descr, 0, proto_rsvd_length); TRACEEXIT3(return);}wstdcall void WIN_FUNC(NdisFreePacketPool,1) (struct ndis_packet_pool *pool){ struct ndis_packet *packet, *next; KIRQL irql; TRACEENTER3("pool: %p", pool); if (!pool) { WARNING("invalid pool"); TRACEEXIT3(return); } irql = nt_spin_lock_irql(&pool->lock, DISPATCH_LEVEL); packet = pool->free_descr; while (packet) { next = (NDIS_PACKET_OOB_DATA(packet))->next; kfree(packet); packet = next; } pool->num_allocated_descr = 0; pool->num_used_descr = 0; pool->free_descr = NULL; nt_spin_unlock_irql(&pool->lock, irql); kfree(pool); TRACEEXIT3(return);}wstdcall UINT WIN_FUNC(NdisPacketPoolUsage,1) (struct ndis_packet_pool *pool){ TRACEEXIT4(return pool->num_used_descr);}wstdcall void WIN_FUNC(NdisAllocatePacket,3) (NDIS_STATUS *status, struct ndis_packet **packet, struct ndis_packet_pool *pool){ struct ndis_packet *ndis_packet; int packet_length; TRACEENTER4("pool: %p", pool); if (!pool) { *status = NDIS_STATUS_RESOURCES; TRACEEXIT4(return); } DBG_BLOCK(2) { if (pool->num_used_descr >= pool->max_descr) WARNING("pool %p is full: %d(%d)", pool, pool->num_used_descr, pool->max_descr); } /* packet has space for 1 byte in protocol_reserved field */ packet_length = sizeof(*ndis_packet) - 1 + pool->proto_rsvd_length + sizeof(struct ndis_packet_oob_data); ndis_packet = atomic_remove_list_head(pool->free_descr, (NDIS_PACKET_OOB_DATA(oldhead))->next); if (!ndis_packet) { ndis_packet = kmalloc(packet_length, gfp_irql()); if (!ndis_packet) { WARNING("couldn't allocate packet"); *status = NDIS_STATUS_RESOURCES; return; } atomic_inc_var(pool->num_allocated_descr); } DBGTRACE3("packet: %p", ndis_packet); atomic_inc_var(pool->num_used_descr); memset(ndis_packet, 0, packet_length); ndis_packet->private.oob_offset = packet_length - sizeof(struct ndis_packet_oob_data); ndis_packet->private.packet_flags = fPACKET_ALLOCATED_BY_NDIS;// | NDIS_PROTOCOL_ID_TCP_IP; ndis_packet->private.pool = pool; *packet = ndis_packet; *status = NDIS_STATUS_SUCCESS; DBGTRACE4("packet: %p, pool: %p", ndis_packet, pool); TRACEEXIT4(return);}wstdcall void WIN_FUNC(NdisDprAllocatePacket,3) (NDIS_STATUS *status, struct ndis_packet **packet, struct ndis_packet_pool *pool)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -