Memory mapped Device Driver in C

Dear All,
I wrote the Device Drivers for PCI Card in C.It is working fine now.But i want the same driver is going to work in PCI Express Card.So I want it to write in Memory Mapped I/O.Can anyone suggest me to help regarding this?

Regards,
Rajesh Kumar.G

If your device has the same programming interface if should not matter what
bus is present. Are you trying to say your PCI version used port I/O but
the PCI Express version is using memory mapped I/O?


Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

“Rajesh” wrote in message news:xxxxx@ntdev…
Dear All,
I wrote the Device Drivers for PCI Card in C.It is working fine now.But i
want the same driver is going to work in PCI Express Card.So I want it to
write in Memory Mapped I/O.Can anyone suggest me to help regarding this?

Regards,
Rajesh Kumar.G

Information from ESET NOD32 Antivirus, version of virus signature
database 5369 (20100816)


The message was checked by ESET NOD32 Antivirus.

http://www.eset.com

Information from ESET NOD32 Antivirus, version of virus signature database 5369 (20100816)

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com

Dear Don Burn,
Yes,My PCI Express Version is using memory mapped I/O.But my PCI Version is using port I/O.Kindly help me to do it in memory mapped I/O because i am entry level programmer in c.For the past two years i had written the code in .Net.

Please let me know your concern.

Regards,
Rajesh Kumar.G

Consider making two drivers, all you accesses to the device will be
different. If you have a bunch of common processing you could create a
common library for those actions.

I have seen way too many drivers that are a mess of spagetti code because
the hardware differred from version to version. Management insisted on one
driver to begin with and then assumed as things went on that the new
hardware would be supported by the old driver. The result was anytime some
one did a bug fix it was likely to break the driver for half the hardware it
supported.

One firm finally got convinced because they analyzed their bugs on the
driver and concluded they needed a testing lab at a minimum of every
combination of the cards this driver supported, or time to reconfigure their
test machines to do. This finally got upper management to understand that
the “we have compatible hardware” the manager spewed (he was a former HW
designer) was total crap.


Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

wrote in message news:xxxxx@ntdev…
> Dear Don Burn,
> Yes,My PCI Express Version is using memory mapped I/O.But my PCI
> Version is using port I/O.Kindly help me to do it in memory mapped I/O
> because i am entry level programmer in c.For the past two years i had
> written the code in .Net.
>
> Please let me know your concern.
>
> Regards,
> Rajesh Kumar.G
>
>
>
> Information from ESET NOD32 Antivirus, version of virus
> signature database 5372 (20100817)

>
> The message was checked by ESET NOD32 Antivirus.
>
> http://www.eset.com
>
>
>

Information from ESET NOD32 Antivirus, version of virus signature database 5372 (20100817)

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com

> Management insisted on one driver to begin with and then assumed as things went on

that the new hardware would be supported by the old driver.

Interesting approach…

I just wonder what the point of designing the new hardware is then - after all, the existing driver (and, hence, the OS) will be unable to take advantage of newly-introduced features anyway…

Anton Bassov

It plugs in a PCI Express socket, as opposed to a PCI socket. Given the preponderance of PCI Express sockets, and the dearth of PCI sockets, that would be a good and valuable thing.

Peter
OSR

>I/O.Kindly help me to do it in memory mapped I/O because i am entry level programmer in c

Just use memory, and not port, resources in MN_START_DEVICE, and pass them via MmMapIoSpace.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

> -----Original Message-----

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Tuesday, August 17, 2010 3:25 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Memory mapped Device Driver in C

I just wonder what the point of designing the new hardware is
then - after all, the existing driver (and, hence, the OS)
will be unable to take advantage of newly-introduced features
anyway…

Why not? It can be an app which utilizes new device features. Drivers
are supposed to be simple and dumb, the don’t need to understand high
level protocols which can be the difference. Next possibility is new hw
design which is better and cheaper. For example new embedded processor
which is faster and uses less silicon. And so on. We try to keep hw
level (USB) the same for all devices so one driver can rule them all;
the devices are very different internally and firmware cooperates
directly with apps. Driver only ensures communication between app and
fw.

The reason for one driver for everything can be driver signing which
costs some money and mainly time. Also it makes people crazy :-/

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]

Dear Maxim S. Shatskih ,

Can you give me any driver source code which is based on memory mapped PCI Express Driver? or suggest me any study material regarding this.Since i am an entry level programmer in c.

Regards,
Rajesh Kumar .G

I don’t believe that there are any such samples in the wdk, if that is what
you’re asking.

mm

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@qmaxtest.com
Sent: Wednesday, August 18, 2010 12:31 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Memory mapped Device Driver in C

Dear Maxim S. Shatskih ,

Can you give me any driver source code which is based on memory
mapped PCI Express Driver? or suggest me any study material regarding
this.Since i am an entry level programmer in c.

Regards,
Rajesh Kumar .G


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Hi all,

I am getting confused after searching google groups on MmMapIoSpace. I
hope that someone can help this .For your reference i will copy the full source code.

FileName : MicroATE.C

