Hi All,
I need to develop a driver for Fastcom:ESCC-PCI for serial interface under qnx and I got code from openqnx. Which is working fine for accessing the PCI bus and able to get port address using mmap_device_memory.
Earlier to PCI driver, i have worked on serial driver using devc-ser8250 which ultimately uses the Resource manager for open,read,write,devctl and after loading driver application can use open, write et.
Issues :
- Is there any resource manager working behind for PCI driver?
- To perform open, read and write on port what API should be used for PCI driver by application ??
Please find my code,
#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_CARD_DEVICE_ID 0x11
#define PCI_CARD_VENDOR_ID 0x18F7
void pci_give_command(uint16_t pci_command, struct pci_dev_info *inf);
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);
}
void pci_give_command(uint16_t pci_command, struct pci_dev_info *inf)
{
uint16_t test_read;
pci_write_config16(inf->BusNumber,inf->DevFunc,0x04,1,&pci_command);
pci_read_config16(inf->BusNumber,inf->DevFunc,0x06,1,&test_read);
fprintf(stdout,"\n pci command register ip=%x",pci_command);
fprintf(stdout,"\n pci command register op =%x",test_read);
}
int main(int argc, char *argv)
{
struct pci_dev_info inf;
int pci_handle;
uint32_t addr_handle;
uint32_t io_addr;
void *addr[2];
void *dev_handle;
unsigned index = 0;
unsigned bus;
unsigned dev;
unsigned func;
unsigned dev_func;
volatile uint8_t* x;
uint32_t value;
uint32_t BAR0, BAR1;
//intial some variable
memset (&inf, 0, sizeof (struct pci_dev_info));
inf.VendorId = PCI_CARD_VENDOR_ID;
inf.DeviceId = PCI_CARD_DEVICE_ID;
//get the hight provillege
ThreadCtl (_NTO_TCTL_IO, 0);
//open PCI server, so that you can use pci_*()
pci_handle = pci_attach(0);
if (pci_handle == -1)
return 0;
//detect pci device
if (pci_find_device (inf.DeviceId,
inf.VendorId,index,&bus,&dev_func) != PCI_SUCCESS)
return 0;
fprintf (stdout," pci_find_device is called");
//get the device information
dev_handle = pci_attach_device (NULL,
(PCI_SHARE|PCI_SEARCH_VENDEV|PCI_INIT_ALL),
0,
&inf);
if (dev_handle == NULL)
return 0;
fprintf (stdout,"\n pci_attach_device is called \n");
//print some information which have been found.
pci_printf (&inf);
//get pci address
if ( pci_read_config32 (inf.BusNumber,
inf.DevFunc,
0x10,
1,
&BAR0)!= PCI_SUCCESS)
return 0;
fprintf (stdout,"\n pci_read_config32 with 10 is called \n ");
//get pci board register address
if ( pci_read_config32 (inf.BusNumber,
inf.DevFunc,
0x14,
1,
&BAR1)!= PCI_SUCCESS)
return 0;
fprintf (stdout,"\n pci_read_config32 with 14 is called \n ");
//remap pci mite address
if (PCI_IS_MEM (BAR0))
addr_handle = PCI_MEM_ADDR (BAR0);
else
addr_handle = PCI_IO_ADDR (BAR0);
fprintf (stdout,"\n addr_handle is %d \n ",addr_handle);
addr[0] = mmap_device_memory (NULL,
*(inf.BaseAddressSize),
(PROT_READ | PROT_WRITE | PROT_NOCACHE),//must NOCACHE
0,
(uint64_t)addr_handle);
if (addr[0] == MAP_FAILED)
{
fprintf (stdout,"\n addr_handle is failed BAR 0\n");
return 0;
}
//remap pci board address
if (PCI_IS_MEM (BAR1))
addr_handle = PCI_MEM_ADDR (BAR1);
else
addr_handle = PCI_IO_ADDR (BAR1);
fprintf (stdout,"\n addr_handle is %d \n ",addr_handle);
addr[1] = mmap_device_memory (NULL,
*(inf.BaseAddressSize),
(PROT_READ | PROT_WRITE | PROT_NOCACHE),
0,
(uint64_t)addr_handle);
if (addr[1] == MAP_FAILED)
{
fprintf (stdout,"\n addr_handle is failed BAR 1 \n");
return 0;
}
pci_give_command(0x384, &inf);
//release re-map memory
if (munmap_device_memory (addr[0], (*(inf.BaseAddressSize))) == -1)
fprintf (stdout, "\n Error:munmap ADDR0 failed!");
if (munmap_device_memory (addr[1], (*(inf.BaseAddressSize))) == -1)
fprintf (stdout, "\n Error:munmap ADDR1 failed!");
//release the relation with the device
if (pci_detach_device(dev_handle) != PCI_SUCCESS)
fprintf(stdout, "\n Error:detach device failed status!\n");
//release pci server
if (pci_detach (pci_handle) != PCI_SUCCESS)
fprintf (stdout, "\n Error:detach pci sever failed status!!%s\n", strerror (errno));
fprintf (stdout, "\n======================================================\n");
return 0;
}