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 winsize *ws; 277 struct kio_bell *bell; 278 struct kio_leds *leds; 279 struct pciio_cfgreg *pci_cfgreg; 280 struct pciio_bdf_cfgreg *pci_bdf_cfgreg; 281 struct pciio_businfo *pci_businfo; 282 struct pciio_map *pci_iomap; 283 struct pciio_acl *pci_acl; 284 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 TIOCSTI: 456 if (ptr == NULL) 457 return dir; 458 459 if (!valuesonly) 460 put_value(proc, NULL, "'%s'", 461 get_escape(*(char *)ptr)); 462 else 463 put_value(proc, NULL, "%u", *(char *)ptr); 464 return IF_ALL; 465 466 case TIOCGWINSZ: 467 case TIOCSWINSZ: 468 if ((ws = (struct winsize *)ptr) == NULL) 469 return dir; 470 471 /* This is a stupid order, but we follow the struct layout. */ 472 put_value(proc, "ws_row", "%u", ws->ws_row); 473 put_value(proc, "ws_col", "%u", ws->ws_col); 474 if (verbose > 0) { 475 put_value(proc, "ws_xpixel", "%u", ws->ws_xpixel); 476 put_value(proc, "ws_ypixel", "%u", ws->ws_ypixel); 477 } 478 return (verbose > 0) ? IF_ALL : 0; 479 480 case KIOCBELL: 481 if ((bell = (struct kio_bell *)ptr) == NULL) 482 return IF_OUT; 483 484 put_value(proc, "kb_pitch", "%u", bell->kb_pitch); 485 put_value(proc, "kb_volume", "%lu", bell->kb_volume); 486 put_struct_timeval(proc, "kb_duration", PF_LOCADDR, 487 (vir_bytes)&bell->kb_duration); 488 489 return IF_ALL; 490 491 case KIOCSLEDS: 492 if ((leds = (struct kio_leds *)ptr) == NULL) 493 return IF_OUT; 494 495 put_flags(proc, "kl_bits", kbd_leds, COUNT(kbd_leds), "0x%x", 496 leds->kl_bits); 497 return IF_ALL; 498 499 case PCI_IOC_CFGREAD: 500 if ((pci_cfgreg = (struct pciio_cfgreg *)ptr) == NULL) 501 return IF_IN; 502 503 put_ptr(proc, "reg", (vir_bytes)pci_cfgreg->reg); 504 put_value(proc, "val", "%08x", pci_cfgreg->val); 505 return IF_ALL; 506 507 case PCI_IOC_CFGWRITE: 508 if ((pci_cfgreg = (struct pciio_cfgreg *)ptr) == NULL) 509 return IF_OUT; 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_BDF_CFGREAD: 516 if ((pci_bdf_cfgreg = (struct pciio_bdf_cfgreg *)ptr) == NULL) 517 return IF_IN; 518 519 put_value(proc, "bus", "%u", pci_bdf_cfgreg->bus); 520 put_value(proc, "device", "%u", pci_bdf_cfgreg->device); 521 put_value(proc, "function", "%u", pci_bdf_cfgreg->function); 522 put_ptr(proc, "cfgreg.reg", (vir_bytes)pci_bdf_cfgreg->cfgreg.reg); 523 put_value(proc, "cfgreg.val", "%08x", pci_bdf_cfgreg->cfgreg.val); 524 return IF_ALL; 525 526 case PCI_IOC_BDF_CFGWRITE: 527 if ((pci_bdf_cfgreg = (struct pciio_bdf_cfgreg *)ptr) == NULL) 528 return IF_OUT; 529 530 put_value(proc, "bus", "%u", pci_bdf_cfgreg->bus); 531 put_value(proc, "device", "%u", pci_bdf_cfgreg->device); 532 put_value(proc, "function", "%u", pci_bdf_cfgreg->function); 533 put_ptr(proc, "cfgreg.reg", (vir_bytes)pci_bdf_cfgreg->cfgreg.reg); 534 put_value(proc, "cfgreg.val", "%08x", pci_bdf_cfgreg->cfgreg.val); 535 return IF_ALL; 536 537 case PCI_IOC_BUSINFO: 538 if ((pci_businfo = (struct pciio_businfo *)ptr) == NULL) 539 return IF_IN; 540 541 put_value(proc, "busno", "%u", pci_businfo->busno); 542 put_value(proc, "maxdevs", "%u", pci_businfo->maxdevs); 543 return IF_ALL; 544 545 case PCI_IOC_MAP: 546 if ((pci_iomap = (struct pciio_map *)ptr) == NULL) 547 return IF_OUT|IF_IN; 548 549 put_value(proc, "flags", "%x", pci_iomap->flags); 550 put_value(proc, "phys_offset", "%08x", pci_iomap->phys_offset); 551 put_value(proc, "size", "%zu", pci_iomap->size); 552 put_value(proc, "readonly", "%x", pci_iomap->readonly); 553 554 if (IF_IN == dir) 555 put_ptr(proc, "vaddr_ret", (vir_bytes)pci_iomap->vaddr_ret); 556 557 return IF_ALL; 558 559 case PCI_IOC_UNMAP: 560 if ((pci_iomap = (struct pciio_map *)ptr) == NULL) 561 return IF_OUT; 562 563 put_ptr(proc, "vaddr", (vir_bytes)pci_iomap->vaddr); 564 565 return IF_ALL; 566 567 case PCI_IOC_RESERVE: 568 if ((pci_acl = (struct pciio_acl *)ptr) == NULL) 569 return IF_OUT; 570 571 put_value(proc, "domain", "%u", pci_acl->domain); 572 put_value(proc, "bus", "%u", pci_acl->bus); 573 put_value(proc, "device", "%u", pci_acl->device); 574 put_value(proc, "function", "%u", pci_acl->function); 575 576 return IF_ALL; 577 case PCI_IOC_RELEASE: 578 if ((pci_acl = (struct pciio_acl *)ptr) == NULL) 579 return IF_OUT; 580 581 put_value(proc, "domain", "%u", pci_acl->domain); 582 put_value(proc, "bus", "%u", pci_acl->bus); 583 put_value(proc, "device", "%u", pci_acl->device); 584 put_value(proc, "function", "%u", pci_acl->function); 585 586 return IF_ALL; 587 588 default: 589 return 0; 590 } 591 } 592