📄 ndis.c
字号:
MmGetMdlByteCount(buf)); DBG_BLOCK(4) { dump_bytes(__FUNCTION__, MmGetSystemAddressForMdl(buf), MmGetMdlByteCount(buf)); } wnd->dma_map_addr[index] = PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev, MmGetSystemAddressForMdl(buf), MmGetMdlByteCount(buf), PCI_DMA_TODEVICE); phy_addr_array[0].phy_addr = wnd->dma_map_addr[index]; phy_addr_array[0].length = MmGetMdlByteCount(buf); TRACE4("%Lx, %d, %d", phy_addr_array[0].phy_addr, phy_addr_array[0].length, index); *array_size = 1;}wstdcall void WIN_FUNC(NdisMCompleteBufferPhysicalMapping,3) (struct ndis_miniport_block *nmb, ndis_buffer *buf, ULONG index){ struct wrap_ndis_device *wnd = nmb->wnd; ENTER3("%p, %p %u (%u)", wnd, buf, index, wnd->dma_map_count); if (unlikely(wnd->sg_dma_size)) WARNING("buffer %p may have been unmapped already", buf); if (index >= wnd->dma_map_count) { ERROR("invalid map register (%u >= %u)", index, wnd->dma_map_count); return; } TRACE4("%lx", (unsigned long)wnd->dma_map_addr[index]); if (wnd->dma_map_addr[index]) { PCI_DMA_UNMAP_SINGLE(wnd->wd->pci.pdev, wnd->dma_map_addr[index], MmGetMdlByteCount(buf), PCI_DMA_TODEVICE); wnd->dma_map_addr[index] = 0; } else WARNING("map registers at %u not used", index);}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; ENTER3("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; EXIT3(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; ENTER3(""); PCI_DMA_FREE_COHERENT(wd->pci.pdev, size, virt, addr); EXIT3(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; ENTER3("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)) EXIT3(return NDIS_STATUS_FAILURE); EXIT3(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; ENTER1("buffers: %d", num_descr); pool = kmalloc(sizeof(*pool), gfp_irql()); if (!pool) { *status = NDIS_STATUS_RESOURCES; EXIT3(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; TRACE1("pool: %p, num_descr: %d", pool, num_descr); EXIT1(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; KIRQL irql; ENTER4("pool: %p, allocated: %d", pool, pool->num_allocated_descr); if (!pool) { *status = NDIS_STATUS_FAILURE; EXIT4(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); } irql = nt_spin_lock_irql(&pool->lock, DISPATCH_LEVEL); if (pool->free_descr) { typeof(descr->flags) flags; descr = pool->free_descr; pool->free_descr = descr->next; nt_spin_unlock_irql(&pool->lock, irql); flags = descr->flags; memset(descr, 0, sizeof(*descr)); MmInitializeMdl(descr, virt, length); if (flags & MDL_CACHE_ALLOCATED) descr->flags |= MDL_CACHE_ALLOCATED; } else { nt_spin_unlock_irql(&pool->lock, irql); descr = allocate_init_mdl(virt, length); if (!descr) { WARNING("couldn't allocate buffer"); *status = NDIS_STATUS_FAILURE; EXIT4(return); } TRACE4("allocated buffer %p for %p, %d", descr, virt, length); atomic_inc_var(pool->num_allocated_descr); } /* TODO: make sure this mdl can map given buffer */ MmBuildMdlForNonPagedPool(descr);// descr->flags |= MDL_ALLOCATED_FIXED_SIZE |// MDL_MAPPED_TO_SYSTEM_VA | MDL_PAGES_LOCKED; descr->pool = pool; *buffer = descr; *status = NDIS_STATUS_SUCCESS; TRACE4("buffer: %p", descr); EXIT4(return);}wstdcall void WIN_FUNC(NdisFreeBuffer,1) (ndis_buffer *buffer){ struct ndis_buffer_pool *pool; KIRQL irql; ENTER4("%p", buffer); if (!buffer || !buffer->pool) { ERROR("invalid buffer"); EXIT4(return); } pool = buffer->pool; irql = nt_spin_lock_irql(&pool->lock, DISPATCH_LEVEL); 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) */ pool->num_allocated_descr--; buffer->pool = NULL; nt_spin_unlock_irql(&pool->lock, irql); free_mdl(buffer); } else { buffer->next = pool->free_descr; pool->free_descr = buffer; nt_spin_unlock_irql(&pool->lock, irql); } EXIT4(return);}wstdcall void WIN_FUNC(NdisFreeBufferPool,1) (struct ndis_buffer_pool *pool){ ndis_buffer *cur, *next; KIRQL irql; TRACE3("pool: %p", pool); if (!pool) { WARNING("invalid pool"); EXIT3(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; EXIT3(return);}wstdcall void WIN_FUNC(NdisAdjustBufferLength,2) (ndis_buffer *buffer, UINT length){ ENTER4("%p, %d", buffer, length); buffer->bytecount = length;}wstdcall void WIN_FUNC(NdisQueryBuffer,3) (ndis_buffer *buffer, void **virt, UINT *length){ ENTER4("buffer: %p", buffer); if (virt) *virt = MmGetSystemAddressForMdl(buffer); *length = MmGetMdlByteCount(buffer); TRACE4("%p, %u", virt? *virt : NULL, *length); return;}wstdcall void WIN_FUNC(NdisQueryBufferSafe,4) (ndis_buffer *buffer, void **virt, UINT *length, enum mm_page_priority priority){ ENTER4("%p, %p, %p, %d", buffer, virt, length, priority); if (virt) *virt = MmGetSystemAddressForMdlSafe(buffer, priority); *length = MmGetMdlByteCount(buffer); TRACE4("%p, %u", virt? *virt : NULL, *length);}wstdcall void *WIN_FUNC(NdisBufferVirtualAddress,1) (ndis_buffer *buffer){ ENTER3("%p", buffer); return MmGetSystemAddressForMdl(buffer);}wstdcall ULONG WIN_FUNC(NdisBufferLength,1) (ndis_buffer *buffer){ ENTER3("%p", buffer); return MmGetMdlByteCount(buffer);}wstdcall void WIN_FUNC(NdisQueryBufferOffset,3) (ndis_buffer *buffer, UINT *offset, UINT *length){ ENTER3("%p", buffer); *offset = MmGetMdlByteOffset(buffer); *length = MmGetMdlByteCount(buffer); TRACE3("%d, %d", *offset, *length);}wstdcall void WIN_FUNC(NdisUnchainBufferAtBack,2) (struct ndis_packet *packet, ndis_buffer **buffer){ ndis_buffer *b, *btail; ENTER3("%p", packet); b = packet->private.buffer_head; if (!b) { /* no buffer in packet */ *buffer = NULL; EXIT3(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; EXIT3(return);}wstdcall void WIN_FUNC(NdisUnchainBufferAtFront,2) (struct ndis_packet *packet, ndis_buffer **buffer){ ENTER3("%p", packet); if (packet->private.buffer_head == NULL) { /* no buffer in packet */ *buffer = NULL; EXIT3(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; EXIT3(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; ENTER3("%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; } TRACE3("%p, %d, %d", *first_buffer_va, *first_buffer_length, *total_buffer_length); EXIT3(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; ENTER3("buffers: %d, length: %d", num_descr, proto_rsvd_length); pool = kmalloc(sizeof(*pool), gfp_irql()); if (!pool) { *status = NDIS_STATUS_RESOURCES; EXIT3(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; TRACE3("pool: %p", pool); EXIT3(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); EXIT3(return);}wstdcall void WIN_FUNC(NdisFreePacketPool,1) (struct ndis_packet_pool *pool){ struct ndis_packet *packet, *next; KIRQL irql; ENTER3("pool: %p", pool); if (!pool) { WARNING("invalid pool"); EXIT3(return); } irql = nt_spin_lock_irql(&pool->lock, DISPATCH_LEVEL); packet = pool->free_descr; while (packet) { next = (struct ndis_packet *)packet->reserved[0]; 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); EXIT3(return);}wstdcall UINT WIN_FUNC(NdisPacketPoolUsage,1) (struct ndis_packet_pool *pool){ EXIT4(return pool->num_used_descr);}wstdcall void WIN_FUNC(NdisAllocatePacket,3) (NDIS_STATUS *status, struct ndis_packet **ndis_packet, struct ndis_packet_pool *pool){ struct ndis_packet *packet; int packet_length; KIRQL irql; ENTER4("pool: %p", pool); if (!pool) { *status = NDIS_STATUS_RESOURCES; EXIT4(return); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -