Thu Dec 8 02:51:08 2011 UTC ()
- 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 macros


(mrg)
diff -r1.181.6.3 -r1.181.6.4 src/sys/dev/usb/ehci.c
diff -r1.218.6.5 -r1.218.6.6 src/sys/dev/usb/ohci.c
diff -r1.240.6.4 -r1.240.6.5 src/sys/dev/usb/uhci.c
diff -r1.125.6.3 -r1.125.6.4 src/sys/dev/usb/usb.c
diff -r1.180.6.1 -r1.180.6.2 src/sys/dev/usb/usb_subr.c
diff -r1.134.2.1 -r1.134.2.2 src/sys/dev/usb/usbdi.c
diff -r1.93.8.1 -r1.93.8.2 src/sys/dev/usb/usbdivar.h

cvs diff -r1.181.6.3 -r1.181.6.4 src/sys/dev/usb/ehci.c (expand / switch to unified diff)

--- 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
211Static ehci_soft_itd_t *ehci_alloc_itd(ehci_softc_t *sc); 211Static ehci_soft_itd_t *ehci_alloc_itd(ehci_softc_t *sc);
212Static void ehci_free_itd(ehci_softc_t *sc, ehci_soft_itd_t *itd); 212Static void ehci_free_itd(ehci_softc_t *sc, ehci_soft_itd_t *itd);
213Static void ehci_rem_free_itd_chain(ehci_softc_t *sc, 213Static void ehci_rem_free_itd_chain(ehci_softc_t *sc,
214 struct ehci_xfer *exfer); 214 struct ehci_xfer *exfer);
215Static void ehci_abort_isoc_xfer(usbd_xfer_handle xfer, 215Static void ehci_abort_isoc_xfer(usbd_xfer_handle xfer,
216 usbd_status status); 216 usbd_status status);
217 217
218Static usbd_status ehci_device_request(usbd_xfer_handle xfer); 218Static usbd_status ehci_device_request(usbd_xfer_handle xfer);
219 219
220Static usbd_status ehci_device_setintr(ehci_softc_t *, ehci_soft_qh_t *, 220Static usbd_status ehci_device_setintr(ehci_softc_t *, ehci_soft_qh_t *,
221 int ival); 221 int ival);
222 222
223Static void ehci_add_qh(ehci_soft_qh_t *, ehci_soft_qh_t *); 223Static void ehci_add_qh(ehci_softc_t *, ehci_soft_qh_t *,
 224 ehci_soft_qh_t *);
