📄 uu.c
字号:
default: /* something random...bad news */ uuc->tu_state = TUS_INIT1; break; } break; case TUS_SENDW: if (c != TUF_CONT && c != TUF_INITF) goto bad; uu_restart(ctlr, ui); break; /* * Got header, now get data; amount to * fetch is included in packet. * (data packets are handled entirely * in uudma) */ case TUS_GETH:#ifndef UUDMA if (data->pk_flag == TUF_DATA) uuc->tu_rbptr = (u_char *)uuc->tu_addr;#endif uuc->tu_rcnt = data->pk_mcount; uuc->tu_state = TUS_GETD; break; /* * Got the data, now fetch the checksum. */ case TUS_GETD: uuc->tu_rbptr = (u_char *)&data->pk_chksum; uuc->tu_rcnt = sizeof (data->pk_chksum); uuc->tu_state = TUS_GETC; break; case TUS_GETC: /* got entire packet */ if (data->pk_chksum != tuchk(*((short *)data), (u_short *) (data->pk_flag == TUF_DATA ? (u_short *) uuc->tu_addr : (u_short *)&data->pk_op), (int)data->pk_mcount)) case TUS_CHKERR: uuc->tu_cerrs++; case TUS_GET: if (data->pk_flag == TUF_DATA) { /* data packet, advance to next */ uuc->tu_addr += data->pk_mcount; uuc->tu_count -= data->pk_mcount; uuc->tu_state = TUS_GETH; uuc->tu_rbptr = (u_char *)data; /* next packet */ uuc->tu_rcnt = 2; } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) { /* end packet, idle and reenable transmitter */ uuc->tu_state = TUS_IDLE; uuc->tu_flag = 0; uuaddr->tcs = UUCS_INTR; if ((bp = uutab->b_actf) == NULL) { printf("uu%d: no bp, active %d\n", data->pk_unit, uitab[ctlr].b_active); uustart(ui); return; } unit = UNIT(bp->b_dev); if (data->pk_mod > 1) { /* hard error */ printf("uu%d: hard error bn%d,", unit, bp->b_blkno); printf(" pk_mod 0%o\n", data->pk_mod&0xff); bp->b_flags |= B_ERROR; uuc->tu_herrs++; } else if (data->pk_mod) /* soft error */ uuc->tu_serrs++; uutab->b_active = NULL; uutab->b_actf = bp->b_actf; bp->b_resid = uuc->tu_count; if ((bp->b_flags&B_READ) == 0) tu_vee(&uu_pcnt[unit]); iodone(bp); uustart(ui); } else { /* * Neither data nor end: data was lost * somehow, flush and restart the transfer. */ uuaddr->rcs = 0; uu_restart(ctlr, ui); uuc->tu_serrs++; } break; case TUS_IDLE: case TUS_INIT1: break; default:bad: if (c == TUF_INITF) { printf("uu%d protocol error, state=", data->pk_unit); printstate(uuc->tu_state); printf(", op=%x, cnt=%d, block=%d\n", cmd->pk_op, cmd->pk_count, cmd->pk_block); uutab->b_active = NULL; if (bp = uutab->b_actf) { bp->b_flags |= B_ERROR; uutab->b_actf = bp->b_actf; if ((bp->b_flags&B_READ) == 0) tu_vee(&uu_pcnt[unit]); iodone(bp); } uuc->tu_state = TUS_INIT1; } else { printf("uu%d receive state error, state=", data->pk_unit); printstate(uuc->tu_state); printf(", byte=%x\n", c & 0xff);#ifdef notdef uuc->tu_state = TUS_INIT1;#endif wakeup((caddr_t)uuc); } }}/* * TU58 transmitter interrupt */uuxintr(ctlr) int ctlr;{ register struct uu_softc *uuc = &uu_softc[ctlr]; register struct uudevice *uuaddr; register struct packet *data; struct uba_device *ui = uudinfo[ctlr]; int c; data = &uudata[ctlr]; uuaddr = (struct uudevice *) ui->ui_addr;top: if (uuc->tu_wcnt > 0) { /* still stuff to send, send one byte */ while ((uuaddr->tcs & UUCS_READY) == 0) ; uuaddr->tdb = *uuc->tu_wbptr++; uuc->tu_wcnt--; return; } /* * Last message byte was sent out. * Switch on tu_state of transfer. */ switch(uuc->tu_state) { /* * Two nulls have been sent, remove break, and send inits */ case TUS_INIT1: uuc->tu_flag = 0; uuaddr->tcs = UUCS_INTR; uuc->tu_state = TUS_INIT2; uuc->tu_wbptr = uuinit; uuc->tu_wcnt = sizeof (uuinit); goto top; /* * Inits have been sent, wait for a continue msg. */ case TUS_INIT2: c = uuaddr->rdb; /* prevent overrun error */ uuaddr->rcs = UUCS_INTR; uuc->tu_flag = 1; break; /* * Read cmd packet sent, get ready for data */ case TUS_SENDR: uuc->tu_state = TUS_GETH; uuc->tu_rbptr = (u_char *)data; uuc->tu_rcnt = 2; uuc->tu_flag = 1; uuaddr->tcs = 0; uuaddr->rcs = UUCS_INTR; break; /* * Write cmd packet sent, wait for continue */ case TUS_SENDW: uuc->tu_state = TUS_WAIT; uuc->tu_flag = 1; if ((uuaddr->rcs&UUCS_INTR) == 0) { printf("NO IE\n"); uuaddr->rcs = UUCS_INTR; } break; /* * Header sent, send data. */ case TUS_SENDH: uuc->tu_state = TUS_SENDD; uuc->tu_wbptr = (u_char *)uuc->tu_addr; uuc->tu_wcnt = data->pk_mcount; goto top; /* * Data sent, follow with checksum. */ case TUS_SENDD: uuc->tu_state = TUS_SENDC; uuc->tu_wbptr = (u_char *)&data->pk_chksum; uuc->tu_wcnt = 2; goto top; /* * Checksum sent, wait for continue. */ case TUS_SENDC: /* * Update buffer address and count. */ uuc->tu_addr += data->pk_mcount; uuc->tu_count -= data->pk_mcount; if (uuc->tu_count > 0) { uuc->tu_state = TUS_WAIT; uuc->tu_flag = 1; break; } /* * End of transmission, get ready for end packet. */ uuc->tu_state = TUS_GET; uuc->tu_rbptr = (u_char *)data; uuc->tu_rcnt = sizeof (*data); uuc->tu_flag = 1; uuaddr->tcs = 0; break; /* * Random interrupt */ case TUS_IDLE: /* stray interrupt? */ default: break; }}uuwatch(){ register struct uu_softc *uuc; register struct uudevice *uuaddr; struct uba_device *ui; struct buf *bp, *uutab; int s, ctlr, active = 0; for (ctlr=0; ctlr<nNUU; ctlr++) { int i; uuc = &uu_softc[ctlr]; if (uuc->tu_dopen[0] || uuc->tu_dopen[1]) active++; if (uuc->tu_flag == 0) /* * If no read is in progress * just skip */ continue; ui = uudinfo[ctlr]; uuaddr = (struct uudevice *)ui->ui_addr; uutab = &uitab[ctlr]; if (uuc->tu_flag++ < 40) continue; printf("uu%d: read stalled\n", uudata[ctlr].pk_unit);#ifdef UUDEBUG printf("%X %X %X %X %X %X %X\n", uuc->tu_rbptr, uuc->tu_rcnt, uuc->tu_wbptr, uuc->tu_wcnt, uuc->tu_state, uuc->tu_addr, uuc->tu_count);#endif s = splx(UUIPL); uuc->tu_flag = 0; i = uuaddr->rdb; /* dummy */ uuaddr->rcs = UUCS_INTR; /* in case we were flushing */ uuaddr->tcs = UUCS_INTR; uuc->tu_state = TUS_IDLE; if (!uutab->b_active) { wakeup((caddr_t)uuc); goto retry; } if (++uutab->b_errcnt <= 1) { uustart(ui); goto retry; } if (bp = uutab->b_actf) { bp->b_flags |= B_ERROR; if ((bp->b_flags&B_READ) == 0) tu_vee(&uu_pcnt[UNIT(bp->b_dev)]); iodone(bp); }retry: (void) splx(s); } if (active) timeout(uuwatch, (caddr_t)0, hz); else uuwstart = 0; return;}#if !defined(VAX750) && !defined(VAX730)/* * 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 */}#endif/* * Make sure this incredibly slow device * doesn't eat up all the buffers in the * system by putting the requesting process * (remember: this device is 'single-user') * to sleep if the write-behind queue grows * larger than NUUQ. */tu_pee(cp) char *cp;{ register int s; s = splx(UUIPL); if (++(*cp) > nNUUQ) sleep(cp, PRIBIO); splx(s);}tu_vee(cp) char *cp;{ register int s; s = splx(UUIPL); if (--(*cp) <= nNUUQ) wakeup(cp); splx(s);}#endifuuioctl(dev, cmd, data, flag) dev_t dev; caddr_t data;{ /* * add code to wind/rewind cassette here */ return (ENXIO);}uu_restart(ctlr, ui) int ctlr; struct uba_device *ui;{ uureset(ctlr); timeout(uustart, (caddr_t)ui, hz * 3);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -