Date: Fri, 30 Nov 2007 20:36:15 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 129840 for review Message-ID: <200711302036.lAUKaF91076450@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=129840 Change 129840 by hselasky@hselasky_laptop001 on 2007/11/30 20:36:08 Updates to UHCI according to change 129799 . All fixup buffers are now separate "page_cache" objects. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/uhci.c#44 edit .. //depot/projects/usb/src/sys/dev/usb/uhci.h#18 edit .. //depot/projects/usb/src/sys/dev/usb/uhci_pci.c#25 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/uhci.c#44 (text+ko) ==== @@ -95,10 +95,8 @@ &uhcidebug, 0, "uhci debug level"); SYSCTL_INT(_hw_usb_uhci, OID_AUTO, loop, CTLFLAG_RW, &uhcinoloop, 0, "uhci noloop"); -static void - uhci_dumpregs(uhci_softc_t *sc); -static void - uhci_dump_tds(uhci_td_t *td); +static void uhci_dumpregs(uhci_softc_t *sc); +static void uhci_dump_tds(uhci_td_t *td); #endif @@ -124,10 +122,6 @@ #define UHCI_INTR_ENDPT 1 -#define SC_HW_PHYSADDR(sc,what) \ - ((sc)->sc_hw_page.physaddr + \ - POINTER_TO_UNSIGNED(&(((struct uhci_hw_softc *)0)->what))) - struct uhci_mem_layout { struct usbd_page_search buf_res; @@ -137,7 +131,6 @@ struct usbd_page_cache *fix_pc; uint32_t buf_offset; - uint32_t fix_offset; uint16_t max_frame_size; }; @@ -167,15 +160,79 @@ static usbd_config_td_command_t uhci_root_ctrl_task; static void uhci_root_ctrl_task_td(struct uhci_softc *sc, struct thread *ctd); static void uhci_do_poll(struct usbd_bus *bus); +static void uhci_device_done(struct usbd_xfer *xfer, usbd_status error); + +void +uhci_iterate_hw_softc(uhci_softc_t *sc, uhci_iterate_cb_t *cb) +{ + uint32_t i; + + cb(sc, &(sc->sc_hw.pframes_pc), &(sc->sc_hw.pframes_pg), + sizeof(uint32_t) * UHCI_FRAMELIST_COUNT, UHCI_FRAMELIST_ALIGN); + + cb(sc, &(sc->sc_hw.ls_ctl_start_pc), &(sc->sc_hw.ls_ctl_start_pg), + sizeof(uhci_qh_t), UHCI_QH_ALIGN); + + cb(sc, &(sc->sc_hw.fs_ctl_start_pc), &(sc->sc_hw.fs_ctl_start_pg), + sizeof(uhci_qh_t), UHCI_QH_ALIGN); + + cb(sc, &(sc->sc_hw.bulk_start_pc), &(sc->sc_hw.bulk_start_pg), + sizeof(uhci_qh_t), UHCI_QH_ALIGN); + + cb(sc, &(sc->sc_hw.last_qh_pc), &(sc->sc_hw.last_qh_pg), + sizeof(uhci_qh_t), UHCI_QH_ALIGN); + + cb(sc, &(sc->sc_hw.last_td_pc), &(sc->sc_hw.last_td_pg), + sizeof(uhci_td_t), UHCI_TD_ALIGN); + + for (i = 0; i != UHCI_VFRAMELIST_COUNT; i++) { + cb(sc, sc->sc_hw.isoc_start_pc + i, + sc->sc_hw.isoc_start_pg + i, + sizeof(uhci_td_t), UHCI_TD_ALIGN); + } + + for (i = 0; i != UHCI_IFRAMELIST_COUNT; i++) { + cb(sc, sc->sc_hw.intr_start_pc + i, + sc->sc_hw.intr_start_pg + i, + sizeof(uhci_qh_t), UHCI_QH_ALIGN); + } + return; +} + +void +uhci_flush_all(uhci_softc_t *sc, struct usbd_page_cache *pc, + struct usbd_page *pg, uint32_t size, uint32_t align) +{ + usbd_pc_cpu_flush(pc); + return; +} + +void +uhci_alloc_all(uhci_softc_t *sc, struct usbd_page_cache *pc, + struct usbd_page *pg, uint32_t size, uint32_t align) +{ + if (usbd_dma_alloc_mem(sc->sc_bus.dma_tag_parent, + sc->sc_bus.dma_tag, pc, pg, size, align)) { + sc->sc_alloc_failed = 1; + } + return; +} +void +uhci_free_all(uhci_softc_t *sc, struct usbd_page_cache *pc, + struct usbd_page *pg, uint32_t size, uint32_t align) +{ + usbd_dma_free_mem(pc); + return; +} + static void uhci_mem_layout_init(struct uhci_mem_layout *ml, struct usbd_xfer *xfer) { ml->buf_pc = xfer->frbuffers + 0; - ml->fix_pc = &(xfer->buf_fixup); + ml->fix_pc = xfer->buf_fixup; ml->buf_offset = 0; - ml->fix_offset = 0; ml->max_frame_size = xfer->max_frame_size; @@ -189,22 +246,10 @@ if (ml->buf_res.length < td->len) { - while (1) { + /* need to do a fixup */ - /* need to do a fixup */ - - usbd_get_page(ml->fix_pc, ml->fix_offset, &(ml->fix_res)); - - /* check if there is room for the current transfer */ - - if (ml->fix_res.length >= td->len) { - break; - } - /* need to do a sub-fixup (goto next page) */ + usbd_get_page(ml->fix_pc, 0, &(ml->fix_res)); - ml->fix_offset += ml->fix_res.length; - } - td->td_buffer = htole32(ml->fix_res.physaddr); /* @@ -224,28 +269,28 @@ if ((td->td_token & htole32(UHCI_TD_PID)) == htole32(UHCI_TD_PID_IN)) { - td->fix_offset = ml->fix_offset; + td->fix_pc = ml->fix_pc; + usbd_pc_cpu_invalidate(ml->fix_pc); + } else { - td->fix_offset = UHCI_FIX_OFFSET_NONE; + td->fix_pc = NULL; /* copy data to fixup location */ - usbd_page_cpu_invalidate(ml->fix_res.page); - usbd_copy_out(ml->buf_pc, ml->buf_offset, ml->fix_res.buffer, td->len); - usbd_page_cpu_flush(ml->fix_res.page); + usbd_pc_cpu_flush(ml->fix_pc); } /* prepare next fixup */ - ml->fix_offset += ml->max_frame_size; + ml->fix_pc++; } else { td->td_buffer = htole32(ml->buf_res.physaddr); - td->fix_offset = UHCI_FIX_OFFSET_NONE; + td->fix_pc = NULL; } /* prepare next data location */ @@ -258,7 +303,8 @@ void uhci_reset(uhci_softc_t *sc) { - u_int n; + struct usbd_page_search buf_res; + uint16_t n; mtx_assert(&sc->sc_bus.mtx, MA_OWNED); @@ -316,8 +362,8 @@ done_2: /* reload the configuration */ - - UWRITE4(sc, UHCI_FLBASEADDR, SC_HW_PHYSADDR(sc, pframes)); + usbd_get_page(&(sc->sc_hw.pframes_pc), 0, &buf_res); + UWRITE4(sc, UHCI_FLBASEADDR, buf_res.physaddr); UWRITE2(sc, UHCI_FRNUM, sc->sc_saved_frnum); UWRITE1(sc, UHCI_SOF, sc->sc_saved_sof); return; @@ -365,18 +411,53 @@ return; } +static struct uhci_qh * +uhci_init_qh(struct usbd_page_cache *pc) +{ + struct usbd_page_search buf_res; + struct uhci_qh *qh; + + usbd_get_page(pc, 0, &buf_res); + + qh = buf_res.buffer; + + qh->qh_self = + htole32(buf_res.physaddr) | + htole32(UHCI_PTR_QH); + + qh->page_cache = pc; + + return qh; +} + +static struct uhci_td * +uhci_init_td(struct usbd_page_cache *pc) +{ + struct usbd_page_search buf_res; + struct uhci_td *td; + + usbd_get_page(pc, 0, &buf_res); + + td = buf_res.buffer; + + td->td_self = + htole32(buf_res.physaddr) | + htole32(UHCI_PTR_TD); + + td->page_cache = pc; + + return td; +} + usbd_status uhci_init(uhci_softc_t *sc) { - struct uhci_hw_softc *hw_ptr; uint16_t bit; uint16_t x; uint16_t y; mtx_lock(&sc->sc_bus.mtx); - hw_ptr = sc->sc_hw_ptr; - DPRINTF(("start\n")); #ifdef USB_DEBUG @@ -388,56 +469,40 @@ sc->sc_saved_sof = 0x40; /* default value */ sc->sc_saved_frnum = 0; /* default frame number */ - usbd_page_cpu_invalidate(&(sc->sc_hw_page)); - /* - * setup self pointers + * Setup QH's */ - hw_ptr->ls_ctl_start.qh_self = - htole32(SC_HW_PHYSADDR(sc, ls_ctl_start) | UHCI_PTR_QH); - hw_ptr->ls_ctl_start.page = - &(sc->sc_hw_page); + sc->sc_ls_ctl_p_last = + uhci_init_qh(&(sc->sc_hw.ls_ctl_start_pc)); - hw_ptr->hs_ctl_start.qh_self = - htole32(SC_HW_PHYSADDR(sc, hs_ctl_start) | UHCI_PTR_QH); - hw_ptr->hs_ctl_start.page = - &(sc->sc_hw_page); + sc->sc_fs_ctl_p_last = + uhci_init_qh(&(sc->sc_hw.fs_ctl_start_pc)); - hw_ptr->bulk_start.qh_self = - htole32(SC_HW_PHYSADDR(sc, bulk_start) | UHCI_PTR_QH); - hw_ptr->bulk_start.page = - &(sc->sc_hw_page); + sc->sc_bulk_p_last = + uhci_init_qh(&(sc->sc_hw.bulk_start_pc)); +#if 0 + sc->sc_reclaim_qh_p = + sc->sc_fs_ctl_p_last; +#else + /* setup reclaim looping point */ + sc->sc_reclaim_qh_p = + sc->sc_bulk_p_last; +#endif - hw_ptr->last_qh.qh_self = - htole32(SC_HW_PHYSADDR(sc, last_qh) | UHCI_PTR_QH); - hw_ptr->last_qh.page = - &(sc->sc_hw_page); + sc->sc_last_qh_p = + uhci_init_qh(&(sc->sc_hw.last_qh_pc)); - hw_ptr->last_td.td_self = - htole32(SC_HW_PHYSADDR(sc, last_td) | UHCI_PTR_TD); - hw_ptr->last_td.page = - &(sc->sc_hw_page); + sc->sc_last_td_p = + uhci_init_td(&(sc->sc_hw.last_td_pc)); - for (x = 0; - x < UHCI_VFRAMELIST_COUNT; - x++) { - hw_ptr->isoc_start[x].td_self = - htole32(SC_HW_PHYSADDR(sc, isoc_start[x]) | UHCI_PTR_TD); - hw_ptr->isoc_start[x].page = - &(sc->sc_hw_page); + for (x = 0; x != UHCI_VFRAMELIST_COUNT; x++) { sc->sc_isoc_p_last[x] = - &(hw_ptr->isoc_start[x]); + uhci_init_td(sc->sc_hw.isoc_start_pc + x); } - for (x = 0; - x < UHCI_IFRAMELIST_COUNT; - x++) { - hw_ptr->intr_start[x].qh_self = - htole32(SC_HW_PHYSADDR(sc, intr_start[x]) | UHCI_PTR_QH); - hw_ptr->intr_start[x].page = - &(sc->sc_hw_page); + for (x = 0; x != UHCI_IFRAMELIST_COUNT; x++) { sc->sc_intr_p_last[x] = - &(hw_ptr->intr_start[x]); + uhci_init_qh(sc->sc_hw.intr_start_pc + x); } /* @@ -448,87 +513,136 @@ while (bit) { x = bit; while (x & bit) { + uhci_qh_t *qh_x; + uhci_qh_t *qh_y; + y = (x ^ bit) | (bit / 2); + /* * the next QH has half the poll interval */ - hw_ptr->intr_start[x].h_next = NULL; - hw_ptr->intr_start[x].qh_h_next = - hw_ptr->intr_start[y].qh_self; - hw_ptr->intr_start[x].e_next = NULL; - hw_ptr->intr_start[x].qh_e_next = htole32(UHCI_PTR_T); + qh_x = sc->sc_intr_p_last[x]; + qh_y = sc->sc_intr_p_last[y]; + + qh_x->h_next = NULL; + qh_x->qh_h_next = qh_y->qh_self; + qh_x->e_next = NULL; + qh_x->qh_e_next = htole32(UHCI_PTR_T); x++; } bit >>= 1; } - /* start QH for interrupt traffic */ - hw_ptr->intr_start[0].h_next = &(hw_ptr->ls_ctl_start); - hw_ptr->intr_start[0].qh_h_next = hw_ptr->ls_ctl_start.qh_self; - hw_ptr->intr_start[0].e_next = 0; - hw_ptr->intr_start[0].qh_e_next = htole32(UHCI_PTR_T); + if (1) { + uhci_qh_t *qh_ls; + uhci_qh_t *qh_intr; + + qh_ls = sc->sc_ls_ctl_p_last; + qh_intr = sc->sc_intr_p_last[0]; + + /* start QH for interrupt traffic */ + qh_intr->h_next = qh_ls; + qh_intr->qh_h_next = qh_ls->qh_self; + qh_intr->e_next = 0; + qh_intr->qh_e_next = htole32(UHCI_PTR_T); + } + for (x = 0; x != UHCI_VFRAMELIST_COUNT; x++) { + + uhci_td_t *td_x; + uhci_qh_t *qh_intr; + + td_x = sc->sc_isoc_p_last[x]; + qh_intr = sc->sc_intr_p_last[x | (UHCI_IFRAMELIST_COUNT / 2)]; - for (x = 0; - x < UHCI_VFRAMELIST_COUNT; - x++) { /* start TD for isochronous traffic */ - hw_ptr->isoc_start[x].next = NULL; - hw_ptr->isoc_start[x].td_next = - hw_ptr->intr_start[x | (UHCI_IFRAMELIST_COUNT / 2)].qh_self; - hw_ptr->isoc_start[x].td_status = htole32(UHCI_TD_IOS); - hw_ptr->isoc_start[x].td_token = htole32(0); - hw_ptr->isoc_start[x].td_buffer = htole32(0); + td_x->next = NULL; + td_x->td_next = qh_intr->qh_self; + td_x->td_status = htole32(UHCI_TD_IOS); + td_x->td_token = htole32(0); + td_x->td_buffer = htole32(0); + } + + if (1) { + uhci_qh_t *qh_ls; + uhci_qh_t *qh_fs; + + qh_ls = sc->sc_ls_ctl_p_last; + qh_fs = sc->sc_fs_ctl_p_last; + + /* start QH where low speed control traffic will be queued */ + qh_ls->h_next = qh_fs; + qh_ls->qh_h_next = qh_fs->qh_self; + qh_ls->e_next = 0; + qh_ls->qh_e_next = htole32(UHCI_PTR_T); } + if (1) { + uhci_qh_t *qh_ctl; + uhci_qh_t *qh_blk; + uhci_qh_t *qh_lst; + uhci_td_t *td_lst; + + qh_ctl = sc->sc_fs_ctl_p_last; + qh_blk = sc->sc_bulk_p_last; + + /* start QH where full speed control traffic will be queued */ + qh_ctl->h_next = qh_blk; + qh_ctl->qh_h_next = qh_blk->qh_self; + qh_ctl->e_next = 0; + qh_ctl->qh_e_next = htole32(UHCI_PTR_T); - /* start QH where low speed control traffic will be queued */ - hw_ptr->ls_ctl_start.h_next = &(hw_ptr->hs_ctl_start); - hw_ptr->ls_ctl_start.qh_h_next = hw_ptr->hs_ctl_start.qh_self; - hw_ptr->ls_ctl_start.e_next = 0; - hw_ptr->ls_ctl_start.qh_e_next = htole32(UHCI_PTR_T); + qh_lst = sc->sc_last_qh_p; - sc->sc_ls_ctl_p_last = &(hw_ptr->ls_ctl_start); + /* start QH where bulk traffic will be queued */ + qh_blk->h_next = qh_lst; + qh_blk->qh_h_next = qh_lst->qh_self; + qh_blk->e_next = 0; + qh_blk->qh_e_next = htole32(UHCI_PTR_T); - /* start QH where high speed control traffic will be queued */ - hw_ptr->hs_ctl_start.h_next = &(hw_ptr->bulk_start); - hw_ptr->hs_ctl_start.qh_h_next = hw_ptr->bulk_start.qh_self; - hw_ptr->hs_ctl_start.e_next = 0; - hw_ptr->hs_ctl_start.qh_e_next = htole32(UHCI_PTR_T); + td_lst = sc->sc_last_td_p; - sc->sc_hs_ctl_p_last = &(hw_ptr->hs_ctl_start); + /* end QH which is used for looping the QHs */ + qh_lst->h_next = 0; + qh_lst->qh_h_next = htole32(UHCI_PTR_T); /* end of QH chain */ + qh_lst->e_next = td_lst; + qh_lst->qh_e_next = td_lst->td_self; - /* start QH where bulk traffic will be queued */ - hw_ptr->bulk_start.h_next = &(hw_ptr->last_qh); - hw_ptr->bulk_start.qh_h_next = hw_ptr->last_qh.qh_self; - hw_ptr->bulk_start.e_next = 0; - hw_ptr->bulk_start.qh_e_next = htole32(UHCI_PTR_T); + /* + * end TD which hangs from the last QH, to avoid a bug in the PIIX + * that makes it run berserk otherwise + */ + td_lst->next = 0; + td_lst->td_next = htole32(UHCI_PTR_T); + td_lst->td_status = htole32(0); /* inactive */ + td_lst->td_token = htole32(0); + td_lst->td_buffer = htole32(0); + } + if (1) { + struct usbd_page_search buf_res; + uint32_t *pframes; - sc->sc_bulk_p_last = &(hw_ptr->bulk_start); + usbd_get_page(&(sc->sc_hw.pframes_pc), 0, &buf_res); - /* end QH which is used for looping the QHs */ - hw_ptr->last_qh.h_next = 0; - hw_ptr->last_qh.qh_h_next = htole32(UHCI_PTR_T); /* end of QH chain */ - hw_ptr->last_qh.e_next = &(hw_ptr->last_td); - hw_ptr->last_qh.qh_e_next = hw_ptr->last_td.td_self; + pframes = buf_res.buffer; - /* - * end TD which hangs from the last QH, to avoid a bug in the PIIX - * that makes it run berserk otherwise - */ - hw_ptr->last_td.next = 0; - hw_ptr->last_td.td_next = htole32(UHCI_PTR_T); - hw_ptr->last_td.td_status = htole32(0); /* inactive */ - hw_ptr->last_td.td_token = htole32(0); - hw_ptr->last_td.td_buffer = htole32(0); - /* setup UHCI framelist */ + /* + * Setup UHCI framelist + * + * Execution order: + * + * pframes -> full speed isochronous -> interrupt QH's -> low + * speed control -> full speed control -> bulk transfers + * + */ - for (x = 0; - x < UHCI_FRAMELIST_COUNT; - x++) { - hw_ptr->pframes[x] = hw_ptr->isoc_start[x % UHCI_VFRAMELIST_COUNT].td_self; + for (x = 0; x != UHCI_FRAMELIST_COUNT; x++) { + pframes[x] = + sc->sc_isoc_p_last[x % UHCI_VFRAMELIST_COUNT]->td_self; + } } + /* flush all cache into memory */ - usbd_page_cpu_flush(&(sc->sc_hw_page)); + uhci_iterate_hw_softc(sc, &uhci_flush_all); LIST_INIT(&sc->sc_interrupt_list_head); @@ -641,7 +755,7 @@ uint32_t td_token; uint8_t temp; - usbd_page_cpu_invalidate(p->page); + usbd_pc_cpu_invalidate(p->page_cache); td_next = le32toh(p->td_next); td_status = le32toh(p->td_status); @@ -687,8 +801,6 @@ UHCI_TD_GET_DT(td_token), UHCI_TD_GET_MAXLEN(td_token)); - usbd_page_cpu_flush(p->page); - return (temp); } @@ -699,7 +811,7 @@ uint32_t qh_h_next; uint32_t qh_e_next; - usbd_page_cpu_invalidate(sqh->page); + usbd_pc_cpu_invalidate(sqh->page_cache); qh_h_next = le32toh(sqh->qh_h_next); qh_e_next = le32toh(sqh->qh_e_next); @@ -710,20 +822,17 @@ temp = ((((sqh->h_next != NULL) && !(qh_h_next & UHCI_PTR_T)) ? 1 : 0) | (((sqh->e_next != NULL) && !(qh_e_next & UHCI_PTR_T)) ? 2 : 0)); - usbd_page_cpu_flush(sqh->page); return (temp); } static void uhci_dump_all(uhci_softc_t *sc) { - struct uhci_hw_softc *hw_ptr = sc->sc_hw_ptr; - uhci_dumpregs(sc); - uhci_dump_qh(&(hw_ptr->ls_ctl_start)); - uhci_dump_qh(&(hw_ptr->hs_ctl_start)); - uhci_dump_qh(&(hw_ptr->bulk_start)); - uhci_dump_qh(&(hw_ptr->last_qh)); + uhci_dump_qh(sc->sc_ls_ctl_p_last); + uhci_dump_qh(sc->sc_fs_ctl_p_last); + uhci_dump_qh(sc->sc_bulk_p_last); + uhci_dump_qh(sc->sc_last_qh_p); return; } @@ -786,7 +895,7 @@ #endif /* - * Let the last QH loop back to the high speed control transfer QH. + * Let the last QH loop back to the full speed control transfer QH. * This is what intel calls "bandwidth reclamation" and improves * USB performance a lot for some devices. * If we are already looping, just count it. @@ -794,29 +903,24 @@ static void uhci_add_loop(uhci_softc_t *sc) { - struct uhci_hw_softc *hw_ptr; + struct uhci_qh *qh_lst; + struct uhci_qh *qh_rec; #ifdef USB_DEBUG if (uhcinoloop) { return; } #endif - if (++sc->sc_loops == 1) { + if (++(sc->sc_loops) == 1) { DPRINTFN(5, ("add\n")); - hw_ptr = sc->sc_hw_ptr; + qh_lst = sc->sc_last_qh_p; + qh_rec = sc->sc_reclaim_qh_p; - usbd_page_cpu_invalidate(&(sc->sc_hw_page)); + /* NOTE: we don't loop back the soft pointer */ - /* NOTE: we don't loop back the soft pointer */ -#if 0 - hw_ptr->last_qh.qh_h_next = - hw_ptr->hs_ctl_start.qh_self; -#else - hw_ptr->last_qh.qh_h_next = - hw_ptr->bulk_start.qh_self; -#endif - usbd_page_cpu_flush(&(sc->sc_hw_page)); + qh_lst->qh_h_next = qh_rec->qh_self; + usbd_pc_cpu_flush(qh_lst->page_cache); } return; } @@ -824,20 +928,19 @@ static void uhci_rem_loop(uhci_softc_t *sc) { - struct uhci_hw_softc *hw_ptr; + struct uhci_qh *qh_lst; #ifdef USB_DEBUG if (uhcinoloop) { return; } #endif - if (--sc->sc_loops == 0) { + if (--(sc->sc_loops) == 0) { DPRINTFN(5, ("remove\n")); - hw_ptr = sc->sc_hw_ptr; - usbd_page_cpu_invalidate(&(sc->sc_hw_page)); - hw_ptr->last_qh.qh_h_next = htole32(UHCI_PTR_T); - usbd_page_cpu_flush(&(sc->sc_hw_page)); + qh_lst = sc->sc_last_qh_p; + qh_lst->qh_h_next = htole32(UHCI_PTR_T); + usbd_pc_cpu_flush(qh_lst->page_cache); } return; } @@ -850,15 +953,12 @@ /* (sc->sc_bus.mtx) must be locked */ - usbd_page_cpu_invalidate(std->page); - std->next = last->next; std->td_next = last->td_next; std->prev = last; - usbd_page_cpu_flush(std->page); - usbd_page_cpu_invalidate(last->page); + usbd_pc_cpu_flush(std->page_cache); /* * the last->next->prev is never followed: std->next->prev = std; @@ -866,7 +966,7 @@ last->next = std; last->td_next = std->td_self; - usbd_page_cpu_flush(last->page); + usbd_pc_cpu_flush(last->page_cache); return (std); } @@ -879,8 +979,6 @@ /* (sc->sc_bus.mtx) must be locked */ - usbd_page_cpu_invalidate(sqh->page); - sqh->e_next = td; sqh->qh_e_next = td->td_self; @@ -889,18 +987,18 @@ sqh->h_prev = last; - usbd_page_cpu_flush(sqh->page); - usbd_page_cpu_invalidate(last->page); + usbd_pc_cpu_flush(sqh->page_cache); /* - * the last->h_next->h_prev is never followed: sqh->h_next->h_prev = - * sqh; + * The "last->h_next->h_prev" is never followed: + * + * "sqh->h_next->h_prev" = sqh; */ last->h_next = sqh; last->qh_h_next = sqh->qh_self; - usbd_page_cpu_flush(last->page); + usbd_pc_cpu_flush(last->page_cache); return (sqh); } @@ -915,17 +1013,14 @@ /* (sc->sc_bus.mtx) must be locked */ - usbd_page_cpu_invalidate(std->prev->page); - std->prev->next = std->next; std->prev->td_next = std->td_next; - usbd_page_cpu_flush(std->prev->page); + usbd_pc_cpu_flush(std->prev->page_cache); if (std->next) { - usbd_page_cpu_invalidate(std->next->page); std->next->prev = std->prev; - usbd_page_cpu_flush(std->next->page); + usbd_pc_cpu_flush(std->next->page_cache); } return ((last == std) ? std->prev : last); } @@ -940,20 +1035,16 @@ /* only remove if not removed from a queue */ if (sqh->h_prev) { - usbd_page_cpu_invalidate(sqh->h_prev->page); sqh->h_prev->h_next = sqh->h_next; sqh->h_prev->qh_h_next = sqh->qh_h_next; - usbd_page_cpu_flush(sqh->h_prev->page); + usbd_pc_cpu_flush(sqh->h_prev->page_cache); if (sqh->h_next) { - usbd_page_cpu_invalidate(sqh->h_next->page); sqh->h_next->h_prev = sqh->h_prev; - usbd_page_cpu_flush(sqh->h_next->page); + usbd_pc_cpu_flush(sqh->h_next->page_cache); } - usbd_page_cpu_invalidate(sqh->page); - /* * set the Terminate-bit in the e_next of the QH, in case * the transferred packet was short so that the QH still @@ -961,7 +1052,7 @@ */ sqh->qh_e_next = htole32(UHCI_PTR_T); - usbd_page_cpu_flush(sqh->page); + usbd_pc_cpu_flush(sqh->page_cache); last = ((last == sqh) ? sqh->h_prev : last); @@ -970,9 +1061,6 @@ return (last); } -static void - uhci_device_done(struct usbd_xfer *xfer, usbd_status error); - static uint8_t uhci_isoc_done(uhci_softc_t *sc, struct usbd_xfer *xfer) { @@ -989,6 +1077,11 @@ DPRINTFN(12, ("xfer=%p pipe=%p transfer done\n", xfer, xfer->pipe)); + /* sync any DMA memory before doing fixups */ + if (xfer->flags.bdma_enable) { + usbd_dma_load_post_sync(xfer); + XXX; + } while (nframes--) { if (td == NULL) { panic("%s:%d: out of TD's\n", @@ -1003,9 +1096,8 @@ uhci_dump_td(td); } #endif - usbd_page_cpu_invalidate(td->page); + usbd_pc_cpu_invalidate(td->page_cache); status = le32toh(td->td_status); - usbd_page_cpu_flush(td->page); /* check for active transfers */ @@ -1017,18 +1109,16 @@ if (len > *plen) { len = *plen; } - if (td->fix_offset != UHCI_FIX_OFFSET_NONE) { + if (td->fix_pc) { - usbd_get_page(&(xfer->buf_fixup), td->fix_offset, &res); + usbd_get_page(td->fix_pc, 0, &res); /* copy data from fixup location to real location */ - usbd_page_cpu_invalidate(res.page); + usbd_pc_cpu_invalidate(td->fix_pc); usbd_copy_in(xfer->frbuffers + 0, offset, res.buffer, len); - - usbd_page_cpu_flush(res.page); } offset += *plen; @@ -1065,10 +1155,9 @@ } while (1) { - usbd_page_cpu_invalidate(td->page); + usbd_pc_cpu_invalidate(td->page_cache); status = le32toh(td->td_status); token = le32toh(td->td_token); - usbd_page_cpu_flush(td->page); /* * Verify the status and add @@ -1084,21 +1173,19 @@ } else if ((xfer->aframes != xfer->nframes) && (len > 0)) { - if (td->fix_offset != UHCI_FIX_OFFSET_NONE) { + if (td->fix_pc) { - usbd_get_page(&(xfer->buf_fixup), td->fix_offset, &res); + usbd_get_page(td->fix_pc, 0, &res); /* * copy data from fixup location to real * location */ - usbd_page_cpu_invalidate(res.page); + usbd_pc_cpu_invalidate(td->fix_pc); usbd_copy_in(xfer->frbuffers + xfer->aframes, xfer->frlengths[xfer->aframes], res.buffer, len); - - usbd_page_cpu_flush(res.page); } /* update actual length */ @@ -1163,7 +1250,6 @@ USBD_STALLED : USBD_NORMAL_COMPLETION; } - static void uhci_non_isoc_done(struct usbd_xfer *xfer) { @@ -1178,6 +1264,10 @@ } #endif + /* sync any DMA memory before doing fixups */ + if (xfer->flags.bdma_enable) { + usbd_dma_load_post_sync(xfer); + } /* reset scanner */ xfer->td_transfer_cache = xfer->td_transfer_first; @@ -1251,9 +1341,8 @@ while (1) { - usbd_page_cpu_invalidate(td->page); td->td_token ^= htole32(UHCI_TD_SET_DT(1)); - usbd_page_cpu_flush(td->page); + usbd_pc_cpu_flush(td->page_cache); if (td == xfer->td_transfer_last) { /* last transfer */ @@ -1268,9 +1357,8 @@ } } /* update the QH */ - usbd_page_cpu_invalidate(qh->page); qh->qh_e_next = td_self; - usbd_page_cpu_flush(qh->page); + usbd_pc_cpu_flush(qh->page_cache); DPRINTFN(12, ("xfer=%p following alt next\n", xfer)); return; @@ -1303,9 +1391,8 @@ td = xfer->td_transfer_last; - usbd_page_cpu_invalidate(td->page); + usbd_pc_invalidate(td->page_cache); status = le32toh(td->td_status); - usbd_page_cpu_flush(td->page); if (!(status & UHCI_TD_ACTIVE)) { uhci_device_done(xfer, USBD_NORMAL_COMPLETION); @@ -1322,10 +1409,9 @@ td = xfer->td_transfer_cache; while (1) { - usbd_page_cpu_invalidate(td->page); + usbd_pc_cpu_invalidate(td->page_cache); status = le32toh(td->td_status); token = le32toh(td->td_token); - usbd_page_cpu_flush(td->page); /* * if there is an active TD the transfer isn't done @@ -1663,8 +1749,6 @@ continue; } - usbd_page_cpu_invalidate(td->page); - /* fill out current TD */ td->td_status = temp->td_status; @@ -1678,7 +1762,7 @@ td->len = 0; td->td_buffer = 0; - td->fix_offset = UHCI_FIX_OFFSET_NONE; + td->fix_pc = NULL; } else { @@ -1706,7 +1790,7 @@ } } - usbd_page_cpu_flush(td->page); + usbd_pc_cpu_flush(td->page_cache); } if (precompute) { @@ -1858,15 +1942,13 @@ } td = temp.td; - usbd_page_cpu_invalidate(td->page); - td->td_next = htole32(UHCI_PTR_T); /* set interrupt bit */ td->td_status |= htole32(UHCI_TD_IOC); - usbd_page_cpu_flush(td->page); + usbd_pc_cpu_flush(td->page_cache); /* must have at least one frame! */ @@ -1903,7 +1985,7 @@ xfer, xfer->pipe, error)); for (qh = xfer->qh_start; qh; qh = qh->obj_next) { - usbd_page_cpu_invalidate(qh->page); + usbd_pc_cpu_invalidate(qh->page_cache); if (!(qh->qh_e_next & htole32(UHCI_PTR_T))) { need_delay = 1; @@ -1911,7 +1993,7 @@ qh->e_next = 0; qh->qh_e_next = htole32(UHCI_PTR_T); - usbd_page_cpu_flush(qh->page); + usbd_pc_cpu_flush(qh->page_cache); } if (xfer->flags_int.bandwidth_reclaimed) { @@ -1925,7 +2007,7 @@ if (xfer->udev->speed == USB_SPEED_LOW) { >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200711302036.lAUKaF91076450>