1 2 #include "inc.h" 3 4 #include <dev/pci/pciio.h> 5 6 #include <minix/fb.h> 7 #include <minix/i2c.h> 8 #include <minix/keymap.h> 9 #include <minix/sound.h> 10 11 #include <sys/fcntl.h> 12 #include <sys/ioctl.h> 13 #include <sys/kbdio.h> 14 #include <sys/termios.h> 15 #include <sys/time.h> 16 17 const char * 18 char_ioctl_name(unsigned long req) 19 { 20 21 switch (req) { 22 NAME(MINIX_I2C_IOCTL_EXEC); 23 NAME(FBIOGET_VSCREENINFO); 24 NAME(FBIOPUT_VSCREENINFO); 25 NAME(FBIOGET_FSCREENINFO); /* TODO: print argument */ 26 NAME(FBIOPAN_DISPLAY); 27 NAME(DSPIORATE); 28 NAME(DSPIOSTEREO); 29 NAME(DSPIOSIZE); 30 NAME(DSPIOBITS); 31 NAME(DSPIOSIGN); 32 NAME(DSPIOMAX); 33 NAME(DSPIORESET); /* no argument */ 34 NAME(DSPIOFREEBUF); 35 NAME(DSPIOSAMPLESINBUF); 36 NAME(DSPIOPAUSE); /* no argument */ 37 NAME(DSPIORESUME); /* no argument */ 38 NAME(MIXIOGETVOLUME); 39 NAME(MIXIOGETINPUTLEFT); 40 NAME(MIXIOGETINPUTRIGHT); 41 NAME(MIXIOGETOUTPUT); 42 NAME(MIXIOSETVOLUME); 43 NAME(MIXIOSETINPUTLEFT); 44 NAME(MIXIOSETINPUTRIGHT); 45 NAME(MIXIOSETOUTPUT); 46 NAME(TIOCEXCL); /* no argument */ 47 NAME(TIOCNXCL); /* no argument */ 48 NAME(TIOCFLUSH); 49 NAME(TIOCGETA); 50 NAME(TIOCSETA); 51 NAME(TIOCSETAW); 52 NAME(TIOCSETAF); 53 NAME(TIOCGETD); 54 NAME(TIOCSETD); 55 NAME(TIOCGLINED); 56 NAME(TIOCSLINED); 57 NAME(TIOCSBRK); /* no argument */ 58 NAME(TIOCCBRK); /* no argument */ 59 NAME(TIOCSDTR); /* no argument */ 60 NAME(TIOCCDTR); /* no argument */ 61 NAME(TIOCGPGRP); 62 NAME(TIOCSPGRP); 63 NAME(TIOCOUTQ); 64 NAME(TIOCSTI); 65 NAME(TIOCNOTTY); /* no argument */ 66 NAME(TIOCPKT); 67 NAME(TIOCSTOP); /* no argument */ 68 NAME(TIOCSTART); /* no argument */ 69 NAME(TIOCMSET); /* TODO: print argument */ 70 NAME(TIOCMBIS); /* TODO: print argument */ 71 NAME(TIOCMBIC); /* TODO: print argument */ 72 NAME(TIOCMGET); /* TODO: print argument */ 73 NAME(TIOCREMOTE); 74 NAME(TIOCGWINSZ); 75 NAME(TIOCSWINSZ); 76 NAME(TIOCUCNTL); 77 NAME(TIOCSTAT); 78 NAME(TIOCGSID); 79 NAME(TIOCCONS); 80 NAME(TIOCSCTTY); /* no argument */ 81 NAME(TIOCEXT); 82 NAME(TIOCSIG); /* no argument */ 83 NAME(TIOCDRAIN); /* no argument */ 84 NAME(TIOCGFLAGS); /* TODO: print argument */ 85 NAME(TIOCSFLAGS); /* TODO: print argument */ 86 NAME(TIOCDCDTIMESTAMP); /* TODO: print argument */ 87 NAME(TIOCRCVFRAME); /* TODO: print argument */ 88 NAME(TIOCXMTFRAME); /* TODO: print argument */ 89 NAME(TIOCPTMGET); /* TODO: print argument */ 90 NAME(TIOCGRANTPT); /* no argument */ 91 NAME(TIOCPTSNAME); /* TODO: print argument */ 92 NAME(TIOCSQSIZE); 93 NAME(TIOCGQSIZE); 94 NAME(TIOCSFON); /* big IOCTL, not printing argument */ 95 NAME(KIOCBELL); 96 NAME(KIOCSLEDS); 97 NAME(KIOCSMAP); /* not worth interpreting */ 98 NAME(PCI_IOC_CFGREAD); 99 NAME(PCI_IOC_CFGWRITE); 100 NAME(PCI_IOC_BDF_CFGREAD); 101 NAME(PCI_IOC_BDF_CFGWRITE); 102 NAME(PCI_IOC_BUSINFO); 103 NAME(PCI_IOC_MAP); 104 NAME(PCI_IOC_UNMAP); 105 NAME(PCI_IOC_RESERVE); 106 NAME(PCI_IOC_RELEASE); 107 } 108 109 return NULL; 110 } 111 112 static void 113 put_i2c_op(struct trace_proc * proc, const char *name, i2c_op_t op) 114 { 115 const char *text = NULL; 116 117 if (!valuesonly) { 118 switch (op) { 119 TEXT(I2C_OP_READ); 120 TEXT(I2C_OP_READ_WITH_STOP); 121 TEXT(I2C_OP_WRITE); 122 TEXT(I2C_OP_WRITE_WITH_STOP); 123 TEXT(I2C_OP_READ_BLOCK); 124 TEXT(I2C_OP_WRITE_BLOCK); 125 } 126 } 127 128 if (text != NULL) 129 put_field(proc, name, text); 130 else 131 put_value(proc, name, "%d", op); 132 } 133 134 static void 135 put_sound_device(struct trace_proc * proc, const char * name, int device) 136 { 137 const char *text = NULL; 138 139 if (!valuesonly) { 140 switch (device) { 141 TEXT(Master); 142 TEXT(Dac); 143 TEXT(Fm); 144 TEXT(Cd); 145 TEXT(Line); 146 TEXT(Mic); 147 TEXT(Speaker); 148 TEXT(Treble); 149 TEXT(Bass); 150 } 151 } 152 153 if (text != NULL) 154 put_field(proc, name, text); 155 else 156 put_value(proc, name, "%d", device); 157 } 158 159 static void 160 put_sound_state(struct trace_proc * proc, const char * name, int state) 161 { 162 163 if (!valuesonly && state == ON) 164 put_field(proc, name, "ON"); 165 else if (!valuesonly && state == OFF) 166 put_field(proc, name, "OFF"); 167 else 168 put_value(proc, name, "%d", state); 169 } 170 171 static const struct flags flush_flags[] = { 172 FLAG(FREAD), 173 FLAG(FWRITE), 174 }; 175 176 static const struct flags tc_iflags[] = { 177 FLAG(IGNBRK), 178 FLAG(BRKINT), 179 FLAG(IGNPAR), 180 FLAG(PARMRK), 181 FLAG(INPCK), 182 FLAG(ISTRIP), 183 FLAG(INLCR), 184 FLAG(IGNCR), 185 FLAG(ICRNL), 186 FLAG(IXON), 187 FLAG(IXOFF), 188 FLAG(IXANY), 189 FLAG(IMAXBEL), 190 }; 191 192 static const struct flags tc_oflags[] = { 193 FLAG(OPOST), 194 FLAG(ONLCR), 195 FLAG(OXTABS), 196 FLAG(ONOEOT), 197 FLAG(OCRNL), 198 FLAG(ONOCR), 199 FLAG(ONLRET), 200 }; 201 202 static const struct flags tc_cflags[] = { 203 FLAG(CIGNORE), 204 FLAG_MASK(CSIZE, CS5), 205 FLAG_MASK(CSIZE, CS6), 206 FLAG_MASK(CSIZE, CS7), 207 FLAG_MASK(CSIZE, CS8), 208 FLAG(CSTOPB), 209 FLAG(CREAD), 210 FLAG(PARENB), 211 FLAG(PARODD), 212 FLAG(HUPCL), 213 FLAG(CLOCAL), 214 FLAG(CRTSCTS), 215 FLAG(CDTRCTS), 216 FLAG(MDMBUF), 217 }; 218 219 static const struct flags tc_lflags[] = { 220 FLAG(ECHOKE), 221 FLAG(ECHOE), 222 FLAG(ECHOK), 223 FLAG(ECHO), 224 FLAG(ECHONL), 225 FLAG(ECHOPRT), 226 FLAG(ECHOCTL), 227 FLAG(ISIG), 228 FLAG(ICANON), 229 FLAG(ALTWERASE), 230 FLAG(IEXTEN), 231 FLAG(EXTPROC), 232 FLAG(TOSTOP), 233 FLAG(FLUSHO), 234 FLAG(NOKERNINFO), 235 FLAG(PENDIN), 236 FLAG(NOFLSH), 237 }; 238 239 static void 240 put_tty_disc(struct trace_proc * proc, const char * name, int disc) 241 { 242 const char *text = NULL; 243 244 if (!valuesonly) { 245 switch (disc) { 246 TEXT(TTYDISC); 247 TEXT(TABLDISC); 248 TEXT(SLIPDISC); 249 TEXT(PPPDISC); 250 TEXT(STRIPDISC); 251 TEXT(HDLCDISC); 252 } 253 } 254 255 if (text != NULL) 256 put_field(proc, name, text); 257 else 258 put_value(proc, name, "%d", disc); 259 } 260 261 static const struct flags kbd_leds[] = { 262 FLAG(KBD_LEDS_NUM), 263 FLAG(KBD_LEDS_CAPS), 264 FLAG(KBD_LEDS_SCROLL), 265 }; 266 267 int 268 char_ioctl_arg(struct trace_proc * proc, unsigned long req, void * ptr, 269 int dir) 270 { 271 minix_i2c_ioctl_exec_t *iie; 272 struct fb_var_screeninfo *fbvs; 273 struct volume_level *level; 274 struct inout_ctrl *inout; 275 struct termios *tc; 276 struct ptmget *pm; 277 struct winsize *ws; 278 struct kio_bell *bell; 279 struct kio_leds *leds; 280 struct pciio_cfgreg *pci_cfgreg; 281 struct pciio_bdf_cfgreg *pci_bdf_cfgreg; 282 struct pciio_businfo *pci_businfo; 283 struct pciio_map *pci_iomap; 284 struct pciio_acl *pci_acl; 285 286 switch (req) { 287 case MINIX_I2C_IOCTL_EXEC: 288 if ((iie = (minix_i2c_ioctl_exec_t *)ptr) == NULL) 289 return IF_OUT; /* we print only the request for now */ 290 291 put_i2c_op(proc, "iie_op", iie->iie_op); 292 put_value(proc, "iie_addr", "0x%04x", iie->iie_addr); 293 return 0; /* TODO: print command/data/result */ 294 295 case FBIOGET_VSCREENINFO: 296 if ((fbvs = (struct fb_var_screeninfo *)ptr) == NULL) 297 return IF_IN; 298 299 put_value(proc, "xres", "%"PRIu32, fbvs->xres); 300 put_value(proc, "yres", "%"PRIu32, fbvs->yres); 301 put_value(proc, "xres_virtual", "%"PRIu32, fbvs->xres_virtual); 302 put_value(proc, "yres_virtual", "%"PRIu32, fbvs->yres_virtual); 303 put_value(proc, "xoffset", "%"PRIu32, fbvs->xoffset); 304 put_value(proc, "yoffset", "%"PRIu32, fbvs->yoffset); 305 put_value(proc, "bits_per_pixel", "%"PRIu32, 306 fbvs->bits_per_pixel); 307 return 0; 308 309 case FBIOPUT_VSCREENINFO: 310 case FBIOPAN_DISPLAY: 311 if ((fbvs = (struct fb_var_screeninfo *)ptr) == NULL) 312 return IF_OUT; 313 314 put_value(proc, "xoffset", "%"PRIu32, fbvs->xoffset); 315 put_value(proc, "yoffset", "%"PRIu32, fbvs->yoffset); 316 return 0; 317 318 case DSPIORATE: 319 case DSPIOSTEREO: 320 case DSPIOSIZE: 321 case DSPIOBITS: 322 case DSPIOSIGN: 323 case DSPIOMAX: 324 case DSPIOFREEBUF: 325 case DSPIOSAMPLESINBUF: 326 if (ptr == NULL) 327 return dir; 328 329 put_value(proc, NULL, "%u", *(unsigned int *)ptr); 330 return IF_ALL; 331 332 case MIXIOGETVOLUME: 333 if ((level = (struct volume_level *)ptr) == NULL) 334 return dir; 335 336 if (dir == IF_OUT) 337 put_sound_device(proc, "device", level->device); 338 else { 339 put_value(proc, "left", "%d", level->left); 340 put_value(proc, "right", "%d", level->right); 341 } 342 return IF_ALL; 343 344 case MIXIOSETVOLUME: 345 /* Print the corrected volume levels only with verbosity on. */ 346 if ((level = (struct volume_level *)ptr) == NULL) 347 return IF_OUT | ((verbose > 0) ? IF_IN : 0); 348 349 if (dir == IF_OUT) 350 put_sound_device(proc, "device", level->device); 351 put_value(proc, "left", "%d", level->left); 352 put_value(proc, "right", "%d", level->right); 353 return IF_ALL; 354 355 case MIXIOGETINPUTLEFT: 356 case MIXIOGETINPUTRIGHT: 357 case MIXIOGETOUTPUT: 358 if ((inout = (struct inout_ctrl *)ptr) == NULL) 359 return dir; 360 361 if (dir == IF_OUT) 362 put_sound_device(proc, "device", inout->device); 363 else { 364 put_sound_state(proc, "left", inout->left); 365 put_sound_state(proc, "right", inout->right); 366 } 367 return IF_ALL; 368 369 case MIXIOSETINPUTLEFT: 370 case MIXIOSETINPUTRIGHT: 371 case MIXIOSETOUTPUT: 372 if ((inout = (struct inout_ctrl *)ptr) == NULL) 373 return IF_OUT; 374 375 put_sound_device(proc, "device", inout->device); 376 put_sound_state(proc, "left", inout->left); 377 put_sound_state(proc, "right", inout->right); 378 return IF_ALL; 379 380 case TIOCFLUSH: 381 if (ptr == NULL) 382 return IF_OUT; 383 384 put_flags(proc, NULL, flush_flags, COUNT(flush_flags), "0x%x", 385 *(int *)ptr); 386 return IF_ALL; 387 388 case TIOCGETA: 389 case TIOCSETA: 390 case TIOCSETAW: 391 case TIOCSETAF: 392 if ((tc = (struct termios *)ptr) == NULL) 393 return dir; 394 395 /* 396 * These are fairly common IOCTLs, so printing everything by 397 * default would create a lot of noise. By default we limit 398 * ourselves to printing the field that contains what I 399 * consider to be the most important flag: ICANON. 400 * TODO: see if we can come up with a decent format for 401 * selectively printing (relatively important) flags. 402 */ 403 if (verbose > 0) { 404 put_flags(proc, "c_iflag", tc_iflags, COUNT(tc_iflags), 405 "0x%x", tc->c_iflag); 406 put_flags(proc, "c_oflag", tc_oflags, COUNT(tc_oflags), 407 "0x%x", tc->c_oflag); 408 put_flags(proc, "c_cflag", tc_cflags, COUNT(tc_cflags), 409 "0x%x", tc->c_cflag); 410 } 411 put_flags(proc, "c_lflag", tc_lflags, COUNT(tc_lflags), "0x%x", 412 tc->c_lflag); 413 if (verbose > 0) { 414 put_value(proc, "c_ispeed", "%d", tc->c_ispeed); 415 put_value(proc, "c_ospeed", "%d", tc->c_ospeed); 416 } 417 return 0; /* TODO: print the c_cc fields */ 418 419 case TIOCGETD: 420 case TIOCSETD: 421 if (ptr == NULL) 422 return dir; 423 424 put_tty_disc(proc, NULL, *(int *)ptr); 425 return IF_ALL; 426 427 case TIOCGLINED: 428 case TIOCSLINED: 429 if (ptr == NULL) 430 return dir; 431 432 put_buf(proc, NULL, PF_LOCADDR | PF_STRING, (vir_bytes)ptr, 433 sizeof(linedn_t)); 434 return IF_ALL; 435 436 case TIOCGPGRP: 437 case TIOCSPGRP: 438 case TIOCOUTQ: 439 case TIOCPKT: 440 case TIOCREMOTE: 441 case TIOCUCNTL: 442 case TIOCSTAT: /* argument seems unused? */ 443 case TIOCGSID: 444 case TIOCCONS: /* argument seems unused? */ 445 case TIOCEXT: 446 case TIOCSQSIZE: 447 case TIOCGQSIZE: 448 /* Print a simple integer. */ 449 if (ptr == NULL) 450 return dir; 451 452 put_value(proc, NULL, "%d", *(int *)ptr); 453 return IF_ALL; 454 455 case TIOCPTSNAME: 456 if ((pm = (struct ptmget *)ptr) == NULL) 457 return IF_IN; 458 459 put_buf(proc, "sn", PF_LOCADDR | PF_STRING, (vir_bytes)pm->sn, 460 sizeof(pm->sn)); 461 return IF_ALL; 462 463 case TIOCSTI: 464 if (ptr == NULL) 465 return dir; 466 467 if (!valuesonly) 468 put_value(proc, NULL, "'%s'", 469 get_escape(*(char *)ptr)); 470 else 471 put_value(proc, NULL, "%u", *(char *)ptr); 472 return IF_ALL; 473 474 case TIOCGWINSZ: 475 case TIOCSWINSZ: 476 if ((ws = (struct winsize *)ptr) == NULL) 477 return dir; 478 479 /* This is a stupid order, but we follow the struct layout. */ 480 put_value(proc, "ws_row", "%u", ws->ws_row); 481 put_value(proc, "ws_col", "%u", ws->ws_col); 482 if (verbose > 0) { 483 put_value(proc, "ws_xpixel", "%u", ws->ws_xpixel); 484 put_value(proc, "ws_ypixel", "%u", ws->ws_ypixel); 485 } 486 return (verbose > 0) ? IF_ALL : 0; 487 488 case KIOCBELL: 489 if ((bell = (struct kio_bell *)ptr) == NULL) 490 return IF_OUT; 491 492 put_value(proc, "kb_pitch", "%u", bell->kb_pitch); 493 put_value(proc, "kb_volume", "%lu", bell->kb_volume); 494 put_struct_timeval(proc, "kb_duration", PF_LOCADDR, 495 (vir_bytes)&bell->kb_duration); 496 497 return IF_ALL; 498 499 case KIOCSLEDS: 500 if ((leds = (struct kio_leds *)ptr) == NULL) 501 return IF_OUT; 502 503 put_flags(proc, "kl_bits", kbd_leds, COUNT(kbd_leds), "0x%x", 504 leds->kl_bits); 505 return IF_ALL; 506 507 case PCI_IOC_CFGREAD: 508 if ((pci_cfgreg = (struct pciio_cfgreg *)ptr) == NULL) 509 return IF_IN; 510 511 put_ptr(proc, "reg", (vir_bytes)pci_cfgreg->reg); 512 put_value(proc, "val", "%08x", pci_cfgreg->val); 513 return IF_ALL; 514 515 case PCI_IOC_CFGWRITE: 516 if ((pci_cfgreg = (struct pciio_cfgreg *)ptr) == NULL) 517 return IF_OUT; 518 519 put_ptr(proc, "reg", (vir_bytes)pci_cfgreg->reg); 520 put_value(proc, "val", "%08x", pci_cfgreg->val); 521 return IF_ALL; 522 523 case PCI_IOC_BDF_CFGREAD: 524 if ((pci_bdf_cfgreg = (struct pciio_bdf_cfgreg *)ptr) == NULL) 525 return IF_IN; 526 527 put_value(proc, "bus", "%u", pci_bdf_cfgreg->bus); 528 put_value(proc, "device", "%u", pci_bdf_cfgreg->device); 529 put_value(proc, "function", "%u", pci_bdf_cfgreg->function); 530 put_ptr(proc, "cfgreg.reg", (vir_bytes)pci_bdf_cfgreg->cfgreg.reg); 531 put_value(proc, "cfgreg.val", "%08x", pci_bdf_cfgreg->cfgreg.val); 532 return IF_ALL; 533 534 case PCI_IOC_BDF_CFGWRITE: 535 if ((pci_bdf_cfgreg = (struct pciio_bdf_cfgreg *)ptr) == NULL) 536 return IF_OUT; 537 538 put_value(proc, "bus", "%u", pci_bdf_cfgreg->bus); 539 put_value(proc, "device", "%u", pci_bdf_cfgreg->device); 540 put_value(proc, "function", "%u", pci_bdf_cfgreg->function); 541 put_ptr(proc, "cfgreg.reg", (vir_bytes)pci_bdf_cfgreg->cfgreg.reg); 542 put_value(proc, "cfgreg.val", "%08x", pci_bdf_cfgreg->cfgreg.val); 543 return IF_ALL; 544 545 case PCI_IOC_BUSINFO: 546 if ((pci_businfo = (struct pciio_businfo *)ptr) == NULL) 547 return IF_IN; 548 549 put_value(proc, "busno", "%u", pci_businfo->busno); 550 put_value(proc, "maxdevs", "%u", pci_businfo->maxdevs); 551 return IF_ALL; 552 553 case PCI_IOC_MAP: 554 if ((pci_iomap = (struct pciio_map *)ptr) == NULL) 555 return IF_OUT|IF_IN; 556 557 put_value(proc, "flags", "%x", pci_iomap->flags); 558 put_value(proc, "phys_offset", "%08x", pci_iomap->phys_offset); 559 put_value(proc, "size", "%zu", pci_iomap->size); 560 put_value(proc, "readonly", "%x", pci_iomap->readonly); 561 562 if (IF_IN == dir) 563 put_ptr(proc, "vaddr_ret", (vir_bytes)pci_iomap->vaddr_ret); 564 565 return IF_ALL; 566 567 case PCI_IOC_UNMAP: 568 if ((pci_iomap = (struct pciio_map *)ptr) == NULL) 569 return IF_OUT; 570 571 put_ptr(proc, "vaddr", (vir_bytes)pci_iomap->vaddr); 572 573 return IF_ALL; 574 575 case PCI_IOC_RESERVE: 576 if ((pci_acl = (struct pciio_acl *)ptr) == NULL) 577 return IF_OUT; 578 579 put_value(proc, "domain", "%u", pci_acl->domain); 580 put_value(proc, "bus", "%u", pci_acl->bus); 581 put_value(proc, "device", "%u", pci_acl->device); 582 put_value(proc, "function", "%u", pci_acl->function); 583 584 return IF_ALL; 585 case PCI_IOC_RELEASE: 586 if ((pci_acl = (struct pciio_acl *)ptr) == NULL) 587 return IF_OUT; 588 589 put_value(proc, "domain", "%u", pci_acl->domain); 590 put_value(proc, "bus", "%u", pci_acl->bus); 591 put_value(proc, "device", "%u", pci_acl->device); 592 put_value(proc, "function", "%u", pci_acl->function); 593 594 return IF_ALL; 595 596 default: 597 return 0; 598 } 599 } 600