📄 nsc.c
字号:
* but I've seen devices get extra resources.
* So give the NdisMQueryAdapterResources call room for 10 resources.
*/
#define RESOURCE_LIST_BUF_SIZE (sizeof(NDIS_RESOURCE_LIST) + (10*sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)))
UCHAR buf[RESOURCE_LIST_BUF_SIZE];
PNDIS_RESOURCE_LIST resList = (PNDIS_RESOURCE_LIST)buf;
UINT bufSize = RESOURCE_LIST_BUF_SIZE;
DBGOUT((TEXT("==>GetPnPResources")));
NdisMQueryAdapterResources(&stat, WrapperConfigurationContext, resList, &bufSize);
if (stat == NDIS_STATUS_SUCCESS){
PCM_PARTIAL_RESOURCE_DESCRIPTOR resDesc;
BOOLEAN haveIRQ = FALSE,
haveIOAddr = FALSE,
haveDma = FALSE;
UINT i;
for (resDesc = resList->PartialDescriptors, i = 0;
i < resList->Count;
resDesc++, i++){
switch (resDesc->Type){
case CmResourceTypePort:
if (haveIOAddr){
/*
* The *PNP0510 chip on the IBM ThinkPad 760EL
* gets an extra IO range assigned to it.
* So only pick up the first IO port range;
* ignore this subsequent one.
*/
DBGERR(("Ignoring extra PnP IO base %xh because already using %xh.",
(UINT)resDesc->u.Port.Start.LowPart,
(UINT)thisDev->portInfo.ioBase));
}
else {
thisDev->portInfo.ioBase = resDesc->u.Port.Start.LowPart;
haveIOAddr = TRUE;
DBGOUT(("Got UART IO addr: %xh.", thisDev->portInfo.ioBase));
}
break;
case CmResourceTypeInterrupt:
if (haveIRQ){
DBGERR(("Ignoring second PnP IRQ %xh because already using %xh.",
(UINT)resDesc->u.Interrupt.Level, thisDev->portInfo.irq));
}
else {
thisDev->portInfo.irq = resDesc->u.Interrupt.Level;
haveIRQ = TRUE;
DBGOUT(("Got PnP IRQ: %d.", thisDev->portInfo.irq));
}
break;
case CmResourceTypeDma:
if (haveDma){
DBGERR(("Ignoring second DMA address %d because already using %d.",
(UINT)resDesc->u.Dma.Channel, (UINT)thisDev->portInfo.DMAChannel));
}
else {
ASSERT(!(resDesc->u.Dma.Channel&0xffffff00));
thisDev->portInfo.DMAChannel = (UCHAR)resDesc->u.Dma.Channel;
haveDma = TRUE;
DBGOUT(("Got DMA channel: %d.", thisDev->portInfo.DMAChannel));
}
break;
}
}
result = (haveIOAddr && haveIRQ && haveDma);
}
DBGOUT((TEXT("<==GetPnPResources")));
return result;
}
#endif // !UNDER_CE
/*
*************************************************************************
* Configure
*************************************************************************
*
* Read configurable parameters out of the system registry.
*
*/
BOOLEAN Configure(
IrDevice *thisDev,
NDIS_HANDLE WrapperConfigurationContext
)
{
//
// Status of Ndis calls.
//
NDIS_STATUS Status;
//
// The handle for reading from the registry.
//
NDIS_HANDLE ConfigHandle;
//
// TRUE if there is a configuration error.
//
BOOLEAN ConfigError = FALSE;
//
// A special value to log concerning the error.
//
ULONG ConfigErrorValue = 0;
#ifndef UNDER_CE
ULONG SlotNumber;
#endif // !UNDER_CE
DBGOUT((TEXT("Configure(0x%x)"), (UINT)thisDev));
NdisOpenConfiguration(&Status, &ConfigHandle, WrapperConfigurationContext);
if (Status != NDIS_STATUS_SUCCESS){
DBGERR((TEXT("NdisOpenConfiguration failed in Configure()")));
return FALSE;
}
NdisCloseConfiguration(ConfigHandle);
DBGINIT((TEXT("NSC configure done: ConfigIO=0x%x UartIO=0x%x irq=%d DMA=%d"),
thisDev->portInfo.ConfigIoBaseAddr,thisDev->portInfo.ioBase,
thisDev->portInfo.irq,thisDev->portInfo.DMAChannel));
DBGOUT((TEXT("<==Configure")));
return TRUE;
}
/*
*************************************************************************
* MiniportInitialize
*************************************************************************
*
*
* Initializes the network interface card.
*
*
*
*/
NDIS_STATUS MiniportInitialize ( PNDIS_STATUS OpenErrorStatus,
PUINT SelectedMediumIndex,
PNDIS_MEDIUM MediumArray,
UINT MediumArraySize,
NDIS_HANDLE NdisAdapterHandle,
NDIS_HANDLE WrapperConfigurationContext
)
{
UINT mediumIndex;
IrDevice *thisDev = NULL;
NDIS_STATUS retStat, result = NDIS_STATUS_SUCCESS;
DBGOUT((TEXT("MiniportInitialize()")));
/*
* Search the passed-in array of supported media for the IrDA medium.
*/
for (mediumIndex = 0; mediumIndex < MediumArraySize; mediumIndex++){
if (MediumArray[mediumIndex] == NdisMediumIrda){
break;
}
}
if (mediumIndex < MediumArraySize){
*SelectedMediumIndex = mediumIndex;
}
else {
/*
* Didn't see the IrDA medium
*/
DBGERR((TEXT("Didn't see the IRDA medium in MiniportInitialize")));
result = NDIS_STATUS_UNSUPPORTED_MEDIA;
goto _initDone;
}
/*
* Allocate a new device object to represent this connection.
*/
thisDev = NewDevice();
if (!thisDev){
return NDIS_STATUS_NOT_ACCEPTED;
}
#ifdef UNDER_CE
// CE - calls NdisMInitializeTimer instead of NdisInitializeTimer. This
// requires the NdisAdapterHandle. Else the timer is initialized
// in InitDevice.
NdisMInitializeTimer(&thisDev->TurnaroundTimer,
NdisAdapterHandle,
DelayedWrite,
thisDev);
#endif // UNDER_CE
/*
* Allocate resources for this connection.
*/
if (!OpenDevice(thisDev)){
DBGERR((TEXT("OpenDevice failed")));
result = NDIS_STATUS_FAILURE;
goto _initDone;
}
/*
* Read the system registry to get parameters like COM port number, etc.
*/
if (!Configure(thisDev, WrapperConfigurationContext)){
result = NDIS_STATUS_FAILURE;
goto _initDone;
}
/*
* This call 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.
*/
NdisMSetAttributes ( NdisAdapterHandle,
(NDIS_HANDLE)thisDev,
FALSE,
NdisInterfaceInternal
);
/*
* Tell NDIS about the range of IO space that we'll be using.
*/
/* retStat = NdisMRegisterIoPortRange( (PVOID)thisDev->mappedPortRange,
NdisAdapterHandle,
thisDev->portInfo.ioBase,
8);
if (retStat != NDIS_STATUS_SUCCESS){
DBGERR((TEXT("NdisMRegisterIoPortRange failed")));
result = NDIS_STATUS_FAILURE;
goto _initDone;
}
*/
/*
* Record the NDIS wrapper's handle for this adapter, which we use
* when we call up to the wrapper.
* (This miniport's adapter handle is just thisDev, the pointer to the device object.).
*/
DBGOUT((TEXT("NDIS handle: %xh <-> NSCIRDA handle: %xh"),
(UINT)NdisAdapterHandle, (UINT)thisDev));
thisDev->ndisAdapterHandle = NdisAdapterHandle;
/*
* Open COMM communication channel.
* This will let the dongle driver update its capabilities from their default values.
*/
if (!DoOpen(thisDev)){
DBGERR((TEXT("DoOpen failed")));
result = NDIS_STATUS_FAILURE;
goto _initDone;
}
/*
* Do special NSC setup
* (do this after comport resources, like read buf, have been allocated).
*/
if (!NSC_Setup(thisDev)){
DBGERR((TEXT("NSC_Setup failed")));
result = NDIS_STATUS_FAILURE;
goto _initDone;
}
/*
* Register an interrupt with NDIS.
*/
retStat = NdisMRegisterInterrupt( (PNDIS_MINIPORT_INTERRUPT)&thisDev->interruptObj,
NdisAdapterHandle,
dwSysIntrIR-dwSysIntrFirmware,//(SYSINTR_IR - SYSINTR_FIRMWARE), // thisDev->portInfo.irq,
dwSysIntrIR-dwSysIntrFirmware,//(SYSINTR_IR - SYSINTR_FIRMWARE), // thisDev->portInfo.irq,
TRUE, // want ISR
TRUE, // MUST share interrupts
NdisInterruptLevelSensitive //99.04.21 NdisInterruptLatched
);
if (retStat != NDIS_STATUS_SUCCESS){
DBGERR((TEXT("NdisMRegisterInterrupt failed")));
result = NDIS_STATUS_FAILURE;
goto _initDone;
}
_initDone:
if (result == NDIS_STATUS_SUCCESS){
/*
* Add this device object to the beginning of our global list.
*/
thisDev->next = firstIrDevice;
firstIrDevice = thisDev;
#ifdef UNDER_CE
// For WinCE, we release the resources and they will be reclaimed,
// when OID_IRDA_REACQUIRE_HW_RESOURCES msg is recvd.
thisDev->resourcesReleased=TRUE;
CloseCOM(thisDev);
// Still successful.
#else // UNDER_CE
thisDev->resourcesReleased=FALSE;
#endif //!UNDER_CE
DBGOUT((TEXT("MiniportInitialize succeeded")));
}
else {
if (thisDev){
FreeDevice(thisDev);
}
DBGERR((TEXT("MiniportInitialize failed")));
}
return result;
}
/*
*************************************************************************
* QueueReceivePacket
*************************************************************************
*
*
*
*
*/
VOID QueueReceivePacket(IrDevice *thisDev, PUCHAR data, UINT dataLen, BOOLEAN IsFIR) /* not need to change */
{
rcvBuffer *rcvBuf = NULL;
PLIST_ENTRY ListEntry;
/*
* Note: We cannot use a spinlock to protect the rcv buffer structures
* in an ISR. This is ok, since we used a sync-with-isr function
* the the deferred callback routine to access the rcv buffers.
*/
LOG(TEXT("==> QueueReceivePacket, len: "), dataLen);
DBGOUT((TEXT("==> QueueReceivePacket(0x%x, 0x%lx, 0x%x)"),
(UINT) thisDev, data, dataLen));
if (!IsFIR)
{
// This function is called inside the ISR during SIR mode.
if (IsListEmpty(&thisDev->rcvBufFree))
{
ListEntry = NULL;
}
else
{
ListEntry = RemoveHeadList(&thisDev->rcvBufFree);
}
}
else
{
ListEntry = NDISSynchronizedRemoveHeadList(&thisDev->rcvBufFree,
&thisDev->interruptObj);
}
if (ListEntry)
{
rcvBuf = CONTAINING_RECORD(ListEntry,
rcvBuffer,
listEntry);
if (IsFIR)
{
LOG_Data(thisDev, data);
}
}
if (rcvBuf){
#ifdef DATALOGDEBUG
{
ULONG index;
PUCHAR workPtr = data;
RETAILMSG(1, (TEXT("IN\r\n")));
for (index = 0; index < dataLen; index++)
{
RETAILMSG(1, (TEXT(" 0x%x\r\n"), *workPtr++));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -