📄 sd53c8xx.c
字号:
else maxscf = NSCF; /* * search large clock factors first since this should * result in more reliable transfers */ for (scf = maxscf; scf >= 1; scf--) { for (xferp = 0; xferp < 8; xferp++) { unsigned char v = c->synctab[scf - 1][xferp]; if (v == 0) continue; if (v >= tpf && v < besttpf) { besttpf = v; bestscfi = scf; bestxferp = xferp; } } } if (besttpf == 1000) return 0; if (scfp) *scfp = bestscfi; if (xferpp) *xferpp = bestxferp; return besttpf;}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("sd53c8xx: 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("sd53c8xx: 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("sd53c8xx: 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) || (n->gpreg & 0x8) == 0) { /* user enabled, or bit 3 of GPREG clear (Symbios cards) */ if (n->sstat2 & (1 << 2)) print("sd53c8xx: can't go differential; wrong cable\n"); else { n->stest2 = (1 << 5); print("sd53c8xx: 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("sd53c8xx: %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("sd53c8xx: %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("sd53c8xx: %d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target); KPRINT("sd53c8xx: %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("sd53c8xx: %d: SDTN: rejected SDTR\n", dsa->target); //async: KPRINT("sd53c8xx: %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("sd53c8xx: %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("sd53c8xx: %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("sd53c8xx: %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("sd53c8xx: %d: WDTN: target init %d\n", dsa->target, hiswide); if (hiswide < mywide) mywide = hiswide; KPRINT("sd53c8xx: %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("sd53c8xx: %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("sd53c8xx: %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("sd53c8xx: %d: WDTN: response accepted\n", dsa->target); *cont = -2; return; case A_SIR_MSG_REJECT: setwide(dsa, c, dsa->target, 0); KPRINT("sd53c8xx: %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("sd53c8xx: %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("sd53c8xx: %d: SDTN: response REJECTed\n", dsa->target); *cont = -2; return; } break; } KPRINT("sd53c8xx: %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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -