bsd_kernel.c revision 266882
1/* $FreeBSD: head/sys/boot/usb/bsd_kernel.c 266882 2014-05-30 13:39:58Z hselasky $ */ 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, driver_filter_t *filter, 384 driver_intr_t *fn, void *arg) 385{ 386 dev->dev_irq_filter = filter; 387 dev->dev_irq_fn = fn; 388 dev->dev_irq_arg = arg; 389} 390 391void 392device_run_interrupts(device_t parent) 393{ 394 device_t child; 395 396 if (parent == NULL) 397 return; 398 399 TAILQ_FOREACH(child, &parent->dev_children, dev_link) { 400 int status; 401 if (child->dev_irq_filter != NULL) 402 status = child->dev_irq_filter(child->dev_irq_arg); 403 else 404 status = FILTER_SCHEDULE_THREAD; 405 406 if (status == FILTER_SCHEDULE_THREAD) { 407 if (child->dev_irq_fn != NULL) 408 (child->dev_irq_fn) (child->dev_irq_arg); 409 } 410 } 411} 412 413void 414device_set_ivars(device_t dev, void *ivars) 415{ 416 dev->dev_aux = ivars; 417} 418 419void * 420device_get_ivars(device_t dev) 421{ 422 return (dev ? dev->dev_aux : NULL); 423} 424 425int 426device_get_unit(device_t dev) 427{ 428 return (dev ? dev->dev_unit : 0); 429} 430 431int 432bus_generic_detach(device_t dev) 433{ 434 device_t child; 435 int error; 436 437 if (!dev->dev_attached) 438 return (EBUSY); 439 440 TAILQ_FOREACH(child, &dev->dev_children, dev_link) { 441 if ((error = device_detach(child)) != 0) 442 return (error); 443 } 444 return (0); 445} 446 447const char * 448device_get_nameunit(device_t dev) 449{ 450 if (dev && dev->dev_nameunit[0]) 451 return (dev->dev_nameunit); 452 453 return (unknown_string); 454} 455 456static uint8_t 457devclass_create(devclass_t *dc_pp) 458{ 459 if (dc_pp == NULL) { 460 return (1); 461 } 462 if (dc_pp[0] == NULL) { 463 dc_pp[0] = malloc(sizeof(**(dc_pp)), 464 M_DEVBUF, M_WAITOK | M_ZERO); 465 466 if (dc_pp[0] == NULL) { 467 return (1); 468 } 469 } 470 return (0); 471} 472 473static const struct module_data * 474devclass_find_create(const char *classname) 475{ 476 const struct module_data *mod; 477 478 TAILQ_FOREACH(mod, &module_head, entry) { 479 if (devclass_equal(mod->mod_name, classname)) { 480 if (devclass_create(mod->devclass_pp)) { 481 continue; 482 } 483 return (mod); 484 } 485 } 486 return (NULL); 487} 488 489static uint8_t 490devclass_add_device(const struct module_data *mod, device_t dev) 491{ 492 device_t *pp_dev; 493 device_t *end; 494 uint8_t unit; 495 496 pp_dev = mod->devclass_pp[0]->dev_list; 497 end = pp_dev + DEVCLASS_MAXUNIT; 498 unit = 0; 499 500 while (pp_dev != end) { 501 if (*pp_dev == NULL) { 502 *pp_dev = dev; 503 dev->dev_unit = unit; 504 dev->dev_module = mod; 505 snprintf(dev->dev_nameunit, 506 sizeof(dev->dev_nameunit), 507 "%s%d", device_get_name(dev), unit); 508 return (0); 509 } 510 pp_dev++; 511 unit++; 512 } 513 DPRINTF("Could not add device to devclass.\n"); 514 return (1); 515} 516 517static void 518devclass_delete_device(const struct module_data *mod, device_t dev) 519{ 520 if (mod == NULL) { 521 return; 522 } 523 mod->devclass_pp[0]->dev_list[dev->dev_unit] = NULL; 524 dev->dev_module = NULL; 525} 526 527static device_t 528make_device(device_t parent, const char *name) 529{ 530 device_t dev = NULL; 531 const struct module_data *mod = NULL; 532 533 if (name) { 534 535 mod = devclass_find_create(name); 536 537 if (!mod) { 538 539 DPRINTF("%s:%d:%s: can't find device " 540 "class %s\n", __FILE__, __LINE__, 541 __FUNCTION__, name); 542 543 goto done; 544 } 545 } 546 dev = malloc(sizeof(*dev), 547 M_DEVBUF, M_WAITOK | M_ZERO); 548 549 if (dev == NULL) 550 goto done; 551 552 dev->dev_parent = parent; 553 TAILQ_INIT(&dev->dev_children); 554 555 if (name) { 556 dev->dev_fixed_class = 1; 557 if (devclass_add_device(mod, dev)) { 558 goto error; 559 } 560 } 561done: 562 return (dev); 563 564error: 565 if (dev) { 566 free(dev, M_DEVBUF); 567 } 568 return (NULL); 569} 570 571device_t 572device_add_child(device_t dev, const char *name, int unit) 573{ 574 device_t child; 575 576 if (unit != -1) { 577 device_printf(dev, "Unit is not -1\n"); 578 } 579 child = make_device(dev, name); 580 if (child == NULL) { 581 device_printf(dev, "Could not add child '%s'\n", name); 582 goto done; 583 } 584 if (dev == NULL) { 585 /* no parent */ 586 goto done; 587 } 588 TAILQ_INSERT_TAIL(&dev->dev_children, child, dev_link); 589done: 590 return (child); 591} 592 593int 594device_delete_child(device_t dev, device_t child) 595{ 596 int error = 0; 597 device_t grandchild; 598 599 /* remove children first */ 600 601 while ((grandchild = TAILQ_FIRST(&child->dev_children))) { 602 error = device_delete_child(child, grandchild); 603 if (error) { 604 device_printf(dev, "Error deleting child!\n"); 605 goto done; 606 } 607 } 608 609 error = device_detach(child); 610 611 if (error) 612 goto done; 613 614 devclass_delete_device(child->dev_module, child); 615 616 if (dev != NULL) { 617 /* remove child from parent */ 618 TAILQ_REMOVE(&dev->dev_children, child, dev_link); 619 } 620 free(child, M_DEVBUF); 621 622done: 623 return (error); 624} 625 626int 627device_delete_children(device_t dev) 628{ 629 device_t child; 630 int error = 0; 631 632 while ((child = TAILQ_FIRST(&dev->dev_children))) { 633 error = device_delete_child(dev, child); 634 if (error) { 635 device_printf(dev, "Error deleting child!\n"); 636 break; 637 } 638 } 639 return (error); 640} 641 642void 643device_quiet(device_t dev) 644{ 645 dev->dev_quiet = 1; 646} 647 648const char * 649device_get_desc(device_t dev) 650{ 651 if (dev) 652 return &(dev->dev_desc[0]); 653 return (unknown_string); 654} 655 656static int 657default_method(void) 658{ 659 /* do nothing */ 660 DPRINTF("Default method called\n"); 661 return (0); 662} 663 664void * 665device_get_method(device_t dev, const char *what) 666{ 667 const struct device_method *mtod; 668 669 mtod = dev->dev_module->driver->methods; 670 while (mtod->func != NULL) { 671 if (devclass_equal(mtod->desc, what)) { 672 return (mtod->func); 673 } 674 mtod++; 675 } 676 return ((void *)&default_method); 677} 678 679const char * 680device_get_name(device_t dev) 681{ 682 if (dev == NULL) 683 return (unknown_string); 684 685 return (dev->dev_module->driver->name); 686} 687 688static int 689device_allocate_softc(device_t dev) 690{ 691 const struct module_data *mod; 692 693 mod = dev->dev_module; 694 695 if ((dev->dev_softc_alloc == 0) && 696 (mod->driver->size != 0)) { 697 dev->dev_sc = malloc(mod->driver->size, 698 M_DEVBUF, M_WAITOK | M_ZERO); 699 700 if (dev->dev_sc == NULL) 701 return (ENOMEM); 702 703 dev->dev_softc_alloc = 1; 704 } 705 return (0); 706} 707 708int 709device_probe_and_attach(device_t dev) 710{ 711 const struct module_data *mod; 712 const char *bus_name_parent; 713 714 bus_name_parent = device_get_name(device_get_parent(dev)); 715 716 if (dev->dev_attached) 717 return (0); /* fail-safe */ 718 719 if (dev->dev_fixed_class) { 720 721 mod = dev->dev_module; 722 723 if (DEVICE_PROBE(dev) <= 0) { 724 725 if (device_allocate_softc(dev) == 0) { 726 727 if (DEVICE_ATTACH(dev) == 0) { 728 /* success */ 729 dev->dev_attached = 1; 730 return (0); 731 } 732 } 733 } 734 device_detach(dev); 735 736 goto error; 737 } 738 /* 739 * Else find a module for our device, if any 740 */ 741 742 TAILQ_FOREACH(mod, &module_head, entry) { 743 if (devclass_equal(mod->bus_name, bus_name_parent)) { 744 if (devclass_create(mod->devclass_pp)) { 745 continue; 746 } 747 if (devclass_add_device(mod, dev)) { 748 continue; 749 } 750 if (DEVICE_PROBE(dev) <= 0) { 751 752 if (device_allocate_softc(dev) == 0) { 753 754 if (DEVICE_ATTACH(dev) == 0) { 755 /* success */ 756 dev->dev_attached = 1; 757 return (0); 758 } 759 } 760 } 761 /* else try next driver */ 762 763 device_detach(dev); 764 } 765 } 766 767error: 768 return (ENODEV); 769} 770 771int 772device_detach(device_t dev) 773{ 774 const struct module_data *mod = dev->dev_module; 775 int error; 776 777 if (dev->dev_attached) { 778 779 error = DEVICE_DETACH(dev); 780 if (error) { 781 return error; 782 } 783 dev->dev_attached = 0; 784 } 785 device_set_softc(dev, NULL); 786 787 if (dev->dev_fixed_class == 0) 788 devclass_delete_device(mod, dev); 789 790 return (0); 791} 792 793void 794device_set_softc(device_t dev, void *softc) 795{ 796 if (dev->dev_softc_alloc) { 797 free(dev->dev_sc, M_DEVBUF); 798 dev->dev_sc = NULL; 799 } 800 dev->dev_sc = softc; 801 dev->dev_softc_alloc = 0; 802} 803 804void * 805device_get_softc(device_t dev) 806{ 807 if (dev == NULL) 808 return (NULL); 809 810 return (dev->dev_sc); 811} 812 813int 814device_is_attached(device_t dev) 815{ 816 return (dev->dev_attached); 817} 818 819void 820device_set_desc(device_t dev, const char *desc) 821{ 822 snprintf(dev->dev_desc, sizeof(dev->dev_desc), "%s", desc); 823} 824 825void 826device_set_desc_copy(device_t dev, const char *desc) 827{ 828 device_set_desc(dev, desc); 829} 830 831void * 832devclass_get_softc(devclass_t dc, int unit) 833{ 834 return (device_get_softc(devclass_get_device(dc, unit))); 835} 836 837int 838devclass_get_maxunit(devclass_t dc) 839{ 840 int max_unit = 0; 841 842 if (dc) { 843 max_unit = DEVCLASS_MAXUNIT; 844 while (max_unit--) { 845 if (dc->dev_list[max_unit]) { 846 break; 847 } 848 } 849 max_unit++; 850 } 851 return (max_unit); 852} 853 854device_t 855devclass_get_device(devclass_t dc, int unit) 856{ 857 return (((unit < 0) || (unit >= DEVCLASS_MAXUNIT) || (dc == NULL)) ? 858 NULL : dc->dev_list[unit]); 859} 860 861devclass_t 862devclass_find(const char *classname) 863{ 864 const struct module_data *mod; 865 866 TAILQ_FOREACH(mod, &module_head, entry) { 867 if (devclass_equal(mod->mod_name, classname)) 868 return (mod->devclass_pp[0]); 869 } 870 return (NULL); 871} 872 873void 874module_register(void *data) 875{ 876 struct module_data *mdata = data; 877 878 TAILQ_INSERT_TAIL(&module_head, mdata, entry); 879} 880 881/*------------------------------------------------------------------------* 882 * System startup 883 *------------------------------------------------------------------------*/ 884 885static void 886sysinit_run(const void **ppdata) 887{ 888 const struct sysinit *psys; 889 890 while ((psys = *ppdata) != NULL) { 891 (psys->func) (psys->data); 892 ppdata++; 893 } 894} 895 896/*------------------------------------------------------------------------* 897 * USB process API 898 *------------------------------------------------------------------------*/ 899 900static int usb_do_process(struct usb_process *); 901static int usb_proc_level = -1; 902static struct mtx usb_proc_mtx; 903 904void 905usb_idle(void) 906{ 907 int old_level = usb_proc_level; 908 int old_giant = Giant.owned; 909 int worked; 910 911 device_run_interrupts(usb_pci_root); 912 913 do { 914 worked = 0; 915 Giant.owned = 0; 916 917 while (++usb_proc_level < USB_PROC_MAX) 918 worked |= usb_do_process(usb_process + usb_proc_level); 919 920 usb_proc_level = old_level; 921 Giant.owned = old_giant; 922 923 } while (worked); 924} 925 926void 927usb_init(void) 928{ 929 sysinit_run(sysinit_data); 930} 931 932void 933usb_uninit(void) 934{ 935 sysinit_run(sysuninit_data); 936} 937 938static void 939usb_process_init_sub(struct usb_process *up) 940{ 941 TAILQ_INIT(&up->up_qhead); 942 943 cv_init(&up->up_cv, "-"); 944 cv_init(&up->up_drain, "usbdrain"); 945 946 up->up_mtx = &usb_proc_mtx; 947} 948 949static void 950usb_process_init(void *arg) 951{ 952 uint8_t x; 953 954 mtx_init(&usb_proc_mtx, "usb-proc-mtx", NULL, MTX_DEF | MTX_RECURSE); 955 956 for (x = 0; x != USB_PROC_MAX; x++) 957 usb_process_init_sub(&usb_process[x]); 958 959} 960SYSINIT(usb_process_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, usb_process_init, NULL); 961 962static int 963usb_do_process(struct usb_process *up) 964{ 965 struct usb_proc_msg *pm; 966 int worked = 0; 967 968 mtx_lock(&usb_proc_mtx); 969 970repeat: 971 pm = TAILQ_FIRST(&up->up_qhead); 972 973 if (pm != NULL) { 974 975 worked = 1; 976 977 (pm->pm_callback) (pm); 978 979 if (pm == TAILQ_FIRST(&up->up_qhead)) { 980 /* nothing changed */ 981 TAILQ_REMOVE(&up->up_qhead, pm, pm_qentry); 982 pm->pm_qentry.tqe_prev = NULL; 983 } 984 goto repeat; 985 } 986 mtx_unlock(&usb_proc_mtx); 987 988 return (worked); 989} 990 991void * 992usb_proc_msignal(struct usb_process *up, void *_pm0, void *_pm1) 993{ 994 struct usb_proc_msg *pm0 = _pm0; 995 struct usb_proc_msg *pm1 = _pm1; 996 struct usb_proc_msg *pm2; 997 usb_size_t d; 998 uint8_t t; 999 1000 t = 0; 1001 1002 if (pm0->pm_qentry.tqe_prev) { 1003 t |= 1; 1004 } 1005 if (pm1->pm_qentry.tqe_prev) { 1006 t |= 2; 1007 } 1008 if (t == 0) { 1009 /* 1010 * No entries are queued. Queue "pm0" and use the existing 1011 * message number. 1012 */ 1013 pm2 = pm0; 1014 } else if (t == 1) { 1015 /* Check if we need to increment the message number. */ 1016 if (pm0->pm_num == up->up_msg_num) { 1017 up->up_msg_num++; 1018 } 1019 pm2 = pm1; 1020 } else if (t == 2) { 1021 /* Check if we need to increment the message number. */ 1022 if (pm1->pm_num == up->up_msg_num) { 1023 up->up_msg_num++; 1024 } 1025 pm2 = pm0; 1026 } else if (t == 3) { 1027 /* 1028 * Both entries are queued. Re-queue the entry closest to 1029 * the end. 1030 */ 1031 d = (pm1->pm_num - pm0->pm_num); 1032 1033 /* Check sign after subtraction */ 1034 if (d & 0x80000000) { 1035 pm2 = pm0; 1036 } else { 1037 pm2 = pm1; 1038 } 1039 1040 TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry); 1041 } else { 1042 pm2 = NULL; /* panic - should not happen */ 1043 } 1044 1045 /* Put message last on queue */ 1046 1047 pm2->pm_num = up->up_msg_num; 1048 TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry); 1049 1050 return (pm2); 1051} 1052 1053/*------------------------------------------------------------------------* 1054 * usb_proc_is_gone 1055 * 1056 * Return values: 1057 * 0: USB process is running 1058 * Else: USB process is tearing down 1059 *------------------------------------------------------------------------*/ 1060uint8_t 1061usb_proc_is_gone(struct usb_process *up) 1062{ 1063 return (0); 1064} 1065 1066/*------------------------------------------------------------------------* 1067 * usb_proc_mwait 1068 * 1069 * This function will return when the USB process message pointed to 1070 * by "pm" is no longer on a queue. This function must be called 1071 * having "usb_proc_mtx" locked. 1072 *------------------------------------------------------------------------*/ 1073void 1074usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1) 1075{ 1076 struct usb_proc_msg *pm0 = _pm0; 1077 struct usb_proc_msg *pm1 = _pm1; 1078 1079 /* Just remove the messages from the queue. */ 1080 if (pm0->pm_qentry.tqe_prev) { 1081 TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry); 1082 pm0->pm_qentry.tqe_prev = NULL; 1083 } 1084 if (pm1->pm_qentry.tqe_prev) { 1085 TAILQ_REMOVE(&up->up_qhead, pm1, pm_qentry); 1086 pm1->pm_qentry.tqe_prev = NULL; 1087 } 1088} 1089 1090/*------------------------------------------------------------------------* 1091 * SYSTEM attach 1092 *------------------------------------------------------------------------*/ 1093 1094#ifdef USB_PCI_PROBE_LIST 1095static device_method_t pci_methods[] = { 1096 DEVMETHOD_END 1097}; 1098 1099static driver_t pci_driver = { 1100 .name = "pci", 1101 .methods = pci_methods, 1102}; 1103 1104static devclass_t pci_devclass; 1105 1106DRIVER_MODULE(pci, pci, pci_driver, pci_devclass, 0, 0); 1107 1108static const char *usb_pci_devices[] = { 1109 USB_PCI_PROBE_LIST 1110}; 1111 1112#define USB_PCI_USB_MAX (sizeof(usb_pci_devices) / sizeof(void *)) 1113 1114static device_t usb_pci_dev[USB_PCI_USB_MAX]; 1115 1116static void 1117usb_pci_mod_load(void *arg) 1118{ 1119 uint32_t x; 1120 1121 usb_pci_root = device_add_child(NULL, "pci", -1); 1122 if (usb_pci_root == NULL) 1123 return; 1124 1125 for (x = 0; x != USB_PCI_USB_MAX; x++) { 1126 usb_pci_dev[x] = device_add_child(usb_pci_root, usb_pci_devices[x], -1); 1127 if (usb_pci_dev[x] == NULL) 1128 continue; 1129 if (device_probe_and_attach(usb_pci_dev[x])) { 1130 device_printf(usb_pci_dev[x], 1131 "WARNING: Probe and attach failed!\n"); 1132 } 1133 } 1134} 1135SYSINIT(usb_pci_mod_load, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_load, 0); 1136 1137static void 1138usb_pci_mod_unload(void *arg) 1139{ 1140 uint32_t x; 1141 1142 for (x = 0; x != USB_PCI_USB_MAX; x++) { 1143 if (usb_pci_dev[x]) { 1144 device_detach(usb_pci_dev[x]); 1145 device_delete_child(usb_pci_root, usb_pci_dev[x]); 1146 } 1147 } 1148 if (usb_pci_root) 1149 device_delete_child(NULL, usb_pci_root); 1150} 1151SYSUNINIT(usb_pci_mod_unload, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_unload, 0); 1152#endif 1153 1154/*------------------------------------------------------------------------* 1155 * MALLOC API 1156 *------------------------------------------------------------------------*/ 1157 1158#ifndef HAVE_MALLOC 1159#define USB_POOL_ALIGN 8 1160 1161static uint8_t usb_pool[USB_POOL_SIZE] __aligned(USB_POOL_ALIGN); 1162static uint32_t usb_pool_rem = USB_POOL_SIZE; 1163static uint32_t usb_pool_entries; 1164 1165struct malloc_hdr { 1166 TAILQ_ENTRY(malloc_hdr) entry; 1167 uint32_t size; 1168} __aligned(USB_POOL_ALIGN); 1169 1170static TAILQ_HEAD(, malloc_hdr) malloc_head = 1171 TAILQ_HEAD_INITIALIZER(malloc_head); 1172 1173void * 1174usb_malloc(unsigned long size) 1175{ 1176 struct malloc_hdr *hdr; 1177 1178 size = (size + USB_POOL_ALIGN - 1) & ~(USB_POOL_ALIGN - 1); 1179 size += sizeof(struct malloc_hdr); 1180 1181 TAILQ_FOREACH(hdr, &malloc_head, entry) { 1182 if (hdr->size == size) 1183 break; 1184 } 1185 1186 if (hdr) { 1187 DPRINTF("MALLOC: Entries = %d; Remainder = %d; Size = %d\n", 1188 (int)usb_pool_entries, (int)usb_pool_rem, (int)size); 1189 1190 TAILQ_REMOVE(&malloc_head, hdr, entry); 1191 memset(hdr + 1, 0, hdr->size - sizeof(*hdr)); 1192 return (hdr + 1); 1193 } 1194 if (usb_pool_rem >= size) { 1195 hdr = (void *)(usb_pool + USB_POOL_SIZE - usb_pool_rem); 1196 hdr->size = size; 1197 1198 usb_pool_rem -= size; 1199 usb_pool_entries++; 1200 1201 DPRINTF("MALLOC: Entries = %d; Remainder = %d; Size = %d\n", 1202 (int)usb_pool_entries, (int)usb_pool_rem, (int)size); 1203 1204 memset(hdr + 1, 0, hdr->size - sizeof(*hdr)); 1205 return (hdr + 1); 1206 } 1207 return (NULL); 1208} 1209 1210void 1211usb_free(void *arg) 1212{ 1213 struct malloc_hdr *hdr; 1214 1215 if (arg == NULL) 1216 return; 1217 1218 hdr = arg; 1219 hdr--; 1220 1221 TAILQ_INSERT_TAIL(&malloc_head, hdr, entry); 1222} 1223#endif 1224 1225char * 1226usb_strdup(const char *str) 1227{ 1228 char *tmp; 1229 int len; 1230 1231 len = 1 + strlen(str); 1232 1233 tmp = malloc(len,XXX,XXX); 1234 if (tmp == NULL) 1235 return (NULL); 1236 1237 memcpy(tmp, str, len); 1238 return (tmp); 1239} 1240