| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ehci.c,v 1.315.2.3 2024/02/06 12:18:55 martin Exp $ */ | | 1 | /* $NetBSD: ehci.c,v 1.315.2.4 2024/02/17 11:27:30 martin Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2004-2012,2016,2020 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2004-2012,2016,2020 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), Jared D. McNeill | | 9 | * Jeremy Morse (jeremy.morse@gmail.com), Jared D. McNeill |
10 | * (jmcneill@invisible.ca). Matthew R. Green (mrg@eterna.com.au), and | | 10 | * (jmcneill@invisible.ca). Matthew R. Green (mrg@eterna.com.au), and |
11 | * Nick Hudson . | | 11 | * Nick Hudson . |
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 |
| @@ -44,27 +44,27 @@ | | | @@ -44,27 +44,27 @@ |
44 | | | 44 | |
45 | /* | | 45 | /* |
46 | * TODO: | | 46 | * TODO: |
47 | * 1) hold off explorations by companion controllers until ehci has started. | | 47 | * 1) hold off explorations by companion controllers until ehci has started. |
48 | * | | 48 | * |
49 | * 2) The hub driver needs to handle and schedule the transaction translator, | | 49 | * 2) The hub driver needs to handle and schedule the transaction translator, |
50 | * to assign place in frame where different devices get to go. See chapter | | 50 | * to assign place in frame where different devices get to go. See chapter |
51 | * on hubs in USB 2.0 for details. | | 51 | * on hubs in USB 2.0 for details. |
52 | * | | 52 | * |
53 | * 3) Command failures are not recovered correctly. | | 53 | * 3) Command failures are not recovered correctly. |
54 | */ | | 54 | */ |
55 | | | 55 | |
56 | #include <sys/cdefs.h> | | 56 | #include <sys/cdefs.h> |
57 | __KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.315.2.3 2024/02/06 12:18:55 martin Exp $"); | | 57 | __KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.315.2.4 2024/02/17 11:27:30 martin Exp $"); |
58 | | | 58 | |
59 | #include "ohci.h" | | 59 | #include "ohci.h" |
60 | #include "uhci.h" | | 60 | #include "uhci.h" |
61 | | | 61 | |
62 | #ifdef _KERNEL_OPT | | 62 | #ifdef _KERNEL_OPT |
63 | #include "opt_usb.h" | | 63 | #include "opt_usb.h" |
64 | #endif | | 64 | #endif |
65 | | | 65 | |
66 | #include <sys/param.h> | | 66 | #include <sys/param.h> |
67 | | | 67 | |
68 | #include <sys/bus.h> | | 68 | #include <sys/bus.h> |
69 | #include <sys/cpu.h> | | 69 | #include <sys/cpu.h> |
70 | #include <sys/device.h> | | 70 | #include <sys/device.h> |
| @@ -279,26 +279,27 @@ Static void ehci_sync_hc(ehci_softc_t * | | | @@ -279,26 +279,27 @@ Static void ehci_sync_hc(ehci_softc_t * |
279 | | | 279 | |
280 | Static void ehci_close_pipe(struct usbd_pipe *, ehci_soft_qh_t *); | | 280 | Static void ehci_close_pipe(struct usbd_pipe *, ehci_soft_qh_t *); |
281 | Static void ehci_abortx(struct usbd_xfer *); | | 281 | Static void ehci_abortx(struct usbd_xfer *); |
282 | | | 282 | |
283 | #ifdef EHCI_DEBUG | | 283 | #ifdef EHCI_DEBUG |
284 | Static ehci_softc_t *theehci; | | 284 | Static ehci_softc_t *theehci; |
285 | void ehci_dump(void); | | 285 | void ehci_dump(void); |
286 | #endif | | 286 | #endif |
287 | | | 287 | |
288 | #ifdef EHCI_DEBUG | | 288 | #ifdef EHCI_DEBUG |
289 | Static void ehci_dump_regs(ehci_softc_t *); | | 289 | Static void ehci_dump_regs(ehci_softc_t *); |
290 | Static void ehci_dump_sqtds(ehci_soft_qtd_t *); | | 290 | Static void ehci_dump_sqtds(ehci_soft_qtd_t *); |
291 | Static void ehci_dump_sqtd(ehci_soft_qtd_t *); | | 291 | Static void ehci_dump_sqtd(ehci_soft_qtd_t *); |
| | | 292 | Static void ehci_dump_qh_qtd(struct ehci_qh_qtd_t *); |
292 | Static void ehci_dump_qtd(ehci_qtd_t *); | | 293 | Static void ehci_dump_qtd(ehci_qtd_t *); |
293 | Static void ehci_dump_sqh(ehci_soft_qh_t *); | | 294 | Static void ehci_dump_sqh(ehci_soft_qh_t *); |
294 | Static void ehci_dump_sitd(struct ehci_soft_itd *); | | 295 | Static void ehci_dump_sitd(struct ehci_soft_itd *); |
295 | Static void ehci_dump_itds(ehci_soft_itd_t *); | | 296 | Static void ehci_dump_itds(ehci_soft_itd_t *); |
296 | Static void ehci_dump_itd(struct ehci_soft_itd *); | | 297 | Static void ehci_dump_itd(struct ehci_soft_itd *); |
297 | Static void ehci_dump_exfer(struct ehci_xfer *); | | 298 | Static void ehci_dump_exfer(struct ehci_xfer *); |
298 | #endif | | 299 | #endif |
299 | | | 300 | |
300 | #define EHCI_NULL htole32(EHCI_LINK_TERMINATE) | | 301 | #define EHCI_NULL htole32(EHCI_LINK_TERMINATE) |
301 | | | 302 | |
302 | static inline void | | 303 | static inline void |
303 | ehci_add_intr_list(ehci_softc_t *sc, struct ehci_xfer *ex) | | 304 | ehci_add_intr_list(ehci_softc_t *sc, struct ehci_xfer *ex) |
304 | { | | 305 | { |
| @@ -1740,26 +1741,44 @@ ehci_dump_sqtd(ehci_soft_qtd_t *sqtd) | | | @@ -1740,26 +1741,44 @@ ehci_dump_sqtd(ehci_soft_qtd_t *sqtd) |
1740 | | | 1741 | |
1741 | usb_syncmem(&sqtd->dma, sqtd->offs, | | 1742 | usb_syncmem(&sqtd->dma, sqtd->offs, |
1742 | sizeof(sqtd->qtd), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | | 1743 | sizeof(sqtd->qtd), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); |
1743 | | | 1744 | |
1744 | DPRINTFN(10, "QTD(%#jx) at 0x%08jx:", (uintptr_t)sqtd, sqtd->physaddr, | | 1745 | DPRINTFN(10, "QTD(%#jx) at 0x%08jx:", (uintptr_t)sqtd, sqtd->physaddr, |
1745 | 0, 0); | | 1746 | 0, 0); |
1746 | ehci_dump_qtd(&sqtd->qtd); | | 1747 | ehci_dump_qtd(&sqtd->qtd); |
1747 | | | 1748 | |
1748 | usb_syncmem(&sqtd->dma, sqtd->offs, | | 1749 | usb_syncmem(&sqtd->dma, sqtd->offs, |
1749 | sizeof(sqtd->qtd), BUS_DMASYNC_PREREAD); | | 1750 | sizeof(sqtd->qtd), BUS_DMASYNC_PREREAD); |
1750 | } | | 1751 | } |
1751 | | | 1752 | |
1752 | Static void | | 1753 | Static void |
| | | 1754 | ehci_dump_qh_qtd(struct ehci_qh_qtd_t *qh_qtd) |
| | | 1755 | { |
| | | 1756 | ehci_qtd_t qtd = { |
| | | 1757 | .qtd_next = qh_qtd->qtd_next, |
| | | 1758 | .qtd_altnext = qh_qtd->qtd_altnext, |
| | | 1759 | .qtd_status = qh_qtd->qtd_status, |
| | | 1760 | }; |
| | | 1761 | |
| | | 1762 | /* Manually memcpy(), because of volatile. */ |
| | | 1763 | for (unsigned i = 0; i < EHCI_QTD_NBUFFERS; i++) { |
| | | 1764 | qtd.qtd_buffer[i] = qh_qtd->qtd_buffer[i]; |
| | | 1765 | qtd.qtd_buffer_hi[i] = qh_qtd->qtd_buffer_hi[i]; |
| | | 1766 | } |
| | | 1767 | |
| | | 1768 | ehci_dump_qtd(&qtd); |
| | | 1769 | } |
| | | 1770 | |
| | | 1771 | Static void |
1753 | ehci_dump_qtd(ehci_qtd_t *qtd) | | 1772 | ehci_dump_qtd(ehci_qtd_t *qtd) |
1754 | { | | 1773 | { |
1755 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | | 1774 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); |
1756 | uint32_t s = le32toh(qtd->qtd_status); | | 1775 | uint32_t s = le32toh(qtd->qtd_status); |
1757 | | | 1776 | |
1758 | DPRINTFN(10, | | 1777 | DPRINTFN(10, |
1759 | " next = 0x%08jx altnext = 0x%08jx status = 0x%08jx", | | 1778 | " next = 0x%08jx altnext = 0x%08jx status = 0x%08jx", |
1760 | qtd->qtd_next, qtd->qtd_altnext, s, 0); | | 1779 | qtd->qtd_next, qtd->qtd_altnext, s, 0); |
1761 | DPRINTFN(10, | | 1780 | DPRINTFN(10, |
1762 | " toggle = %jd ioc = %jd bytes = %#jx c_page = %#jx", | | 1781 | " toggle = %jd ioc = %jd bytes = %#jx c_page = %#jx", |
1763 | EHCI_QTD_GET_TOGGLE(s), EHCI_QTD_GET_IOC(s), | | 1782 | EHCI_QTD_GET_TOGGLE(s), EHCI_QTD_GET_IOC(s), |
1764 | EHCI_QTD_GET_BYTES(s), EHCI_QTD_GET_C_PAGE(s)); | | 1783 | EHCI_QTD_GET_BYTES(s), EHCI_QTD_GET_C_PAGE(s)); |
1765 | DPRINTFN(10, | | 1784 | DPRINTFN(10, |
| @@ -1815,27 +1834,27 @@ ehci_dump_sqh(ehci_soft_qh_t *sqh) | | | @@ -1815,27 +1834,27 @@ ehci_dump_sqh(ehci_soft_qh_t *sqh) |
1815 | EHCI_QH_GET_MPL(endp), EHCI_QH_GET_MPL(endp)); | | 1834 | EHCI_QH_GET_MPL(endp), EHCI_QH_GET_MPL(endp)); |
1816 | | | 1835 | |
1817 | endphub = le32toh(qh->qh_endphub); | | 1836 | endphub = le32toh(qh->qh_endphub); |
1818 | DPRINTFN(10, " endphub = %#jx", endphub, 0, 0, 0); | | 1837 | DPRINTFN(10, " endphub = %#jx", endphub, 0, 0, 0); |
1819 | DPRINTFN(10, " smask = 0x%02jx cmask = 0x%02jx one %jx", | | 1838 | DPRINTFN(10, " smask = 0x%02jx cmask = 0x%02jx one %jx", |
1820 | EHCI_QH_GET_SMASK(endphub), EHCI_QH_GET_CMASK(endphub), 1, 0); | | 1839 | EHCI_QH_GET_SMASK(endphub), EHCI_QH_GET_CMASK(endphub), 1, 0); |
1821 | DPRINTFN(10, " huba = 0x%02jx port = %jd mult = %jd", | | 1840 | DPRINTFN(10, " huba = 0x%02jx port = %jd mult = %jd", |
1822 | EHCI_QH_GET_HUBA(endphub), EHCI_QH_GET_PORT(endphub), | | 1841 | EHCI_QH_GET_HUBA(endphub), EHCI_QH_GET_PORT(endphub), |
1823 | EHCI_QH_GET_MULT(endphub), 0); | | 1842 | EHCI_QH_GET_MULT(endphub), 0); |
1824 | | | 1843 | |
1825 | link = le32toh(qh->qh_curqtd); | | 1844 | link = le32toh(qh->qh_curqtd); |
1826 | ehci_dump_link(link, false); | | 1845 | ehci_dump_link(link, false); |
1827 | DPRINTFN(10, "Overlay qTD:", 0, 0, 0, 0); | | 1846 | DPRINTFN(10, "Overlay qTD:", 0, 0, 0, 0); |
1828 | ehci_dump_qtd(&qh->qh_qtd); | | 1847 | ehci_dump_qh_qtd(&qh->qh_qtd); |
1829 | | | 1848 | |
1830 | usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh), | | 1849 | usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh), |
1831 | BUS_DMASYNC_PREREAD); | | 1850 | BUS_DMASYNC_PREREAD); |
1832 | } | | 1851 | } |
1833 | | | 1852 | |
1834 | Static void | | 1853 | Static void |
1835 | ehci_dump_itds(ehci_soft_itd_t *itd) | | 1854 | ehci_dump_itds(ehci_soft_itd_t *itd) |
1836 | { | | 1855 | { |
1837 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | | 1856 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); |
1838 | int i; | | 1857 | int i; |
1839 | uint32_t stop = 0; | | 1858 | uint32_t stop = 0; |
1840 | | | 1859 | |
1841 | for (i = 0; itd && i < 20 && !stop; itd = itd->xfer_next, i++) { | | 1860 | for (i = 0; itd && i < 20 && !stop; itd = itd->xfer_next, i++) { |