#include “MicroATE.h”

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING strRegistryPath)
{
UNREFERENCED_PARAMETER (strRegistryPath);

DebugPrint ((“Driver Entry\n”));

pDriverObject->MajorFunction[IRP_MJ_CREATE] = Create;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = Close;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Dispatch;
pDriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnP;
pDriverObject->DriverExtension->AddDevice = AddDevice;
pDriverObject->DriverUnload = Unload;
return STATUS_SUCCESS;
}

NTSTATUS AddDevice(IN PDRIVER_OBJECT pDriverObject,IN PDEVICE_OBJECT pPhysicalDeviceObject)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject = NULL;
PLOCAL_DEVICE_INFO deviceInfo;
UNICODE_STRING ntDeviceName;
UNICODE_STRING win32DeviceName;

DebugPrint((“AddDevice1\n”));

PAGED_CODE();
RtlInitUnicodeString(&ntDeviceName, GPD_DEVICE_NAME);
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);

// Create a device object.
status = IoCreateDevice (pDriverObject,
sizeof (LOCAL_DEVICE_INFO),
&ntDeviceName,
MICROATE_TYPE,
0,
FALSE,
&deviceObject);
if (!NT_SUCCESS (status)) {
return status;
}

status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );
if (!NT_SUCCESS(status)) {
IoDeleteDevice(deviceObject);
return status;
}
deviceInfo = (PLOCAL_DEVICE_INFO) deviceObject->DeviceExtension;
deviceInfo->DeviceObject = deviceObject;
deviceInfo->PhysicalDeviceObject = pPhysicalDeviceObject;
deviceInfo->NextLowerDriver = IoAttachDeviceToDeviceStack (
deviceObject, pPhysicalDeviceObject);
if(NULL == deviceInfo->NextLowerDriver) {
IoDeleteSymbolicLink(&win32DeviceName);
IoDeleteDevice(deviceObject);
return STATUS_NO_SUCH_DEVICE;
}

deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

IoInitializeDpcRequest(deviceInfo->DeviceObject, DpcForIsr);

deviceObject->Flags |= DO_BUFFERED_IO;

return STATUS_SUCCESS;
}

VOID Unload(IN PDRIVER_OBJECT pDriverObject )
{
DebugPrint((“Unload\n”));
}

NTSTATUS CompleteRequest(IN PIRP pIrp,IN NTSTATUS pStatus)
{
pIrp->IoStatus.Status = pStatus;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return pStatus;
}

NTSTATUS Create(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp)
{
NTSTATUS status;
PLOCAL_DEVICE_INFO deviceInfo;
deviceInfo = (PLOCAL_DEVICE_INFO)pDeviceObject->DeviceExtension;

DebugPrint((“Create PCI Device Driver Hari \n”));

if(!deviceInfo->Started){
status = STATUS_DEVICE_NOT_READY;
return CompleteRequest(pIrp, status);
}
status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
status = CompleteRequest(pIrp, status);

m_nISREnabled = 0x0000;
m_nInterruptBitStatus = 0x0000;
m_nClearInterruptStatus = 0x0001;

return status;
}

NTSTATUS Close(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp)
{
NTSTATUS status;
PLOCAL_DEVICE_INFO deviceInfo;
deviceInfo = (PLOCAL_DEVICE_INFO)pDeviceObject->DeviceExtension;

DebugPrint((“Close\n”));

status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
status = CompleteRequest(pIrp, status);
return status;
}

NTSTATUS DefaultPnpHandler(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp)
{
PLOCAL_DEVICE_INFO deviceInfo;
IoSkipCurrentIrpStackLocation(pIrp);
deviceInfo = (PLOCAL_DEVICE_INFO)pDeviceObject->DeviceExtension;
DebugPrint((“Default PnP Handler\n”));
return IoCallDriver(deviceInfo->NextLowerDriver, pIrp);
}

NTSTATUS ForwardAndWait(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp)
{
KEVENT event;
PLOCAL_DEVICE_INFO deviceInfo;
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(pIrp);
IoSetCompletionRoutine(pIrp, (PIO_COMPLETION_ROUTINE)CompletionRoutine, (PVOID) &event, TRUE, TRUE, TRUE);
deviceInfo = (PLOCAL_DEVICE_INFO)pDeviceObject->DeviceExtension;
IoCallDriver(deviceInfo->NextLowerDriver, pIrp);
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
DebugPrint((“ForwardAndWait\n”));
return pIrp->IoStatus.Status;
}

NTSTATUS CompletionRoutine(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp,IN PKEVENT pEvent)
{
if (pIrp->PendingReturned) {
IoMarkIrpPending(pIrp);
}
KeSetEvent(pEvent, 0, FALSE);
DebugPrint((“Completion Routine\n”));
return STATUS_MORE_PROCESSING_REQUIRED;
}

VOID DpcForIsr(IN PKDPC pDpc,IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp,IN PLOCAL_DEVICE_INFO deviceInfo)
{
NTSTATUS status = STATUS_SUCCESS;
unsigned short temp = 0;

DebugPrint ((“DpcForIsr\n”));

ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
deviceInfo = (PLOCAL_DEVICE_INFO)pDeviceObject->DeviceExtension;

if(deviceInfo->EventObject != NULL){
KeSetEvent((KEVENT*)deviceInfo->EventObject, 0, FALSE);
DebugPrint((“KEventObject after setting (%x)\n”, (deviceInfo->EventObject)));
}
temp = _inpw(m_nInterruptStatusReg);
_outpw(m_nInterruptStatusReg, temp);
_outpw(m_nInterruptEnableReg, 1);
}

