📄 scsincr53c8xx.c
字号:
static voidsynctabinit(Controller *c){ int scf; unsigned long scsilimit; int xferp; unsigned long cr, sr; int tpf; int fast; int maxscf; if (c->v->feature & Ultra2) maxscf = NULTRA2SCF; else if (c->v->feature & Ultra) maxscf = NULTRASCF; else maxscf = NSCF; /* * for chips with no clock doubler, but Ultra capable (e.g. 860, or interestingly the * first spin of the 875), assume 80MHz * otherwise use the internal (33 Mhz) or external (40MHz) default */ if ((c->v->feature & Ultra) != 0 && (c->v->feature & (ClockDouble | ClockQuad)) == 0) c->sclk = ULTRA_NOCLOCKDOUBLE_SCLK; else c->sclk = SCLK; /* * otherwise, if the chip is Ultra capable, but has a slow(ish) clock, * invoke the doubler */ if (SCLK <= 40000000) { if (c->v->feature & ClockDouble) { c->sclk *= 2; c->clockmult = 1; } else if (c->v->feature & ClockQuad) { c->sclk *= 4; c->clockmult = 1; } else c->clockmult = 0; } else c->clockmult = 0; /* derive CCF from sclk */ /* woebetide anyone with SCLK < 16.7 or > 80MHz */ if (c->sclk <= 25 * MEGA) c->ccf = 1; else if (c->sclk <= 3750000) c->ccf = 2; else if (c->sclk <= 50 * MEGA) c->ccf = 3; else if (c->sclk <= 75 * MEGA) c->ccf = 4; else if ((c->v->feature & ClockDouble) && c->sclk <= 80 * MEGA) c->ccf = 5; else if ((c->v->feature & ClockQuad) && c->sclk <= 120 * MEGA) c->ccf = 6; else if ((c->v->feature & ClockQuad) && c->sclk <= 160 * MEGA) c->ccf = 7; for (scf = 1; scf < maxscf; scf++) { /* check for legal core rate */ /* round up so we run slower for safety */ cr = (c->sclk * 2 + cf2[scf] - 1) / cf2[scf]; if (cr <= MAXSYNCCORERATE) { scsilimit = MAXSYNCSCSIRATE; fast = 0; } else if (cr <= MAXFASTSYNCCORERATE) { scsilimit = MAXFASTSYNCSCSIRATE; fast = 1; } else if ((c->v->feature & Ultra) && cr <= MAXULTRASYNCCORERATE) { scsilimit = MAXULTRASYNCSCSIRATE; fast = 2; } else if ((c->v->feature & Ultra2) && cr <= MAXULTRA2SYNCCORERATE) { scsilimit = MAXULTRA2SYNCSCSIRATE; fast = 3; } else continue; for (xferp = 11; xferp >= 4; xferp--) { int ok; int tp; /* calculate scsi rate - round up again */ /* start from sclk for accuracy */ int totaldivide = xferp * cf2[scf]; sr = (c->sclk * 2 + totaldivide - 1) / totaldivide; if (sr > scsilimit) break; /* * now work out transfer period * round down now so that period is pessimistic */ tp = (MEGA * 1000) / sr; /* * bounds check it */ if (tp < 25 || tp > 255 * 4) continue; /* * spot stupid special case for Ultra or Ultra2 * while working out factor */ if (tp == 25) tpf = 10; else if (tp == 50) tpf = 12; else if (tp < 52) continue; else tpf = tp / 4; /* * now check tpf looks sensible * given core rate */ switch (fast) { case 0: /* scf must be ccf for SCSI 1 */ ok = tpf >= 50 && scf == c->ccf; break; case 1: ok = tpf >= 25 && tpf < 50; break; case 2: /* * must use xferp of 4, or 5 at a pinch * for an Ultra transfer */ ok = xferp <= 5 && tpf >= 12 && tpf < 25; break; case 3: ok = xferp == 4 && (tpf == 10 || tpf == 11); break; default: ok = 0; } if (!ok) continue; c->synctab[scf - 1][xferp - 4] = tpf; } }#ifndef NO_ULTRA2 if (c->v->feature & Ultra2) tpf = 10; else#endif if (c->v->feature & Ultra) tpf = 12; else tpf = 25; for (; tpf < 256; tpf++) { if (chooserate(c, tpf, &scf, &xferp) == tpf) { unsigned tp = tpf == 10 ? 25 : (tpf == 12 ? 50 : tpf * 4); unsigned long khz = (MEGA + tp - 1) / (tp); KPRINT(PRINTPREFIX "tpf=%d scf=%d.%.1d xferp=%d mhz=%ld.%.3ld\n", tpf, cf2[scf] / 2, (cf2[scf] & 1) ? 5 : 0, xferp + 4, khz / 1000, khz % 1000); USED(khz); if (c->tpf == 0) c->tpf = tpf; /* note lowest value for controller */ } }}static voidsynctodsa(Dsa *dsa, Controller *c){/* KPRINT("synctodsa(dsa=%lux, target=%d, scntl3=%.2lx sxfer=%.2x)\n", dsa, dsa->target, c->scntl3[dsa->target], c->sxfer[dsa->target]);*/ dsa->scntl3 = c->scntl3[dsa->target]; dsa->sxfer = c->sxfer[dsa->target];}static voidsetsync(Dsa *dsa, Controller *c, int target, uchar ultra, uchar scf, uchar xferp, uchar reqack){ c->scntl3[target] = (c->scntl3[target] & 0x08) | (((scf << 4) | c->ccf | (ultra << 7)) & ~0x08); c->sxfer[target] = (xferp << 5) | reqack; c->s[target] = BothDone; if (dsa) { synctodsa(dsa, c); c->n->scntl3 = c->scntl3[target]; c->n->sxfer = c->sxfer[target]; }}static voidsetasync(Dsa *dsa, Controller *c, int target){ setsync(dsa, c, target, 0, c->ccf, 0, 0);}static voidsetwide(Dsa *dsa, Controller *c, int target, uchar wide){ c->scntl3[target] = wide ? (1 << 3) : 0; setasync(dsa, c, target); c->s[target] = WideDone;}static intbuildsdtrmsg(uchar *buf, uchar tpf, uchar offset){ *buf++ = X_MSG; *buf++ = 3; *buf++ = X_MSG_SDTR; *buf++ = tpf; *buf = offset; return 5;}static intbuildwdtrmsg(uchar *buf, uchar expo){ *buf++ = X_MSG; *buf++ = 2; *buf++ = X_MSG_WDTR; *buf = expo; return 4;}static voidstart(Controller *c, long entry){ ulong p; if (c->running) panic(PRINTPREFIX "start called while running"); c->running = 1; p = c->scriptpa + entry; lesetl(c->n->dsp, p); if (c->ssm) c->n->dcntl |= 0x4; /* start DMA in SSI mode */}static voidncrcontinue(Controller *c){ if (c->running) panic(PRINTPREFIX "ncrcontinue called while running"); /* set the start DMA bit to continue execution */ c->running = 1; c->n->dcntl |= 0x4;}static voidsoftreset(Controller *c){ Ncr *n = c->n; n->istat = Srst; /* software reset */ n->istat = 0; /* general initialisation */ n->scid = (1 << 6) | 7; /* respond to reselect, ID 7 */ n->respid = 1 << 7; /* response ID = 7 */#ifdef INTERNAL_SCLK n->stest1 = 0x80; /* disable external scsi clock */#else n->stest1 = 0x00;#endif n->stime0 = 0xdd; /* about 0.5 second timeout on each device */ n->scntl0 |= 0x8; /* Enable parity checking */ /* continued setup */ n->sien0 = 0x8f; n->sien1 = 0x04; n->dien = 0x7d; n->stest3 = 0x80; /* TolerANT enable */ c->running = 0; if (c->v->feature & BigFifo) n->ctest5 = (1 << 5); n->dmode = c->v->burst << 6; /* set burst length bits */ if (c->v->burst & 4) n->ctest5 |= (1 << 2); /* including overflow into ctest5 bit 2 */ if (c->v->feature & Prefetch) n->dcntl |= (1 << 5); /* prefetch enable */ else if (c->v->feature & BurstOpCodeFetch) n->dmode |= (1 << 1); /* burst opcode fetch */ if (c->v->feature & Differential) { /* chip capable */ if ((c->feature & Differential) || bios_set_differential(c)) { /* user enabled, or some evidence bios set differential */ if (n->sstat2 & (1 << 2)) print(PRINTPREFIX "can't go differential; wrong cable\n"); else { n->stest2 = (1 << 5); print(PRINTPREFIX "differential mode set\n"); } } } if (c->clockmult) { n->stest1 |= (1 << 3); /* power up doubler */ delay(2); n->stest3 |= (1 << 5); /* stop clock */ n->stest1 |= (1 << 2); /* enable doubler */ n->stest3 &= ~(1 << 5); /* start clock */ /* pray */ }}static voidmsgsm(Dsa *dsa, Controller *c, int msg, int *cont, int *wakeme){ uchar histpf, hisreqack; int tpf; int scf, xferp; int len; Ncr *n = c->n; switch (c->s[dsa->target]) { case SyncInit: switch (msg) { case A_SIR_MSG_SDTR: /* reply to my SDTR */ histpf = n->scratcha[2]; hisreqack = n->scratcha[3]; KPRINT(PRINTPREFIX "%d: SDTN response %d %d\n", dsa->target, histpf, hisreqack); if (hisreqack == 0) setasync(dsa, c, dsa->target); else { /* hisreqack should be <= c->v->maxsyncoff */ tpf = chooserate(c, histpf, &scf, &xferp); KPRINT(PRINTPREFIX "%d: SDTN: using %d %d\n", dsa->target, tpf, hisreqack); setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack); } *cont = -2; return; case A_SIR_EV_PHASE_SWITCH_AFTER_ID: /* target ignored ATN for message after IDENTIFY - not SCSI-II */ KPRINT(PRINTPREFIX "%d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target); KPRINT(PRINTPREFIX "%d: SDTN: async\n", dsa->target); setasync(dsa, c, dsa->target); *cont = E_to_decisions; return; case A_SIR_MSG_REJECT: /* rejection of my SDTR */ KPRINT(PRINTPREFIX "%d: SDTN: rejected SDTR\n", dsa->target); //async: KPRINT(PRINTPREFIX "%d: SDTN: async\n", dsa->target); setasync(dsa, c, dsa->target); *cont = -2; return; } break; case WideInit: switch (msg) { case A_SIR_MSG_WDTR: /* reply to my WDTR */ KPRINT(PRINTPREFIX "%d: WDTN: response %d\n", dsa->target, n->scratcha[2]); setwide(dsa, c, dsa->target, n->scratcha[2]); *cont = -2; return; case A_SIR_EV_PHASE_SWITCH_AFTER_ID: /* target ignored ATN for message after IDENTIFY - not SCSI-II */ KPRINT(PRINTPREFIX "%d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target); setwide(dsa, c, dsa->target, 0); *cont = E_to_decisions; return; case A_SIR_MSG_REJECT: /* rejection of my SDTR */ KPRINT(PRINTPREFIX "%d: WDTN: rejected WDTR\n", dsa->target); setwide(dsa, c, dsa->target, 0); *cont = -2; return; } break; case NeitherDone: case WideDone: case BothDone: switch (msg) { case A_SIR_MSG_WDTR: { uchar hiswide, mywide; hiswide = n->scratcha[2]; mywide = (c->v->feature & Wide) != 0; KPRINT(PRINTPREFIX "%d: WDTN: target init %d\n", dsa->target, hiswide); if (hiswide < mywide) mywide = hiswide; KPRINT(PRINTPREFIX "%d: WDTN: responding %d\n", dsa->target, mywide); setwide(dsa, c, dsa->target, mywide); len = buildwdtrmsg(dsa->msg_out, mywide); setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len); *cont = E_response; c->s[dsa->target] = WideResponse; return; } case A_SIR_MSG_SDTR:#ifdef ASYNC_ONLY *cont = E_reject; return;#else /* target decides to renegotiate */ histpf = n->scratcha[2]; hisreqack = n->scratcha[3]; KPRINT(PRINTPREFIX "%d: SDTN: target init %d %d\n", dsa->target, histpf, hisreqack); if (hisreqack == 0) { /* he wants asynchronous */ setasync(dsa, c, dsa->target); tpf = 0; } else { /* he wants synchronous */ tpf = chooserate(c, histpf, &scf, &xferp); if (hisreqack > c->v->maxsyncoff) hisreqack = c->v->maxsyncoff; KPRINT(PRINTPREFIX "%d: using %d %d\n", dsa->target, tpf, hisreqack); setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack); } /* build my SDTR message */ len = buildsdtrmsg(dsa->msg_out, tpf, hisreqack); setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len); *cont = E_response; c->s[dsa->target] = SyncResponse; return;#endif } break; case WideResponse: switch (msg) { case A_SIR_EV_RESPONSE_OK: c->s[dsa->target] = WideDone; KPRINT(PRINTPREFIX "%d: WDTN: response accepted\n", dsa->target); *cont = -2; return; case A_SIR_MSG_REJECT: setwide(dsa, c, dsa->target, 0); KPRINT(PRINTPREFIX "%d: WDTN: response REJECTed\n", dsa->target); *cont = -2; return; } break; case SyncResponse: switch (msg) { case A_SIR_EV_RESPONSE_OK: c->s[dsa->target] = BothDone; KPRINT(PRINTPREFIX "%d: SDTN: response accepted (%s)\n", dsa->target, phase[n->sstat1 & 7]); *cont = -2; return; /* chf */ case A_SIR_MSG_REJECT: setasync(dsa, c, dsa->target); KPRINT(PRINTPREFIX "%d: SDTN: response REJECTed\n", dsa->target); *cont = -2; return; } break; } KPRINT(PRINTPREFIX "%d: msgsm: state %d msg %d\n", dsa->target, c->s[dsa->target], msg); *wakeme = 1; return;}static voidcalcblockdma(Dsa *d, ulong base, ulong count){ ulong blocks; if (DEBUG(3)) blocks = 0; else { blocks = count / A_BSIZE; if (blocks > 255) blocks = 255; } d->dmablks = blocks; 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(PRINTPREFIX "%d/%d: read_mismatch_recover: DMA FIFO = %d\n", dsa->target, dsa->lun, inchip); } if (n->sxfer & SYNCOFFMASK(c)) { /* SCSI FIFO */ uchar fifo = n->sstat1 >> 4; if (c->v->maxsyncoff > 8) fifo |= (n->sstat2 & (1 << 4)); if (fifo) { inchip += fifo; IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SCSI FIFO = %d\n", dsa->target, dsa->lun, fifo); } } else { if (n->sstat0 & (1 << 7)) { inchip++; IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SIDL full\n", dsa->target, dsa->lun); } if (n->sstat2 & (1 << 7)) { inchip++; IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SIDL msb full\n", dsa->target, dsa->lun); } } USED(inchip); return dbc;}static ulongwrite_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]; USED(dsa); if (n->ctest5 & (1 << 5)) inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff; else inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -