📄 ndis.c
字号:
unsigned int skb_size; TRACEENTER3("handle = %p, packet = %p, bytes_txed = %d", handle, packet, bytes_txed); if (!packet) { WARNING("%s", "illegal packet"); TRACEEXIT3(return); } skb_size = sizeof(packet->header) + packet->look_ahead_size + bytes_txed; skb = dev_alloc_skb(skb_size); if (!skb) { kfree(packet->look_ahead); free_ndis_packet(packet); handle->stats.rx_dropped++; TRACEEXIT3(return); } skb->dev = handle->net_dev; memcpy(skb->data, packet->header, sizeof(packet->header)); memcpy(skb->data + sizeof(packet->header), packet->look_ahead, packet->look_ahead_size); memcpy(skb->data + sizeof(packet->header) + packet->look_ahead_size, MmGetMdlVirtualAddress(packet->private.buffer_head), bytes_txed); kfree(packet->look_ahead); free_ndis_packet(packet); skb_put(skb, skb_size); skb->protocol = eth_type_trans(skb, handle->net_dev); handle->stats.rx_bytes += skb_size; handle->stats.rx_packets++; netif_rx(skb);}/* called via function pointer */STDCALL voidEthRxComplete(struct ndis_handle *handle){ DBGTRACE3("%s", "");}/* Called via function pointer if query returns NDIS_STATUS_PENDING */STDCALL voidNdisMQueryInformationComplete(struct ndis_handle *handle, NDIS_STATUS status){ TRACEENTER3("%08X", status); handle->ndis_comm_res = status; handle->ndis_comm_done = 1; wake_up(&handle->ndis_comm_wq); TRACEEXIT3(return);}STDCALL void WRAP_EXPORT(NdisMCoRequestComplete) (NDIS_STATUS status, struct ndis_handle *handle, struct ndis_request *ndis_request){ TRACEENTER3("%08X", status); handle->ndis_comm_res = status; handle->ndis_comm_done = 1; wake_up(&handle->ndis_comm_wq); TRACEEXIT3(return);}/* Called via function pointer if setinfo returns NDIS_STATUS_PENDING */STDCALL voidNdisMSetInformationComplete(struct ndis_handle *handle, NDIS_STATUS status){ TRACEENTER3("status = %08X", status); handle->ndis_comm_res = status; handle->ndis_comm_done = 1; wake_up(&handle->ndis_comm_wq); TRACEEXIT3(return);}STDCALL void WRAP_EXPORT(NdisMSleep) (ULONG us_to_sleep){ TRACEENTER4("us: %u", us_to_sleep); if (us_to_sleep > 0) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((us_to_sleep * HZ)/1000000); DBGTRACE4("%s", "woke up"); } TRACEEXIT4(return);}STDCALL void WRAP_EXPORT(NdisGetCurrentSystemTime) (LARGE_INTEGER *time){ *time = ticks_1601();}STDCALL NDIS_STATUS WRAP_EXPORT(NdisMRegisterIoPortRange) (void **virt, struct ndis_handle *handle, UINT start, UINT len){ TRACEENTER3("%08x %08x", start, len); *virt = (void *)(ULONG_PTR)start; return NDIS_STATUS_SUCCESS;}STDCALL void WRAP_EXPORT(NdisMDeregisterIoPortRange) (struct ndis_handle *handle, UINT start, UINT len, void* virt){ TRACEENTER1("%08x %08x", start, len);}STDCALL LONG WRAP_EXPORT(NdisInterlockedDecrement) (LONG *val){ LONG x; TRACEENTER4("%s", ""); kspin_lock(&ntoskernel_lock); (*val)--; x = *val; kspin_unlock(&ntoskernel_lock); TRACEEXIT4(return x);}STDCALL LONG WRAP_EXPORT(NdisInterlockedIncrement) (LONG *val){ LONG x; TRACEENTER4("%s", ""); kspin_lock(&ntoskernel_lock); (*val)++; x = *val; kspin_unlock(&ntoskernel_lock); TRACEEXIT4(return x);}STDCALL struct list_entry * WRAP_EXPORT(NdisInterlockedInsertHeadList) (struct list_entry *head, struct list_entry *entry, struct ndis_spinlock *lock){ struct list_entry *flink; TRACEENTER4("lock: %p", lock); NdisAcquireSpinLock(lock); flink = head->fwd_link; entry->fwd_link = flink; entry->bwd_link = head; flink->bwd_link = entry; head->fwd_link = entry; NdisReleaseSpinLock(lock); TRACEEXIT4(return (flink == head) ? NULL : flink);}STDCALL struct list_entry * WRAP_EXPORT(NdisInterlockedInsertTailList) (struct list_entry *head, struct list_entry *entry, struct ndis_spinlock *lock){ struct list_entry *flink; TRACEENTER4("lock: %p", lock); NdisAcquireSpinLock(lock); flink = head->bwd_link; entry->fwd_link = head; entry->bwd_link = flink; flink->fwd_link = entry; head->bwd_link = entry; NdisReleaseSpinLock(lock); TRACEEXIT4(return (flink == head) ? NULL : flink);}STDCALL struct list_entry * WRAP_EXPORT(NdisInterlockedRemoveHeadList) (struct list_entry *head, struct ndis_spinlock *lock){ struct list_entry *flink; TRACEENTER4("lock: %p", lock); NdisAcquireSpinLock(lock); flink = head->fwd_link; head->fwd_link = flink->fwd_link; head->fwd_link->bwd_link = head; NdisReleaseSpinLock(lock); TRACEEXIT4(return (flink == head) ? NULL : flink);}STDCALL NDIS_STATUS WRAP_EXPORT(NdisMInitializeScatterGatherDma) (struct ndis_handle *handle, UCHAR dma_size, ULONG max_phy_map){ TRACEENTER2("dma_size=%d, maxtransfer=%u", dma_size, max_phy_map);#ifdef CONFIG_X86_64 if (dma_size != NDIS_DMA_64BITS) ERROR("DMA size is not 64-bits");#endif handle->use_sg_dma = 1; return NDIS_STATUS_SUCCESS;}STDCALL ULONG WRAP_EXPORT(NdisMGetDmaAlignment) (struct ndis_handle *handle){ TRACEENTER3("%s", "");#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) return dma_get_cache_alignment();#else return L1_CACHE_BYTES;#endif}STDCALL void WRAP_EXPORT(NdisQueryBufferOffset) (ndis_buffer *buffer, UINT *offset, UINT *length){ TRACEENTER3("%s", ""); *offset = MmGetMdlByteOffset(buffer); *length = MmGetMdlByteCount(buffer);}STDCALL CHAR WRAP_EXPORT(NdisSystemProcessorCount) (void){ return NR_CPUS;}STDCALL void WRAP_EXPORT(NdisInitializeEvent) (struct ndis_event *ndis_event){ TRACEENTER3("%p", ndis_event); KeInitializeEvent(&ndis_event->kevent, NotificationEvent, 0);}STDCALL BOOLEAN WRAP_EXPORT(NdisWaitEvent) (struct ndis_event *ndis_event, UINT ms){ LARGE_INTEGER ticks; NTSTATUS res; TRACEENTER3("%p %u", ndis_event, ms); ticks = ms * 10000; res = KeWaitForSingleObject(&ndis_event->kevent, 0, 0, 0, &ticks); if (res == STATUS_SUCCESS) TRACEEXIT3(return TRUE); else TRACEEXIT3(return FALSE);}STDCALL void WRAP_EXPORT(NdisSetEvent) (struct ndis_event *ndis_event){ TRACEENTER3("%p", ndis_event); KeSetEvent(&ndis_event->kevent, 0, 0);}STDCALL void WRAP_EXPORT(NdisResetEvent) (struct ndis_event *ndis_event){ TRACEENTER3("%p", ndis_event); KeResetEvent(&ndis_event->kevent);}/* called via function pointer */STDCALL voidNdisMResetComplete(struct ndis_handle *handle, NDIS_STATUS status, BOOLEAN address_reset){ TRACEENTER2("status: %08X, reset status: %u", status, address_reset); handle->ndis_comm_res = status; handle->reset_status = status; handle->ndis_comm_done = 1; wake_up(&handle->ndis_comm_wq); TRACEEXIT3(return);}/* one worker for all drivers/handles */static void ndis_worker(void *data){ struct ndis_work_entry *ndis_work_entry; struct ndis_sched_work_item *sched_work_item; struct ndis_alloc_mem_work_item *alloc_mem; struct ndis_free_mem_work_item *free_mem; struct ndis_io_work_item *io_work_item; struct ndis_packet *packet; struct ndis_handle *handle; struct miniport_char *miniport; void *virt; NDIS_PHY_ADDRESS phys; KIRQL irql; TRACEENTER3("%s", ""); while (1) { irql = kspin_lock_irql(&ndis_work_list_lock, DISPATCH_LEVEL); if (list_empty(&ndis_work_list)) ndis_work_entry = NULL; else { ndis_work_entry = list_entry(ndis_work_list.next, struct ndis_work_entry, list); list_del(&ndis_work_entry->list); } kspin_unlock_irql(&ndis_work_list_lock, irql); if (!ndis_work_entry) { DBGTRACE3("%s", "No more work"); break; } handle = ndis_work_entry->handle; switch (ndis_work_entry->type) { case NDIS_SCHED_WORK_ITEM: sched_work_item = ndis_work_entry->entry.sched_work_item; DBGTRACE3("Calling work at %p with parameter %p", sched_work_item->func, sched_work_item->ctx); LIN2WIN2(sched_work_item->func, sched_work_item, sched_work_item->ctx); break; case NDIS_IO_WORK_ITEM: io_work_item = ndis_work_entry->entry.io_work_item; DBGTRACE3("Calling work at %p with parameter %p", io_work_item->func, io_work_item->ctx); LIN2WIN2(io_work_item->func, io_work_item->device_object, io_work_item->ctx); break; case NDIS_ALLOC_MEM_WORK_ITEM: alloc_mem = &ndis_work_entry->entry.alloc_mem_work_item; DBGTRACE3("Allocating %scached memory of length %ld", alloc_mem->cached ? "" : "un-", alloc_mem->size); miniport = &handle->driver->miniport_char; NdisMAllocateSharedMemory(handle, alloc_mem->size, alloc_mem->cached, &virt, &phys); irql = raise_irql(DISPATCH_LEVEL); LIN2WIN5(miniport->alloc_complete, handle, virt, &phys, alloc_mem->size, alloc_mem->ctx); lower_irql(irql); break; case NDIS_FREE_MEM_WORK_ITEM: free_mem = &ndis_work_entry->entry.free_mem_work_item; DBGTRACE3("Freeing memory of size %d, flags %d at %p", free_mem->length, free_mem->flags, free_mem->addr); if (free_mem->addr) vfree(free_mem->addr); break; case NDIS_RETURN_PACKET_WORK_ITEM: packet = ndis_work_entry->entry.return_packet; miniport = &handle->driver->miniport_char; irql = raise_irql(DISPATCH_LEVEL); LIN2WIN2(miniport->return_packet, handle->adapter_ctx, packet); lower_irql(irql); break; default: ERROR("unknown ndis work item: %d", ndis_work_entry->type); break; } kfree(ndis_work_entry); } TRACEEXIT3(return);}STDCALL struct ndis_io_work_item *WRAP_EXPORT(IoAllocateWorkItem) (void *device_object){ struct ndis_io_work_item *io_work_item; io_work_item = kmalloc(sizeof(*io_work_item), GFP_ATOMIC); if (!io_work_item) return NULL; io_work_item->device_object = device_object; return io_work_item;}STDCALL void WRAP_EXPORT(IoFreeWorkItem) (struct ndis_io_work_item *io_work_item){ kfree(io_work_item); return;}STDCALL void WRAP_EXPORT(IoQueueWorkItem) (struct ndis_io_work_item *io_work_item, void *func, enum work_queue_type queue_type, void *ctx){ struct ndis_work_entry *ndis_work_entry; KIRQL irql; TRACEENTER3("%s", ""); if (io_work_item == NULL) { ERROR("%s", "io_work_item is NULL; item not queued"); return; } ndis_work_entry = kmalloc(sizeof(*ndis_work_entry), GFP_ATOMIC); if (!ndis_work_entry) BUG(); ndis_work_entry->type = NDIS_IO_WORK_ITEM; io_work_item->func = func; io_work_item->ctx = ctx; ndis_work_entry->entry.io_work_item = io_work_item; 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);}STDCALL NDIS_STATUS WRAP_EXPORT(NdisScheduleWorkItem) (struct ndis_sched_work_item *ndis_sched_work_item){ struct ndis_work_entry *ndis_work_entry; KIRQL irql; TRACEENTER3("%s", ""); /* this function is called from irq_bh by realtek driver */ ndis_work_entry = kmalloc(sizeof(*ndis_work_entry), GFP_ATOMIC); if (!ndis_work_entry) BUG(); ndis_work_entry->type = NDIS_SCHED_WORK_ITEM; ndis_work_entry->entry.sched_work_item = ndis_sched_work_item; 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_SUCCESS);}STDCALL void WRAP_EXPORT(NdisUnchainBufferAtBack) (struct ndis_packet *packet, ndis_buffer **buffer){ ndis_buffer *b, *btail; TRACEENTER3("%p", packet); if (packet == NULL || buffer == NULL) return; b = packet->private.buffer_head; if (!b) { /* no buffer in packet */ *buffer = NULL; TRACEEXIT3(return); } btail = packet->private.buffer_tail; *buffer = btail; packet->private.valid_counts = FALSE; 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; } TRACEEXIT3(return);}STDCALL void WRAP_EXPORT(NdisUnchainBufferAtFront) (struct ndis_packet *packet, ndis_buffer **buffer){ TRACEENTER3("%p", packet); if (buffer == NULL) return; if (p
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -