Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1910 lines
47 KiB

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
card.c
Abstract:
This is the mac ndis file for the Ungermann Bass Ethernet Controller.
This driver conforms to the NDIS 3.0 interface.
It is here that the NDIS3.0 functions defined in the MAC characteristic
table have been deinfed.
Author:
Sanjeev Katariya (sanjeevk) 03-05-92
Environment:
Kernel Mode Operating Systems : NT and other lesser OS's
Revision History:
Brian Lieuallen BrianLie 07/21/92
Made it work.
Brian Lieuallen BrianLie 12/15/93
Made it a mini-port
--*/
// INCLUDES
#include <ndis.h>
#include <efilter.h>
#include "niudata.h"
#include "debug.h"
#include "ubhard.h"
#include "ubsoft.h"
#include "ubnei.h"
#include "map.h"
// INCLUDES:END
UCHAR
CardMapRegisterValue(
IN PUBNEI_ADAPTER pAdapter,
IN ULONG SegAddress
);
BOOLEAN
Reset_GPCNIU(
OUT PUBNEI_ADAPTER pNewAdapt
);
BOOLEAN
Run_NIU_Diagnostics(
OUT PUBNEI_ADAPTER pNewAdapt
);
BOOLEAN
Halt_NIU(
OUT PUBNEI_ADAPTER pNewAdapt
);
BOOLEAN
Reset_OtherNIU(
OUT PUBNEI_ADAPTER pNewAdapt
);
BOOLEAN
ReadStationAddress(
OUT PUBNEI_ADAPTER pNewAdapt
);
BOOLEAN
CardTestMemory(
IN PUBNEI_ADAPTER pAdapter
);
BOOLEAN
CardCodeDataInit(
OUT PUBNEI_ADAPTER pAdapter
);
USHORT
CardSetMulticast(
PUBNEI_ADAPTER pAdapter,
PUCHAR MulticastList,
UINT ListSize
);
#ifdef ALLOC_PRAGMA
#pragma NDIS_INIT_FUNCTION(Reset_GPCNIU)
#pragma NDIS_INIT_FUNCTION(Run_NIU_Diagnostics)
#pragma NDIS_INIT_FUNCTION(Halt_NIU)
#pragma NDIS_INIT_FUNCTION(Reset_OtherNIU)
#pragma NDIS_INIT_FUNCTION(ReadStationAddress)
#pragma NDIS_INIT_FUNCTION(CardTestMemory)
#pragma NDIS_INIT_FUNCTION(CardCodeDataInit)
#pragma NDIS_INIT_FUNCTION(CardTest)
#pragma NDIS_INIT_FUNCTION(CardSetup)
#pragma NDIS_INIT_FUNCTION(CardStartNIU)
#pragma NDIS_INIT_FUNCTION(CardMapRegisterValue)
#endif
// GLOBAL VARIABLES
extern UCHAR GPNIU_IRQ_Selections[];
extern NIUDETAILS NiuDetails[6];
BOOLEAN
CardSetup (
OUT PUBNEI_ADAPTER pAdapter
)
/*++
Routine Description:
Set up the receive buffers and the various descriptors
Set the various statistics and fields assocated with the
receive buffers
Set up the Transmit buffers and the various descriptors
Set the various statistics and fields assocated with the
transmit buffers
Arguments:
Return Value:
--*/
{
ULONG tempLong;
/*
This set of code was used to make sure that the offsets to these structure
elements match the offsets that the assembler created for the data segments
of the down load code
PLOWNIUDATA pTest;
PHIGHNIUDATA pTest2;
pTest->sst.SST_MediaSpecificStatisticsPtr=0l;
pTest->mst.MST_TableSize=0;
pTest->dummy_RDB[0]=(UCHAR)0;
pTest->dummy_buffer[0]=(UCHAR)0;
pTest->Start_Here[0]=(UCHAR)0;
pTest2->System_State=0;
pTest2->Next_Unused_Location_in_1st_32K=0;
pTest2->Stack_Area[0]=0;
pTest2->NOP_command[0]=0;
pTest2->Configure_with_Loopback[0]=0;
pTest2->Dynamically_Allocated_Area[0]=0;
*/
pAdapter->pDataWindow=(PHIGHNIUDATA)((PUCHAR)pAdapter->pCardRam+(0x8000 & pAdapter->WindowMask));
IF_INIT_LOUD (DbgPrint("Card Data segment is at 0x%lx\n",pAdapter->pDataWindow);)
pAdapter->pNIU_Control=(PNIU_CONTROL_AREA)((PUCHAR)pAdapter->pCardRam+(0xff00 & pAdapter->WindowMask));
IF_INIT_LOUD (DbgPrint("Card Control area is at 0x%lx\n",pAdapter->pNIU_Control);)
//
// Setting Initialization Window Base
//
switch ( NiuDetails[pAdapter->AdapterType].AdapterClass ) {
case CHAMELEON:
//
// Set the NIU base address of the shared memory window.
//
// NIUps memory window can be any where in first 16 Meg
//
if ( pAdapter->AdapterType == NIUPS) {
IF_INIT_LOUD( DbgPrint("Set Window base bits 23-20 to %02x\n",(UCHAR)((pAdapter->MemBaseAddr & 0x00F00000) >> 20));)
NdisRawWritePortUchar(
(PUCHAR)pAdapter->SetWindowBasePort+1,
(UCHAR)((pAdapter->MemBaseAddr & 0x00F00000) >> 20)
);
}
//
// Set the low bits for both NIUps and EOTP
//
IF_INIT_LOUD( DbgPrint("Set Window base bits 19-14 to %02x\n",(UCHAR)((pAdapter->MemBaseAddr & 0x000fc000) >> 12));)
NdisRawWritePortUchar(
pAdapter->SetWindowBasePort,
(UCHAR)((pAdapter->MemBaseAddr & 0x000Fc000) >> 12)
);
//
// Enable the GPCNIU adapter.
//
if ( pAdapter->AdapterType == GPCNIU ) {
IF_INIT_LOUD( DbgPrint("Enable the EOTP adapter\n");)
NdisRawWritePortUchar(
pAdapter->InterruptStatusPort,
0x01
);
}
break;
default :
break;
}
//
// Set up the following 4 windows in the NIU Window area
//
// The Initialization
// The ReceiveData
// The TransmitData
// The Code Window
//
//
// InitWindow Page Map
//
tempLong=((((ULONG)NiuDetails[pAdapter->AdapterType].HighestRamSegment<<4)+0x10000)-pAdapter->WindowSize)>>4;
pAdapter->InitWindow_Page = CardMapRegisterValue(pAdapter,tempLong);
IF_INIT_LOUD (DbgPrint("Init page is 0x%x\n",pAdapter->InitWindow_Page );)
//
// ReceiveWindow Page
//
pAdapter->ReceiveDataWindow_Page =
CardMapRegisterValue(pAdapter,
NiuDetails[pAdapter->AdapterType].PrimaryDataSegment);
IF_INIT_LOUD (DbgPrint("Rec page is 0x%x\n",pAdapter->ReceiveDataWindow_Page );)
//
// DataWindow Page
//
pAdapter->DataWindow_Page =
CardMapRegisterValue(pAdapter,
NiuDetails[pAdapter->AdapterType].PrimaryDataSegment+0x800);
IF_INIT_LOUD (DbgPrint("data page is 0x%x\n",pAdapter->DataWindow_Page);)
//
// CodeWindow Page
//
pAdapter->CodeWindow_Page =
CardMapRegisterValue(pAdapter,
NiuDetails[pAdapter->AdapterType].OperationalCodeSegment);
IF_INIT_LOUD (DbgPrint("code page is 0x%x\n",pAdapter->CodeWindow_Page);)
//
// Final Map of the window pages on the 512K Adapter RAM
//
// (CONTROL REGISTER 1 WINDOW MAP)
// 00 08 10 18 20 28 30 38 40 48 50 58 60 68 70 78 80
// ---------------------------------------------------------------
// | | | | | | | | | | | | | |
// | | | | |CW |CW |RDW |DW | | | | |IW |
// | | | | | | | | | | | | | |
// ---------------------------------------------------------------
// 0 32 64 96 128 160 192 224 256 288 320 352 384 416 448 480 512
// (K)
return TRUE;
}
UCHAR
CardMapRegisterValue(
IN PUBNEI_ADAPTER pAdapter,
IN ULONG SegAddress
)
{
UCHAR tempByte;
tempByte=(UCHAR)((SegAddress<<4)/NiuDetails[pAdapter->AdapterType].MinimumWindowSize);
return NiuDetails[pAdapter->AdapterType].MappingTable[tempByte] & ~INTERRUPT_ENABLED;
}
BOOLEAN
CardTest (
OUT PUBNEI_ADAPTER pAdapter
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
BOOLEAN bResult;
//
// Set up the Initialization area on the RAM
//
SET_INITWINDOW(pAdapter,0);
bResult=FALSE;
if (pAdapter->AdapterType==GPCNIU) {
if (!(bResult=Reset_GPCNIU(pAdapter))) {
IF_INIT_LOUD (DbgPrint("CardTest(): Reset_GPCNIU() failed trying one more time\n");)
if (!(bResult=Reset_GPCNIU(pAdapter))) {
IF_INIT_LOUD (DbgPrint("CardTest(): Reset_GPCNIU() failed again! all over\n");)
return FALSE;
}
}
}
if ( !bResult ||( pAdapter->AdapterType != GPCNIU )) {
Reset_OtherNIU(pAdapter);
}
//
// If this is an EOTP see if the user wants to run diagnostics
//
if ((pAdapter->AdapterType!=GPCNIU) ||
(pAdapter->Diagnostics)) {
if (!Run_NIU_Diagnostics(pAdapter))
return FALSE;
}
if (!Halt_NIU(pAdapter))
return FALSE;
if (!ReadStationAddress(pAdapter))
return FALSE;
if (!CardTestMemory(pAdapter))
return FALSE;
return TRUE;
}
BOOLEAN
Reset_GPCNIU(
OUT PUBNEI_ADAPTER pAdapter
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PNIU_CONTROL_AREA volatile pNIU_Control = pAdapter->pNIU_Control;
ULONG i;
USHORT TmpUshort;
//
// Reset the NIU, to make it start running the PROM
// code. First hold the RESET line high
//
NdisRawWritePortUchar(
pAdapter->MapPort,
RESET_SET
);
//
// Wait for 1 millisecond
//
NdisStallExecution( (UINT)2000 );
//
// Take RESET down
// Wait a while again.
NdisRawWritePortUchar(
pAdapter->MapPort,
RESET_CLEAR
);
NdisStallExecution( (UINT)2000 );
//
// GPCNIUs require handshaking with the PROM immediately
// after a reset. This is because the SIF chip *always*
// enables the RIPL window regardless of what the dip
// switches on the board are set to. To get around this,
// the RAMs are *disabled* completely until we do the
// following handshake to inform the PROM that we have
// now disabled the RIPL window from the PC's side.
//
//
// 1: Select "Interrupt B"
// We're about to write 10000001b to the GPCNIU's
// "Window Size, Interrupt Selection, and feature
// enables" register. This selects "IRQB", specifies
// 32K window size, disables the IPL, IBM 3278/9, and
// IRMA features, and leaves the adapter enabled.
//
NdisRawWritePortUchar(
pAdapter->InterruptStatusPort,
0x81
);
//
// 2: Enable interrupts
//
//
// Set the cards window and our shadow register to match
// so the debug code won't break
//
NdisRawWritePortUchar(
pAdapter->MapPort,
pAdapter->InitWindow_Page
);
pAdapter->MapRegSync.CurrentMapRegister=pAdapter->InitWindow_Page;
SET_INITWINDOW(pAdapter,INTERRUPT_ENABLED);
//
// 3: Wait for the PROM to ack with HWresult2 = 0xAA
// We wait up to 1 second. Trials seem to show that
// the actual time required is between 650 and 700
// milliseconds.
//
// Wait for the transmission to complete, for about a second.
//
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&TmpUshort, &(pNIU_Control->us_HWresult2));
for (i=0;(i<1500) && (TmpUshort != (USHORT)0xAA);i++) {
NdisStallExecution( 1000 );
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&TmpUshort, &(pNIU_Control->us_HWresult2));
}
if (TmpUshort != (USHORT)0xAA) {
IF_INIT_LOUD (DbgPrint("Reset_GPCNIU: Timer expired waiting for reset\n");)
goto fail00;
}
//
// 4: Give the PROM a Halt Command.
//
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pNIU_Control->us_HWcommand), 0x1);
//
// 5: Wait for the PROM to ack with HWresult2 = 0x55
//
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&TmpUshort, &(pNIU_Control->us_HWresult2));
for (i=0;(i<500) && (TmpUshort != (USHORT)0x55);i++) {
NdisStallExecution( 1000 );
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&TmpUshort, &(pNIU_Control->us_HWresult2));
}
if (TmpUshort != (USHORT)0x55) {
IF_INIT_LOUD (DbgPrint("Reset_GPCNIU: Timer expired waiting for halt\n");)
goto fail00;
}
//
// 6: Clear the interrupt (that never really happened)
//
SET_INITWINDOW(pAdapter,INTERRUPT_DISABLED);
//
// 7: Select "Interrupt A"
//
NdisRawWritePortUchar(
pAdapter->InterruptStatusPort,
0x01
);
return TRUE;
fail00:
// clear the interrupt
SET_INITWINDOW(pAdapter,INTERRUPT_DISABLED);
// enable IRQA
NdisRawWritePortUchar(
pAdapter->InterruptStatusPort,
0x01
);
return FALSE;
}
BOOLEAN
Reset_OtherNIU(
OUT PUBNEI_ADAPTER pAdapter
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PNIU_CONTROL_AREA volatile pNIU_Control = pAdapter->pNIU_Control;
PUSHORT POD_Status_Address;
POD_Status_Address = (PUSHORT)((PUCHAR)pAdapter->pCardRam+
(NiuDetails[pAdapter->AdapterType].POD_Status_Address & pAdapter->WindowMask));
SET_INITWINDOW(pAdapter,0);
//
// Zero out a couple of locations in which the
// PROM code will report the results of its
// initialization and diagnostics.
//
UBNEI_MOVE_USHORT_TO_SHARED_RAM(POD_Status_Address, 0x0);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pNIU_Control->us_HWcommand), 0x0);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pNIU_Control->us_HWresult1), 0x0);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pNIU_Control->us_HWresult2), 0x0);
//
// We reset the NIU, to make it start running the
// PROM code. First we hold the RESET line high
// (or whatever it is ) for a while.
//
SET_INITWINDOW(pAdapter,RESET_SET);
NdisStallExecution( (UINT)1000 );
//
// Take RESET down (or whatever it is), and wait
// a while again.
//
SET_INITWINDOW(pAdapter,RESET_CLEAR);
NdisStallExecution( (UINT)500000 );
return TRUE;
}
BOOLEAN
Run_NIU_Diagnostics(
OUT PUBNEI_ADAPTER pAdapter
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PNIU_CONTROL_AREA volatile pNIU_Control = pAdapter->pNIU_Control;
PUCHAR POD_status_address;
UCHAR PODStatus;
ULONG i;
ULONG ulPassesNeeded;
ULONG ulDiagnosticPass;
UCHAR TmpUchar;
USHORT HWResult1;
POD_status_address = (PUCHAR)pAdapter->pCardRam+
(NiuDetails[pAdapter->AdapterType].POD_Status_Address & pAdapter->WindowMask);
//
// Some NIUs will run all their diagnostics as a result of the reset
// we just did. Others do some initialization but don't run their full
// set of tests. For these latter, we first wait for them to respond
// to the reset then we tell them to run their diagnostics, and wait
// again for them to report the results.
//
//
// We re-map, and wait for the PROM code to finish and report its result.
// We wait for up to 20 seconds. The way the PROM diagnostic test progress
// and result is reported is different for different kinds of NIUs.
// The test codes are all less than 80h (i.e., no code has the high order
// bit set). If a test fails, either
// (a) the test is repeated indefinitely or
// (b) a failure code
// is stored into 3FEF8h, replacing the test code, and diagnostics are
// terminated.
// In case (a), we'll know that the diagnostics failed because
// our timer will expire. Failure codes all have the 80h bit set, so we
// can detect case (b) by checking the 80h bit in location 3FEF8h. If all
// the diagnostic tests run successfully, the success code, AAh, will be
// stored in 3FEF8h and also in the "HWresult1" byte (at 3FF94). For NIUs
// other than the Atlanta cards, the bytes in which the diagnostic status
// and result codes are reported are at different addresses. They are in
// different segments, and the "FEF8" one is at different offsets.
IF_INIT_LOUD (DbgPrint("Begin adapter diag\n");)
ulPassesNeeded=1;
if ( NiuDetails[pAdapter->AdapterType].AdapterFlags & TWO_PASS_DIAGNOSTICS ) {
ulPassesNeeded++;
}
ulDiagnosticPass=0;
SET_INITWINDOW(pAdapter,0);
for (i=0; i < 20000; i++) {
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&PODStatus, (PUCHAR)(POD_status_address));
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&HWResult1, &(pNIU_Control->us_HWresult1));
if ( (PODStatus & 0x80) &&
( PODStatus != 0xff ) &&
( PODStatus == (UCHAR)HWResult1 )) {
// Final check
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&TmpUchar, (PUCHAR)(POD_status_address));
if ( PODStatus == TmpUchar ) {
if (PODStatus==0xaa) {
ulDiagnosticPass++;
IF_INIT_LOUD ( DbgPrint("Run_NIU_Diag: Adapter competed first pass pod=%02x HwR=%02x\n",PODStatus,HWResult1);)
if (ulDiagnosticPass==ulPassesNeeded) {
IF_INIT_LOUD ( DbgPrint("Run_NIU_Diag: Adapter competed second pass\n");)
return TRUE;
} else {
//
// Requires second set of diagnostics to be run
//
//
// Give the PROM code an "INTERRUPT" command
//
UBNEI_MOVE_UCHAR_TO_SHARED_RAM((PUCHAR)(POD_status_address), 0x0);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pNIU_Control->us_HWcommand), 14);
//
// Wait for it to respond.
//
NdisStallExecution ( (UINT)250000 );
//
// Issue the DIAG command to the prom
//
UBNEI_MOVE_UCHAR_TO_SHARED_RAM((PUCHAR)(POD_status_address), 0xFF);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pNIU_Control->us_HWresult1), 0);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pNIU_Control->us_HWcommand), 3);
}
} else {
IF_INIT_LOUD ( DbgPrint("Run_NIU_DIAG: Adapter returned fail code\n");)
return FALSE;
}
}
} else {
//
// Not a complete status, wait some more
//
NdisStallExecution( 1000 );
}
}
IF_INIT_LOUD ( DbgPrint("Run_NIU_Diag: Adapter failed to complete Diag\n");)
return FALSE;
}
BOOLEAN
Halt_NIU(
OUT PUBNEI_ADAPTER pAdapter
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PNIU_CONTROL_AREA volatile pNIU_Control = pAdapter->pNIU_Control;
ULONG i, LoopLimit;
USHORT TmpUshort;
switch ( NiuDetails[pAdapter->AdapterType].AdapterClass ) {
case CHAMELEON:
SET_INITWINDOW(pAdapter,0);
LoopLimit = 5000;
//
// issue attention command
//
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pNIU_Control->us_HWcommand), 13);
break;
case ATLANTA:
SET_INITWINDOW(pAdapter,0);
LoopLimit = 500;
UBNEI_MOVE_USHORT_TO_SHARED_RAM(
(PUSHORT)((PUCHAR)pAdapter->pCardRam+(0xfefa & pAdapter->WindowMask)),
0x5A5A);
break;
default :
break;
}
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&TmpUshort, &(pNIU_Control->us_HWcommand));
for (i=0;(i<LoopLimit) && ( TmpUshort != 1 );i++) {
NdisStallExecution( 1000 );
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&TmpUshort, &(pNIU_Control->us_HWcommand));
}
if ( TmpUshort != 1 ) {
//
// NIU Failed to halt
//
IF_INIT_LOUD (DbgPrint("Halt_NIU: The Adapter Failed to halt\n");)
return FALSE;
} else {
IF_INIT_LOUD (DbgPrint("Halt_NIU: The Adapter halted properly\n");)
return TRUE;
}
}
BOOLEAN
ReadStationAddress(
OUT PUBNEI_ADAPTER pAdapter
)
/*++
Routine Description:
Read the station address from the NIU control data at the top of
the cards RAM
Arguments:
Return Value:
--*/
{
PNIU_CONTROL_AREA pNIU_Control = pAdapter->pNIU_Control;
SET_INITWINDOW(pAdapter,0);
// while we are looking at the init window, we will get the station address
IF_INIT_LOUD( DbgPrint("The Station address is ");)
UBNEI_MOVE_SHARED_RAM_TO_MEM(pAdapter->PermanentAddress,
(PUCHAR)pNIU_Control->uc_node_id,
ETH_LENGTH_OF_ADDRESS
);
#if DBG
{
UINT i;
for (i=0;i<ETH_LENGTH_OF_ADDRESS;i++) {
IF_INIT_LOUD( DbgPrint(" %02X",pAdapter->PermanentAddress[i]); )
}
}
#endif
IF_INIT_LOUD( DbgPrint("\n");)
//
// One time the card initialized with the wrong station address
// so as a little extra check we will make sure the card has a UB OEM #
//
if (!(pAdapter->PermanentAddress[0]==0x00 &&
pAdapter->PermanentAddress[1]==0xdd &&
(pAdapter->PermanentAddress[2]==0x01 ||
pAdapter->PermanentAddress[2]==0x00))) {
IF_INIT_LOUD( DbgPrint("The Station address does not match a UB address\n");)
return FALSE;
}
return TRUE;
}
BOOLEAN
CardTestMemory(
IN PUBNEI_ADAPTER pAdapter
)
/*++
Routine Description:
Tests the card memory to try to see if there are any mapping
conflicts with the map window. Basically it makes sure the
is ram for the whole map window
Arguments:
Return Value:
--*/
{
PULONG p;
UINT i;
BOOLEAN Result=TRUE;
ULONG TmpUlong;
IF_INIT_LOUD(DbgPrint("UBNEI: CardTestMemory\n");)
//
// first switch to the code window and write our pattern
//
SET_CODEWINDOW(pAdapter,0);
p=(PULONG)pAdapter->pCardRam;
for (i=0;i<(pAdapter->WindowSize/4);i++) {
UBNEI_MOVE_DWORD_TO_SHARED_RAM(p+i, 0x0F55CCF0);
}
//
// switch to the data window and zero it out.
//
SET_RECDWINDOW(pAdapter,0);
for (i=0;i<(pAdapter->WindowSize/4);i++) {
UBNEI_MOVE_DWORD_TO_SHARED_RAM(p+i, 0x0);
}
//
// Back to the code window and make sure the pattern is still there
//
SET_CODEWINDOW(pAdapter,0);
for (i=0;i<(pAdapter->WindowSize/4);i++) {
UBNEI_MOVE_SHARED_RAM_TO_DWORD(&TmpUlong, p+i);
if (TmpUlong != 0x0F55CCF0) {
IF_INIT_LOUD(DbgPrint("UBNEI: CardTestMemory() Failed @ %0x Found %0lx\n",i,*(p+i));)
Result = FALSE;
break;
}
}
return Result;
}
BOOLEAN
CardCodeDataInit(
OUT PUBNEI_ADAPTER pAdapter
)
/*++
Routine Description:
This routine initializes various things in the NIU codes
data segment and actaully copies the NIU code to the card
Arguments:
Return Value:
--*/
{
PLOWNIUDATA pRcvDWindow = (PLOWNIUDATA) pAdapter->pCardRam;
PHIGHNIUDATA pDataWindow = (PHIGHNIUDATA) pAdapter->pDataWindow;
PNIU_CONTROL_AREA pNIU_Control = pAdapter->pNIU_Control;
UINT AdapterType = pAdapter->AdapterType;
UCHAR uc_Byte;
USHORT TmpUshort;
NDIS_HANDLE FileHandle;
UINT FileLength;
NDIS_STATUS Status;
PVOID ImageBuffer;
NDIS_STRING FileName=NDIS_STRING_CONST("ubnei.bin");
//
// Set the RcvDataWindow Page in place.
//
SET_RECDWINDOW(pAdapter,INTERRUPT_DISABLED);
// Zero out the first "page" of the lower 32k of the NIU code's main
// data segment. if there's room).
//
NdisZeroMappedMemory ( pAdapter->pCardRam, pAdapter->WindowSize);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pRcvDWindow->mst.MST_TableSize), sizeof(MediaStatistics));
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pRcvDWindow->mst.MST_StructureVersionLevel), 1);
UBNEI_MOVE_DWORD_TO_SHARED_RAM(&(pRcvDWindow->mst.MST_LateCollisions), 0xFFFFFFFF);
UBNEI_MOVE_DWORD_TO_SHARED_RAM(&(pRcvDWindow->mst.MST_JabberErrors), 0xFFFFFFFF);
UBNEI_MOVE_DWORD_TO_SHARED_RAM(&(pRcvDWindow->mst.MST_CarrierSenseLostDuringTransmission), 0xFFFFFFFF);
UBNEI_MOVE_DWORD_TO_SHARED_RAM(&(pRcvDWindow->sst.SST_FramesSmallerThanMinimumSize), 0xFFFFFFFF);
UBNEI_MOVE_DWORD_TO_SHARED_RAM(&(pRcvDWindow->sst.SST_MediaSpecificStatisticsPtr), 0);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pRcvDWindow->InterruptDisabled), 0xFF);
//
// Now switch to the DataWindow Page
//
SET_DATAWINDOW(pAdapter,INTERRUPT_DISABLED);
//
// Zero out up til end of Data Window
//
NdisZeroMappedMemory ( pAdapter->pCardRam, sizeof(HIGHNIUDATA));
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->NIU_AdapterType), AdapterType);
if ( NiuDetails[AdapterType].AdapterFlags & ASYNCHRONOUS_READY ) {
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&TmpUshort, &(pDataWindow->System_Modes));
TmpUshort |= INTERNAL_READY_SYNC;
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->System_Modes), TmpUshort);
}
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->LED_Off_12Volts_DoParityCheck),
NiuDetails[AdapterType].LED_Off_12Volts_DoParityCheck
);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->LED_On_12Volts_DoParityCheck),
NiuDetails[AdapterType].LED_On_12Volts_DoParityCheck
);
uc_Byte=0;
if (AdapterType == GPCNIU)
uc_Byte=GPNIU_IRQ_Selections[pAdapter->IrqLevel];
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->LED_Off_and_IRQ_Select),
uc_Byte
);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->LED_On_and_IRQ_Select),
uc_Byte | 1
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->HostWindowMask),
(USHORT)(pAdapter->WindowMask)
);
UBNEI_MOVE_DWORD_TO_SHARED_RAM(&(pDataWindow->HostWindowSize),
(ULONG)(pAdapter->WindowSize)
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->_82586_CA_Address),
(USHORT)(NiuDetails[AdapterType]._82586_CA_Port)
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->_82586_RESET_Address),
(USHORT)(NiuDetails[AdapterType]._82586_RESET_Port)
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->HostInterruptPort),
(USHORT)(NiuDetails[AdapterType].HostInterruptPort)
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->AdapterControlPort),
(USHORT)(NiuDetails[AdapterType].AdapterControlPort)
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->IRQ_Select_and_LED_Port),
(USHORT)(NiuDetails[AdapterType].IRQ_Select_And_LED_Port)
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->DeadmanTimerPort),
(USHORT)(NiuDetails[AdapterType].DeadManTimerPort)
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->Xmt_Timeout), 1000);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->Diagnostic_Timeout), 2000);
// UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->Xmt_Buffer_Start), 80);
UBNEI_MOVE_USHORT_TO_SHARED_RAM((&pDataWindow->Default_Address_Base.u.SegOff.Segment),
(NiuDetails[AdapterType].SCPSegment)
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->Default_Address_Base.u.SegOff.Offset),
(0xfff0)
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM((&pDataWindow->SCP_Base.u.SegOff.Offset),
0xfff6
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM((&pDataWindow->SCP_Base.u.SegOff.Segment),
(NiuDetails[AdapterType].SCPSegment)
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->Max_Multicast_Addresses),
pAdapter->MaxMultiCastTableSize
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->Max_General_Requests),
pAdapter->MaxRequests
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->Rcv_Buffer_Size),
pAdapter->ReceiveBufSize
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->Code_and_Xmt_Segment),
NiuDetails[AdapterType].OperationalCodeSegment
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->Xmt_Buffer_Size), 1514);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->Max_Receive_Size), 1514);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->Min_Receive_Size), 60);
//
// user definable things from dos driver, using the defaults
//
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->Rcv_Timeout), 10000);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->user_FIFO_Threshold), 15);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->user_PreambleLength), 2);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->user_CRC_Polynomial), 0);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->user_InterframeSpacing), 96);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->user_SlotTime), 512);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->user_MaxRetries), 15);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->Max_Collisions), 16);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->user_LinearPriority), 0);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->user_ACR_Priority), 0);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->user_BackoffMethod), 0);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->user_CRS_Filter), 0);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->user_CDT_Filter), 0);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->user_Min_Frame_Length), 60);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->MinimumHostWindowSize),
NiuDetails[AdapterType].MinimumWindowSize
);
NdisMoveToMappedMemory((PUCHAR)pDataWindow->Map_Table,NiuDetails[AdapterType].MappingTable,32);
NdisOpenFile(
&Status,
&FileHandle,
&FileLength,
&FileName,
HighestAcceptableMax
);
if (Status==NDIS_STATUS_SUCCESS) {
NdisMapFile(
&Status,
&ImageBuffer,
FileHandle
);
if (Status==NDIS_STATUS_SUCCESS) {
SET_CODEWINDOW(pAdapter,0);
NdisMoveToMappedMemory(pAdapter->pCardRam,ImageBuffer,FileLength);
SET_DATAWINDOW(pAdapter,INTERRUPT_DISABLED);
NdisUnmapFile(FileHandle);
NdisCloseFile(FileHandle);
return TRUE;
} else {
NdisCloseFile(FileHandle);
return FALSE;
}
}
return FALSE;
}
BOOLEAN
CardStartNIU(
OUT PUBNEI_ADAPTER pAdapter
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PLOWNIUDATA pRcvDWindow = (PLOWNIUDATA) pAdapter->pCardRam;
PHIGHNIUDATA pDataWindow = (PHIGHNIUDATA) pAdapter->pDataWindow;
PNIU_CONTROL_AREA volatile pNIU_Control = pAdapter->pNIU_Control;
ULONG i;
BOOLEAN ReturnStatus= TRUE;
USHORT TmpUshort;
USHORT NumberOfXmtBuffers;
USHORT SizeOfXmtBuffers;
USHORT NumberOfRcvBuffers;
USHORT SizeOfRcvBuffers;
//
// With interrupts disabled at the card set the flag
//
NdisMSynchronizeWithInterrupt(
&pAdapter->NdisInterrupt,
UbneiSetInitInterruptSync,
pAdapter
);
//
// Init NIU code and data
//
ReturnStatus=CardCodeDataInit(pAdapter);
if (!ReturnStatus) {
return FALSE;
}
SET_DATAWINDOW(pAdapter,INTERRUPT_DISABLED);
//
// This x86 assembly is copied to the data segment of the
// niu code. The segment portion of the far jump is fixed up
// with the correct segment. The PROM CS:IP in the top of
// the init code segment is set to point to the code in the
// data segment
//
// We wait for two things to happen before we decide the the card
// has success fully started. One the system state flag must indicated
// that the card has initialized and we have to receive and interrupt
// from the card. If we do not get an interrupt then the incorrect
// interrupt has been selected
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->Startup_Code[0]), 0x8C ); // mov ax,cs
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->Startup_Code[1]), 0xC8 );
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->Startup_Code[2]), 0x8E ); // mov ds,ax
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->Startup_Code[3]), 0xD8 );
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->Startup_Code[4]), 0x90 ); // nop
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->Startup_Code[5]), 0xEA ); // jmp far ptr
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->Startup_Code[6]), 0x00 );
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->Startup_Code[7]), 0x00 );
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pDataWindow->Startup_Code_CS_fixup),
(USHORT)NiuDetails[pAdapter->AdapterType].OperationalCodeSegment
);
pAdapter->uInterruptCount=0;
SET_INITWINDOW(pAdapter,0);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pNIU_Control->us_CS_value),
NiuDetails[pAdapter->AdapterType].PrimaryDataSegment
);
TmpUshort = (USHORT)(((PUCHAR)pDataWindow->Startup_Code)-(PUCHAR)pDataWindow)+0x8000;
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pNIU_Control->us_IP_value), TmpUshort);
IF_INIT_LOUD(DbgPrint("UBNEI: down load cs:ip %04x:%04x\n",NiuDetails[pAdapter->AdapterType].PrimaryDataSegment, TmpUshort);)
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pNIU_Control->us_HWcommand), 2);
SET_DATAWINDOW(pAdapter,INTERRUPT_ENABLED);
//
// Wait until the system state is initialized and the interrupt has come
// through
//
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&TmpUshort, &(pDataWindow->System_State));
for (i=0;(i<1000) && !((TmpUshort & INITIALIZED) && (pAdapter->uInterruptCount!=0)); i++) {
NdisStallExecution(1000);
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&TmpUshort, &(pDataWindow->System_State));
}
if (!((TmpUshort & INITIALIZED) )) {
IF_INIT_LOUD( DbgPrint("CardStartNIU: NIU code did not init sys=%04x\n",TmpUshort);)
ReturnStatus=FALSE;
} else {
IF_INIT_LOUD (DbgPrint("CardStartNIU: NIU code Initialized sys=%04x\n",TmpUshort);)
}
SET_DATAWINDOW(pAdapter,INTERRUPT_DISABLED);
NdisMSynchronizeWithInterrupt(
&pAdapter->NdisInterrupt,
UbneiSetNormalInterruptSync,
pAdapter
);
if (pAdapter->uInterruptCount==0) {
IF_INIT_LOUD( DbgPrint("Did not get interrupt from NIU code\n");)
NdisWriteErrorLogEntry(pAdapter->NdisAdapterHandle,
NDIS_ERROR_CODE_INTERRUPT_CONNECT,
1,
(ULONG)pAdapter->IrqLevel
);
ReturnStatus=FALSE;
}
if (ReturnStatus) {
//
// Calulate some statistics from info filled in by the NIU code
//
SET_DATAWINDOW(pAdapter,INTERRUPT_ENABLED);
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&NumberOfXmtBuffers, &pDataWindow->Number_of_Xmt_Buffers);
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&SizeOfXmtBuffers, &pDataWindow->Xmt_Buffer_Size);
pAdapter->TransmitBufferSpace=NumberOfXmtBuffers * SizeOfXmtBuffers;
IF_INIT_LOUD(DbgPrint("TransmitBufferSpace %d\n",pAdapter->TransmitBufferSpace);)
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&NumberOfRcvBuffers, &pDataWindow->Number_of_Rcv_Buffers);
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&SizeOfRcvBuffers, &pDataWindow->Rcv_Buffer_Size);
pAdapter->ReceiveBufferSpace=NumberOfRcvBuffers * SizeOfRcvBuffers;
IF_INIT_LOUD(DbgPrint("ReceiveBufferSpace %d\n",pAdapter->ReceiveBufferSpace);)
pAdapter->TransmitBlockSize=SizeOfXmtBuffers;
pAdapter->ReceiveBlockSize=SizeOfRcvBuffers;
}
SET_RECDWINDOW(pAdapter,INTERRUPT_ENABLED);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pRcvDWindow->InterruptDisabled),0x00);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pRcvDWindow->InterruptActive),0x00);
return ReturnStatus;
}
BOOLEAN
NIU_General_Request3(
IN NIU_GEN_REQ_DPC pDPCCallback,
IN PVOID pContext,
IN USHORT RequestCode,
IN USHORT param1,
IN PUCHAR param2
)
/*++
Routine Description:
This routine adds a general request to a general request queue
for later processing. During the interrupt DPC the request will actually
be sent to the card for processing. Also during the interrupt DPC
the requests that the card has completed will indicated.
NOTE: This code assumes that the spin lock is held
Arguments:
Return Value:
--*/
{
PUBNEI_ADAPTER pAdapt = pContext;
PLOWNIUDATA pRcvDWindow = (PLOWNIUDATA) pAdapt->pCardRam;
PHIGHNIUDATA pDataWindow = (PHIGHNIUDATA) pAdapt->pDataWindow;
USHORT RequestID,i;
PNIUREQUEST pRequestBlock;
IF_REQ_LOUD (DbgPrint("NIU_General_Request cmd=%d\n",RequestCode);)
IF_LOG('3');
IF_LOG((UCHAR)(RequestCode+'0'));
if (pAdapt->NIU_Requests_Pending >= pAdapt->MaxRequests) {
IF_REQ_LOUD (DbgPrint("NIU_General_Request: Fail--Too many request pending\n");)
return FALSE;
}
RequestID=pAdapt->NIU_Request_Head;
pRequestBlock=&pAdapt->NiuRequest[RequestID];
pAdapt->NIU_Requests_Pending++;
pAdapt->NIU_Request_Head=(pAdapt->NIU_Request_Head+1)%pAdapt->MaxRequests;
pRequestBlock->pContext=(PVOID) pContext;
pRequestBlock->pDPCFunc=pDPCCallback;
pRequestBlock->AddressList=param2;
pRequestBlock->rrbe.RequestCode=RequestCode;
pRequestBlock->rrbe.RequestParam1=param1;
if (RequestCode==3 || RequestCode==9) {
//
// Set station address
//
for (i=0;i<6;i++) {
pRequestBlock->rrbe.RequestData[i]=((UCHAR*)param2)[i];
}
}
NIU_Send_Request_To_Card(pAdapt);
IF_LOG('3');
ASSERT_INTERRUPT_ENABLED(pAdapt);
return TRUE;
}
VOID
NIU_Send_Request_To_Card(
IN PUBNEI_ADAPTER pAdapt
)
/*++
Routine Description:
This routine is called by the interrupt handler DPC to see if any
if any general request have been placed on the queue. If there request
they are actaully sent to the NIU by manipulating the request ring
buffer.
NOTE: This is called with the lock held!!!
Arguments:
Return Value:
--*/
{
PLOWNIUDATA pRcvDWindow = (PLOWNIUDATA) pAdapt->pCardRam;
PHIGHNIUDATA pDataWindow = (PHIGHNIUDATA) pAdapt->pDataWindow;
PORB pORB;
PRRBE pRRBE;
UCHAR ucTemp,ucTemp2;
USHORT usTemp;
USHORT ORBOffset;
USHORT BufferBase;
UCHAR WritePtr;
UCHAR ElementSize;
USHORT RequestID,i;
PNIUREQUEST pRequestBlock;
IF_LOG('r');
while (pAdapt->NIU_Next_Request!=pAdapt->NIU_Request_Head) {
RequestID=pAdapt->NIU_Next_Request;
pRequestBlock=&pAdapt->NiuRequest[RequestID];
// Check to see if a multicast change is already pending
pAdapt->NIU_Next_Request=(pAdapt->NIU_Next_Request+1)%pAdapt->MaxRequests;
SET_DATAWINDOW_SYNC(pAdapt,INTERRUPT_ENABLED);
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&ORBOffset, &(pDataWindow->Request_RingBuffer));
pORB=(PORB)((PUCHAR) pAdapt->pCardRam+
(ORBOffset & pAdapt->WindowMask));
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&BufferBase, &(pORB->ORB_BufferBase));
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&WritePtr, &(pORB->ORB_WritePtr_Byte));
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&ElementSize, &(pORB->ORB_ElementSize));
pRRBE=(PRRBE)((PUCHAR)pAdapt->pCardRam+
(WritePtr*ElementSize+
(BufferBase & pAdapt->WindowMask)));
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&pRRBE->RequestCode,pRequestBlock->rrbe.RequestCode);
IF_REQ_LOUD (DbgPrint("NIU_Send_Request_To_Card cmd=%d\n",pRequestBlock->rrbe.RequestCode);)
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&pRRBE->RequestID, RequestID);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&pRRBE->RequestParam1, pRequestBlock->rrbe.RequestParam1);
if (pRequestBlock->rrbe.RequestCode==8) {
usTemp=CardSetMulticast(
pAdapt,
pRequestBlock->AddressList,
pRequestBlock->rrbe.RequestParam1
);
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&pRRBE->RequestParam1, usTemp);
}
if (pRequestBlock->rrbe.RequestCode==3 ||
pRequestBlock->rrbe.RequestCode==9) {
for (i=0;i<6;i++) {
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&pRRBE->RequestData[i], pRequestBlock->rrbe.RequestData[i]);
}
}
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&ucTemp,&pORB->ORB_WritePtr_Byte);
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&ucTemp2,&pORB->ORB_PtrLimit);
ucTemp++;
if (ucTemp>ucTemp2) {
ucTemp=0;
}
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&pORB->ORB_WritePtr_Byte,ucTemp);
SET_RECDWINDOW_SYNC(pAdapt,INTERRUPT_ENABLED);
}
SET_RECDWINDOW_SYNC(pAdapt,INTERRUPT_ENABLED);
return;
}
VOID
NIU_General_Req_Result_Hand(
IN PUBNEI_ADAPTER pAdapt
)
/*++
Routine Description:
This routine is called by the interrupt handler DPC to see if any
if any general request have completed. If they have then the
DPC will be called
NOTE: This is called with the lock held!!!
Arguments:
Return Value:
--*/
{
PHIGHNIUDATA pDataWindow = (PHIGHNIUDATA) pAdapt->pDataWindow;
PORB pORB;
PRESULTRBE pRRBE;
UCHAR ucTemp;
USHORT TmpUshort;
UCHAR TmpUchar1, TmpUchar2;
USHORT ResultID,RequestCode;
NDIS_STATUS status;
PNIUREQUEST pRequestBlock;
if (pAdapt->NIU_Request_Tail==pAdapt->NIU_Next_Request) {
//
// There aren't any request that have not been completed
//
IF_REQ_LOUD(DbgPrint("NIU_General_Req_Result_Hand: Nothing to Do\n");)
return;
}
//
// Now see if any of the requests have completed
//
IF_LOG('h');
SET_DATAWINDOW(pAdapt,INTERRUPT_ENABLED);
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&TmpUshort, &(pDataWindow->Result_RingBuffer));
pORB=(PORB)((PUCHAR) pAdapt->pCardRam + (TmpUshort & pAdapt->WindowMask));
while (1) {
SET_DATAWINDOW(pAdapt,INTERRUPT_ENABLED);
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&TmpUchar1, &(pORB->ORB_ReadPtr_Byte));
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&TmpUchar2, &(pORB->ORB_ElementSize));
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&TmpUshort, &(pORB->ORB_BufferBase));
pRRBE=(PRESULTRBE)((PUCHAR)pAdapt->pCardRam+
(TmpUchar1 * TmpUchar2 +
(TmpUshort & pAdapt->WindowMask)));
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&TmpUchar2, &(pORB->ORB_WritePtr_Byte));
IF_REQ_LOUD(DbgPrint("UBNEI: NIU_General_Req_Result_Hand: read=%d write=%d\n",TmpUchar1,TmpUchar2);)
if (TmpUchar1 == TmpUchar2) {
//
// There aren't any results in the ring buffer, so nothing to do
//
SET_RECDWINDOW(pAdapt,INTERRUPT_ENABLED);
IF_REQ_LOUD(DbgPrint("UBNEI: NIU_General_Req_Result_Hand: No results.\n");)
IF_LOG('H');
return;
}
//
// We found a result in the ring buffer
//
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&TmpUshort, &(pRRBE->ResultCode));
if (TmpUshort == 0) {
status=NDIS_STATUS_SUCCESS;
} else {
IF_REQ_LOUD(DbgPrint("NIU Gen Req failed\n");)
status=NDIS_STATUS_FAILURE;
}
//
// The ID is an index into our request array memory block
//
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&ResultID, &(pRRBE->ResultID));
#if DBG
if (ResultID != pAdapt->NIU_Request_Tail) {
IF_REQ_LOUD (DbgPrint("ResultID != Request_Tail\n");)
}
#endif
//
// We remove the result from the ring buffer
//
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&ucTemp, &(pORB->ORB_ReadPtr_Byte));
ucTemp++;
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&TmpUchar1, &(pORB->ORB_PtrLimit));
if (ucTemp > TmpUchar1)
ucTemp=0;
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pORB->ORB_ReadPtr_Byte), ucTemp);
SET_RECDWINDOW(pAdapt,INTERRUPT_ENABLED);
pRequestBlock=&pAdapt->NiuRequest[ResultID];
RequestCode=pRequestBlock->rrbe.RequestCode;
IF_REQ_LOUD (DbgPrint("NIU_General_Request_Result_Handler cmd=%d\n",RequestCode);)
(*pRequestBlock->pDPCFunc)(status,pRequestBlock->pContext);
pAdapt->NIU_Requests_Pending--;
pAdapt->NIU_Request_Tail=(pAdapt->NIU_Request_Tail+1)%pAdapt->MaxRequests;
IF_LOG('c');
}
IF_LOG('H');
return;
}
USHORT
CardSetMulticast(
PUBNEI_ADAPTER pAdapter,
PUCHAR MulticastList,
UINT ListSize
)
/*++
Routine Description:
This routine copies the multicast list into the card memory.
We copy the list to an area of memory just below the actual
multicast address list. When the card code actually processes
the request it will copy the list from the location up to the
actual location
Arguments:
Return Value:
--*/
{
PHIGHNIUDATA pDataWindow = (PHIGHNIUDATA) pAdapter->pDataWindow;
UINT NumberOfAddress,i;
UCHAR TmpUchar;
NdisMoveToMappedMemory(
(PUCHAR)&pDataWindow->Dynamically_Allocated_Area[pAdapter->MaxMultiCastTableSize],
MulticastList,
ListSize
);
NumberOfAddress= ListSize / 6;
// The 82586 seems to have a problem with 3 multicast addresses,
// so if the list is 3 long we copy the third one into the forth
// place in the list also
if (NumberOfAddress==3) {
IF_INIT_LOUD (DbgPrint("CardSetMulticast() padding list to 4 from 3\n");)
for (i=0;i<6;i++) {
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(
&TmpUchar,
&(pDataWindow->Dynamically_Allocated_Area[pAdapter->MaxMultiCastTableSize+2][i])
);
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(
&(pDataWindow->Dynamically_Allocated_Area[pAdapter->MaxMultiCastTableSize+3][i]),
TmpUchar
);
}
NumberOfAddress+=1;
}
return (NumberOfAddress*ETH_LENGTH_OF_ADDRESS);
}