| thinkpeace 2005-04-12, 6:02 pm |
| I'm porting a device driver to Solaris 9 x86 for a PCI device, and I
get a Bus Error (segmentation fault) when attempting to read the
device, both from Kernel mode and from user mode.
I can read the beginning of the device memory space of register #2,
which is 0x80000 in length, but past an offset of 0x1a000 I get a bus
error.
I ran my user-mode test program with the debugger (gdb). The program
ended with a bus error after attempting to read from an offset of
0x40008. Then I tried inspecting the m_pHardware variable (which is
mapped to the device register #2). Below is the program output:
========================================
===
GNU gdb 5.3
This GDB was configured as "i386-pc-solaris2.9"...
(gdb) run
Starting program: /export/home/samba/hisc1/hiscdiag
Successfully opened /platform/i86pc/kernel/drv/hisc
hiscDevice maped to address D2A90000
Reset FPGA, D2AD0000
Program received signal SIGSEGV, Segmentation fault.
0x08052946 in CFpga::Load (this=0x8047b68, file_name=0x8056981
"digital.pga", fpga_number=0 '\0') at hiscdiag.cpp:189
189 i = *((DWORD *)(m_pHardware + FPGA_COMMAND +
fpgaOffset ));
(gdb) inspect (m_pHardware + 0x19ff0)
$1 = (unsigned char *) 0xd2aa9ff0 ""
(gdb) inspect (m_pHardware + 0x1a000)
$2 = (unsigned char *) 0xd2aaa000 <Address 0xd2aaa000 out of bounds>
(gdb)
========================================
==
Below is the user mode code snipet:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
hiscDevice = open( hiscName, O_RDWR );
if( hiscDevice == -1 ) {
printf( "Failed to Open %s\n", hiscName );
return 0;
}
printf( "Successfully opened %s\n", hiscName );
hiscRegs = (struct hisc_regs *) mmap( (caddr_t) 0, len,
(PROT_READ | PROT_WRITE),
MAP_SHARED, hiscDevice, 0x0 ); // MAP_PRIVATE?
if( hiscRegs == MAP_FAILED ) {
printf( "nmap failed: %d\n", errno );
return 0;
}
printf( "hiscDevice maped to address %lX\n", hiscRegs );
printf( "Reset FPGA, %08lX\n", m_pHardware + FPGA_COMMAND + fpgaOffset
);
m_pHardware = (BYTE *) hiscRegs;
i = *((DWORD *)(m_pHardware + 0x40008 ));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
Below is the devmap function in the driver:
++++++++++++++++++++++++++++++++++++++++
++++
int hisc_devmap(dev_t dev, devmap_cookie_t handle, offset_t off,
size_t len, size_t *maplen, uint_t
model)
{
struct hisc_softstate *softstate;
int error, rnumber;
off_t regsize;
/* Set up data access attribute structure */
struct ddi_device_acc_attr xx_acc_attr = {
DDI_DEVICE_ATTR_V0,
DDI_NEVERSWAP_ACC,
DDI_STRICTORDER_ACC
};
softstate = ddi_get_soft_state(hisc_glob_soft_handle
,
getminor(dev));
if (softstate == NULL)
return (-1);
/* round up len to a multiple of a page size */
len = ptob(btopr(len));
if (off + len > softstate->hisc_memsize)
return (-1);
/* Set up the device mapping */
error = devmap_devmem_setup(handle, softstate->dip, NULL,
softstate->hisc_regindex, off, len, PROT_ALL,
DEVMAP_DEFAULTS, &xx_acc_attr);
/* acknowledge the entire range */
*maplen = len;
return (error);
}
++++++++++++++++++++++++++++++++++++++++
++++
I also tried reading from offset 40008 in the driver in the attach()
function. It causes the system to crash - I assume this is also
causing a Bus Error.
attach() snipet:
status = ddi_regs_map_setup(dip, 2,
(caddr_t *)&softstate->hisc_regs,
0, 0,
&dev_attr, &softstate->hisc_regs_handle);
if (status != DDI_SUCCESS) {
if (status == DDI_REGS_ACC_CONFLICT) {
cmn_err(CE_WARN,
"regs mapping conflicted with other drivers");
hisc_cleanup(softstate);
return DDI_FAILURE;
}
else
{
cmn_err(CE_NOTE,
"regs mapping failed: no registers to map ");
}
}
hisc_debugprint( "Resetting FPGA 0\n" );
ddi_get32( softstate->hisc_regs_handle, softstate->hisc_regs +
0x40008
);
hisc_debugprint( "Reset Done\n" );
Why am I getting a segmentation fault?
Thanks in advance,
Eric
|