📄 3c90x.c
字号:
}
/*++
Routine Name:
tc90x_CheckDCConverter
Routine Description:
Arguments:
IN PNIC_INFORMATION Adapter
IN BOOLEAN EnabledState
Return Value:
BOOLEAN
--*/
BOOLEAN
tc90x_CheckDCConverter (
IN PNIC_INFORMATION Adapter,
IN BOOLEAN EnabledState
)
{
PNIC_INFORMATION pAdapter = Adapter;
NIC_COMMAND(pAdapter,COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
MediaStatus_g = NIC_READ_PORT_USHORT(pAdapter,MEDIA_STATUS_REGISTER);
NIC_DELAY(1000);
if( ((EnabledState) && !(MediaStatus_g & MEDIA_STATUS_DC_CONVERTER_ENABLED) ) ||
((!EnabledState) && (MediaStatus_g & MEDIA_STATUS_DC_CONVERTER_ENABLED)) )
{
DCConverterEnabledState_g = EnabledState; /* for waittimer */
pAdapter->WaitCases = CHECK_DC_CONVERTER;
TimeOutCount = jiffies + 3; // 30ms
if(!InWaitTimer)
{ WaitTimer.expires = RUN_AT(HZ/100);
add_timer(&WaitTimer);
InWaitTimer = TRUE;
}
while(TimeOutCount > jiffies) ;
if( (EnabledState && !(MediaStatus_g & MEDIA_STATUS_DC_CONVERTER_ENABLED)) ||
(!EnabledState && (MediaStatus_g & MEDIA_STATUS_DC_CONVERTER_ENABLED))
)
{ pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
DBGPRINT_ERROR(("ConfigureDCConverter: Timeout setting DC Converter \n"));
return FALSE;
}
}
return TRUE;
}
/*++
Routine Name:
tc90x_SetupConnector
Routine Description:
Setup new transceiver type in InternalConfig. Determine whether to
set JabberGuardEnable, enableSQEStats and linkBeatEnable in MediaStatus.
Determine if the coax transceiver also needs to be enabled/disabled.
Arguments:
IN PNIC_INFORMATION Adapter
IN CONNECTOR_TYPE NewConnector
OUT PCONNECTOR_TYPE OldConnector
Return Value:
VOID
--*/
VOID
tc90x_SetupConnector(
IN PNIC_INFORMATION Adapter,
IN CONNECTOR_TYPE NewConnector,
OUT PCONNECTOR_TYPE OldConnector
)
{
PNIC_INFORMATION pAdapter = Adapter;
ULONG InternalConfig = 0;
ULONG OldInternalConfig = 0;
USHORT MediaStatus = 0;
NIC_COMMAND(
pAdapter,
COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_3);
InternalConfig = NIC_READ_PORT_ULONG(
pAdapter,
INTERNAL_CONFIG_REGISTER);
OldInternalConfig = InternalConfig;
//
// Save old choice
//
*OldConnector =
(InternalConfig & INTERNAL_CONFIG_TRANSCEIVER_MASK) >> 20;
//
// Program the MII registers if forcing the configuration to 10/100BaseT.
//
if ((NewConnector == CONNECTOR_10BASET) ||
(NewConnector == CONNECTOR_100BASETX)){
//
// Clear transceiver type and change to new transceiver type.
//
InternalConfig &= ~(INTERNAL_CONFIG_TRANSCEIVER_MASK);
InternalConfig |= (CONNECTOR_AUTONEGOTIATION << 20);
//
// Update the internal config register. Only do this if the value has
//changed to avoid dropping link.
//
if (OldInternalConfig != InternalConfig) {
NIC_WRITE_PORT_ULONG(
pAdapter,
INTERNAL_CONFIG_REGISTER,
InternalConfig);
}
//
// Force the MII registers to the correct settings.
//
if ( !CheckMIIConfiguration(
pAdapter,
(USHORT)((NewConnector == CONNECTOR_100BASETX)
? MEDIA_OPTIONS_100BASETX_AVAILABLE
: MEDIA_OPTIONS_10BASET_AVAILABLE)) ) {
//
// If the forced configuration didn't work, check the results and see why.
//
CheckMIIAutoNegotiationStatus(pAdapter);
return;
}
}
else {
//
// Clear transceiver type and change to new transceiver type
//
InternalConfig = InternalConfig & (~INTERNAL_CONFIG_TRANSCEIVER_MASK);
InternalConfig |= (NewConnector << 20);
//
// Update the internal config register. Only do this if the value has
// changed to avoid dropping link.
//
if (OldInternalConfig != InternalConfig) {
NIC_WRITE_PORT_ULONG(
pAdapter,
INTERNAL_CONFIG_REGISTER,
InternalConfig);
}
}
//
// Determine whether to set enableSQEStats and linkBeatEnable
// Automatically set JabberGuardEnable in MediaStatus register.
//
NIC_COMMAND(
pAdapter,
COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
MediaStatus = NIC_READ_PORT_USHORT(
pAdapter,
MEDIA_STATUS_REGISTER);
MediaStatus &= ~(
MEDIA_STATUS_SQE_STATISTICS_ENABLE |
MEDIA_STATUS_LINK_BEAT_ENABLE |
MEDIA_STATUS_JABBER_GUARD_ENABLE);
MediaStatus |= MEDIA_STATUS_JABBER_GUARD_ENABLE;
if (NewConnector == CONNECTOR_10AUI)
MediaStatus |= MEDIA_STATUS_SQE_STATISTICS_ENABLE;
if (NewConnector == CONNECTOR_AUTONEGOTIATION)
MediaStatus |= MEDIA_STATUS_LINK_BEAT_ENABLE;
else {
if ((NewConnector == CONNECTOR_10BASET) ||
(NewConnector == CONNECTOR_100BASETX) ||
(NewConnector == CONNECTOR_100BASEFX)) {
if (!pAdapter->Hardware.LinkBeatDisable)
MediaStatus |= MEDIA_STATUS_LINK_BEAT_ENABLE;
}
}
NIC_WRITE_PORT_USHORT(pAdapter, MEDIA_STATUS_REGISTER, MediaStatus);
DBGPRINT_INITIALIZE((
"tc90x_SetupConnector: MediaStatus = %x \n",MediaStatus));
//
// If configured for coax we must start the internal transceiver.
// If not, we stop it (in case the configuration changed across a
// warm boot).
//
if (NewConnector == CONNECTOR_10BASE2) {
NIC_COMMAND(pAdapter, COMMAND_ENABLE_DC_CONVERTER);
//
// Check if DC convertor has been enabled
//
tc90x_CheckDCConverter(pAdapter, TRUE);
}
else {
NIC_COMMAND(pAdapter, COMMAND_DISABLE_DC_CONVERTER);
//
// Check if DC convertor has been disabled
//
tc90x_CheckDCConverter(pAdapter, FALSE);
}
}
/*++
Routine Name:
tc90x_TryMII
Routine Description:
Used to detect if 10Base-T, 100Base-TX, or external MII is available.
Arguments:
IN pAdapter pAdapter - Pointer to the adapter structure
IN CONNECTOR_TYPE newconnector
Return Value:
BOOLEAN
--*/
BOOLEAN
tc90x_TryMII(
IN PNIC_INFORMATION Adapter,
IN USHORT MediaOptions
)
{
PNIC_INFORMATION pAdapter = Adapter;
BOOLEAN Handles100Mbit = FALSE;
//CONNECTOR_TYPE NotUsed;
//USHORT PhyControl;
//BOOLEAN PhyResponding;
//USHORT PhyStatus;
DBGPRINT_FUNCTION(("tc90x_TryMII: IN \n"));
//
// First see if there's anything connected to the MII
//
if (!FindMIIPhy(pAdapter)) {
DBGPRINT_ERROR(("tc90x_TryMII: FindMIIPhy failed \n"));
pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
return FALSE;
}
//
// Nowhere is it written that the register must be latched, and since
// reset is the last bit out, the contents might not be valid. read
// it one more time.
//
/*PhyResponding_g = ReadMIIPhy(pAdapter, MII_PHY_CONTROL, &PhyControl);
if (!PhyResponding_g) {
DBGPRINT_ERROR(("tc90x_TryMII: Phy not responding (1) \n"));
pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
return FALSE;
}*/
//
// Now we can read the status and try to figure out what's out there.
//
PhyResponding_g = ReadMIIPhy(pAdapter, MII_PHY_STATUS, &PhyStatus_g);
if (!PhyResponding_g) {
DBGPRINT_ERROR(("tc90x_TryMII: Phy not responding (2) \n"));
pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
return FALSE;
}
if ((PhyStatus_g & MII_STATUS_AUTO) &&
(PhyStatus_g & MII_STATUS_EXTENDED)) {
//
// If it is capable of auto negotiation, see if it has
// been done already.
//
DBGPRINT_INITIALIZE(("MII Capable of Autonegotiation\n"));
//
// Check the current MII auto-negotiation state and see if we need to
// start auto-neg over.
//
if (!CheckMIIConfiguration(pAdapter, MediaOptions))
return FALSE;
//
// See if link is up...
//
PhyResponding_g = ReadMIIPhy(pAdapter, MII_PHY_STATUS, &PhyStatus_g);
if (!PhyResponding_g) {
DBGPRINT_ERROR(("tc90x_TryMII: Phy not responding (3) \n"));
pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
return FALSE;
}
if (PhyStatus_g & MII_STATUS_LINK_UP) {
if (!GetLinkSpeed(pAdapter, &Handles100Mbit)) {
DBGPRINT_ERROR(("TryMII: Unknown link speed \n"));
pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
return FALSE;
}
if (Handles100Mbit) {
DBGPRINT_INITIALIZE(("TryMII: Link speed set to 100\n"));
pAdapter->Hardware.LinkSpeed = LINK_SPEED_100;
}
else {
DBGPRINT_INITIALIZE(("TryMII: Link speed set to 10\n"));
pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;
}
return TRUE;
} else {
//
// Assume 10Mbit if no link
//
if (PhyStatus_g & MII_STATUS_100MB_MASK) {
DBGPRINT_INITIALIZE((
"TryMII: Link speed defaulted to 100 \n"));
pAdapter->Hardware.LinkSpeed = LINK_SPEED_100;
}
else {
DBGPRINT_INITIALIZE((
"TryMII: Link speed defaulted to 10 \n"));
pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;
}
return TRUE;
}
}
return FALSE;
}
/*++
Routine Name:
tc90x_TryLinkBeat
Routine Description:
Download a self-directed packet. If successful, 100BASE-FX is available.
Arguments:
IN PNIC_INFORMATION Adapter
IN CONNECTOR_TYPE NewConnector
Return Value:
BOOLEAN
--*/
BOOLEAN
tc90x_TryLinkBeat(
IN PNIC_INFORMATION Adapter,
IN CONNECTOR_TYPE NewConnector
)
{
PNIC_INFORMATION pAdapter = Adapter;
USHORT MediaStatus = 0;
BOOLEAN retval = FALSE;
CONNECTOR_TYPE NotUsed;
DBGPRINT_FUNCTION(("tc90x_TryLinkBeat: IN \n"));
//
// Go quiet for 1.5 seconds to get any N-Way hub into a receptive
// state to sense the new link speed. We go quiet by switching over
// to 10BT and disabling Linkbeat.
//
pAdapter->Hardware.LinkBeatDisable = TRUE;
tc90x_SetupConnector(pAdapter, CONNECTOR_10BASET, &NotUsed);
//
// Delay 1.5 seconds
//
TimeOutCount = jiffies + 15*HZ/10;
while(TimeOutCount > jiffies) ;
NIC_COMMAND_WAIT(pAdapter, COMMAND_TX_RESET | TX_RESET_MASK_NETWORK_RESET);
NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_RESET | RX_RESET_MASK_NETWORK_RESET);
//
// Set up for TP transceiver
//
tc90x_SetupConnector(pAdapter, NewConnector, &NotUsed);
// delay 5 milliseconds
TimeOutCount = jiffies + 1; //make it 10ms
while(TimeOutCount > jiffies) ;
//
// We need to send a test packet to clear the
// the Partition if for some reason it's partitioned
// (i.e., we were testing 100mb before.)
// Download a 20 byte packet into the TxFIFO, from us, to us
//
if (!DownloadSelfDirected(pAdapter)) {
return FALSE;
}
//
// Acknowledge the down complete
//
NIC_COMMAND(
pAdapter,
COMMAND_ACKNOWLEDGE_INTERRUPT + INTSTATUS_DOWN_COMPLETE);
//
// Check MediaStatus for linkbeat indication
//
NIC_COMMAND(
pAdapter,
COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
MediaStatus = NIC_READ_PORT_USHORT(pAdapter, MEDIA_STATUS_REGISTER);
if (MediaStatus & MEDIA_STATUS_LINK_DETECT) {
retval = TRUE;
}
NIC_COMMAND_WAIT(pAdapter, COMMAND_TX_RESET | TX_RESET_MASK_NETWORK_RESET);
NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_RESET | RX_RESET_MASK_NETWORK_RESET);
DBGPRINT_INITIALIZE(("tc90x_TryLinkBeat: OUT with success\n"));
return retval;
}
/*++
Routine Name:
DownloadSelfDirected
Routine Description:
Download a 20 byte packet into the TxFIFO, from us, to us.
Arguments:
IN PNIC_INFORMATION Adapter
Return Value:
BOOLEAN
--*/
BOOLEAN
DownloadSelfDirected(
IN PNIC_INFORMATION Adapter
)
{
PNIC_INFORMATION pAdapter = Adapter;
PDPD_LIST_ENTRY dpdVirtual;
ULONG PacketBufPhysAddr;
UCHAR *PacketBuffer;
PUCHAR pbuffer;
//
// Set allocated buffer for transmit
//
PacketBuffer = (PUCHAR)pAdapter->TestBufferVirtual[0];
PacketBufPhysAddr = pAdapter->TestBufferPhysical[0];
//
// Fill data in the buffer
//
pbuffer = pAdapter->StationAddress;
memcpy(PacketBuffer, pbuffer, 6); // destination is me
memcpy(PacketBuffer + 6, pbuffer, 6); // source is me
*(ULONG *)(PacketBuffer + 12) = 0;
*(ULONG *)(PacketBuffer + 16) = 0;
//
// Create a single DPD
//
dpdVirtual = (PDPD_LIST_ENTRY)pAdapter->TestDPDVirtual[0];
dpdVirtual->DownNextPointer = 0;
dpdVirtual->FrameStartHeader = 20 | FSH_ROUND_UP_DEFEAT;
dpdVirtual->SGList[0].Address = PacketBufPhysAddr;
dpdVirtual->SGList[0].Count = 20 | 0x80000000;
//
// Download DPD
//
NIC_COMMAND_WAIT(pAdapter, COMMAND_DOWN_STALL);
NIC_WRITE_PORT_ULONG(
pAdapter,
DOWN_LIST_POINTER_REGISTER,
dpdVirtual->DPDPhysicalAddress);
NIC_COMMAND(pAdapter, COMMAND_DOWN_UNSTALL);
//
// Check if the DPD is done with
//
DownListPointer_g = NIC_READ_PORT_ULONG(pAdapter,DOWN_LIST_POINTER_REGISTER);
NIC_DELAY(100);
if(DownListPointer_g == dpdVirtual->DPDPhysicalAddress)
{
pAdapter->WaitCases = CHECK_DOWNLOAD_SELFDIRECTED;
TimeOutCount = jiffies + 3*HZ; //max = 3s
//WaitTimer.expires = RUN_AT(HZ/100);
//add_timer(&WaitTimer);
//InWaitTimer = TRUE;
while(TimeOutCount > jiffies) ;
if(DownListPointer_g != dpdVirtual->DPDPhysicalAddress)
{ pAdapter->Hardware.Status = HARDWARE_STATUS_FAILURE;
DBGPRINT_ERROR(("DownloadSelfDirected: DPD not finished\n"));
return FALSE;
}
}
return TRUE;
}
BOOLEAN
CheckTransmitInProgress(
IN PNIC_INFORMATION Adapter
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -