09-01-2005 01:43 PM
I am attempting to write the digital lines on an PCI-MIO-16E-1, but see no result.
I do the following steps:
1) Getting the MITE base and board registers base physical address
2) Mapping these into virtual addresses using mmMapIoSpace
3) Initializing the board by doing steps 4-5 on page 4-3 in the PCI E-series Register Level Programming manual
4) Writing the lines using windowed access
All operations complete without an exception. What am I doing wrong the in the code below:
In my handler for IRP_MN_START_DEVICE, I scan the system resources:
case CmResourceTypeMemory:
if (pPartialDescriptor->u.Memory.Start.LowPart == 0xFEAFC000)
{
pDevExt->base1 =
(PVOID) MmMapIoSpace (pPartialDescriptor->u.Memory.Start,
pPartialDescriptor->u.Memory.Length,
MmNonCached);
if(!pDevExt->base1) {
DbgPrint("Could not map memory \n");
IoDecrement(pDevExt);
return STATUS_NO_MEMORY;
}
ASSERT(pPartialDescriptor->u.Memory.Length == 0x1000);
pDevExt->baseLength = pPartialDescriptor->u.Memory.Length;
DbgPrint("Logical Base is: 0x%03X \n", pPartialDescriptor->u.Memory.Start);
DbgPrint("Virtual Base is: 0x%03X \n", pDevExt->base1);
DbgPrint("Length of mapping is %d \n", pDevExt->baseLength);
}
And dito for the other base. The information printed seems correct.
For base1 (corresponds to BAR0 in documentation)
Logical Base is: 0xFEAFC000
Virtual Base is: 0xF8ACC000
Length of mapping is 4096
For base2 (corresponds to BAR0 in documentation)
Logical Base is: 0xFEAFD000
Virtual Base is: 0xF8C29000
Length of mapping is 4096
Now I initialize the board:
void InitializeBoard(IN PDEVICE_OBJECT pDO) {
PDEVICE_EXTENSION pDevExt =
(PDEVICE_EXTENSION)pDO->DeviceExtension;
ULONG windowDataValue =
((0xffffff00 & PtrToUlong (pDevExt->base2)) | 0x80);
DbgPrint("Calculated window data value 0x%03X \n", windowDataValue);
PULONG basePlusOffset = ((PULONG)pDevExt->base1) + 0xc0;
DbgPrint("Calculated base plus offset 0x%03X \n", basePlusOffset);
WRITE_REGISTER_ULONG(basePlusOffset, windowDataValue);
pDevExt->windowDataValue = windowDataValue;
return;
}
That prints:
Calculated window data value 0xF8C29080
Calculated base plus offset 0xF8ACC300
Now in my user application I call CreateFile,
which calls the driver DispatchWrite routine:
NTSTATUS DispatchWrite (IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp ) {
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
WriteWindowAddress(pDevExt,DIO_CONTROL_REG);
WriteWindowData(pDevExt,0xFF);
for (int i=0;i<=255;i++)
{
WriteWindowAddress(pDevExt,DIO_OUTPUT_REG);
WriteWindowData(pDevExt,i);
}
return status;
}
Here WriteWindowData is defined as (similarly to WriteWindowAddress):
void WriteWindowData( PDEVICE_EXTENSION pDevExt, ULONG bData ) {
PULONG o = (PULONG) pDevExt->base2 + WINDOW_DATA_REG;
(WRITE_REGISTER_ULONG( o, bData ));
}
The problem is the lights don't go on.
Thank you for the help.
09-06-2005 12:05 PM
09-07-2005 01:29 PM
I changed the snippet of code to
ULONG windowDataValue = ((0xffffff00 & pDevExt->base2Physical.LowPart) | 0x80);
but it still doesn't work. Also, how do we know which of the two Windows reported address ranges is BAR and
which one is BAR1? In the example, I assume 0xFEAFC000 is BAR and 0xFEAFD000 is BAR1 (It still doesn't work if I do the opposite).
In addition PCI E-series Register Level Programming does not specify the register size at offset 0xc0. Here I am writing all 32 bits with
WRITE_REGISTER_ULONG.
// Write the window data value to offset 0xc0 from
the MITE address.ULONG basePlusOffset = (PtrToUlong (pDevExt->base1)) + 0xc0;
DbgPrint("Calculated base plus offset 0x%03X \n", basePlusOffset);
WRITE_REGISTER_ULONG((PULONG) ULongToPtr(basePlusOffset),
windowDataValue);
09-08-2005 11:39 AM
09-08-2005 12:17 PM
Ok, I do:
ULONG basePlusOffset = (PtrToUlong (pDevExt->base1)) + 0x460; // pDevExt->base1 is the virtual BAR0 base. It is of type Pvoid.
ULONG value = READ_REGISTER_ULONG((PULONG) ULongToPtr(basePlusOffset));
DbgPrint("Read %X \n",value);
and the value I get is FFFFFFFF.
I don't understand your last sentence. I am assumming you are talking about more debug output? What kind of output would be useful in this situation?
09-08-2005 02:56 PM
09-08-2005 04:06 PM
Here are relevant pieces is my device extension:
typedef struct _DEVICE_EXTENSION {
ULONG Signature; // must be ELVIS_FDO_INSTANCE_SIGNATURE
PDEVICE_OBJECT pSelfDevice;
PDEVICE_OBJECT pLowerDevice;
PDEVICE_OBJECT pNextLowerDevice;
…
BOOLEAN isBoardInitialized;
PHYSICAL_ADDRESS basePhysicalBAR0; // I/O register base address (physical)
PHYSICAL_ADDRESS basePhysicalBAR1; // I/O register base address (physical)
PVOID baseBAR0; // I/O register base address (virtual)
PVOID baseBAR1; // I/O register base address (virtual)
ULONG baseLength;
ULONG Irq; // Irq - Interrupt Request Level
ULONG windowDataValue;
…
ULONG Vector;
KAFFINITY Affinity;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
09-08-2005 04:15 PM
Here are relevant pieces of HandleStartDevice, which calls the board initialization function
InitializeBoard:
NTSTATUS HandleStartDevice( IN PDEVICE_OBJECT pDO,
IN PIRP pIrp ) {
DebugPrint(INFO,"Enter HandleStartDevice \n");
...
switch (pPartialDescriptor->Type) {
case CmResourceTypeInterrupt:
pDevExt->IRQL = (KIRQL)
pPartialDescriptor->u.Interrupt.Level;
pDevExt->Vector =
pPartialDescriptor->u.Interrupt.Vector;
pDevExt->Affinity =
pPartialDescriptor->u.Interrupt.Affinity;
pDevExt->mode =
(pPartialDescriptor->Flags == CM_RESOURCE_INTERRUPT_LATCHED)
? Latched : LevelSensitive;
pDevExt->irqShare =
pPartialDescriptor->ShareDisposition == CmResourceShareShared;
DbgPrint("Interrupt Resources are: "
"IRQ=%d Vector=0x%03X Affinity=%X\n",
pDevExt->IRQL, pDevExt->Vector,
pDevExt->Affinity);
break;
case CmResourceTypeDma:
DebugPrint(INFO,"Looking at DMA resources\n");
// We don't do DMA - ignore
break;
case CmResourceTypePort:
DebugPrint(INFO,"Looking at Port usage \n");
// We don't do port usage
break;
case CmResourceTypeMemory:
DebugPrint(INFO,"Looking at Memory usage \n");
pDevExt->isBoardInitialized = false;
// HACK - should get info about which BAR is which from PCI config
if (pPartialDescriptor->u.Memory.Start.LowPart == 0xFEAFC000)
{
pDevExt->basePhysicalBAR0 = pPartialDescriptor->u.Memory.Start;
pDevExt->baseBAR0 =
(PVOID) MmMapIoSpace (pPartialDescriptor->u.Memory.Start,
pPartialDescriptor->u.Memory.Length,
MmNonCached);
if(!pDevExt->baseBAR0) {
DbgPrint("Could not map memory \n");
IoDecrement(pDevExt);
return STATUS_NO_MEMORY;
}
ASSERT(pPartialDescriptor->u.Memory.Length == 0x1000);
pDevExt->baseLength = pPartialDescriptor->u.Memory.Length;
DbgPrint("BAR0 Logical Base is: 0x%03X \n", pPartialDescriptor->u.Memory.Start);
DbgPrint("BAR0 Virtual Base is: 0x%03X \n", pDevExt->baseBAR0);
DbgPrint("Length of mapping is %d \n", pDevExt->baseLength);
}
else if (pPartialDescriptor->u.Memory.Start.LowPart == 0xFEAFD000)
{
...// same here , except I replace BAR0 with BAR1
}
else {
DbgPrint("Unexpected base\n");
}
break;
}
}
} // close if (NULL...
InitializeBoard(pDO);
...
DebugPrint(INFO,"Exiting HandleStartDevice\n");
return status;
}
09-08-2005 04:16 PM
Here is the InitializeBoard:
void InitializeBoard(IN PDEVICE_OBJECT pDO) {
DebugPrint(INFO,"Entering InitializeBoard\n");
PDEVICE_EXTENSION pDevExt =
(PDEVICE_EXTENSION)pDO->DeviceExtension;
if (!pDevExt->isBoardInitialized) {
ULONG windowDataValue =
((0xffffff00L & pDevExt->basePhysicalBAR1.LowPart) | 0x80);
DbgPrint("Calculated window data value 0x%03X \n",
windowDataValue);
ULONG basePlusOffset = (PtrToUlong (pDevExt->baseBAR0)) + 0xc0;
DbgPrint("Calculated base plus offset 0x%03X \n", basePlusOffset);
WRITE_REGISTER_ULONG((PULONG) ULongToPtr(basePlusOffset), windowDataValue);
pDevExt->windowDataValue = windowDataValue;
pDevExt->isBoardInitialized = true;
}
DebugPrint(INFO,"Exiting InitializeBoard\n");
return;
}
Finally, here is my DispatchRead which gets called from a user
application:
NTSTATUS DispatchRead (
IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp ) {
NTSTATUS status = STATUS_SUCCESS;
DebugPrint(INFO,"Read Operation requested (DispatchRead)\n");
PDEVICE_EXTENSION pDevExt =
(PDEVICE_EXTENSION) pDevObj->DeviceExtension;
PIO_STACK_LOCATION stack =
IoGetCurrentIrpStackLocation(pIrp);
ULONG basePlusOffset = (PtrToUlong (pDevExt->baseBAR0)) + 0x460;
DbgPrint("Attempting to read address %X \n",basePlusOffset);
ULONG value = READ_REGISTER_ULONG((PULONG) ULongToPtr(basePlusOffset));
DbgPrint("Read %X \n",value);
return status;
}
09-08-2005 04:17 PM
Here are parts of the debug session. I am pointing with an arrow to relevant output:
…
Iterating through number resources 5
Iterating through resource number 0
Looking at Memory usage
BAR1 Logical Base is: 0xFEAFD000 <-----------------
BAR1 Virtual Base is: 0xF8BD0000 <-----------------
Length of mapping is 4096
Iterating through resource number 1
Iterating through resource number 2
Looking at Memory usage
BAR0 Logical Base is: 0xFEAFC000 <-----------------
BAR0 Virtual Base is: 0xF8BDF000 <-----------------
Length of mapping is 4096
Iterating through resource number 3
Iterating through resource number 4
Interrupt Resources are: IRQ=16 Vector=0x03B Affinity=1
Entering InitializeBoard
Calculated window data value 0xFEAFD080 <-----------------
Calculated base plus offset 0xF8BDF0C0 <-----------------
Exiting InitializeBoard
…
Exiting HandleStartDevice
…