Products & Services Solutions Academia Support User Community Company

Learn more about xPC Target   

PCI Bus Considerations

Introduction

When writing xPC Target drivers for PCI devices, consider the memory access method. A PCI device can be either I/O port mapped or memory mapped.

The PC BIOS automatically assigns a conflict-free set of resources to any PCI device found in the system at boot-up. You typically do not know where the board resides (base address) before driver initialization. However, you can obtain this information by querying the PCI configuration space at run time. The xPC Target software provides functions to accomplish this (see the PCI Configuration Information functions).

To locate a PCI device, you need the following:

You can have the drivers locate PCI devices in one of the following ways:

PCI Configuration Space API

Before you can access a PCI device, you need to access the configuration space to locate the board in the target PC memory. This section describes the procedure to do this.

For PCI devices, the driver will need to access the PCI configuration space for the board. This space contains relevant board information such as the base address and access type (I/O port or memory mapped). The xPC Target software provides functions that allow the driver to access this space.

PCI Device Information

Use the xpcGetPCIDeviceInfo function to get information for a PCI device in your system. The syntax for this function is:

int xpcGetPCIDeviceInfo (uint16_T vendorId, uint16_T deviceId, uint16_T subVendorId, uint16_T subDeviceId, uint16_T bus, uint16_T slot, xpcPCIDevice *pciInfo);

This function returns the xpcPCIDevice structure filled according to the following:

If You Supply...This Function....
All the parametersLooks for a device that matches all the parameters and returns the xpcPCIDevice structure for that device. Use this form if you know that your system has multiple boards from the same vendor with the same ID and you want your user to specify the exact device.
XPC_NO_SUB for the subVendorId or subDeviceId parameterDoes not consider the subvendor or subdevice ID when looking for a match for the specified device. It returns the xpcPCIDevice structure for a device that matches the other parameters. You can use this form if you do not plan to use the subVendorId or subDeviceId values.
XPC_NO_BUS_SLOT for the slot for the deviceReturns the first PCI device it finds that matches the remaining parameters. You can use this form if you know that your system has only one board with a particular ID set.

Passing Slot Information from the Block Mask to Its Driver

xPC Target drivers use the following convention to fill in slot parameters and retrieve slot information. Choose the convention that will work best for you.

Set...To...

Set slot = -1

Assume bus = 0 and call the xpcGetPCIDeviceInfo function to find the first instance of the board.

Set slot = S

Assume bus = 0 and call the xpcGetPCIDeviceInfo function to find the specified board. If the board matches the IDs, return the PCI information to the driver. Otherwise, return an error.

Set slot = [B, S]

Check bus B and slot S for the specified board. If the board matches the IDs, return the PCI information to the driver. Otherwise, return an error.

Setting slot = [0, S] is identical to slot = S.

The following example illustrates how to use the xpcGetPCIDeviceInfo function to program the driver to accept slot number input or slot and bus number input from the driver block.

  1. Call this function from the mdlStart callback function.

  2. Pass the slot number or slot and bus number into the xpcGetPCIDeviceInfo function using code like the following:

    uint16_T       vendorId, deviceId;
    int32_T        bus, slot, subvendor, subdevice;
    xpcPCIDevice   pciInfo;
    
    /* S_PCI_SLOT_ARG is passed in from the mask */
    /* Typically the slot arg is a scalar containing -1 if there is only one board of 
    this type in the target */
    /* If there are multiple boards of this type the slot arg is a vector containing bus 
    and slot info */
    /* This code snipped parses the slot arg into bus and slot */
    if ( (int_T)(mxGetN(ssGetSFcnParam(S, S_PCI_SLOT_ARG))) == 1 ) {
    	bus  = 0;
    	slot = (int32_T)(mxGetPr(ssGetSFcnParam(S, S_PCI_SLOT_ARG))[0]);
    } else {
    	bus  = (int32_T)(mxGetPr(ssGetSFcnParam(S, S_PCI_SLOT_ARG))[0]);
    	slot = (int32_T)(mxGetPr(ssGetSFcnParam(S, S_PCI_SLOT_ARG))[1]);
    }
    
    vendorId = (uint16_T)0x1234;
    deviceId = (uint16_T)0x9876;
    subvendor = (uint16_T)0x5678;
    subdevice = (uint16_T)0x8765;
    /* Set subvendor and subdevice to XPC_NO_SUB, XPC_NO_SUB if they are not necessary */
    
    /* xpcGetPCIDeviceInfo() populates the pciInfo struct */
    if ( xpcGetPCIDeviceInfo(vendorId, deviceId,
    					subvendor, subdevice,
    					bus, slot,
    					&pciInfo) ) {
    	sprintf(msg, "Board 0x%x not found at bus %d slot %d", deviceId, bus, slot);
    	ssSetErrorStatus(S, msg);
    	return;
    }

For detailed information on the xpcPCIDevice structure, see xpcPCIDevice.

Memory-Mapped Accesses

A memory-mapped PCI board uses up to six memory regions to access board regions and memory. Each region might also have a different length. You must call the xpcReserveMemoryRegion function for each PCI memory region you want to access; use the returned virtual address to access the region. Failure to do this will result in a segmentation fault.

To access a memory mapped location, do the following:

  1. Declare a pointer of the appropriate size to the memory. For example:

    volatile uint32 *csr; /* Control and status register */

    Note that you will want to use the volatile keyword here; otherwise, the compiler might optimize away accesses to this location.

  2. Set its value (address) to the physical address at which the register resides.

I/O Port Accesses

To access I/O ports, use the following functions:

  


Related Products & Applications

Learn more about Simulink through this collection of videos, articles, technical literature and the Getting Started with Simulink Guide.

 © 1984-2009- The MathWorks, Inc.    -   Site Help   -   Patents   -   Trademarks   -   Privacy Policy   -   Preventing Piracy   -   RSS