mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-17 10:26:15 +00:00
- Improve IT/IR DMA queue management.
- Improve debug message for mbuf handling. - Wait 1 sec for DMA stop in fwohci_i{t,r}x_disable() before freeing buffers.
This commit is contained in:
parent
8d48318bbb
commit
5a7ba74dc4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=109890
@ -121,184 +121,6 @@ static driver_t firewire_driver = {
|
||||
sizeof(struct firewire_softc),
|
||||
};
|
||||
|
||||
/*
|
||||
* transmitter buffer update.
|
||||
*/
|
||||
int
|
||||
fw_tbuf_update(struct firewire_comm *fc, int sub, int flag){
|
||||
struct fw_bulkxfer *bulkxfer, *bulkxfer2 = NULL;
|
||||
struct fw_xferq *it;
|
||||
int s, err = 0;
|
||||
|
||||
it = fc->it[sub];
|
||||
|
||||
s = splfw();
|
||||
if(it->stdma == NULL){
|
||||
bulkxfer = STAILQ_FIRST(&it->stvalid);
|
||||
}else if(flag != 0){
|
||||
bulkxfer = STAILQ_FIRST(&it->stvalid);
|
||||
if(bulkxfer == it->stdma){
|
||||
STAILQ_REMOVE_HEAD(&it->stvalid, link);
|
||||
it->stdma->flag = 0;
|
||||
STAILQ_INSERT_TAIL(&it->stfree, it->stdma, link);
|
||||
#ifdef FWXFERQ_DV
|
||||
if(!(it->flag & FWXFERQ_DV))
|
||||
#endif
|
||||
wakeup(it);
|
||||
}
|
||||
bulkxfer = STAILQ_FIRST(&it->stvalid);
|
||||
}else{
|
||||
bulkxfer = it->stdma;
|
||||
}
|
||||
if(bulkxfer != NULL){
|
||||
bulkxfer2 = STAILQ_NEXT(bulkxfer, link);
|
||||
#if 0
|
||||
if(it->flag & FWXFERQ_DV && bulkxfer2 == NULL){
|
||||
bulkxfer2 = STAILQ_FIRST(&it->stfree);
|
||||
STAILQ_REMOVE_HEAD(&it->stfree, link);
|
||||
bcopy(bulkxfer->buf, bulkxfer2->buf,
|
||||
it->psize * it->btpacket);
|
||||
STAILQ_INSERT_TAIL(&it->stvalid, bulkxfer2, link);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
it->stdma = bulkxfer;
|
||||
it->stdma2 = bulkxfer2;
|
||||
|
||||
#ifdef FWXFERQ_DV
|
||||
if(it->flag & FWXFERQ_DV){
|
||||
struct fw_dvbuf *dvbuf = NULL;
|
||||
int i, j, chtag;
|
||||
struct fw_pkt *fp;
|
||||
u_int64_t cycle, dvsync;
|
||||
|
||||
chtag = it->flag & 0xff;
|
||||
dvloop:
|
||||
if(it->dvdma == NULL){
|
||||
dvbuf = STAILQ_FIRST(&it->dvvalid);
|
||||
if(dvbuf != NULL){
|
||||
STAILQ_REMOVE_HEAD(&it->dvvalid, link);
|
||||
it->dvdma = dvbuf;
|
||||
it->queued = 0;
|
||||
}
|
||||
}
|
||||
if(it->dvdma == NULL)
|
||||
goto out;
|
||||
|
||||
it->stproc = STAILQ_FIRST(&it->stfree);
|
||||
if(it->stproc != NULL){
|
||||
STAILQ_REMOVE_HEAD(&it->stfree, link);
|
||||
}else{
|
||||
goto out;
|
||||
}
|
||||
#if DV_PAL
|
||||
#define DVSEC 3
|
||||
#define DVFRAC 75 /* PAL: 25 Hz (1875 = 25 * 3) */
|
||||
#define DVDIFF 5 /* 125 = (8000/300 - 25) * 3 */
|
||||
#else
|
||||
#define DVSEC 100
|
||||
#define DVFRAC 2997 /* NTSC: 29.97 Hz (2997 = 29.97 * 100) */
|
||||
#define DVDIFF 203 /* 203 = (8000/250 - 29.97) * 100 */
|
||||
#endif
|
||||
#define CYCLEFRAC 0xc00
|
||||
cycle = (u_int64_t) 8000 * DVSEC * it->dvsync;
|
||||
/* least significant 12 bits */
|
||||
dvsync = (cycle * CYCLEFRAC / DVFRAC) % CYCLEFRAC;
|
||||
/* most significat 4 bits */
|
||||
cycle = (cycle / DVFRAC + it->dvoffset) & 0xf;
|
||||
fp = (struct fw_pkt *)(it->dvdma->buf);
|
||||
#if 1
|
||||
fp->mode.ld[2] = htonl(0x80000000 | (cycle << 12) | dvsync);
|
||||
#else
|
||||
fp->mode.ld[2] = htonl(0x80000000 | dvsync);
|
||||
#endif
|
||||
it->dvsync ++;
|
||||
it->dvsync %= 2997;
|
||||
|
||||
for( i = 0, j = 0 ; i < it->dvpacket ; i++){
|
||||
bcopy(it->dvdma->buf + it->queued * it->psize,
|
||||
it->stproc->buf + j * it->psize, it->psize);
|
||||
fp = (struct fw_pkt *)(it->stproc->buf + j * it->psize);
|
||||
fp->mode.stream.len = htons(488);
|
||||
fp->mode.stream.chtag = chtag;
|
||||
fp->mode.stream.tcode = FWTCODE_STREAM;
|
||||
fp->mode.ld[1] = htonl((fc->nodeid << 24) | 0x00780000 | it->dvdbc);
|
||||
it->dvdbc++;
|
||||
it->dvdbc %= 256;
|
||||
it->queued ++;
|
||||
j++;
|
||||
it->dvdiff += DVDIFF;
|
||||
if(it->dvdiff >= DVFRAC){
|
||||
it->dvdiff %= DVFRAC;
|
||||
fp = (struct fw_pkt *)(it->stproc->buf + j * it->psize);
|
||||
|
||||
fp->mode.stream.len = htons(0x8);
|
||||
fp->mode.stream.chtag = chtag;
|
||||
fp->mode.stream.tcode = FWTCODE_STREAM;
|
||||
fp->mode.ld[1] = htonl((fc->nodeid << 24) |
|
||||
0x00780000 | it->dvdbc);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
it->stproc->npacket = j;
|
||||
STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link);
|
||||
if(it->queued >= it->dvpacket){
|
||||
STAILQ_INSERT_TAIL(&it->dvfree, it->dvdma, link);
|
||||
it->dvdma = NULL;
|
||||
wakeup(it);
|
||||
goto dvloop;
|
||||
}
|
||||
}
|
||||
out:
|
||||
#endif
|
||||
splx(s);
|
||||
return err;
|
||||
}
|
||||
/*
|
||||
* receving buffer update.
|
||||
*/
|
||||
int
|
||||
fw_rbuf_update(struct firewire_comm *fc, int sub, int flag){
|
||||
struct fw_bulkxfer *bulkxfer, *bulkxfer2 = NULL;
|
||||
struct fw_xferq *ir;
|
||||
int s, err = 0;
|
||||
|
||||
ir = fc->ir[sub];
|
||||
s = splfw();
|
||||
if(ir->stdma != NULL){
|
||||
if(flag != 0){
|
||||
STAILQ_INSERT_TAIL(&ir->stvalid, ir->stdma, link);
|
||||
}else{
|
||||
ir->stdma->flag = 0;
|
||||
STAILQ_INSERT_TAIL(&ir->stfree, ir->stdma, link);
|
||||
}
|
||||
}
|
||||
if(ir->stdma2 != NULL){
|
||||
bulkxfer = ir->stdma2;
|
||||
bulkxfer2 = STAILQ_FIRST(&ir->stfree);
|
||||
if(bulkxfer2 != NULL){
|
||||
STAILQ_REMOVE_HEAD(&ir->stfree, link);
|
||||
}
|
||||
}else{
|
||||
bulkxfer = STAILQ_FIRST(&ir->stfree);
|
||||
if(bulkxfer != NULL){
|
||||
STAILQ_REMOVE_HEAD(&ir->stfree, link);
|
||||
bulkxfer2 = STAILQ_FIRST(&ir->stfree);
|
||||
if(bulkxfer2 != NULL){
|
||||
STAILQ_REMOVE_HEAD(&ir->stfree, link);
|
||||
}
|
||||
}else{
|
||||
device_printf(fc->bdev, "no free chunk available\n");
|
||||
bulkxfer = STAILQ_FIRST(&ir->stvalid);
|
||||
STAILQ_REMOVE_HEAD(&ir->stvalid, link);
|
||||
}
|
||||
}
|
||||
splx(s);
|
||||
ir->stdma = bulkxfer;
|
||||
ir->stdma2 = bulkxfer2;
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* To lookup node id. from EUI64.
|
||||
*/
|
||||
|
@ -186,7 +186,7 @@ struct fw_xferq {
|
||||
|
||||
#define FWXFERQ_PACKET (1 << 10)
|
||||
#define FWXFERQ_BULK (1 << 11)
|
||||
#if 0
|
||||
#if 0 /* BROKEN */
|
||||
#define FWXFERQ_DV (1 << 12)
|
||||
#endif
|
||||
#define FWXFERQ_MODEMASK (7 << 10)
|
||||
@ -213,10 +213,9 @@ struct fw_xferq {
|
||||
struct fw_bulkxfer *bulkxfer;
|
||||
STAILQ_HEAD(, fw_bulkxfer) stvalid;
|
||||
STAILQ_HEAD(, fw_bulkxfer) stfree;
|
||||
struct fw_bulkxfer *stdma;
|
||||
struct fw_bulkxfer *stdma2;
|
||||
STAILQ_HEAD(, fw_bulkxfer) stdma;
|
||||
struct fw_bulkxfer *stproc;
|
||||
u_int procptr;
|
||||
#ifdef FWXFERQ_DV
|
||||
int dvdbc, dvdiff, dvsync, dvoffset;
|
||||
struct fw_dvbuf *dvbuf;
|
||||
STAILQ_HEAD(, fw_dvbuf) dvvalid;
|
||||
@ -225,14 +224,13 @@ struct fw_xferq {
|
||||
struct fw_dvbuf *dvproc;
|
||||
u_int dvptr;
|
||||
u_int dvpacket;
|
||||
u_int need_wakeup;
|
||||
#endif
|
||||
struct selinfo rsel;
|
||||
caddr_t sc;
|
||||
void (*hand) __P((struct fw_xferq *));
|
||||
};
|
||||
|
||||
struct fw_bulkxfer{
|
||||
u_int32_t flag;
|
||||
caddr_t buf;
|
||||
STAILQ_ENTRY(fw_bulkxfer) link;
|
||||
caddr_t start;
|
||||
|
@ -173,7 +173,9 @@ fw_close (dev_t dev, int flags, int fmt, fw_proc *td)
|
||||
sc->fc->it[sub]->buf = NULL;
|
||||
free(sc->fc->it[sub]->bulkxfer, M_DEVBUF);
|
||||
sc->fc->it[sub]->bulkxfer = NULL;
|
||||
#ifdef FWXFERQ_DV
|
||||
sc->fc->it[sub]->dvbuf = NULL;
|
||||
#endif
|
||||
sc->fc->it[sub]->flag &= ~FWXFERQ_EXTBUF;
|
||||
sc->fc->it[sub]->psize = 0;
|
||||
sc->fc->it[sub]->maxq = FWMAXQUEUE;
|
||||
@ -284,24 +286,12 @@ fw_read (dev_t dev, struct uio *uio, int ioflag)
|
||||
ir->queued ++;
|
||||
if(ir->queued >= ir->bnpacket){
|
||||
s = splfw();
|
||||
ir->stproc->flag = 0;
|
||||
STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link);
|
||||
splx(s);
|
||||
sc->fc->irx_enable(sc->fc, sub);
|
||||
ir->stproc = NULL;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
if(STAILQ_FIRST(&ir->q) == NULL &&
|
||||
(ir->flag & FWXFERQ_RUNNING) && (ir->flag & FWXFERQ_PACKET)){
|
||||
err = sc->fc->irx_enable(sc->fc, sub);
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
if(STAILQ_FIRST(&ir->stvalid) == NULL &&
|
||||
(ir->flag & FWXFERQ_RUNNING) && !(ir->flag & FWXFERQ_PACKET)){
|
||||
err = sc->fc->irx_enable(sc->fc, sub);
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -357,7 +347,6 @@ fw_write (dev_t dev, struct uio *uio, int ioflag)
|
||||
/* Discard unsent buffered stream packet, when sending Asyrequrst */
|
||||
if(xferq != NULL && it->stproc != NULL){
|
||||
s = splfw();
|
||||
it->stproc->flag = 0;
|
||||
STAILQ_INSERT_TAIL(&it->stfree, it->stproc, link);
|
||||
splx(s);
|
||||
it->stproc = NULL;
|
||||
@ -368,14 +357,14 @@ fw_write (dev_t dev, struct uio *uio, int ioflag)
|
||||
if (xferq == NULL) {
|
||||
#endif
|
||||
isoloop:
|
||||
if(it->stproc == NULL){
|
||||
if (it->stproc == NULL) {
|
||||
it->stproc = STAILQ_FIRST(&it->stfree);
|
||||
if(it->stproc != NULL){
|
||||
if (it->stproc != NULL) {
|
||||
s = splfw();
|
||||
STAILQ_REMOVE_HEAD(&it->stfree, link);
|
||||
splx(s);
|
||||
it->queued = 0;
|
||||
}else if(slept == 0){
|
||||
} else if (slept == 0) {
|
||||
slept = 1;
|
||||
err = sc->fc->itx_enable(sc->fc, sub);
|
||||
if(err){
|
||||
@ -391,10 +380,6 @@ fw_write (dev_t dev, struct uio *uio, int ioflag)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#if 0 /* What's this for? (overwritten by the following uiomove)*/
|
||||
fp = (struct fw_pkt *)(it->stproc->buf + it->queued * it->psize);
|
||||
fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t));
|
||||
#endif
|
||||
err = uiomove(it->stproc->buf + it->queued * it->psize,
|
||||
uio->uio_resid, uio);
|
||||
it->queued ++;
|
||||
@ -403,7 +388,6 @@ fw_write (dev_t dev, struct uio *uio, int ioflag)
|
||||
STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link);
|
||||
splx(s);
|
||||
it->stproc = NULL;
|
||||
fw_tbuf_update(sc->fc, sub, 0);
|
||||
err = sc->fc->itx_enable(sc->fc, sub);
|
||||
}
|
||||
return err;
|
||||
@ -684,22 +668,23 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
it->bnpacket = ibufreq->tx.npacket;
|
||||
it->btpacket = ibufreq->tx.npacket;
|
||||
it->psize = (ibufreq->tx.psize + 3) & ~3;
|
||||
ir->queued = 0;
|
||||
it->queued = 0;
|
||||
|
||||
#ifdef FWXFERQ_DV
|
||||
it->dvdbc = 0;
|
||||
it->dvdiff = 0;
|
||||
it->dvsync = 0;
|
||||
it->dvoffset = 0;
|
||||
#endif
|
||||
|
||||
STAILQ_INIT(&ir->stvalid);
|
||||
STAILQ_INIT(&ir->stfree);
|
||||
ir->stdma = NULL;
|
||||
ir->stdma2 = NULL;
|
||||
STAILQ_INIT(&ir->stdma);
|
||||
ir->stproc = NULL;
|
||||
|
||||
STAILQ_INIT(&it->stvalid);
|
||||
STAILQ_INIT(&it->stfree);
|
||||
it->stdma = NULL;
|
||||
it->stdma2 = NULL;
|
||||
STAILQ_INIT(&it->stdma);
|
||||
it->stproc = NULL;
|
||||
|
||||
for(i = 0 ; i < sc->fc->ir[sub]->bnchunk; i++){
|
||||
@ -707,7 +692,6 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
ir->buf +
|
||||
i * sc->fc->ir[sub]->bnpacket *
|
||||
sc->fc->ir[sub]->psize;
|
||||
ir->bulkxfer[i].flag = 0;
|
||||
STAILQ_INSERT_TAIL(&ir->stfree,
|
||||
&ir->bulkxfer[i], link);
|
||||
ir->bulkxfer[i].npacket = ir->bnpacket;
|
||||
@ -717,7 +701,6 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
it->buf +
|
||||
i * sc->fc->it[sub]->bnpacket *
|
||||
sc->fc->it[sub]->psize;
|
||||
it->bulkxfer[i].flag = 0;
|
||||
STAILQ_INSERT_TAIL(&it->stfree,
|
||||
&it->bulkxfer[i], link);
|
||||
it->bulkxfer[i].npacket = it->bnpacket;
|
||||
|
@ -42,6 +42,7 @@
|
||||
#define IRX_CH 0x24
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mbuf.h>
|
||||
@ -847,17 +848,15 @@ fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
|
||||
|
||||
db_tr->dbcnt++;
|
||||
} else {
|
||||
int mchain=0;
|
||||
/* XXX we assume mbuf chain is shorter than ndesc */
|
||||
for (m = xfer->mbuf; m != NULL; m = m->m_next) {
|
||||
if (m->m_len == 0)
|
||||
/* unrecoverable error could ocurre. */
|
||||
/* unrecoverable error could occur. */
|
||||
continue;
|
||||
mchain++;
|
||||
if (db_tr->dbcnt >= dbch->ndesc)
|
||||
continue;
|
||||
if (db_tr->dbcnt >= dbch->ndesc) {
|
||||
device_printf(sc->fc.dev,
|
||||
"dbch->ndesc is too small"
|
||||
", trancated.\n");
|
||||
break;
|
||||
}
|
||||
db->db.desc.addr
|
||||
= vtophys(mtod(m, caddr_t));
|
||||
db->db.desc.cmd = OHCI_OUTPUT_MORE | m->m_len;
|
||||
@ -865,6 +864,11 @@ fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
|
||||
db++;
|
||||
db_tr->dbcnt++;
|
||||
}
|
||||
if (mchain > dbch->ndesc - 2)
|
||||
device_printf(sc->fc.dev,
|
||||
"dbch->ndesc(%d) is too small for"
|
||||
" mbuf chain(%d), trancated.\n",
|
||||
dbch->ndesc, mchain);
|
||||
}
|
||||
}
|
||||
if (maxdesc < db_tr->dbcnt) {
|
||||
@ -1201,9 +1205,13 @@ static int
|
||||
fwohci_itx_disable(struct firewire_comm *fc, int dmach)
|
||||
{
|
||||
struct fwohci_softc *sc = (struct fwohci_softc *)fc;
|
||||
int dummy;
|
||||
|
||||
OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
|
||||
OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
|
||||
OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
|
||||
/* XXX we cannot free buffers until the DMA really stops */
|
||||
tsleep((void *)&dummy, FWPRI, "fwitxd", hz);
|
||||
fwohci_db_free(&sc->it[dmach]);
|
||||
sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
|
||||
return 0;
|
||||
@ -1213,10 +1221,13 @@ static int
|
||||
fwohci_irx_disable(struct firewire_comm *fc, int dmach)
|
||||
{
|
||||
struct fwohci_softc *sc = (struct fwohci_softc *)fc;
|
||||
int dummy;
|
||||
|
||||
OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
|
||||
OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
|
||||
OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
|
||||
/* XXX we cannot free buffers until the DMA really stops */
|
||||
tsleep((void *)&dummy, FWPRI, "fwirxd", hz);
|
||||
if(sc->ir[dmach].dummy != NULL){
|
||||
free(sc->ir[dmach].dummy, M_DEVBUF);
|
||||
}
|
||||
@ -1415,6 +1426,33 @@ fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
fwochi_next_cycle(struct firewire_comm *fc, int cycle_now)
|
||||
{
|
||||
int sec, cycle, cycle_match;
|
||||
|
||||
cycle = cycle_now & 0x1fff;
|
||||
sec = cycle_now >> 13;
|
||||
#define CYCLE_MOD 0x10
|
||||
#define CYCLE_DELAY 8 /* min delay to start DMA */
|
||||
cycle = cycle + CYCLE_DELAY;
|
||||
if (cycle >= 8000) {
|
||||
sec ++;
|
||||
cycle -= 8000;
|
||||
}
|
||||
cycle = ((cycle + CYCLE_MOD - 1) / CYCLE_MOD) * CYCLE_MOD;
|
||||
if (cycle >= 8000) {
|
||||
sec ++;
|
||||
if (cycle == 8000)
|
||||
cycle = 0;
|
||||
else
|
||||
cycle = CYCLE_MOD;
|
||||
}
|
||||
cycle_match = ((sec << 13) | cycle) & 0x7ffff;
|
||||
|
||||
return(cycle_match);
|
||||
}
|
||||
|
||||
static int
|
||||
fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
|
||||
{
|
||||
@ -1422,15 +1460,18 @@ fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
|
||||
int err = 0;
|
||||
unsigned short tag, ich;
|
||||
struct fwohci_dbch *dbch;
|
||||
int cycle_now, sec, cycle, cycle_match;
|
||||
int cycle_match, cycle_now, s, ldesc;
|
||||
u_int32_t stat;
|
||||
struct fw_bulkxfer *first, *chunk, *prev;
|
||||
struct fw_xferq *it;
|
||||
|
||||
tag = (sc->it[dmach].xferq.flag >> 6) & 3;
|
||||
ich = sc->it[dmach].xferq.flag & 0x3f;
|
||||
dbch = &sc->it[dmach];
|
||||
it = &dbch->xferq;
|
||||
|
||||
tag = (it->flag >> 6) & 3;
|
||||
ich = it->flag & 0x3f;
|
||||
if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) {
|
||||
dbch->xferq.queued = 0;
|
||||
dbch->ndb = dbch->xferq.bnpacket * dbch->xferq.bnchunk;
|
||||
dbch->ndb = it->bnpacket * it->bnchunk;
|
||||
dbch->ndesc = 3;
|
||||
fwohci_db_init(dbch);
|
||||
if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
|
||||
@ -1439,56 +1480,53 @@ fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
|
||||
}
|
||||
if(err)
|
||||
return err;
|
||||
stat = OREAD(sc, OHCI_ITCTL(dmach));
|
||||
if (stat & OHCI_CNTL_DMA_ACTIVE) {
|
||||
if(dbch->xferq.stdma2 != NULL){
|
||||
fwohci_txbufdb(sc, dmach, dbch->xferq.stdma2);
|
||||
((struct fwohcidb_tr *)
|
||||
(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.cmd
|
||||
|= OHCI_BRANCH_ALWAYS;
|
||||
((struct fwohcidb_tr *)
|
||||
(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend =
|
||||
vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
|
||||
((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[0].db.desc.depend =
|
||||
vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
|
||||
((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
|
||||
((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf;
|
||||
} else {
|
||||
device_printf(fc->dev,
|
||||
"fwohci_itxbuf_enable: queue underrun\n");
|
||||
|
||||
s = splfw();
|
||||
prev = STAILQ_LAST(&it->stdma, fw_bulkxfer, link);
|
||||
while ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) {
|
||||
volatile struct fwohcidb *db;
|
||||
|
||||
fwohci_txbufdb(sc, dmach, chunk);
|
||||
ldesc = dbch->ndesc - 1;
|
||||
db = ((struct fwohcidb_tr *)(chunk->end))->db;
|
||||
db[ldesc].db.desc.status = db[0].db.desc.status = 0;
|
||||
db[ldesc].db.desc.count = db[0].db.desc.count = 0;
|
||||
db[ldesc].db.desc.depend &= ~0xf;
|
||||
db[0].db.desc.depend &= ~0xf;
|
||||
if (prev != NULL) {
|
||||
db = ((struct fwohcidb_tr *)(prev->end))->db;
|
||||
db[ldesc].db.desc.cmd |= OHCI_BRANCH_ALWAYS;
|
||||
db[ldesc].db.desc.depend = db[0].db.desc.depend =
|
||||
vtophys(((struct fwohcidb_tr *)
|
||||
(chunk->start))->db) | dbch->ndesc;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
if (firewire_debug)
|
||||
printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat);
|
||||
fw_tbuf_update(&sc->fc, dmach, 0);
|
||||
if(dbch->xferq.stdma == NULL){
|
||||
return err;
|
||||
}
|
||||
if(dbch->xferq.stdma2 == NULL){
|
||||
/* wait until 2 chunks buffered */
|
||||
return err;
|
||||
STAILQ_REMOVE_HEAD(&it->stvalid, link);
|
||||
STAILQ_INSERT_TAIL(&it->stdma, chunk, link);
|
||||
prev = chunk;
|
||||
}
|
||||
splx(s);
|
||||
stat = OREAD(sc, OHCI_ITCTL(dmach));
|
||||
if (stat & (OHCI_CNTL_DMA_ACTIVE | OHCI_CNTL_CYCMATCH_S))
|
||||
return 0;
|
||||
|
||||
OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
|
||||
OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
|
||||
OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
|
||||
OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
|
||||
fwohci_txbufdb(sc, dmach, dbch->xferq.stdma);
|
||||
fwohci_txbufdb(sc, dmach, dbch->xferq.stdma2);
|
||||
((struct fwohcidb_tr *)
|
||||
(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.cmd
|
||||
|= OHCI_BRANCH_ALWAYS;
|
||||
((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend =
|
||||
vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
|
||||
((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[0].db.desc.depend =
|
||||
vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
|
||||
((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
|
||||
((struct fwohcidb_tr *) (dbch->xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf;
|
||||
OWRITE(sc, OHCI_ITCMD(dmach),
|
||||
vtophys(((struct fwohcidb_tr *)
|
||||
(dbch->xferq.stdma->start))->db) | dbch->ndesc);
|
||||
#define CYCLE_OFFSET 1
|
||||
|
||||
first = STAILQ_FIRST(&it->stdma);
|
||||
OWRITE(sc, OHCI_ITCMD(dmach), vtophys(((struct fwohcidb_tr *)
|
||||
(first->start))->db) | dbch->ndesc);
|
||||
if (firewire_debug)
|
||||
printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat);
|
||||
if ((stat & OHCI_CNTL_DMA_RUN) == 0) {
|
||||
#if 1
|
||||
/* Don't start until all chunks are buffered */
|
||||
if (STAILQ_FIRST(&it->stfree) != NULL)
|
||||
goto out;
|
||||
#endif
|
||||
#ifdef FWXFERQ_DV
|
||||
#define CYCLE_OFFSET 1
|
||||
if(dbch->xferq.flag & FWXFERQ_DV){
|
||||
struct fw_pkt *fp;
|
||||
struct fwohcidb_tr *db_tr;
|
||||
@ -1499,41 +1537,26 @@ fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
|
||||
fp->mode.ld[2] |= htonl(dbch->xferq.dvoffset << 12);
|
||||
}
|
||||
#endif
|
||||
/* 2bit second + 13bit cycle */
|
||||
cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff;
|
||||
cycle = cycle_now & 0x1fff;
|
||||
sec = cycle_now >> 13;
|
||||
#define CYCLE_MOD 0x10
|
||||
#define CYCLE_DELAY 8 /* min delay to start DMA */
|
||||
cycle = cycle + CYCLE_DELAY;
|
||||
if (cycle >= 8000) {
|
||||
sec ++;
|
||||
cycle -= 8000;
|
||||
}
|
||||
cycle = ((cycle + CYCLE_MOD - 1) / CYCLE_MOD) * CYCLE_MOD;
|
||||
if (cycle >= 8000) {
|
||||
sec ++;
|
||||
if (cycle == 8000)
|
||||
cycle = 0;
|
||||
else
|
||||
cycle = CYCLE_MOD;
|
||||
}
|
||||
cycle_match = ((sec << 13) | cycle) & 0x7ffff;
|
||||
/* Clear cycle match counter bits */
|
||||
OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000);
|
||||
OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
|
||||
|
||||
/* 2bit second + 13bit cycle */
|
||||
cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff;
|
||||
cycle_match = fwochi_next_cycle(fc, cycle_now);
|
||||
|
||||
OWRITE(sc, OHCI_ITCTL(dmach),
|
||||
OHCI_CNTL_CYCMATCH_S | (cycle_match << 16)
|
||||
| OHCI_CNTL_DMA_RUN);
|
||||
OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
|
||||
if (firewire_debug)
|
||||
printf("cycle_match: 0x%04x->0x%04x\n",
|
||||
cycle_now, cycle_match);
|
||||
} else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) {
|
||||
if (firewire_debug)
|
||||
printf("fwohci_itxbuf_enable: restart 0x%08x\n", stat);
|
||||
OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
|
||||
device_printf(sc->fc.dev,
|
||||
"IT DMA underrun (0x%08x)\n", stat);
|
||||
OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
|
||||
}
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1541,71 +1564,84 @@ static int
|
||||
fwohci_irxbuf_enable(struct firewire_comm *fc, int dmach)
|
||||
{
|
||||
struct fwohci_softc *sc = (struct fwohci_softc *)fc;
|
||||
int err = 0;
|
||||
int err = 0, s, ldesc;
|
||||
unsigned short tag, ich;
|
||||
u_int32_t stat;
|
||||
struct fwohci_dbch *dbch;
|
||||
struct fw_bulkxfer *first, *prev, *chunk;
|
||||
struct fw_xferq *ir;
|
||||
|
||||
if(!(sc->ir[dmach].xferq.flag & FWXFERQ_RUNNING)){
|
||||
tag = (sc->ir[dmach].xferq.flag >> 6) & 3;
|
||||
ich = sc->ir[dmach].xferq.flag & 0x3f;
|
||||
dbch = &sc->ir[dmach];
|
||||
ir = &dbch->xferq;
|
||||
ldesc = dbch->ndesc - 1;
|
||||
|
||||
if ((ir->flag & FWXFERQ_RUNNING) == 0) {
|
||||
tag = (ir->flag >> 6) & 3;
|
||||
ich = ir->flag & 0x3f;
|
||||
OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
|
||||
|
||||
sc->ir[dmach].xferq.queued = 0;
|
||||
sc->ir[dmach].ndb = sc->ir[dmach].xferq.bnpacket *
|
||||
sc->ir[dmach].xferq.bnchunk;
|
||||
sc->ir[dmach].dummy =
|
||||
malloc(sizeof(u_int32_t) * sc->ir[dmach].ndb,
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if(sc->ir[dmach].dummy == NULL){
|
||||
ir->queued = 0;
|
||||
dbch->ndb = ir->bnpacket * ir->bnchunk;
|
||||
dbch->dummy = malloc(sizeof(u_int32_t) * dbch->ndb,
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if (dbch->dummy == NULL) {
|
||||
err = ENOMEM;
|
||||
return err;
|
||||
}
|
||||
sc->ir[dmach].ndesc = 2;
|
||||
fwohci_db_init(&sc->ir[dmach]);
|
||||
if ((sc->ir[dmach].flags & FWOHCI_DBCH_INIT) == 0)
|
||||
dbch->ndesc = 2;
|
||||
fwohci_db_init(dbch);
|
||||
if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
|
||||
return ENOMEM;
|
||||
err = fwohci_rx_enable(sc, &sc->ir[dmach]);
|
||||
err = fwohci_rx_enable(sc, dbch);
|
||||
}
|
||||
if(err)
|
||||
return err;
|
||||
|
||||
stat = OREAD(sc, OHCI_IRCTL(dmach));
|
||||
if (stat & OHCI_CNTL_DMA_ACTIVE) {
|
||||
if(sc->ir[dmach].xferq.stdma2 != NULL){
|
||||
((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend =
|
||||
vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db) | sc->ir[dmach].ndesc;
|
||||
((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend =
|
||||
vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db);
|
||||
((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf;
|
||||
((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf;
|
||||
}
|
||||
} else if (!(stat & OHCI_CNTL_DMA_ACTIVE)
|
||||
&& !(sc->ir[dmach].xferq.flag & FWXFERQ_PACKET)) {
|
||||
if (firewire_debug)
|
||||
device_printf(sc->fc.dev, "IR DMA stat %x\n", stat);
|
||||
fw_rbuf_update(&sc->fc, dmach, 0);
|
||||
s = splfw();
|
||||
|
||||
OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
|
||||
OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
|
||||
OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
|
||||
OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
|
||||
OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000);
|
||||
OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
|
||||
if(sc->ir[dmach].xferq.stdma2 != NULL){
|
||||
((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend =
|
||||
vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db) | sc->ir[dmach].ndesc;
|
||||
((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend =
|
||||
vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db);
|
||||
((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf;
|
||||
}else{
|
||||
((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf;
|
||||
((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend &= ~0xf;
|
||||
}
|
||||
OWRITE(sc, OHCI_IRCMD(dmach),
|
||||
vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->start))->db) | sc->ir[dmach].ndesc);
|
||||
OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
|
||||
OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
|
||||
first = STAILQ_FIRST(&ir->stfree);
|
||||
if (first == NULL) {
|
||||
device_printf(fc->dev, "IR DMA no free chunk\n");
|
||||
splx(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
prev = STAILQ_LAST(&ir->stdma, fw_bulkxfer, link);
|
||||
while ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) {
|
||||
volatile struct fwohcidb *db;
|
||||
|
||||
db = ((struct fwohcidb_tr *)(chunk->end))->db;
|
||||
db[ldesc].db.desc.status = db[ldesc].db.desc.count = 0;
|
||||
db[ldesc].db.desc.depend &= ~0xf;
|
||||
if (prev != NULL) {
|
||||
db = ((struct fwohcidb_tr *)(prev->end))->db;
|
||||
db[ldesc].db.desc.depend =
|
||||
vtophys(((struct fwohcidb_tr *)
|
||||
(chunk->start))->db) | dbch->ndesc;
|
||||
}
|
||||
STAILQ_REMOVE_HEAD(&ir->stfree, link);
|
||||
STAILQ_INSERT_TAIL(&ir->stdma, chunk, link);
|
||||
prev = chunk;
|
||||
}
|
||||
splx(s);
|
||||
stat = OREAD(sc, OHCI_IRCTL(dmach));
|
||||
if (stat & OHCI_CNTL_DMA_ACTIVE)
|
||||
return 0;
|
||||
if (stat & OHCI_CNTL_DMA_RUN) {
|
||||
OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
|
||||
device_printf(sc->fc.dev, "IR DMA overrun (0x%08x)\n", stat);
|
||||
}
|
||||
|
||||
OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
|
||||
OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
|
||||
OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
|
||||
OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000);
|
||||
OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
|
||||
OWRITE(sc, OHCI_IRCMD(dmach),
|
||||
vtophys(((struct fwohcidb_tr *)(first->start))->db)
|
||||
| dbch->ndesc);
|
||||
OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
|
||||
OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1959,92 +1995,72 @@ fwohci_set_intr(struct firewire_comm *fc, int enable)
|
||||
static void
|
||||
fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
|
||||
{
|
||||
int stat;
|
||||
struct firewire_comm *fc = &sc->fc;
|
||||
struct fwohci_dbch *dbch;
|
||||
struct fwohcidb_tr *db_tr;
|
||||
volatile struct fwohcidb *db;
|
||||
struct fw_bulkxfer *chunk;
|
||||
struct fw_xferq *it;
|
||||
u_int32_t stat, count;
|
||||
int s, w=0;
|
||||
|
||||
dbch = &sc->it[dmach];
|
||||
#if 0 /* XXX OHCI interrupt before the last packet is really on the wire */
|
||||
if((dbch->xferq.flag & FWXFERQ_DV) && (dbch->xferq.stdma2 != NULL)){
|
||||
db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma2->start;
|
||||
/*
|
||||
* Overwrite highest significant 4 bits timestamp information
|
||||
*/
|
||||
fp = (struct fw_pkt *)db_tr->buf;
|
||||
fp->mode.ld[2] &= htonl(0xffff0fff);
|
||||
fp->mode.ld[2] |= htonl((fc->cyctimer(fc) + 0x4000) & 0xf000);
|
||||
}
|
||||
it = fc->it[dmach];
|
||||
s = splfw(); /* unnecessary ? */
|
||||
while ((chunk = STAILQ_FIRST(&it->stdma)) != NULL) {
|
||||
db = ((struct fwohcidb_tr *)(chunk->end))->db;
|
||||
stat = db[sc->it[dmach].ndesc - 1].db.desc.status;
|
||||
db = ((struct fwohcidb_tr *)(chunk->start))->db;
|
||||
count = db[sc->it[dmach].ndesc - 1].db.desc.count;
|
||||
if (stat == 0)
|
||||
break;
|
||||
STAILQ_REMOVE_HEAD(&it->stdma, link);
|
||||
switch (stat & FWOHCIEV_MASK){
|
||||
case FWOHCIEV_ACKCOMPL:
|
||||
#if 0
|
||||
device_printf(fc->dev, "0x%08x\n", count);
|
||||
#endif
|
||||
/*
|
||||
* XXX interrupt could be missed.
|
||||
* We have to check more than one buffer/chunk
|
||||
*/
|
||||
if (firewire_debug && dbch->xferq.stdma2 != NULL) {
|
||||
db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma2->end;
|
||||
stat = db_tr->db[2].db.desc.status;
|
||||
if (stat)
|
||||
break;
|
||||
default:
|
||||
device_printf(fc->dev,
|
||||
"stdma2 already done stat:0x%x\n", stat);
|
||||
"Isochronous transmit err %02x\n", stat);
|
||||
}
|
||||
STAILQ_INSERT_TAIL(&it->stfree, chunk, link);
|
||||
w++;
|
||||
}
|
||||
|
||||
stat = OREAD(sc, OHCI_ITCTL(dmach)) & 0x1f;
|
||||
switch(stat){
|
||||
case FWOHCIEV_ACKCOMPL:
|
||||
#ifdef FWXFERQ_DV
|
||||
if (dbch->xferq.flag & FWXFERQ_DV) {
|
||||
struct ciphdr *ciph;
|
||||
int timer, timestamp, cycl, diff;
|
||||
static int last_timer=0;
|
||||
struct fw_pkt *fp;
|
||||
|
||||
timer = (fc->cyctimer(fc) >> 12) & 0xffff;
|
||||
db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma->start;
|
||||
fp = (struct fw_pkt *)db_tr->buf;
|
||||
ciph = (struct ciphdr *) &fp->mode.ld[1];
|
||||
timestamp = db_tr->db[2].db.desc.count & 0xffff;
|
||||
cycl = ntohs(ciph->fdf.dv.cyc) >> 12;
|
||||
diff = cycl - (timestamp & 0xf) - CYCLE_OFFSET;
|
||||
if (diff < 0)
|
||||
diff += 16;
|
||||
if (diff > 8)
|
||||
diff -= 16;
|
||||
if (firewire_debug || diff != 0)
|
||||
printf("dbc: %3d timer: 0x%04x packet: 0x%04x"
|
||||
" cyc: 0x%x diff: %+1d\n",
|
||||
ciph->dbc, last_timer, timestamp, cycl, diff);
|
||||
last_timer = timer;
|
||||
/* XXX adjust dbch->xferq.dvoffset if diff != 0 or 1 */
|
||||
}
|
||||
#endif
|
||||
fw_tbuf_update(fc, dmach, 1);
|
||||
break;
|
||||
default:
|
||||
device_printf(fc->dev, "Isochronous transmit err %02x\n", stat);
|
||||
fw_tbuf_update(fc, dmach, 0);
|
||||
break;
|
||||
}
|
||||
fwohci_itxbuf_enable(fc, dmach);
|
||||
splx(s);
|
||||
if (w)
|
||||
wakeup(it);
|
||||
}
|
||||
|
||||
static void
|
||||
fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
|
||||
{
|
||||
struct firewire_comm *fc = &sc->fc;
|
||||
int stat;
|
||||
volatile struct fwohcidb *db;
|
||||
struct fw_bulkxfer *chunk;
|
||||
struct fw_xferq *ir;
|
||||
u_int32_t stat;
|
||||
int s, w=0;
|
||||
|
||||
stat = OREAD(sc, OHCI_IRCTL(dmach)) & 0x1f;
|
||||
switch(stat){
|
||||
case FWOHCIEV_ACKCOMPL:
|
||||
fw_rbuf_update(fc, dmach, 1);
|
||||
wakeup(fc->ir[dmach]);
|
||||
fwohci_irx_enable(fc, dmach);
|
||||
break;
|
||||
default:
|
||||
device_printf(fc->dev, "Isochronous receive err %02x\n",
|
||||
stat);
|
||||
break;
|
||||
ir = fc->ir[dmach];
|
||||
s = splfw();
|
||||
while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
|
||||
db = ((struct fwohcidb_tr *)(chunk->end))->db;
|
||||
stat = db[sc->ir[dmach].ndesc - 1].db.desc.status;
|
||||
if (stat == 0)
|
||||
break;
|
||||
STAILQ_REMOVE_HEAD(&ir->stdma, link);
|
||||
STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link);
|
||||
switch (stat & FWOHCIEV_MASK) {
|
||||
case FWOHCIEV_ACKCOMPL:
|
||||
break;
|
||||
default:
|
||||
device_printf(fc->dev,
|
||||
"Isochronous receive err %02x\n", stat);
|
||||
}
|
||||
w++;
|
||||
}
|
||||
splx(s);
|
||||
if (w)
|
||||
wakeup(ir);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2294,10 +2310,6 @@ fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
|
||||
/*
|
||||
device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, vtophys(db_tr->db), vtophys(fdb_tr->db));
|
||||
*/
|
||||
if(bulkxfer->flag != 0){
|
||||
return;
|
||||
}
|
||||
bulkxfer->flag = 1;
|
||||
for( idb = 0 ; idb < bulkxfer->npacket ; idb ++){
|
||||
db_tr->db[0].db.desc.cmd
|
||||
= OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8;
|
||||
@ -2308,9 +2320,7 @@ device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, vtophys(db_tr->db), v
|
||||
ohcifp->mode.stream.len = ntohs(fp->mode.stream.len);
|
||||
ohcifp->mode.stream.chtag = chtag;
|
||||
ohcifp->mode.stream.tcode = 0xa;
|
||||
ohcifp->mode.stream.spd = 4;
|
||||
ohcifp->mode.ld[2] = ntohl(fp->mode.ld[1]);
|
||||
ohcifp->mode.ld[3] = ntohl(fp->mode.ld[2]);
|
||||
ohcifp->mode.stream.spd = 0;
|
||||
|
||||
db_tr->db[2].db.desc.cmd
|
||||
= OHCI_OUTPUT_LAST
|
||||
@ -2329,12 +2339,6 @@ device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, vtophys(db_tr->db), v
|
||||
db_tr = (struct fwohcidb_tr *)bulkxfer->end;
|
||||
db_tr->db[0].db.desc.depend &= ~0xf;
|
||||
db_tr->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
|
||||
#if 0
|
||||
/**/
|
||||
db_tr->db[dbch->ndesc - 1].db.desc.cmd &= ~OHCI_BRANCH_ALWAYS;
|
||||
db_tr->db[dbch->ndesc - 1].db.desc.cmd |= OHCI_BRANCH_NEVER;
|
||||
/**/
|
||||
#endif
|
||||
db_tr->db[dbch->ndesc - 1].db.desc.cmd |= OHCI_INTERRUPT_ALWAYS;
|
||||
/* OHCI 1.1 and above */
|
||||
db_tr->db[0].db.desc.cmd |= OHCI_INTERRUPT_ALWAYS;
|
||||
|
Loading…
Reference in New Issue
Block a user