| plan 9 kernel history: overview | file list | diff list |
2001/0314/alphapc/sd53c8xx.c (diff list | history)
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1,54 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1,16 (short | long | prev | next) | ||
| 2000/0515 | /* | |
| 2001/0314 | * NCR/Symbios/LSI Logic 53c8xx driver for Plan 9 * Nigel Roles (nigel@9fs.org) | |
| 2000/0515 | * | |
| 2001/0314 | * 13/3/01 Fixed microcode to support targets > 7 | |
| 2000/0515 | * | |
| 2001/0314 | * 01/12/00 Removed previous comments. Fixed a small problem in * mismatch recovery for targets with synchronous offsets of >=16 * connected to >=875s. Thanks, Jean. | |
| 2000/0515 | * | |
| 2001/0314 | * * Read/write mismatch recovery may fail on 53c1010s. Really need to get a manual. | |
| 2000/0515 | */ #define MAXTARGET 16 /* can be 8 or 16 */ | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:77,82 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:39,46 | ||
| 2000/0515 | /* CPU specific macros */ /**********************************/ | |
| 2001/0314 | #define PRINTPREFIX "sd53c8xx: " | |
| 2000/0515 | #ifdef BOOTDEBUG #define KPRINT oprint | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:315,320 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:279,288 | ||
| 2000/0515 | typedef struct Controller { Lock; | |
| 2001/0314 | struct { uchar scntl3; uchar stest2; } bios; | |
| 2000/0515 | uchar synctab[NULTRA2SCF - 1][8];/* table of legal tpfs */ NegoState s[MAXTARGET]; uchar scntl3[MAXTARGET]; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:340,352 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:308,321 | ||
| 2000/0515 | Lock; uchar head[4]; /* head of free list (NCR byte order) */ Dsa *tail; | |
| 2001/0314 | Dsa *freechain; | |
| 2000/0515 | } dsalist; QLock q[MAXTARGET]; /* queues for each target */ } Controller; | |
| 2001/0314 | #define SYNCOFFMASK(c) (((c)->v->maxsyncoff * 2) - 1) #define SSIDMASK(c) (((c)->v->feature & Wide) ? 15 : 7) | |
| 2000/0515 | /* ISTAT */ enum { Abrt = 0x80, Srst = 0x40, Sigp = 0x20, Sem = 0x10, Con = 0x08, Intf = 0x04, Sip = 0x02, Dip = 0x01 }; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:359,364 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:328,334 | ||
| 2000/0515 | static void setmovedata(Movedata*, ulong, ulong); static void advancedata(Movedata*, long); | |
| 2001/0314 | static int bios_set_differential(Controller *c); | |
| 2000/0515 | static char *phase[] = { "data out", "data in", "command", "status", | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:416,468 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:386,391 | ||
| 2000/0515 | #include "sd53c8xx.i" | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:469,478 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:392,401 | ||
| 2000/0515 | Dsa *d; ilock(&c->dsalist); | |
| 2001/0314 | if ((d = c->dsalist.freechain) == 0) { | |
| 2000/0515 | d = xalloc(sizeof(*d)); if (DEBUG(1)) | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d/%d: allocated new dsa %lux\n", target, lun, (ulong)d); | |
| 2000/0515 | lesetl(d->next, 0); lesetl(d->state, A_STATE_ALLOCATED); if (legetl(c->dsalist.head) == 0) | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:483,490 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:406,413 | ||
| 2000/0515 | } else { if (DEBUG(1)) | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d/%d: reused dsa %lux\n", target, lun, (ulong)d); c->dsalist.freechain = d->freechain; | |
| 2000/0515 | lesetl(d->state, A_STATE_ALLOCATED); } iunlock(&c->dsalist); | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:497,504 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:420,427 | ||
| 2000/0515 | dsafree(Controller *c, Dsa *d) { ilock(&c->dsalist); | |
| 2001/0314 | d->freechain = c->dsalist.freechain; c->dsalist.freechain = d; | |
| 2000/0515 | lesetl(d->state, A_STATE_FREE); iunlock(&c->dsalist); } | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:753,759 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:676,682 | ||
| 2000/0515 | if (chooserate(c, tpf, &scf, &xferp) == tpf) { unsigned tp = tpf == 10 ? 25 : (tpf == 12 ? 50 : tpf * 4); unsigned long khz = (MEGA + tp - 1) / (tp); | |
| 2001/0314 | KPRINT(PRINTPREFIX "tpf=%d scf=%d.%.1d xferp=%d mhz=%ld.%.3ld\n", | |
| 2000/0515 | tpf, cf2[scf] / 2, (cf2[scf] & 1) ? 5 : 0, xferp + 4, khz / 1000, khz % 1000); USED(khz); | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:829,838 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:752,760 | ||
| 2000/0515 | ulong p; if (c->running) | |
| 2001/0314 | panic(PRINTPREFIX "start called while running"); | |
| 2000/0515 | c->running = 1; p = c->scriptpa + entry; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:842,848 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:764,770 | ||
| 2000/0515 | ncrcontinue(Controller *c) { if (c->running) | |
| 2001/0314 | panic(PRINTPREFIX "ncrcontinue called while running"); | |
| 2000/0515 | /* set the start DMA bit to continue execution */ c->running = 1; c->n->dcntl |= 0x4; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:886,898 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:808,820 | ||
| 2000/0515 | n->dmode |= (1 << 1); /* burst opcode fetch */ if (c->v->feature & Differential) { /* chip capable */ | |
| 2001/0314 | if ((c->feature & Differential) || bios_set_differential(c)) { /* user enabled, or some evidence bios set differential */ | |
| 2000/0515 | if (n->sstat2 & (1 << 2)) | |
| 2001/0314 | print(PRINTPREFIX "can't go differential; wrong cable\n"); | |
| 2000/0515 | else { n->stest2 = (1 << 5); | |
| 2001/0314 | print(PRINTPREFIX "differential mode set\n"); | |
| 2000/0515 | } } } | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:923,929 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:845,851 | ||
| 2000/0515 | /* reply to my SDTR */ histpf = n->scratcha[2]; hisreqack = n->scratcha[3]; | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: SDTN response %d %d\n", | |
| 2000/0515 | dsa->target, histpf, hisreqack); if (hisreqack == 0) | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:931,937 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:853,859 | ||
| 2000/0515 | else { /* hisreqack should be <= c->v->maxsyncoff */ tpf = chooserate(c, histpf, &scf, &xferp); | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: SDTN: using %d %d\n", | |
| 2000/0515 | dsa->target, tpf, hisreqack); setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack); } | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:939,954 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:861,876 | ||
| 2000/0515 | return; case A_SIR_EV_PHASE_SWITCH_AFTER_ID: /* target ignored ATN for message after IDENTIFY - not SCSI-II */ | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target); KPRINT(PRINTPREFIX "%d: SDTN: async\n", dsa->target); | |
| 2000/0515 | setasync(dsa, c, dsa->target); *cont = E_to_decisions; return; case A_SIR_MSG_REJECT: /* rejection of my SDTR */ | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: SDTN: rejected SDTR\n", dsa->target); | |
| 2000/0515 | //async: | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: SDTN: async\n", dsa->target); | |
| 2000/0515 | setasync(dsa, c, dsa->target); *cont = -2; return; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:958,964 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:880,886 | ||
| 2000/0515 | switch (msg) { case A_SIR_MSG_WDTR: /* reply to my WDTR */ | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: WDTN: response %d\n", | |
| 2000/0515 | dsa->target, n->scratcha[2]); setwide(dsa, c, dsa->target, n->scratcha[2]); *cont = -2; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:965,977 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:887,899 | ||
| 2000/0515 | return; case A_SIR_EV_PHASE_SWITCH_AFTER_ID: /* target ignored ATN for message after IDENTIFY - not SCSI-II */ | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target); | |
| 2000/0515 | setwide(dsa, c, dsa->target, 0); *cont = E_to_decisions; return; case A_SIR_MSG_REJECT: /* rejection of my SDTR */ | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: WDTN: rejected WDTR\n", dsa->target); | |
| 2000/0515 | setwide(dsa, c, dsa->target, 0); *cont = -2; return; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:986,996 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:908,918 | ||
| 2000/0515 | uchar hiswide, mywide; hiswide = n->scratcha[2]; mywide = (c->v->feature & Wide) != 0; | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: WDTN: target init %d\n", | |
| 2000/0515 | dsa->target, hiswide); if (hiswide < mywide) mywide = hiswide; | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: WDTN: responding %d\n", | |
| 2000/0515 | dsa->target, mywide); setwide(dsa, c, dsa->target, mywide); len = buildwdtrmsg(dsa->msg_out, mywide); | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1007,1013 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:929,935 | ||
| 2000/0515 | /* target decides to renegotiate */ histpf = n->scratcha[2]; hisreqack = n->scratcha[3]; | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: SDTN: target init %d %d\n", | |
| 2000/0515 | dsa->target, histpf, hisreqack); if (hisreqack == 0) { /* he wants asynchronous */ | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1019,1025 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:941,947 | ||
| 2000/0515 | tpf = chooserate(c, histpf, &scf, &xferp); if (hisreqack > c->v->maxsyncoff) hisreqack = c->v->maxsyncoff; | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: using %d %d\n", | |
| 2000/0515 | dsa->target, tpf, hisreqack); setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack); } | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1036,1047 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:958,969 | ||
| 2000/0515 | switch (msg) { case A_SIR_EV_RESPONSE_OK: c->s[dsa->target] = WideDone; | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: WDTN: response accepted\n", dsa->target); | |
| 2000/0515 | *cont = -2; return; case A_SIR_MSG_REJECT: setwide(dsa, c, dsa->target, 0); | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: WDTN: response REJECTed\n", dsa->target); | |
| 2000/0515 | *cont = -2; return; } | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1050,1068 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:972,990 | ||
| 2000/0515 | switch (msg) { case A_SIR_EV_RESPONSE_OK: c->s[dsa->target] = BothDone; | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: SDTN: response accepted (%s)\n", | |
| 2000/0515 | dsa->target, phase[n->sstat1 & 7]); *cont = -2; return; /* chf */ case A_SIR_MSG_REJECT: setasync(dsa, c, dsa->target); | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: SDTN: response REJECTed\n", dsa->target); | |
| 2000/0515 | *cont = -2; return; } break; } | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: msgsm: state %d msg %d\n", | |
| 2000/0515 | dsa->target, c->s[dsa->target], msg); *wakeme = 1; return; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1102,1111 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1024,1033 | ||
| 2000/0515 | else inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f; if (inchip) { | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: DMA FIFO = %d\n", | |
| 2000/0515 | dsa->target, dsa->lun, inchip); } | |
| 2001/0314 | if (n->sxfer & SYNCOFFMASK(c)) { | |
| 2000/0515 | /* SCSI FIFO */ uchar fifo = n->sstat1 >> 4; if (c->v->maxsyncoff > 8) | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1112,1118 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1034,1040 | ||
| 2000/0515 | fifo |= (n->sstat2 & (1 << 4)); if (fifo) { inchip += fifo; | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SCSI FIFO = %d\n", | |
| 2000/0515 | dsa->target, dsa->lun, fifo); } } | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1119,1130 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1041,1052 | ||
| 2000/0515 | else { if (n->sstat0 & (1 << 7)) { inchip++; | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SIDL full\n", | |
| 2000/0515 | dsa->target, dsa->lun); } if (n->sstat2 & (1 << 7)) { inchip++; | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SIDL msb full\n", | |
| 2000/0515 | dsa->target, dsa->lun); } } | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1133,1139 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1055,1061 | ||
| 2000/0515 | } static ulong | |
| 2001/0314 | write_mismatch_recover(Controller *c, Ncr *n, Dsa *dsa) | |
| 2000/0515 | { ulong dbc; uchar dfifo = n->dfifo; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1147,1153 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1069,1075 | ||
| 2000/0515 | inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f; #ifdef WMR_DEBUG if (inchip) { | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: DMA FIFO = %d\n", | |
| 2000/0515 | dsa->target, dsa->lun, inchip); } #endif | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1154,1174 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1076,1096 | ||
| 2000/0515 | if (n->sstat0 & (1 << 5)) { inchip++; #ifdef WMR_DEBUG | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODL full\n", dsa->target, dsa->lun); | |
| 2000/0515 | #endif } if (n->sstat2 & (1 << 5)) { inchip++; #ifdef WMR_DEBUG | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODL msb full\n", dsa->target, dsa->lun); | |
| 2000/0515 | #endif } | |
| 2001/0314 | if (n->sxfer & SYNCOFFMASK(c)) { | |
| 2000/0515 | /* synchronous SODR */ if (n->sstat0 & (1 << 6)) { inchip++; #ifdef WMR_DEBUG | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODR full\n", | |
| 2000/0515 | dsa->target, dsa->lun); #endif } | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1175,1181 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1097,1103 | ||
| 2000/0515 | if (n->sstat2 & (1 << 6)) { inchip++; #ifdef WMR_DEBUG | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODR msb full\n", | |
| 2000/0515 | dsa->target, dsa->lun); #endif } | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1202,1208 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1124,1130 | ||
| 2000/0515 | USED(ur); if (DEBUG(1)) | |
| 2001/0314 | IPRINT(PRINTPREFIX "int\n"); | |
| 2000/0515 | ilock(c); istat = n->istat; if (istat & Intf) { | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1209,1215 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1131,1137 | ||
| 2000/0515 | Dsa *d; int wokesomething = 0; if (DEBUG(1)) | |
| 2001/0314 | IPRINT(PRINTPREFIX "Intfly\n"); | |
| 2000/0515 | n->istat = Intf; /* search for structures in A_STATE_DONE */ for (d = KPTR(legetl(c->dsalist.head)); d; d = KPTR(legetl(d->next))) { | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1216,1233 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1138,1155 | ||
| 2000/0515 | if (d->stateb == A_STATE_DONE) { d->p9status = d->status; if (DEBUG(1)) | |
| 2001/0314 | IPRINT(PRINTPREFIX "waking up dsa %lux\n", (ulong)d); | |
| 2000/0515 | wakeup(d); wokesomething = 1; } } if (!wokesomething) | |
| 2001/0314 | IPRINT(PRINTPREFIX "nothing to wake up\n"); | |
| 2000/0515 | } if ((istat & (Sip | Dip)) == 0) { if (DEBUG(1)) | |
| 2001/0314 | IPRINT(PRINTPREFIX "int end %x\n", istat); | |
| 2000/0515 | iunlock(c); return; } | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1250,1256 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1172,1178 | ||
| 2000/0515 | addr = legetl(n->dsp); sa = addr - c->scriptpa; if (DEBUG(1) || DEBUG(2)) | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: Phase Mismatch sa=%.8lux\n", | |
| 2000/0515 | dsa->target, dsa->lun, sa); /* * now recover | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1260,1266 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1182,1188 | ||
| 2000/0515 | tbc = legetl(dsa->data_buf.dbc) - dbc; advancedata(&dsa->data_buf, tbc); if (DEBUG(1) || DEBUG(2)) | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: transferred = %ld residue = %ld\n", | |
| 2000/0515 | dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc)); cont = E_to_decisions; } | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1286,1301 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1208,1223 | ||
| 2000/0515 | cont = E_data_block_mismatch_recover; } else if (sa == E_data_out_mismatch) { | |
| 2001/0314 | dbc = write_mismatch_recover(c, n, dsa); | |
| 2000/0515 | tbc = legetl(dsa->data_buf.dbc) - dbc; advancedata(&dsa->data_buf, tbc); if (DEBUG(1) || DEBUG(2)) | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: transferred = %ld residue = %ld\n", | |
| 2000/0515 | dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc)); cont = E_to_decisions; } else if (sa == E_data_out_block_mismatch) { | |
| 2001/0314 | dbc = write_mismatch_recover(c, n, dsa); | |
| 2000/0515 | tbc = legetl(dsa->data_buf.dbc) - dbc; /* recover current state from registers */ dmablks = n->scratcha[2]; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1329,1337 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1251,1259 | ||
| 2000/0515 | */ ulong lim = legetl(dsa->msg_out_buf.dbc); uchar p = n->sstat1 & 7; | |
| 2001/0314 | dbc = write_mismatch_recover(c, n, dsa); | |
| 2000/0515 | tbc = lim - dbc; | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: msg_out_mismatch: %lud/%lud sent, phase %s\n", | |
| 2000/0515 | 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); | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1345,1359 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1267,1281 | ||
| 2000/0515 | */ ulong lim = legetl(dsa->cmd_buf.dbc); uchar p = n->sstat1 & 7; | |
| 2001/0314 | dbc = write_mismatch_recover(c, n, dsa); | |
| 2000/0515 | tbc = lim - dbc; | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: cmd_out_mismatch: %lud/%lud sent, phase %s\n", | |
| 2000/0515 | dsa->target, dsa->lun, tbc, lim, phase[p]); USED(p, tbc); cont = E_to_decisions; } else { | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: ma sa=%.8lux wanted=%s got=%s\n", | |
| 2000/0515 | dsa->target, dsa->lun, sa, phase[n->dcmd & 7], phase[n->sstat1 & 7]); | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1364,1370 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1286,1292 | ||
| 2000/0515 | } /*else*/ if (sist & 0x400) { if (DEBUG(0)) | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d Sto\n", dsa->target, dsa->lun); | |
| 2000/0515 | dsa->p9status = SDtimeout; dsa->stateb = A_STATE_DONE; softreset(c); | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1372,1382 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1294,1304 | ||
| 2000/0515 | wakeme = 1; } if (sist & 0x1) { | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: parity error\n", dsa->target, dsa->lun); | |
| 2000/0515 | dsa->parityerror = 1; } if (sist & 0x4) { | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: unexpected disconnect\n", | |
| 2000/0515 | dsa->target, dsa->lun); dumpncrregs(c, 1); //wakeme = 1; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1407,1416 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1329,1338 | ||
| 2000/0515 | break; case A_SIR_MSG_IGNORE_WIDE_RESIDUE: /* back up one in the data transfer */ | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: ignore wide residue %d, WSR = %d\n", | |
| 2000/0515 | dsa->target, dsa->lun, n->scratcha[1], n->scntl2 & 1); if (dsa->dmablks == 0 && dsa->flag) | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: transfer over; residue ignored\n", | |
| 2000/0515 | dsa->target, dsa->lun); else calcblockdma(dsa, legetl(dsa->dmaaddr) - 1, | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1418,1470 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1340,1392 | ||
| 2000/0515 | cont = -2; break; case A_SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT: | |
| 2001/0314 | 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); | |
| 2000/0515 | dumpncrregs(c, 1); wakeme = 1; break; case A_SIR_NOTIFY_MSG_IN: | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: msg_in %d\n", | |
| 2000/0515 | dsa->target, dsa->lun, n->sfbr); cont = -2; break; case A_SIR_NOTIFY_DISC: | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: disconnect:", dsa->target, dsa->lun); | |
| 2000/0515 | goto dsadump; case A_SIR_NOTIFY_STATUS: | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: status\n", dsa->target, dsa->lun); | |
| 2000/0515 | cont = -2; break; case A_SIR_NOTIFY_COMMAND: | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: commands\n", dsa->target, dsa->lun); | |
| 2000/0515 | cont = -2; break; case A_SIR_NOTIFY_DATA_IN: | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: data in a %lx b %lx\n", | |
| 2000/0515 | dsa->target, dsa->lun, legetl(n->scratcha), legetl(n->scratchb)); cont = -2; break; case A_SIR_NOTIFY_BLOCK_DATA_IN: | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: block data in: a2 %x b %lx\n", | |
| 2000/0515 | dsa->target, dsa->lun, n->scratcha[2], legetl(n->scratchb)); cont = -2; break; case A_SIR_NOTIFY_DATA_OUT: | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: data out\n", dsa->target, dsa->lun); | |
| 2000/0515 | cont = -2; break; case A_SIR_NOTIFY_DUMP: | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: dump\n", dsa->target, dsa->lun); | |
| 2000/0515 | dumpncrregs(c, 1); cont = -2; break; case A_SIR_NOTIFY_DUMP2: | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: dump2:", dsa->target, dsa->lun); | |
| 2000/0515 | IPRINT(" sa %lux", legetl(n->dsp) - c->scriptpa); IPRINT(" dsa %lux", legetl(n->dsa)); IPRINT(" sfbr %ux", n->sfbr); | |
| 2001/0314 | IPRINT(" a %lux", legetl(n->scratcha)); | |
| 2000/0515 | IPRINT(" b %lux", legetl(n->scratchb)); IPRINT(" ssid %ux", n->ssid); IPRINT("\n"); | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1471,1486 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1393,1408 | ||
| 2000/0515 | cont = -2; break; case A_SIR_NOTIFY_WAIT_RESELECT: | |
| 2001/0314 | IPRINT(PRINTPREFIX "wait reselect\n"); | |
| 2000/0515 | cont = -2; break; case A_SIR_NOTIFY_RESELECT: | |
| 2001/0314 | IPRINT(PRINTPREFIX "reselect: ssid %.2x sfbr %.2x at %ld\n", | |
| 2000/0515 | n->ssid, n->sfbr, TK2MS(m->ticks)); cont = -2; break; case A_SIR_NOTIFY_ISSUE: | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: issue:", dsa->target, dsa->lun); | |
| 2000/0515 | dsadump: IPRINT(" tgt=%d", dsa->target); IPRINT(" time=%ld", TK2MS(m->ticks)); | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1488,1504 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1410,1426 | ||
| 2000/0515 | cont = -2; break; case A_SIR_NOTIFY_ISSUE_CHECK: | |
| 2001/0314 | IPRINT(PRINTPREFIX "issue check\n"); | |
| 2000/0515 | cont = -2; break; case A_SIR_NOTIFY_SIGP: | |
| 2001/0314 | IPRINT(PRINTPREFIX "responded to SIGP\n"); | |
| 2000/0515 | cont = -2; break; case A_SIR_NOTIFY_DUMP_NEXT_CODE: { ulong *dsp = DMASEG_TO_KADDR(legetl(n->dsp)); int x; | |
| 2001/0314 | IPRINT(PRINTPREFIX "code at %lux", dsp - c->script); | |
| 2000/0515 | for (x = 0; x < 6; x++) IPRINT(" %.8lux", dsp[x]); IPRINT("\n"); | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1507,1527 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1429,1449 | ||
| 2000/0515 | break; } case A_SIR_NOTIFY_WSR: | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: WSR set\n", dsa->target, dsa->lun); | |
| 2000/0515 | cont = -2; break; case A_SIR_NOTIFY_LOAD_SYNC: | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: scntl=%.2x sxfer=%.2x\n", | |
| 2000/0515 | dsa->target, dsa->lun, n->scntl3, n->sxfer); cont = -2; break; case A_SIR_NOTIFY_RESELECTED_ON_SELECT: | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: reselected during select\n", | |
| 2000/0515 | dsa->target, dsa->lun); cont = -2; break; default: | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: script error %ld\n", | |
| 2000/0515 | dsa->target, dsa->lun, legetl(n->dsps)); dumpncrregs(c, 1); wakeme = 1; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1530,1536 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1452,1458 | ||
| 2000/0515 | /*else*/ if (dstat & Iid) { ulong addr = legetl(n->dsp); ulong dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0]; | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: Iid pa=%.8lux sa=%.8lux dbc=%lux\n", | |
| 2000/0515 | dsa->target, dsa->lun, addr, addr - c->scriptpa, dbc); addr = (ulong)DMASEG_TO_KADDR(addr); | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1541,1547 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1463,1469 | ||
| 2000/0515 | wakeme = 1; } /*else*/ if (dstat & Bf) { | |
| 2001/0314 | IPRINT(PRINTPREFIX "%d/%d: Bus Fault\n", dsa->target, dsa->lun); | |
| 2000/0515 | dumpncrregs(c, 1); dsa->p9status = SDeio; wakeme = 1; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1558,1564 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1480,1486 | ||
| 2000/0515 | } iunlock(c); if (DEBUG(1)) { | |
| 2001/0314 | IPRINT(PRINTPREFIX "int end 1\n"); | |
| 2000/0515 | } } | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1599,1605 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1521,1527 | ||
| 2000/0515 | } if (datalen) { | |
| 2001/0314 | KPRINT(PRINTPREFIX "write:"); | |
| 2000/0515 | for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++) KPRINT("%.2ux", *bp); if (i < datalen) { | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1620,1626 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1542,1548 | ||
| 2000/0515 | } if (datalen) { | |
| 2001/0314 | KPRINT(PRINTPREFIX "read:"); | |
| 2000/0515 | for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++) KPRINT("%.2ux", *bp); if (i < datalen) { | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1697,1703 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1619,1625 | ||
| 2000/0515 | /* work out what to do about negotiation */ switch (c->s[target]) { default: | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: strange nego state %d\n", target, c->s[target]); | |
| 2000/0515 | c->s[target] = NeitherDone; /* fall through */ case NeitherDone: | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1709,1735 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1631,1657 | ||
| 2000/0515 | my_expo = target_expo; #ifdef ALWAYS_DO_WDTR bc += buildwdtrmsg(d->msg_out + bc, my_expo); | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: WDTN: initiating expo %d\n", target, my_expo); | |
| 2000/0515 | c->s[target] = WideInit; break; #else if (my_expo) { bc += buildwdtrmsg(d->msg_out + bc, (c->v->feature & Wide) ? 1 : 0); | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: WDTN: initiating expo %d\n", target, my_expo); | |
| 2000/0515 | c->s[target] = WideInit; break; } | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: WDTN: narrow\n", target); | |
| 2000/0515 | /* fall through */ #endif case WideDone: if (c->cap[target] & (1 << 4)) { | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: SDTN: initiating %d %d\n", target, c->tpf, c->v->maxsyncoff); | |
| 2000/0515 | bc += buildsdtrmsg(d->msg_out + bc, c->tpf, c->v->maxsyncoff); c->s[target] = SyncInit; break; } | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: SDTN: async only\n", target); | |
| 2000/0515 | c->s[target] = BothDone; break; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1742,1753 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1664,1675 | ||
| 2000/0515 | calcblockdma(d, DMASEG(r->data), r->dlen); if (DEBUG(0)) { | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d/%d: exec: ", target, r->lun); | |
| 2000/0515 | for (bp = r->cmd; bp < &r->cmd[r->clen]; bp++) KPRINT("%.2ux", *bp); KPRINT("\n"); if (!r->write) | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d/%d: exec: limit=(%d)%ld\n", | |
| 2000/0515 | target, r->lun, d->dmablks, legetl(d->data_buf.dbc)); else dumpwritedata(r->data, r->dlen); | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1759,1771 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1681,1691 | ||
| 2000/0515 | d->parityerror = 0; d->stateb = A_STATE_ISSUE; /* start operation */ | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1775,1787 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1695,1706 | ||
| 2000/0515 | while(waserror()) ; | |
| 2001/0314 | tsleep(d, done, d, 600 * 1000); | |
| 2000/0515 | poperror(); if (!done(d)) { | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d/%d: exec: Timed out\n", target, r->lun); | |
| 2000/0515 | dumpncrregs(c, 0); | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1806,1812 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1725,1731 | ||
| 2000/0515 | if(!r->write) dumpreaddata(r->data, r->rlen); if (DEBUG(0)) | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d/%d: exec: p9status=%d status %d rlen %ld\n", | |
| 2000/0515 | target, r->lun, d->p9status, status, r->rlen); /* * spot the identify | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1817,1823 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1736,1742 | ||
| 2000/0515 | c->capvalid |= 1 << target; bp = r->data; c->cap[target] = bp[7]; | |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: capabilities %.2x\n", target, bp[7]); | |
| 2000/0515 | } if(!check && status == SDcheck && !(r->flags & SDnosense)){ check = 1; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1843,1853 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1762,1791 | ||
| 2000/0515 | status = SDcheck; r->flags |= SDvalidsense; } | |
| 2000/0608 |
| |
| 2001/0314 | KPRINT(PRINTPREFIX "%d: r flags %8.8uX status %d rlen %ld\n", | |
| 2000/0608 | target, r->flags, status, r->rlen); return r->status = status; | |
| 2000/0515 | } | |
| 2001/0314 | static void cribbios(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 int bios_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; } | |
| 2000/0515 | #define NCR_VID 0x1000 #define NCR_810_DID 0x0001 #define NCR_820_DID 0x0002 /* don't know enough about this one to support it */ | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1859,1864 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1797,1803 | ||
| 2000/0515 | #define SYM_895_DID 0x000c #define SYM_885_DID 0x000d /* ditto */ #define SYM_875_DID 0x000f /* ditto */ | |
| 2001/0314 | #define SYM_1010_DID 0x0020 | |
| 2000/0515 | #define SYM_875J_DID 0x008f static Variant variant[] = { | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1877,1882 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1816,1822 | ||
| 2000/0515 | { 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 }, | |
| 2001/0314 | { SYM_1010_DID, 0xff, "SYM53C1010", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 }, | |
| 2000/0515 | }; #define offsetof(s, t) ((ulong)&((s *)0)->t) | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1898,1903 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1838,1845 | ||
| 2000/0515 | *v = offsetof(Dsa, status_buf); return 1; case X_dsa_head: *v = DMASEG(&c->dsalist.head[0]); return 1; | |
| 2001/0314 | case X_ssid_mask: *v = SSIDMASK(c); return 1; | |
| 2000/0515 | default: print("xfunc: can't find external %d\n", x); return 0; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:1958,1981 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1900,1931 | ||
| 2000/0515 | static SDev* sympnp(void) { | |
| 2001/0314 | char *cp; | |
| 2000/0515 | Pcidev *p; Variant *v; | |
| 2001/0314 | int ba, nctlr; | |
| 2000/0515 | void *scriptma; Controller *ctlr; SDev *sdev, *head, *tail; ulong regpa, *script, scriptpa; | |
| 2001/0314 | if(cp = getconf("*maxsd53c8xx")) nctlr = strtoul(cp, 0, 0); else nctlr = 32; | |
| 2000/0515 | p = nil; head = tail = nil; | |
| 2001/0314 | while((p = pcimatch(p, NCR_VID, 0)) != nil && nctlr > 0){ | |
| 2000/0515 | for(v = variant; v < &variant[nelem(variant)]; v++){ if(p->did == v->did && p->rid <= v->maxrid) break; } | |
| 2001/0314 | if(v >= &variant[nelem(variant)]) { print("no match\n"); | |
| 2000/0515 | continue; | |
| 2001/0314 | } print(PRINTPREFIX "%s rev. 0x%2.2x intr=%d command=%4.4luX\n", | |
| 2000/0515 | v->name, p->rid, p->intl, p->pcr); regpa = p->mem[1].bar; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:2044,2050 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:1994,2000 | ||
| 2000/0515 | } swabl(ctlr->script, ctlr->script, sizeof(na_script)); | |
| 2001/0314 | ctlr->dsalist.freechain = 0; | |
| 2000/0515 | lesetl(ctlr->dsalist.head, 0); ctlr->pcidev = p; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:2062,2067 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:2012,2019 | ||
| 2000/0515 | else head = sdev; tail = sdev; | |
| 2001/0314 | nctlr--; | |
| 2000/0515 | } return head; | |
| 2000/1129/sys/src/9/alphapc/sd53c8xx.c:2089,2094 – 2001/0314/sys/src/9/alphapc/sd53c8xx.c:2041,2047 | ||
| 2000/0515 | ilock(ctlr); synctabinit(ctlr); | |
| 2001/0314 | cribbios(ctlr); | |
| 2000/0515 | reset(ctlr); iunlock(ctlr); | |