📄 3c90x.c
字号:
Device = 0;
noAdapterFound++;
}
DBGPRINT_FUNCTION((KERN_CRIT "tc90xbc_ScanDevices: OUT\n"));
if (noAdapterFound) {
DBGPRINT_INITIALIZE(("NoAdapter = %x\n", noAdapterFound));
return NIC_STATUS_SUCCESS;
}
else
return NIC_STATUS_FAILURE;
}
/*++
Routine Name:
tc90x_FillDeviceStructure
Routine Description:
This routine fills the device structure
Arguments:
Device - Pointer to the device structure.
IoBaseAddress - IoBase address for the adapter.
Irq - Irq of the adapter.
Return Value:
-ENODEV if no adapter found
noAdapterFound if adapter(s) found
--*/
NIC_STATUS
tc90x_FillDeviceStructure(
IN PNIC_INFORMATION Adapter
)
{
PNIC_INFORMATION pAdapter = Adapter;
PDEVICE device = pAdapter->Device;
DBGPRINT_INIT(("FillDeviceStructure: IN\n"));
device->base_addr = pAdapter->PCI.IoBaseAddress;
device->irq = pAdapter->PCI.InterruptVector;
device->mtu = MTU;
//
// Set the routine addresses
//
device->open = &NICOpen;
device->hard_start_xmit = &NICSendPacket;
device->stop = &NICClose;
device->get_stats = &NICGetStatistics;
device->do_ioctl = &NICIoctl;
#ifdef NEW_MULTICAST
device->set_multicast_list = &NICSetReceiveMode;
#else
device->set_multicast_list = &NICSetMulticastList;
#endif
DBGPRINT_INIT(("FillDeviceStructure: OUT\n"));
return NIC_STATUS_SUCCESS;
}
/*++
Routine Name:
NICOpen
Routine Description:
This routine opens the interface.
Arguments:
Device - Pointer to the device structure.
Return Value:
0 if SUCCESS
-ENODEV if FAILURE
--*/
INT
NICOpen(
IN PDEVICE Device
)
{
PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Device->priv;
DBGPRINT_FUNCTION(("New NICOpen: IN\n"));
//
// Initialize general wait timer used during driver init
//
init_timer(&WaitTimer);
WaitTimer.data = (ULONG)Device;
WaitTimer.function = &WaitTimerHandler;
pAdapter->WaitCases = NONE;
add_timer(&WaitTimer);
InWaitTimer = TRUE;
pAdapter->ResourcesReserved |= WAIT_TIMER_REGISTERED;
#if LINUX_VERSION_CODE >= 0x20200
pAdapter->SpinLock_int = (spinlock_t) SPIN_LOCK_UNLOCKED;
pAdapter->SpinLock_send = (spinlock_t) SPIN_LOCK_UNLOCKED;
pAdapter->SpinLock_misc = (spinlock_t) SPIN_LOCK_UNLOCKED;
pAdapter->SpinLock_m = (spinlock_t) SPIN_LOCK_UNLOCKED;
#endif
//
// Register IOBase and Irq with the OS
//
if (tc90x_RegisterAdapter(pAdapter) != NIC_STATUS_SUCCESS) {
DBGPRINT_ERROR(("NICOpen: RegisterAdapter failed\n"));
DBGPRINT_FUNCTION(("NICOpen: Out with ERROR\n"));
tc90x_FreeAdapterResources(pAdapter);
return -ENODEV;
}
if (tc90x_GetAdapterProperties(pAdapter) != NIC_STATUS_SUCCESS) {
DBGPRINT_ERROR(("NICOpen: GetAdapterProperties failed\n"));
DBGPRINT_FUNCTION(("NICOpen: Out with ERROR\n"));
tc90x_FreeAdapterResources(pAdapter);
return -ENODEV;
}
if (tc90x_BasicInitializeAdapter(pAdapter) != NIC_STATUS_SUCCESS) {
DBGPRINT_ERROR(("NICOpen: BasicInitializeAdapter failed\n"));
DBGPRINT_FUNCTION(("NICOpen: Out with error\n"));
tc90x_FreeAdapterResources(pAdapter);
return -ENODEV;
}
if (tc90x_TestAdapter(pAdapter) != NIC_STATUS_SUCCESS) {
DBGPRINT_ERROR(("NICOpen: TestAdapter failed\n"));
DBGPRINT_FUNCTION(("NICOpen: Out with error\n"));
tc90x_FreeAdapterResources(pAdapter);
return -ENODEV;
}
if (tc90x_SetupMedia(Device) != NIC_STATUS_SUCCESS) {
DBGPRINT_ERROR(("NICOpen: SetupMedia failed\n"));
DBGPRINT_FUNCTION(("NICOpen: Out with error\n"));
tc90x_FreeAdapterResources(pAdapter);
return -ENODEV;
}
if (tc90x_SoftwareWork(pAdapter) != NIC_STATUS_SUCCESS) {
DBGPRINT_ERROR((
"NICOpen: EnableSoftwareWork failed\n"));
DBGPRINT_FUNCTION(("NICOpen: Out with error\n"));
tc90x_FreeAdapterResources(pAdapter);
return -ENODEV;
}
if (tc90x_StartAdapter(pAdapter) != NIC_STATUS_SUCCESS) {
DBGPRINT_ERROR(("NICOpen: StartAdapter failed\n"));
DBGPRINT_FUNCTION(("NICOpen: Out with error\n"));
tc90x_FreeAdapterResources(pAdapter);
return -ENODEV;
}
Device->tbusy = 0;
Device->interrupt = 0;
Device->start = 1;
//
// Initialize the timer.
//
pAdapter->Resources.TimerInterval = 100;
init_timer(&pAdapter->Resources.Timer);
pAdapter->Resources.Timer.expires = RUN_AT(HZ/10);
pAdapter->Resources.Timer.data = (ULONG)Device;
pAdapter->Resources.Timer.function = &NICTimer;
add_timer(&pAdapter->Resources.Timer);
//
// Initialize task queue for hosterr task, just in case
//
pAdapter->Resources.hostErr_task.routine = ReStartAdapter;
pAdapter->Resources.hostErr_task.data = (void *)&pAdapter;
pAdapter->Resources.hostErr_task.sync = 0;
//
// Timer has been registered.
//
pAdapter->ResourcesReserved |= NIC_TIMER_REGISTERED;
MOD_INC_USE_COUNT;
DBGPRINT_FUNCTION(("NICOpen: OUT with SUCCESS\n"));
return 0;
}
/*++
Routine Name:
NICClose
Routine Description:
This routine closes the interface.
Arguments:
Device - Pointer to the device structure.
Return Value:
-ENODEV if no adapter found
noAdapterFound if adapter(s) found
--*/
INT
NICClose(
IN PDEVICE Device
)
{
PNIC_INFORMATION pAdapter = (PNIC_INFORMATION)Device->priv;
PDEVICE device = pAdapter->Device;
DBGPRINT_FUNCTION(("NICClose: IN\n"));
#if LINUX_VERSION_CODE >= 0x20200
spin_lock(&pAdapter->SpinLock_misc);
#endif
Device->start = 0;
Device->tbusy = 1;
//
// Disable transmit and receive.
//
NIC_COMMAND(pAdapter, COMMAND_TX_DISABLE);
NIC_COMMAND(pAdapter, COMMAND_RX_DISABLE);
//
// Wait for the transmit in progress to go off.
//
NIC_COMMAND(pAdapter,COMMAND_SELECT_REGISTER_WINDOW | REGISTER_WINDOW_4);
MediaStatus_g = NIC_READ_PORT_USHORT(pAdapter,MEDIA_STATUS_REGISTER);
NIC_DELAY(10);
if(MediaStatus_g & MEDIA_STATUS_TX_IN_PROGRESS)
{ pAdapter->WaitCases = CHECK_TRANSMIT_IN_PROGRESS;
TimeOutCount = jiffies + HZ; //max = 1s
if(!InWaitTimer)
{ WaitTimer.expires = RUN_AT(HZ/100);
add_timer(&WaitTimer);
InWaitTimer = TRUE;
}
while(TimeOutCount > jiffies) ;
if(!(MediaStatus_g & MEDIA_STATUS_TX_IN_PROGRESS))
DBGPRINT_ERROR(("NICClose: Adapter is not responding\n"));
}
// Issue Global reset.
//
NIC_COMMAND_WAIT(pAdapter,
COMMAND_GLOBAL_RESET |
GLOBAL_RESET_MASK_TP_AUI_RESET |
GLOBAL_RESET_MASK_ENDEC_RESET |
GLOBAL_RESET_MASK_AISM_RESET |
GLOBAL_RESET_MASK_SMB_RESET |
GLOBAL_RESET_MASK_VCO_RESET);
NIC_COMMAND_WAIT(pAdapter, COMMAND_TX_RESET);
NIC_COMMAND_WAIT(pAdapter, COMMAND_RX_RESET);
//
// Mask and acknowledge all interrupts.
//
NIC_MASK_ALL_INTERRUPT(pAdapter);
NIC_ACKNOWLEDGE_ALL_INTERRUPT(pAdapter);
tc90x_CleanupSendLogic(Device);
//
// Unregister the interrupt handler.
//
if (pAdapter->ResourcesReserved & NIC_INTERRUPT_REGISTERED) {
DBGPRINT_INITIALIZE(("Releasing interrupt\n"));
free_irq(device->irq, device);
pAdapter->ResourcesReserved &= ~NIC_INTERRUPT_REGISTERED;
}
//
// Unregister the timer handler.
//
if (pAdapter->ResourcesReserved & NIC_TIMER_REGISTERED) {
DBGPRINT_INITIALIZE((KERN_CRIT "Releasing Timer\n"));
if (del_timer(&pAdapter->Resources.Timer)) {
DBGPRINT_INITIALIZE(("Timer already queued\n"));
}
pAdapter->ResourcesReserved &= ~NIC_TIMER_REGISTERED;
}
if (pAdapter->ResourcesReserved & WAIT_TIMER_REGISTERED) {
DBGPRINT_INITIALIZE((KERN_CRIT "Releasing WaitTimer\n"));
if (del_timer(&WaitTimer))
DBGPRINT_INITIALIZE(("WaitTimer already queued\n"));
pAdapter->ResourcesReserved &= ~WAIT_TIMER_REGISTERED;
}
MOD_DEC_USE_COUNT;
#if LINUX_VERSION_CODE >= 0x20200
spin_unlock(&pAdapter->SpinLock_misc);
#endif
DBGPRINT_FUNCTION(("NICClose: OUT\n"));
return 0;
}
/*++
Routine Name:
cleanup_module
Routine Description:
This routine releases the resources.
Arguments:
None
Return Value:
None
--*/
#ifdef MODULE
VOID
cleanup_module(
VOID
)
{
PDEVICE nextDevice;
PNIC_INFORMATION pAdapter;
DBGPRINT_FUNCTION(("cleanup_module: IN\n"));
while (RootNICDevice) {
nextDevice = ((PNIC_INFORMATION)
(RootNICDevice->priv))->NextDevice;
unregister_netdev(RootNICDevice);
pAdapter = (PNIC_INFORMATION)RootNICDevice->priv;
tc90x_FreeAdapterResources(pAdapter);
kfree(RootNICDevice);
kfree(pAdapter);
RootNICDevice = nextDevice;
}
DBGPRINT_FUNCTION(("cleanup_module: OUT\n"));
}
#endif
/*++
Routine Name:
MainAutoSelectionRoutine
Routine Description:
If autoselection is set, determine the connector and link speed
by trying the various transceiver types.
Arguments:
IN PNIC_INFORMATION Adapter
IN USHORT Options
Return Value:
VOID
--*/
VOID
tc90x_MainAutoSelectionRoutine(
IN PNIC_INFORMATION Adapter,
IN USHORT Options
)
{
PNIC_INFORMATION pAdapter = Adapter;
CONNECTOR_TYPE NotUsed;
USHORT index;
DBGPRINT_FUNCTION(("MainAutoSelectionRoutine: IN \n"));
pAdapter->Hardware.Connector = CONNECTOR_UNKNOWN;
//
// Try 100MB Connectors
//
if ((Options & MEDIA_OPTIONS_100BASETX_AVAILABLE) ||
(Options & MEDIA_OPTIONS_10BASET_AVAILABLE) ||
(Options & MEDIA_OPTIONS_MII_AVAILABLE)) {
//
// For 10Base-T and 100Base-TX, select autonegotiation
// instead of autoselect before calling trymii
//
if ((Options & MEDIA_OPTIONS_100BASETX_AVAILABLE) ||
(Options & MEDIA_OPTIONS_10BASET_AVAILABLE)) {
pAdapter->Hardware.Connector =
CONNECTOR_AUTONEGOTIATION;
}
else
pAdapter->Hardware.Connector = CONNECTOR_MII;
DBGPRINT_INITIALIZE(("Trying MII\n"));
if (!tc90x_TryMII(pAdapter, Options))
pAdapter->Hardware.Connector = CONNECTOR_UNKNOWN;
}
//
// Transceiver available is 100Base-FX
//
if ((Options & MEDIA_OPTIONS_100BASEFX_AVAILABLE) &&
(pAdapter->Hardware.Connector == CONNECTOR_UNKNOWN)) {
DBGPRINT_INITIALIZE(("Trying 100BFX\n"));
if (tc90x_TryLinkBeat(pAdapter, CONNECTOR_100BASEFX)) {
pAdapter->Hardware.Connector = CONNECTOR_100BASEFX;
pAdapter->Hardware.LinkSpeed = LINK_SPEED_100;
}
}
//
// Transceiver available is 10AUI
//
if ((Options & MEDIA_OPTIONS_10AUI_AVAILABLE) &&
(pAdapter->Hardware.Connector == CONNECTOR_UNKNOWN)) {
DBGPRINT_INITIALIZE(("Trying 10AUI\n"));
tc90x_SetupConnector(pAdapter, CONNECTOR_10AUI, &NotUsed);
//
// Try to loopback packet
//
for (index = 0; index < 3; index++) {
if (TestPacket(pAdapter)) {
pAdapter->Hardware.Connector = CONNECTOR_10AUI;
pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;
DBGPRINT_INITIALIZE(("Found AUI\n"));
break;
}
}
if (index == 3)
DBGPRINT_INITIALIZE(("Unable to find AUI\n"));
}
//
// Transceiver available is 10Base-2
//
if ((Options & MEDIA_OPTIONS_10BASE2_AVAILABLE) &&
(pAdapter->Hardware.Connector == CONNECTOR_UNKNOWN)) {
DBGPRINT_INITIALIZE(("Trying 10BASEB2\n"));
//
// Set up the connector
//
tc90x_SetupConnector(pAdapter, CONNECTOR_10BASE2, &NotUsed);
//
// Try to loopback packet
//
for (index = 0; index < 3; index++) {
if (TestPacket(pAdapter)) {
pAdapter->Hardware.Connector = CONNECTOR_10BASE2;
pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;
DBGPRINT_INITIALIZE(("Found 10Base2 \n"));
break;
}
}
if (index == 3)
DBGPRINT_INITIALIZE(("Unable to find 10Base2\n"));
//
// Disable DC converter
//
NIC_COMMAND(pAdapter, COMMAND_DISABLE_DC_CONVERTER);
//
// Check if DC convertor has been disabled
//
tc90x_CheckDCConverter(pAdapter, FALSE);
}
//
// Nothing left to try!
//
if (pAdapter->Hardware.Connector == CONNECTOR_UNKNOWN) {
pAdapter->Hardware.Connector = pAdapter->Hardware.ConfigConnector;
pAdapter->Hardware.LinkSpeed = LINK_SPEED_10;
DBGPRINT_INITIALIZE(("AutoSelection failed. Using default.\n"));
DBGPRINT_INITIALIZE(("Connector: %x\n",pAdapter->Hardware.Connector));
pAdapter->Hardware.LinkState = LINK_DOWN_AT_INIT;
}
tc90x_SetupConnector(
pAdapter,
pAdapter->Hardware.Connector,
&NotUsed);
DBGPRINT_FUNCTION(("MainAutoSelectionRoutine: OUT \n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -