Recently, I am developing a drvier about PCI6503 in QNX, but it could not work may be some mistake, I have looked for it but get none for a long time. Now I put the all code to openqnx with my boss’s permitte, regard someone can make it good.
The program’s work step is:
1 Get the root prority.
2 Get the pci_* server’s support.
3 Check the pci device is ok.
4 Get Some Information about the pci device.
5 Print the information.
6 Remap the pci mite address and pci board register address.
7 Get the prority to access to BAR1.
8 Operate the board by the point.
9 Release the resource.
Problem description:
The Former code is good because The printed information is OK, the later is the problem’s source.
About PCI6503:
It is USA NI’s 24 DIO pci board, there is a 8255 PPI in it, which have three 8-bit port to control DIO input or output.
BASE+0: PORTA
BASE+1: PORTB
BASE+2: PORTC
BASE+3: CONFIG REGISTER
To configure the PCI MITE chip, you must first write an algorithm that finds and stores all configuration information about the board. To do this, use PCIBIOS calls to search PCI configuration space for the National Instruments vendor ID (0x1093) and PCI-DIO-96 device ID (0x0160), PXI-6508 device ID (0x13c0), or PCI-6503 device ID (0x17d0). If a board is found, the algorithm can store all the board’s configuration information into a data structure. Base Address Register 0 (BAR0) corresponds to the base address of the PCI MITE, while Base Address Register1 (BAR1) is the base address of the board registers. The size of each of these windows is 4KB. Both addresses will most likely be mapped above 1MB in the memory map. This means that you must know how to perform memory cycles to extended memory to communicate with the board. The memory map provides information to re-map the board under 1MB, which simplifies communication with the board. To accomplish this, use PCI BIOS read and write calls. Use the pseudocode in this section to re-map the board below 1MB. If you choose not to re-map the board, you must still perform steps4 and5. All values in this example are 32bits.
- Write the address to which you want to re-map the PCI MITE to PCI configuration space offset 0x10 (BAR0).
- Write the value 0x0000aeae to offset 0x340 from the new PCI MITE address.
- Write the address to which you want to re-map the board (other than the PCI MITE) to PCI configuration space offset 0x14 (BAR1).
- Create the window data value by masking the new board address:window data value = ((0xffffff00 and new board address) or (0x00000080))If you are not remapping the board, then the new board address is the value in BAR1.
- Write the window data value to offset 0xc0 from the new PCI MITE address.
If you are not remapping the board, then the new PCI MITE address is the value in BAR0.The following pseudocode re-maps the PCI MITE to memory address 0xd0000 and the board to memory address 0xd1000.
CWrite(0x10,0x000d0000);
Write(0xd0340,0x0000aeae);
CWrite(0x14,0x000d1000);
Write(0xd00c0,0x000d1080) ;
My Code here:
#include <sys/neutrino.h>
#include <hw/pci.h>
#include <hw/pci_devices.h>
#include <stdio.h>
#include <sys/mman.h>
#include <errno.h>
#define PCI_DEBUG
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#define PCI_CARD_DEVICE_ID 0x17d0
#define PCI_CARD_VENDOR_ID 0x1093
//-----------------------------------------------------------------------------
uint32_t dev_address_value_test;
uint32_t mem_address_value_test;
/********************************************************************************
********************************************************************************/
void pci_printf(struct pci_dev_info *inf)
{
uint32_t i;
fprintf (stdout, “\n device id = %x”, inf->DeviceId);
fprintf (stdout, “\n Vendo id = %x”, inf->VendorId);
fprintf (stdout, “\n BusNumber = %x”, inf->BusNumber);
fprintf (stdout, “\n device number = %x”, ((inf->DevFunc)>>3)&0x1F);
fprintf (stdout, “\n Function number = %x”, (inf->DevFunc)&0x07);
fprintf (stdout, “\n Revision = %x”, inf->Revision);
fprintf (stdout, “\n device class = %x”, inf->Class);
fprintf (stdout, “\n device irq = %x”, inf->Irq);
fprintf (stdout, “\n pcibase address = %x”, ((inf->CpuBaseAddress)));
fprintf (stdout, “\n base address size = %x”, ((inf->BaseAddressSize)));
pci_read_config32 (inf->BusNumber, inf->DevFunc, 0x10, 1, &i);
fprintf (stdout, “\n Base address 0 = %x”, i);
pci_read_config32 (inf->BusNumber, inf->DevFunc, 0x14, 1, &i);
fprintf (stdout, “\n Base address 1 = %x”, i);
}
/********************************************************************************
********************************************************************************/
#define PCI_YES 1
#define ATTACH_PCI_FAILURE -1
#define FIND_FAILURE -2
#define ADDR_ERROR -3
#define ATTACH_DEVICE_FAILURE -4
int pci_card_detect(unsigned index,
unsigned *pci_handle,
struct pci_dev_info *inf,
uint32_t *dev_handle,
uint32_t *mem_handle)
{
uint32_t addr_handle;
uint32_t io_addr;
unsigned bus;
unsigned dev;
unsigned func;
unsigned dev_func;
uint8_t* x;
uint32_t *p;
uint32_t value;
uint32_t BAR0, BAR1;
uint32_t *addr[2];
ThreadCtl (_NTO_TCTL_IO, 0);
*pci_handle = pci_attach(0);
if (*pci_handle == -1)
return ATTACH_PCI_FAILURE;
if (pci_find_device (inf->DeviceId,
inf->VendorId,
index,
&bus,
&dev_func) != PCI_SUCCESS)
return FIND_FAILURE;
dev_handle = pci_attach_device (NULL,
(PCI_SHARE|PCI_SEARCH_VENDEV|PCI_INIT_ALL),
0,
inf);
if (dev_handle == NULL)
return ATTACH_DEVICE_FAILURE;
//print some information which have been found.
pci_printf(inf);
if ( pci_read_config32 (inf->BusNumber,
inf->DevFunc,
0x10,
1,
&BAR0)!= PCI_SUCCESS)
return ADDR_ERROR;
if ( pci_read_config32 (inf->BusNumber,
inf->DevFunc,
0x14,
1,
&BAR1)!= PCI_SUCCESS)
return ADDR_ERROR;
addr_handle = PCI_IO_ADDR(BAR0); //PCI_MEM_ADDR(BAR0);
fprintf (stdout, “\n 1 board mite addr: %x”, addr_handle);
addr[0] = mmap_device_memory (NULL,
*(inf->BaseAddressSize),
(PROT_READ|PROT_WRITE),
0,
(uint64_t)addr_handle);
fprintf (stdout, “\n 1 board mite new : %x”, addr[0]);
addr_handle = PCI_IO_ADDR(BAR1);//PCI_MEM_ADDR(BAR1);
fprintf (stdout, “\n 2 board reg addr : %x”, addr_handle);
addr[1] = mmap_device_memory (NULL,
*(inf->BaseAddressSize),
(PROT_READ|PROT_WRITE),
0,
(uint64_t)addr_handle);
fprintf (stdout, “\n 2 board reg new : %x”, addr[1]);
mem_handle = addr[1];
if (mem_handle == MAP_FAILED)
return;
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
fprintf (stdout, “\n 1 dev_handle: %x”, dev_handle);
fprintf (stdout, “\n 1 mem_handle: %x”, mem_handle);
dev_address_value_test = (uint32_t)dev_handle;
mem_address_value_test = (uint32_t)mem_handle;
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// access to BAR1
pci_write_config32 (inf->BusNumber,
inf->DevFunc,
0x10, //BAR0
1,
&addr[0]);//set the new pci mite value to BAR0
((uint32_t)addr[0] + 0x340) = 0xaeae;
pci_write_config32 (inf->BusNumber,
inf->DevFunc,
0x14,//BAR1
1,
&addr[1]);//set the new pci board reg value to BAR1
((uint32_t)addr[0] + 0xc0) = ((uint32_t)addr[1]& 0xffffff00)|0x80;
//Set Configer Register (all is output port)
x = (uint8_t*)mem_handle+0x03;
*x = 0x80;
fprintf (stdout, “\n Configer register addr = %x”, x);
fprintf (stdout, “\n Configer register value = %x\n”, *x);
//Port A output
x = (uint8_t*)mem_handle+0x0000;
*x = 0xaa;
fprintf (stdout, “\n Port A address = %x”, x);
fprintf (stdout, “\n Port A value = %x\n”, *x);
//Port B output
x = (uint8_t*)mem_handle+0x0001;
*x = 0xaa;
fprintf (stdout, “\n Port B address = %x”, x);
fprintf (stdout, “\n Port B value = %x\n”, *x);
//Port C output
x = (uint8_t*)mem_handle+0x0002;
*x = 0xaa;
fprintf (stdout, “\n Port C address = %x”, x);
fprintf (stdout, “\n Port C value = %x”, *x);
return PCI_YES;
}
/********************************************************************************
********************************************************************************/
void close_card (struct pci_dev_info *inf,
int pci_handle,
void *dev_handle,
void *mem_handle)
{
if (mem_handle == MAP_FAILED)
return;
if (munmap_device_memory (mem_handle, (*(inf->BaseAddressSize))) == -1)
fprintf (stdout, “\n Error:munmap failed!”);
if (pci_detach_device(dev_handle) != PCI_SUCCESS)
fprintf(stdout, “\n Error:detach device failed status!\n”);
if (pci_detach (pci_handle) != PCI_SUCCESS)
fprintf (stdout, “\n Error:detach pci sever failed status!!%s\n”, strerror (errno));
return;
}
/*******************************************************************************/
int main(int argc, char *argv)
{
struct pci_dev_info inf;
int pci_handle;
uint32_t addr_handle;
uint32_t *mem_handle;
uint32_t *dev_handle;
unsigned index = 0;
fprintf (stdout, “======================================================”);
memset (&inf, 0, sizeof (struct pci_dev_info));
inf.VendorId = PCI_CARD_VENDOR_ID;
inf.DeviceId = PCI_CARD_DEVICE_ID;
if (pci_card_detect (index, &pci_handle, &inf, dev_handle,mem_handle) = PCI_YES)
{
dev_handle = (uint32_t*)dev_address_value_test;
mem_handle = (uint32_t*)mem_address_value_test;
close_card(&inf, pci_handle, dev_handle, mem_handle);
}
fprintf (stdout, “\n======================================================\n”);
return 0;
}
/*******************************************************************************/