]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/usb/uhci_pci.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / dev / usb / uhci_pci.c
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$");
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 "opt_bus.h"
52
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>
56 #include <sys/module.h>
57 #include <sys/lock.h>
58 #include <sys/mutex.h>
59 #include <sys/bus.h>
60 #include <sys/queue.h>
61 #include <sys/bus.h>
62
63 #include <machine/bus.h>
64 #include <machine/resource.h>
65 #include <sys/rman.h>
66
67 #include <dev/pci/pcivar.h>
68 #include <dev/pci/pcireg.h>
69
70 #include <dev/usb/usb.h>
71 #include <dev/usb/usbdi.h>
72 #include <dev/usb/usbdivar.h>
73 #include <dev/usb/usb_mem.h>
74
75 #include <dev/usb/uhcireg.h>
76 #include <dev/usb/uhcivar.h>
77
78 #define PCI_UHCI_VENDORID_INTEL         0x8086
79 #define PCI_UHCI_VENDORID_VIA           0x1106
80
81 #define PCI_UHCI_DEVICEID_PIIX3         0x70208086
82 static const char *uhci_device_piix3 = "Intel 82371SB (PIIX3) USB controller";
83
84 #define PCI_UHCI_DEVICEID_PIIX4         0x71128086
85 #define PCI_UHCI_DEVICEID_PIIX4E        0x71128086      /* no separate stepping */
86 static const char *uhci_device_piix4 = "Intel 82371AB/EB (PIIX4) USB controller";
87
88 #define PCI_UHCI_DEVICEID_ICH           0x24128086
89 static const char *uhci_device_ich = "Intel 82801AA (ICH) USB controller";
90
91 #define PCI_UHCI_DEVICEID_ICH0          0x24228086
92 static const char *uhci_device_ich0 = "Intel 82801AB (ICH0) USB controller";
93
94 #define PCI_UHCI_DEVICEID_ICH2_A        0x24428086
95 static const char *uhci_device_ich2_a = "Intel 82801BA/BAM (ICH2) USB controller USB-A";
96
97 #define PCI_UHCI_DEVICEID_ICH2_B        0x24448086
98 static const char *uhci_device_ich2_b = "Intel 82801BA/BAM (ICH2) USB controller USB-B";
99
100 #define PCI_UHCI_DEVICEID_ICH3_A        0x24828086
101 static const char *uhci_device_ich3_a = "Intel 82801CA/CAM (ICH3) USB controller USB-A";
102
103 #define PCI_UHCI_DEVICEID_ICH3_B        0x24848086
104 static const char *uhci_device_ich3_b = "Intel 82801CA/CAM (ICH3) USB controller USB-B";
105
106 #define PCI_UHCI_DEVICEID_ICH3_C        0x24878086
107 static const char *uhci_device_ich3_c = "Intel 82801CA/CAM (ICH3) USB controller USB-C";
108
109 #define PCI_UHCI_DEVICEID_ICH4_A        0x24c28086
110 static const char *uhci_device_ich4_a = "Intel 82801DB (ICH4) USB controller USB-A";
111
112 #define PCI_UHCI_DEVICEID_ICH4_B        0x24c48086
113 static const char *uhci_device_ich4_b = "Intel 82801DB (ICH4) USB controller USB-B";
114
115 #define PCI_UHCI_DEVICEID_ICH4_C        0x24c78086
116 static const char *uhci_device_ich4_c = "Intel 82801DB (ICH4) USB controller USB-C";
117
118 #define PCI_UHCI_DEVICEID_ICH5_A        0x24d28086
119 static const char *uhci_device_ich5_a = "Intel 82801EB (ICH5) USB controller USB-A";
120
121 #define PCI_UHCI_DEVICEID_ICH5_B        0x24d48086
122 static const char *uhci_device_ich5_b = "Intel 82801EB (ICH5) USB controller USB-B";
123
124 #define PCI_UHCI_DEVICEID_ICH5_C        0x24d78086
125 static const char *uhci_device_ich5_c = "Intel 82801EB (ICH5) USB controller USB-C";
126
127 #define PCI_UHCI_DEVICEID_ICH5_D        0x24de8086
128 static const char *uhci_device_ich5_d = "Intel 82801EB (ICH5) USB controller USB-D";
129
130 #define PCI_UHCI_DEVICEID_ICH6_A        0x26588086
131 static const char *uhci_device_ich6_a = "Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-A";
132
133 #define PCI_UHCI_DEVICEID_ICH6_B        0x26598086
134 static const char *uhci_device_ich6_b = "Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-B";
135
136 #define PCI_UHCI_DEVICEID_ICH6_C        0x265a8086
137 static const char *uhci_device_ich6_c = "Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-C";
138
139 #define PCI_UHCI_DEVICEID_ICH6_D        0x265b8086
140 static const char *uhci_device_ich6_d = "Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-D";
141
142 #define PCI_UHCI_DEVICEID_63XXESB_1     0x26888086
143 static const char *uhci_device_esb_1 = "Intel 631XESB/632XESB/3100 USB controller USB-1";
144
145 #define PCI_UHCI_DEVICEID_63XXESB_2     0x26898086
146 static const char *uhci_device_esb_2 = "Intel 631XESB/632XESB/3100 USB controller USB-2";
147
148 #define PCI_UHCI_DEVICEID_63XXESB_3     0x268a8086
149 static const char *uhci_device_esb_3 = "Intel 631XESB/632XESB/3100 USB controller USB-3";
150
151 #define PCI_UHCI_DEVICEID_63XXESB_4     0x268b8086
152 static const char *uhci_device_esb_4 = "Intel 631XESB/632XESB/3100 USB controller USB-4";
153
154 #define PCI_UHCI_DEVICEID_ICH8_A        0x28308086
155 static const char *uhci_device_ich8_a = "Intel 82801H (ICH8) USB controller USB-A";
156
157 #define PCI_UHCI_DEVICEID_ICH8_B        0x28318086
158 static const char *uhci_device_ich8_b = "Intel 82801H (ICH8) USB controller USB-B";
159
160 #define PCI_UHCI_DEVICEID_ICH8_C        0x28328086
161 static const char *uhci_device_ich8_c = "Intel 82801H (ICH8) USB controller USB-C";
162
163 #define PCI_UHCI_DEVICEID_ICH8_D        0x28348086
164 static const char *uhci_device_ich8_d = "Intel 82801H (ICH8) USB controller USB-D";
165
166 #define PCI_UHCI_DEVICEID_ICH8_E        0x28358086
167 static const char *uhci_device_ich8_e = "Intel 82801H (ICH8) USB controller USB-E";
168
169 #define PCI_UHCI_DEVICEID_440MX         0x719a8086
170 static const char *uhci_device_440mx = "Intel 82443MX USB controller";
171
172 #define PCI_UHCI_DEVICEID_460GX         0x76028086
173 static const char *uhci_device_460gx = "Intel 82372FB/82468GX USB controller";
174
175 #define PCI_UHCI_DEVICEID_VT83C572      0x30381106
176 static const char *uhci_device_vt83c572 = "VIA 83C572 USB controller";
177
178 static const char *uhci_device_generic = "UHCI (generic) USB controller";
179
180 #define PCI_UHCI_BASE_REG               0x20
181
182
183 static device_attach_t uhci_pci_attach;
184 static device_detach_t uhci_pci_detach;
185 static device_suspend_t uhci_pci_suspend;
186 static device_resume_t uhci_pci_resume;
187
188 static int
189 uhci_pci_suspend(device_t self)
190 {
191         uhci_softc_t *sc = device_get_softc(self);
192         int err;
193
194         err = bus_generic_suspend(self);
195         if (err)
196                 return err;
197         uhci_power(PWR_SUSPEND, sc);
198
199         return 0;
200 }
201
202 static int
203 uhci_pci_resume(device_t self)
204 {
205         uhci_softc_t *sc = device_get_softc(self);
206
207         pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2);
208
209         uhci_power(PWR_RESUME, sc);
210         bus_generic_resume(self);
211
212         return 0;
213 }
214
215 static const char *
216 uhci_pci_match(device_t self)
217 {
218         u_int32_t device_id = pci_get_devid(self);
219
220         if (device_id == PCI_UHCI_DEVICEID_PIIX3) {
221                 return (uhci_device_piix3);
222         } else if (device_id == PCI_UHCI_DEVICEID_PIIX4) {
223                 return (uhci_device_piix4);
224         } else if (device_id == PCI_UHCI_DEVICEID_ICH) {
225                 return (uhci_device_ich);
226         } else if (device_id == PCI_UHCI_DEVICEID_ICH0) {
227                 return (uhci_device_ich0);
228         } else if (device_id == PCI_UHCI_DEVICEID_ICH2_A) {
229                 return (uhci_device_ich2_a);
230         } else if (device_id == PCI_UHCI_DEVICEID_ICH2_B) {
231                 return (uhci_device_ich2_b);
232         } else if (device_id == PCI_UHCI_DEVICEID_ICH3_A) {
233                 return (uhci_device_ich3_a);
234         } else if (device_id == PCI_UHCI_DEVICEID_ICH3_B) {
235                 return (uhci_device_ich3_b);
236         } else if (device_id == PCI_UHCI_DEVICEID_ICH3_C) {
237                 return (uhci_device_ich3_c);
238         } else if (device_id == PCI_UHCI_DEVICEID_ICH4_A) {
239                 return (uhci_device_ich4_a);
240         } else if (device_id == PCI_UHCI_DEVICEID_ICH4_B) {
241                 return (uhci_device_ich4_b);
242         } else if (device_id == PCI_UHCI_DEVICEID_ICH4_C) {
243                 return (uhci_device_ich4_c);
244         } else if (device_id == PCI_UHCI_DEVICEID_ICH5_A) {
245                 return (uhci_device_ich5_a);
246         } else if (device_id == PCI_UHCI_DEVICEID_ICH5_B) {
247                 return (uhci_device_ich5_b);
248         } else if (device_id == PCI_UHCI_DEVICEID_ICH5_C) {
249                 return (uhci_device_ich5_c);
250         } else if (device_id == PCI_UHCI_DEVICEID_ICH5_D) {
251                 return (uhci_device_ich5_d);
252         } else if (device_id == PCI_UHCI_DEVICEID_ICH6_A) {
253                 return (uhci_device_ich6_a);
254         } else if (device_id == PCI_UHCI_DEVICEID_ICH6_B) {
255                 return (uhci_device_ich6_b);
256         } else if (device_id == PCI_UHCI_DEVICEID_ICH6_C) {
257                 return (uhci_device_ich6_c);
258         } else if (device_id == PCI_UHCI_DEVICEID_ICH6_D) {
259                 return (uhci_device_ich6_d);
260         } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_1) {
261                 return (uhci_device_esb_1);
262         } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_2) {
263                 return (uhci_device_esb_2);
264         } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_3) {
265                 return (uhci_device_esb_3);
266         } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_4) {
267                 return (uhci_device_esb_4);
268         } else if (device_id == PCI_UHCI_DEVICEID_ICH8_A) {
269                 return (uhci_device_ich8_a);
270         } else if (device_id == PCI_UHCI_DEVICEID_ICH8_B) {
271                 return (uhci_device_ich8_b);
272         } else if (device_id == PCI_UHCI_DEVICEID_ICH8_C) {
273                 return (uhci_device_ich8_c);
274         } else if (device_id == PCI_UHCI_DEVICEID_ICH8_D) {
275                 return (uhci_device_ich8_d);
276         } else if (device_id == PCI_UHCI_DEVICEID_ICH8_E) {
277                 return (uhci_device_ich8_e);
278         } else if (device_id == PCI_UHCI_DEVICEID_440MX) {
279                 return (uhci_device_440mx);
280         } else if (device_id == PCI_UHCI_DEVICEID_460GX) {
281                 return (uhci_device_460gx);
282         } else if (device_id == PCI_UHCI_DEVICEID_VT83C572) {
283                 return (uhci_device_vt83c572);
284         } else {
285                 if (pci_get_class(self) == PCIC_SERIALBUS
286                     && pci_get_subclass(self) == PCIS_SERIALBUS_USB
287                     && pci_get_progif(self) == PCI_INTERFACE_UHCI) {
288                         return (uhci_device_generic);
289                 }
290         }
291
292         return NULL;            /* dunno... */
293 }
294
295 static int
296 uhci_pci_probe(device_t self)
297 {
298         const char *desc = uhci_pci_match(self);
299
300         if (desc) {
301                 device_set_desc(self, desc);
302                 return BUS_PROBE_DEFAULT;
303         } else {
304                 return ENXIO;
305         }
306 }
307
308 static int
309 uhci_pci_attach(device_t self)
310 {
311         uhci_softc_t *sc = device_get_softc(self);
312         int rid;
313         int err;
314
315         pci_enable_busmaster(self);
316
317         rid = PCI_UHCI_BASE_REG;
318         sc->io_res = bus_alloc_resource_any(self, SYS_RES_IOPORT, &rid,
319             RF_ACTIVE);
320         if (!sc->io_res) {
321                 device_printf(self, "Could not map ports\n");
322                 return ENXIO;
323         }
324         sc->iot = rman_get_bustag(sc->io_res);
325         sc->ioh = rman_get_bushandle(sc->io_res);
326
327         /* disable interrupts */
328         bus_space_write_2(sc->iot, sc->ioh, UHCI_INTR, 0);
329
330         rid = 0;
331         sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
332             RF_SHAREABLE | RF_ACTIVE);
333         if (sc->irq_res == NULL) {
334                 device_printf(self, "Could not allocate irq\n");
335                 uhci_pci_detach(self);
336                 return ENXIO;
337         }
338         sc->sc_bus.bdev = device_add_child(self, "usb", -1);
339         if (!sc->sc_bus.bdev) {
340                 device_printf(self, "Could not add USB device\n");
341                 uhci_pci_detach(self);
342                 return ENOMEM;
343         }
344         device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
345
346         /* uhci_pci_match must never return NULL if uhci_pci_probe succeeded */
347         device_set_desc(sc->sc_bus.bdev, uhci_pci_match(self));
348         switch (pci_get_vendor(self)) {
349         case PCI_UHCI_VENDORID_INTEL:
350                 sprintf(sc->sc_vendor, "Intel");
351                 break;
352         case PCI_UHCI_VENDORID_VIA:
353                 sprintf(sc->sc_vendor, "VIA");
354                 break;
355         default:
356                 if (bootverbose)
357                         device_printf(self, "(New UHCI DeviceId=0x%08x)\n",
358                             pci_get_devid(self));
359                 sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
360         }
361
362         switch (pci_read_config(self, PCI_USBREV, 1) & PCI_USBREV_MASK) {
363         case PCI_USBREV_PRE_1_0:
364                 sc->sc_bus.usbrev = USBREV_PRE_1_0;
365                 break;
366         case PCI_USBREV_1_0:
367                 sc->sc_bus.usbrev = USBREV_1_0;
368                 break;
369         default:
370                 sc->sc_bus.usbrev = USBREV_UNKNOWN;
371                 break;
372         }
373
374         err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO,
375             NULL, (driver_intr_t *) uhci_intr, sc, &sc->ih);
376         if (err) {
377                 device_printf(self, "Could not setup irq, %d\n", err);
378                 sc->ih = NULL;
379                 uhci_pci_detach(self);
380                 return ENXIO;
381         }
382         /*
383          * Set the PIRQD enable bit and switch off all the others. We don't
384          * want legacy support to interfere with us XXX Does this also mean
385          * that the BIOS won't touch the keyboard anymore if it is connected
386          * to the ports of the root hub?
387          */
388 #ifdef USB_DEBUG
389         if (pci_read_config(self, PCI_LEGSUP, 2) != PCI_LEGSUP_USBPIRQDEN)
390                 device_printf(self, "LegSup = 0x%04x\n",
391                     pci_read_config(self, PCI_LEGSUP, 2));
392 #endif
393         pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2);
394
395         /* Allocate a parent dma tag for DMA maps */
396         err = bus_dma_tag_create(bus_get_dma_tag(self), 1, 0,
397             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
398             BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
399             NULL, NULL, &sc->sc_bus.parent_dmatag);
400         if (err) {
401                 device_printf(self, "Could not allocate parent DMA tag (%d)\n",
402                     err);
403                 uhci_pci_detach(self);
404                 return ENXIO;
405         }
406         /* Allocate a dma tag for transfer buffers */
407         err = bus_dma_tag_create(sc->sc_bus.parent_dmatag, 1, 0,
408             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
409             BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
410             busdma_lock_mutex, &Giant, &sc->sc_bus.buffer_dmatag);
411         if (err) {
412                 device_printf(self, "Could not allocate transfer tag (%d)\n",
413                     err);
414                 uhci_pci_detach(self);
415                 return ENXIO;
416         }
417
418         err = uhci_init(sc);
419         if (!err) {
420                 sc->sc_flags |= UHCI_SCFLG_DONEINIT;
421                 err = device_probe_and_attach(sc->sc_bus.bdev);
422         }
423
424         if (err) {
425                 device_printf(self, "USB init failed\n");
426                 uhci_pci_detach(self);
427                 return EIO;
428         }
429         return 0;               /* success */
430 }
431
432 int
433 uhci_pci_detach(device_t self)
434 {
435         uhci_softc_t *sc = device_get_softc(self);
436
437         if (sc->sc_flags & UHCI_SCFLG_DONEINIT) {
438                 uhci_detach(sc, 0);
439                 sc->sc_flags &= ~UHCI_SCFLG_DONEINIT;
440         }
441
442         if (sc->sc_bus.parent_dmatag != NULL)
443                 bus_dma_tag_destroy(sc->sc_bus.parent_dmatag);
444         if (sc->sc_bus.buffer_dmatag != NULL)
445                 bus_dma_tag_destroy(sc->sc_bus.buffer_dmatag);
446
447         if (sc->irq_res && sc->ih) {
448                 int err = bus_teardown_intr(self, sc->irq_res, sc->ih);
449
450                 if (err)
451                         /* XXX or should we panic? */
452                         device_printf(self, "Could not tear down irq, %d\n",
453                             err);
454                 sc->ih = NULL;
455         }
456         if (sc->sc_bus.bdev) {
457                 device_delete_child(self, sc->sc_bus.bdev);
458                 sc->sc_bus.bdev = NULL;
459         }
460         if (sc->irq_res) {
461                 bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res);
462                 sc->irq_res = NULL;
463         }
464         if (sc->io_res) {
465                 bus_release_resource(self, SYS_RES_IOPORT, PCI_UHCI_BASE_REG,
466                     sc->io_res);
467                 sc->io_res = NULL;
468                 sc->iot = 0;
469                 sc->ioh = 0;
470         }
471         return 0;
472 }
473
474
475 static device_method_t uhci_methods[] = {
476         /* Device interface */
477         DEVMETHOD(device_probe, uhci_pci_probe),
478         DEVMETHOD(device_attach, uhci_pci_attach),
479         DEVMETHOD(device_detach, uhci_pci_detach),
480         DEVMETHOD(device_suspend, uhci_pci_suspend),
481         DEVMETHOD(device_resume, uhci_pci_resume),
482         DEVMETHOD(device_shutdown, bus_generic_shutdown),
483
484         /* Bus interface */
485         DEVMETHOD(bus_print_child, bus_generic_print_child),
486
487         {0, 0}
488 };
489
490 static driver_t uhci_driver = {
491         "uhci",
492         uhci_methods,
493         sizeof(uhci_softc_t),
494 };
495
496 static devclass_t uhci_devclass;
497
498 DRIVER_MODULE(uhci, pci, uhci_driver, uhci_devclass, 0, 0);
499 DRIVER_MODULE(uhci, cardbus, uhci_driver, uhci_devclass, 0, 0);