Fixed an issue with the Nuvoton NCT6791D (hardware monitor i/o space lock wasn't disabled before attempting to read data).
1 //-----------------------------------------------------------------------------
3 // Mail : hiyohiyo@crystalmark.info
4 // Web : http://openlibsys.org/
5 // License : The modified BSD license
7 // Copyright 2007-2008 OpenLibSys.org. All rights reserved.
8 //-----------------------------------------------------------------------------
12 #include "OpenLibSys.h"
14 //-----------------------------------------------------------------------------
18 //-----------------------------------------------------------------------------
20 static ULONG refCount;
22 //-----------------------------------------------------------------------------
25 // DriverEntry / OlsDispatch / Unload
27 //-----------------------------------------------------------------------------
31 IN PDRIVER_OBJECT DriverObject,
32 IN PUNICODE_STRING RegistryPath
39 STATUS_SUCCESS if the driver initialized correctly, otherwise an erroror
40 indicating the reason for failure.
45 UNICODE_STRING ntDeviceName;
46 UNICODE_STRING win32DeviceName;
47 PDEVICE_OBJECT deviceObject = NULL;
49 RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME);
51 status = IoCreateDevice(
52 DriverObject, // Our Driver Object
53 0, // We don't use a device extension
54 &ntDeviceName, // Device name
55 OLS_TYPE, // Device type
56 FILE_DEVICE_SECURE_OPEN, // Device characteristics
57 FALSE, // Not an exclusive device
58 &deviceObject ); // Returned ptr to Device Object
60 if(!NT_SUCCESS(status))
70 // Initialize the driver object with this driver's entry points.
71 DriverObject->MajorFunction[IRP_MJ_CREATE] = OlsDispatch;
72 DriverObject->MajorFunction[IRP_MJ_CLOSE] = OlsDispatch;
73 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = OlsDispatch;
74 DriverObject->DriverUnload = Unload;
76 // Initialize a Unicode String containing the Win32 name for our device.
77 RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
79 // Create a symbolic link between our device name and the Win32 name
80 status = IoCreateSymbolicLink(&win32DeviceName, &ntDeviceName);
82 if (!NT_SUCCESS(status))
84 // Delete everything that this routine has allocated.
85 IoDeleteDevice( deviceObject );
93 IN PDEVICE_OBJECT pDO,
100 This routine is the dispatch handler for the driver. It is responsible
101 for processing the IRPs.
105 pDO - Pointer to device object.
107 pIrp - Pointer to the current IRP.
111 STATUS_SUCCESS if the IRP was processed successfully, otherwise an erroror
112 indicating the reason for failure.
117 PIO_STACK_LOCATION pIrpStack;
121 // Initialize the irp info field.
122 // This is used to return the number of bytes transfered.
123 pIrp->IoStatus.Information = 0;
124 pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
126 // Set default return status
127 status = STATUS_NOT_IMPLEMENTED;
129 // Dispatch based on major fcn code.
130 switch(pIrpStack->MajorFunction)
133 if(refCount != (ULONG)-1){refCount++;}
134 status = STATUS_SUCCESS;
137 if(refCount != (ULONG)-1){refCount--;}
138 status = STATUS_SUCCESS;
141 case IRP_MJ_DEVICE_CONTROL:
143 switch(pIrpStack->Parameters.DeviceIoControl.IoControlCode)
145 case IOCTL_OLS_GET_DRIVER_VERSION:
146 *(PULONG)pIrp->AssociatedIrp.SystemBuffer = OLS_DRIVER_VERSION;
147 pIrp->IoStatus.Information = 4;
148 status = STATUS_SUCCESS;
151 case IOCTL_OLS_GET_REFCOUNT:
152 *(PULONG)pIrp->AssociatedIrp.SystemBuffer = refCount;
153 pIrp->IoStatus.Information = sizeof(refCount);
154 status = STATUS_SUCCESS;
157 case IOCTL_OLS_READ_MSR:
159 pIrp->AssociatedIrp.SystemBuffer,
160 pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
161 pIrp->AssociatedIrp.SystemBuffer,
162 pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
163 (ULONG*)&pIrp->IoStatus.Information
166 case IOCTL_OLS_WRITE_MSR:
168 pIrp->AssociatedIrp.SystemBuffer,
169 pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
170 pIrp->AssociatedIrp.SystemBuffer,
171 pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
172 (ULONG*)&pIrp->IoStatus.Information
175 case IOCTL_OLS_READ_PMC:
177 pIrp->AssociatedIrp.SystemBuffer,
178 pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
179 pIrp->AssociatedIrp.SystemBuffer,
180 pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
181 (ULONG*)&pIrp->IoStatus.Information
186 status = STATUS_SUCCESS;
189 case IOCTL_OLS_READ_IO_PORT:
190 case IOCTL_OLS_READ_IO_PORT_BYTE:
191 case IOCTL_OLS_READ_IO_PORT_WORD:
192 case IOCTL_OLS_READ_IO_PORT_DWORD:
194 pIrpStack->Parameters.DeviceIoControl.IoControlCode,
195 pIrp->AssociatedIrp.SystemBuffer,
196 pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
197 pIrp->AssociatedIrp.SystemBuffer,
198 pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
199 (ULONG*)&pIrp->IoStatus.Information
202 case IOCTL_OLS_WRITE_IO_PORT:
203 case IOCTL_OLS_WRITE_IO_PORT_BYTE:
204 case IOCTL_OLS_WRITE_IO_PORT_WORD:
205 case IOCTL_OLS_WRITE_IO_PORT_DWORD:
206 status = WriteIoPort(
207 pIrpStack->Parameters.DeviceIoControl.IoControlCode,
208 pIrp->AssociatedIrp.SystemBuffer,
209 pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
210 pIrp->AssociatedIrp.SystemBuffer,
211 pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
212 (ULONG*)&pIrp->IoStatus.Information
216 case IOCTL_OLS_READ_PCI_CONFIG:
217 status = ReadPciConfig(
218 pIrp->AssociatedIrp.SystemBuffer,
219 pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
220 pIrp->AssociatedIrp.SystemBuffer,
221 pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
222 (ULONG*)&pIrp->IoStatus.Information
225 case IOCTL_OLS_WRITE_PCI_CONFIG:
226 status = WritePciConfig(
227 pIrp->AssociatedIrp.SystemBuffer,
228 pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
229 pIrp->AssociatedIrp.SystemBuffer,
230 pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
231 (ULONG*)&pIrp->IoStatus.Information
235 case IOCTL_OLS_READ_MEMORY:
237 pIrp->AssociatedIrp.SystemBuffer,
238 pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
239 pIrp->AssociatedIrp.SystemBuffer,
240 pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
241 (ULONG*)&pIrp->IoStatus.Information
244 case IOCTL_OLS_WRITE_MEMORY:
245 status = WriteMemory(
246 pIrp->AssociatedIrp.SystemBuffer,
247 pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
248 pIrp->AssociatedIrp.SystemBuffer,
249 pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
250 (ULONG*)&pIrp->IoStatus.Information
259 // We're done with I/O request. Record the status of the I/O action.
260 pIrp->IoStatus.Status = status;
262 // Don't boost priority when returning since this took little time.
263 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
270 PDRIVER_OBJECT DriverObject
276 This routine is called by the I/O system to unload the driver.
278 Any resources previously allocated must be freed.
282 DriverObject - a pointer to the object that represents our driver.
290 PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
291 UNICODE_STRING win32NameString;
295 // Create counted string version of our Win32 device name.
296 RtlInitUnicodeString(&win32NameString, DOS_DEVICE_NAME);
298 // Delete the link from our device name to a name in the Win32 namespace.
299 IoDeleteSymbolicLink(&win32NameString);
301 if(deviceObject != NULL)
303 IoDeleteDevice(deviceObject);
307 //-----------------------------------------------------------------------------
311 //-----------------------------------------------------------------------------
314 ReadMsr( void *lpInBuffer,
317 ULONG nOutBufferSize,
318 ULONG *lpBytesReturned)
322 ULONGLONG data = __readmsr(*(ULONG*)lpInBuffer);
323 memcpy((PULONG)lpOutBuffer, &data, 8);
324 *lpBytesReturned = 8;
325 return STATUS_SUCCESS;
327 __except(EXCEPTION_EXECUTE_HANDLER)
329 *lpBytesReturned = 0;
330 return STATUS_UNSUCCESSFUL;
335 WriteMsr( void *lpInBuffer,
338 ULONG nOutBufferSize,
339 ULONG *lpBytesReturned)
343 OLS_WRITE_MSR_INPUT* param;
344 param = (OLS_WRITE_MSR_INPUT*)lpInBuffer;
346 __writemsr(param->Register, param->Value.QuadPart);
347 *lpBytesReturned = 0;
348 return STATUS_SUCCESS;
350 __except(EXCEPTION_EXECUTE_HANDLER)
352 *lpBytesReturned = 0;
353 return STATUS_UNSUCCESSFUL;
358 ReadPmc( void *lpInBuffer,
361 ULONG nOutBufferSize,
362 ULONG *lpBytesReturned)
366 ULONGLONG data = __readpmc(*(ULONG*)lpInBuffer);
367 memcpy((PULONG)lpOutBuffer, &data, 8);
368 *lpBytesReturned = 8;
369 return STATUS_SUCCESS;
371 __except(EXCEPTION_EXECUTE_HANDLER)
373 *lpBytesReturned = 0;
374 return STATUS_UNSUCCESSFUL;
378 //-----------------------------------------------------------------------------
382 //-----------------------------------------------------------------------------
385 ReadIoPort( ULONG ioControlCode,
389 ULONG nOutBufferSize,
390 ULONG *lpBytesReturned)
392 ULONG nPort = *(ULONG*)lpInBuffer;
394 switch(ioControlCode)
396 case IOCTL_OLS_READ_IO_PORT_BYTE:
397 *(PUCHAR)lpOutBuffer = READ_PORT_UCHAR((PUCHAR)(ULONG_PTR)nPort);
399 case IOCTL_OLS_READ_IO_PORT_WORD:
400 *(PUSHORT)lpOutBuffer = READ_PORT_USHORT((PUSHORT)(ULONG_PTR)nPort);
402 case IOCTL_OLS_READ_IO_PORT_DWORD:
403 *(PULONG)lpOutBuffer = READ_PORT_ULONG((PULONG)(ULONG_PTR)nPort);
406 *lpBytesReturned = 0;
407 return STATUS_INVALID_PARAMETER;
411 *lpBytesReturned = nInBufferSize;
412 return STATUS_SUCCESS;
416 WriteIoPort(ULONG ioControlCode,
420 ULONG nOutBufferSize,
421 ULONG *lpBytesReturned)
424 OLS_WRITE_IO_PORT_INPUT* param;
426 param = (OLS_WRITE_IO_PORT_INPUT*)lpInBuffer;
427 nPort = param->PortNumber;
429 switch(ioControlCode)
432 case IOCTL_OLS_WRITE_IO_PORT_BYTE:
433 WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)nPort, param->CharData);
435 case IOCTL_OLS_WRITE_IO_PORT_WORD:
436 WRITE_PORT_USHORT((PUSHORT)(ULONG_PTR)nPort, param->ShortData);
438 case IOCTL_OLS_WRITE_IO_PORT_DWORD:
439 WRITE_PORT_ULONG((PULONG)(ULONG_PTR)nPort, param->LongData);
442 return STATUS_INVALID_PARAMETER;
446 return STATUS_SUCCESS;
449 //-----------------------------------------------------------------------------
453 //-----------------------------------------------------------------------------
456 ReadPciConfig( void *lpInBuffer,
459 ULONG nOutBufferSize,
460 ULONG *lpBytesReturned)
462 OLS_READ_PCI_CONFIG_INPUT *param;
465 if(nInBufferSize != sizeof(OLS_READ_PCI_CONFIG_INPUT))
467 return STATUS_INVALID_PARAMETER;
469 param = (OLS_READ_PCI_CONFIG_INPUT *)lpInBuffer;
471 status = pciConfigRead(param->PciAddress, param->PciOffset,
472 lpOutBuffer, nOutBufferSize);
474 if(status == STATUS_SUCCESS)
476 *lpBytesReturned = nOutBufferSize;
480 *lpBytesReturned = 0;
487 WritePciConfig( void *lpInBuffer,
490 ULONG nOutBufferSize,
491 ULONG *lpBytesReturned)
494 OLS_WRITE_PCI_CONFIG_INPUT *param;
498 if(nInBufferSize < offsetof(OLS_WRITE_PCI_CONFIG_INPUT, Data))
500 return STATUS_INVALID_PARAMETER;
503 param = (OLS_WRITE_PCI_CONFIG_INPUT *)lpInBuffer;
504 writeSize = nInBufferSize - offsetof(OLS_WRITE_PCI_CONFIG_INPUT, Data);
506 *lpBytesReturned = 0;
508 return pciConfigWrite(param->PciAddress, param->PciOffset,
509 ¶m->Data, writeSize);
513 //-----------------------------------------------------------------------------
517 //-----------------------------------------------------------------------------
519 NTSTATUS pciConfigRead(ULONG pciAddress, ULONG offset, void *data, int length)
521 PCI_SLOT_NUMBER slot;
525 busNumber = PciGetBus(pciAddress);
527 slot.u.bits.DeviceNumber = PciGetDev(pciAddress);
528 slot.u.bits.FunctionNumber = PciGetFunc(pciAddress);
529 error = HalGetBusDataByOffset(PCIConfiguration, busNumber, slot.u.AsULONG,
530 data, offset, length);
534 return OLS_ERROR_PCI_BUS_NOT_EXIST;
536 else if(length != 2 && error == 2)
538 return OLS_ERROR_PCI_NO_DEVICE;
540 else if(length != error)
542 return OLS_ERROR_PCI_READ_CONFIG;
545 return STATUS_SUCCESS;
548 NTSTATUS pciConfigWrite(ULONG pciAddress, ULONG offset, void *data, int length)
550 PCI_SLOT_NUMBER slot;
554 busNumber = PciGetBus(pciAddress);
557 slot.u.bits.DeviceNumber = PciGetDev(pciAddress);
558 slot.u.bits.FunctionNumber = PciGetFunc(pciAddress);
559 error = HalSetBusDataByOffset(PCIConfiguration, busNumber, slot.u.AsULONG,
560 data, offset, length);
564 return OLS_ERROR_PCI_WRITE_CONFIG;
567 return STATUS_SUCCESS;
571 //-----------------------------------------------------------------------------
575 //-----------------------------------------------------------------------------
578 ReadMemory( void *lpInBuffer,
581 ULONG nOutBufferSize,
582 ULONG *lpBytesReturned)
584 OLS_READ_MEMORY_INPUT *param;
586 PHYSICAL_ADDRESS address;
590 if(nInBufferSize != sizeof(OLS_READ_MEMORY_INPUT))
592 return STATUS_INVALID_PARAMETER;
595 param = (OLS_READ_MEMORY_INPUT *)lpInBuffer;
596 size = param->UnitSize * param->Count;
598 if(nOutBufferSize < size)
600 return STATUS_INVALID_PARAMETER;
603 address.QuadPart = param->Address.QuadPart;
605 #ifndef _PHYSICAL_MEMORY_SUPPORT
607 if(0x000C0000 > address.QuadPart
608 || (address.QuadPart + size - 1) > 0x000FFFFF)
610 return STATUS_INVALID_PARAMETER;
615 maped = MmMapIoSpace(address, size, FALSE);
618 switch(param->UnitSize){
620 READ_REGISTER_BUFFER_UCHAR(maped, lpOutBuffer, param->Count);
623 READ_REGISTER_BUFFER_USHORT(maped, lpOutBuffer, param->Count);
626 READ_REGISTER_BUFFER_ULONG(maped, lpOutBuffer, param->Count);
633 MmUnmapIoSpace(maped, size);
637 return STATUS_INVALID_PARAMETER;
640 *lpBytesReturned = nOutBufferSize;
642 return STATUS_SUCCESS;
646 WriteMemory(void *lpInBuffer,
649 ULONG nOutBufferSize,
650 ULONG *lpBytesReturned)
652 #ifdef _PHYSICAL_MEMORY_SUPPORT
654 OLS_WRITE_MEMORY_INPUT *param;
656 PHYSICAL_ADDRESS address;
660 if(nInBufferSize < offsetof(OLS_WRITE_MEMORY_INPUT, Data))
662 return STATUS_INVALID_PARAMETER;
665 param = (OLS_WRITE_MEMORY_INPUT *)lpInBuffer;
667 size = param->UnitSize * param->Count;
668 if (nInBufferSize < size + offsetof(OLS_WRITE_MEMORY_INPUT, Data))
670 return STATUS_INVALID_PARAMETER;
673 address.QuadPart = param->Address.QuadPart;
675 maped = MmMapIoSpace(address, size, FALSE);
678 switch(param->UnitSize){
680 WRITE_REGISTER_BUFFER_UCHAR(maped,
681 (UCHAR*)¶m->Data, param->Count);
684 WRITE_REGISTER_BUFFER_USHORT(maped,
685 (USHORT*)¶m->Data, param->Count);
688 WRITE_REGISTER_BUFFER_ULONG(maped,
689 (ULONG*)¶m->Data, param->Count);
696 MmUnmapIoSpace(maped, size);
700 return STATUS_INVALID_PARAMETER;
703 *lpBytesReturned = 0;
705 return STATUS_SUCCESS;
709 *lpBytesReturned = 0;
711 return STATUS_INVALID_PARAMETER;