www.pudn.com > 2410winceCE_l80t64.rar > cs8900a.c
//---------------------------------------------------------------------------
//
// Copyright (C) 1996-2003. Unpublished Work of Cirrus Logic Corp.
// All Rights Reserved.
//
// THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
// PROPRIETARY AND TRADE SECRET INFORMATION OF CRYSTAL SEMICONDUCTOR.
// ACCESS TO THIS WORK IS RESTRICTED TO (I) CRYSTAL SEMICONDUCTOR EMPLOYEES
// WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR
// ASSIGNMENTS AND (II) ENTITIES OTHER THAN CRYSTAL SEMICONDUCTOR WHO
// HAVE ENTERED INTO APPROPRIATE LICENSE AGREEMENTS. NO PART OF THIS
// WORK MAY BE USED, PRACTICED, PERFORMED, COPIED, DISTRIBUTED, REVISED,
// MODIFIED, TRANSLATED, ABRIDGED, CONDENSED, EXPANDED, COLLECTED,
// COMPILED,LINKED,RECAST, TRANSFORMED, ADAPTED IN ANY FORM OR BY ANY
// MEANS,MANUAL, MECHANICAL, CHEMICAL, ELECTRICAL, ELECTRONIC, OPTICAL,
// BIOLOGICAL, OR OTHERWISE WITHOUT THE PRIOR WRITTEN PERMISSION AND
// CONSENT OF CRYSTAL SEMICONDUCTOR . ANY USE OR EXPLOITATION OF THIS WORK
// WITHOUT THE PRIOR WRITTEN CONSENT OF CRYSTAL SEMICONDUCTOR COULD
// SUBJECT THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
//
//---------------------------------------------------------------------------
#include "cs8900a.h"
#include "cshrd.h"
#if __DBG
#include "version.h"
#endif
BYTE NDISVerMajor;
BYTE NDISVerMinor;
int EEPROM_NOT_FOUND;
//****************************************************************************
//
// Local type definitions and declarations
//
//****************************************************************************
typedef enum {
CrystalHardwareOk,
CrystalHardwareChecksum,
CrystalHardwareConfig
} CRYSTAL_HARDWARE_STATUS;
//****************************************************************************
//
// Static variables declrations
//
//****************************************************************************
// CRYSTAL_DRIVER CrystalDriver;
//
// This variable is used to control debug output.
//
#if DBG
INT CrystalDbg = 0;
#endif
//****************************************************************************
//
// Function prototypes for functions local to this file
//
//****************************************************************************
#pragma NDIS_INIT_FUNCTION(DriverEntry)
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This is the primary initialization routine for the driver.
It is simply responsible for the intializing the wrapper and registering
the MAC. It then calls a system and architecture specific routine that
will initialize and register each adapter.
Arguments:
DriverObject - Pointer to driver object created by the system.
Return Value:
The status of the operation.
--*/
{
//
// Receives the status of the NdisRegisterMac operation.
//
NDIS_STATUS Status;
NDIS_HANDLE CrystalWrapperHandle;
#define BUS_TYPE NdisInterfaceIsa
#define BUS_MASTER FALSE
NDIS_MINIPORT_CHARACTERISTICS CrystalChar;
NdisZeroMemory( &CrystalChar, sizeof(CrystalChar));
//
// Initialize the wrapper.
//
//DbgPrint("\nCs8900(): DriverEntry 0\n");
NdisMInitializeWrapper(
&CrystalWrapperHandle,
DriverObject,
RegistryPath,
NULL
);
//DbgPrint("\nCs8900(): DriverEntry 1\n");
// CrystalDriver.WrapperHandle = CrystalWrapperHandle;
//
// Initialize the miniport characteristics for the call to
// NdisMRegisterMiniport.
//
NDISVerMajor = CRYSTAL_NDIS_MAJOR_VERSION;
NDISVerMinor = CRYSTAL_NDIS_MINOR_VERSION;
CrystalChar.MajorNdisVersion = CRYSTAL_NDIS_MAJOR_VERSION;
CrystalChar.MinorNdisVersion = CRYSTAL_NDIS_MINOR_VERSION;
CrystalChar.InitializeHandler = CrystalInitialize;
CrystalChar.CheckForHangHandler = CrystalCheckForHang;
CrystalChar.DisableInterruptHandler = CrystalDisableInterrupt;
CrystalChar.EnableInterruptHandler = CrystalEnableInterrupt;
CrystalChar.HaltHandler = CrystalHalt;
CrystalChar.HandleInterruptHandler = CrystalHandleInterrupt;
CrystalChar.ISRHandler = CrystalInterruptService;
CrystalChar.QueryInformationHandler = CrystalQueryInformation;
CrystalChar.ReconfigureHandler = NULL;
CrystalChar.ResetHandler = CrystalReset;
CrystalChar.SendHandler = CrystalSend;
CrystalChar.SetInformationHandler = CrystalSetInformation;
CrystalChar.TransferDataHandler = CrystalTransferData;
CrystalChar.ReturnPacketHandler = NULL;
CrystalChar.SendPacketsHandler = CrystalSendPackets;
CrystalChar.AllocateCompleteHandler = NULL;
Status = NdisMRegisterMiniport(
CrystalWrapperHandle,
&CrystalChar,
sizeof(CrystalChar)
);
//DbgPrint("\nCs8900(): DriverEntry 2\n");
if (Status == NDIS_STATUS_SUCCESS) {
// DbgPrint("\nCs8900(): DriverEntry 3\n");
return NDIS_STATUS_SUCCESS;
}
//
// We can only get here if something went wrong with registering
// the mac or *all* of the adapters.
//
// DbgPrint("\nCs8900(): DriverEntry 4\n");
NdisTerminateWrapper(CrystalWrapperHandle, NULL);
// DbgPrint("\nCs8900(): DriverEntry 5\n");
return NDIS_STATUS_FAILURE;
}
#pragma NDIS_PAGABLE_FUNCTION(CrystalInitialize)
static
NDIS_STATUS
CrystalInitialize(
OUT PNDIS_STATUS OpenErrorStatus,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE MiniportAdapterHandle,
IN NDIS_HANDLE ConfigurationHandle
)
/*++
Routine Description:
CrystalInitialize adds finds and initializes the adapter.
Arguments:
OpenErrorStatus - Extra status bytes for opening token ring adapters.
SelectedMediumIndex - Index of the media type chosen by the driver.
MediumArray - Array of media types for the driver to chose from.
MediumArraySize - Number of entries in the array.
MiniportAdapterHandle - Handle for passing to the wrapper when
referring to this adapter.
ConfigurationHandle - A handle to pass to NdisOpenConfiguration.
Return Value:
NDIS_STATUS_SUCCESS
NDIS_STATUS_FAILURE
NDIS_STATUS_UNSUPPORTED_MEDIA
Assumptions:
The NDIS3 spec states that the miniport driver will not re-entered during
CrystalInitialize().
--*/
{
UINT i;
NDIS_STATUS Status=NDIS_STATUS_SUCCESS;
NDIS_HANDLE ConfigHandle;
WORD Result;
PVOMINIPDATA pOSD;
PVPMINIPDATA pvMini_Context;
PCHIP pChip;
PCD pData;
NDIS_PHYSICAL_ADDRESS Temp = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
int step;
// DbgPrint("\nCs8900a(): CrystalInitialize 1\n");
#if ( defined(SHx_PROCESSOR))
NDIS_PHYSICAL_ADDRESS AddrTemp;
#endif
EEPROM_NOT_FOUND=FALSE;
for (step=1; step<20 && Status==NDIS_STATUS_SUCCESS; step++) {
// DbgPrint("cs8900a(): step=%d\n",step);
switch (step) {
case 1:
//
// Search for the 802.3 media type
//
Status=NDIS_STATUS_UNSUPPORTED_MEDIA;
for (i=0; ipPSD = &pChip->higherdata;
pOSD = pChip->pOSD = &pChip->timerdata;
pData = pChip->pData = &pChip->lowerdata;
//
//setup some of the "higher" cntl blk
//
pvMini_Context->pChip = pChip;
pvMini_Context->vpMiniportAdapterHandle = MiniportAdapterHandle;
pvMini_Context->pChip->pPSD = pvMini_Context;
pvMini_Context->CableConnected = NdisMediaStateDisconnected;
pvMini_Context->CurrentState = NdisHardwareStatusNotReady;
break;
case 4:
VominiStartup( pOSD, MiniportAdapterHandle );
break;
case 5:
NdisMSetAttributes(
MiniportAdapterHandle,
(NDIS_HANDLE)pvMini_Context,
BUS_MASTER,
BUS_TYPE
);
break;
case 6:
//
// Open the configuration information.
//
NdisOpenConfiguration(
&Status,
&ConfigHandle,
ConfigurationHandle
);
break;
case 7:
;
break;
case 8:
#if ( defined(SHx_PROCESSOR))
NdisSetPhysicalAddressHigh(AddrTemp, 0);
NdisSetPhysicalAddressLow(AddrTemp, CS8900_IOPORT_MEM_ADDR);/*The physical memory
address of CS8900 IO port*/
/* Map the physical memory address of the IO port to a virtual address
to read/write registers.
The IO port range can not be cached.*/
pData->vIOSpace = MmMapIoSpace(
AddrTemp,
(ULONG)CRYSTAL_IO_SIZE,
FALSE // cashed or buffered? No.
);
if (pData->vIOSpace == NULL) Status = NDIS_STATUS_FAILURE;
if (Status != NDIS_STATUS_SUCCESS) {
NdisWriteErrorLogEntry(
MiniportAdapterHandle,
NDIS_ERROR_CODE_OUT_OF_RESOURCES,
4,
Status,
(ULONG)CS8900_IOPORT_MEM_ADDR,
(ULONG)CRYSTAL_IO_SIZE
);
break;
}
Status=VchipFindIOBase(pChip, (unsigned long)pData->vIOSpace);
if (Status != NDIS_STATUS_SUCCESS) {
step++; /* increase step so MUnmapIoSpace() can be executed
if MMapIoSpace() is successful but VchipFindIOBase() is NOT
successful.*/
}
break;
#else
Status=VchipFindIOBase(pChip, CRYSTAL_STARTING_PORT);
break;
#endif
case 9:
/* @kml 6/23/99 */
for (;; ) {
if (Status != NDIS_STATUS_SUCCESS) {
break; /* break for loop */
} else {
Status = NdisMRegisterIoPortRange(
&pData->PortOffset,
MiniportAdapterHandle,
(DWORD)pChip->Config.IOBase,
(DWORD)CRYSTAL_IO_SIZE
);
if (Status == NDIS_STATUS_SUCCESS) {
break;/* break for loop */
} else {
Status=VchipFindIOBase(pChip, pChip->Config.IOBase+CRYSTAL_NEXT_PORT_OFFSET );
} /* endif */
} /* end if */
} /* end for */
if (Status != NDIS_STATUS_SUCCESS) {
NdisWriteErrorLogEntry(
MiniportAdapterHandle,
NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS,
2,
Status,
pChip->Config.IOBase
);
} /* endif */
break;
case 10:
if ( EEPROM_NOT_FOUND ) {
Result = AssignedUserDefinedConfig(pvMini_Context->pChip);
} else {
Result = VchipGetConfig( pvMini_Context->pChip);
}
if (Result != CHIP_SUCCESS) {
Status=NDIS_STATUS_FAILURE;
} /* endif */
break;
case 11:
NdisMoveMemory(&pvMini_Context->PermanentNetworkAddress,
&pvMini_Context->pChip->Config.EthernetAddr,
(ULONG) ETH_LENGTH_OF_ADDRESS);
break;
case 12:
if (GetNetworkAddress(ConfigHandle, pvMini_Context->CurrentNetworkAddress) ==
NDIS_STATUS_SUCCESS)
{
NdisMoveMemory(&pvMini_Context->pChip->Config.EthernetAddr,
&pvMini_Context->CurrentNetworkAddress,
(ULONG)ETH_LENGTH_OF_ADDRESS);
}
else {
NdisMoveMemory(&pvMini_Context->CurrentNetworkAddress,
&pvMini_Context->PermanentNetworkAddress,
(ULONG)ETH_LENGTH_OF_ADDRESS);
}
break;
case 13:
// Get the duplex mode from the registry
pvMini_Context->pChip->Config.RequestedDuplexMode=GetDuplexMode(ConfigHandle);
break;
case 14:
NdisCloseConfiguration(ConfigHandle);
break;
case 15:
#if ( defined(ARM_PROCESSOR) || defined(SHx_PROCESSOR))
/* Since SYSINTR_ETHER = SYSINTR_FIRMWARE+10 defined in OALint.h,
pChip->Config.IntLine must be 10 here for CE kernel to map CS8900 ISR
to SYSINTR_ETHER. */
pChip->Config.IntLine = 10;
#endif
DbgPrint("\nCs8900a(): Step 15: IntLint=0x%x; \n",
pvMini_Context->pChip->Config.IntLine);
Status = NdisMRegisterInterrupt(
&(pData->InterruptObject),
MiniportAdapterHandle,
(UINT)pvMini_Context->pChip->Config.IntLine,
(UINT)pvMini_Context->pChip->Config.IntLine,
(BYTE)TRUE, // Installable ISR: False
(BYTE)FALSE, // Shared Interrupt: False
(NDIS_INTERRUPT_MODE)NdisInterruptLatched // Level or Edge
);
if (Status != NDIS_STATUS_SUCCESS) {
NdisWriteErrorLogEntry(
MiniportAdapterHandle,
NDIS_ERROR_CODE_INTERRUPT_CONNECT,
2,
Status,
pvMini_Context->pChip->Config.IntLine
);
} /* endif */
break;
case 17:
NdisMRegisterAdapterShutdownHandler(
MiniportAdapterHandle,
pvMini_Context,
CrystalShutdown
);
pvMini_Context->pChip->Config.Filtering = 0;
pvMini_Context->CurrentState = NdisHardwareStatusInitializing;
break;
case 18:
Result = VchipStartup(pChip );
if (Result != CHIP_SUCCESS) {
Status=NDIS_STATUS_FAILURE;
} /* endif */
break;
case 19:
if ( pvMini_Context->pChip->Config.DetectedMediaType == MEDIA_NONE ) {
pvMini_Context->CableConnected = NdisMediaStateDisconnected;
} else {
pvMini_Context->CableConnected = NdisMediaStateConnected;
} /* endif */
pvMini_Context->CurrentState = NdisHardwareStatusReady;
break;
} /* endswitch */
} /* endfor */
/*
DbgPrint("\nCs8900a(): DuplexMode=%d; IntLint=0x%x; IOBase=0x%x\n Mac0=0x%x Mac1=0x%x Mac2=0x%x\n\n",
pvMini_Context->pChip->Config.RequestedDuplexMode,
pvMini_Context->pChip->Config.IntLine,
pvMini_Context->pChip->Config.MemoryBase,
pChip->Config.EthernetAddr.Part[0],
pChip->Config.EthernetAddr.Part[1],
pChip->Config.EthernetAddr.Part[2]
);
*/
//
//Test for failure and cleanup as a function of how many steps were successful
//
if (Status!=NDIS_STATUS_SUCCESS) {
for (step -= 2; step>0; step--) {
// DbgPrint("cs8900a(): Error Clean Up! step=%d\n",step);
switch (step) {
case 17:
NdisMDeregisterAdapterShutdownHandler(MiniportAdapterHandle);
break;
case 15:
NdisMDeregisterInterrupt( &(pData->InterruptObject) );
break;
case 9:
NdisMDeregisterIoPortRange(
MiniportAdapterHandle,
pvMini_Context->pChip->Config.IOBase,
pvMini_Context->pChip->Config.IOSize,
pData->PortOffset
);
break;
#if ( defined(SHx_PROCESSOR))
case 8:
MmUnmapIoSpace(
pChip->pData->vIOSpace,
CRYSTAL_IO_SIZE
);
break;
#endif
case 4:
VominiShutdown( pOSD );
break;
case 2:
NdisFreeMemory( (PVOID)pChip, (UINT)sizeof(CHIP), 0);
break;
default:
break;
} /* endswitch */
} /* endfor */
} /* endif */
// DbgPrint("\nCs8900a(): CrystalInitialize 2\n");
return Status;
}
#pragma NDIS_PAGABLE_FUNCTION(CrystalHalt)
extern
void
CrystalHalt(
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
Routine Description:
CrystalHalt is called when the driver is to remove itself.
Arguments:
MiniportAdapterContext - Context registered with the wrapper, really
a pointer to the VP context.
Return Value:
None.
--*/
{
PVOID pOSD;
VPM_SetupMiniContext;
pvMini_Context->CurrentState = NdisHardwareStatusClosing;
// DbgPrint("\nCs8900a(): Halt 1\n");
// Disable Chip Interrupts
VchipDisableInterrupts( pChip );
// Call NdisDeregisterAdapterShutdownHandler
NdisMDeregisterAdapterShutdownHandler(
MiniportAdapterHandle
);
// Reset/Shutdown Chip
VchipShutdown( pChip );
NdisMDeregisterInterrupt( &(pChip->pData->InterruptObject) );
NdisMDeregisterIoPortRange(
MiniportAdapterHandle,
pChip->Config.IOBase,
pChip->Config.IOSize,
pChip->pData->PortOffset
);
#if ( defined(SHx_PROCESSOR))
MmUnmapIoSpace(
pChip->pData->vIOSpace,
CRYSTAL_IO_SIZE
);
#endif
// Free All Miniport Resources (Context, ...)
pvMini_Context->CurrentState = NdisHardwareStatusNotReady;
// Save address of OS Data
pOSD = pChip->pOSD;
VominiShutdown( pOSD );
NdisFreeMemory( (PVOID)pChip, (UINT)sizeof(CHIP), 0);
// DbgPrint("\nCs8900a(): Halt 2\n");
return;
}
extern
void
CrystalShutdown(
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
Routine Description:
CrystalShutdown is called when the system is shutdown or it bugchecks.
Arguments:
MiniportAdapterContext - Context registered with the wrapper, really
a pointer to VP context.
Return Value:
None.
--*/
{
VPM_SetupMiniContext;
pvMini_Context->CurrentState = NdisHardwareStatusClosing;
VchipReset( pChip );
pvMini_Context->CurrentState = NdisHardwareStatusNotReady;
return;
}
extern
NDIS_STATUS
CrystalReset(
OUT PBOOLEAN AddressingReset,
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
Routine Description:
The CrystalReset request instructs the driver to issue a hardware reset
to the network adapter. The driver also resets its software state. See
the description of MiniportMReset for a detailed description of this request.
Arguments:
MiniportAdapterContext - Pointer to the VP context.
AddressingReset - Does the adapter need the addressing information reloaded.
Return Value:
The function value is the status of the operation.
--*/
{
// WORD Result;
PNDIS_PACKET Packet;
PTRANSMIT_QUEUE_ELEMENT TxPacket;
VPM_SetupMiniContext;
// DbgPrint("\nCs8900a(): Reset()\n");
// @kml 6/23/99
// return NDIS_STATUS_SUCCESS;
pvMini_Context->CurrentState = NdisHardwareStatusReset;
/* Make sure that all outstanding XMITS get returned on RESET !!! */
// Dequeue the Packet
DEQ_PACKET(&TxPacket, pChip->pData->TransmitQueue);
while (TxPacket!=NULL) {
Packet = CONTAINING_RECORD(TxPacket,NDIS_PACKET,MiniportReserved);
NdisMSendComplete(MiniportAdapterHandle,
Packet,
NDIS_STATUS_SUCCESS
);
DEQ_PACKET(&TxPacket, pChip->pData->TransmitQueue);
} /* endwhile */
pvMini_Context->CurrentState = NdisHardwareStatusReady;
return NDIS_STATUS_SUCCESS;
}
BOOLEAN
CrystalCheckForHang(
IN PVOID MiniportAdapterContext
)
/*++
Routine Description:
This routine checks on to see if the tranmitter is hung.
Arguments:
MiniportAdapterContext - Really a pointer to VP context.
Return Value:
FALSE - This routine actually does a wake up, rather than having
the wrapper do it.
--*/
{
// not yet implemented!
// DbgBreakPoint();
VPM_SetupMiniContext;
// DbgPrint("\nCs8900a(): CheckForHang() \n");
return(FALSE);
}
void VpsMediaChanged( PCHIP pChip )
{
NDIS_STATUS Status;
PNDIS_PACKET Packet;
PTRANSMIT_QUEUE_ELEMENT TxPacket;
VPM_SetupMiniContextFromPchip;
/* If the cable was just disconnected */
if ( pChip->Config.DetectedMediaType == MEDIA_NONE )
{
Status = NDIS_STATUS_MEDIA_DISCONNECT;
pvMini_Context->CableConnected = NdisMediaStateDisconnected;
/* Make sure that all outstanding XMITS get returned on RESET !!! */
// Dequeue the Packet
DEQ_PACKET(&TxPacket, pChip->pData->TransmitQueue);
while (TxPacket!=NULL) {
Packet = CONTAINING_RECORD(TxPacket,NDIS_PACKET,MiniportReserved);
NdisMSendComplete(MiniportAdapterHandle,
Packet,
NDIS_STATUS_SUCCESS
);
DEQ_PACKET(&TxPacket, pChip->pData->TransmitQueue);
} /* endwhile */
}
else /* The cable was just connected */
{
Status = NDIS_STATUS_MEDIA_CONNECT;
pvMini_Context->CableConnected = NdisMediaStateConnected;
}
#ifndef NDIS30_MINIPORT
if ( pvMini_Context->CurrentState != NdisHardwareStatusInitializing )
{
NdisMIndicateStatus( MiniportAdapterHandle, Status, NULL, 0 );
NdisMIndicateStatusComplete( MiniportAdapterHandle );
}
#endif
}
WORD AssignedUserDefinedConfig(PCHIP pChip){
AddIOBase(pChip->Config.IOBase);
/* Default Interrupt Line number is 0xA */
pChip->Config.IntLine = 10;
/* User can assigned Ethernet Address here */
/* Note: Please swap the BYTE-ORDER of the MAC address.
/* The MAC address assigned by following code is 00:12:34:56:78:90.*/
/* For a valid individual MAC address, the first byte must be 0. */
pChip->Config.EthernetAddr.Part[0]=0x1200; /* the least byte of Part[0] should be 0. */
pChip->Config.EthernetAddr.Part[1]=0x5634;
pChip->Config.EthernetAddr.Part[2]=0x9078;
/* Default Media type is 10BaseT */
pChip->Config.RequestedMediaType = MEDIA_BASE_T;
/* Default Duplex mode is Half Duplex */
pChip->Config.RequestedDuplexMode = DUPLEX_HALF;
/* Media Speed is 10MBPS*/
pChip->Config.MediaSpeed = 10;
pChip->Config.BusType = BUS_ISA;
pChip->Config.BusSlot = (WORD)UNSPECIFIED;
pChip->Config.MaxTxCount = CRYSTAL_TRANSMIT_PACKET_MAXIMUM;
pChip->Config.Flags = 0;
pChip->Config.CurrentDuplexMode = DUPLEX_NONE;
pChip->Config.DetectedMediaType = MEDIA_NONE;
/* Memory mode is disabled */
pChip->Config.MemoryBase = (DWORD)UNSPECIFIED;
pChip->Config.MemorySize = (WORD)UNSPECIFIED;
/* A boot ROM is not installed */
pChip->Config.ROMBase = (DWORD)UNSPECIFIED;
pChip->Config.ROMSize = (WORD)UNSPECIFIED;
pChip->Config.DMALine = (BYTE)UNSPECIFIED;
return CHIP_SUCCESS;
}