From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Driver Development Kit (DDK)

cancel
Showing results for 
Search instead for 
Did you mean: 

Configuring PCI-MIO-16E-1 from DDK and performing DIO

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.

 

0 Kudos
Message 1 of 23
(11,227 Views)
Scanning the code, one problem jumped out:

ULONG windowDataValue =
((0xffffff00 & PtrToUlong (pDevExt->base2)) | 0x80);

This value needs to be based on the physical address of the BAR, not the mapped virtual address. If you extend the pDevExt structure to contain the physical address of the BARs and use this value instead, the initialization may work.

geoff
--
Geoff Schmit
Huskie Robotics, FIRST Team 3061 Lead Mentor
http://team3061.org/
@team3061
0 Kudos
Message 2 of 23
(11,173 Views)

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);

0 Kudos
Message 3 of 23
(11,166 Views)
> Also, how do we know which of the two Windows reported address ranges is BAR and which one is BAR1?

I believe Windows reports these resources in order (i.e., the first one is BAR0). I've never seen this promised, however. You can also read the BARs via PCI config access.

> In addition PCI E-series Register Level Programming does not specify the register size at offset 0xc0.

It is 32 bits.

Try reading 32-bits at offset 0x460 from BAR0 and responding with the read value. This will let us know if you're successfully communicating to the device or not.

In addition, perhaps if you most more of the code and the output from executing it, something else will become apparent.

geoff
--
Geoff Schmit
Huskie Robotics, FIRST Team 3061 Lead Mentor
http://team3061.org/
@team3061
0 Kudos
Message 4 of 23
(11,153 Views)

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?

0 Kudos
Message 5 of 23
(11,151 Views)
That is not the expected value. BAR0 is not being mapped successfully.

Sorry, I mistyped the last sentence. I meant to write: perhaps if you post more of the code and the output from executing it, something else will become apparent. That is, you've only posted a small portion of the code; the context is not clear. Also, while the code has a number of debug prints, you have not posted the output of these debug prints when the code is executed. This additional information may help me or someone else notice the problem.

geoff
--
Geoff Schmit
Huskie Robotics, FIRST Team 3061 Lead Mentor
http://team3061.org/
@team3061
0 Kudos
Message 6 of 23
(11,146 Views)

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;

0 Kudos
Message 7 of 23
(11,143 Views)

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;
}

0 Kudos
Message 8 of 23
(11,138 Views)

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;
}

0 Kudos
Message 9 of 23
(11,137 Views)

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

Read Operation requested (DispatchRead)
Attempting to read address F8BDF460  <-----------------
Read  FFFFFFFF   <-----------------

0 Kudos
Message 10 of 23
(11,137 Views)