224Static void ehci_rem_qh(ehci_softc_t *, ehci_soft_qh_t *, 225Static void ehci_rem_qh(ehci_softc_t *, ehci_soft_qh_t *,
225 ehci_soft_qh_t *); 226 ehci_soft_qh_t *);
226Static void ehci_set_qh_qtd(ehci_soft_qh_t *, ehci_soft_qtd_t *); 227Static void ehci_set_qh_qtd(ehci_soft_qh_t *, ehci_soft_qtd_t *);
227Static void ehci_sync_hc(ehci_softc_t *); 228Static void ehci_sync_hc(ehci_softc_t *);
228 229
229Static void ehci_close_pipe(usbd_pipe_handle, ehci_soft_qh_t *); 230Static void ehci_close_pipe(usbd_pipe_handle, ehci_soft_qh_t *);
230Static void ehci_abort_xfer(usbd_xfer_handle, usbd_status); 231Static void ehci_abort_xfer(usbd_xfer_handle, usbd_status);
231 232
232#ifdef EHCI_DEBUG 233#ifdef EHCI_DEBUG
233Static void ehci_dump_regs(ehci_softc_t *); 234Static void ehci_dump_regs(ehci_softc_t *);
234void ehci_dump(void); 235void ehci_dump(void);
235Static ehci_softc_t *theehci; 236Static ehci_softc_t *theehci;
236Static void ehci_dump_link(ehci_link_t, int); 237Static 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
263Static const struct usbd_bus_methods ehci_bus_methods = { 264Static 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
274Static const struct usbd_pipe_methods ehci_root_ctrl_methods = { 275Static 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
283Static const struct usbd_pipe_methods ehci_root_intr_methods = { 284Static 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
292Static const struct usbd_pipe_methods ehci_device_ctrl_methods = { 293Static 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
301Static const struct usbd_pipe_methods ehci_device_intr_methods = { 302Static 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
310Static const struct usbd_pipe_methods ehci_device_bulk_methods = { 311Static 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
319Static const struct usbd_pipe_methods ehci_device_isoc_methods = { 320Static 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
328static const uint8_t revbits[EHCI_MAX_POLLRATE] = { 329static const uint8_t revbits[EHCI_MAX_POLLRATE] = {
3290x00,0x40,0x20,0x60,0x10,0x50,0x30,0x70,0x08,0x48,0x28,0x68,0x18,0x58,0x38,0x78, 3300x00,0x40,0x20,0x60,0x10,0x50,0x30,0x70,0x08,0x48,0x28,0x68,0x18,0x58,0x38,0x78,
3300x04,0x44,0x24,0x64,0x14,0x54,0x34,0x74,0x0c,0x4c,0x2c,0x6c,0x1c,0x5c,0x3c,0x7c, 3310x04,0x44,0x24,0x64,0x14,0x54,0x34,0x74,0x0c,0x4c,0x2c,0x6c,0x1c,0x5c,0x3c,0x7c,
3310x02,0x42,0x22,0x62,0x12,0x52,0x32,0x72,0x0a,0x4a,0x2a,0x6a,0x1a,0x5a,0x3a,0x7a, 3320x02,0x42,0x22,0x62,0x12,0x52,0x32,0x72,0x0a,0x4a,0x2a,0x6a,0x1a,0x5a,0x3a,0x7a,
3320x06,0x46,0x26,0x66,0x16,0x56,0x36,0x76,0x0e,0x4e,0x2e,0x6e,0x1e,0x5e,0x3e,0x7e, 3330x06,0x46,0x26,0x66,0x16,0x56,0x36,0x76,0x0e,0x4e,0x2e,0x6e,0x1e,0x5e,0x3e,0x7e,
3330x01,0x41,0x21,0x61,0x11,0x51,0x31,0x71,0x09,0x49,0x29,0x69,0x19,0x59,0x39,0x79, 3340x01,0x41,0x21,0x61,0x11,0x51,0x31,0x71,0x09,0x49,0x29,0x69,0x19,0x59,0x39,0x79,
3340x05,0x45,0x25,0x65,0x15,0x55,0x35,0x75,0x0d,0x4d,0x2d,0x6d,0x1d,0x5d,0x3d,0x7d, 3350x05,0x45,0x25,0x65,0x15,0x55,0x35,0x75,0x0d,0x4d,0x2d,0x6d,0x1d,0x5d,0x3d,0x7d,
3350x03,0x43,0x23,0x63,0x13,0x53,0x33,0x73,0x0b,0x4b,0x2b,0x6b,0x1b,0x5b,0x3b,0x7b, 3360x03,0x43,0x23,0x63,0x13,0x53,0x33,0x73,0x0b,0x4b,0x2b,0x6b,0x1b,0x5b,0x3b,0x7b,
3360x07,0x47,0x27,0x67,0x17,0x57,0x37,0x77,0x0f,0x4f,0x2f,0x6f,0x1f,0x5f,0x3f,0x7f, 3370x07,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 */
1817Static void 1818Static void
1818ehci_add_qh(ehci_soft_qh_t *sqh, ehci_soft_qh_t *head) 1819ehci_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 */
1844Static void 1846Static void
1845ehci_rem_qh(ehci_softc_t *sc, ehci_soft_qh_t *sqh, ehci_soft_qh_t *head) 1847ehci_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
3719Static usbd_status 3722Static usbd_status
3720ehci_device_intr_transfer(usbd_xfer_handle xfer) 3723ehci_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);

cvs diff -r1.218.6.5 -r1.218.6.6 src/sys/dev/usb/ohci.c (expand / switch to unified diff)

--- 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
112Static usbd_status ohci_open(usbd_pipe_handle); 112Static usbd_status ohci_open(usbd_pipe_handle);
113Static void ohci_poll(struct usbd_bus *); 113Static void ohci_poll(struct usbd_bus *);
114Static void ohci_softintr(void *); 114Static void ohci_softintr(void *);
115Static void ohci_waitintr(ohci_softc_t *, usbd_xfer_handle); 115Static void ohci_waitintr(ohci_softc_t *, usbd_xfer_handle);
116Static void ohci_rhsc(ohci_softc_t *, usbd_xfer_handle); 116Static void ohci_rhsc(ohci_softc_t *, usbd_xfer_handle);
117Static void ohci_rhsc_softint(void *arg); 117Static void ohci_rhsc_softint(void *arg);
118 118
119Static usbd_status ohci_device_request(usbd_xfer_handle xfer); 119Static usbd_status ohci_device_request(usbd_xfer_handle xfer);
120Static void ohci_add_ed(ohci_softc_t *, ohci_soft_ed_t *, 120Static void ohci_add_ed(ohci_softc_t *, ohci_soft_ed_t *,
121 ohci_soft_ed_t *); 121 ohci_soft_ed_t *);
122 122
123Static void ohci_rem_ed(ohci_soft_ed_t *, ohci_soft_ed_t *); 123Static void ohci_rem_ed(ohci_softc_t *, ohci_soft_ed_t *,
 124 ohci_soft_ed_t *);
124Static void ohci_hash_add_td(ohci_softc_t *, ohci_soft_td_t *); 125Static void ohci_hash_add_td(ohci_softc_t *, ohci_soft_td_t *);
125Static void ohci_hash_rem_td(ohci_softc_t *, ohci_soft_td_t *); 126Static void ohci_hash_rem_td(ohci_softc_t *, ohci_soft_td_t *);
126Static ohci_soft_td_t *ohci_hash_find_td(ohci_softc_t *, ohci_physaddr_t); 127Static ohci_soft_td_t *ohci_hash_find_td(ohci_softc_t *, ohci_physaddr_t);
127Static void ohci_hash_add_itd(ohci_softc_t *, ohci_soft_itd_t *); 128Static void ohci_hash_add_itd(ohci_softc_t *, ohci_soft_itd_t *);
128Static void ohci_hash_rem_itd(ohci_softc_t *, ohci_soft_itd_t *); 129Static void ohci_hash_rem_itd(ohci_softc_t *, ohci_soft_itd_t *);
129Static ohci_soft_itd_t *ohci_hash_find_itd(ohci_softc_t *, ohci_physaddr_t); 130Static ohci_soft_itd_t *ohci_hash_find_itd(ohci_softc_t *, ohci_physaddr_t);
130 131
131Static usbd_status ohci_setup_isoc(usbd_pipe_handle pipe); 132Static usbd_status ohci_setup_isoc(usbd_pipe_handle pipe);
132Static void ohci_device_isoc_enter(usbd_xfer_handle); 133Static void ohci_device_isoc_enter(usbd_xfer_handle);
133 134
134Static usbd_status ohci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t); 135Static usbd_status ohci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t);
135Static void ohci_freem(struct usbd_bus *, usb_dma_t *); 136Static 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
273Static const struct usbd_bus_methods ohci_bus_methods = { 274Static 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
284Static const struct usbd_pipe_methods ohci_root_ctrl_methods = { 285Static 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
293Static const struct usbd_pipe_methods ohci_root_intr_methods = { 294Static 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
302Static const struct usbd_pipe_methods ohci_device_ctrl_methods = { 303Static 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
311Static const struct usbd_pipe_methods ohci_device_intr_methods = { 312Static 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
320Static const struct usbd_pipe_methods ohci_device_bulk_methods = { 321Static 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
329Static const struct usbd_pipe_methods ohci_device_isoc_methods = { 330Static 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
338int 339int
339ohci_activate(device_t self, enum devact act) 340ohci_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 */
1872void 1873Static void
1873ohci_add_ed(ohci_softc_t *sc, ohci_soft_ed_t *sed, ohci_soft_ed_t *head) 1874ohci_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 */
1896void 1898Static void
1897ohci_rem_ed(ohci_soft_ed_t *sed, ohci_soft_ed_t *head) 1899ohci_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() */
1930void 1932void
1931ohci_hash_add_td(ohci_softc_t *sc, ohci_soft_td_t *std) 1933ohci_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() */
1941void 1943void
1942ohci_hash_rem_td(ohci_softc_t *sc, ohci_soft_td_t *std) 1944ohci_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
1949ohci_soft_td_t * 1952ohci_soft_td_t *
1950ohci_hash_find_td(ohci_softc_t *sc, ohci_physaddr_t a) 1953ohci_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() */
1964void 1967void
1965ohci_hash_add_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) 1968ohci_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() */
1978void 1981void
1979ohci_hash_rem_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) 1982ohci_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
1989ohci_soft_itd_t * 1992ohci_soft_itd_t *
1990ohci_hash_find_itd(ohci_softc_t *sc, ohci_physaddr_t a) 1993ohci_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

cvs diff -r1.240.6.4 -r1.240.6.5 src/sys/dev/usb/uhci.c (expand / switch to unified diff)

--- 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
286const struct usbd_bus_methods uhci_bus_methods = { 286const 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
297const struct usbd_pipe_methods uhci_root_ctrl_methods = { 297const 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
306const struct usbd_pipe_methods uhci_root_intr_methods = { 306const 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
315const struct usbd_pipe_methods uhci_device_ctrl_methods = { 315const 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
324const struct usbd_pipe_methods uhci_device_intr_methods = { 324const 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
333const struct usbd_pipe_methods uhci_device_bulk_methods = { 333const 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
342const struct usbd_pipe_methods uhci_device_isoc_methods = { 342const 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
360static inline uhci_soft_qh_t * 360static inline uhci_soft_qh_t *
361uhci_find_prev_qh(uhci_soft_qh_t *pqh, uhci_soft_qh_t *sqh) 361uhci_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(). */
1095void 1095void
1096uhci_add_hs_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) 1096uhci_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(). */
1122void 1122void
1123uhci_remove_hs_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) 1123uhci_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(). */
1172void 1172void
1173uhci_add_ls_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) 1173uhci_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(). */
1195void 1195void
1196uhci_remove_ls_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) 1196uhci_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(). */
1229void 1229void
1230uhci_add_bulk(uhci_softc_t *sc, uhci_soft_qh_t *sqh) 1230uhci_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(). */
1253void 1253void
1254uhci_remove_bulk(uhci_softc_t *sc, uhci_soft_qh_t *sqh) 1254uhci_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);

cvs diff -r1.125.6.3 -r1.125.6.4 src/sys/dev/usb/usb.c (expand / switch to unified diff)

--- 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;

cvs diff -r1.180.6.1 -r1.180.6.2 src/sys/dev/usb/usb_subr.c (expand / switch to unified diff)

--- 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. */
764void 759void
765usbd_kill_pipe(usbd_pipe_handle pipe) 760usbd_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}

cvs diff -r1.134.2.1 -r1.134.2.2 src/sys/dev/usb/usbdi.c (expand / switch to unified diff)

--- 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. */
328usbd_status 328usbd_status
329usbd_sync_transfer(usbd_xfer_handle xfer) 329usbd_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
335void * 335void *
336usbd_alloc_buffer(usbd_xfer_handle xfer, u_int32_t size) 336usbd_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
527usbd_status 527usbd_status
528usbd_abort_pipe(usbd_pipe_handle pipe) 528usbd_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
548usbd_status 548usbd_status
549usbd_clear_endpoint_stall(usbd_pipe_handle pipe) 549usbd_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(). */
725Static usbd_status 725Static usbd_status
726usbd_ar_pipe(usbd_pipe_handle pipe) 726usbd_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() */
756void 755void
757usb_transfer_complete(usbd_xfer_handle xfer) 756usb_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
871usbd_status 873usbd_status
872usb_insert_transfer(usbd_xfer_handle xfer) 874usb_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() */
904void 906void
905usbd_start_next(usbd_pipe_handle pipe) 907usbd_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
944usbd_status 946usbd_status
945usbd_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data) 947usbd_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));

cvs diff -r1.93.8.1 -r1.93.8.2 src/sys/dev/usb/usbdivar.h (expand / switch to unified diff)

--- 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 */
38struct usb_dma_block; 73struct usb_dma_block;
39typedef struct { 74typedef 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
44struct usbd_xfer; 79struct usbd_xfer;
45struct usbd_pipe; 80struct usbd_pipe;
46 81
47struct usbd_endpoint { 82struct 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
104struct usbd_bus { 139struct 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
188struct usbd_xfer { 222struct 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
257int usbd_printBCD(char *, size_t, int); 291int usbd_printBCD(char *, size_t, int);
258usbd_status usbd_fill_iface_data(usbd_device_handle, int, int); 292usbd_status usbd_fill_iface_data(usbd_device_handle, int, int);
259void usb_free_device(usbd_device_handle); 293void usb_free_device(usbd_device_handle);
260 294
261usbd_status usb_insert_transfer(usbd_xfer_handle); 295usbd_status usb_insert_transfer(usbd_xfer_handle);
262void usb_transfer_complete(usbd_xfer_handle); 296void usb_transfer_complete(usbd_xfer_handle);
263int usb_disconnect_port(struct usbd_port *, device_t, int); 297int usb_disconnect_port(struct usbd_port *, device_t, int);
264 298
265/* Routines from usb.c */ 299/* Routines from usb.c */
266void usb_needs_explore(usbd_device_handle); 300void usb_needs_explore(usbd_device_handle);
267void usb_needs_reattach(usbd_device_handle); 301void usb_needs_reattach(usbd_device_handle);
268void usb_schedsoftintr(struct usbd_bus *); 302void 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