WinCE5.0 SMDK2410 BSP在GEC2410开发板上的移植(16)-CS8900 NDIS Miniport driver简析(2)

4.NDIS51_MINIPORT_CHARACTERISTICS结构的其他handler
在DriverEntry里注册了其他一些handler,如CS8900Halt,CS8900HandleInterrupt等,下面来一一介绍:
(1)HaltHandler: CS8900Halt
MiniportHalt函数的入口:当网卡去除或者停止时该函数进行资源的释放.必须实现.
MiniportHalt is a required function that de-allocates resources when the network adapter is removed and halts the network adapter.):
因为我们的网卡一直存在,因此该函数没有做任何处理.
extern VOID CS8900Halt( IN NDIS_HANDLE MiniportAdapterContext ) /*++ Routine Description: CS8900Halt removes an adapter that was previously initialized. Arguments: MiniportAdapterContext - The context value that the Miniport returned from CS8900Initialize; actually as pointer to an CS8900_ADAPTER. Return Value: None. --*/ { PCS8900_ADAPTER Adapter; Adapter = PCS8900_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext); DEBUGMSG(1, (TEXT("+CS8900:CS8900Halt/r/n"))); return;
(2)HandleInterruptHandler:CS8900HandleInterrupt(在interrupt.c中实现)
中断服务线程IST,读取CS8900中断状态寄存器获取中断类型,当是接收中断时调用CS8900ReceiveEvent进一步处理.
VOID CS8900HandleInterrupt( IN NDIS_HANDLE MiniportAdapterContext ) /*++ Routine Description: This is the defered processing routine for interrupts. It reads from the Interrupt Status Register any outstanding interrupts and handles them. Arguments: MiniportAdapterContext - a handle to the adapter block. Return Value: NONE. --*/ { // // The adapter to process // PCS8900_ADAPTER Adapter = ((PCS8900_ADAPTER)MiniportAdapterContext); unsigned short Event; Event = CS8900ReadRegister(PKTPG_ISQ); DEBUGMSG(1, (TEXT("++CS8900HandleInterrupt event=%x/r/n"), Event)); while (Event != 0) { switch (Event & REG_NUM_MASK) { case REG_NUM_RX_EVENT: DEBUGMSG(1, (TEXT("RX/r/n"))); CS8900ReceiveEvent(Adapter, Event); break; case REG_NUM_TX_EVENT: DEBUGMSG(1, (TEXT("TX/r/n"))); break; case REG_NUM_BUF_EVENT: DEBUGMSG(1, (TEXT("BUF/r/n"))); break; case REG_NUM_RX_MISS: DEBUGMSG(1, (TEXT("CS8900HandleInterrupt:RX_MISS!/r/n"))); break; case REG_NUM_TX_COL: break; } Event = CS8900ReadRegister(PKTPG_ISQ); DEBUGMSG(1, (TEXT("event=%x/r/n"), Event)); } DEBUGMSG(1, (TEXT("--CS8900HandleInterrupt/r/n"))); }
(3)ISRHandler:CS8900Isr
中断服务例程ISR,这里只是一个空函数,具体处理由HandleInterruptHandler完成.
当中断发生时首先调用CS8900Isr,然后调用CS8900HandleInterrupt

(4)QueryInformationHandler:CS8900QueryInformation
MiniportQueryInformation函数的入口,必须实现,返回网卡及其驱动的状态及性能信息(如输入输出缓冲区大小,帧大小,传输速度等).
This function is a required function that returns information about the capabilities and status of the driver and/or its network adapter
支持的查询信息OID列表定义为:
// // List of supported OID for this driver. // STATIC UINT CS8900SupportedOids[] = { OID_GEN_SUPPORTED_LIST, OID_GEN_HARDWARE_STATUS, OID_GEN_MEDIA_SUPPORTED, OID_GEN_MEDIA_IN_USE, OID_GEN_MAXIMUM_LOOKAHEAD, OID_GEN_MAXIMUM_FRAME_SIZE, OID_GEN_MAXIMUM_TOTAL_SIZE, OID_GEN_MAC_OPTIONS, OID_GEN_PROTOCOL_OPTIONS, OID_GEN_LINK_SPEED, OID_GEN_TRANSMIT_BUFFER_SPACE, OID_GEN_RECEIVE_BUFFER_SPACE, OID_GEN_TRANSMIT_BLOCK_SIZE, OID_GEN_RECEIVE_BLOCK_SIZE, OID_GEN_VENDOR_DESCRIPTION, OID_GEN_VENDOR_ID, OID_GEN_DRIVER_VERSION, OID_GEN_CURRENT_PACKET_FILTER, OID_GEN_CURRENT_LOOKAHEAD, OID_GEN_XMIT_OK, OID_GEN_RCV_OK, OID_GEN_XMIT_ERROR, OID_GEN_RCV_ERROR, OID_GEN_RCV_NO_BUFFER, OID_802_3_PERMANENT_ADDRESS, OID_802_3_CURRENT_ADDRESS, OID_802_3_MULTICAST_LIST, OID_802_3_MAXIMUM_LIST_SIZE, OID_802_3_RCV_ERROR_ALIGNMENT, OID_802_3_XMIT_ONE_COLLISION, OID_802_3_XMIT_MORE_COLLISIONS, OID_GEN_MEDIA_CONNECT_STATUS, OID_GEN_MAXIMUM_SEND_PACKETS, OID_GEN_VENDOR_DRIVER_VERSION, };
CS8900QueryInformation代码如下:
NDIS_STATUS CS8900QueryInformation( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN ULONG InformationBufferLength, OUT PULONG BytesWritten, OUT PULONG BytesNeeded ) /*++ Routine Description: The CS8900QueryInformation process a Query request for NDIS_OIDs that are specific about the Driver. Arguments: MiniportAdapterContext - a pointer to the adapter. Oid - the NDIS_OID to process. InformationBuffer - a pointer into the NdisRequest->InformationBuffer into which store the result of the query. InformationBufferLength - a pointer to the number of bytes left in the InformationBuffer. BytesWritten - a pointer to the number of bytes written into the InformationBuffer. BytesNeeded - If there is not enough room in the information buffer then this will contain the number of bytes needed to complete the request. Return Value: The function value is the status of the operation. --*/ { // // Pointer to the adapter structure. // PCS8900_ADAPTER Adapter = (PCS8900_ADAPTER)MiniportAdapterContext; // // General Algorithm: // // Switch(Request) // Get requested information // Store results in a common variable. // default: // Try protocol query information // If that fails, fail query. // // Copy result in common variable to result buffer. // Finish processing UINT BytesLeft = InformationBufferLength; PUCHAR InfoBuffer = (PUCHAR)(InformationBuffer); NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS; NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady; NDIS_MEDIUM Medium = NdisMedium802_3; // // This variable holds result of query // ULONG GenericULong; USHORT GenericUShort; UCHAR GenericArray[6]; UINT MoveBytes = sizeof(ULONG); PVOID MoveSource = (PVOID)(&GenericULong); DEBUGMSG(1, (TEXT("+CS8900:CS8900QueryInformation/r/n"))); // // Make sure that int is 4 bytes. Else GenericULong must change // to something of size 4. // ASSERT(sizeof(ULONG) == 4); // // Switch on request type // switch (Oid) { case OID_GEN_MAC_OPTIONS: GenericULong = (ULONG)(NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | NDIS_MAC_OPTION_RECEIVE_SERIALIZED | NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | NDIS_MAC_OPTION_NO_LOOPBACK ); DEBUGMSG(1, (TEXT("----> OID_GEN_MAC_OPTIONS/r/n"))); break; case OID_GEN_SUPPORTED_LIST: MoveSource = (PVOID)(CS8900SupportedOids); MoveBytes = sizeof(CS8900SupportedOids); DEBUGMSG(1, (TEXT("----> OID_GEN_SUPPORTED_LIST/r/n"))); break; case OID_GEN_HARDWARE_STATUS: HardwareStatus = NdisHardwareStatusReady; MoveSource = (PVOID)(&HardwareStatus); MoveBytes = sizeof(NDIS_HARDWARE_STATUS); DEBUGMSG(1, (TEXT("----> OID_GEN_HARDWARE_STATUS/r/n"))); break; case OID_GEN_MEDIA_SUPPORTED: case OID_GEN_MEDIA_IN_USE: MoveSource = (PVOID) (&Medium); MoveBytes = sizeof(NDIS_MEDIUM); DEBUGMSG(1, (TEXT("----> OID_GEN_MEDIA/r/n"))); break; case OID_GEN_MAXIMUM_LOOKAHEAD: GenericULong = CS8900_MAX_LOOKAHEAD; DEBUGMSG(1, (TEXT("----> OID_GEN_MAXIMUM_LOOKAHEAD/r/n"))); break; case OID_GEN_MAXIMUM_FRAME_SIZE: GenericULong = (ULONG)(1518 - CS8900_HEADER_SIZE); DEBUGMSG(1, (TEXT("----> OID_GEN_MAXIMUM_FRAME_SIZE/r/n"))); break; case OID_GEN_MAXIMUM_TOTAL_SIZE: GenericULong = (ULONG)(1518); DEBUGMSG(1, (TEXT("----> OID_GEN_TOTAL_SIZE/r/n"))); break; case OID_GEN_LINK_SPEED: GenericULong = (ULONG)(100000); DEBUGMSG(1, (TEXT("----> OID_GEN_LINK_SPEED/r/n"))); break; case OID_GEN_TRANSMIT_BUFFER_SPACE: GenericULong = (ULONG)(1518); DEBUGMSG(1, (TEXT("----> OID_GEN_TRANSMIT_BUFFER_SPACE/r/n"))); // while(1); break; case OID_GEN_RECEIVE_BUFFER_SPACE: GenericULong = (ULONG)(1518); DEBUGMSG(1, (TEXT("----> OID_GEN_RECEIVE_BUFFER_SPACE/r/n"))); // while(1); break; case OID_GEN_TRANSMIT_BLOCK_SIZE: GenericULong = (ULONG)(1518); DEBUGMSG(1, (TEXT("----> OID_GEN_TRANSMIT_BLOCK_SIZE/r/n"))); // while(1); break; case OID_GEN_RECEIVE_BLOCK_SIZE: GenericULong = (ULONG)(1518); DEBUGMSG(1, (TEXT("----> OID_GEN_RECEIVE_BLOCK_SIZE/r/n"))); // while(1); break; #ifdef CS8900 case OID_GEN_VENDOR_ID: NdisMoveMemory( (PVOID)&GenericULong, Adapter->PermanentAddress, 3 ); GenericULong &= 0xFFFFFF00; MoveSource = (PVOID)(&GenericULong); MoveBytes = sizeof(GenericULong); DEBUGMSG(1, (TEXT("----> OID_GEN_VENDER_ID/r/n"))); break; case OID_GEN_VENDOR_DESCRIPTION: MoveSource = (PVOID)"CS8900A Adapter"; MoveBytes = 21; DEBUGMSG(1, (TEXT("----> OID_GEN_VENDOR_DESCRIPTION/r/n"))); break; #else case OID_GEN_VENDOR_ID: NdisMoveMemory( (PVOID)&GenericULong, Adapter->PermanentAddress, 3 ); GenericULong &= 0xFFFFFF00; GenericULong |= 0x01; MoveSource = (PVOID)(&GenericULong); MoveBytes = sizeof(GenericULong); break; case OID_GEN_VENDOR_DESCRIPTION: MoveSource = (PVOID)"Novell 1000 Adapter."; MoveBytes = 21; break; #endif case OID_GEN_DRIVER_VERSION: GenericUShort = ((USHORT)CS8900_NDIS_MAJOR_VERSION << 8) | CS8900_NDIS_MINOR_VERSION; MoveSource = (PVOID)(&GenericUShort); MoveBytes = sizeof(GenericUShort); break; case OID_GEN_CURRENT_LOOKAHEAD: GenericULong = (ULONG)(Adapter->MaxLookAhead); DEBUGMSG(1, (TEXT("----> OID_GEN_CURRENT_LOOKAHEAD/r/n"))); break; case OID_802_3_PERMANENT_ADDRESS: CS8900_MOVE_MEM((PCHAR)GenericArray, Adapter->PermanentAddress, CS8900_LENGTH_OF_ADDRESS); MoveSource = (PVOID)(GenericArray); MoveBytes = sizeof(Adapter->PermanentAddress); DEBUGMSG(1, (TEXT("----> OID_802_3_PERMANENT_ADDRESS/r/n"))); break; case OID_802_3_CURRENT_ADDRESS: CS8900_MOVE_MEM((PCHAR)GenericArray, Adapter->StationAddress, CS8900_LENGTH_OF_ADDRESS); MoveSource = (PVOID)(GenericArray); MoveBytes = sizeof(Adapter->StationAddress); DEBUGMSG(1, (TEXT("----> OID_802_3_CURRENT_ADDRESS/r/n"))); break; case OID_802_3_MAXIMUM_LIST_SIZE: GenericULong = (ULONG) (Adapter->MulticastListMax); DEBUGMSG(1, (TEXT("----> OID_802_3_MAXIMUM_LIST_SIZE/r/n"))); break; case OID_GEN_XMIT_OK: GenericULong = (UINT)(Adapter->FramesXmitGood); DEBUGMSG(1, (TEXT("----> OID_GEN_XMIT_OK/r/n"))); break; case OID_GEN_RCV_OK: GenericULong = (UINT)(Adapter->FramesRcvGood); DEBUGMSG(1, (TEXT("----> OID_GEN_RCV_OK/r/n"))); break; case OID_GEN_XMIT_ERROR: GenericULong = (UINT)(Adapter->FramesXmitBad); DEBUGMSG(1, (TEXT("----> OID_GEN_XMIT_ERROR/r/n"))); break; case OID_GEN_RCV_ERROR: GenericULong = (UINT)(Adapter->CrcErrors); DEBUGMSG(1, (TEXT("----> OID_GEN_RCV_ERROR/r/n"))); break; case OID_GEN_RCV_NO_BUFFER: GenericULong = (UINT)(Adapter->MissedPackets); DEBUGMSG(1, (TEXT("----> OID_GEN_RCV_NO_BUFFER/r/n"))); break; case OID_802_3_RCV_ERROR_ALIGNMENT: GenericULong = (UINT)(Adapter->FrameAlignmentErrors); DEBUGMSG(1, (TEXT("----> OID_802_3_RCV_ERROR_ALIGNMENT/r/n"))); break; case OID_802_3_XMIT_ONE_COLLISION: GenericULong = (UINT)(Adapter->FramesXmitOneCollision); DEBUGMSG(1, (TEXT("----> OID_802_3_XMIT_ONE_COLLISION/r/n"))); break; case OID_802_3_XMIT_MORE_COLLISIONS: GenericULong = (UINT)(Adapter->FramesXmitManyCollisions); break; case OID_GEN_MEDIA_CONNECT_STATUS: GenericULong = NdisMediaStateConnected; break; case OID_GEN_MAXIMUM_SEND_PACKETS: GenericULong = 1; break; case OID_GEN_VENDOR_DRIVER_VERSION: GenericULong = (DRIVER_MAJOR_VERSION << 16) | DRIVER_MINOR_VERSION; break; default: StatusToReturn = NDIS_STATUS_INVALID_OID; break; } if (StatusToReturn == NDIS_STATUS_SUCCESS) { if (MoveBytes > BytesLeft) { // // Not enough room in InformationBuffer. Punt // *BytesNeeded = MoveBytes; StatusToReturn = NDIS_STATUS_INVALID_LENGTH; } else { // // Store result. // CS8900_MOVE_MEM(InfoBuffer, MoveSource, MoveBytes); (*BytesWritten) += MoveBytes; } } DEBUGMSG(1, (TEXT("-CS8900:CS8900QueryInformation/r/n"))); return StatusToReturn; }
(5)SetInformationHandler:CS8900SetInformation
MiniportSetInformation的入口函数,同MiniportQueryInformation相反,是协议驱动,NDIS要求改变miniport驱动为特殊对象保存的状态信息,比如多播地址的改变,也必须实现.
MiniportSetInformation is a required function that allows bound protocol drivers, or NDIS, to request changes in the state information that the miniport maintains for particular object identifiers, such as changes in multicast addresses.
这里实现了OID_802_3_MULTICAST_LIST,OID_GEN_CURRENT_PACKET_FILTER,OID_GEN_CURRENT_LOOKAHEAD这三个OID对象的重新设置.
代码如下:
extern NDIS_STATUS CS8900SetInformation( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN ULONG InformationBufferLength, OUT PULONG BytesRead, OUT PULONG BytesNeeded ) /*++ Routine Description: CS8900SetInformation handles a set operation for a single OID. Arguments: MiniportAdapterContext - Context registered with the wrapper, really a pointer to the adapter. Oid - The OID of the set. InformationBuffer - Holds the data to be set. InformationBufferLength - The length of InformationBuffer. BytesRead - If the call is successful, returns the number of bytes read from InformationBuffer. BytesNeeded - If there is not enough data in InformationBuffer to satisfy the OID, returns the amount of storage needed. Return Value: NDIS_STATUS_SUCCESS NDIS_STATUS_PENDING NDIS_STATUS_INVALID_LENGTH NDIS_STATUS_INVALID_OID --*/ { // // Pointer to the adapter structure. // PCS8900_ADAPTER Adapter = (PCS8900_ADAPTER)MiniportAdapterContext; // // General Algorithm: // // Verify length // Switch(Request) // Process Request // UINT BytesLeft = InformationBufferLength; PUCHAR InfoBuffer = (PUCHAR)(InformationBuffer); // // Variables for a particular request // UINT OidLength; // // Variables for holding the new values to be used. // ULONG LookAhead; ULONG Filter; // // Status of the operation. // NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS; DEBUGMSG(1, (TEXT("+CS8900:CS8900SetInformation/r/n"))); // // Get Oid and Length of request // OidLength = BytesLeft; switch (Oid) { case OID_802_3_MULTICAST_LIST: DEBUGMSG(1, (TEXT("OID_802_3_MULTICAST_LIST/r/n"))); // // Verify length // if ((OidLength % CS8900_LENGTH_OF_ADDRESS) != 0) { StatusToReturn = NDIS_STATUS_INVALID_LENGTH; *BytesRead = 0; *BytesNeeded = 0; break; } // // Set the new list on the adapter. // NdisMoveMemory(Adapter->Addresses, InfoBuffer, OidLength); break; case OID_GEN_CURRENT_PACKET_FILTER: DEBUGMSG(1, (TEXT("OID_GEN_CURRENT_PACKET_FILTER/r/n"))); // // Verify length // if (OidLength != 4 ) { StatusToReturn = NDIS_STATUS_INVALID_LENGTH; *BytesRead = 0; *BytesNeeded = 0; break; } CS8900_MOVE_MEM(&Filter, InfoBuffer, 4); // // Verify bits // if (Filter & (NDIS_PACKET_TYPE_SOURCE_ROUTING | NDIS_PACKET_TYPE_SMT | NDIS_PACKET_TYPE_MAC_FRAME | NDIS_PACKET_TYPE_FUNCTIONAL | NDIS_PACKET_TYPE_ALL_FUNCTIONAL | NDIS_PACKET_TYPE_GROUP )) { StatusToReturn = NDIS_STATUS_NOT_SUPPORTED; *BytesRead = 4; *BytesNeeded = 0; break; } break; case OID_GEN_CURRENT_LOOKAHEAD: DEBUGMSG(1, (TEXT("OID_GEN_CURRENT_LOOKAHEAD/r/n"))); // // Verify length // if (OidLength != 4) { StatusToReturn = NDIS_STATUS_INVALID_LENGTH; *BytesRead = 0; *BytesNeeded = 0; break; } // // Store the new value. // CS8900_MOVE_MEM(&LookAhead, InfoBuffer, 4); if (LookAhead <= CS8900_MAX_LOOKAHEAD) { Adapter->MaxLookAhead = LookAhead; } else { StatusToReturn = NDIS_STATUS_INVALID_LENGTH; } break; default: StatusToReturn = NDIS_STATUS_INVALID_OID; *BytesRead = 0; *BytesNeeded = 0; break; } if (StatusToReturn == NDIS_STATUS_SUCCESS) { *BytesRead = BytesLeft; *BytesNeeded = 0; } DEBUGMSG(1, (TEXT("-CS8900:CS8900SetInformation/r/n"))); return(StatusToReturn); }
(6)ResetHandler:CS8900Reset
MiniportReset的入口函数,网卡软硬件复位时指向的函数.
这里进行网卡的复位和初始化(resetCS,initCS)
NDIS_STATUS CS8900Reset( OUT PBOOLEAN AddressingReset, IN NDIS_HANDLE MiniportAdapterContext ) /*++ Routine Description: The CS8900Reset request instructs the Miniport to issue a hardware reset to the network adapter. The driver also resets its software state. See the description of NdisMReset for a detailed description of this request. Arguments: AddressingReset - Does the adapter need the addressing information reloaded. MiniportAdapterContext - Pointer to the adapter structure. Return Value: The function value is the status of the operation. --*/ { // // Pointer to the adapter structure. // PCS8900_ADAPTER Adapter = (PCS8900_ADAPTER)MiniportAdapterContext; DEBUGMSG(1, (TEXT("+CS8900:CS8900Reset/r/n"))); resetCS(); initCS(); return NDIS_STATUS_SUCCESS; }
(7)TransferDataHandler:CS8900TransferData
MiniportTransferData的入口函数,用在不支持WAN Media不使用NdisMIndicateReceivePacket来通知多包接收或者特定媒体信息的网卡驱动.必须实现.
This function is a required function in network adapter drivers that do not indicate multipacket receives and/or media-specific information with NdisMIndicateReceivePacket and in those that do not support WAN media.
这里我们也不需要,简单返回即可.
NDIS_STATUS CS8900TransferData( OUT PNDIS_PACKET Packet, OUT PUINT BytesTransferred, IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_HANDLE MiniportReceiveContext, IN UINT ByteOffset, IN UINT BytesToTransfer ) /*++ Routine Description: A protocol calls the CS8900TransferData request (indirectly via NdisTransferData) from within its Receive event handler to instruct the driver to copy the contents of the received packet a specified packet buffer. Arguments: MiniportAdapterContext - Context registered with the wrapper, really a pointer to the adapter. MiniportReceiveContext - The context value passed by the driver on its call to NdisMEthIndicateReceive. The driver can use this value to determine which packet, on which adapter, is being received. ByteOffset - An unsigned integer specifying the offset within the received packet at which the copy is to begin. If the entire packet is to be copied, ByteOffset must be zero. BytesToTransfer - An unsigned integer specifying the number of bytes to copy. It is legal to transfer zero bytes; this has no effect. If the sum of ByteOffset and BytesToTransfer is greater than the size of the received packet, then the remainder of the packet (starting from ByteOffset) is transferred, and the trailing portion of the receive buffer is not modified. Packet - A pointer to a descriptor for the packet storage into which the MAC is to copy the received packet. BytesTransfered - A pointer to an unsigned integer. The MAC writes the actual number of bytes transferred into this location. This value is not valid if the return status is STATUS_PENDING. Notes: - The MacReceiveContext will be a pointer to the open block for the packet. --*/ { // // The adapter to transfer from. // PCS8900_ADAPTER Adapter = ((PCS8900_ADAPTER)MiniportReceiveContext); DEBUGMSG(1, (TEXT("+CS8900:CS8900TransferData/r/n"))); return(NDIS_STATUS_SUCCESS); }
(8)CancelSendPacketsHandler:CS8900CancelSendPackets
     AdapterShutdownHandler:CS8900AdapterShutdown
     PnPEventNotifyHandler:CS8900DevicePnPEvent
这三个函数都只有一个框架,没有具体实现.具体内容可参考MS帮助.
其中PnPEventNotifyHandler是在NDIS51_MINIPORT_CHARACTERISTICS新增的,NDIS_MINIPORT_CHARACTERISTICS中没有.

 
   

你可能感兴趣的:(WinCE5.0 SMDK2410 BSP在GEC2410开发板上的移植(16)-CS8900 NDIS Miniport driver简析(2))