BOOLEAN ISR(IN PKINTERRUPT InterruptObject,IN PLOCAL_DEVICE_INFO deviceInfo)
{
DebugPrint((“ISR Entry\n”));
if( m_nISREnabled == 0x100 ){
unsigned short checkBit = 0 , statusBit = 0;

m_nISREnabled = 0;
DebugPrint ((“Enter into ISR function \n”));
checkBit = _inpw(m_nInterruptStatusReg);
statusBit = checkBit;
_outpw(m_nInterruptStatusReg, 0xff);
m_nInterruptBitStatus ^= statusBit;
//DebugPrint( (“data %x”, m_nInterruptBitStatus) );
//IoRequestDpc(deviceInfo->DeviceObject, NULL, deviceInfo);
_outpw(m_nInterruptEnableReg, 0);
return TRUE;
}
else{
DebugPrint ((“ISR Return \n”));
return FALSE;
}
}

NTSTATUS DispatchPnP (IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp)
{
PIO_STACK_LOCATION irpStack;
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING win32DeviceName;
PLOCAL_DEVICE_INFO deviceInfo;

PAGED_CODE();
DebugPrint((“DispatchPnP \n”));

deviceInfo = (PLOCAL_DEVICE_INFO) pDeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(pIrp);

if (!NT_SUCCESS (status)) {
status = CompleteRequest(pIrp, status);
return status;
}

switch (irpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
DebugPrint((“DispatchPnP_StartDevice \n”));
pIrp->IoStatus.Status = STATUS_SUCCESS;
status = ForwardAndWait(pDeviceObject, pIrp);
if (!NT_SUCCESS(status))
return CompleteRequest(pIrp, status);
status = StartDevice(pDeviceObject, pIrp);
if(NT_SUCCESS(status)) {
deviceInfo->Started = TRUE;
deviceInfo->Removed = FALSE;
}
CompleteRequest(pIrp, status);
break;

case IRP_MN_QUERY_STOP_DEVICE:
DebugPrint((“DispatchPnP_QueryStopDevice\n”));
status = STATUS_SUCCESS;
status = CompleteRequest(pIrp, status);
break;

case IRP_MN_QUERY_REMOVE_DEVICE:
DebugPrint((“DispatchPnP_QueryRemoveDevice \n”));
pIrp->IoStatus.Status = STATUS_SUCCESS;
status = DefaultPnpHandler(pDeviceObject, pIrp);
break;

case IRP_MN_SURPRISE_REMOVAL:
DebugPrint((“DispatchPnP_SurpriseRemoval \n”));
deviceInfo->Removed = TRUE;
deviceInfo->Started = FALSE;
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&win32DeviceName);
pIrp->IoStatus.Status = STATUS_SUCCESS;
status = DefaultPnpHandler(pDeviceObject, pIrp);
break;

case IRP_MN_REMOVE_DEVICE:
DebugPrint((“DispatchPnP_RemoveDevice\n”));
if(!deviceInfo->Removed) {
deviceInfo->Removed = TRUE;
deviceInfo->Started = FALSE;
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&win32DeviceName);
}
pIrp->IoStatus.Status = STATUS_SUCCESS;
status = DefaultPnpHandler(pDeviceObject, pIrp);
IoDetachDevice(deviceInfo->NextLowerDriver);
IoDeleteDevice(pDeviceObject);
break;

case IRP_MN_STOP_DEVICE:
DebugPrint((“DispatchPnP_StopDevice \n”));
pIrp->IoStatus.Status = STATUS_SUCCESS;
deviceInfo = (PLOCAL_DEVICE_INFO)pDeviceObject->DeviceExtension;
return DefaultPnpHandler(pDeviceObject, pIrp);
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
// No action required in this case. Just pass it down.
case IRP_MN_CANCEL_STOP_DEVICE:
//No action required in this case.
pIrp->IoStatus.Status = STATUS_SUCCESS;
default:
status = DefaultPnpHandler(pDeviceObject, pIrp);
break;
}
return status;
}

NTSTATUS StartDevice (IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceTrans;
PCM_PARTIAL_RESOURCE_LIST partialResourceListTranslated;
PIO_STACK_LOCATION stack;
ULONG i;
PLOCAL_DEVICE_INFO deviceInfo;
DebugPrint((“Start Device\n”));
deviceInfo = (PLOCAL_DEVICE_INFO)pDeviceObject->DeviceExtension;
stack = IoGetCurrentIrpStackLocation(pIrp);
PAGED_CODE();
if (deviceInfo->Removed) {
return STATUS_DELETE_PENDING;
}
if (NULL == stack->Parameters.StartDevice.AllocatedResourcesTranslated) {

return STATUS_INSUFFICIENT_RESOURCES;
}

partialResourceListTranslated =
&stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
resourceTrans = &partialResourceListTranslated->PartialDescriptors[0];
for (i = 0; i < partialResourceListTranslated->Count; i++, resourceTrans++) {
switch (resourceTrans->Type) {
case CmResourceTypePort:
deviceInfo->PortWasMapped = TRUE;
deviceInfo->PortBase = (PVOID)resourceTrans->u.Port.Start.LowPart;
deviceInfo->PortCount = resourceTrans->u.Port.Length;
DebugPrint((“Resource Translated Port: (%x) Length: (%d)\n”,
resourceTrans->u.Port.Start.LowPart,
resourceTrans->u.Port.Length));
break;
case CmResourceTypeMemory:

deviceInfo->PortWasMapped = TRUE;
deviceInfo->PortBase = MmMapIoSpace(membase,
resourceTrans->u.Port.Length, MmNonCached);
ASSERT(deviceInfo->PortBase != 0);

// membase = resourceTrans->u.Memory.Start;
// deviceInfo->nbytes = resourceTrans->u.Memory.Length;
break;
case CmResourceTypeInterrupt:
DebugPrint((“Main Interrupt”));
deviceInfo->InterruptLevel = resourceTrans->u.Interrupt.Level;
deviceInfo->InterruptVector = resourceTrans->u.Interrupt.Vector;
deviceInfo->InterruptAffinity = resourceTrans->u.Interrupt.Affinity;
if(resourceTrans->Flags == CM_RESOURCE_INTERRUPT_LATCHED) {
DebugPrint((“Interrupt resource type is latched\n”));
deviceInfo->InterruptMode = Latched;
}else{
DebugPrint((“Interrupt resource type is level sensitive\n”));
deviceInfo->InterruptMode = LevelSensitive;
}
deviceInfo->irqShare = resourceTrans->ShareDisposition == CmResourceShareShared;
status = IoConnectInterrupt(&deviceInfo->InterruptObject,
(PKSERVICE_ROUTINE)ISR,
deviceInfo,
NULL,
(UCHAR)deviceInfo->InterruptVector,
(UCHAR)deviceInfo->InterruptLevel,
(UCHAR)deviceInfo->InterruptLevel,
deviceInfo->InterruptMode,
deviceInfo->irqShare,
deviceInfo->InterruptAffinity,
FALSE);
if (!NT_SUCCESS(status)){
DebugPrint((“IoConnectInterrupt fails \n”));
return status;
}
break;

default:
DebugPrint((" resource type \n"));
break;
} //end of switch
// deviceInfo->membase = (PUCHAR) MmMapIoSpace(membase,deviceInfo->nbytes,MmNonCached);
// if (!deviceInfo->membase)
// return STATUS_NO_MEMORY;
} // end of for
deviceInfo->InterfaceType = PCIBus;
return status;
}

