Skip site navigation (1)Skip section navigation (2)
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>