|
|
/***************************************************************************
* * DISPATCH.C * * FastMAC Plus based NDIS3 miniport driver dispatch routines. This module * contains all of the upper interface functions that are not purely * for initialization and closedown (i.e. DriverEntry, MadgeInitialize * and MadgeHalt) excluding MadgeSetInformation and MadgeQueryInformation. * * Copyright (c) Madge Networks Ltd 1994 * * COMPANY CONFIDENTIAL * * Created: PBA 21/06/1994 * ****************************************************************************/
#include <ndis.h>
#include "ftk_defs.h"
#include "ftk_intr.h"
#include "ftk_extr.h"
#include "mdgmport.upd"
#include "ndismod.h"
/****************************************************************************
* * Function - MadgeGetAdapterStatus * * Parameters - systemSpecific1 -> Unused. * context -> Actually a pointer to our NDIS3 level * adapter structure. * systemSpecific2 -> Unused. * systemSpecific3 -> Unused. * * Purpose - This function is called of a timer tick and notifies * open bindings of any interesting events. * * Returns - Nothing. * ****************************************************************************/
VOID MadgeGetAdapterStatus( PVOID systemSpecific1, PVOID context, PVOID systemSpecific2, PVOID systemSpecific3 ) { PMADGE_ADAPTER ndisAdap; NDIS_STATUS notifyStatus; WORD ringStatus;
//
// Do some pre-calculation.
//
ndisAdap = (PMADGE_ADAPTER) context; notifyStatus = 0; ringStatus = ndisAdap->CurrentRingStatus;
if (ndisAdap->CurrentRingState == NdisRingStateOpened) { //
// WARNING: If the adapter has been shutdown, this will return zero
// in the two fields.
//
driver_get_open_and_ring_status( ndisAdap->FtkAdapterHandle, &ndisAdap->CurrentRingStatus, &ndisAdap->LastOpenStatus );
if (ringStatus != ndisAdap->CurrentRingStatus) { if (ndisAdap->CurrentRingStatus & RING_STATUS_RING_RECOVERY) { notifyStatus |= NDIS_RING_RING_RECOVERY; }
if (ndisAdap->CurrentRingStatus & RING_STATUS_SINGLE_STATION) { notifyStatus |= NDIS_RING_SINGLE_STATION; }
if (ndisAdap->CurrentRingStatus & RING_STATUS_COUNTER_OVERFLOW) { notifyStatus |= NDIS_RING_COUNTER_OVERFLOW; }
if (ndisAdap->CurrentRingStatus & RING_STATUS_REMOVE_RECEIVED) { notifyStatus |= NDIS_RING_REMOVE_RECEIVED; }
if (ndisAdap->CurrentRingStatus & RING_STATUS_AUTO_REMOVAL) { notifyStatus |= NDIS_RING_AUTO_REMOVAL_ERROR; }
if (ndisAdap->CurrentRingStatus & RING_STATUS_LOBE_FAULT) { notifyStatus |= NDIS_RING_LOBE_WIRE_FAULT; }
if (ndisAdap->CurrentRingStatus & RING_STATUS_TRANSMIT_BEACON) { notifyStatus |= NDIS_RING_TRANSMIT_BEACON; }
if (ndisAdap->CurrentRingStatus & RING_STATUS_SOFT_ERROR) { notifyStatus |= NDIS_RING_SOFT_ERROR; }
if (ndisAdap->CurrentRingStatus & RING_STATUS_HARD_ERROR) { notifyStatus |= NDIS_RING_HARD_ERROR; }
if (ndisAdap->CurrentRingStatus & RING_STATUS_SIGNAL_LOSS) { notifyStatus |= NDIS_RING_SIGNAL_LOSS; }
if (notifyStatus != 0) { NdisMIndicateStatus( ndisAdap->UsedInISR.MiniportHandle, NDIS_STATUS_RING_STATUS, (PVOID) ¬ifyStatus, sizeof(notifyStatus) );
NdisMIndicateStatusComplete( ndisAdap->UsedInISR.MiniportHandle );
MadgePrint2( "Ring Status %04x\n", ndisAdap->CurrentRingStatus); } } }
//
// Just before we go, clear the JustReadErrorLog flag, so that requests
// for statistics will cause an SRB to be issued every now and then.
//
ndisAdap->JustReadErrorLog = 0;
//
// And finally re-arm the timer.
//
NdisMSetTimer(&ndisAdap->WakeUpTimer, EVERY_2_SECONDS); }
/****************************************************************************
* * Function - MadgeCheckForHang * * Parameters - adapterContext -> A pointer to our NDIS adapter structure. * * Purpose - Process a call from the NDIS3 wrapper to check if * an adapter has hung. * * Returns - We always return FALSE since the only action the wrapper * can take is to invoke a reset, which we don't support * anyway. * ****************************************************************************/
BOOLEAN MadgeCheckForHang(NDIS_HANDLE adapterContext) { return FALSE; }
/****************************************************************************
* * Function - MadgeReset * * Parameters - adapterContext -> A pointer to our NDIS adapter structure. * addressReset -> Ignored. * * Purpose - Process a call from the NDIS3 wrapper to reset an * adapter. * * Returns - NDIS_STATUS_NOT_RESETTABLE as we don't support resets. * ****************************************************************************/
NDIS_STATUS MadgeReset(PBOOLEAN addressReset, NDIS_HANDLE adapterContext) { MadgePrint1("MadgeReset\n");
MadgePrint2( "ndisAdap = %x\n", PMADGE_ADAPTER_FROM_CONTEXT(adapterContext) );
return NDIS_STATUS_NOT_RESETTABLE; }
/****************************************************************************
* * Function - MadgeDisableInterrupts * * Parameters - adapterContext -> A pointer to our NDIS adapter structure. * * Purpose - Process a call from the NDIS3 wrapper to turn adapter * interrupts off. * * Returns - Nothing. * ****************************************************************************/
VOID MadgeDisableInterrupts(NDIS_HANDLE adapterContext) { // MadgePrint1("MadgeDisableInterrupts\n");
//
// Note: it is very difficult for use to disble interrupts at the
// adapter so we don't. We use a spin lock to protect our DPR
// routine.
//
}
/****************************************************************************
* * Function - MadgeEnableInterrupts * * Parameters - adapterContext -> A pointer to our NDIS adapter structure. * * Purpose - Process a call from the NDIS3 wrapper to turn adapter * interrupts on. * * Returns - Nothing. * ****************************************************************************/
VOID MadgeEnableInterrupts(NDIS_HANDLE adapterContext) { // MadgePrint1("MadgeEnableInterrupts\n");
//
// Note: it is very difficult for use to disble interrupts at the
// adapter so we don't. We use a spin lock to protect our DPR
// routine.
//
}
/****************************************************************************
* * Function - MadgeSend * * Parameters - adapterContext -> Pointer to our NDIS level adapter * structure. * packet -> Pointer to the NDIS3 packet to send. * flags -> Optional flags. * * Purpose - Called by the NDIS3 wrapper when it wants us to send a * frame. * * Returns - NDIS3 status code. * ****************************************************************************/
NDIS_STATUS MadgeSend(NDIS_HANDLE adapterContext, PNDIS_PACKET packet, UINT flags) { ULONG *pagePtr; UINT pageCount; UINT physFrags; UINT i; UINT size; UINT bytes; UINT count; NDIS_BUFFER *bufPtr; NDIS_STATUS retCode; PMADGE_ADAPTER ndisAdap; UINT totalPacketSize; WORD status;
//
// Set up a pointer to our adapter handle.
//
ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(adapterContext);
//
// Find out how long the frame is and where it's header is.
//
NdisQueryPacket(packet, NULL, NULL, NULL, &totalPacketSize);
//
// Make sure the frame isn't too long or two short.
//
if (totalPacketSize > ndisAdap->MaxFrameSize || totalPacketSize < FRAME_HEADER_SIZE) { retCode = NDIS_STATUS_INVALID_PACKET; }
//
// Check that a PCMCIA adapter is still physically present.
//
else if (ndisAdap->AdapterRemoved) { MadgePrint1("MadgeSend aborting - adapter removed\n"); retCode = NDIS_STATUS_SUCCESS; }
//
// Otherwise we need to send the frame over the ring.
//
else { status = rxtx_transmit_frame( ndisAdap->FtkAdapterHandle, (DWORD) packet, (WORD) totalPacketSize, TRUE );
//
// Check if the frame has been transmitted completely.
//
if (status == DRIVER_TRANSMIT_SUCCEED) { ndisAdap->FramesTransmitted++; retCode = NDIS_STATUS_SUCCESS;
#ifdef OID_MADGE_MONITOR
//
// Update the appropriate parts of the monitor structure
//
(ndisAdap->MonitorInfo).TransmitFrames++; (ndisAdap->MonitorInfo).TransmitFrameSize[totalPacketSize/128]++;
//
// Find the number of physical fragments sent
//
NdisQueryPacket(packet, NULL, NULL, &bufPtr, &totalPacketSize);
physFrags = 0; count = 0;
while (bufPtr != NULL) { MDL *mdl = (MDL *) bufPtr;
count++; pageCount = (((MDL *) bufPtr)->Size - sizeof(MDL)) / sizeof(ULONG); pagePtr = (ULONG *) (((MDL *) bufPtr) + 1);
physFrags++; // First page.
bytes = mdl->ByteCount;
if (pageCount <= 1) { size = bytes; } else { size = 4096 - mdl->ByteOffset; bytes -= size; }
for (i = 1; i < pageCount; i++) { if (pagePtr[i] != pagePtr[i - 1] + 1) { size = 0; physFrags++; }
if (i == pageCount - 1) { size += bytes; } else { bytes -= 4096; size += 4096; }
}
NdisGetNextBuffer(bufPtr, &bufPtr); }
if (count < 65) { (ndisAdap->MonitorInfo).NumberOfVFrags[count]++; }
if (physFrags < 65) { (ndisAdap->MonitorInfo).NumberOfPFrags[physFrags]++; } #endif
}
//
// Or not transmitted at all, in which case we must
// queue it for later.
//
else { retCode = NDIS_STATUS_RESOURCES; } }
return retCode; }
/***************************************************************************
* * Function - MadgeCopyFromPacketToBuffer * * Parameters - packet -> The NDIS3 packet to copy. * offset -> Starting offset into the packet. * bytesToCopy -> Number of bytes to copy. * destPtr -> Pointer to the destination buffer. * bytesCopied -> Pointer to a holder for the number of * bytes actually copied. * * Purpose - Copy data from an NDIS3 packet into a buffer. * * Returns - Nothing. * ****************************************************************************/ VOID MadgeCopyFromPacketToBuffer( PNDIS_PACKET packet, UINT offset, UINT bytesToCopy, PCHAR destPtr, PUINT bytesCopied ) { UINT bufferCount; PNDIS_BUFFER currentBuffer; PVOID currentPtr; UINT currentLength; UINT amountToMove; UINT localBytesCopied;
*bytesCopied = 0; localBytesCopied = 0;
if (bytesToCopy == 0) { return; }
NdisQueryPacket(packet, NULL, &bufferCount, ¤tBuffer, NULL); if (bufferCount == 0) { return; }
NdisQueryBuffer(currentBuffer, ¤tPtr, ¤tLength);
while (localBytesCopied < bytesToCopy) { if (currentLength == 0) { NdisGetNextBuffer(currentBuffer, ¤tBuffer); if (currentBuffer == 0) { break; }
NdisQueryBuffer(currentBuffer, ¤tPtr, ¤tLength); continue; }
if (offset > 0) { if (offset > currentLength) { offset -= currentLength; currentLength = 0; continue; } else { currentPtr = (PCHAR) currentPtr + offset; currentLength -= offset; offset = 0; } }
amountToMove = (currentLength <= (bytesToCopy - localBytesCopied)) ? currentLength : bytesToCopy - localBytesCopied;
MADGE_MOVE_MEMORY(destPtr, currentPtr, amountToMove);
destPtr = (PCHAR) destPtr + amountToMove; currentPtr = (PCHAR) currentPtr + amountToMove;
localBytesCopied += amountToMove; currentLength -= amountToMove; }
*bytesCopied = localBytesCopied; }
/****************************************************************************
* * Function - MadgeTransferData * * Parameters - adapterContext -> Pointer to our NDIS level adapter * structure. * receiveContext -> Pointer to the start of the frame data. * byteOffset -> Offset to start copying from. * bytesToTransfer -> Number of bytes to copy. * packet -> NDIS packet for the data. * bytesTransferred -> Pointer to a holder for the number of * bytes actually copied. * * Purpose - Copy data from the received frame just indicated into an * NDIS packet. This function is called by the NDIS3 wrapper * in response to our indication frame rxtx_irq_received_frame. * * Returns - An NDIS3 status code. * ****************************************************************************/
NDIS_STATUS MadgeTransferData( PNDIS_PACKET packet, PUINT bytesTransferred, NDIS_HANDLE adapterContext, NDIS_HANDLE receiveContext, UINT byteOffset, UINT bytesToTransfer ) { PMADGE_ADAPTER ndisAdap; NDIS_STATUS retCode;
//
// Pre-calculate some values.
//
ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(adapterContext);
//
// Check that the data pointer is valid.
//
if ((PCHAR) receiveContext == NULL) { retCode = NDIS_STATUS_FAILURE; }
//
// If it is, copy from the frame from the receive buffer
// into the packet.
//
else { MadgeCopyFromBufferToPacket( (PCHAR) receiveContext + byteOffset, bytesToTransfer, packet, 0, bytesTransferred );
retCode = NDIS_STATUS_SUCCESS;
#ifdef OID_MADGE_MONITOR
//
// Update the appropriate parts of the monitor structure
//
if ((ndisAdap->MonitorInfo).ReceiveFlag > 0) { (ndisAdap->MonitorInfo).TransferFrames++; (ndisAdap->MonitorInfo).TransferFrameSize[(ndisAdap->MonitorInfo).CurrentFrameSize/128]++; (ndisAdap->MonitorInfo).ReceiveFlag = 0; } #endif
}
return retCode; }
/***************************************************************************
* * Function - MadgeCopyFromBufferToPacket * * Parameters - srcPtr -> Pointer to the source buffer. * bytesToCopy -> Number of bytes to copy. * packet -> The NDIS3 destination packet. * offset -> Starting offset into the buffer. * bytesCopied -> Pointer to a holder for the number of * bytes actually copied. * * Purpose - Copy data from a buffer into an NDIS3 packet. * * Returns - Nothing. * ****************************************************************************/
VOID MadgeCopyFromBufferToPacket( PCHAR srcPtr, UINT bytesToCopy, PNDIS_PACKET packet, UINT offset, PUINT bytesCopied ) { UINT bufferCount; PNDIS_BUFFER currentBuffer; PVOID virtualAddress; UINT currentLength; UINT amountToMove; UINT localBytesCopied;
*bytesCopied = 0; localBytesCopied = 0;
if (bytesToCopy == 0) { return; }
NdisQueryPacket(packet, NULL, &bufferCount, ¤tBuffer, NULL); if (bufferCount == 0) { return; }
NdisQueryBuffer(currentBuffer, &virtualAddress, ¤tLength);
while (localBytesCopied < bytesToCopy) { if (currentLength == 0) { NdisGetNextBuffer(currentBuffer, ¤tBuffer); if (currentBuffer == NULL) { break; }
NdisQueryBuffer(currentBuffer, &virtualAddress, ¤tLength); continue; }
if (offset > 0) { if (offset > currentLength) { offset -= currentLength; currentLength = 0; continue; } else { virtualAddress = (PCHAR) virtualAddress + offset; currentLength -= offset; offset = 0; } }
amountToMove = (bytesToCopy - localBytesCopied < currentLength) ? bytesToCopy - localBytesCopied : currentLength;
MADGE_MOVE_MEMORY( virtualAddress, srcPtr, amountToMove );
srcPtr += amountToMove; localBytesCopied += amountToMove; currentLength -= amountToMove; }
*bytesCopied = localBytesCopied; }
/***************************************************************************
* * Function - MadgeISR * * Parameters - interruptRecognised -> Pointer to an interrupt recognised * flag we set if we recognise the * interrupt. * queueDPR -> Pointer to DPR required flag we * set if we need a DPR. * adapterContext -> Pointer to our NDIS level adapter * structure. * * Purpose - Process an IRQ from an adapter. All we do is call the * HWI and schedule a DPR if required. * * Returns - Nothing. * ****************************************************************************/
VOID MadgeISR( PBOOLEAN interruptRecognised, PBOOLEAN queueDPR, NDIS_HANDLE adapterContext ) { PMADGE_ADAPTER ndisAdap;
ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(adapterContext);
hwi_interrupt_entry( ndisAdap->FtkAdapterHandle, (WORD) ndisAdap->UsedInISR.InterruptNumber );
//
// If ndisAdap->DprRequired is TRUE then we recognised the interrupt
// and found something that requires further processing (e.g. received
// a frame). If ndisAdap->DprRequired is FALSE then we either didn't
// recognise the interrupt or we don't need any further processing.
// The only operation that doesn't need further processing is ISA
// PIO. Since ISA cards cannot share interrupt lines it doesn't
// matter if we say we don't recognise the interrupt if we don't
// need any further processing. Hence we can use ndisAdap->DprRequired
// to set both *interruptRecognised and *queueDpr.
//
//
// However ...
// There is a race condition with ATULA based cards in PIO mode.
// Normally we do not claim interrupts that are used for PIO transfers
// to avoid the overhead of a DPR on PIO transfers. However, in some
// instances if we do not claim the PIO interrupts used for the
// initial "DMA" tests then WFWG (and possibly NT) permanently disables
// our interrupts. To get around this we claim all interrupts until
// our rx/tx buffers have been allocated since the optimisation of not
// queuing a DPR for PIO interrupts doesn't matter until we have
// rx/tx buffers in place.
//
*interruptRecognised = (ndisAdap->RxTxBufferState != MADGE_RXTX_INITIALIZED) ? TRUE : ndisAdap->DprRequired; *queueDPR = ndisAdap->DprRequired;
ndisAdap->DprRequired = FALSE; }
/*--------------------------------------------------------------------------
| | Function - MadgeSyncSRBPending | | Parameters - synchonizedContext -> A pointer to an NDIS3 level adapter | structure. | | Purpose - Process a completed SRBs. This routine is always | syncronised with IRQs. | | Returns - TRUE if the SRB has actually completed or FALSE if not. | --------------------------------------------------------------------------*/
STATIC BOOLEAN MadgeSyncSRBPending(PVOID synchronizeContext) { PMADGE_ADAPTER ndisAdap; BOOLEAN retCode; ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(synchronizeContext); retCode = ndisAdap->UsedInISR.SrbRequestCompleted;
if (retCode) { ndisAdap->UsedInISR.SrbRequestCompleted = FALSE; ndisAdap->SrbRequestStatus = ndisAdap->UsedInISR.SrbRequestStatus; }
return retCode; }
/****************************************************************************
* * Function - MadgeHandleInterrupt * * Parameters - adapterContext -> Pointer to our NDIS level adapter * structure. * * Purpose - Our DPR routine. * * Returns - Nothing. * ****************************************************************************/
VOID MadgeHandleInterrupt(NDIS_HANDLE adapterContext) { PMADGE_ADAPTER ndisAdap;
ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(adapterContext);
//
// Must do anything if we don't have tx/rx buffers.
//
if (ndisAdap->RxTxBufferState != MADGE_RXTX_INITIALIZED) { return; }
//
// I think this check is a bit paranoid. I think DPRs are guaranteed
// to be single threaded. I suppose it might be needed on a multi-
// processor. Just 'cos your've paraonoid doesn't mean they're not
// out to get you!
//
if (!ndisAdap->DprInProgress) { ndisAdap->DprInProgress = TRUE;
//
// Handle completed SRBs first.
//
if (NdisMSynchronizeWithInterrupt( &ndisAdap->Interrupt, MadgeSyncSRBPending, adapterContext)) { MadgeCompletePendingRequest(ndisAdap); }
//
// If the adapter has been removed then call the housekeeping
// function.
//
if (ndisAdap->AdapterRemoved) { rxtx_adapter_removed(ndisAdap->FtkAdapterHandle); }
//
// Check for transmit completions.
//
rxtx_irq_tx_completion_check( ndisAdap->FtkAdapterHandle, adapter_record[ndisAdap->FtkAdapterHandle] );
//
// See if there are any received frames.
//
driver_get_outstanding_receive(ndisAdap->FtkAdapterHandle);
ndisAdap->DprInProgress = FALSE; }
//
// This else should never be executed!
//
else { MadgePrint1("DPR reentered!!!!\n"); } }
/******** End of DISPATCH.C ************************************************/
|