NTSTATUS Dispatch(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp)
{
PLOCAL_DEVICE_INFO deviceInfo;
PIO_STACK_LOCATION IrpStack;
NTSTATUS status;

unsigned long timeout = -10000;
unsigned short commandReg, sequenceReg;
unsigned short address = 0;
unsigned long data = 0;
PVOID inOutBuffer;
ULONG inBufferLength;
ULONG outBufferLength;

DebugPrint ((“Dispatching Messages\n”));
PAGED_CODE();
pIrp->IoStatus.Information = 0;
deviceInfo = (PLOCAL_DEVICE_INFO)pDeviceObject->DeviceExtension; // Get local info struct
if(!deviceInfo->Started) {
status = STATUS_DEVICE_NOT_READY;
status = CompleteRequest(pIrp, status);
DebugPrint ((“Return\n”));
return status;
}
commandReg = (unsigned short)deviceInfo->PortBase;
sequenceReg = commandReg + 4;
m_nInterruptStatusReg = commandReg + 2;
m_nInterruptEnableReg = commandReg + 8;
m_nCommandReg = commandReg;
m_nSequenceReg = sequenceReg;

IrpStack = IoGetCurrentIrpStackLocation(pIrp);
inOutBuffer = pIrp->AssociatedIrp.SystemBuffer;
inBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
outBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
DebugPrint ((“Before \n”));
switch (IrpStack->MajorFunction)
{

case IRP_MJ_DEVICE_CONTROL:
// Dispatch on IOCTL
switch (IrpStack->Parameters.DeviceIoControl.IoControlCode)
{

case IOCTL_ADD:
address = *(PUSHORT)inOutBuffer;
DebugPrint((“My Function Add : (%x), %x\n”, address, inOutBuffer));
case IOCTL_READWORD:
address = *(PUSHORT)inOutBuffer;
DebugPrint((“ReadAddress2 (%x)\n”, address));
_outpw( commandReg, *(PUSHORT)inOutBuffer );
*(PULONG)inOutBuffer = _inpd( sequenceReg );
data = *(PULONG)inOutBuffer;
DebugPrint((“ReadData2 (%x)\n”, data));
pIrp->IoStatus.Information = sizeof(ULONG);
status = STATUS_SUCCESS;
break;
case IOCTL_WRITEDWORD: // Write a DWORD of data to machine port
{
address = ((PORT_INPUT*)inOutBuffer)->m_nAddress;
data = ((PORT_INPUT*)inOutBuffer)->m_nData;
//DebugPrint((“WriteAddress1 (%x)\n”, address));
//DebugPrint((“WriteData1 (%x)\n”, data));
_outpw( commandReg, ((PORT_INPUT*)inOutBuffer)->m_nAddress );
_outpd( sequenceReg, (ULONG)(((PORT_INPUT*)inOutBuffer)->m_nData ) );
status = STATUS_SUCCESS;
break;
}
case IOCTL_READDWORD: // Read a DWORD of data from machine port
{
address = *(PUSHORT)inOutBuffer;
DebugPrint((“ReadAddress1 (%x)\n”, address));
_outpw( commandReg, *(PUSHORT)inOutBuffer );
*(PULONG)inOutBuffer = _inpd( sequenceReg );
data = *(PULONG)inOutBuffer;
DebugPrint((“ReadData1 (%x)\n”, data));
pIrp->IoStatus.Information = sizeof(ULONG);
status = STATUS_SUCCESS;
break;
}
case IOCTL_WRITEIREGWORD: // Write a WORD to interface card port.
{
USHORT address = commandReg + ((PORT_INPUT*)inOutBuffer)->m_nAddress;
USHORT data = (USHORT)((PORT_INPUT*)inOutBuffer)->m_nData;
DebugPrint((“WriteREGWord (%x)\n”, address));
DebugPrint((“WriteREGWord (%x)\n”, data));
_outpw( address, data );
status = STATUS_SUCCESS;
break;
}
case IOCTL_READIREGWORD: // Read a WORD from interface card port.
{
USHORT address = commandReg + (*((PUSHORT)inOutBuffer));
*(PUSHORT)inOutBuffer = _inpw( address );
pIrp->IoStatus.Information = sizeof(USHORT);
status = STATUS_SUCCESS;
break;
}
case IOCTL_WRITEIREGDWORD: // Write a DWORD to interface card port.
{
USHORT address = commandReg + ((PORT_INPUT*)inOutBuffer)->m_nAddress;
ULONG data = (ULONG)((PORT_INPUT*)inOutBuffer)->m_nData;
_outpd( address, data );
// DebugPrint((“WriteIRegAddress (%x)\n”, address));
// DebugPrint((“WriteIRegData(%x)\n”, data));
status = STATUS_SUCCESS;
break;
}
case IOCTL_READIREGDWORD: // Read a DWORD from interface card port.
{
USHORT address = commandReg + (*(PUSHORT)inOutBuffer);
*(PULONG)inOutBuffer = _inpd( address );
data = *(PULONG)inOutBuffer;
// DebugPrint((“Address (%x)\n”, address));
// DebugPrint((“ReadIRegData (%x)\n”, data));
pIrp->IoStatus.Information = sizeof(ULONG);
status = STATUS_SUCCESS;
break;
}
case IOCTL_READWRITE:
{
READWRITE_INPUT* objInput = (READWRITE_INPUT*)inOutBuffer;
unsigned int write, readIndex, count, totalBytes;
int writeAddress = 0;
int WriteAddressData = 0, readAddressData = 0;
totalBytes = objInput->m_nNoOfBytes;
//DebugPrint((“totalBytes: (%d) \n”, (ULONG)totalBytes ));
write = 1;
readIndex = 0;
for( count = 0; count < totalBytes; count++) {
//DebugPrint((“count =(%d)\n”, count ));
writeAddress = objInput->m_pWriteDataPtr[count];
if((count % 2) == 0){
if( (writeAddress & 0x8000) == 0x8000 ){
//DebugPrint((“Enter into read option” ));
write = 0;
writeAddress = (writeAddress & 0xFFF);
}
//DebugPrint((“WriteAddress =(%x)\n”, (ULONG)writeAddress ));
_outpw(commandReg, writeAddress);
}
else {
if( write == 0 ){
//DebugPrint((“Enter into Read Receive RAM” ));
readAddressData = _inpd(sequenceReg);
//DebugPrint((" readAddressData: (%x)\n", (ULONG)readAddressData ));
objInput->m_pReadDataPtr[readIndex] = readAddressData;
readIndex++;
write = 1;
}
else{
WriteAddressData = objInput->m_pWriteDataPtr[count];
//DebugPrint((“WriteAddressData = (%x)\n”, (ULONG)WriteAddressData ));
_outpd(sequenceReg, WriteAddressData);
}
}
}
status = STATUS_SUCCESS;
break;
}
case IOCTL_READWRITE_AUTOINCR:
{
short nRead = 0;
unsigned int nAddress = 0, nCount = 0, nData = 0, nNoOfDataItems = 0;
READWRITE_INPUT *pInputBuffer = (READWRITE_INPUT*)inOutBuffer;

nNoOfDataItems = pInputBuffer->m_nNoOfBytes;
//[[ Check whether Read or Write
nRead = ( pInputBuffer->m_pWriteDataPtr[0] & 0x00800000 ) ? 1 : 0;
//----------------------------]]
//[[ Write the Address Selection Register to H/W
nAddress = pInputBuffer->m_pWriteDataPtr[0] & 0x000FFFFF;
_outpw( commandReg, nAddress );
//--------------------------------------------]]
//[[ Write the Start Address ( Tick ) to H/W
nData = pInputBuffer->m_pWriteDataPtr[1] & 0x000FFFFF;
_outpd( sequenceReg, nData );
//----------------------------------------]]
//[[ Write the Memory Bank Address to H/W
nAddress = pInputBuffer->m_pWriteDataPtr[3] & 0x000FFFFF;
_outpw( commandReg, nAddress );
//-------------------------------------]]

for( nCount = 0; nCount < nNoOfDataItems; nCount++ ) {
if( nRead == 1 ){ // Read operation…
nData = _inpd( sequenceReg );
pInputBuffer->m_pReadDataPtr[nCount] = nData;
}
else{ // Write operation…
nData = pInputBuffer->m_pWriteDataPtr[nCount + 4];
_outpd( sequenceReg, nData );
}
}

status = STATUS_SUCCESS;
break;
}
case IOCTL_ENABLEINTERRUPT:
{
unsigned short temp = 0;
unsigned short data = 0;

m_nISREnabled = 0;
m_nInterruptBitStatus = 0;
_outpw(m_nInterruptEnableReg, 0);
//DebugPrint( (“Flag: %d\n”, m_nClearInterruptStatus) );
if( m_nClearInterruptStatus == 0x0001 ){
//DebugPrint( (“Clearing Status at 502H\n”) );
_outpw(m_nInterruptStatusReg, 0xff);
m_nClearInterruptStatus = 0x0000;
}
data = _inpw(m_nInterruptStatusReg);
if( ( data & 0x04 ) != 0 ){
//DebugPrint( (“Status at 502H: %x\n”, data&0x04) );
m_nInterruptBitStatus = (data & 0xff);
m_nClearInterruptStatus = 0x0001;
}
*(PUSHORT)inOutBuffer = (data & 0xff);
pIrp->IoStatus.Information = sizeof(USHORT);
status = STATUS_SUCCESS;
break;
}
case IOCTL_CLEARINTERRUPT:
{
_outpw(m_nInterruptStatusReg, 0xff);
m_nInterruptBitStatus = 0;
status = STATUS_SUCCESS;
break;
}
case IOCTL_READ_FOOTSWITCH_STATUS:
{
unsigned short nData = 0;

nData = _inpw( m_nInterruptStatusReg );
if( ( nData & 0x00FF ) != 0x0000 )
_outpw( m_nInterruptStatusReg, 0xFFFF );
*(PUSHORT)inOutBuffer = ( nData & 0xFF );
pIrp->IoStatus.Information = sizeof(USHORT);
status = STATUS_SUCCESS;
break;
}
default:
status = STATUS_INVALID_PARAMETER;

}
break;
default:
status = STATUS_NOT_IMPLEMENTED;
break;
}
status = CompleteRequest(pIrp, status);
return status;
}

