📄 ndis.c
字号:
case Ndis802_11StatusType_MediaStreamMode: break;#ifdef CONFIG_NET_RADIO case Ndis802_11StatusType_PMKID_CandidateList: { u8 *end; unsigned long i; struct ndis_pmkid_candidate_list *cand; cand = buf + sizeof(struct ndis_status_indication); if (len < sizeof(struct ndis_status_indication) + sizeof(struct ndis_pmkid_candidate_list) || cand->version != 1) { WARNING("Unrecognized PMKID_CANDIDATE_LIST" " ignored"); TRACEEXIT1(return); } end = (u8 *)buf + len; DBGTRACE2("PMKID_CANDIDATE_LIST ver %ld num_cand %ld", cand->version, cand->num_candidates); for (i = 0; i < cand->num_candidates; i++) {#if WIRELESS_EXT > 17 struct iw_pmkid_cand pcand; union iwreq_data wrqu;#endif struct ndis_pmkid_candidate *c = &cand->candidates[i]; if ((u8 *)(c + 1) > end) { DBGTRACE2("Truncated " "PMKID_CANDIDATE_LIST"); break; } DBGTRACE2("%ld: " MACSTRSEP " 0x%lx", i, MAC2STR(c->bssid), c->flags);#if WIRELESS_EXT > 17 memset(&pcand, 0, sizeof(pcand)); if (c->flags & 0x01) pcand.flags |= IW_PMKID_CAND_PREAUTH; pcand.index = i; memcpy(pcand.bssid.sa_data, c->bssid, ETH_ALEN); memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.length = sizeof(pcand); wireless_send_event(wnd->net_dev, IWEVPMKIDCAND, &wrqu, (u8 *)&pcand);#endif } break; } case Ndis802_11StatusType_RadioState: radio_status = buf; if (radio_status->radio_state == Ndis802_11RadioStatusOn) INFO("radio is turned on"); else if (radio_status->radio_state == Ndis802_11RadioStatusHardwareOff) INFO("radio is turned off by hardware"); else if (radio_status->radio_state == Ndis802_11RadioStatusSoftwareOff) INFO("radio is turned off by software"); break;#endif default: /* is this RSSI indication? */ DBGTRACE2("unknown indication: %x", si->status_type); break; } break; default: DBGTRACE2("unknown status: %08X", status); break; } TRACEEXIT2(return);}/* called via function pointer; but 64-bit RNDIS driver calls directly */wstdcall void WIN_FUNC(NdisMIndicateStatusComplete,1) (struct ndis_miniport_block *nmb){ struct wrap_ndis_device *wnd = nmb->wnd; TRACEENTER2("%p", wnd); schedule_wrap_work(&wnd->wrap_ndis_work); if (wnd->tx_ok) schedule_wrap_work(&wnd->tx_work);}wstdcall void return_packet(void *arg1, void *arg2){ struct wrap_ndis_device *wnd; struct ndis_packet *packet; struct miniport_char *miniport; KIRQL irql; wnd = arg1; packet = arg2; TRACEENTER4("%p, %p", wnd, packet); miniport = &wnd->wd->driver->ndis_driver->miniport; irql = serialize_lock_irql(wnd); LIN2WIN2(miniport->return_packet, wnd->nmb->adapter_ctx, packet); serialize_unlock_irql(wnd, irql); TRACEEXIT4(return);}WIN_FUNC_DECL(return_packet,2)/* called via function pointer */wstdcall void NdisMIndicateReceivePacket(struct ndis_miniport_block *nmb, struct ndis_packet **packets, UINT nr_packets){ struct wrap_ndis_device *wnd; ndis_buffer *buffer; struct ndis_packet *packet; struct sk_buff *skb; UINT i, length, total_length; struct ndis_packet_oob_data *oob_data; void *virt; TRACEENTER3("%p, %d", nmb, nr_packets); wnd = nmb->wnd; for (i = 0; i < nr_packets; i++) { packet = packets[i]; if (!packet) { WARNING("empty packet ignored"); continue; } wnd->net_dev->last_rx = jiffies; /* get total number of bytes in packet */ NdisGetFirstBufferFromPacketSafe(packet, &buffer, &virt, &length, &total_length, NormalPagePriority); DBGTRACE3("%d, %d", length, total_length); oob_data = NDIS_PACKET_OOB_DATA(packet); skb = dev_alloc_skb(total_length); if (skb) { while (buffer) { memcpy_skb(skb, MmGetSystemAddressForMdl(buffer), MmGetMdlByteCount(buffer)); buffer = buffer->next; } skb->dev = wnd->net_dev; skb->protocol = eth_type_trans(skb, wnd->net_dev); pre_atomic_add(wnd->stats.rx_bytes, total_length); atomic_inc_var(wnd->stats.rx_packets); netif_rx(skb); } else { WARNING("couldn't allocate skb; packet dropped"); atomic_inc_var(wnd->stats.rx_dropped); } /* serialized drivers check the status upon return * from this function */ if (!deserialized_driver(wnd)) { oob_data->status = NDIS_STATUS_SUCCESS; continue; } /* if a deserialized driver sets * NDIS_STATUS_RESOURCES, then it reclaims the packet * upon return from this function */ if (oob_data->status == NDIS_STATUS_RESOURCES) continue; assert(oob_data->status == NDIS_STATUS_SUCCESS); /* deserialized driver doesn't check the status upon * return from this function; we need to call * MiniportReturnPacket later for this packet. Calling * MiniportReturnPacket from here is not correct - the * driver doesn't expect it (at least Centrino driver * crashes) */ schedule_ntos_work_item(WIN_FUNC_PTR(return_packet,2), wnd, packet); } TRACEEXIT3(return);}/* called via function pointer */wstdcall void NdisMSendComplete(struct ndis_miniport_block *nmb, struct ndis_packet *packet, NDIS_STATUS status){ struct wrap_ndis_device *wnd = nmb->wnd; TRACEENTER4("%p, %08X", packet, status); if (deserialized_driver(wnd)) free_tx_packet(wnd, packet, status); else { struct ndis_packet_oob_data *oob_data; NDIS_STATUS pkt_status; TRACEENTER3("%p, %08x", packet, status); oob_data = NDIS_PACKET_OOB_DATA(packet); switch ((pkt_status = xchg(&oob_data->status, status))) { case NDIS_STATUS_NOT_RECOGNIZED: free_tx_packet(wnd, packet, status); break; case NDIS_STATUS_PENDING: case 0: break; default: WARNING("%p: invalid status: %08X", packet, pkt_status); break; } /* In case a serialized driver has earlier requested a * pause by returning NDIS_STATUS_RESOURCES during * MiniportSend(Packets), wakeup tx worker now. */ if (wnd->tx_ok == 0) { atomic_inc_var(wnd->tx_ok); DBGTRACE3("%d, %d", wnd->tx_ring_start, wnd->tx_ring_end); schedule_wrap_work(&wnd->tx_work); } } TRACEEXIT3(return);}/* called via function pointer */wstdcall void NdisMSendResourcesAvailable(struct ndis_miniport_block *nmb){ struct wrap_ndis_device *wnd = nmb->wnd; TRACEENTER3(""); DBGTRACE3("%d, %d", wnd->tx_ring_start, wnd->tx_ring_end); atomic_inc_var(wnd->tx_ok); schedule_wrap_work(&wnd->tx_work); TRACEEXIT3(return);}/* called via function pointer (by NdisMEthIndicateReceive macro); the * first argument is nmb->eth_db */wstdcall void EthRxIndicateHandler(struct ndis_miniport_block *nmb, void *rx_ctx, char *header1, char *header, UINT header_size, void *look_ahead, UINT look_ahead_size, UINT packet_size){ struct sk_buff *skb = NULL; struct wrap_ndis_device *wnd; unsigned int skb_size = 0; KIRQL irql; struct ndis_packet_oob_data *oob_data; TRACEENTER3("nmb = %p, rx_ctx = %p, buf = %p, size = %d, buf = %p, " "size = %d, packet = %d", nmb, rx_ctx, header, header_size, look_ahead, look_ahead_size, packet_size); wnd = nmb->wnd; DBGTRACE3("wnd = %p", wnd); if (!wnd) { ERROR("nmb is NULL"); TRACEEXIT3(return); } wnd->net_dev->last_rx = jiffies; if (look_ahead_size < packet_size) { struct ndis_packet *packet; struct miniport_char *miniport; unsigned int bytes_txed; NDIS_STATUS res; NdisAllocatePacket(&res, &packet, wnd->tx_packet_pool); if (res != NDIS_STATUS_SUCCESS) { atomic_inc_var(wnd->stats.rx_dropped); TRACEEXIT3(return); } oob_data = NDIS_PACKET_OOB_DATA(packet); miniport = &wnd->wd->driver->ndis_driver->miniport; irql = serialize_lock_irql(wnd); res = LIN2WIN6(miniport->tx_data, packet, &bytes_txed, nmb, rx_ctx, look_ahead_size, packet_size); serialize_unlock_irql(wnd, irql); DBGTRACE3("%d, %d, %d", header_size, look_ahead_size, bytes_txed); if (res == NDIS_STATUS_SUCCESS) { ndis_buffer *buffer; skb = dev_alloc_skb(header_size + look_ahead_size + bytes_txed); if (skb) { memcpy_skb(skb, header, header_size); memcpy_skb(skb, look_ahead, look_ahead_size); buffer = packet->private.buffer_head; while (buffer) { memcpy_skb(skb, MmGetSystemAddressForMdl(buffer), MmGetMdlByteCount(buffer)); buffer = buffer->next; } skb_size = header_size+look_ahead_size + bytes_txed; NdisFreePacket(packet); } } else if (res == NDIS_STATUS_PENDING) { /* driver will call td_complete */ oob_data->look_ahead = kmalloc(look_ahead_size, GFP_ATOMIC); if (!oob_data->look_ahead) { NdisFreePacket(packet); ERROR("packet dropped"); atomic_inc_var(wnd->stats.rx_dropped); TRACEEXIT3(return); } memcpy(oob_data->header, header, sizeof(oob_data->header)); memcpy(oob_data->look_ahead, look_ahead, look_ahead_size); oob_data->look_ahead_size = look_ahead_size; TRACEEXIT3(return); } else { WARNING("packet dropped: %08X", res); NdisFreePacket(packet); atomic_inc_var(wnd->stats.rx_dropped); TRACEEXIT3(return); } } else { skb_size = header_size + packet_size; skb = dev_alloc_skb(skb_size); if (skb) { memcpy_skb(skb, header, header_size); memcpy_skb(skb, look_ahead, packet_size); } } if (skb) { skb->dev = wnd->net_dev; skb->protocol = eth_type_trans(skb, wnd->net_dev); pre_atomic_add(wnd->stats.rx_bytes, skb_size); atomic_inc_var(wnd->stats.rx_packets); netif_rx(skb); } else { ERROR("couldn't allocate skb; packet dropped"); atomic_inc_var(wnd->stats.rx_dropped); } TRACEEXIT3(return);}/* called via function pointer */wstdcall void NdisMTransferDataComplete(struct ndis_miniport_block *nmb, struct ndis_packet *packet, NDIS_STATUS status, UINT bytes_txed){ struct wrap_ndis_device *wnd = nmb->wnd; struct sk_buff *skb; unsigned int skb_size; struct ndis_packet_oob_data *oob_data; ndis_buffer *buffer; TRACEENTER3("wnd = %p, packet = %p, bytes_txed = %d", wnd, packet, bytes_txed); if (!packet) { WARNING("illegal packet"); TRACEEXIT3(return); } wnd->net_dev->last_rx = jiffies; oob_data = NDIS_PACKET_OOB_DATA(packet); skb_size = sizeof(oob_data->header) + oob_data->look_ahead_size + bytes_txed; skb = dev_alloc_skb(skb_size); if (!skb) { kfree(oob_data->look_ahead); NdisFreePacket(packet); ERROR("couldn't allocate skb; packet dropped"); atomic_inc_var(wnd->stats.rx_dropped); TRACEEXIT3(return); } memcpy_skb(skb, oob_data->header, sizeof(oob_data->header)); memcpy_skb(skb, oob_data->look_ahead, oob_data->look_ahead_size); buffer = packet->private.buffer_head; while (buffer) { memcpy_skb(skb, MmGetSystemAddressForMdl(buffer), MmGetMdlByteCount(buffer)); buffer = buffer->next; } kfree(oob_data->look_ahead); NdisFreePacket(packet); skb->dev = wnd->net_dev; skb->protocol = eth_type_trans(skb, wnd->net_dev); pre_atomic_add(wnd->stats.rx_bytes, skb_size); atomic_inc_var(wnd->stats.rx_packets); netif_rx(skb);}/* called via function pointer */wstdcall void EthRxComplete(struct ndis_miniport_block *nmb){ DBGTRACE3("");}wstdcall void NdisMQueryInformationComplete(struct ndis_miniport_block *nmb, NDIS_STATUS status){ struct wrap_ndis_device *wnd = nmb->wnd; TRACEENTER2("nmb: %p, wnd: %p, %08X", nmb, wnd, status); wnd->ndis_comm_status = status; wnd->ndis_comm_done = 1; wake_up(&wnd->ndis_comm_wq); TRACEEXIT2(return);}wstdcall void NdisMSetInformationComplete(struct ndis_miniport_block *nmb, NDIS_STATUS status){ struct wrap_ndis_device *wnd = nmb->wnd; TRACEENTER2("status = %08X", status); wnd->ndis_comm_status = status; wnd->ndis_comm_done = 1; wake_up(&wnd->ndis_comm_wq); TRACEEXIT3(return);}wstdcall void WIN_FUNC(NdisMSleep,1) (ULONG us){ unsigned long delay; TRACEENTER4("%p: us: %u", current, us); delay = USEC_TO_HZ(us); sleep_hz(delay); DBGTRACE4("%p: done", current); TRACEEXIT4(return);}wstdcall void WIN_FUNC(NdisGetCurrentSystemTime,1) (LARGE_INTEGER *time){ *time = ticks_1601();}wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterIoPortRange,4) (void **virt, struct ndis_miniport_block *nmb, UINT start, UINT len){ TRACEENTER3("%08x %08x", start, len); *virt = (void *)(ULONG_PTR)start; return NDIS_STATUS_SUCCESS;}wstdcall void WIN_FUNC(NdisMDeregisterIoPortRange,4) (struct ndis_miniport_block *nmb, UINT start, UINT len, void* virt){ TRACEENTER1("%08x %08x", start, len);}wstdcall LONG WIN_FUNC(NdisInterlockedDecrement,1) (LONG *val){ return InterlockedDecrement(val);}wstdcall LONG WIN_FUNC(NdisInterlockedIncrement,1) (LONG *val){ return InterlockedIncrement(val);}wstdcall struct nt_list *WIN_FUNC(NdisInterlockedInsertHeadList,3) (struct nt_list *head, struct nt_list *entry, struct ndis_spinlock *lock){ return ExInterlockedInsertHeadList(head, entry, &lock->klock);}wstdcall struct nt_list *WIN_FUNC(NdisInterlockedInsertTailList,3) (struct nt_list *head, struct nt_list *entry, struct ndis_spinlock *lock){ return ExInterlockedInsertTailList(head, entry, &lock->klock);}wstdcall struct n
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -