📄 genport.c
字号:
}
deviceInfo = (PLOCAL_DEVICE_INFO) deviceObject->DeviceExtension;//提取设备信息(包括地址:地址范围等)
RtlZeroMemory(deviceInfo, sizeof(LOCAL_DEVICE_INFO));
// deviceInfo->DeviceObject = deviceObject;
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);//#define DOS_DEVICE_NAME L"\\DosDevices\\GpdDev"
DebugPrint((">>> win32DeviceName.Buffer=%s \n",win32DeviceName.Buffer));
status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );//在设备和用户可见设备名之间建立连接
if (!NT_SUCCESS(status)) // If we we couldn't create the link then
{ // abort installation.
IoDeleteDevice(deviceObject);
return status;
}
DebugPrint((">>> PortAddr=%X PortCount=%d\n",
(unsigned int)deviceInfo->PortBase ,
deviceInfo->PortCount ));
DebugPrint((">>> PortMemyType=%d \n",
(unsigned int)deviceInfo->PortMemoryType ));
/* deviceInfo->NextLowerDriver = IoAttachDeviceToDeviceStack (//把deviceObject 附属到 物理设备PhysicalDeviceObject上
deviceObject,
PhysicalDeviceObject);//PhysicalDeviceObject是入口参数
if(NULL == deviceInfo->NextLowerDriver) {
IoDeleteSymbolicLink(&win32DeviceName);
IoDeleteDevice(deviceObject);
return STATUS_NO_SUCH_DEVICE;
}
*/
IoInitializeRemoveLock (&deviceInfo->RemoveLock ,
PORTIO_TAG,
1, // MaxLockedMinutes
5); // HighWatermark, this parameter is
// used only on checked build.
//
// Set the flag if the device is not holding a pagefile
// crashdump file or hibernate file.
//
// deviceObject->Flags |= DO_POWER_PAGABLE;
deviceInfo->DeviceObject = deviceObject;//deviceInfo就是我们自己定义的设备参数(地址,地址空间等)
deviceInfo->Removed = FALSE;
deviceInfo->Started = FALSE;
// deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
//
// This values is based on the hardware design.
// Let us assume the address is in I/O space.
//
deviceInfo->PortMemoryType = 0;//存贮器访问 20060216
// DebugPrint(("AddDevice: %p to %p->%p \n", deviceObject,
// deviceInfo->NextLowerDriver,
// PhysicalDeviceObject));
//-------------------------结束 设备创建-----------------------------------------
//----------------查找PCI分配的954IO地址-----------------------------------------
//
// Ask the I/O Manager to use describe user read/write buffers using MDLs
//
deviceObject->Flags |= DO_BUFFERED_IO;//20060217 内存访问
//
// Next, get the HAL to tell us about the resources the device will use.
// These resources include ports, shared memory regions, interrupts, and
// the like. The resources will be resevered for us in the registry (so
// we do not have to call either IoReportResourceUsage or IoAssignResources).
//
deviceInfo->BusNumber = busNumber-1;
deviceInfo->SlotNumber = slotNumber;
status = HalAssignSlotResources(RegistryPath,
NULL,
DriverObject,
NULL,//deviceObject 20060317
PCIBus,
deviceInfo->BusNumber,
deviceInfo->SlotNumber.u.AsULONG,
&resources);
//
// On return from this call, all resources are identified and assigned for
// use by our device.
//
if (!NT_SUCCESS(status)) {
//
// log an appropriate error string.
//
#if DBG
DbgPrint("HalAssignSlotResourced failed! Status = 0x%0x", status);
#endif
//
// Clean up the mess
//
if(configInfo)
ExFreePool(configInfo);
if(resources)
ExFreePool(resources);
// OsrUnload(DriverObj);
//
// Indicate load failure to the I/O manager
//
return(status);
}
#if DBG
//
// For curiosity and debugging purposes, display the resources that were
// allocated for our use.
//
// OsrPrintResourceList(resources);
DbgPrint("%d. resource descriptor list(s) returned\n", resources->Count);
for (index = 0; index < resources->Count; index++) {
DbgPrint("\t[%d] Interface Type 0x%x\n",
index, resources->List[index].InterfaceType);
DbgPrint("\t[%d] BusNumber 0x%x\n",
index, resources->List[index].BusNumber);
DbgPrint("\t[%d] Version 0x%x\n",
index, resources->List[index].PartialResourceList.Version);
DbgPrint("\t[%d] Revision 0x%x\n",
index, resources->List[index].PartialResourceList.Revision);
DbgPrint("\t[%d] Partial Resource Descriptors %d.\n",
index, resources->List[index].PartialResourceList.Count);
for (index2 = 0;
index2 < resources->List[index].PartialResourceList.Count;
index2++) {
PCM_PARTIAL_RESOURCE_DESCRIPTOR prd; // Too much to type!
prd = &resources->List[index].PartialResourceList.PartialDescriptors[index2];
DbgPrint("\t\t[%d] Type 0x%x (%s)\n",
index2, prd->Type, CmResourceTypeStrings[prd->Type]);
DbgPrint("\t\t[%d] Share Disposition 0x%x (%s)\n",
index2, prd->ShareDisposition,
CmShareDispositionStrings[prd->ShareDisposition]);
DbgPrint("\t\t[%d] Flags 0x%x\n", index2, prd->Flags);
DbgPrint("\t\t[%d] Raw 0x%x %x %x\n",
index2, prd->u.DeviceSpecificData.DataSize,
prd->u.DeviceSpecificData.Reserved1,
prd->u.DeviceSpecificData.Reserved2);
switch (prd->Type) {
case CmResourceTypePort:
if (prd->Flags == CM_RESOURCE_PORT_MEMORY)
DbgPrint("\t\t[%d] port memory starting at 0x%x length 0x%x\n",
index2, prd->u.Port.Start.LowPart,
prd->u.Port.Length);
if (prd->Flags == CM_RESOURCE_PORT_IO)
DbgPrint("\t\t[%d] port i/o starting at 0x%x length 0x%x\n",
index2, prd->u.Port.Start.LowPart,
prd->u.Port.Length);
break;
case CmResourceTypeInterrupt:
if (prd->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)
DbgPrint("\t\t[%d] level interrupt at lvl 0x%x vector 0x%x affinity 0x%x\n",
index2, prd->u.Interrupt.Level,
prd->u.Interrupt.Vector,
prd->u.Interrupt.Affinity);
if (prd->Flags == CM_RESOURCE_INTERRUPT_LATCHED)
DbgPrint("\t\t[%d] latched interrupt at lvl 0x%x vector 0x%x affinity 0x%x\n",
index2, prd->u.Interrupt.Level,
prd->u.Interrupt.Vector,
prd->u.Interrupt.Affinity);
break;
case CmResourceTypeMemory:
if (prd->Flags == CM_RESOURCE_MEMORY_READ_WRITE)
DbgPrint("\t\t[%d] r/w memory starting at 0x%x length 0x%x\n",
index2, prd->u.Memory.Start.LowPart,
prd->u.Memory.Length);
if (prd->Flags & CM_RESOURCE_MEMORY_READ_ONLY)
DbgPrint("\t\t[%d] r/o memory starting at 0x%x length 0x%x\n",
index2, prd->u.Memory.Start.LowPart,
prd->u.Memory.Length);
if (prd->Flags & CM_RESOURCE_MEMORY_WRITE_ONLY)
DbgPrint("\t\t[%d] w/o memory starting at 0x%x length 0x%x\n",
index2, prd->u.Memory.Start.LowPart,
prd->u.Memory.Length);
break;
case CmResourceTypeDma:
DbgPrint("\t\t[%d] DMA on channel 0x%x\n",
index2, prd->u.Dma.Channel);
break;
case CmResourceTypeDeviceSpecific:
DbgPrint("\t\t[%d] Device specific data at 0x%x length 0x%x\n",
index2,
((ULONG) &prd->u.DeviceSpecificData.Reserved2) + (ULONG)sizeof(ULONG),
prd->u.DeviceSpecificData.DataSize);
break;
default:
//
// Say what?!! Unknown resource type. Something is pretty wierd here.
//
DbgPrint("Unknown resource type 0x%x\n", prd->Type);
break;
}
}
DbgPrint("\t[%d] ***** End dump ******\n", index);
}
portStart.LowPart = 0;
portLength = 0;
interruptLevel = 0;
interruptVector = 0;
#endif
//
// Decode the returned resources
//
// For our device, we know to expect an interrupt resource, and ONE set
// I/O space port resources. We expect, and we attempt to handle, no
// other resources.
//
for (index = 0; index < resources->Count; index++) {
for (index2 = 0;
index2 < resources->List[index].PartialResourceList.Count;
index2++) {
PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
prd = &resources->List[index].PartialResourceList.PartialDescriptors[index2];
switch (prd->Type) {
case CmResourceTypePort:
//
// Our port resources are in I/O space. And our port
// space is 64. bytes long.
//
// ASSERT(prd->Flags == CM_RESOURCE_PORT_IO);
// ASSERT(prd->u.Port.Length == 64);
portStart.HighPart = 0;
portStart.LowPart = prd->u.Port.Start.LowPart;
portLength = prd->u.Port.Length;
break;
case CmResourceTypeInterrupt:
//
// PCI interrupts are level sensitive
//
ASSERT(prd->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE);
interruptLevel = prd->u.Interrupt.Level;
interruptVector = prd->u.Interrupt.Vector;
if (prd->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)
DbgPrint("\t\t[%d] level interrupt at lvl 0x%x vector 0x%x affinity 0x%x\n",
index2, prd->u.Interrupt.Level,
prd->u.Interrupt.Vector,
prd->u.Interrupt.Affinity);
if (prd->Flags == CM_RESOURCE_INTERRUPT_LATCHED)
DbgPrint("\t\t[%d] latched interrupt at lvl 0x%x vector 0x%x affinity 0x%x\n",
index2, prd->u.Interrupt.Level,
prd->u.Interrupt.Vector,
prd->u.Interrupt.Affinity);
break;
#if DBG
case CmResourceTypeMemory:
portStart = prd->u.Memory.Start;
portLength = prd->u.Memory.Length;
DbgPrint("...Unexpected memory resource!\n");
DbgPrint("\t\tCmResourceTypeMemory[%d] memory starting at 0x%x length 0x%x\n",
index2, prd->u.Memory.Start.LowPart,
prd->u.Memory.Length);
break;
case CmResourceTypeDma:
DbgPrint("...Unexpected DMA resource!\n");
break;
case CmResourceTypeDeviceSpecific:
DbgPrint("...Unexpected device specific resource!\n");
break;
#endif
default:
DbgPrint("Unexpected and unknown resource type\n");
break;
}
}
}
//
// We NEED the interrupt info AND one port
//
ASSERT(interruptLevel && interruptVector && portStart.LowPart && portLength);
//
// Indciate that the resigsters are in port space on this card
//
// addressSpace = 0x01;//原来的程序
addressSpace = 0x00;//20060217 内存空间
//
// Get the HAL to translate our bus-relative port base address, to an
// unambiguous address to be used for device access. If we're returned
// FALSE, the call failed.
//
if (!HalTranslateBusAddress(PCIBus,
deviceInfo->BusNumber,
portStart,
&addressSpace,
&address)) {
//
// Print an appropriate error string.
//
#if DBG
DbgPrint("HalAssignSlotResourced failed\n");
#endif
//
// Clean up the mess
//
// OsrReturnPool(configInfo, deviceDescription, resources);
if(configInfo)
ExFreePool(configInfo);
if(resources)
ExFreePool(resources);
// OsrUnload(DriverObj);
//
//
return(STATUS_UNSUCCESSFUL);
}
//
// If this card's I/O space registers actually appear in memory space on
// this processor, we need to map them with some kernel virtual addresses
// so we can access them. This may be the case on, for example, some RISC
// processors. NOTE HOWEVER, that regardless of the addressSpace returned,
// since the registers on the card are in PORT I/O space, we will ALWAYS
// access them in the driver using WRITE_PORT_xxx and READ_PORT_xxx.
//
if (addressSpace == 0x0) {
ULONG lengthInBytes;
#if DBG
DbgPrint("Address space for port is MEMORY\n");
#endif
lengthInBytes =
resources->List[0].PartialResourceList.PartialDescriptors[2].u.Memory.Length;
DbgPrint("lengthInBytes = 0x%X\n",lengthInBytes);
//
// Maps a potentially 64 bit physical address to a 32 bit virtual address.
//
deviceInfo->PortBase = MmMapIoSpace(address,
lengthInBytes,
FALSE);
deviceInfo->PortCount = lengthInBytes;
deviceInfo->PortWasMapped = TRUE;
DebugPrint(("deviceInfo = 0x%X PortBase = 0x%X length 0x%X",deviceInfo,deviceInfo->PortBase,deviceInfo->PortCount));
//找到内存映射地址之后初始化相关参数
for(i = 0;i < COM_NUM;i ++)
{
for(j = 0;j < 2;j++)
{
deviceInfo->BufBase [j][i] = (PVOID)((ULONG)deviceInfo->PortBase + (ULONG)BUFBASE[j][i]);
deviceInfo->PtrBuf [j][i] = deviceInfo->BufBase [j][i];
deviceInfo->DataNumBase [j][i] = (PVOID)((ULONG)deviceInfo->PortBase + (ULONG)NUMBASE[j][i]);
KeInitializeSemaphore(&deviceInfo->BufSemaphore[j][i], 1, 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -