/* create a new cm object */ cm_create(VOID **ret_cm, NDIS_HANDLE AdapterHandle) { NDIS_PHYSICAL_ADDRESS pa = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); INT n; D_LOG(D_ENTRY, ("cm_create: entry, ret_cm: 0x%p", ret_cm)); /* allocate memory object */ NdisAllocateMemory((PVOID*)ret_cm, sizeof(CM), 0, pa); if ( *ret_cm == NULL ) { D_LOG(D_ALWAYS, ("cm_create: memory allocate failed!")); NdisWriteErrorLogEntry (AdapterHandle, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 0); return(CM_E_NOMEM); } D_LOG(D_ALWAYS, ("cm_create: cm: 0x%x", *ret_cm)); NdisZeroMemory(*ret_cm, sizeof(CM)); /* allocate connection out of local table */ for ( n = 0 ; n < MAX_CM_IN_SYSTEM ; n++ ) if ( !cm_used[n] ) break; if ( n >= MAX_CM_IN_SYSTEM ) { /* free memory */ NdisFreeMemory(*ret_cm, sizeof(CM), 0); return(CM_E_NOSLOT); } /* initialize */ cm_used[n] = 1; cm_tbl[n] = *ret_cm; ((CM*)*ret_cm)->local_conn_index = n; /* return */ return(CM_E_SUCC); }
NDIS_STATUS MPReset( NDIS_HANDLE MiniportAdapterContext, PBOOLEAN AddressingReset ) { PADAPTER adapter = (PADAPTER)MiniportAdapterContext; NDIS_STATUS ndisStatus = NDIS_STATUS_PENDING; NDIS_HANDLE workitemHandle; *AddressingReset = TRUE; #if DBG if (adapter->Debug_BreakOnReset) { DbgPrint("Received NdisReset\n"); DbgBreakPoint(); } #endif do { // // Set the flag so that other routines stop proceeding // MP_SET_ADAPTER_STATUS(adapter, MP_ADAPTER_IN_RESET); // // If our halt handler has been called, we should not reset // if (MP_TEST_ADAPTER_STATUS(adapter, MP_ADAPTER_HALTING)) { MPASSERT(FALSE); // Would be an interesting scenario to investigate ndisStatus = NDIS_STATUS_SUCCESS; break; } // // Handle the reset asynchronously since we can be called at either dispatch // or passive IRQL // workitemHandle = NdisAllocateIoWorkItem(adapter->MiniportAdapterHandle); if(workitemHandle == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate Reset workitem\n")); NdisWriteErrorLogEntry(adapter->MiniportAdapterHandle, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 0 ); ndisStatus = NDIS_STATUS_RESOURCES; break; } // Queue the workitem NdisQueueIoWorkItem(workitemHandle, MpResetWorkItem, adapter ); } while (FALSE); if (ndisStatus != NDIS_STATUS_PENDING) { // Something failed, clear the in reset flag MP_CLEAR_ADAPTER_STATUS(adapter, MP_ADAPTER_IN_RESET); } return ndisStatus; }
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 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); }
extern NDIS_STATUS IbmtokTransferData( IN NDIS_HANDLE MacBindingHandle, IN NDIS_HANDLE MacReceiveContext, IN UINT ByteOffset, IN UINT BytesToTransfer, OUT PNDIS_PACKET Packet, OUT PUINT BytesTransferred ) /*++ Routine Description: A protocol calls the IbmtokTransferData request (indirectly via NdisTransferData) from within its Receive event handler to instruct the MAC to copy the contents of the received packet a specified packet buffer. Arguments: MacBindingHandle - The context value returned by the MAC when the adapter was opened. In reality this is a pointer to IBMTOK. MacReceiveContext - The context value passed by the MAC on its call to NdisIndicateReceive. The MAC can use this value to determine which packet, on which adapter, is being received. ByteOffset - An unsigned integer specifying the offset within the received packet at which the copy is to begin. If the entire packet is to be copied, ByteOffset must be zero. BytesToTransfer - An unsigned integer specifying the number of bytes to copy. It is legal to transfer zero bytes; this has no effect. If the sum of ByteOffset and BytesToTransfer is greater than the size of the received packet, then the remainder of the packet (starting from ByteOffset) is transferred, and the trailing portion of the receive buffer is not modified. Packet - A pointer to a descriptor for the packet storage into which the MAC is to copy the received packet. BytesTransfered - A pointer to an unsigned integer. The MAC writes the actual number of bytes transferred into this location. This value is not valid if the return status is STATUS_PENDING. Return Value: The function value is the status of the operation. --*/ { PIBMTOK_ADAPTER Adapter; NDIS_STATUS StatusToReturn; Adapter = PIBMTOK_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle); NdisAcquireSpinLock(&Adapter->Lock); Adapter->References++; if (!Adapter->NotAcceptingRequests) { PIBMTOK_OPEN Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle); if (!Open->BindingShuttingDown) { // // The code in this section is quite similar to the // code in CopyFromPacketToPacket. It could easily go // into its own routine, except that it is not likely // to be used in any other implementation. // SRAM_PTR SourceReceiveBuffer = Adapter->IndicatedReceiveBuffer; // // Holds the count of the number of ndis buffers comprising // the destination packet. // UINT DestinationBufferCount; // // Points to the buffer into which we are putting data. // PNDIS_BUFFER DestinationCurrentBuffer; // // Holds the virtual address of the current destination // buffer. // PVOID DestinationVirtualAddress; // // Holds the virtual address of the current source buffer. // PRECEIVE_BUFFER SourceBufferAddress; // // Holds the address of the data in the current source buffer. // PVOID SourceVirtualAddress; // // Holds the length of the current destination buffer. // UINT DestinationCurrentLength; // // Holds the length of the current source buffer. // UINT SourceCurrentLength; // // Keep a local variable of BytesTransferred so we aren't // referencing through a pointer. // UINT LocalBytesTransferred = 0; USHORT PortValue; Open->References++; NdisReleaseSpinLock(&Adapter->Lock); *BytesTransferred = 0; ASSERT(sizeof(UINT) >= 2); ASSERT(sizeof(UINT) == sizeof(NDIS_HANDLE)); // // Get the first buffer of the destination. // NdisQueryPacket( Packet, NULL, &DestinationBufferCount, &DestinationCurrentBuffer, NULL ); // // Could have a null packet. // if (DestinationBufferCount != 0) { NdisQueryBuffer( DestinationCurrentBuffer, &DestinationVirtualAddress, &DestinationCurrentLength ); // // Get the information for the first buffer of the source. // SourceBufferAddress = (PRECEIVE_BUFFER) ((PUCHAR)SRAM_PTR_TO_PVOID(Adapter, SourceReceiveBuffer) + 2); // // Adjust the address and length to account for the // header for this frame. // SourceVirtualAddress = SourceBufferAddress->FrameData + Adapter->IndicatedHeaderLength; NdisReadRegisterUshort(&SourceBufferAddress->BufferLength, &PortValue ); SourceCurrentLength = IBMSHORT_TO_USHORT(PortValue) - Adapter->IndicatedHeaderLength; // // Take care of boundary condition of zero length copy. // while (LocalBytesTransferred < BytesToTransfer) { // // Check to see whether we've exhausted the current // destination buffer. If so, move onto the next one. // if (!DestinationCurrentLength) { NdisGetNextBuffer( DestinationCurrentBuffer, &DestinationCurrentBuffer ); if (!DestinationCurrentBuffer) { // // We've reached the end of the packet. We // return with what we've done so far. (Which // must be shorter than requested.) // break; } NdisQueryBuffer( DestinationCurrentBuffer, &DestinationVirtualAddress, &DestinationCurrentLength ); continue; } // // Check to see whether we've exhausted the current // source buffer. If so, move onto the next one. // if (!SourceCurrentLength) { NdisReadRegisterUshort( &SourceBufferAddress->NextBuffer, &SourceReceiveBuffer ); if (SourceReceiveBuffer == NULL_SRAM_PTR) { // // We've reached the end of the frame. We // return with what we've done so far. (Which // must be shorter than requested.) // break; } SourceBufferAddress = (PRECEIVE_BUFFER) SRAM_PTR_TO_PVOID(Adapter, SourceReceiveBuffer); SourceVirtualAddress = (PVOID)SourceBufferAddress->FrameData; NdisReadRegisterUshort( &SourceBufferAddress->BufferLength, &SourceCurrentLength ); SourceCurrentLength = IBMSHORT_TO_USHORT( SourceCurrentLength ); continue; } // // Try to get us up to the point to start the copy. // if (ByteOffset) { if (ByteOffset > SourceCurrentLength) { // // What we want isn't in this buffer. // ByteOffset -= SourceCurrentLength; SourceCurrentLength = 0; continue; } else { SourceVirtualAddress = (PCHAR)SourceVirtualAddress + ByteOffset; SourceCurrentLength -= ByteOffset; ByteOffset = 0; } } // // Copy the data. // { // // Holds the amount of data to move. // UINT AmountToMove; // // Holds the amount desired remaining. // UINT Remaining = BytesToTransfer - LocalBytesTransferred; AmountToMove = ((SourceCurrentLength <= DestinationCurrentLength)? (SourceCurrentLength):(DestinationCurrentLength)); AmountToMove = ((Remaining < AmountToMove)? (Remaining):(AmountToMove)); IBMTOK_MOVE_FROM_MAPPED_MEMORY( DestinationVirtualAddress, SourceVirtualAddress, AmountToMove ); DestinationVirtualAddress = (PCHAR)DestinationVirtualAddress + AmountToMove; SourceVirtualAddress = (PCHAR)SourceVirtualAddress + AmountToMove; LocalBytesTransferred += AmountToMove; SourceCurrentLength -= AmountToMove; DestinationCurrentLength -= AmountToMove; } } *BytesTransferred = LocalBytesTransferred; } NdisAcquireSpinLock(&Adapter->Lock); Open->References--; StatusToReturn = NDIS_STATUS_SUCCESS; } else { StatusToReturn = NDIS_STATUS_REQUEST_ABORTED; } } else { if (Adapter->ResetInProgress) { StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS; } else if (Adapter->OpenInProgress) { StatusToReturn = NDIS_STATUS_FAILURE; } else { NdisWriteErrorLogEntry( Adapter->NdisAdapterHandle, NDIS_ERROR_CODE_DRIVER_FAILURE, 2, IBMTOK_ERRMSG_INVALID_STATE, 1 ); } } IBMTOK_DO_DEFERRED(Adapter); return StatusToReturn; }
VOID NE3200ResetHandler( IN PVOID SystemSpecific1, IN PNE3200_ADAPTER Adapter, IN PVOID SystemSpecific2, IN PVOID SystemSpecific3 ) /*++ Routine Description: This manages the reset/download process. It is responsible for resetting the adapter, waiting for proper status, downloading MAC.BIN, waiting for MAC.BIN initialization, and optionally sending indications to the appropriate protocol. Since the NE3200's status registers must be polled during the reset/download process, this is implemented as a state machine. Arguments: Adapter - The adapter whose hardware is to be initialized. Return Value: None. --*/ { // // Physical address of the MAC.BIN buffer. // NDIS_PHYSICAL_ADDRESS MacBinPhysicalAddress; // // Status from the adapter. // UCHAR Status; // // Simple iteration counter. // UINT i; // // Loop until the reset has completed. // while (Adapter->ResetState != NE3200ResetStateComplete) { switch (Adapter->ResetState) { // // The first stage of resetting an NE3200 // case NE3200ResetStateStarting : // // Unfortunately, a hardware reset to the NE3200 does *not* // reset the BMIC chip. To ensure that we read a proper status, // we'll clear all of the BMIC's registers. // NE3200_WRITE_SYSTEM_INTERRUPT( Adapter, 0 ); // // I changed this to ff since the original 0 didn't work for // some cases. since we don't have the specs.... // NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT( Adapter, 0xff ); NE3200_WRITE_SYSTEM_DOORBELL_MASK( Adapter, 0 ); NE3200_SYNC_CLEAR_SYSTEM_DOORBELL_INTERRUPT( Adapter ); for (i = 0 ; i < 16 ; i += 4 ) { NE3200_WRITE_MAILBOX_ULONG( Adapter, i, 0L ); } // // Toggle the NE3200's reset line. // NE3200_WRITE_RESET( Adapter, NE3200_RESET_BIT_ON ); NE3200_WRITE_RESET( Adapter, NE3200_RESET_BIT_OFF ); // // Switch to the next state. // Adapter->ResetState = NE3200ResetStateResetting; Adapter->ResetTimeoutCounter = NE3200_TIMEOUT_RESET; // // Loop to the next processing // break; // // Part Deux. The actual downloading of the software. // case NE3200ResetStateResetting : // // Read the status mailbox. // NE3200_READ_MAILBOX_UCHAR(Adapter, NE3200_MAILBOX_RESET_STATUS, &Status); if (Status == NE3200_RESET_PASSED) { // // We have good reset. Initiate the MAC.BIN download. // // // The station address for this adapter can be forced to // a specific value at initialization time. When MAC.BIN // first gets control, it reads mailbox 10. If this mailbox // contains a 0xFF, then the burned-in PROM station address // is used. If this mailbox contains any value other than // 0xFF, then mailboxes 10-15 are read. The six bytes // stored in these mailboxes then become the station address. // // Since we have no need for this feature, we will always // initialize mailbox 10 with a 0xFF. // NE3200_WRITE_MAILBOX_UCHAR( Adapter, NE3200_MAILBOX_STATION_ID, 0xFF ); // // Get the MAC.BIN buffer. // MacBinPhysicalAddress = NE3200Globals.MacBinPhysicalAddress; // // Download MAC.BIN to the card. // NE3200_WRITE_MAILBOX_USHORT( Adapter, NE3200_MAILBOX_MACBIN_LENGTH, NE3200Globals.MacBinLength ); NE3200_WRITE_MAILBOX_UCHAR( Adapter, NE3200_MAILBOX_MACBIN_DOWNLOAD_MODE, NE3200_MACBIN_DIRECT ); NE3200_WRITE_MAILBOX_ULONG( Adapter, NE3200_MAILBOX_MACBIN_POINTER, NdisGetPhysicalAddressLow(MacBinPhysicalAddress) ); NE3200_WRITE_MAILBOX_USHORT( Adapter, NE3200_MAILBOX_MACBIN_TARGET, NE3200_MACBIN_TARGET_ADDRESS >> 1 ); // // This next OUT "kicks" the loader into action. // NE3200_WRITE_MAILBOX_UCHAR( Adapter, NE3200_MAILBOX_RESET_STATUS, 0 ); // // Switch to the next state. // Adapter->ResetState = NE3200ResetStateDownloading; Adapter->ResetTimeoutCounter = NE3200_TIMEOUT_DOWNLOAD; // // Loop to the next state. // } else if (Status == NE3200_RESET_FAILED) { // // Reset failure. Notify the authorities and // next of kin. // Adapter->ResetResult = NE3200ResetResultResetFailure; Adapter->ResetState = NE3200ResetStateComplete; NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS); } else { // // Still waiting for results, check if we have // timed out waiting. // Adapter->ResetTimeoutCounter--; if (Adapter->ResetTimeoutCounter == 0) { // // We've timed-out. Bad news. Notify the death. // Adapter->ResetResult = NE3200ResetResultResetTimeout; Adapter->ResetState = NE3200ResetStateComplete; NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS); } else { // // For Synchronous resets, we stall. For async, // we set a timer to check later. // if (!Adapter->ResetAsynchronous) { // // Otherwise, wait and try again. // NdisStallExecution(10000); } else{ // // Try again later. // NdisMSetTimer(&Adapter->ResetTimer, 100); return; } } } break; // // Part Three: The download was started. Check for completion, // and reload the current station address. // case NE3200ResetStateDownloading : // // Read the download status. // NE3200_READ_MAILBOX_UCHAR(Adapter, NE3200_MAILBOX_STATUS, &Status); if (Status == NE3200_INITIALIZATION_PASSED) { // // According to documentation from Compaq, this next port // write will (in a future MAC.BIN) tell MAC.BIN whether or // not to handle loopback internally. This value is currently // not used, but must still be written to the port. // NE3200_WRITE_MAILBOX_UCHAR( Adapter, NE3200_MAILBOX_STATUS, 1 ); // // Initialization is good, the card is ready. // NE3200StartChipAndDisableInterrupts(Adapter, Adapter->ReceiveQueueHead ); { // // Do the work for updating the current address // // // This points to the public Command Block. // PNE3200_SUPER_COMMAND_BLOCK CommandBlock; // // This points to the adapter's configuration block. // PNE3200_CONFIGURATION_BLOCK ConfigurationBlock = Adapter->ConfigurationBlock; // // Get a public command block. // NE3200AcquirePublicCommandBlock(Adapter, &CommandBlock ); Adapter->ResetHandlerCommandBlock = CommandBlock; // // Setup the command block. // CommandBlock->NextCommand = NULL; CommandBlock->Hardware.State = NE3200_STATE_WAIT_FOR_ADAPTER; CommandBlock->Hardware.Status = 0; CommandBlock->Hardware.NextPending = NE3200_NULL; CommandBlock->Hardware.CommandCode = NE3200_COMMAND_CONFIGURE_82586; CommandBlock->Hardware.PARAMETERS.CONFIGURE.ConfigurationBlock = NdisGetPhysicalAddressLow(Adapter->ConfigurationBlockPhysical); // // Now that we've got the command block built, // let's do it! // NE3200SubmitCommandBlock(Adapter, CommandBlock); Adapter->ResetState = NE3200ResetStateReloadAddress; Adapter->ResetTimeoutCounter = NE3200_TIMEOUT_DOWNLOAD; } } else if (Status == NE3200_INITIALIZATION_FAILED) { // // Initialization failed. Notify the wrapper. // Adapter->ResetResult = NE3200ResetResultInitializationFailure; Adapter->ResetState = NE3200ResetStateComplete; NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS); } else { // // See if we've timed-out waiting for the download to // complete. // Adapter->ResetTimeoutCounter--; if (Adapter->ResetTimeoutCounter == 0) { // // We've timed-out. Bad news. // Adapter->ResetResult = NE3200ResetResultInitializationTimeout; Adapter->ResetState = NE3200ResetStateComplete; NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS); } else { // // For Synchronous resets, we stall. For async, // we set a timer to check later. // if (!Adapter->ResetAsynchronous) { // // Otherwise, wait and try again. // NdisStallExecution(10000); } else{ // // Try again later. // NdisMSetTimer(&Adapter->ResetTimer, 100); return; } } } break; // // Part Last: Waiting for the configuring of the adapter // to complete // case NE3200ResetStateReloadAddress : // // Read the command block status. // if (Adapter->ResetHandlerCommandBlock->Hardware.State == NE3200_STATE_EXECUTION_COMPLETE) { // // return this command block // NE3200RelinquishCommandBlock(Adapter, Adapter->ResetHandlerCommandBlock ); // // Reset is complete. Do those indications. // Adapter->ResetResult = NE3200ResetResultSuccessful; Adapter->ResetState = NE3200ResetStateComplete; NE3200DoResetIndications(Adapter, NDIS_STATUS_SUCCESS); } else { // // See if we've timed-out. // Adapter->ResetTimeoutCounter--; if (Adapter->ResetTimeoutCounter == 0) { // // We've timed-out. Bad news. // // // return this command block // NE3200RelinquishCommandBlock(Adapter, Adapter->ResetHandlerCommandBlock ); Adapter->ResetResult = NE3200ResetResultInitializationTimeout; Adapter->ResetState = NE3200ResetStateComplete; NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS); } else { if ( Adapter->ResetTimeoutCounter == (NE3200_TIMEOUT_DOWNLOAD/2) ) { // // The command may have stalled, try again. // NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT( Adapter, NE3200_LOCAL_DOORBELL_NEW_COMMAND ); } // // For Synchronous resets, we stall. For async, // we set a timer to check later. // if (!Adapter->ResetAsynchronous) { // // Otherwise, wait and try again. // NdisStallExecution(10000); } else{ // // Check again later // NdisMSetTimer(&Adapter->ResetTimer, 100); return; } } } break; default : // // Somehow, we reached an invalid state. // // // We'll try to salvage our way out of this. // Adapter->ResetResult = NE3200ResetResultInvalidState; Adapter->ResetState = NE3200ResetStateComplete; NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS); NdisWriteErrorLogEntry( Adapter->MiniportAdapterHandle, NDIS_ERROR_CODE_HARDWARE_FAILURE, 3, resetDpc, NE3200_ERRMSG_BAD_STATE, (ULONG)(Adapter->ResetState) ); break; }
NDIS_STATUS RTMPAllocTxRxRingMemory( IN PRTMP_ADAPTER pAd) { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; ULONG RingBasePaHigh; ULONG RingBasePaLow; PVOID RingBaseVa; INT index, num; PTXD_STRUC pTxD; PRXD_STRUC pRxD; ULONG ErrorValue = 0; PRTMP_TX_RING pTxRing; PRTMP_DMABUF pDmaBuf; PNDIS_PACKET pPacket; DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); do { for (num=0; num<NUM_OF_TX_RING; num++) { ULONG BufBasePaHigh; ULONG BufBasePaLow; PVOID BufBaseVa; pAd->TxDescRing[num].AllocSize = TX_RING_SIZE * TXD_SIZE; RTMP_AllocateTxDescMemory( pAd, num, pAd->TxDescRing[num].AllocSize, FALSE, &pAd->TxDescRing[num].AllocVa, &pAd->TxDescRing[num].AllocPa); if (pAd->TxDescRing[num].AllocVa == NULL) { ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; DBGPRINT_ERR(("Failed to allocate a big buffer\n")); Status = NDIS_STATUS_RESOURCES; break; } NdisZeroMemory(pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocSize); RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxDescRing[num].AllocPa); RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxDescRing[num].AllocPa); RingBaseVa = pAd->TxDescRing[num].AllocVa; pAd->TxBufSpace[num].AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE; RTMP_AllocateFirstTxBuffer( pAd, num, pAd->TxBufSpace[num].AllocSize, FALSE, &pAd->TxBufSpace[num].AllocVa, &pAd->TxBufSpace[num].AllocPa); if (pAd->TxBufSpace[num].AllocVa == NULL) { ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; DBGPRINT_ERR(("Failed to allocate a big buffer\n")); Status = NDIS_STATUS_RESOURCES; break; } NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocSize); BufBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num].AllocPa); BufBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxBufSpace[num].AllocPa); BufBaseVa = pAd->TxBufSpace[num].AllocVa; pTxRing = &pAd->TxRing[num]; for (index = 0; index < TX_RING_SIZE; index++) { pTxRing->Cell[index].pNdisPacket = NULL; pTxRing->Cell[index].pNextNdisPacket = NULL; pTxRing->Cell[index].AllocSize = TXD_SIZE; pTxRing->Cell[index].AllocVa = RingBaseVa; RTMP_SetPhysicalAddressHigh(pTxRing->Cell[index].AllocPa, RingBasePaHigh); RTMP_SetPhysicalAddressLow (pTxRing->Cell[index].AllocPa, RingBasePaLow); pDmaBuf = &pTxRing->Cell[index].DmaBuf; pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE; pDmaBuf->AllocVa = BufBaseVa; RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, BufBasePaHigh); RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow); pTxD = (PTXD_STRUC) pTxRing->Cell[index].AllocVa; pTxD->SDPtr0 = BufBasePaLow; pTxD->DMADONE = 1; RingBasePaLow += TXD_SIZE; RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE; BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE; } DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry allocated\n", num, index)); } if (Status == NDIS_STATUS_RESOURCES) break; pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE; RTMP_AllocateMgmtDescMemory( pAd, pAd->MgmtDescRing.AllocSize, FALSE, &pAd->MgmtDescRing.AllocVa, &pAd->MgmtDescRing.AllocPa); if (pAd->MgmtDescRing.AllocVa == NULL) { ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; DBGPRINT_ERR(("Failed to allocate a big buffer\n")); Status = NDIS_STATUS_RESOURCES; break; } NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize); RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa); RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->MgmtDescRing.AllocPa); RingBaseVa = pAd->MgmtDescRing.AllocVa; for (index = 0; index < MGMT_RING_SIZE; index++) { pAd->MgmtRing.Cell[index].pNdisPacket = NULL; pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL; pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE; pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa; RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index].AllocPa, RingBasePaHigh); RTMP_SetPhysicalAddressLow (pAd->MgmtRing.Cell[index].AllocPa, RingBasePaLow); RingBasePaLow += TXD_SIZE; RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[index].AllocVa; pTxD->DMADONE = 1; } DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", index)); pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE; RTMP_AllocateRxDescMemory( pAd, pAd->RxDescRing.AllocSize, FALSE, &pAd->RxDescRing.AllocVa, &pAd->RxDescRing.AllocPa); if (pAd->RxDescRing.AllocVa == NULL) { ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; DBGPRINT_ERR(("Failed to allocate a big buffer\n")); Status = NDIS_STATUS_RESOURCES; break; } NdisZeroMemory(pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize); printk("RX DESC %p size = %ld\n", pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize); RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa); RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->RxDescRing.AllocPa); RingBaseVa = pAd->RxDescRing.AllocVa; for (index = 0; index < RX_RING_SIZE; index++) { pAd->RxRing.Cell[index].AllocSize = RXD_SIZE; pAd->RxRing.Cell[index].AllocVa = RingBaseVa; RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index].AllocPa, RingBasePaHigh); RTMP_SetPhysicalAddressLow (pAd->RxRing.Cell[index].AllocPa, RingBasePaLow); RingBasePaLow += RXD_SIZE; RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE; pDmaBuf = &pAd->RxRing.Cell[index].DmaBuf; pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE; pPacket = RTMP_AllocateRxPacketBuffer( pAd, pDmaBuf->AllocSize, FALSE, &pDmaBuf->AllocVa, &pDmaBuf->AllocPa); pAd->RxRing.Cell[index].pNdisPacket = pPacket; if (pDmaBuf->AllocVa == NULL) { ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n")); Status = NDIS_STATUS_RESOURCES; break; } NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize); pRxD = (PRXD_STRUC) pAd->RxRing.Cell[index].AllocVa; pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); pRxD->DDONE = 0; } DBGPRINT(RT_DEBUG_TRACE, ("Rx Ring: total %d entry allocated\n", index)); } while (FALSE); NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME)); pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); if (pAd->FragFrame.pFragPacket == NULL) { Status = NDIS_STATUS_RESOURCES; } if (Status != NDIS_STATUS_SUCCESS) { NdisWriteErrorLogEntry( pAd->AdapterHandle, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 1, ErrorValue); } DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); return Status; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Routine Name: NetFlexRingStatus // // Description: // This routine does the clean up work necessary // when a ring status occurs. // // Input: // acb - Our Driver Context for this adapter or head. // // Output: // None // // Called By: // NetFlexHandleInterrupt // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ VOID NetFlexRingStatus( PACB acb ) { USHORT value; ULONG RingStatus = 0; value = acb->acb_ssb_virtptr->SSB_Status; DebugPrint(1,("NF(%d): RingStatus value = %x\n",acb->anum, value)); // // Determine the reason for the ring interrupt. // if (value & RING_STATUS_SIGNAL_LOSS) { RingStatus |= NDIS_RING_SIGNAL_LOSS; DebugPrint(1,("NF(%d): RING_STATUS_SIGNAL_LOSS\n",acb->anum)); // // Have we already reported the error? // if (!acb->SentRingStatusLog && ((acb->acb_lastringstatus & RING_STATUS_SIGNAL_LOSS) == 0)) { // no, so send one. NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_SIGNAL_LOSS_ERROR, 3, NETFLEX_RINGSTATUS_ERROR_CODE, (ULONG) acb->acb_baseaddr, (ULONG) value ); acb->SentRingStatusLog = TRUE; } } if (value & RING_STATUS_HARD_ERROR) { RingStatus |= NDIS_RING_HARD_ERROR; DebugPrint(1,("NF(%d): RING_STATUS_HARD_ERROR\n",acb->anum)); } if (value & RING_STATUS_SOFT_ERROR) { RingStatus |= NDIS_RING_SOFT_ERROR; DebugPrint(1,("NF(%d): RING_STATUS_SOFT_ERROR\n",acb->anum)); } if (value & RING_STATUS_XMIT_BEACON) { RingStatus |= NDIS_RING_TRANSMIT_BEACON; DebugPrint(1,("NF(%d): RING_STATUS_XMIT_BEACON\n",acb->anum)); } if (value & RING_STATUS_LOBE_WIRE_FAULT) { RingStatus |= NDIS_RING_LOBE_WIRE_FAULT; DebugPrint(1,("NF(%d): RING_STATUS_LOBE_WIRE_FAULT\n",acb->anum)); // // Have we already reported the error? // if (!acb->SentRingStatusLog && ((acb->acb_lastringstatus & NDIS_RING_LOBE_WIRE_FAULT) == 0)) { // no, so send one. NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_LOBE_FAILUE_ERROR, 3, NETFLEX_RINGSTATUS_ERROR_CODE, (ULONG) acb->acb_baseaddr, (ULONG) value ); acb->SentRingStatusLog = TRUE; } } if (value & (RING_STATUS_AUTO_REMOVE_1 | RING_STATUS_REMOVE_RECEIVED)) { if (value & RING_STATUS_AUTO_REMOVE_1) { RingStatus |= NDIS_RING_AUTO_REMOVAL_ERROR; DebugPrint(1,("NF(%d): RING_STATUS_AUTO_REMOVE_1\n",acb->anum)); } if (value & RING_STATUS_REMOVE_RECEIVED) { RingStatus |= NDIS_RING_REMOVE_RECEIVED; DebugPrint(1,("NF(%d): RING_STATUS_REMOVE_RECEIVED\n",acb->anum)); } // // Have we already reported the error? // if ((acb->acb_lastringstatus & (RING_STATUS_AUTO_REMOVE_1 | RING_STATUS_REMOVE_RECEIVED )) == 0) { // no, so send one. NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_REMOVE_RECEIVED_ERROR, 3, NETFLEX_RINGSTATUS_ERROR_CODE, (ULONG) acb->acb_baseaddr, (ULONG) value ); } } if (value & RING_STATUS_OVERFLOW) { RingStatus |= NDIS_RING_COUNTER_OVERFLOW; DebugPrint(1,("NF(%d): RING_STATUS_OVERFLOW\n",acb->anum)); } if (value & RING_STATUS_SINGLESTATION) { RingStatus |= NDIS_RING_SINGLE_STATION; DebugPrint(1,("NF(%d): RING_STATUS_SINGLESTATION\n",acb->anum)); } if (value & RING_STATUS_RINGRECOVERY) { RingStatus |= NDIS_RING_RING_RECOVERY; DebugPrint(1,("NF(%d): RING_STATUS_RINGRECOVERY\n",acb->anum)); } // // Save the Ring Status // acb->acb_lastringstatus = RingStatus; // // Indicate to the filter the ring status. // NdisMIndicateStatus( acb->acb_handle, NDIS_STATUS_RING_STATUS, &RingStatus, sizeof(ULONG) ); // // Tell the filter that we have completed the ring status. // NdisMIndicateStatusComplete(acb->acb_handle); }
BOOLEAN NE3200InitialInit( IN PNE3200_ADAPTER Adapter, IN UINT NE3200InterruptVector, IN NDIS_INTERRUPT_MODE NE3200InterruptMode ) /*++ Routine Description: This routine sets up the initial init of the driver, by stopping the adapter, connecting the interrupt and initializing the adapter. Arguments: Adapter - The adapter for the hardware. Return Value: TRUE if the initialization succeeds, else FALSE. --*/ { // // Status of NDIS calls // NDIS_STATUS Status; // // First we make sure that the device is stopped. // NE3200StopChip(Adapter); // // The ISR will set this to FALSE if we get an interrupt // Adapter->InitialInit = TRUE; // // Initialize the interrupt. // Status = NdisMRegisterInterrupt( &Adapter->Interrupt, Adapter->MiniportAdapterHandle, NE3200InterruptVector, NE3200InterruptVector, FALSE, FALSE, NE3200InterruptMode ); // // So far so good // if (Status == NDIS_STATUS_SUCCESS) { // // Now try to initialize the adapter // if (!NE3200SetConfigurationBlockAndInit(Adapter)) { // // Failed. Write out an error log entry. // NdisWriteErrorLogEntry( Adapter->MiniportAdapterHandle, NDIS_ERROR_CODE_TIMEOUT, 2, initialInit, NE3200_ERRMSG_NO_DELAY ); // // Unhook the interrupt // NdisMDeregisterInterrupt(&Adapter->Interrupt); Adapter->InitialInit = FALSE; return FALSE; } // // Get hardware assigned network address. // NE3200GetStationAddress( Adapter ); // // We can start the chip. We may not // have any bindings to indicate to but this // is unimportant. // Status = NE3200ChangeCurrentAddress(Adapter); Adapter->InitialInit = FALSE; return(Status == NDIS_STATUS_SUCCESS); } else { // // Interrupt line appears to be taken. Notify user. // NdisWriteErrorLogEntry( Adapter->MiniportAdapterHandle, NDIS_ERROR_CODE_INTERRUPT_CONNECT, 2, initialInit, NE3200_ERRMSG_INIT_INTERRUPT ); Adapter->InitialInit = FALSE; return(FALSE); } }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Routine Name: NetFlexHandleInterrupt // // Description: // This routine is the deferred processing // routine for all adapter interrupts. // // Input: // acb - Our Driver Context for this adapter or head. // // Output: // None // // Called By: // Miniport Wrapper // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ VOID NetFlexHandleInterrupt( IN NDIS_HANDLE MiniportAdapterContext ) { USHORT sifint_reg; USHORT tmp_reg; USHORT ReceivesProcessed = 0; PACB acb = (PACB) MiniportAdapterContext; // // Read the SifInt // NdisRawReadPortUshort( acb->SifIntPort, &sifint_reg); while (sifint_reg & SIFINT_SYSINT) { // // Ack the interrupt // sifint_reg &= ~SIFINT_SYSINT; NdisRawWritePortUshort( acb->SifIntPort, sifint_reg); // // mask off the int code // sifint_reg &= INT_CODES; // // See if there are any recieves to do... // if (acb->acb_rcv_head->RCV_CSTAT & RCSTAT_COMPLETE) { // // Increment the interrupt count. // acb->acb_int_count++; // // yes, do them... // acb->handled_interrupts++; ReceivesProcessed += acb->ProcessReceiveHandler(acb); } // // See if there are any transmits to do... // NetFlexProcessXmit(acb); switch (sifint_reg) { case INT_SCBCLEAR: acb->acb_scbclearout = FALSE; // // Is the SCB really clear? // // If the SCB is clear, send a SCB command off now. // Otherwise, if we are not currently waiting for an SCB clear // interrupt, signal the adapter to send us a SCB clear interrupt // when it is done with the SCB. // if (acb->acb_scb_virtptr->SCB_Cmd == 0) { NetFlexSendNextSCB(acb); } else if ((acb->acb_xmit_whead) || (acb->acb_rcv_whead) || (acb->acb_scbreq_next)) { acb->acb_scbclearout = TRUE; NdisRawWritePortUshort( acb->SifIntPort, (USHORT)SIFINT_SCBREQST); } break; case INT_COMMAND: NetFlexCommand(acb); // // Do we have any commands to complete? // if (acb->acb_confirm_qhead != NULL) { NetFlexProcessMacReq(acb); } break; case INT_ADPCHECK: // // Read the Adapter Check Status @ 1.05e0 // NdisRawWritePortUshort(acb->SifAddrxPort, (USHORT) 1); NdisRawWritePortUshort(acb->SifAddrPort, (USHORT) 0x5e0); NdisRawReadPortUshort( acb->SifDIncPort, &tmp_reg); DebugPrint(1,("NF(%d): Adapter Check - 0x%x\n",acb->anum,tmp_reg)); // // Reset has failed, errorlog an entry. // NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_ADAPTER_CHECK_ERROR, 2, NETFLEX_ADAPTERCHECK_ERROR_CODE, tmp_reg ); // // Set the variables up showing that the hardware has an unrecoverable // error. // acb->acb_state = AS_HARDERROR; break; case INT_RINGSTAT: NetFlexRingStatus(acb); break; case INT_RECEIVE: break; case INT_TRANSMIT: // // If we reached the end of the xmit lists, // then the xmit status will indicate COMMAND_COMPLETE. // The transmiter will be stalled until another transmit // command is issued with a valid list. // if (acb->acb_ssb_virtptr->SSB_Status & XSTAT_LERROR) { // // We have a list error... // NetFlexTransmitStatus(acb); } default: break; } // // Issue a ssb clear. After this we may see SIFCMD interrupts. // NdisRawWritePortUshort(acb->SifIntPort, SIFINT_SSBCLEAR); // // Read the SifInt // NdisRawReadPortUshort(acb->SifIntPort, &sifint_reg); } // // Processed any receives which need IndicateReceiveComplete? // if (ReceivesProcessed) { if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5) { // Token Ring // NdisMTrIndicateReceiveComplete(acb->acb_handle); } else { // Ethernet // NdisMEthIndicateReceiveComplete(acb->acb_handle); } } }
NDIS_STATUS MPInitializeEx( __in NDIS_HANDLE AdapterHandle, __in NDIS_HANDLE MiniportDriverContext, __in PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters ) { PHWT_ADAPTER newAdapter = NULL; NDIS_STATUS ndisStatus; UNREFERENCED_PARAMETER(MiniportDriverContext); DbgPrint("[HWTest]: MPInitializeEx -->\n"); do { ndisStatus = MpAllocateAdapter(AdapterHandle, &newAdapter); if (ndisStatus != NDIS_STATUS_SUCCESS) { DbgPrint("[HWTest]: MpAllocateAdapter return %08x\n", ndisStatus); break; } ndisStatus = NICInitializeAdapter(newAdapter, AdapterHandle); if (ndisStatus != NDIS_STATUS_SUCCESS) { DbgPrint("[HWTest]: NICInitializeAdapter return %08x\n", ndisStatus); ndisStatus = NDIS_STATUS_FAILURE; break; } ndisStatus = MpSetRegistrationAttributes(newAdapter); if (ndisStatus != NDIS_STATUS_SUCCESS) { DbgPrint("[HWTest]: MpSetRegistrationAttributes return %08x\n", ndisStatus); break; } ndisStatus = MpSetMiniportAttributes(newAdapter); if (ndisStatus != NDIS_STATUS_SUCCESS) { DbgPrint("[HWTest]: MpSetMiniportAttributes return %08x\n", ndisStatus); break; } ndisStatus = VNicAllocateNdisPort(AdapterHandle, &newAdapter->PortNumber); if (ndisStatus != NDIS_STATUS_SUCCESS) { DbgPrint("[HWTest]: VNicAllocateNdisPort return %08x\n", ndisStatus); break; } } while (FALSE); if (ndisStatus != NDIS_STATUS_SUCCESS) { if (newAdapter != NULL) { VNicFreeNdisPort(newAdapter); NICCleanAdapter(newAdapter); MpFreeAdapter(newAdapter); NdisWriteErrorLogEntry(AdapterHandle, NDIS_ERROR_CODE_HARDWARE_FAILURE, 0); } } else { NICAttachAdapter(newAdapter); NICRegisterDevice(); } DbgPrint("[HWTest]: MPInitializeEx return %08x\n", ndisStatus); return ndisStatus; }
/* ======================================================================== Routine Description: Allocate DMA memory blocks for send, receive Arguments: Adapter Pointer to our adapter Return Value: NDIS_STATUS_SUCCESS NDIS_STATUS_FAILURE NDIS_STATUS_RESOURCES IRQL = PASSIVE_LEVEL Note: ======================================================================== */ NDIS_STATUS RTMPAllocTxRxRingMemory( IN PRTMP_ADAPTER pAd) { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; ULONG RingBasePaHigh; ULONG RingBasePaLow; PVOID RingBaseVa; INT index, num; PTXD_STRUC pTxD; PRXD_STRUC pRxD; ULONG ErrorValue = 0; PRTMP_TX_RING pTxRing; PRTMP_DMABUF pDmaBuf; PNDIS_PACKET pPacket; DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); do { // // Allocate all ring descriptors, include TxD, RxD, MgmtD. // Although each size is different, to prevent cacheline and alignment // issue, I intentional set them all to 64 bytes. // for (num=0; num<NUM_OF_TX_RING; num++) { ULONG BufBasePaHigh; ULONG BufBasePaLow; PVOID BufBaseVa; // // Allocate Tx ring descriptor's memory (5 TX rings = 4 ACs + 1 HCCA) // pAd->TxDescRing[num].AllocSize = TX_RING_SIZE * TXD_SIZE; RTMP_AllocateTxDescMemory( pAd, num, pAd->TxDescRing[num].AllocSize, FALSE, &pAd->TxDescRing[num].AllocVa, &pAd->TxDescRing[num].AllocPa); if (pAd->TxDescRing[num].AllocVa == NULL) { ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; DBGPRINT_ERR(("Failed to allocate a big buffer\n")); Status = NDIS_STATUS_RESOURCES; break; } // Zero init this memory block NdisZeroMemory(pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocSize); // Save PA & VA for further operation RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxDescRing[num].AllocPa); RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxDescRing[num].AllocPa); RingBaseVa = pAd->TxDescRing[num].AllocVa; // // Allocate all 1st TXBuf's memory for this TxRing // pAd->TxBufSpace[num].AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE; RTMP_AllocateFirstTxBuffer( pAd, num, pAd->TxBufSpace[num].AllocSize, FALSE, &pAd->TxBufSpace[num].AllocVa, &pAd->TxBufSpace[num].AllocPa); if (pAd->TxBufSpace[num].AllocVa == NULL) { ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; DBGPRINT_ERR(("Failed to allocate a big buffer\n")); Status = NDIS_STATUS_RESOURCES; break; } // Zero init this memory block NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocSize); // Save PA & VA for further operation BufBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num].AllocPa); BufBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxBufSpace[num].AllocPa); BufBaseVa = pAd->TxBufSpace[num].AllocVa; // // Initialize Tx Ring Descriptor and associated buffer memory // pTxRing = &pAd->TxRing[num]; for (index = 0; index < TX_RING_SIZE; index++) { pTxRing->Cell[index].pNdisPacket = NULL; pTxRing->Cell[index].pNextNdisPacket = NULL; // Init Tx Ring Size, Va, Pa variables pTxRing->Cell[index].AllocSize = TXD_SIZE; pTxRing->Cell[index].AllocVa = RingBaseVa; RTMP_SetPhysicalAddressHigh(pTxRing->Cell[index].AllocPa, RingBasePaHigh); RTMP_SetPhysicalAddressLow (pTxRing->Cell[index].AllocPa, RingBasePaLow); // Setup Tx Buffer size & address. only 802.11 header will store in this space pDmaBuf = &pTxRing->Cell[index].DmaBuf; pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE; pDmaBuf->AllocVa = BufBaseVa; RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, BufBasePaHigh); RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow); // link the pre-allocated TxBuf to TXD pTxD = (PTXD_STRUC) pTxRing->Cell[index].AllocVa; pTxD->SDPtr0 = BufBasePaLow; // advance to next ring descriptor address pTxD->DMADONE = 1; RingBasePaLow += TXD_SIZE; RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; // advance to next TxBuf address BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE; BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE; } DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry allocated\n", num, index)); } if (Status == NDIS_STATUS_RESOURCES) break; // // Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler // pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE; RTMP_AllocateMgmtDescMemory( pAd, pAd->MgmtDescRing.AllocSize, FALSE, &pAd->MgmtDescRing.AllocVa, &pAd->MgmtDescRing.AllocPa); if (pAd->MgmtDescRing.AllocVa == NULL) { ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; DBGPRINT_ERR(("Failed to allocate a big buffer\n")); Status = NDIS_STATUS_RESOURCES; break; } // Zero init this memory block NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize); // Save PA & VA for further operation RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa); RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->MgmtDescRing.AllocPa); RingBaseVa = pAd->MgmtDescRing.AllocVa; // // Initialize MGMT Ring and associated buffer memory // for (index = 0; index < MGMT_RING_SIZE; index++) { pAd->MgmtRing.Cell[index].pNdisPacket = NULL; pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL; // Init MGMT Ring Size, Va, Pa variables pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE; pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa; RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index].AllocPa, RingBasePaHigh); RTMP_SetPhysicalAddressLow (pAd->MgmtRing.Cell[index].AllocPa, RingBasePaLow); // Offset to next ring descriptor address RingBasePaLow += TXD_SIZE; RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; // link the pre-allocated TxBuf to TXD pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[index].AllocVa; pTxD->DMADONE = 1; // no pre-allocated buffer required in MgmtRing for scatter-gather case } DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", index)); // // Allocate RX ring descriptor's memory except Tx ring which allocated eariler // pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE; RTMP_AllocateRxDescMemory( pAd, pAd->RxDescRing.AllocSize, FALSE, &pAd->RxDescRing.AllocVa, &pAd->RxDescRing.AllocPa); if (pAd->RxDescRing.AllocVa == NULL) { ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; DBGPRINT_ERR(("Failed to allocate a big buffer\n")); Status = NDIS_STATUS_RESOURCES; break; } // Zero init this memory block NdisZeroMemory(pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize); printk("RX DESC %p size = %ld\n", pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize); // Save PA & VA for further operation RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa); RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->RxDescRing.AllocPa); RingBaseVa = pAd->RxDescRing.AllocVa; // // Initialize Rx Ring and associated buffer memory // for (index = 0; index < RX_RING_SIZE; index++) { // Init RX Ring Size, Va, Pa variables pAd->RxRing.Cell[index].AllocSize = RXD_SIZE; pAd->RxRing.Cell[index].AllocVa = RingBaseVa; RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index].AllocPa, RingBasePaHigh); RTMP_SetPhysicalAddressLow (pAd->RxRing.Cell[index].AllocPa, RingBasePaLow); // Offset to next ring descriptor address RingBasePaLow += RXD_SIZE; RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE; // Setup Rx associated Buffer size & allocate share memory pDmaBuf = &pAd->RxRing.Cell[index].DmaBuf; pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE; pPacket = RTMP_AllocateRxPacketBuffer( pAd, pDmaBuf->AllocSize, FALSE, &pDmaBuf->AllocVa, &pDmaBuf->AllocPa); /* keep allocated rx packet */ pAd->RxRing.Cell[index].pNdisPacket = pPacket; // Error handling if (pDmaBuf->AllocVa == NULL) { ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n")); Status = NDIS_STATUS_RESOURCES; break; } // Zero init this memory block NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize); // Write RxD buffer address & allocated buffer length pRxD = (PRXD_STRUC) pAd->RxRing.Cell[index].AllocVa; pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); pRxD->DDONE = 0; } DBGPRINT(RT_DEBUG_TRACE, ("Rx Ring: total %d entry allocated\n", index)); } while (FALSE); NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME)); pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); if (pAd->FragFrame.pFragPacket == NULL) { Status = NDIS_STATUS_RESOURCES; } if (Status != NDIS_STATUS_SUCCESS) { // Log error inforamtion NdisWriteErrorLogEntry( pAd->AdapterHandle, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 1, ErrorValue); } DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); return Status; }
NDIS_STATUS NdisMAllocateMapRegisters( IN NDIS_HANDLE MiniportAdapterHandle, IN UINT DmaChannel, IN BOOLEAN Dma32BitAddresses, IN ULONG PhysicalMapRegistersNeeded, IN ULONG MaximumPhysicalMapping ) /*++ Routine Description: Allocates map registers for bus mastering devices. Arguments: MiniportAdapterHandle - Handle passed to MiniportInitialize. PhysicalMapRegistersNeeded - The maximum number of map registers needed by the Miniport at any one time. MaximumPhysicalMapping - Maximum length of a buffer that will have to be mapped. Return Value: None. --*/ { // // Convert the handle to our internal structure. // PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) MiniportAdapterHandle; // // This is needed by HalGetAdapter. // DEVICE_DESCRIPTION DeviceDescription; // // Returned by HalGetAdapter. // ULONG MapRegistersAllowed; // // Returned by HalGetAdapter. // PADAPTER_OBJECT AdapterObject; // // Map registers needed per channel. // ULONG MapRegistersPerChannel; NTSTATUS NtStatus; KIRQL OldIrql; UINT i; LARGE_INTEGER TimeoutValue; // // If the device is a busmaster, we get an adapter // object for it. // If map registers are needed, we loop, allocating an // adapter channel for each map register needed. // if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_BUS_MASTER) && (Miniport->BusType != (NDIS_INTERFACE_TYPE)-1) && (Miniport->BusNumber != (ULONG)-1)) { TimeoutValue.QuadPart = Int32x32To64(2 * 1000, -10000); Miniport->PhysicalMapRegistersNeeded = PhysicalMapRegistersNeeded; Miniport->MaximumPhysicalMapping = MaximumPhysicalMapping; // // Allocate storage for holding the appropriate // information for each map register. // Miniport->MapRegisters = (PMAP_REGISTER_ENTRY) ALLOC_FROM_POOL(sizeof(MAP_REGISTER_ENTRY) * PhysicalMapRegistersNeeded, NDIS_TAG_DEFAULT); if (Miniport->MapRegisters == (PMAP_REGISTER_ENTRY)NULL) { // // Error out // NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 1, 0xFFFFFFFF); return NDIS_STATUS_RESOURCES; } // // Use this event to tell us when ndisAllocationExecutionRoutine // has been called. // INITIALIZE_EVENT(&Miniport->AllocationEvent); // // Set up the device description; zero it out in case its // size changes. // ZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION)); DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; DeviceDescription.Master = TRUE; DeviceDescription.ScatterGather = TRUE; DeviceDescription.BusNumber = Miniport->BusNumber; DeviceDescription.DmaChannel = DmaChannel; DeviceDescription.InterfaceType = Miniport->AdapterType; if (DeviceDescription.InterfaceType == NdisInterfaceIsa) { // // For ISA devices, the width is based on the DMA channel: // 0-3 == 8 bits, 5-7 == 16 bits. Timing is compatibility // mode. // if (DmaChannel > 4) { DeviceDescription.DmaWidth = Width16Bits; } else { DeviceDescription.DmaWidth = Width8Bits; } DeviceDescription.DmaSpeed = Compatible; } else if ((DeviceDescription.InterfaceType == NdisInterfaceEisa) || (DeviceDescription.InterfaceType == NdisInterfacePci) || (DeviceDescription.InterfaceType == NdisInterfaceMca)) { DeviceDescription.Dma32BitAddresses = Dma32BitAddresses; } DeviceDescription.MaximumLength = MaximumPhysicalMapping; // // Get the adapter object. // AdapterObject = HalGetAdapter (&DeviceDescription, &MapRegistersAllowed); if (AdapterObject == NULL) { NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 1, 0xFFFFFFFF); FREE_POOL(Miniport->MapRegisters); Miniport->MapRegisters = NULL; DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("<==NdisRegisterAdapter\n")); return NDIS_STATUS_RESOURCES; } // // We save this to call IoFreeMapRegisters later. // Miniport->SystemAdapterObject = AdapterObject; // // Determine how many map registers we need per channel. // MapRegistersPerChannel = ((MaximumPhysicalMapping - 2) / PAGE_SIZE) + 2; ASSERT (MapRegistersAllowed >= MapRegistersPerChannel); // // Now loop, allocating an adapter channel each time, then // freeing everything but the map registers. // for (i=0; i<Miniport->PhysicalMapRegistersNeeded; i++) { Miniport->CurrentMapRegister = i; RAISE_IRQL_TO_DISPATCH(&OldIrql); NtStatus = IoAllocateAdapterChannel(AdapterObject, Miniport->DeviceObject, MapRegistersPerChannel, ndisAllocationExecutionRoutine, Miniport); if (!NT_SUCCESS(NtStatus)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("AllocateAdapterChannel: %lx\n", NtStatus)); for (; i != 0; i--) { IoFreeMapRegisters(Miniport->SystemAdapterObject, Miniport->MapRegisters[i-1].MapRegister, MapRegistersPerChannel); } LOWER_IRQL(OldIrql); NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 1, 0xFFFFFFFF); FREE_POOL(Miniport->MapRegisters); Miniport->MapRegisters = NULL; return NDIS_STATUS_RESOURCES; } LOWER_IRQL(OldIrql); TimeoutValue.QuadPart = Int32x32To64(2 * 1000, -10000); // // ndisAllocationExecutionRoutine will set this event // when it has gotten FirstTranslationEntry. // NtStatus = WAIT_FOR_OBJECT(&Miniport->AllocationEvent, &TimeoutValue); if (NtStatus != STATUS_SUCCESS) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("NDIS DMA AllocateAdapterChannel: %lx\n", NtStatus)); RAISE_IRQL_TO_DISPATCH(&OldIrql); for (; i != 0; i--) { IoFreeMapRegisters(Miniport->SystemAdapterObject, Miniport->MapRegisters[i-1].MapRegister, MapRegistersPerChannel); } LOWER_IRQL(OldIrql); NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport, NDIS_ERROR_CODE_OUT_OF_RESOURCES, 1, 0xFFFFFFFF); FREE_POOL(Miniport->MapRegisters); Miniport->MapRegisters = NULL; return NDIS_STATUS_RESOURCES; } RESET_EVENT(&Miniport->AllocationEvent); } } return NDIS_STATUS_SUCCESS; }
/*----------------------------------------------------------------------------*/ NDIS_STATUS windowsRegisterIsrt ( IN P_GLUE_INFO_T prGlueInfo ) { NDIS_STATUS rStatus; P_GL_HIF_INFO_T prHifInfo; DEBUGFUNC("windowsRegisterIsrt"); ASSERT(prGlueInfo); prHifInfo = &prGlueInfo->rHifInfo; /* Next we'll register our interrupt with the NDIS wrapper. */ /* Hook our interrupt vector. We used level-triggered, shared interrupts with our PCI adapters. */ INITLOG(("Register IRQ: handle=0x%x, irq=0x%x, level-triggered\n", prGlueInfo->rMiniportAdapterHandle, prHifInfo->u4InterruptLevel)); rStatus = NdisMRegisterInterrupt(&prHifInfo->rInterrupt, prGlueInfo->rMiniportAdapterHandle, (UINT) prHifInfo->u4InterruptVector, (UINT) prHifInfo->u4InterruptLevel, TRUE, /* RequestIsr */ FALSE, /* SharedInterrupt */ NIC_INTERRUPT_MODE); if (rStatus != NDIS_STATUS_SUCCESS) { ERRORLOG(("Interrupt conflict: status=0x%08x, IRQ=%d, level-sensitive\n", rStatus, prHifInfo->u4InterruptLevel)); NdisWriteErrorLogEntry(prGlueInfo->rMiniportAdapterHandle, NDIS_ERROR_CODE_INTERRUPT_CONNECT, 1, (UINT_32) prHifInfo->u4InterruptLevel); } GLUE_SET_FLAG(prGlueInfo, GLUE_FLAG_INTERRUPT_IN_USE); INITLOG(("Register interrupt -- OK\n")); #if SC32442_SPI { UINT_32 g_SysIntr; prHifInfo->gWaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &prHifInfo->u4InterruptLevel, sizeof(UINT32), &g_SysIntr, sizeof(UINT32), NULL)) { INITLOG(("ERROR:Failed to request sysintr value for Timer1 inturrupt!/n")); } else { INITLOG(("Request sysintr value %d!/r/n", g_SysIntr)); prHifInfo->u4sysIntr = g_SysIntr; } if (!(InterruptInitialize(g_SysIntr, prHifInfo->gWaitEvent, 0, 0))) { INITLOG(("ERROR: Interrupt initialize failed.\n")); } } #endif return rStatus; } /* windowsRegisterIsrt */