From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/ndis/htdsu/card.c | 722 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 722 insertions(+) create mode 100644 private/ntos/ndis/htdsu/card.c (limited to 'private/ntos/ndis/htdsu/card.c') diff --git a/private/ntos/ndis/htdsu/card.c b/private/ntos/ndis/htdsu/card.c new file mode 100644 index 000000000..eb62fba71 --- /dev/null +++ b/private/ntos/ndis/htdsu/card.c @@ -0,0 +1,722 @@ +/***************************************************************************\ +|* Copyright (c) 1994 Microsoft Corporation *| +|* Developed for Microsoft by TriplePoint, Inc. Beaverton, Oregon *| +|* *| +|* This file is part of the HT Communications DSU41 WAN Miniport Driver. *| +\***************************************************************************/ +#include "version.h" +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Module Name: + + card.c + +Abstract: + + This module implements the low-level hardware control functions used by + the NDIS Minport driver on the HT DSU41 controller. You will need to + replace this module with the control functions required to support your + hardware. + CardIdentify() + CardDoCommand() + CardInitialize() + CardLineConfig() + CardLineDisconnect() + CardLineDisconnect() + CardPrepareTransmit() + CardGetReceiveInfo() + CardDialNumber() + + This driver conforms to the NDIS 3.0 Miniport interface. + +Author: + + Larry Hattery - TriplePoint, Inc. (larryh@tpi.com) Jun-94 + +Environment: + + Windows NT 3.5 kernel mode Miniport driver or equivalent. + +Revision History: + +---------------------------------------------------------------------------*/ + +#define __FILEID__ 2 // Unique file ID for error logging + +#include "htdsu.h" + + +NDIS_STATUS +CardIdentify( + IN PHTDSU_ADAPTER Adapter + ) + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Functional Description: + + This routine will attempt to verify that the controller is located in + memory where the driver has been configured to expect it. + +Parameters: + + Adapter _ A pointer ot our adapter information structure. + +Return Values: + + NDIS_STATUS_SUCCESS + NDIS_STATUS_ADAPTER_NOT_FOUND + +---------------------------------------------------------------------------*/ + +{ + DBG_FUNC("CardIdentify") + + NDIS_STATUS Status; + + /* + // These values are read from the adapter to make sure this driver will + // work with the firmware on the adapter. + */ + USHORT CoProcessorId; + USHORT CoProcessorVersion; + USHORT DsuId; + USHORT DsuVersion; + + DBG_ENTER(Adapter); + + /* + // Read the configuration values from the card. + */ + CoProcessorId = READ_REGISTER_USHORT(&Adapter->AdapterRam->CoProcessorId); + CoProcessorVersion = READ_REGISTER_USHORT(&Adapter->AdapterRam->CoProcessorVersion); + DsuId = READ_REGISTER_USHORT(&Adapter->AdapterRam->DsuId); + DsuVersion = READ_REGISTER_USHORT(&Adapter->AdapterRam->DsuVersion); + + /* + // Make sure these values are what we expect. + */ + if ((CoProcessorId == HTDSU_COPROCESSOR_ID) && + (CoProcessorVersion >= HTDSU_COPROCESSOR_VERSION) && + ((DsuId & 0x00FF) == HTDSU_DSU_ID) && + (DsuVersion >= HTDSU_DSU_VERSION)) + { + /* + // Record the number of lines on this adapter. + */ + Adapter->NumLineDevs = HTDSU_NUM_LINKS; + if ((DsuId & 0xFF00) == 0) + { + --Adapter->NumLineDevs; + } + DBG_NOTICE(Adapter,("NumLineDevs=%d\n",Adapter->NumLineDevs)); + + Status = NDIS_STATUS_SUCCESS; + } + else + { + DBG_ERROR(Adapter,("Adapter not found or invalid firmware:\n" + "CoProcessorId = %Xh\n" + "CoProcessorVersion = %Xh\n" + "DsuId = %Xh\n" + "DsuVersion = %Xh\n", + CoProcessorId, + CoProcessorVersion, + DsuId, + DsuVersion + )); + + Status = NDIS_STATUS_ADAPTER_NOT_FOUND; + /* + // Log error message and return. + */ + NdisWriteErrorLogEntry( + Adapter->MiniportAdapterHandle, + NDIS_ERROR_CODE_ADAPTER_NOT_FOUND, + 7, + CoProcessorId, + CoProcessorVersion, + DsuId, + DsuVersion, + Status, + __FILEID__, + __LINE__ + ); + } + + DBG_LEAVE(Adapter); + + return (Status); +} + + +NDIS_STATUS +CardDoCommand( + IN PHTDSU_ADAPTER Adapter, + IN USHORT CardLine, /* HTDSU_CMD_LINE1 or HTDSU_CMD_LINE2 */ + IN USHORT CommandValue + ) + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Functional Description: + + This routine routine will execute a command on the card after making + sure the previous command has completed properly. + +Parameters: + + Adapter _ A pointer ot our adapter information structure. + + CardLine _ Specifies which line to use for the transmit (HTDSU_LINEx_ID). + + CommandValue _ HTDSU_CMD_??? command to be executed. + +Return Values: + + NDIS_STATUS_SUCCESS + NDIS_STATUS_HARD_ERRORS + +---------------------------------------------------------------------------*/ +{ + DBG_FUNC("CardDoCommand") + + ULONG TimeOut = 0; + + DBG_ENTER(Adapter); + DBG_FILTER(Adapter, DBG_PARAMS_ON,("Line=%d, Command=%04X, LineStatus=%Xh\n", + CardLine, CommandValue, + READ_REGISTER_USHORT(&Adapter->AdapterRam->StatusLine1) + )); + + /* + // Wait for command register to go idle - but don't wait too long. + // If we timeout here, there's gotta be something wrong with the adapter. + */ + while ((READ_REGISTER_USHORT(&Adapter->AdapterRam->Command) != + HTDSU_CMD_NOP) || + (READ_REGISTER_USHORT(&Adapter->AdapterRam->CoProcessorId) != + HTDSU_COPROCESSOR_ID)) + { + if (TimeOut++ > HTDSU_SELFTEST_TIMEOUT) + { + DBG_ERROR(Adapter,("Timeout waiting for %04X command to clear\n", + READ_REGISTER_USHORT(&Adapter->AdapterRam->Command))); + /* + // Ask for reset, and disable interrupts until we get it. + */ + Adapter->NeedReset = TRUE; + Adapter->InterruptEnableFlag = HTDSU_INTR_DISABLE; + CardDisableInterrupt(Adapter); + + return (NDIS_STATUS_HARD_ERRORS); + } + NdisStallExecution(_100_MICROSECONDS); + } + DBG_NOTICE(Adapter,("Timeout=%d waiting to submit %04X\n", + TimeOut, CommandValue)); + + /* + // Before starting a reset command, we clear the the co-processor ID + // which then gets set to the proper value when the reset is complete. + */ + if (CommandValue == HTDSU_CMD_RESET) + { + WRITE_REGISTER_USHORT(&Adapter->AdapterRam->CoProcessorId, 0); + } + + /* + // Send the command to the adapter. + */ + WRITE_REGISTER_USHORT( + &Adapter->AdapterRam->Command, + (USHORT) (CommandValue + CardLine) + ); + + DBG_LEAVE(Adapter); + + return (NDIS_STATUS_SUCCESS); +} + + +NDIS_STATUS +CardInitialize( + IN PHTDSU_ADAPTER Adapter, + IN BOOLEAN PerformSelfTest + ) + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Functional Description: + + This routine will attempt to initialize the controller, but will not + enable transmits or receives. + +Parameters: + + Adapter _ A pointer ot our adapter information structure. + + PerformSelfTest _ TRUE if caller wants to run selftest diagnostics. + This normally takes about 4 seconds to complete, so you + wouldn't want to do it every time you start up. + +Return Values: + + NDIS_STATUS_HARD_ERRORS + NDIS_STATUS_SUCCESS + +---------------------------------------------------------------------------*/ + +{ + DBG_FUNC("CardInitialize") + + NDIS_STATUS Status; + + USHORT SelfTestStatus; + + UINT TimeOut; + + DBG_ENTER(Adapter); + + /* + // First we make sure the adapter is where we think it is. + */ + Status = CardIdentify(Adapter); + if (Status != NDIS_STATUS_SUCCESS) + { + return (Status); + } + + /* + // Reset the hardware to make sure we're in a known state. + */ + Status = CardDoCommand(Adapter, 0, HTDSU_CMD_RESET); + + if (PerformSelfTest) + { + /* + // Wait for the reset to complete before starting the self-test. + // Then issue the self-test command to see if the adapter firmware + // is happy with the situation. + */ + Status = CardDoCommand(Adapter, 0, HTDSU_CMD_SELFTEST); + if (Status != NDIS_STATUS_SUCCESS) + { + DBG_ERROR(Adapter,("Failed HTDSU_CMD_RESET\n")); + /* + // Log error message and return. + */ + NdisWriteErrorLogEntry( + Adapter->MiniportAdapterHandle, + NDIS_ERROR_CODE_HARDWARE_FAILURE, + 3, + Status, + __FILEID__, + __LINE__ + ); + return (Status); + } + + /* + // Wait for the self test to complete, but don't wait forever. + */ + TimeOut = 0; + while (Status == NDIS_STATUS_SUCCESS && + READ_REGISTER_USHORT(&Adapter->AdapterRam->Command) != + HTDSU_CMD_NOP) + { + if (TimeOut++ > HTDSU_SELFTEST_TIMEOUT) + { + DBG_ERROR(Adapter,("Timeout waiting for SELFTEST to complete\n")); + Status = NDIS_STATUS_HARD_ERRORS; + } + else + { + NdisStallExecution(_100_MICROSECONDS); + } + } + if (Status != NDIS_STATUS_SUCCESS) + { + DBG_ERROR(Adapter,("Failed HTDSU_CMD_SELFTEST\n")); + /* + // Log error message and return. + */ + NdisWriteErrorLogEntry( + Adapter->MiniportAdapterHandle, + NDIS_ERROR_CODE_HARDWARE_FAILURE, + 3, + Status, + __FILEID__, + __LINE__ + ); + return (Status); + } + + /* + // Verify that self test was successful. + */ + SelfTestStatus = READ_REGISTER_USHORT(&Adapter->AdapterRam->SelfTestStatus); + if (SelfTestStatus != 0 && SelfTestStatus != HTDSU_SELFTEST_OK) + { + DBG_ERROR(Adapter,("Failed HTDSU_CMD_SELFTEST (Status=%X)\n", + SelfTestStatus)); + /* + // Log error message and return. + */ + NdisWriteErrorLogEntry( + Adapter->MiniportAdapterHandle, + NDIS_ERROR_CODE_HARDWARE_FAILURE, + 3, + SelfTestStatus, + __FILEID__, + __LINE__ + ); + return (NDIS_STATUS_HARD_ERRORS); + } + } + + DBG_LEAVE(Adapter); + + return (NDIS_STATUS_SUCCESS); +} + + +VOID +CardLineConfig( + IN PHTDSU_ADAPTER Adapter, + IN USHORT CardLine /* HTDSU_CMD_LINE1 or HTDSU_CMD_LINE2 */ + ) + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Functional Description: + + This routine will ready the controller to send and receive packets. + +Parameters: + + Adapter _ A pointer ot our adapter information structure. + + CardLine _ Specifies which line to use for the transmit (HTDSU_LINEx_ID). + +Return Values: + + None + +---------------------------------------------------------------------------*/ + +{ + DBG_FUNC("CardLineConfig") + + USHORT ClockCommand; + USHORT LineCommand; + + DBG_ENTER(Adapter); + + ASSERT((CardLine==HTDSU_CMD_LINE1) || (CardLine==HTDSU_CMD_LINE2)); + + /* + // Configure the line for HDLC framing and for leased or dialup mode. + */ + if (Adapter->LineType == HTDSU_LINEMODE_LEASED) + { + ClockCommand = HTDSU_CMD_INTERNAL_TX_CLOCK; + LineCommand = HTDSU_CMD_LEASED_LINE; + } + else + { + ClockCommand = HTDSU_CMD_DDS_TX_CLOCK; + LineCommand = HTDSU_CMD_DIALUP_LINE; + } + + CardDoCommand(Adapter, CardLine, ClockCommand); + CardDoCommand(Adapter, CardLine, HTDSU_CMD_HDLC_PROTOCOL); + CardDoCommand(Adapter, CardLine, LineCommand); + CardDoCommand(Adapter, CardLine, Adapter->LineRate); + + /* + // Clear any pending interrupts. + */ + CardDoCommand(Adapter, 0, HTDSU_CMD_CLEAR_INTERRUPT); + CardClearInterrupt(Adapter); + + DBG_LEAVE(Adapter); +} + + +VOID +CardLineDisconnect( + IN PHTDSU_ADAPTER Adapter, + IN USHORT CardLine /* HTDSU_CMD_LINE1 or HTDSU_CMD_LINE2 */ + ) + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Functional Description: + + This routine will disconnect any call currently on the line. + +Parameters: + + Adapter _ A pointer ot our adapter information structure. + + CardLine _ Specifies which line to use for the transmit (HTDSU_LINEx_ID). + +Return Values: + + None + +---------------------------------------------------------------------------*/ + +{ + DBG_FUNC("CardLineDisconnect") + + DBG_ENTER(Adapter); + + ASSERT((CardLine==HTDSU_CMD_LINE1) || (CardLine==HTDSU_CMD_LINE2)); + + /* + // Disconnect the line and reconfigure the line for next time. + */ + CardDoCommand(Adapter, CardLine, HTDSU_CMD_DISCONNECT); + CardLineConfig(Adapter, CardLine); + + DBG_LEAVE(Adapter); +} + + +VOID +CardPrepareTransmit( + IN PHTDSU_ADAPTER Adapter, + IN USHORT CardLine, /* HTDSU_CMD_LINE1 or HTDSU_CMD_LINE2 */ + IN USHORT BytesToSend + ) + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Functional Description: + + This routine will write the packet header information into the + transmit buffer. This assumes that the controller has notified the + driver that the transmit buffer is empty. + +Parameters: + + Adapter _ A pointer ot our adapter information structure. + + CardLine _ Specifies which line to use for the transmit (HTDSU_LINEx_ID). + + BytesToSend _ Number of bytes to transmit. + +Return Values: + + None + +---------------------------------------------------------------------------*/ + +{ + DBG_FUNC("CardPrepareTransmit") + + DBG_ENTER(Adapter); + + ASSERT((CardLine==HTDSU_CMD_LINE1) || (CardLine==HTDSU_CMD_LINE2)); + ASSERT(READ_REGISTER_USHORT(&Adapter->AdapterRam->TxDataEmpty)); + ASSERT(BytesToSend > 0); + + /* + // Tell the adapter how many bytes are to be sent, and which line to use. + */ + WRITE_REGISTER_USHORT( + &Adapter->AdapterRam->TxBuffer.Address, + (USHORT) (CardLine - HTDSU_CMD_LINE1) + ); + WRITE_REGISTER_USHORT( + &Adapter->AdapterRam->TxBuffer.Length, + BytesToSend + ); + + /* + // Mark the end of packet and end of packet list. + */ + WRITE_REGISTER_USHORT( + &Adapter->AdapterRam->TxBuffer.Data[(BytesToSend+1)/sizeof(USHORT)], + HTDSU_DATA_TERMINATOR + ); + WRITE_REGISTER_USHORT( + &Adapter->AdapterRam->TxBuffer.Data[(BytesToSend+3)/sizeof(USHORT)], + HTDSU_DATA_TERMINATOR + ); + + DBG_LEAVE(Adapter); +} + + +VOID +CardGetReceiveInfo( + IN PHTDSU_ADAPTER Adapter, + OUT PUSHORT CardLine, /* HTDSU_CMD_LINE1 or HTDSU_CMD_LINE2 */ + OUT PUSHORT BytesReceived, + OUT PUSHORT RxErrors + ) + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Functional Description: + + This routine will retrieve the packet header information from the + receive buffer. This assumes that the controller has notified the + driver that a packet has been received. + +Parameters: + + Adapter _ A pointer ot our adapter information structure. + + CardLine _ Specifies which line the packet was received on (HTDSU_LINEx_ID). + + BytesReceived _ Number of bytes received. + + RxErrors _ Receive error flags non-zero if packet has errors. + +Return Values: + + None + +---------------------------------------------------------------------------*/ +{ + DBG_FUNC("CardGetReceiveInfo") + + USHORT Length; + + DBG_ENTER(Adapter); + + /* + // This should be true if we're here, but there are race conditions + // on hangup where I've seen this condition hit. + */ + if (READ_REGISTER_USHORT(&Adapter->AdapterRam->RxDataAvailable) == 0) + { + *RxErrors = 0; + *BytesReceived = 0; + *CardLine = HTDSU_CMD_LINE1; // Don't return a bad line # + } + else + { + /* + // The length field tells us how many bytes are in the packet, and + // the most significant bit tells us whether the packet has a CRC error. + */ + Length = READ_REGISTER_USHORT(&Adapter->AdapterRam->RxBuffer.Length); + *BytesReceived = Length & ~HTDSU_CRC_ERROR; + *RxErrors = Length & HTDSU_CRC_ERROR; + + /* + // The least significant nibble of the address tells us what line the + // packet was received on -- at least it better... + */ + *CardLine = (READ_REGISTER_USHORT( + &Adapter->AdapterRam->RxBuffer.Address) & + 0x000F) + HTDSU_CMD_LINE1; + + if ((*CardLine != HTDSU_CMD_LINE1) && (*CardLine != HTDSU_CMD_LINE2)) + { + *RxErrors |= HTDSU_RX_ERROR; + *CardLine = HTDSU_CMD_LINE1; // Don't return a bad line # + } + else if (*BytesReceived > HTDSU_MAX_PACKET_SIZE) + { + *RxErrors |= HTDSU_RX_ERROR; + } + } + + DBG_LEAVE(Adapter); +} + + +VOID +CardDialNumber( + IN PHTDSU_ADAPTER Adapter, + IN USHORT CardLine, /* HTDSU_CMD_LINE1 or HTDSU_CMD_LINE2 */ + IN PUCHAR DialString, + IN ULONG DialStringLength + ) + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Functional Description: + + Place a dial string on the adapter and start the dialing sequence. + +Parameters: + + Adapter _ A pointer ot our adapter information structure. + + CardLine _ Specifies which line to use for the transmit (HTDSU_LINEx_ID). + + DialString _ A pointer to an ASCII null-terminated string of digits. + + DialStringLength _ Number of bytes in dial string. + +Return Values: + + None + +---------------------------------------------------------------------------*/ + +{ + DBG_FUNC("CardDialNumber") + + UINT Index; + UINT NumDigits; + + PUSHORT DialRam; + + DBG_ENTER(Adapter); + + ASSERT(READ_REGISTER_USHORT(&Adapter->AdapterRam->TxDataEmpty)); + ASSERT(READ_REGISTER_USHORT(&Adapter->AdapterRam->Command) == HTDSU_CMD_NOP); + + /* + // Copy the digits to be dialed onto the adapter. + // The adapter interprets phone numbers as high byte is valid digit, + // low byte is ignored, the last digit gets bit 15 set. + */ + DialRam = (PUSHORT) &Adapter->AdapterRam->TxBuffer; + + for (NumDigits = Index = 0; Index < DialStringLength && *DialString; Index++) + { + if ((*DialString >= '0') && (*DialString <= '9')) + { + WRITE_REGISTER_USHORT( + DialRam, + (USHORT) ((*DialString - '0') << 8) + ); + DialRam++; + + /* + // Make sure dial string is within the limit of the adapter. + */ + if (++NumDigits >= HTDSU_MAX_DIALING_DIGITS) + { + break; + } + } + DialString++; + } + + /* + // Set the MSB in the last digit. + */ + DialRam--; + WRITE_REGISTER_USHORT( + DialRam, + (USHORT) (READ_REGISTER_USHORT(DialRam) | 0x8000) + ); + + /* + // Initiate the dial sequence. + */ + CardDoCommand(Adapter, CardLine, HTDSU_CMD_DIAL); + + DBG_LEAVE(Adapter); +} + -- cgit v1.2.3