Juan,
I have a driver problem with free bsd. Could you forward this to the
appropriate person and get the results back to me.
Doug Madderom
-----------------------------------------------------------------------------------------------
I wrote a character device driver using ioct as the method to pass data in a
structure to and from the device driver. If I do not include either a printf or
scanf in the application program that uses the driver the pointer the OS passes
to the ioctl in the driver is not set up right and the driver panics. What am I
doing wrong ? Do I need to do something special in the driver to get the ioctl
to link up properly and this is what the printf/scanf is doing in the
application? This is my first Bsd device driver I wrote several in Solaris 86
and Unixware and never seen this behavior.
Any help would be appreciated. Included is copy of source and test code that
fails.
Doug Madderom
[EMAIL PROTECTED]
623-582-7245
Here is the definition for the ioctl commands:
--------------------------------------------
struct Ioctl_args {
int status;
int device;
unsigned int address;
unsigned char value;} ;
#define ALARMIO_READ _IOWR('a', 1, struct Ioctl_args)
#define ALARMIO_WRITE _IOWR('a', 2, struct Ioctl_args)
#define ALARMIO_TEST _IOWR('a', 3, int)
Attached is copy of progream that fails and device driver.
Program that fails ( works if first line in program is a printf)
------------------------------
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/alarmio.h>
struct Ioctl_args requestData;
int main (void)
{
int result;
int fd;
requestData.address = 0x8152;
requestData.device = 0;
requestData.value = 0;
if ((fd = open("/dev/alarmio0",O_RDWR)) == -1)
{
perror("Can't open device /dev/alarmio0");
exit(1);
}
if ((result = ioctl(fd, ALARMIO_READ, &requestData)) == -1)
{
if (errno == EIO)
{
printf ("Driver read access error EIO on fd = %d, error value
returned = %d\n",
fd, requestData.status);
}
else
{
printf ("Driver read access error\n");
}
}
else
{
printf ("Data read device %d address %x data %x \n",
requestData.device, requestData.address, requestData.value);
}
return 0;
}
Device driver:
----------------------------------------------
/* alarmio driver for free BDS */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h> /* SYSINIT stuff */
#include <sys/conf.h> /* cdevsw stuff */
#include <sys/malloc.h> /* malloc region definitions */
#include <sys/signal.h>
#include <sys/signalvar.h>
#include <sys/filio.h> /* FIOXXX */
#include <machine/clock.h> /* DELAY() */
#include <machine/cpufunc.h> /* inb and outb commands*/
#include <sys/ioctl.h>
#include <sys/errno.h>
#include </usr/src/sys/i386/isa/isa_device.h>
/* Function prototypes (these should all be static ) */
static d_open_t alarmioopen;
static d_close_t alarmioclose;
static d_ioctl_t alarmioioctl;
static int alarmioprobe (struct isa_device *);
static int alarmioattach (struct isa_device *);
struct isa_driver alarmiodriver = {alarmioprobe, alarmioattach, "alarmio"};
#define CDEV_MAJOR 120
/*static struct cdevsw alarmio_cdevsw = {
alarmioopen,
alarmioclose,
NULL,
NULL,
alarmioioctl,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
"alarmio",
NULL,
-1 }; */
static struct cdevsw alarmio_cdevsw =
{ alarmioopen, alarmioclose, noread, nowrite, /*31*/
alarmioioctl, nostop, nullreset, nodevtotty,/*alarmio */
noselect, nommap, NULL, "alarmio", NULL, -1 };
/* alarmio.c */
/*
alarmio driver to read and set alarms on radisys board
*/
#include <sys/alarmio.h>
static int debug=1; /* debug flag */
static unsigned char dallas1[0x4f]; /* temp arrary for dallas part*/
static unsigned char dallas2[0x4f]; /* temp arrary for dallas part*/
static int
alarmioprobe (struct isa_device *dev)
{
return 1;
}
static int
alarmioattach (struct isa_device *dev)
{
return 1;
}
static void
alarmio_drvinit(void *unused)
{
dev_t dev;
int unit;
if(debug) printf("alarmio_drvinit called \n");
dev = makedev(CDEV_MAJOR, 0);
cdevsw_add(&dev, &alarmio_cdevsw, NULL);
}
/*
* alarmio_open is called in response to the open(2) system call
*/
/*ARGSUSED*/
static int
alarmioopen(dev_t dev, int oflags, int devtype, struct proc *p)
{
int retval = 0;
if(debug) printf("OPEN:CALLED \n");
return (retval);
}
/*
close device
*/
static int
alarmioclose(dev_t dev, int fflag, int devtype, struct proc *p)
{
if(debug) printf("CLOSE:CALLED \n");
return (0);
}
/*
*
*/
/*ARGSUSED*/
static
int alarmioioctl (dev_t dev, int cmd, caddr_t arg, int flag, struct proc *p)
{
int retval = 0;
struct Ioctl_args *tmp;
struct Ioctl_args *result;
struct Ioctl_args result_storage;
/* test code */
result=&result_storage;
if(debug) printf("IOCTL:CALLED \n");
/* get pointer to passed in ioctl arguments */
switch (cmd) {
case ALARMIO_READ:
case ALARMIO_WRITE:
/* get ioctl args in temp */
/* if (copyin(arg, &tmp, sizeof (struct Ioctl_args)) != 0) {
return(EFAULT);
} */
*tmp=*(struct Ioctl_args *)arg;
if(debug) printf("READ OR WRITE stat %x dev %x add %x val %x \n",
tmp->status,tmp->device,tmp->address,tmp->value);
/* populate result buffer with input data */
result->status=0;
result->device=tmp->device;
result->address=tmp->address;
result->value=tmp->value;
/* process read/write request */
switch(tmp->device){
case CPU_REG:
if(tmp->address >= 0x8150 && tmp->address <=0x8210){
if(cmd==ALARMIO_READ)
result->value=inb(tmp->address);
else
outb(tmp->address,tmp->value);
result->status=0;
}
else{
if(debug) printf("READ/WRITE ERROR \n");
retval=EIO;
result->status=ADDRESS_ERROR;
}
/* return results */
*(struct Ioctl_args *)arg=*result;
/* if (copyout(&tmp, arg, sizeof (struct Ioctl_args)) != 0) {
return( EFAULT);
} */
break;
case DALLAS_1:
case DALLAS_2:
retval = ENOTTY;
break;
default:
retval = ENOTTY;
break;
} /*end of device switch */
break;
default:
retval = ENOTTY;
break;
} /*end of cmd switch*/
return (retval);
}
SYSINIT(alarmiodev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR,
alarmio_drvinit, NULL)