1590 lines
40 KiB
C
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
|