418 lines
11 KiB
C
418 lines
11 KiB
C
/**************************************************************************************************************************
|
|
* OPENCLOS.C SigmaTel STIR4200 init/shutdown module
|
|
**************************************************************************************************************************
|
|
* (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/12/2000
|
|
* Version 0.94
|
|
* Edited: 05/19/2000
|
|
* Version 0.95
|
|
*
|
|
*
|
|
**************************************************************************************************************************/
|
|
|
|
#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 "irndis.h"
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Function: InitializeDevice
|
|
*
|
|
* Synopsis: initialize resources for a single IR device object
|
|
*
|
|
* Arguments: pThisDev - IR device object to initialize
|
|
*
|
|
* Returns: NDIS_STATUS_SUCCESS - if device is successfully opened
|
|
* NDIS_STATUS_RESOURCES - could not claim sufficient
|
|
* resources
|
|
*
|
|
*
|
|
* Notes:
|
|
* we do a lot of stuff in this open device function
|
|
* - allocate packet pool
|
|
* - allocate buffer pool
|
|
* - allocate packets/buffers/memory and chain together
|
|
* (only one buffer per packet)
|
|
* - initialize send queue
|
|
*
|
|
* This function should be called with device lock held.
|
|
*
|
|
* We don't initialize the following ir device object entries, since
|
|
* these values will outlast an reset.
|
|
* pUsbDevObj
|
|
* hNdisAdapter
|
|
* dongleCaps
|
|
* fGotFilterIndication
|
|
*
|
|
*****************************************************************************/
|
|
NDIS_STATUS
|
|
InitializeDevice(
|
|
IN OUT PIR_DEVICE pThisDev
|
|
)
|
|
{
|
|
int i;
|
|
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
|
|
|
|
DEBUGMSG(DBG_FUNC|DBG_PNP, ("+InitializeDevice\n"));
|
|
|
|
IRUSB_ASSERT( pThisDev != NULL );
|
|
|
|
//
|
|
// Current speed is the default (9600).
|
|
//
|
|
pThisDev->linkSpeedInfo = &supportedBaudRateTable[BAUDRATE_9600];
|
|
pThisDev->currentSpeed = DEFAULT_BAUD_RATE;
|
|
|
|
//
|
|
// Init statistical info.
|
|
// We need to do this cause reset won't free and realloc pThisDev!
|
|
//
|
|
pThisDev->packetsReceived = 0;
|
|
pThisDev->packetsReceivedDropped = 0;
|
|
pThisDev->packetsReceivedOverflow = 0;
|
|
pThisDev->packetsReceivedChecksum = 0;
|
|
pThisDev->packetsReceivedRunt = 0;
|
|
pThisDev->packetsReceivedNoBuffer = 0;
|
|
|
|
pThisDev->packetsSent = 0;
|
|
pThisDev->packetsSentDropped = 0;
|
|
pThisDev->packetsSentRejected = 0;
|
|
pThisDev->packetsSentInvalid = 0;
|
|
|
|
pThisDev->NumDataErrors = 0;
|
|
pThisDev->NumReadWriteErrors = 0;
|
|
|
|
pThisDev->NumReads = 0;
|
|
pThisDev->NumWrites = 0;
|
|
pThisDev->NumReadWrites = 0;
|
|
|
|
#if DBG
|
|
pThisDev->TotalBytesReceived = 0;
|
|
pThisDev->TotalBytesSent = 0;
|
|
pThisDev->NumYesQueryMediaBusyOids = 0;
|
|
pThisDev->NumNoQueryMediaBusyOids = 0;
|
|
pThisDev->NumSetMediaBusyOids = 0;
|
|
pThisDev->NumMediaBusyIndications = 0;
|
|
pThisDev->packetsHeldByProtocol = 0;
|
|
pThisDev->MaxPacketsHeldByProtocol = 0;
|
|
pThisDev->NumPacketsSentRequiringTurnaroundTime = 0;
|
|
pThisDev->NumPacketsSentNotRequiringTurnaroundTime = 0;
|
|
#endif
|
|
|
|
//
|
|
// Variables about the state of the device
|
|
//
|
|
pThisDev->fDeviceStarted = FALSE;
|
|
pThisDev->fGotFilterIndication = FALSE;
|
|
pThisDev->fPendingHalt = FALSE;
|
|
pThisDev->fPendingReadClearStall = FALSE;
|
|
pThisDev->fPendingWriteClearStall = FALSE;
|
|
pThisDev->fPendingReset = FALSE;
|
|
|
|
pThisDev->fPendingClearTotalStall = FALSE;
|
|
|
|
pThisDev->fKillPollingThread = FALSE;
|
|
|
|
pThisDev->fKillPassiveLevelThread = FALSE;
|
|
|
|
pThisDev->LastQueryTime.QuadPart = 0;
|
|
pThisDev->LastSetTime.QuadPart = 0;
|
|
pThisDev->PendingIrpCount = 0;
|
|
|
|
//
|
|
// OID Set/Query pending
|
|
//
|
|
pThisDev->fQuerypending = FALSE;
|
|
pThisDev->fSetpending = FALSE;
|
|
|
|
//
|
|
// Diags are off
|
|
//
|
|
#if defined(DIAGS)
|
|
pThisDev->DiagsActive = FALSE;
|
|
pThisDev->DiagsPendingActivation = FALSE;
|
|
#endif
|
|
|
|
//
|
|
// Some more state variables
|
|
//
|
|
InterlockedExchange( &pThisDev->fMediaBusy, FALSE );
|
|
InterlockedExchange( &pThisDev->fIndicatedMediaBusy, FALSE );
|
|
|
|
pThisDev->pCurrentRecBuf = NULL;
|
|
|
|
pThisDev->fProcessing = FALSE;
|
|
pThisDev->fCurrentlyReceiving = FALSE;
|
|
|
|
pThisDev->fReadHoldingReg = FALSE;
|
|
|
|
pThisDev->BaudRateMask = 0xffff; // as per Class Descriptor; may be reset in registry
|
|
|
|
//
|
|
// Initialize the queues.
|
|
//
|
|
if( TRUE != IrUsb_InitSendStructures( pThisDev ) )
|
|
{
|
|
DEBUGMSG(DBG_ERR, (" Failed to init WDM objects\n"));
|
|
goto done;
|
|
}
|
|
|
|
//
|
|
// Allocate the NDIS packet and NDIS buffer pools
|
|
// for this device's RECEIVE buffer queue.
|
|
// Our receive packets must only contain one buffer a piece,
|
|
// so #buffers == #packets.
|
|
//
|
|
NdisAllocatePacketPool(
|
|
&status, // return status
|
|
&pThisDev->hPacketPool, // handle to the packet pool
|
|
NUM_RCV_BUFS, // number of packet descriptors
|
|
16 // number of bytes reserved for ProtocolReserved field
|
|
);
|
|
|
|
if( status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
DEBUGMSG(DBG_ERR, (" NdisAllocatePacketPool failed. Returned 0x%.8x\n", status));
|
|
goto done;
|
|
}
|
|
|
|
NdisAllocateBufferPool(
|
|
&status, // return status
|
|
&pThisDev->hBufferPool,// handle to the buffer pool
|
|
NUM_RCV_BUFS // number of buffer descriptors
|
|
);
|
|
|
|
if( status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
DEBUGMSG(DBG_ERR, (" NdisAllocateBufferPool failed. Returned 0x%.8x\n", status));
|
|
pThisDev->BufferPoolAllocated = FALSE;
|
|
goto done;
|
|
}
|
|
|
|
pThisDev->BufferPoolAllocated = TRUE;
|
|
|
|
//
|
|
// Prepare the work items
|
|
//
|
|
for( i = 0; i < NUM_WORK_ITEMS; i++ )
|
|
{
|
|
PIR_WORK_ITEM pWorkItem;
|
|
|
|
pWorkItem = &(pThisDev->WorkItems[i]);
|
|
|
|
pWorkItem->pIrDevice = pThisDev;
|
|
pWorkItem->pInfoBuf = NULL;
|
|
pWorkItem->InfoBufLen = 0;
|
|
pWorkItem->fInUse = FALSE;
|
|
pWorkItem->Callback = NULL;
|
|
}
|
|
|
|
//
|
|
// Initialize each of the RECEIVE objects for this device.
|
|
//
|
|
for( i = 0; i < NUM_RCV_BUFS; i++ )
|
|
{
|
|
PNDIS_BUFFER pBuffer = NULL;
|
|
PRCV_BUFFER pReceivBuffer = &pThisDev->rcvBufs[i];
|
|
|
|
//
|
|
// Allocate a data buffer
|
|
//
|
|
pReceivBuffer->pDataBuf = MyMemAlloc( MAX_RCV_DATA_SIZE );
|
|
|
|
if( pReceivBuffer->pDataBuf == NULL )
|
|
{
|
|
status = NDIS_STATUS_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
NdisZeroMemory(
|
|
pReceivBuffer->pDataBuf,
|
|
MAX_RCV_DATA_SIZE
|
|
);
|
|
|
|
pReceivBuffer->pThisDev = pThisDev;
|
|
pReceivBuffer->DataLen = 0;
|
|
pReceivBuffer->BufferState = RCV_STATE_FREE;
|
|
|
|
#if defined(WORKAROUND_MISSING_C1)
|
|
pReceivBuffer->MissingC1Detected = FALSE;
|
|
#endif
|
|
|
|
//
|
|
// Allocate the NDIS_PACKET.
|
|
//
|
|
NdisAllocatePacket(
|
|
&status, // return status
|
|
&((PNDIS_PACKET)pReceivBuffer->pPacket), // return pointer to allocated descriptor
|
|
pThisDev->hPacketPool // handle to packet pool
|
|
);
|
|
|
|
if( status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
DEBUGMSG(DBG_ERR, (" NdisAllocatePacket failed. Returned 0x%.8x\n", status));
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
//
|
|
// These are the receive objects for the USB
|
|
//
|
|
pThisDev->PreReadBuffer.pDataBuf = MyMemAlloc( STIR4200_FIFO_SIZE );
|
|
|
|
if( pThisDev->PreReadBuffer.pDataBuf == NULL )
|
|
{
|
|
status = NDIS_STATUS_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
NdisZeroMemory(
|
|
pThisDev->PreReadBuffer.pDataBuf,
|
|
STIR4200_FIFO_SIZE
|
|
);
|
|
|
|
pThisDev->PreReadBuffer.pThisDev = pThisDev;
|
|
pThisDev->PreReadBuffer.DataLen = 0;
|
|
pThisDev->PreReadBuffer.BufferState = RCV_STATE_FREE;
|
|
|
|
//
|
|
// Synchronization events
|
|
//
|
|
KeInitializeEvent(
|
|
&pThisDev->EventSyncUrb,
|
|
NotificationEvent, // non-auto-clearing event
|
|
FALSE // event initially non-signalled
|
|
);
|
|
|
|
KeInitializeEvent(
|
|
&pThisDev->EventAsyncUrb,
|
|
NotificationEvent, // non-auto-clearing event
|
|
FALSE // event initially non-signalled
|
|
);
|
|
|
|
done:
|
|
//
|
|
// If we didn't complete the init successfully, then we should clean
|
|
// up what we did allocate.
|
|
//
|
|
if( status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
DEBUGMSG(DBG_ERR, (" InitializeDevice() FAILED\n"));
|
|
DeinitializeDevice(pThisDev);
|
|
}
|
|
else
|
|
{
|
|
DEBUGMSG(DBG_OUT, (" InitializeDevice() SUCCEEDED\n"));
|
|
}
|
|
|
|
DEBUGMSG(DBG_FUNC|DBG_PNP, ("-InitializeDevice()\n"));
|
|
return status;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Function: DeinitializeDevice
|
|
*
|
|
* Synopsis: deallocate the resources of the IR device object
|
|
*
|
|
* Arguments: pThisDev - the IR device object to close
|
|
*
|
|
* Returns: none
|
|
*
|
|
*
|
|
* Notes:
|
|
*
|
|
* Called for shutdown and reset.
|
|
* Don't clear hNdisAdapter, since we might just be resetting.
|
|
* This function should be called with device lock held.
|
|
*
|
|
*****************************************************************************/
|
|
VOID
|
|
DeinitializeDevice(
|
|
IN OUT PIR_DEVICE pThisDev
|
|
)
|
|
{
|
|
UINT i;
|
|
|
|
DEBUGMSG( DBG_FUNC|DBG_PNP, ("+DeinitializeDevice\n"));
|
|
|
|
pThisDev->linkSpeedInfo = NULL;
|
|
|
|
//
|
|
// Free all resources for the RECEIVE buffer queue.
|
|
//
|
|
for( i = 0; i < NUM_RCV_BUFS; i++ )
|
|
{
|
|
PNDIS_BUFFER pBuffer = NULL;
|
|
PRCV_BUFFER pRcvBuf = &pThisDev->rcvBufs[i];
|
|
|
|
if( pRcvBuf->pPacket != NULL )
|
|
{
|
|
NdisFreePacket( (PNDIS_PACKET)pRcvBuf->pPacket );
|
|
pRcvBuf->pPacket = NULL;
|
|
}
|
|
|
|
if( pRcvBuf->pDataBuf != NULL )
|
|
{
|
|
MyMemFree( pRcvBuf->pDataBuf, MAX_RCV_DATA_SIZE );
|
|
pRcvBuf->pDataBuf = NULL;
|
|
}
|
|
|
|
pRcvBuf->DataLen = 0;
|
|
}
|
|
|
|
//
|
|
// Deallocate the USB receive buffers
|
|
//
|
|
if( pThisDev->PreReadBuffer.pDataBuf != NULL )
|
|
MyMemFree( pThisDev->PreReadBuffer.pDataBuf, STIR4200_FIFO_SIZE );
|
|
|
|
//
|
|
// Free the packet and buffer pool handles for this device.
|
|
//
|
|
if( pThisDev->hPacketPool )
|
|
{
|
|
NdisFreePacketPool( pThisDev->hPacketPool );
|
|
pThisDev->hPacketPool = NULL;
|
|
}
|
|
|
|
if( pThisDev->BufferPoolAllocated )
|
|
{
|
|
NdisFreeBufferPool( pThisDev->hBufferPool );
|
|
pThisDev->BufferPoolAllocated = FALSE;
|
|
}
|
|
|
|
if( pThisDev->fDeviceStarted )
|
|
{
|
|
NTSTATUS ntstatus;
|
|
|
|
ntstatus = IrUsb_StopDevice( pThisDev );
|
|
DEBUGMSG(DBG_FUNC, (" DeinitializeDevice IrUsb_StopDevice() status = 0x%x\n",ntstatus));
|
|
}
|
|
|
|
InterlockedExchange( &pThisDev->fMediaBusy, FALSE );
|
|
InterlockedExchange( &pThisDev->fIndicatedMediaBusy, FALSE );
|
|
|
|
IrUsb_FreeSendStructures( pThisDev );
|
|
|
|
DEBUGMSG(DBG_FUNC|DBG_PNP, ("-DeinitializeDevice\n"));
|
|
}
|
|
|