FileName : MicroATE.h

#include “ntddk.h”
#include “IoStruct.h”
#include “QtIoctl.h”

#ifndef MicroATE_H
#define MicroATE_H

//#define GPD_DEVICE_NAME L"\Device\MicroATE"
//#define GPD_DEVICE_NAME L"\Device\PXIQT25"
#define GPD_DEVICE_NAME L"\Device\PXIICM"

//#define DOS_DEVICE_NAME L"\DosDevices\MicroATE"
//#define DOS_DEVICE_NAME L"\DosDevices\PXIQT25"
#define DOS_DEVICE_NAME L"\DosDevices\PXIICM"

#define MICROATE_TYPE 40000

#if DBG
#define DebugPrint(x) \
DbgPrint (“QmaxPCI:”); \
DbgPrint x;

#define TRAP() DbgBreakPoint()

#else
#define DebugPrint(x)
#define TRAP()
#endif
PHYSICAL_ADDRESS membase;
typedef struct _LOCAL_DEVICE_INFO{
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT PhysicalDeviceObject;
PDEVICE_OBJECT NextLowerDriver;

BOOLEAN Started;
BOOLEAN Removed;
PVOID PortBase; // base port address
ULONG PortCount; // Count of I/O addresses used.
BOOLEAN PortWasMapped;
INTERFACE_TYPE InterfaceType;
PUCHAR membase;
ULONG nbytes;
PKINTERRUPT InterruptObject;
PVOID EventObject;

ULONG InterruptLevel;
ULONG InterruptVector;
ULONG InterruptAffinity;
ULONG InterruptMode;
BOOLEAN irqShare;
BOOLEAN MappedPorts;

CM_RESOURCE_LIST TranslatedResourceList;

}LOCAL_DEVICE_INFO, *PLOCAL_DEVICE_INFO;

unsigned short m_nCommandReg, m_nSequenceReg, m_nInterruptStatusReg, m_nInterruptEnableReg;
unsigned short m_nInterruptBitStatus = 0x0000, m_nISREnabled = 0x0000, m_nClearInterruptStatus = 0x0001;

NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING strRegistryPath
);

NTSTATUS
AddDevice(
IN PDRIVER_OBJECT pDriveObject,
IN PDEVICE_OBJECT pPhysicalDeviceObject
);

VOID
Unload(
IN PDRIVER_OBJECT pDriverObject
);

NTSTATUS
CompleteRequest(
IN PIRP pIrp,
IN NTSTATUS pStatus
);

NTSTATUS
Create(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
);

NTSTATUS
Close(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
);

NTSTATUS
DefaultPnpHandler(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
);

NTSTATUS
ForwardAndWait(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
);

NTSTATUS
CompletionRoutine(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PKEVENT pEvent
);

VOID
DpcForIsr(
IN PKDPC pDpc,
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PLOCAL_DEVICE_INFO deviceInfo
);

BOOLEAN
ISR(
IN PKINTERRUPT InterruptObject,
IN PLOCAL_DEVICE_INFO deviceInfo
);

NTSTATUS
DispatchPnP (
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
);

NTSTATUS
StartDevice (
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
);

NTSTATUS
Dispatch(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
);

#endif

Am I doing the right thing? If not, please correct me. Thanks.

Regards,
Rajesh Kumar.G

Seriously? "I am getting confused " + the source code for an entire driver + “Am I doing the right thing”… and you expect a useful answer?

C’mon OP… without knowing what you want to do, what you’re trying to do, or what the problem you’re having is… you want us, what? To do a full code review for you?

So… in answer to: “Am I doing the right thing” the answer is “no”.

The right thing would be for you to spend some time reading up on how to write WDM drivers. Or, MUCH better yet, start again using KMDF. When you encounter a specific error that you need help with, come and ask us.

Peter
OSR

xxxxx@qmaxtest.com wrote:

I am getting confused after searching google groups on MmMapIoSpace. I
hope that someone can help this .For your reference i will copy the full source code.

This driver uses bad practices to begin with. You should not use the
_inpw, _inpd. _outpw, and _outpd intrinsics. Instead, you should have
been using the APIs provided for this: READ_PORT_WORD, READ_PORT_DWORD,
WRITE_PORT_WORD, WRITE_PORT_DWORD.

Your code already has partial code to handle CmResourceTypeMemory. You
need to extend that to map the memory region into memory and save the
address it got mapped to. Then change those _inpw/_inpd/_outpw/_outpd
calls to READ_REGISTER_WORD etc. The PORT APIs manipulate I/O ports.
The REGISTER APIs manipulate memory mapped I/O.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Dear Tim Roberts,

Can you tell me the steps to complete the memory mapped PCI Device Driver?
Since I am new to this Driver Development.

Kindly tell me the steps to map the memory region into memory and save the address it got mapped to.

Rajesh Kumar G

> Kindly tell me the steps to map the memory region into memory and save the address it got

mapped to.

MmMapIoSpace

The undo is MmUnmapIoSpace

The difference with port-based driver is:

a) use CmResourceTypeMemory, not Port
b) pass the addresses through MmMapIoSpace
c) save the result
d) use this result to access the registers using READ/WRITE_REGISTER_xxx
e) MmUnmapIoSpace to undo in several other PnP paths - MN_STOP, MN_SURPRISE_REMOVAL, MN_REMOVE and repetitive MN_START in started state.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

You should do following

membase = resourceTrans->u.Memory.Start;
deviceInfo->membase = (PUCHAR)mMapIoSpace(membase,resourceTrans->Memory.Length;,MmNonCached);

WDK contains good sample of working with PCI device
It is
\WinDDK\7600.16385.1\src\general\PLX9x5x\sys
Because you don’t have much experience in Windows device driver development you should start using KMDF.

Igor Sharovar

xxxxx@qmaxtest.com wrote:

Can you tell me the steps to complete the memory mapped PCI Device Driver?
Since I am new to this Driver Development.

Kindly tell me the steps to map the memory region into memory and save the address it got mapped to.

I don’t mean to be rude, but you could have found this information more
quickly on your own. You can’t just learn about PCI memory-mapped I/O
in a vacuum. You have to understand device drivers. That means you
have a fair amount of reading to do.

There are many samples in the WDK that demonstrate this process. I’m
not going to point you to one, because it will be more valuable to
explore the samples yourself.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Dear Igor Sharovar /Tim Roberts,

@ Igor Sharovar : Now i am downloading the WDK Samples from Microsoft site.I ll Check and get back to you if i have any doubts.

@Tim Roberts : I am accepting that what you are coming to say.But my gave me only 7 days to finish this task.HowEver, i did not wrote the code for I/O Port Device Drivers for PCI.I am only going to edit the already existing code to obtain memory mapped Device Drivers for PCI

Although,Can you tell me how long it will take to study and write the driver eventhouh it depends up on human capability?

Rajesh Kumar G

Dear All,

I am receiveing the blueScreen error while writing data to specific memory space.give me your suggestion?

