Sat Sep 22 14:27:24 2012 UTC ()
Fix PR kern/46828 (6.0_BETA2 and 6.0_RC1 won't start on DL320/G5p):
 In ehci_get_ownership(), don't explicitly clear EHCI_LEG_HC_BIOS_OWNED
 semaphore bit in the driver before asking BIOS to give up ownership.
 The EHCI spec implies that the semaphore should not be changed by
 the other agent and actually the previous one (introduced in rev 1.53
 after 5.x) caused hangup during probe on at least two HP machines
 as mentioned in the PR.  Analyzed and patch provided by Ryo ONODERA.

Should be pulled up to netbsd-6 (fatal hangup during boot).


(tsutsui)
diff -r1.56 -r1.57 src/sys/dev/pci/ehci_pci.c

cvs diff -r1.56 -r1.57 src/sys/dev/pci/ehci_pci.c (switch to unified diff)

--- src/sys/dev/pci/ehci_pci.c 2012/07/20 01:26:19 1.56
+++ src/sys/dev/pci/ehci_pci.c 2012/09/22 14:27:24 1.57
@@ -1,495 +1,493 @@ @@ -1,495 +1,493 @@
1/* $NetBSD: ehci_pci.c,v 1.56 2012/07/20 01:26:19 uwe Exp $ */ 1/* $NetBSD: ehci_pci.c,v 1.57 2012/09/22 14:27:24 tsutsui Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc. 4 * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart@augustsson.net). 8 * by Lennart Augustsson (lennart@augustsson.net).
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.56 2012/07/20 01:26:19 uwe Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.57 2012/09/22 14:27:24 tsutsui Exp $");
34 34
35#include <sys/param.h> 35#include <sys/param.h>
36#include <sys/systm.h> 36#include <sys/systm.h>
37#include <sys/kernel.h> 37#include <sys/kernel.h>
38#include <sys/device.h> 38#include <sys/device.h>
39#include <sys/proc.h> 39#include <sys/proc.h>
40#include <sys/queue.h> 40#include <sys/queue.h>
41 41
42#include <sys/bus.h> 42#include <sys/bus.h>
43 43
44#include <dev/pci/pcidevs.h> 44#include <dev/pci/pcidevs.h>
45#include <dev/pci/pcivar.h> 45#include <dev/pci/pcivar.h>
46#include <dev/pci/usb_pci.h> 46#include <dev/pci/usb_pci.h>
47 47
48#include <dev/usb/usb.h> 48#include <dev/usb/usb.h>
49#include <dev/usb/usbdi.h> 49#include <dev/usb/usbdi.h>
50#include <dev/usb/usbdivar.h> 50#include <dev/usb/usbdivar.h>
51#include <dev/usb/usb_mem.h> 51#include <dev/usb/usb_mem.h>
52 52
53#include <dev/usb/ehcireg.h> 53#include <dev/usb/ehcireg.h>
54#include <dev/usb/ehcivar.h> 54#include <dev/usb/ehcivar.h>
55 55
56#ifdef EHCI_DEBUG 56#ifdef EHCI_DEBUG
57#define DPRINTF(x) if (ehcidebug) printf x 57#define DPRINTF(x) if (ehcidebug) printf x
58extern int ehcidebug; 58extern int ehcidebug;
59#else 59#else
60#define DPRINTF(x) 60#define DPRINTF(x)
61#endif 61#endif
62 62
63enum ehci_pci_quirk_flags { 63enum ehci_pci_quirk_flags {
64 EHCI_PCI_QUIRK_AMD_SB600 = 0x1, /* always need a quirk */ 64 EHCI_PCI_QUIRK_AMD_SB600 = 0x1, /* always need a quirk */
65 EHCI_PCI_QUIRK_AMD_SB700 = 0x2, /* depends on the SMB revision */ 65 EHCI_PCI_QUIRK_AMD_SB700 = 0x2, /* depends on the SMB revision */
66}; 66};
67 67
68static const struct pci_quirkdata ehci_pci_quirks[] = { 68static const struct pci_quirkdata ehci_pci_quirks[] = {
69 { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB600_USB_EHCI, 69 { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB600_USB_EHCI,
70 EHCI_PCI_QUIRK_AMD_SB600 }, 70 EHCI_PCI_QUIRK_AMD_SB600 },
71 { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB700_USB_EHCI, 71 { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB700_USB_EHCI,
72 EHCI_PCI_QUIRK_AMD_SB700 }, 72 EHCI_PCI_QUIRK_AMD_SB700 },
73}; 73};
74 74
75static void ehci_release_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, 75static void ehci_release_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc,
76 pcitag_t tag); 76 pcitag_t tag);
77static void ehci_get_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, 77static void ehci_get_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc,
78 pcitag_t tag); 78 pcitag_t tag);
79static bool ehci_pci_suspend(device_t, const pmf_qual_t *); 79static bool ehci_pci_suspend(device_t, const pmf_qual_t *);
80static bool ehci_pci_resume(device_t, const pmf_qual_t *); 80static bool ehci_pci_resume(device_t, const pmf_qual_t *);
81 81
82struct ehci_pci_softc { 82struct ehci_pci_softc {
83 ehci_softc_t sc; 83 ehci_softc_t sc;
84 pci_chipset_tag_t sc_pc; 84 pci_chipset_tag_t sc_pc;
85 pcitag_t sc_tag; 85 pcitag_t sc_tag;
86 void *sc_ih; /* interrupt vectoring */ 86 void *sc_ih; /* interrupt vectoring */
87}; 87};
88 88
89static int ehci_sb700_match(const struct pci_attach_args *pa); 89static int ehci_sb700_match(const struct pci_attach_args *pa);
90static int ehci_apply_amd_quirks(struct ehci_pci_softc *sc); 90static int ehci_apply_amd_quirks(struct ehci_pci_softc *sc);
91enum ehci_pci_quirk_flags ehci_pci_lookup_quirkdata(pci_vendor_id_t, 91enum ehci_pci_quirk_flags ehci_pci_lookup_quirkdata(pci_vendor_id_t,
92 pci_product_id_t); 92 pci_product_id_t);
93 93
94#define EHCI_MAX_BIOS_WAIT 100 /* ms*10 */ 94#define EHCI_MAX_BIOS_WAIT 100 /* ms*10 */
95#define EHCI_SBx00_WORKAROUND_REG 0x50 95#define EHCI_SBx00_WORKAROUND_REG 0x50
96#define EHCI_SBx00_WORKAROUND_ENABLE __BIT(27) 96#define EHCI_SBx00_WORKAROUND_ENABLE __BIT(27)
97 97
98 98
99static int 99static int
100ehci_pci_match(device_t parent, cfdata_t match, void *aux) 100ehci_pci_match(device_t parent, cfdata_t match, void *aux)
101{ 101{
102 struct pci_attach_args *pa = (struct pci_attach_args *) aux; 102 struct pci_attach_args *pa = (struct pci_attach_args *) aux;
103 103
104 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_SERIALBUS && 104 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_SERIALBUS &&
105 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_SERIALBUS_USB && 105 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_SERIALBUS_USB &&
106 PCI_INTERFACE(pa->pa_class) == PCI_INTERFACE_EHCI) 106 PCI_INTERFACE(pa->pa_class) == PCI_INTERFACE_EHCI)
107 return 1; 107 return 1;
108 108
109 return 0; 109 return 0;
110} 110}
111 111
112static void 112static void
113ehci_pci_attach(device_t parent, device_t self, void *aux) 113ehci_pci_attach(device_t parent, device_t self, void *aux)
114{ 114{
115 struct ehci_pci_softc *sc = device_private(self); 115 struct ehci_pci_softc *sc = device_private(self);
116 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 116 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
117 pci_chipset_tag_t pc = pa->pa_pc; 117 pci_chipset_tag_t pc = pa->pa_pc;
118 pcitag_t tag = pa->pa_tag; 118 pcitag_t tag = pa->pa_tag;
119 char const *intrstr; 119 char const *intrstr;
120 pci_intr_handle_t ih; 120 pci_intr_handle_t ih;
121 pcireg_t csr; 121 pcireg_t csr;
122 const char *vendor; 122 const char *vendor;
123 usbd_status r; 123 usbd_status r;
124 int ncomp; 124 int ncomp;
125 struct usb_pci *up; 125 struct usb_pci *up;
126 int quirk; 126 int quirk;
127 127
128 sc->sc.sc_dev = self; 128 sc->sc.sc_dev = self;
129 sc->sc.sc_bus.hci_private = sc; 129 sc->sc.sc_bus.hci_private = sc;
130 130
131 pci_aprint_devinfo(pa, "USB controller"); 131 pci_aprint_devinfo(pa, "USB controller");
132 132
133 /* Check for quirks */ 133 /* Check for quirks */
134 quirk = ehci_pci_lookup_quirkdata(PCI_VENDOR(pa->pa_id), 134 quirk = ehci_pci_lookup_quirkdata(PCI_VENDOR(pa->pa_id),
135 PCI_PRODUCT(pa->pa_id)); 135 PCI_PRODUCT(pa->pa_id));
136 136
137 /* Map I/O registers */ 137 /* Map I/O registers */
138 if (pci_mapreg_map(pa, PCI_CBMEM, PCI_MAPREG_TYPE_MEM, 0, 138 if (pci_mapreg_map(pa, PCI_CBMEM, PCI_MAPREG_TYPE_MEM, 0,
139 &sc->sc.iot, &sc->sc.ioh, NULL, &sc->sc.sc_size)) { 139 &sc->sc.iot, &sc->sc.ioh, NULL, &sc->sc.sc_size)) {
140 sc->sc.sc_size = 0; 140 sc->sc.sc_size = 0;
141 aprint_error_dev(self, "can't map memory space\n"); 141 aprint_error_dev(self, "can't map memory space\n");
142 return; 142 return;
143 } 143 }
144 144
145 /* Disable interrupts, so we don't get any spurious ones. */ 145 /* Disable interrupts, so we don't get any spurious ones. */
146 sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH); 146 sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH);
147 DPRINTF(("%s: offs=%d\n", device_xname(self), sc->sc.sc_offs)); 147 DPRINTF(("%s: offs=%d\n", device_xname(self), sc->sc.sc_offs));
148 EOWRITE4(&sc->sc, EHCI_USBINTR, 0); 148 EOWRITE4(&sc->sc, EHCI_USBINTR, 0);
149 149
150 sc->sc_pc = pc; 150 sc->sc_pc = pc;
151 sc->sc_tag = tag; 151 sc->sc_tag = tag;
152 sc->sc.sc_bus.dmatag = pa->pa_dmat; 152 sc->sc.sc_bus.dmatag = pa->pa_dmat;
153 153
154 /* Handle quirks */ 154 /* Handle quirks */
155 switch (quirk) { 155 switch (quirk) {
156 case EHCI_PCI_QUIRK_AMD_SB600: 156 case EHCI_PCI_QUIRK_AMD_SB600:
157 ehci_apply_amd_quirks(sc); 157 ehci_apply_amd_quirks(sc);
158 break; 158 break;
159 case EHCI_PCI_QUIRK_AMD_SB700: 159 case EHCI_PCI_QUIRK_AMD_SB700:
160 if (pci_find_device(NULL, ehci_sb700_match)) 160 if (pci_find_device(NULL, ehci_sb700_match))
161 ehci_apply_amd_quirks(sc); 161 ehci_apply_amd_quirks(sc);
162 break; 162 break;
163 } 163 }
164 164
165 /* Enable the device. */ 165 /* Enable the device. */
166 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 166 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
167 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, 167 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
168 csr | PCI_COMMAND_MASTER_ENABLE); 168 csr | PCI_COMMAND_MASTER_ENABLE);
169 169
170 /* Map and establish the interrupt. */ 170 /* Map and establish the interrupt. */
171 if (pci_intr_map(pa, &ih)) { 171 if (pci_intr_map(pa, &ih)) {
172 aprint_error_dev(self, "couldn't map interrupt\n"); 172 aprint_error_dev(self, "couldn't map interrupt\n");
173 goto fail; 173 goto fail;
174 } 174 }
175 175
176 /* 176 /*
177 * Allocate IRQ 177 * Allocate IRQ
178 */ 178 */
179 intrstr = pci_intr_string(pc, ih); 179 intrstr = pci_intr_string(pc, ih);
180 sc->sc_ih = pci_intr_establish(pc, ih, IPL_SCHED, ehci_intr, sc); 180 sc->sc_ih = pci_intr_establish(pc, ih, IPL_SCHED, ehci_intr, sc);
181 if (sc->sc_ih == NULL) { 181 if (sc->sc_ih == NULL) {
182 aprint_error_dev(self, "couldn't establish interrupt"); 182 aprint_error_dev(self, "couldn't establish interrupt");
183 if (intrstr != NULL) 183 if (intrstr != NULL)
184 aprint_error(" at %s", intrstr); 184 aprint_error(" at %s", intrstr);
185 aprint_error("\n"); 185 aprint_error("\n");
186 return; 186 return;
187 } 187 }
188 aprint_normal_dev(self, "interrupting at %s\n", intrstr); 188 aprint_normal_dev(self, "interrupting at %s\n", intrstr);
189 189
190 switch(pci_conf_read(pc, tag, PCI_USBREV) & PCI_USBREV_MASK) { 190 switch(pci_conf_read(pc, tag, PCI_USBREV) & PCI_USBREV_MASK) {
191 case PCI_USBREV_PRE_1_0: 191 case PCI_USBREV_PRE_1_0:
192 case PCI_USBREV_1_0: 192 case PCI_USBREV_1_0:
193 case PCI_USBREV_1_1: 193 case PCI_USBREV_1_1:
194 sc->sc.sc_bus.usbrev = USBREV_UNKNOWN; 194 sc->sc.sc_bus.usbrev = USBREV_UNKNOWN;
195 aprint_verbose_dev(self, "pre-2.0 USB rev\n"); 195 aprint_verbose_dev(self, "pre-2.0 USB rev\n");
196 return; 196 return;
197 case PCI_USBREV_2_0: 197 case PCI_USBREV_2_0:
198 sc->sc.sc_bus.usbrev = USBREV_2_0; 198 sc->sc.sc_bus.usbrev = USBREV_2_0;
199 break; 199 break;
200 default: 200 default:
201 sc->sc.sc_bus.usbrev = USBREV_UNKNOWN; 201 sc->sc.sc_bus.usbrev = USBREV_UNKNOWN;
202 break; 202 break;
203 } 203 }
204 204
205 /* Figure out vendor for root hub descriptor. */ 205 /* Figure out vendor for root hub descriptor. */
206 vendor = pci_findvendor(pa->pa_id); 206 vendor = pci_findvendor(pa->pa_id);
207 sc->sc.sc_id_vendor = PCI_VENDOR(pa->pa_id); 207 sc->sc.sc_id_vendor = PCI_VENDOR(pa->pa_id);
208 if (vendor) 208 if (vendor)
209 strlcpy(sc->sc.sc_vendor, vendor, sizeof(sc->sc.sc_vendor)); 209 strlcpy(sc->sc.sc_vendor, vendor, sizeof(sc->sc.sc_vendor));
210 else 210 else
211 snprintf(sc->sc.sc_vendor, sizeof(sc->sc.sc_vendor), 211 snprintf(sc->sc.sc_vendor, sizeof(sc->sc.sc_vendor),
212 "vendor 0x%04x", PCI_VENDOR(pa->pa_id)); 212 "vendor 0x%04x", PCI_VENDOR(pa->pa_id));
213 213
214 /* Enable workaround for dropped interrupts as required */ 214 /* Enable workaround for dropped interrupts as required */
215 switch (sc->sc.sc_id_vendor) { 215 switch (sc->sc.sc_id_vendor) {
216 case PCI_VENDOR_ATI: 216 case PCI_VENDOR_ATI:
217 case PCI_VENDOR_VIATECH: 217 case PCI_VENDOR_VIATECH:
218 sc->sc.sc_flags |= EHCIF_DROPPED_INTR_WORKAROUND; 218 sc->sc.sc_flags |= EHCIF_DROPPED_INTR_WORKAROUND;
219 aprint_normal_dev(self, "dropped intr workaround enabled\n"); 219 aprint_normal_dev(self, "dropped intr workaround enabled\n");
220 break; 220 break;
221 default: 221 default:
222 break; 222 break;
223 } 223 }
224 224
225 /* 225 /*
226 * Find companion controllers. According to the spec they always 226 * Find companion controllers. According to the spec they always
227 * have lower function numbers so they should be enumerated already. 227 * have lower function numbers so they should be enumerated already.
228 */ 228 */
229 const u_int maxncomp = EHCI_HCS_N_CC(EREAD4(&sc->sc, EHCI_HCSPARAMS)); 229 const u_int maxncomp = EHCI_HCS_N_CC(EREAD4(&sc->sc, EHCI_HCSPARAMS));
230 KASSERT(maxncomp <= EHCI_COMPANION_MAX); 230 KASSERT(maxncomp <= EHCI_COMPANION_MAX);
231 ncomp = 0; 231 ncomp = 0;
232 TAILQ_FOREACH(up, &ehci_pci_alldevs, next) { 232 TAILQ_FOREACH(up, &ehci_pci_alldevs, next) {
233 if (up->bus == pa->pa_bus && up->device == pa->pa_device 233 if (up->bus == pa->pa_bus && up->device == pa->pa_device
234 && !up->claimed) { 234 && !up->claimed) {
235 DPRINTF(("ehci_pci_attach: companion %s\n", 235 DPRINTF(("ehci_pci_attach: companion %s\n",
236 device_xname(up->usb))); 236 device_xname(up->usb)));
237 sc->sc.sc_comps[ncomp++] = up->usb; 237 sc->sc.sc_comps[ncomp++] = up->usb;
238 up->claimed = true; 238 up->claimed = true;
239 if (ncomp == maxncomp) 239 if (ncomp == maxncomp)
240 break; 240 break;
241 } 241 }
242 } 242 }
243 sc->sc.sc_ncomp = ncomp; 243 sc->sc.sc_ncomp = ncomp;
244 244
245 ehci_get_ownership(&sc->sc, pc, tag); 245 ehci_get_ownership(&sc->sc, pc, tag);
246 246
247 r = ehci_init(&sc->sc); 247 r = ehci_init(&sc->sc);
248 if (r != USBD_NORMAL_COMPLETION) { 248 if (r != USBD_NORMAL_COMPLETION) {
249 aprint_error_dev(self, "init failed, error=%d\n", r); 249 aprint_error_dev(self, "init failed, error=%d\n", r);
250 goto fail; 250 goto fail;
251 } 251 }
252 252
253 if (!pmf_device_register1(self, ehci_pci_suspend, ehci_pci_resume, 253 if (!pmf_device_register1(self, ehci_pci_suspend, ehci_pci_resume,
254 ehci_shutdown)) 254 ehci_shutdown))
255 aprint_error_dev(self, "couldn't establish power handler\n"); 255 aprint_error_dev(self, "couldn't establish power handler\n");
256 256
257 /* Attach usb device. */ 257 /* Attach usb device. */
258 sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint); 258 sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint);
259 return; 259 return;
260 260
261fail: 261fail:
262 if (sc->sc_ih) { 262 if (sc->sc_ih) {
263 pci_intr_disestablish(sc->sc_pc, sc->sc_ih); 263 pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
264 sc->sc_ih = NULL; 264 sc->sc_ih = NULL;
265 } 265 }
266 if (sc->sc.sc_size) { 266 if (sc->sc.sc_size) {
267 ehci_release_ownership(&sc->sc, sc->sc_pc, sc->sc_tag); 267 ehci_release_ownership(&sc->sc, sc->sc_pc, sc->sc_tag);
268 bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); 268 bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
269 sc->sc.sc_size = 0; 269 sc->sc.sc_size = 0;
270 } 270 }
271 return; 271 return;
272} 272}
273 273
274static int 274static int
275ehci_pci_detach(device_t self, int flags) 275ehci_pci_detach(device_t self, int flags)
276{ 276{
277 struct ehci_pci_softc *sc = device_private(self); 277 struct ehci_pci_softc *sc = device_private(self);
278 int rv; 278 int rv;
279 279
280 rv = ehci_detach(&sc->sc, flags); 280 rv = ehci_detach(&sc->sc, flags);
281 if (rv) 281 if (rv)
282 return rv; 282 return rv;
283 283
284 pmf_device_deregister(self); 284 pmf_device_deregister(self);
285 ehci_shutdown(self, flags); 285 ehci_shutdown(self, flags);
286 286
287 /* disable interrupts */ 287 /* disable interrupts */
288 EOWRITE4(&sc->sc, EHCI_USBINTR, 0); 288 EOWRITE4(&sc->sc, EHCI_USBINTR, 0);
289 /* XXX grotty hack to flush the write */ 289 /* XXX grotty hack to flush the write */
290 (void)EOREAD4(&sc->sc, EHCI_USBINTR); 290 (void)EOREAD4(&sc->sc, EHCI_USBINTR);
291 291
292 if (sc->sc_ih != NULL) { 292 if (sc->sc_ih != NULL) {
293 pci_intr_disestablish(sc->sc_pc, sc->sc_ih); 293 pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
294 sc->sc_ih = NULL; 294 sc->sc_ih = NULL;
295 } 295 }
296 if (sc->sc.sc_size) { 296 if (sc->sc.sc_size) {
297 ehci_release_ownership(&sc->sc, sc->sc_pc, sc->sc_tag); 297 ehci_release_ownership(&sc->sc, sc->sc_pc, sc->sc_tag);
298 bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); 298 bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
299 sc->sc.sc_size = 0; 299 sc->sc.sc_size = 0;
300 } 300 }
301 301
302#if 1 302#if 1
303 /* XXX created in ehci.c */ 303 /* XXX created in ehci.c */
304 mutex_destroy(&sc->sc.sc_lock); 304 mutex_destroy(&sc->sc.sc_lock);
305 mutex_destroy(&sc->sc.sc_intr_lock); 305 mutex_destroy(&sc->sc.sc_intr_lock);
306 306
307 softint_disestablish(sc->sc.sc_doorbell_si); 307 softint_disestablish(sc->sc.sc_doorbell_si);
308 softint_disestablish(sc->sc.sc_pcd_si); 308 softint_disestablish(sc->sc.sc_pcd_si);
309#endif 309#endif
310 310
311 return 0; 311 return 0;
312} 312}
313 313
314CFATTACH_DECL3_NEW(ehci_pci, sizeof(struct ehci_pci_softc), 314CFATTACH_DECL3_NEW(ehci_pci, sizeof(struct ehci_pci_softc),
315 ehci_pci_match, ehci_pci_attach, ehci_pci_detach, ehci_activate, NULL, 315 ehci_pci_match, ehci_pci_attach, ehci_pci_detach, ehci_activate, NULL,
316 ehci_childdet, DVF_DETACH_SHUTDOWN); 316 ehci_childdet, DVF_DETACH_SHUTDOWN);
317 317
318#ifdef EHCI_DEBUG 318#ifdef EHCI_DEBUG
319static void 319static void
320ehci_dump_caps(ehci_softc_t *sc, pci_chipset_tag_t pc, pcitag_t tag) 320ehci_dump_caps(ehci_softc_t *sc, pci_chipset_tag_t pc, pcitag_t tag)
321{ 321{
322 uint32_t cparams, legctlsts, addr, cap, id; 322 uint32_t cparams, legctlsts, addr, cap, id;
323 int maxdump = 10; 323 int maxdump = 10;
324 324
325 cparams = EREAD4(sc, EHCI_HCCPARAMS); 325 cparams = EREAD4(sc, EHCI_HCCPARAMS);
326 addr = EHCI_HCC_EECP(cparams); 326 addr = EHCI_HCC_EECP(cparams);
327 while (addr != 0) { 327 while (addr != 0) {
328 cap = pci_conf_read(pc, tag, addr); 328 cap = pci_conf_read(pc, tag, addr);
329 id = EHCI_CAP_GET_ID(cap); 329 id = EHCI_CAP_GET_ID(cap);
330 switch (id) { 330 switch (id) {
331 case EHCI_CAP_ID_LEGACY: 331 case EHCI_CAP_ID_LEGACY:
332 legctlsts = pci_conf_read(pc, tag, 332 legctlsts = pci_conf_read(pc, tag,
333 addr + PCI_EHCI_USBLEGCTLSTS); 333 addr + PCI_EHCI_USBLEGCTLSTS);
334 printf("ehci_dump_caps: legsup=0x%08x " 334 printf("ehci_dump_caps: legsup=0x%08x "
335 "legctlsts=0x%08x\n", cap, legctlsts); 335 "legctlsts=0x%08x\n", cap, legctlsts);
336 break; 336 break;
337 default: 337 default:
338 printf("ehci_dump_caps: cap=0x%08x\n", cap); 338 printf("ehci_dump_caps: cap=0x%08x\n", cap);
339 break; 339 break;
340 } 340 }
341 if (--maxdump < 0) 341 if (--maxdump < 0)
342 break; 342 break;
343 addr = EHCI_CAP_GET_NEXT(cap); 343 addr = EHCI_CAP_GET_NEXT(cap);
344 } 344 }
345} 345}
346#endif 346#endif
347 347
348static void 348static void
349ehci_release_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, pcitag_t tag) 349ehci_release_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, pcitag_t tag)
350{ 350{
351 const char *devname = device_xname(sc->sc_dev); 351 const char *devname = device_xname(sc->sc_dev);
352 uint32_t cparams, addr, cap; 352 uint32_t cparams, addr, cap;
353 pcireg_t legsup; 353 pcireg_t legsup;
354 int maxcap = 10; 354 int maxcap = 10;
355 355
356 cparams = EREAD4(sc, EHCI_HCCPARAMS); 356 cparams = EREAD4(sc, EHCI_HCCPARAMS);
357 addr = EHCI_HCC_EECP(cparams); 357 addr = EHCI_HCC_EECP(cparams);
358 while (addr != 0) { 358 while (addr != 0) {
359 cap = pci_conf_read(pc, tag, addr); 359 cap = pci_conf_read(pc, tag, addr);
360 if (EHCI_CAP_GET_ID(cap) != EHCI_CAP_ID_LEGACY) 360 if (EHCI_CAP_GET_ID(cap) != EHCI_CAP_ID_LEGACY)
361 goto next; 361 goto next;
362 legsup = pci_conf_read(pc, tag, addr + PCI_EHCI_USBLEGSUP); 362 legsup = pci_conf_read(pc, tag, addr + PCI_EHCI_USBLEGSUP);
363 pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGSUP, 363 pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGSUP,
364 legsup & ~EHCI_LEG_HC_OS_OWNED); 364 legsup & ~EHCI_LEG_HC_OS_OWNED);
365 365
366next: 366next:
367 if (--maxcap < 0) { 367 if (--maxcap < 0) {
368 aprint_normal("%s: broken extended capabilities " 368 aprint_normal("%s: broken extended capabilities "
369 "ignored\n", devname); 369 "ignored\n", devname);
370 return; 370 return;
371 } 371 }
372 addr = EHCI_CAP_GET_NEXT(cap); 372 addr = EHCI_CAP_GET_NEXT(cap);
373 } 373 }
374} 374}
375 375
376static void 376static void
377ehci_get_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, pcitag_t tag) 377ehci_get_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, pcitag_t tag)
378{ 378{
379 const char *devname = device_xname(sc->sc_dev); 379 const char *devname = device_xname(sc->sc_dev);
380 uint32_t cparams, addr, cap; 380 uint32_t cparams, addr, cap;
381 pcireg_t legsup; 381 pcireg_t legsup;
382 int maxcap = 10; 382 int maxcap = 10;
383 int ms; 383 int ms;
384 384
385#ifdef EHCI_DEBUG 385#ifdef EHCI_DEBUG
386 if (ehcidebug) 386 if (ehcidebug)
387 ehci_dump_caps(sc, pc, tag); 387 ehci_dump_caps(sc, pc, tag);
388#endif 388#endif
389 cparams = EREAD4(sc, EHCI_HCCPARAMS); 389 cparams = EREAD4(sc, EHCI_HCCPARAMS);
390 addr = EHCI_HCC_EECP(cparams); 390 addr = EHCI_HCC_EECP(cparams);
391 while (addr != 0) { 391 while (addr != 0) {
392 cap = pci_conf_read(pc, tag, addr); 392 cap = pci_conf_read(pc, tag, addr);
393 if (EHCI_CAP_GET_ID(cap) != EHCI_CAP_ID_LEGACY) 393 if (EHCI_CAP_GET_ID(cap) != EHCI_CAP_ID_LEGACY)
394 goto next; 394 goto next;
395 legsup = pci_conf_read(pc, tag, addr + PCI_EHCI_USBLEGSUP); 395 legsup = pci_conf_read(pc, tag, addr + PCI_EHCI_USBLEGSUP);
396 if (legsup & EHCI_LEG_HC_BIOS_OWNED) { 396 if (legsup & EHCI_LEG_HC_BIOS_OWNED) {
397 /* Ask BIOS to give up ownership */ 397 /* Ask BIOS to give up ownership */
398 legsup &= ~EHCI_LEG_HC_BIOS_OWNED; 
399 legsup |= EHCI_LEG_HC_OS_OWNED; 
400 pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGSUP, 398 pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGSUP,
401 legsup); 399 legsup | EHCI_LEG_HC_OS_OWNED);
402 for (ms = 0; ms < EHCI_MAX_BIOS_WAIT; ms++) { 400 for (ms = 0; ms < EHCI_MAX_BIOS_WAIT; ms++) {
403 legsup = pci_conf_read(pc, tag, 401 legsup = pci_conf_read(pc, tag,
404 addr + PCI_EHCI_USBLEGSUP); 402 addr + PCI_EHCI_USBLEGSUP);
405 if (!(legsup & EHCI_LEG_HC_BIOS_OWNED)) 403 if (!(legsup & EHCI_LEG_HC_BIOS_OWNED))
406 break; 404 break;
407 delay(10000); 405 delay(10000);
408 } 406 }
409 if (ms == EHCI_MAX_BIOS_WAIT) { 407 if (ms == EHCI_MAX_BIOS_WAIT) {
410 aprint_normal("%s: BIOS refuses to give up " 408 aprint_normal("%s: BIOS refuses to give up "
411 "ownership, using force\n", devname); 409 "ownership, using force\n", devname);
412 pci_conf_write(pc, tag, 410 pci_conf_write(pc, tag,
413 addr + PCI_EHCI_USBLEGSUP, 0); 411 addr + PCI_EHCI_USBLEGSUP, 0);
414 } else 412 } else
415 aprint_verbose("%s: BIOS has given up " 413 aprint_verbose("%s: BIOS has given up "
416 "ownership\n", devname); 414 "ownership\n", devname);
417 } 415 }
418 416
419 /* Disable SMIs */ 417 /* Disable SMIs */
420 pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGCTLSTS, 0); 418 pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGCTLSTS, 0);
421 419
422next: 420next:
423 if (--maxcap < 0) { 421 if (--maxcap < 0) {
424 aprint_normal("%s: broken extended capabilities " 422 aprint_normal("%s: broken extended capabilities "
425 "ignored\n", devname); 423 "ignored\n", devname);
426 return; 424 return;
427 } 425 }
428 addr = EHCI_CAP_GET_NEXT(cap); 426 addr = EHCI_CAP_GET_NEXT(cap);
429 } 427 }
430 428
431} 429}
432 430
433static bool 431static bool
434ehci_pci_suspend(device_t dv, const pmf_qual_t *qual) 432ehci_pci_suspend(device_t dv, const pmf_qual_t *qual)
435{ 433{
436 struct ehci_pci_softc *sc = device_private(dv); 434 struct ehci_pci_softc *sc = device_private(dv);
437 435
438 ehci_suspend(dv, qual); 436 ehci_suspend(dv, qual);
439 ehci_release_ownership(&sc->sc, sc->sc_pc, sc->sc_tag); 437 ehci_release_ownership(&sc->sc, sc->sc_pc, sc->sc_tag);
440 438
441 return true; 439 return true;
442} 440}
443 441
444static bool 442static bool
445ehci_pci_resume(device_t dv, const pmf_qual_t *qual) 443ehci_pci_resume(device_t dv, const pmf_qual_t *qual)
446{ 444{
447 struct ehci_pci_softc *sc = device_private(dv); 445 struct ehci_pci_softc *sc = device_private(dv);
448 446
449 ehci_get_ownership(&sc->sc, sc->sc_pc, sc->sc_tag); 447 ehci_get_ownership(&sc->sc, sc->sc_pc, sc->sc_tag);
450 return ehci_resume(dv, qual); 448 return ehci_resume(dv, qual);
451} 449}
452 450
453static int 451static int
454ehci_sb700_match(const struct pci_attach_args *pa) 452ehci_sb700_match(const struct pci_attach_args *pa)
455{ 453{
456 if (!(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ATI && 454 if (!(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ATI &&
457 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_SB600_SMB)) 455 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_SB600_SMB))
458 return 0; 456 return 0;
459 457
460 switch (PCI_REVISION(pa->pa_class)) { 458 switch (PCI_REVISION(pa->pa_class)) {
461 case 0x3a: 459 case 0x3a:
462 case 0x3b: 460 case 0x3b:
463 return 1; 461 return 1;
464 } 462 }
465 463
466 return 0; 464 return 0;
467} 465}
468 466
469static int 467static int
470ehci_apply_amd_quirks(struct ehci_pci_softc *sc) 468ehci_apply_amd_quirks(struct ehci_pci_softc *sc)
471{ 469{
472 pcireg_t value; 470 pcireg_t value;
473  471
474 aprint_normal_dev(sc->sc.sc_dev, 472 aprint_normal_dev(sc->sc.sc_dev,
475 "applying AMD SB600/SB700 USB freeze workaround\n"); 473 "applying AMD SB600/SB700 USB freeze workaround\n");
476 value = pci_conf_read(sc->sc_pc, sc->sc_tag, EHCI_SBx00_WORKAROUND_REG); 474 value = pci_conf_read(sc->sc_pc, sc->sc_tag, EHCI_SBx00_WORKAROUND_REG);
477 pci_conf_write(sc->sc_pc, sc->sc_tag, EHCI_SBx00_WORKAROUND_REG, 475 pci_conf_write(sc->sc_pc, sc->sc_tag, EHCI_SBx00_WORKAROUND_REG,
478 value | EHCI_SBx00_WORKAROUND_ENABLE); 476 value | EHCI_SBx00_WORKAROUND_ENABLE);
479 477
480 return 0; 478 return 0;
481} 479}
482 480
483enum ehci_pci_quirk_flags 481enum ehci_pci_quirk_flags
484ehci_pci_lookup_quirkdata(pci_vendor_id_t vendor, pci_product_id_t product) 482ehci_pci_lookup_quirkdata(pci_vendor_id_t vendor, pci_product_id_t product)
485{ 483{
486 int i; 484 int i;
487 485
488 for (i = 0; i < __arraycount(ehci_pci_quirks); i++) { 486 for (i = 0; i < __arraycount(ehci_pci_quirks); i++) {
489 if (vendor == ehci_pci_quirks[i].vendor && 487 if (vendor == ehci_pci_quirks[i].vendor &&
490 product == ehci_pci_quirks[i].product) 488 product == ehci_pci_quirks[i].product)
491 return ehci_pci_quirks[i].quirks; 489 return ehci_pci_quirks[i].quirks;
492 } 490 }
493 return 0; 491 return 0;
494} 492}
495 493