/** * Replacement structures for iofunc_ocb_t and iofunc_attr_t * "The iofunc_ocb_t structure is an Open Control Block, * a block of data that's established by a resource manager * during its handling of the client's open() function. " * Note: The Resource Manager example that shows how to extend the ocb structure * creates a list ocb structures but I don't think we need this. * We create an ocb structure for every call to fileOpen * */ struct sw_ocb { iofunc_ocb_t hdr; /* Must be first in structure field list */ int channel; /* Software channel information */ }; /* The iofunc_attr_t structure describes the attributes of the device * that's associated with a resource manager. * There is one sw_device_attr structure per board */ struct sw_device_attr { iofunc_attr_t attr; /* must always be first in structure field list */ void* pDevice; /* pointer to SpaceWire pci mk2 device */ }; /** * The function called to handle a read call on the device. * * @param ctp a pointer to the resource manager's context information * @param msg a pointer to the read message received by the resource manager * @param ocb a pointer to the open control block for the resource * * @return a status value indicating if the read was successfully performed */ int star_pci_io_read(resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb) { int status; int nparts; void* pDevice; /* Pointer to pci device structure for low level driver */ U32 wordsRead = 0; /* amount of data read: returned from readFile */ U8 channel; /* hardware channel to read from */ void *pBuffer; /* buffer to read into */ U32 wordsize; /* size of data to read in a single call */ /* Check that the message can be accessed for reading */ status = iofunc_read_verify(ctp, msg, ocb, NULL); if (status != EOK) { printf("\nERROR: star_pci_io_read, iofunc_read_verify returned an error"); fflush(stdout); return status; } /* Make sure no special xtypes are specified in the command*/ if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) { printf("\nERROR: star_pci_io_read, xtypes are specified in the command"); fflush(stdout); return (ENOSYS); } /* Get handle to sw device structure required by low level driver */ pDevice = ocb->hdr.attr->pDevice; /* Need to get the hardware channel, the pointer to the buffer and the data size * for the low level writeFile driver function*/ channel = ocb->channel; wordsize = msg->i.nbytes / 4; /* From QNX documentation: "The commented-out declaration for data in io_write_t * structure indicates that nbytes bytes of data immediately follow the io_write_t * structure. */ pBuffer = (void *)(msg + 1); /* Unlock the attributes so multiple threads can call ioctl/read/write */ iofunc_attr_unlock(&ocb->hdr.attr->attr); /* Low level driver read data function */ wordsRead = readFile(pDevice, channel, pBuffer, wordsize); /* Lock the attributes */ iofunc_attr_lock(&ocb->hdr.attr->attr); if (wordsRead == 0) { /* no data was read */ _IO_SET_READ_NBYTES(ctp, 0); nparts = 0; printf("\nERROR: star_pci_io_read, wordsRead == 0"); fflush(stdout); } else { /* set up the return data IOV */ SETIOV(ctp->iov, pBuffer, wordsRead * 4); /* set up the number of bytes (returned by client's read()) */ _IO_SET_READ_NBYTES(ctp, wordsRead * 4); nparts = 1; /* Mark the access time as invalid as we just accessed it */ /* Complex dereferencing * Might want to split into the following to retrieve the io structures: * iofunc_ocb_t ocb_t = ocb->hdr; * iofunc_attr_t* attr_t3 = &ocb->hdr.attr->attr; */ ocb->hdr.attr->attr.flags |= IOFUNC_ATTR_ATIME; } /* Return the number of IOVs in the array */ return _RESMGR_NPARTS(nparts); }