1/* $FreeBSD$ */ 2/*- 3 * Copyright (c) 2013 Hans Petter Selasky. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <bsd_global.h> 28 29struct usb_process usb_process[USB_PROC_MAX]; 30 31static device_t usb_pci_root; 32 33/*------------------------------------------------------------------------* 34 * Implementation of mutex API 35 *------------------------------------------------------------------------*/ 36 37struct mtx Giant; 38 39static void 40mtx_system_init(void *arg) 41{ 42 mtx_init(&Giant, "Giant", NULL, MTX_DEF | MTX_RECURSE); 43} 44SYSINIT(mtx_system_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, mtx_system_init, NULL); 45 46void 47mtx_init(struct mtx *mtx, const char *name, const char *type, int opt) 48{ 49 mtx->owned = 0; 50 mtx->parent = mtx; 51} 52 53void 54mtx_lock(struct mtx *mtx) 55{ 56 mtx = mtx->parent; 57 mtx->owned++; 58} 59 60void 61mtx_unlock(struct mtx *mtx) 62{ 63 mtx = mtx->parent; 64 mtx->owned--; 65} 66 67int 68mtx_owned(struct mtx *mtx) 69{ 70 mtx = mtx->parent; 71 return (mtx->owned != 0); 72} 73 74void 75mtx_destroy(struct mtx *mtx) 76{ 77 /* NOP */ 78} 79 80/*------------------------------------------------------------------------* 81 * Implementation of shared/exclusive mutex API 82 *------------------------------------------------------------------------*/ 83 84void 85sx_init_flags(struct sx *sx, const char *name, int flags) 86{ 87 sx->owned = 0; 88} 89 90void 91sx_destroy(struct sx *sx) 92{ 93 /* NOP */ 94} 95 96void 97sx_xlock(struct sx *sx) 98{ 99 sx->owned++; 100} 101 102void 103sx_xunlock(struct sx *sx) 104{ 105 sx->owned--; 106} 107 108int 109sx_xlocked(struct sx *sx) 110{ 111 return (sx->owned != 0); 112} 113 114/*------------------------------------------------------------------------* 115 * Implementaiton of condition variable API 116 *------------------------------------------------------------------------*/ 117 118void 119cv_init(struct cv *cv, const char *desc) 120{ 121 cv->sleeping = 0; 122} 123 124void 125cv_destroy(struct cv *cv) 126{ 127 /* NOP */ 128} 129 130void 131cv_wait(struct cv *cv, struct mtx *mtx) 132{ 133 cv_timedwait(cv, mtx, -1); 134} 135 136int 137cv_timedwait(struct cv *cv, struct mtx *mtx, int timo) 138{ 139 int start = ticks; 140 int delta; 141 142 if (cv->sleeping) 143 return (EWOULDBLOCK); /* not allowed */ 144 145 cv->sleeping = 1; 146 147 while (cv->sleeping) { 148 if (timo >= 0) { 149 delta = ticks - start; 150 if (delta >= timo || delta < 0) 151 break; 152 } 153 mtx_unlock(mtx); 154 155 usb_idle(); 156 157 mtx_lock(mtx); 158 } 159 160 if (cv->sleeping) { 161 cv->sleeping = 0; 162 return (EWOULDBLOCK); /* not allowed */ 163 } 164 return (0); 165} 166 167void 168cv_signal(struct cv *cv) 169{ 170 cv->sleeping = 0; 171} 172 173void 174cv_broadcast(struct cv *cv) 175{ 176 cv->sleeping = 0; 177} 178 179/*------------------------------------------------------------------------* 180 * Implementation of callout API 181 *------------------------------------------------------------------------*/ 182 183static void callout_proc_msg(struct usb_proc_msg *); 184 185volatile int ticks = 0; 186 187static LIST_HEAD(, callout) head_callout = LIST_HEAD_INITIALIZER(&head_callout); 188 189static struct mtx mtx_callout; 190static struct usb_proc_msg callout_msg[2]; 191 192static void 193callout_system_init(void *arg) 194{ 195 mtx_init(&mtx_callout, "callout-mtx", NULL, MTX_DEF | MTX_RECURSE); 196 197 callout_msg[0].pm_callback = &callout_proc_msg; 198 callout_msg[1].pm_callback = &callout_proc_msg; 199} 200SYSINIT(callout_system_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, callout_system_init, NULL); 201 202static void 203callout_callback(struct callout *c) 204{ 205 mtx_lock(c->mtx); 206 207 mtx_lock(&mtx_callout); 208 if (c->entry.le_prev != NULL) { 209 LIST_REMOVE(c, entry); 210 c->entry.le_prev = NULL; 211 } 212 mtx_unlock(&mtx_callout); 213 214 if (c->func) 215 (c->func) (c->arg); 216 217 if (!(c->flags & CALLOUT_RETURNUNLOCKED)) 218 mtx_unlock(c->mtx); 219} 220 221void 222callout_process(int timeout) 223{ 224 ticks += timeout; 225 usb_proc_msignal(usb_process + 2, &callout_msg[0], &callout_msg[1]); 226} 227 228static void 229callout_proc_msg(struct usb_proc_msg *pmsg) 230{ 231 struct callout *c; 232 int delta; 233 234repeat: 235 mtx_lock(&mtx_callout); 236 237 LIST_FOREACH(c, &head_callout, entry) { 238 239 delta = c->timeout - ticks; 240 if (delta < 0) { 241 mtx_unlock(&mtx_callout); 242 243 callout_callback(c); 244 245 goto repeat; 246 } 247 } 248 mtx_unlock(&mtx_callout); 249} 250 251void 252callout_init_mtx(struct callout *c, struct mtx *mtx, int flags) 253{ 254 memset(c, 0, sizeof(*c)); 255 256 if (mtx == NULL) 257 mtx = &Giant; 258 259 c->mtx = mtx; 260 c->flags = (flags & CALLOUT_RETURNUNLOCKED); 261} 262 263void 264callout_reset(struct callout *c, int to_ticks, 265 void (*func) (void *), void *arg) 266{ 267 callout_stop(c); 268 269 c->func = func; 270 c->arg = arg; 271 c->timeout = ticks + to_ticks; 272 273 mtx_lock(&mtx_callout); 274 LIST_INSERT_HEAD(&head_callout, c, entry); 275 mtx_unlock(&mtx_callout); 276} 277 278void 279callout_stop(struct callout *c) 280{ 281 mtx_lock(&mtx_callout); 282 283 if (c->entry.le_prev != NULL) { 284 LIST_REMOVE(c, entry); 285 c->entry.le_prev = NULL; 286 } 287 mtx_unlock(&mtx_callout); 288 289 c->func = NULL; 290 c->arg = NULL; 291} 292 293void 294callout_drain(struct callout *c) 295{ 296 if (c->mtx == NULL) 297 return; /* not initialised */ 298 299 mtx_lock(c->mtx); 300 callout_stop(c); 301 mtx_unlock(c->mtx); 302} 303 304int 305callout_pending(struct callout *c) 306{ 307 int retval; 308 309 mtx_lock(&mtx_callout); 310 retval = (c->entry.le_prev != NULL); 311 mtx_unlock(&mtx_callout); 312 313 return (retval); 314} 315 316/*------------------------------------------------------------------------* 317 * Implementation of device API 318 *------------------------------------------------------------------------*/ 319 320static const char unknown_string[] = { "unknown" }; 321 322static TAILQ_HEAD(, module_data) module_head = 323 TAILQ_HEAD_INITIALIZER(module_head); 324 325static uint8_t 326devclass_equal(const char *a, const char *b) 327{ 328 char ta, tb; 329 330 if (a == b) 331 return (1); 332 333 while (1) { 334 ta = *a; 335 tb = *b; 336 if (ta != tb) 337 return (0); 338 if (ta == 0) 339 break; 340 a++; 341 b++; 342 } 343 return (1); 344} 345 346int 347bus_generic_resume(device_t dev) 348{ 349 return (0); 350} 351 352int 353bus_generic_shutdown(device_t dev) 354{ 355 return (0); 356} 357 358int 359bus_generic_suspend(device_t dev) 360{ 361 return (0); 362} 363 364int 365bus_generic_print_child(device_t dev, device_t child) 366{ 367 return (0); 368} 369 370void 371bus_generic_driver_added(device_t dev, driver_t *driver) 372{ 373 return; 374} 375 376device_t 377device_get_parent(device_t dev) 378{ 379 return (dev ? dev->dev_parent : NULL); 380} 381 382void 383device_set_interrupt(device_t dev, intr_fn_t *fn, void *arg) 384{ 385 dev->dev_irq_fn = fn; 386 dev->dev_irq_arg = arg; 387} 388 389void 390device_run_interrupts(device_t parent) 391{ 392 device_t child; 393 394 if (parent == NULL) 395 return; 396 397 TAILQ_FOREACH(child, &parent->dev_children, dev_link) { 398 if (child->dev_irq_fn != NULL) 399 (child->dev_irq_fn) (child->dev_irq_arg); 400 } 401} 402 403void 404device_set_ivars(device_t dev, void *ivars) 405{ 406 dev->dev_aux = ivars; 407} 408 409void * 410device_get_ivars(device_t dev) 411{ 412 return (dev ? dev->dev_aux : NULL); 413} 414 415int 416device_get_unit(device_t dev) 417{ 418 return (dev ? dev->dev_unit : 0); 419} 420 421int 422bus_generic_detach(device_t dev) 423{ 424 device_t child; 425 int error; 426 427 if (!dev->dev_attached) 428 return (EBUSY); 429 430 TAILQ_FOREACH(child, &dev->dev_children, dev_link) { 431 if ((error = device_detach(child)) != 0) 432 return (error); 433 } 434 return (0); 435} 436 437const char * 438device_get_nameunit(device_t dev) 439{ 440 if (dev && dev->dev_nameunit[0]) 441 return (dev->dev_nameunit); 442 443 return (unknown_string); 444} 445 446static uint8_t 447devclass_create(devclass_t *dc_pp) 448{ 449 if (dc_pp == NULL) { 450 return (1); 451 } 452 if (dc_pp[0] == NULL) { 453 dc_pp[0] = malloc(sizeof(**(dc_pp)), 454 M_DEVBUF, M_WAITOK | M_ZERO); 455 456 if (dc_pp[0] == NULL) { 457 return (1); 458 } 459 } 460 return (0); 461} 462 463static const struct module_data * 464devclass_find_create(const char *classname) 465{ 466 const struct module_data *mod; 467 468 TAILQ_FOREACH(mod, &module_head, entry) { 469 if (devclass_equal(mod->mod_name, classname)) { 470 if (devclass_create(mod->devclass_pp)) { 471 continue; 472 } 473 return (mod); 474 } 475 } 476 return (NULL); 477} 478 479static uint8_t 480devclass_add_device(const struct module_data *mod, device_t dev) 481{ 482 device_t *pp_dev; 483 device_t *end; 484 uint8_t unit; 485 486 pp_dev = mod->devclass_pp[0]->dev_list; 487 end = pp_dev + DEVCLASS_MAXUNIT; 488 unit = 0; 489 490 while (pp_dev != end) { 491 if (*pp_dev == NULL) { 492 *pp_dev = dev; 493 dev->dev_unit = unit; 494 dev->dev_module = mod; 495 snprintf(dev->dev_nameunit, 496 sizeof(dev->dev_nameunit), 497 "%s%d", device_get_name(dev), unit); 498 return (0); 499 } 500 pp_dev++; 501 unit++; 502 } 503 DPRINTF("Could not add device to devclass.\n"); 504 return (1); 505} 506 507static void 508devclass_delete_device(const struct module_data *mod, device_t dev) 509{ 510 if (mod == NULL) { 511 return; 512 } 513 mod->devclass_pp[0]->dev_list[dev->dev_unit] = NULL; 514 dev->dev_module = NULL; 515} 516 517static device_t 518make_device(device_t parent, const char *name) 519{ 520 device_t dev = NULL; 521 const struct module_data *mod = NULL; 522 523 if (name) { 524 525 mod = devclass_find_create(name); 526 527 if (!mod) { 528 529 DPRINTF("%s:%d:%s: can't find device " 530 "class %s\n", __FILE__, __LINE__, 531 __FUNCTION__, name); 532 533 goto done; 534 } 535 } 536 dev = malloc(sizeof(*dev), 537 M_DEVBUF, M_WAITOK | M_ZERO); 538 539 if (dev == NULL) 540 goto done; 541 542 dev->dev_parent = parent; 543 TAILQ_INIT(&dev->dev_children); 544 545 if (name) { 546 dev->dev_fixed_class = 1; 547 if (devclass_add_device(mod, dev)) { 548 goto error; 549 } 550 } 551done: 552 return (dev); 553 554error: 555 if (dev) { 556 free(dev, M_DEVBUF); 557 } 558 return (NULL); 559} 560 561device_t 562device_add_child(device_t dev, const char *name, int unit) 563{ 564 device_t child; 565 566 if (unit != -1) { 567 device_printf(dev, "Unit is not -1\n"); 568 } 569 child = make_device(dev, name); 570 if (child == NULL) { 571 device_printf(dev, "Could not add child '%s'\n", name); 572 goto done; 573 } 574 if (dev == NULL) { 575 /* no parent */ 576 goto done; 577 } 578 TAILQ_INSERT_TAIL(&dev->dev_children, child, dev_link); 579done: 580 return (child); 581} 582 583int 584device_delete_child(device_t dev, device_t child) 585{ 586 int error = 0; 587 device_t grandchild; 588 589 /* remove children first */ 590 591 while ((grandchild = TAILQ_FIRST(&child->dev_children))) { 592 error = device_delete_child(child, grandchild); 593 if (error) { 594 device_printf(dev, "Error deleting child!\n"); 595 goto done; 596 } 597 } 598 599 error = device_detach(child); 600 601 if (error) 602 goto done; 603 604 devclass_delete_device(child->dev_module, child); 605 606 if (dev != NULL) { 607 /* remove child from parent */ 608 TAILQ_REMOVE(&dev->dev_children, child, dev_link); 609 } 610 free(child, M_DEVBUF); 611 612done: 613 return (error); 614} 615 616int 617device_delete_children(device_t dev) 618{ 619 device_t child; 620 int error = 0; 621 622 while ((child = TAILQ_FIRST(&dev->dev_children))) { 623 error = device_delete_child(dev, child); 624 if (error) { 625 device_printf(dev, "Error deleting child!\n"); 626 break; 627 } 628 } 629 return (error); 630} 631 632void 633device_quiet(device_t dev) 634{ 635 dev->dev_quiet = 1; 636} 637 638const char * 639device_get_desc(device_t dev) 640{ 641 if (dev) 642 return &(dev->dev_desc[0]); 643 return (unknown_string); 644} 645 646static int 647default_method(void) 648{ 649 /* do nothing */ 650 DPRINTF("Default method called\n"); 651 return (0); 652} 653 654void * 655device_get_method(device_t dev, const char *what) 656{ 657 const struct device_method *mtod; 658 659 mtod = dev->dev_module->driver->methods; 660 while (mtod->func != NULL) { 661 if (devclass_equal(mtod->desc, what)) { 662 return (mtod->func); 663 } 664 mtod++; 665 } 666 return ((void *)&default_method); 667} 668 669const char * 670device_get_name(device_t dev) 671{ 672 if (dev == NULL) 673 return (unknown_string); 674 675 return (dev->dev_module->driver->name); 676} 677 678static int 679device_allocate_softc(device_t dev) 680{ 681 const struct module_data *mod; 682 683 mod = dev->dev_module; 684 685 if ((dev->dev_softc_alloc == 0) && 686 (mod->driver->size != 0)) { 687 dev->dev_sc = malloc(mod->driver->size, 688 M_DEVBUF, M_WAITOK | M_ZERO); 689 690 if (dev->dev_sc == NULL) 691 return (ENOMEM); 692 693 dev->dev_softc_alloc = 1; 694 } 695 return (0); 696} 697 698int 699device_probe_and_attach(device_t dev) 700{ 701 const struct module_data *mod; 702 const char *bus_name_parent; 703 704 bus_name_parent = device_get_name(device_get_parent(dev)); 705 706 if (dev->dev_attached) 707 return (0); /* fail-safe */ 708 709 if (dev->dev_fixed_class) { 710 711 mod = dev->dev_module; 712 713 if (DEVICE_PROBE(dev) <= 0) { 714 715 if (device_allocate_softc(dev) == 0) { 716 717 if (DEVICE_ATTACH(dev) == 0) { 718 /* success */ 719 dev->dev_attached = 1; 720 return (0); 721 } 722 } 723 } 724 device_detach(dev); 725 726 goto error; 727 } 728 /* 729 * Else find a module for our device, if any 730 */ 731 732 TAILQ_FOREACH(mod, &module_head, entry) { 733 if (devclass_equal(mod->bus_name, bus_name_parent)) { 734 if (devclass_create(mod->devclass_pp)) { 735 continue; 736 } 737 if (devclass_add_device(mod, dev)) { 738 continue; 739 } 740 if (DEVICE_PROBE(dev) <= 0) { 741 742 if (device_allocate_softc(dev) == 0) { 743 744 if (DEVICE_ATTACH(dev) == 0) { 745 /* success */ 746 dev->dev_attached = 1; 747 return (0); 748 } 749 } 750 } 751 /* else try next driver */ 752 753 device_detach(dev); 754 } 755 } 756 757error: 758 return (ENODEV); 759} 760 761int 762device_detach(device_t dev) 763{ 764 const struct module_data *mod = dev->dev_module; 765 int error; 766 767 if (dev->dev_attached) { 768 769 error = DEVICE_DETACH(dev); 770 if (error) { 771 return error; 772 } 773 dev->dev_attached = 0; 774 } 775 device_set_softc(dev, NULL); 776 777 if (dev->dev_fixed_class == 0) 778 devclass_delete_device(mod, dev); 779 780 return (0); 781} 782 783void 784device_set_softc(device_t dev, void *softc) 785{ 786 if (dev->dev_softc_alloc) { 787 free(dev->dev_sc, M_DEVBUF); 788 dev->dev_sc = NULL; 789 } 790 dev->dev_sc = softc; 791 dev->dev_softc_alloc = 0; 792} 793 794void * 795device_get_softc(device_t dev) 796{ 797 if (dev == NULL) 798 return (NULL); 799 800 return (dev->dev_sc); 801} 802 803int 804device_is_attached(device_t dev) 805{ 806 return (dev->dev_attached); 807} 808 809void 810device_set_desc(device_t dev, const char *desc) 811{ 812 snprintf(dev->dev_desc, sizeof(dev->dev_desc), "%s", desc); 813} 814 815void 816device_set_desc_copy(device_t dev, const char *desc) 817{ 818 device_set_desc(dev, desc); 819} 820 821void * 822devclass_get_softc(devclass_t dc, int unit) 823{ 824 return (device_get_softc(devclass_get_device(dc, unit))); 825} 826 827int 828devclass_get_maxunit(devclass_t dc) 829{ 830 int max_unit = 0; 831 832 if (dc) { 833 max_unit = DEVCLASS_MAXUNIT; 834 while (max_unit--) { 835 if (dc->dev_list[max_unit]) { 836 break; 837 } 838 } 839 max_unit++; 840 } 841 return (max_unit); 842} 843 844device_t 845devclass_get_device(devclass_t dc, int unit) 846{ 847 return (((unit < 0) || (unit >= DEVCLASS_MAXUNIT) || (dc == NULL)) ? 848 NULL : dc->dev_list[unit]); 849} 850 851devclass_t 852devclass_find(const char *classname) 853{ 854 const struct module_data *mod; 855 856 TAILQ_FOREACH(mod, &module_head, entry) { 857 if (devclass_equal(mod->mod_name, classname)) 858 return (mod->devclass_pp[0]); 859 } 860 return (NULL); 861} 862 863void 864module_register(void *data) 865{ 866 struct module_data *mdata = data; 867 868 TAILQ_INSERT_TAIL(&module_head, mdata, entry); 869} 870 871/*------------------------------------------------------------------------* 872 * System startup 873 *------------------------------------------------------------------------*/ 874 875static void 876sysinit_run(const void **ppdata) 877{ 878 const struct sysinit *psys; 879 880 while ((psys = *ppdata) != NULL) { 881 (psys->func) (psys->data); 882 ppdata++; 883 } 884} 885 886/*------------------------------------------------------------------------* 887 * USB process API 888 *------------------------------------------------------------------------*/ 889 890static int usb_do_process(struct usb_process *); 891static int usb_proc_level = -1; 892static struct mtx usb_proc_mtx; 893 894void 895usb_idle(void) 896{ 897 int old_level = usb_proc_level; 898 int old_giant = Giant.owned; 899 int worked; 900 901 device_run_interrupts(usb_pci_root); 902 903 do { 904 worked = 0; 905 Giant.owned = 0; 906 907 while (++usb_proc_level < USB_PROC_MAX) 908 worked |= usb_do_process(usb_process + usb_proc_level); 909 910 usb_proc_level = old_level; 911 Giant.owned = old_giant; 912 913 } while (worked); 914} 915 916void 917usb_init(void) 918{ 919 sysinit_run(sysinit_data); 920} 921 922void 923usb_uninit(void) 924{ 925 sysinit_run(sysuninit_data); 926} 927 928static void 929usb_process_init_sub(struct usb_process *up) 930{ 931 TAILQ_INIT(&up->up_qhead); 932 933 cv_init(&up->up_cv, "-"); 934 cv_init(&up->up_drain, "usbdrain"); 935 936 up->up_mtx = &usb_proc_mtx; 937} 938 939static void 940usb_process_init(void *arg) 941{ 942 uint8_t x; 943 944 mtx_init(&usb_proc_mtx, "usb-proc-mtx", NULL, MTX_DEF | MTX_RECURSE); 945 946 for (x = 0; x != USB_PROC_MAX; x++) 947 usb_process_init_sub(&usb_process[x]); 948 949} 950SYSINIT(usb_process_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, usb_process_init, NULL); 951 952static int 953usb_do_process(struct usb_process *up) 954{ 955 struct usb_proc_msg *pm; 956 int worked = 0; 957 958 mtx_lock(&usb_proc_mtx); 959 960repeat: 961 pm = TAILQ_FIRST(&up->up_qhead); 962 963 if (pm != NULL) { 964 965 worked = 1; 966 967 (pm->pm_callback) (pm); 968 969 if (pm == TAILQ_FIRST(&up->up_qhead)) { 970 /* nothing changed */ 971 TAILQ_REMOVE(&up->up_qhead, pm, pm_qentry); 972 pm->pm_qentry.tqe_prev = NULL; 973 } 974 goto repeat; 975 } 976 mtx_unlock(&usb_proc_mtx); 977 978 return (worked); 979} 980 981void * 982usb_proc_msignal(struct usb_process *up, void *_pm0, void *_pm1) 983{ 984 struct usb_proc_msg *pm0 = _pm0; 985 struct usb_proc_msg *pm1 = _pm1; 986 struct usb_proc_msg *pm2; 987 usb_size_t d; 988 uint8_t t; 989 990 t = 0; 991 992 if (pm0->pm_qentry.tqe_prev) { 993 t |= 1; 994 } 995 if (pm1->pm_qentry.tqe_prev) { 996 t |= 2; 997 } 998 if (t == 0) { 999 /* 1000 * No entries are queued. Queue "pm0" and use the existing 1001 * message number. 1002 */ 1003 pm2 = pm0; 1004 } else if (t == 1) { 1005 /* Check if we need to increment the message number. */ 1006 if (pm0->pm_num == up->up_msg_num) { 1007 up->up_msg_num++; 1008 } 1009 pm2 = pm1; 1010 } else if (t == 2) { 1011 /* Check if we need to increment the message number. */ 1012 if (pm1->pm_num == up->up_msg_num) { 1013 up->up_msg_num++; 1014 } 1015 pm2 = pm0; 1016 } else if (t == 3) { 1017 /* 1018 * Both entries are queued. Re-queue the entry closest to 1019 * the end. 1020 */ 1021 d = (pm1->pm_num - pm0->pm_num); 1022 1023 /* Check sign after subtraction */ 1024 if (d & 0x80000000) { 1025 pm2 = pm0; 1026 } else { 1027 pm2 = pm1; 1028 } 1029 1030 TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry); 1031 } else { 1032 pm2 = NULL; /* panic - should not happen */ 1033 } 1034 1035 /* Put message last on queue */ 1036 1037 pm2->pm_num = up->up_msg_num; 1038 TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry); 1039 1040 return (pm2); 1041} 1042 1043/*------------------------------------------------------------------------* 1044 * usb_proc_is_gone 1045 * 1046 * Return values: 1047 * 0: USB process is running 1048 * Else: USB process is tearing down 1049 *------------------------------------------------------------------------*/ 1050uint8_t 1051usb_proc_is_gone(struct usb_process *up) 1052{ 1053 return (0); 1054} 1055 1056/*------------------------------------------------------------------------* 1057 * usb_proc_mwait 1058 * 1059 * This function will return when the USB process message pointed to 1060 * by "pm" is no longer on a queue. This function must be called 1061 * having "usb_proc_mtx" locked. 1062 *------------------------------------------------------------------------*/ 1063void 1064usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1) 1065{ 1066 struct usb_proc_msg *pm0 = _pm0; 1067 struct usb_proc_msg *pm1 = _pm1; 1068 1069 /* Just remove the messages from the queue. */ 1070 if (pm0->pm_qentry.tqe_prev) { 1071 TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry); 1072 pm0->pm_qentry.tqe_prev = NULL; 1073 } 1074 if (pm1->pm_qentry.tqe_prev) { 1075 TAILQ_REMOVE(&up->up_qhead, pm1, pm_qentry); 1076 pm1->pm_qentry.tqe_prev = NULL; 1077 } 1078} 1079 1080/*------------------------------------------------------------------------* 1081 * SYSTEM attach 1082 *------------------------------------------------------------------------*/ 1083 1084static device_method_t pci_methods[] = { 1085 DEVMETHOD_END 1086}; 1087 1088static driver_t pci_driver = { 1089 .name = "pci", 1090 .methods = pci_methods, 1091}; 1092 1093static devclass_t pci_devclass; 1094 1095DRIVER_MODULE(pci, pci, pci_driver, pci_devclass, 0, 0); 1096 1097static const char *usb_pci_devices[] = { 1098#ifdef USB_PROBE_LIST 1099 USB_PROBE_LIST 1100#endif 1101}; 1102 1103#define USB_PCI_USB_MAX (sizeof(usb_pci_devices) / sizeof(void *)) 1104 1105static device_t usb_pci_dev[USB_PCI_USB_MAX]; 1106 1107static void 1108usb_pci_mod_load(void *arg) 1109{ 1110 uint32_t x; 1111 1112 usb_pci_root = device_add_child(NULL, "pci", -1); 1113 if (usb_pci_root == NULL) 1114 return; 1115 1116 for (x = 0; x != USB_PCI_USB_MAX; x++) { 1117 usb_pci_dev[x] = device_add_child(usb_pci_root, usb_pci_devices[x], -1); 1118 if (usb_pci_dev[x] == NULL) 1119 continue; 1120 if (device_probe_and_attach(usb_pci_dev[x])) { 1121 device_printf(usb_pci_dev[x], 1122 "WARNING: Probe and attach failed!\n"); 1123 } 1124 } 1125} 1126SYSINIT(usb_pci_mod_load, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_load, 0); 1127 1128static void 1129usb_pci_mod_unload(void *arg) 1130{ 1131 uint32_t x; 1132 1133 for (x = 0; x != USB_PCI_USB_MAX; x++) { 1134 if (usb_pci_dev[x]) { 1135 device_detach(usb_pci_dev[x]); 1136 device_delete_child(usb_pci_root, usb_pci_dev[x]); 1137 } 1138 } 1139 if (usb_pci_root) 1140 device_delete_child(NULL, usb_pci_root); 1141} 1142SYSUNINIT(usb_pci_mod_unload, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_unload, 0); 1143 1144/*------------------------------------------------------------------------* 1145 * MALLOC API 1146 *------------------------------------------------------------------------*/ 1147 1148#define USB_POOL_ALIGN 8 1149 1150static uint8_t usb_pool[USB_POOL_SIZE] __aligned(USB_POOL_ALIGN); 1151static uint32_t usb_pool_rem = USB_POOL_SIZE; 1152static uint32_t usb_pool_entries; 1153 1154struct malloc_hdr { 1155 TAILQ_ENTRY(malloc_hdr) entry; 1156 uint32_t size; 1157} __aligned(USB_POOL_ALIGN); 1158 1159static TAILQ_HEAD(, malloc_hdr) malloc_head = 1160 TAILQ_HEAD_INITIALIZER(malloc_head); 1161 1162void * 1163usb_malloc(unsigned long size) 1164{ 1165 struct malloc_hdr *hdr; 1166 1167 size = (size + USB_POOL_ALIGN - 1) & ~(USB_POOL_ALIGN - 1); 1168 size += sizeof(struct malloc_hdr); 1169 1170 TAILQ_FOREACH(hdr, &malloc_head, entry) { 1171 if (hdr->size == size) 1172 break; 1173 } 1174 1175 if (hdr) { 1176 printf("MALLOC: Entries = %d; Remainder = %d; Size = %d\n", 1177 (int)usb_pool_entries, (int)usb_pool_rem, (int)size); 1178 1179 TAILQ_REMOVE(&malloc_head, hdr, entry); 1180 memset(hdr + 1, 0, hdr->size - sizeof(*hdr)); 1181 return (hdr + 1); 1182 } 1183 if (usb_pool_rem >= size) { 1184 hdr = (void *)(usb_pool + USB_POOL_SIZE - usb_pool_rem); 1185 hdr->size = size; 1186 1187 usb_pool_rem -= size; 1188 usb_pool_entries++; 1189 1190 printf("MALLOC: Entries = %d; Remainder = %d; Size = %d\n", 1191 (int)usb_pool_entries, (int)usb_pool_rem, (int)size); 1192 1193 memset(hdr + 1, 0, hdr->size - sizeof(*hdr)); 1194 return (hdr + 1); 1195 } 1196 return (NULL); 1197} 1198 1199void 1200usb_free(void *arg) 1201{ 1202 struct malloc_hdr *hdr; 1203 1204 if (arg == NULL) 1205 return; 1206 1207 hdr = arg; 1208 hdr--; 1209 1210 TAILQ_INSERT_TAIL(&malloc_head, hdr, entry); 1211} 1212 1213char * 1214usb_strdup(const char *str) 1215{ 1216 char *tmp; 1217 int len; 1218 1219 len = 1 + strlen(str); 1220 1221 tmp = usb_malloc(len); 1222 if (tmp == NULL) 1223 return (NULL); 1224 1225 memcpy(tmp, str, len); 1226 return (tmp); 1227} 1228