diff options
Diffstat (limited to 'private/ntos/ndis/madge/driver/dispatch.c')
-rw-r--r-- | private/ntos/ndis/madge/driver/dispatch.c | 919 |
1 files changed, 919 insertions, 0 deletions
diff --git a/private/ntos/ndis/madge/driver/dispatch.c b/private/ntos/ndis/madge/driver/dispatch.c new file mode 100644 index 000000000..593ef071d --- /dev/null +++ b/private/ntos/ndis/madge/driver/dispatch.c @@ -0,0 +1,919 @@ +/*************************************************************************** +* +* 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 ************************************************/ + |