
Hello guys,
Since few days I implement a simple rs232 driver on Darwin. But during this implementation I have got some understand problem about a data structure.
Today I will introduce you a part of the kpi : the struct uio and a lot of conveniance functions about uio. And this api is the sources of my past problems. But after my explication I will seem dumb because uio is very simple to understand and to implement.
Uio what s that ? Its simply a api to work with data buffer. Which is the relationship between the rs232 and the struct uio? The functions pointer you ll need to implement to register your driver use uio (like the read or write). Why is this destabilizing? because the struct uio is defined like that in the uio header :
struct uio;
So we don't know the members of that structure. Why apple does that? Because they want to be able to change the code managing this data without the change of all the code using this api.
Since few days I implement a simple rs232 driver on Darwin. But during this implementation I have got some understand problem about a data structure.
Today I will introduce you a part of the kpi : the struct uio and a lot of conveniance functions about uio. And this api is the sources of my past problems. But after my explication I will seem dumb because uio is very simple to understand and to implement.
Uio what s that ? Its simply a api to work with data buffer. Which is the relationship between the rs232 and the struct uio? The functions pointer you ll need to implement to register your driver use uio (like the read or write). Why is this destabilizing? because the struct uio is defined like that in the uio header :
struct uio;
So we don't know the members of that structure. Why apple does that? Because they want to be able to change the code managing this data without the change of all the code using this api.
an uio is a container of iovec. It can have one iovec or a collections of iovec. The iovec contains data. the iovec structure looks like :
struct iovec
{
void *iov_base;
size_t iov_len;
}
This API offers some functions to work on uio containing just one iovec :
void uio_setresid( uio_t a_uio, user_ssize_t a_value );
int uio_rw( uio_t a_uio );
void uio_setrw( uio_t a_uio, int a_value );
int uio_isuserspace( uio_t a_uio );
for collections of data uio struct can work with this fuctions :
void uio_setresid( uio_t a_uio, user_ssize_t a_value );
int uio_rw( uio_t a_uio );
void uio_setrw( uio_t a_uio, int a_value );
int uio_isuserspace( uio_t a_uio );
for collections of data uio struct can work with this fuctions :
int uio_iovcnt( uio_t a_uio );
uio_t uio_create( int a_iovcount, off_t a_offset, int a_spacetype, int a_iodirection );
void uio_reset( uio_t a_uio, off_t a_offset, int a_spacetype, int a_iodirection );
uio_t uio_duplicate( uio_t a_uio );
void uio_free( uio_t a_uio );
void uio_update( uio_t a_uio, user_size_t a_count );
user_ssize_t uio_resid( uio_t a_uio );
int uio_iovcnt( uio_t a_uio );
off_t uio_offset( uio_t a_uio );
void uio_setoffset( uio_t a_uio, off_t a_offset );
user_addr_t uio_curriovbase( uio_t a_uio );
user_size_t uio_curriovlen( uio_t a_uio );
int uio_addiov( uio_t a_uio, user_addr_t a_baseaddr, user_size_t a_length );
int uio_getiov(uio_t a_uio, int a_index, user_addr_t *a_baseaddr_p,
uio_t uio_create( int a_iovcount, off_t a_offset, int a_spacetype, int a_iodirection );
void uio_reset( uio_t a_uio, off_t a_offset, int a_spacetype, int a_iodirection );
uio_t uio_duplicate( uio_t a_uio );
void uio_free( uio_t a_uio );
void uio_update( uio_t a_uio, user_size_t a_count );
user_ssize_t uio_resid( uio_t a_uio );
int uio_iovcnt( uio_t a_uio );
off_t uio_offset( uio_t a_uio );
void uio_setoffset( uio_t a_uio, off_t a_offset );
user_addr_t uio_curriovbase( uio_t a_uio );
user_size_t uio_curriovlen( uio_t a_uio );
int uio_addiov( uio_t a_uio, user_addr_t a_baseaddr, user_size_t a_length );
int uio_getiov(uio_t a_uio, int a_index, user_addr_t *a_baseaddr_p,
user_size_t * a_length_p );
off_t uio_offset( uio_t a_uio );
void uio_setoffset( uio_t a_uio, off_t a_offset );
My rs232 driver read and write exemple :
/*
** Serial read, read one byte from the device
*/
int serial_read(dev_t dev, struct uio *uio, int ioflag)
{
struct device *current;
int len;
int rlen;
char buff[1];
int size= 1;
int i;
*buff = 0;
if (uio_rw(uio) != UIO_READ)
return (EINVAL);
if (minor(dev) >= MAX_PORTS)
return (ENXIO);
current = &serial[minor(dev)];
if (!(current->attached))
return (EBUSY);
len = uio_resid(uio);
rlen = MIN(size, len);
for (i = 0; i <>
off_t uio_offset( uio_t a_uio );
void uio_setoffset( uio_t a_uio, off_t a_offset );
My rs232 driver read and write exemple :
/*
** Serial read, read one byte from the device
*/
int serial_read(dev_t dev, struct uio *uio, int ioflag)
{
struct device *current;
int len;
int rlen;
char buff[1];
int size= 1;
int i;
*buff = 0;
if (uio_rw(uio) != UIO_READ)
return (EINVAL);
if (minor(dev) >= MAX_PORTS)
return (ENXIO);
current = &serial[minor(dev)];
if (!(current->attached))
return (EBUSY);
len = uio_resid(uio);
rlen = MIN(size, len);
for (i = 0; i <>
{
while(((inb(current->port + LSR)) & 0x01) == 0);
buff[i] = inb(current->port + RECEIVER);
}
uiomove(buff, rlen, uio);
printf(DEVICE_NAME " READ\n");
return KERN_SUCCESS;
}
/*
** Serial write, write n bytes to the device
*/
int serial_write(dev_t dev, struct uio *uio, int ioflag)
{
struct device *current;
int len;
char *buff;
int i;
if (uio_rw(uio) != UIO_WRITE)
return (EINVAL);
if (minor(dev) >= MAX_PORTS)
return (ENXIO);
current = &serial[minor(dev)];
if (!(current->attached))
return (EBUSY);
len = uio_resid(uio);
MALLOC(buff, char *, len * sizeof(*buff), M_WAITOK|M_ZERO, M_TEMP);
if ((uiomove(buff, len, uio)) != 0)
{
printf(DEVICE_NAME "KPI error");
return KERN_FAILURE;
}
for (i = 0 ; i < style="text-align: justify;"> {
buff[i] = inb(current->port + RECEIVER);
}
uiomove(buff, rlen, uio);
printf(DEVICE_NAME " READ\n");
return KERN_SUCCESS;
}
/*
** Serial write, write n bytes to the device
*/
int serial_write(dev_t dev, struct uio *uio, int ioflag)
{
struct device *current;
int len;
char *buff;
int i;
if (uio_rw(uio) != UIO_WRITE)
return (EINVAL);
if (minor(dev) >= MAX_PORTS)
return (ENXIO);
current = &serial[minor(dev)];
if (!(current->attached))
return (EBUSY);
len = uio_resid(uio);
MALLOC(buff, char *, len * sizeof(*buff), M_WAITOK|M_ZERO, M_TEMP);
if ((uiomove(buff, len, uio)) != 0)
{
printf(DEVICE_NAME "KPI error");
return KERN_FAILURE;
}
for (i = 0 ; i < style="text-align: justify;"> {
while((inb(current->port + LSR) & 0x20) == 0);
outb(current->port + TRANSMITTER, buff[i]);
}
FREE(buff, M_WAITOK|M_ZERO);
printf(DEVICE_NAME " WRITE\n");
return KERN_SUCCESS;
}
outb(current->port + TRANSMITTER, buff[i]);
}
FREE(buff, M_WAITOK|M_ZERO);
printf(DEVICE_NAME " WRITE\n");
return KERN_SUCCESS;
}

0 comments:
Post a Comment