1 #include <sys/types.h> 2 3 #include <dev/pci/pciio.h> 4 5 #include <minix/chardriver.h> 6 #include <minix/driver.h> 7 #include <minix/rs.h> 8 9 #include "pci.h" 10 11 int debug = 0; 12 struct pci_acl pci_acl[NR_DRIVERS]; 13 14 /*======================================================================* 15 * Helpers * 16 *======================================================================*/ 17 static struct rs_pci * 18 find_acl(int endpoint) 19 { 20 int i; 21 22 /* Find ACL entry for caller */ 23 for (i= 0; i<NR_DRIVERS; i++) 24 { 25 if (!pci_acl[i].inuse) 26 continue; 27 if (pci_acl[i].acl.rsp_endpoint == endpoint) 28 return &pci_acl[i].acl; 29 } 30 return NULL; 31 } 32 33 static void 34 reply(message *mp, int result) 35 { 36 int r; 37 message m; 38 39 m.m_type= result; 40 r= ipc_send(mp->m_source, &m); 41 if (r != 0) 42 printf("reply: unable to send to %d: %d\n", mp->m_source, r); 43 } 44 45 static void 46 do_init(message *mp) 47 { 48 int r; 49 50 #if DEBUG 51 printf("PCI: do_init: called by '%d'\n", mp->m_source); 52 #endif 53 54 mp->m_type= 0; 55 r= ipc_send(mp->m_source, mp); 56 if (r != 0) 57 printf("PCI: do_init: unable to send to %d: %d\n", 58 mp->m_source, r); 59 } 60 61 static void 62 do_first_dev(message *mp) 63 { 64 int r, devind; 65 u16_t vid, did; 66 struct rs_pci *aclp; 67 68 aclp= find_acl(mp->m_source); 69 70 if (!aclp && debug) 71 printf("PCI: do_first_dev: no acl for caller %d\n", 72 mp->m_source); 73 74 r= _pci_first_dev(aclp, &devind, &vid, &did); 75 if (r == 1) 76 { 77 mp->m1_i1= devind; 78 mp->m1_i2= vid; 79 mp->m1_i3= did; 80 } 81 mp->m_type= r; 82 r= ipc_send(mp->m_source, mp); 83 if (r != 0) 84 { 85 printf("PCI: do_first_dev: unable to send to %d: %d\n", 86 mp->m_source, r); 87 } 88 } 89 90 static void 91 do_next_dev(message *mp) 92 { 93 int r, devind; 94 u16_t vid, did; 95 struct rs_pci *aclp; 96 97 devind= mp->m1_i1; 98 aclp= find_acl(mp->m_source); 99 100 r= _pci_next_dev(aclp, &devind, &vid, &did); 101 if (r == 1) 102 { 103 mp->m1_i1= devind; 104 mp->m1_i2= vid; 105 mp->m1_i3= did; 106 } 107 mp->m_type= r; 108 r= ipc_send(mp->m_source, mp); 109 if (r != 0) 110 { 111 printf("PCI: do_next_dev: unable to send to %d: %d\n", 112 mp->m_source, r); 113 } 114 } 115 116 static void 117 do_find_dev(message *mp) 118 { 119 int r, devind; 120 u8_t bus, dev, func; 121 122 bus= mp->m1_i1; 123 dev= mp->m1_i2; 124 func= mp->m1_i3; 125 126 r= _pci_find_dev(bus, dev, func, &devind); 127 if (r == 1) 128 mp->m1_i1= devind; 129 mp->m_type= r; 130 r= ipc_send(mp->m_source, mp); 131 if (r != 0) 132 { 133 printf("PCI: do_find_dev: unable to send to %d: %d\n", 134 mp->m_source, r); 135 } 136 } 137 138 static void 139 do_ids(message *mp) 140 { 141 int r, devind; 142 u16_t vid, did; 143 144 devind= mp->m1_i1; 145 146 r= _pci_ids(devind, &vid, &did); 147 if (r != OK) 148 { 149 printf("pci:do_ids: failed for devind %d: %d\n", 150 devind, r); 151 } 152 153 mp->m1_i1= vid; 154 mp->m1_i2= did; 155 mp->m_type= r; 156 r= ipc_send(mp->m_source, mp); 157 if (r != 0) 158 { 159 printf("PCI: do_ids: unable to send to %d: %d\n", 160 mp->m_source, r); 161 } 162 } 163 164 static void 165 do_dev_name(message *mp) 166 { 167 int r, name_len, len; 168 u16_t vid, did; 169 cp_grant_id_t name_gid; 170 const char *name; 171 172 vid= mp->m7_i1; 173 did= mp->m7_i2; 174 name_len= mp->m7_i3; 175 name_gid= mp->m7_i4; 176 177 name= _pci_dev_name(vid, did); 178 if (name == NULL) 179 { 180 /* No name */ 181 r= ENOENT; 182 } 183 else 184 { 185 len= strlen(name)+1; 186 if (len > name_len) 187 len= name_len; 188 r= sys_safecopyto(mp->m_source, name_gid, 0, (vir_bytes)name, 189 len); 190 } 191 192 mp->m_type= r; 193 r= ipc_send(mp->m_source, mp); 194 if (r != 0) 195 { 196 printf("PCI: do_dev_name: unable to send to %d: %d\n", 197 mp->m_source, r); 198 } 199 } 200 201 static void 202 do_slot_name(message *mp) 203 { 204 int r, devind, name_len, len; 205 cp_grant_id_t gid; 206 char *name; 207 208 devind= mp->m1_i1; 209 name_len= mp->m1_i2; 210 gid= mp->m1_i3; 211 212 r= _pci_slot_name(devind, &name); 213 if (r != OK) 214 { 215 printf("pci:do_slot_name_s: failed for devind %d: %d\n", 216 devind, r); 217 } 218 219 if (r == OK) 220 { 221 len= strlen(name)+1; 222 if (len > name_len) 223 len= name_len; 224 r= sys_safecopyto(mp->m_source, gid, 0, 225 (vir_bytes)name, len); 226 } 227 228 mp->m_type= r; 229 r= ipc_send(mp->m_source, mp); 230 if (r != 0) 231 { 232 printf("PCI: do_slot_name: unable to send to %d: %d\n", 233 mp->m_source, r); 234 } 235 } 236 237 static void 238 do_set_acl(message *mp) 239 { 240 int i, r, gid; 241 242 if (mp->m_source != RS_PROC_NR) 243 { 244 printf("PCI: do_set_acl: not from RS\n"); 245 reply(mp, EPERM); 246 return; 247 } 248 249 for (i= 0; i<NR_DRIVERS; i++) 250 { 251 if (!pci_acl[i].inuse) 252 break; 253 } 254 if (i >= NR_DRIVERS) 255 { 256 printf("PCI: do_set_acl: table is full\n"); 257 reply(mp, ENOMEM); 258 return; 259 } 260 261 gid= mp->m1_i1; 262 263 r= sys_safecopyfrom(mp->m_source, gid, 0, (vir_bytes)&pci_acl[i].acl, 264 sizeof(pci_acl[i].acl)); 265 if (r != OK) 266 { 267 printf("PCI: do_set_acl: safecopyfrom failed\n"); 268 reply(mp, r); 269 return; 270 } 271 pci_acl[i].inuse= 1; 272 if(debug) 273 printf("PCI: do_acl: setting ACL for %d ('%s') at entry %d\n", 274 pci_acl[i].acl.rsp_endpoint, pci_acl[i].acl.rsp_label, 275 i); 276 277 reply(mp, OK); 278 } 279 280 static void 281 do_del_acl(message *mp) 282 { 283 int i, proc_nr; 284 285 if (mp->m_source != RS_PROC_NR) 286 { 287 printf("do_del_acl: not from RS\n"); 288 reply(mp, EPERM); 289 return; 290 } 291 292 proc_nr= mp->m1_i1; 293 294 for (i= 0; i<NR_DRIVERS; i++) 295 { 296 if (!pci_acl[i].inuse) 297 continue; 298 if (pci_acl[i].acl.rsp_endpoint == proc_nr) 299 break; 300 } 301 302 if (i >= NR_DRIVERS) 303 { 304 printf("do_del_acl: nothing found for %d\n", proc_nr); 305 reply(mp, EINVAL); 306 return; 307 } 308 309 pci_acl[i].inuse= 0; 310 #if 0 311 printf("do_acl: deleting ACL for %d ('%s') at entry %d\n", 312 pci_acl[i].acl.rsp_endpoint, pci_acl[i].acl.rsp_label, i); 313 #endif 314 315 /* Also release all devices held by this process */ 316 _pci_release(proc_nr); 317 318 reply(mp, OK); 319 } 320 321 static void 322 do_reserve(message *mp) 323 { 324 struct rs_pci *aclp; 325 int r, devind; 326 327 devind= mp->m1_i1; 328 329 aclp= find_acl(mp->m_source); 330 331 mp->m_type= _pci_reserve(devind, mp->m_source, aclp); 332 r= ipc_send(mp->m_source, mp); 333 if (r != 0) 334 { 335 printf("do_reserve: unable to send to %d: %d\n", 336 mp->m_source, r); 337 } 338 } 339 340 static void 341 do_attr_r8(message *mp) 342 { 343 int r, devind, port; 344 u8_t v; 345 346 devind= mp->m2_i1; 347 port= mp->m2_i2; 348 349 r= _pci_attr_r8(devind, port, &v); 350 if (r != OK) 351 { 352 printf( 353 "pci:do_attr_r8: pci_attr_r8(%d, %d, ...) failed: %d\n", 354 devind, port, r); 355 } 356 mp->m2_l1= v; 357 mp->m_type= r; 358 r= ipc_send(mp->m_source, mp); 359 if (r != 0) 360 { 361 printf("do_attr_r8: unable to send to %d: %d\n", 362 mp->m_source, r); 363 } 364 } 365 366 static void 367 do_attr_r16(message *mp) 368 { 369 int r, devind, port; 370 u16_t v; 371 372 devind= mp->m2_i1; 373 port= mp->m2_i2; 374 375 r= _pci_attr_r16(devind, port, &v); 376 if (r != OK) 377 { 378 printf( 379 "pci:do_attr_r16: pci_attr_r16(%d, %d, ...) failed: %d\n", 380 devind, port, r); 381 } 382 mp->m2_l1= v; 383 mp->m_type= OK; 384 r= ipc_send(mp->m_source, mp); 385 if (r != 0) 386 { 387 printf("do_attr_r16: unable to send to %d: %d\n", 388 mp->m_source, r); 389 } 390 } 391 392 static void 393 do_attr_r32(message *mp) 394 { 395 int r, devind, port; 396 u32_t v; 397 398 devind= mp->m2_i1; 399 port= mp->m2_i2; 400 401 r= _pci_attr_r32(devind, port, &v); 402 if (r != OK) 403 { 404 printf( 405 "pci:do_attr_r32: pci_attr_r32(%d, %d, ...) failed: %d\n", 406 devind, port, r); 407 } 408 mp->m2_l1= v; 409 mp->m_type= OK; 410 r= ipc_send(mp->m_source, mp); 411 if (r != 0) 412 { 413 printf("do_attr_r32: unable to send to %d: %d\n", 414 mp->m_source, r); 415 } 416 } 417 418 static void 419 do_attr_w8(message *mp) 420 { 421 int r, devind, port; 422 u8_t v; 423 424 devind= mp->m2_i1; 425 port= mp->m2_i2; 426 v= mp->m2_l1; 427 428 _pci_attr_w8(devind, port, v); 429 mp->m_type= OK; 430 r= ipc_send(mp->m_source, mp); 431 if (r != 0) 432 { 433 printf("do_attr_w8: unable to send to %d: %d\n", 434 mp->m_source, r); 435 } 436 } 437 438 static void 439 do_attr_w16(message *mp) 440 { 441 int r, devind, port; 442 u16_t v; 443 444 devind= mp->m2_i1; 445 port= mp->m2_i2; 446 v= mp->m2_l1; 447 448 _pci_attr_w16(devind, port, v); 449 mp->m_type= OK; 450 r= ipc_send(mp->m_source, mp); 451 if (r != 0) 452 { 453 printf("do_attr_w16: unable to send to %d: %d\n", 454 mp->m_source, r); 455 } 456 } 457 458 static void 459 do_attr_w32(message *mp) 460 { 461 int r, devind, port; 462 u32_t v; 463 464 devind= mp->m2_i1; 465 port= mp->m2_i2; 466 v= mp->m2_l1; 467 468 _pci_attr_w32(devind, port, v); 469 mp->m_type= OK; 470 r= ipc_send(mp->m_source, mp); 471 if (r != 0) 472 { 473 printf("do_attr_w32: unable to send to %d: %d\n", 474 mp->m_source, r); 475 } 476 } 477 478 static void 479 do_get_bar(message *mp) 480 { 481 int r, devind, port, ioflag; 482 u32_t base, size; 483 484 devind= mp->m_lsys_pci_busc_get_bar.devind; 485 port= mp->m_lsys_pci_busc_get_bar.port; 486 487 mp->m_type= _pci_get_bar(devind, port, &base, &size, &ioflag); 488 489 if (mp->m_type == OK) 490 { 491 mp->m_pci_lsys_busc_get_bar.base= base; 492 mp->m_pci_lsys_busc_get_bar.size= size; 493 mp->m_pci_lsys_busc_get_bar.flags= ioflag; 494 } 495 496 r= ipc_send(mp->m_source, mp); 497 if (r != 0) 498 { 499 printf("do_get_bar: unable to send to %d: %d\n", 500 mp->m_source, r); 501 } 502 } 503 504 static void 505 do_rescan_bus(message *mp) 506 { 507 int r, busnr; 508 509 busnr= mp->m2_i1; 510 511 _pci_rescan_bus(busnr); 512 mp->m_type= OK; 513 r= ipc_send(mp->m_source, mp); 514 if (r != 0) 515 { 516 printf("do_rescan_bus: unable to send to %d: %d\n", 517 mp->m_source, r); 518 } 519 } 520 521 /*======================================================================* 522 * CharDriver Callbacks * 523 *======================================================================*/ 524 static int 525 pci_open(devminor_t UNUSED(minor), int UNUSED(access), 526 endpoint_t UNUSED(user_endpt)) 527 { 528 return OK; 529 } 530 531 static int 532 pci_close(devminor_t UNUSED(minor)) 533 { 534 return OK; 535 } 536 537 static int 538 pci_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt, 539 cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id) 540 { 541 int devind; 542 int r = ENOTTY; 543 544 switch(request) 545 { 546 case PCI_IOC_BDF_CFGREAD: 547 { 548 struct pciio_bdf_cfgreg bdf; 549 550 if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&bdf, 551 sizeof(bdf))) != OK) 552 break; 553 554 r = _pci_find_dev(bdf.bus, bdf.device, bdf.function, &devind); 555 if (r != 1) { 556 r = EINVAL; 557 break; 558 } 559 560 if ((r = _pci_attr_r32(devind, bdf.cfgreg.reg, 561 &bdf.cfgreg.val)) != OK) 562 break; 563 564 r = sys_safecopyto(endpt, grant, 0, (vir_bytes)&bdf, 565 sizeof(bdf)); 566 break; 567 } 568 case PCI_IOC_BDF_CFGWRITE: 569 { 570 struct pciio_bdf_cfgreg bdf; 571 572 if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&bdf, 573 sizeof(bdf))) != OK) 574 break; 575 576 r = _pci_find_dev(bdf.bus, bdf.device, bdf.function, &devind); 577 if (r != 1) { 578 r = EINVAL; 579 break; 580 } 581 582 _pci_attr_w32(devind, bdf.cfgreg.reg, bdf.cfgreg.val); 583 r = OK; 584 break; 585 } 586 case PCI_IOC_BUSINFO: 587 break; 588 case PCI_IOC_MAP: 589 { 590 struct pciio_map map; 591 struct minix_mem_range mr; 592 593 if ((r = sys_safecopyfrom(endpt, grant, 0, 594 (vir_bytes)&map, sizeof(map))) != OK) 595 break; 596 597 #if 1 598 mr.mr_base = map.phys_offset; 599 mr.mr_limit = map.phys_offset + map.size - 1; 600 601 r = sys_privctl(user_endpt, SYS_PRIV_ADD_MEM, &mr); 602 if (r != OK) 603 { 604 break; 605 } 606 #endif 607 608 map.vaddr_ret = vm_map_phys(user_endpt, 609 (void *)map.phys_offset, map.size); 610 r = sys_safecopyto(endpt, grant, 0, (vir_bytes)&map, 611 sizeof(map)); 612 break; 613 } 614 case PCI_IOC_UNMAP: 615 { 616 struct pciio_map map; 617 618 if ((r = sys_safecopyfrom(endpt, grant, 0, 619 (vir_bytes)&map, sizeof(map))) != OK) 620 break; 621 622 r = vm_unmap_phys(user_endpt, map.vaddr, map.size); 623 break; 624 } 625 case PCI_IOC_RESERVE: 626 { 627 struct pciio_acl acl; 628 629 if ((r = sys_safecopyfrom(endpt, grant, 0, 630 (vir_bytes)&acl, sizeof(acl))) != OK) 631 break; 632 633 r = _pci_find_dev(acl.bus, acl.device, acl.function, &devind); 634 if (r != 1) { 635 r = EINVAL; 636 break; 637 } 638 639 r = _pci_grant_access(devind, user_endpt); 640 break; 641 } 642 case PCI_IOC_RELEASE: 643 { 644 struct pciio_acl acl; 645 646 if ((r = sys_safecopyfrom(endpt, grant, 0, 647 (vir_bytes)&acl, sizeof(acl))) != OK) 648 break; 649 650 r = _pci_find_dev(acl.bus, acl.device, acl.function, &devind); 651 if (r != 1) { 652 r = EINVAL; 653 break; 654 } 655 656 _pci_release(endpt); 657 r = OK; 658 659 break; 660 } 661 case PCI_IOC_CFGREAD: 662 case PCI_IOC_CFGWRITE: 663 default: 664 r = ENOTTY; 665 } 666 return r; 667 } 668 669 static void 670 pci_other(message *m, int ipc_status) 671 { 672 switch(m->m_type) 673 { 674 case BUSC_PCI_INIT: do_init(m); break; 675 case BUSC_PCI_FIRST_DEV: do_first_dev(m); break; 676 case BUSC_PCI_NEXT_DEV: do_next_dev(m); break; 677 case BUSC_PCI_FIND_DEV: do_find_dev(m); break; 678 case BUSC_PCI_IDS: do_ids(m); break; 679 case BUSC_PCI_RESERVE: do_reserve(m); break; 680 case BUSC_PCI_ATTR_R8: do_attr_r8(m); break; 681 case BUSC_PCI_ATTR_R16: do_attr_r16(m); break; 682 case BUSC_PCI_ATTR_R32: do_attr_r32(m); break; 683 case BUSC_PCI_ATTR_W8: do_attr_w8(m); break; 684 case BUSC_PCI_ATTR_W16: do_attr_w16(m); break; 685 case BUSC_PCI_ATTR_W32: do_attr_w32(m); break; 686 case BUSC_PCI_RESCAN: do_rescan_bus(m); break; 687 case BUSC_PCI_DEV_NAME_S: do_dev_name(m); break; 688 case BUSC_PCI_SLOT_NAME_S: do_slot_name(m); break; 689 case BUSC_PCI_SET_ACL: do_set_acl(m); break; 690 case BUSC_PCI_DEL_ACL: do_del_acl(m); break; 691 case BUSC_PCI_GET_BAR: do_get_bar(m); break; 692 default: 693 printf("PCI: unhandled message from %d, type %d\n", 694 m->m_source, m->m_type); 695 break; 696 } 697 } 698 699 static struct chardriver driver = 700 { 701 .cdr_open = pci_open, 702 .cdr_close = pci_close, 703 .cdr_ioctl = pci_ioctl, 704 .cdr_other = pci_other, 705 }; 706 707 /*======================================================================* 708 * SEF Callbacks * 709 *======================================================================*/ 710 /* NOTE: sef_cb_init is in pci.c. */ 711 static void 712 sef_local_startup(void) 713 { 714 /* 715 * Register init callbacks. Use the same function for all event types 716 */ 717 sef_setcb_init_fresh(sef_cb_init); 718 sef_setcb_init_restart(sef_cb_init); 719 720 /* Let SEF perform startup. */ 721 sef_startup(); 722 } 723 724 /*======================================================================* 725 * main * 726 *======================================================================*/ 727 int 728 main(void) 729 { 730 /* 731 * Perform initialization. 732 */ 733 sef_local_startup(); 734 735 /* 736 * Run the main loop. 737 */ 738 chardriver_task(&driver); 739 return OK; 740 } 741