1 /* $NetBSD: netbsd32_ioctl.c,v 1.5 1999/12/30 15:40:45 eeh Exp $ */ 2 3 /* 4 * Copyright (c) 1998 Matthew R. Green 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* 32 * handle ioctl conversions from netbsd32 -> sparc64 33 */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/audioio.h> 38 #include <sys/disklabel.h> 39 #include <sys/dkio.h> 40 #include <sys/malloc.h> 41 #include <sys/proc.h> 42 #include <sys/sockio.h> 43 #include <sys/socket.h> 44 #include <sys/ttycom.h> 45 #include <sys/mount.h> 46 #include <sys/syscallargs.h> 47 48 #include <machine/fbio.h> 49 #include <machine/openpromio.h> 50 51 #include <net/if.h> 52 #include <net/route.h> 53 54 #include <netinet/in.h> 55 #include <netinet/in_var.h> 56 #include <netinet/igmp.h> 57 #include <netinet/igmp_var.h> 58 #include <netinet/ip_mroute.h> 59 60 #include <compat/netbsd32/netbsd32.h> 61 #include <compat/netbsd32/netbsd32_ioctl.h> 62 #include <compat/netbsd32/netbsd32_syscallargs.h> 63 64 void 65 netbsd32_to_fbcmap(s32p, p) 66 struct netbsd32_fbcmap *s32p; 67 struct fbcmap *p; 68 { 69 70 p->index = s32p->index; 71 p->count = s32p->count; 72 p->red = (u_char *)(u_long)s32p->red; 73 p->green = (u_char *)(u_long)s32p->green; 74 p->blue = (u_char *)(u_long)s32p->blue; 75 } 76 77 void 78 netbsd32_to_fbcursor(s32p, p) 79 struct netbsd32_fbcursor *s32p; 80 struct fbcursor *p; 81 { 82 83 p->set = s32p->set; 84 p->enable = s32p->enable; 85 p->pos = s32p->pos; 86 p->hot = s32p->hot; 87 netbsd32_to_fbcmap(&s32p->cmap, &p->cmap); 88 p->size = s32p->size; 89 p->image = (char *)(u_long)s32p->image; 90 p->mask = (char *)(u_long)s32p->mask; 91 } 92 93 void 94 netbsd32_to_opiocdesc(s32p, p) 95 struct netbsd32_opiocdesc *s32p; 96 struct opiocdesc *p; 97 { 98 99 p->op_nodeid = s32p->op_nodeid; 100 p->op_namelen = s32p->op_namelen; 101 p->op_name = (char *)(u_long)s32p->op_name; 102 p->op_buflen = s32p->op_buflen; 103 p->op_buf = (char *)(u_long)s32p->op_buf; 104 } 105 106 void 107 netbsd32_to_partinfo(s32p, p) 108 struct netbsd32_partinfo *s32p; 109 struct partinfo *p; 110 { 111 112 p->disklab = (struct disklabel *)(u_long)s32p->disklab; 113 p->part = (struct partition *)(u_long)s32p->part; 114 } 115 116 void 117 netbsd32_to_format_op(s32p, p) 118 struct netbsd32_format_op *s32p; 119 struct format_op *p; 120 { 121 122 p->df_buf = (char *)(u_long)s32p->df_buf; 123 p->df_count = s32p->df_count; 124 p->df_startblk = s32p->df_startblk; 125 memcpy(p->df_reg, s32p->df_reg, sizeof(s32p->df_reg)); 126 } 127 128 #if 0 /* XXX see below */ 129 void 130 netbsd32_to_ifreq(s32p, p, cmd) 131 struct netbsd32_ifreq *s32p; 132 struct ifreq *p; 133 u_long cmd; /* XXX unused yet */ 134 { 135 136 /* 137 * XXX 138 * struct ifreq says the same, but sometimes the ifr_data 139 * union member needs to be converted to 64 bits... this 140 * is very driver specific and so we ignore it for now.. 141 */ 142 memcpy(p, s32p, sizeof *s32p); 143 } 144 #endif 145 146 void 147 netbsd32_to_ifconf(s32p, p) 148 struct netbsd32_ifconf *s32p; 149 struct ifconf *p; 150 { 151 152 p->ifc_len = s32p->ifc_len; 153 /* ifc_buf & ifc_req are the same size so this works */ 154 p->ifc_buf = (caddr_t)(u_long)s32p->ifc_buf; 155 } 156 157 void 158 netbsd32_to_ifmediareq(s32p, p) 159 struct netbsd32_ifmediareq *s32p; 160 struct ifmediareq *p; 161 { 162 163 memcpy(p, s32p, sizeof *s32p); 164 p->ifm_ulist = (int *)(u_long)s32p->ifm_ulist; 165 } 166 167 void 168 netbsd32_to_ifdrv(s32p, p) 169 struct netbsd32_ifdrv *s32p; 170 struct ifdrv *p; 171 { 172 173 memcpy(p, s32p, sizeof *s32p); 174 p->ifd_data = (void *)(u_long)s32p->ifd_data; 175 } 176 177 void 178 netbsd32_to_sioc_vif_req(s32p, p) 179 struct netbsd32_sioc_vif_req *s32p; 180 struct sioc_vif_req *p; 181 { 182 183 p->vifi = s32p->vifi; 184 p->icount = (u_long)s32p->icount; 185 p->ocount = (u_long)s32p->ocount; 186 p->ibytes = (u_long)s32p->ibytes; 187 p->obytes = (u_long)s32p->obytes; 188 } 189 190 void 191 netbsd32_to_sioc_sg_req(s32p, p) 192 struct netbsd32_sioc_sg_req *s32p; 193 struct sioc_sg_req *p; 194 { 195 196 p->src = s32p->src; 197 p->grp = s32p->grp; 198 p->pktcnt = (u_long)s32p->pktcnt; 199 p->bytecnt = (u_long)s32p->bytecnt; 200 p->wrong_if = (u_long)s32p->wrong_if; 201 } 202 203 /* 204 * handle ioctl conversions from sparc64 -> netbsd32 205 */ 206 207 void 208 netbsd32_from_fbcmap(p, s32p) 209 struct fbcmap *p; 210 struct netbsd32_fbcmap *s32p; 211 { 212 213 s32p->index = p->index; 214 s32p->count = p->count; 215 /* filled in */ 216 #if 0 217 s32p->red = (netbsd32_u_charp)p->red; 218 s32p->green = (netbsd32_u_charp)p->green; 219 s32p->blue = (netbsd32_u_charp)p->blue; 220 #endif 221 } 222 223 void 224 netbsd32_from_fbcursor(p, s32p) 225 struct fbcursor *p; 226 struct netbsd32_fbcursor *s32p; 227 { 228 229 s32p->set = p->set; 230 s32p->enable = p->enable; 231 s32p->pos = p->pos; 232 s32p->hot = p->hot; 233 netbsd32_from_fbcmap(&p->cmap, &s32p->cmap); 234 s32p->size = p->size; 235 /* filled in */ 236 #if 0 237 s32p->image = (netbsd32_charp)p->image; 238 s32p->mask = (netbsd32_charp)p->mask; 239 #endif 240 } 241 242 void 243 netbsd32_from_opiocdesc(p, s32p) 244 struct opiocdesc *p; 245 struct netbsd32_opiocdesc *s32p; 246 { 247 248 s32p->op_nodeid = p->op_nodeid; 249 s32p->op_namelen = p->op_namelen; 250 s32p->op_name = (netbsd32_charp)(u_long)p->op_name; 251 s32p->op_buflen = p->op_buflen; 252 s32p->op_buf = (netbsd32_charp)(u_long)p->op_buf; 253 } 254 255 void 256 netbsd32_from_format_op(p, s32p) 257 struct format_op *p; 258 struct netbsd32_format_op *s32p; 259 { 260 261 /* filled in */ 262 #if 0 263 s32p->df_buf = (netbsd32_charp)p->df_buf; 264 #endif 265 s32p->df_count = p->df_count; 266 s32p->df_startblk = p->df_startblk; 267 memcpy(s32p->df_reg, p->df_reg, sizeof(p->df_reg)); 268 } 269 270 #if 0 /* XXX see below */ 271 void 272 netbsd32_from_ifreq(p, s32p, cmd) 273 struct ifreq *p; 274 struct netbsd32_ifreq *s32p; 275 u_long cmd; /* XXX unused yet */ 276 { 277 278 /* 279 * XXX 280 * struct ifreq says the same, but sometimes the ifr_data 281 * union member needs to be converted to 64 bits... this 282 * is very driver specific and so we ignore it for now.. 283 */ 284 *s32p = *p; 285 } 286 #endif 287 288 void 289 netbsd32_from_ifconf(p, s32p) 290 struct ifconf *p; 291 struct netbsd32_ifconf *s32p; 292 { 293 294 s32p->ifc_len = p->ifc_len; 295 /* ifc_buf & ifc_req are the same size so this works */ 296 s32p->ifc_buf = (netbsd32_caddr_t)(u_long)p->ifc_buf; 297 } 298 299 void 300 netbsd32_from_ifmediareq(p, s32p) 301 struct ifmediareq *p; 302 struct netbsd32_ifmediareq *s32p; 303 { 304 305 memcpy(s32p, p, sizeof *p); 306 /* filled in? */ 307 #if 0 308 s32p->ifm_ulist = (netbsd32_intp_t)p->ifm_ulist; 309 #endif 310 } 311 312 void 313 netbsd32_from_ifdrv(p, s32p) 314 struct ifdrv *p; 315 struct netbsd32_ifdrv *s32p; 316 { 317 318 memcpy(s32p, p, sizeof *p); 319 /* filled in? */ 320 #if 0 321 s32p->ifm_data = (netbsd32_u_longp_t)p->ifm_data; 322 #endif 323 } 324 325 void 326 netbsd32_from_sioc_vif_req(p, s32p) 327 struct sioc_vif_req *p; 328 struct netbsd32_sioc_vif_req *s32p; 329 { 330 331 s32p->vifi = p->vifi; 332 s32p->icount = (netbsd32_u_long)p->icount; 333 s32p->ocount = (netbsd32_u_long)p->ocount; 334 s32p->ibytes = (netbsd32_u_long)p->ibytes; 335 s32p->obytes = (netbsd32_u_long)p->obytes; 336 } 337 338 void 339 netbsd32_from_sioc_sg_req(p, s32p) 340 struct sioc_sg_req *p; 341 struct netbsd32_sioc_sg_req *s32p; 342 { 343 344 s32p->src = p->src; 345 s32p->grp = p->grp; 346 s32p->pktcnt = (netbsd32_u_long)p->pktcnt; 347 s32p->bytecnt = (netbsd32_u_long)p->bytecnt; 348 s32p->wrong_if = (netbsd32_u_long)p->wrong_if; 349 } 350 351 352 /* 353 * main ioctl syscall. 354 * 355 * ok, here we are in the biggy. we have to do fix ups depending 356 * on the ioctl command before and afterwards. 357 */ 358 int 359 netbsd32_ioctl(p, v, retval) 360 struct proc *p; 361 void *v; 362 register_t *retval; 363 { 364 struct netbsd32_ioctl_args /* { 365 syscallarg(int) fd; 366 syscallarg(netbsd32_u_long) com; 367 syscallarg(netbsd32_voidp) data; 368 } */ *uap = v; 369 struct sys_ioctl_args ua; 370 void *data = NULL; 371 int rv; 372 373 /* 374 * we need to translate some commands (_IOW) before calling sys_ioctl, 375 * some after (_IOR), and some both (_IOWR). 376 */ 377 #if 0 378 { 379 char *dirs[8] = { "NONE!", "VOID", "OUT", "VOID|OUT!", "IN", "VOID|IN!", 380 "INOUT", "VOID|IN|OUT!" }; 381 382 printf("netbsd32_ioctl(%d, %x, %x): %s group %c base %d len %d\n", 383 SCARG(uap, fd), SCARG(uap, com), SCARG(uap, data), 384 dirs[((SCARG(uap, com) & IOC_DIRMASK)>>29)], 385 IOCGROUP(SCARG(uap, com)), IOCBASECMD(SCARG(uap, com)), 386 IOCPARM_LEN(SCARG(uap, com))); 387 } 388 #endif 389 390 /* we define some handy macros here... */ 391 #define IOCTL_STRUCT_CONV_TO(type) \ 392 data = malloc(sizeof(struct type), M_TEMP, M_WAITOK); \ 393 __CONCAT(netbsd32_to_, type)((struct __CONCAT(netbsd32_, type) *) \ 394 (u_long)SCARG(uap, data), data) 395 396 #define IOCTL_STRUCT_CONV_CMD_TO(type, cmd) \ 397 data = malloc(sizeof(struct type), M_TEMP, M_WAITOK); \ 398 __CONCAT(netbsd32_to_, type)((struct __CONCAT(netbsd32_, type) *) \ 399 (u_long)SCARG(uap, data), data, cmd) 400 401 #define IOCTL_STRUCT_CONV_FROM(type) \ 402 __CONCAT(netbsd32_from_, type)(data, \ 403 (struct __CONCAT(netbsd32_, type) *) (u_long)SCARG(uap, data)) 404 405 #define IOCTL_STRUCT_CONV_CMD_FROM(type, cmd) \ 406 __CONCAT(netbsd32_from_, type)(data, \ 407 (struct __CONCAT(netbsd32_, type) *) (u_long)SCARG(uap, data), cmd) 408 409 /* 410 * convert various structures, pointers, and other objects that 411 * change size from 32 bit -> 64 bit, for all ioctl commands. 412 */ 413 switch (SCARG(uap, com)) { 414 case FBIOPUTCMAP: 415 case FBIOGETCMAP: 416 IOCTL_STRUCT_CONV_TO(fbcmap); 417 break; 418 419 case FBIOSCURSOR: 420 case FBIOGCURSOR: 421 IOCTL_STRUCT_CONV_TO(fbcursor); 422 break; 423 424 case OPIOCGET: 425 case OPIOCSET: 426 case OPIOCNEXTPROP: 427 IOCTL_STRUCT_CONV_TO(opiocdesc); 428 break; 429 430 case DIOCGPART: 431 IOCTL_STRUCT_CONV_TO(partinfo); 432 break; 433 434 case DIOCRFORMAT: 435 case DIOCWFORMAT: 436 IOCTL_STRUCT_CONV_TO(format_op); 437 break; 438 439 /* 440 * only a few ifreq syscalls need conversion and those are 441 * all driver specific... XXX 442 */ 443 #if 0 444 case SIOCGADDRROM: 445 case SIOCGCHIPID: 446 case SIOCSIFADDR: 447 case OSIOCGIFADDR: 448 case SIOCGIFADDR: 449 case SIOCSIFDSTADDR: 450 case OSIOCGIFDSTADDR: 451 case SIOCGIFDSTADDR: 452 case SIOCSIFFLAGS: 453 case SIOCGIFFLAGS: 454 case OSIOCGIFBRDADDR: 455 case SIOCGIFBRDADDR: 456 case SIOCSIFBRDADDR: 457 case OSIOCGIFNETMASK: 458 case SIOCGIFNETMASK: 459 case SIOCSIFNETMASK: 460 case SIOCGIFMETRIC: 461 case SIOCSIFMETRIC: 462 case SIOCDIFADDR: 463 case SIOCADDMULTI: 464 case SIOCDELMULTI: 465 case SIOCSIFMEDIA: 466 case SIOCSIFMTU: 467 case SIOCGIFMTU: 468 case SIOCSIFASYNCMAP: 469 case SIOCGIFASYNCMAP: 470 /* case BIOCGETIF: READ ONLY */ 471 case BIOCSETIF: 472 case SIOCPHASE1: 473 case SIOCPHASE2: 474 IOCTL_STRUCT_CONV_CMD_TO(ifreq, SCARG(uap, cmd)); 475 break; 476 #endif 477 478 case OSIOCGIFCONF: 479 case SIOCGIFCONF: 480 IOCTL_STRUCT_CONV_TO(ifconf); 481 break; 482 483 case SIOCGIFMEDIA: 484 IOCTL_STRUCT_CONV_TO(ifmediareq); 485 break; 486 487 case SIOCSDRVSPEC: 488 IOCTL_STRUCT_CONV_TO(ifdrv); 489 break; 490 491 case SIOCGETVIFCNT: 492 IOCTL_STRUCT_CONV_TO(sioc_vif_req); 493 break; 494 495 case SIOCGETSGCNT: 496 IOCTL_STRUCT_CONV_TO(sioc_sg_req); 497 break; 498 499 } 500 501 /* 502 * if we malloced a new data segment, plug it into the 503 * syscall args, otherwise copy incoming one as a void 504 * pointer. also copy the rest of the syscall args... 505 */ 506 if (data) 507 SCARG(&ua, data) = data; 508 else 509 NETBSD32TOP_UAP(data, void); 510 NETBSD32TO64_UAP(fd); 511 NETBSD32TOX_UAP(com, u_long); 512 513 /* call the real ioctl */ 514 rv = sys_ioctl(p, &ua, retval); 515 516 /* 517 * convert _back_ to 32 bit the results of the command. 518 */ 519 switch (SCARG(uap, com)) { 520 case FBIOGETCMAP: 521 IOCTL_STRUCT_CONV_FROM(fbcmap); 522 break; 523 524 case FBIOGCURSOR: 525 IOCTL_STRUCT_CONV_FROM(fbcursor); 526 break; 527 528 case OPIOCGET: 529 case OPIOCNEXTPROP: 530 IOCTL_STRUCT_CONV_FROM(opiocdesc); 531 break; 532 533 case DIOCRFORMAT: 534 case DIOCWFORMAT: 535 IOCTL_STRUCT_CONV_FROM(format_op); 536 break; 537 538 /* 539 * only a few ifreq syscalls need conversion and those are 540 * all driver specific... XXX 541 */ 542 #if 0 543 case SIOCGADDRROM: 544 case SIOCGCHIPID: 545 case SIOCSIFADDR: 546 case OSIOCGIFADDR: 547 case SIOCGIFADDR: 548 case SIOCSIFDSTADDR: 549 case OSIOCGIFDSTADDR: 550 case SIOCGIFDSTADDR: 551 case SIOCSIFFLAGS: 552 case SIOCGIFFLAGS: 553 case OSIOCGIFBRDADDR: 554 case SIOCGIFBRDADDR: 555 case SIOCSIFBRDADDR: 556 case OSIOCGIFNETMASK: 557 case SIOCGIFNETMASK: 558 case SIOCSIFNETMASK: 559 case SIOCGIFMETRIC: 560 case SIOCSIFMETRIC: 561 case SIOCDIFADDR: 562 case SIOCADDMULTI: 563 case SIOCDELMULTI: 564 case SIOCSIFMEDIA: 565 case SIOCSIFMTU: 566 case SIOCGIFMTU: 567 case SIOCSIFASYNCMAP: 568 case SIOCGIFASYNCMAP: 569 /* case BIOCGETIF: READ ONLY */ 570 case BIOCSETIF: 571 case SIOCPHASE1: 572 case SIOCPHASE2: 573 IOCTL_STRUCT_CONV_CMD_FROM(ifreq, SCARG(uap, cmd)); 574 break; 575 #endif 576 577 case OSIOCGIFCONF: 578 case SIOCGIFCONF: 579 IOCTL_STRUCT_CONV_FROM(ifconf); 580 break; 581 582 case SIOCGIFMEDIA: 583 IOCTL_STRUCT_CONV_FROM(ifmediareq); 584 break; 585 586 case SIOCSDRVSPEC: 587 IOCTL_STRUCT_CONV_FROM(ifdrv); 588 break; 589 590 case SIOCGETVIFCNT: 591 IOCTL_STRUCT_CONV_FROM(sioc_vif_req); 592 break; 593 594 case SIOCGETSGCNT: 595 IOCTL_STRUCT_CONV_FROM(sioc_sg_req); 596 break; 597 } 598 599 /* if we malloced data, free it here */ 600 if (data) 601 free(data, M_TEMP); 602 603 /* done! */ 604 return (rv); 605 } 606