📄 tu.c
字号:
/* not reached */ break; } tu.tu_rcnt = tudata.pk_mcount; tu.tu_state = TUS_GETD; break; /* * Got the data, now fetch the checksum. */ case TUS_GETD: tu.tu_rbptr = (u_char *)&tudata.pk_chksum; tu.tu_rcnt = sizeof (tudata.pk_chksum); tu.tu_state = TUS_GETC; break; case TUS_CHKERR: /* from tudma only */ tu.tu_cerrs++; goto tus_get; case TUS_GET: if (!MRSP) /* * The checksum has already been calculated and * verified in the pseudo DMA routine */ goto tus_get; case TUS_GETC: /* got entire packet */ if (tudata.pk_chksum != tuchk(*((short *)&tudata), (u_short *) (tudata.pk_flag == TUF_DATA ? (u_short *) tu.tu_addr : (u_short *)&tudata.pk_op), (int)tudata.pk_mcount)) tu.tu_cerrs++;tus_get: if (tudata.pk_flag == TUF_DATA) { /* data packet, advance to next */ tu.tu_addr += tudata.pk_mcount; tu.tu_count -= tudata.pk_mcount; tu.tu_state = TUS_GETH; tu.tu_rbptr = (u_char *)&tudata; /* next packet */ tu.tu_rcnt = 2; tu.tu_flag = 1; } else if (tudata.pk_flag==TUF_CMD && tudata.pk_op==TUOP_END) { /* end packet, idle and reenable transmitter */ tu.tu_state = TUS_IDLE; tu.tu_flag = 0; mtpr(CSTS, IE);#ifdef TUDEBUG printd("ON ");#endif if ((bp = tutab.b_actf) == NULL) { printf("tu%d: no bp, active %d\n", tudata.pk_unit, tutab.b_active); tustart(); return; } if (tudata.pk_mod > 1) { /* hard error */ bp->b_flags |= B_ERROR; tu.tu_herrs++; switch (tudata.pk_mod & 0377) { case 0377: sp = errstrgs[0]; break; case 0376: sp = errstrgs[1]; break; case 0370: sp = errstrgs[2]; break; case 0367: sp = errstrgs[3]; break; case 0365: sp = errstrgs[4]; break; case 0357: sp = errstrgs[5]; break; case 0340: sp = errstrgs[6]; break; case 0337: sp = errstrgs[7]; break; case 0320: sp = errstrgs[8]; break; case 0311: sp = errstrgs[9]; break; default: sp = errstrgs[10]; break; } printf("tu%d: hard error bn%d, pk_status %o %s\n", minor(bp->b_dev)&DNUM, bp->b_blkno, tudata.pk_mod&0377, sp); } else if (tudata.pk_mod != 0) /* soft error */ tu.tu_serrs++; tutab.b_active = NULL; tutab.b_actf = bp->av_forw; bp->b_resid = tu.tu_count; if ((bp->b_flags&B_READ) == 0) tu_vee(&tu_pcnt[minor(bp->b_dev)&DNUM]); timeout(iodone,bp,1); tu.tu_toerrs = tu.tu_poerrs = 0; tustart(); } else { /* * Neither data nor end: data was lost * somehow, restart the transfer */ mtpr(CSRS, 0); /* flush the rest */ tu_restart(); tu.tu_serrs++; } break; case TUS_IDLE: case TUS_INIT1: break; default:bad: if (c == TUF_INITF) { mprintf("tu%d: protocol error, state=%s op=%x cnt=%d \ block=%d\n", (int)tucmd.pk_unit, tustates[tu.tu_state], tucmd.pk_op, tucmd.pk_count, tucmd.pk_block); /* resync protocol and retry ---- pmk */ if (++tu.tu_poerrs > MAXERRS) { tu.tu_poerrs = 0; if ((bp = tutab.b_actf) != NULL) { bp->b_flags |= B_ERROR; tutab.b_active = NULL; tutab.b_actf = bp->av_forw; if ((bp->b_flags&B_READ) == 0) tu_vee(&tu_pcnt[minor(bp->b_dev)&DNUM]); timeout(iodone,bp,1); } } tureset(); } else { mprintf("tu%d: receive state error, state=%s byte=%x\n", (int)tucmd.pk_unit,tustates[tu.tu_state],c&0xff); if (tutab.b_actf) tu_restart(); else wakeup((caddr_t)&tu); } }}/* * TU58 transmitter interrupt */tuxintr(){top: if (tu.tu_wcnt) { /* still stuff to send, send one byte */ while ((mfpr(CSTS) & READY) == 0) ; mtpr(CSTD, *tu.tu_wbptr++); tu.tu_wcnt--; return; } /* * Last message byte was sent out. * Switch on state of transfer. */#ifdef TUDEBG if (tudebug) { printf("tuxintr: state="); printstate(tu.tu_state); }#endif switch(tu.tu_state) { /* * Two nulls have been sent, remove break, and send inits */ case TUS_INIT1: mtpr(CSTS, IE);#ifdef TUDEBUG printd("ON2 ");#endif tu.tu_state = TUS_INIT2; tu.tu_wbptr = tuinit; tu.tu_wcnt = sizeof (tuinit); goto top; /* * Inits have been sent, wait for a continue msg. */ case TUS_INIT2: mtpr(CSTS, 0); /* disable transmitter interrupts */ (void) mfpr(CSRD); mtpr(CSRS, IE); tu.tu_flag = 1; break; /* * Read cmd packet sent, get ready for data */ case TUS_SENDR: tu.tu_state = TUS_GETH; tu.tu_rbptr = (u_char *)&tudata; tu.tu_rcnt = 2; tu.tu_flag = 1; mtpr(CSTS, 0); /* disable transmitter interrupts */#ifdef TUDEBUG printd("OFF ");#endif break; /* * Write cmd packet sent, wait for continue */ case TUS_SENDW: tu.tu_state = TUS_WAIT; tu.tu_flag = 1; if ((mfpr(CSRS)&IE) == 0) { printf("NO IE\n"); mtpr(CSRS, IE); } break; /* * Header sent, send data. */ case TUS_SENDH: tu.tu_state = TUS_SENDD; tu.tu_wbptr = (u_char *)tu.tu_addr; tu.tu_wcnt = tudata.pk_mcount; goto top; /* * Data sent, follow with checksum. */ case TUS_SENDD: tu.tu_state = TUS_SENDC; tu.tu_wbptr = (u_char *)&tudata.pk_chksum; tu.tu_wcnt = sizeof tudata.pk_chksum; goto top; /* * Checksum sent, wait for continue. */ case TUS_SENDC: /* * Updata buffer address and count. */ tu.tu_addr += tudata.pk_mcount; tu.tu_count -= tudata.pk_mcount; if (tu.tu_count) { tu.tu_state = TUS_WAIT; tu.tu_flag = 1; break; } /* * End of transmission, get ready for end packet. */ tu.tu_state = TUS_GET; tu.tu_rbptr = (u_char *)&tudata; tu.tu_rcnt = sizeof (tudata); tu.tu_flag = 1; mtpr(CSTS, 0);#ifdef TUDEBUG printd("OFF2 ");#endif break; /* * Random interrupt, probably from MRSP ACK */ case TUS_IDLE: default: break; }#ifdef TUDEBUG if (tudebug) { printd(" new tu_state="); printstate(tu.tu_state); }#endif}/* * Compute checksum TU58 fashion */#ifdef linttuchk(word, cp, n) register word; register unsigned short *cp; int n;{ register int c = n >> 1; register long temp; do { temp = *cp++; /* temp, only because vax cc won't *r++ */ word += temp; } while (--c > 0); if (n & 1) word += *(unsigned char *)cp; while (word & 0xffff0000) word = (word & 0xffff) + ((word >> 16) & 0xffff); return (word);}#elsetuchk(word0, wp, n) register int word0; /* r11 */ register char *wp; /* r10 */ register int n; /* r9 */{ asm("loop:"); asm(" addw2 (r10)+,r11"); /* add a word to sum */ asm(" adwc $0,r11"); /* add in carry, end-around */ asm(" acbl $2,$-2,r9,loop"); /* done yet? */ asm(" blbc r9,ok"); /* odd byte count? */ asm(" movzbw (r10),r10"); /* yes, get last byte */ asm(" addw2 r10,r11"); /* add it in */ asm(" adwc $0,r11"); /* and the carry */ asm("ok:"); asm(" movl r11,r0"); /* return sum */}#endiftuwatch(){ register int s; register struct buf *bp; if (tutimer == -1) { /* set in tuclose */ tutimer = 0; return; } if (tu.tu_flag == 0) { /* if no read in progress - skip */ timeout(tuwatch, (caddr_t)0, hz); return; } if (tu.tu_flag++ <= 40) { timeout(tuwatch, (caddr_t)0, hz); return; } printf("tu%d: timeout, %s\n", tucmd.pk_unit, tu.tu_toerrs < MAXERRS ? "command restarted" : "give up!");#ifdef TUDEBUG printf(" %X %X %X %X %X %X %X %X\n", tu.tu_rbptr, tu.tu_rcnt, tu.tu_wbptr, tu.tu_wcnt, tu.tu_state, tu.tu_flag, tu.tu_addr, tu.tu_count);#endif s = splx(TUIPL); tu.tu_flag = 0; (void) mfpr(CSRD); mtpr(CSRS, IE); /* in case we were flushing */ mtpr(CSTS, IE); tu.tu_state = TUS_IDLE; if (!tutab.b_active) { wakeup((caddr_t)&tu); goto retry; } if (tu.tu_toerrs++ < MAXERRS) { tustart(); goto retry; } if ((bp = tutab.b_actf) != NULL) { bp->b_flags |= B_ERROR; tutab.b_active = NULL; tutab.b_actf = bp->av_forw; if ((bp->b_flags&B_READ) == 0) tu_vee(&tu_pcnt[minor(bp->b_dev)&DNUM]); timeout(iodone,bp,1); tu.tu_toerrs = 0; tustart(); }retry: splx(s); timeout(tuwatch, (caddr_t)0, hz);}tu_pee(cp) char *cp;{ register int s; s = splx(TUIPL); if (++(*cp) > NTUQ) sleep(cp, PRIBIO); splx(s);}tu_vee(cp) char *cp;{ register int s; s = splx(TUIPL); if (--(*cp) <= NTUQ) wakeup(cp); splx(s);}tu_restart(){ register int s; s = splx(TUIPL); tu.tu_flag = 0; (void) mfpr(CSRD); mtpr(CSRS, IE); /* in case we were flushing */ mtpr(CSTS, IE); tu.tu_state = TUS_IDLE; timeout(tustart, (caddr_t)0, hz * 4); splx(s);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -