📄 sd53c8xx.c
字号:
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(PRINTPREFIX "%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(PRINTPREFIX "%d/%d: write_mismatch_recover: SODL full\n", dsa->target, dsa->lun);#endif } if (n->sstat2 & (1 << 5)) { inchip++;#ifdef WMR_DEBUG IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODL msb full\n", dsa->target, dsa->lun);#endif } if (n->sxfer & SYNCOFFMASK(c)) { /* synchronous SODR */ if (n->sstat0 & (1 << 6)) { inchip++;#ifdef WMR_DEBUG IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODR full\n", dsa->target, dsa->lun);#endif } if (n->sstat2 & (1 << 6)) { inchip++;#ifdef WMR_DEBUG IPRINT(PRINTPREFIX "%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 voidsd53c8xxinterrupt(Ureg *ur, void *a){ uchar istat; ushort sist; uchar dstat; int wakeme = 0; int cont = -1; Dsa *dsa; ulong dsapa; Controller *c = a; Ncr *n = c->n; USED(ur); if (DEBUG(1)) { IPRINT(PRINTPREFIX "int\n"); } ilock(c); istat = n->istat; if (istat & Intf) { Dsa *d; int wokesomething = 0; if (DEBUG(1)) { IPRINT(PRINTPREFIX "Intfly\n"); } n->istat = Intf; /* search for structures in A_STATE_DONE */ for (d = KPTR(legetl(c->dsalist.head)); d != dsaend; d = KPTR(legetl(d->next))) { if (d->stateb == A_STATE_DONE) { d->p9status = d->status; if (DEBUG(1)) { IPRINT(PRINTPREFIX "waking up dsa %lux\n", (ulong)d); } wakeup(d); wokesomething = 1; } } if (!wokesomething) { IPRINT(PRINTPREFIX "nothing to wake up\n"); } } if ((istat & (Sip | Dip)) == 0) { if (DEBUG(1)) { IPRINT(PRINTPREFIX "int end %x\n", istat); } iunlock(c); return; } sist = (n->sist1<<8)|n->sist0; /* BUG? can two-byte read be inconsistent? */ dstat = n->dstat; dsapa = legetl(n->dsa); /* * Can't compute dsa until we know that dsapa is valid. */ if(dsapa < -KZERO) dsa = (Dsa*)DMASEG_TO_KADDR(dsapa); else{ dsa = nil; /* * happens at startup on some cards but we * don't actually deref dsa because none of the * flags we are about are set. * still, print in case that changes and we're * about to dereference nil. */ iprint("sd53c8xxinterrupt: dsa=%.8lux istat=%ux sist=%ux dstat=%ux\n", dsapa, istat, sist, dstat); } 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(PRINTPREFIX "%d/%d: Phase Mismatch sa=%.8lux\n", dsa->target, dsa->lun, sa); } /* * now recover */ if (sa == E_data_in_mismatch) { /* * though this is a failure in the residue, there may have been blocks * as well. if so, dmablks will not have been zeroed, since the state * was not saved by the microcode. */ dbc = read_mismatch_recover(c, n, dsa); tbc = legetl(dsa->data_buf.dbc) - dbc; dsa->dmablks = 0; n->scratcha[2] = 0; advancedata(&dsa->data_buf, tbc); if (DEBUG(1) || DEBUG(2)) { IPRINT(PRINTPREFIX "%d/%d: transferred = %ld residue = %ld\n", dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc)); } cont = E_data_mismatch_recover; } 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(c, n, dsa); tbc = legetl(dsa->data_buf.dbc) - dbc; dsa->dmablks = 0; n->scratcha[2] = 0; advancedata(&dsa->data_buf, tbc); if (DEBUG(1) || DEBUG(2)) { IPRINT(PRINTPREFIX "%d/%d: transferred = %ld residue = %ld\n", dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc)); } cont = E_data_mismatch_recover; } else if (sa == E_data_out_block_mismatch) { dbc = write_mismatch_recover(c, 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(c, n, dsa); tbc = lim - dbc; IPRINT(PRINTPREFIX "%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(c, n, dsa); tbc = lim - dbc; IPRINT(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%d/%d Sto\n", dsa->target, dsa->lun); } dsa->p9status = SDtimeout; dsa->stateb = A_STATE_DONE; coherence(); softreset(c); cont = E_issue_check; wakeme = 1; } if (sist & 0x1) { IPRINT(PRINTPREFIX "%d/%d: parity error\n", dsa->target, dsa->lun); dsa->parityerror = 1; } if (sist & 0x4) { IPRINT(PRINTPREFIX "%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 w = legetl(n->dsp) - c->scriptpa; 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(PRINTPREFIX "%d/%d: ignore wide residue %d, WSR = %d\n", dsa->target, dsa->lun, n->scratcha[1], n->scntl2 & 1); if (dsa->flag == 2) { IPRINT(PRINTPREFIX "%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(PRINTPREFIX "%d: not msg_in after reselect (%s)", n->ssid & SSIDMASK(c), phase[n->sstat1 & 7]); dsa = dsafind(c, n->ssid & SSIDMASK(c), -1, A_STATE_DISCONNECTED); dumpncrregs(c, 1); wakeme = 1; break; case A_SIR_NOTIFY_LOAD_STATE: IPRINT(PRINTPREFIX ": load_state dsa=%p\n", dsa); if (dsa == (void*)KZERO || dsa == (void*)-1) { dsadump(c); dumpncrregs(c, 1); panic("bad dsa in load_state"); } cont = -2; break; case A_SIR_NOTIFY_MSG_IN: IPRINT(PRINTPREFIX "%d/%d: msg_in %d\n", dsa->target, dsa->lun, n->sfbr); cont = -2; break; case A_SIR_NOTIFY_DISC: IPRINT(PRINTPREFIX "%d/%d: disconnect:", dsa->target, dsa->lun); goto dsadump; case A_SIR_NOTIFY_STATUS: IPRINT(PRINTPREFIX "%d/%d: status\n", dsa->target, dsa->lun); cont = -2; break; case A_SIR_NOTIFY_COMMAND: IPRINT(PRINTPREFIX "%d/%d: commands\n", dsa->target, dsa->lun); cont = -2; break; case A_SIR_NOTIFY_DATA_IN: IPRINT(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%d/%d: data out\n", dsa->target, dsa->lun); cont = -2; break; case A_SIR_NOTIFY_DUMP: IPRINT(PRINTPREFIX "%d/%d: dump\n", dsa->target, dsa->lun); dumpncrregs(c, 1); cont = -2; break; case A_SIR_NOTIFY_DUMP2: IPRINT(PRINTPREFIX "%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", legetl(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(PRINTPREFIX "wait reselect\n"); cont = -2; break; case A_SIR_NOTIFY_RESELECT: IPRINT(PRINTPREFIX "reselect: ssid %.2x sfbr %.2x at %ld\n", n->ssid, n->sfbr, TK2MS(m->ticks)); cont = -2; break; case A_SIR_NOTIFY_ISSUE: IPRINT(PRINTPREFIX "%d/%d: issue dsa=%p end=%p:", dsa->target, dsa->lun, dsa, dsaend); dsadump: IPRINT(" tgt=%d", dsa->target); IPRINT(" time=%ld", TK2MS(m->ticks)); IPRINT("\n"); cont = -2; break; case A_SIR_NOTIFY_ISSUE_CHECK: IPRINT(PRINTPREFIX "issue check\n"); cont = -2; break; case A_SIR_NOTIFY_SIGP: IPRINT(PRINTPREFIX "responded to SIGP\n"); cont = -2; break; case A_SIR_NOTIFY_DUMP_NEXT_CODE: { ulong *dsp = c->script + (legetl(n->dsp)-c->scriptpa)/4; int x; IPRINT(PRINTPREFIX "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(PRINTPREFIX "%d/%d: WSR set\n", dsa->target, dsa->lun); cont = -2; break; case A_SIR_NOTIFY_LOAD_SYNC: IPRINT(PRINTPREFIX "%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: if (DEBUG(2)) { IPRINT(PRINTPREFIX "%d/%d: reselected during select\n", dsa->target, dsa->lun); } cont = -2; break; case A_error_reselected: /* dsa isn't valid here */ iprint(PRINTPREFIX "reselection error\n"); dumpncrregs(c, 1); for (dsa = KPTR(legetl(c->dsalist.head)); dsa != dsaend; dsa = KPTR(legetl(dsa->next))) { IPRINT(PRINTPREFIX "dsa target %d lun %d state %d\n", dsa->target, dsa->lun, dsa->stateb); } break; default: IPRINT(PRINTPREFIX "%d/%d: script error %ld\n", dsa->target, dsa->lun, legetl(n->dsps)); dumpncrregs(c, 1); wakeme = 1; } } /*else*/ if (dstat & Iid) { int i, target, lun; ulong addr, dbc, *v; addr = legetl(n->dsp); if(dsa){ target = dsa->target; lun = dsa->lun; }else{ target = -1; lun = -1; } dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0]; // if(dsa == nil) idebug++; IPRINT(PRINTPREFIX "%d/%d: Iid pa=%.8lux sa=%.8lux dbc=%lux\n", target, lun, addr, addr - c->scriptpa, dbc); addr = (ulong)c->script + addr - c->scriptpa; addr -= 64; addr &= ~63; v = (ulong*)addr; for(i=0; i<8; i++){ IPRINT("%.8lux: %.8lux %.8lux %.8lux %.8lux\n", addr, v[0], v[1], v[2], v[3]); addr += 4*4; v += 4; } USED(addr, dbc); if(dsa == nil){ dsadump(c); dumpncrregs(c, 1); panic("bad dsa"); } dsa->p9status = SDeio; wakeme = 1; } /*else*/ if (dstat & Bf) { IPRINT(PRINTPREFIX "%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(PRINTPREFIX "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; } if (datalen) { KPRINT(PRINTPREFIX "write:"); for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++) { KPRINT("%.2ux", *bp); } if (i < datalen) { KPRINT("..."); } KPRINT("\n"); }}static voiddumpreaddata(uchar *data, int datalen){ int i; uchar *bp; if (!DEBUG(0)){ USED(data, datalen); return; } if (datalen) { KPRINT(PRINTPREFIX "read:");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -