I’m writing an interface to a PCI card for the first time and I’m having a
lot of trouble getting the card to work. Each time I access the memory
mapped by mmap_device_memory the box actually locks up completely. I’m not
sure if the base address returned from the card is correct or not. The
pci_attach_device function attachs to the card but doesn’t fill in the base
address and size in the pci_dev_info structure, so to work around this I
find the base address and size by using pci_read_config32 and
pci_write_config32 functions. If anyone has any ideas on what I’m doing
wrong I’d appreciate it. Attached is the code from my test application if
anyone would like to look at it.
read_data = *(addr+3); // THIS IS THE LINE THAT CAUSES THE LOCKUP
Here is some info from pci -vs.
Class = Bridge (Unknown)
Vendor ID = 148ah, Opto 22
Device ID = ac51h, Unknown Unknown
PCI index = 0h
Class Codes = 068000h
Revision ID = 0h
Bus number = 2
Device number = 4
Function num = 0
Status Reg = 280h
Command Reg = 0h
Some code:
// system includes
#include <hw/pci.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/neutrino.h>
#include <limits.h>
#include <sys/mman.h>
#include <fcntl.h>
#include “datatype.h”
#include “genlib.h”
#include “maxima.h”
#include “mastdefs.h”
#include “objmast.h”
#include “objlib.h”
#define DEVICE_ID 0x148A
#define VENDOR_ID 0xAC51
#define MAX_INDEXES 1
//================================
// main function call
//================================
int main(void)
{
int pci_handle = -1;
unsigned int bus_attach_flags = 0; // none are supported as of yet
char proc[] = “ac51 driver, main()”;
struct pci_dev_info pci_info[MAX_INDEXES];
unsigned int index[MAX_INDEXES];
unsigned int bus[MAX_INDEXES];
unsigned int dev_func[MAX_INDEXES];
unsigned int addr_data, write_data= ~0, size_data;
unsigned int idx = 0;
unsigned int device_attach_flags = 0;
int ret_val = 0;
int *handle = NULL;
int loop_idx = 0;
volatile unsigned char *addr;
unsigned char read_data;
unsigned int mem;
//===============================================
// clear out the pci_info structures
//===============================================
for (loop_idx = 0; loop_idx < MAX_INDEXES; loop_idx++)
{
memset( &pci_info[loop_idx], 0, sizeof( pci_info[loop_idx] ) );
pci_info[loop_idx].VendorId = DEVICE_ID;
pci_info[loop_idx].DeviceId = VENDOR_ID;
index[loop_idx] = 0;
bus[loop_idx] = 0;
dev_func[loop_idx] = 0;
}
//===============================================
// to allow us to call mmap_device_memory
//===============================================
ThreadCtl(_NTO_TCTL_IO, 0);
//===============================================
// attach to the PCI bus
//===============================================
pci_handle = pci_attach( bus_attach_flags );
//===============================================
// check for a connection error to the PCI bus server
//===============================================
if (pci_handle == -1)
debug(0, proc, “error opening pci_handle, errno = %d, (%s)”,
errno, strerror(errno));
//===============================================
// go through each card on the PCI bus, until we are finished
// find a card, any card
//===============================================
idx = 0;
while ( (ret_val = pci_find_device(
pci_info[idx].DeviceId,
pci_info[idx].VendorId,
index[idx],
&bus[idx],
&dev_func[idx]) ) == PCI_SUCCESS)
{
debug(0, proc, “PCI_SUCCESS”);
//=============================================
// the first time we call pci_attach_device we need to make
handle NULL
//=============================================
if (idx == 0)
handle = NULL;
device_attach_flags |= PCI_INIT_ALL;
handle = pci_attach_device(handle,
device_attach_flags,
index[idx],//idx,
&pci_info[idx]);
// check for an attach failure
if (handle == NULL)
{
debug(0, proc, “Error attaching to pci device, %d
(%s)”,errno, strerror(errno));
break;
}
else
{
debug(0, proc, “found device at idx=%d”,idx);
pci_read_config32( bus[idx], dev_func[idx], 0x14, 1, (char
*) &addr_data );
pci_write_config32( bus[idx], dev_func[idx], 0x14, 1,
(char *) &write_data );
pci_read_config32( bus[idx], dev_func[idx], 0x14, 1, (char
*) &size_data );
pci_write_config32( bus[idx], dev_func[idx], 0x14, 1,
(char *) &addr_data );
debug(0, proc, “addr_data = %x”,addr_data);
debug(0, proc, “write_data = %x”,write_data);
debug(0, proc, “size_data = %x”,size_data);
debug(0, proc, “~size_data = %x”,~(size_data));
size_data = ~(size_data) +1;
debug(0, proc, “new size_data = %x”,size_data);
//======================================
// just a precautionary check
//======================================
if (PCI_IS_IO(addr_data))
{
debug(0, proc, “is io”);
exit (1);
}
else
{
if (PCI_IS_MEM(addr_data))
{
debug(0, proc, “is mem”);
addr_data = PCI_MEM_ADDR(addr_data);
debug(0, proc, “new addr_data =
%x”,addr_data);
}
}
addr = mmap_device_memory(NULL,
size_data,
PROT_READ | PROT_WRITE | PROT_NOCACHE,
0,
addr_data);
debug(0, proc, “handle = %d(%x)”,handle, handle);
if (addr == MAP_FAILED)
{
debug(0, proc, “mmap failed :%d (%s)”,errno,
strerror(errno));
}
else
{
debug(0, proc, “mmap successful”);
debug(0, proc, “addr = %p (%d)”, addr, addr);
read_data = *(addr+3); // THIS IS THE LINE THAT
CAUSES THE LOCKUP
debug(0, proc, “read_data = %x”, read_data);
}
}
debug(0, proc, “idx++”);
idx++;
if (idx >= MAX_INDEXES)
{
debug(0, proc, “Potentially too many cards found, increase
MAX_INDEXES to be one greater than total AC51 cards on PCI bus”);
break;
}
}
//=======================================
// device not found
//=======================================
if (ret_val == PCI_DEVICE_NOT_FOUND)
{
debug(0, proc, “device not found”);
debug(0, proc, “ret_val = %x”,ret_val);
debug (0, proc, “deviceID=(%x),
VendorID=(%x)”,pci_info[idx].DeviceId, pci_info[idx].VendorId);
debug(0, proc, “index=(%d) bus=(%d) dev_func=(%d)”, index[idx],
bus[idx], dev_func[idx]);
}
//=======================================
// error finding device
//=======================================
if (ret_val == -1)
debug(0, proc, “Error = %d, (%s)”, errno, strerror(errno));
//=======================================
// detach from the pci bus server…
//=======================================
pci_detach(pci_handle);
//================================================
// unmap the memory
//================================================
munmap_device_memory( (unsigned char *)addr, size_data);
//================================================
// if we get here just return to OS
//================================================
return 0;
}
\
C. Scott