📄 ndis.c
字号:
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 = kzalloc(sizeof(*pool), irql_gfp()); if (!pool) { *status = NDIS_STATUS_RESOURCES; EXIT3(return); } 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; ENTER3("pool: %p", pool); if (!pool) { WARNING("invalid pool"); EXIT3(return); } spin_lock_bh(&pool->lock); 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; spin_unlock_bh(&pool->lock); 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; ENTER4("pool: %p", pool); if (!pool) { *status = NDIS_STATUS_RESOURCES; *ndis_packet = NULL; EXIT4(return); } assert_irql(_irql_ <= SOFT_LEVEL); if (pool->num_used_descr > pool->max_descr) { TRACE3("pool %p is full: %d(%d)", pool, pool->num_used_descr, pool->max_descr);#ifndef ALLOW_POOL_OVERFLOW *status = NDIS_STATUS_RESOURCES; *ndis_packet = NULL; return;#endif } /* packet has space for 1 byte in protocol_reserved field */ packet_length = sizeof(*packet) - 1 + pool->proto_rsvd_length + sizeof(struct ndis_packet_oob_data); spin_lock_bh(&pool->lock); if ((packet = pool->free_descr)) pool->free_descr = (void *)packet->reserved[0]; spin_unlock_bh(&pool->lock); if (!packet) { packet = kmalloc(packet_length, irql_gfp()); if (!packet) { WARNING("couldn't allocate packet"); *status = NDIS_STATUS_RESOURCES; *ndis_packet = NULL; return; } atomic_inc_var(pool->num_allocated_descr); } TRACE4("%p, %p, %p", pool, packet, pool->free_descr); atomic_inc_var(pool->num_used_descr); memset(packet, 0, packet_length); packet->private.oob_offset = packet_length - sizeof(struct ndis_packet_oob_data); packet->private.packet_flags = fPACKET_ALLOCATED_BY_NDIS; packet->private.pool = pool; *ndis_packet = packet; *status = NDIS_STATUS_SUCCESS; EXIT4(return);}wstdcall void WIN_FUNC(NdisDprAllocatePacket,3) (NDIS_STATUS *status, struct ndis_packet **packet, struct ndis_packet_pool *pool){ NdisAllocatePacket(status, packet, pool);}wstdcall void WIN_FUNC(NdisFreePacket,1) (struct ndis_packet *packet){ struct ndis_packet_pool *pool; ENTER4("packet: %p, pool: %p", packet, packet->private.pool); pool = packet->private.pool; if (!pool) { ERROR("pool for descriptor %p is invalid", packet); EXIT4(return); } spin_lock_bh(&pool->lock); pool->num_used_descr--; if (packet->reserved[1]) { TRACE3("%p, %p", packet, (void *)packet->reserved[1]); kfree((void *)packet->reserved[1]); packet->reserved[1] = 0; } if (pool->num_allocated_descr > MAX_ALLOCATED_NDIS_PACKETS) { TRACE3("%p", packet); pool->num_allocated_descr--; kfree(packet); } else { TRACE4("%p, %p, %p", pool, packet, pool->free_descr); packet->reserved[0] = (typeof(packet->reserved[0]))pool->free_descr; pool->free_descr = packet; } spin_unlock_bh(&pool->lock); EXIT4(return);}wstdcall struct ndis_packet_stack *WIN_FUNC(NdisIMGetCurrentPacketStack,2) (struct ndis_packet *packet, BOOLEAN *stacks_remain){ struct ndis_packet_stack *stack; if (!packet->reserved[1]) { stack = kzalloc(2 * sizeof(*stack), irql_gfp()); TRACE3("%p, %p", packet, stack); packet->reserved[1] = (typeof(packet->reserved[1]))stack; } else { stack = (void *)packet->reserved[1];; if (xchg(&stack->ndis_reserved[0], 1)) { stack++; if (xchg(&stack->ndis_reserved[0], 1)) stack = NULL; } TRACE3("%p", stack); } if (stack) *stacks_remain = TRUE; else *stacks_remain = FALSE; EXIT3(return stack);}wstdcall void WIN_FUNC(NdisCopyFromPacketToPacketSafe,7) (struct ndis_packet *dst, UINT dst_offset, UINT num_to_copy, struct ndis_packet *src, UINT src_offset, UINT *num_copied, enum mm_page_priority priority){ UINT dst_n, src_n, n, left; ndis_buffer *dst_buf; ndis_buffer *src_buf; ENTER4(""); if (!dst || !src) { *num_copied = 0; EXIT4(return); } dst_buf = dst->private.buffer_head; src_buf = src->private.buffer_head; if (!dst_buf || !src_buf) { *num_copied = 0; EXIT4(return); } dst_n = MmGetMdlByteCount(dst_buf) - dst_offset; src_n = MmGetMdlByteCount(src_buf) - src_offset; n = min(src_n, dst_n); n = min(n, num_to_copy); memcpy(MmGetSystemAddressForMdl(dst_buf) + dst_offset, MmGetSystemAddressForMdl(src_buf) + src_offset, n); left = num_to_copy - n; while (left > 0) { src_offset += n; dst_offset += n; dst_n -= n; src_n -= n; if (dst_n == 0) { dst_buf = dst_buf->next; if (!dst_buf) break; dst_n = MmGetMdlByteCount(dst_buf); dst_offset = 0; } if (src_n == 0) { src_buf = src_buf->next; if (!src_buf) break; src_n = MmGetMdlByteCount(src_buf); src_offset = 0; } n = min(src_n, dst_n); n = min(n, left); memcpy(MmGetSystemAddressForMdl(dst_buf) + dst_offset, MmGetSystemAddressForMdl(src_buf) + src_offset, n); left -= n; } *num_copied = num_to_copy - left; EXIT4(return);}wstdcall void WIN_FUNC(NdisCopyFromPacketToPacket,6) (struct ndis_packet *dst, UINT dst_offset, UINT num_to_copy, struct ndis_packet *src, UINT src_offset, UINT *num_copied){ NdisCopyFromPacketToPacketSafe(dst, dst_offset, num_to_copy, src, src_offset, num_copied, NormalPagePriority); return;}wstdcall void WIN_FUNC(NdisIMCopySendPerPacketInfo,2) (struct ndis_packet *dst, struct ndis_packet *src){ struct ndis_packet_oob_data *dst_oob, *src_oob; dst_oob = NDIS_PACKET_OOB_DATA(dst); src_oob = NDIS_PACKET_OOB_DATA(src); memcpy(&dst_oob->ext, &src_oob->ext, sizeof(dst_oob->ext)); return;}wstdcall void WIN_FUNC(NdisSend,3) (NDIS_STATUS *status, struct ndis_mp_block *nmb, struct ndis_packet *packet){ struct wrap_ndis_device *wnd = nmb->wnd; struct miniport *mp; KIRQL irql; mp = &wnd->wd->driver->ndis_driver->mp; if (mp->send_packets) { irql = serialize_lock_irql(wnd); assert_irql(_irql_ == DISPATCH_LEVEL); LIN2WIN3(mp->send_packets, wnd->nmb->mp_ctx, &packet, 1); serialize_unlock_irql(wnd, irql); if (deserialized_driver(wnd)) *status = NDIS_STATUS_PENDING; else { struct ndis_packet_oob_data *oob_data; oob_data = NDIS_PACKET_OOB_DATA(packet); *status = oob_data->status; switch (*status) { case NDIS_STATUS_SUCCESS: free_tx_packet(wnd, packet, *status); break; case NDIS_STATUS_PENDING: break; case NDIS_STATUS_RESOURCES: wnd->tx_ok = 0; break; case NDIS_STATUS_FAILURE: default: free_tx_packet(wnd, packet, *status); break; } } } else { irql = serialize_lock_irql(wnd); assert_irql(_irql_ == DISPATCH_LEVEL); *status = LIN2WIN3(mp->send, wnd->nmb->mp_ctx, packet, 0); serialize_unlock_irql(wnd, irql); switch (*status) { case NDIS_STATUS_SUCCESS: free_tx_packet(wnd, packet, *status); break; case NDIS_STATUS_PENDING: break; case NDIS_STATUS_RESOURCES: wnd->tx_ok = 0; break; case NDIS_STATUS_FAILURE: default: free_tx_packet(wnd, packet, *status); break; } } EXIT3(return);}/* called for serialized drivers only */wstdcall void mp_timer_dpc(struct kdpc *kdpc, void *ctx, void *arg1, void *arg2){ struct ndis_mp_timer *timer; struct ndis_mp_block *nmb; timer = ctx; TIMERENTER("%p, %p, %p, %p", timer, timer->func, timer->ctx, timer->nmb); assert_irql(_irql_ == DISPATCH_LEVEL); nmb = timer->nmb; serialize_lock(nmb->wnd); LIN2WIN4(timer->func, NULL, timer->ctx, NULL, NULL); serialize_unlock(nmb->wnd); TIMEREXIT(return);}WIN_FUNC_DECL(mp_timer_dpc,4)wstdcall void WIN_FUNC(NdisMInitializeTimer,4) (struct ndis_mp_timer *timer, struct ndis_mp_block *nmb, DPC func, void *ctx){ TIMERENTER("%p, %p, %p, %p", timer, func, ctx, nmb); assert_irql(_irql_ == PASSIVE_LEVEL); timer->func = func; timer->ctx = ctx; timer->nmb = nmb; if (deserialized_driver(nmb->wnd)) KeInitializeDpc(&timer->kdpc, func, ctx); else KeInitializeDpc(&timer->kdpc, WIN_FUNC_PTR(mp_timer_dpc,4), timer); wrap_init_timer(&timer->nt_timer, NotificationTimer, nmb); TIMEREXIT(return);}wstdcall void WIN_FUNC(NdisMSetPeriodicTimer,2) (struct ndis_mp_timer *timer, UINT period_ms){ unsigned long expires = MSEC_TO_HZ(period_ms); TIMERENTER("%p, %u, %ld", timer, period_ms, expires); assert_irql(_irql_ <= DISPATCH_LEVEL); wrap_set_timer(&timer->nt_timer, expires, expires, &timer->kdpc); TIMEREXIT(return);}wstdcall void WIN_FUNC(NdisMCancelTimer,2) (struct ndis_mp_timer *timer, BOOLEAN *canceled){ TIMERENTER("%p", timer); assert_irql(_irql_ <= DISPATCH_LEVEL); *canceled = KeCancelTimer(&timer->nt_timer); TIMERTRACE("%d", *canceled); return;}wstdcall void WIN_FUNC(NdisInitializeTimer,3) (struct ndis_timer *timer, void *func, void *ctx){ TIMERENTER("%p, %p, %p", timer, func, ctx); assert_irql(_irql_ == PASSIVE_LEVEL); KeInitializeDpc(&timer->kdpc, func, ctx); wrap_init_timer(&timer->nt_timer, NotificationTimer, NULL); TIMEREXIT(return);}/* NdisMSetTimer is a macro that calls NdisSetTimer with * ndis_mp_timer typecast to ndis_timer */wstdcall void WIN_FUNC(NdisSetTimer,2) (struct ndis_timer *timer, UINT duetime_ms){ unsigned long expires = MSEC_TO_HZ(duetime_ms); TIMERENTER("%p, %p, %u, %ld", timer, timer->nt_timer.wrap_timer, duetime_ms, expires); assert_irql(_irql_ <= DISPATCH_LEVEL); wrap_set_timer(&timer->nt_timer, expires, 0, &timer->kdpc); TIMEREXIT(return);}wstdcall void WIN_FUNC(NdisCancelTimer,2) (struct ndis_timer *timer, BOOLEAN *canceled){ TIMERENTER("%p", timer); assert_irql(_irql_ <= DISPATCH_LEVEL); *canceled = KeCancelTimer(&timer->nt_timer); TIMEREXIT(return);}wstdcall void WIN_FUNC(NdisMRegisterAdapterShutdownHandler,3) (struct ndis_mp_block *nmb, void *ctx, void *func){ struct wrap_ndis_device *wnd = nmb->wnd; ENTER1("%p", func); wnd->wd->driver->ndis_driver->mp.shutdown = func; wnd->shutdown_ctx = ctx;}wstdcall void WIN_FUNC(NdisMDeregisterAdapterShutdownHandler,1) (struct ndis_mp_block *nmb){ struct wrap_ndis_device *wnd = nmb->wnd; wnd->wd->driver->ndis_driver->mp.shutdown = NULL; wnd->shutdown_ctx = NULL;}/* TODO: rt61 (serialized) driver doesn't want MiniportEnableInterrupt * to be called in irq handler, but mrv800c (deserialized) driver * wants. NDIS is confusing about when to call MiniportEnableInterrupt * For now, handle these cases with two separate irq handlers based on * observation of these two drivers. However, it is likely not * correct. */wstdcall void deserialized_irq_handler(struct kdpc *kdpc, void *ctx, void *arg1, void *arg2){ struct wrap_ndis_device *wnd = ctx; ndis_interrupt_handler irq_handler = arg1; struct miniport *mp = arg2; TRACE6("%p", irq_handler); assert_irql(_irql_ == DISPATCH_LEVEL); LIN2WIN1(irq_handler, wnd->nmb->mp_ctx); if (mp->enable_interrupt) LIN2WIN1(mp->enable_interrupt, wnd->nmb->mp_ctx); EXIT6(return);}WIN_FUNC_DECL(deserialized_irq_handler,4)wstdcall void serialized_irq_handler(struct kdpc *kdpc, void *ctx, void *arg1, void *arg2){ struct wrap_ndis_device *wnd = ctx; ndis_interrupt_handler irq_handler = arg1; TRACE6("%p", irq_handler); assert_irql(_irql_ == DISPATCH_LEVEL); serialize_lock(wnd); LIN2WIN1(irq_handler, arg2); serialize_unlock(wnd); EXIT6(return);}WIN_FUNC_DECL(serialized_irq_handler,4)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -