| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ehci.c,v 1.234.2.35 2015/03/02 21:52:02 skrll Exp $ */ | | 1 | /* $NetBSD: ehci.c,v 1.234.2.36 2015/03/02 22:16:38 skrll Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2004-2012 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2004-2012 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) and Matthew R. Green (mrg@eterna.com.au). | | 10 | * (jmcneill@invisible.ca) and Matthew R. Green (mrg@eterna.com.au). |
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.234.2.35 2015/03/02 21:52:02 skrll Exp $"); | | 56 | __KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.234.2.36 2015/03/02 22:16:38 skrll 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 | | | 63 | |
64 | #include <sys/bus.h> | | 64 | #include <sys/bus.h> |
65 | #include <sys/cpu.h> | | 65 | #include <sys/cpu.h> |
66 | #include <sys/device.h> | | 66 | #include <sys/device.h> |
67 | #include <sys/kernel.h> | | 67 | #include <sys/kernel.h> |
68 | #include <sys/kmem.h> | | 68 | #include <sys/kmem.h> |
69 | #include <sys/mutex.h> | | 69 | #include <sys/mutex.h> |
| @@ -2757,27 +2757,27 @@ ehci_free_sqtd(ehci_softc_t *sc, ehci_so | | | @@ -2757,27 +2757,27 @@ ehci_free_sqtd(ehci_softc_t *sc, ehci_so |
2757 | } | | 2757 | } |
2758 | | | 2758 | |
2759 | Static usbd_status | | 2759 | Static usbd_status |
2760 | ehci_alloc_sqtd_chain(struct ehci_pipe *epipe, ehci_softc_t *sc, | | 2760 | ehci_alloc_sqtd_chain(struct ehci_pipe *epipe, ehci_softc_t *sc, |
2761 | int alen, int rd, usbd_xfer_handle xfer, | | 2761 | int alen, int rd, usbd_xfer_handle xfer, |
2762 | ehci_soft_qtd_t **sp, ehci_soft_qtd_t **ep) | | 2762 | ehci_soft_qtd_t **sp, ehci_soft_qtd_t **ep) |
2763 | { | | 2763 | { |
2764 | ehci_soft_qtd_t *next, *cur; | | 2764 | ehci_soft_qtd_t *next, *cur; |
2765 | ehci_physaddr_t nextphys; | | 2765 | ehci_physaddr_t nextphys; |
2766 | uint32_t qtdstatus; | | 2766 | uint32_t qtdstatus; |
2767 | int len, curlen, mps; | | 2767 | int len, curlen, mps; |
2768 | int i, tog; | | 2768 | int i, tog; |
2769 | int pages, pageoffs; | | 2769 | int pages, pageoffs; |
2770 | bus_size_t curoffs; | | 2770 | size_t curoffs; |
2771 | vaddr_t va, va_offs; | | 2771 | vaddr_t va, va_offs; |
2772 | usb_dma_t *dma = &xfer->ux_dmabuf; | | 2772 | usb_dma_t *dma = &xfer->ux_dmabuf; |
2773 | uint16_t flags = xfer->ux_flags; | | 2773 | uint16_t flags = xfer->ux_flags; |
2774 | paddr_t a; | | 2774 | paddr_t a; |
2775 | | | 2775 | |
2776 | USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); | | 2776 | USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); |
2777 | | | 2777 | |
2778 | USBHIST_LOG(ehcidebug, "start len=%d", alen, 0, 0, 0); | | 2778 | USBHIST_LOG(ehcidebug, "start len=%d", alen, 0, 0, 0); |
2779 | | | 2779 | |
2780 | len = alen; | | 2780 | len = alen; |
2781 | qtdstatus = EHCI_QTD_ACTIVE | | | 2781 | qtdstatus = EHCI_QTD_ACTIVE | |
2782 | EHCI_QTD_SET_PID(rd ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT) | | | 2782 | EHCI_QTD_SET_PID(rd ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT) | |
2783 | EHCI_QTD_SET_CERR(3) | | 2783 | EHCI_QTD_SET_CERR(3) |
| @@ -2804,27 +2804,27 @@ ehci_alloc_sqtd_chain(struct ehci_pipe * | | | @@ -2804,27 +2804,27 @@ ehci_alloc_sqtd_chain(struct ehci_pipe * |
2804 | /* we can handle it in this QTD */ | | 2804 | /* we can handle it in this QTD */ |
2805 | curlen = len - curoffs; | | 2805 | curlen = len - curoffs; |
2806 | } else { | | 2806 | } else { |
2807 | /* must use multiple TDs, fill as much as possible. */ | | 2807 | /* must use multiple TDs, fill as much as possible. */ |
2808 | curlen = EHCI_QTD_MAXTRANSFER - va_offs; | | 2808 | curlen = EHCI_QTD_MAXTRANSFER - va_offs; |
2809 | | | 2809 | |
2810 | /* the length must be a multiple of the max size */ | | 2810 | /* the length must be a multiple of the max size */ |
2811 | curlen -= curlen % mps; | | 2811 | curlen -= curlen % mps; |
2812 | USBHIST_LOG(ehcidebug, "multiple QTDs, " | | 2812 | USBHIST_LOG(ehcidebug, "multiple QTDs, " |
2813 | "curlen=%d", curlen, 0, 0, 0); | | 2813 | "curlen=%d", curlen, 0, 0, 0); |
2814 | KASSERT(curlen != 0); | | 2814 | KASSERT(curlen != 0); |
2815 | } | | 2815 | } |
2816 | USBHIST_LOG(ehcidebug, "len=%d curlen=%d curoffs=%zu", | | 2816 | USBHIST_LOG(ehcidebug, "len=%d curlen=%d curoffs=%zu", |
2817 | len, curlen, (size_t)curoffs, 0); | | 2817 | len, curlen, curoffs, 0); |
2818 | | | 2818 | |
2819 | /* | | 2819 | /* |
2820 | * Allocate another transfer if there's more data left, | | 2820 | * Allocate another transfer if there's more data left, |
2821 | * or if force last short transfer flag is set and we're | | 2821 | * or if force last short transfer flag is set and we're |
2822 | * allocating a multiple of the max packet size. | | 2822 | * allocating a multiple of the max packet size. |
2823 | */ | | 2823 | */ |
2824 | | | 2824 | |
2825 | if (curoffs + curlen != len || | | 2825 | if (curoffs + curlen != len || |
2826 | ((curlen % mps) == 0 && !rd && curlen != 0 && | | 2826 | ((curlen % mps) == 0 && !rd && curlen != 0 && |
2827 | (flags & USBD_FORCE_SHORT_XFER))) { | | 2827 | (flags & USBD_FORCE_SHORT_XFER))) { |
2828 | next = ehci_alloc_sqtd(sc); | | 2828 | next = ehci_alloc_sqtd(sc); |
2829 | if (next == NULL) | | 2829 | if (next == NULL) |
2830 | goto nomem; | | 2830 | goto nomem; |
| @@ -2847,27 +2847,27 @@ ehci_alloc_sqtd_chain(struct ehci_pipe * | | | @@ -2847,27 +2847,27 @@ ehci_alloc_sqtd_chain(struct ehci_pipe * |
2847 | | | 2847 | |
2848 | /* First buffer pointer requires a page offset to start at */ | | 2848 | /* First buffer pointer requires a page offset to start at */ |
2849 | va = (vaddr_t)KERNADDR(dma, curoffs); | | 2849 | va = (vaddr_t)KERNADDR(dma, curoffs); |
2850 | cur->qtd.qtd_buffer[0] |= htole32(EHCI_PAGE_OFFSET(va)); | | 2850 | cur->qtd.qtd_buffer[0] |= htole32(EHCI_PAGE_OFFSET(va)); |
2851 | | | 2851 | |
2852 | cur->nextqtd = next; | | 2852 | cur->nextqtd = next; |
2853 | cur->qtd.qtd_next = cur->qtd.qtd_altnext = nextphys; | | 2853 | cur->qtd.qtd_next = cur->qtd.qtd_altnext = nextphys; |
2854 | cur->qtd.qtd_status = | | 2854 | cur->qtd.qtd_status = |
2855 | htole32(qtdstatus | EHCI_QTD_SET_BYTES(curlen)); | | 2855 | htole32(qtdstatus | EHCI_QTD_SET_BYTES(curlen)); |
2856 | cur->xfer = xfer; | | 2856 | cur->xfer = xfer; |
2857 | cur->len = curlen; | | 2857 | cur->len = curlen; |
2858 | | | 2858 | |
2859 | USBHIST_LOG(ehcidebug, "cbp=0x%08zx end=0x%08zx", | | 2859 | USBHIST_LOG(ehcidebug, "cbp=0x%08zx end=0x%08zx", |
2860 | (size_t)curoffs, (size_t)(curoffs + curlen), 0, 0); | | 2860 | curoffs, curoffs + curlen, 0, 0); |
2861 | | | 2861 | |
2862 | /* | | 2862 | /* |
2863 | * adjust the toggle based on the number of packets in this | | 2863 | * adjust the toggle based on the number of packets in this |
2864 | * qtd | | 2864 | * qtd |
2865 | */ | | 2865 | */ |
2866 | if (((curlen + mps - 1) / mps) & 1) { | | 2866 | if (((curlen + mps - 1) / mps) & 1) { |
2867 | tog ^= 1; | | 2867 | tog ^= 1; |
2868 | qtdstatus ^= EHCI_QTD_TOGGLE_MASK; | | 2868 | qtdstatus ^= EHCI_QTD_TOGGLE_MASK; |
2869 | } | | 2869 | } |
2870 | if (next == NULL) | | 2870 | if (next == NULL) |
2871 | break; | | 2871 | break; |
2872 | usb_syncmem(&cur->dma, cur->offs, sizeof(cur->qtd), | | 2872 | usb_syncmem(&cur->dma, cur->offs, sizeof(cur->qtd), |
2873 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 2873 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |