Use cycleMatch for precise IT DMA start timing.

This commit is contained in:
Hidetoshi Shimokawa 2003-01-16 07:01:54 +00:00
parent 42c0e331cd
commit 97ae6c1f15

View File

@ -1166,7 +1166,6 @@ fwohci_db_init(struct fwohci_dbch *dbch)
STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link);
if (!(dbch->xferq.flag & FWXFERQ_PACKET) &&
dbch->xferq.bnpacket != 0) {
/* XXX what those for? */
if (idb % dbch->xferq.bnpacket == 0)
dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket
].start = (caddr_t)db_tr;
@ -1416,6 +1415,8 @@ fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
struct fwohci_dbch *dbch;
struct fw_pkt *fp;
struct fwohcidb_tr *db_tr;
int cycle_now, sec, cycle, cycle_match;
u_int32_t stat;
tag = (sc->it[dmach].xferq.flag >> 6) & 3;
ich = sc->it[dmach].xferq.flag & 0x3f;
@ -1431,7 +1432,8 @@ fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
}
if(err)
return err;
if(OREAD(sc, OHCI_ITCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE){
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 *)
@ -1445,7 +1447,7 @@ fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
((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 if(!(OREAD(sc, OHCI_ITCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE)){
} else if(!(stat & OHCI_CNTL_DMA_RUN)) {
if (firewire_debug)
printf("fwohci_itxbuf_enable: kick 0x%08x\n",
OREAD(sc, OHCI_ITCTL(dmach)));
@ -1453,11 +1455,12 @@ fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
if(dbch->xferq.stdma == NULL){
return err;
}
#if 0
OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
#endif
OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xf0000000);
fwohci_txbufdb(sc, dmach, dbch->xferq.stdma);
if(dbch->xferq.stdma2 != NULL){
fwohci_txbufdb(sc, dmach, dbch->xferq.stdma2);
@ -1477,19 +1480,44 @@ fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
OWRITE(sc, OHCI_ITCMD(dmach),
vtophys(((struct fwohcidb_tr *)
(dbch->xferq.stdma->start))->db) | dbch->ndesc);
#define CYCLE_OFFSET 1
if(dbch->xferq.flag & FWXFERQ_DV){
db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma->start;
fp = (struct fw_pkt *)db_tr->buf;
dbch->xferq.dvoffset =
((fc->cyctimer(fc) >> 12) + 4) & 0xf;
#if 0
printf("dvoffset: %d\n", dbch->xferq.dvoffset);
#endif
dbch->xferq.dvoffset = CYCLE_OFFSET;
fp->mode.ld[2] |= htonl(dbch->xferq.dvoffset << 12);
}
OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
/* 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;
if (firewire_debug)
printf("cycle_match: 0x%04x->0x%04x\n",
cycle_now, cycle_match);
/* Clear cycle match counter bits */
OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000);
OWRITE(sc, OHCI_ITCTL(dmach),
OHCI_CNTL_CYCMATCH_S | (cycle_match << 16)
| OHCI_CNTL_DMA_RUN);
OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
} else {
OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_WAKE);
}
return err;
}
@ -1933,7 +1961,7 @@ fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
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) - 1;
diff = cycl - (timestamp & 0xf) - CYCLE_OFFSET;
if (diff < 0)
diff += 16;
if (diff > 8)