- convert usbd_bus_methods{} and usbd_pipe_methods{} to use c99 struct initialisers - move the locks from the pipe to the bus, since we'll need access to them from bus-level ops - remove dead-for-years SPLUSBCHECK and replaced it with asserts that the thread lock is held - begin to document the locking scheme - convert usbd_*lock_pipe() into real function-like macrosdiff -r1.181.6.3 -r1.181.6.4 src/sys/dev/usb/ehci.c
(mrg)
--- src/sys/dev/usb/ehci.c 2011/12/06 02:10:01 1.181.6.3
+++ src/sys/dev/usb/ehci.c 2011/12/08 02:51:07 1.181.6.4
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ehci.c,v 1.181.6.3 2011/12/06 02:10:01 mrg Exp $ */ | 1 | /* $NetBSD: ehci.c,v 1.181.6.4 2011/12/08 02:51:07 mrg Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2004-2011 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2004-2011 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), Charles M. Hannum, | 8 | * by Lennart Augustsson (lennart@augustsson.net), Charles M. Hannum, | |
9 | * Jeremy Morse (jeremy.morse@gmail.com), and Jared D. McNeill | 9 | * Jeremy Morse (jeremy.morse@gmail.com), and Jared D. McNeill | |
10 | * (jmcneill@invisible.ca). | 10 | * (jmcneill@invisible.ca). | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
@@ -43,27 +43,27 @@ | @@ -43,27 +43,27 @@ | |||
43 | 43 | |||
44 | /* | 44 | /* | |
45 | * TODO: | 45 | * TODO: | |
46 | * 1) hold off explorations by companion controllers until ehci has started. | 46 | * 1) hold off explorations by companion controllers until ehci has started. | |
47 | * | 47 | * | |
48 | * 2) The hub driver needs to handle and schedule the transaction translator, | 48 | * 2) The hub driver needs to handle and schedule the transaction translator, | |
49 | * to assign place in frame where different devices get to go. See chapter | 49 | * to assign place in frame where different devices get to go. See chapter | |
50 | * on hubs in USB 2.0 for details. | 50 | * on hubs in USB 2.0 for details. | |
51 | * | 51 | * | |
52 | * 3) Command failures are not recovered correctly. | 52 | * 3) Command failures are not recovered correctly. | |
53 | */ | 53 | */ | |
54 | 54 | |||
55 | #include <sys/cdefs.h> | 55 | #include <sys/cdefs.h> | |
56 | __KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.181.6.3 2011/12/06 02:10:01 mrg Exp $"); | 56 | __KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.181.6.4 2011/12/08 02:51:07 mrg Exp $"); | |
57 | 57 | |||
58 | #include "ohci.h" | 58 | #include "ohci.h" | |
59 | #include "uhci.h" | 59 | #include "uhci.h" | |
60 | #include "opt_usb.h" | 60 | #include "opt_usb.h" | |
61 | 61 | |||
62 | #include <sys/param.h> | 62 | #include <sys/param.h> | |
63 | #include <sys/systm.h> | 63 | #include <sys/systm.h> | |
64 | #include <sys/kernel.h> | 64 | #include <sys/kernel.h> | |
65 | #include <sys/kmem.h> | 65 | #include <sys/kmem.h> | |
66 | #include <sys/device.h> | 66 | #include <sys/device.h> | |
67 | #include <sys/select.h> | 67 | #include <sys/select.h> | |
68 | #include <sys/proc.h> | 68 | #include <sys/proc.h> | |
69 | #include <sys/queue.h> | 69 | #include <sys/queue.h> | |
@@ -210,27 +210,28 @@ Static void ehci_free_sqtd_chain(ehci_s | @@ -210,27 +210,28 @@ Static void ehci_free_sqtd_chain(ehci_s | |||
210 | 210 | |||
211 | Static ehci_soft_itd_t *ehci_alloc_itd(ehci_softc_t *sc); | 211 | Static ehci_soft_itd_t *ehci_alloc_itd(ehci_softc_t *sc); | |
212 | Static void ehci_free_itd(ehci_softc_t *sc, ehci_soft_itd_t *itd); | 212 | Static void ehci_free_itd(ehci_softc_t *sc, ehci_soft_itd_t *itd); | |
213 | Static void ehci_rem_free_itd_chain(ehci_softc_t *sc, | 213 | Static void ehci_rem_free_itd_chain(ehci_softc_t *sc, | |
214 | struct ehci_xfer *exfer); | 214 | struct ehci_xfer *exfer); | |
215 | Static void ehci_abort_isoc_xfer(usbd_xfer_handle xfer, | 215 | Static void ehci_abort_isoc_xfer(usbd_xfer_handle xfer, | |
216 | usbd_status status); | 216 | usbd_status status); | |
217 | 217 | |||
218 | Static usbd_status ehci_device_request(usbd_xfer_handle xfer); | 218 | Static usbd_status ehci_device_request(usbd_xfer_handle xfer); | |
219 | 219 | |||
220 | Static usbd_status ehci_device_setintr(ehci_softc_t *, ehci_soft_qh_t *, | 220 | Static usbd_status ehci_device_setintr(ehci_softc_t *, ehci_soft_qh_t *, | |
221 | int ival); | 221 | int ival); | |
222 | 222 | |||
223 | Static void ehci_add_qh(ehci_soft_qh_t *, ehci_soft_qh_t *); | 223 | Static void ehci_add_qh(ehci_softc_t *, ehci_soft_qh_t *, | |
224 | ehci_soft_qh_t *); | |||
224 | Static void ehci_rem_qh(ehci_softc_t *, ehci_soft_qh_t *, | 225 | Static void ehci_rem_qh(ehci_softc_t *, ehci_soft_qh_t *, | |
225 | ehci_soft_qh_t *); | 226 | ehci_soft_qh_t *); | |
226 | Static void ehci_set_qh_qtd(ehci_soft_qh_t *, ehci_soft_qtd_t *); | 227 | Static void ehci_set_qh_qtd(ehci_soft_qh_t *, ehci_soft_qtd_t *); | |
227 | Static void ehci_sync_hc(ehci_softc_t *); | 228 | Static void ehci_sync_hc(ehci_softc_t *); | |
228 | 229 | |||
229 | Static void ehci_close_pipe(usbd_pipe_handle, ehci_soft_qh_t *); | 230 | Static void ehci_close_pipe(usbd_pipe_handle, ehci_soft_qh_t *); | |
230 | Static void ehci_abort_xfer(usbd_xfer_handle, usbd_status); | 231 | Static void ehci_abort_xfer(usbd_xfer_handle, usbd_status); | |
231 | 232 | |||
232 | #ifdef EHCI_DEBUG | 233 | #ifdef EHCI_DEBUG | |
233 | Static void ehci_dump_regs(ehci_softc_t *); | 234 | Static void ehci_dump_regs(ehci_softc_t *); | |
234 | void ehci_dump(void); | 235 | void ehci_dump(void); | |
235 | Static ehci_softc_t *theehci; | 236 | Static ehci_softc_t *theehci; | |
236 | Static void ehci_dump_link(ehci_link_t, int); | 237 | Static void ehci_dump_link(ehci_link_t, int); | |
@@ -251,88 +252,88 @@ Static void ehci_dump_exfer(struct ehci | @@ -251,88 +252,88 @@ Static void ehci_dump_exfer(struct ehci | |||
251 | 252 | |||
252 | #define EHCI_INTR_ENDPT 1 | 253 | #define EHCI_INTR_ENDPT 1 | |
253 | 254 | |||
254 | #define ehci_add_intr_list(sc, ex) \ | 255 | #define ehci_add_intr_list(sc, ex) \ | |
255 | TAILQ_INSERT_TAIL(&(sc)->sc_intrhead, (ex), inext); | 256 | TAILQ_INSERT_TAIL(&(sc)->sc_intrhead, (ex), inext); | |
256 | #define ehci_del_intr_list(sc, ex) \ | 257 | #define ehci_del_intr_list(sc, ex) \ | |
257 | do { \ | 258 | do { \ | |
258 | TAILQ_REMOVE(&sc->sc_intrhead, (ex), inext); \ | 259 | TAILQ_REMOVE(&sc->sc_intrhead, (ex), inext); \ | |
259 | (ex)->inext.tqe_prev = NULL; \ | 260 | (ex)->inext.tqe_prev = NULL; \ | |
260 | } while (0) | 261 | } while (0) | |
261 | #define ehci_active_intr_list(ex) ((ex)->inext.tqe_prev != NULL) | 262 | #define ehci_active_intr_list(ex) ((ex)->inext.tqe_prev != NULL) | |
262 | 263 | |||
263 | Static const struct usbd_bus_methods ehci_bus_methods = { | 264 | Static const struct usbd_bus_methods ehci_bus_methods = { | |
264 | ehci_open, | 265 | .open_pipe = ehci_open, | |
265 | ehci_softintr, | 266 | .soft_intr = ehci_softintr, | |
266 | ehci_poll, | 267 | .do_poll = ehci_poll, | |
267 | ehci_allocm, | 268 | .allocm = ehci_allocm, | |
268 | ehci_freem, | 269 | .freem = ehci_freem, | |
269 | ehci_allocx, | 270 | .allocx = ehci_allocx, | |
270 | ehci_freex, | 271 | .freex = ehci_freex, | |
271 | ehci_get_locks, | 272 | .get_locks = ehci_get_locks, | |
272 | }; | 273 | }; | |
273 | 274 | |||
274 | Static const struct usbd_pipe_methods ehci_root_ctrl_methods = { | 275 | Static const struct usbd_pipe_methods ehci_root_ctrl_methods = { | |
275 | ehci_root_ctrl_transfer, | 276 | .transfer = ehci_root_ctrl_transfer, | |
276 | ehci_root_ctrl_start, | 277 | .start = ehci_root_ctrl_start, | |
277 | ehci_root_ctrl_abort, | 278 | .abort = ehci_root_ctrl_abort, | |
278 | ehci_root_ctrl_close, | 279 | .close = ehci_root_ctrl_close, | |
279 | ehci_noop, | 280 | .cleartoggle = ehci_noop, | |
280 | ehci_root_ctrl_done, | 281 | .done = ehci_root_ctrl_done, | |
281 | }; | 282 | }; | |
282 | 283 | |||
283 | Static const struct usbd_pipe_methods ehci_root_intr_methods = { | 284 | Static const struct usbd_pipe_methods ehci_root_intr_methods = { | |
284 | ehci_root_intr_transfer, | 285 | .transfer = ehci_root_intr_transfer, | |
285 | ehci_root_intr_start, | 286 | .start = ehci_root_intr_start, | |
286 | ehci_root_intr_abort, | 287 | .abort = ehci_root_intr_abort, | |
287 | ehci_root_intr_close, | 288 | .close = ehci_root_intr_close, | |
288 | ehci_noop, | 289 | .cleartoggle = ehci_noop, | |
289 | ehci_root_intr_done, | 290 | .done = ehci_root_intr_done, | |
290 | }; | 291 | }; | |
291 | 292 | |||
292 | Static const struct usbd_pipe_methods ehci_device_ctrl_methods = { | 293 | Static const struct usbd_pipe_methods ehci_device_ctrl_methods = { | |
293 | ehci_device_ctrl_transfer, | 294 | .transfer = ehci_device_ctrl_transfer, | |
294 | ehci_device_ctrl_start, | 295 | .start = ehci_device_ctrl_start, | |
295 | ehci_device_ctrl_abort, | 296 | .abort = ehci_device_ctrl_abort, | |
296 | ehci_device_ctrl_close, | 297 | .close = ehci_device_ctrl_close, | |
297 | ehci_noop, | 298 | .cleartoggle = ehci_noop, | |
298 | ehci_device_ctrl_done, | 299 | .done = ehci_device_ctrl_done, | |
299 | }; | 300 | }; | |
300 | 301 | |||
301 | Static const struct usbd_pipe_methods ehci_device_intr_methods = { | 302 | Static const struct usbd_pipe_methods ehci_device_intr_methods = { | |
302 | ehci_device_intr_transfer, | 303 | .transfer = ehci_device_intr_transfer, | |
303 | ehci_device_intr_start, | 304 | .start = ehci_device_intr_start, | |
304 | ehci_device_intr_abort, | 305 | .abort = ehci_device_intr_abort, | |
305 | ehci_device_intr_close, | 306 | .close = ehci_device_intr_close, | |
306 | ehci_device_clear_toggle, | 307 | .cleartoggle = ehci_device_clear_toggle, | |
307 | ehci_device_intr_done, | 308 | .done = ehci_device_intr_done, | |
308 | }; | 309 | }; | |
309 | 310 | |||
310 | Static const struct usbd_pipe_methods ehci_device_bulk_methods = { | 311 | Static const struct usbd_pipe_methods ehci_device_bulk_methods = { | |
311 | ehci_device_bulk_transfer, | 312 | .transfer = ehci_device_bulk_transfer, | |
312 | ehci_device_bulk_start, | 313 | .start = ehci_device_bulk_start, | |
313 | ehci_device_bulk_abort, | 314 | .abort = ehci_device_bulk_abort, | |
314 | ehci_device_bulk_close, | 315 | .close = ehci_device_bulk_close, | |
315 | ehci_device_clear_toggle, | 316 | .cleartoggle = ehci_device_clear_toggle, | |
316 | ehci_device_bulk_done, | 317 | .done = ehci_device_bulk_done, | |
317 | }; | 318 | }; | |
318 | 319 | |||
319 | Static const struct usbd_pipe_methods ehci_device_isoc_methods = { | 320 | Static const struct usbd_pipe_methods ehci_device_isoc_methods = { | |
320 | ehci_device_isoc_transfer, | 321 | .transfer = ehci_device_isoc_transfer, | |
321 | ehci_device_isoc_start, | 322 | .start = ehci_device_isoc_start, | |
322 | ehci_device_isoc_abort, | 323 | .abort = ehci_device_isoc_abort, | |
323 | ehci_device_isoc_close, | 324 | .close = ehci_device_isoc_close, | |
324 | ehci_noop, | 325 | .cleartoggle = ehci_noop, | |
325 | ehci_device_isoc_done, | 326 | .done = ehci_device_isoc_done, | |
326 | }; | 327 | }; | |
327 | 328 | |||
328 | static const uint8_t revbits[EHCI_MAX_POLLRATE] = { | 329 | static const uint8_t revbits[EHCI_MAX_POLLRATE] = { | |
329 | 0x00,0x40,0x20,0x60,0x10,0x50,0x30,0x70,0x08,0x48,0x28,0x68,0x18,0x58,0x38,0x78, | 330 | 0x00,0x40,0x20,0x60,0x10,0x50,0x30,0x70,0x08,0x48,0x28,0x68,0x18,0x58,0x38,0x78, | |
330 | 0x04,0x44,0x24,0x64,0x14,0x54,0x34,0x74,0x0c,0x4c,0x2c,0x6c,0x1c,0x5c,0x3c,0x7c, | 331 | 0x04,0x44,0x24,0x64,0x14,0x54,0x34,0x74,0x0c,0x4c,0x2c,0x6c,0x1c,0x5c,0x3c,0x7c, | |
331 | 0x02,0x42,0x22,0x62,0x12,0x52,0x32,0x72,0x0a,0x4a,0x2a,0x6a,0x1a,0x5a,0x3a,0x7a, | 332 | 0x02,0x42,0x22,0x62,0x12,0x52,0x32,0x72,0x0a,0x4a,0x2a,0x6a,0x1a,0x5a,0x3a,0x7a, | |
332 | 0x06,0x46,0x26,0x66,0x16,0x56,0x36,0x76,0x0e,0x4e,0x2e,0x6e,0x1e,0x5e,0x3e,0x7e, | 333 | 0x06,0x46,0x26,0x66,0x16,0x56,0x36,0x76,0x0e,0x4e,0x2e,0x6e,0x1e,0x5e,0x3e,0x7e, | |
333 | 0x01,0x41,0x21,0x61,0x11,0x51,0x31,0x71,0x09,0x49,0x29,0x69,0x19,0x59,0x39,0x79, | 334 | 0x01,0x41,0x21,0x61,0x11,0x51,0x31,0x71,0x09,0x49,0x29,0x69,0x19,0x59,0x39,0x79, | |
334 | 0x05,0x45,0x25,0x65,0x15,0x55,0x35,0x75,0x0d,0x4d,0x2d,0x6d,0x1d,0x5d,0x3d,0x7d, | 335 | 0x05,0x45,0x25,0x65,0x15,0x55,0x35,0x75,0x0d,0x4d,0x2d,0x6d,0x1d,0x5d,0x3d,0x7d, | |
335 | 0x03,0x43,0x23,0x63,0x13,0x53,0x33,0x73,0x0b,0x4b,0x2b,0x6b,0x1b,0x5b,0x3b,0x7b, | 336 | 0x03,0x43,0x23,0x63,0x13,0x53,0x33,0x73,0x0b,0x4b,0x2b,0x6b,0x1b,0x5b,0x3b,0x7b, | |
336 | 0x07,0x47,0x27,0x67,0x17,0x57,0x37,0x77,0x0f,0x4f,0x2f,0x6f,0x1f,0x5f,0x3f,0x7f, | 337 | 0x07,0x47,0x27,0x67,0x17,0x57,0x37,0x77,0x0f,0x4f,0x2f,0x6f,0x1f,0x5f,0x3f,0x7f, | |
337 | }; | 338 | }; | |
338 | 339 | |||
@@ -1743,33 +1744,33 @@ ehci_open(usbd_pipe_handle pipe) | @@ -1743,33 +1744,33 @@ ehci_open(usbd_pipe_handle pipe) | |||
1743 | 1744 | |||
1744 | switch (xfertype) { | 1745 | switch (xfertype) { | |
1745 | case UE_CONTROL: | 1746 | case UE_CONTROL: | |
1746 | err = usb_allocmem(&sc->sc_bus, sizeof(usb_device_request_t), | 1747 | err = usb_allocmem(&sc->sc_bus, sizeof(usb_device_request_t), | |
1747 | 0, &epipe->u.ctl.reqdma); | 1748 | 0, &epipe->u.ctl.reqdma); | |
1748 | #ifdef EHCI_DEBUG | 1749 | #ifdef EHCI_DEBUG | |
1749 | if (err) | 1750 | if (err) | |
1750 | printf("ehci_open: usb_allocmem()=%d\n", err); | 1751 | printf("ehci_open: usb_allocmem()=%d\n", err); | |
1751 | #endif | 1752 | #endif | |
1752 | if (err) | 1753 | if (err) | |
1753 | goto bad; | 1754 | goto bad; | |
1754 | pipe->methods = &ehci_device_ctrl_methods; | 1755 | pipe->methods = &ehci_device_ctrl_methods; | |
1755 | mutex_enter(&sc->sc_lock); | 1756 | mutex_enter(&sc->sc_lock); | |
1756 | ehci_add_qh(sqh, sc->sc_async_head); | 1757 | ehci_add_qh(sc, sqh, sc->sc_async_head); | |
1757 | mutex_exit(&sc->sc_lock); | 1758 | mutex_exit(&sc->sc_lock); | |
1758 | break; | 1759 | break; | |
1759 | case UE_BULK: | 1760 | case UE_BULK: | |
1760 | pipe->methods = &ehci_device_bulk_methods; | 1761 | pipe->methods = &ehci_device_bulk_methods; | |
1761 | mutex_enter(&sc->sc_lock); | 1762 | mutex_enter(&sc->sc_lock); | |
1762 | ehci_add_qh(sqh, sc->sc_async_head); | 1763 | ehci_add_qh(sc, sqh, sc->sc_async_head); | |
1763 | mutex_exit(&sc->sc_lock); | 1764 | mutex_exit(&sc->sc_lock); | |
1764 | break; | 1765 | break; | |
1765 | case UE_INTERRUPT: | 1766 | case UE_INTERRUPT: | |
1766 | pipe->methods = &ehci_device_intr_methods; | 1767 | pipe->methods = &ehci_device_intr_methods; | |
1767 | ival = pipe->interval; | 1768 | ival = pipe->interval; | |
1768 | if (ival == USBD_DEFAULT_INTERVAL) { | 1769 | if (ival == USBD_DEFAULT_INTERVAL) { | |
1769 | if (speed == EHCI_QH_SPEED_HIGH) { | 1770 | if (speed == EHCI_QH_SPEED_HIGH) { | |
1770 | if (ed->bInterval > 16) { | 1771 | if (ed->bInterval > 16) { | |
1771 | /* | 1772 | /* | |
1772 | * illegal with high-speed, but there | 1773 | * illegal with high-speed, but there | |
1773 | * were documentation bugs in the spec, | 1774 | * were documentation bugs in the spec, | |
1774 | * so be generous | 1775 | * so be generous | |
1775 | */ | 1776 | */ | |
@@ -1805,29 +1806,30 @@ ehci_open(usbd_pipe_handle pipe) | @@ -1805,29 +1806,30 @@ ehci_open(usbd_pipe_handle pipe) | |||
1805 | } | 1806 | } | |
1806 | return (USBD_NORMAL_COMPLETION); | 1807 | return (USBD_NORMAL_COMPLETION); | |
1807 | 1808 | |||
1808 | bad: | 1809 | bad: | |
1809 | if (sqh != NULL) | 1810 | if (sqh != NULL) | |
1810 | ehci_free_sqh(sc, sqh); | 1811 | ehci_free_sqh(sc, sqh); | |
1811 | return (err); | 1812 | return (err); | |
1812 | } | 1813 | } | |
1813 | 1814 | |||
1814 | /* | 1815 | /* | |
1815 | * Add an ED to the schedule. Called at splusb(). | 1816 | * Add an ED to the schedule. Called at splusb(). | |
1816 | */ | 1817 | */ | |
1817 | Static void | 1818 | Static void | |
1818 | ehci_add_qh(ehci_soft_qh_t *sqh, ehci_soft_qh_t *head) | 1819 | ehci_add_qh(ehci_softc_t *sc, ehci_soft_qh_t *sqh, ehci_soft_qh_t *head) | |
1819 | { | 1820 | { | |
1820 | SPLUSBCHECK; | 1821 | ||
1822 | KASSERT(mutex_owned(&sc->sc_lock)); | |||
1821 | 1823 | |||
1822 | usb_syncmem(&head->dma, head->offs + offsetof(ehci_qh_t, qh_link), | 1824 | usb_syncmem(&head->dma, head->offs + offsetof(ehci_qh_t, qh_link), | |
1823 | sizeof(head->qh.qh_link), BUS_DMASYNC_POSTWRITE); | 1825 | sizeof(head->qh.qh_link), BUS_DMASYNC_POSTWRITE); | |
1824 | sqh->next = head->next; | 1826 | sqh->next = head->next; | |
1825 | sqh->qh.qh_link = head->qh.qh_link; | 1827 | sqh->qh.qh_link = head->qh.qh_link; | |
1826 | usb_syncmem(&sqh->dma, sqh->offs + offsetof(ehci_qh_t, qh_link), | 1828 | usb_syncmem(&sqh->dma, sqh->offs + offsetof(ehci_qh_t, qh_link), | |
1827 | sizeof(sqh->qh.qh_link), BUS_DMASYNC_PREWRITE); | 1829 | sizeof(sqh->qh.qh_link), BUS_DMASYNC_PREWRITE); | |
1828 | head->next = sqh; | 1830 | head->next = sqh; | |
1829 | head->qh.qh_link = htole32(sqh->physaddr | EHCI_LINK_QH); | 1831 | head->qh.qh_link = htole32(sqh->physaddr | EHCI_LINK_QH); | |
1830 | usb_syncmem(&head->dma, head->offs + offsetof(ehci_qh_t, qh_link), | 1832 | usb_syncmem(&head->dma, head->offs + offsetof(ehci_qh_t, qh_link), | |
1831 | sizeof(head->qh.qh_link), BUS_DMASYNC_PREWRITE); | 1833 | sizeof(head->qh.qh_link), BUS_DMASYNC_PREWRITE); | |
1832 | 1834 | |||
1833 | #ifdef EHCI_DEBUG | 1835 | #ifdef EHCI_DEBUG | |
@@ -1836,27 +1838,28 @@ ehci_add_qh(ehci_soft_qh_t *sqh, ehci_so | @@ -1836,27 +1838,28 @@ ehci_add_qh(ehci_soft_qh_t *sqh, ehci_so | |||
1836 | ehci_dump_sqh(sqh); | 1838 | ehci_dump_sqh(sqh); | |
1837 | } | 1839 | } | |
1838 | #endif | 1840 | #endif | |
1839 | } | 1841 | } | |
1840 | 1842 | |||
1841 | /* | 1843 | /* | |
1842 | * Remove an ED from the schedule. Called at splusb(). | 1844 | * Remove an ED from the schedule. Called at splusb(). | |
1843 | */ | 1845 | */ | |
1844 | Static void | 1846 | Static void | |
1845 | ehci_rem_qh(ehci_softc_t *sc, ehci_soft_qh_t *sqh, ehci_soft_qh_t *head) | 1847 | ehci_rem_qh(ehci_softc_t *sc, ehci_soft_qh_t *sqh, ehci_soft_qh_t *head) | |
1846 | { | 1848 | { | |
1847 | ehci_soft_qh_t *p; | 1849 | ehci_soft_qh_t *p; | |
1848 | 1850 | |||
1849 | SPLUSBCHECK; | 1851 | KASSERT(mutex_owned(&sc->sc_lock)); | |
1852 | ||||
1850 | /* XXX */ | 1853 | /* XXX */ | |
1851 | for (p = head; p != NULL && p->next != sqh; p = p->next) | 1854 | for (p = head; p != NULL && p->next != sqh; p = p->next) | |
1852 | ; | 1855 | ; | |
1853 | if (p == NULL) | 1856 | if (p == NULL) | |
1854 | panic("ehci_rem_qh: ED not found"); | 1857 | panic("ehci_rem_qh: ED not found"); | |
1855 | usb_syncmem(&sqh->dma, sqh->offs + offsetof(ehci_qh_t, qh_link), | 1858 | usb_syncmem(&sqh->dma, sqh->offs + offsetof(ehci_qh_t, qh_link), | |
1856 | sizeof(sqh->qh.qh_link), BUS_DMASYNC_POSTWRITE); | 1859 | sizeof(sqh->qh.qh_link), BUS_DMASYNC_POSTWRITE); | |
1857 | p->next = sqh->next; | 1860 | p->next = sqh->next; | |
1858 | p->qh.qh_link = sqh->qh.qh_link; | 1861 | p->qh.qh_link = sqh->qh.qh_link; | |
1859 | usb_syncmem(&p->dma, p->offs + offsetof(ehci_qh_t, qh_link), | 1862 | usb_syncmem(&p->dma, p->offs + offsetof(ehci_qh_t, qh_link), | |
1860 | sizeof(p->qh.qh_link), BUS_DMASYNC_PREWRITE); | 1863 | sizeof(p->qh.qh_link), BUS_DMASYNC_PREWRITE); | |
1861 | 1864 | |||
1862 | ehci_sync_hc(sc); | 1865 | ehci_sync_hc(sc); | |
@@ -3701,27 +3704,27 @@ ehci_device_setintr(ehci_softc_t *sc, eh | @@ -3701,27 +3704,27 @@ ehci_device_setintr(ehci_softc_t *sc, eh | |||
3701 | 3704 | |||
3702 | /* Find a poll rate that is large enough. */ | 3705 | /* Find a poll rate that is large enough. */ | |
3703 | for (lev = EHCI_IPOLLRATES - 1; lev > 0; lev--) | 3706 | for (lev = EHCI_IPOLLRATES - 1; lev > 0; lev--) | |
3704 | if (EHCI_ILEV_IVAL(lev) <= ival) | 3707 | if (EHCI_ILEV_IVAL(lev) <= ival) | |
3705 | break; | 3708 | break; | |
3706 | 3709 | |||
3707 | /* Pick an interrupt slot at the right level. */ | 3710 | /* Pick an interrupt slot at the right level. */ | |
3708 | /* XXX could do better than picking at random */ | 3711 | /* XXX could do better than picking at random */ | |
3709 | sc->sc_rand = (sc->sc_rand + 191) % sc->sc_flsize; | 3712 | sc->sc_rand = (sc->sc_rand + 191) % sc->sc_flsize; | |
3710 | islot = EHCI_IQHIDX(lev, sc->sc_rand); | 3713 | islot = EHCI_IQHIDX(lev, sc->sc_rand); | |
3711 | 3714 | |||
3712 | sqh->islot = islot; | 3715 | sqh->islot = islot; | |
3713 | isp = &sc->sc_islots[islot]; | 3716 | isp = &sc->sc_islots[islot]; | |
3714 | ehci_add_qh(sqh, isp->sqh); | 3717 | ehci_add_qh(sc, sqh, isp->sqh); | |
3715 | 3718 | |||
3716 | return (USBD_NORMAL_COMPLETION); | 3719 | return (USBD_NORMAL_COMPLETION); | |
3717 | } | 3720 | } | |
3718 | 3721 | |||
3719 | Static usbd_status | 3722 | Static usbd_status | |
3720 | ehci_device_intr_transfer(usbd_xfer_handle xfer) | 3723 | ehci_device_intr_transfer(usbd_xfer_handle xfer) | |
3721 | { | 3724 | { | |
3722 | ehci_softc_t *sc = xfer->pipe->device->bus->hci_private; | 3725 | ehci_softc_t *sc = xfer->pipe->device->bus->hci_private; | |
3723 | usbd_status err; | 3726 | usbd_status err; | |
3724 | 3727 | |||
3725 | /* Insert last in queue. */ | 3728 | /* Insert last in queue. */ | |
3726 | mutex_enter(&sc->sc_lock); | 3729 | mutex_enter(&sc->sc_lock); | |
3727 | err = usb_insert_transfer(xfer); | 3730 | err = usb_insert_transfer(xfer); |
--- src/sys/dev/usb/ohci.c 2011/12/07 05:41:53 1.218.6.5
+++ src/sys/dev/usb/ohci.c 2011/12/08 02:51:07 1.218.6.6
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ohci.c,v 1.218.6.5 2011/12/07 05:41:53 macallan Exp $ */ | 1 | /* $NetBSD: ohci.c,v 1.218.6.6 2011/12/08 02:51:07 mrg Exp $ */ | |
2 | /* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */ | 2 | /* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (c) 1998, 2004, 2005, 2011 The NetBSD Foundation, Inc. | 5 | * Copyright (c) 1998, 2004, 2005, 2011 The NetBSD Foundation, Inc. | |
6 | * All rights reserved. | 6 | * All rights reserved. | |
7 | * | 7 | * | |
8 | * This code is derived from software contributed to The NetBSD Foundation | 8 | * This code is derived from software contributed to The NetBSD Foundation | |
9 | * by Lennart Augustsson (lennart@augustsson.net) at | 9 | * by Lennart Augustsson (lennart@augustsson.net) at | |
10 | * Carlstedt Research & Technology, Jared D. McNeill (jmcneill@invisible.ca) | 10 | * Carlstedt Research & Technology, Jared D. McNeill (jmcneill@invisible.ca) | |
11 | * and Matthew R. Green. | 11 | * and Matthew R. Green. | |
12 | * This code is derived from software contributed to The NetBSD Foundation | 12 | * This code is derived from software contributed to The NetBSD Foundation | |
13 | * by Charles M. Hannum. | 13 | * by Charles M. Hannum. | |
14 | * | 14 | * | |
@@ -32,27 +32,27 @@ | @@ -32,27 +32,27 @@ | |||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
34 | * POSSIBILITY OF SUCH DAMAGE. | 34 | * POSSIBILITY OF SUCH DAMAGE. | |
35 | */ | 35 | */ | |
36 | 36 | |||
37 | /* | 37 | /* | |
38 | * USB Open Host Controller driver. | 38 | * USB Open Host Controller driver. | |
39 | * | 39 | * | |
40 | * OHCI spec: http://www.compaq.com/productinfo/development/openhci.html | 40 | * OHCI spec: http://www.compaq.com/productinfo/development/openhci.html | |
41 | * USB spec: http://www.usb.org/developers/docs/ | 41 | * USB spec: http://www.usb.org/developers/docs/ | |
42 | */ | 42 | */ | |
43 | 43 | |||
44 | #include <sys/cdefs.h> | 44 | #include <sys/cdefs.h> | |
45 | __KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.218.6.5 2011/12/07 05:41:53 macallan Exp $"); | 45 | __KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.218.6.6 2011/12/08 02:51:07 mrg Exp $"); | |
46 | 46 | |||
47 | #include "opt_usb.h" | 47 | #include "opt_usb.h" | |
48 | 48 | |||
49 | #include <sys/param.h> | 49 | #include <sys/param.h> | |
50 | #include <sys/systm.h> | 50 | #include <sys/systm.h> | |
51 | #include <sys/kmem.h> | 51 | #include <sys/kmem.h> | |
52 | #include <sys/kernel.h> | 52 | #include <sys/kernel.h> | |
53 | #include <sys/device.h> | 53 | #include <sys/device.h> | |
54 | #include <sys/select.h> | 54 | #include <sys/select.h> | |
55 | #include <sys/proc.h> | 55 | #include <sys/proc.h> | |
56 | #include <sys/queue.h> | 56 | #include <sys/queue.h> | |
57 | 57 | |||
58 | #include <sys/bus.h> | 58 | #include <sys/bus.h> | |
@@ -110,27 +110,28 @@ Static usbd_status ohci_alloc_std_chain( | @@ -110,27 +110,28 @@ Static usbd_status ohci_alloc_std_chain( | |||
110 | ohci_soft_td_t *, ohci_soft_td_t **); | 110 | ohci_soft_td_t *, ohci_soft_td_t **); | |
111 | 111 | |||
112 | Static usbd_status ohci_open(usbd_pipe_handle); | 112 | Static usbd_status ohci_open(usbd_pipe_handle); | |
113 | Static void ohci_poll(struct usbd_bus *); | 113 | Static void ohci_poll(struct usbd_bus *); | |
114 | Static void ohci_softintr(void *); | 114 | Static void ohci_softintr(void *); | |
115 | Static void ohci_waitintr(ohci_softc_t *, usbd_xfer_handle); | 115 | Static void ohci_waitintr(ohci_softc_t *, usbd_xfer_handle); | |
116 | Static void ohci_rhsc(ohci_softc_t *, usbd_xfer_handle); | 116 | Static void ohci_rhsc(ohci_softc_t *, usbd_xfer_handle); | |
117 | Static void ohci_rhsc_softint(void *arg); | 117 | Static void ohci_rhsc_softint(void *arg); | |
118 | 118 | |||
119 | Static usbd_status ohci_device_request(usbd_xfer_handle xfer); | 119 | Static usbd_status ohci_device_request(usbd_xfer_handle xfer); | |
120 | Static void ohci_add_ed(ohci_softc_t *, ohci_soft_ed_t *, | 120 | Static void ohci_add_ed(ohci_softc_t *, ohci_soft_ed_t *, | |
121 | ohci_soft_ed_t *); | 121 | ohci_soft_ed_t *); | |
122 | 122 | |||
123 | Static void ohci_rem_ed(ohci_soft_ed_t *, ohci_soft_ed_t *); | 123 | Static void ohci_rem_ed(ohci_softc_t *, ohci_soft_ed_t *, | |
124 | ohci_soft_ed_t *); | |||
124 | Static void ohci_hash_add_td(ohci_softc_t *, ohci_soft_td_t *); | 125 | Static void ohci_hash_add_td(ohci_softc_t *, ohci_soft_td_t *); | |
125 | Static void ohci_hash_rem_td(ohci_softc_t *, ohci_soft_td_t *); | 126 | Static void ohci_hash_rem_td(ohci_softc_t *, ohci_soft_td_t *); | |
126 | Static ohci_soft_td_t *ohci_hash_find_td(ohci_softc_t *, ohci_physaddr_t); | 127 | Static ohci_soft_td_t *ohci_hash_find_td(ohci_softc_t *, ohci_physaddr_t); | |
127 | Static void ohci_hash_add_itd(ohci_softc_t *, ohci_soft_itd_t *); | 128 | Static void ohci_hash_add_itd(ohci_softc_t *, ohci_soft_itd_t *); | |
128 | Static void ohci_hash_rem_itd(ohci_softc_t *, ohci_soft_itd_t *); | 129 | Static void ohci_hash_rem_itd(ohci_softc_t *, ohci_soft_itd_t *); | |
129 | Static ohci_soft_itd_t *ohci_hash_find_itd(ohci_softc_t *, ohci_physaddr_t); | 130 | Static ohci_soft_itd_t *ohci_hash_find_itd(ohci_softc_t *, ohci_physaddr_t); | |
130 | 131 | |||
131 | Static usbd_status ohci_setup_isoc(usbd_pipe_handle pipe); | 132 | Static usbd_status ohci_setup_isoc(usbd_pipe_handle pipe); | |
132 | Static void ohci_device_isoc_enter(usbd_xfer_handle); | 133 | Static void ohci_device_isoc_enter(usbd_xfer_handle); | |
133 | 134 | |||
134 | Static usbd_status ohci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t); | 135 | Static usbd_status ohci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t); | |
135 | Static void ohci_freem(struct usbd_bus *, usb_dma_t *); | 136 | Static void ohci_freem(struct usbd_bus *, usb_dma_t *); | |
136 | 137 | |||
@@ -261,88 +262,88 @@ struct ohci_pipe { | @@ -261,88 +262,88 @@ struct ohci_pipe { | |||
261 | u_int length; | 262 | u_int length; | |
262 | int isread; | 263 | int isread; | |
263 | } bulk; | 264 | } bulk; | |
264 | /* Iso pipe */ | 265 | /* Iso pipe */ | |
265 | struct iso { | 266 | struct iso { | |
266 | int next, inuse; | 267 | int next, inuse; | |
267 | } iso; | 268 | } iso; | |
268 | } u; | 269 | } u; | |
269 | }; | 270 | }; | |
270 | 271 | |||
271 | #define OHCI_INTR_ENDPT 1 | 272 | #define OHCI_INTR_ENDPT 1 | |
272 | 273 | |||
273 | Static const struct usbd_bus_methods ohci_bus_methods = { | 274 | Static const struct usbd_bus_methods ohci_bus_methods = { | |
274 | ohci_open, | 275 | .open_pipe = ohci_open, | |
275 | ohci_softintr, | 276 | .soft_intr = ohci_softintr, | |
276 | ohci_poll, | 277 | .do_poll = ohci_poll, | |
277 | ohci_allocm, | 278 | .allocm = ohci_allocm, | |
278 | ohci_freem, | 279 | .freem = ohci_freem, | |
279 | ohci_allocx, | 280 | .allocx = ohci_allocx, | |
280 | ohci_freex, | 281 | .freex = ohci_freex, | |
281 | ohci_get_locks, | 282 | .get_locks = ohci_get_locks, | |
282 | }; | 283 | }; | |
283 | 284 | |||
284 | Static const struct usbd_pipe_methods ohci_root_ctrl_methods = { | 285 | Static const struct usbd_pipe_methods ohci_root_ctrl_methods = { | |
285 | ohci_root_ctrl_transfer, | 286 | .transfer = ohci_root_ctrl_transfer, | |
286 | ohci_root_ctrl_start, | 287 | .start = ohci_root_ctrl_start, | |
287 | ohci_root_ctrl_abort, | 288 | .abort = ohci_root_ctrl_abort, | |
288 | ohci_root_ctrl_close, | 289 | .close = ohci_root_ctrl_close, | |
289 | ohci_noop, | 290 | .cleartoggle = ohci_noop, | |
290 | ohci_root_ctrl_done, | 291 | .done = ohci_root_ctrl_done, | |
291 | }; | 292 | }; | |
292 | 293 | |||
293 | Static const struct usbd_pipe_methods ohci_root_intr_methods = { | 294 | Static const struct usbd_pipe_methods ohci_root_intr_methods = { | |
294 | ohci_root_intr_transfer, | 295 | .transfer = ohci_root_intr_transfer, | |
295 | ohci_root_intr_start, | 296 | .start = ohci_root_intr_start, | |
296 | ohci_root_intr_abort, | 297 | .abort = ohci_root_intr_abort, | |
297 | ohci_root_intr_close, | 298 | .close = ohci_root_intr_close, | |
298 | ohci_noop, | 299 | .cleartoggle = ohci_noop, | |
299 | ohci_root_intr_done, | 300 | .done = ohci_root_intr_done, | |
300 | }; | 301 | }; | |
301 | 302 | |||
302 | Static const struct usbd_pipe_methods ohci_device_ctrl_methods = { | 303 | Static const struct usbd_pipe_methods ohci_device_ctrl_methods = { | |
303 | ohci_device_ctrl_transfer, | 304 | .transfer = ohci_device_ctrl_transfer, | |
304 | ohci_device_ctrl_start, | 305 | .start = ohci_device_ctrl_start, | |
305 | ohci_device_ctrl_abort, | 306 | .abort = ohci_device_ctrl_abort, | |
306 | ohci_device_ctrl_close, | 307 | .close = ohci_device_ctrl_close, | |
307 | ohci_noop, | 308 | .cleartoggle = ohci_noop, | |
308 | ohci_device_ctrl_done, | 309 | .done = ohci_device_ctrl_done, | |
309 | }; | 310 | }; | |
310 | 311 | |||
311 | Static const struct usbd_pipe_methods ohci_device_intr_methods = { | 312 | Static const struct usbd_pipe_methods ohci_device_intr_methods = { | |
312 | ohci_device_intr_transfer, | 313 | .transfer = ohci_device_intr_transfer, | |
313 | ohci_device_intr_start, | 314 | .start = ohci_device_intr_start, | |
314 | ohci_device_intr_abort, | 315 | .abort = ohci_device_intr_abort, | |
315 | ohci_device_intr_close, | 316 | .close = ohci_device_intr_close, | |
316 | ohci_device_clear_toggle, | 317 | .cleartoggle = ohci_device_clear_toggle, | |
317 | ohci_device_intr_done, | 318 | .done = ohci_device_intr_done, | |
318 | }; | 319 | }; | |
319 | 320 | |||
320 | Static const struct usbd_pipe_methods ohci_device_bulk_methods = { | 321 | Static const struct usbd_pipe_methods ohci_device_bulk_methods = { | |
321 | ohci_device_bulk_transfer, | 322 | .transfer = ohci_device_bulk_transfer, | |
322 | ohci_device_bulk_start, | 323 | .start = ohci_device_bulk_start, | |
323 | ohci_device_bulk_abort, | 324 | .abort = ohci_device_bulk_abort, | |
324 | ohci_device_bulk_close, | 325 | .close = ohci_device_bulk_close, | |
325 | ohci_device_clear_toggle, | 326 | .cleartoggle = ohci_device_clear_toggle, | |
326 | ohci_device_bulk_done, | 327 | .done = ohci_device_bulk_done, | |
327 | }; | 328 | }; | |
328 | 329 | |||
329 | Static const struct usbd_pipe_methods ohci_device_isoc_methods = { | 330 | Static const struct usbd_pipe_methods ohci_device_isoc_methods = { | |
330 | ohci_device_isoc_transfer, | 331 | .transfer = ohci_device_isoc_transfer, | |
331 | ohci_device_isoc_start, | 332 | .start = ohci_device_isoc_start, | |
332 | ohci_device_isoc_abort, | 333 | .abort = ohci_device_isoc_abort, | |
333 | ohci_device_isoc_close, | 334 | .close = ohci_device_isoc_close, | |
334 | ohci_noop, | 335 | .cleartoggle = ohci_noop, | |
335 | ohci_device_isoc_done, | 336 | .done = ohci_device_isoc_done, | |
336 | }; | 337 | }; | |
337 | 338 | |||
338 | int | 339 | int | |
339 | ohci_activate(device_t self, enum devact act) | 340 | ohci_activate(device_t self, enum devact act) | |
340 | { | 341 | { | |
341 | struct ohci_softc *sc = device_private(self); | 342 | struct ohci_softc *sc = device_private(self); | |
342 | 343 | |||
343 | switch (act) { | 344 | switch (act) { | |
344 | case DVACT_DEACTIVATE: | 345 | case DVACT_DEACTIVATE: | |
345 | sc->sc_dying = 1; | 346 | sc->sc_dying = 1; | |
346 | return 0; | 347 | return 0; | |
347 | default: | 348 | default: | |
348 | return EOPNOTSUPP; | 349 | return EOPNOTSUPP; | |
@@ -1859,56 +1860,57 @@ ohci_device_request(usbd_xfer_handle xfe | @@ -1859,56 +1860,57 @@ ohci_device_request(usbd_xfer_handle xfe | |||
1859 | return (USBD_NORMAL_COMPLETION); | 1860 | return (USBD_NORMAL_COMPLETION); | |
1860 | 1861 | |||
1861 | bad3: | 1862 | bad3: | |
1862 | ohci_free_std(sc, tail); | 1863 | ohci_free_std(sc, tail); | |
1863 | bad2: | 1864 | bad2: | |
1864 | ohci_free_std(sc, stat); | 1865 | ohci_free_std(sc, stat); | |
1865 | bad1: | 1866 | bad1: | |
1866 | return (err); | 1867 | return (err); | |
1867 | } | 1868 | } | |
1868 | 1869 | |||
1869 | /* | 1870 | /* | |
1870 | * Add an ED to the schedule. Called at splusb(). | 1871 | * Add an ED to the schedule. Called at splusb(). | |
1871 | */ | 1872 | */ | |
1872 | void | 1873 | Static void | |
1873 | ohci_add_ed(ohci_softc_t *sc, ohci_soft_ed_t *sed, ohci_soft_ed_t *head) | 1874 | ohci_add_ed(ohci_softc_t *sc, ohci_soft_ed_t *sed, ohci_soft_ed_t *head) | |
1874 | { | 1875 | { | |
1875 | DPRINTFN(8,("ohci_add_ed: sed=%p head=%p\n", sed, head)); | 1876 | DPRINTFN(8,("ohci_add_ed: sed=%p head=%p\n", sed, head)); | |
1876 | 1877 | |||
1877 | SPLUSBCHECK; | 1878 | KASSERT(mutex_owned(&sc->sc_lock)); | |
1879 | ||||
1878 | usb_syncmem(&head->dma, head->offs + offsetof(ohci_ed_t, ed_nexted), | 1880 | usb_syncmem(&head->dma, head->offs + offsetof(ohci_ed_t, ed_nexted), | |
1879 | sizeof(head->ed.ed_nexted), | 1881 | sizeof(head->ed.ed_nexted), | |
1880 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | 1882 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | |
1881 | sed->next = head->next; | 1883 | sed->next = head->next; | |
1882 | sed->ed.ed_nexted = head->ed.ed_nexted; | 1884 | sed->ed.ed_nexted = head->ed.ed_nexted; | |
1883 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_nexted), | 1885 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_nexted), | |
1884 | sizeof(sed->ed.ed_nexted), | 1886 | sizeof(sed->ed.ed_nexted), | |
1885 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 1887 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
1886 | head->next = sed; | 1888 | head->next = sed; | |
1887 | head->ed.ed_nexted = HTOO32(sed->physaddr); | 1889 | head->ed.ed_nexted = HTOO32(sed->physaddr); | |
1888 | usb_syncmem(&head->dma, head->offs + offsetof(ohci_ed_t, ed_nexted), | 1890 | usb_syncmem(&head->dma, head->offs + offsetof(ohci_ed_t, ed_nexted), | |
1889 | sizeof(head->ed.ed_nexted), | 1891 | sizeof(head->ed.ed_nexted), | |
1890 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 1892 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
1891 | } | 1893 | } | |
1892 | 1894 | |||
1893 | /* | 1895 | /* | |
1894 | * Remove an ED from the schedule. Called at splusb(). | 1896 | * Remove an ED from the schedule. Called at splusb(). | |
1895 | */ | 1897 | */ | |
1896 | void | 1898 | Static void | |
1897 | ohci_rem_ed(ohci_soft_ed_t *sed, ohci_soft_ed_t *head) | 1899 | ohci_rem_ed(ohci_softc_t *sc, ohci_soft_ed_t *sed, ohci_soft_ed_t *head) | |
1898 | { | 1900 | { | |
1899 | ohci_soft_ed_t *p; | 1901 | ohci_soft_ed_t *p; | |
1900 | 1902 | |||
1901 | SPLUSBCHECK; | 1903 | KASSERT(mutex_owned(&sc->sc_lock)); | |
1902 | 1904 | |||
1903 | /* XXX */ | 1905 | /* XXX */ | |
1904 | for (p = head; p != NULL && p->next != sed; p = p->next) | 1906 | for (p = head; p != NULL && p->next != sed; p = p->next) | |
1905 | ; | 1907 | ; | |
1906 | if (p == NULL) | 1908 | if (p == NULL) | |
1907 | panic("ohci_rem_ed: ED not found"); | 1909 | panic("ohci_rem_ed: ED not found"); | |
1908 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_nexted), | 1910 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_nexted), | |
1909 | sizeof(sed->ed.ed_nexted), | 1911 | sizeof(sed->ed.ed_nexted), | |
1910 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | 1912 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | |
1911 | p->next = sed->next; | 1913 | p->next = sed->next; | |
1912 | p->ed.ed_nexted = sed->ed.ed_nexted; | 1914 | p->ed.ed_nexted = sed->ed.ed_nexted; | |
1913 | usb_syncmem(&p->dma, p->offs + offsetof(ohci_ed_t, ed_nexted), | 1915 | usb_syncmem(&p->dma, p->offs + offsetof(ohci_ed_t, ed_nexted), | |
1914 | sizeof(p->ed.ed_nexted), | 1916 | sizeof(p->ed.ed_nexted), | |
@@ -1922,73 +1924,74 @@ ohci_rem_ed(ohci_soft_ed_t *sed, ohci_so | @@ -1922,73 +1924,74 @@ ohci_rem_ed(ohci_soft_ed_t *sed, ohci_so | |||
1922 | * and we have no simple way to translate this back to a kernel address. | 1924 | * and we have no simple way to translate this back to a kernel address. | |
1923 | * To make the translation possible (and fast) we use a hash table of | 1925 | * To make the translation possible (and fast) we use a hash table of | |
1924 | * TDs currently in the schedule. The physical address is used as the | 1926 | * TDs currently in the schedule. The physical address is used as the | |
1925 | * hash value. | 1927 | * hash value. | |
1926 | */ | 1928 | */ | |
1927 | 1929 | |||
1928 | #define HASH(a) (((a) >> 4) % OHCI_HASH_SIZE) | 1930 | #define HASH(a) (((a) >> 4) % OHCI_HASH_SIZE) | |
1929 | /* Called at splusb() */ | 1931 | /* Called at splusb() */ | |
1930 | void | 1932 | void | |
1931 | ohci_hash_add_td(ohci_softc_t *sc, ohci_soft_td_t *std) | 1933 | ohci_hash_add_td(ohci_softc_t *sc, ohci_soft_td_t *std) | |
1932 | { | 1934 | { | |
1933 | int h = HASH(std->physaddr); | 1935 | int h = HASH(std->physaddr); | |
1934 | 1936 | |||
1935 | SPLUSBCHECK; | 1937 | KASSERT(mutex_owned(&sc->sc_lock)); | |
1936 | 1938 | |||
1937 | LIST_INSERT_HEAD(&sc->sc_hash_tds[h], std, hnext); | 1939 | LIST_INSERT_HEAD(&sc->sc_hash_tds[h], std, hnext); | |
1938 | } | 1940 | } | |
1939 | 1941 | |||
1940 | /* Called at splusb() */ | 1942 | /* Called at splusb() */ | |
1941 | void | 1943 | void | |
1942 | ohci_hash_rem_td(ohci_softc_t *sc, ohci_soft_td_t *std) | 1944 | ohci_hash_rem_td(ohci_softc_t *sc, ohci_soft_td_t *std) | |
1943 | { | 1945 | { | |
1944 | SPLUSBCHECK; | 1946 | ||
1947 | KASSERT(mutex_owned(&sc->sc_lock)); | |||
1945 | 1948 | |||
1946 | LIST_REMOVE(std, hnext); | 1949 | LIST_REMOVE(std, hnext); | |
1947 | } | 1950 | } | |
1948 | 1951 | |||
1949 | ohci_soft_td_t * | 1952 | ohci_soft_td_t * | |
1950 | ohci_hash_find_td(ohci_softc_t *sc, ohci_physaddr_t a) | 1953 | ohci_hash_find_td(ohci_softc_t *sc, ohci_physaddr_t a) | |
1951 | { | 1954 | { | |
1952 | int h = HASH(a); | 1955 | int h = HASH(a); | |
1953 | ohci_soft_td_t *std; | 1956 | ohci_soft_td_t *std; | |
1954 | 1957 | |||
1955 | for (std = LIST_FIRST(&sc->sc_hash_tds[h]); | 1958 | for (std = LIST_FIRST(&sc->sc_hash_tds[h]); | |
1956 | std != NULL; | 1959 | std != NULL; | |
1957 | std = LIST_NEXT(std, hnext)) | 1960 | std = LIST_NEXT(std, hnext)) | |
1958 | if (std->physaddr == a) | 1961 | if (std->physaddr == a) | |
1959 | return (std); | 1962 | return (std); | |
1960 | return (NULL); | 1963 | return (NULL); | |
1961 | } | 1964 | } | |
1962 | 1965 | |||
1963 | /* Called at splusb() */ | 1966 | /* Called at splusb() */ | |
1964 | void | 1967 | void | |
1965 | ohci_hash_add_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) | 1968 | ohci_hash_add_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) | |
1966 | { | 1969 | { | |
1967 | int h = HASH(sitd->physaddr); | 1970 | int h = HASH(sitd->physaddr); | |
1968 | 1971 | |||
1969 | SPLUSBCHECK; | 1972 | KASSERT(mutex_owned(&sc->sc_lock)); | |
1970 | 1973 | |||
1971 | DPRINTFN(10,("ohci_hash_add_itd: sitd=%p physaddr=0x%08lx\n", | 1974 | DPRINTFN(10,("ohci_hash_add_itd: sitd=%p physaddr=0x%08lx\n", | |
1972 | sitd, (u_long)sitd->physaddr)); | 1975 | sitd, (u_long)sitd->physaddr)); | |
1973 | 1976 | |||
1974 | LIST_INSERT_HEAD(&sc->sc_hash_itds[h], sitd, hnext); | 1977 | LIST_INSERT_HEAD(&sc->sc_hash_itds[h], sitd, hnext); | |
1975 | } | 1978 | } | |
1976 | 1979 | |||
1977 | /* Called at splusb() */ | 1980 | /* Called at splusb() */ | |
1978 | void | 1981 | void | |
1979 | ohci_hash_rem_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) | 1982 | ohci_hash_rem_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) | |
1980 | { | 1983 | { | |
1981 | SPLUSBCHECK; | 1984 | KASSERT(mutex_owned(&sc->sc_lock)); | |
1982 | 1985 | |||
1983 | DPRINTFN(10,("ohci_hash_rem_itd: sitd=%p physaddr=0x%08lx\n", | 1986 | DPRINTFN(10,("ohci_hash_rem_itd: sitd=%p physaddr=0x%08lx\n", | |
1984 | sitd, (u_long)sitd->physaddr)); | 1987 | sitd, (u_long)sitd->physaddr)); | |
1985 | 1988 | |||
1986 | LIST_REMOVE(sitd, hnext); | 1989 | LIST_REMOVE(sitd, hnext); | |
1987 | } | 1990 | } | |
1988 | 1991 | |||
1989 | ohci_soft_itd_t * | 1992 | ohci_soft_itd_t * | |
1990 | ohci_hash_find_itd(ohci_softc_t *sc, ohci_physaddr_t a) | 1993 | ohci_hash_find_itd(ohci_softc_t *sc, ohci_physaddr_t a) | |
1991 | { | 1994 | { | |
1992 | int h = HASH(a); | 1995 | int h = HASH(a); | |
1993 | ohci_soft_itd_t *sitd; | 1996 | ohci_soft_itd_t *sitd; | |
1994 | 1997 | |||
@@ -2261,27 +2264,27 @@ ohci_close_pipe(usbd_pipe_handle pipe, o | @@ -2261,27 +2264,27 @@ ohci_close_pipe(usbd_pipe_handle pipe, o | |||
2261 | usbd_dump_pipe(&opipe->pipe); | 2264 | usbd_dump_pipe(&opipe->pipe); | |
2262 | #endif | 2265 | #endif | |
2263 | #ifdef OHCI_DEBUG | 2266 | #ifdef OHCI_DEBUG | |
2264 | ohci_dump_ed(sc, sed); | 2267 | ohci_dump_ed(sc, sed); | |
2265 | if (std) | 2268 | if (std) | |
2266 | ohci_dump_td(sc, std); | 2269 | ohci_dump_td(sc, std); | |
2267 | #endif | 2270 | #endif | |
2268 | usb_delay_ms(&sc->sc_bus, 2); | 2271 | usb_delay_ms(&sc->sc_bus, 2); | |
2269 | if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) != | 2272 | if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) != | |
2270 | (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK)) | 2273 | (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK)) | |
2271 | printf("ohci_close_pipe: pipe still not empty\n"); | 2274 | printf("ohci_close_pipe: pipe still not empty\n"); | |
2272 | } | 2275 | } | |
2273 | #endif | 2276 | #endif | |
2274 | ohci_rem_ed(sed, head); | 2277 | ohci_rem_ed(sc, sed, head); | |
2275 | /* Make sure the host controller is not touching this ED */ | 2278 | /* Make sure the host controller is not touching this ED */ | |
2276 | usb_delay_ms(&sc->sc_bus, 1); | 2279 | usb_delay_ms(&sc->sc_bus, 1); | |
2277 | pipe->endpoint->datatoggle = | 2280 | pipe->endpoint->datatoggle = | |
2278 | (O32TOH(sed->ed.ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0; | 2281 | (O32TOH(sed->ed.ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0; | |
2279 | ohci_free_sed(sc, opipe->sed); | 2282 | ohci_free_sed(sc, opipe->sed); | |
2280 | } | 2283 | } | |
2281 | 2284 | |||
2282 | /* | 2285 | /* | |
2283 | * Abort a device request. | 2286 | * Abort a device request. | |
2284 | * If this routine is called at splusb() it guarantees that the request | 2287 | * If this routine is called at splusb() it guarantees that the request | |
2285 | * will be removed from the hardware scheduling and that the callback | 2288 | * will be removed from the hardware scheduling and that the callback | |
2286 | * for it will be called with USBD_CANCELLED status. | 2289 | * for it will be called with USBD_CANCELLED status. | |
2287 | * It's impossible to guarantee that the requested transfer will not | 2290 | * It's impossible to guarantee that the requested transfer will not |
--- src/sys/dev/usb/uhci.c 2011/12/06 05:40:02 1.240.6.4
+++ src/sys/dev/usb/uhci.c 2011/12/08 02:51:08 1.240.6.5
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: uhci.c,v 1.240.6.4 2011/12/06 05:40:02 mrg Exp $ */ | 1 | /* $NetBSD: uhci.c,v 1.240.6.5 2011/12/08 02:51:08 mrg Exp $ */ | |
2 | /* $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $ */ | 2 | /* $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (c) 1998, 2004, 2011 The NetBSD Foundation, Inc. | 5 | * Copyright (c) 1998, 2004, 2011 The NetBSD Foundation, Inc. | |
6 | * All rights reserved. | 6 | * All rights reserved. | |
7 | * | 7 | * | |
8 | * This code is derived from software contributed to The NetBSD Foundation | 8 | * This code is derived from software contributed to The NetBSD Foundation | |
9 | * by Lennart Augustsson (lennart@augustsson.net) at | 9 | * by Lennart Augustsson (lennart@augustsson.net) at | |
10 | * Carlstedt Research & Technology, Jared D. McNeill (jmcneill@invisible.ca) | 10 | * Carlstedt Research & Technology, Jared D. McNeill (jmcneill@invisible.ca) | |
11 | * and Matthew R. Green. | 11 | * and Matthew R. Green. | |
12 | * | 12 | * | |
13 | * Redistribution and use in source and binary forms, with or without | 13 | * Redistribution and use in source and binary forms, with or without | |
14 | * modification, are permitted provided that the following conditions | 14 | * modification, are permitted provided that the following conditions | |
@@ -33,27 +33,27 @@ | @@ -33,27 +33,27 @@ | |||
33 | */ | 33 | */ | |
34 | 34 | |||
35 | /* | 35 | /* | |
36 | * USB Universal Host Controller driver. | 36 | * USB Universal Host Controller driver. | |
37 | * Handles e.g. PIIX3 and PIIX4. | 37 | * Handles e.g. PIIX3 and PIIX4. | |
38 | * | 38 | * | |
39 | * UHCI spec: http://www.intel.com/technology/usb/spec.htm | 39 | * UHCI spec: http://www.intel.com/technology/usb/spec.htm | |
40 | * USB spec: http://www.usb.org/developers/docs/ | 40 | * USB spec: http://www.usb.org/developers/docs/ | |
41 | * PIIXn spec: ftp://download.intel.com/design/intarch/datashts/29055002.pdf | 41 | * PIIXn spec: ftp://download.intel.com/design/intarch/datashts/29055002.pdf | |
42 | * ftp://download.intel.com/design/intarch/datashts/29056201.pdf | 42 | * ftp://download.intel.com/design/intarch/datashts/29056201.pdf | |
43 | */ | 43 | */ | |
44 | 44 | |||
45 | #include <sys/cdefs.h> | 45 | #include <sys/cdefs.h> | |
46 | __KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.240.6.4 2011/12/06 05:40:02 mrg Exp $"); | 46 | __KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.240.6.5 2011/12/08 02:51:08 mrg Exp $"); | |
47 | 47 | |||
48 | #include "opt_usb.h" | 48 | #include "opt_usb.h" | |
49 | 49 | |||
50 | #include <sys/param.h> | 50 | #include <sys/param.h> | |
51 | #include <sys/systm.h> | 51 | #include <sys/systm.h> | |
52 | #include <sys/kernel.h> | 52 | #include <sys/kernel.h> | |
53 | #include <sys/kmem.h> | 53 | #include <sys/kmem.h> | |
54 | #include <sys/device.h> | 54 | #include <sys/device.h> | |
55 | #include <sys/select.h> | 55 | #include <sys/select.h> | |
56 | #include <sys/extent.h> | 56 | #include <sys/extent.h> | |
57 | #include <sys/proc.h> | 57 | #include <sys/proc.h> | |
58 | #include <sys/queue.h> | 58 | #include <sys/queue.h> | |
59 | #include <sys/bus.h> | 59 | #include <sys/bus.h> | |
@@ -274,88 +274,88 @@ UREAD4(uhci_softc_t *sc, bus_size_t r) | @@ -274,88 +274,88 @@ UREAD4(uhci_softc_t *sc, bus_size_t r) | |||
274 | return bus_space_read_4(sc->iot, sc->ioh, r); | 274 | return bus_space_read_4(sc->iot, sc->ioh, r); | |
275 | } | 275 | } | |
276 | 276 | |||
277 | #define UHCICMD(sc, cmd) UWRITE2(sc, UHCI_CMD, cmd) | 277 | #define UHCICMD(sc, cmd) UWRITE2(sc, UHCI_CMD, cmd) | |
278 | #define UHCISTS(sc) UREAD2(sc, UHCI_STS) | 278 | #define UHCISTS(sc) UREAD2(sc, UHCI_STS) | |
279 | 279 | |||
280 | #define UHCI_RESET_TIMEOUT 100 /* ms, reset timeout */ | 280 | #define UHCI_RESET_TIMEOUT 100 /* ms, reset timeout */ | |
281 | 281 | |||
282 | #define UHCI_CURFRAME(sc) (UREAD2(sc, UHCI_FRNUM) & UHCI_FRNUM_MASK) | 282 | #define UHCI_CURFRAME(sc) (UREAD2(sc, UHCI_FRNUM) & UHCI_FRNUM_MASK) | |
283 | 283 | |||
284 | #define UHCI_INTR_ENDPT 1 | 284 | #define UHCI_INTR_ENDPT 1 | |
285 | 285 | |||
286 | const struct usbd_bus_methods uhci_bus_methods = { | 286 | const struct usbd_bus_methods uhci_bus_methods = { | |
287 | uhci_open, | 287 | .open_pipe = uhci_open, | |
288 | uhci_softintr, | 288 | .soft_intr = uhci_softintr, | |
289 | uhci_poll, | 289 | .do_poll = uhci_poll, | |
290 | uhci_allocm, | 290 | .allocm = uhci_allocm, | |
291 | uhci_freem, | 291 | .freem = uhci_freem, | |
292 | uhci_allocx, | 292 | .allocx = uhci_allocx, | |
293 | uhci_freex, | 293 | .freex = uhci_freex, | |
294 | uhci_get_locks, | 294 | .get_locks = uhci_get_locks, | |
295 | }; | 295 | }; | |
296 | 296 | |||
297 | const struct usbd_pipe_methods uhci_root_ctrl_methods = { | 297 | const struct usbd_pipe_methods uhci_root_ctrl_methods = { | |
298 | uhci_root_ctrl_transfer, | 298 | .transfer = uhci_root_ctrl_transfer, | |
299 | uhci_root_ctrl_start, | 299 | .start = uhci_root_ctrl_start, | |
300 | uhci_root_ctrl_abort, | 300 | .abort = uhci_root_ctrl_abort, | |
301 | uhci_root_ctrl_close, | 301 | .close = uhci_root_ctrl_close, | |
302 | uhci_noop, | 302 | .cleartoggle = uhci_noop, | |
303 | uhci_root_ctrl_done, | 303 | .done = uhci_root_ctrl_done, | |
304 | }; | 304 | }; | |
305 | 305 | |||
306 | const struct usbd_pipe_methods uhci_root_intr_methods = { | 306 | const struct usbd_pipe_methods uhci_root_intr_methods = { | |
307 | uhci_root_intr_transfer, | 307 | .transfer = uhci_root_intr_transfer, | |
308 | uhci_root_intr_start, | 308 | .start = uhci_root_intr_start, | |
309 | uhci_root_intr_abort, | 309 | .abort = uhci_root_intr_abort, | |
310 | uhci_root_intr_close, | 310 | .close = uhci_root_intr_close, | |
311 | uhci_noop, | 311 | .cleartoggle = uhci_noop, | |
312 | uhci_root_intr_done, | 312 | .done = uhci_root_intr_done, | |
313 | }; | 313 | }; | |
314 | 314 | |||
315 | const struct usbd_pipe_methods uhci_device_ctrl_methods = { | 315 | const struct usbd_pipe_methods uhci_device_ctrl_methods = { | |
316 | uhci_device_ctrl_transfer, | 316 | .transfer = uhci_device_ctrl_transfer, | |
317 | uhci_device_ctrl_start, | 317 | .start = uhci_device_ctrl_start, | |
318 | uhci_device_ctrl_abort, | 318 | .abort = uhci_device_ctrl_abort, | |
319 | uhci_device_ctrl_close, | 319 | .close = uhci_device_ctrl_close, | |
320 | uhci_noop, | 320 | .cleartoggle = uhci_noop, | |
321 | uhci_device_ctrl_done, | 321 | .done = uhci_device_ctrl_done, | |
322 | }; | 322 | }; | |
323 | 323 | |||
324 | const struct usbd_pipe_methods uhci_device_intr_methods = { | 324 | const struct usbd_pipe_methods uhci_device_intr_methods = { | |
325 | uhci_device_intr_transfer, | 325 | .transfer = uhci_device_intr_transfer, | |
326 | uhci_device_intr_start, | 326 | .start = uhci_device_intr_start, | |
327 | uhci_device_intr_abort, | 327 | .abort = uhci_device_intr_abort, | |
328 | uhci_device_intr_close, | 328 | .close = uhci_device_intr_close, | |
329 | uhci_device_clear_toggle, | 329 | .cleartoggle = uhci_device_clear_toggle, | |
330 | uhci_device_intr_done, | 330 | .done = uhci_device_intr_done, | |
331 | }; | 331 | }; | |
332 | 332 | |||
333 | const struct usbd_pipe_methods uhci_device_bulk_methods = { | 333 | const struct usbd_pipe_methods uhci_device_bulk_methods = { | |
334 | uhci_device_bulk_transfer, | 334 | .transfer = uhci_device_bulk_transfer, | |
335 | uhci_device_bulk_start, | 335 | .start = uhci_device_bulk_start, | |
336 | uhci_device_bulk_abort, | 336 | .abort = uhci_device_bulk_abort, | |
337 | uhci_device_bulk_close, | 337 | .close = uhci_device_bulk_close, | |
338 | uhci_device_clear_toggle, | 338 | .cleartoggle = uhci_device_clear_toggle, | |
339 | uhci_device_bulk_done, | 339 | .done = uhci_device_bulk_done, | |
340 | }; | 340 | }; | |
341 | 341 | |||
342 | const struct usbd_pipe_methods uhci_device_isoc_methods = { | 342 | const struct usbd_pipe_methods uhci_device_isoc_methods = { | |
343 | uhci_device_isoc_transfer, | 343 | .transfer = uhci_device_isoc_transfer, | |
344 | uhci_device_isoc_start, | 344 | .start = uhci_device_isoc_start, | |
345 | uhci_device_isoc_abort, | 345 | .abort = uhci_device_isoc_abort, | |
346 | uhci_device_isoc_close, | 346 | .close = uhci_device_isoc_close, | |
347 | uhci_noop, | 347 | .cleartoggle = uhci_noop, | |
348 | uhci_device_isoc_done, | 348 | .done = uhci_device_isoc_done, | |
349 | }; | 349 | }; | |
350 | 350 | |||
351 | #define uhci_add_intr_info(sc, ii) \ | 351 | #define uhci_add_intr_info(sc, ii) \ | |
352 | LIST_INSERT_HEAD(&(sc)->sc_intrhead, (ii), list) | 352 | LIST_INSERT_HEAD(&(sc)->sc_intrhead, (ii), list) | |
353 | #define uhci_del_intr_info(ii) \ | 353 | #define uhci_del_intr_info(ii) \ | |
354 | do { \ | 354 | do { \ | |
355 | LIST_REMOVE((ii), list); \ | 355 | LIST_REMOVE((ii), list); \ | |
356 | (ii)->list.le_prev = NULL; \ | 356 | (ii)->list.le_prev = NULL; \ | |
357 | } while (0) | 357 | } while (0) | |
358 | #define uhci_active_intr_info(ii) ((ii)->list.le_prev != NULL) | 358 | #define uhci_active_intr_info(ii) ((ii)->list.le_prev != NULL) | |
359 | 359 | |||
360 | static inline uhci_soft_qh_t * | 360 | static inline uhci_soft_qh_t * | |
361 | uhci_find_prev_qh(uhci_soft_qh_t *pqh, uhci_soft_qh_t *sqh) | 361 | uhci_find_prev_qh(uhci_soft_qh_t *pqh, uhci_soft_qh_t *sqh) | |
@@ -1087,54 +1087,54 @@ uhci_rem_loop(uhci_softc_t *sc) { | @@ -1087,54 +1087,54 @@ uhci_rem_loop(uhci_softc_t *sc) { | |||
1087 | usb_syncmem(&sc->sc_last_qh->dma, | 1087 | usb_syncmem(&sc->sc_last_qh->dma, | |
1088 | sc->sc_last_qh->offs + offsetof(uhci_qh_t, qh_hlink), | 1088 | sc->sc_last_qh->offs + offsetof(uhci_qh_t, qh_hlink), | |
1089 | sizeof(sc->sc_last_qh->qh.qh_hlink), | 1089 | sizeof(sc->sc_last_qh->qh.qh_hlink), | |
1090 | BUS_DMASYNC_PREWRITE); | 1090 | BUS_DMASYNC_PREWRITE); | |
1091 | } | 1091 | } | |
1092 | } | 1092 | } | |
1093 | 1093 | |||
1094 | /* Add high speed control QH, called at splusb(). */ | 1094 | /* Add high speed control QH, called at splusb(). */ | |
1095 | void | 1095 | void | |
1096 | uhci_add_hs_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) | 1096 | uhci_add_hs_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) | |
1097 | { | 1097 | { | |
1098 | uhci_soft_qh_t *eqh; | 1098 | uhci_soft_qh_t *eqh; | |
1099 | 1099 | |||
1100 | SPLUSBCHECK; | 1100 | KASSERT(mutex_owned(&sc->sc_lock)); | |
1101 | 1101 | |||
1102 | DPRINTFN(10, ("uhci_add_ctrl: sqh=%p\n", sqh)); | 1102 | DPRINTFN(10, ("uhci_add_ctrl: sqh=%p\n", sqh)); | |
1103 | eqh = sc->sc_hctl_end; | 1103 | eqh = sc->sc_hctl_end; | |
1104 | usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink), | 1104 | usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink), | |
1105 | sizeof(eqh->qh.qh_hlink), | 1105 | sizeof(eqh->qh.qh_hlink), | |
1106 | BUS_DMASYNC_POSTWRITE); | 1106 | BUS_DMASYNC_POSTWRITE); | |
1107 | sqh->hlink = eqh->hlink; | 1107 | sqh->hlink = eqh->hlink; | |
1108 | sqh->qh.qh_hlink = eqh->qh.qh_hlink; | 1108 | sqh->qh.qh_hlink = eqh->qh.qh_hlink; | |
1109 | usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh), | 1109 | usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh), | |
1110 | BUS_DMASYNC_PREWRITE); | 1110 | BUS_DMASYNC_PREWRITE); | |
1111 | eqh->hlink = sqh; | 1111 | eqh->hlink = sqh; | |
1112 | eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); | 1112 | eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); | |
1113 | sc->sc_hctl_end = sqh; | 1113 | sc->sc_hctl_end = sqh; | |
1114 | usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink), | 1114 | usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink), | |
1115 | sizeof(eqh->qh.qh_hlink), BUS_DMASYNC_PREWRITE); | 1115 | sizeof(eqh->qh.qh_hlink), BUS_DMASYNC_PREWRITE); | |
1116 | #ifdef UHCI_CTL_LOOP | 1116 | #ifdef UHCI_CTL_LOOP | |
1117 | uhci_add_loop(sc); | 1117 | uhci_add_loop(sc); | |
1118 | #endif | 1118 | #endif | |
1119 | } | 1119 | } | |
1120 | 1120 | |||
1121 | /* Remove high speed control QH, called at splusb(). */ | 1121 | /* Remove high speed control QH, called at splusb(). */ | |
1122 | void | 1122 | void | |
1123 | uhci_remove_hs_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) | 1123 | uhci_remove_hs_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) | |
1124 | { | 1124 | { | |
1125 | uhci_soft_qh_t *pqh; | 1125 | uhci_soft_qh_t *pqh; | |
1126 | 1126 | |||
1127 | SPLUSBCHECK; | 1127 | KASSERT(mutex_owned(&sc->sc_lock)); | |
1128 | 1128 | |||
1129 | DPRINTFN(10, ("uhci_remove_hs_ctrl: sqh=%p\n", sqh)); | 1129 | DPRINTFN(10, ("uhci_remove_hs_ctrl: sqh=%p\n", sqh)); | |
1130 | #ifdef UHCI_CTL_LOOP | 1130 | #ifdef UHCI_CTL_LOOP | |
1131 | uhci_rem_loop(sc); | 1131 | uhci_rem_loop(sc); | |
1132 | #endif | 1132 | #endif | |
1133 | /* | 1133 | /* | |
1134 | * The T bit should be set in the elink of the QH so that the HC | 1134 | * The T bit should be set in the elink of the QH so that the HC | |
1135 | * doesn't follow the pointer. This condition may fail if the | 1135 | * doesn't follow the pointer. This condition may fail if the | |
1136 | * the transferred packet was short so that the QH still points | 1136 | * the transferred packet was short so that the QH still points | |
1137 | * at the last used TD. | 1137 | * at the last used TD. | |
1138 | * In this case we set the T bit and wait a little for the HC | 1138 | * In this case we set the T bit and wait a little for the HC | |
1139 | * to stop looking at the TD. | 1139 | * to stop looking at the TD. | |
1140 | * Note that if the TD chain is large enough, the controller | 1140 | * Note that if the TD chain is large enough, the controller | |
@@ -1164,50 +1164,50 @@ uhci_remove_hs_ctrl(uhci_softc_t *sc, uh | @@ -1164,50 +1164,50 @@ uhci_remove_hs_ctrl(uhci_softc_t *sc, uh | |||
1164 | sizeof(pqh->qh.qh_hlink), | 1164 | sizeof(pqh->qh.qh_hlink), | |
1165 | BUS_DMASYNC_PREWRITE); | 1165 | BUS_DMASYNC_PREWRITE); | |
1166 | delay(UHCI_QH_REMOVE_DELAY); | 1166 | delay(UHCI_QH_REMOVE_DELAY); | |
1167 | if (sc->sc_hctl_end == sqh) | 1167 | if (sc->sc_hctl_end == sqh) | |
1168 | sc->sc_hctl_end = pqh; | 1168 | sc->sc_hctl_end = pqh; | |
1169 | } | 1169 | } | |
1170 | 1170 | |||
1171 | /* Add low speed control QH, called at splusb(). */ | 1171 | /* Add low speed control QH, called at splusb(). */ | |
1172 | void | 1172 | void | |
1173 | uhci_add_ls_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) | 1173 | uhci_add_ls_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) | |
1174 | { | 1174 | { | |
1175 | uhci_soft_qh_t *eqh; | 1175 | uhci_soft_qh_t *eqh; | |
1176 | 1176 | |||
1177 | SPLUSBCHECK; | 1177 | KASSERT(mutex_owned(&sc->sc_lock)); | |
1178 | 1178 | |||
1179 | DPRINTFN(10, ("uhci_add_ls_ctrl: sqh=%p\n", sqh)); | 1179 | DPRINTFN(10, ("uhci_add_ls_ctrl: sqh=%p\n", sqh)); | |
1180 | eqh = sc->sc_lctl_end; | 1180 | eqh = sc->sc_lctl_end; | |
1181 | usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink), | 1181 | usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink), | |
1182 | sizeof(eqh->qh.qh_hlink), BUS_DMASYNC_POSTWRITE); | 1182 | sizeof(eqh->qh.qh_hlink), BUS_DMASYNC_POSTWRITE); | |
1183 | sqh->hlink = eqh->hlink; | 1183 | sqh->hlink = eqh->hlink; | |
1184 | sqh->qh.qh_hlink = eqh->qh.qh_hlink; | 1184 | sqh->qh.qh_hlink = eqh->qh.qh_hlink; | |
1185 | usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh), | 1185 | usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh), | |
1186 | BUS_DMASYNC_PREWRITE); | 1186 | BUS_DMASYNC_PREWRITE); | |
1187 | eqh->hlink = sqh; | 1187 | eqh->hlink = sqh; | |
1188 | eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); | 1188 | eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); | |
1189 | usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink), | 1189 | usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink), | |
1190 | sizeof(eqh->qh.qh_hlink), BUS_DMASYNC_PREWRITE); | 1190 | sizeof(eqh->qh.qh_hlink), BUS_DMASYNC_PREWRITE); | |
1191 | sc->sc_lctl_end = sqh; | 1191 | sc->sc_lctl_end = sqh; | |
1192 | } | 1192 | } | |
1193 | 1193 | |||
1194 | /* Remove low speed control QH, called at splusb(). */ | 1194 | /* Remove low speed control QH, called at splusb(). */ | |
1195 | void | 1195 | void | |
1196 | uhci_remove_ls_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) | 1196 | uhci_remove_ls_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) | |
1197 | { | 1197 | { | |
1198 | uhci_soft_qh_t *pqh; | 1198 | uhci_soft_qh_t *pqh; | |
1199 | 1199 | |||
1200 | SPLUSBCHECK; | 1200 | KASSERT(mutex_owned(&sc->sc_lock)); | |
1201 | 1201 | |||
1202 | DPRINTFN(10, ("uhci_remove_ls_ctrl: sqh=%p\n", sqh)); | 1202 | DPRINTFN(10, ("uhci_remove_ls_ctrl: sqh=%p\n", sqh)); | |
1203 | /* See comment in uhci_remove_hs_ctrl() */ | 1203 | /* See comment in uhci_remove_hs_ctrl() */ | |
1204 | usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink), | 1204 | usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink), | |
1205 | sizeof(sqh->qh.qh_elink), | 1205 | sizeof(sqh->qh.qh_elink), | |
1206 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | 1206 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | |
1207 | if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) { | 1207 | if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) { | |
1208 | sqh->qh.qh_elink = htole32(UHCI_PTR_T); | 1208 | sqh->qh.qh_elink = htole32(UHCI_PTR_T); | |
1209 | usb_syncmem(&sqh->dma, | 1209 | usb_syncmem(&sqh->dma, | |
1210 | sqh->offs + offsetof(uhci_qh_t, qh_elink), | 1210 | sqh->offs + offsetof(uhci_qh_t, qh_elink), | |
1211 | sizeof(sqh->qh.qh_elink), | 1211 | sizeof(sqh->qh.qh_elink), | |
1212 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 1212 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
1213 | delay(UHCI_QH_REMOVE_DELAY); | 1213 | delay(UHCI_QH_REMOVE_DELAY); | |
@@ -1221,51 +1221,51 @@ uhci_remove_ls_ctrl(uhci_softc_t *sc, uh | @@ -1221,51 +1221,51 @@ uhci_remove_ls_ctrl(uhci_softc_t *sc, uh | |||
1221 | sizeof(pqh->qh.qh_hlink), | 1221 | sizeof(pqh->qh.qh_hlink), | |
1222 | BUS_DMASYNC_PREWRITE); | 1222 | BUS_DMASYNC_PREWRITE); | |
1223 | delay(UHCI_QH_REMOVE_DELAY); | 1223 | delay(UHCI_QH_REMOVE_DELAY); | |
1224 | if (sc->sc_lctl_end == sqh) | 1224 | if (sc->sc_lctl_end == sqh) | |
1225 | sc->sc_lctl_end = pqh; | 1225 | sc->sc_lctl_end = pqh; | |
1226 | } | 1226 | } | |
1227 | 1227 | |||
1228 | /* Add bulk QH, called at splusb(). */ | 1228 | /* Add bulk QH, called at splusb(). */ | |
1229 | void | 1229 | void | |
1230 | uhci_add_bulk(uhci_softc_t *sc, uhci_soft_qh_t *sqh) | 1230 | uhci_add_bulk(uhci_softc_t *sc, uhci_soft_qh_t *sqh) | |
1231 | { | 1231 | { | |
1232 | uhci_soft_qh_t *eqh; | 1232 | uhci_soft_qh_t *eqh; | |
1233 | 1233 | |||
1234 | SPLUSBCHECK; | 1234 | KASSERT(mutex_owned(&sc->sc_lock)); | |
1235 | 1235 | |||
1236 | DPRINTFN(10, ("uhci_add_bulk: sqh=%p\n", sqh)); | 1236 | DPRINTFN(10, ("uhci_add_bulk: sqh=%p\n", sqh)); | |
1237 | eqh = sc->sc_bulk_end; | 1237 | eqh = sc->sc_bulk_end; | |
1238 | usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink), | 1238 | usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink), | |
1239 | sizeof(eqh->qh.qh_hlink), BUS_DMASYNC_POSTWRITE); | 1239 | sizeof(eqh->qh.qh_hlink), BUS_DMASYNC_POSTWRITE); | |
1240 | sqh->hlink = eqh->hlink; | 1240 | sqh->hlink = eqh->hlink; | |
1241 | sqh->qh.qh_hlink = eqh->qh.qh_hlink; | 1241 | sqh->qh.qh_hlink = eqh->qh.qh_hlink; | |
1242 | usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh), | 1242 | usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh), | |
1243 | BUS_DMASYNC_PREWRITE); | 1243 | BUS_DMASYNC_PREWRITE); | |
1244 | eqh->hlink = sqh; | 1244 | eqh->hlink = sqh; | |
1245 | eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); | 1245 | eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); | |
1246 | usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink), | 1246 | usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink), | |
1247 | sizeof(eqh->qh.qh_hlink), BUS_DMASYNC_PREWRITE); | 1247 | sizeof(eqh->qh.qh_hlink), BUS_DMASYNC_PREWRITE); | |
1248 | sc->sc_bulk_end = sqh; | 1248 | sc->sc_bulk_end = sqh; | |
1249 | uhci_add_loop(sc); | 1249 | uhci_add_loop(sc); | |
1250 | } | 1250 | } | |
1251 | 1251 | |||
1252 | /* Remove bulk QH, called at splusb(). */ | 1252 | /* Remove bulk QH, called at splusb(). */ | |
1253 | void | 1253 | void | |
1254 | uhci_remove_bulk(uhci_softc_t *sc, uhci_soft_qh_t *sqh) | 1254 | uhci_remove_bulk(uhci_softc_t *sc, uhci_soft_qh_t *sqh) | |
1255 | { | 1255 | { | |
1256 | uhci_soft_qh_t *pqh; | 1256 | uhci_soft_qh_t *pqh; | |
1257 | 1257 | |||
1258 | SPLUSBCHECK; | 1258 | KASSERT(mutex_owned(&sc->sc_lock)); | |
1259 | 1259 | |||
1260 | DPRINTFN(10, ("uhci_remove_bulk: sqh=%p\n", sqh)); | 1260 | DPRINTFN(10, ("uhci_remove_bulk: sqh=%p\n", sqh)); | |
1261 | uhci_rem_loop(sc); | 1261 | uhci_rem_loop(sc); | |
1262 | /* See comment in uhci_remove_hs_ctrl() */ | 1262 | /* See comment in uhci_remove_hs_ctrl() */ | |
1263 | usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink), | 1263 | usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink), | |
1264 | sizeof(sqh->qh.qh_elink), | 1264 | sizeof(sqh->qh.qh_elink), | |
1265 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | 1265 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | |
1266 | if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) { | 1266 | if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) { | |
1267 | sqh->qh.qh_elink = htole32(UHCI_PTR_T); | 1267 | sqh->qh.qh_elink = htole32(UHCI_PTR_T); | |
1268 | usb_syncmem(&sqh->dma, | 1268 | usb_syncmem(&sqh->dma, | |
1269 | sqh->offs + offsetof(uhci_qh_t, qh_elink), | 1269 | sqh->offs + offsetof(uhci_qh_t, qh_elink), | |
1270 | sizeof(sqh->qh.qh_elink), | 1270 | sizeof(sqh->qh.qh_elink), | |
1271 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 1271 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
--- src/sys/dev/usb/usb.c 2011/12/07 22:52:17 1.125.6.3
+++ src/sys/dev/usb/usb.c 2011/12/08 02:51:08 1.125.6.4
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: usb.c,v 1.125.6.3 2011/12/07 22:52:17 mrg Exp $ */ | 1 | /* $NetBSD: usb.c,v 1.125.6.4 2011/12/08 02:51:08 mrg Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2002, 2008 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 2002, 2008 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) at | 8 | * by Lennart Augustsson (lennart@augustsson.net) at | |
9 | * Carlstedt Research & Technology. | 9 | * Carlstedt Research & Technology. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -27,27 +27,27 @@ | @@ -27,27 +27,27 @@ | |||
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | /* | 33 | /* | |
34 | * USB specifications and other documentation can be found at | 34 | * USB specifications and other documentation can be found at | |
35 | * http://www.usb.org/developers/docs/ and | 35 | * http://www.usb.org/developers/docs/ and | |
36 | * http://www.usb.org/developers/devclass_docs/ | 36 | * http://www.usb.org/developers/devclass_docs/ | |
37 | */ | 37 | */ | |
38 | 38 | |||
39 | #include <sys/cdefs.h> | 39 | #include <sys/cdefs.h> | |
40 | __KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.125.6.3 2011/12/07 22:52:17 mrg Exp $"); | 40 | __KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.125.6.4 2011/12/08 02:51:08 mrg Exp $"); | |
41 | 41 | |||
42 | #include "opt_compat_netbsd.h" | 42 | #include "opt_compat_netbsd.h" | |
43 | #include "opt_usb.h" | 43 | #include "opt_usb.h" | |
44 | 44 | |||
45 | #include <sys/param.h> | 45 | #include <sys/param.h> | |
46 | #include <sys/systm.h> | 46 | #include <sys/systm.h> | |
47 | #include <sys/kernel.h> | 47 | #include <sys/kernel.h> | |
48 | #include <sys/malloc.h> | 48 | #include <sys/malloc.h> | |
49 | #include <sys/device.h> | 49 | #include <sys/device.h> | |
50 | #include <sys/kthread.h> | 50 | #include <sys/kthread.h> | |
51 | #include <sys/proc.h> | 51 | #include <sys/proc.h> | |
52 | #include <sys/conf.h> | 52 | #include <sys/conf.h> | |
53 | #include <sys/fcntl.h> | 53 | #include <sys/fcntl.h> | |
@@ -216,26 +216,33 @@ usb_doattach(device_t self) | @@ -216,26 +216,33 @@ usb_doattach(device_t self) | |||
216 | 216 | |||
217 | switch (sc->sc_bus->usbrev) { | 217 | switch (sc->sc_bus->usbrev) { | |
218 | case USBREV_1_0: | 218 | case USBREV_1_0: | |
219 | case USBREV_1_1: | 219 | case USBREV_1_1: | |
220 | speed = USB_SPEED_FULL; | 220 | speed = USB_SPEED_FULL; | |
221 | break; | 221 | break; | |
222 | case USBREV_2_0: | 222 | case USBREV_2_0: | |
223 | speed = USB_SPEED_HIGH; | 223 | speed = USB_SPEED_HIGH; | |
224 | break; | 224 | break; | |
225 | default: | 225 | default: | |
226 | panic("usb_doattach"); | 226 | panic("usb_doattach"); | |
227 | } | 227 | } | |
228 | 228 | |||
229 | if (mpsafe) { | |||
230 | sc->sc_bus->methods->get_locks(sc->sc_bus, | |||
231 | &sc->sc_bus->intr_lock, &sc->sc_bus->lock); | |||
232 | } else { | |||
233 | sc->sc_bus->intr_lock = sc->sc_bus->lock = NULL; | |||
234 | } | |||
235 | ||||
229 | ue = usb_alloc_event(); | 236 | ue = usb_alloc_event(); | |
230 | ue->u.ue_ctrlr.ue_bus = device_unit(self); | 237 | ue->u.ue_ctrlr.ue_bus = device_unit(self); | |
231 | usb_add_event(USB_EVENT_CTRLR_ATTACH, ue); | 238 | usb_add_event(USB_EVENT_CTRLR_ATTACH, ue); | |
232 | 239 | |||
233 | /* XXX we should have our own level */ | 240 | /* XXX we should have our own level */ | |
234 | sc->sc_bus->soft = softint_establish( | 241 | sc->sc_bus->soft = softint_establish( | |
235 | SOFTINT_NET | (mpsafe ? SOFTINT_MPSAFE : 0), | 242 | SOFTINT_NET | (mpsafe ? SOFTINT_MPSAFE : 0), | |
236 | sc->sc_bus->methods->soft_intr, sc->sc_bus); | 243 | sc->sc_bus->methods->soft_intr, sc->sc_bus); | |
237 | if (sc->sc_bus->soft == NULL) { | 244 | if (sc->sc_bus->soft == NULL) { | |
238 | aprint_error("%s: can't register softintr\n", | 245 | aprint_error("%s: can't register softintr\n", | |
239 | device_xname(self)); | 246 | device_xname(self)); | |
240 | sc->sc_dying = 1; | 247 | sc->sc_dying = 1; | |
241 | return; | 248 | return; |
--- src/sys/dev/usb/usb_subr.c 2011/12/04 13:23:17 1.180.6.1
+++ src/sys/dev/usb/usb_subr.c 2011/12/08 02:51:08 1.180.6.2
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: usb_subr.c,v 1.180.6.1 2011/12/04 13:23:17 jmcneill Exp $ */ | 1 | /* $NetBSD: usb_subr.c,v 1.180.6.2 2011/12/08 02:51:08 mrg Exp $ */ | |
2 | /* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $ */ | 2 | /* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc. | 5 | * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc. | |
6 | * All rights reserved. | 6 | * All rights reserved. | |
7 | * | 7 | * | |
8 | * This code is derived from software contributed to The NetBSD Foundation | 8 | * This code is derived from software contributed to The NetBSD Foundation | |
9 | * by Lennart Augustsson (lennart@augustsson.net) at | 9 | * by Lennart Augustsson (lennart@augustsson.net) at | |
10 | * Carlstedt Research & Technology. | 10 | * Carlstedt Research & Technology. | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
@@ -22,27 +22,27 @@ | @@ -22,27 +22,27 @@ | |||
22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
31 | * POSSIBILITY OF SUCH DAMAGE. | 31 | * POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | #include <sys/cdefs.h> | 34 | #include <sys/cdefs.h> | |
35 | __KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.180.6.1 2011/12/04 13:23:17 jmcneill Exp $"); | 35 | __KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.180.6.2 2011/12/08 02:51:08 mrg Exp $"); | |
36 | 36 | |||
37 | #include "opt_compat_netbsd.h" | 37 | #include "opt_compat_netbsd.h" | |
38 | #include "opt_usbverbose.h" | 38 | #include "opt_usbverbose.h" | |
39 | 39 | |||
40 | #include <sys/param.h> | 40 | #include <sys/param.h> | |
41 | #include <sys/systm.h> | 41 | #include <sys/systm.h> | |
42 | #include <sys/kernel.h> | 42 | #include <sys/kernel.h> | |
43 | #include <sys/malloc.h> | 43 | #include <sys/malloc.h> | |
44 | #include <sys/device.h> | 44 | #include <sys/device.h> | |
45 | #include <sys/select.h> | 45 | #include <sys/select.h> | |
46 | #include <sys/proc.h> | 46 | #include <sys/proc.h> | |
47 | 47 | |||
48 | #include <sys/bus.h> | 48 | #include <sys/bus.h> | |
@@ -741,31 +741,26 @@ usbd_setup_pipe(usbd_device_handle dev, | @@ -741,31 +741,26 @@ usbd_setup_pipe(usbd_device_handle dev, | |||
741 | p->running = 0; | 741 | p->running = 0; | |
742 | p->aborting = 0; | 742 | p->aborting = 0; | |
743 | p->repeat = 0; | 743 | p->repeat = 0; | |
744 | p->interval = ival; | 744 | p->interval = ival; | |
745 | SIMPLEQ_INIT(&p->queue); | 745 | SIMPLEQ_INIT(&p->queue); | |
746 | err = dev->bus->methods->open_pipe(p); | 746 | err = dev->bus->methods->open_pipe(p); | |
747 | if (err) { | 747 | if (err) { | |
748 | DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error=" | 748 | DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error=" | |
749 | "%s\n", | 749 | "%s\n", | |
750 | ep->edesc->bEndpointAddress, usbd_errstr(err))); | 750 | ep->edesc->bEndpointAddress, usbd_errstr(err))); | |
751 | free(p, M_USB); | 751 | free(p, M_USB); | |
752 | return (err); | 752 | return (err); | |
753 | } | 753 | } | |
754 | if (dev->bus->methods->get_locks) { | |||
755 | dev->bus->methods->get_locks(dev->bus, &p->intr_lock, &p->lock); | |||
756 | } else { | |||
757 | p->intr_lock = p->lock = NULL; | |||
758 | } | |||
759 | *pipe = p; | 754 | *pipe = p; | |
760 | return (USBD_NORMAL_COMPLETION); | 755 | return (USBD_NORMAL_COMPLETION); | |
761 | } | 756 | } | |
762 | 757 | |||
763 | /* Abort the device control pipe. */ | 758 | /* Abort the device control pipe. */ | |
764 | void | 759 | void | |
765 | usbd_kill_pipe(usbd_pipe_handle pipe) | 760 | usbd_kill_pipe(usbd_pipe_handle pipe) | |
766 | { | 761 | { | |
767 | usbd_abort_pipe(pipe); | 762 | usbd_abort_pipe(pipe); | |
768 | pipe->methods->close(pipe); | 763 | pipe->methods->close(pipe); | |
769 | pipe->endpoint->refcnt--; | 764 | pipe->endpoint->refcnt--; | |
770 | free(pipe, M_USB); | 765 | free(pipe, M_USB); | |
771 | } | 766 | } |
--- src/sys/dev/usb/usbdi.c 2011/12/04 13:23:17 1.134.2.1
+++ src/sys/dev/usb/usbdi.c 2011/12/08 02:51:08 1.134.2.2
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: usbdi.c,v 1.134.2.1 2011/12/04 13:23:17 jmcneill Exp $ */ | 1 | /* $NetBSD: usbdi.c,v 1.134.2.2 2011/12/08 02:51:08 mrg Exp $ */ | |
2 | /* $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.28 1999/11/17 22:33:49 n_hibma Exp $ */ | 2 | /* $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.28 1999/11/17 22:33:49 n_hibma Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (c) 1998 The NetBSD Foundation, Inc. | 5 | * Copyright (c) 1998 The NetBSD Foundation, Inc. | |
6 | * All rights reserved. | 6 | * All rights reserved. | |
7 | * | 7 | * | |
8 | * This code is derived from software contributed to The NetBSD Foundation | 8 | * This code is derived from software contributed to The NetBSD Foundation | |
9 | * by Lennart Augustsson (lennart@augustsson.net) at | 9 | * by Lennart Augustsson (lennart@augustsson.net) at | |
10 | * Carlstedt Research & Technology. | 10 | * Carlstedt Research & Technology. | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
@@ -22,27 +22,27 @@ | @@ -22,27 +22,27 @@ | |||
22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
31 | * POSSIBILITY OF SUCH DAMAGE. | 31 | * POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | #include <sys/cdefs.h> | 34 | #include <sys/cdefs.h> | |
35 | __KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.134.2.1 2011/12/04 13:23:17 jmcneill Exp $"); | 35 | __KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.134.2.2 2011/12/08 02:51:08 mrg Exp $"); | |
36 | 36 | |||
37 | #include "opt_compat_netbsd.h" | 37 | #include "opt_compat_netbsd.h" | |
38 | #include "opt_usb.h" | 38 | #include "opt_usb.h" | |
39 | 39 | |||
40 | #include <sys/param.h> | 40 | #include <sys/param.h> | |
41 | #include <sys/systm.h> | 41 | #include <sys/systm.h> | |
42 | #include <sys/kernel.h> | 42 | #include <sys/kernel.h> | |
43 | #include <sys/device.h> | 43 | #include <sys/device.h> | |
44 | #include <sys/malloc.h> | 44 | #include <sys/malloc.h> | |
45 | #include <sys/proc.h> | 45 | #include <sys/proc.h> | |
46 | 46 | |||
47 | #include <sys/bus.h> | 47 | #include <sys/bus.h> | |
48 | 48 | |||
@@ -300,37 +300,37 @@ usbd_transfer(usbd_xfer_handle xfer) | @@ -300,37 +300,37 @@ usbd_transfer(usbd_xfer_handle xfer) | |||
300 | struct usbd_bus *bus = pipe->device->bus; | 300 | struct usbd_bus *bus = pipe->device->bus; | |
301 | 301 | |||
302 | bus->methods->freem(bus, &xfer->dmabuf); | 302 | bus->methods->freem(bus, &xfer->dmabuf); | |
303 | xfer->rqflags &= ~URQ_AUTO_DMABUF; | 303 | xfer->rqflags &= ~URQ_AUTO_DMABUF; | |
304 | } | 304 | } | |
305 | } | 305 | } | |
306 | 306 | |||
307 | if (!(flags & USBD_SYNCHRONOUS)) | 307 | if (!(flags & USBD_SYNCHRONOUS)) | |
308 | return (err); | 308 | return (err); | |
309 | 309 | |||
310 | /* Sync transfer, wait for completion. */ | 310 | /* Sync transfer, wait for completion. */ | |
311 | if (err != USBD_IN_PROGRESS) | 311 | if (err != USBD_IN_PROGRESS) | |
312 | return (err); | 312 | return (err); | |
313 | usbd_lock(pipe->lock); | 313 | usbd_lock_pipe(pipe); | |
314 | if (!xfer->done) { | 314 | if (!xfer->done) { | |
315 | if (pipe->device->bus->use_polling) | 315 | if (pipe->device->bus->use_polling) | |
316 | panic("usbd_transfer: not done"); | 316 | panic("usbd_transfer: not done"); | |
317 | if (pipe->lock) { | 317 | if (pipe->device->bus->lock) { | |
318 | cv_wait(&xfer->cv, pipe->lock); | 318 | cv_wait(&xfer->cv, pipe->device->bus->lock); | |
319 | } else { | 319 | } else { | |
320 | tsleep(xfer, PRIBIO, "usbsyn", 0); | 320 | tsleep(xfer, PRIBIO, "usbsyn", 0); | |
321 | } | 321 | } | |
322 | } | 322 | } | |
323 | usbd_unlock(pipe->lock); | 323 | usbd_unlock_pipe(pipe); | |
324 | return (xfer->status); | 324 | return (xfer->status); | |
325 | } | 325 | } | |
326 | 326 | |||
327 | /* Like usbd_transfer(), but waits for completion. */ | 327 | /* Like usbd_transfer(), but waits for completion. */ | |
328 | usbd_status | 328 | usbd_status | |
329 | usbd_sync_transfer(usbd_xfer_handle xfer) | 329 | usbd_sync_transfer(usbd_xfer_handle xfer) | |
330 | { | 330 | { | |
331 | xfer->flags |= USBD_SYNCHRONOUS; | 331 | xfer->flags |= USBD_SYNCHRONOUS; | |
332 | return (usbd_transfer(xfer)); | 332 | return (usbd_transfer(xfer)); | |
333 | } | 333 | } | |
334 | 334 | |||
335 | void * | 335 | void * | |
336 | usbd_alloc_buffer(usbd_xfer_handle xfer, u_int32_t size) | 336 | usbd_alloc_buffer(usbd_xfer_handle xfer, u_int32_t size) | |
@@ -527,29 +527,29 @@ usbd_abort_default_pipe(struct usbd_devi | @@ -527,29 +527,29 @@ usbd_abort_default_pipe(struct usbd_devi | |||
527 | usbd_status | 527 | usbd_status | |
528 | usbd_abort_pipe(usbd_pipe_handle pipe) | 528 | usbd_abort_pipe(usbd_pipe_handle pipe) | |
529 | { | 529 | { | |
530 | usbd_status err; | 530 | usbd_status err; | |
531 | int s; | 531 | int s; | |
532 | usbd_xfer_handle intrxfer = pipe->intrxfer; | 532 | usbd_xfer_handle intrxfer = pipe->intrxfer; | |
533 | 533 | |||
534 | #ifdef DIAGNOSTIC | 534 | #ifdef DIAGNOSTIC | |
535 | if (pipe == NULL) { | 535 | if (pipe == NULL) { | |
536 | printf("usbd_abort_pipe: pipe==NULL\n"); | 536 | printf("usbd_abort_pipe: pipe==NULL\n"); | |
537 | return (USBD_NORMAL_COMPLETION); | 537 | return (USBD_NORMAL_COMPLETION); | |
538 | } | 538 | } | |
539 | #endif | 539 | #endif | |
540 | usbd_lock(pipe->lock); | 540 | usbd_lock_pipe(pipe); | |
541 | err = usbd_ar_pipe(pipe); | 541 | err = usbd_ar_pipe(pipe); | |
542 | usbd_unlock(pipe->lock); | 542 | usbd_unlock_pipe(pipe); | |
543 | if (pipe->intrxfer != intrxfer) | 543 | if (pipe->intrxfer != intrxfer) | |
544 | usbd_free_xfer(intrxfer); | 544 | usbd_free_xfer(intrxfer); | |
545 | return (err); | 545 | return (err); | |
546 | } | 546 | } | |
547 | 547 | |||
548 | usbd_status | 548 | usbd_status | |
549 | usbd_clear_endpoint_stall(usbd_pipe_handle pipe) | 549 | usbd_clear_endpoint_stall(usbd_pipe_handle pipe) | |
550 | { | 550 | { | |
551 | usbd_device_handle dev = pipe->device; | 551 | usbd_device_handle dev = pipe->device; | |
552 | usb_device_request_t req; | 552 | usb_device_request_t req; | |
553 | usbd_status err; | 553 | usbd_status err; | |
554 | 554 | |||
555 | DPRINTFN(8, ("usbd_clear_endpoint_stall\n")); | 555 | DPRINTFN(8, ("usbd_clear_endpoint_stall\n")); | |
@@ -717,68 +717,66 @@ usbd_get_interface(usbd_interface_handle | @@ -717,68 +717,66 @@ usbd_get_interface(usbd_interface_handle | |||
717 | USETW(req.wIndex, iface->idesc->bInterfaceNumber); | 717 | USETW(req.wIndex, iface->idesc->bInterfaceNumber); | |
718 | USETW(req.wLength, 1); | 718 | USETW(req.wLength, 1); | |
719 | return (usbd_do_request(iface->device, &req, aiface)); | 719 | return (usbd_do_request(iface->device, &req, aiface)); | |
720 | } | 720 | } | |
721 | 721 | |||
722 | /*** Internal routines ***/ | 722 | /*** Internal routines ***/ | |
723 | 723 | |||
724 | /* Dequeue all pipe operations, called at splusb(). */ | 724 | /* Dequeue all pipe operations, called at splusb(). */ | |
725 | Static usbd_status | 725 | Static usbd_status | |
726 | usbd_ar_pipe(usbd_pipe_handle pipe) | 726 | usbd_ar_pipe(usbd_pipe_handle pipe) | |
727 | { | 727 | { | |
728 | usbd_xfer_handle xfer; | 728 | usbd_xfer_handle xfer; | |
729 | 729 | |||
730 | SPLUSBCHECK; | 730 | KASSERT(pipe->device->bus->lock == NULL || mutex_owned(pipe->device->bus->lock)); | |
731 | KASSERT(pipe->lock == NULL || mutex_owned(pipe->lock)); | |||
732 | 731 | |||
733 | DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe)); | 732 | DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe)); | |
734 | #ifdef USB_DEBUG | 733 | #ifdef USB_DEBUG | |
735 | if (usbdebug > 5) | 734 | if (usbdebug > 5) | |
736 | usbd_dump_queue(pipe); | 735 | usbd_dump_queue(pipe); | |
737 | #endif | 736 | #endif | |
738 | pipe->repeat = 0; | 737 | pipe->repeat = 0; | |
739 | pipe->aborting = 1; | 738 | pipe->aborting = 1; | |
740 | while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) { | 739 | while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) { | |
741 | DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n", | 740 | DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n", | |
742 | pipe, xfer, pipe->methods)); | 741 | pipe, xfer, pipe->methods)); | |
743 | /* Make the HC abort it (and invoke the callback). */ | 742 | /* Make the HC abort it (and invoke the callback). */ | |
744 | if (pipe->lock) | 743 | if (pipe->device->bus->lock) | |
745 | mutex_exit(pipe->lock); | 744 | mutex_exit(pipe->device->bus->lock); | |
746 | pipe->methods->abort(xfer); | 745 | pipe->methods->abort(xfer); | |
747 | if (pipe->lock) | 746 | if (pipe->device->bus->lock) | |
748 | mutex_enter(pipe->lock); | 747 | mutex_enter(pipe->device->bus->lock); | |
749 | /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */ | 748 | /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */ | |
750 | } | 749 | } | |
751 | pipe->aborting = 0; | 750 | pipe->aborting = 0; | |
752 | return (USBD_NORMAL_COMPLETION); | 751 | return (USBD_NORMAL_COMPLETION); | |
753 | } | 752 | } | |
754 | 753 | |||
755 | /* Called at splusb() */ | 754 | /* Called at splusb() */ | |
756 | void | 755 | void | |
757 | usb_transfer_complete(usbd_xfer_handle xfer) | 756 | usb_transfer_complete(usbd_xfer_handle xfer) | |
758 | { | 757 | { | |
759 | usbd_pipe_handle pipe = xfer->pipe; | 758 | usbd_pipe_handle pipe = xfer->pipe; | |
760 | usb_dma_t *dmap = &xfer->dmabuf; | 759 | usb_dma_t *dmap = &xfer->dmabuf; | |
761 | int sync = xfer->flags & USBD_SYNCHRONOUS; | 760 | int sync = xfer->flags & USBD_SYNCHRONOUS; | |
762 | int erred = xfer->status == USBD_CANCELLED || | 761 | int erred = xfer->status == USBD_CANCELLED || | |
763 | xfer->status == USBD_TIMEOUT; | 762 | xfer->status == USBD_TIMEOUT; | |
764 | int repeat, polling; | 763 | int repeat, polling; | |
765 | 764 | |||
766 | SPLUSBCHECK; | |||
767 | 765 | |||
768 | DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d " | 766 | DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d " | |
769 | "actlen=%d\n", pipe, xfer, xfer->status, xfer->actlen)); | 767 | "actlen=%d\n", pipe, xfer, xfer->status, xfer->actlen)); | |
770 | 768 | |||
771 | KASSERT(pipe->lock == NULL || mutex_owned(pipe->lock)); | 769 | KASSERT(pipe->device->bus->lock == NULL || mutex_owned(pipe->device->bus->lock)); | |
772 | 770 | |||
773 | #ifdef DIAGNOSTIC | 771 | #ifdef DIAGNOSTIC | |
774 | if (xfer->busy_free != XFER_ONQU) { | 772 | if (xfer->busy_free != XFER_ONQU) { | |
775 | printf("usb_transfer_complete: xfer=%p not busy 0x%08x\n", | 773 | printf("usb_transfer_complete: xfer=%p not busy 0x%08x\n", | |
776 | xfer, xfer->busy_free); | 774 | xfer, xfer->busy_free); | |
777 | } | 775 | } | |
778 | #endif | 776 | #endif | |
779 | 777 | |||
780 | #ifdef DIAGNOSTIC | 778 | #ifdef DIAGNOSTIC | |
781 | if (pipe == NULL) { | 779 | if (pipe == NULL) { | |
782 | printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer); | 780 | printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer); | |
783 | return; | 781 | return; | |
784 | } | 782 | } | |
@@ -827,68 +825,72 @@ usb_transfer_complete(usbd_xfer_handle x | @@ -827,68 +825,72 @@ usb_transfer_complete(usbd_xfer_handle x | |||
827 | ++pipe->device->bus->stats.uds_requests | 825 | ++pipe->device->bus->stats.uds_requests | |
828 | [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE]; | 826 | [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE]; | |
829 | 827 | |||
830 | xfer->done = 1; | 828 | xfer->done = 1; | |
831 | if (!xfer->status && xfer->actlen < xfer->length && | 829 | if (!xfer->status && xfer->actlen < xfer->length && | |
832 | !(xfer->flags & USBD_SHORT_XFER_OK)) { | 830 | !(xfer->flags & USBD_SHORT_XFER_OK)) { | |
833 | DPRINTFN(-1,("usbd_transfer_cb: short transfer %d<%d\n", | 831 | DPRINTFN(-1,("usbd_transfer_cb: short transfer %d<%d\n", | |
834 | xfer->actlen, xfer->length)); | 832 | xfer->actlen, xfer->length)); | |
835 | xfer->status = USBD_SHORT_XFER; | 833 | xfer->status = USBD_SHORT_XFER; | |
836 | } | 834 | } | |
837 | 835 | |||
838 | if (repeat) { | 836 | if (repeat) { | |
839 | if (xfer->callback) { | 837 | if (xfer->callback) { | |
840 | if (pipe->lock) mutex_exit(pipe->lock); | 838 | if (pipe->device->bus->lock) | |
839 | mutex_exit(pipe->device->bus->lock); | |||
841 | xfer->callback(xfer, xfer->priv, xfer->status); | 840 | xfer->callback(xfer, xfer->priv, xfer->status); | |
842 | if (pipe->lock) mutex_enter(pipe->lock); | 841 | if (pipe->device->bus->lock) | |
842 | mutex_enter(pipe->device->bus->lock); | |||
843 | } | 843 | } | |
844 | pipe->methods->done(xfer); | 844 | pipe->methods->done(xfer); | |
845 | } else { | 845 | } else { | |
846 | pipe->methods->done(xfer); | 846 | pipe->methods->done(xfer); | |
847 | if (xfer->callback) { | 847 | if (xfer->callback) { | |
848 | if (pipe->lock) mutex_exit(pipe->lock); | 848 | if (pipe->device->bus->lock) | |
849 | mutex_exit(pipe->device->bus->lock); | |||
849 | xfer->callback(xfer, xfer->priv, xfer->status); | 850 | xfer->callback(xfer, xfer->priv, xfer->status); | |
850 | if (pipe->lock) mutex_enter(pipe->lock); | 851 | if (pipe->device->bus->lock) | |
852 | mutex_enter(pipe->device->bus->lock); | |||
851 | } | 853 | } | |
852 | } | 854 | } | |
853 | 855 | |||
854 | if (sync && !polling) { | 856 | if (sync && !polling) { | |
855 | if (pipe->lock) { | 857 | if (pipe->device->bus->lock) { | |
856 | cv_broadcast(&xfer->cv); | 858 | cv_broadcast(&xfer->cv); | |
857 | } else { | 859 | } else { | |
858 | wakeup(xfer); | 860 | wakeup(xfer); | |
859 | } | 861 | } | |
860 | } | 862 | } | |
861 | 863 | |||
862 | if (!repeat) { | 864 | if (!repeat) { | |
863 | /* XXX should we stop the queue on all errors? */ | 865 | /* XXX should we stop the queue on all errors? */ | |
864 | if (erred && pipe->iface != NULL) /* not control pipe */ | 866 | if (erred && pipe->iface != NULL) /* not control pipe */ | |
865 | pipe->running = 0; | 867 | pipe->running = 0; | |
866 | else | 868 | else | |
867 | usbd_start_next(pipe); | 869 | usbd_start_next(pipe); | |
868 | } | 870 | } | |
869 | } | 871 | } | |
870 | 872 | |||
871 | usbd_status | 873 | usbd_status | |
872 | usb_insert_transfer(usbd_xfer_handle xfer) | 874 | usb_insert_transfer(usbd_xfer_handle xfer) | |
873 | { | 875 | { | |
874 | usbd_pipe_handle pipe = xfer->pipe; | 876 | usbd_pipe_handle pipe = xfer->pipe; | |
875 | usbd_status err; | 877 | usbd_status err; | |
876 | int s; | 878 | int s; | |
877 | 879 | |||
878 | DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n", | 880 | DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n", | |
879 | pipe, pipe->running, xfer->timeout)); | 881 | pipe, pipe->running, xfer->timeout)); | |
880 | 882 | |||
881 | KASSERT(pipe->lock == NULL || mutex_owned(pipe->lock)); | 883 | KASSERT(pipe->device->bus->lock == NULL || mutex_owned(pipe->device->bus->lock)); | |
882 | 884 | |||
883 | #ifdef DIAGNOSTIC | 885 | #ifdef DIAGNOSTIC | |
884 | if (xfer->busy_free != XFER_BUSY) { | 886 | if (xfer->busy_free != XFER_BUSY) { | |
885 | printf("usb_insert_transfer: xfer=%p not busy 0x%08x\n", | 887 | printf("usb_insert_transfer: xfer=%p not busy 0x%08x\n", | |
886 | xfer, xfer->busy_free); | 888 | xfer, xfer->busy_free); | |
887 | return (USBD_INVAL); | 889 | return (USBD_INVAL); | |
888 | } | 890 | } | |
889 | xfer->busy_free = XFER_ONQU; | 891 | xfer->busy_free = XFER_ONQU; | |
890 | #endif | 892 | #endif | |
891 | s = splusb(); | 893 | s = splusb(); | |
892 | SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next); | 894 | SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next); | |
893 | if (pipe->running) | 895 | if (pipe->running) | |
894 | err = USBD_IN_PROGRESS; | 896 | err = USBD_IN_PROGRESS; | |
@@ -897,52 +899,52 @@ usb_insert_transfer(usbd_xfer_handle xfe | @@ -897,52 +899,52 @@ usb_insert_transfer(usbd_xfer_handle xfe | |||
897 | err = USBD_NORMAL_COMPLETION; | 899 | err = USBD_NORMAL_COMPLETION; | |
898 | } | 900 | } | |
899 | splx(s); | 901 | splx(s); | |
900 | return (err); | 902 | return (err); | |
901 | } | 903 | } | |
902 | 904 | |||
903 | /* Called at splusb() */ | 905 | /* Called at splusb() */ | |
904 | void | 906 | void | |
905 | usbd_start_next(usbd_pipe_handle pipe) | 907 | usbd_start_next(usbd_pipe_handle pipe) | |
906 | { | 908 | { | |
907 | usbd_xfer_handle xfer; | 909 | usbd_xfer_handle xfer; | |
908 | usbd_status err; | 910 | usbd_status err; | |
909 | 911 | |||
910 | SPLUSBCHECK; | 912 | KASSERT(pipe->device->bus->lock == NULL || mutex_owned(pipe->device->bus->lock)); | |
911 | 913 | |||
912 | #ifdef DIAGNOSTIC | 914 | #ifdef DIAGNOSTIC | |
913 | if (pipe == NULL) { | 915 | if (pipe == NULL) { | |
914 | printf("usbd_start_next: pipe == NULL\n"); | 916 | printf("usbd_start_next: pipe == NULL\n"); | |
915 | return; | 917 | return; | |
916 | } | 918 | } | |
917 | if (pipe->methods == NULL || pipe->methods->start == NULL) { | 919 | if (pipe->methods == NULL || pipe->methods->start == NULL) { | |
918 | printf("usbd_start_next: pipe=%p no start method\n", pipe); | 920 | printf("usbd_start_next: pipe=%p no start method\n", pipe); | |
919 | return; | 921 | return; | |
920 | } | 922 | } | |
921 | #endif | 923 | #endif | |
922 | 924 | |||
923 | KASSERT(pipe->lock == NULL || mutex_owned(pipe->lock)); | 925 | KASSERT(pipe->device->bus->lock == NULL || mutex_owned(pipe->device->bus->lock)); | |
924 | 926 | |||
925 | /* Get next request in queue. */ | 927 | /* Get next request in queue. */ | |
926 | xfer = SIMPLEQ_FIRST(&pipe->queue); | 928 | xfer = SIMPLEQ_FIRST(&pipe->queue); | |
927 | DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer)); | 929 | DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer)); | |
928 | if (xfer == NULL) { | 930 | if (xfer == NULL) { | |
929 | pipe->running = 0; | 931 | pipe->running = 0; | |
930 | } else { | 932 | } else { | |
931 | if (pipe->lock) | 933 | if (pipe->device->bus->lock) | |
932 | mutex_exit(pipe->lock); | 934 | mutex_exit(pipe->device->bus->lock); | |
933 | err = pipe->methods->start(xfer); | 935 | err = pipe->methods->start(xfer); | |
934 | if (pipe->lock) | 936 | if (pipe->device->bus->lock) | |
935 | mutex_enter(pipe->lock); | 937 | mutex_enter(pipe->device->bus->lock); | |
936 | if (err != USBD_IN_PROGRESS) { | 938 | if (err != USBD_IN_PROGRESS) { | |
937 | printf("usbd_start_next: error=%d\n", err); | 939 | printf("usbd_start_next: error=%d\n", err); | |
938 | pipe->running = 0; | 940 | pipe->running = 0; | |
939 | /* XXX do what? */ | 941 | /* XXX do what? */ | |
940 | } | 942 | } | |
941 | } | 943 | } | |
942 | } | 944 | } | |
943 | 945 | |||
944 | usbd_status | 946 | usbd_status | |
945 | usbd_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data) | 947 | usbd_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data) | |
946 | { | 948 | { | |
947 | return (usbd_do_request_flags(dev, req, data, 0, 0, | 949 | return (usbd_do_request_flags(dev, req, data, 0, 0, | |
948 | USBD_DEFAULT_TIMEOUT)); | 950 | USBD_DEFAULT_TIMEOUT)); |
--- src/sys/dev/usb/usbdivar.h 2011/12/04 13:23:17 1.93.8.1
+++ src/sys/dev/usb/usbdivar.h 2011/12/08 02:51:08 1.93.8.2
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: usbdivar.h,v 1.93.8.1 2011/12/04 13:23:17 jmcneill Exp $ */ | 1 | /* $NetBSD: usbdivar.h,v 1.93.8.2 2011/12/08 02:51:08 mrg Exp $ */ | |
2 | /* $FreeBSD: src/sys/dev/usb/usbdivar.h,v 1.11 1999/11/17 22:33:51 n_hibma Exp $ */ | 2 | /* $FreeBSD: src/sys/dev/usb/usbdivar.h,v 1.11 1999/11/17 22:33:51 n_hibma Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (c) 1998 The NetBSD Foundation, Inc. | 5 | * Copyright (c) 1998 The NetBSD Foundation, Inc. | |
6 | * All rights reserved. | 6 | * All rights reserved. | |
7 | * | 7 | * | |
8 | * This code is derived from software contributed to The NetBSD Foundation | 8 | * This code is derived from software contributed to The NetBSD Foundation | |
9 | * by Lennart Augustsson (lennart@augustsson.net) at | 9 | * by Lennart Augustsson (lennart@augustsson.net) at | |
10 | * Carlstedt Research & Technology. | 10 | * Carlstedt Research & Technology. | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
@@ -24,26 +24,61 @@ | @@ -24,26 +24,61 @@ | |||
24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
31 | * POSSIBILITY OF SUCH DAMAGE. | 31 | * POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | #include <sys/callout.h> | 34 | #include <sys/callout.h> | |
35 | #include <sys/mutex.h> | 35 | #include <sys/mutex.h> | |
36 | 36 | |||
37 | /* | |||
38 | * Discussion about locking in the USB code: | |||
39 | * | |||
40 | * There are two locks presented by the host controller: the interrupt lock | |||
41 | * and the thread lock. The interrupt lock, either a spin or adaptive mutex, | |||
42 | * manages hardware state and anything else touched in an interrupt context. | |||
43 | * The thread lock has everything else. | |||
44 | * | |||
45 | * List of hardware interface methods, and which locks are held when each | |||
46 | * is called by this module: | |||
47 | * | |||
48 | * BUS METHOD INTR THREAD NOTES | |||
49 | * ----------------------- ------- ------- ------------------------- | |||
50 | * open_pipe - - might want to take thread lock? | |||
51 | * soft_intr - - intr lock is taken sometimes, thread lock taken often, but nothing demanded? | |||
52 | * do_poll - - might want to take thread lock? | |||
53 | * allocm - - | |||
54 | * freem - - | |||
55 | * allocx - - | |||
56 | * freex - - | |||
57 | * get_locks - - Called at attach time | |||
58 | * | |||
59 | * PIPE METHOD INTR THREAD NOTES | |||
60 | * ----------------------- ------- ------- ------------------------- | |||
61 | * transfer - - | |||
62 | * start - - | |||
63 | * abort - - | |||
64 | * close - - | |||
65 | * cleartoggle - - | |||
66 | * done - x | |||
67 | * | |||
68 | * The above semantics are likely to change. | |||
69 | * | |||
70 | */ | |||
71 | ||||
37 | /* From usb_mem.h */ | 72 | /* From usb_mem.h */ | |
38 | struct usb_dma_block; | 73 | struct usb_dma_block; | |
39 | typedef struct { | 74 | typedef struct { | |
40 | struct usb_dma_block *block; | 75 | struct usb_dma_block *block; | |
41 | u_int offs; | 76 | u_int offs; | |
42 | } usb_dma_t; | 77 | } usb_dma_t; | |
43 | 78 | |||
44 | struct usbd_xfer; | 79 | struct usbd_xfer; | |
45 | struct usbd_pipe; | 80 | struct usbd_pipe; | |
46 | 81 | |||
47 | struct usbd_endpoint { | 82 | struct usbd_endpoint { | |
48 | usb_endpoint_descriptor_t *edesc; | 83 | usb_endpoint_descriptor_t *edesc; | |
49 | int refcnt; | 84 | int refcnt; | |
@@ -97,27 +132,29 @@ struct usbd_hub { | @@ -97,27 +132,29 @@ struct usbd_hub { | |||
97 | void *hubsoftc; | 132 | void *hubsoftc; | |
98 | usb_hub_descriptor_t hubdesc; | 133 | usb_hub_descriptor_t hubdesc; | |
99 | struct usbd_port ports[1]; | 134 | struct usbd_port ports[1]; | |
100 | }; | 135 | }; | |
101 | 136 | |||
102 | /*****/ | 137 | /*****/ | |
103 | 138 | |||
104 | struct usbd_bus { | 139 | struct usbd_bus { | |
105 | /* Filled by HC driver */ | 140 | /* Filled by HC driver */ | |
106 | void *hci_private; | 141 | void *hci_private; | |
107 | const struct usbd_bus_methods *methods; | 142 | const struct usbd_bus_methods *methods; | |
108 | u_int32_t pipe_size; /* size of a pipe struct */ | 143 | u_int32_t pipe_size; /* size of a pipe struct */ | |
109 | /* Filled by usb driver */ | 144 | /* Filled by usb driver */ | |
110 | struct usbd_device *root_hub; | 145 | kmutex_t *intr_lock; | |
146 | kmutex_t *lock; | |||
147 | struct usbd_device *root_hub; | |||
111 | usbd_device_handle devices[USB_MAX_DEVICES]; | 148 | usbd_device_handle devices[USB_MAX_DEVICES]; | |
112 | char needs_explore;/* a hub a signalled a change */ | 149 | char needs_explore;/* a hub a signalled a change */ | |
113 | char use_polling; | 150 | char use_polling; | |
114 | device_t usbctl; | 151 | device_t usbctl; | |
115 | struct usb_device_stats stats; | 152 | struct usb_device_stats stats; | |
116 | int intr_context; | 153 | int intr_context; | |
117 | u_int no_intrs; | 154 | u_int no_intrs; | |
118 | int usbrev; /* USB revision */ | 155 | int usbrev; /* USB revision */ | |
119 | #define USBREV_UNKNOWN 0 | 156 | #define USBREV_UNKNOWN 0 | |
120 | #define USBREV_PRE_1_0 1 | 157 | #define USBREV_PRE_1_0 1 | |
121 | #define USBREV_1_0 2 | 158 | #define USBREV_1_0 2 | |
122 | #define USBREV_1_1 3 | 159 | #define USBREV_1_1 3 | |
123 | #define USBREV_2_0 4 | 160 | #define USBREV_2_0 4 | |
@@ -168,29 +205,26 @@ struct usbd_pipe { | @@ -168,29 +205,26 @@ struct usbd_pipe { | |||
168 | struct usbd_interface *iface; | 205 | struct usbd_interface *iface; | |
169 | struct usbd_device *device; | 206 | struct usbd_device *device; | |
170 | struct usbd_endpoint *endpoint; | 207 | struct usbd_endpoint *endpoint; | |
171 | int refcnt; | 208 | int refcnt; | |
172 | char running; | 209 | char running; | |
173 | char aborting; | 210 | char aborting; | |
174 | SIMPLEQ_HEAD(, usbd_xfer) queue; | 211 | SIMPLEQ_HEAD(, usbd_xfer) queue; | |
175 | LIST_ENTRY(usbd_pipe) next; | 212 | LIST_ENTRY(usbd_pipe) next; | |
176 | 213 | |||
177 | usbd_xfer_handle intrxfer; /* used for repeating requests */ | 214 | usbd_xfer_handle intrxfer; /* used for repeating requests */ | |
178 | char repeat; | 215 | char repeat; | |
179 | int interval; | 216 | int interval; | |
180 | 217 | |||
181 | kmutex_t *intr_lock; | |||
182 | kmutex_t *lock; | |||
183 | ||||
184 | /* Filled by HC driver. */ | 218 | /* Filled by HC driver. */ | |
185 | const struct usbd_pipe_methods *methods; | 219 | const struct usbd_pipe_methods *methods; | |
186 | }; | 220 | }; | |
187 | 221 | |||
188 | struct usbd_xfer { | 222 | struct usbd_xfer { | |
189 | struct usbd_pipe *pipe; | 223 | struct usbd_pipe *pipe; | |
190 | void *priv; | 224 | void *priv; | |
191 | void *buffer; | 225 | void *buffer; | |
192 | kcondvar_t cv; | 226 | kcondvar_t cv; | |
193 | u_int32_t length; | 227 | u_int32_t length; | |
194 | u_int32_t actlen; | 228 | u_int32_t actlen; | |
195 | u_int16_t flags; | 229 | u_int16_t flags; | |
196 | u_int32_t timeout; | 230 | u_int32_t timeout; | |
@@ -257,29 +291,28 @@ void usbd_remove_device(usbd_device_han | @@ -257,29 +291,28 @@ void usbd_remove_device(usbd_device_han | |||
257 | int usbd_printBCD(char *, size_t, int); | 291 | int usbd_printBCD(char *, size_t, int); | |
258 | usbd_status usbd_fill_iface_data(usbd_device_handle, int, int); | 292 | usbd_status usbd_fill_iface_data(usbd_device_handle, int, int); | |
259 | void usb_free_device(usbd_device_handle); | 293 | void usb_free_device(usbd_device_handle); | |
260 | 294 | |||
261 | usbd_status usb_insert_transfer(usbd_xfer_handle); | 295 | usbd_status usb_insert_transfer(usbd_xfer_handle); | |
262 | void usb_transfer_complete(usbd_xfer_handle); | 296 | void usb_transfer_complete(usbd_xfer_handle); | |
263 | int usb_disconnect_port(struct usbd_port *, device_t, int); | 297 | int usb_disconnect_port(struct usbd_port *, device_t, int); | |
264 | 298 | |||
265 | /* Routines from usb.c */ | 299 | /* Routines from usb.c */ | |
266 | void usb_needs_explore(usbd_device_handle); | 300 | void usb_needs_explore(usbd_device_handle); | |
267 | void usb_needs_reattach(usbd_device_handle); | 301 | void usb_needs_reattach(usbd_device_handle); | |
268 | void usb_schedsoftintr(struct usbd_bus *); | 302 | void usb_schedsoftintr(struct usbd_bus *); | |
269 | 303 | |||
270 | #define usbd_lock(m) if (m) { s = -1; mutex_enter(m); } else s = splusb() | 304 | #define usbd_lock_pipe(p) do { \ | |
271 | #define usbd_unlock(m) if (m) { s = -1; mutex_exit(m); } else splx(s) | 305 | if ((p)->device->bus->lock) { \ | |
272 | 306 | s = -1; \ | ||
273 | /* | 307 | mutex_enter((p)->device->bus->lock); \ | |
274 | * XXX This check is extremely bogus. Bad Bad Bad. | 308 | } else \ | |
275 | */ | 309 | s = splusb(); \ | |
276 | #if defined(DIAGNOSTIC) && 0 | 310 | } while (0) | |
277 | #define SPLUSBCHECK \ | 311 | ||
278 | do { int _s = splusb(), _su = splusb(); \ | 312 | #define usbd_unlock_pipe(p) do { \ | |
279 | if (!cold && _s != _su) printf("SPLUSBCHECK failed 0x%x!=0x%x, %s:%d\n", \ | 313 | if ((p)->device->bus->lock) { \ | |
280 | _s, _su, __FILE__, __LINE__); \ | 314 | s = -1; \ | |
281 | splx(_s); \ | 315 | mutex_exit((p)->device->bus->lock); \ | |
282 | } while (0) | 316 | } else \ | |
283 | #else | 317 | splx(s); \ | |
284 | #define SPLUSBCHECK | 318 | } while (0) | |
285 | #endif |