/************************************************************************************************************************** * IRUSB.C SigmaTel STIR4200 main module (contains main NDIS entry points) ************************************************************************************************************************** * (C) Unpublished Copyright of Sigmatel, Inc. All Rights Reserved. * * * Created: 04/06/2000 * Version 0.9 * Edited: 04/24/2000 * Version 0.91 * Edited: 04/27/2000 * Version 0.92 * Edited: 05/03/2000 * Version 0.93 * Edited: 05/12/2000 * Version 0.94 * Edited: 05/19/2000 * Version 0.95 * Edited: 05/24/2000 * Version 0.96 * Edited: 08/22/2000 * Version 1.02 * Edited: 09/25/2000 * Version 1.10 * Edited: 10/13/2000 * Version 1.11 * Edited: 11/13/2000 * Version 1.12 * Edited: 12/29/2000 * Version 1.13 * * **************************************************************************************************************************/ #define DOBREAKS // enable debug breaks #include #include // defines OID's #include #include #include "debug.h" #include "ircommon.h" #include "irusb.h" #include "irndis.h" #include "diags.h" // // Diagnostic global variables // #if defined(DIAGS) NDIS_HANDLE hSavedWrapper; PIR_DEVICE pGlobalDev; #endif // // Mark the DriverEntry function to run once during initialization. // NDIS_STATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath ); #pragma NDIS_INIT_FUNCTION( DriverEntry ) /***************************************************************************** * * Function: DriverEntry * * Synopsis: register driver entry functions with NDIS * * Arguments: DriverObject - the driver object being initialized * RegistryPath - registry path of the driver * * Returns: value returned by NdisMRegisterMiniport * * Algorithm: * * * Notes: * * This routine runs at IRQL PASSIVE_LEVEL. * *****************************************************************************/ NDIS_STATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath ) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; NDIS50_MINIPORT_CHARACTERISTICS characteristics; NDIS_HANDLE hWrapper; DEBUGMSG(DBG_FUNC, ("+DriverEntry(IrUsb)\n")); DEBUGMSG( DBG_FUNC ,(" Entering IRUSB DriverEntry(), pRegistryPath=\n %ws\n", pRegistryPath->Buffer )); NdisMInitializeWrapper( &hWrapper, pDriverObject, pRegistryPath, NULL ); #if defined(DIAGS) hSavedWrapper = hWrapper; #endif DEBUGMSG(DBG_FUNC, (" DriverEntry(IrUsb) called NdisMInitializeWrapper()\n")); NdisZeroMemory( &characteristics, sizeof(NDIS50_MINIPORT_CHARACTERISTICS) ); characteristics.MajorNdisVersion = (UCHAR)NDIS_MAJOR_VERSION; characteristics.MinorNdisVersion = (UCHAR)NDIS_MINOR_VERSION; characteristics.Reserved = 0; characteristics.HaltHandler = StIrUsbHalt; characteristics.InitializeHandler = StIrUsbInitialize; characteristics.QueryInformationHandler = StIrUsbQueryInformation; characteristics.SetInformationHandler = StIrUsbSetInformation; characteristics.ResetHandler = StIrUsbReset; // // For now we will allow NDIS to send only one packet at a time. // characteristics.SendHandler = StIrUsbSend; characteristics.SendPacketsHandler = StIrUsbSendPackets; // // We don't use NdisMIndicateXxxReceive function, so we will // need a ReturnPacketHandler to retrieve our packet resources. // characteristics.ReturnPacketHandler = StIrUsbReturnPacket; characteristics.TransferDataHandler = NULL; // // NDIS never calls the ReconfigureHandler. // characteristics.ReconfigureHandler = NULL; characteristics.CheckForHangHandler = StIrUsbCheckForHang; // // This miniport driver does not handle interrupts. // characteristics.HandleInterruptHandler = NULL; characteristics.ISRHandler = NULL; characteristics.DisableInterruptHandler = NULL; characteristics.EnableInterruptHandler = NULL; // // This miniport does not control a busmaster DMA with // NdisMAllocateShareMemoryAsysnc, AllocateCompleteHandler won't be // called from NDIS. // characteristics.AllocateCompleteHandler = NULL; DEBUGMSG(DBG_FUNC, (" DriverEntry(IrUsb) initted locks and events\n")); DEBUGMSG(DBG_FUNC, (" DriverEntry(IrUsb) about to NdisMRegisterMiniport()\n")); status = NdisMRegisterMiniport( hWrapper, &characteristics, sizeof(NDIS50_MINIPORT_CHARACTERISTICS) ); DEBUGMSG(DBG_FUNC, (" DriverEntry(IrUsb) after NdisMRegisterMiniport() status 0x%x\n", status)); DEBUGMSG(DBG_WARN, ("-DriverEntry(IrUsb) status = 0x%x\n", status)); return status; } /***************************************************************************** * * Function: StIrUsbInitialize * * Synopsis: Initializes the device (usbd.sys) and allocates all resources * required to carry out 'network' io operations. * * Arguments: OpenErrorStatus - allows StIrUsbInitialize to return additional * status code NDIS_STATUS_xxx if returning * NDIS_STATUS_OPEN_FAILED * SelectedMediumIndex - specifies to NDIS the medium type the * driver uses * MediumArray - array of NdisMediumXXX the driver can choose * MediumArraySize * MiniportAdapterHandle - handle identifying miniport's NIC * WrapperConfigurationContext - used with Ndis config and init * routines * * Returns: NDIS_STATUS_SUCCESS if properly configure and resources allocated * NDIS_STATUS_FAILURE, otherwise * * more specific failures: * NDIS_STATUS_UNSUPPORTED_MEDIA - driver can't support any medium * NDIS_STATUS_ADAPTER_NOT_FOUND - NdisOpenConfiguration or * NdisReadConfiguration failed * NDIS_STATUS_OPEN_FAILED - failed to open serial.sys * NDIS_STATUS_NOT_ACCEPTED - serial.sys does not accept the * configuration * NDIS_STATUS_RESOURCES - could not claim sufficient * resources * * * Notes: NDIS will not submit requests until this is complete. * * This routine runs at IRQL PASSIVE_LEVEL. * *****************************************************************************/ NDIS_STATUS StIrUsbInitialize( OUT PNDIS_STATUS OpenErrorStatus, OUT PUINT SelectedMediumIndex, IN PNDIS_MEDIUM MediumArray, IN UINT MediumArraySize, IN NDIS_HANDLE NdisAdapterHandle, IN NDIS_HANDLE WrapperConfigurationContext ) { UINT i; PIR_DEVICE pThisDev = NULL; NDIS_STATUS status = NDIS_STATUS_SUCCESS; NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_OBJECT pPhysicalDeviceObject = NULL; PDEVICE_OBJECT pNextDeviceObject = NULL; #if defined(DIAGS) UNICODE_STRING SymbolicLinkName; UNICODE_STRING DeviceName; PDEVICE_OBJECT pDeviceObject; PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION+1]; #endif DEBUGMSG(DBG_WARN, ("+StIrUsbInitialize\n")); // // Search for the irda medium in the medium array. // for( i = 0; i < MediumArraySize; i++ ) { if( MediumArray[i] == NdisMediumIrda ) { break; } } if( i < MediumArraySize ) { *SelectedMediumIndex = i; } else { // // Irda medium not found. // DEBUGMSG(DBG_ERROR, (" Failure: NdisMediumIrda not found!\n")); status = NDIS_STATUS_UNSUPPORTED_MEDIA; // // Log the error // NdisWriteErrorLogEntry( NdisAdapterHandle, NDIS_STATUS_UNSUPPORTED_MEDIA, 1, status ); goto done; } // // This will connect to a specific bus // NdisMGetDeviceProperty( NdisAdapterHandle, &pPhysicalDeviceObject, NULL, &pNextDeviceObject, NULL, NULL ); IRUSB_ASSERT( pPhysicalDeviceObject ); IRUSB_ASSERT( pNextDeviceObject ); DEBUGMSG( DBG_OUT, ("NdisMGetDeviceProperty PDO 0x%x,Next DO 0x%x\n", pPhysicalDeviceObject, pNextDeviceObject) ); // // Allocate a functional device object. // ntStatus = IrUsb_AddDevice( &pThisDev ); IRUSB_ASSERT( pThisDev ); if( (ntStatus != STATUS_SUCCESS) || (pThisDev == NULL) ) { // // Log the error // NdisWriteErrorLogEntry( NdisAdapterHandle, NDIS_STATUS_RESOURCES, 1, ntStatus ); DEBUGMSG(DBG_ERROR, (" IrUsb_AddDevice() FAILED.\n")); status = NDIS_STATUS_RESOURCES; goto done; } pThisDev->pUsbDevObj = pNextDeviceObject; pThisDev->pPhysDevObj = pPhysicalDeviceObject; // // Initialize device object and resources. // All the queues and buffer/packets etc. are allocated here. // status = InitializeDevice( pThisDev ); if( status != NDIS_STATUS_SUCCESS ) { // // Log the error // NdisWriteErrorLogEntry( NdisAdapterHandle, NDIS_STATUS_RESOURCES, 1, status ); DEBUGMSG(DBG_ERROR, (" InitializeDevice failed. Returned 0x%.8x\n", status)); status = NDIS_STATUS_RESOURCES; goto done; } // // Record the NdisAdapterHandle. // pThisDev->hNdisAdapter = NdisAdapterHandle; // // NdisMSetAttributes will associate our adapter handle with the wrapper's // adapter handle. The wrapper will then always use our handle // when calling us. We use a pointer to the device object as the context. // NdisMSetAttributesEx( NdisAdapterHandle, (NDIS_HANDLE)pThisDev, 0, NDIS_ATTRIBUTE_DESERIALIZE, NdisInterfaceInternal ); // // Now we're ready to do our own startup processing. // USB client drivers such as us set up URBs (USB Request Packets) to send requests // to the host controller driver (HCD). The URB structure defines a format for all // possible commands that can be sent to a USB device. // Here, we request the device descriptor and store it, // and configure the device. // In USB, no special HW processing is required to 'open' or 'close' the pipes // pThisDev->WrapperConfigurationContext = WrapperConfigurationContext; ntStatus = IrUsb_StartDevice( pThisDev ); if( ntStatus != STATUS_SUCCESS ) { // // Log the error // NdisWriteErrorLogEntry( pThisDev->hNdisAdapter, NDIS_STATUS_ADAPTER_NOT_FOUND, 1, ntStatus ); DEBUGMSG(DBG_ERROR, (" IrUsb_StartDevice FAILED. Returned 0x%.8x\n", ntStatus)); status = NDIS_STATUS_ADAPTER_NOT_FOUND; goto done; } // // Create an irp and begin our receives. // NOTE: All other receive processing will be done in the read completion // routine and PollingThread started therein. // status = InitializeProcessing( pThisDev, TRUE ); if( status != NDIS_STATUS_SUCCESS ) { // // Log the error // NdisWriteErrorLogEntry( pThisDev->hNdisAdapter, NDIS_STATUS_RESOURCES, 1, status ); DEBUGMSG(DBG_ERROR, (" InitializeProcessing failed. Returned 0x%.8x\n", status)); status = NDIS_STATUS_RESOURCES; goto done; } // // Initialize the diagnostic portion // #if defined(DIAGS) NdisZeroMemory( MajorFunction, sizeof(PDRIVER_DISPATCH)*(IRP_MJ_MAXIMUM_FUNCTION+1) ); RtlInitUnicodeString( &SymbolicLinkName, L"\\DosDevices\\Stirusb" ); RtlInitUnicodeString( &DeviceName, L"\\Device\\Stirusb" ); MajorFunction[IRP_MJ_CREATE] = StIrUsbCreate; MajorFunction[IRP_MJ_CLOSE] = StIrUsbClose; MajorFunction[IRP_MJ_DEVICE_CONTROL] = StIrUsbDispatch; NdisMRegisterDevice( hSavedWrapper, &DeviceName, &SymbolicLinkName, MajorFunction, &pDeviceObject, &pThisDev->NdisDeviceHandle ); pGlobalDev = pThisDev; #endif done: if( status != NDIS_STATUS_SUCCESS ) { if( pThisDev != NULL ) { DeinitializeDevice( pThisDev ); FreeDevice( pThisDev ); } } if( status!=NDIS_STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" IrUsb: StIrUsbInitialize failed %x\n", status)); } else { DEBUGMSG(DBG_ERR, (" IrUsb: StIrUsbInitialize SUCCESS %x\n", status)); } DEBUGMSG(DBG_FUNC, ("-StIrUsbInitialize\n")); return status; } /***************************************************************************** * * Function: StIrUsbHalt * * Synopsis: Deallocates resources when the NIC is removed and halts the * device. * * Arguments: Context - pointer to the ir device object * * Returns: None * * Algorithm: Mirror image of StIrUsbInitialize...undoes everything initialize * did. * Notes: * * This routine runs at IRQL PASSIVE_LEVEL. * * BUGBUG: Could StIrUsbReset fail and then StIrUsbHalt be called. If so, we need * to chech validity of all the pointers, etc. before trying to * deallocate. * *****************************************************************************/ VOID StIrUsbHalt( IN NDIS_HANDLE Context ) { PIR_DEVICE pThisDev; NTSTATUS ntstatus; DEBUGMSG(DBG_WARN, ("+StIrUsbHalt\n")); // change to FUNC later? pThisDev = CONTEXT_TO_DEV( Context ); if( TRUE == pThisDev->fPendingHalt ) { DEBUGMSG(DBG_ERR, (" StIrUsbHalt called with halt already pending\n")); IRUSB_ASSERT( 0 ); goto done; } // // Let the send completion and receive completion routine know that there // is a pending reset. // pThisDev->fPendingHalt = TRUE; IrUsb_CommonShutdown( pThisDev, TRUE ); //shutdown logic common to halt and reset; see below // // We had better not have left any pending read, write, or control IRPS hanging out there! // IRUSB_ASSERT( 0 == pThisDev->PendingIrpCount ); if ( 0 != pThisDev->PendingIrpCount ) { DEBUGMSG(DBG_ERR, (" StIrUsbHalt WE LEFT %d PENDING IRPS!!!!!\n", pThisDev->PendingIrpCount)); } IRUSB_ASSERT( FALSE == pThisDev->fSetpending ); IRUSB_ASSERT( FALSE == pThisDev->fQuerypending ); // // Destroy diags // #if defined(DIAGS) NdisMDeregisterDevice( pThisDev->NdisDeviceHandle ); #endif // // Free our own IR device object. // FreeDevice( pThisDev ); done: DEBUGMSG(DBG_ERR, (" StIrUsbHalt HALT complete\n")); DEBUGMSG(DBG_WARN, ("-StIrUsbHalt\n")); // change to FUNC later? } /***************************************************************************** * * Function: IrUsb_CommonShutdown * * Synopsis: Deallocates resources when the NIC is removed and halts the * device. This is stuff common to IrUsbHalt and IrUsbReset and is called by both * * Arguments: pThisDev - pointer to IR device * KillPassiveThread - determines whether we need to kill the passive thread * * Returns: None * * Algorithm: Mirror image of IrUsbInitialize...undoes everything initialize * did. * * Notes: * * This routine runs at IRQL PASSIVE_LEVEL. * * *****************************************************************************/ VOID IrUsb_CommonShutdown( IN OUT PIR_DEVICE pThisDev, BOOLEAN KillPassiveThread ) { DEBUGMSG(DBG_WARN, ("+IrUsb_CommonShutdown\n")); //chg to FUNC later? // // Stop processing and sleep 50 milliseconds. // InterlockedExchange( (PLONG)&pThisDev->fProcessing, FALSE ); NdisMSleep( 50000 ); // // Kill the passive thread // if( KillPassiveThread ) { DEBUGMSG(DBG_WARN, (" IrUsb_CommonShutdown About to Kill PassiveLevelThread\n")); pThisDev->fKillPassiveLevelThread = TRUE; KeSetEvent(&pThisDev->EventPassiveThread, 0, FALSE); while( pThisDev->hPassiveThread != NULL ) { // // Sleep 50 milliseconds. // NdisMSleep( 50000 ); } DEBUGMSG(DBG_WARN, (" passive thread killed\n")); } // // Kill the polling thread // DEBUGMSG(DBG_WARN, (" IrUsb_CommonShutdown About to kill Polling thread\n")); pThisDev->fKillPollingThread = TRUE; while( pThisDev->hPollingThread != NULL ) { // // Sleep 50 milliseconds. // NdisMSleep( 50000 ); } IRUSB_ASSERT( pThisDev->packetsHeldByProtocol == 0 ); DEBUGMSG( DBG_WARN, (" Polling thread killed\n") ); // // Sleep 50 milliseconds so pending io might finish normally // NdisMSleep( 50000 ); DEBUGMSG(DBG_WARN, (" IrUsb_CommonShutdown About to IrUsb_CancelPendingIo()\n")); // // Cancel any outstandig IO we may have // IrUsb_CancelPendingIo( pThisDev ); // // Deinitialize our own ir device object. // DeinitializeDevice( pThisDev ); pThisDev->fDeviceStarted = FALSE; DEBUGMSG(DBG_WARN, ("-IrUsb_CommonShutdown\n")); //chg to FUNC later? } /***************************************************************************** * * Function: StIrUsbReset * * Synopsis: Resets the drivers software state. * * Arguments: AddressingReset - return arg. If set to TRUE, NDIS will call * MiniportSetInformation to restore addressing * information to the current values. * Context - pointer to ir device object * * Returns: NDIS_STATUS_PENDING * * * Notes: * * *****************************************************************************/ NDIS_STATUS StIrUsbReset( OUT PBOOLEAN AddressingReset, IN NDIS_HANDLE MiniportAdapterContext ) { PIR_DEVICE pThisDev; NDIS_STATUS status = NDIS_STATUS_PENDING; DEBUGMSG(DBG_WARN, ("+StIrUsbReset\n")); // CHANGE TO FUNC? pThisDev = CONTEXT_TO_DEV( MiniportAdapterContext ); if( TRUE == pThisDev->fPendingReset ) { DEBUGMSG(DBG_ERROR, (" StIrUsbReset called with reset already pending\n")); status = NDIS_STATUS_RESET_IN_PROGRESS ; goto done; } // // Let the send completion and receive completion routine know that there // is a pending reset. // pThisDev->fPendingReset = TRUE; InterlockedExchange( (PLONG)&pThisDev->fProcessing, FALSE ); *AddressingReset = TRUE; if( FALSE == ScheduleWorkItem( pThisDev, ResetIrDevice, NULL, 0) ) { status = NDIS_STATUS_FAILURE; } done: DEBUGMSG(DBG_WARN, ("-StIrUsbReset\n")); // change to FUNC later? return status; } /***************************************************************************** * * Function: StIrUsbCheckForHang * * Synopsis: Makes sure the device/driver operating state is correct * * Arguments: Context - pointer to ir device object * * Returns: TRUE - driver is hung * FALSE - otherwise * * Notes: * * *****************************************************************************/ BOOLEAN StIrUsbCheckForHang( IN NDIS_HANDLE MiniportAdapterContext ) { PIR_DEVICE pThisDev; pThisDev = CONTEXT_TO_DEV( MiniportAdapterContext ); /*if( pThisDev->fPendingClearTotalStall ) { DEBUGMSG(DBG_ERROR, (" StIrUsbCheckForHang USB hang, will ask for a reset\n")); return TRUE; } else*/ return FALSE; } /***************************************************************************** * * Function: SuspendIrDevice * * Synopsis: Callback for a going into suspend mode * * Arguments: pWorkItem - pointer to the reset work item * * Returns: None * * Notes: * *****************************************************************************/ VOID SuspendIrDevice( IN PIR_WORK_ITEM pWorkItem ) { PIR_DEVICE pThisDev = (PIR_DEVICE)pWorkItem->pIrDevice; NTSTATUS Status = STATUS_SUCCESS; // // We no longer need the work item // FreeWorkItem( pWorkItem ); // // Now cancel everything that's pending, after a little time to complete // NdisMSleep( 100*1000 ); DEBUGMSG(DBG_ERROR, (" SuspendIrDevice(), cancelling pending IRPs\n")); IrUsb_CancelPendingIo( pThisDev ); // // Prepare the part // #if defined(SUPPORT_LA8) if( pThisDev->ChipRevision >= CHIP_REVISION_8 ) { Status = St4200EnableOscillatorPowerDown( pThisDev ); if( Status == STATUS_SUCCESS ) { Status = St4200TurnOnSuspend( pThisDev ); } } #endif // // Tell the OS // if( pThisDev->fQuerypending ) MyNdisMQueryInformationComplete( pThisDev, Status ); } /***************************************************************************** * * Function: ResumeIrDevice * * Synopsis: Callback for a going out of suspend mode * * Arguments: pWorkItem - pointer to the reset work item * * Returns: None * * Notes: * *****************************************************************************/ VOID ResumeIrDevice( IN PIR_WORK_ITEM pWorkItem ) { PIR_DEVICE pThisDev = (PIR_DEVICE)pWorkItem->pIrDevice; // // We no longer need the work item // FreeWorkItem( pWorkItem ); // // Get the device back up and running // #if defined(SUPPORT_LA8) if( pThisDev->ChipRevision >= CHIP_REVISION_8 ) { St4200TurnOffSuspend( pThisDev ); } #endif St4200SetSpeed( pThisDev ); InterlockedExchange( (PLONG)&pThisDev->currentSpeed, pThisDev->linkSpeedInfo->BitsPerSec ); InterlockedExchange( (PLONG)&pThisDev->fProcessing, TRUE ); } /***************************************************************************** * * Function: RestoreIrDevice * * Synopsis: Callback for a on-the-fly reset * * Arguments: pWorkItem - pointer to the reset work item * * Returns: None * * Notes: * *****************************************************************************/ VOID RestoreIrDevice( IN PIR_WORK_ITEM pWorkItem ) { NDIS_STATUS status = STATUS_SUCCESS; PIR_DEVICE pThisDev = (PIR_DEVICE)pWorkItem->pIrDevice; UINT CurrentSpeed, i; DEBUGMSG(DBG_WARN, ("+RestoreIrDevice\n")); DEBUGMSG(DBG_ERROR, (" RestoreIrDevice USB hang, resetting\n")); // // We no longer need the work item // FreeWorkItem( pWorkItem ); // // Give a little time to complete // NdisMSleep( 100*1000 ); // // Force a reset on the USB bus // status = IrUsb_ResetUSBD( pThisDev, FALSE ); if( status != NDIS_STATUS_SUCCESS ) { //IrUsb_ResetUSBD( pThisDev, TRUE ); pThisDev->fDeviceStarted = FALSE; InterlockedExchange( (PLONG)&pThisDev->fProcessing, FALSE ); DEBUGMSG(DBG_ERROR, (" RestoreIrDevice() IrUsb_ResetUSBD failed. Returned 0x%.8x\n", status)); goto done; } // // Save the current speed // CurrentSpeed = pThisDev->currentSpeed; // // Shutdown the device // DEBUGMSG(DBG_WARN, (" RestoreIrDevice() about to call IrUsb_CommonShutdown()\n")); // change to FUNC later? IrUsb_CommonShutdown( pThisDev, FALSE ); //shutdown logic common to halt and reset; see above DEBUGMSG(DBG_WARN, (" RestoreIrDevice() after IrUsb_CommonShutdown()\n")); // change to FUNC later? // // Destroy and create again the USB portion of the device // DEBUGMSG(DBG_WARN, (" RestoreIrDevice() about to refresh USB info\n")); // change to FUNC later? FreeUsbInfo( pThisDev ); if( !AllocUsbInfo( pThisDev ) ) { DEBUGMSG(DBG_ERROR, (" RestoreIrDevice() AllocUsbInfo failed\n")); goto done; } DEBUGMSG(DBG_WARN, (" RestoreIrDevice() after refreshing USB info\n")); // change to FUNC later? // // Reinitialize the device // DEBUGMSG(DBG_WARN, (" RestoreIrDevice() about to call InitializeDevice()\n")); // change to FUNC later? status = InitializeDevice( pThisDev ); if( status != NDIS_STATUS_SUCCESS ) { DEBUGMSG(DBG_ERROR, (" RestoreIrDevice() InitializeDevice failed. Returned 0x%.8x\n", status)); goto done; } DEBUGMSG(DBG_WARN, (" RestoreIrDevice() InitializeProcessing() SUCCESS, about to call InitializeReceive()\n")); // change to FUNC later? // // Restart it // status = IrUsb_StartDevice( pThisDev ); if( status != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERROR, (" RestoreIrDevice() IrUsb_StartDevice failed. Returned 0x%.8x\n", status)); goto done; } // // Keep a pointer to the link speed which was previously set // for( i = 0; i < NUM_BAUDRATES; i++ ) { if( supportedBaudRateTable[i].BitsPerSec == CurrentSpeed ) { pThisDev->linkSpeedInfo = &supportedBaudRateTable[i]; break; //for } } // // restore the old speed // DEBUGMSG( DBG_ERR, (" Restoring speed to: %d\n", pThisDev->linkSpeedInfo->BitsPerSec)); status = St4200SetSpeed( pThisDev ); if( status != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERROR, (" RestoreIrDevice() St4200SetSpeed failed. Returned 0x%.8x\n", status)); goto done; } InterlockedExchange( (PLONG)&pThisDev->currentSpeed, CurrentSpeed ); // // Initialize receive loop. // status = InitializeProcessing( pThisDev, FALSE ); if( status != NDIS_STATUS_SUCCESS ) { DEBUGMSG(DBG_ERROR, (" RestoreIrDevice() InitializeProcessing failed. Returned 0x%.8x\n", status)); goto done; } done: DEBUGCOND(DBG_ERROR, (status != NDIS_STATUS_SUCCESS), (" RestoreIrDevice failed = 0x%.8x\n", status)); } /***************************************************************************** * * Function: ResetIrDevice * * Synopsis: Callback for StIrUsbReset * * Arguments: pWorkItem - pointer to the reset work item * * Returns: None * * Notes: * * The following elements of the ir device object outlast the reset: * * pUsbDevObj * hNdisAdapter * *****************************************************************************/ VOID ResetIrDevice( IN PIR_WORK_ITEM pWorkItem ) { NDIS_STATUS status = STATUS_SUCCESS; PIR_DEVICE pThisDev = (PIR_DEVICE)pWorkItem->pIrDevice; DEBUGMSG(DBG_WARN, ("+ResetIrDevice\n")); // change to FUNC later? // // We no longer need the work item // FreeWorkItem( pWorkItem ); // // Now cancel everything that's pending, after a little time to complete // NdisMSleep( 100*1000 ); DEBUGMSG(DBG_ERROR, (" ResetIrDevice(), cancelling pending IRPs\n")); IrUsb_CancelPendingIo( pThisDev ); // // reset the part // status = IrUsb_ResetUSBD( pThisDev, FALSE ); if( status != STATUS_SUCCESS ) { pThisDev->fDeviceStarted = FALSE; // // Log the error // NdisWriteErrorLogEntry( pThisDev->hNdisAdapter, NDIS_STATUS_ADAPTER_NOT_FOUND, 1, status ); DEBUGMSG(DBG_ERROR, (" ResetIrDevice() IrUsb_ResetUSBD failed. Returned 0x%.8x\n", status)); status = NDIS_STATUS_ADAPTER_NOT_FOUND; goto done; } // // Shutdown the device // DEBUGMSG(DBG_WARN, (" ResetIrDevice() about to call IrUsb_CommonShutdown()\n")); // change to FUNC later? IrUsb_CommonShutdown( pThisDev, FALSE ); //shutdown logic common to halt and reset; see above DEBUGMSG(DBG_WARN, (" ResetIrDevice() after IrUsb_CommonShutdown()\n")); // change to FUNC later? // // Destroy and create again the USB portion of the device // DEBUGMSG(DBG_WARN, (" ResetIrDevice() about to refresh USB info\n")); // change to FUNC later? FreeUsbInfo( pThisDev ); if( !AllocUsbInfo( pThisDev ) ) { // // Log the error // NdisWriteErrorLogEntry( pThisDev->hNdisAdapter, NDIS_STATUS_RESOURCES, 1, status ); DEBUGMSG(DBG_ERROR, (" ResetIrDevice() AllocUsbInfo failed\n")); status = NDIS_STATUS_FAILURE; goto done; } DEBUGMSG(DBG_WARN, (" ResetIrDevice() after refreshing USB info\n")); // change to FUNC later? // // Reinitialize the device // DEBUGMSG(DBG_WARN, (" ResetIrDevice() about to call InitializeDevice()\n")); // change to FUNC later? status = InitializeDevice( pThisDev ); if( status != NDIS_STATUS_SUCCESS ) { // // Log the error // NdisWriteErrorLogEntry( pThisDev->hNdisAdapter, NDIS_STATUS_RESOURCES, 1, status ); DEBUGMSG(DBG_ERROR, (" ResetIrDevice() InitializeDevice failed. Returned 0x%.8x\n", status)); status = NDIS_STATUS_FAILURE; goto done; } DEBUGMSG(DBG_WARN, (" ResetIrDevice() InitializeProcessing() SUCCESS, about to call InitializeReceive()\n")); // change to FUNC later? // // Restart it // status = IrUsb_StartDevice( pThisDev ); if( status != STATUS_SUCCESS ) { // // Log the error // NdisWriteErrorLogEntry( pThisDev->hNdisAdapter, NDIS_STATUS_ADAPTER_NOT_FOUND, 1, status ); DEBUGMSG(DBG_ERROR, (" ResetIrDevice() IrUsb_StartDevice failed. Returned 0x%.8x\n", status)); status = NDIS_STATUS_ADAPTER_NOT_FOUND; goto done; } // // Initialize receive loop. // status = InitializeProcessing( pThisDev, FALSE ); if( status != NDIS_STATUS_SUCCESS ) { // // Log the error // NdisWriteErrorLogEntry( pThisDev->hNdisAdapter, NDIS_STATUS_RESOURCES, 1, status ); DEBUGMSG(DBG_ERROR, (" ResetIrDevice() InitializeProcessing failed. Returned 0x%.8x\n", status)); status = NDIS_STATUS_FAILURE; goto done; } done: DEBUGCOND(DBG_ERROR, (status != NDIS_STATUS_SUCCESS), (" ResetIrDevice failed = 0x%.8x\n", status)); // // Deal with possible errors // if( status != STATUS_SUCCESS ) { status = NDIS_STATUS_HARD_ERRORS; } NdisMResetComplete( pThisDev->hNdisAdapter, status, TRUE ); DEBUGMSG(DBG_WARN, ("-ResetIrDevice\n")); // change to FUNC later? } /***************************************************************************** * * Function: GetPacketInfo * * Synopsis: Gets the IR specific information for an input packet * * Arguments: pPacket - pointer to packet * * Returns: PNDIS_IRDA_PACKET_INFO structure for the packet * * Notes: * *****************************************************************************/ PNDIS_IRDA_PACKET_INFO GetPacketInfo( IN PNDIS_PACKET pPacket ) { PMEDIA_SPECIFIC_INFORMATION pMediaInfo; UINT Size; NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO( pPacket, &pMediaInfo, &Size ); if( Size ) return (PNDIS_IRDA_PACKET_INFO)pMediaInfo->ClassInformation; else return NULL; } /***************************************************************************** * * Function: MyNdisMSetInformationComplete * * Synopsis: Call NdisMSetInformationComplete() * * Arguments: pThisDev - pointer to IR device * Status - status to signal * * Returns: None * * Notes: * *****************************************************************************/ VOID MyNdisMSetInformationComplete( IN PIR_DEVICE pThisDev, IN NDIS_STATUS Status ) { DEBUGMSG( DBG_FUNC,("+MyNdisMSetInformationComplete\n")); NdisMSetInformationComplete( (NDIS_HANDLE)pThisDev->hNdisAdapter, Status ); pThisDev->LastSetTime.QuadPart = 0; pThisDev->fSetpending = FALSE; DEBUGMSG( DBG_FUNC,("-MyNdisMSetInformationComplete\n")); } /***************************************************************************** * * Function: MyNdisMQueryInformationComplete * * Synopsis: Call NdisMQueryInformationComplete() * * Arguments: pThisDev - pointer to IR device * Status - status to signal * * Returns: None * * Notes: * *****************************************************************************/ VOID MyNdisMQueryInformationComplete( IN PIR_DEVICE pThisDev, IN NDIS_STATUS Status ) { DEBUGMSG( DBG_FUNC,("+MyNdisMQueryInformationComplete\n")); NdisMQueryInformationComplete( (NDIS_HANDLE)pThisDev->hNdisAdapter, Status ); pThisDev->LastQueryTime.QuadPart = 0; pThisDev->fQuerypending = FALSE; DEBUGMSG( DBG_FUNC,("-MyNdisMQueryInformationComplete\n")); } /***************************************************************************** * * Function: IndicateMediaBusy * * Synopsis: Call NdisMIndicateStatus() * * Arguments: pThisDev - pointer to IR device * * Returns: None * * Notes: * *****************************************************************************/ VOID IndicateMediaBusy( IN PIR_DEVICE pThisDev ) { DEBUGMSG( DBG_FUNC,("+IndicateMediaBusy\n")); NdisMIndicateStatus( pThisDev->hNdisAdapter, NDIS_STATUS_MEDIA_BUSY, NULL, 0 ); NdisMIndicateStatusComplete( pThisDev->hNdisAdapter, ); #if DBG pThisDev->NumMediaBusyIndications ++; #endif #if !defined(ONLY_ERROR_MESSAGES) DEBUGMSG(DBG_ERR, (" IndicateMediaBusy()\n")); #endif DEBUGMSG( DBG_FUNC,("-IndicateMediaBusy\n")); } /***************************************************************************** * * Function: StIrUsbSendPackets * * Synopsis: Send a packet to the USB driver and add the sent irp and io context to * To the pending send queue; this que is really just needed for possible later error cancellation * * * Arguments: MiniportAdapterContext - pointer to current ir device object * PacketArray - pointer to array of packets to send * NumberOfPackets - number of packets in the array * * Returns: VOID * * Notes: This routine does nothing but calling StIrUsbSend * * *****************************************************************************/ VOID StIrUsbSendPackets( IN NDIS_HANDLE MiniportAdapterContext, IN PPNDIS_PACKET PacketArray, IN UINT NumberOfPackets ) { ULONG i; // // This is a great opportunity to be lazy. // Just call StIrUsbSend with each packet // in sequence and set the result in the // packet array object. // for( i=0; ifProcessing || pThisDev->DiagsPendingActivation ) #else if( !pThisDev->fProcessing ) #endif { Status = NDIS_STATUS_FAILURE; goto done; } // // Send the packet to the hardware // NDIS_SET_PACKET_STATUS( pPacketToSend, NDIS_STATUS_PENDING ); Status = SendPacketPreprocess( pThisDev, pPacketToSend ); done: // // If the operation didn't pend we have to complete // We are really bouncing the packets... // if( Status != NDIS_STATUS_PENDING ) { NdisMSendComplete( pThisDev->hNdisAdapter, pPacketToSend, NDIS_STATUS_SUCCESS ); } DEBUGMSG( DBG_FUNC,("-StIrUsbSend()\n")); return Status; } // Diagnostic entry points #if defined(DIAGS) /***************************************************************************** * * Function: StIrUsbDispatch * * Synopsis: Processes the diagnostic Irps * * Arguments: DeviceObject - pointer to the device object * Irp - pointer to the Irp * * Returns: NT status code * * Notes: * *****************************************************************************/ NTSTATUS StIrUsbDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIR_DEVICE pThisDev = pGlobalDev; PIO_STACK_LOCATION irpSp; ULONG FunctionCode; NTSTATUS status; PVOID pBuffer; ULONG BufferLength; USHORT DiagsCode; DEBUGMSG( DBG_FUNC,("+StIrUsbDispatch()\n")); // // Get the Irp // irpSp = IoGetCurrentIrpStackLocation( Irp ); // // Get the data // FunctionCode = irpSp->Parameters.DeviceIoControl.IoControlCode; pBuffer = Irp->AssociatedIrp.SystemBuffer; BufferLength = irpSp->Parameters.DeviceIoControl.InputBufferLength; DiagsCode = *(PUSHORT)pBuffer; // // Process the diagnostic operation // switch( FunctionCode ) { case IOCTL_PROTOCOL_DIAGS: switch( DiagsCode ) { case DIAGS_ENABLE: status = Diags_Enable( pThisDev ); break; case DIAGS_DISABLE: status = Diags_Disable( pThisDev ); break; case DIAGS_READ_REGISTERS: status = Diags_ReadRegisters( pThisDev, pBuffer, BufferLength ); if( status == STATUS_SUCCESS ) { Irp->IoStatus.Information = sizeof(DIAGS_READ_REGISTERS_IOCTL); } break; case DIAGS_WRITE_REGISTER: status = Diags_WriteRegister( pThisDev, pBuffer, BufferLength ); break; case DIAGS_BULK_OUT: status = Diags_PrepareBulk( pThisDev, pBuffer, BufferLength, TRUE ); break; case DIAGS_BULK_IN: status = Diags_PrepareBulk( pThisDev, pBuffer, BufferLength, FALSE ); if( status == STATUS_SUCCESS ) { PDIAGS_BULK_IOCTL pIOCTL = pThisDev->pIOCTL; Irp->IoStatus.Information = sizeof(DIAGS_BULK_IOCTL)+pIOCTL->DataSize-1; } break; case DIAGS_SEND: status = Diags_PrepareSend( pThisDev, pBuffer, BufferLength ); break; case DIAGS_RECEIVE: status = Diags_Receive( pThisDev, pBuffer, BufferLength ); if( status == STATUS_SUCCESS ) { PDIAGS_RECEIVE_IOCTL pIOCTL = pThisDev->pIOCTL; Irp->IoStatus.Information = sizeof(DIAGS_RECEIVE_IOCTL)+pIOCTL->DataSize-1; } break; case DIAGS_GET_SPEED: status = Diags_GetSpeed( pThisDev, pBuffer, BufferLength ); if( status == STATUS_SUCCESS ) { Irp->IoStatus.Information = sizeof(DIAGS_SPEED_IOCTL); } break; case DIAGS_SET_SPEED: status = Diags_SetSpeed( pThisDev, pBuffer, BufferLength ); break; default: status = STATUS_NOT_SUPPORTED; break; } break; default: status = STATUS_NOT_SUPPORTED; break; } // // Complete and return // Irp->IoStatus.Status = status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); DEBUGMSG( DBG_FUNC,("-StIrUsbDispatch()\n")); return status; } /***************************************************************************** * * Function: StIrUsbCreate * * Synopsis: Creates a new diagnostic object (it does nothing) * * Arguments: DeviceObject - pointer to the device object * Irp - pointer to the Irp * * Returns: NT status code * * Notes: * *****************************************************************************/ NTSTATUS StIrUsbCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIR_DEVICE pThisDev = pGlobalDev; // // Initialize list for holding pending read requests // KeInitializeSpinLock( &pThisDev->DiagsReceiveLock ); InitializeListHead( &pThisDev->DiagsReceiveQueue ); Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return STATUS_SUCCESS; } /***************************************************************************** * * Function: StIrUsbClose * * Synopsis: Destroys a new diagnostic object (it does nothing) * * Arguments: DeviceObject - pointer to the device object * Irp - pointer to the Irp * * Returns: NT status code * * Notes: * *****************************************************************************/ NTSTATUS StIrUsbClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return STATUS_SUCCESS; } #endif