1433d6423SLionel Sambuc #include <sys/cdefs.h> 2433d6423SLionel Sambuc #include "namespace.h" 3433d6423SLionel Sambuc #include <lib.h> 4433d6423SLionel Sambuc #include <stdarg.h> 5433d6423SLionel Sambuc 6433d6423SLionel Sambuc #include <sys/ioctl.h> 7433d6423SLionel Sambuc #include <minix/i2c.h> 8433d6423SLionel Sambuc #include <string.h> 9433d6423SLionel Sambuc #include <sys/ioccom.h> 10433d6423SLionel Sambuc #include <stdarg.h> 11*ed223591SDavid van Moolenbroek #include <fcntl.h> 12433d6423SLionel Sambuc 13433d6423SLionel Sambuc static void rewrite_i2c_netbsd_to_minix(minix_i2c_ioctl_exec_t *out, 14433d6423SLionel Sambuc i2c_ioctl_exec_t *in); 15433d6423SLionel Sambuc static void rewrite_i2c_minix_to_netbsd(i2c_ioctl_exec_t *out, 16433d6423SLionel Sambuc minix_i2c_ioctl_exec_t *in); 17433d6423SLionel Sambuc 18433d6423SLionel Sambuc static void rewrite_i2c_netbsd_to_minix(minix_i2c_ioctl_exec_t *out, 19433d6423SLionel Sambuc i2c_ioctl_exec_t *in) 20433d6423SLionel Sambuc { 21433d6423SLionel Sambuc memset(out, '\0', sizeof(minix_i2c_ioctl_exec_t)); 22433d6423SLionel Sambuc 23433d6423SLionel Sambuc out->iie_op = in->iie_op; 24433d6423SLionel Sambuc out->iie_addr = in->iie_addr; 25433d6423SLionel Sambuc out->iie_cmdlen = I2C_EXEC_MAX_CMDLEN < in->iie_cmdlen ? 26433d6423SLionel Sambuc I2C_EXEC_MAX_CMDLEN : in->iie_cmdlen; 27433d6423SLionel Sambuc out->iie_buflen = I2C_EXEC_MAX_BUFLEN < in->iie_buflen ? 28433d6423SLionel Sambuc I2C_EXEC_MAX_BUFLEN : in->iie_buflen; 29433d6423SLionel Sambuc 30433d6423SLionel Sambuc if (in->iie_cmdlen > 0 && in->iie_cmd != NULL) { 31433d6423SLionel Sambuc memcpy(out->iie_cmd, in->iie_cmd, in->iie_cmdlen); 32433d6423SLionel Sambuc } 33433d6423SLionel Sambuc 34433d6423SLionel Sambuc if (in->iie_buflen > 0 && in->iie_buf != NULL) { 35433d6423SLionel Sambuc memcpy(out->iie_buf, in->iie_buf, in->iie_buflen); 36433d6423SLionel Sambuc } 37433d6423SLionel Sambuc } 38433d6423SLionel Sambuc 39433d6423SLionel Sambuc static void rewrite_i2c_minix_to_netbsd(i2c_ioctl_exec_t *out, 40433d6423SLionel Sambuc minix_i2c_ioctl_exec_t *in) 41433d6423SLionel Sambuc { 42433d6423SLionel Sambuc /* the only field that changes is iie_buf, everything else is the same */ 4354841c01SEmmanuel Blot if (in->iie_buflen > 0 ) { 44433d6423SLionel Sambuc memcpy(out->iie_buf, in->iie_buf, in->iie_buflen); 45433d6423SLionel Sambuc } 46433d6423SLionel Sambuc } 47433d6423SLionel Sambuc 48*ed223591SDavid van Moolenbroek /* 49*ed223591SDavid van Moolenbroek * Library implementation of FIOCLEX and FIONCLEX. 50*ed223591SDavid van Moolenbroek */ 51*ed223591SDavid van Moolenbroek static int 52*ed223591SDavid van Moolenbroek ioctl_to_setfd(int fd, int mask, int val) 53*ed223591SDavid van Moolenbroek { 54*ed223591SDavid van Moolenbroek int fl; 55*ed223591SDavid van Moolenbroek 56*ed223591SDavid van Moolenbroek if ((fl = fcntl(fd, F_GETFD)) == -1) 57*ed223591SDavid van Moolenbroek return -1; 58*ed223591SDavid van Moolenbroek 59*ed223591SDavid van Moolenbroek fl = (fl & ~mask) | val; 60*ed223591SDavid van Moolenbroek 61*ed223591SDavid van Moolenbroek return fcntl(fd, F_SETFD, fl); 62*ed223591SDavid van Moolenbroek } 63*ed223591SDavid van Moolenbroek 64*ed223591SDavid van Moolenbroek /* 65*ed223591SDavid van Moolenbroek * Library implementation of FIONBIO and FIOASYNC. 66*ed223591SDavid van Moolenbroek */ 67*ed223591SDavid van Moolenbroek static int 68*ed223591SDavid van Moolenbroek ioctl_to_setfl(int fd, void * data, int sfl) 69*ed223591SDavid van Moolenbroek { 70*ed223591SDavid van Moolenbroek int arg, fl; 71*ed223591SDavid van Moolenbroek 72*ed223591SDavid van Moolenbroek arg = *(int *)data; 73*ed223591SDavid van Moolenbroek 74*ed223591SDavid van Moolenbroek if ((fl = fcntl(fd, F_GETFL)) == -1) 75*ed223591SDavid van Moolenbroek return -1; 76*ed223591SDavid van Moolenbroek 77*ed223591SDavid van Moolenbroek if (arg) 78*ed223591SDavid van Moolenbroek fl |= sfl; 79*ed223591SDavid van Moolenbroek else 80*ed223591SDavid van Moolenbroek fl &= ~sfl; 81*ed223591SDavid van Moolenbroek 82*ed223591SDavid van Moolenbroek return fcntl(fd, F_SETFL, fl & ~O_ACCMODE); 83*ed223591SDavid van Moolenbroek } 84*ed223591SDavid van Moolenbroek 85*ed223591SDavid van Moolenbroek /* 86*ed223591SDavid van Moolenbroek * Library implementation of various deprecated IOCTLs. These particular IOCTL 87*ed223591SDavid van Moolenbroek * calls change how the file descriptors behave, and have nothing to do with 88*ed223591SDavid van Moolenbroek * the actual open file. They should therefore be handled by VFS rather than 89*ed223591SDavid van Moolenbroek * individual device drivers. We rewrite them to use fcntl(2) instead here. 90*ed223591SDavid van Moolenbroek */ 91*ed223591SDavid van Moolenbroek static int 92*ed223591SDavid van Moolenbroek ioctl_to_fcntl(int fd, unsigned long request, void * data) 93*ed223591SDavid van Moolenbroek { 94*ed223591SDavid van Moolenbroek switch (request) { 95*ed223591SDavid van Moolenbroek case FIOCLEX: 96*ed223591SDavid van Moolenbroek return ioctl_to_setfd(fd, FD_CLOEXEC, FD_CLOEXEC); 97*ed223591SDavid van Moolenbroek case FIONCLEX: 98*ed223591SDavid van Moolenbroek return ioctl_to_setfd(fd, FD_CLOEXEC, 0); 99*ed223591SDavid van Moolenbroek case FIONBIO: 100*ed223591SDavid van Moolenbroek return ioctl_to_setfl(fd, data, O_NONBLOCK); 101*ed223591SDavid van Moolenbroek case FIOASYNC: 102*ed223591SDavid van Moolenbroek return ioctl_to_setfl(fd, data, O_ASYNC); 103*ed223591SDavid van Moolenbroek case FIOSETOWN: /* XXX TODO */ 104*ed223591SDavid van Moolenbroek case FIOGETOWN: /* XXX TODO */ 105*ed223591SDavid van Moolenbroek default: 106*ed223591SDavid van Moolenbroek errno = ENOTTY; 107*ed223591SDavid van Moolenbroek return -1; 108*ed223591SDavid van Moolenbroek } 109*ed223591SDavid van Moolenbroek } 110*ed223591SDavid van Moolenbroek 111433d6423SLionel Sambuc int ioctl(int fd, unsigned long request, ...) 112433d6423SLionel Sambuc { 113433d6423SLionel Sambuc int r, request_save; 114433d6423SLionel Sambuc message m; 115433d6423SLionel Sambuc vir_bytes addr; 116433d6423SLionel Sambuc void *data; 117433d6423SLionel Sambuc va_list ap; 118433d6423SLionel Sambuc 119433d6423SLionel Sambuc va_start(ap, request); 120433d6423SLionel Sambuc data = va_arg(ap, void *); 121*ed223591SDavid van Moolenbroek va_end(ap); 122433d6423SLionel Sambuc 123433d6423SLionel Sambuc /* 124433d6423SLionel Sambuc * To support compatibility with interfaces on other systems, certain 125433d6423SLionel Sambuc * requests are re-written to flat structures (i.e. without pointers). 126433d6423SLionel Sambuc */ 127433d6423SLionel Sambuc minix_i2c_ioctl_exec_t i2c; 128433d6423SLionel Sambuc 129433d6423SLionel Sambuc request_save = request; 130433d6423SLionel Sambuc 131433d6423SLionel Sambuc switch (request) { 132*ed223591SDavid van Moolenbroek case FIOCLEX: 133*ed223591SDavid van Moolenbroek case FIONCLEX: 134*ed223591SDavid van Moolenbroek case FIONBIO: 135*ed223591SDavid van Moolenbroek case FIOASYNC: 136*ed223591SDavid van Moolenbroek case FIOSETOWN: 137*ed223591SDavid van Moolenbroek case FIOGETOWN: 138*ed223591SDavid van Moolenbroek return ioctl_to_fcntl(fd, request, data); 139*ed223591SDavid van Moolenbroek 140433d6423SLionel Sambuc case I2C_IOCTL_EXEC: 141433d6423SLionel Sambuc rewrite_i2c_netbsd_to_minix(&i2c, data); 142433d6423SLionel Sambuc addr = (vir_bytes) &i2c; 143433d6423SLionel Sambuc request = MINIX_I2C_IOCTL_EXEC; 144433d6423SLionel Sambuc break; 145433d6423SLionel Sambuc default: 146433d6423SLionel Sambuc /* Keep original as-is */ 1475dd8da10SDavid van Moolenbroek addr = (vir_bytes)data; 148433d6423SLionel Sambuc break; 149433d6423SLionel Sambuc } 150433d6423SLionel Sambuc 151433d6423SLionel Sambuc memset(&m, 0, sizeof(m)); 152433d6423SLionel Sambuc m.m_lc_vfs_ioctl.fd = fd; 153433d6423SLionel Sambuc m.m_lc_vfs_ioctl.req = request; 154433d6423SLionel Sambuc m.m_lc_vfs_ioctl.arg = addr; 155433d6423SLionel Sambuc 156433d6423SLionel Sambuc r = _syscall(VFS_PROC_NR, VFS_IOCTL, &m); 157433d6423SLionel Sambuc 158433d6423SLionel Sambuc /* Translate back to original form */ 159433d6423SLionel Sambuc switch (request_save) { 160433d6423SLionel Sambuc case I2C_IOCTL_EXEC: 161433d6423SLionel Sambuc rewrite_i2c_minix_to_netbsd(data, &i2c); 162433d6423SLionel Sambuc break; 163433d6423SLionel Sambuc default: 164433d6423SLionel Sambuc /* Nothing to do */ 165433d6423SLionel Sambuc break; 166433d6423SLionel Sambuc } 167433d6423SLionel Sambuc 168433d6423SLionel Sambuc return r; 169433d6423SLionel Sambuc } 170