PERFORCE change 129840 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Fri Nov 30 12:36:16 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=129840
Change 129840 by hselasky at 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) <<<
More information about the p4-projects
mailing list