📄 sd53c8xx.c
字号:
for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++) { KPRINT("%.2ux", *bp); } if (i < datalen) { KPRINT("..."); } KPRINT("\n"); }}static voidbusreset(Controller *c){ int x, ntarget; /* bus reset */ c->n->scntl1 |= (1 << 3); delay(500); c->n->scntl1 &= ~(1 << 3); if(!(c->v->feature & Wide)) ntarget = 8; else ntarget = MAXTARGET; for (x = 0; x < ntarget; x++) { setwide(0, c, x, 0);#ifndef ASYNC_ONLY c->s[x] = NeitherDone;#endif } c->capvalid = 0;}static voidreset(Controller *c){ /* should wakeup all pending tasks */ softreset(c); busreset(c);}static intsd53c8xxrio(SDreq* r){ Dsa *d; uchar *bp; Controller *c; uchar target_expo, my_expo; int bc, check, i, status, target; if((target = r->unit->subno) == 0x07) return r->status = SDtimeout; /* assign */ c = r->unit->dev->ctlr; check = 0; d = dsaalloc(c, target, r->lun); qlock(&c->q[target]); /* obtain access to target */docheck: /* 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 | r->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(r->cmd), r->clen); calcblockdma(d, r->data ? DMASEG(r->data) : 0, r->dlen); if (DEBUG(0)) { KPRINT(PRINTPREFIX "%d/%d: exec: ", target, r->lun); for (bp = r->cmd; bp < &r->cmd[r->clen]; bp++) { KPRINT("%.2ux", *bp); } KPRINT("\n"); if (!r->write) { KPRINT(PRINTPREFIX "%d/%d: exec: limit=(%d)%ld\n", target, r->lun, d->dmablks, legetl(d->data_buf.dbc)); } else dumpwritedata(r->data, r->dlen); } setmovedata(&d->status_buf, DMASEG(&d->status), 1); d->p9status = SDnostatus; d->parityerror = 0; coherence(); d->stateb = A_STATE_ISSUE; /* start operation */ coherence(); ilock(c); if (c->ssm) c->n->dcntl |= 0x10; /* single step */ if (c->running) { c->n->istat = Sigp; } else { start(c, E_issue_check); } iunlock(c); while(waserror()) ; tsleep(d, done, d, 600 * 1000); poperror(); if (!done(d)) { KPRINT(PRINTPREFIX "%d/%d: exec: Timed out\n", target, r->lun); dumpncrregs(c, 0); dsafree(c, d); reset(c); qunlock(&c->q[target]); r->status = SDtimeout; return r->status = SDtimeout; /* assign */ } if((status = d->p9status) == SDeio) c->s[target] = NeitherDone; if (d->parityerror) { status = SDeio; } /* * adjust datalen */ r->rlen = r->dlen; if (DEBUG(0)) { KPRINT(PRINTPREFIX "%d/%d: exec: before rlen adjust: dmablks %d flag %d dbc %lud\n", target, r->lun, d->dmablks, d->flag, legetl(d->data_buf.dbc)); } r->rlen = r->dlen; if (d->flag != 2) { r->rlen -= d->dmablks * A_BSIZE; r->rlen -= legetl(d->data_buf.dbc); } if(!r->write) dumpreaddata(r->data, r->rlen); if (DEBUG(0)) { KPRINT(PRINTPREFIX "%d/%d: exec: p9status=%d status %d rlen %ld\n", target, r->lun, d->p9status, status, r->rlen); } /* * spot the identify */ if ((c->capvalid & (1 << target)) == 0 && (status == SDok || status == SDcheck) && r->cmd[0] == 0x12 && r->dlen >= 8) { c->capvalid |= 1 << target; bp = r->data; c->cap[target] = bp[7]; KPRINT(PRINTPREFIX "%d: capabilities %.2x\n", target, bp[7]); } if(!check && status == SDcheck && !(r->flags & SDnosense)){ check = 1; r->write = 0; memset(r->cmd, 0, sizeof(r->cmd)); r->cmd[0] = 0x03; r->cmd[1] = r->lun<<5; r->cmd[4] = sizeof(r->sense)-1; r->clen = 6; r->data = r->sense; r->dlen = sizeof(r->sense)-1; /* * Clear out the microcode state * so the Dsa can be re-used. */ lesetl(&d->stateb, A_STATE_ALLOCATED); coherence(); goto docheck; } qunlock(&c->q[target]); dsafree(c, d); if(status == SDok && check){ status = SDcheck; r->flags |= SDvalidsense; } if(DEBUG(0)) KPRINT(PRINTPREFIX "%d: r flags %8.8uX status %d rlen %ld\n", target, r->flags, status, r->rlen); if(r->flags & SDvalidsense){ if(!DEBUG(0)) KPRINT(PRINTPREFIX "%d: r flags %8.8uX status %d rlen %ld\n", target, r->flags, status, r->rlen); for(i = 0; i < r->rlen; i++) KPRINT(" %2.2uX", r->sense[i]); KPRINT("\n"); } return r->status = status;}#define vpt ((ulong*)VPT)#define VPTX(va) (((ulong)(va))>>12)static voidcribbios(Controller *c){ c->bios.scntl3 = c->n->scntl3; c->bios.stest2 = c->n->stest2; print(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_1011_DID 0x0021#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 },{ SYM_1011_DID, 0xff, "SYM53C1010", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },};static intxfunc(Controller *c, enum na_external x, unsigned long *v){ switch (x) { case X_scsi_id_buf: *v = offsetof(Dsa, scsi_id_buf[0]); return 1; case X_msg_out_buf: *v = offsetof(Dsa, msg_out_buf); return 1; case X_cmd_buf: *v = offsetof(Dsa, cmd_buf); return 1; case X_data_buf: *v = offsetof(Dsa, data_buf); return 1; case X_status_buf: *v = offsetof(Dsa, status_buf); return 1; case X_dsa_head: *v = DMASEG(&c->dsalist.head[0]); return 1; case X_ssid_mask: *v = SSIDMASK(c); return 1; default: print("xfunc: can't find external %d\n", x); return 0; } return 1;}static 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;}static SDev*sd53c8xxpnp(void){ char *cp; Pcidev *p; Variant *v; int ba, nctlr; void *scriptma; Controller *ctlr; SDev *sdev, *head, *tail; ulong regpa, *script, scriptpa; void *regva, *scriptva; if(cp = getconf("*maxsd53c8xx")) nctlr = strtoul(cp, 0, 0); else nctlr = 32; p = nil; head = tail = nil; while((p = pcimatch(p, NCR_VID, 0)) != nil && nctlr > 0){ for(v = variant; v < &variant[nelem(variant)]; v++){ if(p->did == v->did && p->rid <= v->maxrid) break; } if(v >= &variant[nelem(variant)]) { print("no match\n"); continue; } print(PRINTPREFIX "%s rev. 0x%2.2x intr=%d command=%4.4uX\n", v->name, p->rid, p->intl, p->pcr); regpa = p->mem[1].bar; ba = 2; if(regpa & 0x04){ if(p->mem[2].bar) continue; ba++; } if(regpa == 0) print("regpa 0\n"); regpa &= ~0xF; regva = vmap(regpa, p->mem[1].size); if(regva == 0) continue; script = nil; scriptpa = 0; scriptva = nil; scriptma = nil; if((v->feature & LocalRAM) && sizeof(na_script) <= 4096){ scriptpa = p->mem[ba].bar; if((scriptpa & 0x04) && p->mem[ba+1].bar){ vunmap(regva, p->mem[1].size); continue; } scriptpa &= ~0x0F; scriptva = vmap(scriptpa, p->mem[ba].size); if(scriptva) script = scriptva; } if(scriptpa == 0){ /* * Either the map failed, or this chip does not have * local RAM. It will need a copy of the microcode. */ scriptma = malloc(sizeof(na_script)); if(scriptma == nil){ vunmap(regva, p->mem[1].size); continue; } scriptpa = DMASEG(scriptma); script = scriptma; } ctlr = malloc(sizeof(Controller)); sdev = malloc(sizeof(SDev)); if(ctlr == nil || sdev == nil){buggery: if(ctlr) free(ctlr); if(sdev) free(sdev); if(scriptma) free(scriptma); else if(scriptva) vunmap(scriptva, p->mem[ba].size); if(regva) vunmap(regva, p->mem[1].size); continue; } if(dsaend == nil) dsaend = xalloc(sizeof *dsaend); lesetl(&dsaend->stateb, A_STATE_END); // lesetl(dsaend->next, DMASEG(dsaend)); coherence(); lesetl(ctlr->dsalist.head, DMASEG(dsaend)); coherence(); ctlr->dsalist.freechain = 0; ctlr->n = regva; ctlr->v = v; ctlr->script = script; memmove(ctlr->script, na_script, sizeof(na_script)); /* * Because we don't yet have an abstraction for the * addresses as seen from the controller side (and on * the 386 it doesn't matter), the following three lines * are different between the 386 and alpha copies of * this driver. */ USED(scriptpa); ctlr->scriptpa = p->mem[ba].bar & ~0x0F; if(!na_fixup(ctlr, p->mem[1].bar & ~0x0F, na_patches, NA_PATCHES, xfunc)){ print("script fixup failed\n"); goto buggery; } swabl(ctlr->script, ctlr->script, sizeof(na_script)); ctlr->pcidev = p; sdev->ifc = &sd53c8xxifc; sdev->ctlr = ctlr; sdev->idno = '0'; if(!(v->feature & Wide)) sdev->nunit = 8; else sdev->nunit = MAXTARGET; ctlr->sdev = sdev; if(head != nil) tail->next = sdev; else head = sdev; tail = sdev; nctlr--; } return head;}static intsd53c8xxenable(SDev* sdev){ Pcidev *pcidev; Controller *ctlr; char name[32]; ctlr = sdev->ctlr; pcidev = ctlr->pcidev; pcisetbme(pcidev); ilock(ctlr); synctabinit(ctlr); cribbios(ctlr); reset(ctlr); snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name); intrenable(pcidev->intl, sd53c8xxinterrupt, ctlr, pcidev->tbdf, name); iunlock(ctlr); return 1;}SDifc sd53c8xxifc = { "53c8xx", /* name */ sd53c8xxpnp, /* pnp */ nil, /* legacy */ sd53c8xxenable, /* enable */ nil, /* disable */ scsiverify, /* verify */ scsionline, /* online */ sd53c8xxrio, /* rio */ nil, /* rctl */ nil, /* wctl */ scsibio, /* bio */ nil, /* probe */ nil, /* clear */ nil, /* stat */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -