1 #include <sys/cdefs.h> 2 #include "namespace.h" 3 #include <lib.h> 4 #include <stdarg.h> 5 6 #include <sys/ioctl.h> 7 #include <minix/i2c.h> 8 #include <string.h> 9 #include <sys/ioccom.h> 10 #include <stdarg.h> 11 #include <fcntl.h> 12 13 static void rewrite_i2c_netbsd_to_minix(minix_i2c_ioctl_exec_t *out, 14 i2c_ioctl_exec_t *in); 15 static void rewrite_i2c_minix_to_netbsd(i2c_ioctl_exec_t *out, 16 minix_i2c_ioctl_exec_t *in); 17 18 static void rewrite_i2c_netbsd_to_minix(minix_i2c_ioctl_exec_t *out, 19 i2c_ioctl_exec_t *in) 20 { 21 memset(out, '\0', sizeof(minix_i2c_ioctl_exec_t)); 22 23 out->iie_op = in->iie_op; 24 out->iie_addr = in->iie_addr; 25 out->iie_cmdlen = I2C_EXEC_MAX_CMDLEN < in->iie_cmdlen ? 26 I2C_EXEC_MAX_CMDLEN : in->iie_cmdlen; 27 out->iie_buflen = I2C_EXEC_MAX_BUFLEN < in->iie_buflen ? 28 I2C_EXEC_MAX_BUFLEN : in->iie_buflen; 29 30 if (in->iie_cmdlen > 0 && in->iie_cmd != NULL) { 31 memcpy(out->iie_cmd, in->iie_cmd, in->iie_cmdlen); 32 } 33 34 if (in->iie_buflen > 0 && in->iie_buf != NULL) { 35 memcpy(out->iie_buf, in->iie_buf, in->iie_buflen); 36 } 37 } 38 39 static void rewrite_i2c_minix_to_netbsd(i2c_ioctl_exec_t *out, 40 minix_i2c_ioctl_exec_t *in) 41 { 42 /* the only field that changes is iie_buf, everything else is the same */ 43 if (in->iie_buflen > 0 ) { 44 memcpy(out->iie_buf, in->iie_buf, in->iie_buflen); 45 } 46 } 47 48 /* 49 * Library implementation of FIOCLEX and FIONCLEX. 50 */ 51 static int 52 ioctl_to_setfd(int fd, int mask, int val) 53 { 54 int fl; 55 56 if ((fl = fcntl(fd, F_GETFD)) == -1) 57 return -1; 58 59 fl = (fl & ~mask) | val; 60 61 return fcntl(fd, F_SETFD, fl); 62 } 63 64 /* 65 * Library implementation of FIONBIO and FIOASYNC. 66 */ 67 static int 68 ioctl_to_setfl(int fd, void * data, int sfl) 69 { 70 int arg, fl; 71 72 arg = *(int *)data; 73 74 if ((fl = fcntl(fd, F_GETFL)) == -1) 75 return -1; 76 77 if (arg) 78 fl |= sfl; 79 else 80 fl &= ~sfl; 81 82 return fcntl(fd, F_SETFL, fl & ~O_ACCMODE); 83 } 84 85 /* 86 * Library implementation of various deprecated IOCTLs. These particular IOCTL 87 * calls change how the file descriptors behave, and have nothing to do with 88 * the actual open file. They should therefore be handled by VFS rather than 89 * individual device drivers. We rewrite them to use fcntl(2) instead here. 90 */ 91 static int 92 ioctl_to_fcntl(int fd, unsigned long request, void * data) 93 { 94 switch (request) { 95 case FIOCLEX: 96 return ioctl_to_setfd(fd, FD_CLOEXEC, FD_CLOEXEC); 97 case FIONCLEX: 98 return ioctl_to_setfd(fd, FD_CLOEXEC, 0); 99 case FIONBIO: 100 return ioctl_to_setfl(fd, data, O_NONBLOCK); 101 case FIOASYNC: 102 return ioctl_to_setfl(fd, data, O_ASYNC); 103 case FIOSETOWN: /* XXX TODO */ 104 case FIOGETOWN: /* XXX TODO */ 105 default: 106 errno = ENOTTY; 107 return -1; 108 } 109 } 110 111 int ioctl(int fd, unsigned long request, ...) 112 { 113 int r, request_save; 114 message m; 115 vir_bytes addr; 116 void *data; 117 va_list ap; 118 119 va_start(ap, request); 120 data = va_arg(ap, void *); 121 va_end(ap); 122 123 /* 124 * To support compatibility with interfaces on other systems, certain 125 * requests are re-written to flat structures (i.e. without pointers). 126 */ 127 minix_i2c_ioctl_exec_t i2c; 128 129 request_save = request; 130 131 switch (request) { 132 case FIOCLEX: 133 case FIONCLEX: 134 case FIONBIO: 135 case FIOASYNC: 136 case FIOSETOWN: 137 case FIOGETOWN: 138 return ioctl_to_fcntl(fd, request, data); 139 140 case I2C_IOCTL_EXEC: 141 rewrite_i2c_netbsd_to_minix(&i2c, data); 142 addr = (vir_bytes) &i2c; 143 request = MINIX_I2C_IOCTL_EXEC; 144 break; 145 default: 146 /* Keep original as-is */ 147 addr = (vir_bytes)data; 148 break; 149 } 150 151 memset(&m, 0, sizeof(m)); 152 m.m_lc_vfs_ioctl.fd = fd; 153 m.m_lc_vfs_ioctl.req = request; 154 m.m_lc_vfs_ioctl.arg = addr; 155 156 r = _syscall(VFS_PROC_NR, VFS_IOCTL, &m); 157 158 /* Translate back to original form */ 159 switch (request_save) { 160 case I2C_IOCTL_EXEC: 161 rewrite_i2c_minix_to_netbsd(data, &i2c); 162 break; 163 default: 164 /* Nothing to do */ 165 break; 166 } 167 168 return r; 169 } 170