NTSTATUS Dispatch(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp)
{
PLOCAL_DEVICE_INFO deviceInfo;
PIO_STACK_LOCATION IrpStack;
NTSTATUS status;
unsigned long timeout = -10000;
unsigned short commandReg, sequenceReg;
unsigned short address = 0;
unsigned long data = 0;
PVOID inOutBuffer;
ULONG inBufferLength;
ULONG outBufferLength;
PULONG pIOBuffer;
ULONG nPort; // Port number to read

DebugPrint ((“Dispatching Messages\n”));
PAGED_CODE();
pIrp->IoStatus.Information = 0;
deviceInfo = (PLOCAL_DEVICE_INFO)pDeviceObject->DeviceExtension; // Get local info struct
if(!deviceInfo->Started) {
status = STATUS_DEVICE_NOT_READY;
status = CompleteRequest(pIrp, status);
DebugPrint ((“Return\n”));
return status;
}
IrpStack = IoGetCurrentIrpStackLocation(pIrp);
inOutBuffer = pIrp->AssociatedIrp.SystemBuffer;
pIOBuffer = pIrp->AssociatedIrp.SystemBuffer;
inBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
outBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
nPort = *pIOBuffer;
DebugPrint ((“Before \n”));
switch (IrpStack->MajorFunction)
{

case IRP_MJ_DEVICE_CONTROL:
// Dispatch on IOCTL
switch (IrpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_WRITEDWORD: // Write a DWORD of data to address
{
DebugPrint((“WriteAddress1 - PortMemoryType \n”));
WRITE_REGISTER_ULONG(
(PULONG)((ULONG_PTR)deviceInfo->PortBase + nPort),
*(PULONG)pIOBuffer );
pIrp->IoStatus.Information = sizeof(ULONG);
status = STATUS_SUCCESS;

break;
}
case IOCTL_READDWORD: // Read a DWORD of data from address
{
DebugPrint((“ReadData1 - PortMemoryType \n”));

*(PULONG)pIOBuffer = READ_REGISTER_ULONG(
(PULONG)((ULONG_PTR)deviceInfo->PortBase + nPort) );
data = *(PULONG)pIOBuffer;
DebugPrint((“ReadData - memory (%x)\n”, data));

pIrp->IoStatus.Information = sizeof(ULONG);
status = STATUS_SUCCESS;

break;
}
}
status = CompleteRequest(pIrp, status);
return status;
}

Is it correct?

help me

Test your code under the debugger!

Then you can fix it yourself.

The mailing list is not a remote debugger.

Thomas F. Divine


From:
Sent: Friday, August 20, 2010 8:01 AM
To: “Windows System Software Devs Interest List”
Subject: RE:[ntdev] Memory mapped Device Driver in C

> Dear All,
>
> I am receiveing the blueScreen error while writing data to
> specific memory space.give me your suggestion?
>
>
> NTSTATUS Dispatch(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp)
> {
> PLOCAL_DEVICE_INFO deviceInfo;
> PIO_STACK_LOCATION IrpStack;
> NTSTATUS status;
> unsigned long timeout = -10000;
> unsigned short commandReg, sequenceReg;
> unsigned short address = 0;
> unsigned long data = 0;
> PVOID inOutBuffer;
> ULONG inBufferLength;
> ULONG outBufferLength;
> PULONG pIOBuffer;
> ULONG nPort; // Port number to read
>
>
> DebugPrint ((“Dispatching Messages\n”));
> PAGED_CODE();
> pIrp->IoStatus.Information = 0;
> deviceInfo = (PLOCAL_DEVICE_INFO)pDeviceObject->DeviceExtension; //
> Get local info struct
> if(!deviceInfo->Started) {
> status = STATUS_DEVICE_NOT_READY;
> status = CompleteRequest(pIrp, status);
> DebugPrint ((“Return\n”));
> return status;
> }
> IrpStack = IoGetCurrentIrpStackLocation(pIrp);
> inOutBuffer = pIrp->AssociatedIrp.SystemBuffer;
> pIOBuffer = pIrp->AssociatedIrp.SystemBuffer;
> inBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
> outBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
> nPort = *pIOBuffer;
> DebugPrint ((“Before \n”));
> switch (IrpStack->MajorFunction)
> {
>
> case IRP_MJ_DEVICE_CONTROL:
> // Dispatch on IOCTL
> switch (IrpStack->Parameters.DeviceIoControl.IoControlCode)
> {
> case IOCTL_WRITEDWORD: // Write a DWORD of data to address
> {
> DebugPrint((“WriteAddress1 - PortMemoryType \n”));
> WRITE_REGISTER_ULONG(
> (PULONG)((ULONG_PTR)deviceInfo->PortBase + nPort),
> *(PULONG)pIOBuffer );
> pIrp->IoStatus.Information = sizeof(ULONG);
> status = STATUS_SUCCESS;
>
> break;
> }
> case IOCTL_READDWORD: // Read a DWORD of data from address
> {
> DebugPrint((“ReadData1 - PortMemoryType \n”));
>
> *(PULONG)pIOBuffer = READ_REGISTER_ULONG(
> (PULONG)((ULONG_PTR)deviceInfo->PortBase +
> nPort) );
> data = *(PULONG)pIOBuffer;
> DebugPrint((“ReadData - memory (%x)\n”, data));
>
> pIrp->IoStatus.Information = sizeof(ULONG);
> status = STATUS_SUCCESS;
>
> break;
> }
> }
> status = CompleteRequest(pIrp, status);
> return status;
> }
>
> Is it correct?
>
> help me
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer