📄 ax88172.c
字号:
/*++
Copyright (c) 1998-2001 ASIX Electronics Corporation
Module Name:
ax88172.c
Abstract:
This is the main file for the ASIX AX88172 USB-Ethernet Controller.
This driver conforms to the NDIS3/NDIS5 miniport interface.
Author:
William Lee, June 2001, July 2002,
Environment:
Windows 98/98SE/2000/ME/XP
Revision History:
--*/
#include "ax88170.h"
//
// The global Miniport driver block.
//
static DRIVER_BLOCK AX88172MiniportBlock;
//
// List of supported OID for this driver.
//
static const NDIS_OID AX88172SupportedOids[] =
{
OID_GEN_SUPPORTED_LIST,
OID_GEN_HARDWARE_STATUS,
OID_GEN_MEDIA_SUPPORTED,
OID_GEN_MEDIA_IN_USE,
OID_GEN_MEDIA_CONNECT_STATUS,
OID_GEN_MAXIMUM_LOOKAHEAD,
OID_GEN_MAXIMUM_FRAME_SIZE,
OID_GEN_MAXIMUM_TOTAL_SIZE,
OID_GEN_MAXIMUM_SEND_PACKETS,
OID_GEN_MAC_OPTIONS,
OID_GEN_PROTOCOL_OPTIONS,
OID_GEN_LINK_SPEED,
OID_GEN_TRANSMIT_BUFFER_SPACE,
OID_GEN_TRANSMIT_BLOCK_SIZE,
OID_GEN_TRANSMIT_QUEUE_LENGTH,
OID_GEN_RECEIVE_BUFFER_SPACE,
OID_GEN_RECEIVE_BLOCK_SIZE,
OID_GEN_VENDOR_ID,
OID_GEN_VENDOR_DESCRIPTION,
OID_GEN_VENDOR_DRIVER_VERSION,
OID_GEN_CURRENT_PACKET_FILTER,
OID_GEN_CURRENT_LOOKAHEAD,
OID_GEN_DRIVER_VERSION,
OID_GEN_XMIT_OK,
OID_GEN_XMIT_ERROR,
OID_GEN_RCV_OK,
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_BACKDOOR_GPBITS
};
USHORT HIFG[3] = { 0x17,0x0c,0x14 }; //HomePNA
USHORT EIFG[3] = { 0x15,0x0c,0x12 }; //Ethernet
#include "card.c"
#include "interrup.c"
VOID
AXTransmitHandler(
IN PVOID SystemSpecific1,
IN PAX_ADAPTER Adapter,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3
)
{
Adapter->fgBusy = TRUE;
while ( Adapter->FirstPacket )
{
if ( Adapter->TransmitIoCount<numTransmitQ )
AX88172DoNextSend(Adapter);
else
{
NdisMSetTimer( &Adapter->TransmitHandleTimer,1 );
return;
}
}
Adapter->StartTransmit = FALSE;
}
ULONG
compute_crc32(
IN UINT length,
IN PUCHAR buffer
)
{
ULONG crc32 = 0xffffffff;
for ( ; length; length-- )
{
UCHAR current_byte = *buffer++;
UINT j;
for ( j=0; j<8; j++ )
{
UCHAR carry = current_byte & 1;
if ( crc32 & 0x80000000 )
carry ^= 1;
crc32 <<= 1;
current_byte >>= 1;
if ( carry )
crc32 ^= 0x04c11db7; /*big endian polynomial*/
}
}
return crc32;
}
VOID
AXReceiveHandler(
IN PVOID SystemSpecific1,
IN PAX_ADAPTER Adapter,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3
)
{
ULONG IoCount;
NdisAcquireSpinLock( &Adapter->ReceiveIoCountSpinLock );
IoCount = Adapter->ReceiveIoCount;
while ( IoCount )
{
PUCHAR BufferOffset;
UINT totalLength;
NdisReleaseSpinLock( &Adapter->ReceiveIoCountSpinLock );
BufferOffset = &Adapter->ReceiveBuffer[Adapter->LastReceive][0];
totalLength = Adapter->ReceiveLength[Adapter->LastReceive] -ETH_HEADER_SIZE;
NdisMEthIndicateReceive(
Adapter->MiniportAdapterHandle,
(NDIS_HANDLE)Adapter,
BufferOffset,
ETH_HEADER_SIZE,
(PUCHAR)BufferOffset +ETH_HEADER_SIZE,
totalLength,
totalLength
);
NdisMEthIndicateReceiveComplete( Adapter->MiniportAdapterHandle );
if ( Adapter->StopReceive )
{
Adapter->StopReceive = FALSE;
BulkUsb_PacketReceive( Adapter );
}
Adapter->FramesRcvGood++;
if ( Adapter->LastReceive<(numReceiveQ-1) )
Adapter->LastReceive++;
else
Adapter->LastReceive = 0;
NdisAcquireSpinLock( &Adapter->ReceiveIoCountSpinLock );
IoCount = NdisInterlockedDecrement(&Adapter->ReceiveIoCount);
}
NdisReleaseSpinLock( &Adapter->ReceiveIoCountSpinLock );
Adapter->StartReceive = FALSE;
}
VOID
AXWaitTransmit(
IN PVOID SystemSpecific1,
IN PAX_ADAPTER Adapter,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3
)
{
BulkUsb_PacketTransmit( Adapter );
}
VOID
AXWaitReceive(
IN PVOID SystemSpecific1,
IN PAX_ADAPTER Adapter,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3
)
{
BulkUsb_PacketReceive( Adapter );
}
VOID
AXWaitInterrupt(
IN PVOID SystemSpecific1,
IN PAX_ADAPTER Adapter,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3
)
{
if ( !Adapter->HaltEvents && Adapter->fgReady )
{
if ( Adapter->StartReceive||Adapter->StartTransmit )
NdisMSetTimer( &Adapter->InterruptTimer,160 );
else
BulkUsb_InterruptEvent( Adapter );
}
}
VOID
MiiReadRegister(
IN PAX_ADAPTER Adapter,
IN PURB pUrb,
IN USHORT uPhyAddr,
IN USHORT uRegNum,
IN PUSHORT puRegData
)
{
UsbBuildVendorRequest(
pUrb,
URB_FUNCTION_VENDOR_DEVICE,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
(USBD_TRANSFER_DIRECTION_IN |USBD_SHORT_TRANSFER_OK),
0,
7,
uPhyAddr,
uRegNum,
puRegData,
NULL,
2,
NULL
);
BulkUsb_CallUSBD(Adapter, pUrb);
}
USHORT
_MiiReadRegister(
IN NDIS_HANDLE MiniportAdapterContext,
IN USHORT uRegNum
)
{
PAX_ADAPTER Adapter = (PAX_ADAPTER)(MiniportAdapterContext);
URB Urb;
USHORT uRegData;
UsbBuildVendorRequest(
&Urb,
URB_FUNCTION_VENDOR_DEVICE,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
(USBD_TRANSFER_DIRECTION_IN |USBD_SHORT_TRANSFER_OK),
0,
7,
Adapter->SecondaryPhy,
uRegNum,
&uRegData,
NULL,
2,
NULL
);
BulkUsb_CallUSBD(Adapter, &Urb);
return uRegData;
}
VOID
MiiWriteRegister(
IN PAX_ADAPTER Adapter,
IN PURB pUrb,
IN USHORT uPhyAddr,
IN USHORT uRegNum,
IN USHORT uRegData
)
{
UsbBuildVendorRequest(
pUrb,
URB_FUNCTION_VENDOR_DEVICE,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
USBD_TRANSFER_DIRECTION_OUT,
0,
8,
uPhyAddr,
uRegNum,
&uRegData,
NULL,
2,
NULL
);
BulkUsb_CallUSBD(Adapter, pUrb);
}
VOID
_MiiWriteRegister(
IN NDIS_HANDLE MiniportAdapterContext,
IN USHORT uRegNum,
IN USHORT uRegData
)
{
PAX_ADAPTER Adapter = (PAX_ADAPTER)(MiniportAdapterContext);
URB Urb;
UsbBuildVendorRequest(
&Urb,
URB_FUNCTION_VENDOR_DEVICE,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
USBD_TRANSFER_DIRECTION_OUT,
0,
8,
Adapter->SecondaryPhy,
uRegNum,
&uRegData,
NULL,
2,
NULL
);
BulkUsb_CallUSBD(Adapter, &Urb);
}
VOID
PhyInitial( IN PAX_ADAPTER Adapter );
#pragma NDIS_PAGEABLE_FUNCTION(PhyInitial)
VOID
PhyInitial(
IN PAX_ADAPTER Adapter
)
{
URB Urb;
USHORT uPhyId_1, uPhyId_2;
USHORT i,uPhyRegister;
//Disable MII operation of AX88172 Hardware
UsbBuildVendorRequest(
&Urb,
URB_FUNCTION_VENDOR_DEVICE,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
USBD_TRANSFER_DIRECTION_OUT,
0,6,0,0,
NULL,NULL,
0,
NULL
);
BulkUsb_CallUSBD(Adapter, &Urb);
#if 0
UsbBuildVendorRequest(
&Urb,
URB_FUNCTION_VENDOR_DEVICE,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
USBD_TRANSFER_DIRECTION_OUT,
0,
0x1f,
0x13,
0,
NULL,NULL,
0,
NULL
);
BulkUsb_CallUSBD(Adapter, &Urb);
UsbBuildVendorRequest(
&Urb,
URB_FUNCTION_VENDOR_DEVICE,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
USBD_TRANSFER_DIRECTION_OUT,
0,
0x1f,
1,
0,
NULL,NULL,
0,
NULL
);
BulkUsb_CallUSBD(Adapter, &Urb);
NdisStallExecution(50);
UsbBuildVendorRequest(
&Urb,
URB_FUNCTION_VENDOR_DEVICE,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
USBD_TRANSFER_DIRECTION_OUT,
0,
0x1f,
3,
0,
NULL,NULL,
0,
NULL
);
BulkUsb_CallUSBD(Adapter, &Urb);
#endif
uPhyRegister = 0;
while ( ~uPhyRegister&1 )
{
NdisStallExecution(50);
UsbBuildVendorRequest(
&Urb,
URB_FUNCTION_VENDOR_DEVICE,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
USBD_TRANSFER_DIRECTION_IN |USBD_SHORT_TRANSFER_OK,
0,9,0,0,
&uPhyRegister,
NULL,
1,
NULL
);
BulkUsb_CallUSBD(Adapter, &Urb);
}
if ( Adapter->PrimaryPhy || (Adapter->PrimaryPhyType!=7) )
{
MiiReadRegister(
Adapter,
&Urb,
Adapter->PrimaryPhy,
PhyStatusReg,
&uPhyId_1
);
MiiReadRegister(
Adapter,
&Urb,
Adapter->PrimaryPhy,
PhyControlReg,
&uPhyId_2
);
if ( (uPhyId_1&uPhyId_2) != 0xffff )
{
MiiWriteRegister(
Adapter,
&Urb,
Adapter->PrimaryPhy,
PhyControlReg,
MiiPhyCtrlIsolate|MiiPhyCtrlPowerDown
);
MiiReadRegister(
Adapter,
&Urb,
Adapter->PrimaryPhy,
PhyId_1,
&uPhyId_1
);
MiiReadRegister(
Adapter,
&Urb,
Adapter->PrimaryPhy,
PhyId_2,
&uPhyId_2
);
Adapter->ulPrimaryPhyId = (uPhyId_1<<16) + (uPhyId_2&0xFFF0);
Adapter->PrimaryPhyExist = TRUE;
}
}
if ( Adapter->SecondaryPhy || (Adapter->SecondaryPhyType!=7) )
{
MiiWriteRegister(
Adapter,
&Urb,
0,
PhyAddress,
Adapter->SecondaryPhy
);
if ( (_MiiReadRegister( Adapter,PhyStatusReg ) &
_MiiReadRegister( Adapter,PhyControlReg ) ) != 0xffff )
{
_MiiWriteRegister(
Adapter,
PhyControlReg,
MiiPhyCtrlIsolate|MiiPhyCtrlPowerDown
);
uPhyId_1 = _MiiReadRegister( Adapter,PhyId_1 );
uPhyId_2 = _MiiReadRegister( Adapter,PhyId_2 );
Adapter->ulSecondaryPhyId = (uPhyId_1<<16) + (uPhyId_2&0xFFF0);
Adapter->SecondaryPhyExist = TRUE;
if ( !Adapter->PrimaryPhyExist )
Adapter->PhoneNetworkMedia = TRUE;
}
}
if ( Adapter->PrimaryPhyExist && Adapter->SecondaryPhyExist )
{
MiiWriteRegister(
Adapter,
&Urb,
0,
PhyControlReg,
MiiPhyCtrlIsolate|MiiPhyCtrlPowerDown
);
}
else
Adapter->FixedPhy = TRUE;
if ( Adapter->PhoneNetworkMedia )
{
_MiiWriteRegister(
Adapter,
PhyControlReg,
0
);
_MiiWriteRegister(
Adapter,
PhyControlReg,
MiiPhyCtrlReset
);
if ( Adapter->PrimaryPhyExist )
MiiWriteRegister(
Adapter,
&Urb,
0,
PhyAddress,
Adapter->SecondaryPhy
);
for ( i=0; _MiiReadRegister( Adapter,PhyControlReg )&MiiPhyCtrlReset; i++)
{
if ( i > 1000 )
break;
NdisStallExecution(5000);
}
_MiiWriteRegister(
Adapter,
0x10, //1M8 PHY Control Register
Adapter->uPhoneLine
);
}
else
{
MiiWriteRegister(
Adapter,
&Urb,
Adapter->PrimaryPhy,
PhyControlReg,
0
);
MiiWriteRegister(
Adapter,
&Urb,
Adapter->PrimaryPhy,
PhyControlReg,
MiiPhyCtrlReset
);
uPhyRegister = MiiPhyCtrlReset;
for ( i=0; uPhyRegister & MiiPhyCtrlReset; i++)
{
if ( i > 1000 )
break;
NdisStallExecution(5000);
MiiReadRegister(
Adapter,
&Urb,
Adapter->PrimaryPhy,
PhyControlReg,
&uPhyRegister
);
}
MiiWriteRegister(
Adapter,
&Urb,
Adapter->PrimaryPhy,
PhyNwayAdvertisement,
(USHORT)Adapter->uConnectionType
);
MiiWriteRegister(
Adapter,
&Urb,
Adapter->PrimaryPhy,
PhyControlReg,
MiiPhyCtrlEnableNway|MiiPhyCtrlRestartNway
);
}
UsbBuildVendorRequest(
&Urb,
URB_FUNCTION_VENDOR_DEVICE,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
USBD_TRANSFER_DIRECTION_OUT,
0,10,0,0,
NULL,NULL,
0,
NULL
);
BulkUsb_CallUSBD(Adapter, &Urb);
for ( i=0; i<3; i++ )
{
UsbBuildVendorRequest(
&Urb,
URB_FUNCTION_VENDOR_DEVICE,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
USBD_TRANSFER_DIRECTION_OUT,
0,
18+i,
(Adapter->PhoneNetworkMedia)? HIFG[i]:EIFG[i],
0,
NULL,
NULL,
0,
NULL
);
BulkUsb_CallUSBD(Adapter, &Urb);
}
}
#pragma NDIS_PAGEABLE_FUNCTION(AX88172RegisterAdapter)
NDIS_STATUS
AX88172RegisterAdapter(
IN PAX_ADAPTER Adapter
)
/*++
Routine Description:
Called when a new adapter should be registered. It allocates space for
the adapter, initializes the adapter's block, registers resources
with the wrapper and initializes the physical adapter.
Arguments:
Adapter - The adapter structure.
ConfigurationHandle - Handle passed to AX88172Initialize.
Return Value:
Indicates the success or failure of the registration.
--*/
{
//
// Temporary looping variable.
UINT i;
UCHAR MiiData[2];
PDEVICE_OBJECT FunctionalDeviceObject;
PDEVICE_OBJECT NextDeviceObject;
PCM_RESOURCE_LIST AllocatedResources,AllocatedResourcesTranslated;
URB Urb;
PURB pUrb;
USHORT siz;
USBD_VERSION_INFORMATION UsbVersionInfo;
PUSB_INTERFACE_DESCRIPTOR UsbInterfaceDescriptor;
PUSBD_INTERFACE_INFORMATION UsbInterface;
PUSBD_INTERFACE_LIST_ENTRY interfaceList, tmp;
///
// USB Initialize!
///
NdisMGetDeviceProperty(
Adapter->MiniportAdapterHandle,
&Adapter->PhysicalDeviceObject,
&FunctionalDeviceObject,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -