windows-nt/Source/XPSP1/NT/drivers/net/irda/sigmatel/sys/irusb.c
2020-09-26 16:20:57 +08:00

1590 lines
40 KiB
C

/**************************************************************************************************************************
* 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 <ndis.h>
#include <ntddndis.h> // defines OID's
#include <usbdi.h>
#include <usbdlib.h>
#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; i<NumberOfPackets; i++ )
{
StIrUsbSend( MiniportAdapterContext, PacketArray[i], 0 );
}
}
/*****************************************************************************
*
* Function: StIrUsbSend
*
* 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
* pPacketToSend - pointer to packet to send
* Flags - any flags set by protocol
*
* Returns: NDIS_STATUS_PENDING - This is generally what we should
* return. We will call NdisMSendComplete
* when the USB driver completes the
* send.
*
* Unsupported returns:
* NDIS_STATUS_SUCCESS - We should never return this since
* results will always be pending from
* the USB driver.
* NDIS_STATUS_RESOURCES - This indicates to the protocol that the
* device currently has no resources to complete
* the request. The protocol will resend
* the request when it receives either
* NdisMSendResourcesAvailable or
* NdisMSendComplete from the device.
*
* Notes: This routine delegates all the real work to SendPacketPreprocess in send.c
*
*
*****************************************************************************/
NDIS_STATUS
StIrUsbSend(
IN NDIS_HANDLE MiniportAdapterContext,
IN PNDIS_PACKET pPacketToSend,
IN UINT Flags
)
{
PIR_DEVICE pThisDev = (PIR_DEVICE)MiniportAdapterContext;
NDIS_STATUS Status;
DEBUGMSG( DBG_FUNC,("+StIrUsbSend()\n"));
//
// Make sure we are in the proper status, i.e. we are processing
// and no diagnostics are active
//
#if defined(DIAGS)
if( !pThisDev->fProcessing || 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