IMD 1.17: 17/11/2010 7:11:02 /usr/sys/dev (I/O handlers) (system sources)  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  \&%$#"!      kjihgfecba`_^]\d|{zyxwvH  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJWOMNOPQRSTUVWXYZ[\]^_`abcdelIQ`, ldHldH l[HlOHBQ,Q,Q,Q, Q,Q, Q,Q,`lMFlMF/Q,Q,P/Q,Q,i Q,Q,<Q,Q,6Q,Q,}~Q,Q, rlIlHt lNFlNFWXYZ[Q,Q,RSTUVQ,Q,*NOPQlFQ,FGHIJKLMQ,Q,BCDEQ,Q,~:;<=>?@AQ,Q,t7Q,Q,,-.Q,Q,+Q,Q,()*Q,Q,$Q,Q,Q,Q,Q,Q,{Q,Q, ror = ENXIO; } ctclose() { cat.catlock = 0; } ctwrite(dev) { register c; extern lbolt; while ((c=cpass()) >= 0) { spl5( 0 */ 0111, /* 150 baud: 8b/ch, speed 1 */ 0, /* 200 baud */ 0121, /* 300 baud: 8b/ch, speed 2 */ 0, /* 600 baud */ 013); while (cat.oq.c_cc > CATHIWAT) sleep(&cat.oq, PCAT); while (putc(c, &cat.oq) < 0) sleep(&lbolt, PCAT); catintr();1, /* 1200 baud */ 0, /* 1800 baud */ 0, /* 2400 baud */ 0, /* 4800 baud */ 0, /* 9600 baud */ 0, /* X0 */ 0, /* X1 spl0(); } } catintr() { register int c; if (CATADDR->catcsr&DONE && (c=getc(&cat.oq))>=0) { CATADDR->catbuf = c; if  */ }; /* * Transmitter speed table */ int dctstab[] { 0, /* 0 baud */ 0, /* 50 baud */ 0, /* 75 baud */ 0, /* 110 ba(cat.oq.c_cc==0 || cat.oq.c_cc==CATLOWAT) wakeup(&cat.oq); } else { if (cat.catlock==0) CATADDR->catcsr = 0; } } ud */ 0501, /* 134.5 baud: stop 1 */ 0511, /* 150 baud */ 0, /* 200 baud */ 0521, /* 300 baud */ 0, /* 600 baud */ 0531, /* 1200 baud */ 0, /* 1800 baud */ 0, /* 2400 baud */ 0, /* 4800 baud */ 0, /* 9600 baud */ 0, /* X0 */ 0, /* X# /* */ /* * DC-11 driver */ #include "../param.h" #include "../conf.h" #include "../user.h" #include "../tty.h" #include 1 */ }; /* * Open a DC11, waiting until carrier is established. * Default initial conditions are set up on the first open. *...ecat.cddc.ccdevstart.cbdh.cadhdm.c`dhfdm.c"../proc.h" /* * Base address of DC-11's. Minor device i is at * DCADDR + 10*i. */ #define DCADDR 0174000 /* * Number of_dn.c^dp.c]hp.c\hs.c[ht.cZkl.cYlp.cXpc.c DC's for which table space is allocated. */ #define NDC11 14 /* * Control bits in device registers */ #define CDLEAD 01 #deOkl.oVqx.cUrf.cTrhstart.cSrk.cRrp.cQrx.cPrx.dec.cfine CARRIER 04 #define SPEED1 010 #define STOP1 0400 #define RQSEND 01 #define PARITY 040 #define ERROR 0100000 #define CTRANS Wqx.oNtc.cMtm.cLvs.cKvt.cJread-me040000 #define RINGIND 020000 struct tty dc11[NDC11]; struct dcregs { int dcrcsr; int dcrbuf; int dctcsr; int dctbuf; }; # /* */ /* * GP DR11C driver used for C/A/T */ #include "../param.h" #include "../user.h" #include "../tty.h" #define CATA /* * Input-side speed and control bit table. * Each DC11 has 4 speeds which correspond to the 4 non-zero entries. * The tablDDR 0167750 #define PCAT 9 #define CATHIWAT 60 #define CATLOWAT 15 struct { int catlock; struct clist oq; } cat; struct { ie index is the same as the speed-selector * number for the DH11. * Attempts to set the speed to a zero entry are ignored. */ nt catcsr; int catbuf; }; ctopen(dev) { if (cat.catlock==0) { cat.catlock++; CATADDR->catcsr =| IENABLE; } else u.u_erint dcrstab[] { 0, /* 0 baud */ 0, /* 50 baud */ 0, /* 75 baud */ 0, /* 110 baud */ 01101, /* 134.5 baud: 7b/ch, speed |CDLEAD|SPEED1; addr->dctcsr = IENABLE|SPEED1|STOP1|RQSEND; rtp->t_state = ISOPEN | WOPEN; rtp->t_flags = ODDP|EVENP|ECHO;register struct tty *tp; register r; tp = &dc11[dev.d_minor]; if (ttystty(tp, av)) return; if (r = dcrstab[tp->t_speeds.l } if (addr->dcrcsr & CARRIER) rtp->t_state =| CARR_ON; while ((rtp->t_state & CARR_ON) == 0) sleep(&rtp->t_rawq, TTIPRI); ttyopen(dev, rtp); } /* * Close a dc11 */ dcclose(dev) { register struct tty *tp; (tp = &dc11[dev.d_minor])->t_state = 0; if (tp->t_flags&HUPCL) tp->t_addr->dcrcsr =& ~CDLEAD; wflushtty(tp); } /* * Read a DC11 */ dcread(dev) { ttread(&dc11[dev.d_minor]); } /* * Write a DC11 */ dcwrite(dev) { ttwrite(&dc11[dev.d_minor]); } /* * DC11 transmitter interrupt. */ dcxint(dev) { register struct tty *tp; ttstart(tp = &dc11[dev.d_minor]); if (tp->t_outq.c_cc == 0 || tp->t_outq.c_cc == TTLOobyte&017]) tp->t_addr->dcrcsr = r; else tp->t_addr->dcrcsr =& ~CDLEAD; if (r = dctstab[tp->t_speeds.hibyte&017]) tp->t_WAT) wakeup(&tp->t_outq); } /* * DC11 receiver interrupt. */ dcrint(dev) { register struct tty *tp; register int c, csr; addr->dctcsr = r; }  tp = &dc11[dev.d_minor]; c = tp->t_addr->dcrbuf; /* * If carrier is off, and an open is not in progress, * knock down the CD lead to hang up the local dataset * and signal a hangup. */ if (((csr = tp->t_addr->dcrcsr) & CARRIER) == 0) { if (( t_state's CARR_ON bit is a pure copy of the hardware * CARRIER bit, and is only used to regularize * carrier tests in generaltp->t_state&WOPEN) == 0) { tp->t_addr->dcrcsr =& ~CDLEAD; if (tp->t_state & CARR_ON) signal(tp, SIGHUP); flushtty(t tty routines. */ dcopen(dev, flag) { register struct tty *rtp; register *addr; if (dev.d_minor >= NDC11) { u.u_error = Ep); } tp->t_state =& ~CARR_ON; return; } if (csr&ERROR || (tp->t_state&ISOPEN)==0) { if (tp->t_state&WOPEN && csr&CARRNXIO; return; } rtp = &dc11[dev.d_minor]; rtp->t_addr = addr = DCADDR + dev.d_minor*8; rtp->t_state =| WOPEN; addr->dcrcsIER) tp->t_state =| CARR_ON; wakeup(tp); return; } csr =& PARITY; if (csr&&(tp->t_flags&ODDP) || !csr&&(tp->t_flags&EVr =| IENABLE|CDLEAD; if ((rtp->t_state&ISOPEN) == 0) { rtp->t_erase = CERASE; rtp->t_kill = CKILL; addr->dcrcsr = IENABLEENP)) ttyinput(c, tp); } /* * DC11 stty/gtty. * Perform general functions and set speeds. */ dcsgtty(dev, av) int *av; {  ayout of the older DEC controllers (RF, RK, RP, TM) */ #define IENABLE 0100 #define WCOM 02 #define RCOM 04 #define GO 01 devstincorrectly say this bit causes generation of even parity. */ #define OPAR 040 #define HDUPLX 040000 #define IENABLE 030100 #deart(bp, devloc, devblk, hbcom) struct buf *bp; int *devloc; { register int *dp; register struct buf *rbp; register int com; fine PERROR 010000 #define FRERROR 020000 #define XINT 0100000 #define SSPEED 7 /* standard speed: 300 baud */ /* * Software c dp = devloc; rbp = bp; *dp = devblk; /* block address */ *--dp = rbp->b_addr; /* buffer address */ *--dp = rbp->b_wcountopy of last dhbar */ int dhsar; struct dhregs { int dhcsr; int dhnxch; int dhlpr; int dhcar; int dhbcr; int dhbar; int ; /* word count */ com = (hbcom<<8) | IENABLE | GO; if (rbp->b_flags&B_READ) com =| RCOM; else com =| WCOM; *--dp = comdhbreak; int dhsilo; }; /* * Open a DH11 line. */ dhopen(dev, flag) { register struct tty *tp; extern dhstart(); if (dev; } .d_minor >= NDH11) { u.u_error = ENXIO; return; } tp = &dh11[dev.d_minor]; tp->t_addr = dhstart; DHADDR->dhcsr =| IENABLE; tp->t_state =| WOPEN|SSTART; if ((tp->t_state&ISOPEN) == 0) { tp->t_erase = CERASE; tp->t_kill = CKILL; tp->t_speeds = SSPEED | (SSPEED<<8); tp->t_flags = ODDP|EVENP|ECHO; dhparam(tp); } dmopen(dev); ttyopen(dev, tp); } /* * Close a DH1# /* */ /* * DH-11 driver * This driver calls on the DHDM driver. * If the DH has no DM11-BB, then the latter will * be fa1 line. */ dhclose(dev) { register struct tty *tp; tp = &dh11[dev.d_minor]; dmclose(dev); tp->t_state =& (CARR_ON|SSTART);ke. To insure loading of the correct DM code, * lib2 should have dhdm.o, dh.o and dhfdm.o in that order. */ #include "../para wflushtty(tp); } /* * Read from a DH11 line. */ dhread(dev) { ttread(&dh11[dev.d_minor]); } /* * write on a DH11 line *m.h" #include "../conf.h" #include "../user.h" #include "../tty.h" #include "../proc.h" #define DHADDR 0160020 #define NDH11 16/ dhwrite(dev) { ttwrite(&dh11[dev.d_minor]); } /* * DH11 receiver interrupt. */ dhrint() { register struct tty *tp; regis /* number of lines */ #define DHNCH 8 /* max number of DMA chars */ struct tty dh11[NDH11]; /* * Place from which to do DMA oter int c; while ((c = DHADDR->dhnxch) < 0) { /* char. present */ tp = &dh11[(c>>8)&017]; if (tp >= &dh11[NDH11]) contin output */ char dh_clist[NDH11][DHNCH]; /* * Used to communicate the number of lines to the DM */ int ndh11 NDH11; /* * Hnue; if((tp->t_state&ISOPEN)==0 || (c&PERROR)) { wakeup(tp); continue; } if (c&FRERROR) /* break */ if (tp->t_fl#include "../param.h" #include "../buf.h" /* * Device start routine for disks * and other devices that have the register * lardware control bits */ #define BITS6 01 #define BITS7 02 #define BITS8 03 #define TWOSB 04 #define PENABLE 020 /* DEC manuals  Y; dhstart(tp); } ttybit =<< 1; } } /* * Start (restart) transmission on the given DH11 line. */ dhstart(atp) struct  start transmission; * otherwise, check for possible delay. */ if (nch) { DHADDR->dhcsr.lobyte = dev | IENABLE; DHADDR-tty *atp; { extern ttrstrt(); register c, nch; register struct tty *tp; int dev; int sps; char *cp; sps = PS->integ; sp>dhcar = cp+nch; DHADDR->dhbcr = nch; c = 1<dhbar =| c; dhsar =| c; tp->t_state =| BUSY; } else if (c =ags&RAW) c = 0; /* null (for getty) */ else c = 0177; /* DEL (intr) */ ttyinput(c, tp); } } /* * stty/gtty for l5(); tp = atp; /* * If it's currently active, or delaying, * no need to do anything. */ if (tp->t_state&(TIMEOUT|BUSY)DH11 */ dhsgtty(dev, av) int *av; { register struct tty *tp; register r; tp = &dh11[dev.d_minor]; if (ttystty(tp, av)) r !"#%&'eturn; dhparam(tp); } /* * Set parameters from open or stty into the DH hardware * registers. */ dhparam(atp) struct tty *atp; { register struct tty *tp; register int lpr; register int dev; tp = atp; dev = tp - &dh11[0]; spl5(); DHADDR->dhcsr.lobyte = dev | IENABLE; /* * Hang up line? */ if (tp->t_speeds.lobyte==0) { tp->t_flags =| HUPCL; dmclose(dev); return; } lpr = (tp->t_speeds.hibyte<<10) | (tp->t_speeds.lobyte<<6); if (tp->t_speeds.lobyte == 4) /* 134.5 baud */ lpr =| BI) goto out; /* * t_char is a delay indicator which may have been * left over from the last start. * Arrange for the delTS6|PENABLE|HDUPLX; else if (tp->t_flags&EVENP) if (tp->t_flags&ODDP) lpr =| BITS8; else lpr =| BITS7|PENABLE; elseay. */ if (c = tp->t_char) { tp->t_char = 0; timeout(ttrstrt, tp, (c&0177)+6); tp->t_state =| TIMEOUT; goto out; }  lpr =| BITS7|OPAR|PENABLE; if (tp->t_speeds.lobyte == 3) /* 110 baud */ lpr =| TWOSB; DHADDR->dhlpr = lpr; spl0(); } /dev = tp - &dh11[0]; cp = dh_clist[dev]; nch = 0; /* * Copy DHNCH characters, or up to a delay indicator, * to the DMA ar* * DH11 transmitter interrupt. * Restart each line which used to be active but has * terminated transmission since the last ea. */ while (nch > -DHNCH && (c = getc(&tp->t_outq))>=0) { if (c >= 0200) { tp->t_char = c; break; } *cp++ = c; interrupt. */ dhxint() { register struct tty *tp; register ttybit, bar; bar = dhsar & ~DHADDR->dhbar; DHADDR->dhcsr =& ~XI nch--; } /* * If the writer was sleeping on output overflow, * wake him when low tide is reached. */ if (tp->t_outq.cNT; ttybit = 1; for (tp = dh11; bar; tp++) { if(bar&ttybit) { dhsar =& ~ttybit; bar =& ~ttybit; tp->t_state =& ~BUS_cc<=TTLOWAT && tp->t_state&ASLEEP) { tp->t_state =& ~ASLEEP; wakeup(&tp->t_outq); } /* * If any characters were set up, tp; tp = &dh11[dev.d_minor]; DMADDR->dmcsr = dev.d_minor; DMADDR->dmlstat = TURNON; if (DMADDR->dmlstat&CARRIER) tp->t_st char dn_stat; char dn_reg; } dn11[3]; } #define DNADDR 0175200 #define PWI 00200 #define ACR 00100 #define DLO 0020 #defiate =| CARR_ON; DMADDR->dmcsr = IENABLE|SCENABL; spl5(); while ((tp->t_state&CARR_ON)==0) sleep(&tp->t_rawq, TTIPRI); spl0ne DONE 0200 #define IENABLE 0100 #define DSS 040 #define PND 020 #define MENABLE 04 #define DPR 02 #define CRQ 01 #define DNPR(); } /* * If a DH line has the HUPCL mode, * turn off carrier when it is closed. */ dmclose(dev) { register struct tty *tpI 5 dnopen(dev, flag) { register struct dn *dp; register int rdev; rdev = dev.d_minor; dp = &DNADDR->dn11[rdev]; if (dp->; tp = &dh11[dev.d_minor]; if (tp->t_flags&HUPCL) { DMADDR->dmcsr = dev.d_minor; DMADDR->dmlstat = TURNOFF; DMADDR->dmcdn_reg&(PWI|DLO)) u.u_error = ENXIO; else { DNADDR->dn11[0].dn_stat =| MENABLE; dp->dn_stat = IENABLE|MENABLE|CRQ; } } sr = IENABLE|SCENABL; } } /* * DM11 interrupt. * Mainly, deal with carrier transitions. */ dmint() { register struct tty *dnclose(dev) { DNADDR->dn11[dev.d_minor].dn_stat =& MENABLE; } dnwrite(dev) { register struct dn *dp; register c; extern lb tp->t_char) { tp->t_char = 0; timeout(ttrstrt, tp, (c&0177)+6); tp->t_state =| TIMEOUT; } out: PS->integ = sps; } tp; if (DMADDR->dmcsr&DONE) { tp = &dh11[DMADDR->dmcsr&017]; if (tp < &dh11[ndh11]) { wakeup(tp); if ((DMADDR->dmlstat&CARRIER)==0) { if ((tp->t_state&WOPEN)==0) { signal(tp, SIGHUP); DMADDR->dmlstat = 0; flushtty(tp); }  tp->t_state =& ~CARR_ON; } else tp->t_state =| CARR_ON; } DMADDR->dmcsr = IENABLE|SCENABL; } } # /* */ /* * DM-BB fake driver */ #include "../tty.h" #include "../conf.h" struct tty dh11[]; dmopen(dev) { register stru# /* */ /* * DM-BB driver */ #include "../param.h" #include "../tty.h" #include "../conf.h" #define DMADDR 0170500 struct ct tty *tp; tp = &dh11[dev.d_minor]; tp->t_state =| CARR_ON; } dmclose(dev) { } tty dh11[]; int ndh11; /* Set by dh.c to number of lines */ #define DONE 0200 #define SCENABL 040 #define CLSCAN 01000 #define TURNON 07 /* RQ send, CD lead, line enable */ #define TURNOFF 1 /* line enable only */ #define CARRIER 0100 struct dmregs { int dmcsr; int dmlstat; }; /* * Turn on the line associated with the (DH) device dev. */ dmopen(dev) { register struct tty *# /* */ /* * DN-11 ACU interface */ #include "../param.h" #include "../conf.h" #include "../user.h" struct dn { struct {  , HZ); } DPADDR->dpsyn0 = SYN; DPADDR->dprcsr = HDUPLX|IENABLE; DPADDR->dptcsr = IENABLE|SIENABL|DTRDY; } dpclose() { DPAD# /* */ /* * DP-11 Synchronous interface driver * This driver is rather insensitive to the remote * device it talks to, whiDR->dprcsr = 0; DPADDR->dptcsr = 0; dp11.dp_timer = 0; dp11.dp_proc = 0; if (dp11.dp_buf != 0) { brelse(dp11.dp_buf); dpch is to say most of the protocol * must be supplied by the calling program. * Exceptions: parity is even; 7 data bits per cha11.dp_buf = 0; } } /* * Read waits until: * there is loss of "data set ready", or * a timeout occurs, or * a full recorracter; * max. of 512 characters per record; 10 second timeout * on waiting to receive; half-duplex transmission. */ #includd has been received. * The former two result in an error. */ dpread() { register char *bp, **epp; bp = dp11.dp_buf->b_addr;e "../param.h" #include "../conf.h" #include "../user.h" #include "../buf.h" /* control info */ struct { char *dp_buf; char * epp = &dp11.dp_bufp; for(;;) { if(dpwait()) return; if (*epp > bp) break; spl6(); if (dp11.dp_timer <= 1) { dp_bufp; int dp_nxmit; char dp_state; char dp_timer; int dp_proc; } dp11; /* device registers */ struct { int dprcsr; chaspl0(); return; } sleep(&dp11, DPPRI); spl0(); } iomove(dp11.dp_buf, 0, min(u.u_count, *epp-bp), B_READ); } /* * wrr dprbuf; char dpsyn0; int dptcsr; char dptbuf; char dpsyn1; }; /* bits */ #define ODDPAR 010000 #define IENABLE 0100 #defiite checks to make sure that the data set is not reading, * and that it is ready. Then the record is copied * and transmissione HDUPLX 02 #define CTRANS 0100000 #define RORUN 040000 #define RING 020000 #define DSRDY 010000 #define CARRIER 04000 #definen started. */ dpwrite() { register char *bp; if (u.u_count==0 || dpwait()) return; dp11.dp_state = WRITE; bp = dp11.dp_bolt; dp = &DNADDR->dn11[dev.d_minor]; for(;;) { while ((dp->dn_stat&DONE)==0) sleep(DNADDR, DNPRI); dp->dn_stat =& ~DO DONE 0200 #define IENABLE 0100 #define SIENABL 040 #define WRITE 1 #define READ 0 #define DTRDY 01 #define RCVACT 04000 #defNE; contin: if (dp->dn_reg&(PWI|ACR)) { u.u_error = EIO; return; } if (dp->dn_stat&DSS) return; c = 0; iine DPADDR 0174770 #define DPPRI 5 #define SYN 026 /* (receive) sync character */ /* * The open fails unless the device is nof (u.u_count==0 || (dp->dn_stat&PND)==0 || (c=cpass())<0) continue; if (c=='-') { sleep(&lbolt, DNPRI); sleep(&lbolt,t open or * the opening process is the one that has it open already. */ dpopen(dev, flag) { int dptimeout(); if (dp11.dp_pr DNPRI); goto contin; } dp->dn_reg = c-'0'; dp->dn_stat =| DPR; } } dnint(dev) { wakeup(DNADDR); } oc!=0 && dp11.dp_proc!=u.u_procp) { u.u_error = ENXIO; return; } dp11.dp_proc = u.u_procp; dp11.dp_state = READ; if (dp11.dp_buf==0) { dp11.dp_buf = getblk(NODEV); dp11.dp_bufp = dp11.dp_buf->b_addr; dp11.dp_timer = HZ; timeout(dptimeout, 0   state with no carrier, * which means a record has just been received. */ dpwait() { for(;;) { if ((DPADDR->dptcsr&DSRDY)==0 || dp11.dp_buf==0) { u.u_error = EIO; return(1); } spl6(); if (dp11.dp_state==READ && (DPADDR->dptcsr&CARRIER)==0)er interrupt: * Knock down hardware bits. * If carrier has dropped, the record is done, so turn the line around; * otherwise  { spl0(); return(0); } sleep(&dp11, DPPRI); spl0(); } } /* * Start off the next character to be transmitted; * start another character. */ dpxint() { register int dpstat; dpstat = DPADDR->dptcsr; DPADDR->dptcsr =& ~(CTRANS|RORUN|RING|when the record is done, drop back into read state. */ dpstart() { register int c; extern char partab[]; dp11.dp_timer = 10DONE); if (dpstat & (CTRANS|RORUN)) dpturnaround(); else if (dpstat&DONE && dp11.dp_state==WRITE) dpstart(); } /* * Chan; if (--dp11.dp_nxmit >= 0) { c = (*dp11.dp_bufp++) & 0177; DPADDR->dptbuf = c | ~partab[c]&0200; } else { dp11.dp_bufp ge the state from writing to reading at the end of a record. */ dpturnaround() { DPADDR->dprcsr =& ~RCVACT; if (dp11.dp_state= dp11.dp_buf->b_addr; dp11.dp_state = READ; } } /* * Count down the DP timer (once per second) * If it runs out, it presu==WRITE) { dp11.dp_timer = 10; dp11.dp_state = READ; dp11.dp_bufp = dp11.dp_buf->b_addr; } wakeup(&dp11); } mably means the other station * won't speak. */ dptimeout() { if (dp11.dp_timer==0) return; if (--dp11.dp_timer==0) { dpturnaround(); dp11.dp_timer = 1; } timeout(dptimeout, 0, HZ); } /* * Receiver interrupt: if reading, stash character * unless there is an overrun. */ dprint() { register int c; c = DPADDR->dprbuf & 0177; if (dp11.dp_state==READ) { if ((DPADDR->dprcsr&ODDPAR) == 0) c =| 0200; if (dp11.dp_bufp < dp11.dp_buf->b_addr+512) *dp11.dp_bufp++ = c; } } /* * Transmitt# /* */ /* * RP04 disk driver * * This driver has been tested on a working RP04 for a few hours. * It does not attempt ECC/012345689 error correction and is probably * deficient in general in the case of errors and when packs * are dismounted. */ #include uf->b_addr; dp11.dp_bufp = bp; if (u.u_count>512) u.u_count = 512; dp11.dp_nxmit = u.u_count; iomove(dp11.dp_buf, 0, u.u_count, B_WRITE); dpstart(); } /* * If "data set ready" is down return an error; otherwise * wait until the dataset is in read  40000 /* hper1 - Drive Unsafe */ #define DTE 010000 /* hper1 - Drive Timing Error */ #define OPI 020000 /* hper1 - Operation Iregister int ctr; if (hptab.d_active == 0) return; bp = hptab.d_actf; hptab.d_active = 0; if (HPADDR->hpcs1 & ERR) { /* "../param.h" #include "../buf.h" #include "../conf.h" #include "../user.h" struct { int hpcs1; /* Control and Status register ncomplete */ /* Error Correction Code errors */ #define DCK 0100000 /* hper1 - Data Check error */ #define ECH 0100 /* hper1 */ int hpwc; /* Word count register */ int hpba; /* UNIBUS address register */ int hpda; /* Desired address register */ in1 - ECC hard error */ #define CLR 040 /* hpcs2 - Controller Clear */ #define FMT22 010000 /* hpof - 16 bit /word format */ /* t hpcs2; /* Control and Status register 2*/ int hpds; /* Drive Status */ int hper1; /* Error register 1 */ int hpas; /* Atten * Use av_back to save track+sector, * b_resid for cylinder. */ #define trksec av_back #define cylin b_resid hpopen() { iftion Summary */ int hpla; /* Look ahead */ int hpdb; /* Data buffer */ int hpmr; /* Maintenance register */ int hpdt; /* Dri(!hp_openf){ hp_openf++; HPADDR->hpcs2 = CLR; HPADDR->hpcs1 = RCLR|GO; HPADDR->hpcs1 = PRESET|GO; HPADDR->hpof = FMT22ve type */ int hpsn; /* Serial number */ int hpof; /* Offset register */ int hpca; /* Desired Cylinder address register*/ in; } } hpstrategy(abp) struct buf *abp; { register struct buf *bp; register char *p1, *p2; bp = abp; p1 = &hp_sizes[bp->b_t hpcc; /* Current Cylinder */ int hper2; /* Error register 2 */ int hper3; /* Error register 3 */ int hppos; /* Burst error dev.d_minor&07]; if (bp->b_dev.d_minor >= (NHP<<3) || bp->b_blkno >= p1->nblocks) { bp->b_flags =| B_ERROR; iodone(bp)bit position */ int hppat; /* Burst error bit pattern */ int hpbae; /* 11/70 bus extension */ }; #define HPADDR 0176700 #defi; return; } bp->av_forw = 0; bp->cylin = p1->cyloff; p1 = bp->b_blkno; p2 = lrem(p1, 22); p1 = ldiv(p1, 22); bp->trksecne NHP 8 struct { char *nblocks; int cyloff; } hp_sizes[] { 9614, 0, /* cyl 0 thru 23 */ /* cyl 24 thru 43 available */ = (p1%19)<<8 | p2; bp->cylin =+ p1/19; spl5(); if ((p1 = hptab.d_actf)==0) hptab.d_actf = bp; else { for (; p2 = p1->av -1, 44, /* cyl 44 thru 200 */ -1, 201, /* cyl 201 thru 357 */ 20900, 358, /* cyl 358 thru 407 */ /* cyl 408 thru 410 _forw; p1 = p2) { if (p1->cylin <= bp->cylin && bp->cylin < p2->cylin || p1->cylin >= bp->cylin && bp->cylin > blank */ 40600, 0, 40600, 100, 40600, 200, 40600, 300, }; struct devtab hptab; char hp_openf; /* Drive Commands */ #dep2->cylin) break; } bp->av_forw = p2; p1->av_forw = bp; } if (hptab.d_active==0) hpstart(); spl0(); } hpstart()fine GO 01 #define PRESET 020 #define RECAL 06 #define RCLR 010 #define OFFSET 014 #define READY 0200 /* hpds - drive ready */  { register struct buf *bp; if ((bp = hptab.d_actf) == 0) return; hptab.d_active++; HPADDR->hpcs2 = bp->b_dev.d_minor >> #define PIP 020000 /* hpds - Positioning Operation in Progress */ #define ERR 040000 /* hpcs1 - composite error */ #define DU 03; HPADDR->hpca = bp->cylin; rhstart(bp, &HPADDR->hpda, bp->trksec, &HPADDR->hpbae); } hpintr() { register struct buf *bp;  R 0172040 #define ERR 040000 /* hscs1 - composite error */ #define GO 01 #define RCLR 010 #define DRY 0200 /* hsds - Drive Rea int htdt; int htsn; int httc; int htbae; /* 11/70 bus extension */ }; struct devtab httab; #define NUNIT 8 char h_openf[NUdy */ hsstrategy(abp) struct buf *abp; { register struct buf *bp; register mblks; bp = abp; mblks = 1024; /* RJS03 */ if(NIT]; char *h_blkno[NUNIT]; char *h_nxrec[NUNIT]; #define HTADDR 0172440 #define GO 01 #define NOP 0 #define WEOF 026 #define bp->b_dev.d_minor >= 8) mblks = 2048; /* RJS04 */ if(bp->b_blkno >= mblks) { bp->b_flags =| B_ERROR; iodone(bp); returnSFORW 030 #define SREV 032 #define ERASE 024 #define REW 06 #define CLR 010 #define P800 01300 /* 800 + pdp11 mode */ #define P; } bp->av_forw = 0; spl5(); if (hstab.d_actf==0) hstab.d_actf = bp; else hstab.d_actl->av_forw = bp; hstab.d_actl = bp1600 02300 /* 1600 + pdp11 mode */ #define IENABLE 0100 #define CRDY 0200 #define EOF 04 #define DRY 0200 #define MOL 010000 #derror bit */ if(HPADDR->hper1 & (DU|DTE|OPI)) { HPADDR->hpcs2 = CLR; HPADDR->hpcs1 = RECAL|GO; ctr = 0; while ((HP; if (hstab.d_active==0) hsstart(); spl0(); } hsstart() { register struct buf *bp; register addr; if ((bp = hstab.d_actADDR->hpds&PIP) && --ctr); } HPADDR->hpcs1 = RCLR|GO; if (++hptab.d_errcnt <= 10) { hpstart(); return; } bp->b_ff) == 0) return; hstab.d_active++; addr = bp->b_blkno; if(bp->b_dev.d_minor < 8) addr =<< 1; /* RJS03 */ HSADDR->hscs2 =lags =| B_ERROR; } hptab.d_errcnt = 0; hptab.d_actf = bp->av_forw; bp->b_resid = HPADDR->hpwc; iodone(bp); hpstart(); }  bp->b_dev.d_minor & 07; rhstart(bp, &HSADDR->hsda, addr<<1, &HSADDR->hsbae); } hsintr() { register struct buf *bp; if (hstab.d_active == 0) return; bp = hstab.d_actf; hstab.d_active = 0; if(HSADDR->hscs1 & ERR){ /* error bit */ HSADDR->hscs1 =# /* */ /* * RS03/04 disk driver */ #include "../param.h" #include "../buf.h" #include "../conf.h" #include "../user.h" s RCLR|GO; if (++hstab.d_errcnt <= 10) { hsstart(); return; } bp->b_flags =| B_ERROR; } hstab.d_errcnt = 0; hstab.truct { int hscs1; /* Control and Status register 1 */ int hswc; /* Word count register */ int hsba; /* UNIBUS address registd_actf = bp->av_forw; iodone(bp); hsstart(); } hsread(dev) { physio(hsstrategy, &rhsbuf, dev, B_READ); } hswrite(dev) { er */ int hsda; /* Desired address register */ int hscs2; /* Control and Status register 2 */ int hsds; /* Drive Status */ iphysio(hsstrategy, &rhsbuf, dev, B_WRITE); } nt hser; /* Error register */ int hsas; /* not used */ int hsla; /* not used */ int hsdb; /* not used */ int hsmr; /* not us# /* */ /* * TJU16 tape driver */ #include "../param.h" #include "../buf.h" #include "../conf.h" #include "../user.h" strued */ int hsdt; /* not used */ int hsbae; /* 11/70 bus extension */ }; struct devtab hstab; struct buf rhsbuf; #define HSADDct { int htcs1; int htwc; int htba; int htfc; int htcs2; int htds; int hter; int htas; int htck; int htdb; int htmr;  00 | (unit&07); while((HTADDR->htds&(MOL|PIP)) != MOL) sleep(&lbolt, 1); HTADDR->htcs1 = com | GO; } htstrategy(abp) struct&077; if (HTADDR->htcs1 & ERR) { if(HTADDR->htds&EOF) { if(h_openf[unit]) h_openf[unit] = -1; } HTADDR->htcs1 = ER buf *abp; { register struct buf *bp; register char **p; bp = abp; p = &h_nxrec[bp->b_dev.d_minor&077]; if (*p <= bp->b_blR|CLR|GO; if ((HTADDR->htds&DRY)!=0 && httab.d_active==SIO) { if (++httab.d_errcnt < 10) { h_blkno[unit]++; httab.dkno) { if (*p < bp->b_blkno) { bp->b_flags =| B_ERROR; iodone(bp); return; } if (bp->b_flags&B_READ) { clrbuf(_active = 0; htstart(); return; } } bp->b_flags =| B_ERROR; httab.d_active = SIO; } if (httab.d_active == SIObp); iodone(bp); return; } } if ((bp->b_flags&B_READ)==0) *p = bp->b_blkno + 1; bp->av_forw = 0; spl5(); if (htta) { httab.d_errcnt = 0; h_blkno[unit]++; httab.d_actf = bp->av_forw; httab.d_active = 0; iodone(bp); bp->b_resid = Hb.d_actf==0) httab.d_actf = bp; else httab.d_actl->av_forw = bp; httab.d_actl = bp; if (httab.d_active==0) htstart(); TADDR->htfc; } else h_blkno[unit] = bp->b_blkno; htstart(); } spl0(); } htstart() { register struct buf *bp; register int unit; register char *blkno; loop: if ((bp = httab.d_actf) == 0) return; unit = bp->b_dev.d_minor; HTADDR->htcs2 = (unit>>3)&07; if(unit >= 64) HTADDR->httc = P800 | (unit&07); elsefine PIP 020000 #define ERR 040000 #define SSEEK 1 #define SIO 2 htopen(dev, flag) { register unit; unit = dev.d_minor&077e HTADDR->httc = P1600 | (unit&07); unit =& 077; blkno = h_blkno[unit]; if (h_openf[unit] < 0 || (HTADDR->htcs1 & CRDY)==0); if (unit >= NUNIT || h_openf[unit]) u.u_error = ENXIO; else { h_openf[unit]++; h_blkno[unit] = 0; h_nxrec[unit] = 65 { bp->b_flags =| B_ERROR; httab.d_actf = bp->av_forw; iodone(bp); goto loop; } if (blkno != bp->b_blkno) { httab.d_535; hcommand(dev, NOP); } } htclose(dev, flag) { register int unit; unit = dev.d_minor&077; h_openf[unit] = 0; if (flaactive = SSEEK; if (blkno < bp->b_blkno) { HTADDR->htfc = blkno - bp->b_blkno; HTADDR->htcs1 = SFORW|IENABLE|GO; } elsg) { hcommand(dev, WEOF); hcommand(dev, WEOF); } hcommand(dev, REW); } hcommand(dev, com) { register unit; extern lbolte { if (bp->b_blkno == 0) HTADDR->htcs1 = REW|IENABLE|GO; else { HTADDR->htfc = bp->b_blkno - blkno; HTADDR->h; unit = dev.d_minor; while (httab.d_active || (HTADDR->htcs1 & CRDY)==0) sleep(&lbolt, 1); HTADDR->htcs2 = (unit>>3)&07; tcs1 = SREV|IENABLE|GO; } } return; } httab.d_active = SIO; rhstart(bp, &HTADDR->htfc, bp->b_wcount<<1, &HTADDR->htbae while((HTADDR->htds&DRY) == 0) sleep(&lbolt, 1); if(unit >= 64) HTADDR->httc = P800 | (unit&07); else HTADDR->httc = P16); } htintr() { register struct buf *bp; register int unit; if ((bp = httab.d_actf)==0) return; unit = bp->b_dev.d_minor   int klrbuf; int kltcsr; int kltbuf; } klopen(dev, flag) { register char *addr; register struct tty *tp; if(dev.d_minor ># /* */ /* * LP-11 Line printer driver */ #include "../param.h" #include "../conf.h" #include "../user.h" #define LPADDR 0= NKL11+NDL11) { u.u_error = ENXIO; return; } tp = &kl11[dev.d_minor]; /* * set up minor 0 to address KLADDR * set up177514 #define IENABLE 0100 #define DONE 0200 #define LPPRI 10 #define LPLWAT 50 #define LPHWAT 100 #define EJLINE 60 #define  minor 1 thru NKL11-1 to address from KLBASE * set up minor NKL11 on to address from DLBASE */ addr = KLADDR + 8*dev.d_minoMAXCOL 80 struct { int lpsr; int lpbuf; }; struct { int cc; int cf; int cl; int flag; int mcc; int ccc; int mlc; } lr; if(dev.d_minor) addr =+ KLBASE-KLADDR-8; if(dev.d_minor >= NKL11) addr =+ DLBASE-KLBASE-8*NKL11+8; tp->t_addr = addr; p11; #define CAP 01 /* Set to 0 for 96-char printer, else to 01 */ #define EJECT 02 #define OPEN 04 #define IND 010 /* Set to if ((tp->t_state&ISOPEN) == 0) { tp->t_state = ISOPEN|CARR_ON; tp->t_flags = XTABS|LCASE|ECHO|CRMOD; tp->t_erase = CERASE 0 for no indent, else to 010 */ #define FORM 014 lpopen(dev, flg) { if(lp11.flag & OPEN || LPADDR->lpsr < 0) { u.u_error ; tp->t_kill = CKILL; } addr->klrcsr =| IENABLE|DSRDY|RDRENB; addr->kltcsr =| IENABLE; ttyopen(dev, tp); } klclose(dev) {= EIO; return; } lp11.flag =| (IND|EJECT|OPEN|CAP); LPADDR->lpsr =| IENABLE; lpcanon(FORM); } lpclose(dev, flg) { lpcano register struct tty *tp; tp = &kl11[dev.d_minor]; wflushtty(tp); tp->t_state = 0; } klread(dev) { ttread(&kl11[dev.d_minn(FORM); lp11.flag = 0; } lpwrite() { register int c; while ((c=cpass())>=0) lpcanon(c); } lpcanon(c) { register c1, c2or]); } klwrite(dev) { ttwrite(&kl11[dev.d_minor]); } klxint(dev) { register struct tty *tp; tp = &kl11[dev.d_minor]; tts; c1 = c; if(lp11.flag&CAP) { if(c1>='a' && c1<='z') c1 =+ 'A'-'a'; else switch(c1) { case '{': c2 = '('; gottart(tp); if (tp->t_outq.c_cc == 0 || tp->t_outq.c_cc == TTLOWAT) wakeup(&tp->t_outq); } klrint(dev) { register int c, *addo esc; case '}': c2 = ')'; goto esc; case '`': c2 = '\''; goto esc; case '|': c2 = '!'; goto esc; r; register struct tty *tp; tp = &kl11[dev.d_minor]; addr = tp->t_addr; c = addr->klrbuf; addr->klrcsr =| RDRENB; if ((c&case '~': c2 = '^'; esc: lpcanon(c2); lp11.ccc--; c1 = '-'; } } switch(c1) { case '\t': lp11.ccc = (lp11# /* */ /* * KL/DL-11 driver */ #include "../param.h" #include "../conf.h" #include "../user.h" #include "../tty.h" /* ba0177)==0) addr->kltbuf = c; /* hardware botch */ ttyinput(c, tp); } klsgtty(dev, v) int *v; { register struct tty *tp; tpse address */ #define KLADDR 0177560 /* console */ #define KLBASE 0176500 /* kl and dl11-a */ #define DLBASE 0175610 /* dl-e */  = &kl11[dev.d_minor]; ttystty(tp, v); } #define NKL11 1 #define NDL11 0 #define DSRDY 02 #define RDRENB 01 struct tty kl11[NKL11+NDL11]; struct klregs { int klrcsr;  .ccc+8) & ~7; return; case FORM: case '\n': if((lp11.flag&EJECT) == 0 || lp11.mcc!=0 || lp11.mlc!=0) { lp11.mcc = 100 #define PCIHWAT 250 struct { int pcrcsr; int pcrbuf; int pcpcsr; int pcpbuf; }; struct clist { int cc; int cf; int 0; lp11.mlc++; if(lp11.mlc >= EJLINE && lp11.flag&EJECT) c1 = FORM; lpoutput(c1); if(c1 == FORM) lp11.mlc = cl; }; struct pc11 { int pcstate; struct clist pcin; struct clist pcout; } pc11; pcopen(dev, flag) { extern lbolt; if ( 0; } case '\r': lp11.ccc = 0; if(lp11.flag&IND) lp11.ccc = 8; return; case 010: if(lp11.ccc > 0) lp11.ccc--flag==0) { if (pc11.pcstate!=CLOSED) { u.u_error = ENXIO; return; } pc11.pcstate = WAITING; while(pc11.pcstate==WA; return; case ' ': lp11.ccc++; return; default: if(lp11.ccc < lp11.mcc) { lpoutput('\r'); lp11.mcc = 0; } ITING) { PCADDR->pcrcsr = IENABLE|RDRENB; sleep(&lbolt, PCIPRI); } } else { PCADDR->pcpcsr =| IENABLE; pcleader();  if(lp11.ccc < MAXCOL) { while(lp11.ccc > lp11.mcc) { lpoutput(' '); lp11.mcc++; } lpoutput(c1); lp11.mcc++; } } pcclose(dev, flag) { if (flag==0) { spl4(); while (getc(&pc11.pcin) >= 0); PCADDR->pcrcsr = 0; pc11.pcstate = CLO } lp11.ccc++; } } lpstart() { register int c; while (LPADDR->lpsr&DONE && (c = getc(&lp11)) >= 0) LPADDR->lpbuf = c;SED; spl0(); } else pcleader(); } pcread() { register int c; spl4(); do { while ((c = getc(&pc11.pcin)) < 0) { if } lpint() { register int c; lpstart(); if (lp11.cc == LPLWAT || lp11.cc == 0) wakeup(&lp11); } lpoutput(c) { if (lp11. (pc11.pcstate==EOF) goto out; if ((PCADDR->pcrcsr&(ERROR|BUSY|DONE))==0) PCADDR->pcrcsr =| IENABLE|RDRENB; sleep(cc >= LPHWAT) sleep(&lp11, LPPRI); putc(c, &lp11); spl4(); lpstart(); spl0(); } &pc11.pcin, PCIPRI); } } while (passc(c)>=0); out: spl0(); } pcwrite() { register int c; while ((c=cpass())>=0) pcoutput(c); } pcstart() { register int c; if (PCADDR->pcpcsr&DONE && (c = getc(&pc11.pcout)) >= 0) PCADDR->pcpbuf = c; } pcrint() { if (pc11.pcstate==WAITING) { if (PCADDR->pcrcsr&ERROR) return; pc11.pcstate = READING; } if (pc11.pcstate==READI# /* */ /* * PC-11 Paper tape reader/punch driver */ #include "../param.h" #include "../conf.h" #include "../user.h" #defiNG) { if (PCADDR->pcrcsr&ERROR) pc11.pcstate = EOF; else { putc(PCADDR->pcrbuf, &pc11.pcin); if (pc11.pcin.cc < PCIne PCADDR 0177550 #define CLOSED 0 #define WAITING 1 #define READING 2 #define EOF 3 #define RDRENB 01 #define IENABLE 0100 #dHWAT) PCADDR->pcrcsr =| IENABLE|RDRENB; } wakeup(&pc11.pcin); } } pcpint() { pcstart(); if (pc11.pcout.cc <= PCOLWAefine DONE 0200 #define BUSY 04000 #define ERROR 0100000 #define PCIPRI 30 #define PCOPRI 40 #define PCOLWAT 50 #define PCOHWATT) wakeup(&pc11.pcout); } pcoutput(c) { if (PCADDR->pcpcsr&ERROR) { u.u_error = EIO; return; } if (pc11.pcout.cc >= PC CLOCK 02 /* real time clock; intr. after 2 ms. */ #define STEPIN 04 /* step toward center of floppy */ #define STEPOUT 06 art(); spl0(); } /* * qxstart: * initiate I/O request on 512-byte block */ qxstart() { register struct buf *bp; regi/* step away from center of floppy */ #define READID 010 #define QXREAD 012 #define QXWRITE 014 #define WRDEL 016 /* * erster struct qxinfo *qp; if((bp = qxtab.d_actf)==0) return; /* * start transfer of next block req. in queue */ qp = &qror conditions */ #define ERROR 0100000 #define NOSYNC 040000 #define LATE 020000 #define CRCERR 010000 #define WRPROT 04x[bp->b_dev.d_minor&QXMASK]; /* * set this flag to indicate some activity */ qxtab.d_active++; qp->q_count = (-bp->b_wcOHWAT) sleep(&pc11.pcout, PCOPRI); putc(c, &pc11.pcout); spl4(); pcstart(); spl0(); } pcleader() { register int i; i =000 #define DELDATA 02000 /* non-fatal */ #define ERRORS 076000 /* (NOSYNC|LATE|CRCERR|WRPROT|DELDATA) */ /* * status  100; do pcoutput(0); while (--i); } */ #define DONE 0200 #define TRACK0 01000 #define HDDOWN 020 #define HDUP 0 struct { int qxcs; int qxdb; }; struct {  char track; char sector; }; struct qxinfo { int q_id; int q_reqid; int q_count; /* (positive) word count */ int q_sector; char *q_addr; /* starting (byte) buffer address */ int q_timeleft; int q_stepdir; /* step direction: STEPIN, STEPOUT */ # /* * QX floppy disk driver * Marc Smith, SICL, Sept. 1979 */ #include "../param.h" #include "../buf.h" #include "../conf.}; struct qxinfo qx[NQX]; struct devtab qxtab; int qxunit; /* current unit, ready to be stuffed into reg. */ int qxhd; h" #include "../user.h" /* * "physical" constants */ #define NQX 4 #define QXMASK 03 #define SECSZ 64 /* 64 wrds/sctr * /* current head state */ #define WAIT() while(!(QXADDR->qxcs&DONE)) #define ERROR() { qxintr(); return; } /* * qxstrategy:/ #define SECPERBLK 4 #define SECPERTRK 26 #define NUMTRK 76 #define NUMSEC (76*26) /* 76 tracks by 26 sectors/trk */ #define * queue up I/O request */ qxstrategy(abp) struct buf *abp; { register struct buf *bp; bp = abp; /* * check unit no., NUMBLK 494 #define SECINCR 3 /* distance to next sector of block */ #define INTRLV 9 /* interleave factor */ #define SKEWP blk no., and word count */ if(bp->b_dev.d_minor >= NQX || bp->b_blkno + (-bp->b_wcount>>8) > NUMBLK || -bp->b_wcount&ERTRK 6 /* sector skew across tracks */ #define MAXRETRY 10 #define QXADDR 0177000 /* * controller commands (write only) 037) { bp->b_flags =| B_ERROR; iodone(bp); return; } /* * put request in I/O queue */ bp->av_forw = 0; spl5();  */ #define IENABLE 0100 #define LOWCUR 040 /* low current: reset for trks 1-43 */ #define NOOP 0 #define GO 01 #define RT if(qxtab.d_actf==0) qxtab.d_actf = bp; else qxtab.d_actl->av_forw = bp; qxtab.d_actl = bp; if(qxtab.d_active==0) qxst */ nw = min(qp->q_count, SECSZ); cp = qp->q_addr; i = QXADDR->qxcs; /* reset data buffer by simply refering to it */ do y remaining accum. time */ QXADDR->qxcs = qxunit | HDDOWN | READID | GO; WAIT(); if(QXADDR->qxcs<0) ERROR(); qp->q_id = { QXADDR->qxdb = *cp++; } while(--nw); /* * reset low current bit if within 43rd track */ low = (qp->q_reqid.traQXADDR->qxdb; /* continue reading sector ID's until we stumble upon correct one */ } while(qp->q_reqid != qp->q_id); /* *ck <= 43 ? 0 : LOWCUR); } /* * get current head state */ qxhd = QXADDR->qxcs & HDDOWN; /* * seek to desired track, s Start I/O on a sector */ QXADDR->qxcs = qxunit | HDDOWN | (bp->b_flags&B_READ ? QXREAD : (QXWRITE | low)) | IENABLE | GO;\]^_`abcefghijk return; /* and wait for interrupt */ } /* * qxintr: * handle I/O completion interrupts, * error conditions */ qxintr() { register struct buf *bp; register struct qxinfo *qp; register int *cp; int nw, qxerr; if(qxtab.d_active==0) /* false alarm */ return; qxtab.d_active = 0; bp = qxtab.d_actf; qp = &qx[bp->b_dev.d_minor&QXMASK]; qxerr = QXADDR->qxcs; ount); qp->q_sector = bp->b_blkno * SECPERBLK; qp->q_addr = bp->b_addr; qxsector(bp,qp); /* start first sector of block */  } /* * qxsector: * performs I/O request on single sector (128-bytes) of 512-byte block */ qxsector(bp,aqp) struct buf *bector */ do { /* * check if on right track (so to speak)... * ...if not, step to correct track */ if(qp->q_reqidp; struct qxinfo *aqp; { register struct qxinfo *qp; register int i; register int *cp; int nw, low; qp = aqp; /* .track != qp->q_id.track) { qp->q_stepdir = ((qp->q_reqid.track < qp->q_id.track) ? STEPOUT : STEPIN); i = qp->q_id.track  * compute actual track/sector address */ qp->q_reqid.track = qp->q_sector / SECPERTRK; i = qp->q_sector % SECPERTRK; i = - qp->q_reqid.track; if(i < 0) i = -i; if(i >= 8) qxhd = HDUP; while(i--) { /* step i tracks in specific direction */ (i % INTRLV)*SECINCR + (i / INTRLV); qp->q_reqid.sector = (i + qp->q_reqid.track*SKEWPERTRK) % SECPERTRK; qp->q_reqid.track++; if(i <= 4) qxhead(qp); /* load head */ QXADDR->qxcs = qxunit | qxhd | qp->q_stepdir | GO; WAIT(); if(QXADDR /* track number from 1 to 76 */ qp->q_reqid.sector++; /* sector number from 1 to 26 */ /* * set current unit id */ q->qxcs < 0) ERROR(); qxtimer(qp,6); /* track settle time is in milliseconds */ } qxtimer(qp,24); /* extra settle downxunit = (bp->b_dev.d_minor&QXMASK)<<8; /* * if write request, load data buffer */ if((bp->b_flags&B_READ)==0) { /* write  time on last track */ } /* read ID */ qxhead(qp); /* make sure head is down */ qxtimer(qp,qp->q_timeleft); /* wait an imer(qp,100); /* wait .1 sec */ } while(QXADDR->qxcs < 0); } /* retry */ qxtab.d_active++; qxsector(bp,qp); rELDATA 02000 /* non-fatal */ #define ERRS 076000 /* (NOSYNC|LATE|CRCERR|WRPROT|DELDATA) */ #define CLR_INT (~01501) /* masketurn; } printf(" qx%d: err %o, id %o\n", bp->b_dev.d_minor, qxerr, qp->q_id); bp->b_flags =| B_ERROR; } else { /*  out IENABLE | QXUNIT | GO */ /* * status */ #define DONE 0200 #define TRACK0 01000 #define HDDOWN 020 #define HDUP 0 Command completed successfully */ /* * if read completed, unload data buffer */ if(bp->b_flags & B_READ) { cp = qp- struct { int qxcs; int qxdb; }; struct { char track; char sector; }; struct qxinfo { int q_id; int q_reqid; int q_co>q_addr; nw = min(qp->q_count, SECSZ); do { *cp++ = QXADDR->qxdb; } while(--nw); } /* * bump up start addreunt; /* (positive) word count */ int q_sector; char *q_addr; int q_timeleft; int q_stepdir; /* step direction: STEPIN, STEss, reduce byte count for next sector in block */ qp->q_addr =+ (SECSZ<<1); qp->q_count =- SECSZ; qp->q_sector++; ifPOUT */ }; struct qxinfo qx[NQX]; struct devtab qxtab; int qxunit; /* current unit, ready to be stuffed into reg. */ int (qp->q_count > 0 && qp->q_sector < NUMSEC) { qxtab.d_active++; qxsector(bp,qp); /* get next sector */ return; } } qxhd; /* current head state */ #define WAIT while((QXADDR->qxcs&DONE)==0) #define FAULT { qxintr(); return;} /* * qxstra /* all done with block; unlink buffer from queue */ qxtab.d_errcnt = 0; qxtab.d_actf = bp->av_forw; iodone(bp); qxstart(); tegy: * queue up I/O request */ qxstrategy(abp) struct buf *abp; { register struct buf *bp; bp = abp; #ifdef DEBUG printf } /* * qxtimer: * time out function, using QX real time 2 ms. clock */ qxtimer(aqp,msec) struct qxinfo *aqp; int msec; {("qxstgy(%o) b=%d r=%o\n",bp,bp->b_blkno,bp->b_flags&B_READ); #endif /* * check unit no., blk no., and word count */ if(b register time; register struct qxinfo *qp; qp = aqp; time = msec; while(time > 0) { QXADDR->qxcs = qxunit | qxhd | RTCp->b_dev.d_minor >= NQX || bp->b_blkno + (-bp->b_wcount>>8) > NUMBLK /* || -bp->b_wcount&037 */ ) { bp->b_flags =| /* disable interrupts */ QXADDR->qxcs =& ~(IENABLE|GO); if(qxerr < 0) { /* error */ if(++qxtab.d_errcnt <= MAXRETRY) { LOCK | GO; WAIT(); /* for 2 ms. */ time =- 2; if(qp->q_timeleft > 0) qp->q_timeleft =- 2; } } /* * qxhead: * loa if(qxerr & ERRORS) { if(qxerr & CRCERR) printf(" qx%d: CRC err, id %o\n", bp->b_dev.d_minor, qp->q_id); if(d head, if not already loaded */ qxhead(qp) struct qxinfo *qp; { qxhd = HDDOWN; if((QXADDR->qxcs & HDDOWN) != HDDOWN) /*qxerr & NOSYNC) qp->q_id.track++; else if(qxerr & TRACK0) qp->q_id.track--; else if(qp->q_stepdir==STE * must wait 50 ms. for head settling */ qp->q_timeleft = 50; } POUT) qp->q_id.track++; else qp->q_id.track--; } else { /* drive not ready */ qxhd = HDUP; do { qxts */ #define ERROR 0100000 #define NOSYNC 040000 #define LATE 020000 #define CRCERR 010000 #define WRPROT 04000 #define D xtab.d_actf = bp; else qxtab.d_actl->av_forw = bp; qxtab.d_actl = bp; if(qxtab.d_active==0) qxstart(); spl0(); } /*stlmnopquvwxyz{| * qxstart: * initiate I/O request on 512-byte block */ qxstart() { register struct buf *bp; register struct qxinfo *qp;  if((bp = qxtab.d_actf)==0) return; #ifdef DEBUG printf("qxstrt(%o)\n",bp); #endif /* * start transfer of next block req. in queue */ qp = &qx[bp->b_dev.d_minor&QXMASK]; /* * set this flag to indicate some activity */ qxtab.d_active++; qp->q_count = (-bp->b_wcount); qp->q_sector = bp->b_blkno * SECPERBLK; qp->q_addr = bp->b_addr; qxsector(bp,qp); /* start fir# /* * QX floppy disk driver * April, 1980 */ #include "../param.h" #include "../buf.h" #include "../conf.h" #include "../ust sector of block */ } /* * qxsector: * performs I/O request on single sector (128-bytes) of 512-byte block */ qxsector(ser.h" /* * "physical" constants */ #define NQX 3 #define QXMASK 03 #define SECSZ 64 /* 64 words/sector */ #define SECPabp,aqp) struct buf *abp; struct qxinfo *aqp; { register struct buf *bp; register struct qxinfo *qp; register int n; ERBLK 4 #define SECPERTRK 26 #define NUMTRK 76 #define NUMSEC (76*26) /* 76 tracks by 26 sectors/trk */ #define NUMBLK 494 # int *cp, low; bp = abp; qp = aqp; #ifdef DEBUG printf("qxsec(%o,%o),a=%o,r=%o\n",bp,qp,qp->q_addr,bp->b_flags&B_READ); #endidefine SECINCR 2 /* distance to next sector of block */ #define INTRLV 13 /* interleave factor */ #define SKEWPERTRK 6 /* sf /* * compute actual track/sector address */ qp->q_reqid.track = qp->q_sector / SECPERTRK; n = qp->q_sector % SECPERTRKector skew across tracks */ #define MAXRETRY 10 #define QXADDR 0177000 /* * controller commands (write only) */ #define ; n = (n % INTRLV)*SECINCR + (n / INTRLV); qp->q_reqid.sector = (n + qp->q_reqid.track*SKEWPERTRK) % SECPERTRK; qp->q_reqid.tIENABLE 0100 #define LOWCUR 040 /* low current: reset for trks 1-43 */ #define NOOP 0 #define GO 01 #define RTCLOCK 02 /*rack++; /* track number from 1 to 76 */ qp->q_reqid.sector++; /* sector number from 1 to 26 */ /* * set current unit id  real time clock; intr. after 2 ms. */ #define STEPIN 04 /* step toward center of floppy */ #define STEPOUT 06 /* step away  */ qxunit = (bp->b_dev.d_minor&QXMASK)<<8; /* * if write request, load data buffer */ if((bp->b_flags&B_READ)==0) { /*from center of floppy */ #define READID 010 #define QXREAD 012 #define QXWRITE 014 #define WRDEL 016 /* * error conditionB_ERROR; iodone(bp); return; } /* * put request in I/O queue */ bp->av_forw = 0; spl5(); if(qxtab.d_actf==0) q write */ n = QXADDR->qxcs; /* reset data buffer by simply refering to cs reg. */ n = min(qp->q_count, SECSZ); cp = qp->q_ efine _QX_READ 0133 /* hddown | qxread | ienable | go */ #define _QX_WRITE 0135 /* hddown | qxwrite | ienable | go */ QXADDR- } /* * bump up start address, reduce byte count for next sector in block */ qp->q_addr =+ (SECSZ*2); qp->q_count >qxcs = qxunit | (bp->b_flags&B_READ ? _QX_READ : (_QX_WRITE | low)); return; /* and wait for interrupt */ } /* * qxintr=- SECSZ; qp->q_sector++; if((qp->q_count > 0) && (qp->q_sector < NUMSEC)) { qxsector(bp,qp); /* get next sector */ readdr; do { QXADDR->qxdb = *cp++; } while(--n); /* sluff excess bytes */ for(n = SECSZ-(qp->q_count); n>0; --n) { Q: * handle I/O completion interrupts, * error conditions */ qxintr() { register struct buf *bp; register struct qxinfo *qpXADDR->qxdb = 0; } /* * reset low current bit if within 43rd track */ low = (qp->q_reqid.track <= 43 ? 0 : LOWCUR);; register int *cp; int nw, qxerr; if(qxtab.d_active==0) /* false alarm */ return; #ifdef DEBUG printf("qxintr(%o,%o)\ } /* * seek to desired track, sector */ do { qxhd = QXADDR->qxcs & HDDOWN; /* * check if on right track (so to sn",bp,qp); #endif bp = qxtab.d_actf; qp = &qx[bp->b_dev.d_minor&QXMASK]; qxunit = (bp->b_dev.d_minor & QXMASK) << 8; qxerpeak)... * ...if not, step to correct track */ if(qp->q_reqid.track != qp->q_id.track) { qp->q_stepdir = ((qp->q_reqir = QXADDR->qxcs; /* disable interrupts */ QXADDR->qxcs = ( qxerr & CLR_INT ) | qxunit; if(qxerr & ERROR) { /* error */ d.track < qp->q_id.track) ? STEPOUT : STEPIN); n = qp->q_id.track - qp->q_reqid.track; if(n < 0) n = -n; if(n >= 8) qxh if(++qxtab.d_errcnt <= MAXRETRY) { if(qxerr & ERRS) { if(qxerr & NOSYNC) qp->q_id.track++; else if(qxerr & d = HDUP; while(n--) { /* step n tracks in specific direction */ if(n <= 4) qxhead(qp); /* load head */ QXADDR-TRACK0) qp->q_id.track--; else if(qp->q_stepdir==STEPOUT) qp->q_id.track++; else qp->q_id.track--; } >qxcs = qxunit | qxhd | qp->q_stepdir | GO; WAIT; if(QXADDR->qxcs < 0) FAULT; qxtimer(qp,6); /* track settle time is else { /* drive not ready */ qxhd = HDUP; do { qxtimer(qp,100); /* wait .1 sec */ } while(QXADDR->qxcs & ERRO in milliseconds */ } qxtimer(qp,24); /* extra settle down time on last track */ } /* read ID */ qxhead(qp); /* mR); } qxsector(bp,qp); /* retry */ return; } #ifdef DEBUG printf(" qx%d: err %o, id %o\n", bp->b_dev.d_minor, qxake sure head is down */ qxtimer(qp,qp->q_timeleft); /* wait any remaining accum. time */ #define _READ_ID 031; /* hddown | reerr, qp->q_id); #endif bp->b_flags =| B_ERROR; } else { /* Command completed successfully */ /* * if read completed, adid | go */ QXADDR->qxcs = qxunit | _READ_ID; WAIT; if(QXADDR->qxcs<0) FAULT; qp->q_id = QXADDR->qxdb; /* continue reunload data buffer */ if(bp->b_flags & B_READ) { cp = qp->q_addr; nw = min(qp->q_count, SECSZ) ; do { *cp++ = ading sector ID's until we stumble upon correct one */ } while(qp->q_reqid != qp->q_id); /* * Start I/O on a sector */ #dQXADDR->qxdb; } while(--nw); /* sluff excess */ for(nw=SECSZ-(qp->q_count); nw>0; --nw) { cp = QXADDR->qxdb; }  define GO 01 #define RCOM 02 #define WCOM 04 #define CTLCLR 0400 #define IENABLE 0100 rfstrategy(abp) struct buf *abp; { regis /* buffer address */ *--dp = rbp->b_wcount; /* word count */ com = IENABLE | GO; if (rbp->b_flags&B_READ) /* command */ ter struct buf *bp; bp = abp; if (bp->b_blkno >= NRFBLK*(bp->b_dev.d_minor+1)) { bp->b_flags =| B_ERROR; iodone(bp); recom =| RHRCOM; else com =| RHWCOM; *--dp = com; } turn; } bp->av_forw = 0; spl5(); if (rftab.d_actf==0) rftab.d_actf = bp; else rftab.d_actl->av_forw = bp; rftab.d_actl = bp; if (rftab.d_active==0) rfstart(); spl0(); } rfstart() { register struct buf *bp; if ((bp = rftab.d_actf) == 0) return; rftab.d_active++; RFADDR->rfdae = bp->b_blkno.hibyte; devstart(bp, &RFADDR->rfda, bp->b_blkno<<8, 0); } rfintr() { turn; } } /* all done with block; unlink buffer from queue */ qxtab.d_active = 0; qxtab.d_errcnt = 0; qxtab.d_actf = bpregister struct buf *bp; if (rftab.d_active == 0) return; bp = rftab.d_actf; rftab.d_active = 0; if (RFADDR->rfcs < 0) { ->av_forw; iodone(bp); #ifdef DEBUG printf("iodone(%o)\n",bp); #endif qxstart(); } /* * qxtimer: * time out function, usi /* error bit */ RFADDR->rfcs = CTLCLR; if (++rftab.d_errcnt <= 10) { rfstart(); return; } bp->b_flags =| B_ERROR;ng QX real time 2 ms. clock */ qxtimer(aqp,msec) struct qxinfo *aqp; int msec; { register time; register struct qxinfo *qp } rftab.d_errcnt = 0; rftab.d_actf = bp->av_forw; iodone(bp); rfstart(); } ; qp = aqp; time = msec; while(time > 0) { QXADDR->qxcs = qxunit | qxhd | RTCLOCK | GO; WAIT; /* for 2 ms. */ time =- 2; if(qp->q_timeleft > 0) qp->q_timeleft =- 2; } } /* * qxhead: * load head, if not already loaded */ qxhead(qp) struct qxinfo *qp; { qxhd = HDDOWN; if((QXADDR->qxcs & HDDOWN) != HDDOWN) /* * must wait 50 ms. for head settling */ #include "../param.h" #include "../buf.h" /* * startup routine for RH controllers. */ #define IENABLE 0100 #define RHWCOM 060# /* */ /* * RF disk driver */ #include "../param.h" #include "../buf.h" #include "../conf.h" #include "../user.h" struct  #define RHRCOM 070 #define GO 01 rhstart(bp, devloc, devblk, abae) struct buf *bp; int *devloc, *abae; { register int *dp; r{ int rfcs; int rfwc; int rfba; int rfda; int rfdae; }; struct devtab rftab; #define NRFBLK 1024 #define RFADDR 0177460 #egister struct buf *rbp; register int com; dp = devloc; rbp = bp; *dp = devblk; /* block address */ *--dp = rbp->b_addr; _actf==0) rktab.d_actf = bp; else rktab.d_actl->av_forw = bp; rktab.d_actl = bp; if (rktab.d_active==0) rkstart(); splUse av_back to save track+sector, * b_resid for cylinder. */ #define trksec av_back #define cylin b_resid rpstrategy(abp) st0(); } rkstart() { register struct buf *bp; if ((bp = rktab.d_actf) == 0) return; rktab.d_active++; devstart(bp, &RKADDRruct buf *abp; { register struct buf *bp; register char *p1, *p2; bp = abp; p1 = &rp_sizes[bp->b_dev.d_minor&07]; if (bp->->rkda, rkaddr(bp->b_dev.d_minor, bp->b_blkno), 0); } rkintr() { register struct buf *bp; if (rktab.d_active == 0) return;b_dev.d_minor >= (NRP<<3) || bp->b_blkno >= p1->nblocks) { bp->b_flags =| B_ERROR; iodone(bp); return; } bp->av_for bp = rktab.d_actf; rktab.d_active = 0; if (RKADDR->rkcs < 0) { /* error bit */ RKADDR->rkcs = RESET|GO; while((RKADDR->w = 0; bp->cylin = p1->cyloff; p1 = bp->b_blkno; p2 = lrem(p1, 10); p1 = ldiv(p1, 10); bp->trksec = (p1%20)<<8 | p2; bp->crkcs&CTLRDY) == 0) ; if (++rktab.d_errcnt <= 10) { rkstart(); return; } bp->b_flags =| B_ERROR; } rktab.d_errcnt =ylin =+ p1/20; spl5(); if ((p1 = rptab.d_actf)==0) rptab.d_actf = bp; else { for (; p2 = p1->av_forw; p1 = p2) { if (p 0; rktab.d_actf = bp->av_forw; iodone(bp); rkstart(); } 1->cylin <= bp->cylin && bp->cylin < p2->cylin || p1->cylin >= bp->cylin && bp->cylin > p2->cylin) break; } bp->av_forw = p2; p1->av_forw = bp; } if (rptab.d_active==0) rpstart(); spl0(); } rpstart() { register struct buf *b# /* */ /* * RP disk driver */ #include "../param.h" #include "../buf.h" #include "../conf.h" #include "../user.h" struct p; if ((bp = rptab.d_actf) == 0) return; rptab.d_active++; RPADDR->rpda = bp->trksec; devstart(bp, &RPADDR->rpca, bp->cyl# /* */ /* * RK disk driver */ #include "../param.h" #include "../buf.h" #include "../conf.h" #include "../user.h" #define{ int rpds; int rper; int rpcs; int rpwc; int rpba; int rpca; int rpda; }; #define RPADDR 0176710 #define NRP 8 struct  RKADDR 0177400 #define NRK 4 #define NRKBLK 4872 #define RESET 0 #define GO 01 #define DRESET 014 #define IENABLE 0100 #define{ char *nblocks; int cyloff; } rp_sizes[] { 40600, 0, /* cyl 0 thru 202 */ 40600, 203, /* cyl 203 thru 405 */ 9200, 0, / DRY 0200 #define ARDY 0100 #define WLO 020000 #define CTLRDY 0200 struct { int rkds; int rker; int rkcs; int rkwc; int rk* cyl 0 thru 45 */ 9200, 360, /* cyl 360 thru 405 */ -1, 0, /* cyl 0 thru 327 */ -1, 78, /* cyl 78 thru 405 */ 15600, 0, ba; int rkda; }; struct devtab rktab; rkstrategy(abp) struct buf *abp; { register struct buf *bp; register *qc, *ql; bp = /* cyl 0 thru 77 */ 15600, 328, /* cyl 328 thru 405 */ }; struct devtab rptab; #define GO 01 #define RESET 0 #define HSEEK 0 abp; if (bp->b_blkno >= NRKBLK) { bp->b_flags =| B_ERROR; iodone(bp); return; } bp->av_forw = 0; spl5(); if (rktab.d14 #define IENABLE 0100 #define READY 0200 #define SUFU 01000 #define SUSU 02000 #define SUSI 04000 #define HNF 010000 /* *  rpcs.lobyte = HSEEK|GO; ctr = 0; while ((RPADDR->rpds&SUSU) && --ctr); } RPADDR->rpcs = RESET|GO; ctr = 0; while (struct { int rxcs; int rxdb; }; struct rxtype { int secsize; /* size (bytes) one sector */ int secpertrk; /* sectors/trac(RPADDR->rpcs&READY) == 0 && --ctr); if (++rptab.d_errcnt <= 10) { rpstart(); return; } bp->b_flags =| B_ERROR; } k */ int secperblk; /* sectors/unix block */ int numsec; /* total sectors on device */ int numblks; /* number of blocks orptab.d_errcnt = 0; rptab.d_actf = bp->av_forw; bp->b_resid = RPADDR->rpwc; iodone(bp); rpstart(); } n device */ int secincr; /* increment to get next sector of block */ int intrlv; /* interleaving factor */ int skew; /* sector skew across tracks */ int trkoffset; /* offset num of 1st sec */ } rxtypes[NRXTYP] { 128, 26, 4, 77*26, 500, 2, 13, 6# /* * RX11 floppy disk driver * * Modified 15 DEC 77 by SSB,DWD,BEB, University of Minnesota * for RX11 floppy drive. * M, 0, /* our "standard" format */ 128, 26, 4, 77*26, 500, 1, 26, 0, 0, /* IBM format */ 128, 26, 4, 76*26, 494, 2, 13, 6, 1 /odified 2/1/78, Brad Blasing, to emulate DMA operations. * Modified 6/16/78, Brad Blasing, to provide better error recovery * * Terak or RT11 format */ }; struct rxstat { int fminor; /* present request device number */ struct rxtype *ftype; /* pres (we don't loop at spl5 waiting for INIT to finish any more). * */ #include "../param.h" #include "../buf.h" #include "../conent request floppy type */ int bytect; /* remaining bytes (neg) */ int sector; /* absolute sector (0..numsec-1) */ int tof.h" #include "../user.h" /* #define DMA 1 turn on for dma driver */ /* #define DEBUG 1 */ #define RXADDR 0177170 #define Nutact; /* timeout active */ int reqnum; /* floppy request number for timeout */ char *coreaddr; /* current core address foRXTYP 3 #define MAXRETRY 5 #define TTIME 60 /* Timeout time in HZ */ #define RRATE 6 /* Recall rate for rxreset */ #define RESEr transfer */ #ifdef DMA char *coreblk; /* block no. to put in seg. register */ #endif } rxstat; struct devtab rxtab; rxstraTMAX 50 /* Max. num. of reset recalls before timeout */ /* RESETMAX*RRATE/60 = time in second */ /* rxcs commands and masks tegy(abp) struct buf *abp; { register struct buf *bp; extern int rxtimeout(); #ifdef DEBUG if(abp->b_dev.d_minor == 127) { */ #define INIT 0040000 #define ERROR 0100000 #define IENABLE 0100 #define TR 0200 #define DONE 040 #define GO 001 #define FILL  rxdebug(); iodone(abp); spl0(); return; } #endif bp = abp; #ifdef CPU70 if(bp->b_flags&B_PHYS) /* * only valid foin, bp->b_dev.d_minor>>3); } rpintr() { register struct buf *bp; register int ctr; if (rptab.d_active == 0) return; bp =000 #define EMPTY 002 #define WRITE 004 #define READ 006 #define RDSTAT 012 #define RDERR 016 /* status register masks */ #defi rptab.d_actf; rptab.d_active = 0; if (RPADDR->rpcs < 0) { /* error bit */ if(RPADDR->rpds & (SUFU|SUSI|HNF)) { RPADDR->ne DR 0200 /* Drive Ready */ #define WAITTR /* while((RXADDR->rxcs & TR) == 0) ; */ #define KISA 0172340 #define KISD 0172300  rom timing out. */ rxstat.reqnum++; } } else { RXADDR->rxcs = INIT; rxtab.d_active++; rxstat.reqnum++; timer an 11/70 */ mapalloc(bp); #endif CPU70 /* * test for valid request */ if(rxok(bp) == 0) { bp->b_flags =| B_ERROR; iodone(bp); return; } /* * link buffer into device queue */ bp->av_forw = 0; spl5(); if(rxtab.d_actf == 0) rxtab.d_actf = bp; else rxtab.d_actl->av_forw = bp; rxtab.d_actl = bp; /* * start rxtimeout if inactive */ if(rxstat.toutact == 0) { rxstat.toutact++; timeout(rxtimeout, 0, TTIME); } /* * start device if there is no current request */ if(rxRR | GO; /* deverror(bp, RXADDR->rxcs, RXADDR->rxdb); */ /* * make MAXRETRY retries on an error */ if(++rxtab.d_errtab.d_active == 0) rxstart(); spl0(); } rxstart() { register struct buf *bp; register int minor; /* * if there is no rcnt <= MAXRETRY) { rxreset(0); return; } /* * return an i/o error */ bp->b_flags =| B_ERROR; } else { /* equest in queue...return */ loop: if((bp = rxtab.d_actf) == 0) return; /* * check if drive ready */ minor = (bp->b_dev * if we just read a sector, we need to * empty the device buffer */ if(bp->b_flags & B_READ) rxempty(bp); /* .d_minor & 1) << 4; RXADDR->rxcs = minor | RDSTAT | GO; while((RXADDR->rxcs & DONE) == 0) ; if((RXADDR->rxdb & DR) == 0) { /** see if there is more data to read for * this request. */ rxstat.bytect =+ rxt->secsize; rxstat.sector++; if(rxstat prdev("Floppy not ready", bp->b_dev); */ rxabtbuf(); goto loop; } /* * set active request flag */ rxtab.d_active++.bytect < 0 && rxstat.sector < rxt->numsec) { rxtab.d_active++; rxregs(bp); return; } } rxtab.d_errcnt = 0; /* *; rxsetup(bp); rxregs(bp); } rxintr() { register struct buf *bp; register struct rxtype *rxt; /* * if there is no activ unlink block from queue */ rxtab.d_actf = bp->av_forw; iodone(bp); /* * start i/o on next buffer in queue */ rxstart(e request, false alarm. */ if(rxtab.d_active == 0) return; rxtab.d_active = 0; /* * pointer to the buffer */ bp = r); } rxreset(flag) { /* * Check to see if this is a call from rxintr or * a recall from timeout. */ if(flag) { if(RXAxtab.d_actf; /* * pointer to a data structure describing * the type of device (i.e. interleaving) */ rxt = rxstat.ftypeDDR->rxcs & DONE) { rxtab.d_active = 0; rxstart(); } else if(flag > RESETMAX) { /* prdev("Reset timeout", rxtab.d; /* * check error bit */ if(RXADDR->rxcs & ERROR) { /* * send read error register command */ RXADDR->rxcs = RDE_actf->b_dev); */ rxabtbuf(); rxstart(); } else { timeout(rxreset, flag+1, RRATE); /* * Keep rxtimeout f ster int minor; /* * get sub-device number and type from minor device number */ minor = (bp = abp)->b_dev.d_minor; type tes */ for(i=128-wc; i>0; --i) { WAITTR cp = RXADDR->rxdb; } } rxfill(abp) struct buf *abp; { register int i; registe= minor >> 3; /* * check for valid type * * check for block number within range of device */ if(type >= NRXTYP || bpr char *cp; register int wc; /* * initiate the fill buffer command */ RXADDR->rxcs = FILL | GO; /* * get core address->b_blkno >= rxtypes[type].numblks) return(0); return(1); } rxsetup(abp) struct buf *abp; { register struct buf *bp; regis and byte count */ cp = rxstat.coreaddr; rxstat.coreaddr =+ 128; wc = ((rxstat.bytect <= -128)? 128 : -rxstat.bytect); /* ter int minor; register struct rxtype *rxt; /* * get minor device number from buffer */ minor = (bp = abp)->b_dev.d_mino * move wc bytes from the in-core buffer to * the device buffer */ for(i=wc; i>0; --i) { WAITTR RXADDR->rxdb = *cp+out(rxreset, 1, 1); } } rxregs(abp) struct buf *abp; { register struct buf *bp; register int minor; register struct rxtype r; /* * get sub-device number from minor device number */ rxt = rxstat.ftype = &rxtypes[minor >> 3]; /* * make sure dev*rxt; int cursec, curtrk; /* * set device bit into proper position for command */ minor = rxstat.fminor << 4; bp = abp;ice number is only 0 or 1 */ rxstat.fminor = minor & 1; /* * get byte count to read from buffer (negative number) */ rx rxt = rxstat.ftype; /* * increment interrupt request number */ rxstat.reqnum++; /* * if command is read, initiate thestat.bytect = (bp->b_wcount << 1); /* * transform block number into the first * sector to read on the floppy */ rxstat.s command */ if(bp->b_flags & B_READ){ RXADDR->rxcs = minor | IENABLE | GO | READ; } else { /* * if command is write, ector = bp->b_blkno * rxt->secperblk; /* * set the core address to get or put bytes. */ #ifndef DMA rxstat.coreaddr = bp->fill the device buffer, * then initiate the write */ rxfill(bp); RXADDR->rxcs = minor | IENABLE | GO | WRITE; } /*b_addr; #endif #ifdef DMA rxstat.coreaddr = (bp->b_addr & 077) + 0120000; rxstat.coreblk = ((bp->b_addr >> 6) & 01777) | ((b * set track number */ curtrk = rxstat.sector / rxt->secpertrk; /* * set sector number */ minor = rxstat.sector % rxtp->b_xmem & 03) << 10); #endif } #ifndef DMA rxempty(abp) struct buf *abp; { register int i; register char *cp; register int->secpertrk; cursec = (minor % rxt->intrlv) * rxt->secincr + (minor / rxt->intrlv); /* * add skew to sector */ if(rxt-> wc; /* * start empty buffer command */ RXADDR->rxcs = EMPTY | GO; /* * get core address and byte count */ cp = rxsskew != 0) cursec = (cursec + curtrk * rxt->skew) % rxt->secpertrk; /* * massage registers */ RXADDR->rxdb = cursec +tat.coreaddr; rxstat.coreaddr =+ 128; wc = ((rxstat.bytect <= -128)? 128 : -rxstat.bytect); /* * move wc bytes from the dev 1; RXADDR->rxdb = curtrk + rxt->trkoffset; } rxok(abp) struct buf *abp; { register struct buf *bp; register int type; regiice buffer * into the in core buffer */ for(i=wc; i>0; --i) { WAITTR *cp++ = RXADDR->rxdb; } /* * sluff excess by  buffer command */ RXADDR->rxcs = EMPTY | GO; /* * get core address and byte count */ cp = rxstat.coreaddr; wc = ((rxs rxabtbuf(); rxstart(); } prevreq = rxstat.reqnum; timeout(rxtimeout, 0, TTIME); } else { /* * if queue is empty,tat.bytect <= -128)? 128 : -rxstat.bytect); /* * save and set segmentation register. */ a = KISA->r[5]; d = KISD->r[5];  just quit and rxstrategy will * restart us. */ rxstat.toutact = 0; } } rxabtbuf() { register struct buf *bp; /* spl7(); KISA->r[5] = rxstat.coreblk; KISD->r[5] = 01006; /* * move wc bytes from the device buffer * into the in core b* abort the current buffer with an error and unlink it. */ bp = rxtab.d_actf; bp->b_flags =| B_ERROR; rxtab.d_actf = bp->avuffer */ for(i=wc; i>0; --i) { WAITTR *cp++ = RXADDR->rxdb; } /* * sluff excess bytes */ for(i=128-wc; i>0; --i) {_forw; rxtab.d_errcnt = rxtab.d_active = 0; iodone(bp); } #ifdef DEBUG rxdebug() { register struct buf *bp; spl5(); print WAITTR cp = RXADDR->rxdb; } KISA->r[5] = a; KISD->r[5] = d; spl5(); rxstat.coreblk =+ 2; } rxfill(abp) struct buf *abf("Debug: &rxtab=%o, &rxstat=%o\n", &rxtab, &rxstat); printf(" rxstat: fminor=%l, bytect=%l, sec=%l\n", rxstat.fminor, -rxsp; { register int i; register char *cp; register int wc; int a,d; /* * initiate the fill buffer command */ RXADDR->rxtat.bytect, rxstat.sector); printf(" reqnum=%l\n", rxstat.reqnum); printf(" rxtab: d_active=%l, buffers:\n", rxtab.d_activecs = FILL | GO; /* * get core address and byte count */ cp = rxstat.coreaddr; wc = ((rxstat.bytect <= -128)? 128 : -rxsta); for(bp=rxtab.d_actf; bp; bp=bp->av_forw) printf(" dev=%l/%l, blkno=%l, wcnt=%l, flags=%o.\n", bp->b_dev.d_major, bp->b_+; } /* * sluff excess bytes */ for(i=128-wc; i>0; --i) { WAITTR RXADDR->rxdb = 0; } } #endif #ifdef DMA /* * Tht.bytect); /* * save and set segmentation register. */ a = KISA->r[5]; d = KISD->r[5]; spl7(); KISA->r[5] = rxstat.coreis copy of the fill and empty routines emulate a dma * floppy controller. It adds the feature of being able * to write anywblk; KISD->r[5] = 01006; /* * move wc bytes from the in-core buffer to * the device buffer */ for(i=wc; i>0; --i) { here in physical memory, just like an rk * disk. To do this, we borrow a segmentation register * to do the transfer. While WAITTR RXADDR->rxdb = *cp++; } /* * sluff excess bytes */ for(i=128-wc; i>0; --i) { WAITTR RXADDR->rxdb = 0; }  the segmentation register * is pointing to the proper place, we need to run at spl7. * This is harder on the system, so theKISA->r[5] = a; KISD->r[5] = d; spl5(); rxstat.coreblk =+ 2; } #endif rxtimeout(dummy) { static int prevreq; register stru non-dma driver should * be used if you only intend to do buffer requests (i.e. * no swapping or raw i/o). */ struct { inct buf *bp; bp = rxtab.d_actf; /* * if the queue isn't empty and the current request number is the * same as last time, at r[]; }; rxempty(abp) struct buf *abp; { register int i; register char *cp; register int wc; int a,d; /* * start emptybort the buffer and restart i/o. */ if(bp) { if(prevreq == rxstat.reqnum) { /* prdev("Floppy timeout", bp->b_dev); */  odified 2/1/78, Brad Blasing, to emulate DMA operations. * Modified 6/16/78, Brad Blasing, to provide better error recovery *  1 /* Terak or RT11 format */ }; struct rxstat { int fminor; /* present request device number */ struct rxtype *ftype; /*  (we don't loop at spl5 waiting for INIT to finish any more). * */ #include "../param.h" #include "../buf.h" #include "../conpresent request floppy type */ int bytect; /* remaining bytes (neg) */ int sector; /* absolute sector (0..numsec-1) */ inf.h" #include "../user.h" /* #define DMA 1 turn on for dma driver */ #define DEBUG 1 #define RXADDR 0177170 #define NRXTYP t toutact; /* timeout active */ int reqnum; /* floppy request number for timeout */ char *coreaddr; /* current core addres3 #define MAXRETRY 5 #define TTIME 60 /* Timeout time in HZ */ #define RRATE 6 /* Recall rate for rxreset */ #define RESETMAX 1s for transfer */ #ifdef DMA char *coreblk; /* block no. to put in seg. register */ #endif } rxstat; struct devtab rxtab; wa00 /* Max. num. of reset recalls before timeout */ /* RESETMAX*RRATE/60 = time in second */ /* rxcs commands and masks */ #dittr() { int delay; delay = 0; while(!(RXADDR->rxcs & TR) && --delay); if(delay == 0 && SW->integ == 0177777) printf("TR tefine INIT 0040000 #define ERROR 0100000 #define IENABLE 0100 #define TR 0200 #define DONE 040 #define GO 001 #define FILL 000 #imeout.\n"); } rxstrategy(abp) struct buf *abp; { register struct buf *bp; extern int rxtimeout(); #ifdef DEBUG if(abp->b_dedefine EMPTY 002 #define WRITE 004 #define READ 006 #define RDSTAT 012 #define RDERR 016 /* status register masks */ #define DRv.d_minor == 127) { rxdebug(); iodone(abp); spl0(); return; } #endif bp = abp; #ifdef CPU70 if(bp->b_flags&B_PHYS)  0200 /* Drive Ready */ #define WAITTR waittr(); /* while((RXADDR->rxcs & TR) != 0); */ #define KISA 0172340 #define KISD 01723/* * only valid for an 11/70 */ mapalloc(bp); #endif CPU70 /* * test for valid request */ if(rxok(bp) == 0) { bp00 struct { int rxcs; int rxdb; }; struct rxtype { int secsize; /* size (bytes) one sector */ int secpertrk; /* sectors/->b_flags =| B_ERROR; iodone(bp); return; } /* * link buffer into device queue */ bp->av_forw = 0; spl5(); if(rxtabtrack */ int secperblk; /* sectors/unix block */ int numsec; /* total sectors on device */ int numblks; /* number of bloc.d_actf == 0) rxtab.d_actf = bp; else rxtab.d_actl->av_forw = bp; rxtab.d_actl = bp; /* * start rxtimeout if inactive dev.d_minor, bp->b_blkno, -bp->b_wcount, bp->b_flags); putchar('\n'); } #endif ks on device */ int secincr; /* increment to get next sector of block */ int intrlv; /* interleaving factor */ int skew;  /* sector skew across tracks */ int trkoffset; /* offset num of 1st sec */ } rxtypes[NRXTYP] { 128, 26, 4, 77*26, 500, 2, 1# /* * RX11 floppy disk driver * * Modified 15 DEC 77 by SSB,DWD,BEB, University of Minnesota * for RX11 floppy drive. * M3, 6, 0, /* our "standard" format */ 128, 26, 4, 77*26, 500, 1, 26, 0, 0, /* IBM format */ 128, 26, 4, 76*26, 494, 2, 13, 6,  */ if(rxstat.toutact == 0) { rxstat.toutact++; timeout(rxtimeout, 0, TTIME); } /* * start device if there is no currenDDR->rxcs = RDERR | GO; deverror(bp, RXADDR->rxcs, RXADDR->rxdb); /* * make MAXRETRY retries on an error */ if(++rxt request */ if(rxtab.d_active == 0) rxstart(); spl0(); } rxstart() { register struct buf *bp; register int minor; /*tab.d_errcnt <= MAXRETRY) { rxreset(0); return; } /* * return an i/o error */ bp->b_flags =| B_ERROR; } else  * if there is no request in queue...return */ loop: if((bp = rxtab.d_actf) == 0) return; /* * check if drive ready *{ /* * if we just read a sector, we need to * empty the device buffer */ if(bp->b_flags & B_READ) rxempty(bp);/ minor = (bp->b_dev.d_minor & 1) << 4; RXADDR->rxcs = minor | RDSTAT | GO; while((RXADDR->rxcs & DONE) == 0) ; if((RXADDR-> /* * see if there is more data to read for * this request. */ rxstat.bytect =+ rxt->secsize; rxstat.sector++; rxdb & DR) == 0) { prdev("Floppy not ready", bp->b_dev); rxabtbuf(); goto loop; } /* * set active request flag */ rif(rxstat.bytect < 0 && rxstat.sector < rxt->numsec) { rxtab.d_active++; rxregs(bp); return; } } rxtab.d_errcnt = 0xtab.d_active++; rxsetup(bp); rxregs(bp); } rxintr() { register struct buf *bp; register struct rxtype *rxt; /* * if th; /* * unlink block from queue */ rxtab.d_actf = bp->av_forw; iodone(bp); /* * start i/o on next buffer in queue */ ere is no active request, false alarm. */ if(rxtab.d_active == 0) return; rxtab.d_active = 0; /* * pointer to the buff rxstart(); } rxreset(flag) { /* * Check to see if this is a call from rxintr or * a recall from timeout. */ if(flag) {er */ bp = rxtab.d_actf; /* * pointer to a data structure describing * the type of device (i.e. interleaving) */ rxt if(RXADDR->rxcs & DONE) { rxtab.d_active = 0; rxstart(); } else if(flag > RESETMAX) { prdev("Reset timeout", rxtab.d_actf->b_dev); rxabtbuf(); rxstart(); } else { timeout(rxreset, flag+1, RRATE); /* * Keep rxtimeout from timing out. */ rxstat.reqnum++; } } else { RXADDR->rxcs = INIT; rxtab.d_active++; rxstat.reqnum++; timeout(rxreset, 1, 1); } } rxregs(abp) struct buf *abp; { register struct buf *bp; register int minor; register struct rxtype *rxt; int cursec, curtrk; /* * set device bit into proper position for command */ minor = rxstat.fminor << 4; bp = a = rxstat.ftype; /* * check error bit */ if(RXADDR->rxcs & ERROR) { /* * send read error register command */ RXAbp; rxt = rxstat.ftype; /* * increment interrupt request number */ rxstat.reqnum++; /* * if command is read, initiate   abp)->b_dev.d_minor; /* * get sub-device number from minor device number */ rxt = rxstat.ftype = &rxtypes[minor >> 3]; /RXADDR->rxdb = *cp++; } /* * sluff excess bytes */ for(i=128-wc; i>0; --i) { WAITTR RXADDR->rxdb = 0; } } #endif #i* * make sure device number is only 0 or 1 */ rxstat.fminor = minor & 1; /* * get byte count to read from buffer (negatifdef DMA /* * This copy of the fill and empty routines emulate a dma * floppy controller. It adds the feature of being ablve number) */ rxstat.bytect = (bp->b_wcount << 1); /* * transform block number into the first * sector to read on the fle * to write anywhere in physical memory, just like an rk * disk. To do this, we borrow a segmentation register * to do tthe command */ if(bp->b_flags & B_READ){ RXADDR->rxcs = minor | IENABLE | GO | READ; } else { /* * if command is writoppy */ rxstat.sector = bp->b_blkno * rxt->secperblk; /* * set the core address to get or put bytes. */ #ifndef DMA rxse, fill the device buffer, * then initiate the write */ rxfill(bp); RXADDR->rxcs = minor | IENABLE | GO | WRITE; } tat.coreaddr = bp->b_addr; #endif #ifdef DMA rxstat.coreaddr = (bp->b_addr & 077) + 0120000; rxstat.coreblk = ((bp->b_addr >>  /* * set track number */ curtrk = rxstat.sector / rxt->secpertrk; /* * set sector number */ minor = rxstat.sector % 6) & 01777) | ((bp->b_xmem & 03) << 10); #endif } #ifndef DMA rxempty(abp) struct buf *abp; { register int i; register charrxt->secpertrk; cursec = (minor % rxt->intrlv) * rxt->secincr + (minor / rxt->intrlv); /* * add skew to sector */ if(rx *cp; register int wc; /* * start empty buffer command */ RXADDR->rxcs = EMPTY | GO; /* * get core address and byte ct->skew != 0) cursec = (cursec + curtrk * rxt->skew) % rxt->secpertrk; /* * massage registers */ WAITTR RXADDR->rxdbount */ cp = rxstat.coreaddr; rxstat.coreaddr =+ 128; wc = ((rxstat.bytect <= -128)? 128 : -rxstat.bytect); /* * move wc = cursec + 1; WAITTR RXADDR->rxdb = curtrk + rxt->trkoffset; } rxok(abp) struct buf *abp; { register struct buf *bp; regis bytes from the device buffer * into the in core buffer */ for(i=wc; i>0; --i) { WAITTR *cp++ = RXADDR->rxdb; } /* ter int type; register int minor; /* * get sub-device number and type from minor device number */ minor = (bp = abp)->b_ * sluff excess bytes */ for(i=128-wc; i>0; --i) { WAITTR cp = RXADDR->rxdb; } } rxfill(abp) struct buf *abp; { regisdev.d_minor; type = minor >> 3; /* * check for valid type * * check for block number within range of device */ if(typter int i; register char *cp; register int wc; /* * initiate the fill buffer command */ RXADDR->rxcs = FILL | GO; /* e >= NRXTYP || bp->b_blkno >= rxtypes[type].numblks) return(0); return(1); } rxsetup(abp) struct buf *abp; { register str * get core address and byte count */ cp = rxstat.coreaddr; rxstat.coreaddr =+ 128; wc = ((rxstat.bytect <= -128)? 128 : -ruct buf *bp; register int minor; register struct rxtype *rxt; /* * get minor device number from buffer */ minor = (bp =xstat.bytect); /* * move wc bytes from the in-core buffer to * the device buffer */ for(i=wc; i>0; --i) { WAITTR  128-wc; i>0; --i) { WAITTR cp = RXADDR->rxdb; } KISA->r[5] = a; KISD->r[5] = d; spl5(); rxstat.coreblk =+ 2; } rxfill(pl5(); printf("Debug: &rxtab=%o, &rxstat=%o\n", &rxtab, &rxstat); printf(" rxstat: fminor=%l, bytect=%l, sec=%l\n", rxstatabp) struct buf *abp; { register int i; register char *cp; register int wc; int a,d; /* * initiate the fill buffer comma.fminor, -rxstat.bytect, rxstat.sector); printf(" reqnum=%l\n", rxstat.reqnum); printf(" rxtab: d_active=%l, buffers:\n", rnd */ RXADDR->rxcs = FILL | GO; /* * get core address and byte count */ cp = rxstat.coreaddr; wc = ((rxstat.bytect <= xtab.d_active); for(bp=rxtab.d_actf; bp; bp=bp->av_forw) printf(" dev=%l/%l, blkno=%l, wcnt=%l, flags=%o.\n", bp->b_dev.d_maj-128)? 128 : -rxstat.bytect); /* * save and set segmentation register. */ a = KISA->r[5]; d = KISD->r[5]; spl7(); KISA-or, bp->b_dev.d_minor, bp->b_blkno, -bp->b_wcount, bp->b_flags); putchar('\n'); } #endif >r[5] = rxstat.coreblk; KISD->r[5] = 01006; /* * move wc bytes from the in-core buffer to * the device buffer */ for(Xw %4CteDuepeeH3 #@UCU@i=wc; i>0; --i) { WAITTR RXADDR->rxdb = *cp++; } /* * sluff excess bytes */ for(i=128-wc; i>0; --i) { WAITTR RXAf ww |Due 4wbw ^@te wHw D@te w.w *Due %he transfer. While the segmentation register * is pointing to the proper place, we need to run at spl7. * This is harder onDDR->rxdb = 0; } KISA->r[5] = a; KISD->r[5] = d; spl5(); rxstat.coreblk =+ 2; } #endif rxtimeout(dummy) { static int prev the system, so the non-dma driver should * be used if you only intend to do buffer requests (i.e. * no swapping or raw i/o)req; register struct buf *bp; bp = rxtab.d_actf; /* * if the queue isn't empty and the current request number is the * s. */ struct { int r[]; }; rxempty(abp) struct buf *abp; { register int i; register char *cp; register int wc; int a,d; ame as last time, abort the buffer and restart i/o. */ if(bp) { if(prevreq == rxstat.reqnum) { prdev("Floppy timeout", b /* * start empty buffer command */ RXADDR->rxcs = EMPTY | GO; /* * get core address and byte count */ cp = rxstat.cop->b_dev); rxabtbuf(); rxstart(); } prevreq = rxstat.reqnum; timeout(rxtimeout, 0, TTIME); } else { /* * if qureaddr; wc = ((rxstat.bytect <= -128)? 128 : -rxstat.bytect); /* * save and set segmentation register. */ a = KISA->r[5];eue is empty, just quit and rxstrategy will * restart us. */ rxstat.toutact = 0; } } rxabtbuf() { register struct buf d = KISD->r[5]; spl7(); KISA->r[5] = rxstat.coreblk; KISD->r[5] = 01006; /* * move wc bytes from the device buffer *  *bp; /* * abort the current buffer with an error and unlink it. */ bp = rxtab.d_actf; bp->b_flags =| B_ERROR; rxtab.d_ into the in core buffer */ for(i=wc; i>0; --i) { WAITTR *cp++ = RXADDR->rxdb; } /* * sluff excess bytes */ for(i=actf = bp->av_forw; rxtab.d_errcnt = rxtab.d_active = 0; iodone(bp); } #ifdef DEBUG rxdebug() { register struct buf *bp; s tab _kl11 _klopen"~klopenflagaddrtpdevcsv L2L1|@  %w nCD`]\U5  w4w 0*E%@2 wL36L4BL5f_ttyopen cret _klclose"~klclosetpdev_wflusht _klread(Ix"~klreaddev_ttread _klwrite"~klwritedev_ttwrite _klxint"~klxinttpdev_ttstart L10000L9_wakeup _klrint"~klrintaddrtpcdevL12*_ttyinpu _klsgtty"8~klsgtty8tpvdev_ttystty w D  tm%U 4  707  ww  xEWpCe~ 3t33& wTw PDC r3 rB r & r eB(Wp` r@3 Et75(@ _e~@  +  5_buf  e ww BteU53& ww DueN& wIE7D3 @ %$7 L!% :]6\ U5  xwh8Ih         U5 "5[@U]]w ]IhIhIhhIh EWpCe Et7l@EA]Z5=K E'5|5@5ˊ% 7 dIhxI_bdevsw _nblkdev _cdevsw _nchrdev _u &_par  5& U777 :w5@ 5 @5 e "~qxstratbpabpcsv L10000$L20_iodone L1^_spl5 L3DL4LL5Z_qxstart"b_spl0 cret ~qxstartbbpqpL6_qxsecto"~qxsectobpcpqpabpnaqplowL17r_min L11<L12 Files rx.c and rx.dec.c are drivers for Plessey PM-XS11AD floppy drives and DEC RX01 floppy drives, respectively. They were u qp->q_timeleft = 50; } sed on the PDP-11/40, running Unix V6, when downloading the Terak-UNIX floppies. The drivers handle 3 floppy formats: minor device no. format tracks interleave skew ---------------- ------ ------ ---------- ---- 0,1 "Unix" 0-76 2:1 6 8,9 "IBM" 0-76 consecutive 0 16,17 "Terak" 1-76 2:1 6  = { compl(SASEEK), 2, { compl(0), compl(10) } }; struct command saio; register struct buf *bp; register int i; register strZL20001TL10001jL10002nL18 L10003L10004L19L21L20003L23_qxhuct command *cp; if((bp = satab.d_actf) == 0) return; /* I think this is right; if sastart() is called * while there's noead"L24L26L20004_qxintr"`L7_qxtimer"L27*L10005NL10006V~qxintr`thing on the queue, I don't * even bother to check if it's in the initialize sequence. */ satab.d_active++; /* state swbpcpqpnwqxerrL30(L31,L32 L33L34L20007itch -- runs through sequence, leaving request * in queue until the drive is ready. If there is an error, * the saintr() L40L36L20008L43L44L45nL48HL49hL20006`~qxtimermsecroutine will notice and return it to the user. * If the drive is not ready, the interrupt routine resets * the state variaqptimeaqpL54L20013L56~qxheadqpL59ble so that we restart the sequence * on the next I/O request. */ if(sa_state < STREADY) sa_state++; switch(sa_state) { _bfreeli _bdevsw _nblkdev _cdevsw _nchrdev _u &_qx *_qxtab _qxunit _qxhd _qxstrat   if(++satab.d_errcnt < MAXTRIES) { sastart(); return; } bp->b_flags =| B_ERROR; } satab.d_errcnt = 0; satab.d_actf goto loop; } if (((*tccmp).hibyte&07) != bp->b_dev.d_minor) (*tccmp).lobyte = SAT|GO; tctab.d_errcnt = 20; tctab.d_active = bp->av_forw; iodone(bp); sastart(); } /* saread(dev) { physio(sastrategy, &rsabuf, dev, B_READ); } sawrite(dev) { physi= SFORW; com = (bp->b_dev.d_minor<<8) | IENABLE|RNUM|GO; if ((TCADDR->tccsr & UPS) == 0) { com =| TREV; tctab.d_active = S default: case STINIT: cp = &initcmd; break; case STCALIB: cp = &calibcmd; break; case STSEEK0: cp = &seek0cmd; break; o(sastrategy, &rsabuf, dev, B_WRITE); } */  case STREADY: /* do real i/o now */ saio.cmd = (bp->b_flags & B_READ) ? compl(SAREAD) : compl(SAWRITE); i = ldiv(bp->b# /* */ /* * TC-11 DECtape driver */ #include "../param.h" #include "../conf.h" #include "../buf.h" #include "../user.h" s_blkno, SASECSPERTRK); saio.sector = compl(lrem(bp->b_blkno, SASECSPERTRK)); saio.cylinder = compl(i / SATRKSPERCYL); /* truct { int tccsr; int tccm; int tcwc; int tcba; int tcdt; }; struct devtab tctab; char tcper[8]; #define TCADDR 0177340 set fixed head bit if cylinder 202 */ saio.head = compl(((i % SATRKSPERCYL) << 4) + (i >= SACYLINDERS*SATRKSPERCYL) ? SAFIX#define NTCBLK 578 #define TAPERR 0100000 #define TREV 04000 #define READY 0200 #define IENABLE 0100 #define UPS 0200 #define EED : 0); saio.secount = (255 + (-bp->b_wcount)) / 256; saio.nparams = 4; SADISK->saaddr_lo = bp->b_addr; cp = &saio; } NDZ 0100000 #define BLKM 02000 #define ILGOP 010000 #define SELERR 04000 #define SAT 0 #define RNUM 02 #define RDATA 04 #define SADISK->sacmd = cp->cmd & 0377; while(compl(SADISK->sastatus) & CMDFULL) ; for(i = 0; i < cp->nparams; i++) { while(compl( SST 010 #define WDATA 014 #define GO 01 #define SFORW 1 #define SREV 2 #define SIO 3 tcclose(dev) { bflush(dev); tcper[dev&SADISK->sastatus) & PARAMFULL) ; /* wait */ SADISK->saparam = cp->parm[i] & 0377; } } saintr() { register struct buf *bp; 07] = 0; } tcstrategy(abp) struct buf *abp; { register struct buf *bp; bp = abp; if(bp->b_blkno >= NTCBLK || tcper[bp->b_deregister int status; register int result; /* Note: the result register must be read after * receiving an interrupt, or tv&07]) { bp->b_flags =| B_ERROR; iodone(bp); return; } bp->av_forw = 0; spl6(); if (tctab.d_actf==0) tctab.d_actf = he controller will * interrupt forever. * The status register must be read before the result * if its value is wanted fbp; else tctab.d_actl->av_forw = bp; tctab.d_actl = bp; if (tctab.d_active==0) tcstart(); spl0(); } tcstart() { registor anything. */ result = compl(SADISK->saresult); if(satab.d_active == 0) return; bp = satab.d_actf; satab.d_active = 0; er struct buf *bp; register int *tccmp, com; loop: tccmp = &TCADDR->tccm; if ((bp = tctab.d_actf) == 0) return; if(tcper[ if((result&COMPLETION) != 0) { /* nonzero completion type => error */ if(result == UNREADY) { sa_state = STRESET; } elsebp->b_dev&07]) { if((tctab.d_actf = bp->av_forw) == 0) (*tccmp).lobyte = SAT|GO; bp->b_flags =| B_ERROR; iodone(bp); !  | (bp->b_flags&B_READ?RDATA:WDATA); tctab.d_active = SIO; return; case SREV: if (*tcdtp+3 > bp->b_blkno) goto se buf *abp; { register struct buf *bp; register char **p; bp = abp; p = &t_nxrec[bp->b_dev.d_minor]; if (*p <= bp->b_blkno)tback; goto setforw; } }  { if (*p < bp->b_blkno) { bp->b_flags =| B_ERROR; iodone(bp); return; } if (bp->b_flags&B_READ) { clrbuf(bp); iodone(bp); return; } } if ((bp->b_flags&B_READ)==0) *p = bp->b_blkno + 1; bp->av_forw = 0; spl5(); if (tmtab.d_actf==0) tmtab.d_actf = bp; else tmtab.d_actl->av_forw = bp; tmtab.d_actl = bp; if (tmtab.d_active==0) tmstart(); spl0# /* */ /* * TM tape driver */ #include "../param.h" #include "../buf.h" #include "../conf.h" #include "../user.h" struct (); } tmstart() { register struct buf *bp; register int com; int unit; register char *blkno; loop: if ((bp = tmtab.d_REV; } *tccmp = com; } tcintr() { register struct buf *bp; register int *tccmp; register int *tcdtp; tccmp = &TCADDR->tc{ int tmer; int tmcs; int tmbc; int tmba; int tmdb; int tmrd; }; struct devtab tmtab; char t_openf[8]; char *t_blkno[8]; cm; tcdtp = &TCADDR->tccsr; bp = tctab.d_actf; if (*tccmp&TAPERR) { if((*tcdtp&(ENDZ|BLKM)) == 0) if(*tcdtp & (ILGOP|SELEchar *t_nxrec[8]; #define TMADDR 0172520 #define GO 01 #define RCOM 02 #define WCOM 04 #define WEOF 06 #define SFORW 010 #defiRR)) { tcper[bp->b_dev&07]++; tctab.d_errcnt = 0; } *tccmp =& ~TAPERR; if (--tctab.d_errcnt <= 0) { bp->b_flags ne SREV 012 #define WIRG 014 #define REW 016 #define DENS 060000 /* 9-channel */ #define IENABLE 0100 #define CRDY 0200 #define=| B_ERROR; goto done; } if (*tccmp&TREV) { setforw: tctab.d_active = SFORW; *tccmp =& ~TREV; } else { setbac GAPSD 010000 #define TUR 1 #define HARD 0102200 /* ILC, EOT, NXM */ #define EOF 0040000 #define SSEEK 1 #define SIO 2 tmopen(k: tctab.d_active = SREV; *tccmp =| TREV; } (*tccmp).lobyte = IENABLE|RNUM|GO; return; } tcdtp = &TCADDR->tcdt; sdev, flag) { register dminor; dminor = dev.d_minor; if (t_openf[dminor]) u.u_error = ENXIO; else { t_openf[dminor]++; witch (tctab.d_active) { case SIO: done: tctab.d_active = 0; if (tctab.d_actf = bp->av_forw) tcstart(); else TCAD t_blkno[dminor] = 0; t_nxrec[dminor] = 65535; } } tmclose(dev, flag) { register int dminor; dminor = dev.d_minor; t_opeDR->tccm.lobyte = SAT|GO; iodone(bp); return; case SFORW: if (*tcdtp > bp->b_blkno) goto setback; if (*tcdtp < bp->nf[dminor] = 0; if (flag) tcommand(dminor, WEOF); tcommand(dminor, REW); } tcommand(unit, com) { extern lbolt; while (tmb_blkno) goto setforw; *--tcdtp = bp->b_addr; /* core address */ *--tcdtp = bp->b_wcount; tccmp->lobyte = IENABLE|GO tab.d_active || (TMADDR->tmcs & CRDY)==0) sleep(&lbolt, 1); TMADDR->tmcs = DENS|com|GO | (unit<<8); } tmstrategy(abp) struct" ddr; /* core address */ TMADDR->tmcs = com | ((bp->b_flags&B_READ)? RCOM|GO: ((tmtab.d_errcnt)? WIRG|GO: WCOM|GO)); } tmq) >= 0); } vswrite(dev) { register int count, c; count = 0; while ((c=cpass()) >= 0) { if (--count <= 0) { count = 60intr() { register struct buf *bp; register int unit; if ((bp = tmtab.d_actf)==0) return; unit = bp->b_dev.d_minor; if (T; vschar(0); } vschar(c); } vschar(0); } vschar(c) { c =^ MAGIC_MAP; spl5(); while (vs.oq.c_cc > 60) { vsxintr()MADDR->tmcs < 0) { /* error bit */ while(TMADDR->tmrd & GAPSD) ; /* wait for gap shutdown */ if ((TMADDR->tmer&(HARD|EOF))=; sleep(&vs.oq, TTIPRI); } putc(c, &vs.oq); vsxintr(); spl0(); } vsxintr() { static lchar; register c; register int *x=0 && tmtab.d_active==SIO) { if (++tmtab.d_errcnt < 10) { t_blkno[unit]++; tmtab.d_active = 0; tmstart(); retcsr; xcsr = &VSADDR->vsxcsr; if (*xcsr&DONE) { if (lchar==MAGIC_MAP) { *xcsr =& ~RQSEND; lchar = 0; if (vs.oq.c_ccurn; } } else if((TMADDR->tmer&EOF)==0) t_openf[unit] = -1; bp->b_flags =| B_ERROR; tmtab.d_active = SIO; } if==0) goto wake; } if ((*xcsr&CLSEND) == 0) { *xcsr =& ~RQSEND; *xcsr =| RQSEND; if ((*xcsr&CLSEND) == 0) go (tmtab.d_active == SIO) { tmtab.d_errcnt = 0; t_blkno[unit]++; tmtab.d_actf = bp->av_forw; tmtab.d_active = 0; iodoneto wake; } if ((c = getc(&vs.oq)) >= 0) VSADDR->vsxbuf = lchar = c; if (vs.oq.c_cc <= 15) wake: wakeup(&vs.oq);(bp); bp->b_resid = TMADDR->tmbc; } else t_blkno[unit] = bp->b_blkno; tmstart(); }  } } vsread(dev) { register int c; spl5(); while ((c = getc(&vs.iq)) < 0) sleep(&vs.iq, TTIPRI); spl0(); passc("?0*#?546?213?879?"[c&017]); } vsrintr() { register int c; c = VSADDR->vsrbuf; if (vs.iq.c_cc<=10) putc(c, &vs.iq); wakeup(&vs.actf) == 0) return; unit = bp->b_dev.d_minor; blkno = t_blkno[unit]; if (t_openf[unit] < 0 || (TMADDR->tmcs & CRDY)==0) {  bp->b_flags =| B_ERROR; tmtab.d_actf = bp->av_forw; iodone(bp); goto loop; } com = (unit<<8) | IENABLE |DENS; if (blkn# /* */ /* * Screw Works interface via DC-11 */ #include "../tty.h" #define VSADDR 0174150 #define CDLEAD 01 #define B1200o != bp->b_blkno) { tmtab.d_active = SSEEK; if (blkno < bp->b_blkno) { com =| SFORW|GO; TMADDR->tmbc = blkno - bp->b_b 030 #define STOP1 0400 #define CLSEND 02 #define RQSEND 01 #define MAGIC_MAP 0377 struct { int vsrcsr; int vsrbuf; int vsxlkno; } else { if (bp->b_blkno == 0) com =| REW|GO; else { com =| SREV|GO; TMADDR->tmbc = bp->b_blkno - blkncsr; int vsxbuf; }; struct { struct clist iq; struct clist oq; } vs; vsopen(dev) { VSADDR->vsrcsr = IENABLE|B1200|CDLEAD; o; } } TMADDR->tmcs = com; return; } tmtab.d_active = SIO; TMADDR->tmbc = bp->b_wcount << 1; TMADDR->tmba = bp->b_a VSADDR->vsxcsr = STOP1|IENABLE|B1200; vschar(0); } vsclose(dev) { vschar(0); VSADDR->vsrcsr =& ~IENABLE; while (getc(&vs.i# # /* */ /* * VT01 driver via DR11C to 11/20 */ #include "../param.h" #include "../user.h" int vtflag; struct vtreg { int csr; int buf; }; #define VTADDR 0167770 #define RQINT 01 #define BIENABL 040 #define SEOF 0100000 #define VTPRI 8 vtopen(dev, flag) { if (!flag) u.u_error = ENXIO; else VTADDR->csr = BIENABL; } vtclose() { VTADDR->buf = SEOF; VTADDR->csr =| RQINT; } vtwrite() { register int c; int register count; while ((c=cpass()) >= 0) { retry: for (count=0; count<10; count++) if ((VTADDR->csr&RQINT)==0) { VTADDR->buf = c&0377; VTADDR->csr =| RQINT; goto contin; } spl5(); if (VTADDR->csr&RQINT) { vtflag++; sleep(VTADDR, VTPRI); } spl0(); goto retry; contin:; } } vtintr() { VTADDR->csr =& ~RQINT; if (vtflag) { vtflag = 0; wakeup(VTADDR); } } iq); } $ % & ' ( ) * + , - . d~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('/ 0 1 2 3 4 5 [ISDbin5en& tn____ _(Y6 7 8 9 VVVn____- -,  ĥ e BtU2ĥ$8 tĥ0+ĥ9(e- m7 ğ ċ7 ~# S_(Y 2ĥ\ &ĥ  w ĥ$vREw X d%\ ` R N B w4 %4 6 fe& q%% .q   @w eu-Vt@& m Nf nd w w 5 DD-Br7R y e r 5 bf $e 33 %&UaN&e .d 3  Nf $e w w  DD-0r7  y e   bf e 2N&e(Y?YY$94YY(Y(Y_8(YY (YpN_9b9(YI(YZ_;(YIt_.Yx_ * HYU_T=@ |_| $e 22 w Nf e w j 5 @ȥ)U5 5 5 5 5 5 DD-_f5s7  y HYU_*?UHY|I___|} 0 AII_!IIIVAII_'A4v_24\A4v_3'z4vzߴߪzz(o  e5 e 5eD->U eD-Zt& m %< & 6  .qw  p % n% p 7 & Br%7e04v Bss 5 ~5 @ @m ! P bNf nd 3sss 75sts~%47 ^--c%Pt> p  q w @ @m Ne b5 u-@ `A Amp w Be  &  w w  tms Dm- do  do e7@ 7  tm h7 w zvz4v ^tf m @w~ w l @Ewn w \  A@ : xs@ bt n ht n .@z77| R˥ ztH{ppl  bPz .d Ls Dm gw:w ( e   n kt Dm% t tm   e wt n tt n t n   r erA! y  Ġ(ĥ 7wU? ?  7t& m ? 7 N tt n  x   pNe t n tt n  @ N  pNe t n tu n  [IEDbindbin& m ?| xw xv@ 7`l-jft tm` wZw HJĝD7@`. ĥ e4t Dm: fr tm5u tm u Dm5!N nwl nw Rw\w JwTfwuwT f@)w>fwannot execute wait:try again : cannot open: cannot create/dev/null/etc/globglob: cannot execute /usr/bin/: not foundw < ouwfw7 fw w w w  wfAW @wH fT{/bin/shNo shell! : too large : -- Core dumped 7v 0+(v  %ew &n u n @55 5 5%u_h %5 N p@ p5@N m u1T{7< 5 eow(u 5& wx& L& H& D& @&z <&t 8&n 4&h 0& tm5_BhNf@  p @& q 5 @ tm"u Dm V@ =5@& q 5b ,&\ (&V $&P &J &D &> &8 &2 &, && & f& f$f & f q%@& p 5 @ tm0u Dm  pN nN p5 pN nN p@ BRfw,ufwuw| f |& wb }f@wF fww p5 p@ nN p@ p5 @  5  p @u q 5 4   do  uw&@& HADCBFf@ffA w,w"|e"w"rew"h@lw"` do %@@E4P g   p7 ~gf Xg @JuNe@& n Tu tm AlewS &@t`e fw0w,uwlf@wwuwJf@wwgf Xg ?| N@& l f ju @ NF e l N4 l @ tmtu Dm 8@5uw( f@wwuw7 F6rw* 6r@s%s,s1sEsTs]sfsyssss\ p  p J q 58 q 5* p@@EU4PNef& g%@@EU4Pssssssrrrr$  ) pbabFbpbFbbFbFbFbpbaFbFbFbFb &(); dddddd()^|lHePeTeTeNfe& g%_Bh@E5@t] g@t] g_Bhw 8De f n %T  Je()<>le"fLf.ffgikl.__pf0HangupQuitIllegal instructionTrace/BPT trapIOT trapEMT trapFloating exceptionKilled ue& n u tm %   tmu Dm ww N tmu tm  & & q% ww DBus errorMemory faultBad system callSig 14Sig 15Sig 16Sig 17Sig 18Sig 19/usr/adm/sha% # /usr/adm/shb: cannot opens m̋ww fe r%wvw d f& Br% m f& Tr%e0 mw:w (D̋@-wyntax error '" ;&<>()|^ "'Command line overflow Too many argsToo many characters;& <>([?*chdircdchdir: bad directory w DCԢӋw w  ?(v p(v |pNe p%.CE frD- mu tm /usrchdir: "/usr" bad directoryshiftshift: no args synclogin/bin/loginlogin: cannot execute newgrp/bin/newgrpnewgrp: c; 4v 75sts~%47 ^--c%Pt> p  q z4v tms Dm- do  do e7@ 7  tm h7 w zvz4v߶az77| R˥ ztH{ppl  bPz .d Ls Dm gw:w ( e Lnߪ߀z4vz6iuzz7vz߼lzddz߀z7vazsfas`- r erA! y  Ġ(ĥ 7wU? ?  7t& m ? 7 N t[IEDbin4vdbin& m ?| xw xv@ 7`l-jft tm` wZw HJĝD7@`. ĥ e4t Dm00001s9vz zvzzH{l ls VVV4vn____#?S_(Y(Y?YY$94YY(Y(Y_8(YY (YpN_9b9(YI(YZ_;(YIt_.Yx_ * HYU|HYU_ |HYU_J?U|I___|} < AI \II_I4v_'I("A4v_24\"A4v_3&z4vzߴLnp & 6  .qw  p % n% p 7 & Br%7e04v Bss<  $e 22 w Nf e w j 5 @ȥ)U5 5 5 5 5 5 DD-_f5s7  y \ p  p J q 58 q 5* p@@EU4PNef& g%@@EU4P  e5 e 5eD->U eD-Zt& m %<Nfe& g%_Bh@E5@t] g@t] g_Bhw 8De f n %T   5 ~5 @ @m ! P bNf nd 3sss ue& n u tm %   tmu Dm ww N tmu tm  & & q% ww Dw @ @m Ne b5 u-@ `A Amp w Be  &  w w  m̋ww fe r%wvw d f& Br% m f& Tr%e0 mw:w (D̋@-w ^tf m @w~ w l @Ewn w \  A@ : xs@ bt n ht n .@ w DCԢӋw w  ?(v p(v |pNe p%.CE frD- mu tm   n kt Dm% t tm   e wt n tt n t n  fr tm5u tm u Dm5!N nwl nw Rw\w JwTfwuwT f@)w>fwt n  x   pNe t n tt n  @ N  pNe t n tu n  w < ouwfw7 fw w w w  wfAW @wH fT{ &n u n @55 5 5%u_h %5 N p@ p5@N m u1T{7< 5 eow(u 5& wx& L& H& D& @&z <&t 8&n 4&h 0&- -,  ĥ e BtU2ĥ$8 tĥ0+ĥ9(e- m7 ğ ċ7 ~ tm5_BhNf@  p @& q 5 @ tm"u Dm V@ =5@& q 5 2ĥ\ &ĥ  w ĥ$vREw X d%\ ` R N B w4 %4 6 fe & f q%@& p 5 @ tm0u Dm  pN nN p5 pN nN p@& q%% .q   @w eu-Vt@& m Nf nd w w 5 DD- p5 p@ nN p@ p5 @  5  p @u q 5 4   do  Br7R y e r 5 bf $e 33 %&UaN&e .d 3 do %@@E4P g   p7 ~gf Xg @JuNe@& n Tu tm   Nf $e w w  DD-0r7  y e   bf e 2N&egf Xg ?| N@& l f ju @ NF e l N4 l @ tmtu Dm 8@5= uw&@& HADCBFf@ffA w,w"|e"w"rew"h@lw"`AlewS &@t`e fw0w,uwlf@wwuwJf@wwuw( f@wwuw7 F6rw* 6r@s%s,s1sEsTs]sfsyssssssssssrrrr$  ) pbabFbpbFbbFbFbFbpbaFbFbFbFb &(); dddddd()^|lHePeTeTeJe()<>le"fLf.ffgikl.__pf0HangupQuitIllegal instructionTrace/BPT trapIOT trapEMT trapFloating exceptionKilledBus errorMemory faultBad system callSig 14Sig 15Sig 16Sig 17Sig 18Sig 19/usr/adm/sha% # /usr/adm/shb: cannot opens4vyntax error '" ;&<>()|^ "'Command line overflow Too many argsToo many characters;& <>([?*chdircdchdir: bad directoryz4v/usrchdir: "/usr" bad directoryshiftshift: no args synclogin/bin/loginlogin: cannot execute newgrp/bin/newgrpnewgrp: c߶aannot execute wait:try again : cannot open: cannot create/dev/null/etc/globglob: cannot execute /usr/bin/: not foundLnߪ߀z4vzizzz7vz߼lzddz߀z7vazsfas`-/bin/shNo shell! : too large : -- Core dumped 7v 0+(v  %ew00001s9vz zvzzH{lls b ,&\ (&V $&P &J &D &> &8 &2 &, && & f& f$f BRfw,ufwuw| f |& wb }f@wF fww> ? @ A B C D E F G H I J K L