1*433d6423SLionel Sambuc #include <sys/cdefs.h> 2*433d6423SLionel Sambuc #include "namespace.h" 3*433d6423SLionel Sambuc #include <lib.h> 4*433d6423SLionel Sambuc #include <stdarg.h> 5*433d6423SLionel Sambuc 6*433d6423SLionel Sambuc #include <sys/ioctl.h> 7*433d6423SLionel Sambuc #include <minix/i2c.h> 8*433d6423SLionel Sambuc #include <string.h> 9*433d6423SLionel Sambuc #include <sys/ioccom.h> 10*433d6423SLionel Sambuc #include <stdarg.h> 11*433d6423SLionel Sambuc 12*433d6423SLionel Sambuc static void rewrite_i2c_netbsd_to_minix(minix_i2c_ioctl_exec_t *out, 13*433d6423SLionel Sambuc i2c_ioctl_exec_t *in); 14*433d6423SLionel Sambuc static void rewrite_i2c_minix_to_netbsd(i2c_ioctl_exec_t *out, 15*433d6423SLionel Sambuc minix_i2c_ioctl_exec_t *in); 16*433d6423SLionel Sambuc 17*433d6423SLionel Sambuc static void rewrite_i2c_netbsd_to_minix(minix_i2c_ioctl_exec_t *out, 18*433d6423SLionel Sambuc i2c_ioctl_exec_t *in) 19*433d6423SLionel Sambuc { 20*433d6423SLionel Sambuc memset(out, '\0', sizeof(minix_i2c_ioctl_exec_t)); 21*433d6423SLionel Sambuc 22*433d6423SLionel Sambuc out->iie_op = in->iie_op; 23*433d6423SLionel Sambuc out->iie_addr = in->iie_addr; 24*433d6423SLionel Sambuc out->iie_cmdlen = I2C_EXEC_MAX_CMDLEN < in->iie_cmdlen ? 25*433d6423SLionel Sambuc I2C_EXEC_MAX_CMDLEN : in->iie_cmdlen; 26*433d6423SLionel Sambuc out->iie_buflen = I2C_EXEC_MAX_BUFLEN < in->iie_buflen ? 27*433d6423SLionel Sambuc I2C_EXEC_MAX_BUFLEN : in->iie_buflen; 28*433d6423SLionel Sambuc 29*433d6423SLionel Sambuc if (in->iie_cmdlen > 0 && in->iie_cmd != NULL) { 30*433d6423SLionel Sambuc memcpy(out->iie_cmd, in->iie_cmd, in->iie_cmdlen); 31*433d6423SLionel Sambuc } 32*433d6423SLionel Sambuc 33*433d6423SLionel Sambuc if (in->iie_buflen > 0 && in->iie_buf != NULL) { 34*433d6423SLionel Sambuc memcpy(out->iie_buf, in->iie_buf, in->iie_buflen); 35*433d6423SLionel Sambuc } 36*433d6423SLionel Sambuc } 37*433d6423SLionel Sambuc 38*433d6423SLionel Sambuc static void rewrite_i2c_minix_to_netbsd(i2c_ioctl_exec_t *out, 39*433d6423SLionel Sambuc minix_i2c_ioctl_exec_t *in) 40*433d6423SLionel Sambuc { 41*433d6423SLionel Sambuc /* the only field that changes is iie_buf, everything else is the same */ 42*433d6423SLionel Sambuc if (in->iie_buflen > 0 && in->iie_buf != NULL) { 43*433d6423SLionel Sambuc memcpy(out->iie_buf, in->iie_buf, in->iie_buflen); 44*433d6423SLionel Sambuc } 45*433d6423SLionel Sambuc } 46*433d6423SLionel Sambuc 47*433d6423SLionel Sambuc int ioctl(int fd, unsigned long request, ...) 48*433d6423SLionel Sambuc { 49*433d6423SLionel Sambuc int r, request_save; 50*433d6423SLionel Sambuc message m; 51*433d6423SLionel Sambuc vir_bytes addr; 52*433d6423SLionel Sambuc void *data; 53*433d6423SLionel Sambuc va_list ap; 54*433d6423SLionel Sambuc 55*433d6423SLionel Sambuc va_start(ap, request); 56*433d6423SLionel Sambuc data = va_arg(ap, void *); 57*433d6423SLionel Sambuc 58*433d6423SLionel Sambuc /* 59*433d6423SLionel Sambuc * To support compatibility with interfaces on other systems, certain 60*433d6423SLionel Sambuc * requests are re-written to flat structures (i.e. without pointers). 61*433d6423SLionel Sambuc */ 62*433d6423SLionel Sambuc minix_i2c_ioctl_exec_t i2c; 63*433d6423SLionel Sambuc 64*433d6423SLionel Sambuc request_save = request; 65*433d6423SLionel Sambuc 66*433d6423SLionel Sambuc switch (request) { 67*433d6423SLionel Sambuc case I2C_IOCTL_EXEC: 68*433d6423SLionel Sambuc rewrite_i2c_netbsd_to_minix(&i2c, data); 69*433d6423SLionel Sambuc addr = (vir_bytes) &i2c; 70*433d6423SLionel Sambuc request = MINIX_I2C_IOCTL_EXEC; 71*433d6423SLionel Sambuc break; 72*433d6423SLionel Sambuc default: 73*433d6423SLionel Sambuc /* Keep original as-is */ 74*433d6423SLionel Sambuc addr = data; 75*433d6423SLionel Sambuc break; 76*433d6423SLionel Sambuc } 77*433d6423SLionel Sambuc 78*433d6423SLionel Sambuc memset(&m, 0, sizeof(m)); 79*433d6423SLionel Sambuc m.m_lc_vfs_ioctl.fd = fd; 80*433d6423SLionel Sambuc m.m_lc_vfs_ioctl.req = request; 81*433d6423SLionel Sambuc m.m_lc_vfs_ioctl.arg = addr; 82*433d6423SLionel Sambuc 83*433d6423SLionel Sambuc r = _syscall(VFS_PROC_NR, VFS_IOCTL, &m); 84*433d6423SLionel Sambuc 85*433d6423SLionel Sambuc /* Translate back to original form */ 86*433d6423SLionel Sambuc switch (request_save) { 87*433d6423SLionel Sambuc case I2C_IOCTL_EXEC: 88*433d6423SLionel Sambuc rewrite_i2c_minix_to_netbsd(data, &i2c); 89*433d6423SLionel Sambuc break; 90*433d6423SLionel Sambuc default: 91*433d6423SLionel Sambuc /* Nothing to do */ 92*433d6423SLionel Sambuc break; 93*433d6423SLionel Sambuc } 94*433d6423SLionel Sambuc 95*433d6423SLionel Sambuc va_end(ap); 96*433d6423SLionel Sambuc 97*433d6423SLionel Sambuc return r; 98*433d6423SLionel Sambuc } 99