📄 sd53c8xx.c
字号:
d->dmaaddr[0] = base; d->dmaaddr[1] = base >> 8; d->dmaaddr[2] = base >> 16; d->dmaaddr[3] = base >> 24; setmovedata(&d->data_buf, base + blocks * A_BSIZE, count - blocks * A_BSIZE); if (legetl(d->data_buf.dbc) == 0) d->flag = 1;}static ulongread_mismatch_recover(Controller *c, Ncr *n, Dsa *dsa){ ulong dbc; uchar dfifo = n->dfifo; int inchip; dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0]; if (n->ctest5 & (1 << 5)) inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff; else inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f; if (inchip) { IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: DMA FIFO = %d\n", dsa->target, dsa->lun, inchip); } if (n->sxfer & 0xf) { /* SCSI FIFO */ uchar fifo = n->sstat1 >> 4; if (c->v->maxsyncoff > 8) fifo |= (n->sstat2 & (1 << 4)); if (fifo) { inchip += fifo; IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SCSI FIFO = %d\n", dsa->target, dsa->lun, fifo); } } else { if (n->sstat0 & (1 << 7)) { inchip++; IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SIDL full\n", dsa->target, dsa->lun); } if (n->sstat2 & (1 << 7)) { inchip++; IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SIDL msb full\n", dsa->target, dsa->lun); } } USED(inchip); return dbc;}static ulongwrite_mismatch_recover(Ncr *n, Dsa *dsa){ ulong dbc; uchar dfifo = n->dfifo; int inchip; dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0]; USED(dsa); if (n->ctest5 & (1 << 5)) inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff; else inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;#ifdef WMR_DEBUG if (inchip) { IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: DMA FIFO = %d\n", dsa->target, dsa->lun, inchip); }#endif if (n->sstat0 & (1 << 5)) { inchip++;#ifdef WMR_DEBUG IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODL full\n", dsa->target, dsa->lun);#endif } if (n->sstat2 & (1 << 5)) { inchip++;#ifdef WMR_DEBUG IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODL msb full\n", dsa->target, dsa->lun);#endif } if (n->sxfer & 0xf) { /* synchronous SODR */ if (n->sstat0 & (1 << 6)) { inchip++;#ifdef WMR_DEBUG IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODR full\n", dsa->target, dsa->lun);#endif } if (n->sstat2 & (1 << 6)) { inchip++;#ifdef WMR_DEBUG IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODR msb full\n", dsa->target, dsa->lun);#endif } } /* clear the dma fifo */ n->ctest3 |= (1 << 2); /* wait till done */ while ((n->dstat & Dfe) == 0) ; return dbc + inchip;}static voidinterrupt(Ureg *ur, void *a){ uchar istat; ushort sist; uchar dstat; int wakeme = 0; int cont = -1; Dsa *dsa; Controller *c = a; Ncr *n = c->n; USED(ur); if (DEBUG(1)) IPRINT("sd53c8xx: int\n"); ilock(c); istat = n->istat; if (istat & Intf) { Dsa *d; int wokesomething = 0; if (DEBUG(1)) IPRINT("sd53c8xx: Intfly\n"); n->istat = Intf; /* search for structures in A_STATE_DONE */ for (d = KPTR(legetl(c->dsalist.head)); d; d = KPTR(legetl(d->next))) { if (d->stateb == A_STATE_DONE) { d->p9status = d->status; if (DEBUG(1)) IPRINT("sd53c8xx: waking up dsa %lux\n", d); wakeup(d); wokesomething = 1; } } if (!wokesomething) IPRINT("sd53c8xx: nothing to wake up\n"); } if ((istat & (Sip | Dip)) == 0) { if (DEBUG(1)) IPRINT("sd53c8xx: int end %x\n", istat); iunlock(c); return; } sist = (n->sist1<<8)|n->sist0; /* BUG? can two-byte read be inconsistent? */ dstat = n->dstat; dsa = (Dsa *)DMASEG_TO_KADDR(legetl(n->dsa)); c->running = 0; if (istat & Sip) { if (DEBUG(1)) IPRINT("sist = %.4x\n", sist); if (sist & 0x80) { ulong addr; ulong sa; ulong dbc; ulong tbc; int dmablks; ulong dmaaddr; addr = legetl(n->dsp); sa = addr - c->scriptpa; if (DEBUG(1) || DEBUG(2)) IPRINT("sd53c8xx: %d/%d: Phase Mismatch sa=%.8lux\n", dsa->target, dsa->lun, sa); /* * now recover */ if (sa == E_data_in_mismatch) { dbc = read_mismatch_recover(c, n, dsa); tbc = legetl(dsa->data_buf.dbc) - dbc; advancedata(&dsa->data_buf, tbc); if (DEBUG(1) || DEBUG(2)) IPRINT("sd53c8xx: %d/%d: transferred = %ld residue = %ld\n", dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc)); cont = E_to_decisions; } else if (sa == E_data_in_block_mismatch) { dbc = read_mismatch_recover(c, n, dsa); tbc = A_BSIZE - dbc; /* recover current state from registers */ dmablks = n->scratcha[2]; dmaaddr = legetl(n->scratchb); /* we have got to dmaaddr + tbc */ /* we have dmablks * A_BSIZE - tbc + residue left to do */ /* so remaining transfer is */ IPRINT("in_block_mismatch: dmaaddr = 0x%lux tbc=%lud dmablks=%d\n", dmaaddr, tbc, dmablks); calcblockdma(dsa, dmaaddr + tbc, dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc)); /* copy changes into scratch registers */ IPRINT("recalc: dmablks %d dmaaddr 0x%lx pa 0x%lx dbc %ld\n", dsa->dmablks, legetl(dsa->dmaaddr), legetl(dsa->data_buf.pa), legetl(dsa->data_buf.dbc)); n->scratcha[2] = dsa->dmablks; lesetl(n->scratchb, dsa->dmancr); cont = E_data_block_mismatch_recover; } else if (sa == E_data_out_mismatch) { dbc = write_mismatch_recover(n, dsa); tbc = legetl(dsa->data_buf.dbc) - dbc; advancedata(&dsa->data_buf, tbc); if (DEBUG(1) || DEBUG(2)) IPRINT("sd53c8xx: %d/%d: transferred = %ld residue = %ld\n", dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc)); cont = E_to_decisions; } else if (sa == E_data_out_block_mismatch) { dbc = write_mismatch_recover(n, dsa); tbc = legetl(dsa->data_buf.dbc) - dbc; /* recover current state from registers */ dmablks = n->scratcha[2]; dmaaddr = legetl(n->scratchb); /* we have got to dmaaddr + tbc */ /* we have dmablks blocks - tbc + residue left to do */ /* so remaining transfer is */ IPRINT("out_block_mismatch: dmaaddr = %lux tbc=%lud dmablks=%d\n", dmaaddr, tbc, dmablks); calcblockdma(dsa, dmaaddr + tbc, dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc)); /* copy changes into scratch registers */ n->scratcha[2] = dsa->dmablks; lesetl(n->scratchb, dsa->dmancr); cont = E_data_block_mismatch_recover; } else if (sa == E_id_out_mismatch) { /* * target switched phases while attention held during * message out. The possibilities are: * 1. It didn't like the last message. This is indicated * by the new phase being message_in. Use script to recover * * 2. It's not SCSI-II compliant. The new phase will be other * than message_in. We should also indicate that the device * is asynchronous, if it's the SDTR that got ignored * * For now, if the phase switch is not to message_in, and * and it happens after IDENTIFY and before SDTR, we * notify the negotiation state machine. */ ulong lim = legetl(dsa->msg_out_buf.dbc); uchar p = n->sstat1 & 7; dbc = write_mismatch_recover(n, dsa); tbc = lim - dbc; IPRINT("sd53c8xx: %d/%d: msg_out_mismatch: %lud/%lud sent, phase %s\n", dsa->target, dsa->lun, tbc, lim, phase[p]); if (p != MessageIn && tbc == 1) { msgsm(dsa, c, A_SIR_EV_PHASE_SWITCH_AFTER_ID, &cont, &wakeme); } else cont = E_id_out_mismatch_recover; } else if (sa == E_cmd_out_mismatch) { /* * probably the command count is longer than the device wants ... */ ulong lim = legetl(dsa->cmd_buf.dbc); uchar p = n->sstat1 & 7; dbc = write_mismatch_recover(n, dsa); tbc = lim - dbc; IPRINT("sd53c8xx: %d/%d: cmd_out_mismatch: %lud/%lud sent, phase %s\n", dsa->target, dsa->lun, tbc, lim, phase[p]); USED(p, tbc); cont = E_to_decisions; } else { IPRINT("sd53c8xx: %d/%d: ma sa=%.8lux wanted=%s got=%s\n", dsa->target, dsa->lun, sa, phase[n->dcmd & 7], phase[n->sstat1 & 7]); dumpncrregs(c, 1); dsa->p9status = SDeio; /* chf */ wakeme = 1; } } /*else*/ if (sist & 0x400) { if (DEBUG(0)) IPRINT("sd53c8xx: %d/%d Sto\n", dsa->target, dsa->lun); dsa->p9status = SDtimeout; dsa->stateb = A_STATE_DONE; softreset(c); cont = E_issue_check; wakeme = 1; } if (sist & 0x1) { IPRINT("sd53c8xx: %d/%d: parity error\n", dsa->target, dsa->lun); dsa->parityerror = 1; } if (sist & 0x4) { IPRINT("sd53c8xx: %d/%d: unexpected disconnect\n", dsa->target, dsa->lun); dumpncrregs(c, 1); //wakeme = 1; dsa->p9status = SDeio; } } if (istat & Dip) { if (DEBUG(1)) IPRINT("dstat = %.2x\n", dstat); /*else*/ if (dstat & Ssi) { ulong *p = DMASEG_TO_KADDR(legetl(n->dsp)); ulong w = (uchar *)p - (uchar *)c->script; IPRINT("[%lux]", w); USED(w); cont = -2; /* restart */ } if (dstat & Sir) { switch (legetl(n->dsps)) { case A_SIR_MSG_IO_COMPLETE: dsa->p9status = dsa->status; wakeme = 1; break; case A_SIR_MSG_SDTR: case A_SIR_MSG_WDTR: case A_SIR_MSG_REJECT: case A_SIR_EV_RESPONSE_OK: msgsm(dsa, c, legetl(n->dsps), &cont, &wakeme); break; case A_SIR_MSG_IGNORE_WIDE_RESIDUE: /* back up one in the data transfer */ IPRINT("sd53c8xx: %d/%d: ignore wide residue %d, WSR = %d\n", dsa->target, dsa->lun, n->scratcha[1], n->scntl2 & 1); if (dsa->dmablks == 0 && dsa->flag) IPRINT("sd53c8xx: %d/%d: transfer over; residue ignored\n", dsa->target, dsa->lun); else calcblockdma(dsa, legetl(dsa->dmaaddr) - 1, dsa->dmablks * A_BSIZE + legetl(dsa->data_buf.dbc) + 1); cont = -2; break; case A_SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT: IPRINT("sd53c8xx: %d: not msg_in after reselect (%s)", n->ssid & 7, phase[n->sstat1 & 7]); dsa = dsafind(c, n->ssid & 7, -1, A_STATE_DISCONNECTED); dumpncrregs(c, 1); wakeme = 1; break; case A_SIR_NOTIFY_MSG_IN: IPRINT("sd53c8xx: %d/%d: msg_in %d\n", dsa->target, dsa->lun, n->sfbr); cont = -2; break; case A_SIR_NOTIFY_DISC: IPRINT("sd53c8xx: %d/%d: disconnect:", dsa->target, dsa->lun); goto dsadump; case A_SIR_NOTIFY_STATUS: IPRINT("sd53c8xx: %d/%d: status\n", dsa->target, dsa->lun); cont = -2; break; case A_SIR_NOTIFY_COMMAND: IPRINT("sd53c8xx: %d/%d: commands\n", dsa->target, dsa->lun); cont = -2; break; case A_SIR_NOTIFY_DATA_IN: IPRINT("sd53c8xx: %d/%d: data in a %lx b %lx\n", dsa->target, dsa->lun, legetl(n->scratcha), legetl(n->scratchb)); cont = -2; break; case A_SIR_NOTIFY_BLOCK_DATA_IN: IPRINT("sd53c8xx: %d/%d: block data in: a2 %x b %lx\n", dsa->target, dsa->lun, n->scratcha[2], legetl(n->scratchb)); cont = -2; break; case A_SIR_NOTIFY_DATA_OUT: IPRINT("sd53c8xx: %d/%d: data out\n", dsa->target, dsa->lun); cont = -2; break; case A_SIR_NOTIFY_DUMP: IPRINT("sd53c8xx: %d/%d: dump\n", dsa->target, dsa->lun); dumpncrregs(c, 1); cont = -2; break; case A_SIR_NOTIFY_DUMP2: IPRINT("sd53c8xx: %d/%d: dump2:", dsa->target, dsa->lun); IPRINT(" sa %lux", legetl(n->dsp) - c->scriptpa); IPRINT(" dsa %lux", legetl(n->dsa)); IPRINT(" sfbr %ux", n->sfbr); IPRINT(" a %lux", n->scratcha); IPRINT(" b %lux", legetl(n->scratchb)); IPRINT(" ssid %ux", n->ssid); IPRINT("\n"); cont = -2; break; case A_SIR_NOTIFY_WAIT_RESELECT: IPRINT("sd53c8xx: wait reselect\n"); cont = -2; break; case A_SIR_NOTIFY_RESELECT: IPRINT("sd53c8xx: reselect: ssid %.2x sfbr %.2x at %ld\n", n->ssid, n->sfbr, TK2MS(m->ticks)); cont = -2; break; case A_SIR_NOTIFY_ISSUE: IPRINT("sd53c8xx: %d/%d: issue:", dsa->target, dsa->lun); dsadump: IPRINT(" tgt=%d", dsa->target); IPRINT(" time=%ld", TK2MS(m->ticks)); IPRINT("\n"); cont = -2; break; case A_SIR_NOTIFY_ISSUE_CHECK: IPRINT("sd53c8xx: issue check\n"); cont = -2; break; case A_SIR_NOTIFY_SIGP: IPRINT("sd53c8xx: responded to SIGP\n"); cont = -2; break; case A_SIR_NOTIFY_DUMP_NEXT_CODE: { ulong *dsp = DMASEG_TO_KADDR(legetl(n->dsp)); int x; IPRINT("sd53c8xx: code at %lux", dsp - c->script); for (x = 0; x < 6; x++) IPRINT(" %.8lux", dsp[x]); IPRINT("\n"); USED(dsp); cont = -2; break; } case A_SIR_NOTIFY_WSR: IPRINT("sd53c8xx: %d/%d: WSR set\n", dsa->target, dsa->lun); cont = -2; break; case A_SIR_NOTIFY_LOAD_SYNC: IPRINT("sd53c8xx: %d/%d: scntl=%.2x sxfer=%.2x\n", dsa->target, dsa->lun, n->scntl3, n->sxfer); cont = -2; break; case A_SIR_NOTIFY_RESELECTED_ON_SELECT: IPRINT("sd53c8xx: %d/%d: reselected during select\n", dsa->target, dsa->lun); cont = -2; break; default: IPRINT("sd53c8xx: %d/%d: script error %ld\n", dsa->target, dsa->lun, legetl(n->dsps)); dumpncrregs(c, 1); wakeme = 1; } } /*else*/ if (dstat & Iid) { ulong addr = legetl(n->dsp); ulong dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0]; IPRINT("sd53c8xx: %d/%d: Iid pa=%.8lux sa=%.8lux dbc=%lux\n", dsa->target, dsa->lun, addr, addr - c->scriptpa, dbc); addr = (ulong)DMASEG_TO_KADDR(addr); IPRINT("%.8lux %.8lux %.8lux\n", *(ulong *)(addr - 12), *(ulong *)(addr - 8), *(ulong *)(addr - 4)); USED(addr, dbc); dsa->p9status = SDeio; wakeme = 1; } /*else*/ if (dstat & Bf) { IPRINT("sd53c8xx: %d/%d: Bus Fault\n", dsa->target, dsa->lun); dumpncrregs(c, 1); dsa->p9status = SDeio; wakeme = 1; } } if (cont == -2) ncrcontinue(c); else if (cont >= 0) start(c, cont); if (wakeme){ if(dsa->p9status == SDnostatus) dsa->p9status = SDeio; wakeup(dsa); } iunlock(c); if (DEBUG(1)) { IPRINT("sd53c8xx: int end 1\n"); }}static intdone(void *arg){ return ((Dsa *)arg)->p9status != SDnostatus;}static voidsetmovedata(Movedata *d, ulong pa, ulong bc){ d->pa[0] = pa; d->pa[1] = pa>>8; d->pa[2] = pa>>16; d->pa[3] = pa>>24; d->dbc[0] = bc; d->dbc[1] = bc>>8; d->dbc[2] = bc>>16; d->dbc[3] = bc>>24;}static voidadvancedata(Movedata *d, long v){ lesetl(d->pa, legetl(d->pa) + v); lesetl(d->dbc, legetl(d->dbc) - v);}static voiddumpwritedata(uchar *data, int datalen){ int i; uchar *bp; if (!DEBUG(0)){ USED(data, datalen); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -