📄 ndis.c
字号:
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(*packet) - 1 + pool->proto_rsvd_length + sizeof(struct ndis_packet_oob_data); irql = nt_spin_lock_irql(&pool->lock, DISPATCH_LEVEL); if (pool->free_descr) { packet = pool->free_descr; pool->free_descr = (void *)(ULONG_PTR)packet->reserved[0]; nt_spin_unlock_irql(&pool->lock, irql); } else { nt_spin_unlock_irql(&pool->lock, irql); packet = kmalloc(packet_length, gfp_irql()); if (!packet) { WARNING("couldn't allocate packet"); *status = NDIS_STATUS_RESOURCES; return; } atomic_inc_var(pool->num_allocated_descr); } TRACE3("packet: %p", packet); 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; TRACE4("packet: %p, pool: %p", packet, pool); 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; KIRQL irql; ENTER3("packet: %p, pool: %p", packet, packet->private.pool); pool = packet->private.pool; if (!pool) { ERROR("pool for descriptor %p is invalid", packet); EXIT4(return); } atomic_dec_var(pool->num_used_descr); irql = nt_spin_lock_irql(&pool->lock, DISPATCH_LEVEL); if (pool->num_allocated_descr > MAX_ALLOCATED_NDIS_PACKETS) { nt_spin_unlock_irql(&pool->lock, irql); atomic_dec_var(pool->num_allocated_descr); kfree(packet); } else { packet->reserved[0] = (ULONG_PTR)pool->free_descr; pool->free_descr = packet; nt_spin_unlock_irql(&pool->lock, irql); } EXIT4(return);}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_miniport_block *nmb, struct ndis_packet *packet){ struct wrap_ndis_device *wnd = nmb->wnd; struct miniport_char *miniport; KIRQL irql; miniport = &wnd->wd->driver->ndis_driver->miniport; if (miniport->send_packets) { irql = serialize_lock_irql(wnd); LIN2WIN3(miniport->send_packets, wnd->nmb->adapter_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); *status = LIN2WIN3(miniport->send, wnd->nmb->adapter_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);}wstdcall void wrap_miniport_timer(struct kdpc *kdpc, void *ctx, void *arg1, void *arg2){ struct ndis_miniport_timer *timer; struct ndis_miniport_block *nmb; timer = ctx; TIMERENTER("timer: %p, func: %p, ctx: %p, nmb: %p", timer, timer->func, timer->ctx, timer->nmb); nmb = timer->nmb; /* already called at DISPATCH_LEVEL */ if (!deserialized_driver(nmb->wnd)) serialize_lock(nmb->wnd); LIN2WIN4(timer->func, &timer->kdpc, timer->ctx, NULL, NULL); if (!deserialized_driver(nmb->wnd)) serialize_unlock(nmb->wnd); TIMEREXIT(return);}WIN_FUNC_DECL(wrap_miniport_timer,4)wstdcall void WIN_FUNC(NdisMInitializeTimer,4) (struct ndis_miniport_timer *timer, struct ndis_miniport_block *nmb, DPC func, void *ctx){ TIMERENTER("timer: %p, func: %p, ctx: %p, nmb: %p", timer, func, ctx, nmb); timer->func = func; timer->ctx = ctx; timer->nmb = nmb;// KeInitializeDpc(&timer->kdpc, func, ctx); KeInitializeDpc(&timer->kdpc, WIN_FUNC_PTR(wrap_miniport_timer,4), timer); wrap_init_timer(&timer->nt_timer, NotificationTimer, &timer->kdpc, nmb); TIMEREXIT(return);}wstdcall void WIN_FUNC(NdisMSetPeriodicTimer,2) (struct ndis_miniport_timer *timer, UINT period_ms){ unsigned long expires = MSEC_TO_HZ(period_ms) + 1; TIMERENTER("%p, %u, %ld", timer, period_ms, expires); wrap_set_timer(&timer->nt_timer, expires, expires, NULL); TIMEREXIT(return);}wstdcall void WIN_FUNC(NdisMCancelTimer,2) (struct ndis_miniport_timer *timer, BOOLEAN *canceled){ TIMERENTER("%p", timer); *canceled = KeCancelTimer(&timer->nt_timer); TIMEREXIT(return);}wstdcall void WIN_FUNC(NdisInitializeTimer,3) (struct ndis_timer *timer, void *func, void *ctx){ TIMERENTER("%p, %p, %p", timer, func, ctx); KeInitializeDpc(&timer->kdpc, func, ctx); wrap_init_timer(&timer->nt_timer, NotificationTimer, &timer->kdpc, NULL); TIMEREXIT(return);}/* NdisMSetTimer is a macro that calls NdisSetTimer with * ndis_miniport_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) + 1; TIMERENTER("%p, %p, %u, %ld", timer, timer->nt_timer.wrap_timer, duetime_ms, expires); wrap_set_timer(&timer->nt_timer, expires, 0, NULL); TIMEREXIT(return);}wstdcall void WIN_FUNC(NdisCancelTimer,2) (struct ndis_timer *timer, BOOLEAN *canceled){ TIMERENTER("%p", timer); *canceled = KeCancelTimer(&timer->nt_timer); TIMEREXIT(return);}wstdcall void WIN_FUNC(NdisReadNetworkAddress,4) (NDIS_STATUS *status, void **addr, UINT *len, struct ndis_miniport_block *nmb){ struct wrap_ndis_device *wnd = nmb->wnd; struct ndis_configuration_parameter *param; struct unicode_string key; struct ansi_string ansi; int ret; ENTER1(""); RtlInitAnsiString(&ansi, "mac_address"); *len = 0; *status = NDIS_STATUS_FAILURE; if (RtlAnsiStringToUnicodeString(&key, &ansi, TRUE) != STATUS_SUCCESS) EXIT1(return); NdisReadConfiguration(status, ¶m, nmb, &key, NdisParameterString); RtlFreeUnicodeString(&key); if (*status == NDIS_STATUS_SUCCESS) { int int_mac[ETH_ALEN]; ret = RtlUnicodeStringToAnsiString(&ansi, ¶m->data.string, TRUE); if (ret != NDIS_STATUS_SUCCESS) EXIT1(return); ret = sscanf(ansi.buf, MACSTRSEP, MACINTADR(int_mac)); if (ret != ETH_ALEN) ret = sscanf(ansi.buf, MACSTR, MACINTADR(int_mac)); RtlFreeAnsiString(&ansi); if (ret == ETH_ALEN) { int i; for (i = 0; i < ETH_ALEN; i++) wnd->mac[i] = int_mac[i]; printk(KERN_INFO "%s: %s ethernet device " MACSTRSEP "\n", wnd->net_dev->name, DRIVER_NAME, MAC2STR(wnd->mac)); *len = ETH_ALEN; *addr = wnd->mac; *status = NDIS_STATUS_SUCCESS; } } EXIT1(return);}wstdcall void WIN_FUNC(NdisMRegisterAdapterShutdownHandler,3) (struct ndis_miniport_block *nmb, void *ctx, void *func){ struct wrap_ndis_device *wnd = nmb->wnd; ENTER1("%p", func); wnd->wd->driver->ndis_driver->miniport.shutdown = func; wnd->shutdown_ctx = ctx;}wstdcall void WIN_FUNC(NdisMDeregisterAdapterShutdownHandler,1) (struct ndis_miniport_block *nmb){ struct wrap_ndis_device *wnd = nmb->wnd; wnd->wd->driver->ndis_driver->miniport.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. */static void deserialized_irq_handler(unsigned long data){ struct ndis_mp_interrupt *mp_interrupt = (typeof(mp_interrupt))data; struct wrap_ndis_device *wnd = mp_interrupt->nmb->wnd; LIN2WIN1(mp_interrupt->mp_dpc, wnd->nmb->adapter_ctx); if (mp_interrupt->enable) { struct miniport_char *miniport; miniport = &wnd->wd->driver->ndis_driver->miniport; LIN2WIN1(miniport->enable_interrupt, wnd->nmb->adapter_ctx); }}static void serialized_irq_handler(unsigned long data){ struct ndis_mp_interrupt *mp_interrupt = (typeof(mp_interrupt))data; struct wrap_ndis_device *wnd = mp_interrupt->nmb->wnd; serialize_lock(wnd); LIN2WIN1(mp_interrupt->mp_dpc, wnd->nmb->adapter_ctx); serialize_unlock(wnd);}irqreturn_t ndis_isr(int irq, void *data ISR_PT_REGS_PARAM_DECL){ struct ndis_mp_interrupt *mp_interrupt = data; struct wrap_ndis_device *wnd = mp_interrupt->nmb->wnd; BOOLEAN recognized, queue_handler; /* this spinlock should be shared with NdisMSynchronizeWithInterrupt */ nt_spin_lock(&mp_interrupt->lock); if (mp_interrupt->shared) LIN2WIN3(mp_interrupt->isr, &recognized, &queue_handler, wnd->nmb->adapter_ctx); else { struct miniport_char *miniport; miniport = &wnd->wd->driver->ndis_driver->miniport; LIN2WIN1(miniport->disable_interrupt, wnd->nmb->adapter_ctx); /* it is not shared interrupt, so handler must be called */ recognized = queue_handler = TRUE; } nt_spin_unlock(&mp_interrupt->lock); if (recognized) { if (queue_handler) tasklet_schedule(&wnd->irq_tasklet); EXIT6(return IRQ_HANDLED); } EXIT6(return IRQ_NONE);}wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterInterrupt,7) (struct ndis_mp_interrupt *mp_interrupt, struct ndis_miniport_block *nmb, UINT vector, UINT level, BOOLEAN req_isr, BOOLEAN shared, enum kinterrupt_mode mode){ struct wrap_ndis_device *wnd = nmb->wnd; struct miniport_char *miniport; ENTER1("%p, vector:%d, level:%d, req_isr:%d, shared:%d, mode:%d", mp_interrupt, vector, level, req_isr, shared, mode); mp_interrupt->irq = vector; mp_interrupt->nmb = nmb; mp_interrupt->req_isr = req_isr; if (shared && !req_isr) WARNING("shared but dynamic interrupt!"); mp_interrupt->shared = shared; nt_spin_lock_init(&mp_interrupt->lock); wnd->mp_interrupt = mp_interrupt; miniport = &wnd->wd->driver->ndis_driver->miniport; mp_interrupt->isr = miniport->isr; mp_interrupt->mp_dpc = miniport->handle_interrupt; if (miniport->enable_interrupt) mp_interrupt->enable = TRUE; else mp_interrupt->enable = FALSE; tasklet_init(&wnd->irq_tasklet, deserialized_driver(wnd) ? deserialized_irq_handler : serialized_irq_handler, (unsigned long)mp_interrupt); if (request_irq(vector, ndis_isr, req_isr ? IRQF_SHARED : 0, wnd->net_dev->name, mp_interrupt)) { printk(KERN_WARNING "%s: request for IRQ %d failed\n", DRIVER_NAME, vector); EXIT1(return NDIS_STATUS_RESOURCES); } printk(KERN_INFO "%s: using IRQ %d\n", DRIVER_NAME, vector); EXIT1(return NDIS_STATUS_SUCCESS);}wstdcall void WIN_FUNC(NdisMDeregisterInterrupt,1) (struct ndis_mp_interrupt *mp_interrupt){ struct ndis_miniport_block *nmb; ENTER1("%p", mp_interrupt); nmb = mp_interrupt->nmb; free_irq(mp_interrupt->irq, mp_interrupt); tasklet_kill(&nmb->wnd->irq_tasklet); mp_interrupt->nmb = NULL; nmb->wnd->mp_interrupt = NULL; EXIT1(return);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -