windows-nt/Source/XPSP1/NT/drivers/net/nec/detect/nia35det/nia35det.c
2020-09-26 16:20:57 +08:00

827 lines
23 KiB
C

#if 1 // The following includes are used when building with the microsoft internal build tree.
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#else // These headers are used when building with the microsoft DDK.
#include <ntddk.h>
#include <windef.h>
#include <winerror.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ntddnetd.h>
#include <ncnet.h>
#include <netdet.h>
BOOLEAN
Nia35DetInit(
IN HANDLE hModule,
IN DWORD dwReason,
IN DWORD dwReserved
)
/*++
Routine Description:
This routine is the entry point into the detection dll.
This routine only return "TRUE".
++*/
{
return (TRUE);
}
ULONG
Nia35NextIoAddress(
IN ULONG IoBaseAddress
)
/*++
Routine Description:
This routine provide next I/O address for detect PC-9801-107/108.
++*/
{
switch(IoBaseAddress){
case 0x0770:
return (0x2770);
case 0x2770:
return (0x4770);
case 0x4770:
return (0x6770);
default:
return (0xffff);
}
}
VOID
Nia35CardSetup(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
OUT PULONG MemoryBaseAddress,
IN BOOLEAN EightBitSlot
)
/*++
Routine Description:
Sets up the card, using the sequence given in the Etherlink II
technical reference.
Arguments:
InterfaceType - The type of bus, ISA or EISA.
BusNumber - The bus number in the system.
IoBaseAddress - The IO port address of the card.
MemoryBaseAddress - Pointer to store the base address of card memory.
EightBitSlot - TRUE if the adapter is in an 8-bit slot.
Return Value:
None.
--*/
{
UINT i;
UCHAR Tmp;
NTSTATUS NtStatus;
LARGE_INTEGER Delay;
*MemoryBaseAddress = 0;
// Stop the card.
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress,
0x21); // STOP | ABORT_DMA
if(!NT_SUCCESS(NtStatus)){
return;
}
// Initialize the Data Configuration register.
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x100c, // NIC_DATA_CONFIG
0x50); // DCR_AUTO_INIT | DCR_FIFO_8_BYTE
if(!NT_SUCCESS(NtStatus)){
return;
}
// Set Xmit start location
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x0008, // NIC_XMIT_START
0xA0);
if(!NT_SUCCESS(NtStatus)){
return;
}
// Set Xmit configuration
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x100a, // NIC_XMIT_CONFIG
0x0);
if(!NT_SUCCESS(NtStatus)){
return;
}
// Set Receive configuration
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x1008, // NIC_RCV_CONFIG
0);
if(!NT_SUCCESS(NtStatus)){
return;
}
// Set Receive start
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x0002, // NIC_PAGE_START
0x4);
if(!NT_SUCCESS(NtStatus)){
return;
}
// Set Receive end
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x0004, // NIC_PAGE_STOP
0xFF);
if(!NT_SUCCESS(NtStatus)){
return;
}
// Set Receive boundary
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x0006, // NIC_BOUNDARY
0x4);
if(!NT_SUCCESS(NtStatus)){
return;
}
// Set Xmit bytes
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x000a, // NIC_XMIT_COUNT_LSB
0x3C);
if(!NT_SUCCESS(NtStatus)){
return;
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x000c, // NIC_XMIT_COUNT_MSB
0x0);
if(!NT_SUCCESS(NtStatus)){
return;
}
// Pause
// Wait for reset to complete. (100 ms)
Delay.LowPart = 100000;
Delay.HighPart = 0;
NtDelayExecution(FALSE, &Delay);
// Ack all interrupts that we might have produced
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x000e, // NIC_INTR_STATUS
0xFF);
if(!NT_SUCCESS(NtStatus)){
return;
}
// Change to page 1
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress,
0x61); // CR_PAGE1 | CR_STOP
if(!NT_SUCCESS(NtStatus)){
return;
}
// Set current
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x000e, // NIC_CURRENT
0x4);
if(!NT_SUCCESS(NtStatus)){
return;
}
// Back to page 0
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress,
0x21); // CR_PAGE0 | CR_STOP
if(!NT_SUCCESS(NtStatus)){
return;
}
// Pause
Delay.LowPart = 2000;
Delay.HighPart = 0;
NtDelayExecution(FALSE, &Delay);
// Do initialization errata
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x1004, // NIC_RMT_COUNT_LSB
55);
if(!NT_SUCCESS(NtStatus)){
return;
}
// Reset the chip
NtStatus = NDetReadPortUchar(InterfaceType,
BusNumber,
((IoBaseAddress >> 1) & 0xf000) + 0x088a, //NIC_RESET
&Tmp);
if(!NT_SUCCESS(NtStatus)){
return;
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
((IoBaseAddress >> 1) & 0xf000) + 0x088a, //NIC_RESET
0xFF);
if(!NT_SUCCESS(NtStatus)){
return;
}
// Start the chip
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress,
0x22);
if(!NT_SUCCESS(NtStatus)){
return;
}
// Mask Interrupts
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x100e, // NIC_INTR_MASK
0xFF);
if(!NT_SUCCESS(NtStatus)){
return;
}
if(EightBitSlot){
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x100c, // NIC_DATA_CONFIG
0x48); // DCR_FIFO_8_BYTE | DCR_NORMAL | DCR_BYTE_WIDE
}else{
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x100c, // NIC_DATA_CONFIG
0x49); // DCR_FIFO_8_BYTE | DCR_NORMAL | DCR_WORD_WIDE
}
if(!NT_SUCCESS(NtStatus)){
return;
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x100a, // NIC_XMIT_CONFIG
0);
if(!NT_SUCCESS(NtStatus)){
return;
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x1008, // NIC_RCV_CONFIG
0);
if(!NT_SUCCESS(NtStatus)){
return;
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x000e, // NIC_INTR_STATUS
0xFF);
if(!NT_SUCCESS(NtStatus)){
return;
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress,
0x21); // CR_NO_DMA | CR_STOP
if(!NT_SUCCESS(NtStatus)){
return;
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x1004, // NIC_RMT_COUNT_LSB
0);
if(!NT_SUCCESS(NtStatus)){
return;
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x1006, // NIC_RMT_COUNT_MSB
0);
if(!NT_SUCCESS(NtStatus)){
return;
}
// Wait for STOP to complete
i = 0xFF;
while (--i){
NtStatus = NDetReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x000e, // NIC_INTR_STATUS
&Tmp);
if(!NT_SUCCESS(NtStatus)){
return;
}
// ISR_RESET
if(Tmp & 0x80){
break;
}
}
// Put card in loopback mode
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x100a, // NIC_XMIT_CONFIG
0x2); // TCR_LOOPBACK
if(NtStatus != STATUS_SUCCESS){
return;
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress,
0x22); // CR_NO_DMA | CR_START
if(NtStatus != STATUS_SUCCESS){
return;
}
// ... but it is still in loopback mode.
return;
}
NTSTATUS
Nia35CardSlotTest(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
OUT PBOOLEAN EightBitSlot
)
/*++
Routine Description:
Checks if the card is in an 8 or 16 bit slot and sets a flag in the
adapter structure.
Arguments:
InterfaceType - The type of bus, ISA or EISA.
BusNumber - The bus number in the system.
IoBaseAddress - The IO port address of the card.
EightBitSlot - Result of test.
Return Value:
TRUE, if all goes well, else FALSE.
--*/
{
UCHAR Tmp;
UCHAR RomCopy[32];
UCHAR i;
NTSTATUS NtStatus;
LARGE_INTEGER Delay;
// Reset the chip
NtStatus = NDetReadPortUchar(InterfaceType,
BusNumber,
((IoBaseAddress >> 1) & 0xf000) + 0x088a, //NIC_RESET
&Tmp);
if(!NT_SUCCESS(NtStatus)){
return(NtStatus);
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
((IoBaseAddress >> 1) & 0xf000) + 0x088a, //NIC_RESET
0xFF);
if(!NT_SUCCESS(NtStatus)){
return(NtStatus);
}
// Go to page 0 and stop
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress,
0x21); // CR_STOP | CR_NO_DMA
if(!NT_SUCCESS(NtStatus)){
return(NtStatus);
}
// Pause
Delay.LowPart = 2000;
Delay.HighPart = 0;
NtDelayExecution(FALSE, &Delay);
// Setup to read from ROM
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x100c, // NIC_DATA_CONFIG
0x48); // DCR_BYTE_WIDE | DCR_FIFO_8_BYTE | DCR_NORMAL
if(!NT_SUCCESS(NtStatus)){
return(NtStatus);
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x100e, // NIC_INTR_MASK
0x0);
if(!NT_SUCCESS(NtStatus)){
return(NtStatus);
}
// Ack any interrupts that may be hanging around
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x000e, // NIC_INTR_STATUS
0xFF);
if(!NT_SUCCESS(NtStatus)){
return(NtStatus);
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x1000, // NIC_RMT_ADDR_LSB
0x0);
if(!NT_SUCCESS(NtStatus)){
return(NtStatus);
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x1002, // NIC_RMT_ADDR_MSB,
0x0);
if(!NT_SUCCESS(NtStatus)){
return(NtStatus);
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x1004, // NIC_RMT_COUNT_LSB
32);
if(!NT_SUCCESS(NtStatus)){
return(NtStatus);
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + 0x1006, // NIC_RMT_COUNT_MSB
0x0);
if(!NT_SUCCESS(NtStatus)){
return(NtStatus);
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress,
0xA); // CR_DMA_READ | CR_START
if(!NT_SUCCESS(NtStatus)){
return(NtStatus);
}
// Read first 32 bytes in 16 bit mode
for (i = 0; i < 32; i++){
NtStatus = NDetReadPortUchar(InterfaceType,
BusNumber,
((IoBaseAddress >> 1) & 0xf000) + 0x0888, //NIC_RACK_NIC
RomCopy + i);
if(NtStatus != STATUS_SUCCESS){
return(NtStatus);
}
}
// Reset the chip
NtStatus = NDetReadPortUchar(InterfaceType,
BusNumber,
((IoBaseAddress >> 1) & 0xf000) + 0x088a, //NIC_RESET
&Tmp);
if(NtStatus != STATUS_SUCCESS){
return(NtStatus);
}
NtStatus = NDetWritePortUchar(InterfaceType,
BusNumber,
((IoBaseAddress >> 1) & 0xf000) + 0x088a, //NIC_RESET
0xFF);
if(NtStatus != STATUS_SUCCESS){
return(NtStatus);
}
// Check ROM for 'B' (byte) or 'W' (word)
for (i = 16; i < 31; i++){
if (((RomCopy[i] == 'B') && (RomCopy[i+1] == 'B')) ||
((RomCopy[i] == 'W') && (RomCopy[i+1] == 'W'))){
if(RomCopy[i] == 'B'){
*EightBitSlot = TRUE;
}else{
*EightBitSlot = FALSE;
}
// Now check that the address is singular. On an Ne1000 the
// ethernet address is store in offsets 0 thru 5. On the Ne2000 and Nia35
// the address is stored in offsets 0 thru 11, where each byte
// is duplicated.
//
if ((RomCopy[0] == RomCopy[1]) &&
(RomCopy[2] == RomCopy[3]) &&
(RomCopy[4] == RomCopy[5]) &&
(RomCopy[6] == RomCopy[7]) &&
(RomCopy[8] == RomCopy[9]) &&
(RomCopy[10] == RomCopy[11])){
return(STATUS_SUCCESS);
}
return(STATUS_UNSUCCESSFUL);
}
}
// If neither found -- then not an NIA35
return(STATUS_UNSUCCESSFUL);
}
NTSTATUS
FindNia35Adapter(
OUT PMND_ADAPTER_INFO *pDetectedAdapter,
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
IN PWSTR pPnpId
)
{
NTSTATUS NtStatus;
UCHAR Data;
USHORT CheckSum = 0;
USHORT StoredCheckSum;
UINT Place;
UCHAR Interrupt = 0;
HANDLE TrapHandle;
UCHAR InterruptList[4];
UCHAR ResultList[4] = {0};
UINT cResources;
UINT c;
UCHAR Value;
ULONG RamAddr = 0;
do{
// check I/O port range.
NtStatus = NDetCheckPortUsage(InterfaceType,
BusNumber,
IoBaseAddress,
0x10);
NtStatus |= NDetCheckPortUsage(InterfaceType,
BusNumber,
IoBaseAddress + 0x1000, // upper range
0x10);
NtStatus |= NDetCheckPortUsage(InterfaceType,
BusNumber,
((IoBaseAddress >> 1) & 0xf000) + 0x0888, // NIC_RACK_NIC
0x2);
NtStatus |= NDetCheckPortUsage(InterfaceType,
BusNumber,
((IoBaseAddress >> 1) & 0xf000) + 0x088a, // NIC_RESET
0x2);
if(!NT_SUCCESS(NtStatus)){
#if DBG
DbgPrint("FindNia35Adapter : Port range in use. IoBaseAddress = %x\n", IoBaseAddress);
#endif
break;
}
NDetReadPortUchar(InterfaceType,
BusNumber,
((IoBaseAddress >> 1) & 0xf000) + 0x088a, //NIC_RESET
&Value);
NDetWritePortUchar(InterfaceType,
BusNumber,
((IoBaseAddress >> 1) & 0xf000) + 0x088a, //NIC_RESET
0xFF);
NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress, // COMMAND
0x21);
// check interrupt.
InterruptList[0] = 3;
InterruptList[1] = 5;
InterruptList[2] = 6;
InterruptList[3] = 12;
NtStatus = NDetSetInterruptTrap(InterfaceType,
BusNumber,
&TrapHandle,
InterruptList,
4);
if(NT_SUCCESS(NtStatus)){
NtStatus = Nia35CardSlotTest(InterfaceType,
BusNumber,
IoBaseAddress,
&Value);
if(!NT_SUCCESS(NtStatus)){
NDetRemoveInterruptTrap(TrapHandle);
break;
}
// CardSetup
Nia35CardSetup(InterfaceType,
BusNumber,
IoBaseAddress,
&RamAddr,
Value);
// Check for interrupt.
NtStatus = NDetQueryInterruptTrap(TrapHandle, ResultList, 4);
// Stop the chip.
NDetReadPortUchar(InterfaceType,
BusNumber,
((IoBaseAddress >> 1) & 0xf000) + 0x088a, //NIC_RESET
&Value);
NDetWritePortUchar(InterfaceType,
BusNumber,
((IoBaseAddress >> 1) & 0xf000) + 0x088a, //NIC_RESET
0xFF);
NDetWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress, // COMMAND
0x21);
NtStatus = NDetRemoveInterruptTrap(TrapHandle);
if(!NT_SUCCESS(NtStatus)){
break;
}
for(c=0 ; c<4 ; c++){
if((ResultList[c] == 1) || (ResultList[c] == 2)){
Interrupt = InterruptList[c];
break;
}
}
}
// Allocate the adapter information.
NtStatus = NetDetectAllocAdapterInfo(pDetectedAdapter,
InterfaceType,
BusNumber,
pPnpId,
0,
0,
0,
2);
if (!NT_SUCCESS(NtStatus)){
#if DBG
DbgPrint("FindNia35Adapter: Unable to allocate adapter info\n");
#endif
break;
}
// Initialize the resources.
NetDetectInitializeResource(*pDetectedAdapter,
0,
MndResourcePort,
IoBaseAddress,
0x10);
NetDetectInitializeResource(*pDetectedAdapter,
0,
MndResourcePort,
IoBaseAddress + 0x1000,
0x10);
NetDetectInitializeResource(*pDetectedAdapter,
0,
MndResourcePort,
((IoBaseAddress >> 1) & 0xf000) + 0x0888, // NIC_RACK_NIC
0x2);
NetDetectInitializeResource(*pDetectedAdapter,
0,
MndResourcePort,
((IoBaseAddress >> 1) & 0xf000) + 0x088a, // NIC_RESET
0x2);
if(Interrupt != 0){
NetDetectInitializeResource(*pDetectedAdapter,
1,
MndResourceInterrupt,
Interrupt,
MND_RESOURCE_INTERRUPT_LATCHED);
}
NtStatus = STATUS_SUCCESS;
}while(FALSE);
return (NtStatus);
}
NTSTATUS
WINAPI
FindAdapterHandler(
IN OUT PMND_ADAPTER_INFO *pDetectedAdapter,
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN PDET_ADAPTER_INFO pAdapterInfo,
IN PDET_CONTEXT pDetContext
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NTSTATUS NtStatus;
ULONG IoBaseAddress;
if(InterfaceType != Isa){
return(STATUS_INVALID_PARAMETER);
}
// Are we looking for the first adapter?
if (fDET_CONTEXT_FIND_FIRST == (pDetContext->Flags & fDET_CONTEXT_FIND_FIRST)){
// Initialize the context information so that we start detecting
// at the initialize port range.
pDetContext->ISA.IoBaseAddress = 0x0770;
}
for (IoBaseAddress = pDetContext->ISA.IoBaseAddress;
IoBaseAddress <= 0x6770;
IoBaseAddress = Nia35NextIoAddress(IoBaseAddress)){
// Look for the ee16 adapter at the current port.
NtStatus = FindNia35Adapter(pDetectedAdapter,
InterfaceType,
BusNumber,
IoBaseAddress,
pAdapterInfo->PnPId);
if (NT_SUCCESS(NtStatus)){
// We found an adapter. Save the next IO address to check.
pDetContext->ISA.IoBaseAddress = Nia35NextIoAddress(IoBaseAddress);
break;
}
}
if (0xffff == IoBaseAddress){
NtStatus = STATUS_NO_MORE_ENTRIES;
}
return(NtStatus);
}