📄 scsincr53c8xx.c
字号:
int *transferred){ uchar *bp; int bc; Dsa *d; Ncr *n = c->n; uchar target_expo, my_expo; ushort status; d = dsaalloc(c, target, lun); qlock(&c->q[target]); /* obtain access to target */ /* load the transfer control stuff */ d->scsi_id_buf[0] = 0; d->scsi_id_buf[1] = c->sxfer[target]; d->scsi_id_buf[2] = target; d->scsi_id_buf[3] = c->scntl3[target]; synctodsa(d, c); bc = 0; d->msg_out[bc] = 0x80 | lun;#ifndef NO_DISCONNECT d->msg_out[bc] |= (1 << 6);#endif bc++; /* work out what to do about negotiation */ switch (c->s[target]) { default: KPRINT(PRINTPREFIX "%d: strange nego state %d\n", target, c->s[target]); c->s[target] = NeitherDone; /* fall through */ case NeitherDone: if ((c->capvalid & (1 << target)) == 0) break; target_expo = (c->cap[target] >> 5) & 3; my_expo = (c->v->feature & Wide) != 0; if (target_expo < my_expo) my_expo = target_expo;#ifdef ALWAYS_DO_WDTR bc += buildwdtrmsg(d->msg_out + bc, my_expo); KPRINT(PRINTPREFIX "%d: WDTN: initiating expo %d\n", target, my_expo); c->s[target] = WideInit; break;#else if (my_expo) { bc += buildwdtrmsg(d->msg_out + bc, (c->v->feature & Wide) ? 1 : 0); KPRINT(PRINTPREFIX "%d: WDTN: initiating expo %d\n", target, my_expo); c->s[target] = WideInit; break; } KPRINT(PRINTPREFIX "%d: WDTN: narrow\n", target); /* fall through */#endif case WideDone: if (c->cap[target] & (1 << 4)) { KPRINT(PRINTPREFIX "%d: SDTN: initiating %d %d\n", target, c->tpf, c->v->maxsyncoff); bc += buildsdtrmsg(d->msg_out + bc, c->tpf, c->v->maxsyncoff); c->s[target] = SyncInit; break; } KPRINT(PRINTPREFIX "%d: SDTN: async only\n", target); c->s[target] = BothDone; break; case BothDone: break; } setmovedata(&d->msg_out_buf, DMASEG(d->msg_out), bc); setmovedata(&d->cmd_buf, DMASEG(cmd), cmdlen); calcblockdma(d, DMASEG(data), datalen); if (DEBUG(0)) { KPRINT(PRINTPREFIX "%d/%d: exec: ", target, lun); for (bp = cmd; bp < &cmd[cmdlen]; bp++) KPRINT("%.2ux", *bp); KPRINT("\n"); if (rw) KPRINT(PRINTPREFIX "%d/%d: exec: limit=(%d)%ld\n", target, lun, d->dmablks, legetl(d->data_buf.dbc)); else dumpwritedata(data, datalen); } setmovedata(&d->status_buf, DMASEG(&d->status), 1); d->p9status = 0xffff; d->parityerror = 0; d->stateb = A_STATE_ISSUE; /* start operation */ ilock(c); if (c->ssm) c->n->dcntl |= 0x10; /* SSI */ if (c->running) { n->istat |= Sigp; } else { start(c, E_issue_check); } iunlock(c);#ifdef CPU while(waserror()) ;#ifdef QUICK_TIMEOUT tsleep(d, done, d, 30 * 1000);#else tsleep(d, done, d, 60 * 60 * 1000);#endif poperror(); if (!done(d)) { KPRINT(PRINTPREFIX "%d/%d: exec: Timed out\n", target, lun); dumpncrregs(c, 0); dsafree(c, d); reset(c); qunlock(&c->q[target]); error(Eio); }#endif#ifdef FS sleep(d, done, d);#endif if (d->p9status == STATUS_SELECTION_TIMEOUT) c->s[target] = NeitherDone; if (d->parityerror) { d->p9status = STATUS_FAIL; } /* * adjust datalen */ if (d->dmablks > 0) datalen -= d->dmablks * A_BSIZE; else if (d->flag == 0) datalen -= legetl(d->data_buf.dbc); if (transferred) *transferred = datalen; if (rw) dumpreaddata(data, datalen); if (DEBUG(0)) KPRINT(PRINTPREFIX "%d/%d: exec: p9status=%d status %d rlen %d\n", target, lun, d->p9status, status, datalen); /* * spot the identify */ if ((c->capvalid & (1 << target)) == 0 && d->p9status == STATUS_COMPLETE && cmd[0] == 0x12 && datalen >= 8) { c->capvalid |= 1 << target; c->cap[target] = data[7]; KPRINT(PRINTPREFIX "%d: capabilities %.2x\n", target, data[7]); } status = d->p9status; dsafree(c, d); qunlock(&c->q[target]); return status;}#ifdef CPUstatic intexec(Scsi *p, int rw){ int transferred; Controller *c = &controller; /* MULTIPLE - map from scsi bus to controller instance */ p->status = io(c, p->target, p->lun, rw, p->cmd.base, p->cmd.lim - p->cmd.base, p->data.base, p->data.lim - p->data.base, &transferred); p->data.ptr = p->data.base + transferred; return p->status;}#endif#ifdef Plan9fsstatic intexec(Device d, int rw, uchar *cmd, int clen, void *data, int dlen){ Controller *c = &controller; /* MULTIPLE - map from scsi bus to controller instance */ return io(c, d.unit, (cmd[1] >> 5) & 7, rw, cmd, clen, data, dlen, 0);}#endif /* Plan9fs#ifdef FSstatic intexec(Target* t, int rw, uchar* cmd, int cbytes, void* data, int* dbytes){ int n, s; Controller *ctlr; if((ctlr = ctlrxx[t->ctlrno]) == nil || ctlr->n == nil) return STharderr; if(t->targetno == 0x07) return STownid; if(dbytes) n = *dbytes; else n = 0; s = io(ctlr, t->targetno, (cmd[1] >> 5) & 7, rw, cmd, cbytes, data, n, dbytes); switch(s){ case STATUS_COMPLETE: return STok; case STATUS_FAIL: return STharderr; case STATUS_SELECTION_TIMEOUT: return STtimeout; case 0x6002: return STcheck; default: print("scsi#%d: exec status 0x%ux\n", ctlr->ctlrno, s); return STharderr; }}#endifstatic voidcribbios(Controller *c){ c->bios.scntl3 = c->n->scntl3; c->bios.stest2 = c->n->stest2; KPRINT(PRINTPREFIX "bios scntl3(%.2x) stest2(%.2x)\n", c->bios.scntl3, c->bios.stest2);}static intbios_set_differential(Controller *c){ /* Concept lifted from FreeBSD - thanks Gerard */ /* basically, if clock conversion factors are set, then there is * evidence the bios had a go at the chip, and if so, it would * have set the differential enable bit in stest2 */ return (c->bios.scntl3 & 7) != 0 && (c->bios.stest2 & 0x20) != 0;}#define NCR_VID 0x1000#define NCR_810_DID 0x0001#define NCR_820_DID 0x0002 /* don't know enough about this one to support it */#define NCR_825_DID 0x0003#define NCR_815_DID 0x0004#define SYM_810AP_DID 0x0005#define SYM_860_DID 0x0006#define SYM_896_DID 0x000b#define SYM_895_DID 0x000c#define SYM_885_DID 0x000d /* ditto */#define SYM_875_DID 0x000f /* ditto */#define SYM_1010_DID 0x0020#define SYM_875J_DID 0x008fstatic Variant variant[] = {{ NCR_810_DID, 0x0f, "NCR53C810", Burst16, 8, 24, 0 },{ NCR_810_DID, 0x1f, "SYM53C810ALV", Burst16, 8, 24, Prefetch },{ NCR_810_DID, 0xff, "SYM53C810A", Burst16, 8, 24, Prefetch },{ SYM_810AP_DID, 0xff, "SYM53C810AP", Burst16, 8, 24, Prefetch },{ NCR_815_DID, 0xff, "NCR53C815", Burst16, 8, 24, BurstOpCodeFetch },{ NCR_825_DID, 0x0f, "NCR53C825", Burst16, 8, 24, Wide|BurstOpCodeFetch|Differential },{ NCR_825_DID, 0xff, "SYM53C825A", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide },{ SYM_860_DID, 0x0f, "SYM53C860", Burst16, 8, 24, Prefetch|Ultra },{ SYM_860_DID, 0xff, "SYM53C860LV", Burst16, 8, 24, Prefetch|Ultra },{ SYM_875_DID, 0x01, "SYM53C875r1", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra },{ SYM_875_DID, 0xff, "SYM53C875", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },{ SYM_875J_DID, 0xff, "SYM53C875j", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },{ SYM_885_DID, 0xff, "SYM53C885", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|ClockDouble },{ SYM_895_DID, 0xff, "SYM53C895", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },{ SYM_896_DID, 0xff, "SYM53C896", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },{ SYM_1010_DID, 0xff, "SYM53C1010", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },};#define MAXVAR (sizeof(variant)/sizeof(variant[0]))#ifndef NAINCLUDEstatic intna_fixup(Controller *c, ulong pa_reg, struct na_patch *patch, int patches, int (*externval)(Controller*, int, ulong*)){ int p; int v; ulong *script, pa_script; unsigned long lw, lv; script = c->script; pa_script = c->scriptpa; for (p = 0; p < patches; p++) { switch (patch[p].type) { case 1: /* script relative */ script[patch[p].lwoff] += pa_script; break; case 2: /* register i/o relative */ script[patch[p].lwoff] += pa_reg; break; case 3: /* data external */ lw = script[patch[p].lwoff]; v = (lw >> 8) & 0xff; if (!(*externval)(c, v, &lv)) return 0; v = lv & 0xff; script[patch[p].lwoff] = (lw & 0xffff00ffL) | (v << 8); break; case 4: /* 32 bit external */ lw = script[patch[p].lwoff]; if (!(*externval)(c, lw, &lv)) return 0; script[patch[p].lwoff] = lv; break; case 5: /* 24 bit external */ lw = script[patch[p].lwoff]; if (!(*externval)(c, lw & 0xffffff, &lv)) return 0; script[patch[p].lwoff] = (lw & 0xff000000L) | (lv & 0xffffffL); break; } } return 1;}#endif /* NAINCLUDE */typedef struct Adapter { Pcidev* pcidev; int port; int irq; int rid;} Adapter;static Msgbuf* adapter;static voidscanpci(void){ Pcidev *p; Msgbuf *mb, *last; Adapter *ap; p = nil; last = nil; while(p = pcimatch(p, NCR_VID, 0)){ mb = mballoc(sizeof(Adapter), 0, Mxxx); ap = (Adapter*)mb->data; ap->pcidev = p; ap->port = p->mem[0].bar & ~0x01; if(adapter == nil) adapter = mb; else last->next = mb; last = mb; }}static intinit(Controller* ctlr, ISAConf* isa, int differential){ int is64, var, rid; ulong regpa, scriptpa; Pcidev *pcidev; Msgbuf *mb, **mbb; Adapter *ap; extern ulong upamalloc(ulong, int, int); /* * Any adapter matches if no isa->port is supplied, * otherwise the ports must match. */ pcidev = nil; mbb = &adapter; for(mb = *mbb; mb; mb = mb->next){ ap = (Adapter*)mb->data; if(isa->port == 0 || isa->port == ap->port){ pcidev = ap->pcidev; *mbb = mb->next; mbfree(mb); break; } mbb = &mb->next; } if(pcidev == nil) return 0; rid = pcicfgr8(pcidev, PciRID); for (var = 0; var < MAXVAR; var++) { if (pcidev->did == variant[var].did && rid <= variant[var].maxrid) break; } if (var >= MAXVAR) return 0; print("scsi#%d: %s rev. 0x%.2x intr=%d command=%.4x\n", ctlr->ctlrno, variant[var].name, rid, pcidev->intl, pcicfgr16(pcidev, PciPCR)); is64 = pcidev->mem[1].bar & 0x04; if(is64 && pcidev->mem[2].bar){ print("scsi#%d: registers in 64-bit space\n", ctlr->ctlrno); return 0; } regpa = upamalloc(pcidev->mem[1].bar & ~0x0F, pcidev->mem[1].size, 0); if (regpa == 0) { print("scsi#%d: failed to map registers\n", ctlr->ctlrno); return 0; } ctlr->n = KADDR(regpa); ctlr->v = &variant[var]; scriptpa = 0; if ((ctlr->v->feature & LocalRAM) && sizeof(na_script) <= 4096) { if(is64){ if((pcidev->mem[3].bar & 0x04) && pcidev->mem[4].bar){ print("scsi#%d: RAM in 64-bit space\n", ctlr->ctlrno); scriptpa = 0; } else scriptpa = upamalloc(pcidev->mem[3].bar & ~0x0F, pcidev->mem[3].size, 0); } else scriptpa = upamalloc(pcidev->mem[2].bar & ~0x0F, pcidev->mem[2].size, 0); if (scriptpa == 0) print("scsi#%d: failed to map onboard RAM\n", ctlr->ctlrno); else { ctlr->script = KADDR(scriptpa); ctlr->scriptpa = scriptpa; memmove(ctlr->script, na_script, sizeof(na_script)); print("scsi#%d: local SCRIPT ram enabled\n", ctlr->ctlrno); } } if (scriptpa == 0) { /* either the map failed, or this chip does not have local RAM * it will need a copy of the microcode */ /* * should allocate memory and copy na_script into it for * multiple controllers here * single controller version uses the microcode in place */ ctlr->script = na_script; ctlr->scriptpa = DMASEG(na_script); } /* fixup script */ if (!na_fixup(ctlr, regpa, na_patches, NA_PATCHES, xfunc)) { print("script fixup failed\n"); return 0; } if (differential) ctlr->feature |= Differential; swabl(ctlr->script, ctlr->script, sizeof(na_script)); ctlr->dsalist.freechain = 0; lesetl(ctlr->dsalist.head, 0); isa->port = (ulong)KADDR(regpa); isa->irq = pcidev->intl; synctabinit(ctlr); cribbios(ctlr); /* intrenable(isa->irq, interrupt, ctlr, pcidev->tbdf); */ setvec(IRQBASE + isa->irq, interrupt, ctlr); reset(ctlr); return 1;}#ifdef CPUint (*ncr53c8xxreset(void))(Scsi*, int){ ISAConf isaconf; int ic; int differential = 0; int o; Controller *c; memset(&isaconf, 0, sizeof(isaconf)); strcpy(isaconf.type, DEVICENAME); ic = isaconfig("scsi", 0, &isaconf); /* search any ISA opts */ if (ic) { for (o = 0; o < isaconf.nopt; o++) { if (strcmp(isaconf.opt[o], "diff") == 0) differential = 1; } } c = &controller; /* MULTIPLE - map from scsi bus to controller instance */ if (init(c, differential)) return exec; return 0;}#endif#ifdef Plan9fsint (*ncr53c8xxreset(int /*ctlrno*/, ISAConf */*isa*/))(Device, int, uchar*, int, void*, int){ Controller *c = &controller; /* MULTIPLE - map from scsi bus to controller instance */ if (init(c, 0)) return exec; return 0;}#endif /* Plan9fs */#ifdef FSScsiioncr53c8xxreset(int ctlrno, ISAConf* isa){ int differential, o; Controller *ctlr; static int scandone; if(scandone == 0){ scanpci(); scandone = 1; } differential = 0; for (o = 0; o < isa->nopt; o++) { if (strcmp(isa->opt[o], "diff") == 0) differential = 1; } if((ctlr = xalloc(sizeof(Controller))) == 0){ print("scsi#%d: %s: controller allocation failed\n", ctlrno, isa->type); return 0; } ctlrxx[ctlrno] = ctlr; ctlr->ctlrno = ctlrno; if (init(ctlr, isa, differential)) return exec; return 0;}#endif /* FS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -