196 197 /* sentinel */ 198 {0 /* null id */, "unknown", CB_UNKNOWN}, 199}; 200 201/* sysctl vars */ 202SYSCTL_NODE(_hw, OID_AUTO, cbb, CTLFLAG_RD, 0, "CBB parameters"); 203 204/* There's no way to say TUNEABLE_LONG to get the right types */ 205u_long pccbb_start_mem = PCCBB_START_MEM; 206TUNABLE_INT("hw.cbb.start_memory", (int *)&pccbb_start_mem); 207SYSCTL_ULONG(_hw_cbb, OID_AUTO, start_memory, CTLFLAG_RW, 208 &pccbb_start_mem, PCCBB_START_MEM, 209 "Starting address for memory allocations"); 210 211u_long pccbb_start_16_io = PCCBB_START_16_IO; 212TUNABLE_INT("hw.cbb.start_16_io", (int *)&pccbb_start_16_io); 213SYSCTL_ULONG(_hw_cbb, OID_AUTO, start_16_io, CTLFLAG_RW, 214 &pccbb_start_16_io, PCCBB_START_16_IO, 215 "Starting ioport for 16-bit cards"); 216 217u_long pccbb_start_32_io = PCCBB_START_32_IO; 218TUNABLE_INT("hw.cbb.start_32_io", (int *)&pccbb_start_32_io); 219SYSCTL_ULONG(_hw_cbb, OID_AUTO, start_32_io, CTLFLAG_RW, 220 &pccbb_start_32_io, PCCBB_START_32_IO, 221 "Starting ioport for 32-bit cards"); 222 223int cbb_debug = 0; 224TUNABLE_INT("hw.cbb.debug", &cbb_debug); 225SYSCTL_ULONG(_hw_cbb, OID_AUTO, debug, CTLFLAG_RW, &cbb_debug, 0, 226 "Verbose cardbus bridge debugging"); 227 228static int pccbb_chipset(uint32_t pci_id, const char **namep); 229static int pccbb_probe(device_t brdev); 230static void pccbb_chipinit(struct pccbb_softc *sc); 231static int pccbb_attach(device_t brdev); 232static int pccbb_detach(device_t brdev); 233static int pccbb_shutdown(device_t brdev); 234static void pccbb_driver_added(device_t brdev, driver_t *driver); 235static void pccbb_child_detached(device_t brdev, device_t child); 236static int pccbb_card_reprobe(device_t brdev, device_t busdev); 237static void pccbb_event_thread(void *arg); 238static void pccbb_insert(struct pccbb_softc *sc); 239static void pccbb_removal(struct pccbb_softc *sc); 240static void pccbb_intr(void *arg); 241static int pccbb_detect_voltage(device_t brdev); 242static int pccbb_power(device_t brdev, int volts); 243static void pccbb_cardbus_reset(device_t brdev); 244static int pccbb_cardbus_power_enable_socket(device_t brdev, 245 device_t child); 246static void pccbb_cardbus_power_disable_socket(device_t brdev, 247 device_t child); 248static int pccbb_cardbus_io_open(device_t brdev, int win, uint32_t start, 249 uint32_t end); 250static int pccbb_cardbus_mem_open(device_t brdev, int win, 251 uint32_t start, uint32_t end); 252static void pccbb_cardbus_auto_open(struct pccbb_softc *sc, int type); 253static int pccbb_cardbus_activate_resource(device_t brdev, device_t child, 254 int type, int rid, struct resource *res); 255static int pccbb_cardbus_deactivate_resource(device_t brdev, 256 device_t child, int type, int rid, struct resource *res); 257static struct resource *pccbb_cardbus_alloc_resource(device_t brdev, 258 device_t child, int type, int *rid, u_long start, 259 u_long end, u_long count, uint flags); 260static int pccbb_cardbus_release_resource(device_t brdev, device_t child, 261 int type, int rid, struct resource *res); 262static int pccbb_power_enable_socket(device_t brdev, device_t child); 263static void pccbb_power_disable_socket(device_t brdev, device_t child); 264static int pccbb_activate_resource(device_t brdev, device_t child, 265 int type, int rid, struct resource *r); 266static int pccbb_deactivate_resource(device_t brdev, device_t child, 267 int type, int rid, struct resource *r); 268static struct resource *pccbb_alloc_resource(device_t brdev, device_t child, 269 int type, int *rid, u_long start, u_long end, u_long count, 270 uint flags); 271static int pccbb_release_resource(device_t brdev, device_t child, 272 int type, int rid, struct resource *r); 273static int pccbb_read_ivar(device_t brdev, device_t child, int which, 274 uintptr_t *result); 275static int pccbb_write_ivar(device_t brdev, device_t child, int which, 276 uintptr_t value); 277static int pccbb_maxslots(device_t brdev); 278static uint32_t pccbb_read_config(device_t brdev, int b, int s, int f, 279 int reg, int width); 280static void pccbb_write_config(device_t brdev, int b, int s, int f, 281 int reg, uint32_t val, int width); 282 283/* 284 */ 285static __inline void 286pccbb_set(struct pccbb_softc *sc, uint32_t reg, uint32_t val) 287{ 288 bus_space_write_4(sc->bst, sc->bsh, reg, val); 289} 290 291static __inline uint32_t 292pccbb_get(struct pccbb_softc *sc, uint32_t reg) 293{ 294 return (bus_space_read_4(sc->bst, sc->bsh, reg)); 295} 296 297static __inline void 298pccbb_setb(struct pccbb_softc *sc, uint32_t reg, uint32_t bits) 299{ 300 pccbb_set(sc, reg, pccbb_get(sc, reg) | bits); 301} 302 303static __inline void 304pccbb_clrb(struct pccbb_softc *sc, uint32_t reg, uint32_t bits) 305{ 306 pccbb_set(sc, reg, pccbb_get(sc, reg) & ~bits); 307} 308
| 181 182 /* sentinel */ 183 {0 /* null id */, "unknown", CB_UNKNOWN}, 184}; 185 186/* sysctl vars */ 187SYSCTL_NODE(_hw, OID_AUTO, cbb, CTLFLAG_RD, 0, "CBB parameters"); 188 189/* There's no way to say TUNEABLE_LONG to get the right types */ 190u_long pccbb_start_mem = PCCBB_START_MEM; 191TUNABLE_INT("hw.cbb.start_memory", (int *)&pccbb_start_mem); 192SYSCTL_ULONG(_hw_cbb, OID_AUTO, start_memory, CTLFLAG_RW, 193 &pccbb_start_mem, PCCBB_START_MEM, 194 "Starting address for memory allocations"); 195 196u_long pccbb_start_16_io = PCCBB_START_16_IO; 197TUNABLE_INT("hw.cbb.start_16_io", (int *)&pccbb_start_16_io); 198SYSCTL_ULONG(_hw_cbb, OID_AUTO, start_16_io, CTLFLAG_RW, 199 &pccbb_start_16_io, PCCBB_START_16_IO, 200 "Starting ioport for 16-bit cards"); 201 202u_long pccbb_start_32_io = PCCBB_START_32_IO; 203TUNABLE_INT("hw.cbb.start_32_io", (int *)&pccbb_start_32_io); 204SYSCTL_ULONG(_hw_cbb, OID_AUTO, start_32_io, CTLFLAG_RW, 205 &pccbb_start_32_io, PCCBB_START_32_IO, 206 "Starting ioport for 32-bit cards"); 207 208int cbb_debug = 0; 209TUNABLE_INT("hw.cbb.debug", &cbb_debug); 210SYSCTL_ULONG(_hw_cbb, OID_AUTO, debug, CTLFLAG_RW, &cbb_debug, 0, 211 "Verbose cardbus bridge debugging"); 212 213static int pccbb_chipset(uint32_t pci_id, const char **namep); 214static int pccbb_probe(device_t brdev); 215static void pccbb_chipinit(struct pccbb_softc *sc); 216static int pccbb_attach(device_t brdev); 217static int pccbb_detach(device_t brdev); 218static int pccbb_shutdown(device_t brdev); 219static void pccbb_driver_added(device_t brdev, driver_t *driver); 220static void pccbb_child_detached(device_t brdev, device_t child); 221static int pccbb_card_reprobe(device_t brdev, device_t busdev); 222static void pccbb_event_thread(void *arg); 223static void pccbb_insert(struct pccbb_softc *sc); 224static void pccbb_removal(struct pccbb_softc *sc); 225static void pccbb_intr(void *arg); 226static int pccbb_detect_voltage(device_t brdev); 227static int pccbb_power(device_t brdev, int volts); 228static void pccbb_cardbus_reset(device_t brdev); 229static int pccbb_cardbus_power_enable_socket(device_t brdev, 230 device_t child); 231static void pccbb_cardbus_power_disable_socket(device_t brdev, 232 device_t child); 233static int pccbb_cardbus_io_open(device_t brdev, int win, uint32_t start, 234 uint32_t end); 235static int pccbb_cardbus_mem_open(device_t brdev, int win, 236 uint32_t start, uint32_t end); 237static void pccbb_cardbus_auto_open(struct pccbb_softc *sc, int type); 238static int pccbb_cardbus_activate_resource(device_t brdev, device_t child, 239 int type, int rid, struct resource *res); 240static int pccbb_cardbus_deactivate_resource(device_t brdev, 241 device_t child, int type, int rid, struct resource *res); 242static struct resource *pccbb_cardbus_alloc_resource(device_t brdev, 243 device_t child, int type, int *rid, u_long start, 244 u_long end, u_long count, uint flags); 245static int pccbb_cardbus_release_resource(device_t brdev, device_t child, 246 int type, int rid, struct resource *res); 247static int pccbb_power_enable_socket(device_t brdev, device_t child); 248static void pccbb_power_disable_socket(device_t brdev, device_t child); 249static int pccbb_activate_resource(device_t brdev, device_t child, 250 int type, int rid, struct resource *r); 251static int pccbb_deactivate_resource(device_t brdev, device_t child, 252 int type, int rid, struct resource *r); 253static struct resource *pccbb_alloc_resource(device_t brdev, device_t child, 254 int type, int *rid, u_long start, u_long end, u_long count, 255 uint flags); 256static int pccbb_release_resource(device_t brdev, device_t child, 257 int type, int rid, struct resource *r); 258static int pccbb_read_ivar(device_t brdev, device_t child, int which, 259 uintptr_t *result); 260static int pccbb_write_ivar(device_t brdev, device_t child, int which, 261 uintptr_t value); 262static int pccbb_maxslots(device_t brdev); 263static uint32_t pccbb_read_config(device_t brdev, int b, int s, int f, 264 int reg, int width); 265static void pccbb_write_config(device_t brdev, int b, int s, int f, 266 int reg, uint32_t val, int width); 267 268/* 269 */ 270static __inline void 271pccbb_set(struct pccbb_softc *sc, uint32_t reg, uint32_t val) 272{ 273 bus_space_write_4(sc->bst, sc->bsh, reg, val); 274} 275 276static __inline uint32_t 277pccbb_get(struct pccbb_softc *sc, uint32_t reg) 278{ 279 return (bus_space_read_4(sc->bst, sc->bsh, reg)); 280} 281 282static __inline void 283pccbb_setb(struct pccbb_softc *sc, uint32_t reg, uint32_t bits) 284{ 285 pccbb_set(sc, reg, pccbb_get(sc, reg) | bits); 286} 287 288static __inline void 289pccbb_clrb(struct pccbb_softc *sc, uint32_t reg, uint32_t bits) 290{ 291 pccbb_set(sc, reg, pccbb_get(sc, reg) & ~bits); 292} 293
|
624 pccbb_chipinit(sc); 625 626 /* attach children */ 627 sc->cbdev = device_add_child(brdev, "cardbus", -1); 628 if (sc->cbdev == NULL) 629 DEVPRINTF((brdev, "WARNING: cannot add cardbus bus.\n")); 630 else if (device_probe_and_attach(sc->cbdev) != 0) { 631 DEVPRINTF((brdev, "WARNING: cannot attach cardbus bus!\n")); 632 sc->cbdev = NULL; 633 } 634 635 sc->pccarddev = device_add_child(brdev, "pccard", -1); 636 if (sc->pccarddev == NULL) 637 DEVPRINTF((brdev, "WARNING: cannot add pccard bus.\n")); 638 else if (device_probe_and_attach(sc->pccarddev) != 0) { 639 DEVPRINTF((brdev, "WARNING: cannot attach pccard bus.\n")); 640 sc->pccarddev = NULL; 641 } 642 643 /* Map and establish the interrupt. */ 644 rid = 0; 645 sc->irq_res = bus_alloc_resource(brdev, SYS_RES_IRQ, &rid, 0, ~0, 1, 646 RF_SHAREABLE | RF_ACTIVE); 647 if (sc->irq_res == NULL) { 648 printf("pccbb: Unable to map IRQ...\n"); 649 bus_release_resource(brdev, SYS_RES_MEMORY, CBBR_SOCKBASE, 650 sc->base_res); 651 mtx_destroy(&sc->mtx); 652 cv_destroy(&sc->cv); 653 return (ENOMEM); 654 } 655 656 if (bus_setup_intr(brdev, sc->irq_res, INTR_TYPE_AV, pccbb_intr, sc, 657 &sc->intrhand)) { 658 device_printf(brdev, "couldn't establish interrupt"); 659 bus_release_resource(brdev, SYS_RES_IRQ, 0, sc->irq_res); 660 bus_release_resource(brdev, SYS_RES_MEMORY, CBBR_SOCKBASE, 661 sc->base_res); 662 mtx_destroy(&sc->mtx); 663 cv_destroy(&sc->cv); 664 return (ENOMEM); 665 } 666 667 /* reset 16-bit pcmcia bus */ 668 exca_clrb(&sc->exca, EXCA_INTR, EXCA_INTR_RESET); 669 670 /* turn off power */ 671 pccbb_power(brdev, CARD_VCC_0V | CARD_VPP_0V); 672 673 /* CSC Interrupt: Card detect interrupt on */ 674 pccbb_setb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD); 675 676 /* reset interrupt */ 677 pccbb_set(sc, CBB_SOCKET_EVENT, pccbb_get(sc, CBB_SOCKET_EVENT)); 678 679 /* Start the thread */ 680 if (kthread_create(pccbb_event_thread, sc, &sc->event_thread, 0, 681 "%s%d", device_get_name(sc->dev), device_get_unit(sc->dev))) { 682 device_printf (sc->dev, "unable to create event thread.\n"); 683 panic ("pccbb_create_event_thread"); 684 } 685 686 return (0); 687} 688 689static int 690pccbb_detach(device_t brdev) 691{ 692 struct pccbb_softc *sc = device_get_softc(brdev); 693 int numdevs; 694 device_t *devlist; 695 int tmp; 696 int error; 697 698 device_get_children(brdev, &devlist, &numdevs); 699 700 error = 0; 701 for (tmp = 0; tmp < numdevs; tmp++) { 702 if (device_detach(devlist[tmp]) == 0) 703 device_delete_child(brdev, devlist[tmp]); 704 else 705 error++; 706 } 707 free(devlist, M_TEMP); 708 if (error > 0) 709 return (ENXIO); 710 711 mtx_lock(&sc->mtx); 712 bus_teardown_intr(brdev, sc->irq_res, sc->intrhand); 713 sc->flags |= PCCBB_KTHREAD_DONE; 714 if (sc->flags & PCCBB_KTHREAD_RUNNING) { 715 wakeup(sc); 716 mtx_unlock(&sc->mtx); 717 DEVPRINTF((brdev, "waiting for kthread exit...")); 718 error = tsleep(sc, PWAIT, "pccbb-detach-wait", 60 * hz); 719 if (error) 720 DPRINTF(("timeout\n")); 721 else 722 DPRINTF(("done\n")); 723 } else { 724 mtx_unlock(&sc->mtx); 725 } 726 727 bus_release_resource(brdev, SYS_RES_IRQ, 0, sc->irq_res); 728 bus_release_resource(brdev, SYS_RES_MEMORY, CBBR_SOCKBASE, 729 sc->base_res); 730 mtx_destroy(&sc->mtx); 731 cv_destroy(&sc->cv); 732 return (0); 733} 734 735static int 736pccbb_shutdown(device_t brdev) 737{ 738 struct pccbb_softc *sc = (struct pccbb_softc *)device_get_softc(brdev); 739 /* properly reset everything at shutdown */ 740 741 PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL, |CBBM_BRIDGECTRL_RESET, 2); 742 exca_clrb(&sc->exca, EXCA_INTR, EXCA_INTR_RESET); 743 744 pccbb_set(sc, CBB_SOCKET_MASK, 0); 745 746 pccbb_power(brdev, CARD_VCC_0V | CARD_VPP_0V); 747 748 exca_write(&sc->exca, EXCA_ADDRWIN_ENABLE, 0); 749 pci_write_config(brdev, CBBR_MEMBASE0, 0, 4); 750 pci_write_config(brdev, CBBR_MEMLIMIT0, 0, 4); 751 pci_write_config(brdev, CBBR_MEMBASE1, 0, 4); 752 pci_write_config(brdev, CBBR_MEMLIMIT1, 0, 4); 753 pci_write_config(brdev, CBBR_IOBASE0, 0, 4); 754 pci_write_config(brdev, CBBR_IOLIMIT0, 0, 4); 755 pci_write_config(brdev, CBBR_IOBASE1, 0, 4); 756 pci_write_config(brdev, CBBR_IOLIMIT1, 0, 4); 757 pci_write_config(brdev, PCIR_COMMAND, 0, 2); 758 return (0); 759} 760 761static int 762pccbb_setup_intr(device_t dev, device_t child, struct resource *irq, 763 int flags, driver_intr_t *intr, void *arg, void **cookiep) 764{ 765 int err; 766 767 /* 768 * You aren't allowed to have fast interrupts for pccard/cardbus 769 * things since those interrupts are PCI and shared. Since we use 770 * the PCI interrupt for the status change interrupts, it can't be 771 * free for use by the driver. Fast interrupts must not be shared. 772 */ 773 if ((flags & INTR_FAST) != 0) 774 return (EINVAL); 775 err = bus_generic_setup_intr(dev, child, irq, flags, intr, arg, 776 cookiep); 777 /* 778 * XXX need to turn on ISA interrupts, if we ever support them, but 779 * XXX for now that's all we need to do. 780 */ 781 return (err); 782} 783 784static int 785pccbb_teardown_intr(device_t dev, device_t child, struct resource *irq, 786 void *cookie) 787{ 788 /* XXX Need to do different things for ISA interrupts. */ 789 return (bus_generic_teardown_intr(dev, child, irq, cookie)); 790} 791 792 793static void 794pccbb_driver_added(device_t brdev, driver_t *driver) 795{ 796 struct pccbb_softc *sc = device_get_softc(brdev); 797 device_t *devlist; 798 int tmp; 799 int numdevs; 800 int wake; 801 uint32_t sockstate; 802 803 DEVICE_IDENTIFY(driver, brdev); 804 device_get_children(brdev, &devlist, &numdevs); 805 wake = 0; 806 sockstate = pccbb_get(sc, CBB_SOCKET_STATE); 807 for (tmp = 0; tmp < numdevs; tmp++) { 808 if (device_get_state(devlist[tmp]) == DS_NOTPRESENT && 809 device_probe_and_attach(devlist[tmp]) == 0) { 810 if (devlist[tmp] == NULL) 811 /* NOTHING */; 812 else if (strcmp(driver->name, "cardbus") == 0) { 813 sc->cbdev = devlist[tmp]; 814 if (((sockstate & CBB_SOCKET_STAT_CD) == 0) && 815 (sockstate & CBB_SOCKET_STAT_CB)) 816 wake++; 817 } else if (strcmp(driver->name, "pccard") == 0) { 818 sc->pccarddev = devlist[tmp]; 819 if (((sockstate & CBB_SOCKET_STAT_CD) == 0) && 820 (sockstate & CBB_SOCKET_STAT_16BIT)) 821 wake++; 822 } else 823 device_printf(brdev, 824 "Unsupported child bus: %s\n", 825 driver->name); 826 } 827 } 828 free(devlist, M_TEMP); 829 830 if (wake > 0) { 831 if ((pccbb_get(sc, CBB_SOCKET_STATE) & CBB_SOCKET_STAT_CD) 832 == 0) { 833 mtx_lock(&sc->mtx); 834 wakeup(sc); 835 mtx_unlock(&sc->mtx); 836 } 837 } 838} 839 840static void 841pccbb_child_detached(device_t brdev, device_t child) 842{ 843 struct pccbb_softc *sc = device_get_softc(brdev); 844 845 if (child == sc->cbdev) 846 sc->cbdev = NULL; 847 else if (child == sc->pccarddev) 848 sc->pccarddev = NULL; 849 else 850 device_printf(brdev, "Unknown child detached: %s %p/%p\n", 851 device_get_nameunit(child), sc->cbdev, sc->pccarddev); 852} 853 854static int 855pccbb_card_reprobe(device_t brdev, device_t busdev) 856{ 857 struct pccbb_softc *sc = device_get_softc(brdev); 858 int wake = 0; 859 uint32_t sockstate; 860 861 sockstate = pccbb_get(sc, CBB_SOCKET_STATE); 862 863 if ((sockstate & CBB_SOCKET_STAT_CD) == 0) { 864 if (busdev == sc->cbdev && 865 (sockstate & CBB_SOCKET_STAT_CB)) 866 wake++; 867 else if (busdev == sc->pccarddev && 868 (sockstate & CBB_SOCKET_STAT_16BIT)) 869 wake++; 870 871 if (wake > 0) { 872 mtx_lock(&sc->mtx); 873 wakeup(sc); 874 mtx_unlock(&sc->mtx); 875 return (0); 876 } 877 return (EBUSY); 878 } 879 return (ENOENT); 880} 881 882/************************************************************************/ 883/* Kthreads */ 884/************************************************************************/ 885 886static void 887pccbb_event_thread(void *arg) 888{ 889 struct pccbb_softc *sc = arg; 890 uint32_t status; 891 int err; 892 893 /* 894 * We take out Giant here because we drop it in tsleep 895 * and need it for kthread_exit, which drops it. 896 */ 897 mtx_lock(&Giant); 898 sc->flags |= PCCBB_KTHREAD_RUNNING; 899 while (1) { 900 /* 901 * Check to see if we have anything first so that 902 * if there's a card already inserted, we do the 903 * right thing. 904 */ 905 if (sc->flags & PCCBB_KTHREAD_DONE) 906 break; 907 908 status = pccbb_get(sc, CBB_SOCKET_STATE); 909 if ((status & CBB_SOCKET_STAT_CD) == 0) 910 pccbb_insert(sc); 911 else 912 pccbb_removal(sc); 913 /* 914 * Wait until it has been 1s since the last time we 915 * get an interrupt. We handle the rest of the interrupt 916 * at the top of the loop. 917 */ 918 mtx_lock(&sc->mtx); 919 cv_wait(&sc->cv, &sc->mtx); 920 do { 921 err = cv_timedwait(&sc->cv, &sc->mtx, 1 * hz); 922 } while (err != EWOULDBLOCK && 923 (sc->flags & PCCBB_KTHREAD_DONE) == 0); 924 mtx_unlock(&sc->mtx); 925 } 926 sc->flags &= ~PCCBB_KTHREAD_RUNNING; 927 /* 928 * XXX I think there's a race here. If we wakeup in the other 929 * thread before kthread_exit is called and this routine returns, 930 * and that thread causes us to be unmapped, then we are setting 931 * ourselves up for a panic. Make sure that I check out 932 * jhb's crash.c for a fix. 933 */ 934 wakeup(sc); 935 kthread_exit(0); 936} 937 938/************************************************************************/ 939/* Insert/removal */ 940/************************************************************************/ 941 942static void 943pccbb_insert(struct pccbb_softc *sc) 944{ 945 uint32_t sockevent, sockstate; 946 int timeout = 30; 947 948 /* 949 * Debounce interrupt. However, most of the debounce 950 * is done in the thread's timeout routines. 951 */ 952 do { 953 sockevent = pccbb_get(sc, CBB_SOCKET_EVENT); 954 sockstate = pccbb_get(sc, CBB_SOCKET_STATE); 955 } while (sockstate & CBB_SOCKET_STAT_CD && --timeout > 0); 956 957 if (timeout < 0) { 958 device_printf (sc->dev, "insert timeout"); 959 return; 960 } 961 962 DEVPRINTF((sc->dev, "card inserted: event=0x%08x, state=%08x\n", 963 sockevent, sockstate)); 964 965 if (sockstate & CBB_SOCKET_STAT_16BIT) { 966 if (sc->pccarddev != NULL) { 967 sc->flags |= PCCBB_16BIT_CARD; 968 if (CARD_ATTACH_CARD(sc->pccarddev) != 0) 969 device_printf(sc->dev, 970 "PC Card card activation failed\n"); 971 } else { 972 device_printf(sc->dev, 973 "PC Card inserted, but no pccard bus.\n"); 974 } 975 } else if (sockstate & CBB_SOCKET_STAT_CB) { 976 if (sc->cbdev != NULL) { 977 sc->flags &= ~PCCBB_16BIT_CARD; 978 if (CARD_ATTACH_CARD(sc->cbdev) != 0) 979 device_printf(sc->dev, 980 "CardBus card activation failed\n"); 981 } else { 982 device_printf(sc->dev, 983 "CardBUS card inserted, but no cardbus bus.\n"); 984 } 985 } else { 986 /* 987 * We should power the card down, and try again a couple of 988 * times if this happens. XXX 989 */ 990 device_printf (sc->dev, "Unsupported card type detected\n"); 991 } 992} 993 994static void 995pccbb_removal(struct pccbb_softc *sc) 996{ 997 if (sc->flags & PCCBB_16BIT_CARD && sc->pccarddev != NULL) 998 CARD_DETACH_CARD(sc->pccarddev, DETACH_FORCE); 999 else if ((!(sc->flags & PCCBB_16BIT_CARD)) && sc->cbdev != NULL) 1000 CARD_DETACH_CARD(sc->cbdev, DETACH_FORCE); 1001 pccbb_destroy_res(sc); 1002} 1003 1004/************************************************************************/ 1005/* Interrupt Handler */ 1006/************************************************************************/ 1007 1008static void 1009pccbb_intr(void *arg) 1010{ 1011 struct pccbb_softc *sc = arg; 1012 uint32_t sockevent; 1013 1014 /* 1015 * This ISR needs work XXX 1016 */ 1017 sockevent = pccbb_get(sc, CBB_SOCKET_EVENT); 1018 if (sockevent) { 1019 /* ack the interrupt */ 1020 pccbb_setb(sc, CBB_SOCKET_EVENT, sockevent); 1021 1022 if (sockevent & CBB_SOCKET_EVENT_CD) { 1023 mtx_lock(&sc->mtx); 1024 cv_signal(&sc->cv); 1025 mtx_unlock(&sc->mtx); 1026 } 1027 if (sockevent & CBB_SOCKET_EVENT_CSTS) { 1028 DPRINTF((" cstsevent occured: 0x%08x\n", 1029 pccbb_get(sc, CBB_SOCKET_STATE))); 1030 } 1031 if (sockevent & CBB_SOCKET_EVENT_POWER) { 1032 DPRINTF((" pwrevent occured: 0x%08x\n", 1033 pccbb_get(sc, CBB_SOCKET_STATE))); 1034 } 1035 /* Other bits? */ 1036 } 1037 1038 /* Call the interrupt if we still have the card */ 1039} 1040 1041/************************************************************************/ 1042/* Generic Power functions */ 1043/************************************************************************/ 1044 1045static int 1046pccbb_detect_voltage(device_t brdev) 1047{ 1048 struct pccbb_softc *sc = device_get_softc(brdev); 1049 uint32_t psr; 1050 int vol = CARD_UKN_CARD; 1051 1052 psr = pccbb_get(sc, CBB_SOCKET_STATE); 1053 1054 if (psr & CBB_SOCKET_STAT_5VCARD) 1055 vol |= CARD_5V_CARD; 1056 if (psr & CBB_SOCKET_STAT_3VCARD) 1057 vol |= CARD_3V_CARD; 1058 if (psr & CBB_SOCKET_STAT_XVCARD) 1059 vol |= CARD_XV_CARD; 1060 if (psr & CBB_SOCKET_STAT_YVCARD) 1061 vol |= CARD_YV_CARD; 1062 1063 return (vol); 1064} 1065 1066static int 1067pccbb_power(device_t brdev, int volts) 1068{ 1069 uint32_t status, sock_ctrl; 1070 struct pccbb_softc *sc = device_get_softc(brdev); 1071 int timeout; 1072 uint32_t sockevent; 1073 1074 DEVPRINTF((sc->dev, "pccbb_power: %s and %s [%x]\n", 1075 (volts & CARD_VCCMASK) == CARD_VCC_UC ? "CARD_VCC_UC" : 1076 (volts & CARD_VCCMASK) == CARD_VCC_5V ? "CARD_VCC_5V" : 1077 (volts & CARD_VCCMASK) == CARD_VCC_3V ? "CARD_VCC_3V" : 1078 (volts & CARD_VCCMASK) == CARD_VCC_XV ? "CARD_VCC_XV" : 1079 (volts & CARD_VCCMASK) == CARD_VCC_YV ? "CARD_VCC_YV" : 1080 (volts & CARD_VCCMASK) == CARD_VCC_0V ? "CARD_VCC_0V" : 1081 "VCC-UNKNOWN", 1082 (volts & CARD_VPPMASK) == CARD_VPP_UC ? "CARD_VPP_UC" : 1083 (volts & CARD_VPPMASK) == CARD_VPP_12V ? "CARD_VPP_12V" : 1084 (volts & CARD_VPPMASK) == CARD_VPP_VCC ? "CARD_VPP_VCC" : 1085 (volts & CARD_VPPMASK) == CARD_VPP_0V ? "CARD_VPP_0V" : 1086 "VPP-UNKNOWN", 1087 volts)); 1088 1089 status = pccbb_get(sc, CBB_SOCKET_STATE); 1090 sock_ctrl = pccbb_get(sc, CBB_SOCKET_CONTROL); 1091 1092 switch (volts & CARD_VCCMASK) { 1093 case CARD_VCC_UC: 1094 break; 1095 case CARD_VCC_5V: 1096 if (CBB_SOCKET_STAT_5VCARD & status) { /* check 5 V card */ 1097 sock_ctrl &= ~CBB_SOCKET_CTRL_VCCMASK; 1098 sock_ctrl |= CBB_SOCKET_CTRL_VCC_5V; 1099 } else { 1100 device_printf(sc->dev, 1101 "BAD voltage request: no 5 V card\n"); 1102 } 1103 break; 1104 case CARD_VCC_3V: 1105 if (CBB_SOCKET_STAT_3VCARD & status) { 1106 sock_ctrl &= ~CBB_SOCKET_CTRL_VCCMASK; 1107 sock_ctrl |= CBB_SOCKET_CTRL_VCC_3V; 1108 } else { 1109 device_printf(sc->dev, 1110 "BAD voltage request: no 3.3 V card\n"); 1111 } 1112 break; 1113 case CARD_VCC_0V: 1114 sock_ctrl &= ~CBB_SOCKET_CTRL_VCCMASK; 1115 break; 1116 default: 1117 return (0); /* power NEVER changed */ 1118 break; 1119 } 1120 1121 switch (volts & CARD_VPPMASK) { 1122 case CARD_VPP_UC: 1123 break; 1124 case CARD_VPP_0V: 1125 sock_ctrl &= ~CBB_SOCKET_CTRL_VPPMASK; 1126 break; 1127 case CARD_VPP_VCC: 1128 sock_ctrl &= ~CBB_SOCKET_CTRL_VPPMASK; 1129 sock_ctrl |= ((sock_ctrl >> 4) & 0x07); 1130 break; 1131 case CARD_VPP_12V: 1132 sock_ctrl &= ~CBB_SOCKET_CTRL_VPPMASK; 1133 sock_ctrl |= CBB_SOCKET_CTRL_VPP_12V; 1134 break; 1135 } 1136 1137 if (pccbb_get(sc, CBB_SOCKET_CONTROL) == sock_ctrl) 1138 return (1); /* no change necessary */ 1139 1140 pccbb_set(sc, CBB_SOCKET_CONTROL, sock_ctrl); 1141 status = pccbb_get(sc, CBB_SOCKET_STATE); 1142 1143 /* 1144 * XXX This busy wait is bogus. We should wait for a power 1145 * interrupt and then whine if the status is bad. If we're 1146 * worried about the card not coming up, then we should also 1147 * schedule a timeout which we can cacel in the power interrupt. 1148 */ 1149 timeout = 20; 1150 do { 1151 DELAY(20*1000); 1152 sockevent = pccbb_get(sc, CBB_SOCKET_EVENT); 1153 } while (!(sockevent & CBB_SOCKET_EVENT_POWER) && --timeout > 0); 1154 /* reset event status */ 1155 /* XXX should only reset EVENT_POWER */ 1156 pccbb_set(sc, CBB_SOCKET_EVENT, sockevent); 1157 if (timeout < 0) { 1158 printf ("VCC supply failed.\n"); 1159 return (0); 1160 } 1161 1162 /* XXX 1163 * delay 400 ms: thgough the standard defines that the Vcc set-up time 1164 * is 20 ms, some PC-Card bridge requires longer duration. 1165 * XXX Note: We should check the stutus AFTER the delay to give time 1166 * for things to stabilize. 1167 */ 1168 DELAY(400*1000); 1169 1170 if (status & CBB_SOCKET_STAT_BADVCC) { 1171 device_printf(sc->dev, 1172 "bad Vcc request. ctrl=0x%x, status=0x%x\n", 1173 sock_ctrl ,status); 1174 printf("pccbb_power: %s and %s [%x]\n", 1175 (volts & CARD_VCCMASK) == CARD_VCC_UC ? "CARD_VCC_UC" : 1176 (volts & CARD_VCCMASK) == CARD_VCC_5V ? "CARD_VCC_5V" : 1177 (volts & CARD_VCCMASK) == CARD_VCC_3V ? "CARD_VCC_3V" : 1178 (volts & CARD_VCCMASK) == CARD_VCC_XV ? "CARD_VCC_XV" : 1179 (volts & CARD_VCCMASK) == CARD_VCC_YV ? "CARD_VCC_YV" : 1180 (volts & CARD_VCCMASK) == CARD_VCC_0V ? "CARD_VCC_0V" : 1181 "VCC-UNKNOWN", 1182 (volts & CARD_VPPMASK) == CARD_VPP_UC ? "CARD_VPP_UC" : 1183 (volts & CARD_VPPMASK) == CARD_VPP_12V ? "CARD_VPP_12V": 1184 (volts & CARD_VPPMASK) == CARD_VPP_VCC ? "CARD_VPP_VCC": 1185 (volts & CARD_VPPMASK) == CARD_VPP_0V ? "CARD_VPP_0V" : 1186 "VPP-UNKNOWN", 1187 volts); 1188 return (0); 1189 } 1190 return (1); /* power changed correctly */ 1191} 1192 1193/* 1194 * detect the voltage for the card, and set it. Since the power 1195 * used is the square of the voltage, lower voltages is a big win 1196 * and what Windows does (and what Microsoft prefers). The MS paper 1197 * also talks about preferring the CIS entry as well. 1198 */ 1199static int 1200pccbb_do_power(device_t brdev) 1201{ 1202 int voltage; 1203 1204 /* Prefer lowest voltage supported */ 1205 voltage = pccbb_detect_voltage(brdev); 1206 pccbb_power(brdev, CARD_VCC_0V | CARD_VPP_0V); 1207 if (voltage & CARD_YV_CARD) 1208 pccbb_power(brdev, CARD_VCC_YV | CARD_VPP_VCC); 1209 else if (voltage & CARD_XV_CARD) 1210 pccbb_power(brdev, CARD_VCC_XV | CARD_VPP_VCC); 1211 else if (voltage & CARD_3V_CARD) 1212 pccbb_power(brdev, CARD_VCC_3V | CARD_VPP_VCC); 1213 else if (voltage & CARD_5V_CARD) 1214 pccbb_power(brdev, CARD_VCC_5V | CARD_VPP_VCC); 1215 else { 1216 device_printf(brdev, "Unknown card voltage\n"); 1217 return (ENXIO); 1218 } 1219 return (0); 1220} 1221 1222/************************************************************************/ 1223/* Cardbus power functions */ 1224/************************************************************************/ 1225 1226static void 1227pccbb_cardbus_reset(device_t brdev) 1228{ 1229 struct pccbb_softc *sc = device_get_softc(brdev); 1230 int delay_us; 1231 1232 delay_us = sc->chipset == CB_RF5C47X ? 400*1000 : 20*1000; 1233 1234 PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL, |CBBM_BRIDGECTRL_RESET, 2); 1235 1236 DELAY(delay_us); 1237 1238 /* If a card exists, unreset it! */ 1239 if ((pccbb_get(sc, CBB_SOCKET_STATE) & CBB_SOCKET_STAT_CD) == 0) { 1240 PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL, 1241 &~CBBM_BRIDGECTRL_RESET, 2); 1242 DELAY(delay_us); 1243 } 1244} 1245 1246static int 1247pccbb_cardbus_power_enable_socket(device_t brdev, device_t child) 1248{ 1249 struct pccbb_softc *sc = device_get_softc(brdev); 1250 int err; 1251 1252 if ((pccbb_get(sc, CBB_SOCKET_STATE) & CBB_SOCKET_STAT_CD) == 1253 CBB_SOCKET_STAT_CD) 1254 return (ENODEV); 1255 1256 err = pccbb_do_power(brdev); 1257 if (err) 1258 return (err); 1259 pccbb_cardbus_reset(brdev); 1260 return (0); 1261} 1262 1263static void 1264pccbb_cardbus_power_disable_socket(device_t brdev, device_t child) 1265{ 1266 pccbb_power(brdev, CARD_VCC_0V | CARD_VPP_0V); 1267 pccbb_cardbus_reset(brdev); 1268} 1269 1270/************************************************************************/ 1271/* Cardbus Resource */ 1272/************************************************************************/ 1273 1274static int 1275pccbb_cardbus_io_open(device_t brdev, int win, uint32_t start, uint32_t end) 1276{ 1277 int basereg; 1278 int limitreg; 1279 1280 if ((win < 0) || (win > 1)) { 1281 DEVPRINTF((brdev, 1282 "pccbb_cardbus_io_open: window out of range %d\n", win)); 1283 return (EINVAL); 1284 } 1285 1286 basereg = win * 8 + CBBR_IOBASE0; 1287 limitreg = win * 8 + CBBR_IOLIMIT0; 1288 1289 pci_write_config(brdev, basereg, start, 4); 1290 pci_write_config(brdev, limitreg, end, 4); 1291 return (0); 1292} 1293 1294static int 1295pccbb_cardbus_mem_open(device_t brdev, int win, uint32_t start, uint32_t end) 1296{ 1297 int basereg; 1298 int limitreg; 1299 1300 if ((win < 0) || (win > 1)) { 1301 DEVPRINTF((brdev, 1302 "pccbb_cardbus_mem_open: window out of range %d\n", win)); 1303 return (EINVAL); 1304 } 1305 1306 basereg = win*8 + CBBR_MEMBASE0; 1307 limitreg = win*8 + CBBR_MEMLIMIT0; 1308 1309 pci_write_config(brdev, basereg, start, 4); 1310 pci_write_config(brdev, limitreg, end, 4); 1311 return (0); 1312} 1313 1314/* 1315 * XXX The following function belongs in the pci bus layer. 1316 */ 1317static void 1318pccbb_cardbus_auto_open(struct pccbb_softc *sc, int type) 1319{ 1320 uint32_t starts[2]; 1321 uint32_t ends[2]; 1322 struct pccbb_reslist *rle; 1323 int align; 1324 int prefetchable[2]; 1325 uint32_t reg; 1326 1327 starts[0] = starts[1] = 0xffffffff; 1328 ends[0] = ends[1] = 0; 1329 1330 if (type == SYS_RES_MEMORY) 1331 align = CBB_MEMALIGN; 1332 else if (type == SYS_RES_IOPORT) 1333 align = CBB_IOALIGN; 1334 else 1335 align = 1; 1336 1337 SLIST_FOREACH(rle, &sc->rl, link) { 1338 if (rle->type != type) 1339 ; 1340 else if (rle->res == NULL) { 1341 device_printf(sc->dev, "WARNING: Resource not reserved? " 1342 "(type=%d, addr=%lx)\n", 1343 rle->type, rman_get_start(rle->res)); 1344 } else if (!(rman_get_flags(rle->res) & RF_ACTIVE)) { 1345 /* XXX */ 1346 } else if (starts[0] == 0xffffffff) { 1347 starts[0] = rman_get_start(rle->res); 1348 ends[0] = rman_get_end(rle->res); 1349 prefetchable[0] = 1350 rman_get_flags(rle->res) & RF_PREFETCHABLE; 1351 } else if (rman_get_end(rle->res) > ends[0] && 1352 rman_get_start(rle->res) - ends[0] < 1353 PCCBB_AUTO_OPEN_SMALLHOLE && prefetchable[0] == 1354 (rman_get_flags(rle->res) & RF_PREFETCHABLE)) { 1355 ends[0] = rman_get_end(rle->res); 1356 } else if (rman_get_start(rle->res) < starts[0] && 1357 starts[0] - rman_get_end(rle->res) < 1358 PCCBB_AUTO_OPEN_SMALLHOLE && prefetchable[0] == 1359 (rman_get_flags(rle->res) & RF_PREFETCHABLE)) { 1360 starts[0] = rman_get_start(rle->res); 1361 } else if (starts[1] == 0xffffffff) { 1362 starts[1] = rman_get_start(rle->res); 1363 ends[1] = rman_get_end(rle->res); 1364 prefetchable[1] = 1365 rman_get_flags(rle->res) & RF_PREFETCHABLE; 1366 } else if (rman_get_end(rle->res) > ends[1] && 1367 rman_get_start(rle->res) - ends[1] < 1368 PCCBB_AUTO_OPEN_SMALLHOLE && prefetchable[1] == 1369 (rman_get_flags(rle->res) & RF_PREFETCHABLE)) { 1370 ends[1] = rman_get_end(rle->res); 1371 } else if (rman_get_start(rle->res) < starts[1] && 1372 starts[1] - rman_get_end(rle->res) < 1373 PCCBB_AUTO_OPEN_SMALLHOLE && prefetchable[1] == 1374 (rman_get_flags(rle->res) & RF_PREFETCHABLE)) { 1375 starts[1] = rman_get_start(rle->res); 1376 } else { 1377 uint32_t diffs[2]; 1378 int win; 1379 1380 diffs[0] = diffs[1] = 0xffffffff; 1381 if (rman_get_start(rle->res) > ends[0]) 1382 diffs[0] = rman_get_start(rle->res) - ends[0]; 1383 else if (rman_get_end(rle->res) < starts[0]) 1384 diffs[0] = starts[0] - rman_get_end(rle->res); 1385 if (rman_get_start(rle->res) > ends[1]) 1386 diffs[1] = rman_get_start(rle->res) - ends[1]; 1387 else if (rman_get_end(rle->res) < starts[1]) 1388 diffs[1] = starts[1] - rman_get_end(rle->res); 1389 1390 win = (diffs[0] <= diffs[1])?0:1; 1391 if (rman_get_start(rle->res) > ends[win]) 1392 ends[win] = rman_get_end(rle->res); 1393 else if (rman_get_end(rle->res) < starts[win]) 1394 starts[win] = rman_get_start(rle->res); 1395 if (!(rman_get_flags(rle->res) & RF_PREFETCHABLE)) 1396 prefetchable[win] = 0; 1397 } 1398 1399 if (starts[0] != 0xffffffff) 1400 starts[0] -= starts[0] % align; 1401 if (starts[1] != 0xffffffff) 1402 starts[1] -= starts[1] % align; 1403 if (ends[0] % align != 0) 1404 ends[0] += align - ends[0]%align - 1; 1405 if (ends[1] % align != 0) 1406 ends[1] += align - ends[1]%align - 1; 1407 } 1408 1409 if (type == SYS_RES_MEMORY) { 1410 pccbb_cardbus_mem_open(sc->dev, 0, starts[0], ends[0]); 1411 pccbb_cardbus_mem_open(sc->dev, 1, starts[1], ends[1]); 1412 reg = pci_read_config(sc->dev, CBBR_BRIDGECTRL, 2); 1413 reg &= ~(CBBM_BRIDGECTRL_PREFETCH_0| 1414 CBBM_BRIDGECTRL_PREFETCH_1); 1415 reg |= (prefetchable[0]?CBBM_BRIDGECTRL_PREFETCH_0:0)| 1416 (prefetchable[1]?CBBM_BRIDGECTRL_PREFETCH_1:0); 1417 pci_write_config(sc->dev, CBBR_BRIDGECTRL, reg, 2); 1418 } else if (type == SYS_RES_IOPORT) { 1419 pccbb_cardbus_io_open(sc->dev, 0, starts[0], ends[0]); 1420 pccbb_cardbus_io_open(sc->dev, 1, starts[1], ends[1]); 1421 } 1422} 1423 1424static int 1425pccbb_cardbus_activate_resource(device_t brdev, device_t child, int type, 1426 int rid, struct resource *res) 1427{ 1428 int ret; 1429 1430 ret = BUS_ACTIVATE_RESOURCE(device_get_parent(brdev), child, 1431 type, rid, res); 1432 if (ret != 0) 1433 return (ret); 1434 pccbb_cardbus_auto_open(device_get_softc(brdev), type); 1435 return (0); 1436} 1437 1438static int 1439pccbb_cardbus_deactivate_resource(device_t brdev, device_t child, int type, 1440 int rid, struct resource *res) 1441{ 1442 int ret; 1443 1444 ret = BUS_DEACTIVATE_RESOURCE(device_get_parent(brdev), child, 1445 type, rid, res); 1446 if (ret != 0) 1447 return (ret); 1448 pccbb_cardbus_auto_open(device_get_softc(brdev), type); 1449 return (0); 1450} 1451 1452static struct resource * 1453pccbb_cardbus_alloc_resource(device_t brdev, device_t child, int type, 1454 int *rid, u_long start, u_long end, u_long count, uint flags) 1455{ 1456 struct pccbb_softc *sc = device_get_softc(brdev); 1457 int tmp; 1458 struct resource *res; 1459 1460 switch (type) { 1461 case SYS_RES_IRQ: 1462 tmp = rman_get_start(sc->irq_res); 1463 if (start > tmp || end < tmp || count != 1) { 1464 device_printf(child, "requested interrupt %ld-%ld," 1465 "count = %ld not supported by pccbb\n", 1466 start, end, count); 1467 return (NULL); 1468 } 1469 start = end = tmp; 1470 break; 1471 case SYS_RES_IOPORT: 1472 if (start <= pccbb_start_32_io) 1473 start = pccbb_start_32_io; 1474 if (end < start) 1475 end = start; 1476 break; 1477 case SYS_RES_MEMORY: 1478 if (start <= pccbb_start_mem) 1479 start = pccbb_start_mem; 1480 if (end < start) 1481 end = start; 1482 break; 1483 } 1484 1485 res = BUS_ALLOC_RESOURCE(device_get_parent(brdev), child, type, rid, 1486 start, end, count, flags & ~RF_ACTIVE); 1487 if (res == NULL) { 1488 printf("pccbb alloc res fail\n"); 1489 return (NULL); 1490 } 1491 pccbb_insert_res(sc, res, type, *rid); 1492 if (flags & RF_ACTIVE) 1493 if (bus_activate_resource(child, type, *rid, res) != 0) { 1494 bus_release_resource(child, type, *rid, res); 1495 return (NULL); 1496 } 1497 1498 return (res); 1499} 1500 1501static int 1502pccbb_cardbus_release_resource(device_t brdev, device_t child, int type, 1503 int rid, struct resource *res) 1504{ 1505 struct pccbb_softc *sc = device_get_softc(brdev); 1506 int error; 1507 1508 if (rman_get_flags(res) & RF_ACTIVE) { 1509 error = bus_deactivate_resource(child, type, rid, res); 1510 if (error != 0) 1511 return (error); 1512 } 1513 pccbb_remove_res(sc, res); 1514 return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child, 1515 type, rid, res)); 1516} 1517 1518/************************************************************************/ 1519/* PC Card Power Functions */ 1520/************************************************************************/ 1521 1522static int 1523pccbb_pcic_power_enable_socket(device_t brdev, device_t child) 1524{ 1525 struct pccbb_softc *sc = device_get_softc(brdev); 1526 int err; 1527 1528 DPRINTF(("pccbb_pcic_socket_enable:\n")); 1529 1530 /* power down/up the socket to reset */ 1531 err = pccbb_do_power(brdev); 1532 if (err) 1533 return (err); 1534 exca_reset(&sc->exca, child); 1535 1536 return (0); 1537} 1538 1539static void 1540pccbb_pcic_power_disable_socket(device_t brdev, device_t child) 1541{ 1542 struct pccbb_softc *sc = device_get_softc(brdev); 1543 1544 DPRINTF(("pccbb_pcic_socket_disable\n")); 1545 1546 /* reset signal asserting... */ 1547 exca_clrb(&sc->exca, EXCA_INTR, EXCA_INTR_RESET); 1548 DELAY(2*1000); 1549 1550 /* power down the socket */ 1551 pccbb_power(brdev, CARD_VCC_0V | CARD_VPP_0V); 1552 exca_clrb(&sc->exca, EXCA_PWRCTL, EXCA_PWRCTL_OE); 1553 1554 /* wait 300ms until power fails (Tpf). */ 1555 DELAY(300 * 1000); 1556} 1557 1558/************************************************************************/ 1559/* POWER methods */ 1560/************************************************************************/ 1561 1562static int 1563pccbb_power_enable_socket(device_t brdev, device_t child) 1564{ 1565 struct pccbb_softc *sc = device_get_softc(brdev); 1566 1567 if (sc->flags & PCCBB_16BIT_CARD) 1568 return (pccbb_pcic_power_enable_socket(brdev, child)); 1569 else 1570 return (pccbb_cardbus_power_enable_socket(brdev, child)); 1571} 1572 1573static void 1574pccbb_power_disable_socket(device_t brdev, device_t child) 1575{ 1576 struct pccbb_softc *sc = device_get_softc(brdev); 1577 if (sc->flags & PCCBB_16BIT_CARD) 1578 pccbb_pcic_power_disable_socket(brdev, child); 1579 else 1580 pccbb_cardbus_power_disable_socket(brdev, child); 1581} 1582static int 1583pccbb_pcic_activate_resource(device_t brdev, device_t child, int type, int rid, 1584 struct resource *res) 1585{ 1586 int err; 1587 struct pccbb_softc *sc = device_get_softc(brdev); 1588 if (!(rman_get_flags(res) & RF_ACTIVE)) { /* not already activated */ 1589 switch (type) { 1590 case SYS_RES_IOPORT: 1591 err = exca_io_map(&sc->exca, 0, res); 1592 break; 1593 case SYS_RES_MEMORY: 1594 err = exca_mem_map(&sc->exca, 0, res); 1595 break; 1596 default: 1597 err = 0; 1598 break; 1599 } 1600 if (err) 1601 return (err); 1602 1603 } 1604 return (BUS_ACTIVATE_RESOURCE(device_get_parent(brdev), child, 1605 type, rid, res)); 1606} 1607 1608static int 1609pccbb_pcic_deactivate_resource(device_t brdev, device_t child, int type, 1610 int rid, struct resource *res) 1611{ 1612 struct pccbb_softc *sc = device_get_softc(brdev); 1613 1614 if (rman_get_flags(res) & RF_ACTIVE) { /* if activated */ 1615 switch (type) { 1616 case SYS_RES_IOPORT: 1617 if (exca_io_unmap_res(&sc->exca, res)) 1618 return (ENOENT); 1619 break; 1620 case SYS_RES_MEMORY: 1621 if (exca_mem_unmap_res(&sc->exca, res)) 1622 return (ENOENT); 1623 break; 1624 } 1625 } 1626 return (BUS_DEACTIVATE_RESOURCE(device_get_parent(brdev), child, 1627 type, rid, res)); 1628} 1629 1630static struct resource * 1631pccbb_pcic_alloc_resource(device_t brdev, device_t child, int type, int *rid, 1632 u_long start, u_long end, u_long count, uint flags) 1633{ 1634 struct resource *res = NULL; 1635 struct pccbb_softc *sc = device_get_softc(brdev); 1636 int tmp; 1637 1638 switch (type) { 1639 case SYS_RES_MEMORY: 1640 if (start < pccbb_start_mem) 1641 start = pccbb_start_mem; 1642 if (end < start) 1643 end = start; 1644 flags = (flags & ~RF_ALIGNMENT_MASK) | 1645 rman_make_alignment_flags(CBB_MEMALIGN); 1646 break; 1647 case SYS_RES_IOPORT: 1648 if (start < pccbb_start_16_io) 1649 start = pccbb_start_16_io; 1650 if (end < start) 1651 end = start; 1652 break; 1653 case SYS_RES_IRQ: 1654 tmp = rman_get_start(sc->irq_res); 1655 if (start > tmp || end < tmp || count != 1) { 1656 device_printf(child, "requested interrupt %ld-%ld," 1657 "count = %ld not supported by pccbb\n", 1658 start, end, count); 1659 return (NULL); 1660 } 1661 flags |= RF_SHAREABLE; 1662 start = end = rman_get_start(sc->irq_res); 1663 break; 1664 } 1665 res = BUS_ALLOC_RESOURCE(device_get_parent(brdev), child, type, rid, 1666 start, end, count, flags & ~RF_ACTIVE); 1667 if (res == NULL) 1668 return (NULL); 1669 pccbb_insert_res(sc, res, type, *rid); 1670 if (flags & RF_ACTIVE) { 1671 if (bus_activate_resource(child, type, *rid, res) != 0) { 1672 bus_release_resource(child, type, *rid, res); 1673 return (NULL); 1674 } 1675 } 1676 1677 return (res); 1678} 1679 1680static int 1681pccbb_pcic_release_resource(device_t brdev, device_t child, int type, 1682 int rid, struct resource *res) 1683{ 1684 struct pccbb_softc *sc = device_get_softc(brdev); 1685 int error; 1686 1687 if (rman_get_flags(res) & RF_ACTIVE) { 1688 error = bus_deactivate_resource(child, type, rid, res); 1689 if (error != 0) 1690 return (error); 1691 } 1692 pccbb_remove_res(sc, res); 1693 return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child, 1694 type, rid, res)); 1695} 1696 1697/************************************************************************/ 1698/* PC Card methods */ 1699/************************************************************************/ 1700 1701static int 1702pccbb_pcic_set_res_flags(device_t brdev, device_t child, int type, int rid, 1703 uint32_t flags) 1704{ 1705 struct pccbb_softc *sc = device_get_softc(brdev); 1706 struct resource *res; 1707 1708 if (type != SYS_RES_MEMORY) 1709 return (EINVAL); 1710 res = pccbb_find_res(sc, type, rid); 1711 if (res == NULL) { 1712 device_printf(brdev, 1713 "set_res_flags: specified rid not found\n"); 1714 return (ENOENT); 1715 } 1716 return (exca_mem_set_flags(&sc->exca, res, flags)); 1717} 1718 1719static int 1720pccbb_pcic_set_memory_offset(device_t brdev, device_t child, int rid, 1721 uint32_t cardaddr, uint32_t *deltap) 1722{ 1723 struct pccbb_softc *sc = device_get_softc(brdev); 1724 struct resource *res; 1725 1726 res = pccbb_find_res(sc, SYS_RES_MEMORY, rid); 1727 if (res == NULL) { 1728 device_printf(brdev, 1729 "set_memory_offset: specified rid not found\n"); 1730 return (ENOENT); 1731 } 1732 return (exca_mem_set_offset(&sc->exca, res, cardaddr, deltap)); 1733} 1734 1735/************************************************************************/ 1736/* BUS Methods */ 1737/************************************************************************/ 1738 1739 1740static int 1741pccbb_activate_resource(device_t brdev, device_t child, int type, int rid, 1742 struct resource *r) 1743{ 1744 struct pccbb_softc *sc = device_get_softc(brdev); 1745 1746 if (sc->flags & PCCBB_16BIT_CARD) 1747 return (pccbb_pcic_activate_resource(brdev, child, type, rid, r)); 1748 else 1749 return (pccbb_cardbus_activate_resource(brdev, child, type, rid, 1750 r)); 1751} 1752 1753static int 1754pccbb_deactivate_resource(device_t brdev, device_t child, int type, 1755 int rid, struct resource *r) 1756{ 1757 struct pccbb_softc *sc = device_get_softc(brdev); 1758 1759 if (sc->flags & PCCBB_16BIT_CARD) 1760 return (pccbb_pcic_deactivate_resource(brdev, child, type, 1761 rid, r)); 1762 else 1763 return (pccbb_cardbus_deactivate_resource(brdev, child, type, 1764 rid, r)); 1765} 1766 1767static struct resource * 1768pccbb_alloc_resource(device_t brdev, device_t child, int type, int *rid, 1769 u_long start, u_long end, u_long count, uint flags) 1770{ 1771 struct pccbb_softc *sc = device_get_softc(brdev); 1772 1773 if (sc->flags & PCCBB_16BIT_CARD) 1774 return (pccbb_pcic_alloc_resource(brdev, child, type, rid, 1775 start, end, count, flags)); 1776 else 1777 return (pccbb_cardbus_alloc_resource(brdev, child, type, rid, 1778 start, end, count, flags)); 1779} 1780 1781static int 1782pccbb_release_resource(device_t brdev, device_t child, int type, int rid, 1783 struct resource *r) 1784{ 1785 struct pccbb_softc *sc = device_get_softc(brdev); 1786 1787 if (sc->flags & PCCBB_16BIT_CARD) 1788 return (pccbb_pcic_release_resource(brdev, child, type, 1789 rid, r)); 1790 else 1791 return (pccbb_cardbus_release_resource(brdev, child, type, 1792 rid, r)); 1793} 1794 1795static int 1796pccbb_read_ivar(device_t brdev, device_t child, int which, uintptr_t *result) 1797{ 1798 struct pccbb_softc *sc = device_get_softc(brdev); 1799 1800 switch (which) { 1801 case PCIB_IVAR_BUS: 1802 *result = sc->secbus; 1803 return (0); 1804 } 1805 return (ENOENT); 1806} 1807 1808static int 1809pccbb_write_ivar(device_t brdev, device_t child, int which, uintptr_t value) 1810{ 1811 struct pccbb_softc *sc = device_get_softc(brdev); 1812 1813 switch (which) { 1814 case PCIB_IVAR_BUS: 1815 sc->secbus = value; 1816 break; 1817 } 1818 return (ENOENT); 1819} 1820 1821/************************************************************************/ 1822/* PCI compat methods */ 1823/************************************************************************/ 1824 1825static int 1826pccbb_maxslots(device_t brdev) 1827{ 1828 return (0); 1829} 1830 1831static uint32_t 1832pccbb_read_config(device_t brdev, int b, int s, int f, int reg, int width) 1833{ 1834 /* 1835 * Pass through to the next ppb up the chain (i.e. our grandparent). 1836 */ 1837 return (PCIB_READ_CONFIG(device_get_parent(device_get_parent(brdev)), 1838 b, s, f, reg, width)); 1839} 1840 1841static void 1842pccbb_write_config(device_t brdev, int b, int s, int f, int reg, uint32_t val, 1843 int width) 1844{ 1845 /* 1846 * Pass through to the next ppb up the chain (i.e. our grandparent). 1847 */ 1848 PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(brdev)), 1849 b, s, f, reg, val, width); 1850} 1851 1852static int 1853pccbb_suspend(device_t self) 1854{ 1855 int error = 0; 1856 struct pccbb_softc* sc = device_get_softc(self); 1857 1858 bus_teardown_intr(self, sc->irq_res, sc->intrhand); 1859 error = bus_generic_suspend(self); 1860 return (error); 1861} 1862 1863static int 1864pccbb_resume(device_t self) 1865{ 1866 int error = 0; 1867 struct pccbb_softc *sc = (struct pccbb_softc *)device_get_softc(self); 1868 uint32_t tmp; 1869 1870 pci_write_config(self, CBBR_SOCKBASE, rman_get_start(sc->base_res), 4); 1871 DEVPRINTF((self, "PCI Memory allocated: %08lx\n", 1872 rman_get_start(sc->base_res))); 1873 1874 pccbb_chipinit(sc); 1875 1876 /* re-establish the interrupt. */ 1877 if (bus_setup_intr(self, sc->irq_res, INTR_TYPE_AV, pccbb_intr, sc, 1878 &sc->intrhand)) { 1879 device_printf(self, "couldn't re-establish interrupt"); 1880 bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res); 1881 bus_release_resource(self, SYS_RES_MEMORY, CBBR_SOCKBASE, 1882 sc->base_res); 1883 sc->irq_res = NULL; 1884 sc->base_res = NULL; 1885 return (ENOMEM); 1886 } 1887 1888 /* CSC Interrupt: Card detect interrupt on */ 1889 pccbb_setb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD); 1890 1891 /* reset interrupt */ 1892 tmp = pccbb_get(sc, CBB_SOCKET_EVENT); 1893 pccbb_set(sc, CBB_SOCKET_EVENT, tmp); 1894 1895 /* 1896 * Some BIOSes will not save the BARs for the pci chips, so we 1897 * must do it ourselves. If the BAR is reset to 0 for an I/O 1898 * device, it will read back as 0x1, so no explicit test for 1899 * memory devices are needed. 1900 * 1901 * Note: The PCI bus code should do this automatically for us on 1902 * suspend/resume, but until it does, we have to cope. 1903 */ 1904 if (pci_read_config(self, CBBR_SOCKBASE, 4) == 0) 1905 pci_write_config(self, CBBR_SOCKBASE, 1906 rman_get_start(sc->base_res), 4); 1907 1908 error = bus_generic_resume(self); 1909 1910 return (error); 1911} 1912 1913static device_method_t pccbb_methods[] = { 1914 /* Device interface */ 1915 DEVMETHOD(device_probe, pccbb_probe), 1916 DEVMETHOD(device_attach, pccbb_attach), 1917 DEVMETHOD(device_detach, pccbb_detach), 1918 DEVMETHOD(device_shutdown, pccbb_shutdown), 1919 DEVMETHOD(device_suspend, pccbb_suspend), 1920 DEVMETHOD(device_resume, pccbb_resume), 1921 1922 /* bus methods */ 1923 DEVMETHOD(bus_print_child, bus_generic_print_child), 1924 DEVMETHOD(bus_read_ivar, pccbb_read_ivar), 1925 DEVMETHOD(bus_write_ivar, pccbb_write_ivar), 1926 DEVMETHOD(bus_alloc_resource, pccbb_alloc_resource), 1927 DEVMETHOD(bus_release_resource, pccbb_release_resource), 1928 DEVMETHOD(bus_activate_resource, pccbb_activate_resource), 1929 DEVMETHOD(bus_deactivate_resource, pccbb_deactivate_resource), 1930 DEVMETHOD(bus_driver_added, pccbb_driver_added), 1931 DEVMETHOD(bus_child_detached, pccbb_child_detached), 1932 DEVMETHOD(bus_setup_intr, pccbb_setup_intr), 1933 DEVMETHOD(bus_teardown_intr, pccbb_teardown_intr), 1934 1935 /* 16-bit card interface */ 1936 DEVMETHOD(card_set_res_flags, pccbb_pcic_set_res_flags), 1937 DEVMETHOD(card_set_memory_offset, pccbb_pcic_set_memory_offset), 1938 DEVMETHOD(card_reprobe_card, pccbb_card_reprobe), 1939 1940 /* power interface */ 1941 DEVMETHOD(power_enable_socket, pccbb_power_enable_socket), 1942 DEVMETHOD(power_disable_socket, pccbb_power_disable_socket), 1943 1944 /* pcib compatibility interface */ 1945 DEVMETHOD(pcib_maxslots, pccbb_maxslots), 1946 DEVMETHOD(pcib_read_config, pccbb_read_config), 1947 DEVMETHOD(pcib_write_config, pccbb_write_config), 1948 {0,0} 1949}; 1950 1951static driver_t pccbb_driver = { 1952 "pccbb", 1953 pccbb_methods, 1954 sizeof(struct pccbb_softc) 1955}; 1956 1957static devclass_t pccbb_devclass; 1958 1959DRIVER_MODULE(pccbb, pci, pccbb_driver, pccbb_devclass, 0, 0); 1960MODULE_VERSION(pccbb, 1); 1961MODULE_DEPEND(pccbb, exca, 1, 1, 1); 1962MODULE_DEPEND(pccbb, pccard, 1, 1, 1); 1963MODULE_DEPEND(pccbb, cardbus, 1, 1, 1);
| 628 pccbb_chipinit(sc); 629 630 /* attach children */ 631 sc->cbdev = device_add_child(brdev, "cardbus", -1); 632 if (sc->cbdev == NULL) 633 DEVPRINTF((brdev, "WARNING: cannot add cardbus bus.\n")); 634 else if (device_probe_and_attach(sc->cbdev) != 0) { 635 DEVPRINTF((brdev, "WARNING: cannot attach cardbus bus!\n")); 636 sc->cbdev = NULL; 637 } 638 639 sc->pccarddev = device_add_child(brdev, "pccard", -1); 640 if (sc->pccarddev == NULL) 641 DEVPRINTF((brdev, "WARNING: cannot add pccard bus.\n")); 642 else if (device_probe_and_attach(sc->pccarddev) != 0) { 643 DEVPRINTF((brdev, "WARNING: cannot attach pccard bus.\n")); 644 sc->pccarddev = NULL; 645 } 646 647 /* Map and establish the interrupt. */ 648 rid = 0; 649 sc->irq_res = bus_alloc_resource(brdev, SYS_RES_IRQ, &rid, 0, ~0, 1, 650 RF_SHAREABLE | RF_ACTIVE); 651 if (sc->irq_res == NULL) { 652 printf("pccbb: Unable to map IRQ...\n"); 653 bus_release_resource(brdev, SYS_RES_MEMORY, CBBR_SOCKBASE, 654 sc->base_res); 655 mtx_destroy(&sc->mtx); 656 cv_destroy(&sc->cv); 657 return (ENOMEM); 658 } 659 660 if (bus_setup_intr(brdev, sc->irq_res, INTR_TYPE_AV, pccbb_intr, sc, 661 &sc->intrhand)) { 662 device_printf(brdev, "couldn't establish interrupt"); 663 bus_release_resource(brdev, SYS_RES_IRQ, 0, sc->irq_res); 664 bus_release_resource(brdev, SYS_RES_MEMORY, CBBR_SOCKBASE, 665 sc->base_res); 666 mtx_destroy(&sc->mtx); 667 cv_destroy(&sc->cv); 668 return (ENOMEM); 669 } 670 671 /* reset 16-bit pcmcia bus */ 672 exca_clrb(&sc->exca, EXCA_INTR, EXCA_INTR_RESET); 673 674 /* turn off power */ 675 pccbb_power(brdev, CARD_VCC_0V | CARD_VPP_0V); 676 677 /* CSC Interrupt: Card detect interrupt on */ 678 pccbb_setb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD); 679 680 /* reset interrupt */ 681 pccbb_set(sc, CBB_SOCKET_EVENT, pccbb_get(sc, CBB_SOCKET_EVENT)); 682 683 /* Start the thread */ 684 if (kthread_create(pccbb_event_thread, sc, &sc->event_thread, 0, 685 "%s%d", device_get_name(sc->dev), device_get_unit(sc->dev))) { 686 device_printf (sc->dev, "unable to create event thread.\n"); 687 panic ("pccbb_create_event_thread"); 688 } 689 690 return (0); 691} 692 693static int 694pccbb_detach(device_t brdev) 695{ 696 struct pccbb_softc *sc = device_get_softc(brdev); 697 int numdevs; 698 device_t *devlist; 699 int tmp; 700 int error; 701 702 device_get_children(brdev, &devlist, &numdevs); 703 704 error = 0; 705 for (tmp = 0; tmp < numdevs; tmp++) { 706 if (device_detach(devlist[tmp]) == 0) 707 device_delete_child(brdev, devlist[tmp]); 708 else 709 error++; 710 } 711 free(devlist, M_TEMP); 712 if (error > 0) 713 return (ENXIO); 714 715 mtx_lock(&sc->mtx); 716 bus_teardown_intr(brdev, sc->irq_res, sc->intrhand); 717 sc->flags |= PCCBB_KTHREAD_DONE; 718 if (sc->flags & PCCBB_KTHREAD_RUNNING) { 719 wakeup(sc); 720 mtx_unlock(&sc->mtx); 721 DEVPRINTF((brdev, "waiting for kthread exit...")); 722 error = tsleep(sc, PWAIT, "pccbb-detach-wait", 60 * hz); 723 if (error) 724 DPRINTF(("timeout\n")); 725 else 726 DPRINTF(("done\n")); 727 } else { 728 mtx_unlock(&sc->mtx); 729 } 730 731 bus_release_resource(brdev, SYS_RES_IRQ, 0, sc->irq_res); 732 bus_release_resource(brdev, SYS_RES_MEMORY, CBBR_SOCKBASE, 733 sc->base_res); 734 mtx_destroy(&sc->mtx); 735 cv_destroy(&sc->cv); 736 return (0); 737} 738 739static int 740pccbb_shutdown(device_t brdev) 741{ 742 struct pccbb_softc *sc = (struct pccbb_softc *)device_get_softc(brdev); 743 /* properly reset everything at shutdown */ 744 745 PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL, |CBBM_BRIDGECTRL_RESET, 2); 746 exca_clrb(&sc->exca, EXCA_INTR, EXCA_INTR_RESET); 747 748 pccbb_set(sc, CBB_SOCKET_MASK, 0); 749 750 pccbb_power(brdev, CARD_VCC_0V | CARD_VPP_0V); 751 752 exca_write(&sc->exca, EXCA_ADDRWIN_ENABLE, 0); 753 pci_write_config(brdev, CBBR_MEMBASE0, 0, 4); 754 pci_write_config(brdev, CBBR_MEMLIMIT0, 0, 4); 755 pci_write_config(brdev, CBBR_MEMBASE1, 0, 4); 756 pci_write_config(brdev, CBBR_MEMLIMIT1, 0, 4); 757 pci_write_config(brdev, CBBR_IOBASE0, 0, 4); 758 pci_write_config(brdev, CBBR_IOLIMIT0, 0, 4); 759 pci_write_config(brdev, CBBR_IOBASE1, 0, 4); 760 pci_write_config(brdev, CBBR_IOLIMIT1, 0, 4); 761 pci_write_config(brdev, PCIR_COMMAND, 0, 2); 762 return (0); 763} 764 765static int 766pccbb_setup_intr(device_t dev, device_t child, struct resource *irq, 767 int flags, driver_intr_t *intr, void *arg, void **cookiep) 768{ 769 int err; 770 771 /* 772 * You aren't allowed to have fast interrupts for pccard/cardbus 773 * things since those interrupts are PCI and shared. Since we use 774 * the PCI interrupt for the status change interrupts, it can't be 775 * free for use by the driver. Fast interrupts must not be shared. 776 */ 777 if ((flags & INTR_FAST) != 0) 778 return (EINVAL); 779 err = bus_generic_setup_intr(dev, child, irq, flags, intr, arg, 780 cookiep); 781 /* 782 * XXX need to turn on ISA interrupts, if we ever support them, but 783 * XXX for now that's all we need to do. 784 */ 785 return (err); 786} 787 788static int 789pccbb_teardown_intr(device_t dev, device_t child, struct resource *irq, 790 void *cookie) 791{ 792 /* XXX Need to do different things for ISA interrupts. */ 793 return (bus_generic_teardown_intr(dev, child, irq, cookie)); 794} 795 796 797static void 798pccbb_driver_added(device_t brdev, driver_t *driver) 799{ 800 struct pccbb_softc *sc = device_get_softc(brdev); 801 device_t *devlist; 802 int tmp; 803 int numdevs; 804 int wake; 805 uint32_t sockstate; 806 807 DEVICE_IDENTIFY(driver, brdev); 808 device_get_children(brdev, &devlist, &numdevs); 809 wake = 0; 810 sockstate = pccbb_get(sc, CBB_SOCKET_STATE); 811 for (tmp = 0; tmp < numdevs; tmp++) { 812 if (device_get_state(devlist[tmp]) == DS_NOTPRESENT && 813 device_probe_and_attach(devlist[tmp]) == 0) { 814 if (devlist[tmp] == NULL) 815 /* NOTHING */; 816 else if (strcmp(driver->name, "cardbus") == 0) { 817 sc->cbdev = devlist[tmp]; 818 if (((sockstate & CBB_SOCKET_STAT_CD) == 0) && 819 (sockstate & CBB_SOCKET_STAT_CB)) 820 wake++; 821 } else if (strcmp(driver->name, "pccard") == 0) { 822 sc->pccarddev = devlist[tmp]; 823 if (((sockstate & CBB_SOCKET_STAT_CD) == 0) && 824 (sockstate & CBB_SOCKET_STAT_16BIT)) 825 wake++; 826 } else 827 device_printf(brdev, 828 "Unsupported child bus: %s\n", 829 driver->name); 830 } 831 } 832 free(devlist, M_TEMP); 833 834 if (wake > 0) { 835 if ((pccbb_get(sc, CBB_SOCKET_STATE) & CBB_SOCKET_STAT_CD) 836 == 0) { 837 mtx_lock(&sc->mtx); 838 wakeup(sc); 839 mtx_unlock(&sc->mtx); 840 } 841 } 842} 843 844static void 845pccbb_child_detached(device_t brdev, device_t child) 846{ 847 struct pccbb_softc *sc = device_get_softc(brdev); 848 849 if (child == sc->cbdev) 850 sc->cbdev = NULL; 851 else if (child == sc->pccarddev) 852 sc->pccarddev = NULL; 853 else 854 device_printf(brdev, "Unknown child detached: %s %p/%p\n", 855 device_get_nameunit(child), sc->cbdev, sc->pccarddev); 856} 857 858static int 859pccbb_card_reprobe(device_t brdev, device_t busdev) 860{ 861 struct pccbb_softc *sc = device_get_softc(brdev); 862 int wake = 0; 863 uint32_t sockstate; 864 865 sockstate = pccbb_get(sc, CBB_SOCKET_STATE); 866 867 if ((sockstate & CBB_SOCKET_STAT_CD) == 0) { 868 if (busdev == sc->cbdev && 869 (sockstate & CBB_SOCKET_STAT_CB)) 870 wake++; 871 else if (busdev == sc->pccarddev && 872 (sockstate & CBB_SOCKET_STAT_16BIT)) 873 wake++; 874 875 if (wake > 0) { 876 mtx_lock(&sc->mtx); 877 wakeup(sc); 878 mtx_unlock(&sc->mtx); 879 return (0); 880 } 881 return (EBUSY); 882 } 883 return (ENOENT); 884} 885 886/************************************************************************/ 887/* Kthreads */ 888/************************************************************************/ 889 890static void 891pccbb_event_thread(void *arg) 892{ 893 struct pccbb_softc *sc = arg; 894 uint32_t status; 895 int err; 896 897 /* 898 * We take out Giant here because we drop it in tsleep 899 * and need it for kthread_exit, which drops it. 900 */ 901 mtx_lock(&Giant); 902 sc->flags |= PCCBB_KTHREAD_RUNNING; 903 while (1) { 904 /* 905 * Check to see if we have anything first so that 906 * if there's a card already inserted, we do the 907 * right thing. 908 */ 909 if (sc->flags & PCCBB_KTHREAD_DONE) 910 break; 911 912 status = pccbb_get(sc, CBB_SOCKET_STATE); 913 if ((status & CBB_SOCKET_STAT_CD) == 0) 914 pccbb_insert(sc); 915 else 916 pccbb_removal(sc); 917 /* 918 * Wait until it has been 1s since the last time we 919 * get an interrupt. We handle the rest of the interrupt 920 * at the top of the loop. 921 */ 922 mtx_lock(&sc->mtx); 923 cv_wait(&sc->cv, &sc->mtx); 924 do { 925 err = cv_timedwait(&sc->cv, &sc->mtx, 1 * hz); 926 } while (err != EWOULDBLOCK && 927 (sc->flags & PCCBB_KTHREAD_DONE) == 0); 928 mtx_unlock(&sc->mtx); 929 } 930 sc->flags &= ~PCCBB_KTHREAD_RUNNING; 931 /* 932 * XXX I think there's a race here. If we wakeup in the other 933 * thread before kthread_exit is called and this routine returns, 934 * and that thread causes us to be unmapped, then we are setting 935 * ourselves up for a panic. Make sure that I check out 936 * jhb's crash.c for a fix. 937 */ 938 wakeup(sc); 939 kthread_exit(0); 940} 941 942/************************************************************************/ 943/* Insert/removal */ 944/************************************************************************/ 945 946static void 947pccbb_insert(struct pccbb_softc *sc) 948{ 949 uint32_t sockevent, sockstate; 950 int timeout = 30; 951 952 /* 953 * Debounce interrupt. However, most of the debounce 954 * is done in the thread's timeout routines. 955 */ 956 do { 957 sockevent = pccbb_get(sc, CBB_SOCKET_EVENT); 958 sockstate = pccbb_get(sc, CBB_SOCKET_STATE); 959 } while (sockstate & CBB_SOCKET_STAT_CD && --timeout > 0); 960 961 if (timeout < 0) { 962 device_printf (sc->dev, "insert timeout"); 963 return; 964 } 965 966 DEVPRINTF((sc->dev, "card inserted: event=0x%08x, state=%08x\n", 967 sockevent, sockstate)); 968 969 if (sockstate & CBB_SOCKET_STAT_16BIT) { 970 if (sc->pccarddev != NULL) { 971 sc->flags |= PCCBB_16BIT_CARD; 972 if (CARD_ATTACH_CARD(sc->pccarddev) != 0) 973 device_printf(sc->dev, 974 "PC Card card activation failed\n"); 975 } else { 976 device_printf(sc->dev, 977 "PC Card inserted, but no pccard bus.\n"); 978 } 979 } else if (sockstate & CBB_SOCKET_STAT_CB) { 980 if (sc->cbdev != NULL) { 981 sc->flags &= ~PCCBB_16BIT_CARD; 982 if (CARD_ATTACH_CARD(sc->cbdev) != 0) 983 device_printf(sc->dev, 984 "CardBus card activation failed\n"); 985 } else { 986 device_printf(sc->dev, 987 "CardBUS card inserted, but no cardbus bus.\n"); 988 } 989 } else { 990 /* 991 * We should power the card down, and try again a couple of 992 * times if this happens. XXX 993 */ 994 device_printf (sc->dev, "Unsupported card type detected\n"); 995 } 996} 997 998static void 999pccbb_removal(struct pccbb_softc *sc) 1000{ 1001 if (sc->flags & PCCBB_16BIT_CARD && sc->pccarddev != NULL) 1002 CARD_DETACH_CARD(sc->pccarddev, DETACH_FORCE); 1003 else if ((!(sc->flags & PCCBB_16BIT_CARD)) && sc->cbdev != NULL) 1004 CARD_DETACH_CARD(sc->cbdev, DETACH_FORCE); 1005 pccbb_destroy_res(sc); 1006} 1007 1008/************************************************************************/ 1009/* Interrupt Handler */ 1010/************************************************************************/ 1011 1012static void 1013pccbb_intr(void *arg) 1014{ 1015 struct pccbb_softc *sc = arg; 1016 uint32_t sockevent; 1017 1018 /* 1019 * This ISR needs work XXX 1020 */ 1021 sockevent = pccbb_get(sc, CBB_SOCKET_EVENT); 1022 if (sockevent) { 1023 /* ack the interrupt */ 1024 pccbb_setb(sc, CBB_SOCKET_EVENT, sockevent); 1025 1026 if (sockevent & CBB_SOCKET_EVENT_CD) { 1027 mtx_lock(&sc->mtx); 1028 cv_signal(&sc->cv); 1029 mtx_unlock(&sc->mtx); 1030 } 1031 if (sockevent & CBB_SOCKET_EVENT_CSTS) { 1032 DPRINTF((" cstsevent occured: 0x%08x\n", 1033 pccbb_get(sc, CBB_SOCKET_STATE))); 1034 } 1035 if (sockevent & CBB_SOCKET_EVENT_POWER) { 1036 DPRINTF((" pwrevent occured: 0x%08x\n", 1037 pccbb_get(sc, CBB_SOCKET_STATE))); 1038 } 1039 /* Other bits? */ 1040 } 1041 1042 /* Call the interrupt if we still have the card */ 1043} 1044 1045/************************************************************************/ 1046/* Generic Power functions */ 1047/************************************************************************/ 1048 1049static int 1050pccbb_detect_voltage(device_t brdev) 1051{ 1052 struct pccbb_softc *sc = device_get_softc(brdev); 1053 uint32_t psr; 1054 int vol = CARD_UKN_CARD; 1055 1056 psr = pccbb_get(sc, CBB_SOCKET_STATE); 1057 1058 if (psr & CBB_SOCKET_STAT_5VCARD) 1059 vol |= CARD_5V_CARD; 1060 if (psr & CBB_SOCKET_STAT_3VCARD) 1061 vol |= CARD_3V_CARD; 1062 if (psr & CBB_SOCKET_STAT_XVCARD) 1063 vol |= CARD_XV_CARD; 1064 if (psr & CBB_SOCKET_STAT_YVCARD) 1065 vol |= CARD_YV_CARD; 1066 1067 return (vol); 1068} 1069 1070static int 1071pccbb_power(device_t brdev, int volts) 1072{ 1073 uint32_t status, sock_ctrl; 1074 struct pccbb_softc *sc = device_get_softc(brdev); 1075 int timeout; 1076 uint32_t sockevent; 1077 1078 DEVPRINTF((sc->dev, "pccbb_power: %s and %s [%x]\n", 1079 (volts & CARD_VCCMASK) == CARD_VCC_UC ? "CARD_VCC_UC" : 1080 (volts & CARD_VCCMASK) == CARD_VCC_5V ? "CARD_VCC_5V" : 1081 (volts & CARD_VCCMASK) == CARD_VCC_3V ? "CARD_VCC_3V" : 1082 (volts & CARD_VCCMASK) == CARD_VCC_XV ? "CARD_VCC_XV" : 1083 (volts & CARD_VCCMASK) == CARD_VCC_YV ? "CARD_VCC_YV" : 1084 (volts & CARD_VCCMASK) == CARD_VCC_0V ? "CARD_VCC_0V" : 1085 "VCC-UNKNOWN", 1086 (volts & CARD_VPPMASK) == CARD_VPP_UC ? "CARD_VPP_UC" : 1087 (volts & CARD_VPPMASK) == CARD_VPP_12V ? "CARD_VPP_12V" : 1088 (volts & CARD_VPPMASK) == CARD_VPP_VCC ? "CARD_VPP_VCC" : 1089 (volts & CARD_VPPMASK) == CARD_VPP_0V ? "CARD_VPP_0V" : 1090 "VPP-UNKNOWN", 1091 volts)); 1092 1093 status = pccbb_get(sc, CBB_SOCKET_STATE); 1094 sock_ctrl = pccbb_get(sc, CBB_SOCKET_CONTROL); 1095 1096 switch (volts & CARD_VCCMASK) { 1097 case CARD_VCC_UC: 1098 break; 1099 case CARD_VCC_5V: 1100 if (CBB_SOCKET_STAT_5VCARD & status) { /* check 5 V card */ 1101 sock_ctrl &= ~CBB_SOCKET_CTRL_VCCMASK; 1102 sock_ctrl |= CBB_SOCKET_CTRL_VCC_5V; 1103 } else { 1104 device_printf(sc->dev, 1105 "BAD voltage request: no 5 V card\n"); 1106 } 1107 break; 1108 case CARD_VCC_3V: 1109 if (CBB_SOCKET_STAT_3VCARD & status) { 1110 sock_ctrl &= ~CBB_SOCKET_CTRL_VCCMASK; 1111 sock_ctrl |= CBB_SOCKET_CTRL_VCC_3V; 1112 } else { 1113 device_printf(sc->dev, 1114 "BAD voltage request: no 3.3 V card\n"); 1115 } 1116 break; 1117 case CARD_VCC_0V: 1118 sock_ctrl &= ~CBB_SOCKET_CTRL_VCCMASK; 1119 break; 1120 default: 1121 return (0); /* power NEVER changed */ 1122 break; 1123 } 1124 1125 switch (volts & CARD_VPPMASK) { 1126 case CARD_VPP_UC: 1127 break; 1128 case CARD_VPP_0V: 1129 sock_ctrl &= ~CBB_SOCKET_CTRL_VPPMASK; 1130 break; 1131 case CARD_VPP_VCC: 1132 sock_ctrl &= ~CBB_SOCKET_CTRL_VPPMASK; 1133 sock_ctrl |= ((sock_ctrl >> 4) & 0x07); 1134 break; 1135 case CARD_VPP_12V: 1136 sock_ctrl &= ~CBB_SOCKET_CTRL_VPPMASK; 1137 sock_ctrl |= CBB_SOCKET_CTRL_VPP_12V; 1138 break; 1139 } 1140 1141 if (pccbb_get(sc, CBB_SOCKET_CONTROL) == sock_ctrl) 1142 return (1); /* no change necessary */ 1143 1144 pccbb_set(sc, CBB_SOCKET_CONTROL, sock_ctrl); 1145 status = pccbb_get(sc, CBB_SOCKET_STATE); 1146 1147 /* 1148 * XXX This busy wait is bogus. We should wait for a power 1149 * interrupt and then whine if the status is bad. If we're 1150 * worried about the card not coming up, then we should also 1151 * schedule a timeout which we can cacel in the power interrupt. 1152 */ 1153 timeout = 20; 1154 do { 1155 DELAY(20*1000); 1156 sockevent = pccbb_get(sc, CBB_SOCKET_EVENT); 1157 } while (!(sockevent & CBB_SOCKET_EVENT_POWER) && --timeout > 0); 1158 /* reset event status */ 1159 /* XXX should only reset EVENT_POWER */ 1160 pccbb_set(sc, CBB_SOCKET_EVENT, sockevent); 1161 if (timeout < 0) { 1162 printf ("VCC supply failed.\n"); 1163 return (0); 1164 } 1165 1166 /* XXX 1167 * delay 400 ms: thgough the standard defines that the Vcc set-up time 1168 * is 20 ms, some PC-Card bridge requires longer duration. 1169 * XXX Note: We should check the stutus AFTER the delay to give time 1170 * for things to stabilize. 1171 */ 1172 DELAY(400*1000); 1173 1174 if (status & CBB_SOCKET_STAT_BADVCC) { 1175 device_printf(sc->dev, 1176 "bad Vcc request. ctrl=0x%x, status=0x%x\n", 1177 sock_ctrl ,status); 1178 printf("pccbb_power: %s and %s [%x]\n", 1179 (volts & CARD_VCCMASK) == CARD_VCC_UC ? "CARD_VCC_UC" : 1180 (volts & CARD_VCCMASK) == CARD_VCC_5V ? "CARD_VCC_5V" : 1181 (volts & CARD_VCCMASK) == CARD_VCC_3V ? "CARD_VCC_3V" : 1182 (volts & CARD_VCCMASK) == CARD_VCC_XV ? "CARD_VCC_XV" : 1183 (volts & CARD_VCCMASK) == CARD_VCC_YV ? "CARD_VCC_YV" : 1184 (volts & CARD_VCCMASK) == CARD_VCC_0V ? "CARD_VCC_0V" : 1185 "VCC-UNKNOWN", 1186 (volts & CARD_VPPMASK) == CARD_VPP_UC ? "CARD_VPP_UC" : 1187 (volts & CARD_VPPMASK) == CARD_VPP_12V ? "CARD_VPP_12V": 1188 (volts & CARD_VPPMASK) == CARD_VPP_VCC ? "CARD_VPP_VCC": 1189 (volts & CARD_VPPMASK) == CARD_VPP_0V ? "CARD_VPP_0V" : 1190 "VPP-UNKNOWN", 1191 volts); 1192 return (0); 1193 } 1194 return (1); /* power changed correctly */ 1195} 1196 1197/* 1198 * detect the voltage for the card, and set it. Since the power 1199 * used is the square of the voltage, lower voltages is a big win 1200 * and what Windows does (and what Microsoft prefers). The MS paper 1201 * also talks about preferring the CIS entry as well. 1202 */ 1203static int 1204pccbb_do_power(device_t brdev) 1205{ 1206 int voltage; 1207 1208 /* Prefer lowest voltage supported */ 1209 voltage = pccbb_detect_voltage(brdev); 1210 pccbb_power(brdev, CARD_VCC_0V | CARD_VPP_0V); 1211 if (voltage & CARD_YV_CARD) 1212 pccbb_power(brdev, CARD_VCC_YV | CARD_VPP_VCC); 1213 else if (voltage & CARD_XV_CARD) 1214 pccbb_power(brdev, CARD_VCC_XV | CARD_VPP_VCC); 1215 else if (voltage & CARD_3V_CARD) 1216 pccbb_power(brdev, CARD_VCC_3V | CARD_VPP_VCC); 1217 else if (voltage & CARD_5V_CARD) 1218 pccbb_power(brdev, CARD_VCC_5V | CARD_VPP_VCC); 1219 else { 1220 device_printf(brdev, "Unknown card voltage\n"); 1221 return (ENXIO); 1222 } 1223 return (0); 1224} 1225 1226/************************************************************************/ 1227/* Cardbus power functions */ 1228/************************************************************************/ 1229 1230static void 1231pccbb_cardbus_reset(device_t brdev) 1232{ 1233 struct pccbb_softc *sc = device_get_softc(brdev); 1234 int delay_us; 1235 1236 delay_us = sc->chipset == CB_RF5C47X ? 400*1000 : 20*1000; 1237 1238 PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL, |CBBM_BRIDGECTRL_RESET, 2); 1239 1240 DELAY(delay_us); 1241 1242 /* If a card exists, unreset it! */ 1243 if ((pccbb_get(sc, CBB_SOCKET_STATE) & CBB_SOCKET_STAT_CD) == 0) { 1244 PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL, 1245 &~CBBM_BRIDGECTRL_RESET, 2); 1246 DELAY(delay_us); 1247 } 1248} 1249 1250static int 1251pccbb_cardbus_power_enable_socket(device_t brdev, device_t child) 1252{ 1253 struct pccbb_softc *sc = device_get_softc(brdev); 1254 int err; 1255 1256 if ((pccbb_get(sc, CBB_SOCKET_STATE) & CBB_SOCKET_STAT_CD) == 1257 CBB_SOCKET_STAT_CD) 1258 return (ENODEV); 1259 1260 err = pccbb_do_power(brdev); 1261 if (err) 1262 return (err); 1263 pccbb_cardbus_reset(brdev); 1264 return (0); 1265} 1266 1267static void 1268pccbb_cardbus_power_disable_socket(device_t brdev, device_t child) 1269{ 1270 pccbb_power(brdev, CARD_VCC_0V | CARD_VPP_0V); 1271 pccbb_cardbus_reset(brdev); 1272} 1273 1274/************************************************************************/ 1275/* Cardbus Resource */ 1276/************************************************************************/ 1277 1278static int 1279pccbb_cardbus_io_open(device_t brdev, int win, uint32_t start, uint32_t end) 1280{ 1281 int basereg; 1282 int limitreg; 1283 1284 if ((win < 0) || (win > 1)) { 1285 DEVPRINTF((brdev, 1286 "pccbb_cardbus_io_open: window out of range %d\n", win)); 1287 return (EINVAL); 1288 } 1289 1290 basereg = win * 8 + CBBR_IOBASE0; 1291 limitreg = win * 8 + CBBR_IOLIMIT0; 1292 1293 pci_write_config(brdev, basereg, start, 4); 1294 pci_write_config(brdev, limitreg, end, 4); 1295 return (0); 1296} 1297 1298static int 1299pccbb_cardbus_mem_open(device_t brdev, int win, uint32_t start, uint32_t end) 1300{ 1301 int basereg; 1302 int limitreg; 1303 1304 if ((win < 0) || (win > 1)) { 1305 DEVPRINTF((brdev, 1306 "pccbb_cardbus_mem_open: window out of range %d\n", win)); 1307 return (EINVAL); 1308 } 1309 1310 basereg = win*8 + CBBR_MEMBASE0; 1311 limitreg = win*8 + CBBR_MEMLIMIT0; 1312 1313 pci_write_config(brdev, basereg, start, 4); 1314 pci_write_config(brdev, limitreg, end, 4); 1315 return (0); 1316} 1317 1318/* 1319 * XXX The following function belongs in the pci bus layer. 1320 */ 1321static void 1322pccbb_cardbus_auto_open(struct pccbb_softc *sc, int type) 1323{ 1324 uint32_t starts[2]; 1325 uint32_t ends[2]; 1326 struct pccbb_reslist *rle; 1327 int align; 1328 int prefetchable[2]; 1329 uint32_t reg; 1330 1331 starts[0] = starts[1] = 0xffffffff; 1332 ends[0] = ends[1] = 0; 1333 1334 if (type == SYS_RES_MEMORY) 1335 align = CBB_MEMALIGN; 1336 else if (type == SYS_RES_IOPORT) 1337 align = CBB_IOALIGN; 1338 else 1339 align = 1; 1340 1341 SLIST_FOREACH(rle, &sc->rl, link) { 1342 if (rle->type != type) 1343 ; 1344 else if (rle->res == NULL) { 1345 device_printf(sc->dev, "WARNING: Resource not reserved? " 1346 "(type=%d, addr=%lx)\n", 1347 rle->type, rman_get_start(rle->res)); 1348 } else if (!(rman_get_flags(rle->res) & RF_ACTIVE)) { 1349 /* XXX */ 1350 } else if (starts[0] == 0xffffffff) { 1351 starts[0] = rman_get_start(rle->res); 1352 ends[0] = rman_get_end(rle->res); 1353 prefetchable[0] = 1354 rman_get_flags(rle->res) & RF_PREFETCHABLE; 1355 } else if (rman_get_end(rle->res) > ends[0] && 1356 rman_get_start(rle->res) - ends[0] < 1357 PCCBB_AUTO_OPEN_SMALLHOLE && prefetchable[0] == 1358 (rman_get_flags(rle->res) & RF_PREFETCHABLE)) { 1359 ends[0] = rman_get_end(rle->res); 1360 } else if (rman_get_start(rle->res) < starts[0] && 1361 starts[0] - rman_get_end(rle->res) < 1362 PCCBB_AUTO_OPEN_SMALLHOLE && prefetchable[0] == 1363 (rman_get_flags(rle->res) & RF_PREFETCHABLE)) { 1364 starts[0] = rman_get_start(rle->res); 1365 } else if (starts[1] == 0xffffffff) { 1366 starts[1] = rman_get_start(rle->res); 1367 ends[1] = rman_get_end(rle->res); 1368 prefetchable[1] = 1369 rman_get_flags(rle->res) & RF_PREFETCHABLE; 1370 } else if (rman_get_end(rle->res) > ends[1] && 1371 rman_get_start(rle->res) - ends[1] < 1372 PCCBB_AUTO_OPEN_SMALLHOLE && prefetchable[1] == 1373 (rman_get_flags(rle->res) & RF_PREFETCHABLE)) { 1374 ends[1] = rman_get_end(rle->res); 1375 } else if (rman_get_start(rle->res) < starts[1] && 1376 starts[1] - rman_get_end(rle->res) < 1377 PCCBB_AUTO_OPEN_SMALLHOLE && prefetchable[1] == 1378 (rman_get_flags(rle->res) & RF_PREFETCHABLE)) { 1379 starts[1] = rman_get_start(rle->res); 1380 } else { 1381 uint32_t diffs[2]; 1382 int win; 1383 1384 diffs[0] = diffs[1] = 0xffffffff; 1385 if (rman_get_start(rle->res) > ends[0]) 1386 diffs[0] = rman_get_start(rle->res) - ends[0]; 1387 else if (rman_get_end(rle->res) < starts[0]) 1388 diffs[0] = starts[0] - rman_get_end(rle->res); 1389 if (rman_get_start(rle->res) > ends[1]) 1390 diffs[1] = rman_get_start(rle->res) - ends[1]; 1391 else if (rman_get_end(rle->res) < starts[1]) 1392 diffs[1] = starts[1] - rman_get_end(rle->res); 1393 1394 win = (diffs[0] <= diffs[1])?0:1; 1395 if (rman_get_start(rle->res) > ends[win]) 1396 ends[win] = rman_get_end(rle->res); 1397 else if (rman_get_end(rle->res) < starts[win]) 1398 starts[win] = rman_get_start(rle->res); 1399 if (!(rman_get_flags(rle->res) & RF_PREFETCHABLE)) 1400 prefetchable[win] = 0; 1401 } 1402 1403 if (starts[0] != 0xffffffff) 1404 starts[0] -= starts[0] % align; 1405 if (starts[1] != 0xffffffff) 1406 starts[1] -= starts[1] % align; 1407 if (ends[0] % align != 0) 1408 ends[0] += align - ends[0]%align - 1; 1409 if (ends[1] % align != 0) 1410 ends[1] += align - ends[1]%align - 1; 1411 } 1412 1413 if (type == SYS_RES_MEMORY) { 1414 pccbb_cardbus_mem_open(sc->dev, 0, starts[0], ends[0]); 1415 pccbb_cardbus_mem_open(sc->dev, 1, starts[1], ends[1]); 1416 reg = pci_read_config(sc->dev, CBBR_BRIDGECTRL, 2); 1417 reg &= ~(CBBM_BRIDGECTRL_PREFETCH_0| 1418 CBBM_BRIDGECTRL_PREFETCH_1); 1419 reg |= (prefetchable[0]?CBBM_BRIDGECTRL_PREFETCH_0:0)| 1420 (prefetchable[1]?CBBM_BRIDGECTRL_PREFETCH_1:0); 1421 pci_write_config(sc->dev, CBBR_BRIDGECTRL, reg, 2); 1422 } else if (type == SYS_RES_IOPORT) { 1423 pccbb_cardbus_io_open(sc->dev, 0, starts[0], ends[0]); 1424 pccbb_cardbus_io_open(sc->dev, 1, starts[1], ends[1]); 1425 } 1426} 1427 1428static int 1429pccbb_cardbus_activate_resource(device_t brdev, device_t child, int type, 1430 int rid, struct resource *res) 1431{ 1432 int ret; 1433 1434 ret = BUS_ACTIVATE_RESOURCE(device_get_parent(brdev), child, 1435 type, rid, res); 1436 if (ret != 0) 1437 return (ret); 1438 pccbb_cardbus_auto_open(device_get_softc(brdev), type); 1439 return (0); 1440} 1441 1442static int 1443pccbb_cardbus_deactivate_resource(device_t brdev, device_t child, int type, 1444 int rid, struct resource *res) 1445{ 1446 int ret; 1447 1448 ret = BUS_DEACTIVATE_RESOURCE(device_get_parent(brdev), child, 1449 type, rid, res); 1450 if (ret != 0) 1451 return (ret); 1452 pccbb_cardbus_auto_open(device_get_softc(brdev), type); 1453 return (0); 1454} 1455 1456static struct resource * 1457pccbb_cardbus_alloc_resource(device_t brdev, device_t child, int type, 1458 int *rid, u_long start, u_long end, u_long count, uint flags) 1459{ 1460 struct pccbb_softc *sc = device_get_softc(brdev); 1461 int tmp; 1462 struct resource *res; 1463 1464 switch (type) { 1465 case SYS_RES_IRQ: 1466 tmp = rman_get_start(sc->irq_res); 1467 if (start > tmp || end < tmp || count != 1) { 1468 device_printf(child, "requested interrupt %ld-%ld," 1469 "count = %ld not supported by pccbb\n", 1470 start, end, count); 1471 return (NULL); 1472 } 1473 start = end = tmp; 1474 break; 1475 case SYS_RES_IOPORT: 1476 if (start <= pccbb_start_32_io) 1477 start = pccbb_start_32_io; 1478 if (end < start) 1479 end = start; 1480 break; 1481 case SYS_RES_MEMORY: 1482 if (start <= pccbb_start_mem) 1483 start = pccbb_start_mem; 1484 if (end < start) 1485 end = start; 1486 break; 1487 } 1488 1489 res = BUS_ALLOC_RESOURCE(device_get_parent(brdev), child, type, rid, 1490 start, end, count, flags & ~RF_ACTIVE); 1491 if (res == NULL) { 1492 printf("pccbb alloc res fail\n"); 1493 return (NULL); 1494 } 1495 pccbb_insert_res(sc, res, type, *rid); 1496 if (flags & RF_ACTIVE) 1497 if (bus_activate_resource(child, type, *rid, res) != 0) { 1498 bus_release_resource(child, type, *rid, res); 1499 return (NULL); 1500 } 1501 1502 return (res); 1503} 1504 1505static int 1506pccbb_cardbus_release_resource(device_t brdev, device_t child, int type, 1507 int rid, struct resource *res) 1508{ 1509 struct pccbb_softc *sc = device_get_softc(brdev); 1510 int error; 1511 1512 if (rman_get_flags(res) & RF_ACTIVE) { 1513 error = bus_deactivate_resource(child, type, rid, res); 1514 if (error != 0) 1515 return (error); 1516 } 1517 pccbb_remove_res(sc, res); 1518 return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child, 1519 type, rid, res)); 1520} 1521 1522/************************************************************************/ 1523/* PC Card Power Functions */ 1524/************************************************************************/ 1525 1526static int 1527pccbb_pcic_power_enable_socket(device_t brdev, device_t child) 1528{ 1529 struct pccbb_softc *sc = device_get_softc(brdev); 1530 int err; 1531 1532 DPRINTF(("pccbb_pcic_socket_enable:\n")); 1533 1534 /* power down/up the socket to reset */ 1535 err = pccbb_do_power(brdev); 1536 if (err) 1537 return (err); 1538 exca_reset(&sc->exca, child); 1539 1540 return (0); 1541} 1542 1543static void 1544pccbb_pcic_power_disable_socket(device_t brdev, device_t child) 1545{ 1546 struct pccbb_softc *sc = device_get_softc(brdev); 1547 1548 DPRINTF(("pccbb_pcic_socket_disable\n")); 1549 1550 /* reset signal asserting... */ 1551 exca_clrb(&sc->exca, EXCA_INTR, EXCA_INTR_RESET); 1552 DELAY(2*1000); 1553 1554 /* power down the socket */ 1555 pccbb_power(brdev, CARD_VCC_0V | CARD_VPP_0V); 1556 exca_clrb(&sc->exca, EXCA_PWRCTL, EXCA_PWRCTL_OE); 1557 1558 /* wait 300ms until power fails (Tpf). */ 1559 DELAY(300 * 1000); 1560} 1561 1562/************************************************************************/ 1563/* POWER methods */ 1564/************************************************************************/ 1565 1566static int 1567pccbb_power_enable_socket(device_t brdev, device_t child) 1568{ 1569 struct pccbb_softc *sc = device_get_softc(brdev); 1570 1571 if (sc->flags & PCCBB_16BIT_CARD) 1572 return (pccbb_pcic_power_enable_socket(brdev, child)); 1573 else 1574 return (pccbb_cardbus_power_enable_socket(brdev, child)); 1575} 1576 1577static void 1578pccbb_power_disable_socket(device_t brdev, device_t child) 1579{ 1580 struct pccbb_softc *sc = device_get_softc(brdev); 1581 if (sc->flags & PCCBB_16BIT_CARD) 1582 pccbb_pcic_power_disable_socket(brdev, child); 1583 else 1584 pccbb_cardbus_power_disable_socket(brdev, child); 1585} 1586static int 1587pccbb_pcic_activate_resource(device_t brdev, device_t child, int type, int rid, 1588 struct resource *res) 1589{ 1590 int err; 1591 struct pccbb_softc *sc = device_get_softc(brdev); 1592 if (!(rman_get_flags(res) & RF_ACTIVE)) { /* not already activated */ 1593 switch (type) { 1594 case SYS_RES_IOPORT: 1595 err = exca_io_map(&sc->exca, 0, res); 1596 break; 1597 case SYS_RES_MEMORY: 1598 err = exca_mem_map(&sc->exca, 0, res); 1599 break; 1600 default: 1601 err = 0; 1602 break; 1603 } 1604 if (err) 1605 return (err); 1606 1607 } 1608 return (BUS_ACTIVATE_RESOURCE(device_get_parent(brdev), child, 1609 type, rid, res)); 1610} 1611 1612static int 1613pccbb_pcic_deactivate_resource(device_t brdev, device_t child, int type, 1614 int rid, struct resource *res) 1615{ 1616 struct pccbb_softc *sc = device_get_softc(brdev); 1617 1618 if (rman_get_flags(res) & RF_ACTIVE) { /* if activated */ 1619 switch (type) { 1620 case SYS_RES_IOPORT: 1621 if (exca_io_unmap_res(&sc->exca, res)) 1622 return (ENOENT); 1623 break; 1624 case SYS_RES_MEMORY: 1625 if (exca_mem_unmap_res(&sc->exca, res)) 1626 return (ENOENT); 1627 break; 1628 } 1629 } 1630 return (BUS_DEACTIVATE_RESOURCE(device_get_parent(brdev), child, 1631 type, rid, res)); 1632} 1633 1634static struct resource * 1635pccbb_pcic_alloc_resource(device_t brdev, device_t child, int type, int *rid, 1636 u_long start, u_long end, u_long count, uint flags) 1637{ 1638 struct resource *res = NULL; 1639 struct pccbb_softc *sc = device_get_softc(brdev); 1640 int tmp; 1641 1642 switch (type) { 1643 case SYS_RES_MEMORY: 1644 if (start < pccbb_start_mem) 1645 start = pccbb_start_mem; 1646 if (end < start) 1647 end = start; 1648 flags = (flags & ~RF_ALIGNMENT_MASK) | 1649 rman_make_alignment_flags(CBB_MEMALIGN); 1650 break; 1651 case SYS_RES_IOPORT: 1652 if (start < pccbb_start_16_io) 1653 start = pccbb_start_16_io; 1654 if (end < start) 1655 end = start; 1656 break; 1657 case SYS_RES_IRQ: 1658 tmp = rman_get_start(sc->irq_res); 1659 if (start > tmp || end < tmp || count != 1) { 1660 device_printf(child, "requested interrupt %ld-%ld," 1661 "count = %ld not supported by pccbb\n", 1662 start, end, count); 1663 return (NULL); 1664 } 1665 flags |= RF_SHAREABLE; 1666 start = end = rman_get_start(sc->irq_res); 1667 break; 1668 } 1669 res = BUS_ALLOC_RESOURCE(device_get_parent(brdev), child, type, rid, 1670 start, end, count, flags & ~RF_ACTIVE); 1671 if (res == NULL) 1672 return (NULL); 1673 pccbb_insert_res(sc, res, type, *rid); 1674 if (flags & RF_ACTIVE) { 1675 if (bus_activate_resource(child, type, *rid, res) != 0) { 1676 bus_release_resource(child, type, *rid, res); 1677 return (NULL); 1678 } 1679 } 1680 1681 return (res); 1682} 1683 1684static int 1685pccbb_pcic_release_resource(device_t brdev, device_t child, int type, 1686 int rid, struct resource *res) 1687{ 1688 struct pccbb_softc *sc = device_get_softc(brdev); 1689 int error; 1690 1691 if (rman_get_flags(res) & RF_ACTIVE) { 1692 error = bus_deactivate_resource(child, type, rid, res); 1693 if (error != 0) 1694 return (error); 1695 } 1696 pccbb_remove_res(sc, res); 1697 return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child, 1698 type, rid, res)); 1699} 1700 1701/************************************************************************/ 1702/* PC Card methods */ 1703/************************************************************************/ 1704 1705static int 1706pccbb_pcic_set_res_flags(device_t brdev, device_t child, int type, int rid, 1707 uint32_t flags) 1708{ 1709 struct pccbb_softc *sc = device_get_softc(brdev); 1710 struct resource *res; 1711 1712 if (type != SYS_RES_MEMORY) 1713 return (EINVAL); 1714 res = pccbb_find_res(sc, type, rid); 1715 if (res == NULL) { 1716 device_printf(brdev, 1717 "set_res_flags: specified rid not found\n"); 1718 return (ENOENT); 1719 } 1720 return (exca_mem_set_flags(&sc->exca, res, flags)); 1721} 1722 1723static int 1724pccbb_pcic_set_memory_offset(device_t brdev, device_t child, int rid, 1725 uint32_t cardaddr, uint32_t *deltap) 1726{ 1727 struct pccbb_softc *sc = device_get_softc(brdev); 1728 struct resource *res; 1729 1730 res = pccbb_find_res(sc, SYS_RES_MEMORY, rid); 1731 if (res == NULL) { 1732 device_printf(brdev, 1733 "set_memory_offset: specified rid not found\n"); 1734 return (ENOENT); 1735 } 1736 return (exca_mem_set_offset(&sc->exca, res, cardaddr, deltap)); 1737} 1738 1739/************************************************************************/ 1740/* BUS Methods */ 1741/************************************************************************/ 1742 1743 1744static int 1745pccbb_activate_resource(device_t brdev, device_t child, int type, int rid, 1746 struct resource *r) 1747{ 1748 struct pccbb_softc *sc = device_get_softc(brdev); 1749 1750 if (sc->flags & PCCBB_16BIT_CARD) 1751 return (pccbb_pcic_activate_resource(brdev, child, type, rid, r)); 1752 else 1753 return (pccbb_cardbus_activate_resource(brdev, child, type, rid, 1754 r)); 1755} 1756 1757static int 1758pccbb_deactivate_resource(device_t brdev, device_t child, int type, 1759 int rid, struct resource *r) 1760{ 1761 struct pccbb_softc *sc = device_get_softc(brdev); 1762 1763 if (sc->flags & PCCBB_16BIT_CARD) 1764 return (pccbb_pcic_deactivate_resource(brdev, child, type, 1765 rid, r)); 1766 else 1767 return (pccbb_cardbus_deactivate_resource(brdev, child, type, 1768 rid, r)); 1769} 1770 1771static struct resource * 1772pccbb_alloc_resource(device_t brdev, device_t child, int type, int *rid, 1773 u_long start, u_long end, u_long count, uint flags) 1774{ 1775 struct pccbb_softc *sc = device_get_softc(brdev); 1776 1777 if (sc->flags & PCCBB_16BIT_CARD) 1778 return (pccbb_pcic_alloc_resource(brdev, child, type, rid, 1779 start, end, count, flags)); 1780 else 1781 return (pccbb_cardbus_alloc_resource(brdev, child, type, rid, 1782 start, end, count, flags)); 1783} 1784 1785static int 1786pccbb_release_resource(device_t brdev, device_t child, int type, int rid, 1787 struct resource *r) 1788{ 1789 struct pccbb_softc *sc = device_get_softc(brdev); 1790 1791 if (sc->flags & PCCBB_16BIT_CARD) 1792 return (pccbb_pcic_release_resource(brdev, child, type, 1793 rid, r)); 1794 else 1795 return (pccbb_cardbus_release_resource(brdev, child, type, 1796 rid, r)); 1797} 1798 1799static int 1800pccbb_read_ivar(device_t brdev, device_t child, int which, uintptr_t *result) 1801{ 1802 struct pccbb_softc *sc = device_get_softc(brdev); 1803 1804 switch (which) { 1805 case PCIB_IVAR_BUS: 1806 *result = sc->secbus; 1807 return (0); 1808 } 1809 return (ENOENT); 1810} 1811 1812static int 1813pccbb_write_ivar(device_t brdev, device_t child, int which, uintptr_t value) 1814{ 1815 struct pccbb_softc *sc = device_get_softc(brdev); 1816 1817 switch (which) { 1818 case PCIB_IVAR_BUS: 1819 sc->secbus = value; 1820 break; 1821 } 1822 return (ENOENT); 1823} 1824 1825/************************************************************************/ 1826/* PCI compat methods */ 1827/************************************************************************/ 1828 1829static int 1830pccbb_maxslots(device_t brdev) 1831{ 1832 return (0); 1833} 1834 1835static uint32_t 1836pccbb_read_config(device_t brdev, int b, int s, int f, int reg, int width) 1837{ 1838 /* 1839 * Pass through to the next ppb up the chain (i.e. our grandparent). 1840 */ 1841 return (PCIB_READ_CONFIG(device_get_parent(device_get_parent(brdev)), 1842 b, s, f, reg, width)); 1843} 1844 1845static void 1846pccbb_write_config(device_t brdev, int b, int s, int f, int reg, uint32_t val, 1847 int width) 1848{ 1849 /* 1850 * Pass through to the next ppb up the chain (i.e. our grandparent). 1851 */ 1852 PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(brdev)), 1853 b, s, f, reg, val, width); 1854} 1855 1856static int 1857pccbb_suspend(device_t self) 1858{ 1859 int error = 0; 1860 struct pccbb_softc* sc = device_get_softc(self); 1861 1862 bus_teardown_intr(self, sc->irq_res, sc->intrhand); 1863 error = bus_generic_suspend(self); 1864 return (error); 1865} 1866 1867static int 1868pccbb_resume(device_t self) 1869{ 1870 int error = 0; 1871 struct pccbb_softc *sc = (struct pccbb_softc *)device_get_softc(self); 1872 uint32_t tmp; 1873 1874 pci_write_config(self, CBBR_SOCKBASE, rman_get_start(sc->base_res), 4); 1875 DEVPRINTF((self, "PCI Memory allocated: %08lx\n", 1876 rman_get_start(sc->base_res))); 1877 1878 pccbb_chipinit(sc); 1879 1880 /* re-establish the interrupt. */ 1881 if (bus_setup_intr(self, sc->irq_res, INTR_TYPE_AV, pccbb_intr, sc, 1882 &sc->intrhand)) { 1883 device_printf(self, "couldn't re-establish interrupt"); 1884 bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res); 1885 bus_release_resource(self, SYS_RES_MEMORY, CBBR_SOCKBASE, 1886 sc->base_res); 1887 sc->irq_res = NULL; 1888 sc->base_res = NULL; 1889 return (ENOMEM); 1890 } 1891 1892 /* CSC Interrupt: Card detect interrupt on */ 1893 pccbb_setb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD); 1894 1895 /* reset interrupt */ 1896 tmp = pccbb_get(sc, CBB_SOCKET_EVENT); 1897 pccbb_set(sc, CBB_SOCKET_EVENT, tmp); 1898 1899 /* 1900 * Some BIOSes will not save the BARs for the pci chips, so we 1901 * must do it ourselves. If the BAR is reset to 0 for an I/O 1902 * device, it will read back as 0x1, so no explicit test for 1903 * memory devices are needed. 1904 * 1905 * Note: The PCI bus code should do this automatically for us on 1906 * suspend/resume, but until it does, we have to cope. 1907 */ 1908 if (pci_read_config(self, CBBR_SOCKBASE, 4) == 0) 1909 pci_write_config(self, CBBR_SOCKBASE, 1910 rman_get_start(sc->base_res), 4); 1911 1912 error = bus_generic_resume(self); 1913 1914 return (error); 1915} 1916 1917static device_method_t pccbb_methods[] = { 1918 /* Device interface */ 1919 DEVMETHOD(device_probe, pccbb_probe), 1920 DEVMETHOD(device_attach, pccbb_attach), 1921 DEVMETHOD(device_detach, pccbb_detach), 1922 DEVMETHOD(device_shutdown, pccbb_shutdown), 1923 DEVMETHOD(device_suspend, pccbb_suspend), 1924 DEVMETHOD(device_resume, pccbb_resume), 1925 1926 /* bus methods */ 1927 DEVMETHOD(bus_print_child, bus_generic_print_child), 1928 DEVMETHOD(bus_read_ivar, pccbb_read_ivar), 1929 DEVMETHOD(bus_write_ivar, pccbb_write_ivar), 1930 DEVMETHOD(bus_alloc_resource, pccbb_alloc_resource), 1931 DEVMETHOD(bus_release_resource, pccbb_release_resource), 1932 DEVMETHOD(bus_activate_resource, pccbb_activate_resource), 1933 DEVMETHOD(bus_deactivate_resource, pccbb_deactivate_resource), 1934 DEVMETHOD(bus_driver_added, pccbb_driver_added), 1935 DEVMETHOD(bus_child_detached, pccbb_child_detached), 1936 DEVMETHOD(bus_setup_intr, pccbb_setup_intr), 1937 DEVMETHOD(bus_teardown_intr, pccbb_teardown_intr), 1938 1939 /* 16-bit card interface */ 1940 DEVMETHOD(card_set_res_flags, pccbb_pcic_set_res_flags), 1941 DEVMETHOD(card_set_memory_offset, pccbb_pcic_set_memory_offset), 1942 DEVMETHOD(card_reprobe_card, pccbb_card_reprobe), 1943 1944 /* power interface */ 1945 DEVMETHOD(power_enable_socket, pccbb_power_enable_socket), 1946 DEVMETHOD(power_disable_socket, pccbb_power_disable_socket), 1947 1948 /* pcib compatibility interface */ 1949 DEVMETHOD(pcib_maxslots, pccbb_maxslots), 1950 DEVMETHOD(pcib_read_config, pccbb_read_config), 1951 DEVMETHOD(pcib_write_config, pccbb_write_config), 1952 {0,0} 1953}; 1954 1955static driver_t pccbb_driver = { 1956 "pccbb", 1957 pccbb_methods, 1958 sizeof(struct pccbb_softc) 1959}; 1960 1961static devclass_t pccbb_devclass; 1962 1963DRIVER_MODULE(pccbb, pci, pccbb_driver, pccbb_devclass, 0, 0); 1964MODULE_VERSION(pccbb, 1); 1965MODULE_DEPEND(pccbb, exca, 1, 1, 1); 1966MODULE_DEPEND(pccbb, pccard, 1, 1, 1); 1967MODULE_DEPEND(pccbb, cardbus, 1, 1, 1);
|