Passing device structure to open/read/write operations-reg

Hi,
I wanted to pass device structure which holds the master/slave address, interrrupt number etc., this structure is initialized in Resource Manager init function, I need to pass these values to open, read/write operations. How can I pass these handle to POSIX file operation functions. Please check the following snippet code for an i2c master,

Following is the device structure,
typedef struct {
unsigned reglen;
uintptr_t regbase;
unsigned physbase;
unsigned int base;
unsigned short div;
unsigned short slave;
unsigned int status;
iofunc_attr_t attr;
resmgr_connect_funcs_t connect_funcs;
resmgr_io_funcs_t io_funcs;
dispatch_t *i2c_dispatch;
dispatch_context_t *i2c_ctp;
} mx6x_i2c_dev_t;

Following is the i2c-master RM,

void mx6q_i2c_reset(mx6x_i2c_dev_t *dev)
{
printf(“Addr 0x%x”,dev->regbase);
out16(dev->regbase + I2C_AR, 0);
out16(dev->regbase + I2C_IFDR, 0);
out16(dev->regbase + I2C_I2CR, 0);
out16(dev->regbase + I2C_I2SR, 0);
out16(dev->regbase + I2C_I2DR, 0);

 printf("Addr 0x%x",dev->regbase);

}

int i2c_io_open(resmgr_context_t *ctp, io_open_t *msg, RESMGR_HANDLE_T *handle, void *extra)
{
printf(“I2C driver opened \n”);

mx6q_i2c_reset(dev); [u]//NEED TO HANDLE DEVICE STRUCTURE HERE[/u]

return(iofunc_open_default( ctp, msg, handle, extra ));

}

int mx6q_i2c_init()
{
resmgr_attr_t resmgr_attr;
mx6x_i2c_dev_t *dev;

if (-1 == ThreadCtl(_NTO_TCTL_IO, 0)) {
        perror("ThreadCtl");
        return NULL;
}

dev = malloc(sizeof(mx6x_i2c_dev_t));
if (!dev)
        return NULL;

dev->base	 = MX6X_I2C1_BASE;
dev->div	 = MX6Q_I2C_FRE;
dev->reglen	 = MX6Q_I2C_REGLEN;

dev->regbase = mmap_device_io(dev->reglen, dev->base);
if (dev->regbase == (uintptr_t)MAP_FAILED) {
       perror("mmap_device_io");
	   goto fail;
}

if((dev->i2c_dispatch = dispatch_create()) == NULL){
	fprintf( stderr, "Unable to alloc pool attr \n" );
	return EXIT_FAILURE;
}

memset(&resmgr_attr, 0, sizeof (resmgr_attr));
resmgr_attr.nparts_max = 1;
resmgr_attr.msg_max_size = 2048;

iofunc_attr_init (&dev->attr, S_IFNAM | 0666, 0, 0);

iofunc_func_init (_RESMGR_CONNECT_NFUNCS, &dev->connect_funcs,
                    _RESMGR_IO_NFUNCS, &dev->io_funcs);

  if (resmgr_attach (dev->i2c_dispatch, &resmgr_attr, "/dev/i2c1", _FTYPE_ANY,
                      0, &dev->connect_funcs, &dev->io_funcs, &dev->attr) == -1) {
        printf("Unable to resmgr_attach");
        return EXIT_FAILURE;
}


dev->connect_funcs.open = i2c_io_open;
dev->io_funcs.close_ocb = i2c_io_close;
dev->io_funcs.read = i2c_read;
dev->io_funcs.write = i2c_write;

dev->i2c_ctp = dispatch_context_alloc (dev->i2c_dispatch);

 while (1) {
       if ((dev->i2c_ctp = dispatch_block (dev->i2c_ctp)) == NULL) {
           printf ("Unable to dispatch_block");
           exit (EXIT_FAILURE);
       }
       dispatch_handler (dev->i2c_ctp);
 }
       return (EXIT_SUCCESS);

fail:
free(dev);
return NULL;
}

int main( int argc, char *argv[] )
{
mx6q_i2c_init();
exit( EXIT_SUCCESS );
}

As shared above I need to share “dev” to open, read and write, is there any adapter functions to handle this, since the device base address unable to share to other functions. Please suggest.

Is all this code in the same process?

If it is, then don’t pass it all in function calls, just make a global variable that holds your structure.

mx6x_i2c_dev_t *dev;  // My Global device structure pointer accessible anywhere in my process.

int main( int argc, char *argv[] )
{
mx6q_i2c_init();
exit( EXIT_SUCCESS );
}

You can change your int mx6q_i2c_init() function to no longer have a local dev variable.

Tim

Tim, Thanks for the reply. Temporarily an work around is done and made it work, but what has to be done if it runs in different process, will there be an issue if read/write runs in different threads.

Like to understand from the following code snippet

dev->base = MX6X_I2C1_BASE; (actual base address of I2C as defined in data sheet)
dev->div = MX6Q_I2C_FRE;
dev->reglen = MX6Q_I2C_REGLEN;

dev->regbase = mmap_device_io(dev->reglen, dev->base);
if (dev->regbase == (uintptr_t)MAP_FAILED) {
perror(“mmap_device_io”);
goto fail;
}

But dev->regbase returns different address which is used to access the registers.
As in freescale i.mx6 BSP the I2C driver uses dev->regbase as Base address to access offset registers of I2C controller,
how does it work with different base address to access registers. For eg,
out16(dev->regbase + I2C_AR, 0);
out16(dev->regbase + I2C_IFDR, 0);

There is no issue to read/write in different threads.

Why would you want to put that structure in another process when this process is the one that uses it? That makes no sense.

You should read the doc’s on mmap_device_io(). What gets returned isn’t a physical address. It’s a ‘handle’ from the O/S to that address in the same manner you get a handle to an open file when you are writing to disk.

Tim

Yes Tim, its an physical address but dev->base and dev->regbase are different.if dev->base is 0x021A0000, mmap_device_io returns 0x28000000, unable to predict why it is ?. Even tried to print the address from in-built i2c driver in freescale BSP, it also returns different address

Why would you expect them to be the same? If they were the same value why would there be any need to call mmap_device_io()?

You are telling the O/S where the device IO memory is located (base) and how much there is (reglen) in the absolute memory space of the machine. In return the O/S is giving you back an address (regbase) you can use to access that memory and that address you get back is an address in YOUR processes memory space. When you read/write to regbase the O/S sends that to the address you specified in base.

Tim