1 /* $NetBSD: ehci_cardbus.c,v 1.6 2002/10/02 16:33:41 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson (lennart@augustsson.net) at 9 * Carlstedt Research & Technology. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 #include <sys/cdefs.h> 41 __KERNEL_RCSID(0, "$NetBSD: ehci_cardbus.c,v 1.6 2002/10/02 16:33:41 thorpej Exp $"); 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/kernel.h> 46 #include <sys/device.h> 47 #include <sys/proc.h> 48 49 #include <machine/bus.h> 50 51 #if defined pciinc 52 #include <dev/pci/pcidevs.h> 53 #endif 54 55 #include <dev/cardbus/cardbusvar.h> 56 #include <dev/cardbus/cardbusdevs.h> 57 58 #include <dev/cardbus/usb_cardbus.h> 59 60 #include <dev/usb/usb.h> 61 #include <dev/usb/usbdi.h> 62 #include <dev/usb/usbdivar.h> 63 #include <dev/usb/usb_mem.h> 64 65 #include <dev/usb/ehcireg.h> 66 #include <dev/usb/ehcivar.h> 67 68 #ifdef EHCI_DEBUG 69 #define DPRINTF(x) if (ehcidebug) printf x 70 extern int ehcidebug; 71 #else 72 #define DPRINTF(x) 73 #endif 74 75 int ehci_cardbus_match(struct device *, struct cfdata *, void *); 76 void ehci_cardbus_attach(struct device *, struct device *, void *); 77 int ehci_cardbus_detach(device_ptr_t, int); 78 79 struct ehci_cardbus_softc { 80 ehci_softc_t sc; 81 cardbus_chipset_tag_t sc_cc; 82 cardbus_function_tag_t sc_cf; 83 cardbus_devfunc_t sc_ct; 84 void *sc_ih; /* interrupt vectoring */ 85 }; 86 87 CFATTACH_DECL(ehci_cardbus, sizeof(struct ehci_cardbus_softc), 88 ehci_cardbus_match, ehci_cardbus_attach, ehci_cardbus_detach, ehci_activate); 89 90 #define CARDBUS_INTERFACE_EHCI PCI_INTERFACE_EHCI 91 #define CARDBUS_CBMEM PCI_CBMEM 92 #define cardbus_findvendor pci_findvendor 93 #define cardbus_devinfo pci_devinfo 94 95 static TAILQ_HEAD(, usb_cardbus) ehci_cardbus_alldevs = 96 TAILQ_HEAD_INITIALIZER(ehci_cardbus_alldevs); 97 98 int 99 ehci_cardbus_match(struct device *parent, struct cfdata *match, void *aux) 100 { 101 struct cardbus_attach_args *ca = (struct cardbus_attach_args *)aux; 102 103 if (CARDBUS_CLASS(ca->ca_class) == CARDBUS_CLASS_SERIALBUS && 104 CARDBUS_SUBCLASS(ca->ca_class) == CARDBUS_SUBCLASS_SERIALBUS_USB && 105 CARDBUS_INTERFACE(ca->ca_class) == CARDBUS_INTERFACE_EHCI) 106 return (1); 107 108 return (0); 109 } 110 111 void 112 ehci_cardbus_attach(struct device *parent, struct device *self, void *aux) 113 { 114 struct ehci_cardbus_softc *sc = (struct ehci_cardbus_softc *)self; 115 struct cardbus_attach_args *ca = aux; 116 cardbus_devfunc_t ct = ca->ca_ct; 117 cardbus_chipset_tag_t cc = ct->ct_cc; 118 cardbus_function_tag_t cf = ct->ct_cf; 119 cardbusreg_t csr; 120 char devinfo[256]; 121 usbd_status r; 122 char *vendor; 123 u_int ncomp; 124 const char *devname = sc->sc.sc_bus.bdev.dv_xname; 125 struct usb_cardbus *up; 126 127 cardbus_devinfo(ca->ca_id, ca->ca_class, 0, devinfo); 128 printf(": %s (rev. 0x%02x)\n", devinfo, 129 CARDBUS_REVISION(ca->ca_class)); 130 131 /* Map I/O registers */ 132 if (Cardbus_mapreg_map(ct, CARDBUS_CBMEM, CARDBUS_MAPREG_TYPE_MEM, 0, 133 &sc->sc.iot, &sc->sc.ioh, NULL, &sc->sc.sc_size)) { 134 printf("%s: can't map mem space\n", devname); 135 return; 136 } 137 138 sc->sc_cc = cc; 139 sc->sc_cf = cf; 140 sc->sc_ct = ct; 141 sc->sc.sc_bus.dmatag = ca->ca_dmat; 142 143 #if rbus 144 #else 145 XXX (ct->ct_cf->cardbus_mem_open)(cc, 0, iob, iob + 0x40); 146 #endif 147 (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE); 148 (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE); 149 150 /* Enable the device. */ 151 csr = cardbus_conf_read(cc, cf, ca->ca_tag, 152 CARDBUS_COMMAND_STATUS_REG); 153 cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_COMMAND_STATUS_REG, 154 csr | CARDBUS_COMMAND_MASTER_ENABLE 155 | CARDBUS_COMMAND_MEM_ENABLE); 156 157 /* Disable interrupts, so we don't get any spurious ones. */ 158 sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH); 159 DPRINTF(("%s: offs=%d\n", devname, sc->sc.sc_offs)); 160 EOWRITE2(&sc->sc, EHCI_USBINTR, 0); 161 162 sc->sc_ih = cardbus_intr_establish(cc, cf, ca->ca_intrline, 163 IPL_USB, ehci_intr, sc); 164 if (sc->sc_ih == NULL) { 165 printf("%s: couldn't establish interrupt\n", devname); 166 return; 167 } 168 printf("%s: interrupting at %d\n", devname, ca->ca_intrline); 169 170 /* Figure out vendor for root hub descriptor. */ 171 vendor = cardbus_findvendor(ca->ca_id); 172 sc->sc.sc_id_vendor = CARDBUS_VENDOR(ca->ca_id); 173 if (vendor) 174 strncpy(sc->sc.sc_vendor, vendor, 175 sizeof(sc->sc.sc_vendor) - 1); 176 else 177 sprintf(sc->sc.sc_vendor, "vendor 0x%04x", 178 CARDBUS_VENDOR(ca->ca_id)); 179 180 /* 181 * Find companion controllers. According to the spec they always 182 * have lower function numbers so they should be enumerated already. 183 */ 184 ncomp = 0; 185 TAILQ_FOREACH(up, &ehci_cardbus_alldevs, next) { 186 if (up->bus == ca->ca_bus && up->device == ca->ca_device) { 187 DPRINTF(("ehci_cardbus_attach: companion %s\n", 188 USBDEVNAME(up->usb->bdev))); 189 sc->sc.sc_comps[ncomp++] = up->usb; 190 if (ncomp >= EHCI_COMPANION_MAX) 191 break; 192 } 193 } 194 sc->sc.sc_ncomp = ncomp; 195 196 r = ehci_init(&sc->sc); 197 if (r != USBD_NORMAL_COMPLETION) { 198 printf("%s: init failed, error=%d\n", devname, r); 199 200 /* Avoid spurious interrupts. */ 201 cardbus_intr_disestablish(sc->sc_cc, sc->sc_cf, sc->sc_ih); 202 sc->sc_ih = NULL; 203 204 return; 205 } 206 207 /* Attach usb device. */ 208 sc->sc.sc_child = config_found((void *)sc, &sc->sc.sc_bus, 209 usbctlprint); 210 } 211 212 int 213 ehci_cardbus_detach(device_ptr_t self, int flags) 214 { 215 struct ehci_cardbus_softc *sc = (struct ehci_cardbus_softc *)self; 216 struct cardbus_devfunc *ct = sc->sc_ct; 217 int rv; 218 219 rv = ehci_detach(&sc->sc, flags); 220 if (rv) 221 return (rv); 222 if (sc->sc_ih != NULL) { 223 cardbus_intr_disestablish(sc->sc_cc, sc->sc_cf, sc->sc_ih); 224 sc->sc_ih = NULL; 225 } 226 if (sc->sc.sc_size) { 227 Cardbus_mapreg_unmap(ct, CARDBUS_CBMEM, sc->sc.iot, 228 sc->sc.ioh, sc->sc.sc_size); 229 sc->sc.sc_size = 0; 230 } 231 return (0); 232 } 233 234 void 235 usb_cardbus_add(struct usb_cardbus *up, struct cardbus_attach_args *ca, struct usbd_bus *bu) 236 { 237 TAILQ_INSERT_TAIL(&ehci_cardbus_alldevs, up, next); 238 up->bus = ca->ca_bus; 239 up->device = ca->ca_device; 240 up->function = ca->ca_function; 241 up->usb = bu; 242 } 243 244 void 245 usb_cardbus_rem(struct usb_cardbus *up) 246 { 247 TAILQ_REMOVE(&ehci_cardbus_alldevs, up, next); 248 } 249