Correctly handle the conversion from virtual to physical addresses. The
problem was basically (for offset > 4096): vtophys(addr) + offset != vtophys(addr + offset) Also, use TD's with a maximum size of 4k instead of 8kb for OHCI controllers. This problem occurs in drivers that use large transfer sizes: umass, host2host and ethernet with jumbo frames.
This commit is contained in:
parent
9fcc079584
commit
8f9683e20c
@ -387,8 +387,8 @@ ohci_alloc_sed(sc)
|
|||||||
return (0);
|
return (0);
|
||||||
for(i = 0; i < OHCI_SED_CHUNK; i++) {
|
for(i = 0; i < OHCI_SED_CHUNK; i++) {
|
||||||
offs = i * OHCI_SED_SIZE;
|
offs = i * OHCI_SED_SIZE;
|
||||||
sed = (ohci_soft_ed_t *)((char *)KERNADDR(&dma) +offs);
|
sed = (ohci_soft_ed_t *)((char *)KERNADDR(&dma, offs));
|
||||||
sed->physaddr = DMAADDR(&dma) + offs;
|
sed->physaddr = DMAADDR(&dma, offs);
|
||||||
sed->next = sc->sc_freeeds;
|
sed->next = sc->sc_freeeds;
|
||||||
sc->sc_freeeds = sed;
|
sc->sc_freeeds = sed;
|
||||||
}
|
}
|
||||||
@ -426,8 +426,8 @@ ohci_alloc_std(sc)
|
|||||||
return (0);
|
return (0);
|
||||||
for(i = 0; i < OHCI_STD_CHUNK; i++) {
|
for(i = 0; i < OHCI_STD_CHUNK; i++) {
|
||||||
offs = i * OHCI_STD_SIZE;
|
offs = i * OHCI_STD_SIZE;
|
||||||
std = (ohci_soft_td_t *)((char *)KERNADDR(&dma) +offs);
|
std = (ohci_soft_td_t *)((char *)KERNADDR(&dma, offs));
|
||||||
std->physaddr = DMAADDR(&dma) + offs;
|
std->physaddr = DMAADDR(&dma, offs);
|
||||||
std->nexttd = sc->sc_freetds;
|
std->nexttd = sc->sc_freetds;
|
||||||
sc->sc_freetds = std;
|
sc->sc_freetds = std;
|
||||||
}
|
}
|
||||||
@ -449,23 +449,25 @@ ohci_free_std(sc, std)
|
|||||||
}
|
}
|
||||||
|
|
||||||
usbd_status
|
usbd_status
|
||||||
ohci_alloc_std_chain(opipe, sc, len, rd, flags, dma, sp, ep)
|
ohci_alloc_std_chain(opipe, sc, len, rd, flags, dma, std, rstd)
|
||||||
struct ohci_pipe *opipe;
|
struct ohci_pipe *opipe;
|
||||||
ohci_softc_t *sc;
|
ohci_softc_t *sc;
|
||||||
int len, rd;
|
int len, rd;
|
||||||
u_int16_t flags;
|
u_int16_t flags;
|
||||||
usb_dma_t *dma;
|
usb_dma_t *dma;
|
||||||
ohci_soft_td_t *sp, **ep;
|
ohci_soft_td_t *std, **rstd;
|
||||||
{
|
{
|
||||||
ohci_soft_td_t *next, *cur;
|
ohci_soft_td_t *next, *cur;
|
||||||
ohci_physaddr_t dataphys, dataphysend;
|
ohci_physaddr_t dataphys, dataphysend;
|
||||||
u_int32_t intr, tdflags;
|
u_int32_t intr, tdflags;
|
||||||
|
int offset = 0;
|
||||||
int curlen;
|
int curlen;
|
||||||
|
|
||||||
DPRINTFN(len < 4096,("ohci_alloc_std_chain: start len=%d\n", len));
|
DPRINTFN(len < 4096,("ohci_alloc_std_chain: start len=%d\n", len));
|
||||||
cur = sp;
|
|
||||||
dataphys = DMAADDR(dma);
|
cur = std;
|
||||||
dataphysend = OHCI_PAGE(dataphys + len - 1);
|
|
||||||
|
dataphysend = DMAADDR(dma, len - 1);
|
||||||
tdflags =
|
tdflags =
|
||||||
(rd ? OHCI_TD_IN : OHCI_TD_OUT) |
|
(rd ? OHCI_TD_IN : OHCI_TD_OUT) |
|
||||||
OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY |
|
OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY |
|
||||||
@ -476,15 +478,41 @@ ohci_alloc_std_chain(opipe, sc, len, rd, flags, dma, sp, ep)
|
|||||||
if (next == 0)
|
if (next == 0)
|
||||||
goto nomem;
|
goto nomem;
|
||||||
|
|
||||||
|
dataphys = DMAADDR(dma, offset);
|
||||||
|
|
||||||
/* The OHCI hardware can handle at most one page crossing. */
|
/* The OHCI hardware can handle at most one page crossing. */
|
||||||
if (OHCI_PAGE(dataphys) == dataphysend ||
|
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
OHCI_PAGE(dataphys) + OHCI_PAGE_SIZE == dataphysend) {
|
if (OHCI_PAGE(dataphys) == OHCI_PAGE(dataphysend) ||
|
||||||
|
OHCI_PAGE(dataphys) + OHCI_PAGE_SIZE == OHCI_PAGE(dataphysend))
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
/* XXX This is pretty broken: Because we do not allocate
|
||||||
|
* a contiguous buffer (contiguous in physical pages) we
|
||||||
|
* can only transfer one page in one go.
|
||||||
|
* So check whether the start and end of the buffer are on
|
||||||
|
* the same page.
|
||||||
|
*/
|
||||||
|
if (OHCI_PAGE(dataphys) == OHCI_PAGE(dataphysend))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
/* we can handle it in this TD */
|
/* we can handle it in this TD */
|
||||||
curlen = len;
|
curlen = len;
|
||||||
} else {
|
} else {
|
||||||
|
/* XXX The calculation below is wrong and could
|
||||||
|
* result in a packet that is not a multiple of the
|
||||||
|
* MaxPacketSize in the case where the buffer does not
|
||||||
|
* start on an appropriate address (like for example in
|
||||||
|
* the case of an mbuf cluster). You'll get an early
|
||||||
|
* short packet.
|
||||||
|
*/
|
||||||
|
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
/* must use multiple TDs, fill as much as possible. */
|
/* must use multiple TDs, fill as much as possible. */
|
||||||
curlen = 2 * OHCI_PAGE_SIZE -
|
curlen = 2 * OHCI_PAGE_SIZE -
|
||||||
(dataphys & (OHCI_PAGE_SIZE-1));
|
OHCI_PAGE_MASK(dataphys);
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
/* See comment above (XXX) */
|
||||||
|
curlen = OHCI_PAGE_SIZE -
|
||||||
|
OHCI_PAGE_MASK(dataphys);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
DPRINTFN(4,("ohci_alloc_std_chain: dataphys=0x%08x "
|
DPRINTFN(4,("ohci_alloc_std_chain: dataphys=0x%08x "
|
||||||
"dataphysend=0x%08x len=%d curlen=%d\n",
|
"dataphysend=0x%08x len=%d curlen=%d\n",
|
||||||
@ -505,7 +533,7 @@ ohci_alloc_std_chain(opipe, sc, len, rd, flags, dma, sp, ep)
|
|||||||
if (len == 0)
|
if (len == 0)
|
||||||
break;
|
break;
|
||||||
DPRINTFN(10,("ohci_alloc_std_chain: extend chain\n"));
|
DPRINTFN(10,("ohci_alloc_std_chain: extend chain\n"));
|
||||||
dataphys += curlen;
|
offset += curlen;
|
||||||
cur = next;
|
cur = next;
|
||||||
}
|
}
|
||||||
if ((flags & USBD_FORCE_SHORT_XFER) &&
|
if ((flags & USBD_FORCE_SHORT_XFER) &&
|
||||||
@ -526,7 +554,7 @@ ohci_alloc_std_chain(opipe, sc, len, rd, flags, dma, sp, ep)
|
|||||||
DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n"));
|
DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n"));
|
||||||
}
|
}
|
||||||
cur->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
|
cur->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
|
||||||
*ep = next;
|
*rstd = next;
|
||||||
|
|
||||||
return (USBD_NORMAL_COMPLETION);
|
return (USBD_NORMAL_COMPLETION);
|
||||||
|
|
||||||
@ -568,8 +596,8 @@ ohci_alloc_sitd(sc)
|
|||||||
return (0);
|
return (0);
|
||||||
for(i = 0; i < OHCI_STD_CHUNK; i++) {
|
for(i = 0; i < OHCI_STD_CHUNK; i++) {
|
||||||
offs = i * OHCI_STD_SIZE;
|
offs = i * OHCI_STD_SIZE;
|
||||||
sitd = (ohci_soft_itd_t *)((char*)KERNADDR(&dma)+offs);
|
sitd = (ohci_soft_itd_t *)((char*)KERNADDR(&dma, offs));
|
||||||
sitd->physaddr = DMAADDR(&dma) + offs;
|
sitd->physaddr = DMAADDR(&dma, offs);
|
||||||
sitd->nextitd = sc->sc_freeitds;
|
sitd->nextitd = sc->sc_freeitds;
|
||||||
sc->sc_freeitds = sitd;
|
sc->sc_freeitds = sitd;
|
||||||
}
|
}
|
||||||
@ -627,7 +655,7 @@ ohci_init(sc)
|
|||||||
OHCI_HCCA_ALIGN, &sc->sc_hccadma);
|
OHCI_HCCA_ALIGN, &sc->sc_hccadma);
|
||||||
if (err)
|
if (err)
|
||||||
return (err);
|
return (err);
|
||||||
sc->sc_hcca = (struct ohci_hcca *)KERNADDR(&sc->sc_hccadma);
|
sc->sc_hcca = (struct ohci_hcca *)KERNADDR(&sc->sc_hccadma, 0);
|
||||||
memset(sc->sc_hcca, 0, OHCI_HCCA_SIZE);
|
memset(sc->sc_hcca, 0, OHCI_HCCA_SIZE);
|
||||||
|
|
||||||
sc->sc_eintrs = OHCI_NORMAL_INTRS;
|
sc->sc_eintrs = OHCI_NORMAL_INTRS;
|
||||||
@ -746,7 +774,7 @@ ohci_init(sc)
|
|||||||
/* The controller is now in SUSPEND state, we have 2ms to finish. */
|
/* The controller is now in SUSPEND state, we have 2ms to finish. */
|
||||||
|
|
||||||
/* Set up HC registers. */
|
/* Set up HC registers. */
|
||||||
OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma));
|
OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0));
|
||||||
OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr);
|
OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr);
|
||||||
OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr);
|
OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr);
|
||||||
/* disable all interrupts and then switch on all desired interrupts */
|
/* disable all interrupts and then switch on all desired interrupts */
|
||||||
@ -1238,7 +1266,7 @@ ohci_device_intr_done(xfer)
|
|||||||
OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
|
OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
|
||||||
if (xfer->flags & USBD_SHORT_XFER_OK)
|
if (xfer->flags & USBD_SHORT_XFER_OK)
|
||||||
data->td.td_flags |= LE(OHCI_TD_R);
|
data->td.td_flags |= LE(OHCI_TD_R);
|
||||||
data->td.td_cbp = LE(DMAADDR(&xfer->dmabuf));
|
data->td.td_cbp = LE(DMAADDR(&xfer->dmabuf, 0));
|
||||||
data->nexttd = tail;
|
data->nexttd = tail;
|
||||||
data->td.td_nexttd = LE(tail->physaddr);
|
data->td.td_nexttd = LE(tail->physaddr);
|
||||||
data->td.td_be = LE(LE(data->td.td_cbp) + xfer->length - 1);
|
data->td.td_be = LE(LE(data->td.td_cbp) + xfer->length - 1);
|
||||||
@ -1287,7 +1315,7 @@ ohci_rhsc(sc, xfer)
|
|||||||
pipe = xfer->pipe;
|
pipe = xfer->pipe;
|
||||||
opipe = (struct ohci_pipe *)pipe;
|
opipe = (struct ohci_pipe *)pipe;
|
||||||
|
|
||||||
p = KERNADDR(&xfer->dmabuf);
|
p = KERNADDR(&xfer->dmabuf, 0);
|
||||||
m = min(sc->sc_noport, xfer->length * 8 - 1);
|
m = min(sc->sc_noport, xfer->length * 8 - 1);
|
||||||
memset(p, 0, xfer->length);
|
memset(p, 0, xfer->length);
|
||||||
for (i = 1; i <= m; i++) {
|
for (i = 1; i <= m; i++) {
|
||||||
@ -1414,7 +1442,7 @@ ohci_device_request(xfer)
|
|||||||
(isread ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC |
|
(isread ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC |
|
||||||
OHCI_TD_TOGGLE_1 | OHCI_TD_NOINTR |
|
OHCI_TD_TOGGLE_1 | OHCI_TD_NOINTR |
|
||||||
(xfer->flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0));
|
(xfer->flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0));
|
||||||
data->td.td_cbp = LE(DMAADDR(&xfer->dmabuf));
|
data->td.td_cbp = LE(DMAADDR(&xfer->dmabuf, 0));
|
||||||
data->nexttd = stat;
|
data->nexttd = stat;
|
||||||
data->td.td_nexttd = LE(stat->physaddr);
|
data->td.td_nexttd = LE(stat->physaddr);
|
||||||
data->td.td_be = LE(LE(data->td.td_cbp) + len - 1);
|
data->td.td_be = LE(LE(data->td.td_cbp) + len - 1);
|
||||||
@ -1430,11 +1458,11 @@ ohci_device_request(xfer)
|
|||||||
stat->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
|
stat->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(KERNADDR(&opipe->u.ctl.reqdma), req, sizeof *req);
|
memcpy(KERNADDR(&opipe->u.ctl.reqdma, 0), req, sizeof *req);
|
||||||
|
|
||||||
setup->td.td_flags = LE(OHCI_TD_SETUP | OHCI_TD_NOCC |
|
setup->td.td_flags = LE(OHCI_TD_SETUP | OHCI_TD_NOCC |
|
||||||
OHCI_TD_TOGGLE_0 | OHCI_TD_NOINTR);
|
OHCI_TD_TOGGLE_0 | OHCI_TD_NOINTR);
|
||||||
setup->td.td_cbp = LE(DMAADDR(&opipe->u.ctl.reqdma));
|
setup->td.td_cbp = LE(DMAADDR(&opipe->u.ctl.reqdma, 0));
|
||||||
setup->nexttd = next;
|
setup->nexttd = next;
|
||||||
setup->td.td_nexttd = LE(next->physaddr);
|
setup->td.td_nexttd = LE(next->physaddr);
|
||||||
setup->td.td_be = LE(LE(setup->td.td_cbp) + sizeof *req - 1);
|
setup->td.td_be = LE(LE(setup->td.td_cbp) + sizeof *req - 1);
|
||||||
@ -2013,7 +2041,7 @@ ohci_root_ctrl_start(xfer)
|
|||||||
index = UGETW(req->wIndex);
|
index = UGETW(req->wIndex);
|
||||||
|
|
||||||
if (len != 0)
|
if (len != 0)
|
||||||
buf = KERNADDR(&xfer->dmabuf);
|
buf = KERNADDR(&xfer->dmabuf, 0);
|
||||||
|
|
||||||
#define C(x,y) ((x) | ((y) << 8))
|
#define C(x,y) ((x) | ((y) << 8))
|
||||||
switch(C(req->bRequest, req->bmRequestType)) {
|
switch(C(req->bRequest, req->bmRequestType)) {
|
||||||
@ -2616,7 +2644,7 @@ ohci_device_intr_start(xfer)
|
|||||||
OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
|
OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
|
||||||
if (xfer->flags & USBD_SHORT_XFER_OK)
|
if (xfer->flags & USBD_SHORT_XFER_OK)
|
||||||
data->td.td_flags |= LE(OHCI_TD_R);
|
data->td.td_flags |= LE(OHCI_TD_R);
|
||||||
data->td.td_cbp = LE(DMAADDR(&xfer->dmabuf));
|
data->td.td_cbp = LE(DMAADDR(&xfer->dmabuf, 0));
|
||||||
data->nexttd = tail;
|
data->nexttd = tail;
|
||||||
data->td.td_nexttd = LE(tail->physaddr);
|
data->td.td_nexttd = LE(tail->physaddr);
|
||||||
data->td.td_be = LE(LE(data->td.td_cbp) + len - 1);
|
data->td.td_be = LE(LE(data->td.td_cbp) + len - 1);
|
||||||
@ -2826,7 +2854,7 @@ ohci_device_isoc_enter(xfer)
|
|||||||
|
|
||||||
s = splusb();
|
s = splusb();
|
||||||
sitd = opipe->tail.itd;
|
sitd = opipe->tail.itd;
|
||||||
buf = DMAADDR(&xfer->dmabuf);
|
buf = DMAADDR(&xfer->dmabuf, 0);
|
||||||
sitd->itd.itd_bp0 = LE(buf & OHCI_ITD_PAGE_MASK);
|
sitd->itd.itd_bp0 = LE(buf & OHCI_ITD_PAGE_MASK);
|
||||||
nframes = xfer->nframes;
|
nframes = xfer->nframes;
|
||||||
offs = buf & OHCI_ITD_OFFSET_MASK;
|
offs = buf & OHCI_ITD_OFFSET_MASK;
|
||||||
|
@ -143,6 +143,7 @@ struct ohci_hcca {
|
|||||||
|
|
||||||
#define OHCI_PAGE_SIZE 0x1000
|
#define OHCI_PAGE_SIZE 0x1000
|
||||||
#define OHCI_PAGE(x) ((x) &~ 0xfff)
|
#define OHCI_PAGE(x) ((x) &~ 0xfff)
|
||||||
|
#define OHCI_PAGE_MASK(x) ((x) & 0xfff)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u_int32_t ed_flags;
|
u_int32_t ed_flags;
|
||||||
|
@ -368,9 +368,9 @@ uhci_init(sc)
|
|||||||
UHCI_FRAMELIST_ALIGN, &sc->sc_dma);
|
UHCI_FRAMELIST_ALIGN, &sc->sc_dma);
|
||||||
if (err)
|
if (err)
|
||||||
return (err);
|
return (err);
|
||||||
sc->sc_pframes = KERNADDR(&sc->sc_dma);
|
sc->sc_pframes = KERNADDR(&sc->sc_dma, 0);
|
||||||
UWRITE2(sc, UHCI_FRNUM, 0); /* set frame number to 0 */
|
UWRITE2(sc, UHCI_FRNUM, 0); /* set frame number to 0 */
|
||||||
UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma)); /* set frame list*/
|
UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma, 0)); /* set frame list*/
|
||||||
|
|
||||||
/* Allocate the dummy QH where bulk traffic will be queued. */
|
/* Allocate the dummy QH where bulk traffic will be queued. */
|
||||||
bsqh = uhci_alloc_sqh(sc);
|
bsqh = uhci_alloc_sqh(sc);
|
||||||
@ -761,7 +761,7 @@ uhci_timo(addr)
|
|||||||
|
|
||||||
usb_timeout(uhci_timo, xfer, sc->sc_ival, xfer->timo_handle);
|
usb_timeout(uhci_timo, xfer, sc->sc_ival, xfer->timo_handle);
|
||||||
|
|
||||||
p = KERNADDR(&xfer->dmabuf);
|
p = KERNADDR(&xfer->dmabuf, 0);
|
||||||
p[0] = 0;
|
p[0] = 0;
|
||||||
if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC))
|
if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC))
|
||||||
p[0] |= 1<<1;
|
p[0] |= 1<<1;
|
||||||
@ -1345,8 +1345,8 @@ uhci_alloc_std(sc)
|
|||||||
return (0);
|
return (0);
|
||||||
for(i = 0; i < UHCI_STD_CHUNK; i++) {
|
for(i = 0; i < UHCI_STD_CHUNK; i++) {
|
||||||
offs = i * UHCI_STD_SIZE;
|
offs = i * UHCI_STD_SIZE;
|
||||||
std = (uhci_soft_td_t *)((char *)KERNADDR(&dma) +offs);
|
std = (uhci_soft_td_t *)((char *)KERNADDR(&dma, offs));
|
||||||
std->physaddr = DMAADDR(&dma) + offs;
|
std->physaddr = DMAADDR(&dma, offs);
|
||||||
std->link.std = sc->sc_freetds;
|
std->link.std = sc->sc_freetds;
|
||||||
sc->sc_freetds = std;
|
sc->sc_freetds = std;
|
||||||
}
|
}
|
||||||
@ -1391,8 +1391,8 @@ uhci_alloc_sqh(sc)
|
|||||||
return (0);
|
return (0);
|
||||||
for(i = 0; i < UHCI_SQH_CHUNK; i++) {
|
for(i = 0; i < UHCI_SQH_CHUNK; i++) {
|
||||||
offs = i * UHCI_SQH_SIZE;
|
offs = i * UHCI_SQH_SIZE;
|
||||||
sqh = (uhci_soft_qh_t *)((char *)KERNADDR(&dma) +offs);
|
sqh = (uhci_soft_qh_t *)((char *)KERNADDR(&dma, offs));
|
||||||
sqh->physaddr = DMAADDR(&dma) + offs;
|
sqh->physaddr = DMAADDR(&dma, offs);
|
||||||
sqh->hlink = sc->sc_freeqhs;
|
sqh->hlink = sc->sc_freeqhs;
|
||||||
sc->sc_freeqhs = sqh;
|
sc->sc_freeqhs = sqh;
|
||||||
}
|
}
|
||||||
@ -1512,7 +1512,7 @@ uhci_alloc_std_chain(upipe, sc, len, rd, flags, dma, sp, ep)
|
|||||||
p->td.td_token =
|
p->td.td_token =
|
||||||
LE(rd ? UHCI_TD_IN (l, endpt, addr, tog) :
|
LE(rd ? UHCI_TD_IN (l, endpt, addr, tog) :
|
||||||
UHCI_TD_OUT(l, endpt, addr, tog));
|
UHCI_TD_OUT(l, endpt, addr, tog));
|
||||||
p->td.td_buffer = LE(DMAADDR(dma) + i * maxp);
|
p->td.td_buffer = LE(DMAADDR(dma, i * maxp));
|
||||||
tog ^= 1;
|
tog ^= 1;
|
||||||
}
|
}
|
||||||
*sp = lastp;
|
*sp = lastp;
|
||||||
@ -1957,13 +1957,13 @@ uhci_device_request(xfer)
|
|||||||
}
|
}
|
||||||
upipe->u.ctl.length = len;
|
upipe->u.ctl.length = len;
|
||||||
|
|
||||||
memcpy(KERNADDR(&upipe->u.ctl.reqdma), req, sizeof *req);
|
memcpy(KERNADDR(&upipe->u.ctl.reqdma, 0), req, sizeof *req);
|
||||||
|
|
||||||
setup->link.std = next;
|
setup->link.std = next;
|
||||||
setup->td.td_link = LE(next->physaddr | UHCI_PTR_VF);
|
setup->td.td_link = LE(next->physaddr | UHCI_PTR_VF);
|
||||||
setup->td.td_status = LE(UHCI_TD_SET_ERRCNT(3) | ls | UHCI_TD_ACTIVE);
|
setup->td.td_status = LE(UHCI_TD_SET_ERRCNT(3) | ls | UHCI_TD_ACTIVE);
|
||||||
setup->td.td_token = LE(UHCI_TD_SETUP(sizeof *req, endpt, addr));
|
setup->td.td_token = LE(UHCI_TD_SETUP(sizeof *req, endpt, addr));
|
||||||
setup->td.td_buffer = LE(DMAADDR(&upipe->u.ctl.reqdma));
|
setup->td.td_buffer = LE(DMAADDR(&upipe->u.ctl.reqdma, 0));
|
||||||
|
|
||||||
stat->link.std = 0;
|
stat->link.std = 0;
|
||||||
stat->td.td_link = LE(UHCI_PTR_T);
|
stat->td.td_link = LE(UHCI_PTR_T);
|
||||||
@ -2101,7 +2101,7 @@ uhci_device_isoc_enter(xfer)
|
|||||||
xfer->status = USBD_IN_PROGRESS;
|
xfer->status = USBD_IN_PROGRESS;
|
||||||
xfer->hcprivint = next;
|
xfer->hcprivint = next;
|
||||||
|
|
||||||
buf = DMAADDR(&xfer->dmabuf);
|
buf = DMAADDR(&xfer->dmabuf, 0);
|
||||||
status = LE(UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) |
|
status = LE(UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) |
|
||||||
UHCI_TD_ACTIVE |
|
UHCI_TD_ACTIVE |
|
||||||
UHCI_TD_IOS));
|
UHCI_TD_IOS));
|
||||||
@ -2745,7 +2745,7 @@ uhci_root_ctrl_start(xfer)
|
|||||||
index = UGETW(req->wIndex);
|
index = UGETW(req->wIndex);
|
||||||
|
|
||||||
if (len != 0)
|
if (len != 0)
|
||||||
buf = KERNADDR(&xfer->dmabuf);
|
buf = KERNADDR(&xfer->dmabuf, 0);
|
||||||
|
|
||||||
#define C(x,y) ((x) | ((y) << 8))
|
#define C(x,y) ((x) | ((y) << 8))
|
||||||
switch(C(req->bRequest, req->bmRequestType)) {
|
switch(C(req->bRequest, req->bmRequestType)) {
|
||||||
|
@ -51,8 +51,8 @@ typedef struct usb_dma_block {
|
|||||||
LIST_ENTRY(usb_dma_block) next;
|
LIST_ENTRY(usb_dma_block) next;
|
||||||
} usb_dma_block_t;
|
} usb_dma_block_t;
|
||||||
|
|
||||||
#define DMAADDR(dma) ((dma)->block->segs[0].ds_addr + (dma)->offs)
|
#define DMAADDR(dma, offset) ((dma)->block->segs[0].ds_addr + (dma)->offs + (offset))
|
||||||
#define KERNADDR(dma) ((void *)((dma)->block->kaddr + (dma)->offs))
|
#define KERNADDR(dma, offset) ((void *)((dma)->block->kaddr + (dma)->offs) + (offset))
|
||||||
|
|
||||||
usbd_status usb_allocmem __P((usbd_bus_handle,size_t,size_t, usb_dma_t *));
|
usbd_status usb_allocmem __P((usbd_bus_handle,size_t,size_t, usb_dma_t *));
|
||||||
void usb_freemem __P((usbd_bus_handle, usb_dma_t *));
|
void usb_freemem __P((usbd_bus_handle, usb_dma_t *));
|
||||||
@ -80,10 +80,10 @@ void usb_freemem __P((usbd_bus_handle, usb_dma_t *));
|
|||||||
#define usb_freemem(t,p) (free(*(p), M_USB))
|
#define usb_freemem(t,p) (free(*(p), M_USB))
|
||||||
|
|
||||||
#ifdef __alpha__
|
#ifdef __alpha__
|
||||||
#define DMAADDR(dma) (alpha_XXX_dmamap((vm_offset_t) *(dma)))
|
#define DMAADDR(dma, offset) (alpha_XXX_dmamap((vm_offset_t) *(dma) + (offset)))
|
||||||
#else
|
#else
|
||||||
#define DMAADDR(dma) (vtophys(*(dma)))
|
#define DMAADDR(dma, offset) (vtophys(*(dma) + (offset)))
|
||||||
#endif
|
#endif
|
||||||
#define KERNADDR(dma) ((void *) *(dma))
|
#define KERNADDR(dma, offset) ((void *) (*(dma) + (offset)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -275,7 +275,7 @@ __CONCAT(dname,_detach)(self, flags) \
|
|||||||
#define USBDEVPTRNAME(bdev) device_get_nameunit(bdev)
|
#define USBDEVPTRNAME(bdev) device_get_nameunit(bdev)
|
||||||
#define USBDEVUNIT(bdev) device_get_unit(bdev)
|
#define USBDEVUNIT(bdev) device_get_unit(bdev)
|
||||||
|
|
||||||
#define DECLARE_USB_DMA_T typedef void * usb_dma_t
|
#define DECLARE_USB_DMA_T typedef char * usb_dma_t
|
||||||
|
|
||||||
/* XXX Change this when FreeBSD has memset */
|
/* XXX Change this when FreeBSD has memset */
|
||||||
#define memcpy(d, s, l) bcopy((s),(d),(l))
|
#define memcpy(d, s, l) bcopy((s),(d),(l))
|
||||||
|
@ -282,7 +282,7 @@ usbd_transfer(xfer)
|
|||||||
/* Copy data if going out. */
|
/* Copy data if going out. */
|
||||||
if (!(xfer->flags & USBD_NO_COPY) && size != 0 &&
|
if (!(xfer->flags & USBD_NO_COPY) && size != 0 &&
|
||||||
!usbd_xfer_isread(xfer))
|
!usbd_xfer_isread(xfer))
|
||||||
memcpy(KERNADDR(dmap), xfer->buffer, size);
|
memcpy(KERNADDR(dmap, 0), xfer->buffer, size);
|
||||||
|
|
||||||
err = pipe->methods->transfer(xfer);
|
err = pipe->methods->transfer(xfer);
|
||||||
|
|
||||||
@ -348,7 +348,7 @@ usbd_alloc_buffer(xfer, size)
|
|||||||
if (err)
|
if (err)
|
||||||
return (0);
|
return (0);
|
||||||
xfer->rqflags |= URQ_DEV_DMABUF;
|
xfer->rqflags |= URQ_DEV_DMABUF;
|
||||||
return (KERNADDR(&xfer->dmabuf));
|
return (KERNADDR(&xfer->dmabuf, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -371,7 +371,7 @@ usbd_get_buffer(xfer)
|
|||||||
{
|
{
|
||||||
if (!(xfer->rqflags & URQ_DEV_DMABUF))
|
if (!(xfer->rqflags & URQ_DEV_DMABUF))
|
||||||
return (0);
|
return (0);
|
||||||
return (KERNADDR(&xfer->dmabuf));
|
return (KERNADDR(&xfer->dmabuf, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
usbd_xfer_handle
|
usbd_xfer_handle
|
||||||
@ -800,7 +800,7 @@ usb_transfer_complete(xfer)
|
|||||||
xfer->actlen = xfer->length;
|
xfer->actlen = xfer->length;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
memcpy(xfer->buffer, KERNADDR(dmap), xfer->actlen);
|
memcpy(xfer->buffer, KERNADDR(dmap, 0), xfer->actlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we allocated the buffer in usbd_transfer() we free it here. */
|
/* if we allocated the buffer in usbd_transfer() we free it here. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user