📄 pnp.c
字号:
// driver
//
//
// Wait until all active requests on the device have
// completed...
//
OsrWaitForStop(devExt);
//
// There are NO ACTIVE IRPs on the device at this point.
//
//
// Return any resources we're using.
//
OsrReturnResources(devExt);
//
// NOTE: We DO NOT delete our device object here. This is
// one difference between a _STOP_DEVICE and _REMOVE_DEVICE.
//
#if DBG
DbgPrint("OsrPnp: Passing along request\n");
#endif
//
// Pass this request on down to the bus driver
//
IoSkipCurrentIrpStackLocation(Irp);
//
// We're cool with the stop...
//
Irp->IoStatus.Status = STATUS_SUCCESS;
code = IoCallDriver(devExt->DeviceToSendIrpsTo, Irp);
break;
//
// STATE: STOP_PENDING
// IRP_MN: _CANCEL_STOP_DEVICE
//
// We're here because we've already received a QUERY_STOP,
// that we've agreed to. We've completed any pending I/O
// requests. Now we've received a CANCEL_STOP_DEVICE
// IRP, that sort of says "never mind" about that stop.
//
// We restart our queues and return to Started state.
//
case STATE_STOP_PENDING + IRP_MN_CANCEL_STOP_DEVICE:
#if DBG
DbgPrint("OsrPnp: PROCESSING CANCEL_STOP\n");
#endif
//
// fall through...
//
//
// STATE: REMOVE_PENDING
// IRP_MN: _CANCEL_REMOVE_DEVICE
//
// We're here because we've already received a QUERY_REMOVE,
// that we've agreed to. We've completed any pending I/O
// requests. Now we've received a CANCEL_REMOVE_DEVICE
// IRP, that sort of says "never mind" about that remove.
//
// We restart our queues and return to Started state.
//
case STATE_REMOVE_PENDING + IRP_MN_CANCEL_REMOVE_DEVICE:
#if DBG
if( devExt->State == STATE_REMOVE_PENDING) {
DbgPrint("OsrPnp: PROCESSING CANCEL_REMOVE\n");
}
#endif
//
// The Underlying BUS DRIVER must handle these IRPs
// before we do...
//
//
// We need to wait for the underlying bus driver to
// get restarted, before we can continue processing.
//
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
OsrPnpComplete,
&eventWaitLowerDrivers,
TRUE,
TRUE,
TRUE);
code = IoCallDriver(devExt->DeviceToSendIrpsTo, Irp);
if(code == STATUS_PENDING) {
KeWaitForSingleObject(&eventWaitLowerDrivers,
Executive,
KernelMode,
FALSE,
NULL);
}
//
// We're now in STARTED state
//
devExt->State = STATE_STARTED;
//
// Go see if there's a request that we can start now
//
OsrProcessQueuedRequests(devExt);
code = STATUS_SUCCESS;
Irp->IoStatus.Status = code;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
default:
//
// DEFAULT CASE
// Just pass the request to the lower driver
//
#if DBG
DbgPrint("OsrPnp: Default case: Just pass it along...\n");
#endif
IoSkipCurrentIrpStackLocation (Irp);
code = IoCallDriver (devExt->DeviceToSendIrpsTo, Irp);
break;
}
//
// Adjust in-progress request count
//
OsrRequestDecrement(devExt);
#if DBG
DbgPrint("OsrPnp: Leaving with new state ");
OsrPrintState(devExt);
DbgPrint("OsrPnp: exit (%d.).\n", devExt->OutstandingIO);
#endif
//
// We always finish our work in this function
//
ASSERT(code != STATUS_PENDING);
return(code);
}
//
// OsrPnpComplete
//
// This is the completion routine for IRP_MJ_PNP requests
//
NTSTATUS
OsrPnpComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
{
PIO_STACK_LOCATION iostack;
PKEVENT pEvent = (PKEVENT) Context;
NTSTATUS status = STATUS_SUCCESS;
UNREFERENCED_PARAMETER (DeviceObject);
iostack = IoGetCurrentIrpStackLocation (Irp);
//
// Driver Writers, please note:
//
// The following code is only necessary IF (a) WE have a completion
// routine, AND (b) WE return STATUS_PENDING from our dispatch entry
// point after re-claiming the IRP. Since neither of these things
// is true... this code does not belong here.
//
// if (Irp->PendingReturned) {
//
// IoMarkIrpPending( Irp );
//
// }
switch (iostack->MajorFunction) {
case IRP_MJ_PNP:
KeSetEvent(pEvent, 0, FALSE);
//
// Take the IRP back so that we can continue using it during
// the IRP_MN_START_DEVICE dispatch routine.
// NB: we will have to call IoCompleteRequest
//
return STATUS_MORE_PROCESSING_REQUIRED;
break;
case IRP_MJ_POWER:
#if DBG
DbgPrint("OsrPnpComplete: NOT MJ_POWER support in this driver!\n");
#endif
break;
default:
#if DBG
DbgPrint("OsrPnpComplete: NOT MJ_PNP or MJ_POWER IRP??\n");
#endif
break;
}
return status;
}
///////////////////////////////////////////////////////////////////////////////
//
// OsrStartDevice
//
// This function is called from the DispatchPnp Entry Point to
// actually start the hardware.
//
// INPUTS:
//
// DevExt - Address of our device extension.
// IoStackLocation -- Pointer to I/O Stack Location containing
// configuration information
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// STATUS_SUCCESS;
//
// IRQL:
//
//
// NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS
OsrStartDevice(IN POSR_DEVICE_EXT DevExt,
IN PIO_STACK_LOCATION IoStackLocation)
{
NTSTATUS code = STATUS_SUCCESS;
ULONG index;
PDEVICE_DESCRIPTION deviceDescription;
PCM_RESOURCE_LIST pResourceList, pResourceListTranslated;
PCM_PARTIAL_RESOURCE_LIST prl, prlTranslated;
PCM_PARTIAL_RESOURCE_DESCRIPTOR prd, prdTranslated;
PCM_FULL_RESOURCE_DESCRIPTOR frd, frdTranslated;
pResourceList = IoStackLocation->Parameters.StartDevice.AllocatedResources;
pResourceListTranslated = IoStackLocation->Parameters.StartDevice.AllocatedResourcesTranslated;
frd = &pResourceList->List[0];
frdTranslated = &pResourceListTranslated->List[0];
prl = &frd->PartialResourceList;
prlTranslated = &frdTranslated->PartialResourceList;
#if DBG
OsrPrintResourceList(pResourceList);
OsrPrintResourceList(pResourceListTranslated);
#endif
//
// Ensure the base address starts as NULL
//
DevExt->AmccBaseRegisterAddress = NULL;
//
// Walk through the partial resource descriptors to find the
// hardware resources that have been allocated to us
//
// We need one range of port addresses (0x40 bytes long) and
// and interrupt resource.
//
for (index = 0,
prd = &prl->PartialDescriptors[index],
prdTranslated = &prlTranslated->PartialDescriptors[index];
index < prl->Count && NT_SUCCESS(code);
index++, prd++, prdTranslated++) {
switch (prd->Type) {
case CmResourceTypePort:
//
// Newer AMCC Demo Boards have more than just one BAR
// programmed in the PCI configuration ROM. We want
// the FIRST BAR, which is the base address of the
// device itself. So, we ignore any ports reported to
// us after the first one.
//
if (DevExt->AmccBaseRegisterAddress) {
#if DBG
DbgPrint("Ignoring additional port resource ...\n");
if(prdTranslated->Type == CmResourceTypePort) {
DbgPrint("(Translated port 0x%0x)\n",
prdTranslated->u.Port.Start.LowPart);
} else {
DbgPrint("(Translated memory 0x%0x)\n",
prdTranslated->u.Memory.Start);
}
#endif
break;
}
#if DBG
DbgPrint("Configuring port resource ...\n");
#endif
//
// Should only get ONE port resources
//
ASSERT(DevExt->AmccBaseRegisterAddress == NULL);
//
// Our port space on this card is 0x40 bytes longs
//
ASSERT(prd->u.Memory.Length == 0x40);
//
// Do the device ports appear in port I/O space or
// in memory space on this machine.
//
if(prdTranslated->Type == CmResourceTypePort) {
//
// The port is in port space on this machine. Just
// store away the address
//
DevExt->MappedPorts = FALSE;
DevExt->AmccBaseRegisterAddress =
(PVOID) prdTranslated->u.Port.Start.LowPart;
#if DBG
DbgPrint("Translated resource is a port at 0x%0x\n",
DevExt->AmccBaseRegisterAddress);
#endif
} else {
ASSERT(prdTranslated->Type == CmResourceTypeMemory);
//
// The port is in memory space on this machine. We
// need to map some virtual addresses over the physical
// address provided us, and remember to do an UNMAP
// if/when we have to return the resources.
//
DevExt->MappedPorts = TRUE;
DevExt->AmccBaseRegisterAddress =
MmMapIoSpace(prdTranslated->u.Memory.Start,
prdTranslated->u.Memory.Length,
MmNonCached);
#if DBG
DbgPrint("Translated resource is MEMORY at 0x%0x\n",
DevExt->AmccBaseRegisterAddress);
#endif
}
break;
case CmResourceTypeInterrupt:
#if DBG
DbgPrint("Configuring Interrupt resource ...\n");
#endif
//
// Be sure we get only ONE interrupt resource
//
ASSERT(DevExt->InterruptLevel == 0);
//
// Again, assume that the translated and raw resources
// are in the same order and number
//
ASSERT(CmResourceTypeInterrupt == prdTranslated->Type);
DevExt->InterruptLevel = (UCHAR)prdTranslated->u.Interrupt.Level;
DevExt->InterruptVector = prdTranslated->u.Interrupt.Vector;
DevExt->InterruptAffinity = prdTranslated->u.Interrupt.Affinity;
if (prdTranslated->Flags & CM_RESOURCE_INTERRUPT_LATCHED) {
DevExt->InterruptMode = Latched;
} else {
DevExt->InterruptMode = LevelSensitive;
}
//
// Because this is a PCI device, we KNOW it must be
// a LevelSensitive Interrupt
//
ASSERT(DevExt->InterruptMode == LevelSensitive);
#if DBG
DbgPrint("Interrupt level: 0x%0x, Vector: 0x%0x, Affinity: 0x%0x\n",
DevExt->InterruptLevel,
DevExt->InterruptVector,
DevExt->InterruptAffinity);
#endif
break;
default:
#if DBG
DbgPrint("OSRPCI: Unhandled Resource -- CmResourceType received 0x%x\n", prd->Type);
#endif
break;
}
}
//
// We NEED the interrupt info AND one port
//
ASSERT(DevExt->InterruptLevel && DevExt->AmccBaseRegisterAddress);
//
// Register our DPCforISR routine. This is the routine which will
// be used to complete our interrupt processing.
//
IoInitializeDpcRequest(DevExt->FunctionalDeviceObject, OsrDpcForIsr);
//
// Connect to interrupt from the device. After this call,
// interrupts from the device will result in calls to our OsrHandleInterrupt
// function.
//
code = IoConnectInterrupt(&DevExt->InterruptObject,
OsrHandleInterrupt,
DevExt, // ISR Context
NULL,
DevExt->InterruptVector,
DevExt->InterruptLevel,
DevExt->InterruptLevel,
DevExt->InterruptMode,
TRUE,
DevExt->InterruptAffinity,
FALSE);
if (!NT_SUCCESS(code)) {
#if DBG
DbgPrint("IoConnectInterrupt failed with error 0x%x", code);
#endif
//
// We're outa here
//
return(code);
}
//
// Now we reset the adapter card.
//
OsrResetAdapter(DevExt->FunctionalDeviceObject, FALSE);
//
// Finally, we get our adapter object from the HAL. When we do this,
// we describe out device to the HAL, in pretty gory detail. In
// return, the HAL gives us a pointer to our adapter object, and
// tells us the maximum number of mapping registers we can ever
// hope to get.
//
deviceDescription = ExAllocatePoolWithTag(PagedPool,
sizeof(DEVICE_DESCRIPTION),
'pRSO');
//
// Important: Zero out the entire structure first!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -