Sorry, I forgot the attachment previously.
Darmawan Salihun wrote:
> Hi all,
> I attach the device driver code for my experimental flashrom port to
> windows back then. It's buggy, too much direct access, etc.
> But, it works at some points during my brief testing phase. It's based
> on the old flashrom version 1.23. I know, it's not a good example
> of software engineering practice. Nonetheless, I want to discuss, on
> which API that I should be removing from user mode application
> accesses and which one to retain.
>
> Regards,
> Darmawan
>
>
#ifndef __BIOS_PROBE_H__
#define __BIOS_PROBE_H__
#include <ntddk.h>
#include "../interfaces.h"
// Debugging macros
#if DBG
#define BIOS_PROBE_KDPRINT(_x_) \
DbgPrint("BIOS_PROBE.SYS: ");\
DbgPrint _x_;
#else
#define BIOS_PROBE_KDPRINT(_x_)
#endif
#define BIOS_PROBE_DEVICE_NAME_U L"\\Device\\bios_probe"
#define BIOS_PROBE_DOS_DEVICE_NAME_U L"\\DosDevices\\bios_probe"
typedef struct _MMIO_RING_0_MAP{
PVOID sysAddrBase; // the starting system virtual address of the
mapped physical address range
ULONG size; // size of the mapped physical address range
PVOID usermodeAddrBase; // pointer to the usermode virtual address where
this range is mapped
PMDL pMdl; // Memory Descriptor List for the memory mapped I/O
range to be mapped
}MMIO_RING_0_MAP, *PMMIO_RING_0_MAP;
typedef struct _DEVICE_EXTENSION{
MMIO_RING_0_MAP mapZone[MAX_MAPPED_MMIO];
ULONG rtl8139IoBase; // quick hack!
}DEVICE_EXTENSION, *PDEVICE_EXTENSION;
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING registryPath
);
NTSTATUS
DispatchCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
DispatchClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
DispatchUnload(
IN PDRIVER_OBJECT DriverObject
);
NTSTATUS
DispatchRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
DispatchWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
DispatchIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
#endif //__BIOS_PROBE_H__
/*++
Module Name: bios_probe.c
Abstract: The main file of the BIOS probing utility device driver
Author: Darmawan Salihun (Aug 27, 2006)
Environment: Kernel mode
Revision History:
- Originated from the CancelSafeIrq Win_XP DDK sample by Eliyas Yakub
- (August 27, 2006) BIOS Probing device driver constructed by Darmawan
Salihun
- (Sept. 9th, 2006) Device driver architecture reworked to accomodate up to
256
memory mapped I/O (MMIO) range to be mapped by the driver.
Systematic comments added.
TODO:
- Add routines to check if a requested physical address range __overlaps__
with the currently allocated mapZone in the device extension. Do this
in MapMmio function!
--*/
#include "bios_probe.h"
#include <devioctl.h>
#include "../interfaces.h"
#include "rtl8139_hack.h"
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
Installable driver initialization entry point.
This entry point is called directly by the I/O system.
Arguments:
DriverObject - pointer to the driver object
registryPath - pointer to a unicode string representing the path,
to driver-specific key in the registry.
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING unicodeDeviceName;
UNICODE_STRING unicodeDosDeviceName;
PDEVICE_OBJECT deviceObject;
PDEVICE_EXTENSION pDevExt;
ULONG i;
UNREFERENCED_PARAMETER (RegistryPath);
BIOS_PROBE_KDPRINT(("DriverEntry Enter \n"));
DriverObject->DriverUnload = DispatchUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE]= DispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoControl;
(void) RtlInitUnicodeString(&unicodeDeviceName, BIOS_PROBE_DEVICE_NAME_U);
status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
&unicodeDeviceName,
FILE_DEVICE_UNKNOWN,
0,
(BOOLEAN) FALSE,
&deviceObject
);
if (!NT_SUCCESS(status))
{
return status;
}
DbgPrint("DeviceObject %p\n", deviceObject);
//
// Set the flag signifying that we will do direct I/O. This causes NT
// to lock the user buffer into memory when it's accessed
//
deviceObject->Flags |= DO_DIRECT_IO;
//
// Allocate and initialize a Unicode String containing the Win32 name
// for our device.
//
(void)RtlInitUnicodeString( &unicodeDosDeviceName,
BIOS_PROBE_DOS_DEVICE_NAME_U );
status = IoCreateSymbolicLink( (PUNICODE_STRING) &unicodeDosDeviceName,
(PUNICODE_STRING) &unicodeDeviceName );
if (!NT_SUCCESS(status))
{
IoDeleteDevice(deviceObject);
return status;
}
//
// Initialize device extension
//
pDevExt = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
for(i = 0; i < MAX_MAPPED_MMIO; i++)
{
pDevExt->mapZone[i].sysAddrBase = NULL;
pDevExt->mapZone[i].size = 0;
pDevExt->mapZone[i].usermodeAddrBase = NULL;
pDevExt->mapZone[i].pMdl = NULL;
}
pDevExt->rtl8139IoBase = 0; // quick hack !
BIOS_PROBE_KDPRINT(("DriverEntry Exit = %x\n", status));
return status;
}
NTSTATUS
DispatchCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Process the create IRPs sent to this device.
This routine does nothing but signalling
successful IRP handling.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Return Value:
NT Status code
--*/
{
NTSTATUS status = STATUS_SUCCESS;
BIOS_PROBE_KDPRINT(("DispatchCreate Enter\n"));
//
// The dispatch routine for IRP_MJ_CREATE is called when a
// file object associated with the device is created.
// This is typically because of a call to CreateFile() in
// a user-mode program or because a another driver is
// layering itself over a this driver. A driver is
// required to supply a dispatch routine for IRP_MJ_CREATE.
//
BIOS_PROBE_KDPRINT(("IRP_MJ_CREATE\n"));
Irp->IoStatus.Information = 0;
//
// Save Status for return and complete Irp
//
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
BIOS_PROBE_KDPRINT((" DispatchCreate Exit = %x\n", status));
return status;
}
NTSTATUS ReadPortByte(PIRP pIrp)
/*++
Routine Description:
Process the IRPs with IOCTL_READ_PORT_BYTE code.
This routine reads a byte from the designated port,
and returns the value to usermode application
through pointer to the locked-down usermode buffer
in the IRP.
Arguments:
pIrp - pointer to an I/O Request Packet.
Return Value:
NT Status code
--*/
{
NTSTATUS status = STATUS_SUCCESS;
IO_BYTE* pUsermodeMem = (IO_BYTE*) MmGetSystemAddressForMdlSafe(
pIrp->MdlAddress, NormalPagePriority );
if( NULL != pUsermodeMem) {
__asm
{
pushad ;// save all register contents
mov ebx, pUsermodeMem ;// build user-mode memory pointer register
mov dx,[ebx].port8 ;// fetch input port addr
in al,dx ;// read the byte from the device
mov [ebx].value8, al ;// write probing result directly to
user-mode memory
popad ;// restore all saved register value
}
} else {
status = STATUS_INVALID_USER_BUFFER;
}
return status;
}
NTSTATUS ReadPortWord(PIRP pIrp)
/*++
Routine Description:
Process the IRPs with IOCTL_READ_PORT_WORD code.
This routine reads a word from the designated port,
and returns the value to usermode application
through pointer to the locked-down usermode buffer
in the IRP.
Arguments:
pIrp - pointer to an I/O Request Packet.
Return Value:
NT Status code
--*/
{
NTSTATUS status = STATUS_SUCCESS;
IO_WORD* pUsermodeMem = (IO_WORD*) MmGetSystemAddressForMdlSafe(
pIrp->MdlAddress, NormalPagePriority );
if( NULL != pUsermodeMem) {
__asm
{
pushad ;// save all register contents
mov ebx, pUsermodeMem ;// build user-mode memory pointer
register
mov dx, [ebx].port16 ;// fetch input port addr
in ax, dx ;// read the bytes from the device
mov [ebx].value16, ax ;// write probing result directly to
user-mode memory
popad ;// restore all saved register value
}
} else {
status = STATUS_INVALID_USER_BUFFER;
}
return status;
}
NTSTATUS ReadPortLong(PIRP pIrp)
/*++
Routine Description:
Process the IRPs with IOCTL_READ_PORT_LONG code.
This routine reads a DWORD from the designated port,
and returns the value to usermode application
through pointer to the locked-down usermode buffer
in the IRP.
Arguments:
pIrp - pointer to an I/O Request Packet.
Return Value:
NT Status code
--*/
{
NTSTATUS status = STATUS_SUCCESS;
IO_LONG* pUsermodeMem = (IO_LONG*) MmGetSystemAddressForMdlSafe(
pIrp->MdlAddress, NormalPagePriority );
if( NULL != pUsermodeMem) {
__asm
{
pushad ;// save all register contents
mov ebx, pUsermodeMem ;// build user-mode memory pointer
register
mov dx, [ebx].port32 ;// fetch input port addr
in eax, dx ;// read the bytes from the device
mov [ebx].value32, eax ;// write probing result directly to
user-mode memory
popad ;// restore all saved register value
}
} else {
status = STATUS_INVALID_USER_BUFFER;
}
return status;
}
NTSTATUS WritePortByte(PIRP pIrp)
/*++
Routine Description:
Process the IRPs with IOCTL_WRITE_PORT_BYTE code.
This routine writes a byte to the designated port.
The value of the byte and the port address are obtained
through pointer to the locked-down buffer in the IRP.
Arguments:
pIrp - pointer to an I/O Request Packet.
Return Value:
NT Status code
--*/
{
NTSTATUS status = STATUS_SUCCESS;
IO_BYTE* pUsermodeMem = (IO_BYTE*) MmGetSystemAddressForMdlSafe(
pIrp->MdlAddress, NormalPagePriority );
if( NULL != pUsermodeMem) {
__asm
{
pushad ;// save all register contents
mov ebx, pUsermodeMem ;// build user-mode memory pointer
register
mov dx, [ebx].port8 ;// fetch input port addr
mov al, [ebx].value8 ;// read the value to be written
directly from user-mode memory
out dx, al ;// write the byte to the device
popad ;// restore all saved register value
}
} else {
status = STATUS_INVALID_USER_BUFFER;
}
return status;
}
NTSTATUS WritePortWord(PIRP pIrp)
/*++
Routine Description:
Process the IRPs with IOCTL_WRITE_PORT_WORD code.
This routine writes a word to the designated port.
The value of the word and the port address are obtained
through pointer to the locked-down buffer in the IRP.
Arguments:
pIrp - pointer to an I/O Request Packet.
Return Value:
NT Status code
--*/
{
NTSTATUS status = STATUS_SUCCESS;
IO_WORD* pUsermodeMem = (IO_WORD*) MmGetSystemAddressForMdlSafe(
pIrp->MdlAddress, NormalPagePriority );
if( NULL != pUsermodeMem) {
__asm
{
pushad ;// save all register contents
mov ebx, pUsermodeMem ;// build user-mode memory pointer
register
mov dx, [ebx].port16 ;// fetch input port addr
mov ax, [ebx].value16 ;// read the value to be written
directly from user-mode memory
out dx, ax ;// write the bytes to the device
popad ;// restore all saved register value
}
} else {
status = STATUS_INVALID_USER_BUFFER;
}
return status;
}
NTSTATUS WritePortLong(PIRP pIrp)
/*++
Routine Description:
Process the IRPs with IOCTL_WRITE_PORT_LONG code.
This routine writes a dword to the designated port.
The value of the dword and the port address are obtained
through pointer to the locked-down buffer in the IRP.
Arguments:
pIrp - pointer to an I/O Request Packet.
Return Value:
NT Status code
--*/
{
NTSTATUS status = STATUS_SUCCESS;
IO_LONG* pUsermodeMem = (IO_LONG*) MmGetSystemAddressForMdlSafe(
pIrp->MdlAddress, NormalPagePriority );
if( NULL != pUsermodeMem) {
__asm
{
pushad ;// save all register contents
mov ebx, pUsermodeMem ;// build user-mode memory pointer
register
mov dx, [ebx].port32 ;// fetch input port addr
mov eax, [ebx].value32 ;// read the value to be written
directly from user-mode memory
out dx, eax ;// write the bytes to the device
popad ;// restore all saved register value
}
} else {
status = STATUS_INVALID_USER_BUFFER;
}
return status;
}
NTSTATUS MapMmio(PDEVICE_OBJECT pDO, PIRP pIrp)
/*++
Routine Description:
Process the IRPs with IOCTL_MAP_MMIO code.
This routine maps a physical address range
to the usermode application address space.
Arguments:
pDO - pointer to the device object of this driver.
pIrp - pointer to an I/O Request Packet.
Return Value:
NT Status code
Notes:
This function can only map the area
below the 4-GB limit.
--*/
{
PDEVICE_EXTENSION pDevExt;
PHYSICAL_ADDRESS phyAddr;
PMMIO_MAP pUsermodeMem;
ULONG i, free_idx;
pDevExt = (PDEVICE_EXTENSION) pDO->DeviceExtension;
//
// Check for free mapZone in the device extension.
// If none is free, return an error code.
//
for(i = 0; i < MAX_MAPPED_MMIO; i++)
{
if( pDevExt->mapZone[i].sysAddrBase == NULL )
{
free_idx = i;
break;
}
}
if( i == MAX_MAPPED_MMIO )
{
return STATUS_INVALID_DEVICE_REQUEST;
}
//
// We have obtained a free mapZone, map the physical address range.
//
pUsermodeMem = (MMIO_MAP*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress,
NormalPagePriority );
if( NULL == pUsermodeMem) {
return STATUS_INVALID_USER_BUFFER;
}
phyAddr.HighPart = 0;
phyAddr.LowPart = pUsermodeMem->phyAddrStart;
pDevExt->mapZone[free_idx].sysAddrBase = MmMapIoSpace( phyAddr,
pUsermodeMem->size, MmNonCached);
if(NULL == pDevExt->mapZone[free_idx].sysAddrBase)
{
return STATUS_BUFFER_TOO_SMALL;
}
pDevExt->mapZone[free_idx].pMdl =
IoAllocateMdl(pDevExt->mapZone[free_idx].sysAddrBase,
pUsermodeMem->size, FALSE,
FALSE, NULL);
if(NULL == pDevExt->mapZone[free_idx].pMdl)
{
MmUnmapIoSpace(pDevExt->mapZone[free_idx].sysAddrBase,
pUsermodeMem->size);
pDevExt->mapZone[free_idx].sysAddrBase = NULL;
return STATUS_BUFFER_TOO_SMALL;
}
pDevExt->mapZone[free_idx].size = pUsermodeMem->size;
//
// Map the system virtual address to usermode virtual address
//
MmBuildMdlForNonPagedPool(pDevExt->mapZone[free_idx].pMdl);
pDevExt->mapZone[free_idx].usermodeAddrBase = MmMapLockedPagesSpecifyCache(
pDevExt->mapZone[free_idx].pMdl,
UserMode, MmNonCached,
NULL, FALSE,
NormalPagePriority);
if(NULL == pDevExt->mapZone[free_idx].usermodeAddrBase)
{
IoFreeMdl(pDevExt->mapZone[free_idx].pMdl);
MmUnmapIoSpace(pDevExt->mapZone[free_idx].sysAddrBase,
pDevExt->mapZone[free_idx].size);
pDevExt->mapZone[free_idx].sysAddrBase = NULL;
pDevExt->mapZone[free_idx].size = 0;
return STATUS_BUFFER_TOO_SMALL;
}
// copy the resulting usermode virtual address to IRP "buffer"
pUsermodeMem->usermodeVirtAddr =
pDevExt->mapZone[free_idx].usermodeAddrBase;
return STATUS_SUCCESS;
}
NTSTATUS CleanupMmioMapping(PDEVICE_EXTENSION pDevExt, ULONG i)
/*++
Routine Description:
This routine cleanup the mapping of a MMIO range
and resources it consumes.
Arguments:
pDevExt - pointer to the device extension of the driver
i - index of the mapZone to cleanup
Return Value:
NT Status code
--*/
{
if( NULL != pDevExt->mapZone[i].usermodeAddrBase )
{
MmUnmapLockedPages( pDevExt->mapZone[i].usermodeAddrBase,
pDevExt->mapZone[i].pMdl);
pDevExt->mapZone[i].usermodeAddrBase = NULL;
}
if( NULL != pDevExt->mapZone[i].pMdl )
{
IoFreeMdl(pDevExt->mapZone[i].pMdl);
pDevExt->mapZone[i].pMdl = NULL;
}
if( NULL != pDevExt->mapZone[i].sysAddrBase )
{
MmUnmapIoSpace( pDevExt->mapZone[i].sysAddrBase,
pDevExt->mapZone[i].size);
pDevExt->mapZone[i].sysAddrBase = NULL;
pDevExt->mapZone[i].size = 0;
}
return STATUS_SUCCESS;
}
NTSTATUS UnmapMmio(PDEVICE_OBJECT pDO, PIRP pIrp)
/*++
Routine Description:
Process the IRPs with IOCTL_UNMAP_MMIO code.
This routine unmaps a previously mapped physical
address range.
Arguments:
pDO - pointer to the device object of this driver.
pIrp - pointer to an I/O Request Packet.
Return Value:
NT Status code
Notes:
This function can only unmap the area
below the 4-GB limit.
--*/
{
PDEVICE_EXTENSION pDevExt;
PMMIO_MAP pMmioMap;
ULONG i;
//
// Unmap the requested zone from the system address space
// and update the device extension data
//
pDevExt = (PDEVICE_EXTENSION) pDO->DeviceExtension;
pMmioMap = (PMMIO_MAP) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress,
NormalPagePriority );
for(i = 0 ; i < MAX_MAPPED_MMIO; i++)
{
if(pDevExt->mapZone[i].usermodeAddrBase == pMmioMap->usermodeVirtAddr)
{
CleanupMmioMapping(pDevExt, i);
break;
}
}
return STATUS_SUCCESS;
}
NTSTATUS
DispatchIoControl(
IN PDEVICE_OBJECT pDO,
IN PIRP pIrp
)
/*++
Routine Description:
Io control code dispatch routine
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to current Irp
Return Value:
NT status code.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(pIrp);
ULONG * pIoBase = NULL;
ULONG bufLength, i;
UCHAR * buf;
PDEVICE_EXTENSION pDevExt;
switch(irpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_READ_PORT_BYTE:
{
if(irpStack->Parameters.DeviceIoControl.InputBufferLength >=
sizeof(IO_BYTE)) {
status = ReadPortByte(pIrp);
} else {
status = STATUS_BUFFER_TOO_SMALL;
}
}break;
case IOCTL_READ_PORT_WORD:
{
if(irpStack->Parameters.DeviceIoControl.InputBufferLength >=
sizeof(IO_WORD)) {
status = ReadPortWord(pIrp);
} else {
status = STATUS_BUFFER_TOO_SMALL;
}
}break;
case IOCTL_READ_PORT_LONG:
{
if(irpStack->Parameters.DeviceIoControl.InputBufferLength >=
sizeof(IO_LONG)) {
status = ReadPortLong(pIrp);
} else {
status = STATUS_BUFFER_TOO_SMALL;
}
}break;
case IOCTL_WRITE_PORT_BYTE:
{
if(irpStack->Parameters.DeviceIoControl.InputBufferLength >=
sizeof(IO_BYTE)) {
status = WritePortByte(pIrp);
} else {
status = STATUS_BUFFER_TOO_SMALL;
}
}break;
case IOCTL_WRITE_PORT_WORD:
{
if(irpStack->Parameters.DeviceIoControl.InputBufferLength >=
sizeof(IO_WORD)) {
status = WritePortWord(pIrp);
} else {
status = STATUS_BUFFER_TOO_SMALL;
}
}break;
case IOCTL_WRITE_PORT_LONG:
{
if(irpStack->Parameters.DeviceIoControl.InputBufferLength >=
sizeof(IO_LONG)) {
status = WritePortLong(pIrp);
} else {
status = STATUS_BUFFER_TOO_SMALL;
}
}break;
case IOCTL_MAP_MMIO:
{
if(irpStack->Parameters.DeviceIoControl.InputBufferLength >=
sizeof(MMIO_MAP)) {
status = MapMmio(pDO, pIrp);
} else {
status = STATUS_BUFFER_TOO_SMALL;
}
}break;
case IOCTL_UNMAP_MMIO:
{
if(irpStack->Parameters.DeviceIoControl.InputBufferLength >=
sizeof(MMIO_MAP)) {
status = UnmapMmio(pDO, pIrp);
} else {
status = STATUS_BUFFER_TOO_SMALL;
}
}break;
case IOCTL_RTL8139_IOBASE_HACK: // must be called prior to
IOCTL_RTL8139_ROM_WRITE_HACK
// (writing into RTL8139 ROM)
{
if(irpStack->Parameters.DeviceIoControl.OutputBufferLength >=
sizeof(ULONG)) {
pIoBase = (ULONG*)
MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
pDevExt = (PDEVICE_EXTENSION) pDO->DeviceExtension;
pDevExt->rtl8139IoBase = *pIoBase;
} else {
status = STATUS_BUFFER_TOO_SMALL;
}
}break;
case IOCTL_RTL8139_ROM_WRITE_HACK: // must be called __after__
IOCTL_RTL8139_IOBASE_HACK
{
bufLength =
irpStack->Parameters.DeviceIoControl.OutputBufferLength;
DbgPrint("IOCTL_RTL8139_ROM_WRITE_HACK: buffer length = %d\n",
bufLength);
buf = (UCHAR*) MmGetSystemAddressForMdlSafe(pIrp->MdlAddress,
NormalPagePriority);
/*
for( i = 0; i < bufLength; i+=4)
{
DbgPrint("IOCTL_RTL8139_ROM_WRITE_HACK: buf[%04X] =
%08X\n", i,*((ULONG*)&buf[i]));
}
*/
pDevExt = (PDEVICE_EXTENSION) pDO->DeviceExtension;
DbgPrint("IOCTL_RTL8139_ROM_WRITE_HACK: pDevExt->rtl8139IoBase
= %X\n", pDevExt->rtl8139IoBase);
WriteRtl8139RomHack(pDevExt->rtl8139IoBase, bufLength, buf);
}break;
default:
{
status = STATUS_INVALID_DEVICE_REQUEST;
}break;
}
//
// complete the I/O request and return appropriate values
//
pIrp->IoStatus.Status = status;
// Set number of bytes to copy back to user-mode
if(status == STATUS_SUCCESS)
{
pIrp->IoStatus.Information =
irpStack->Parameters.DeviceIoControl.OutputBufferLength;
}
else
{
pIrp->IoStatus.Information = 0;
}
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return status;
}
NTSTATUS
DispatchRead(
IN PDEVICE_OBJECT pDO,
IN PIRP pIrp
)
/*++
Routine Description:
Read dispatch routine
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to current Irp
Return Value:
NT status code.
Note:
This function does nothing. It's merely a place holder
to satisfy the need of the user mode code to open the driver
with a GENERIC_READ parameter.
--*/
{
// Just complete the I/O request right away
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
NTSTATUS
DispatchWrite(
IN PDEVICE_OBJECT pDO,
IN PIRP pIrp
)
/*++
Routine Description:
Write dispatch routine
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to current Irp
Return Value:
NT status code.
Note:
This function does nothing. It's merely a place holder
to satisfy the need of the user mode code to open the driver
with a GENERIC_WRITE parameter.
--*/
{
// Just complete the I/O request right away
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
NTSTATUS
DispatchClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Process the close IRPs sent to this device.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Return Value:
NT Status code
Note:
This function clean-up the mapped MMIO ranges that
haven't been cleaned-up by a "buggy" usermode application.
--*/
{
PDEVICE_EXTENSION pDevExt;
ULONG i;
NTSTATUS status = STATUS_SUCCESS;
BIOS_PROBE_KDPRINT(("DispatchClose Enter\n"));
pDevExt = DeviceObject->DeviceExtension ;
//
// Clean-up the mapped MMIO space in case the usermode
// application forget to call UnmapMmio for some MMIO zone.
// This is to guard against some buggy usermode application.
//
for(i = 0; i < MAX_MAPPED_MMIO; i++)
{
if(pDevExt->mapZone[i].sysAddrBase != NULL)
{
CleanupMmioMapping(pDevExt, i);
}
}
//
// The IRP_MJ_CLOSE dispatch routine is called when a file object
// opened on the driver is being removed from the system; that is,
// all file object handles have been closed and the reference count
// of the file object is down to 0.
//
BIOS_PROBE_KDPRINT(("IRP_MJ_CLOSE\n"));
Irp->IoStatus.Information = 0;
//
// Save Status for return and complete Irp
//
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
BIOS_PROBE_KDPRINT((" DispatchClose Exit = %x\n", status));
return status;
}
VOID
DispatchUnload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
Free all the allocated resources, etc.
Arguments:
DriverObject - pointer to a driver object.
Return Value:
VOID
--*/
{
PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
UNICODE_STRING uniWin32NameString;
BIOS_PROBE_KDPRINT(("DispatchUnload Enter\n"));
//
// Create counted string version of our Win32 device name.
//
RtlInitUnicodeString( &uniWin32NameString, BIOS_PROBE_DOS_DEVICE_NAME_U );
IoDeleteSymbolicLink( &uniWin32NameString );
ASSERT(!deviceObject->AttachedDevice);
IoDeleteDevice( deviceObject );
BIOS_PROBE_KDPRINT(("DispatchUnload Exit\n"));
return;
}
--
linuxbios mailing list
[email protected]
http://www.linuxbios.org/mailman/listinfo/linuxbios