uhci_pci.c revision 190749
1/*- 2 * Copyright (c) 1998 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Lennart Augustsson (augustss@carlstedt.se) at 7 * Carlstedt Research & Technology. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the NetBSD 20 * Foundation, Inc. and its contributors. 21 * 4. Neither the name of The NetBSD Foundation nor the names of its 22 * contributors may be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38#include <sys/cdefs.h> 39__FBSDID("$FreeBSD: head/sys/dev/usb/controller/uhci_pci.c 190749 2009-04-05 21:24:15Z piso $"); 40 41/* Universal Host Controller Interface 42 * 43 * UHCI spec: http://www.intel.com/ 44 */ 45 46/* The low level controller code for UHCI has been split into 47 * PCI probes and UHCI specific code. This was done to facilitate the 48 * sharing of code between *BSD's 49 */ 50 51#include <dev/usb/usb_mfunc.h> 52#include <dev/usb/usb.h> 53 54#include <dev/usb/usb_core.h> 55#include <dev/usb/usb_busdma.h> 56#include <dev/usb/usb_process.h> 57#include <dev/usb/usb_sw_transfer.h> 58#include <dev/usb/usb_util.h> 59#include <dev/usb/usb_debug.h> 60 61#include <dev/usb/usb_controller.h> 62#include <dev/usb/usb_bus.h> 63#include <dev/usb/usb_pci.h> 64#include <dev/usb/controller/uhci.h> 65 66#define PCI_UHCI_VENDORID_INTEL 0x8086 67#define PCI_UHCI_VENDORID_VIA 0x1106 68 69/* PIIX4E has no separate stepping */ 70 71#define PCI_UHCI_BASE_REG 0x20 72 73static device_probe_t uhci_pci_probe; 74static device_attach_t uhci_pci_attach; 75static device_detach_t uhci_pci_detach; 76static device_suspend_t uhci_pci_suspend; 77static device_resume_t uhci_pci_resume; 78 79static int 80uhci_pci_suspend(device_t self) 81{ 82 uhci_softc_t *sc = device_get_softc(self); 83 int err; 84 85 err = bus_generic_suspend(self); 86 if (err) { 87 return (err); 88 } 89 uhci_suspend(sc); 90 return (0); 91} 92 93static int 94uhci_pci_resume(device_t self) 95{ 96 uhci_softc_t *sc = device_get_softc(self); 97 98 pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2); 99 100 uhci_resume(sc); 101 102 bus_generic_resume(self); 103 return (0); 104} 105 106static const char * 107uhci_pci_match(device_t self) 108{ 109 uint32_t device_id = pci_get_devid(self); 110 111 switch (device_id) { 112 case 0x26888086: 113 return ("Intel 631XESB/632XESB/3100 USB controller USB-1"); 114 115 case 0x26898086: 116 return ("Intel 631XESB/632XESB/3100 USB controller USB-2"); 117 118 case 0x268a8086: 119 return ("Intel 631XESB/632XESB/3100 USB controller USB-3"); 120 121 case 0x268b8086: 122 return ("Intel 631XESB/632XESB/3100 USB controller USB-4"); 123 124 case 0x70208086: 125 return ("Intel 82371SB (PIIX3) USB controller"); 126 127 case 0x71128086: 128 return ("Intel 82371AB/EB (PIIX4) USB controller"); 129 130 case 0x24128086: 131 return ("Intel 82801AA (ICH) USB controller"); 132 133 case 0x24228086: 134 return ("Intel 82801AB (ICH0) USB controller"); 135 136 case 0x24428086: 137 return ("Intel 82801BA/BAM (ICH2) USB controller USB-A"); 138 139 case 0x24448086: 140 return ("Intel 82801BA/BAM (ICH2) USB controller USB-B"); 141 142 case 0x24828086: 143 return ("Intel 82801CA/CAM (ICH3) USB controller USB-A"); 144 145 case 0x24848086: 146 return ("Intel 82801CA/CAM (ICH3) USB controller USB-B"); 147 148 case 0x24878086: 149 return ("Intel 82801CA/CAM (ICH3) USB controller USB-C"); 150 151 case 0x24c28086: 152 return ("Intel 82801DB (ICH4) USB controller USB-A"); 153 154 case 0x24c48086: 155 return ("Intel 82801DB (ICH4) USB controller USB-B"); 156 157 case 0x24c78086: 158 return ("Intel 82801DB (ICH4) USB controller USB-C"); 159 160 case 0x24d28086: 161 return ("Intel 82801EB (ICH5) USB controller USB-A"); 162 163 case 0x24d48086: 164 return ("Intel 82801EB (ICH5) USB controller USB-B"); 165 166 case 0x24d78086: 167 return ("Intel 82801EB (ICH5) USB controller USB-C"); 168 169 case 0x24de8086: 170 return ("Intel 82801EB (ICH5) USB controller USB-D"); 171 172 case 0x26588086: 173 return ("Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-A"); 174 175 case 0x26598086: 176 return ("Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-B"); 177 178 case 0x265a8086: 179 return ("Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-C"); 180 181 case 0x265b8086: 182 return ("Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-D"); 183 184 case 0x28308086: 185 return ("Intel 82801H (ICH8) USB controller USB-A"); 186 case 0x28318086: 187 return ("Intel 82801H (ICH8) USB controller USB-B"); 188 case 0x28328086: 189 return ("Intel 82801H (ICH8) USB controller USB-C"); 190 case 0x28348086: 191 return ("Intel 82801H (ICH8) USB controller USB-D"); 192 case 0x28358086: 193 return ("Intel 82801H (ICH8) USB controller USB-E"); 194 case 0x29348086: 195 return ("Intel 82801I (ICH9) USB controller"); 196 case 0x29358086: 197 return ("Intel 82801I (ICH9) USB controller"); 198 case 0x29368086: 199 return ("Intel 82801I (ICH9) USB controller"); 200 case 0x29378086: 201 return ("Intel 82801I (ICH9) USB controller"); 202 case 0x29388086: 203 return ("Intel 82801I (ICH9) USB controller"); 204 case 0x29398086: 205 return ("Intel 82801I (ICH9) USB controller"); 206 207 case 0x719a8086: 208 return ("Intel 82443MX USB controller"); 209 210 case 0x76028086: 211 return ("Intel 82372FB/82468GX USB controller"); 212 213 case 0x30381106: 214 return ("VIA 83C572 USB controller"); 215 216 default: 217 break; 218 } 219 220 if ((pci_get_class(self) == PCIC_SERIALBUS) && 221 (pci_get_subclass(self) == PCIS_SERIALBUS_USB) && 222 (pci_get_progif(self) == PCI_INTERFACE_UHCI)) { 223 return ("UHCI (generic) USB controller"); 224 } 225 return (NULL); 226} 227 228static int 229uhci_pci_probe(device_t self) 230{ 231 const char *desc = uhci_pci_match(self); 232 233 if (desc) { 234 device_set_desc(self, desc); 235 return (0); 236 } else { 237 return (ENXIO); 238 } 239} 240 241static int 242uhci_pci_attach(device_t self) 243{ 244 uhci_softc_t *sc = device_get_softc(self); 245 int rid; 246 int err; 247 248 /* initialise some bus fields */ 249 sc->sc_bus.parent = self; 250 sc->sc_bus.devices = sc->sc_devices; 251 sc->sc_bus.devices_max = UHCI_MAX_DEVICES; 252 253 /* get all DMA memory */ 254 if (usb2_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self), 255 &uhci_iterate_hw_softc)) { 256 return ENOMEM; 257 } 258 sc->sc_dev = self; 259 260 pci_enable_busmaster(self); 261 262 rid = PCI_UHCI_BASE_REG; 263 sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_IOPORT, &rid, 264 RF_ACTIVE); 265 if (!sc->sc_io_res) { 266 device_printf(self, "Could not map ports\n"); 267 goto error; 268 } 269 sc->sc_io_tag = rman_get_bustag(sc->sc_io_res); 270 sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res); 271 sc->sc_io_size = rman_get_size(sc->sc_io_res); 272 273 /* disable interrupts */ 274 bus_space_write_2(sc->sc_io_tag, sc->sc_io_hdl, UHCI_INTR, 0); 275 276 rid = 0; 277 sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, 278 RF_SHAREABLE | RF_ACTIVE); 279 if (sc->sc_irq_res == NULL) { 280 device_printf(self, "Could not allocate irq\n"); 281 goto error; 282 } 283 sc->sc_bus.bdev = device_add_child(self, "usbus", -1); 284 if (!sc->sc_bus.bdev) { 285 device_printf(self, "Could not add USB device\n"); 286 goto error; 287 } 288 device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); 289 290 /* 291 * uhci_pci_match must never return NULL if uhci_pci_probe 292 * succeeded 293 */ 294 device_set_desc(sc->sc_bus.bdev, uhci_pci_match(self)); 295 switch (pci_get_vendor(self)) { 296 case PCI_UHCI_VENDORID_INTEL: 297 sprintf(sc->sc_vendor, "Intel"); 298 break; 299 case PCI_UHCI_VENDORID_VIA: 300 sprintf(sc->sc_vendor, "VIA"); 301 break; 302 default: 303 if (bootverbose) { 304 device_printf(self, "(New UHCI DeviceId=0x%08x)\n", 305 pci_get_devid(self)); 306 } 307 sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self)); 308 } 309 310 switch (pci_read_config(self, PCI_USBREV, 1) & PCI_USB_REV_MASK) { 311 case PCI_USB_REV_PRE_1_0: 312 sc->sc_bus.usbrev = USB_REV_PRE_1_0; 313 break; 314 case PCI_USB_REV_1_0: 315 sc->sc_bus.usbrev = USB_REV_1_0; 316 break; 317 default: 318 /* Quirk for Parallels Desktop 4.0 */ 319 device_printf(self, "USB revision is unknown. Assuming v1.1.\n"); 320 sc->sc_bus.usbrev = USB_REV_1_1; 321 break; 322 } 323 324#if (__FreeBSD_version >= 700031) 325 err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 326 NULL, (driver_intr_t *)uhci_interrupt, sc, &sc->sc_intr_hdl); 327#else 328 err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 329 (driver_intr_t *)uhci_interrupt, sc, &sc->sc_intr_hdl); 330#endif 331 332 if (err) { 333 device_printf(self, "Could not setup irq, %d\n", err); 334 sc->sc_intr_hdl = NULL; 335 goto error; 336 } 337 /* 338 * Set the PIRQD enable bit and switch off all the others. We don't 339 * want legacy support to interfere with us XXX Does this also mean 340 * that the BIOS won't touch the keyboard anymore if it is connected 341 * to the ports of the root hub? 342 */ 343#if USB_DEBUG 344 if (pci_read_config(self, PCI_LEGSUP, 2) != PCI_LEGSUP_USBPIRQDEN) { 345 device_printf(self, "LegSup = 0x%04x\n", 346 pci_read_config(self, PCI_LEGSUP, 2)); 347 } 348#endif 349 pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2); 350 351 err = uhci_init(sc); 352 if (!err) { 353 err = device_probe_and_attach(sc->sc_bus.bdev); 354 } 355 if (err) { 356 device_printf(self, "USB init failed\n"); 357 goto error; 358 } 359 return (0); 360 361error: 362 uhci_pci_detach(self); 363 return (ENXIO); 364} 365 366int 367uhci_pci_detach(device_t self) 368{ 369 uhci_softc_t *sc = device_get_softc(self); 370 device_t bdev; 371 372 if (sc->sc_bus.bdev) { 373 bdev = sc->sc_bus.bdev; 374 device_detach(bdev); 375 device_delete_child(self, bdev); 376 } 377 /* during module unload there are lots of children leftover */ 378 device_delete_all_children(self); 379 380 /* 381 * disable interrupts that might have been switched on in 382 * uhci_init. 383 */ 384 if (sc->sc_io_res) { 385 USB_BUS_LOCK(&sc->sc_bus); 386 387 /* stop the controller */ 388 uhci_reset(sc); 389 390 USB_BUS_UNLOCK(&sc->sc_bus); 391 } 392 pci_disable_busmaster(self); 393 394 if (sc->sc_irq_res && sc->sc_intr_hdl) { 395 int err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl); 396 397 if (err) { 398 /* XXX or should we panic? */ 399 device_printf(self, "Could not tear down irq, %d\n", 400 err); 401 } 402 sc->sc_intr_hdl = NULL; 403 } 404 if (sc->sc_irq_res) { 405 bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res); 406 sc->sc_irq_res = NULL; 407 } 408 if (sc->sc_io_res) { 409 bus_release_resource(self, SYS_RES_IOPORT, PCI_UHCI_BASE_REG, 410 sc->sc_io_res); 411 sc->sc_io_res = NULL; 412 } 413 usb2_bus_mem_free_all(&sc->sc_bus, &uhci_iterate_hw_softc); 414 415 return (0); 416} 417 418static driver_t uhci_driver = 419{ 420 .name = "uhci", 421 .methods = (device_method_t[]){ 422 /* device interface */ 423 DEVMETHOD(device_probe, uhci_pci_probe), 424 DEVMETHOD(device_attach, uhci_pci_attach), 425 DEVMETHOD(device_detach, uhci_pci_detach), 426 427 DEVMETHOD(device_suspend, uhci_pci_suspend), 428 DEVMETHOD(device_resume, uhci_pci_resume), 429 DEVMETHOD(device_shutdown, bus_generic_shutdown), 430 431 /* Bus interface */ 432 DEVMETHOD(bus_print_child, bus_generic_print_child), 433 {0, 0} 434 }, 435 .size = sizeof(struct uhci_softc), 436}; 437 438static devclass_t uhci_devclass; 439 440DRIVER_MODULE(uhci, pci, uhci_driver, uhci_devclass, 0, 0); 441MODULE_DEPEND(uhci, usb, 1, 1, 1); 442