?dmr/bio.c2l ßdmr/cat.c{k 3udmr/dc.ck 5dmr/rm.c&%&fdmr/dhdm.ck I"/dmr/dhfdm.ck Lqdmr/dj11.cZ VMdmr/dl.c ( >R8dmr/mg.doc >Admr/rm.doc^C#dmr/dr.c bcdmr/vlp.ct+ fdmr/calcomp.doc {dmr/dr.doc$"dmr/kl.c ohdmr/lp.c"Sdmr/mem.cl ۆdmr/partab.ck qdmr/pc.cl Pۋdmr/rf.cl _ې¨dmr/rk.cx tjdmr/rp.c* l ۗdmr/sys.ck odmr/tc.c l ۟dmr/tm.ck ?dmr/tty.c." ^dmr/vs.ck dmr/vt.cBk Hdmr/vlp.docAjBconf/c.c :conf/data.sFk ,g,conf/l.s X!conf/m40.sg* ȼconf/m45.s(l dmr/xx.cB1 x_calcomp.doc conf/sysfix.cS l !dr.docH1dmr/mg.c3%o4!Odmr/omg.c7"(qB dmr/mgtty.c 1w&mg.doc rm.doc^vlp.docA# /* */ #include "../param.h" #include "../user.h" #include "../buf.h" #include "../conf.h" #include "../systm.h" #include "../proc.h" #include "../seg.h" /* * This is the set of buffers proper, whose heads * were declared in buf.h. There can exist buffer * headers not pointing here that are used purely * as arguments to the I/O routines to describe * I/O to be done-- e.g. swbuf, just below, for * swapping. */ char buffers[NBUF][514]; struct buf swbuf; /* * Declarations of the tables for the magtape devices; * see bdwrite. */ int tmtab; int httab; /* * The following several routines allocate and free * buffers with various side effects. In general the * arguments to an allocate routine are a device and * a block number, and the value is a pointer to * to the buffer header; the buffer is marked "busy" * so that no on else can touch it. If the block was * already in core, no I/O need be done; if it is * already busy, the process waits until it becomes free. * The following routines allocate a buffer: * getblk * bread * breada * Eventually the buffer must be released, possibly with the * side effect of writing it out, by using one of * bwrite * bdwrite * bawrite * brelse */ /* * Read in (if necessary) the block and return a buffer pointer. */ bread(dev, blkno) { register struct buf *rbp; rbp = getblk(dev, blkno); if (rbp->b_flags&B_DONE) return(rbp); rbp->b_flags =| B_READ; rbp->b_wcount = -256; (*bdevsw[dev.d_major].d_strategy)(rbp); iowait(rbp); return(rbp); } /* * Read in the block, like bread, but also start I/O on the * read-ahead block (which is not allocated to the caller) */ breada(adev, blkno, rablkno) { register struct buf *rbp, *rabp; register int dev; dev = adev; rbp = 0; if (!incore(dev, blkno)) { rbp = getblk(dev, blkno); if ((rbp->b_flags&B_DONE) == 0) { rbp->b_flags =| B_READ; rbp->b_wcount = -256; (*bdevsw[adev.d_major].d_strategy)(rbp); } } if (rablkno && !incore(dev, rablkno)) { rabp = getblk(dev, rablkno); if (rabp->b_flags & B_DONE) brelse(rabp); else { rabp->b_flags =| B_READ|B_ASYNC; rabp->b_wcount = -256; (*bdevsw[adev.d_major].d_strategy)(rabp); } } if (rbp==0) return(bread(dev, blkno)); iowait(rbp); return(rbp); } /* * Write the buffer, waiting for completion. * Then release the buffer. */ bwrite(bp) struct buf *bp; { register struct buf *rbp; register flag; rbp = bp; flag = rbp->b_flags; rbp->b_flags =& ~(B_READ | B_DONE | B_ERROR | B_DELWRI); rbp->b_wcount = -256; (*bdevsw[rbp->b_dev.d_major].d_strategy)(rbp); if ((flag&B_ASYNC) == 0) { iowait(rbp); brelse(rbp); } else if ((flag&B_DELWRI)==0) geterror(rbp); } /* * Release the buffer, marking it so that if it is grabbed * for another purpose it will be written out before being * given up (e.g. when writing a partial block where it is * assumed that another write for the same block will soon follow). * This can't be done for magtape, since writes must be done * in the same order as requested. */ bdwrite(bp) struct buf *bp; { register struct buf *rbp; register struct devtab *dp; rbp = bp; dp = bdevsw[rbp->b_dev.d_major].d_tab; if (dp == &tmtab || dp == &httab) bawrite(rbp); else { rbp->b_flags =| B_DELWRI | B_DONE; brelse(rbp); } } /* * Release the buffer, start I/O on it, but don't wait for completion. */ bawrite(bp) struct buf *bp; { register struct buf *rbp; rbp = bp; rbp->b_flags =| B_ASYNC; bwrite(rbp); } /* * release the buffer, with no I/O implied. */ brelse(bp) struct buf *bp; { register struct buf *rbp, **backp; register int sps; rbp = bp; if (rbp->b_flags&B_WANTED) wakeup(rbp); if (bfreelist.b_flags&B_WANTED) { bfreelist.b_flags =& ~B_WANTED; wakeup(&bfreelist); } if (rbp->b_flags&B_ERROR) rbp->b_dev.d_minor = -1; /* no assoc. on error */ backp = &bfreelist.av_back; sps = PS->integ; spl6(); rbp->b_flags =& ~(B_WANTED|B_BUSY|B_ASYNC); (*backp)->av_forw = rbp; rbp->av_back = *backp; *backp = rbp; rbp->av_forw = &bfreelist; PS->integ = sps; } /* * See if the block is associated with some buffer * (mainly to avoid getting hung up on a wait in breada) */ incore(adev, blkno) { register int dev; register struct buf *bp; register struct devtab *dp; dev = adev; dp = bdevsw[adev.d_major].d_tab; for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) if (bp->b_blkno==blkno && bp->b_dev==dev) return(bp); return(0); } /* * Assign a buffer for the given block. If the appropriate * block is already associated, return it; otherwise search * for the oldest non-busy buffer and reassign it. * When a 512-byte area is wanted for some random reason * (e.g. during exec, for the user arglist) getblk can be called * with device NODEV to avoid unwanted associativity. */ getblk(dev, blkno) { register struct buf *bp; register struct devtab *dp; extern lbolt; if(dev.d_major >= nblkdev) panic("blkdev"); loop: if (dev < 0) dp = &bfreelist; else { dp = bdevsw[dev.d_major].d_tab; if(dp == NULL) panic("devtab"); for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) { if (bp->b_blkno!=blkno || bp->b_dev!=dev) continue; spl6(); if (bp->b_flags&B_BUSY) { bp->b_flags =| B_WANTED; sleep(bp, PRIBIO); spl0(); goto loop; } spl0(); notavail(bp); return(bp); } } spl6(); if (bfreelist.av_forw == &bfreelist) { bfreelist.b_flags =| B_WANTED; sleep(&bfreelist, PRIBIO); spl0(); goto loop; } spl0(); notavail(bp = bfreelist.av_forw); if (bp->b_flags & B_DELWRI) { bp->b_flags =| B_ASYNC; bwrite(bp); goto loop; } bp->b_flags = B_BUSY | B_RELOC; bp->b_back->b_forw = bp->b_forw; bp->b_forw->b_back = bp->b_back; bp->b_forw = dp->b_forw; bp->b_back = dp; dp->b_forw->b_back = bp; dp->b_forw = bp; bp->b_dev = dev; bp->b_blkno = blkno; return(bp); } /* * Wait for I/O completion on the buffer; return errors * to the user. */ iowait(bp) struct buf *bp; { register struct buf *rbp; rbp = bp; spl6(); while ((rbp->b_flags&B_DONE)==0) sleep(rbp, PRIBIO); spl0(); geterror(rbp); } /* * Unlink a buffer from the available list and mark it busy. * (internal interface) */ notavail(bp) struct buf *bp; { register struct buf *rbp; register int sps; rbp = bp; sps = PS->integ; spl6(); rbp->av_back->av_forw = rbp->av_forw; rbp->av_forw->av_back = rbp->av_back; rbp->b_flags =| B_BUSY; PS->integ = sps; } /* * Mark I/O complete on a buffer, release it if I/O is asynchronous, * and wake up anyone waiting for it. */ iodone(bp) struct buf *bp; { register struct buf *rbp; rbp = bp; if(rbp->b_flags&B_MAP) mapfree(rbp); rbp->b_flags =| B_DONE; if (rbp->b_flags&B_ASYNC) brelse(rbp); else { rbp->b_flags =& ~B_WANTED; wakeup(rbp); } } /* * Zero the core associated with a buffer. */ clrbuf(bp) int *bp; { register *p; register c; p = bp->b_addr; c = 256; do *p++ = 0; while (--c); } /* * Initialize the buffer I/O system by freeing * all buffers and setting all device buffer lists to empty. */ binit() { register struct buf *bp; register struct devtab *dp; register int i; struct bdevsw *bdp; bfreelist.b_forw = bfreelist.b_back = bfreelist.av_forw = bfreelist.av_back = &bfreelist; for (i=0; ib_dev = -1; bp->b_addr = buffers[i]; bp->b_back = &bfreelist; bp->b_forw = bfreelist.b_forw; bfreelist.b_forw->b_back = bp; bfreelist.b_forw = bp; bp->b_flags = B_BUSY; brelse(bp); } i = 0; for (bdp = bdevsw; bdp->d_open; bdp++) { dp = bdp->d_tab; if(dp) { dp->b_forw = dp; dp->b_back = dp; } i++; } nblkdev = i; } /* * Device start routine for disks * and other devices that have the register * layout of the older DEC controllers (RF, RK, RP, TM) */ #define IENABLE 0100 #define WCOM 02 #define RCOM 04 #define GO 01 devstart(bp, devloc, devblk, hbcom) struct buf *bp; int *devloc; { register int *dp; register struct buf *rbp; register int com; dp = devloc; rbp = bp; *dp = devblk; /* block address */ *--dp = rbp->b_addr; /* buffer address */ *--dp = rbp->b_wcount; /* word count */ com = (hbcom<<8) | IENABLE | GO | ((rbp->b_xmem & 03) << 4); if (rbp->b_flags&B_READ) /* command + x-mem */ com =| RCOM; else com =| WCOM; *--dp = com; } /* * startup routine for RH controllers. */ #define RHWCOM 060 #define RHRCOM 070 rhstart(bp, devloc, devblk, abae) struct buf *bp; int *devloc, *abae; { register int *dp; register struct buf *rbp; register int com; dp = devloc; rbp = bp; if(cputype == 70) *abae = rbp->b_xmem; *dp = devblk; /* block address */ *--dp = rbp->b_addr; /* buffer address */ *--dp = rbp->b_wcount; /* word count */ com = IENABLE | GO | ((rbp->b_xmem & 03) << 8); if (rbp->b_flags&B_READ) /* command + x-mem */ com =| RHRCOM; else com =| RHWCOM; *--dp = com; } /* * 11/70 routine to allocate the * UNIBUS map and initialize for * a unibus device. * The code here and in * rhstart assumes that an rh on an 11/70 * is an rh70 and contains 22 bit addressing. */ int maplock; mapalloc(abp) struct buf *abp; { register i, a; register struct buf *bp; if(cputype != 70) return; spl6(); while(maplock&B_BUSY) { maplock =| B_WANTED; sleep(&maplock, PSWP); } maplock =| B_BUSY; spl0(); bp = abp; bp->b_flags =| B_MAP; a = bp->b_xmem; for(i=16; i<32; i=+2) UBMAP->r[i+1] = a; for(a++; i<48; i=+2) UBMAP->r[i+1] = a; bp->b_xmem = 1; } mapfree(bp) struct buf *bp; { bp->b_flags =& ~B_MAP; if(maplock&B_WANTED) wakeup(&maplock); maplock = 0; } /* * swap I/O */ swap(blkno, coreaddr, count, rdflg) { register int *fp; fp = &swbuf.b_flags; spl6(); while (*fp&B_BUSY) { *fp =| B_WANTED; sleep(fp, PSWP); } *fp = B_BUSY | B_PHYS | rdflg; swbuf.b_dev = swapdev; swbuf.b_wcount = - (count<<5); /* 32 w/block */ swbuf.b_blkno = blkno; swbuf.b_addr = coreaddr<<6; /* 64 b/block */ swbuf.b_xmem = (coreaddr>>10) & 077; (*bdevsw[swapdev>>8].d_strategy)(&swbuf); spl6(); while((*fp&B_DONE)==0) sleep(fp, PSWP); if (*fp&B_WANTED) wakeup(fp); spl0(); *fp =& ~(B_BUSY|B_WANTED); return(*fp&B_ERROR); } /* * make sure all write-behind blocks * on dev (or NODEV for all) * are flushed out. * (from umount and update) */ bflush(dev) { register struct buf *bp; loop: spl6(); for (bp = bfreelist.av_forw; bp != &bfreelist; bp = bp->av_forw) { if (bp->b_flags&B_DELWRI && (dev == NODEV||dev==bp->b_dev)) { bp->b_flags =| B_ASYNC; notavail(bp); bwrite(bp); goto loop; } } spl0(); } /* * Raw I/O. The arguments are * The strategy routine for the device * A buffer, which will always be a special buffer * header owned exclusively by the device for this purpose * The device number * Read/write flag * Essentially all the work is computing physical addresses and * validating them. */ physio(strat, abp, dev, rw) struct buf *abp; int (*strat)(); { register struct buf *bp; register char *base; register int nb; int ts; bp = abp; base = u.u_base; /* * Check odd base, odd count, and address wraparound */ if (base&01 || u.u_count&01 || base>=base+u.u_count) goto bad; ts = (u.u_tsize+127) & ~0177; if (u.u_sep) ts = 0; nb = (base>>6) & 01777; /* * Check overlap with text. (ts and nb now * in 64-byte clicks) */ if (nb < ts) goto bad; /* * Check that transfer is either entirely in the * data or in the stack: that is, either * the end is in the data or the start is in the stack * (remember wraparound was already checked). */ if ((((base+u.u_count)>>6)&01777) >= ts+u.u_dsize && nb < 1024-u.u_ssize) goto bad; spl6(); while (bp->b_flags&B_BUSY) { bp->b_flags =| B_WANTED; sleep(bp, PRIBIO); } bp->b_flags = B_BUSY | B_PHYS | rw; bp->b_dev = dev; /* * Compute physical address by simulating * the segmentation hardware. */ bp->b_addr = base&077; base = (u.u_sep? UDSA: UISA)->r[nb>>7] + (nb&0177); bp->b_addr =+ base<<6; bp->b_xmem = (base>>10) & 077; bp->b_blkno = lshift(u.u_offset, -9); bp->b_wcount = -((u.u_count>>1) & 077777); bp->b_error = 0; u.u_procp->p_flag =| SLOCK; (*strat)(bp); spl6(); while ((bp->b_flags&B_DONE) == 0) sleep(bp, PRIBIO); u.u_procp->p_flag =& ~SLOCK; if (bp->b_flags&B_WANTED) wakeup(bp); spl0(); bp->b_flags =& ~(B_BUSY|B_WANTED); u.u_count = (-bp->b_resid)<<1; geterror(bp); return; bad: u.u_error = EFAULT; } /* * Pick up the device's error number and pass it to the user; * if there is an error but the number is 0 set a generalized * code. Actually the latter is always true because devices * don't yet return specific errors. */ geterror(abp) struct buf *abp; { register struct buf *bp; bp = abp; if (bp->b_flags&B_ERROR) if ((u.u_error = bp->b_error)==0) u.u_error = EIO; } ); bp->b_flags =& ~(B_BUSY|B_WANTED); u.u_count = (-bp->b_resid)<<1; geterror(bp); return; bad: u.u_error = EFAULT; } /* * Pick up the device's error number and pass it to the user; * if there is an error but the number is 0 set a generalized * code. Actually the latter is always true because devices * don't yet return specific errors. */ geterror(abp) struct buf *abp; { register struct buf *bp; bp = abp; if (bp->b_flags&B_ERROR) if ((u.u_error = bp->b_error)==0) u.u_# /* */ /* * GP DR11C driver used for C/A/T */ #include "../param.h" #include "../user.h" #include "../tty.h" #define CATADDR 0167750 #define PCAT 9 #define CATHIWAT 60 #define CATLOWAT 15 struct { int catlock; struct clist oq; } cat; struct { int catcsr; int catbuf; }; ctopen(dev) { if (cat.catlock==0) { cat.catlock++; CATADDR->catcsr =| IENABLE; } else u.u_error = ENXIO; } ctclose() { cat.catlock = 0; } ctwrite(dev) { register c; extern lbolt; while ((c=cpass()) >= 0) { spl5(); while (cat.oq.c_cc > CATHIWAT) sleep(&cat.oq, PCAT); while (putc(c, &cat.oq) < 0) sleep(&lbolt, PCAT); catintr(); spl0(); } } catintr() { register int c; if (CATADDR->catcsr&DONE && (c=getc(&cat.oq))>=0) { CATADDR->catbuf = c; if (cat.oq.c_cc==0 || cat.oq.c_cc==CATLOWAT) wakeup(&cat.oq); } else { if (cat.catlock==0) CATADDR->catcsr = 0; } } .u_error = ENXIO; } ctclose() { cat.catlock = 0; } ctwrite(dev) { register c; extern lbolt; while ((c=cpass()) >= 0) { spl5(# /* */ /* * DC-11 driver */ #include "../param.h" #include "../conf.h" #include "../user.h" #include "../tty.h" #include "../proc.h" /* * Base address of DC-11's. Minor device i is at * DCADDR + 10*i. */ #define DCADDR 0174000 /* * Number of DC's for which table space is allocated. */ #define NDC11 14 /* * Control bits in device registers */ #define CDLEAD 01 #define CARRIER 04 #define SPEED1 010 #define STOP1 0400 #define RQSEND 01 #define PARITY 040 #define ERROR 0100000 #define CTRANS 040000 #define RINGIND 020000 struct tty dc11[NDC11]; struct dcregs { int dcrcsr; int dcrbuf; int dctcsr; int dctbuf; }; /* * Input-side speed and control bit table. * Each DC11 has 4 speeds which correspond to the 4 non-zero entries. * The table index is the same as the speed-selector * number for the DH11. * Attempts to set the speed to a zero entry are ignored. */ int dcrstab[] { 0, /* 0 baud */ 0, /* 50 baud */ 0, /* 75 baud */ 0, /* 110 baud */ 01101, /* 134.5 baud: 7b/ch, speed 0 */ 0111, /* 150 baud: 8b/ch, speed 1 */ 0, /* 200 baud */ 0121, /* 300 baud: 8b/ch, speed 2 */ 0, /* 600 baud */ 0131, /* 1200 baud */ 0, /* 1800 baud */ 0, /* 2400 baud */ 0, /* 4800 baud */ 0, /* 9600 baud */ 0, /* X0 */ 0, /* X1 */ }; /* * Transmitter speed table */ int dctstab[] { 0, /* 0 baud */ 0, /* 50 baud */ 0, /* 75 baud */ 0, /* 110 baud */ 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, /* X1 */ }; /* * Open a DC11, waiting until carrier is established. * Default initial conditions are set up on the first open. * t_state's CARR_ON bit is a pure copy of the hardware * CARRIER bit, and is only used to regularize * carrier tests in general tty routines. */ dcopen(dev, flag) { register struct tty *rtp; register *addr; if (dev.d_minor >= NDC11) { u.u_error = ENXIO; return; } rtp = &dc11[dev.d_minor]; rtp->t_addr = addr = DCADDR + dev.d_minor*8; rtp->t_state =| WOPEN; addr->dcrcsr =| IENABLE|CDLEAD; if ((rtp->t_state&ISOPEN) == 0) { rtp->t_erase = CERASE; rtp->t_kill = CKILL; addr->dcrcsr = IENABLE|CDLEAD|SPEED1; addr->dctcsr = IENABLE|SPEED1|STOP1|RQSEND; rtp->t_state = ISOPEN | WOPEN; rtp->t_flags = ODDP|EVENP|ECHO; } if (addr->dcrcsr & CARRIER) rtp->t_state =| CARR_ON; while ((rtp->t_state & CARR_ON) == 0) sleep(&rtp->t_rawq, TTIPRI); rtp->t_state =& ~WOPEN; if (u.u_procp->p_ttyp == 0) { u.u_procp->p_ttyp = rtp; rtp->t_dev = dev; } } /* * 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 == TTLOWAT) wakeup(&tp->t_outq); } /* * DC11 receiver interrupt. */ dcrint(dev) { register struct tty *tp; register int c, csr; 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 ((tp->t_state&WOPEN) == 0) { tp->t_addr->dcrcsr =& ~CDLEAD; if (tp->t_state & CARR_ON) signal(tp, SIGHUP); flushtty(tp); } tp->t_state =& ~CARR_ON; return; } if (csr&ERROR || (tp->t_state&ISOPEN)==0) { if (tp->t_state&WOPEN && csr&CARRIER) tp->t_state =| CARR_ON; wakeup(tp); return; } csr =& PARITY; if (csr&&(tp->t_flags&ODDP) || !csr&&(tp->t_flags&EVENP)) ttyinput(c, tp); } /* * DC11 stty/gtty. * Perform general functions and set speeds. */ dcsgtty(dev, av) int *av; { register struct tty *tp; register r; tp = &dc11[dev.d_minor]; if (ttystty(tp, av)) return; if (r = dcrstab[tp->t_speeds.lobyte&017]) tp->t_addr->dcrcsr = r; else tp->t_addr->dcrcsr =& ~CDLEAD; if (r = dctstab[tp->t_speeds.hibyte&017]) tp->t_addr->dctcsr = r; } =| CARR_ON; wakeup(tp); return; } csr =& PARITY; if (csr&&(tp->t_flags&ODDP) || !csr&&(tp->t_flags&EVENP)) ttyinput(c, tp); } /* * DC11 stty/gtty. * Perform general functions and set speeds. */ dcsgtty(dev, av) int *av; { register struct tty *tp; register r; tp.th mg IV .sh NAME .nf mg Megatek 7000 Display mgpio Programmed IO mgper Peripherals ttym Megatekttyroutines .fi .sh DESCRIPTION The Megatek 7000 is a microprocessor-controlled refresh display with 16K (standard) 32-bit memory. The UNIX driver has four minor devices: dma to/from memory, programmed io to/from memory, peripherals (keyboard, joystick, tablet) and a tty simulator. .sh "DMA and PIO Minor Devices:" All i/o with the megatek memory requires a special data buffer structure: .nf struct megbuf { int megaddr; /* megatek memory address */ int data[2 * #megwords]; } megbuf; which corresponds to write(megfd, &megbuf, sizeof megbuf); -or- read(megfd, &megbuf, 2 * #megwords); .fi Note that megaddr must be set before the call, the buffer must be word-aligned, and the byte count must be a multiple of four. When writing, the byte count includes megaddr. When reading, however, the read byte count does not, and the first returned data word overwrites megaddr. (ugly...) .sh "Peripheral Minor Device:" The peripherals are read separately from memory, and /dev/mgper must be opened after /dev/mg. All peripherals generate interrupts on input (keyboard,joystick,tablet). The data is stored in a FIFO buffer in the driver. A read on /dev/mgper returns the data appropriately flagged as per megatek documentation, or 0 (zero) for empty buffer. Gtty can also be used to read peripheral buffer into the first vector word. Gtty, however, will sleep until the buffer is not empty, thus guaranteeing input. Writes to /dev/mgper are illegal. Use /dev/mg to interact with the peripheral control words in memory. .sh "TTY Minor Device:" The megatek can also be used as a standard terminal using the hardware scolling option of the microprocessor. /dev/ttym can not be opened if the graphics device (/dev/mg) is open. The reverse is ok. When used for both a tty and graphics the keyboard must be directed to either UNIX or to your graphics program. The STATUS key toggles the keyboard between the two. The UNIX text appears when in 'tty' mode, otherwise you are in graphics mode. Also, in tty mode the COPY key generates a tab, and the CLEAR key clears the screen. .sh FILES .nf /dev/mg Memory dma /dev/mgpio Memory programmed IO /dev/mgper Peripherals /dev/ttym tty .fi .sh BUGS pened if the graphics device (/dev/mg) is open. The reverse is ok. When used for both a tty and graphics the keyboard must be directed to either UNIX or to your graphics program. The STATUS key toggles the keyboard between the two. The UNIX text appears when in 'tty' m.th rm IV .sh NAME .nf rm Ramtek 9351 Raster Graphics Display Driver rmpio Programmed IO rmper Peripherals .fi .sh DESCRIPTION The Ramtek is a microprocessor-controlled display connected to the PDP with a general purpose interface (GPIF) and a PIO/DMA parallel interface (DR-11B/C). The driver has three minor devices: the dma (commands), programmed io (for special usage), and a peripheral/sgtty for peripheral io to/from the keyboard and joystick. The dma must be opened first, optionally followed by the peripheral device. Transfers are done directly from/to the user's buffer. Byte counts must be even (words), and the buffer must be word-aligned. .sh "DMA and PIO Minor Devices:" Transfers are standard read/write's from the user buffer. It is entirely the user's responsibility to manage the flow of data to and from the Ramtek, i.e., reading the right number of bytes returned for a given request command sent to the device. .sh "Peripheral Minor Device:" To minimize the number of special files, the peripheral minor device serves two purposes: a read() on the peripheral device returns keyboard characters, while sgtty() sets or returns cursor position and status. Stty(fd,v) is used to control the read/gtty mode of operation , and to set the cursor position. The third vector word, v[2] flags the purpose of the call: if bit 0 is set (SETCUR=01), the stty is a set cursor command: v[0] = x, and v[1] = y and the VIS bit (02000). If SETCUR is reset, v[2] is the OR of the read/gtty modes: called WAITKB and WAITEN. .P WAITKB (= 0100000) set causes the read to wait for a character. WAITKB reset will cause immediate return. The read count must be two. The first byte returned is the ASCII key code, and the second has a flag (040 bit) that means "no-data" when set. .P WAITEN (=0040000) set causes the gtty(fd,v) call to wait for the ENTER switch to be depressed on the joystick before returning. WAITEN reset will return immediately. v[0] = x, v[1] = y and the "no-data" flag (020000), and v[2] = the current flag status. .sh FILES .nf /dev/rm dma /dev/rmpio programmed io /dev/rmper peripherals .sh BUGS The wait options actually use polling and sleeping, not interrupts from the Ramtek (due to hardware problems). second has a flag (040 bit) that means "no-data" when set. .P WAITEN (=0040000) set causes the gtty(fd,v) call to wait for the ENTER switch to be depressed on the joystick before returning. WAITEN reset will return immediately. v[0] = x, v[1] = y and the "no-data" flag (020000), and v[2] = the current flag status. .sh FILES .nf ->t_dev.d_minor; DHADDR->dhbar =| c; dhsar =| c; tp->t_state =| BUSY; } else if (c = tp->t_char) { tp->t_char = 0; timeout(ttrstrt, tp, (c&0177)+6); tp->t_state =| TIMEOUT; } out: PS->integ = sps; } &ASLEEP) { tp->t_state =& ~ASLEEP; wakeup(&tp->t_outq); } /* * If any characters were set up, start transmission; * otherwise, check for possible delay. */ if (nch) { DHADDR->dhcsr.lobyte = tp->t_dev.d_minor | IENABLE; DHADDR->dhcar = cp+nch; DHADDR->dhbcr = nch; c = 1<dmcsr = dev.d_minor; DMADDR->dmlstat = TURNON; if (DMADDR->dmlstat&CARRIER) tp->t_state =| CARR_ON; DMADDR->dmcsr = IENABLE|SCENABL; spl5(); while ((tp->t_state&CARR_ON)==0) sleep(&tp->t_rawq, TTIPRI); spl0(); } /* * If a DH line has the HUPCL mode, * turn off carrier when it is closed. */ dmclose(dev) { register struct tty *tp; tp = &dh11[dev.d_minor]; if (tp->t_flags&HUPCL) { DMADDR->dmcsr = dev.d_minor; DMADDR->dmlstat = TURNOFF; DMADDR->dmcsr = IENABLE|SCENABL; } } /* * DM11 interrupt. * Mainly, deal with carrier transitions. */ dmint() { register struct tty *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; } } FF; DMADDR->dmc# /* */ /* * DM-BB fake driver */ #include "../tty.h" #include "../conf.h" struct tty dh11[]; dmopen(dev) { register struct tty *tp; tp = &dh11[dev.d_minor]; tp->t_state =| CARR_ON; } dmclose(dev) { } h11]) { 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; } } FF; DMADDR->dmc# /* copyright 1975, ian inc * * This driver is from the University of New South Wales * */ /* * DJ-11 DRIVER */ #include "../param.h" #include "../conf.h" #include "../user.h" #include "../tty.h" #include "../proc.h" #define NDJ11 16 /*only 1 dj all lines*/ #define DJADDR 0160010 /*1st dj address*/ #define DJTIE 0040000 /*xmit interupt enable*/ #define DJTSE 0000400 /*xmit scan enable*/ #define DJTR 0100000 /*xmitter ready*/ #define DJDP 0100000 /*data present*/ #define DJRIE 0000100 /*rcvr interupt enable*/ #define DJRE 0000001 /*rcvr enable*/ #define ERRFLAG 0060000 /*oe,fe,pe*/ struct tty DJ11[NDJ11]; struct djregs { int djcsr; int djrbuf; int djtcr; int djtbuf; } djopen(dev,flag) { register char *addr; register struct tty *tp; extern djstart(); if(dev.d_minor >= NDJ11) { u.u_error = ENXIO; return; } tp = &DJ11[dev.d_minor]; if(u.u_procp->p_ttyp == 0) u.u_procp->p_ttyp = tp; tp->t_addr = djstart; /* a special start routine */ tp->t_dev = dev; if((tp->t_state&ISOPEN) == 0) { tp->t_state = SSTART | ISOPEN | CARR_ON; tp->t_flags = XTABS | LCASE | ECHO | CRMOD; tp->t_erase = CERASE; tp->t_kill = CKILL; } DJADDR->djcsr = DJTIE | DJTSE | DJRE | DJRIE; } djclose(dev) { register struct tty *tp; tp = &DJ11[dev.d_minor]; wflushtty(tp); tp->t_state = 0; } djread(dev) { ttread(&DJ11[dev.d_minor]); } djwrite(dev) { ttwrite(&DJ11[dev.d_minor]); } djstart(atp) struct tty *atp; { /* enable xmitter for this line */ DJADDR->djtcr =| 1<<(atp-DJ11); } djxint(dev) { register int c; register struct tty *tp; while (DJADDR->djcsr&DJTR) /*loop till xmitter happy */ { c = DJADDR->djtbuf; tp = &DJ11[c>>8]; if((c = getc(&tp->t_outq)) >= 0) DJADDR->djtbuf = c + (partab[c]&0200); else DJADDR->djtcr =& ~(1<<(tp-DJ11)); /*turn it off*/ if(tp->t_outq.c_cc == 0 || tp->t_outq.c_cc == TTLOWAT) wakeup(&tp->t_outq); } } djrint(dev) { register int c, *addr; register struct tty *tp; while (DJADDR->djrbuf) /*loop till fifo empty*/ { c = DJADDR->djrbuf; if(c&ERRFLAG) return; tp = &DJ11[(c>>8)&017]; /*line number*/ c =& 0177; ttyinput(c,tp); } } djsgtty(dev,v) int *v; { register struct tty *tp; tp = &DJ11[dev.d_minor]; ttystty(tp,v); } c + (partab[c]&0200); else DJADDR->djtcr =& ~(1<<(tp-DJ11)); /*turn it off*/ if(tp->t_outq.c_cc == 0 || tp->t_outq.c_cc == TTLOWAT) wakeup(&tp->t_outq); } } djrint(dev) { register int c, *addr; register struct tty *tp; while (DJADDR->djrbuf) /*loop till fifo empt# /* * external dl11-abcd driver */ #include "../param.h" #include "../user.h" #include "../conf.h" #include "../tty.h" /* dl11-3 */ #define DLADDR 0175640 /* control bits */ #define IENABLE 0100 #define OUTRDY 0200 struct { /* dl11 registers */ int rcsr; int rbuf; int xcsr; int xbuf; }; struct dl11 { int inuse; struct clist inpq; struct clist outq; }; struct dl11 dl; exopen(dev,flag) { if( dl.inuse) u.u_error = ENXIO; else { dl.inuse++; DLADDR->rcsr = IENABLE; } } exclose(dev) { extern lbolt; while( dl.outq.c_cc) sleep(&lbolt,TTOPRI); while( getc(&dl.inpq) >= 0) ; dl.inuse=0; } exwrite(dev) { extern lbolt; register c; while( (c=cpass()) >= 0){ spl4(); while( dl.outq.c_cc > TTHIWAT) sleep( &dl.outq,TTOPRI); while( putc(c,&dl.outq)<0) sleep(&lbolt,TTOPRI); exxint(dev); spl0(); } } exread(dev) { register c; spl4(); do { while( (c=getc(&dl.inpq)) <0) sleep(&dl.inpq,TTIPRI); } while ( passc(c) >= 0) ; spl0(); } exxint(dev) { register c; if( DLADDR->xcsr & OUTRDY) { if( (c=getc(&dl.outq)) >=0){ DLADDR->xbuf=c; DLADDR->xcsr =| IENABLE; if( dl.outq.c_cc == 0 || dl.outq.c_cc == TTLOWAT) wakeup(&dl.outq); } else DLADDR->xcsr =& ~IENABLE; } } exrint(dev) { register c; putc( DLADDR->rbuf, &dl.inpq); wakeup(&dl.inpq); } PRI); exxint(dev); spl0(); } } exread(dev) { register c; spl4(); do { while( (c=getc(&dl.inpq)) <0) sleep(&dl.inpq,TTIPRI); } while ( passc(c) >= 0) ; spl0(); } exxint(dev) { register c; if( DLADDR# /* * Device Driver for the Ramtek 9351: * * Computer Aided Design and Graphics Lab * Purdue University * W. Lafayette, IN 47907 * (317) 493-9385 * * 10/26/79 * */ #include #include #include #include #define ADDR 0172466 /* unibus address */ /* DRIF command/status bits: */ #define ER 0100000 /* error bit */ #define NEX 040000 /* non-existant memory */ #define AID 01000 /* set = turn auto-increment off for dma */ #define RDY 0200 /* set = ready */ #define IE 0100 /* set = enable interrupts */ #define GIE 010 #define DIO 02 /* dma direction (set=receive from ramtek) */ #define GO 01 /* start dma! */ /* ramtek functions: */ #define RCUR 013400 /* read ramtek cursor */ #define WCUR 013000 /* write ramtek cursor */ #define RKB 014400 /* read ramtek kb */ /* etc. */ #define NTRIES 50 /* # times to wait for a ready before sleeping */ #define RMPRI 10 /* priority sleeping on */ #define VIS 002000 #define KBNODAT 020000 #define CUREN 020000 /* minor devices: */ #define DMA 0 #define PIO 1 #define KEYBOARD 2 /* GPIF command word: */ #define RESET 0100000 #define WRVE 0010000 #define WMXE 0004000 #define WPRE 0002000 /* GPIF status word: */ #define RPRE 010000 /* rm.flags definitions: */ /* Note: IE also set in rm.flags*/ #define WAITKB 0100000 #define WAITEN 040000 #define NOINCR 000004 /* stty "command" flag bit */ #define SETCUR 01 /* unibus structure: */ struct { int gpcsr; int drwc; int drba; int drst; int gpdata; }; /* our own flags: */ struct { int procp; int flags; } rm; /* structures to be used by physio: */ struct buf rmbuf; rmopen(dev,flag) { if( rm.procp != 0 ){ if( rm.procp != u.u_procp ) u.u_error = ENXIO; return; } spl5(); ADDR->drst = IE; /* enable interrupts so will sleep till ready */ rm.flags=IE; ADDR->gpcsr = RESET; rmrdy(); /*does spl0*/ if( ADDR->drst&ER ) { /* see if device is even there */ u.u_error = EIO; printf("Ramtek Error,drst=%o\n",ADDR->drst); return; } rm.procp = u.u_procp; } /* close the ramtek: */ rmclose(dev) { rmrdy(); /* be sure all transmissions are done */ ADDR->drst = 0; /* disable interrupts */ ADDR->gpcsr = 0; rm.procp = 0; } /* interrupt handler: */ rmint( dev ) { if( rm.flags&IE ) { /* waiting for a dr int */ rm.flags &= ~IE; ADDR->drst &= ~(IE|GIE); rmbuf.b_flags |= B_DONE; wakeup( &rmbuf ); }else printf("Ramtek Error, Unexp Int\n"); } /* read (do different things depending on the minor device): */ rmread(dev) { int rmstrategy(); register w; extern int lbolt; rmrdy(); switch( dev.d_minor ) { case DMA: physio(&rmstrategy , &rmbuf , dev , B_READ); break; case PIO: directio(B_READ); break; case KEYBOARD: if( u.u_count!=2 ) { u.u_error = ENXIO; return; } kbloop: clearpre(); /* clear the pre-fetch bit */ wrrm( RKB ); rmrdy(); setpre(); w= rdrm(); if( (w&KBNODAT)==0 || (rm.flags&WAITKB)==0){ suword(u.u_base,w); return; } /* Note: following code commented out, does not work! rmrdy(); spl5(); rm.flags |= IE; ADDR->drst |= ( IE | GIE); ADDR->gpcsr = WRVE; sleep( &rmbuf, RMPRI); spl0(); ... don't know why either */ sleep(&lbolt, RMPRI); rmrdy(); goto kbloop; } } /* write (do different things depending on the minor device): */ rmwrite(dev) { int rmstrategy(); rmrdy(); switch( dev.d_minor ) { case DMA: physio(&rmstrategy , &rmbuf , dev , B_WRITE); break; case PIO: directio(B_WRITE); break; case KEYBOARD: u.u_error = ENXIO; return; } } /* perform programmed i/o: */ directio( flag ) { register int count , *base; count = u.u_count; if( (count<=0) || (count&01)!=0 ){ u.u_error = EIO; return; } count >>= 1; /* words, not bytes */ base = u.u_base; if( (char *)base & 01){ u.u_error = EIO; return; } switch( flag ) { case B_READ: setpre(); /* set the pre-fetch bit */ while( count-- ) suword( base++, rdrm() ); break; case B_WRITE: clearpre(); while( count-- ) wrrm( fuword(base++) ); break; } } /* wait till ramtek interface is ready: */ rmrdy() { extern int lbolt; register int n; for(;;) { for(n=0; n<=NTRIES; n++){ if( ADDR->drst&RDY ){ if( ADDR->drst&ER ) printf("Ramtek Error,drst=%o\n",ADDR->drst); return; } } spl5(); if( rm.flags&IE ){ sleep(&rmbuf , RMPRI); spl0(); }else{ spl0(); sleep(&lbolt , RMPRI); } } } /* set the pre-fetch bit if not already set: */ /* (assume rmrdy has been called prior to coming here) */ setpre() { if( ADDR->gpcsr&RPRE ) return; /* already set */ ADDR->gpcsr = WPRE; /* set it (and nothing else in the gpcsr) */ rmrdy(); } /* clear the pre-fetch bit if not already cleared: */ /* (assume rmrdy has been called prior to coming here) */ clearpre() { if( ADDR->gpcsr&RPRE ) { ADDR->gpcsr = 0; rmrdy(); } } /* strategy routine for the dma: */ /* Note: this is really strategy and start put together*/ rmstrategy(abp) struct buf *abp; { register struct buf *bp; register int cmd; register char *p; p = ADDR; bp = abp; p->drba = bp->b_addr; cmd = (bp->b_xmem&03) << 4; if( rm.flags&NOINCR ) { cmd |= AID; rm.flags &= ~NOINCR; } if( bp->b_flags&B_READ ) { setpre(); cmd |= DIO; } else clearpre(); p->drwc = -(u.u_count>>1); p->drst = cmd|IE; rm.flags |= IE; p->drst++; /* GO */ } /* read or write to the joystick via gtty and stty: */ rmsgtty(dev , av) int *av; { register int *v; register w; register char *p; extern int lbolt; rmrdy(); p = ADDR; if( v=av ){ /* gtty */ enloop: clearpre(); wrrm(RCUR); rmrdy(); setpre(); v[0] = rdrm(); w = v[1] = rdrm(); v[2] = rm.flags; if( (w&CUREN) !=0 || (rm.flags&WAITEN)==0) return; /* Note: following code commented out like kbloop spl5(); rm.flags |= IE; p->drst |= (IE|GIE); p->gpcsr = WMXE; sleep( &rmbuf,RMPRI); spl0(); ... also don't know why */ rmrdy(); sleep(&lbolt, RMPRI); goto enloop; } else { /* stty */ w= u.u_arg[2]; if( (w&SETCUR) == 0){ rm.flags = u.u_arg[2] & ~(IE|WMXE|WRVE); return; } /* else set cursor command */ clearpre(); wrrm(WCUR); wrrm(u.u_arg[0]); wrrm(u.u_arg[1] | VIS); } } rdrm() { register char *p; p = ADDR; while( (p->drst & RDY) == 0) /*null*/; return( p->gpdata ); } wrrm(w) { register char *p; p = ADDR; while( (p->drst & RDY) == 0) /*null*/; p->gpdata = w; } .. also don't know why */ rmrdy(); sleep(&lbolt, RMPRI); goto enloop; } else { /* stty */ w= u.u_arg[2]; if( (w&SETCUR) == 0){# /* * dr11-c word driver */ #include #include #include #define DRADDR 0167770 #define PDR 11 /* number of dr11's */ #define NDR11 2 /* control bits */ #define INPRDY 0100000 #define OUTRDY 0000200 #define OUTINT 0000100 #define INPINT 0000040 struct { /*dr11 registers */ int csr; int xbuf; int rbuf; }; char drlock[NDR11]; /* open flag */ dropen(dev,flag) { register j; register char *addr; if( (j=dev.d_minor) >= NDR11 || drlock[j] ){ u.u_error = ENXIO; return; } drlock[j]++; addr = DRADDR - (j<<3); addr->csr=0; j= addr->rbuf; /* clear any hanging input */ } drclose(dev) { register char *addr; register j; j=dev.d_minor; drlock[j]=0; addr = DRADDR-(j<<3); addr->csr=0; /*clear all*/ } drwrite(dev) { register char *addr; register *base, nwords; int count; if( (nwords=u.u_count)&01 || ((char *)base=u.u_base)&01 ){ u.u_error = EIO; return; } addr = DRADDR - (dev.d_minor<<3); nwords =>> 1; while( nwords ){ retry: for( count=0; count<10; count++ ) if( addr->csr & OUTRDY ){ addr->xbuf = fuword(base++); nwords--; goto contin; } spl5(); addr->csr =| OUTINT; sleep(addr,PDR); spl0(); goto retry; contin: ; } } drread(dev) { register char *addr; register *base, nwords; int count; if( (nwords=u.u_count)&01 || ((char *)base=u.u_base)&01){ u.u_error = EIO; return; } addr = DRADDR - (dev.d_minor<<3); nwords =>> 1; while( nwords ){ retry2: for( count=0; count<10; count++ ) if( addr->csr & INPRDY ){ suword(base++, addr->rbuf); nwords--; goto contin2; } spl5(); addr->csr =| INPINT; sleep(addr,PDR); spl0(); goto retry2; contin2: ; } } drxint(dev) { register char *addr; addr = DRADDR - (dev.d_minor<<3); addr->csr =& ~OUTINT; wakeup(addr); } drrint(dev) { register char *addr; addr = DRADDR -(dev.d_minor<<3); addr->csr =& ~INPINT; wakeup(addr); } dev.d_minor<<3); nwords =>> 1; while( nwords ){ retry2: for( count=0; count<10; count++ ) if( addr->csr # /***************************************************************** VERSATEC printer/plotter driver Bill Allen (May 1975) Gerry Barksdale (June 1975) Naval Postgraduate School D. Anderson (Sept.,1977, Purdue Univ.) *****************************************************************/ #include #include #include #include #define VLADDR 0177514 #define PLOTADR 0177510 #define DMA 0177500 #define DMABUSY 020000 #define IENABLE 0100 #define DONE 0200 #define RLT 040 /*remote line terminate*/ #define VPPRI 10 #define VPLWAT 50 #define VPHWAT 100 #define EJLINE 60 #define MAXCOL 132 struct { int vpsr; int vpbuf; }; struct { int plotbytes; int addrext; int printbytes; int addr; }; struct { int cc; int cf; int cl; int flag; int count; int mcc; int ccc; int mlc; } vp11; int vpstat; struct devtab vptab; struct buf rvpbuf; #define SPP 01 /*simultaneous print plot*/ #define EJECT 02 #define OPEN 04 #define RESET 02 #define REOT 010 #define EOT 004 #define FORM 014 vlopen(dev, flag) { if(vp11.flag & OPEN || VLADDR->vpsr < 0) { u.u_error = EIO; return; } vp11.flag = (OPEN) | (dev.d_minor ? SPP : 0); /*nonzero minor => SPP*/ VLADDR->vpsr = IENABLE; vp11.count++; } vlclose(dev, flag) { if(--vp11.count > 0) return; vlcanon(EOT); /* sleep(&vp11,VPPRI); /*wait for eot to take*/ vp11.flag = 0; vp11.count = 0; } vlwrite() { register int c; while ((c=cpass())>=0) vlcanon(c); } vlcanon(c) { register c1, c2; c1 = c&0177; switch(c1) { case '\t': vp11.ccc = (vp11.ccc+8) & ~7; return; case FORM: case '\n': vp11.mcc = 0; vloutput(c1); case '\r': vp11.ccc = 0; return; case 010: /*backspace*/ vloutput('B'); vloutput('S'); case ' ': vp11.ccc++; return; default: if(vp11.ccc < vp11.mcc) { vloutput('\n'); /*newline*/ vp11.mcc = 0; } if(vp11.ccc < MAXCOL) { while(vp11.ccc > vp11.mcc) { vloutput(' '); vp11.mcc++; } vloutput(c1); vp11.mcc++; } vp11.ccc++; } } vlstart() { register int c; while(((VLADDR->vpsr&DONE)||vpstat)&&(c=getc(&vp11))>=0) VLADDR->vpbuf = c; } vlint(dev) { if (VLADDR->vpsr < 0) { /* error bit */ prdev("Versatec Print Error",dev); wakeup(&vp11); return; } vlstart(); if (vp11.cc == VPLWAT || vp11.cc == 0) wakeup(&vp11); } vloutput(c) { if (vp11.cc >= VPHWAT) sleep(&vp11, VPPRI); putc(c, &vp11); spl4(); vlstart(); spl0(); } vpctl() { while((PLOTADR->vpsr & DONE) == 0) sleep(&vp11,VPPRI); vpstat = PLOTADR->vpsr = u.u_arg[0]&077 | IENABLE; /*control bits*/ vpstat =& SPP; } /* routines for versatec plotter in DMA mode*/ vpopen(dev, flag) { if(((vp11.flag & OPEN ) && !(vp11.flag & SPP)) || PLOTADR->vpsr < 0) { u.u_error = EIO; return; } vp11.flag =| (OPEN); vpstat=PLOTADR->vpsr=(IENABLE)|((vp11.flag&SPP)?SPP:0); vpstat =& SPP; vp11.count++; } vpclose(dev, flag) { if(--vp11.count > 0) return; /* while ((PLOTADR->vpsr&DONE) == 0)*/ /* sleep(&vp11,VPPRI);*/ /* PLOTADR->vpsr = REOT; /*end of plotting*/ vp11.flag = 0; vp11.count = 0; vpstat = 0; } vpstrategy(abp) struct buf *abp; { register struct buf *bp; bp = abp; bp->av_forw = 0; spl4(); if (vptab.d_actf==0) vptab.d_actf = bp; else vptab.d_actl->av_forw = bp; vptab.d_actl = bp; if (vptab.d_active==0) vpstart(); spl0(); } vpstart() { register struct buf *bp; if ((bp = vptab.d_actf) && !(PLOTADR->vpsr & DMABUSY)) { vptab.d_active++; DMA->addr = bp->b_addr; /*clears addrext*/ DMA->addrext = ((bp->b_xmem & 03) << 4); /*order important*/ DMA->plotbytes = u.u_count; /*positive! & GO*/ bp->b_resid = 0; } } vpint(dev) { register struct buf *bp; if (PLOTADR->vpsr < 0) { /* error bit */ prdev("Versatec Plot Error",dev); wakeup(&vp11); return; } if (vptab.d_active == 0) { wakeup(&vp11); return; } vptab.d_active = 0; bp = vptab.d_actf; vptab.d_actf = bp->av_forw; iodone(bp); vpstart(); } vpwrite(dev) { if( !vpstat && !(VLADDR->vpsr & DONE) ) sleep(&vp11,VPPRI); physio(vpstrategy, &rvpbuf, dev, B_WRITE); while(PLOTADR->vpsr & DMABUSY) sleep(&vp11,VPPRI); PLOTADR->vpsr = RLT | IENABLE | vpstat; /*remote line terminate*/ } if (PLOTADR->vpsr < 0) { /* error bit */ prdev("Versatec Plot Error",dev); wakeup(&vp11); return; } if (vptab.d_active == 0) { wakeup(&vp11); return; } vptab.d_active = 0; bp = vptab.d_actf; vptab.d_actf = bp->av_forw; iodone(bp); vpstart(); } vpwrite(dev) { if( !vpstat && !(VLADDR->vpsr & DONE) ) sleep(&vp11,VPPRI); physio(vpstrategy, &rvpbuf, dev, B_WRITE); while(# /* * KL/DL-11 driver */ #include #include #include #include #include /* base address */ #define KLADDR 0177560 /* console */ #define KLBASE 0176500 /* kl and dl11-a */ #define DLBASE 0175610 /* dl-e */ #define NKL11 1 #define NDL11 4 #define DSRDY 02 #define RDRENB 01 struct tty kl11[NKL11+NDL11]; struct klregs { int klrcsr; int klrbuf; int kltcsr; int kltbuf; } klopen(dev, flag) { register char *addr; register struct tty *tp; if(dev.d_minor >= NKL11+NDL11) { u.u_error = ENXIO; return; } tp = &kl11[dev.d_minor]; if (u.u_procp->p_ttyp == 0) { u.u_procp->p_ttyp = tp; tp->t_dev = dev; } /* * set up minor 0 to address KLADDR * set up minor 1 thru NKL11-1 to address from KLBASE * set up minor NKL11 on to address from DLBASE */ addr = KLADDR + 8*dev.d_minor; if(dev.d_minor) addr += KLBASE-KLADDR-8; if(dev.d_minor >= NKL11) addr =+ DLBASE-KLBASE-8*NKL11+8; tp->t_addr = addr; if ((tp->t_state&ISOPEN) == 0) { tp->t_state = ISOPEN|CARR_ON; tp->t_flags = XTABS|LCASE|ECHO|CRMOD; tp->t_erase = CERASE; tp->t_kill = CKILL; tp->t_tabexp = TABLEN; } addr->klrcsr |= IENABLE|DSRDY|RDRENB; addr->kltcsr |= IENABLE; } klclose(dev) { register struct tty *tp; tp = &kl11[dev.d_minor]; wflushtty(tp); tp->t_state = 0; } klread(dev) { ttread(&kl11[dev.d_minor]); } klwrite(dev) { ttwrite(&kl11[dev.d_minor]); } klxint(dev) { register struct tty *tp; tp = &kl11[dev.d_minor]; ttstart(tp); if (tp->t_outq.c_cc == 0 || tp->t_outq.c_cc == TTLOWAT) wakeup(&tp->t_outq); } klrint(dev) { register int c, *addr; register struct tty *tp; tp = &kl11[dev.d_minor]; addr = tp->t_addr; c = addr->klrbuf; /* addr->klrcsr |= RDRENB; if ((c&0177)==0) addr->kltbuf = c; /* hardware botch */ /* * system mod: * check if trying for high speed input - if so, bypass ttyinput: * * roughly plagarized from EE's "upload" system. * -- mjb 04/17/79 */ if( tp->t_xxpar ) { /* high ! */ sufet(c , tp->t_xxpar , tp->t_xxoff); return; } /* normal operation: */ ttyinput(c, tp); } klsgtty(dev, v) int *v; { register struct tty *tp; tp = &kl11[dev.d_minor]; ttystty(tp, v); } p->t_addr; c = addr->klrbuf; /* addr->klrcsr |= RDRENB; if ((c&0177)==0) addr->kltbuf = c; /* hardware botch */ /* * system mod: * check if trying for high speed input - if so, bypass ttyinput: * * roughly plagarized from EE's "upload" system. * -- mjb 04/17/79 */ if( tp->t_xxpar ) { /* high ! */ sufet(c , tp->t_xxpar , tp-># /* */ /* * RK disk driver */ /* modified by dca to give deverr after 10 retries */ #include #include #include #include #define RKADDR 0177400 #define NRK 4 #define NRKBLK 4872 #define RESET 0 #define GO 01 #define DRESET 014 #define IENABLE 0100 #define DRY 0200 #define ARDY 0100 #define WLO 020000 #define CTLRDY 0200 struct { int rkds; int rker; int rkcs; int rkwc; int rkba; int rkda; }; struct devtab rktab; struct buf rrkbuf; rkstrategy(abp) struct buf *abp; { register struct buf *bp; register *qc, *ql; int d; bp = abp; if(bp->b_flags&B_PHYS) mapalloc(bp); d = bp->b_dev.d_minor-7; if(d <= 0) d = 1; if (bp->b_blkno >= NRKBLK*d) { bp->b_flags =| B_ERROR; iodone(bp); return; } bp->av_forw = 0; spl5(); if (rktab.d_actf==0) rktab.d_actf = bp; else rktab.d_actl->av_forw = bp; rktab.d_actl = bp; if (rktab.d_active==0) rkstart(); spl0(); } rkaddr(bp) struct buf *bp; { register struct buf *p; register int b; int d, m; p = bp; b = p->b_blkno; m = p->b_dev.d_minor - 7; if(m <= 0) d = p->b_dev.d_minor; else { d = lrem(b, m); b = ldiv(b, m); } return(d<<13 | (b/12)<<4 | b%12); } rkstart() { register struct buf *bp; if ((bp = rktab.d_actf) == 0) return; rktab.d_active++; devstart(bp, &RKADDR->rkda, rkaddr(bp), 0); } rkintr() { register struct buf *bp; if (rktab.d_active == 0) return; bp = rktab.d_actf; rktab.d_active = 0; if (RKADDR->rkcs < 0) { /* error bit */ RKADDR->rkcs = RESET|GO; while((RKADDR->rkcs&CTLRDY) == 0) ; if (++rktab.d_errcnt <= 10) { rkstart(); return; } deverror(bp, RKADDR->rker, RKADDR->rkds); bp->b_flags =| B_ERROR; } rktab.d_errcnt = 0; rktab.d_actf = bp->av_forw; iodone(bp); rkstart(); } rkread(dev) { physio(rkstrategy, &rrkbuf, dev, B_READ); } rkwrite(dev) { physio(rkstrategy, &rrkbuf, dev, B_WRITE); } tab.d_active == 0) return; bp = rktab.d_actf; rktab.d_active = 0; if (RKADDR->rkcs < 0) { /* error bit */ RKADDR->rkcs = RESET|G# /* * xx.c - fake a high speed transfer. * * use of these routines cause any input from that particular dl-11 * to be dumped into a large circular buffer in user space. * * roughly plagarized from EE's "upload" code. * -- mjb 04/17/79 * */ #include #include #include #include #include #include #include struct tty kl11[]; /* this is actually defined in kl.c */ xxopen(dev) { register struct tty *tp; tp = &kl11[ dev.d_minor ]; if( tp->t_xxpid ) { /* already using this line for high speed! */ u.u_error = ENXIO; return; } tp->t_xxpid = u.u_procp; /* save current process id */ } xxread(dev) { /* actually this does no reading, just sets up to await interrupts! */ register int nb; register struct tty *tp; tp = &kl11[ dev.d_minor ]; u.u_procp->p_flag |= SLOCK; /* lock the little bugger in core */ nb = (u.u_base>>6) & 01777; /* this is the virtual block number */ tp->t_xxoff = u.u_base&077; /* this is the offset from the Page Address Register */ tp->t_xxpar = UISA->r[nb>>7] + (nb&0177); /* page address field + block # => physical block # */ /* see physio for help */ } xxclose(dev) { register struct tty *tp; tp = &kl11[ dev.d_minor ]; tp->t_xxpar = tp->t_xxoff = tp->t_xxpid = 0; u.u_procp->p_flag &= ~SLOCK; } 11[ dev.d_minor ]; u.u_procp->p_flag |= SLOCK; /* lock the little bugger in core */ nb = (u.u_base>>6) & 01777; /* this is the virtual block number */ tp->t_xxoff = u.u_base&077; /* this .th calcomp IV .sh NAME CLI 8008 Calcomp Plotter Driver .sh DESCRIPTION The CLI 8008 is an 8-bit microprocessor that is programmed in PROM to drive a Calcomp 502 plotter. The 8008 reads a buffer of (pencode,dx,dy) triples from a 2400 baud serial line from the PDP using a simple binary protocol. It then drives the plotter using a digital stepping algorithm. .sh "Startup:" The 8008 should be powered on (switch on the back). The 8008 program is started by toggling '5' into its data switches (lsb on top,1=left), then depressing the 'run' button (second button from the bottom). The small red light should be on. If not, alternately depress the 1st and 2nd buttons from the bottom until the light is on. DEC interface #1 should be patched to the "calcomp controller" at 2400 baud (check the speed switch behind the 11/40 cpu). .sh "Protocol:" Communication to the 8008 is through /dev/tty1 in raw mode. The protocol consists of a leading command byte, followed by optional values: .nf Command(octal) Meaning 020 "setup" - move pen down & left 12" 060 "abort" - interrupt plotting and reset 070 "begin plotting" - from buffer .fi After each action is completed, the 8008 sends a "ready" byte: <001> after setup and plotting, and <003> after abort. The user must not send to the 8008 in the interim, except abort. .P Any other command is interpreted as a pencode, followed by 4 bytes giving 16-bits of dx and dy. These are stored in the buffer until the "070" is seen. After the last vector is drawn, the ack <001> is returned. The abort (060) can be issued to stop plotting and begin scanning again. The pencodes are: .nf 0 pen up 1 pen down 2 dashed line .fi .sh "WARNING" The buffer holds 1000 bytes, or 200 vectors. It is the user's responsibility to count bytes and issue 070 before the buffer overflows! .sh FILES /dev/tty1 the communication path (raw mode) .sh BUGS Requires 8-bit raw io. .br The host must know the buffer capacity. n the buffer until the "070" is seen. After the last vector is drawn, the ack <001> is returned. T.th dr IV .sh NAME dr - DR11-C Programmed IO Parallel Interface Driver .sh DESCRIPTION Each read or write causes words to be received or sent via the DR11-C interface in programmed io mode, meaning one at a time. All transfer byte counts must be even, and buffers must be word-aligned. The user has exclusive access to the dr. .sh FILES /dev/dr0 Unit 0 (Imlac pds1) .br /dev/dr1 Unit 1 (Imlac pds4) .sh BUGS Transfers to/from outside the user's address space are not checked. drawn, the ack <001> is returned. Tnsfers to/from outside the user's address space are not checked. river .sh DESCRIPTION Each read or write causes words to be received or sent via the DR11-C interface in programmed io mode, or one at a time. All transfer byte counts must be even, and buffers must be word-aligned. Only one user can have a dr open at a time. .br Note that due to the coding, it is far more efficient to use larger transfer counts to avoid sleeping. .sh FILES /dev/dr0 Unit 0 (Imlac pds1) /dev/dr1 Unit 1 (Imlac pds4) .sh BUGS Tra# /* */ /* * LP-11 Line printer driver */ #include "../param.h" #include "../conf.h" #include "../user.h" #define LPADDR 0177514 #define IENABLE 0100 #define DONE 0200 #define LPPRI 10 #define LPLWAT 50 #define LPHWAT 100 #define EJLINE 60 #define MAXCOL 80 struct { int lpsr; int lpbuf; }; struct { int cc; int cf; int cl; int flag; int mcc; int ccc; int mlc; } lp11; #define CAP 00 /* Set to 0 for 96-char printer, else to 01 */ #define EJECT 02 #define OPEN 04 #define IND 000 /* Set to 0 for no indent, else to 010 */ #define FORM 014 lpopen(dev, flag) { if(lp11.flag & OPEN || LPADDR->lpsr < 0) { u.u_error = EIO; return; } lp11.flag =| (IND|EJECT|OPEN); LPADDR->lpsr =| IENABLE; lpcanon(FORM); } lpclose(dev, flag) { lpcanon(FORM); lp11.flag = 0; } lpwrite() { register int c; while ((c=cpass())>=0) lpcanon(c); } lpcanon(c) { register c1, c2; c1 = c; if(lp11.flag&CAP) { if(c1>='a' && c1<='z') c1 =+ 'A'-'a'; else switch(c1) { case '{': c2 = '('; goto esc; case '}': c2 = ')'; goto esc; case '`': c2 = '\''; goto esc; case '|': c2 = '!'; goto esc; case '~': c2 = '^'; esc: lpcanon(c2); lp11.ccc--; c1 = '-'; } } switch(c1) { case '\t': lp11.ccc = (lp11.ccc+8) & ~7; return; case FORM: case '\n': if((lp11.flag&EJECT) == 0 || lp11.mcc!=0 || lp11.mlc!=0) { lp11.mcc = 0; lp11.mlc++; if(lp11.mlc >= EJLINE && lp11.flag&EJECT) c1 = FORM; lpoutput(c1); if(c1 == FORM) lp11.mlc = 0; } case '\r': lp11.ccc = 0; if(lp11.flag&IND) lp11.ccc = 8; return; case 010: if(lp11.ccc > 0) lp11.ccc--; return; case ' ': lp11.ccc++; return; default: if(lp11.ccc < lp11.mcc) { lpoutput('\r'); lp11.mcc = 0; } if(lp11.ccc < MAXCOL) { while(lp11.ccc > lp11.mcc) { lpoutput(' '); lp11.mcc++; } lpoutput(c1); lp11.mcc++; } lp11.ccc++; } } lpstart() { register int c; while (LPADDR->lpsr&DONE && (c = getc(&lp11)) >= 0) LPADDR->lpbuf = c; } lpint() { register int c; lpstart(); if (lp11.cc == LPLWAT || lp11.cc == 0) wakeup(&lp11); } lpoutput(c) { if (lp11.cc >= LPHWAT) sleep(&lp11, LPPRI); putc(c, &lp11); spl4(); lpstart(); spl0(); } lpoutput('\r'); lp11.mcc = 0; } if(lp11.ccc < MAXCOL) { while(lp11.ccc > lp11.mcc) { lpoutput(' '); lp11.mcc++; } lpoutput(c1); lp11.mcc++; } lp11.ccc++; } } lpstart() { register int c; while (LPADDR->lpsr&DONE && (c = getc(&lp11)) >= 0) LPADDR->lpbuf = c; }# /* */ /* * Memory special file * minor device 0 is physical memory * minor device 1 is kernel memory * minor device 2 is EOF/RATHOLE */ #include "../param.h" #include "../user.h" #include "../conf.h" #include "../seg.h" mmread(dev) { register c, bn, on; int a, d; if(dev.d_minor == 2) return; do { bn = lshift(u.u_offset, -6); on = u.u_offset[1] & 077; a = UISA->r[0]; d = UISD->r[0]; spl7(); UISA->r[0] = bn; UISD->r[0] = 077406; if(dev.d_minor == 1) UISA->r[0] = (ka6-6)->r[(bn>>7)&07] + (bn & 0177); c = fuibyte(on); UISA->r[0] = a; UISD->r[0] = d; spl0(); } while(u.u_error==0 && passc(c)>=0); } mmwrite(dev) { register c, bn, on; int a, d; if(dev.d_minor == 2) { c = u.u_count; u.u_count = 0; u.u_base =+ c; dpadd(u.u_offset, c); return; } for(;;) { bn = lshift(u.u_offset, -6); on = u.u_offset[1] & 077; if ((c=cpass())<0 || u.u_error!=0) break; a = UISA->r[0]; d = UISD->r[0]; spl7(); UISA->r[0] = bn; UISD->r[0] = 077406; if(dev.d_minor == 1) UISA->r[0] = (ka6-6)->r[(bn>>7)&07] + (bn & 0177); suibyte(on, c); UISA->r[0] = a; UISD->r[0] = d; spl0(); } } mmwrite(dev) { register c, bn, on; int a, d; if(dev.d_minor == 2) { c = u.u_count; u.u_count = 0; u.u_base =+ c; dpadd(u.u_offset, c); return; } for(;;) { bn = lshift(u.u_offset, -6); on = u.u_offset[1] & 077; if ((c=cpass())<0 || u.u_error!=0) break; a = UISA->r[0]; d = UISD->r[0]; spl7(); UISA->r[0] = bn; UISD->r[0] = 077406; if(dev.d_m/* */ char partab[] { 0001,0201,0201,0001,0201,0001,0001,0201, 0202,0004,0003,0205,0005,0206,0201,0001, 0201,0001,0001,0201,0001,0201,0201,0001, 0001,0201,0201,0001,0201,0001,0001,0201, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0201 }; 0201, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,# /* */ /* * PC-11 Paper tape reader/punch driver */ #include "../param.h" #include "../conf.h" #include "../user.h" #define PCADDR 0177550 #define CLOSED 0 #define WAITING 1 #define READING 2 #define EOF 3 #define RDRENB 01 #define IENABLE 0100 #define DONE 0200 #define BUSY 04000 #define ERROR 0100000 #define PCIPRI 30 #define PCOPRI 40 #define PCOLWAT 50 #define PCOHWAT 100 #define PCIHWAT 250 struct { int pcrcsr; int pcrbuf; int pcpcsr; int pcpbuf; }; struct clist { int cc; int cf; int cl; }; struct pc11 { int pcstate; struct clist pcin; struct clist pcout; } pc11; pcopen(dev, flag) { extern lbolt; if (flag==0) { if (pc11.pcstate!=CLOSED) { u.u_error = ENXIO; return; } pc11.pcstate = WAITING; while(pc11.pcstate==WAITING) { PCADDR->pcrcsr = IENABLE|RDRENB; sleep(&lbolt, PCIPRI); } } else { PCADDR->pcpcsr =| IENABLE; pcleader(); } } pcclose(dev, flag) { if (flag==0) { spl4(); while (getc(&pc11.pcin) >= 0); PCADDR->pcrcsr = 0; pc11.pcstate = CLOSED; spl0(); } else pcleader(); } pcread() { register int c; spl4(); do { while ((c = getc(&pc11.pcin)) < 0) { if (pc11.pcstate==EOF) goto out; if ((PCADDR->pcrcsr&(ERROR|BUSY|DONE))==0) PCADDR->pcrcsr =| IENABLE|RDRENB; sleep(&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==READING) { if (PCADDR->pcrcsr&ERROR) pc11.pcstate = EOF; else { putc(PCADDR->pcrbuf, &pc11.pcin); if (pc11.pcin.cc < PCIHWAT) PCADDR->pcrcsr =| IENABLE|RDRENB; } wakeup(&pc11.pcin); } } pcpint() { pcstart(); if (pc11.pcout.cc <= PCOLWAT) wakeup(&pc11.pcout); } pcoutput(c) { if (PCADDR->pcpcsr&ERROR) { u.u_error = EIO; return; } if (pc11.pcout.cc >= PCOHWAT) sleep(&pc11.pcout, PCOPRI); putc(c, &pc11.pcout); spl4(); pcstart(); spl0(); } pcleader() { register int i; i = 100; do pcoutput(0); while (--i); } .pcstate = EOF; else { putc(PCADDR->pcrbuf, &pc11.pcin); if (pc11.pcin.cc < PCIHWAT) PCADDR->pcrcsr =| IENABLE|RDRENB; } wakeup(&pc11.pcin); } } pcpint() { pcstart(); if (pc11.pcout.cc <= PCOLWAT) wakeup(&pc11.pcout); } pcoutput(c) { if (PCADDR->pcpcsr&ERROR) { u.u_error = EIO; return; } if (pc11.pcout.cc >= PC# /* */ /* * RF disk driver */ #include "../param.h" #include "../buf.h" #include "../conf.h" #include "../user.h" struct { int rfcs; int rfwc; int rfba; int rfda; int rfdae; }; struct devtab rftab; struct buf rrfbuf; #define NRFBLK 1024 #define RFADDR 0177460 #define GO 01 #define RCOM 02 #define WCOM 04 #define CTLCLR 0400 #define IENABLE 0100 rfstrategy(abp) struct buf *abp; { register struct buf *bp; bp = abp; if(bp->b_flags&B_PHYS) mapalloc(bp); if (bp->b_blkno >= NRFBLK*(bp->b_dev.d_minor+1)) { bp->b_flags =| B_ERROR; iodone(bp); return; } 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() { register struct buf *bp; if (rftab.d_active == 0) return; bp = rftab.d_actf; rftab.d_active = 0; if (RFADDR->rfcs < 0) { /* error bit */ deverror(bp, RFADDR->rfcs, RFADDR->rfdae); RFADDR->rfcs = CTLCLR; if (++rftab.d_errcnt <= 10) { rfstart(); return; } bp->b_flags =| B_ERROR; } rftab.d_errcnt = 0; rftab.d_actf = bp->av_forw; iodone(bp); rfstart(); } rfread(dev) { physio(rfstrategy, &rrfbuf, dev, B_READ); } rfwrite(dev) { physio(rfstrategy, &rrfbuf, dev, B_WRITE); } () { register struct buf *bp; if (rftab.d_active == 0) return; bp = .th vpp/lp IV .sh NAME .nf lp Versatec line printer vpp Versatec plotter spp Versatec line printer with SPP .fi .sh DESCRIPTION The Versatec 1200A may be used as a printer, plotter or printer/plotter (simultaneous print plot mode). .sh "Printer Mode:" A full ASCII printer, with 132 characters per line on an 11 inch wide page; 64 lines may be printed in the 8.5 inch page length. All control characters except new-line, form-feed, and tab are invalid. The print line is released when the new-line character is received. Only the first 132 characters of a print line are printed. .sh "Plotter Mode:" The plotting area is the same as the printing area. Plotting is accomplished by writing data bytes to the plotter. Whenever the byte has a 1 bit, the plotter will activate the plotting nib corresponding to that bit. A maximum of 264 bytes may be plotted per line. The plotter has a resolution of 200 dots per inch in both directions. At least one plot line is produced per write. If less than 264 bytes are written, the line is null padded. When the number of bytes is greater than 264, the plotter transfers full lines, then null pads the remaining partial line if necessary. The bits in each byte follow left (msb) to right (lsb) nib writing order. .sh WARNINGS The byte array which is written must begin on a word boundary, and the count must be even. .sh "SPP Mode:" To use SPP, both the printer and plotter must be opened simultaneously. The printer is opened first as /dev/spp, followed by the plotter (/dev/vpp). The order should be as follows: .nf 1. write the text line 2. write 20 plot lines 3. write any additional plot lines .fi The plot line dots and the text characters are OR'd. .sh FILES .nf /dev/vpp plotter device /dev/lp printer /dev/spp SPP /dev/rvp raw mode plot .fi .sh DIAGNOSTICS "Bad System Call" returned for odd byte count or odd buffer address. .sh BUGS Turning off the plotter causes an annoying console message. neously. The printer is opened first as /dev/spp, followed by the plotter (/dev/vpp). The order sho# /* */ /* * RP disk driver */ #include "../param.h" #include "../buf.h" #include "../conf.h" #include "../user.h" struct { int rpds; int rper; int rpcs; int rpwc; int rpba; int rpca; int rpda; }; #define RPADDR 0176710 #define NRP 8 struct { char *nblocks; int cyloff; } rp_sizes[] { 40600, 0, /* cyl 0 thru 202 */ 40600, 203, /* cyl 203 thru 405 */ 9200, 0, /* cyl 0 thru 45 */ 9200, 360, /* cyl 360 thru 405 */ -1, 0, /* cyl 0 thru 327 */ -1, 78, /* cyl 78 thru 405 */ 15600, 0, /* cyl 0 thru 77 */ 15600, 328, /* cyl 328 thru 405 */ }; struct devtab rptab; struct buf rrpbuf; #define GO 01 #define RESET 0 #define HSEEK 014 #define IENABLE 0100 #define READY 0200 #define SUFU 01000 #define SUSU 02000 #define SUSI 04000 #define HNF 010000 /* * Use av_back to save track+sector, * b_resid for cylinder. */ #define trksec av_back #define cylin b_resid rpstrategy(abp) struct buf *abp; { register struct buf *bp; register char *p1, *p2; bp = abp; if(bp->b_flags&B_PHYS) mapalloc(bp); p1 = &rp_sizes[bp->b_dev.d_minor&07]; if (bp->b_dev.d_minor >= (NRP<<3) || bp->b_blkno >= p1->nblocks) { bp->b_flags =| B_ERROR; iodone(bp); return; } bp->av_forw = 0; bp->cylin = p1->cyloff; p1 = bp->b_blkno; p2 = lrem(p1, 10); p1 = ldiv(p1, 10); bp->trksec = (p1%20)<<8 | p2; bp->cylin =+ p1/20; spl5(); if ((p1 = rptab.d_actf)==0) rptab.d_actf = bp; else { for (; p2 = p1->av_forw; p1 = p2) { if (p1->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 *bp; if ((bp = rptab.d_actf) == 0) return; rptab.d_active++; RPADDR->rpda = bp->trksec; devstart(bp, &RPADDR->rpca, bp->cylin, bp->b_dev.d_minor>>3); } rpintr() { register struct buf *bp; register int ctr; if (rptab.d_active == 0) return; bp = rptab.d_actf; rptab.d_active = 0; if (RPADDR->rpcs < 0) { /* error bit */ deverror(bp, RPADDR->rper, RPADDR->rpds); if(RPADDR->rpds & (SUFU|SUSI|HNF)) { RPADDR->rpcs.lobyte = HSEEK|GO; ctr = 0; while ((RPADDR->rpds&SUSU) && --ctr); } RPADDR->rpcs = RESET|GO; ctr = 0; while ((RPADDR->rpcs&READY) == 0 && --ctr); if (++rptab.d_errcnt <= 10) { rpstart(); return; } bp->b_flags =| B_ERROR; } rptab.d_errcnt = 0; rptab.d_actf = bp->av_forw; bp->b_resid = RPADDR->rpwc; iodone(bp); rpstart(); } rpread(dev) { if(rpphys(dev)) physio(rpstrategy, &rrpbuf, dev, B_READ); } rpwrite(dev) { if(rpphys(dev)) physio(rpstrategy, &rrpbuf, dev, B_WRITE); } rpphys(dev) { register c; c = lshift(u.u_offset, -9); c =+ ldiv(u.u_count+511, 512); if(c > rp_sizes[dev.d_minor & 07].nblocks) { u.u_error = ENXIO; return(0); } return(1); } { rpstart(); return; } bp->b_flags =| B_ERROR; } rptab.d_errcnt = 0; rptab.d_actf = bp->av_forw; bp->b_resid = RPADDR->rpwc; iodone(bp); rpstart(); } rpread(dev) { if(rpphys(dev)) physio(rpstra# /* */ /* * indirect driver for controlling tty. */ #include "../param.h" #include "../conf.h" #include "../user.h" #include "../tty.h" #include "../proc.h" syopen(dev, flag) { register *tp; if(tp = syttyp()) (*cdevsw[tp->t_dev.d_major].d_open)(tp->t_dev, flag); } syread(dev) { register *tp; if(tp = syttyp()) (*cdevsw[tp->t_dev.d_major].d_read)(tp->t_dev); } sywrite(dev) { register *tp; if(tp = syttyp()) (*cdevsw[tp->t_dev.d_major].d_write)(tp->t_dev); } sysgtty(dev, flag) { register *tp; if(tp = syttyp()) (*cdevsw[tp->t_dev.d_major].d_sgtty)(tp->t_dev, flag); } syttyp() { register tp; tp = u.u_procp->p_ttyp; if(tp == NULL) u.u_error = ENXIO; return(tp); } gister *tp; if(tp = syttyp()) (*cdevsw[tp->t_dev.d_major].d_open)(tp->t_dev, flag); } syread(dev) { register *tp; if(tp = syttyp()) (*cdevsw[tp->t_dev.d_major].d_read)(tp->t_dev); } sywrite(dev) { register *tp; if(tp = syttyp()) (*cdevsw[tp->t_dev.d_major].d_write)(tp->t_dev); } sysgtty(dev, flag) { register *# /* */ /* * TC-11 DECtape driver */ #include "../param.h" #include "../conf.h" #include "../buf.h" #include "../user.h" struct { int tccsr; int tccm; int tcwc; int tcba; int tcdt; }; struct devtab tctab; char tcper[8]; #define TCADDR 0177340 #define NTCBLK 578 #define TAPERR 0100000 #define TREV 04000 #define READY 0200 #define IENABLE 0100 #define UPS 0200 #define ENDZ 0100000 #define BLKM 02000 #define ILGOP 010000 #define SELERR 04000 #define SAT 0 #define RNUM 02 #define RDATA 04 #define SST 010 #define WDATA 014 #define GO 01 #define SFORW 1 #define SREV 2 #define SIO 3 tcclose(dev) { bflush(dev); tcper[dev&07] = 0; } tcstrategy(abp) struct buf *abp; { register struct buf *bp; bp = abp; if(bp->b_flags&B_PHYS) mapalloc(bp); if(bp->b_blkno >= NTCBLK || tcper[bp->b_dev&07]) { bp->b_flags =| B_ERROR; iodone(bp); return; } bp->av_forw = 0; spl6(); if (tctab.d_actf==0) tctab.d_actf = bp; else tctab.d_actl->av_forw = bp; tctab.d_actl = bp; if (tctab.d_active==0) tcstart(); spl0(); } tcstart() { register struct buf *bp; register int *tccmp, com; loop: tccmp = &TCADDR->tccm; if ((bp = tctab.d_actf) == 0) return; if(tcper[bp->b_dev&07]) { if((tctab.d_actf = bp->av_forw) == 0) (*tccmp).lobyte = SAT|GO; bp->b_flags =| B_ERROR; iodone(bp); goto loop; } if (((*tccmp).hibyte&07) != bp->b_dev.d_minor) (*tccmp).lobyte = SAT|GO; tctab.d_errcnt = 20; tctab.d_active = SFORW; com = (bp->b_dev.d_minor<<8) | IENABLE|RNUM|GO; if ((TCADDR->tccsr & UPS) == 0) { com =| TREV; tctab.d_active = SREV; } *tccmp = com; } tcintr() { register struct buf *bp; register int *tccmp; register int *tcdtp; tccmp = &TCADDR->tccm; tcdtp = &TCADDR->tccsr; bp = tctab.d_actf; if (*tccmp&TAPERR) { if((*tcdtp&(ENDZ|BLKM)) == 0) deverror(bp, *tcdtp, 0); if(*tcdtp & (ILGOP|SELERR)) { tcper[bp->b_dev&07]++; tctab.d_errcnt = 0; } *tccmp =& ~TAPERR; if (--tctab.d_errcnt <= 0) { bp->b_flags =| B_ERROR; goto done; } if (*tccmp&TREV) { setforw: tctab.d_active = SFORW; *tccmp =& ~TREV; } else { setback: tctab.d_active = SREV; *tccmp =| TREV; } (*tccmp).lobyte = IENABLE|RNUM|GO; return; } tcdtp = &TCADDR->tcdt; switch (tctab.d_active) { case SIO: done: tctab.d_active = 0; if (tctab.d_actf = bp->av_forw) tcstart(); else TCADDR->tccm.lobyte = SAT|GO; iodone(bp); return; case SFORW: if (*tcdtp > bp->b_blkno) goto setback; if (*tcdtp < bp->b_blkno) goto setforw; *--tcdtp = bp->b_addr; /* core address */ *--tcdtp = bp->b_wcount; tccmp->lobyte = ((bp->b_xmem & 03) << 4) | IENABLE|GO | (bp->b_flags&B_READ?RDATA:WDATA); tctab.d_active = SIO; return; case SREV: if (*tcdtp+3 > bp->b_blkno) goto setback; goto setforw; } } ctive = 0; if (tctab.d_actf = bp->av_forw) tcstart(); else TCADDR->tccm.lobyte = SAT|GO; iodone(bp); return; case SFORW: if (*tcdtp > bp->b_blkno) goto setback; if (*tcdtp < bp->b_blkno) goto setforw; *--tcdtp = bp->b_addr; /* core # /* */ /* * TM tape driver */ #include "../param.h" #include "../buf.h" #include "../conf.h" #include "../user.h" struct { int tmer; int tmcs; int tmbc; int tmba; int tmdb; int tmrd; }; struct devtab tmtab; struct buf rtmbuf; char t_openf[8]; char *t_blkno[8]; char *t_nxrec[8]; #define TMADDR 0172520 #define GO 01 #define RCOM 02 #define WCOM 04 #define WEOF 06 #define SFORW 010 #define SREV 012 #define WIRG 014 #define REW 016 #define DENS 060000 /* 9-channel */ #define IENABLE 0100 #define CRDY 0200 #define GAPSD 010000 #define TUR 1 #define HARD 0102200 /* ILC, EOT, NXM */ #define EOF 0040000 #define SSEEK 1 #define SIO 2 tmopen(dev, flag) { register dminor; dminor = dev.d_minor; if (t_openf[dminor]) u.u_error = ENXIO; else { t_openf[dminor]++; t_blkno[dminor] = 0; t_nxrec[dminor] = 65535; } } tmclose(dev, flag) { register int dminor; dminor = dev.d_minor; t_openf[dminor] = 0; if (flag) tcommand(dminor, WEOF); tcommand(dminor, REW); } tcommand(unit, com) { extern lbolt; while (tmtab.d_active || (TMADDR->tmcs & CRDY)==0) sleep(&lbolt, 1); TMADDR->tmcs = DENS|com|GO | (unit<<8); } tmstrategy(abp) struct buf *abp; { register struct buf *bp; register char **p; bp = abp; p = &t_nxrec[bp->b_dev.d_minor]; if (*p <= bp->b_blkno) { 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(); } tmstart() { register struct buf *bp; register int com; int unit; register char *blkno; loop: if ((bp = tmtab.d_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) | ((bp->b_xmem & 03) << 4) | IENABLE|DENS; if (blkno != bp->b_blkno) { tmtab.d_active = SSEEK; if (blkno < bp->b_blkno) { com =| SFORW|GO; TMADDR->tmbc = blkno - bp->b_blkno; } else { if (bp->b_blkno == 0) com =| REW|GO; else { com =| SREV|GO; TMADDR->tmbc = bp->b_blkno - blkno; } } TMADDR->tmcs = com; return; } tmtab.d_active = SIO; TMADDR->tmbc = bp->b_wcount << 1; TMADDR->tmba = bp->b_addr; /* core address */ TMADDR->tmcs = com | ((bp->b_flags&B_READ)? RCOM|GO: ((tmtab.d_errcnt)? WIRG|GO: WCOM|GO)); } tmintr() { register struct buf *bp; register int unit; if ((bp = tmtab.d_actf)==0) return; unit = bp->b_dev.d_minor; if (TMADDR->tmcs < 0) { /* error bit */ /* deverror(bp, TMADDR->tmer); */ while(TMADDR->tmrd & GAPSD) ; /* wait for gap shutdown */ if ((TMADDR->tmer&(HARD|EOF))==0 && tmtab.d_active==SIO) { if (++tmtab.d_errcnt < 10) { t_blkno[unit]++; tmtab.d_active = 0; tmstart(); return; } } else if(bp != &rtmbuf && (TMADDR->tmer&EOF)==0) t_openf[unit] = -1; bp->b_flags =| B_ERROR; tmtab.d_active = SIO; } if (tmtab.d_active == SIO) { tmtab.d_errcnt = 0; t_blkno[unit]++; tmtab.d_actf = bp->av_forw; tmtab.d_active = 0; iodone(bp); bp->b_resid = TMADDR->tmbc; } else t_blkno[unit] = bp->b_blkno; tmstart(); } tmread(dev) { tmphys(dev); physio(tmstrategy, &rtmbuf, dev, B_READ); u.u_count = -rtmbuf.b_resid; } tmwrite(dev) { tmphys(dev); physio(tmstrategy, &rtmbuf, dev, B_WRITE); u.u_count = 0; } tmphys(dev) { register unit, a; unit = dev.d_minor; a = lshift(u.u_offset, -9); t_blkno[unit] = a; t_nxrec[unit] = ++a; } mtab.d_errcnt = 0; t_blkno[unit]++; tmtab.d_actf = bp->av_forw; tmtab.d_active = 0; iodone(bp); bp->b_resid = TMADDR->tmbc; } else t_blkno[unit] = bp->b_blkno; tmstart(); } tmread(dev) { tmphys(dev); physio(tmstrategy, &rtmbuf, dev, B_READ); u.u_count = -rtmbuf.b_resid; } tmwrite(dev) { tmphys(dev); physio(tmstrategy, &rtmbuf, dev, B_WRITE); u.u_count = 0; }# /* * Device Driver for the Ramtek 9351: * * Computer Aided Design and Graphics Lab * Purdue University * W. Lafayette, IN 47907 * (317) 493-9385 * * 10/26/79 * */ #include "../param.h" #include "../user.h" #include "../conf.h" #include "../buf.h" #define ADDR 0172466 /* unibus address */ /* DRIF command/status bits: */ #define ER 0100000 /* error bit */ #define NEX 040000 /* non-existant memory */ #define AID 01000 /* set = turn auto-increment off for dma */ #define RDY 0200 /* set = ready */ #define IE 0100 /* set = enable interrupts */ #define GIE 010 #define DIO 02 /* dma direction (set=receive from ramtek) */ #define GO 01 /* start dma! */ /* ramtek functions: */ #define RCUR 013400 /* read ramtek cursor */ #define WCUR 013000 /* write ramtek cursor */ #define RKB 014400 /* read ramtek kb */ /* etc. */ #define NTRIES 50 /* # times to wait for a ready before sleeping */ #define RMPRI 10 /* priority sleeping on */ #define VIS 002000 #define KBNODAT 020000 #define CUREN 020000 /* minor devices: */ #define DMA 0 #define PIO 1 #define KEYBOARD 2 /* GPIF command word: */ #define RESET 0100000 #define WRVE 0010000 #define WMXE 0004000 #define WPRE 0002000 /* GPIF status word: */ #define RPRE 010000 /* rm.flags definitions: */ /* Note: IE also set in rm.flags*/ #define WAITKB 0100000 #define WAITEN 040000 #define NOINCR 000004 /* stty "command" flag bit */ #define SETCUR 01 /* unibus structure: */ struct { int gpcsr; int drwc; int drba; int drst; int gpdata; }; /* our own flags: */ struct { int procp; int flags; } rm; /* structures to be used by physio: */ struct buf rmbuf; rmopen(dev,flag) { if( rm.procp != 0 ){ if( rm.procp != u.u_procp ) u.u_error = ENXIO; return; } spl5(); ADDR->drst = IE; /* enable interrupts so will sleep till ready */ rm.flags=IE; ADDR->gpcsr = RESET; rmrdy(); /*does spl0*/ if( ADDR->drst&ER ) { /* see if device is even there */ u.u_error = EIO; printf("Ramtek Error,drst=%o\n",ADDR->drst); return; } rm.procp = u.u_procp; } /* close the ramtek: */ rmclose(dev) { rmrdy(); /* be sure all transmissions are done */ ADDR->drst = 0; /* disable interrupts */ ADDR->gpcsr = 0; rm.procp = 0; } /* interrupt handler: */ rmint( dev ) { if( rm.flags&IE ) { /* waiting for a dr int */ rm.flags &= ~IE; ADDR->drst &= ~(IE|GIE); rmbuf.b_flags |= B_DONE; wakeup( &rmbuf ); }else printf("Ramtek Error, Unexp Int\n"); } /* read (do different things depending on the minor device): */ rmread(dev) { int rmstrategy(); register w; rmrdy(); switch( dev.d_minor ) { case DMA: physio(&rmstrategy , &rmbuf , dev , B_READ); break; case PIO: directio(B_READ); break; case KEYBOARD: if( u.u_count!=2 ) { u.u_error = ENXIO; return; } kbloop: clearpre(); /* clear the pre-fetch bit */ wrrm( RKB ); rmrdy(); setpre(); w= rdrm(); if( (w&KBNODAT)==0 || (rm.flags&WAITKB)==0){ suword(u.u_base,w); return; } rmrdy(); spl5(); rm.flags |= IE; ADDR->drst |= ( IE | GIE); ADDR->gpcsr = WRVE; sleep( &rmbuf, RMPRI); spl0(); rmrdy(); goto kbloop; } } /* write (do different things depending on the minor device): */ rmwrite(dev) { int rmstrategy(); rmrdy(); switch( dev.d_minor ) { case DMA: physio(&rmstrategy , &rmbuf , dev , B_WRITE); break; case PIO: directio(B_WRITE); break; case KEYBOARD: u.u_error = ENXIO; return; } } /* perform programmed i/o: */ directio( flag ) { register int count , *base; count = u.u_count; if( (count<=0) || (count&01)!=0 ){ u.u_error = EIO; return; } count >>= 1; /* words, not bytes */ base = u.u_base; if( (char *)base & 01){ u.u_error = EIO; return; } switch( flag ) { case B_READ: setpre(); /* set the pre-fetch bit */ while( count-- ) suword( base++, rdrm() ); break; case B_WRITE: clearpre(); while( count-- ) wrrm( fuword(base++) ); break; } } /* wait till ramtek interface is ready: */ rmrdy() { extern int lbolt; register int n; for(;;) { for(n=0; n<=NTRIES; n++){ if( ADDR->drst&RDY ){ if( ADDR->drst&ER ) printf("Ramtek Error,drst=%o\n",ADDR->drst); return; } } spl5(); if( rm.flags&IE ){ sleep(&rmbuf , RMPRI); spl0(); }else{ spl0(); sleep(&lbolt , RMPRI); } } } /* set the pre-fetch bit if not already set: */ /* (assume rmrdy has been called prior to coming here) */ setpre() { if( ADDR->gpcsr&RPRE ) return; /* already set */ ADDR->gpcsr = WPRE; /* set it (and nothing else in the gpcsr) */ rmrdy(); } /* clear the pre-fetch bit if not already cleared: */ /* (assume rmrdy has been called prior to coming here) */ clearpre() { if( ADDR->gpcsr&RPRE ) { ADDR->gpcsr = 0; rmrdy(); } } /* strategy routine for the dma: */ /* Note: this is really strategy and start put together*/ rmstrategy(abp) struct buf *abp; { register struct buf *bp; register int cmd; register char *p; p = ADDR; bp = abp; p->drba = bp->b_addr; cmd = (bp->b_xmem&03) << 4; if( rm.flags&NOINCR ) { cmd |= AID; rm.flags &= ~NOINCR; } if( bp->b_flags&B_READ ) { setpre(); cmd |= DIO; } else clearpre(); p->drwc = -(u.u_count>>1); p->drst = cmd|IE; rm.flags |= IE; p->drst++; /* GO */ } /* read or write to the joystick via gtty and stty: */ rmsgtty(dev , av) int *av; { register int *v; register w; register char *p; rmrdy(); p = ADDR; if( v=av ){ /* gtty */ enloop: clearpre(); wrrm(RCUR); rmrdy(); setpre(); v[0] = rdrm(); w = v[1] = rdrm(); v[2] = rm.flags; if( (w&CUREN) !=0 || (rm.flags&WAITEN)==0) return; spl5(); rm.flags |= IE; p->drst |= (IE|GIE); p->gpcsr = WMXE; sleep( &rmbuf,RMPRI); spl0(); rmrdy(); goto enloop; } else { /* stty */ w= u.u_arg[2]; if( (w&SETCUR) == 0){ rm.flags = u.u_arg[2] & ~(IE|WMXE|WRVE); return; } /* else set cursor command */ clearpre(); wrrm(WCUR); wrrm(u.u_arg[0]); wrrm(u.u_arg[1] | VIS); } } rdrm() { register char *p; p = ADDR; while( (p->drst & RDY) == 0) /*null*/; return( p->gpdata ); } wrrm(w) { register char *p; p = ADDR; while( (p->drst & RDY) == 0) /*null*/; p->gpdata = w; } ->gpcsr = WMXE; sleep( &rmbuf,RMPRI); spl0(); rmrdy(); goto enloop; } else { /* stty */ w= u.u_arg[2]; if( (w&SETCUR) == 0){ rm.flags = u.u_arg[2] & ~(IE|WMXE|WRVE); return; } /* else set cursor command */ clearpre(); wrrm(WCUR); wrrm(u.u_arg[0]); wrrm(u.u_arg[1] | VIS); } } rdrm() { register char *p; p = ADDR; while( (p->drst & RDY) == 0) /*null*/; re break; } if ('a'<=c && c<='z') c =+ 'A' - 'a'; } /* * turn to if desired. */ if (c=='\n' && rtp->t_flags&CRMOD) ttyoutput('\r', rtp); if (putc(c, &rtp->t_outq)) return; /* * Calculate delays. * The numbers here represent clock ticks * and are not necessarily optimal for all terminals. * The delays are indicated by characters above 0200, * thus (unfortunately) restricting the transmission * path to 7 bits. */ colp = &rtp->t_col; ctype = partab[c]; c = 0; switch (ctype&077) { /* ordinary */ case 0: (*colp)++; /* non-printing */ case 1: break; /* backspace */ case 2: if (*colp) (*colp)--; break; /* newline */ case 3: ctype = (rtp->t_flags >> 8) & 03; if(ctype == 1) { /* tty 37 */ if (*colp) c = max((*colp>>4) + 3, 6); } else if(ctype == 2) { /* vt05 */ c = 6; } *colp = 0; break; /* tab */ case 4: ctype = (rtp->t_flags >> 10) & 03; if(ctype == 1) { /* tty 37 */ c = 1 - (*colp | ~07); if(c < 5) c = 0; } *colp =| 07; (*colp)++; break; /* vertical motion */ case 5: if(rtp->t_flags & VTDELAY) /* tty 37 */ c = 0177; break; /* carriage return */ case 6: ctype = (rtp->t_flags >> 12) & 03; if(ctype == 1) { /* tn 300 */ c = 5; } else if(ctype == 2) { /* ti 700 */ c = 10; } *colp = 0; } if(c) putc(c|0200, &rtp->t_outq); } /* * Restart typewriter output following a delay * timeout. * The name of the routine is passed to the timeout * subroutine and it is called during a clock interrupt. */ ttrstrt(atp) { register struct tty *tp; tp = atp; tp->t_state =& ~TIMEOUT; ttstart(tp); } /* * Start output on the typewriter. It is used from the top half * after some characters have been put on the output queue, * from the interrupt routine to transmit the next * character, and after a timeout has finished. * If the SSTART bit is off for the tty the work is done here, * using the protocol of the single-line interfaces (KL, DL, DC); * otherwise the address word of the tty structure is * taken to be the name of the device-dependent startup routine. */ ttstart(atp) struct tty *atp; { register int *addr, c; register struct tty *tp; struct { int (*func)(); }; tp = atp; addr = tp->t_addr; if (tp->t_state&SSTART) { (*addr.func)(tp); return; } if ((addr->tttcsr&DONE)==0 || tp->t_state&TIMEOUT) return; if ((c=getc(&tp->t_outq)) >= 0) { if( tp->t_flags&RAW) { addr->tttbuf = c; return; } if (c<=0177) addr->tttbuf = c | (partab[c]&0200); else { timeout(ttrstrt, tp, c&0177); tp->t_state =| TIMEOUT; } } } /* * Called from device's read routine after it has * calculated the tty-structure given as argument. * The pc is backed up for the duration of this call. * In case of a caught interrupt, an RTI will re-execute. */ ttread(atp) struct tty *atp; { register struct tty *tp; tp = atp; if ((tp->t_state&CARR_ON)==0) return; if (tp->t_canq.c_cc || canon(tp)) while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0); } /* * Called from the device's write routine after it has * calculated the tty-structure given as argument. */ ttwrite(atp) struct tty *atp; { register struct tty *tp; register int c; tp = atp; if ((tp->t_state&CARR_ON)==0) return; while ((c=cpass())>=0) { spl5(); while (tp->t_outq.c_cc > TTHIWAT) { ttstart(tp); tp->t_state =| ASLEEP; sleep(&tp->t_outq, TTOPRI); } spl0(); ttyoutput(c, tp); } ttstart(tp); } /* * Common code for gtty and stty functions on typewriters. * If v is non-zero then gtty is being done and information is * passed back therein; * if it is zero stty is being done and the input information is in the * u_arg array. */ ttystty(atp, av) int *atp, *av; { register *tp, *v; tp = atp; if(v = av) { *v++ = tp->t_speeds; v->lobyte = tp->t_erase; v->hibyte = tp->t_kill; v[1] = tp->t_flags; return(1); } wflushtty(tp); v = u.u_arg; tp->t_speeds = *v++; tp->t_erase = v->lobyte; tp->t_kill = v->hibyte; tp->t_flags = v[1]; return(0); } * If v is non-zero # /* */ /* * Screw Works interface via DC-11 */ #include "../tty.h" #define VSADDR 0174150 #define CDLEAD 01 #define B1200 030 #define STOP1 0400 #define CLSEND 02 #define RQSEND 01 #define MAGIC_MAP 0377 struct { int vsrcsr; int vsrbuf; int vsxcsr; int vsxbuf; }; struct { struct clist iq; struct clist oq; } vs; vsopen(dev) { VSADDR->vsrcsr = IENABLE|B1200|CDLEAD; VSADDR->vsxcsr = STOP1|IENABLE|B1200; vschar(0); } vsclose(dev) { vschar(0); VSADDR->vsrcsr =& ~IENABLE; while (getc(&vs.iq) >= 0); } vswrite(dev) { register int count, c; count = 0; while ((c=cpass()) >= 0) { if (--count <= 0) { count = 60; vschar(0); } vschar(c); } vschar(0); } vschar(c) { c =^ MAGIC_MAP; spl5(); while (vs.oq.c_cc > 60) { vsxintr(); sleep(&vs.oq, TTIPRI); } putc(c, &vs.oq); vsxintr(); spl0(); } vsxintr() { static lchar; register c; register int *xcsr; xcsr = &VSADDR->vsxcsr; if (*xcsr&DONE) { if (lchar==MAGIC_MAP) { *xcsr =& ~RQSEND; lchar = 0; if (vs.oq.c_cc==0) goto wake; } if ((*xcsr&CLSEND) == 0) { *xcsr =& ~RQSEND; *xcsr =| RQSEND; if ((*xcsr&CLSEND) == 0) goto wake; } if ((c = getc(&vs.oq)) >= 0) VSADDR->vsxbuf = lchar = c; if (vs.oq.c_cc <= 15) wake: wakeup(&vs.oq); } } 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.iq); } goto wake; } if ((*xcsr&CLSEND) == 0) { *xcsr =& ~RQSEND; *xcsr =| RQSEND; if ((*xcsr&CLSEND) == 0) goto wake; } if ((c = getc(&vs.oq)) >= 0) VSADDR->vsxbuf = lchar = c; if (vs.oq.c_cc <= 15) wake: wakeup(&vs.oq); } } 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.# /* */ /* * 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); } } IENABL; } vtclose() { VTADDR->buf = SEOF; VTADDR->csr =| RQINT; } vtwrite() { register int c; int register count; while ((c=cpass()) >= 0) { retry: for (count=0; count<10; cou/* */ int (*bdevsw[])() { &nulldev, &nulldev, &rkstrategy, &rktab, /* rk */ &nodev, &nodev, &nodev, 0, /* rp */ &nodev, &nodev, &nodev, 0, /* rf */ &nodev, &nodev, &nodev, 0, /* tm */ &nulldev, &tcclose, &tcstrategy, &tctab, /* tc */ &vpopen, &vpclose, &vpstrategy, &vptab, /* vpp */ &nodev, &nodev, &nodev, 0, /* hp */ &nodev, &nodev, &nodev, 0, /* ht */ 0 }; int (*cdevsw[])() { &klopen, &klclose, &klread, &klwrite, &klsgtty, /* console */ &nodev, &nodev, &nodev, &nodev, &nodev, /* pc */ &vlopen, &vlclose, &nodev, &vlwrite, &nodev, /* vlp */ &nodev, &nodev, &nodev, &nodev, &nodev, /* dc */ &nodev, &nodev, &nodev, &nodev, &nodev, /* dh */ &nodev, &nodev, &nodev, &nodev, &nodev, /* dp */ &dropen, &drclose, &drread, &drwrite, &nodev, /* dr */ &nodev, &nodev, &nodev, &nodev, &nodev, /* dn */ &nulldev, &nulldev, &mmread, &mmwrite, &nodev, /* mem */ &nulldev, &nulldev, &rkread, &rkwrite, &nodev, /* rk */ &nodev, &nodev, &nodev, &nodev, &nodev, /* rf */ &nodev, &nodev, &nodev, &nodev, &nodev, /* rp */ &nodev, &nodev, &nodev, &nodev, &nodev, /* tm */ &vpopen, &vpclose, &nodev, &vpwrite, &vpctl, /* rvpp */ &rmopen, &rmclose, &rmread, &rmwrite, &rmsgtty, /* ramtek - rm */ &nodev, &nodev, &nodev, &nodev, &nodev, /* ? */ &xxopen, &xxclose, &xxread, &nodev, &nodev, /* 16 = high speed xfer */ &megopen, &megclose, &megread, &megwrite, &mgsgtty, /* megatek */ 0 }; int rootdev {(0<<8)|0}; int swapdev {(0<<8)|0}; int swplo 4000; /* cannot be zero */ int nswap 872; &nodev, &nodev, &nodev, /* tm */ &vpopen, &vpclose, &nodev, &vpwrite, &vpctl, /* rvpp */ &rmopen, &rmclose, &rmread, &rmwrite, &rmsgtty, /* ramtek - rm */ &nodev, &nodev, &nodev, &nodev, &nodev, /* ? */ &xxopen, &xxclose, &xxread, &nodev, &nodev, /* 16 = h/ low core br4 = 200 br5 = 240 br6 = 300 br7 = 340 . = 0^. br 1f 4 / trap vectors trap; br7+0. / bus error trap; br7+1. / illegal instruction trap; br7+2. / bpt-trace trap trap; br7+3. / iot trap trap; br7+4. / power fail trap; br7+5. / emulator trap trap; br7+6. / system entry . = 40^. .globl start, dump 1: jmp start jmp dump . = 60^. klin; br4 klou; br4 . = 100^. kwlp; br6 kwlp; br6 . = 114^. trap; br7+7. / 11/70 parity . = 140^. ramint; br5 / ramtek ramint; br5 / ramtek . = 174^. vpint; br4+0. / versatec plotter . = 200^. vlint; br4+0 / versatec lp (vlp) . = 214^. tcio; br6 . = 220^. rkio; br5 . = 240^. trap; br7+7. / programmed interrupt trap; br7+8. / floating point trap; br7+9. / segmentation violation / floating vectors . = 300^. drout; br5+1. drin ; br5+1. drout; br5+0. drin ; br5+0. . = 320^. klin; br4+1. klou; br4+1. klin; br4+2. klou; br4+2. klin; br4+3. klou; br4+3. klin; br4+4. klou; br4+4. . = 370^. mgint; br5 mgpint; br4 ////////////////////////////////////////////////////// / interface code to C ////////////////////////////////////////////////////// .globl call, trap / serial ports: .globl _klrint klin: jsr r0,call; _klrint .globl _klxint klou: jsr r0,call; _klxint .globl _clock kwlp: jsr r0,call; _clock .globl _tcintr tcio: jsr r0,call; _tcintr / rk05 disk: .globl _rkintr rkio: jsr r0,call; _rkintr / parallel interfaces to imlacs: .globl _drrint drin: jsr r0,call; _drrint .globl _drxint drout: jsr r0,call; _drxint / versatek: .globl _vlint vlint: jsr r0,call; _vlint .globl _vpint vpint: jsr r0,call; _vpint / ramtek: .globl _rmint ramint: jsr r0,call; _rmint / megatek graphics and peripherals: .globl _megintr mgint: jsr r0,call; _megintr .globl _megpintr mgpint: jsr r0,call; _megpintr clock .globl _tcintr tcio: jsr r0,call; _tcintr / rk05 disk: .globl _rkintr rkio: jsr r0,call; _rkintr / parallel interfaces to imlacs: .globl _drrint drin: jsr r0,call; _drrint .globl _drxint drout: jsr r0,call; _drxint / l45.o needs to be in data space / to get l45.o; as data.s l.s .data &nodev, &nodev, &nodev, &nodev, &nodev, /* rp */ &nodev, &nodev, &nodev, &nodev, &nodev, /* tm */ &nodev, &nodev, &nodev, &nodev, &nodev, /* hs */ &nodev, &nodev, &nodev, &nodev, &nodev, /* hp */ &nodev, &nodev, &nodev, &nodev, &nodev, /* ht */ 0 }; int rootdev {(0<<8)|0}; int swapdev {(0<<8)|0}; int swplo 4000; /* cannot be zero */ int nswap 872; d, &rkwrite, &nodev, /*/ machine language assist / for 11/40 / non-UNIX instructions mfpi = 6500^tst mtpi = 6600^tst wait = 1 rtt = 6 reset = 5 .globl trap, call .globl _trap trap: mov PS,-4(sp) tst nofault bne 1f mov SSR0,ssr mov SSR2,ssr+4 mov $1,SSR0 jsr r0,call1; _trap / no return 1: mov $1,SSR0 mov nofault,(sp) rtt .globl _runrun, _swtch call1: tst -(sp) bic $340,PS br 1f call: mov PS,-(sp) 1: mov r1,-(sp) mfpi sp mov 4(sp),-(sp) bic $!37,(sp) bit $30000,PS beq 1f jsr pc,*(r0)+ 2: bis $340,PS tstb _runrun beq 2f bic $340,PS jsr pc,_swtch br 2b 2: tst (sp)+ mtpi sp br 2f 1: bis $30000,PS jsr pc,*(r0)+ cmp (sp)+,(sp)+ 2: mov (sp)+,r1 tst (sp)+ mov (sp)+,r0 rtt .globl _savfp, _display _savfp: _display: rts pc .globl _incupc _incupc: mov r2,-(sp) mov 6(sp),r2 / base of prof with base,leng,off,scale mov 4(sp),r0 / pc sub 4(r2),r0 / offset clc ror r0 mul 6(r2),r0 / scale ashc $-14.,r0 inc r1 bic $1,r1 cmp r1,2(r2) / length bhis 1f add (r2),r1 / base mov nofault,-(sp) mov $2f,nofault mfpi (r1) inc (sp) mtpi (r1) br 3f 2: clr 6(r2) 3: mov (sp)+,nofault 1: mov (sp)+,r2 rts pc / Character list get/put .globl _getc, _putc .globl _cfreelist _getc: mov 2(sp),r1 mov PS,-(sp) mov r2,-(sp) bis $340,PS bic $100,PS / spl 5 mov 2(r1),r2 / first ptr beq 9f / empty movb (r2)+,r0 / character bic $!377,r0 mov r2,2(r1) dec (r1)+ / count bne 1f clr (r1)+ clr (r1)+ / last block br 2f 1: bit $7,r2 bne 3f mov -10(r2),(r1) / next block add $2,(r1) 2: dec r2 bic $7,r2 mov _cfreelist,(r2) mov r2,_cfreelist 3: mov (sp)+,r2 mov (sp)+,PS rts pc 9: clr 4(r1) mov $-1,r0 mov (sp)+,r2 mov (sp)+,PS rts pc _putc: mov 2(sp),r0 mov 4(sp),r1 mov PS,-(sp) mov r2,-(sp) mov r3,-(sp) bis $340,PS bic $100,PS / spl 5 mov 4(r1),r2 / last ptr bne 1f mov _cfreelist,r2 beq 9f mov (r2),_cfreelist clr (r2)+ mov r2,2(r1) / first ptr br 2f 1: bit $7,r2 bne 2f mov _cfreelist,r3 beq 9f mov (r3),_cfreelist mov r3,-10(r2) mov r3,r2 clr (r2)+ 2: movb r0,(r2)+ mov r2,4(r1) inc (r1) / count clr r0 mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,PS rts pc 9: mov pc,r0 mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,PS rts pc .globl _backup .globl _regloc _backup: mov 2(sp),ssr+2 mov r2,-(sp) jsr pc,backup mov r2,ssr+2 mov (sp)+,r2 movb jflg,r0 bne 2f mov 2(sp),r0 movb ssr+2,r1 jsr pc,1f movb ssr+3,r1 jsr pc,1f movb _regloc+7,r1 asl r1 add r0,r1 mov ssr+4,(r1) clr r0 2: rts pc 1: mov r1,-(sp) asr (sp) asr (sp) asr (sp) bic $!7,r1 movb _regloc(r1),r1 asl r1 add r0,r1 sub (sp)+,(r1) rts pc / hard part / simulate the ssr2 register missing on 11/40 backup: clr r2 / backup register ssr1 mov $1,bflg / clrs jflg mov ssr+4,r0 jsr pc,fetch mov r0,r1 ash $-11.,r0 bic $!36,r0 jmp *0f(r0) 0: t00; t01; t02; t03; t04; t05; t06; t07 t10; t11; t12; t13; t14; t15; t16; t17 t00: clrb bflg t10: mov r1,r0 swab r0 bic $!16,r0 jmp *0f(r0) 0: u0; u1; u2; u3; u4; u5; u6; u7 u6: / single op, m[tf]pi, sxt, illegal bit $400,r1 beq u5 / all but m[tf], sxt bit $200,r1 beq 1f / mfpi bit $100,r1 bne u5 / sxt / simulate mtpi with double (sp)+,dd bic $4000,r1 / turn instr into (sp)+ br t01 / simulate mfpi with double ss,-(sp) 1: ash $6,r1 bis $46,r1 / -(sp) br t01 u4: / jsr mov r1,r0 jsr pc,setreg / assume no fault bis $173000,r2 / -2 from sp rts pc t07: / EIS clrb bflg u0: / jmp, swab u5: / single op mov r1,r0 br setreg t01: / mov t02: / cmp t03: / bit t04: / bic t05: / bis t06: / add t16: / sub clrb bflg t11: / movb t12: / cmpb t13: / bitb t14: / bicb t15: / bisb mov r1,r0 ash $-6,r0 jsr pc,setreg swab r2 mov r1,r0 jsr pc,setreg / if delta(dest) is zero, / no need to fetch source bit $370,r2 beq 1f / if mode(source) is R, / no fault is possible bit $7000,r1 beq 1f / if reg(source) is reg(dest), / too bad. mov r2,-(sp) bic $174370,(sp) cmpb 1(sp),(sp)+ beq t17 / start source cycle / pick up value of reg mov r1,r0 ash $-6,r0 bic $!7,r0 movb _regloc(r0),r0 asl r0 add ssr+2,r0 mov (r0),r0 / if reg has been incremented, / must decrement it before fetch bit $174000,r2 ble 2f dec r0 bit $10000,r2 beq 2f dec r0 2: / if mode is 6,7 fetch and add X(R) to R bit $4000,r1 beq 2f bit $2000,r1 beq 2f mov r0,-(sp) mov ssr+4,r0 add $2,r0 jsr pc,fetch add (sp)+,r0 2: / fetch operand / if mode is 3,5,7 fetch * jsr pc,fetch bit $1000,r1 beq 1f bit $6000,r1 bne fetch 1: rts pc t17: / illegal u1: / br u2: / br u3: / br u7: / illegal incb jflg rts pc setreg: mov r0,-(sp) bic $!7,r0 bis r0,r2 mov (sp)+,r0 ash $-3,r0 bic $!7,r0 movb 0f(r0),r0 tstb bflg beq 1f bit $2,r2 beq 2f bit $4,r2 beq 2f 1: cmp r0,$20 beq 2f cmp r0,$-20 beq 2f asl r0 2: bisb r0,r2 rts pc 0: .byte 0,0,10,20,-10,-20,0,0 fetch: bic $1,r0 mov nofault,-(sp) mov $1f,nofault mfpi (r0) mov (sp)+,r0 mov (sp)+,nofault rts pc 1: mov (sp)+,nofault clrb r2 / clear out dest on fault mov $-1,r0 rts pc .bss bflg: .=.+1 jflg: .=.+1 .text .globl _fubyte, _subyte .globl _fuibyte, _suibyte .globl _fuword, _suword .globl _fuiword, _suiword _fuibyte: _fubyte: mov 2(sp),r1 bic $1,r1 jsr pc,gword cmp r1,2(sp) beq 1f swab r0 1: bic $!377,r0 rts pc _suibyte: _subyte: mov 2(sp),r1 bic $1,r1 jsr pc,gword mov r0,-(sp) cmp r1,4(sp) beq 1f movb 6(sp),1(sp) br 2f 1: movb 6(sp),(sp) 2: mov (sp)+,r0 jsr pc,pword clr r0 rts pc _fuiword: _fuword: mov 2(sp),r1 fuword: jsr pc,gword rts pc gword: mov PS,-(sp) bis $340,PS mov nofault,-(sp) mov $err,nofault mfpi (r1) mov (sp)+,r0 br 1f _suiword: _suword: mov 2(sp),r1 mov 4(sp),r0 suword: jsr pc,pword rts pc pword: mov PS,-(sp) bis $340,PS mov nofault,-(sp) mov $err,nofault mov r0,-(sp) mtpi (r1) 1: mov (sp)+,nofault mov (sp)+,PS rts pc err: mov (sp)+,nofault mov (sp)+,PS tst (sp)+ mov $-1,r0 rts pc / / system mod : store a character in user space / used with high speed transfers / -- mjb 04/17/79 / / sufet(char , PAR , offset) / .globl _sufet _sufet: mov 6(sp),r0 / offset from P A R add $40000,r0 / set flag for Page Address 2 mov r0,r1 mov PS,-(sp) / save status mov KISA2,-(sp) / save PAR 2 bis $340,PS / set priority to 7 (an interrupt would be a disaster now!) mov 10(sp),KISA2 / point PAR to user space add (r0),r1 / r1 has address where char should go inc (r0) / inc. "in" pointer movb 6(sp),(r1) / store char cmp (r0)+,(r0) / see if "in" pointer is at the limit (wrapping) bne 2f / no - continue mov $10,-2(r0) / 8 -> "in" 2: cmp -(r0),4(r0) / "in" = "out" ? bne 3f / no - no overflow yet inc 6(r0) / increment overflow flag 3: mov (sp)+,KISA2 / replace Page Address Register 2 mov (sp)+,PS / replace PS rts pc .globl _copyin, _copyout _copyin: jsr pc,copsu 1: mfpi (r0)+ mov (sp)+,(r1)+ sob r2,1b br 2f _copyout: jsr pc,copsu 1: mov (r0)+,-(sp) mtpi (r1)+ sob r2,1b 2: mov (sp)+,nofault mov (sp)+,r2 clr r0 rts pc copsu: mov (sp)+,r0 mov r2,-(sp) mov nofault,-(sp) mov r0,-(sp) mov 10(sp),r0 mov 12(sp),r1 mov 14(sp),r2 asr r2 mov $1f,nofault rts pc 1: mov (sp)+,nofault mov (sp)+,r2 mov $-1,r0 rts pc .globl _idle _idle: mov PS,-(sp) bic $340,PS wait mov (sp)+,PS rts pc .globl _savu, _retu, _aretu _savu: bis $340,PS mov (sp)+,r1 mov (sp),r0 mov sp,(r0)+ mov r5,(r0)+ bic $340,PS jmp (r1) _aretu: bis $340,PS mov (sp)+,r1 mov (sp),r0 br 1f _retu: bis $340,PS mov (sp)+,r1 mov (sp),KISA6 mov $_u,r0 1: mov (r0)+,sp mov (r0)+,r5 bic $340,PS jmp (r1) .globl _spl0, _spl1, _spl4, _spl5, _spl6, _spl7 _spl0: bic $340,PS rts pc _spl1: bis $40,PS bic $300,PS rts pc _spl4: _spl5: bis $340,PS bic $100,PS rts pc _spl6: bis $340,PS bic $40,PS rts pc _spl7: bis $340,PS rts pc .globl _copyseg _copyseg: mov PS,-(sp) mov UISA0,-(sp) mov UISA1,-(sp) mov $30340,PS mov 10(sp),UISA0 mov 12(sp),UISA1 mov UISD0,-(sp) mov UISD1,-(sp) mov $6,UISD0 mov $6,UISD1 mov r2,-(sp) clr r0 mov $8192.,r1 mov $32.,r2 1: mfpi (r0)+ mtpi (r1)+ sob r2,1b mov (sp)+,r2 mov (sp)+,UISD1 mov (sp)+,UISD0 mov (sp)+,UISA1 mov (sp)+,UISA0 mov (sp)+,PS rts pc .globl _clearseg _clearseg: mov PS,-(sp) mov UISA0,-(sp) mov $30340,PS mov 6(sp),UISA0 mov UISD0,-(sp) mov $6,UISD0 clr r0 mov $32.,r1 1: clr -(sp) mtpi (r0)+ sob r1,1b mov (sp)+,UISD0 mov (sp)+,UISA0 mov (sp)+,PS rts pc .globl _dpadd _dpadd: mov 2(sp),r0 add 4(sp),2(r0) adc (r0) rts pc .globl _dpcmp _dpcmp: mov 2(sp),r0 mov 4(sp),r1 sub 6(sp),r0 sub 8(sp),r1 sbc r0 bge 1f cmp r0,$-1 bne 2f cmp r1,$-512. bhi 3f 2: mov $-512.,r0 rts pc 1: bne 2f cmp r1,$512. blo 3f 2: mov $512.,r1 3: mov r1,r0 rts pc .globl dump dump: bit $1,SSR0 bne dump / save regs r0,r1,r2,r3,r4,r5,r6,KIA6 / starting at abs location 4 mov r0,4 mov $6,r0 mov r1,(r0)+ mov r2,(r0)+ mov r3,(r0)+ mov r4,(r0)+ mov r5,(r0)+ mov sp,(r0)+ mov KISA6,(r0)+ / dump all of core (ie to first mt error) / onto mag tape. (9 track or 7 track 'binary') mov $MTC,r0 mov $60004,(r0)+ clr 2(r0) 1: mov $-512.,(r0) inc -(r0) 2: tstb (r0) bge 2b tst (r0)+ bge 1b reset / end of file and loop mov $60007,-(r0) br . .globl start, _end, _edata, _main start: bit $1,SSR0 bne start / loop if restart reset / initialize systems segments mov $KISA0,r0 mov $KISD0,r1 mov $200,r4 clr r2 mov $6,r3 1: mov r2,(r0)+ mov $77406,(r1)+ / 4k rw add r4,r2 sob r3,1b / initialize user segment mov $_end+63.,r2 ash $-6,r2 bic $!1777,r2 mov r2,(r0)+ / ksr6 = sysu mov $usize-1\<8|6,(r1)+ / initialize io segment / set up counts on supervisor segments mov $IO,(r0)+ mov $77406,(r1)+ / rw 4k / get a sp and start segmentation mov $_u+[usize*64.],sp inc SSR0 / clear bss mov $_edata,r0 1: clr (r0)+ cmp r0,$_end blo 1b / clear user block mov $_u,r0 1: clr (r0)+ cmp r0,$_u+[usize*64.] blo 1b / set up previous mode and call main / on return, enter user mode at 0R mov $30000,PS jsr pc,_main mov $170000,-(sp) clr -(sp) rtt .globl _ldiv _ldiv: clr r0 mov 2(sp),r1 div 4(sp),r0 rts pc .globl _lrem _lrem: clr r0 mov 2(sp),r1 div 4(sp),r0 mov r1,r0 rts pc .globl _lshift _lshift: mov 2(sp),r1 mov (r1)+,r0 mov (r1),r1 ashc 4(sp),r0 mov r1,r0 rts pc .globl csv csv: mov r5,r0 mov sp,r5 mov r4,-(sp) mov r3,-(sp) mov r2,-(sp) jsr pc,(r0) .globl cret cret: mov r5,r1 mov -(r1),r4 mov -(r1),r3 mov -(r1),r2 mov r5,sp mov (sp)+,r5 rts pc .globl _u _u = 140000 usize = 16. PS = 177776 SSR0 = 177572 SSR2 = 177576 KISA0 = 172340 KISA1 = 172342 KISA2 = 172344 KISA6 = 172354 KISD0 = 172300 MTC = 172522 UISA0 = 177640 UISA1 = 177642 UISD0 = 177600 UISD1 = 177602 IO = 7600 .data .globl _ka6, _cputype _ka6: KISA6 _cputype:40. .bss .globl nofault, ssr, badtrap nofault:.=.+2 ssr: .=.+6 badtrap:.=.+2 sp) mov r3,-(sp) mov r2,-(sp) jsr pc,(r0) .globl cret cret: mov r5,r1 mov -(r1),r4 mov -(r1),r3 mov -(r1),r2 mov r5,sp mov (sp)+,r5 rts pc .globl _u _u = 140000 usize = 16. PS = 177776 SSR0 = 177572 SSR2 = 177576 KISA0 = 172340 KISA1 = 172342 KISA2 = 172344 KISA6 = 172354 KISD0 = 172300 MTC = 172522 UISA0 = 177640 UISA1 = 177642 UISD0 = 177600 UISD1 = 177602 IO = 7600 .data .globl _ka6, _cput340 KISA6 = 172354 KISD0 = 172300 MTC = 172522 UISA0 = 177640 UISA1 = 177642 UISD0 = 177600 UISD1 = 177602 IO = 7600 .data .globl _ka6, _cputype _ka6: KISA6 _cputype:40. .bss .globl nofault, ssr, badtrap nofault:.=.+2 ssr: .=.+6 badtrap:.=.+2 ov r5,r0 mov sp,r5 mov r4,-(sp) mov r3,-(sp) mov r2,-(sp) jsr pc,(r0) .globl cret cret: mov r5,r1 mov -(r1),r4 mov -(r1),r3 mov -(r1),r2 mov r5,sp mov (sp)+,r5 rts pc .globl _u _u = 140000 usize = 16. PS = 177776 SSR0 = 177572 SSR2 = 177576 KISA0 = 172/ machine language assist / for 11/45 or 11/70 CPUs .fpp = 1 / non-UNIX instructions mfpi = 6500^tst mtpi = 6600^tst mfpd = 106500^tst mtpd = 106600^tst spl = 230 ldfps = 170100^tst stfps = 170200^tst wait = 1 rtt = 6 reset = 5 HIPRI = 300 HIGH = 6 / Mag tape dump / save registers in low core and / write all core onto mag tape. / entry is thru 44 abs .data .globl dump dump: bit $1,SSR0 bne dump / save regs r0,r1,r2,r3,r4,r5,r6,KIA6 / starting at abs location 4 mov r0,4 mov $6,r0 mov r1,(r0)+ mov r2,(r0)+ mov r3,(r0)+ mov r4,(r0)+ mov r5,(r0)+ mov sp,(r0)+ mov KDSA6,(r0)+ / dump all of core (ie to first mt error) / onto mag tape. (9 track or 7 track 'binary') mov $MTC,r0 mov $60004,(r0)+ clr 2(r0) 1: mov $-512.,(r0) inc -(r0) 2: tstb (r0) bge 2b tst (r0)+ bge 1b reset / end of file and loop mov $60007,-(r0) br . .globl start, _end, _edata, _etext, _main / 11/45 and 11/70 startup. / entry is thru 0 abs. / since core is shuffled, / this code can be executed but once start: inc $-1 bne . reset clr PS / set KI0 to physical 0 mov $77406,r3 mov $KISA0,r0 mov $KISD0,r1 clr (r0)+ mov r3,(r1)+ / set KI1-6 to eventual text resting place mov $_end+63.,r2 ash $-6,r2 bic $!1777,r2 1: mov r2,(r0)+ mov r3,(r1)+ add $200,r2 cmp r0,$KISA7 blos 1b / set KI7 to IO seg for escape mov $IO,-(r0) / set KD0-7 to physical mov $KDSA0,r0 mov $KDSD0,r1 clr r2 1: mov r2,(r0)+ mov r3,(r1)+ add $200,r2 cmp r0,$KDSA7 blos 1b / initialization / get a temp (1-word) stack / turn on segmentation / copy text to I space / clear bss in D space mov $stk+2,sp mov $65,SSR3 / 22-bit, map, K+U sep bit $20,SSR3 beq 1f mov $70.,_cputype 1: inc SSR0 mov $_etext,r0 mov $_edata,r1 add $_etext-8192.,r1 1: mov -(r1),-(sp) mtpi -(r0) cmp r1,$_edata bhi 1b 1: clr (r1)+ cmp r1,$_end blo 1b / use KI escape to set KD7 to IO seg / set KD6 to first available core mov $IO,-(sp) mtpi *$KDSA7 mov $_etext-8192.+63.,r2 ash $-6,r2 bic $!1777,r2 add KISA1,r2 mov r2,KDSA6 / set up supervisor D registers mov $6,SISD0 mov $6,SISD1 / set up real sp / clear user block mov $_u+[usize*64.],sp mov $_u,r0 1: clr (r0)+ cmp r0,sp blo 1b / jsr pc,_isprof / set up previous mode and call main / on return, enter user mode at 0R mov $30000,PS jsr pc,_main mov $170000,-(sp) clr -(sp) rtt .globl trap, call .globl _trap / all traps and interrupts are / vectored thru this routine. trap: mov PS,saveps tst nofault bne 1f mov SSR0,ssr mov SSR1,ssr+2 mov SSR2,ssr+4 mov $1,SSR0 jsr r0,call1; _trap / no return 1: mov $1,SSR0 mov nofault,(sp) rtt .text .globl _runrun, _swtch call1: mov saveps,-(sp) spl 0 br 1f call: mov PS,-(sp) 1: mov r1,-(sp) mfpd sp mov 4(sp),-(sp) bic $!37,(sp) bit $30000,PS beq 1f .if .fpp mov $20,_u+4 / FP maint mode .endif jsr pc,*(r0)+ 2: spl HIGH tstb _runrun beq 2f spl 0 jsr pc,_savfp jsr pc,_swtch br 2b 2: .if .fpp mov $_u+4,r1 bit $20,(r1) bne 2f mov (r1)+,r0 ldfps r0 movf (r1)+,fr0 movf (r1)+,fr1 movf fr1,fr4 movf (r1)+,fr1 movf fr1,fr5 movf (r1)+,fr1 movf (r1)+,fr2 movf (r1)+,fr3 ldfps r0 2: .endif tst (sp)+ mtpd sp br 2f 1: bis $30000,PS jsr pc,*(r0)+ cmp (sp)+,(sp)+ 2: mov (sp)+,r1 tst (sp)+ mov (sp)+,r0 rtt .globl _savfp _savfp: .if .fpp mov $_u+4,r1 bit $20,(r1) beq 1f stfps (r1)+ movf fr0,(r1)+ movf fr4,fr0 movf fr0,(r1)+ movf fr5,fr0 movf fr0,(r1)+ movf fr1,(r1)+ movf fr2,(r1)+ movf fr3,(r1)+ 1: .endif rts pc .globl _incupc _incupc: mov r2,-(sp) mov 6(sp),r2 / base of prof with base,leng,off,scale mov 4(sp),r0 / pc sub 4(r2),r0 / offset clc ror r0 mul 6(r2),r0 / scale ashc $-14.,r0 inc r1 bic $1,r1 cmp r1,2(r2) / length bhis 1f add (r2),r1 / base mov nofault,-(sp) mov $2f,nofault mfpd (r1) inc (sp) mtpd (r1) br 3f 2: clr 6(r2) 3: mov (sp)+,nofault 1: mov (sp)+,r2 rts pc .globl _display _display: dec dispdly bge 2f clr dispdly mov PS,-(sp) mov $HIPRI,PS mov CSW,r1 bit $1,r1 beq 1f bis $30000,PS dec r1 1: jsr pc,fuword mov r0,CSW mov (sp)+,PS cmp r0,$-1 bne 2f mov $120.,dispdly / 2 sec delay after CSW fault 2: rts pc / Character list get/put .globl _getc, _putc .globl _cfreelist _getc: mov 2(sp),r1 mov PS,-(sp) mov r2,-(sp) spl 5 mov 2(r1),r2 / first ptr beq 9f / empty movb (r2)+,r0 / character bic $!377,r0 mov r2,2(r1) dec (r1)+ / count bne 1f clr (r1)+ clr (r1)+ / last block br 2f 1: bit $7,r2 bne 3f mov -10(r2),(r1) / next block add $2,(r1) 2: dec r2 bic $7,r2 mov _cfreelist,(r2) mov r2,_cfreelist 3: mov (sp)+,r2 mov (sp)+,PS rts pc 9: clr 4(r1) mov $-1,r0 mov (sp)+,r2 mov (sp)+,PS rts pc _putc: mov 2(sp),r0 mov 4(sp),r1 mov PS,-(sp) mov r2,-(sp) mov r3,-(sp) spl 5 mov 4(r1),r2 / last ptr bne 1f mov _cfreelist,r2 beq 9f mov (r2),_cfreelist clr (r2)+ mov r2,2(r1) / first ptr br 2f 1: bit $7,r2 bne 2f mov _cfreelist,r3 beq 9f mov (r3),_cfreelist mov r3,-10(r2) mov r3,r2 clr (r2)+ 2: movb r0,(r2)+ mov r2,4(r1) inc (r1) / count clr r0 mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,PS rts pc 9: mov pc,r0 mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,PS rts pc .globl _backup .globl _regloc _backup: mov 2(sp),r0 movb ssr+2,r1 jsr pc,1f movb ssr+3,r1 jsr pc,1f movb _regloc+7,r1 asl r1 add r0,r1 mov ssr+4,(r1) clr r0 2: rts pc 1: mov r1,-(sp) asr (sp) asr (sp) asr (sp) bic $!7,r1 movb _regloc(r1),r1 asl r1 add r0,r1 sub (sp)+,(r1) rts pc .globl _fubyte, _subyte .globl _fuword, _suword .globl _fuibyte, _suibyte .globl _fuiword, _suiword _fuibyte: mov 2(sp),r1 bic $1,r1 jsr pc,giword br 2f _fubyte: mov 2(sp),r1 bic $1,r1 jsr pc,gword 2: cmp r1,2(sp) beq 1f swab r0 1: bic $!377,r0 rts pc _suibyte: mov 2(sp),r1 bic $1,r1 jsr pc,giword mov r0,-(sp) cmp r1,4(sp) beq 1f movb 6(sp),1(sp) br 2f 1: movb 6(sp),(sp) 2: mov (sp)+,r0 jsr pc,piword clr r0 rts pc _subyte: mov 2(sp),r1 bic $1,r1 jsr pc,gword mov r0,-(sp) cmp r1,4(sp) beq 1f movb 6(sp),1(sp) br 2f 1: movb 6(sp),(sp) 2: mov (sp)+,r0 jsr pc,pword clr r0 rts pc _fuiword: mov 2(sp),r1 fuiword: jsr pc,giword rts pc _fuword: mov 2(sp),r1 fuword: jsr pc,gword rts pc giword: mov PS,-(sp) spl HIGH mov nofault,-(sp) mov $err,nofault mfpi (r1) mov (sp)+,r0 br 1f gword: mov PS,-(sp) spl HIGH mov nofault,-(sp) mov $err,nofault mfpd (r1) mov (sp)+,r0 br 1f _suiword: mov 2(sp),r1 mov 4(sp),r0 suiword: jsr pc,piword rts pc _suword: mov 2(sp),r1 mov 4(sp),r0 suword: jsr pc,pword rts pc piword: mov PS,-(sp) spl HIGH mov nofault,-(sp) mov $err,nofault mov r0,-(sp) mtpi (r1) br 1f pword: mov PS,-(sp) spl HIGH mov nofault,-(sp) mov $err,nofault mov r0,-(sp) mtpd (r1) 1: mov (sp)+,nofault mov (sp)+,PS rts pc err: mov (sp)+,nofault mov (sp)+,PS tst (sp)+ mov $-1,r0 rts pc .globl _copyin, _copyout .globl _copyiin, _copyiout _copyiin: jsr pc,copsu 1: mfpi (r0)+ mov (sp)+,(r1)+ sob r2,1b br 2f _copyin: jsr pc,copsu 1: mfpd (r0)+ mov (sp)+,(r1)+ sob r2,1b br 2f _copyiout: jsr pc,copsu 1: mov (r0)+,-(sp) mtpi (r1)+ sob r2,1b br 2f _copyout: jsr pc,copsu 1: mov (r0)+,-(sp) mtpd (r1)+ sob r2,1b 2: mov (sp)+,nofault mov (sp)+,r2 clr r0 rts pc copsu: mov (sp)+,r0 mov r2,-(sp) mov nofault,-(sp) mov r0,-(sp) mov 10(sp),r0 mov 12(sp),r1 mov 14(sp),r2 asr r2 mov $1f,nofault rts pc 1: mov (sp)+,nofault mov (sp)+,r2 mov $-1,r0 rts pc .globl _idle _idle: mov PS,-(sp) spl 0 wait mov (sp)+,PS rts pc .globl _savu, _retu, _aretu _savu: spl HIGH mov (sp)+,r1 mov (sp),r0 mov sp,(r0)+ mov r5,(r0)+ spl 0 jmp (r1) _aretu: spl 7 mov(sp)+,r1 mov (sp),r0 br 1f _retu: spl 7 mov (sp)+,r1 mov (sp),KDSA6 mov $_u,r0 1: mov (r0)+,sp mov (r0)+,r5 spl 0 jmp (r1) .globl _spl0, _spl1, _spl4, _spl5, _spl6, _spl7 _spl0: spl 0 rts pc _spl1: spl 1 rts pc _spl4: spl 4 rts pc _spl5: spl 5 rts pc _spl6: spl 6 rts pc _spl7: spl HIGH rts pc .globl _copyseg _copyseg: mov PS,-(sp) mov 4(sp),SISA0 mov 6(sp),SISA1 mov $10000+HIPRI,PS mov r2,-(sp) clr r0 mov $8192.,r1 mov $32.,r2 1: mfpd (r0)+ mtpd (r1)+ sob r2,1b mov (sp)+,r2 mov (sp)+,PS rts pc .globl _clearseg _clearseg: mov PS,-(sp) mov 4(sp),SISA0 mov $10000+HIPRI,PS clr r0 mov $32.,r1 1: clr -(sp) mtpd (r0)+ sob r1,1b mov (sp)+,PS rts pc .globl _dpadd _dpadd: mov 2(sp),r0 add 4(sp),2(r0) adc (r0) rts pc .globl _dpcmp _dpcmp: mov 2(sp),r0 mov 4(sp),r1 sub 6(sp),r0 sub 8(sp),r1 sbc r0 bge 1f cmp r0,$-1 bne 2f cmp r1,$-512. bhi 3f 2: mov $-512.,r0 rts pc 1: bne 2f cmp r1,$512. blo 3f 2: mov $512.,r1 3: mov r1,r0 rts pc .globl _ldiv _ldiv: clr r0 mov 2(sp),r1 div 4(sp),r0 rts pc .globl _lrem _lrem: clr r0 mov 2(sp),r1 div 4(sp),r0 mov r1,r0 rts pc .globl _lshift _lshift: mov 2(sp),r1 mov (r1)+,r0 mov (r1),r1 ashc 4(sp),r0 mov r1,r0 rts pc .globl csv csv: mov r5,r0 mov sp,r5 mov r4,-(sp) mov r3,-(sp) mov r2,-(sp) jsr pc,(r0) .globl cret cret: mov r5,r1 mov -(r1),r4 mov -(r1),r3 mov -(r1),r2 mov r5,sp mov (sp)+,r5 rts pc .globl _u _u = 140000 usize = 16. CSW = 177570 PS = 177776 SSR0 = 177572 SSR1 = 177574 SSR2 = 177576 SSR3 = 172516 KISA0 = 172340 KISA1 = 172342 KISA7 = 172356 KISD0 = 172300 KDSA0 = 172360 KDSA6 = 172374 KDSA7 = 172376 KDSD0 = 172320 MTC = 172522 SISA0 = 172240 SISA1 = 172242 SISD0 = 172200 SISD1 = 172202 IO = 177600 .data .globl _ka6 .globl _cputype _ka6: KDSA6 _cputype:45. stk: 0 .bss .globl nofault, ssr nofault:.=.+2 ssr: .=.+6 dispdly:.=.+2 saveps: .=.+2 .text / system profiler / /rtt = 6 /CCSB = 172542 /CCSR = 172540 /PS = 177776 / /.globl _sprof, _xprobuf, _probuf, _probsiz, _mode /_probsiz = 7500.+2048. / /_isprof: / mov $_sprof,104 / interrupt / mov $340,106 / pri / mov $100.,CCSB / count set = 100 / mov $113,CCSR / count down, 10kHz, repeat / rts pc / /_sprof: / mov r0,-(sp) / mov PS,r0 / ash $-11.,r0 / bic $!14,r0 / add $1,_mode+2(r0) / adc _mode(r0) / cmp r0,$14 / user / beq done / mov 2(sp),r0 / pc / asr r0 / asr r0 / bic $140001,r0 / cmp r0,$_probsiz / blo 1f / inc _outside / br done /1: / inc _probuf(r0) / bne done / mov r1,-(sp) / mov $_xprobuf,r1 /2: / cmp (r1)+,r0 / bne 3f / inc (r1) / br 4f /3: / tst (r1)+ / bne 2b / sub $4,r1 / mov r0,(r1)+ / mov $1,(r1)+ /4: / mov (sp)+,r1 /done: / mov (sp)+,r0 / mov $113,CCSR / rtt / /.bss /_xprobuf: .=.+512. /_probuf:.=.+_probsiz /_mode: .=.+16. /_outside: .=.+2 $!14,r0 / add $1,_mode+2(r0) / adc _mode(r0) / cmp r0,$14 / user / beq done / mov 2(sp),r0 / pc / asr r0 / asr r0 / bic $140001,r0 / cmp r0,$_probsiz / blo 1f / inc _outside / br done /1: / inc _probuf(r0) / bne done / mov r1,-(sp) / mov $_xprobuf,r1 /2: / cmp (r1)+,r0 / # /* */ /* * general TTY subroutines * modified for 8 bit i/o by d.anderson, may 27,1976 * modified to suspend output on ESC rla 7/19/79 * modified for variable size tabs & * control x processing rla 8/1/79 */ #include #include #include #include #include #include #include #include #include /* * Input mapping table-- if an entry is non-zero, when the * corresponding character is typed preceded by "\" the escape * sequence is replaced by the table value. Mostly used for * upper-case only terminals. */ char maptab[] { 000,000,000,000,004,000,000,000, 000,000,000,000,000,000,000,000, 000,000,000,000,000,000,000,000, 000,000,000,000,000,000,000,000, 000,'|',000,'#',000,000,000,'`', '{','}',000,000,000,000,000,000, 000,000,000,000,000,000,000,000, 000,000,000,000,000,000,000,000, '@',000,000,000,000,000,000,000, 000,000,000,000,000,000,000,000, 000,000,000,000,000,000,000,000, 000,000,000,000,000,000,'~',000, 000,'A','B','C','D','E','F','G', 'H','I','J','K','L','M','N','O', 'P','Q','R','S','T','U','V','W', 'X','Y','Z',000,000,000,000,000, }; /* * The actual structure of a clist block manipulated by * getc and putc (m40.s) */ struct cblock { struct cblock *c_next; char info[6]; }; /* The character lists-- space for 6*NCLIST characters */ struct cblock cfree[NCLIST]; /* List head for unused character blocks. */ struct cblock *cfreelist; /* * structure of device registers for KL, DL, and DC * interfaces-- more particularly, those for which the * SSTART bit is off and can be treated by general routines * (that is, not DH). */ struct { int ttrcsr; int ttrbuf; int tttcsr; int tttbuf; }; /* * The routine implementing the gtty system call. * Just call lower level routine and pass back values. */ gtty() { int v[3]; register *up, *vp; vp = v; sgtty(vp); if (u.u_error) return; up = u.u_arg[0]; suword(up, *vp++); suword(++up, *vp++); suword(++up, *vp++); } /* * The routine implementing the stty system call. * Read in values and call lower level. */ stty() { register int *up; up = u.u_arg[0]; u.u_arg[0] = fuword(up); u.u_arg[1] = fuword(++up); u.u_arg[2] = fuword(++up); sgtty(0); } /* * Stuff common to stty and gtty. * Check legality and switch out to individual * device routine. * v is 0 for stty; the parameters are taken from u.u_arg[]. * c is non-zero for gtty and is the place in which the device * routines place their information. */ sgtty(v) int *v; { register struct file *fp; register struct inode *ip; if ((fp = getf(u.u_ar0[R0])) == NULL) return; ip = fp->f_inode; if ((ip->i_mode&IFMT) != IFCHR) { u.u_error = ENOTTY; return; } (*cdevsw[ip->i_addr[0].d_major].d_sgtty)(ip->i_addr[0], v); } /* * Wait for output to drain, then flush input waiting. */ wflushtty(atp) struct tty *atp; { register struct tty *tp; tp = atp; spl5(); nohold: if(tp->t_state&HOLD){ tp->t_state &= ~(HOLD|TIMEOUT); ttrstrt(tp); } while (tp->t_outq.c_cc) { if(tp->t_state&HOLD) goto nohold; tp->t_state |= ASLEEP; sleep(&tp->t_outq, TTOPRI); } flushtty(tp); spl0(); } /* * Initialize clist by freeing all character blocks, then count * number of character devices. (Once-only routine) */ cinit() { register int ccp; register struct cblock *cp; register struct cdevsw *cdp; ccp = cfree; for (cp=(ccp+07)&~07; cp <= &cfree[NCLIST-1]; cp++) { cp->c_next = cfreelist; cfreelist = cp; } ccp = 0; for(cdp = cdevsw; cdp->d_open; cdp++) ccp++; nchrdev = ccp; } /* * flush all TTY queues */ flushtty(atp) struct tty *atp; { register struct tty *tp; register int sps; tp = atp; while (getc(&tp->t_canq) >= 0); while (getc(&tp->t_outq) >= 0); wakeup(&tp->t_rawq); wakeup(&tp->t_outq); sps = PS->integ; spl5(); while (getc(&tp->t_rawq) >= 0); tp->t_delct = 0; tp->t_state &= ~(TIMEOUT|HOLD); ttstart(tp); /* to clear hold */ PS->integ = sps; } /* * transfer raw input list to canonical list, * doing erase-kill processing and handling escapes. * It waits until a full line has been typed in cooked mode, * or until any character has been typed in raw mode. */ canon(atp) struct tty *atp; { register char *bp; char *bp1; register struct tty *tp; register int c; tp = atp; spl5(); while (tp->t_delct==0) { if ((tp->t_state&CARR_ON)==0) return(0); sleep(&tp->t_rawq, TTIPRI); } spl0(); loop: bp = &canonb[2]; while ((c=getc(&tp->t_rawq)) >= 0) { if( tp->t_flags&RAW) { tp->t_delct--; goto put; } if (c==0377) { tp->t_delct--; break; } if (bp[-1]!='\\') { if (c==tp->t_erase) { if (bp > &canonb[2]) bp--; continue; } if (c==tp->t_kill) goto loop; if (c==CEOT) continue; } else if (maptab[c] && (maptab[c]==c || (tp->t_flags&LCASE))) { if (bp[-2] != '\\') c = maptab[c]; bp--; } put: *bp++ = c; if (bp>=canonb+CANBSIZ) break; } bp1 = bp; bp = &canonb[2]; c = &tp->t_canq; while (bpt_flags; if( t_flags & RAW ) goto skip; if ((c &= 0177) == '\r' && t_flags&CRMOD) c = '\n'; if ((t_flags&RAW)==0 && (c==CQUIT || c==CINTR)) { signal(tp, c==CINTR? SIGINT:SIGQIT); flushtty(tp); return; } if((t_flags&RAW)==0 && (c==CHOLD||c==CACK)){ if(tp->t_state & HOLD){ tp->t_state &= ~HOLD; ttrstrt(tp); }else { tp->t_state |= (TIMEOUT|HOLD); ttstart(tp); } return; } if(t_flags&LCASE && c>='A' && c<='Z') c += 'a'-'A'; skip: if (tp->t_rawq.c_cc>=TTYHOG) { flushtty(tp); return; } putc(c, &tp->t_rawq); if (t_flags&RAW || c=='\n' || c==004) { wakeup(&tp->t_rawq); if ( t_flags&RAW ||(putc(0377, &tp->t_rawq)==0)) tp->t_delct++; } if(( c==tp->t_kill) && ((tp->t_flags&RAW) == 0)){ ttyoutput('x',tp); ttyoutput('x',tp); ttyoutput('x',tp); ttyoutput('\n',tp); ttstart(tp); return; } if( t_flags&RAW) return; if (t_flags&ECHO) { ttyoutput(c, tp); ttstart(tp); } if (t_flags&HOLD){ tp->t_state &= ~HOLD; ttrstrt(tp); } } /* * put character on TTY output queue, adding delays, * expanding tabs, and handling the CR/NL bit. * It is called both from the top half for output, and from * interrupt level for echoing. * The arguments are the character and the tty structure. */ ttyoutput(ac, tp) struct tty *tp; { register int c; register struct tty *rtp; register char *colp; int ctype; rtp = tp; if( rtp->t_flags&RAW) { putc(ac,&rtp->t_outq); return; } c = ac&0177; /* * Ignore EOT in normal mode to avoid hanging up * certain terminals. */ if (c==004 && (rtp->t_flags&RAW)==0) return; /* * Turn tabs to spaces as required */ if (c=='\t' && rtp->t_flags&XTABS) { do ttyoutput(' ', rtp); while (rtp->t_col&rtp->t_tabexp); return; } /* * for upper-case-only terminals, * generate escapes. */ if (rtp->t_flags&LCASE) { colp = "({)}!|^~'`"; while(*colp++) if(c == *colp++) { ttyoutput('\\', rtp); c = colp[-2]; break; } if ('a'<=c && c<='z') c += 'A' - 'a'; } /* * turn to if desired. */ if (c=='\n' && rtp->t_flags&CRMOD) ttyoutput('\r', rtp); if (putc(c, &rtp->t_outq)) return; /* * Calculate delays. * The numbers here represent clock ticks * and are not necessarily optimal for all terminals. * The delays are indicated by characters above 0200, * thus (unfortunately) restricting the transmission * path to 7 bits. */ colp = &rtp->t_col; ctype = partab[c]; c = 0; switch (ctype&077) { /* ordinary */ case 0: (*colp)++; /* non-printing */ case 1: break; /* backspace */ case 2: if (*colp) (*colp)--; break; /* newline */ case 3: ctype = (rtp->t_flags >> 8) & 03; if(ctype == 1) { /* tty 37 */ if (*colp) c = max((*colp>>4) + 3, 6); } else if(ctype == 2) { /* vt05 */ c = 6; } *colp = 0; break; /* tab */ case 4: ctype = (rtp->t_flags >> 10) & 03; if(ctype == 1) { /* tty 37 */ c = 1 - (*colp | ~rtp->t_tabexp); if(c < 5) c = 0; } *colp |= rtp->t_tabexp; (*colp)++; break; /* vertical motion */ case 5: if(rtp->t_flags & VTDELAY) /* tty 37 */ c = 0177; break; /* carriage return */ case 6: ctype = (rtp->t_flags >> 12) & 03; if(ctype == 1) { /* tn 300 */ c = 5; } else if(ctype == 2) { /* ti 700 */ c = 10; } *colp = 0; } if(c) putc(c|0200, &rtp->t_outq); } /* * Restart typewriter output following a delay * timeout. * The name of the routine is passed to the timeout * subroutine and it is called during a clock interrupt. */ ttrstrt(atp) { register struct tty *tp; tp = atp; if(tp->t_state&HOLD) return; tp->t_state &= ~TIMEOUT; ttstart(tp); } /* * Start output on the typewriter. It is used from the top half * after some characters have been put on the output queue, * from the interrupt routine to transmit the next * character, and after a timeout has finished. * If the SSTART bit is off for the tty the work is done here, * using the protocol of the single-line interfaces (KL, DL, DC); * otherwise the address word of the tty structure is * taken to be the name of the device-dependent startup routine. */ ttstart(atp) struct tty *atp; { register int *addr, c; register struct tty *tp; struct { int (*func)(); }; tp = atp; addr = tp->t_addr; if (tp->t_state&SSTART) { (*addr.func)(tp); return; } if ((addr->tttcsr&DONE)==0 || tp->t_state&TIMEOUT) return; if ((c=getc(&tp->t_outq)) >= 0) { if( tp->t_flags&RAW) { addr->tttbuf = c; return; } if (c<=0177) addr->tttbuf = c | (partab[c]&0200); else if((c&0377)==0376) /* suspend output */ tp->t_state |= (HOLD|TIMEOUT); else{ timeout(ttrstrt, tp, c&0177); tp->t_state |= TIMEOUT; } } } /* * Called from device's read routine after it has * calculated the tty-structure given as argument. * The pc is backed up for the duration of this call. * In case of a caught interrupt, an RTI will re-execute. */ ttread(atp) struct tty *atp; { register struct tty *tp; tp = atp; if ((tp->t_state&CARR_ON)==0) return; if (tp->t_canq.c_cc || canon(tp)) while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0); } /* * Called from the device's write routine after it has * calculated the tty-structure given as argument. */ ttwrite(atp) struct tty *atp; { register struct tty *tp; register int c; tp = atp; if ((tp->t_state&CARR_ON)==0) return; while ((c=cpass())>=0) { spl5(); while (tp->t_outq.c_cc > TTHIWAT) { ttstart(tp); tp->t_state |= ASLEEP; sleep(&tp->t_outq, TTOPRI); } spl0(); ttyoutput(c, tp); } ttstart(tp); } /* * Common code for gtty and stty functions on typewriters. * If v is non-zero then gtty is being done and information is * passed back therein; * if it is zero stty is being done and the input information is in the * u_arg array. */ ttystty(atp, av) int *atp, *av; { register *tp, *v; tp = atp; if(v = av) { *v++ = tp->t_tabexp; v->lobyte = tp->t_erase; v->hibyte = tp->t_kill; v[1] = tp->t_flags; /* * SYSTEM MODS: MJB 03/14/79 : CHANGE TO USE 'EMPTY' (RAND CHANGE): */ u.u_arg[4] = (tp->t_canq.c_cc==0 && tp->t_delct==0 && (tp->t_state&CARR_ON) ); return(1); } wflushtty(tp); v = u.u_arg; tp->t_tabexp = *v++; tp->t_erase = v->lobyte; tp->t_kill = v->hibyte; tp->t_flags = v[1]; return(0); } * u_arg array. */ ttystty(atp, av) int *atp, *av; { register *tp, *v; tp = atp; if(v = av) { *v++ = tp->t_tabexp; v->lobyte = tp->t_erase; v->hibyte = tp->t_kill; v[1] = tp->t_flags; /* * SYSTEM MODS: MJB 03/14/79 : CHANGE TO USE 'EMPTY' (RAND CHANGE): */ u.u_arg[4] = (tp->t_canq.c_cc==0 && tp->t_delct==0 && (tp->t_state&CARR_ON) ); return(1); } wflushtty(tp); v = u.u_arg; tp->t_tabexp = *v++; tp->t_erase = v->lobyte; tp->t_kill = v->hibyte; tp->t_flags = v[1]; return(0_rpintr\n", "\t&nulldev,\t&nulldev,\t&rpstrategy, \t&rptab,", "\t&nulldev, &nulldev, &rpread, &rpwrite, &nodev,", "hp", 0, 254, BLOCK+CHAR+INTR, "\thpio; br5\n", ".globl\t_hpintr\n", "hpio:\tjsr\tr0,call; _hpintr\n", "\t&hpopen,\t&nulldev,\t&hpstrategy, \t&hptab,", "\t&hpopen, &nulldev, &hpread, &hpwrite, &nodev,", /* * 260 TA11 * 264-274 unused */ "dc", 0, 308, CHAR+INTR, "\tdcin; br5+%d.\n\tdcou; br5+%d.\n", ".globl\t_dcrint\ndcin:\tjsr\tr0,call; _dcrint\n", ".globl\t_dcxint\ndcou:\tjsr\tr0,call; _dcxint\n", "", "\t&dcopen, &dcclose, &dcread, &dcwrite, &dcsgtty,", "kl", 0, 308, INTR+KL, "\tklin; br4+%d.\n\tklou; br4+%d.\n", "", "", "", "", "dp", 0, 308, CHAR+INTR, "\tdpin; br6+%d.\n\tdpou; br6+%d.\n", ".globl\t_dprint\ndpin:\tjsr\tr0,call; _dprint\n", ".globl\t_dpxint\ndpou:\tjsr\tr0,call; _dpxint\n", "", "\t&dpopen, &dpclose, &dpread, &dpwrite, &nodev,", /* * DM11-A */ "dn", 0, 304, CHAR+INTR, "\tdnou; br5+%d.\n", "", ".globl\t_dnint\ndnou:\tjsr\tr0,call; _dnint\n", "", "\t&dnopen, &dnclose, &nodev, &dnwrite, &nodev,", "dhdm", 0, 304, INTR, "\tdmin; br4+%d.\n", "", ".globl\t_dmint\ndmin:\tjsr\tr0,call; _dmint\n", "", "", /* * DR11-A+ * DR11-C+ * PA611+ * PA611+ * DT11+ * DX11+ */ "dl", 0, 308, INTR+KL, "\tklin; br4+%d.\n\tklou; br4+%d.\n", "", "", "", "", /* * DJ11 */ "dj", 0, 316, CHAR+INTR, " .= 0410\n\tdjin; br5+%d.\n\tdjou; br5+%d.\n", ".globl\t_djrint\ndjin:\tjsr\tr0,call; _djrint\n", ".globl\t_djxint\ndjou:\tjsr\tro,call; _djxint\n", "", "\t&djopen, &djclose, &djread, &djwrite, &djsgtty,", "dh", 0, 308, CHAR+INTR+EVEN, "\tdhin; br5+%d.\n\tdhou; br5+%d.\n", ".globl\t_dhrint\ndhin:\tjsr\tr0,call; _dhrint\n", ".globl\t_dhxint\ndhou:\tjsr\tr0,call; _dhxint\n", "", "\t&dhopen, &dhclose, &dhread, &dhwrite, &dhsgtty,", /* * GT40 * LPS+ * VT20 */ 0 }; char *stra[] { "/ low core", "", "br4 = 200", "br5 = 240", "br6 = 300", "br7 = 340", "", ". = 0^.", "\tbr\t1f", "\t4", "", "/ trap vectors", "\ttrap; br7+0.\t\t/ bus error", "\ttrap; br7+1.\t\t/ illegal instruction", "\ttrap; br7+2.\t\t/ bpt-trace trap", "\ttrap; br7+3.\t\t/ iot trap", "\ttrap; br7+4.\t\t/ power fail", "\ttrap; br7+5.\t\t/ emulator trap", "\ttrap; br7+6.\t\t/ system entry", "", ". = 40^.", ".globl\tstart, dump", "1:\tjmp\tstart", "\tjmp\tdump", "", 0, }; char *strb[] { "", ". = 240^.", "\ttrap; br7+7.\t\t/ programmed interrupt", "\ttrap; br7+8.\t\t/ floating point", "\ttrap; br7+9.\t\t/ segmentation violation", 0 }; char *strc[] { "", "/ floating vectors", ". = 300^.", 0, }; char *strd[] { "", "//////////////////////////////////////////////////////", "/\t\tinterface code to C", "//////////////////////////////////////////////////////", "", ".globl\tcall, trap", 0 }; char *stre[] { "/*", " */", "", "int\t(*bdevsw[])()", "{", 0, }; char *strf[] { "\t0", "};", "", "int\t(*cdevsw[])()", "{", 0, }; char *strg[] { "\t0", "};", "", "int\trootdev\t{(%d<<8)|0};", "int\tswapdev\t{(%d<<8)|0};", "int\tswplo\t4000;\t/* cannot be zero */", "int\tnswap\t872;", 0, }; int fout; int root -1; main() { register struct tab *p; register *q; int i, n, ev, nkl; int flagf, flagb; while(input()); /* * pass1 -- create interrupt vectors */ nkl = 0; flagf = flagb = 1; fout = creat("l.s", 0666); puke(stra); for(p=table; p->name; p++) if(p->count != 0 && p->key & INTR) { if(p->address>240 && flagb) { flagb = 0; puke(strb); } if(p->address >= 300) { if(flagf) { ev = 0; flagf = 0; puke(strc); } if(p->key & EVEN && ev & 07) { printf("\t.=.+4\n"); ev =+ 4; } ev =+ p->address - 300; } else printf("\n. = %d^.\n", p->address); n = p->count; if(n < 0) n = -n; for(i=0; ikey & KL) { printf(p->codea, nkl, nkl); nkl++; } else printf(p->codea, i, i); } if(flagb) puke(strb); puke(strd); for(p=table; p->name; p++) if(p->count != 0 && p->key & INTR) printf("\n%s%s", p->codeb, p->codec); flush(); close(fout); /* * pass 2 -- create configuration table */ fout = creat("c.c", 0666); puke(stre); for(i=0; q=btab[i]; i++) { for(p=table; p->name; p++) if(equal(q, p->name) && (p->key&BLOCK) && p->count) { printf("%s\t/* %s */\n", p->coded, q); if(p->key & ROOT) root = i; goto newb; } printf("\t&nodev,\t\t&nodev,\t\t&nodev,\t\t0,\t/* %s */\n", q); newb:; } puke(strf); for(i=0; q=ctab[i]; i++) { for(p=table; p->name; p++) if(equal(q, p->name) && (p->key&CHAR) && p->count) { printf("%s\t/* %s */\n", p->codee, q); goto newc; } printf("\t&nodev, &nodev, &nodev, &nodev, &nodev,\t/* %s */\n", q); newc:; } puke(strg, root); flush(); close(fout); if(root < 0) write(2, "no block device given\n", 22); } puke(s, a) char **s; { char *c; while(c = *s++) { printf(c, a); printf("\n"); } } input() { char line[100]; register char *p; register struct tab *q; register n; p = line; while((n=getchar()) != '\n') { if(n == 0) return(0); if(n == ' ' || n == '\t') continue; *p++ = n; } *p++ = 0; n = 0; p = line; while(*p>='0' && *p<='9') { n =* 10; n =+ *p++ - '0'; } if(n == 0) n = 1; if(*p == 0) return(1); for(q=table; q->name; q++) if(equal(q->name, p)) { if(root < 0 && (q->key&BLOCK)) { root = 0; q->key =| ROOT; } if(q->count < 0) { printf("%s: no more, no less\n", p); return(1); } q->count =+ n; if(q->address < 300 && q->count > 1) { q->count = 1; printf("%s: only one\n", p); } return(1); } if(equal(p, "done")) return(0); printf("%s: cannot find\n", p); return(1); } equal(a, b) char *a, *b; { while(*a++ == *b) if(*b++ == 0) return(1); return(0); } getchar() { int c; c = 0; read(0, &c, 1); return(c); } if(root < 0 && (q->key&BLOCK)) { root = 0; q->key =| ROOT; } if(q->count < 0) { printf("%s: no more, no less\n", p); return(1); } q->count =+ n; if(q->address < 300 && q->count > 1) { q->count = 1; printf("%s: only one\n", p); /* * fix system image for I/D space * Move data down to 0; move text to 4K. * Also put the data at the start of the * file and the text after it. */ int tbuf[259]; int rbuf[259]; int obuf[259]; int txtsiz; int datsiz; int bsssiz; int symsiz; int txtrel 8192; int datrel; main(argc, argv) char **argv; { register word, rel, s; if (argc<3) { printf("Arg count\n"); exit(1); } if ((tbuf[0] = open(argv[1], 0)) < 0) { printf("Input file\n"); exit(1); } rbuf[0] = open(argv[1], 0); if ((fcreat(argv[2], obuf)) < 0) { printf("Output file\n"); exit(1); } if (getw(tbuf) != 0407) { printf("Bad input format\n"); exit(1); } putw(0407, obuf); txtsiz = getw(tbuf); datsiz = getw(tbuf); bsssiz = getw(tbuf); symsiz = getw(tbuf); getw(tbuf); getw(tbuf); if (getw(tbuf) != 0) { printf("No relocation bits\n"); exit(1); } putw(txtsiz, obuf); putw(datsiz, obuf); putw(bsssiz, obuf); putw(symsiz, obuf); putw(0, obuf); putw(0, obuf); putw(1, obuf); datrel = -txtsiz; /* * Copy out data first */ tbuf[1] = 0; seek(tbuf[0], 020+txtsiz, 0); seek(rbuf[0], 020+txtsiz, 0); seek(rbuf[0], txtsiz, 1); seek(rbuf[0], datsiz, 1); s = datsiz >> 1; while (s--) { word = getw(tbuf); rel = getw(rbuf); if (rel&01) word =- datrel; word =+ getrel(rel); putw(word, obuf); } /* * Now to the text. */ rbuf[1] = 0; tbuf[1] = 0; seek(rbuf[0], 020+txtsiz, 0); seek(rbuf[0], datsiz, 1); seek(tbuf[0], 020, 0); s = txtsiz >> 1; while(s--) { rel = getw(rbuf); word = getw(tbuf); if (rel&01) word =- txtrel; word =+ getrel(rel); putw(word, obuf); } /* * The symbol table. */ tbuf[1] = 0; seek(tbuf[0], 020+txtsiz, 0); seek(tbuf[0], txtsiz, 1); seek(tbuf[0], datsiz, 1); seek(tbuf[0], datsiz, 1); s = symsiz; while ((s =- 12) >= 0) { putw(getw(tbuf), obuf); putw(getw(tbuf), obuf); putw(getw(tbuf), obuf); putw(getw(tbuf), obuf); rel = getw(tbuf); putw(rel, obuf); word = getw(tbuf); switch(rel&07) { case 2: word =+ txtrel; break; case 3: case 4: word =+ datrel; } putw(word, obuf); } fflush(obuf); close(obuf[0]); exit(0); } getrel(r) { switch (r&016) { case 02: /* ref to text */ return(txtrel); case 04: /* ref to data */ case 06: /* ref to bss */ return(datrel); case 0: return(0); default: printf("Bad relocation %o\n", r); return(0); } } , obuf); putw(getw(tbuf), obuf); rel = getw(tbuf); putw(rel, obuf); word = getw(tbuf); switch(rel&07) { case 2: word =+ txtrel; break; case 3: ca# /* * Device Driver for the Ramtek 9351: * * Computer Aided Design and Graphics Lab * Purdue University * W. Lafayette, IN 47907 * (317) 493-9385 * * 10/26/79 * Revised: 03/07/80 -- new kb,joystick logic * * Special files: * /dev/rm dma read/write memory * /dev/rmpio prog. io read/write memory * /dev/rmkb read kb, write kb lights * /dev/rmjoy read joystick, write cursor * /dev/rmnor reopen without reset * */ #include #include #include #include #define ADDR 0172466 /* unibus address */ /* DRIF command/status bits: */ #define ER 0100000 /* error bit */ #define NEX 040000 /* non-existant memory */ #define AID 01000 /* set = turn auto-increment off for dma */ #define RDY 0200 /* set = ready */ #define IE 0100 /* set = enable interrupts */ #define GIE 010 #define DIO 02 /* dma direction (set=receive from ramtek) */ #define GO 01 /* start dma! */ /* ramtek functions: */ #define RCUR 013400 /* read ramtek cursor */ #define WCUR 013000 /* write ramtek cursor */ #define RKB 014400 /* read ramtek kb */ #define WKB 014000 /* write ramtek kb */ #define SPS 015000 /* sense peripheral status */ #define S_CBIT 0400 /* enter switch bit in sps */ #define S_XBIT 0002 #define S_RBIT 0001 /* etc. */ #define NTRIES 50 /* # times to wait for a ready before sleeping */ #define RMPRI 10 /* priority sleeping on */ #define VIS 002000 #define KBNODAT 020000 #define CUREN 020000 /* minor devices: */ #define DMA 0 #define PIO 1 #define KEYBOARD 2 #define JOYSTICK 3 #define RMNOR 4 /* GPIF command word: */ #define RESET 0100000 #define WRVE 0010000 #define WMXE 0004000 #define WPRE 0002000 /* GPIF status word: */ #define RPRE 010000 /* rm.flags definitions: */ #define NOINCR 000004 /* unibus structure: */ struct { int gpcsr; int drwc; int drba; int drst; int gpdata; }; /* our own flags: */ struct { int procp; int flags; } rm; /* structures to be used by physio: */ struct buf rmbuf; rmopen(dev,flag) { register char *p = ADDR; if( rm.procp != 0 ){ if( rm.procp != u.u_procp && dev.d_minor != RMNOR) u.u_error = ENXIO; return; } if(dev.d_minor != RMNOR){ spl5(); p->drst = IE; /* enable interrupts so will sleep till ready */ rm.flags=IE; p->gpcsr = RESET; rmrdy(); /*does spl0*/ if( p->drst&ER ) { /* see if device is even there */ u.u_error = EIO; printf("Ramtek Error,drst=%o\n",p->drst); return; } } rm.procp = u.u_procp; } /* close the ramtek: */ rmclose(dev) { register char *p = ADDR; rmrdy(); /* be sure all transmissions are done */ p->drst = 0; /* disable interrupts */ p->gpcsr = 0; rm.procp = 0; } /* interrupt handler: */ rmint( dev ) { if( rm.flags&IE ) { /* waiting for a dr int */ rm.flags &= ~IE; ADDR->drst &= ~(IE|GIE); rmbuf.b_flags |= B_DONE; wakeup( &rmbuf ); }else printf("Ramtek Error, Unexp Int\n"); } /* read (do different things depending on the minor device): */ rmread(dev) { int rmstrategy(); register int *base; rmrdy(); base = u.u_base; switch( dev.d_minor ) { case DMA: physio(&rmstrategy , &rmbuf , dev , B_READ); break; case PIO: directio(B_READ); break; case KEYBOARD: if( u.u_count!=2 ) { u.u_error = ENXIO; return; } wrrm( RKB ); suword( base, rdrm() ); break; case JOYSTICK: if( u.u_count != 4){ u.u_error = ENXIO; return; } wrrm( RCUR ); suword(base++, rdrm() ); suword(base , rdrm() ); break; default: u.u_error = EIO; break; } } /* write (do different things depending on the minor device): */ rmwrite(dev) { int rmstrategy(); register int *base; rmrdy(); base = u.u_base; switch( dev.d_minor ) { case DMA: physio(&rmstrategy , &rmbuf , dev , B_WRITE); break; case PIO: directio(B_WRITE); break; case KEYBOARD: if( u.u_count != 2){ u.u_error = ENXIO; return; } wrrm( WKB ); wrrm( fuword( base )); break; case JOYSTICK: if( u.u_count != 4){ u.u_error = ENXIO; return; } wrrm( WCUR ); wrrm( fuword(base++) ); wrrm( fuword(base) ); break; default: u.u_error = EIO; break; } } /* perform programmed i/o: */ directio( flag ) { register int count , *base; count = u.u_count; if( (count<=0) || (count&01)!=0 ){ u.u_error = EIO; return; } count >>= 1; /* words, not bytes */ base = u.u_base; if( (char *)base & 01){ u.u_error = EIO; return; } switch( flag ) { case B_READ: while( count-- ) suword( base++, rdrm() ); break; case B_WRITE: while( count-- ) wrrm( fuword(base++) ); break; } } /* wait till ramtek interface is ready: */ rmrdy() { extern int lbolt; register int n; register char *p = ADDR; for(;;) { for(n=0; n<=NTRIES; n++){ if( p->drst&RDY ){ if( p->drst&ER ) printf("Ramtek Error,drst=%o\n",p->drst); return; } } spl5(); if( rm.flags&IE ){ sleep(&rmbuf , RMPRI); spl0(); }else{ spl0(); sleep(&lbolt , RMPRI+1); } } } /* set the pre-fetch bit if not already set: */ setpre() { register char *p = ADDR; while( (p->drst & RDY)==0 ) /* null */; if( p->gpcsr&RPRE ) return; /* already set */ p->gpcsr = WPRE; /* set it (and nothing else in the gpcsr) */ while( (p->drst & RDY) == 0) /* null */; } /* clear the pre-fetch bit if not already cleared: */ clearpre() { register char *p = ADDR; while( (p->drst & RDY ) == 0) /* null */; if( p->gpcsr&RPRE ){ p->gpcsr = 0; while( (p->drst & RDY)==0) /* null */; } } /* strategy routine for the dma: */ /* Note: this is really strategy and start put together*/ rmstrategy(abp) struct buf *abp; { register struct buf *bp; register int cmd; register char *p; p = ADDR; bp = abp; p->drba = bp->b_addr; cmd = (bp->b_xmem&03) << 4; if( rm.flags&NOINCR ) { cmd |= AID; rm.flags &= ~NOINCR; } if( bp->b_flags&B_READ ) { setpre(); cmd |= DIO; } else clearpre(); p->drwc = -(u.u_count>>1); p->drst = cmd|IE; rm.flags |= IE; p->drst++; /* GO */ } /* * gtty -- sense status until peripheral has input * stty -- set NOINCR flag in rm.flags (cleared after io) */ rmsgtty(dev , av) int *av; { register int *v; register w; register char *p = ADDR; extern int lbolt; rmrdy(); if( v=av ) /* gtty */ for(;;){ wrrm( SPS ); w = rdrm(); if( w & (S_CBIT|S_RBIT) ){ v[0] = w; return; } sleep(&lbolt, RMPRI+2); } else /* stty */ rm.flags |= (u.u_arg[0] & NOINCR ); } rdrm() { register char *p = ADDR; setpre(); return( p->gpdata ); } wrrm(w) { register char *p = ADDR; clearpre(); p->gpdata = w; } ag in rm.flags (cleared after io) */ rmsgtty(dev , av) int *av; { register int *v; register w; register char *p = ADDR; extern int lbolt; rmrdy(); if( v=av ) /* gtty */ for(;;){ wrrm( SPS ); w = rdrm(); if( w & (S_CBIT|S_RBIT) ){ v[0] = w; return; } sleep(&lbolt, RMPRI+2); } else /* stty */ rm.flags |= (u.u_arg[0] & NOINCR ); } rdrm() { register char *p = ADDR; setpre(); return( p->gpdata ); } wrrm(w) { register char *p = ADDR; clearpre(); p-# /* * UNIX device driver for the Megatek 7000 : * * * Computer Aided Design and Graphics Lab * School of Mechanical Engineering * Purdue University * W. Lafayette, IN 47907 * (317) 493-9385 * * 12/20/79 * */ #include #include #include #include #include #include #define ADDR 0166000 /* location of megatek on unibus */ #define MEMSIZE 037777 /* GXST bits: */ #define STARTW 01 /* initiate a write DMA operation */ #define STARTR 02 /* initiate a read DMA operation */ #define RESET 04 /* bus reset */ #define CLRER 010 /* clear error bits */ #define IE 0100 /* interrupt enable */ #define RDY 0200 /* ready */ #define PIOER 010000 /* PIO error */ #define INTER 020000 /* interface error */ #define TOER 040000 /* bus time-out error */ #define ER 0100000 /* error bit (means one of the previous 3 should have been set) */ /* GPST (peripherals) bits: */ #define START 01 #define CLEAR 02 #define PULSE 04 /* IE 0100 */ #define MPDONE 0200 #define MPBUSY 04000 /* Peripheral Control / Select: */ #define IPCU 064 #define INPUT 0100 /* * general definitions: */ #define MEGPRI 9 /* sleeping priority */ #define NTRIES 50 #define BUFSIZE 20 /* size of peripheral circular buffer */ /* minor devices: */ #define DMA 0 #define PIO 1 #define PERIPH 2 #define TTY 3 struct { /* unibus structure */ int gxst; int gxmsd; /* most significant word of 32 bit data */ int gxlsd; /* least significant word of 32 bit data */ int gxpda; int gxwct; /* 2's comp of # of 16-bit words */ int gxsad; /* megatek start address */ int gpst; int gpd; /* peripheral data xfer word */ int gpcs; /* peripheral control word */ }; struct { /* bookkeeping */ int flags; /* status for interrupt waiting */ int procp; } mg , mgp; struct buf megbuf; int megaddr; /* megatek address */ int mgmode; /* -1 = tty, 0 = graphics */ int mcircbuf[BUFSIZE]; /* for peripheral circular buffer */ int *mget , *mput; /* * tty defines and data: */ #define TTYMODE -1 #define GRAPHMODE 0 /* Megatek opcodes */ #define DJMS 0176200 #define DNOP 0177000 #define DRET 0177100 /* IPCU kb commands */ #define TCLEAR 0141600 #define WTEXT 0140400 #define OPENNEW 0141603 /* character size and constants */ #define CSIZE 3 #define NCPL 72 #define NLPP 55 /* address constants */ #define TCBA 044 /* Text control block address */ #define BSTART (040000-1024) /* buffer start, 16k */ #define BEND 037777 /* buffer end, 16k */ #define ASEGTAB 0400 /* address of segment table */ /* etc. */ #define CURSOR '.' /* cursor character */ #define KCOPY 0222 #define KSTATUS 0223 #define KCLEAR 0224 #define KEYFLAG 0100000 struct tty mgtty; int bufhead[] = { /* buffer header */ 0140000+(-2047&07777), 0040000+2000, /* abs vector to x,y */ DJMS+0100, 2, /* rel djms .+2 */ DRET, 0, /* dret */ }; int tcb[] = { /* text control block */ BSTART+(sizeof(bufhead)/4), BEND, CURSOR<<8, (NCPL<<8) + NLPP, 0175400+(CSIZE<<4)+017, 0, }; int segtab[] = { /* short seg table for tty */ 0177000, 000044, /* display one */ 0177200, 010000, /* set z origin=0 */ 0150000, 070000, /* set x y origins=0 */ DJMS , BSTART, /* seg table start */ 0177000, 040000, /* sync and restart */ }; /* open the megatek: */ megopen(dev,flag) { register char *p; register struct tty *tp; if( dev.d_minor == TTY ){ mgtopen(dev,flag); return; } if( mg.procp != 0 ) { if( mg.procp!=u.u_procp ) { u.u_error = ENXIO; return; } if( dev.d_minor!=PERIPH ) return; } tp = &mgtty; if( dev.d_minor==PERIPH ) { /* want to init peripherals */ if( mg.procp==0 ) { /* must setup others first */ u.u_error = ENXIO; return; } wrmg( 0100, 0, 3); /* setup button for int. */ wrmg( 0102, 0, 0); /* raw joystick values */ wrmg( 0103, -2048, -2048); /* lower left corner of joystick bounds */ wrmg( 0104, 2047, 2047); /* upper right corner of joystick bounds */ wrmg( 0105, 0140000, 040000); /* blank vector for cursor */ wrmg( 0106, DRET, 0); /* ensure DRET */ wrmg( 0110, 0, 3); /* tablet strike ints. */ wrmg( 0112, 0, 0); /* raw tablet values */ wrmg( 0113, -2048, -2048); /* lower left corner of tablet bounds */ wrmg( 0114, 2047, 2047); /* upper right corner of tablet bounds */ wrmg( 0115, 0140000, 040000); /* blank vector for cursor */ wrmg( 0116, DRET, 0); /* ensure DRET */ mget = mput = mcircbuf; /* setup peripheral circular buffer */ mgrdy(); /* be sure megatek is ready again */ mgpinit(0006000); /* tablet */ mgpinit(0030000); /* init joystick */ if( (tp->t_state&ISOPEN)==0) mgpinit(0140000); /* init kb if tty not open */ mgmode = GRAPHMODE; return; } if( tp->t_state&ISOPEN == 0) if( mgreset() ) return; /* error during reset */ mg.procp = u.u_procp; } mgreset() { mgrdy(); /* be sure megatek is ready */ ADDR->gxst = RESET; mgrdy(); if( mgerr() ) { u.u_error = ENXIO; /* something wrong with interface */ return(1); } return(0); /* ok */ } megclose(dev) { register char *p; mgrdy(); p = ADDR; switch( dev.d_minor ){ case DMA: p->gxst = mg.procp = 0; break; case PERIPH: if( mgtty.t_state&ISOPEN ){ mgmode = TTYMODE; /* reset mode if tty open */ wrmg(ASEGTAB+3,DJMS, BSTART); /* reenable display */ }else p->gpst = mgp.flags = 0; break; case TTY: if( mg.procp ) mgmode = GRAPHMODE; mgtclose(dev); break; } } megwrite(dev) { int mgstrategy(); register char *p; if( dev.d_minor == TTY){ ttwrite(&mgtty); return; } megaddr = fuword(u.u_base); u.u_base += 2; u.u_count -= 2; if( megaddr == -1 || u.u_count&03 ){ u.u_error = EIO; return; } mgrdy(); switch( dev.d_minor ) { case DMA: physio( &mgstrategy , &megbuf , dev , B_WRITE ); break; case PIO: mgpio( B_WRITE ); break; default: u.u_error = ENXIO; break; } } megread(dev) { int mgstrategy(); if( dev.d_minor == TTY){ ttread(&mgtty); return; } if( dev.d_minor != PERIPH){ megaddr = fuword(u.u_base); if( megaddr == -1 || u.u_count&03){ u.u_error = EIO; return; } } mgrdy(); switch( dev.d_minor ) { case DMA: physio( &mgstrategy , &megbuf , dev , B_READ ); break; case PIO: mgpio( B_READ ); break; case PERIPH: if(u.u_count != 2){ u.u_error= EIO; return; } suword( u.u_base, mbufread() ); /* immediate return of data */ break; } } /* strategy for dma xfer (this routine combines strategy and start): */ mgstrategy(abp) struct buf *abp; { register struct buf *bp; register int cmd; register char *p; bp=abp; p = ADDR; p->gxsad = megaddr; p->gxpda = bp->b_addr; cmd = (bp->b_xmem&03) << 4; p->gxst = cmd|IE; p->gxwct = bp->b_wcount; if( bp->b_flags&B_READ ) p->gxst |= STARTR; else p->gxst |= STARTW; } /* handle interrupts from i/o interface: */ megintr(dev) { mg.flags &= ~IE; ADDR->gxst &= ~IE; megbuf.b_flags |= B_DONE; wakeup( &megbuf ); } /* handle interrupts from the peripherals: */ megpintr(dev) { int c; register w; register struct tty *tp; register char *p; tp = &mgtty; p = ADDR; if( ((c = p->gpcs)&077) == IPCU ) { /* this was a peripheral interrupt */ p->gpcs = IPCU; /* echo it back */ if( c & INPUT ){ w = p->gpd; /* read input */ if( w&KEYFLAG) /* key */ switch( w&0377 ){ case KSTATUS: if((tp->t_state&ISOPEN) && mg.procp){ mgmode = ~mgmode; /* toggle tty/graphics */ if(mgmode==TTYMODE) wrmg(ASEGTAB+3, DJMS, BSTART); else wrmg(ASEGTAB+3, DNOP, 0); goto doclear; } case KCLEAR: while(p->gpst & MPBUSY) /*wait*/; p->gpst |= (PULSE|CLEAR); p->gpcs = IPCU; p->gpd = (WTEXT | KCLEAR); p->gpst |= (START | IE); return; case KCOPY: w = '\t'; /* and fall thru */ default: if(mgmode==TTYMODE){ ttyinput(w,tp); goto doclear; } } if( ++mput >= &mcircbuf[BUFSIZE] ) mput = mcircbuf; if( mput==mget ) { /* buffer overflow! */ mput = mget = mcircbuf; mput++; /* wipe out buffer and start over */ } *mput = w; doclear: p->gpst |= CLEAR; /* clear ipcu */ }else{ /* write interrupt */ p->gpst |= (PULSE|CLEAR); if( tp->t_state&ISOPEN){ ttstart( tp ); if(tp->t_outq.c_cc==0 || tp->t_outq.c_cc == TTLOWAT) wakeup( &tp->t_outq ); } } }else{ p->gpst |= CLEAR; printf("Meg IPCU Error,gpcs=%o\n",c); } if( mgp.flags&IE){ mgp.flags &= ~IE; wakeup( &mgp ); } } /* handle programmed i/o (PIO): */ mgpio( flag ) { register int count , *base; register maddr; int w[2]; base = u.u_base; maddr = megaddr; if( (char *)base&1 || u.u_count&3 ){ u.u_error = EIO; return; } count = u.u_count>>2; switch( flag ) { case B_READ: while( count-- ) { rdmg(maddr++, w); suword(base++, w[1]); /* rdmg returns msd second */ suword(base++, w[0]); } break; case B_WRITE: while( count-- ) { w[0] = fuword(base++); w[1] = fuword(base++); wrmg(maddr++, w[0], w[1]); } break; } } /* be sure megatek interface is ready: */ mgrdy() { register int n; register char *p; p = ADDR; for(;;){ for(n=0; n<=NTRIES; n++) if( p->gxst&RDY ) return; spl5(); mg.flags |= IE; p->gxst |= IE; sleep(&megbuf, MEGPRI); spl0(); } } /* be sure megatek peripheral interface is ready: */ mgprdy() { register int n; register char *p; p = ADDR; for(;;) { for(n=0; n<=NTRIES; n++) if( (p->gpst&MPBUSY) == 0 ) return; spl4(); mgp.flags |= IE; p->gpst |= IE; sleep(&mgp, MEGPRI); spl0(); } } /* do PIO to/from megatek: */ rdmg(maddr,aw) int *aw; { register int *w; register char *p; mgrdy(); p = ADDR; w = aw; p->gxsad = maddr; *w++ = p->gxlsd; /* note w[0] = lsd! */ *w = p->gxmsd; /* and w[1] = msd */ } wrmg(maddr, w1, w2) { register char *p; p = ADDR; while( (p->gxst&RDY) == 0) /* null */ ; p->gxsad = maddr; p->gxmsd = w1; p->gxlsd = w2; } /* detect megatek errors: */ mgerr() { register int stat; register char *p; p = ADDR; if( (stat=p->gxst)&ER ) { printf("Megatek DMA Error,gxst=%o\n",stat); p->gxst |= CLRER; return(1); } return(0); } /* handle the initiation of a megatek peripheral: */ mgpinit( idev ) { register char *p; mgprdy(); /* NOTE: interrupts not enabled at this point */ p = ADDR; p->gpcs = IPCU; p->gpd = idev; /* which device */ p->gpst |= (START|IE); mgprdy(); p->gpcs = IPCU; p->gpd = idev; p->gpst |= (PULSE|CLEAR); } /* * stty: * do nothing * * gtty: * wait to read anything from a peripheral. * NOTE: a 'gtty' is only legal if /dev/mgper has been opened! * */ mgsgtty(dev , av) int *av; { register int *v; if( dev.d_minor == TTY){ ttystty(&mgtty, av); return; } if( (v=av) != 0 ) { /* stty */ if( dev.d_minor!=PERIPH ) { u.u_error = EIO; return; } for(;;){ mgprdy(); if( v[0] = mbufread() ) return; /* something was read, so return */ spl4(); ADDR->gpst |= IE; /* be sure interrupts are enabled */ mgp.flags |= IE; sleep(&mgp , MEGPRI); spl0(); } } } /* read from circular buffer */ mbufread() { if( mget==mput ) return(0); /* nothing there worth reading */ if( ++mget >= &mcircbuf[BUFSIZE] ) mget = mcircbuf; return( *mget); } /* * Megatek 7000 TTY driver routines */ /* open megatek tty: */ mgtopen(dev, flag) { register char *p; register struct tty *tp; int mgtstart(); if( mg.procp != 0){ u.u_error = ENXIO; return; } tp = &mgtty; if (u.u_procp->p_ttyp == 0) { u.u_procp->p_ttyp = tp; tp->t_dev = dev; } p = ADDR; if ((tp->t_state&ISOPEN) == 0) { if( mgreset() ) return; tp->t_state = ISOPEN|CARR_ON | SSTART; tp->t_flags = XTABS|ECHO|CRMOD; tp->t_erase = CERASE; tp->t_kill = CKILL; tp->t_tabexp = TABLEN; tp->t_addr = &mgtstart; mgdma( ASEGTAB, segtab, sizeof segtab); mgdma( TCBA, tcb, sizeof tcb); mgdma( BSTART, bufhead, sizeof bufhead); wrmg(1, 0, ASEGTAB); mgpinit( 0140000 ) ; /* init kb */ mgprdy(); p->gpcs = IPCU; p->gpd = TCLEAR; /*clear text */ p->gpst |= START; mgprdy(); p->gpcs = IPCU; p->gpd = OPENNEW; /* open new text buffer */ p->gpst |= START; mgprdy(); wrmg( 0177761, 5, 0); /* start micro */ wrmg(2, 1, BSTART); /* tell grafic we're here */ mgmode = TTYMODE; } } /* close Megatek tty */ mgtclose(dev) { register struct tty *tp; register char *p; p = ADDR; tp = &mgtty; wflushtty(tp); tp->t_state = 0; wrmg(2, 0, 0); if( mgp.procp == 0 ) p->gpst = 0; } /* write chars to megatek from output queue: * called by ttstart */ mgtstart(atp) struct tty *atp; { register c; register char *p; p = ADDR; if( p->gpst & MPBUSY ) return; if( (c=getc(&atp->t_outq)) >= 0){ if( mgmode==GRAPHMODE ){ /* switch to tty mode on char printing */ mgmode = TTYMODE; wrmg( ASEGTAB+3, DJMS, BSTART); } p->gpcs = IPCU; p->gpd = (WTEXT | c); p->gpst |= (START | IE); } } /* dma output to megatek: */ mgdma(maddr, baddr, nbytes) { register char *p; mgrdy(); p = ADDR; p->gxsad = maddr; p->gxpda = baddr; p->gxwct = -(nbytes>>1); p->gxst = IE; p->gxst |= STARTW; } er c; register char *p; p = ADpripL53tL20009pL20011~L58L59L60gL20013L61L64L65vL66lL67|_copyseg _expand"~expandinpnewsizea1a2L70L69XL71L724L20015 subr.o w @55S@5/5LN C5 @ @m@ @m0  %@0 @U@t55@ @mBN 0 w2@ @mN  @ @m7 %@ @m7@ @m0f %4@tEe5 `N 5 @ `AH  f 5D@E5 `N 5@ `N   7 %@ `7w     w@ j w ğ  Ewb jw Duw:w 6w2w .DCB~wY(y((((YYYYYYYyYYYYYYYYyYYhYYyyy_bdevsw _nblkdev _cdevsw _nchrdev _inode _u "_buf h_bfreeli _canonb _coremap _swapmap _rootdir _cputype _execnt _lbolt _time _tout _callout x_mount _mpid _runin _runout _runrun _curpri _maxmem _lks _rootdev _swapdev _swplo _nswap _updlock _rablock _regloc _bmap"~bmapbnbpnbipdibapnbpcsv L2"L20005L9L4_alloc L20004J_bdwrite L12L13:L14(L1cret L10L11$L15H_bread L16L17L18_brelse L19L20L21_passc"~passccL24NL25.L27<L10000jL20006FL23J_subyte _cpass"n~cpassncL29L20009xL28L20008~L31L33_fubyte _nodev"~nodev_nulldev"~nulldev_bcopy"~bcopytofromabccountL39text.oD l<w D 5et l  < f& e ~  f %4p7j w^w Z$0  <54 et& %  ww _8  e % t-0a 4 tle?tEet  e  & & e7 N v e& e3C      % ww D  & %wout of swap spaceswap errorout of textout of swap spaceI(h)I()I(h)I)_canonb _coremap _swapmap _rootdir _cputype _execnt _lbolt _time _tout _callout x_mount _mpid _runin _runout _runrun _curpri _maxmem _lks _rootdev _swapdev _swplo _nswap _updlock _rablock _regloc _u "_proc L_text _inode _xswap"~xswapffosrpapcsv L2_malloc L38L4l_panic _xccdec"<_swap L5fL6~L7~_mfree L1_wakeup cret _xfree"~xfreeipxpL9_iput _xalloc"~xallociprpxptsL138L14L20001L16L15>L21L22JL23L24L25_expand _estabur _readi L264_savu _swtch ~xccdec<rpxpL27htrap.oD VPw @E%U@e 7@  x&J NeT N^ l   ~  v wjNe %  >7mENe Ete%)N e E?%?Ete "e  1  N  1e "b d_~U5 _~ _r __rCL  _~ _rw . 7ww d'ww w:::::::n::ka6 = %o aps = %o trap type %o trapIY )8Yhhhh(HIxYIYIY_canonb _coremap _swapmap _rootdir _cputype _execnt _lbolt _time _tout _callout x_mount _mpid _runin _runout _runrun _curpri _maxmem _lks _rootdev _swapdev _swplo _nswap _updlock _rablock _regloc#_u "_proc L_ka6 _sysent _trap"L10002&L29L5:L10nL11L13L14L15L16L30L31~trappcsppsaidevcallpnps r1r0 csv _savfp L2L6J_printf L7TL8^L9l_panic L3r_psignal L12~_issig L33_psig _setpri L1cret _fuiword L10000L17B_fuword L18L19(L22bL23^L20001F_trap1"L26|L27_backup L32_grow ~trap1f_savu _nosys"~nosys_nullsys"~nullsyssig.o*Pw t-N& * e%Lww %D t̥d̕d̥ ww Ĝ   Ĝ  wr 5w ` ˕ P  x% , e%L ww J2 57/%% 0 e j&e & 0E x7D  etQ7* ^wZw V78  mI C 55`1FB- 7 @7 >2. e & && e7 t77   ww d t@-@@ & @e 60`(" e  w>v` h`@l &   `w R̥ - 0- e%L:  7 FE7x

e U E_D _ _2Jdcore)i)i)i)9i)9i)hxi)i()i)i  8 H X X 9_canonb _coremap _swapmap _rootdir _cputype _execnt _lbolt _time _tout _callout x_mount _mpid _runin _runout _runrun _curpri _maxmem _lks _rootdev _swapdev _swplo _nswap _updlock _rablock _regloc _u "_proc L_inode _ipc _signal"~signaltppsigcsv L20001L4_psignal"*cret ~psignal*rppsigL6^L7HL8R_setrun _issig"b~issigbnpL20004L12_stop"L1cpppL16L20006_wakeup _swtch L15_procxmt"L17L20008_exit _psig"L10001L35L25~psigrpnpL23nL24_grow"j_suword L22_core"~coreipsL388_schar _namei L39L20012^_maknode _access L42R_itrunc _writei _estabur _iput L10002dL37`~growjsispaiL20020_ldiv L46L43_expand L47L20017_copyseg L50 L20019_clearse _ptrace"~ptracepL54.L53L200222L57LL59^L60t_sleep L61L20024L63L10007(L68L702L71JL72dL73L74L80L81~procxmtipL65L20025L64L69 _fuibyte _fuiword L20028,_fubyte _fuword _suiword L20029L10005L75L76L20027L79sysent.o<K hX(8HXhx(8HXhx(8HXhx_sysent#_nullsys _rexit _fork _read _write _open _close _wait _creat _link _unlink _exec _chdir _gtime _mknod _chmod _chown _sbreak _stat _seek _getpid _smount _sumount _setuid _getuid _stime _ptrace _nosys _fstat _stty _gtty _saccess _nice _sslep _sync _kill _getswit _dup _pipe _times _profil _setgid _getgid _ssig _lock _unlock _empty _wake _nicer clock.oP ,w M 2 e  5#   &  e  3ee3@E%  f  h F%<@_5f<, * " -- 5 ʋE%  r2d e%Lۂ7 @E%@e 7 v  n wbw ^ B J e e   !tt_wyXiiiyyyyyh(Ii(yyy_canonb _coremap _swapmap _rootdir _cputype _execnt _lbolt _time _tout _callout x_mount _mpid _runin _runout _runrun _curpri _maxmem _lks _rootdev _swapdev _swplo _nswap _updlock _rablock _regloc _u "_proc L_clock"~clockpcsppsppdevnps r1r0 p1p2csv _display L2xL3$L20001L4(_spl5 L6TL20003BL7ZL8pL20005`L10L12_incupc L13L1L15_spl1 L16_wakeup L17L20007L20RL22"L23@L24D_setpri L26n_issig L28_psig cret _timeout"~timeoutargstfuntimp1p2_spl7 L30L20009L31L32L20011L34L20013fio.o ~"w C % w  w D̵Ee e  E& v ww DE~7 yfWp % w@ft w *DE7 y-fWp ft %-ww DC% %!̵  %@5I 7 t7 t0 wPw L    7 h   ww Jw9 w   ?w % w   04 4 we%   ` `&2no file  hhHh(YH(9   h  H _u "_file _bdevsw _nblkdev _cdevsw _nchrdev _inode _getf"~getffprffcsv L2 L1cret _closef"*~closef*fpiprfpL5V_wakeup L6n_closei"vL10001~L10002L11L12L8~closeiviprwmajdevripL10003L20000_iput _openi"L10005L10006L16L18&L132~openiiprwmajdevripL10007L17,L20001"L20003_access"6~access6ipmodemaipL20l_getfs L21fL20009L20006^L23L10008L24L19L25_owner"~ownerip_uchar _namei L29L20014L20011L28_suser"~suserL33L32_ufalloc"~ufallociL20016L37L34_falloc"0~falloc0fpiL40ZL20021<L39VL20018@L20020^L45_printf malloc.o0hw CK-smK ewe  w BD e D-m tm@m-*4c &e44@m- tLm  Lew$ii_malloc"~mallocbpmpsizeacsv L2<L20001 L48L62L9"L14cret _mfree"D~mfreeDbpmpsizeataaL11ZL20003RL12`L14L10L16L19L24nami.ohw : %/&  %/    _ _E%@@& H   %VҐ %/%V %/o7 v7 p^5 & 7R5 J$ N % & 7B @e7 5 N  & & 5X@&E` %e  HZH` %V N % & _Pw5 >f _\_Vw E ww   %jwiY888HX8ii_inode _u "_canonb _coremap _swapmap _rootdir _cputype _execnt _lbolt _time _tout _callout x_mount _mpid _runin _runout _runrun _curpri _maxmem _lks _rootdev _swapdev _swplo _nswap _updlock _rablock _regloc _buf h_bfreeli _namei"~nameiflagdpcpeobpfuncccsv L2_iget L32L20001,L7\L20010BL6PL20014J_iput L20015VL1L20003_access L10L20005L13L12L20007L15L20009_ldiv L17L18@L19_brelse L21:L23~L24V_bmap _bread _bcopy L25L20012L30L31 cret _schar"0~schar0_uchar"D~ucharDc_fubyte L35bpipe.o tw  # ( ʕ2˕3̕w3@ 0  w  *̵'̵,  ˵@5 ?VNe g> Www D0˵@@e 7 4 3 5Ee   Ue  Z, 7 7  ww |D Z  7   } z w4 e  Z˵@% U e 7 * & 7  5Ee w D& ̵w~w zD̵ w^))8YY)h)Hh)HHHX)H)_canonb _coremap _swapmap _rootdir _cputype _execnt _lbolt _time _tout _callout x_mount _mpid _runin _runout _runrun _curpri _maxmem _lks _rootdev _swapdev _swplo _nswap _updlock _rablock _regloc _u "_inode _file _pipe"~piperrfipwfcsv _ialloc L1X_falloc L20001jL20003\cret _iput _empty"r~emptyrvfpip_getf L5L6L10001L10000L10002L4_sgtty _readp"~readpfpiprpL10RL20007L12_wakeup L20005vL13._prele"L9|_sleep _plock"Z_readi _writep"~writepcfpiprpL16L17L15L19_psignal L20011L21_min _writei ~plockZiprpL24tL20013d~preleiprpL26sys1.o ,w    _V %  5@ _45`_4@5 5 $ %_4eBN %_4 %_4  55 `\7 \7 VD 7:7_45 %Nm7 e?tE5me?tE5Nff e _47   De$ $ 4˵ _4% % s_4pa % & f& e7 Je7D: www e@@ A @e5pNf @ ef & ҋ@ fe z5 b Z 5 G5 e%  m %0  %6 N % ww t7^ ww %   e% L  ,  % D& %̕,   ,  ʥ e%L e%Lڂ w  , n ʥL h  % 2 2 22 2lB   l    1ʥ   WtUp0 e%L ( _p wzw vˋ e%L  T ? `7 X7 V7 J7 H7 F7 <  @81`ww  e?tE  t  e`` e ` `|t&  N wz `< &     out of swapXYY(xhxxx(8YXXYii(((X9hxXX9(8iYiX iX h_canonb _coremap _swapmap _rootdir _cputype _execnt _lbolt _time _tout _callout x_mount _mpid _runin _runout _runrun _curpri _maxmem _lks _rootdev _swapdev _swplo _nswap _updlock _rablock _regloc _u "_proc L_buf h_bfreeli _inode _exec"~execnaapncbpdsipcptscsepcsv _uchar _namei L2*L1VL20001_sleep _getblk _access L44L5L20015tL7_fubyte L9_fuword L10_readi L11L16_estabur _xfree _expand _xalloc L17L20003L12L20005_clearse _suword L19L20007|L23_subyte L24L25L20009L30L20011L20013*_iput _brelse L36R_wakeup cret _rexit"Z~rexitZ_exit"r~exitraqpL20017L20019L43_closef _malloc L45L46_panic _bcopy _bwrite _mfree L47L20023L50XL200210L54J_setrun _swtch _wait"j~waitjbpfpL58pL20025tL61\L63 _bread _dpadd L57L65PL66|_fork"~forkp1p2L20027L71L72_newproc L73L67_sbreak"~sbreakadinL75_nseg L76L74L77L78rL20029d_copyseg L80L20031L82sys2.o. <w  ww  ww C >̰ 87̵ %  77%  6&e "?fwLw H     & $%w"w  ?E  & $%ww CB%5 5 E%@'   rE tE @ 0  w0w ,> 2 0  w w  D̵#=%t 5t5%E ~5    x.5mfe ttwl E5` w N  Ag6E%@  +d - #N0-    ww    R H wpw l d`\jfe F@ff e  (w$" e Nf e wwZ nn  x(8 x x (H x x8 x xHH8H  xH yy8yy yyH_canonb _coremap _swapmap _rootdir _cputype _execnt _lbolt _time _tout _callout x_mount _mpid _runin _runout _runrun _curpri _maxmem _lks _rootdev _swapdev _swplo _nswap _updlock _rablock _regloc _u "_file _inode _read"~readcsv _rdwr" cret _write"~write~rdwr fpmodem_getf L3L4@L5lL6d_readp L8_writep L9_readi L10_writei _dpadd _open"~openip_uchar _namei L11_open1"$_creat"~creatipL13L12 _maknode L20003~open1$fpipmodeimtrfripL16rL17L_access L20L21_itrunc _prele _falloc _openi L15_iput _close"~closefpL22_closef _seek"L10001.L29L32nL33~seekfpntL23L24L25FL27`L20007x_link"~linkipxpL36DL37L38>L10002_suser L39L400_wdir _mknod"H~mknodHipL42nL44L41_sslep"~sslepd_spl7 L20008_dpcmp L20010_spl0 L10003L48 _sleep sys3.o  w  & L ww    & L  ww f @&e @& @&e tle@e5 Nef e % f e % ww     ww 5!   5     "  w~ e%  2& f@t %}f g 2J 2& %22E2  w 5; " e%* 5-e % & f@t % 3  ww$w ww & %  00ww  3 $  E%@ X7    wlw h  E%@{ @& n 7f ww  E8EE4P ww     ww p%%  ? J!0wfw b 5 n    ,%d7\ & e%L܂ 3ww   e%ww E7 E7ww ww wzw v 5   % ,%|7t j- %4e%Lт 1ww  ww ĝ   !5 5p 5\@  7wvunlink -- iget  Y x  Y   Y     Y HXx Y   HX h  x   Y       (     Y     Y x  HX h h h _u "_inode _canonb _coremap _swapmap _rootdir _cputype _execnt _lbolt _time _tout _callout x_mount _mpid _runin _runout _runrun _curpri _maxmem _lks _rootdev _swapdev _swplo _nswap _updlock _rablock _regloc _proc L__iob _getswit"~getswitcsv cret _gtime"~gtime_stime"&~stime&_suser L3J_wakeup _setuid"N~setuidNuidL10000dL5t_getuid"x~getuidx_setgid"~setgidgidL10001L8_getgid"~getgid_getpid"~getpid_sync"~sync_update _nice"~nicenL14L15_unlink"~unlinkippp_uchar _namei L17_prele _iget L18JL19_panic L10002`L20_writei _iput _chdir"~chdiripL21L22L23_access _chmod"~chmodip_owner L24L25_chown""~chown"ipL26L_ssig"P~ssigPaL10003fL28nL27_kill"~killafpqL20001L33L10004L10005L10006_psignal L30_times"~timespL20003_suword _profil",~profil,_lock"Z~lockZL39p_unlock"t~unlockt_nicer"~nicerafpqL20005L10007L45L10008L10009L10010L10011L10012L42_wake" ~wake L47_saccess""~saccess"svuidipL50L51TL52hL53|04L10005L10006_psignal L30_times"~timespL20003_suword _profil",~profil,_lock"Z~lockZL39ebio.o4 w Nf " 5wU &@t   w B N  N " 5 U &@t  #N  N " 5  U @t  N w w DE & t  5  5 ww D t%% rU ww DU wxw tD5@ 5@^E@V 5  6EH0 ww D@t s-3! w  w @-4  %<U@ @t;  t-t-  f5U@& P LwD :< L5U 0003t tw D & 5  ww D 00Uww D5  pU5 E@ wPw L@ ~w8w 4 727,7&7  WpDe Wpet07  %  @ e ww DCL @ tEWt@PUA5UUwVw RDC%FD L EtUA5U8U0w w %F5 U@ 5U BU  e%   e%0ww E 5@ 7 rwnw j bU@& 5@ U  j'ww D57wblkdevdevtab88888HX))(((8I(())(HY8YY)HY())))(()))8Ii h Hi i Yi h i 8H9999988HY)(Y     H  H Y   _u "_buf h_bfreeli _bdevsw _nblkdev _cdevsw _nchrdev _canonb _coremap _swapmap _rootdir _cputype _execnt _lbolt _time _tout _callout x_mount _mpid _runin _runout _runrun _curpri _maxmem _lks _rootdev _swapdev _swplo _nswap _updlock _rablock _regloc _proc L_ka6 _buffers _swbuf _tmtab _httab _bread"~breadblknodevrbpcsv _getblk""L2 L20000cret _iowait"_breada"B~breadaBblknorablknodevrbpadevrabp_incore"L4L6L7_brelse"L9L3_bwrite"~bwriterbpflagbpL11,L108_geterro"_bdwrite"<~bdwrite<rbpbpdpL10000\L15d_bawrite"rL14n~bawriterrbpbp~brelsebackprbpspsbpL19_wakeup L20L21_spl6 ~incoreblknodevadevbpdpL23L20002L25L22~getblk"blknodevbpdpL30bL294_panic L20004:L32>L39L20007X_sleep _spl0 L33~L34;L35L37L38_notavai"LL20008L40~iowaitrbpbpL428L20010,~notavaiLrbpspsbp_iodone"|~iodone|rbpbpL46_mapfree"pL47L45_clrbuf"~clrbufcpbpL52_binit"~binitbdpibpdpL20012L57RL200148L60J_devstar"`~devstar`hbcom comrbpdevlocdevblkbpdpL62L63_rhstart"~rhstartcomrbpdevlocdevblkabae bpdpL65L66L67_maplock _mapallo"~mapalloabpaibpL68lL69L20016L20018>L74`L20020T~mapfreepbpL78_swap"~swapblknocountrdflg coreaddrfpL80L20022L82L20024L840_bflush"B~bflushBdevbpL86hL20026HL10001XL89xL87|L20028r_physio"~physioabpstratdevbasenbbptsrw L92 L93L10002L94*L20030L10003VL10004Z_lshift L96L20032L98L91~geterroabpbpL990cat.oHw  U@ww 7 ww "   %<  &   w~w z5  `%X   F w<i)) i)i)(X)X(i())(8)_u "_partab _cat _ctopen"~ctopendevcsv L2L1cret _ctclose" ~ctclose _ctwrite",~ctwrite,devcL6vL200052_spl5 L8FL200018_sleep L10^L20003P_lbolt _putc _catintr"_spl0 _cpass ~catintrcL13_getc L10000L12_wakeup dr.o}<w D% Wt@ ww C3Wt@ ww 55wAWt@ e 4 5 5 %  BU@ & .w ( b5V5CwAWt@ e 5 5 %  U  & w AWt@E@ ww AWt@E  wjX X X  (Yhy HYhy  _u "_bdevsw _nblkdev _cdevsw _nchrdev _drlock _dropen"~_dropencsv _dev_flag_j_addrL10000L4L34cret _drclose"8~_drclos8_dev_addr_j_drwrite"X~_drwritX_dev_addr_base_nwords_countL10001rL11|L10xL12L20001_fuword L14L20003_spl5 _sleep _spl0 _drread"~_drread_dev_addr_base_nwords_countL10002L23L22L24L20005 _suword L26"L20007&_drxint"R~_drxintR_dev_addr_wakeup _drrint"t~_drrintt_dev_addrkl.oVx~w %<AWp(Ce sDuepeeH3UCU@wpw lAWp(De 4wPw LAWp(Ne w6w 2AWp(Ne ww AWp(De % e ww AWp(BeU $  $& %& ww AWp(DeN& wIxIYxYxYx(YxxYx(HYxY_bdevsw _nblkdev _cdevsw _nchrdev _u "_partab _proc L_kl11 _klopen"~klopendevflagaddrtpcsv L2L1L36L4LL5XL6cret _klclose"~klclosedevtp_wflusht _klread"~klreaddev_ttread _klwrite"~klwritedev_ttwrite _klxint"~klxintdevtp_ttstart L10000 L10_wakeup _klrint"~klrintdevcaddrtpL13N_sufet L12X_ttyinpu _klsgtty"\~klsgtty\devvtp_ttystty lp.o 4w 5 L UU@L ^ww  ^7 ww  ^ ww D %a%z e7 y 7n y ( )'!^ ^ D-:eE7.w 5   7  %< 5  % 7 7   - 7 %P  -  w | N5Lw^w Z %2P J wYIYYYYYYYYYYYYYYYYYYYYYYYYYYXYYXXYXX_bdevsw _nblkdev _cdevsw _nchrdev _u "_lp11 _lpopen"~lpopendevflagcsv L10000L2L1._lpcanon"^cret _lpclose"2~lpclose2devflag_lpwrite"F~lpwriteFcL5RL20001L_cpass L10002L10003L16L13L17L15L18L8|L10007L10008 L292L21L23L27 L31zL32>~lpcanon^cc1c2L9L10009L10004L14L7L10005L25_lpoutpu"L33RL35hL20003\_lpstart"~lpstartcL38L20005_getc L37_lpint"~lpintcL10010L40_wakeup ~lpoutpucL43_sleep _putc _spl4 _spl0 mem.odFw AB  E tE mE@` __ ~ wjw f7 7aB w>B nE "Q tE mE@` __  )YHY hy y 9 )YXY_u "_bdevsw _nblkdev _cdevsw _nchrdev _ka6 _mmread"~mmreaddevacdbnoncsv L1L4_lshift _spl7 L5j_fuibyte _spl0 _passc cret _mmwrite"~mmwritedevacdbnonL8_dpadd L6_cpass L10*_suibyte mg.o,ZZw E@E@U ww E%t e%(- 77e4U  E@z vwrw n l -d^ZB F@<  E( @ H  M @  77 Z0 Z Z @@   ww  777 wvw rDj EtU@ E 5UUw$w Z 7eLH @  xZ f ew w  7 @  x`f ew w t5w^u@  xf  e e  e  e   w     5@   %25ww    ~  5@r   %25 wNw J F7 @>w8 4 J, &w   *7  _w ww 5tE5@ j ~5  ww 4_U@UA E%4N _U U wFw BD E0_ w P t ( 5 U@ U@  w - we%( &.ZvMegatek Bus TimeoutMegatek Interface ErrorMegatek Peripheral Init Error)y8I)8I)y y yy yI)yyI) I)  I ) I ) I 88)yI)I)I)I)8I)8I) I)I_u "_bdevsw _nblkdev _cdevsw _nchrdev _buf h_bfreeli _mg _mgp _megbuf _meg_add _mgpio _mcircbu (_mget _mput _megintr"~megintrdevcsv _wakeup cret _megpint""~megpint"dev_spl5 L3xL4LL5f_spl0 _megopen"~megopendevflagL7L8L20000L6dL9<_wrmg"_mgrdy"_mdv_ini"Z_mgerr"_megclos"h~megcloshdevflag_mgstrat"~mgstratabpcmdbpL14L13_megwrit"L10001ZL19 L20&L21.~megwritdev_fuword L16"_physio _mdirect"_megread"6L10003`L25ZL26vL27~megread6devL22rL10006fL36L33~mdirectcountflagbaseL10004L29L28_rdmg"_suword ~mgrdynL39RL20004 _sleep L200068L41TL20008<_lbolt _mgprdy"f~mgprdyfnL47L20012lL20014L49L20016~rdmgL55L54~wrmgwL57L56~mgerrdevstatL59TL60NL61jL20019:_prdev L58VL20021FL63~~mdv_iniZidevgpcsL65L66L64_mgsgtty"~mgsgttydevvwavL68L69L67L20023L20025L72_mbufrea"(~mbufrea(ipL75:L746L76Npartab.o _partab#pc.o$w  !%Ah U@l vww    h7  Fww ~%v5hUAh    >w:w 6 t *w"w 5l nww %5h!%5hj %UAh ww ~%2 ww 5l%dz( f P * HwDw @d tw0YIYY)XY)YXXH))X)YYYYXhYXx)YXx)IYXXh))_bdevsw _nblkdev _cdevsw _nchrdev _u "_pc11 _pcopen"~pcopendevflagcsv L2<L3L1FL4_lbolt _sleep _pcleade"cret _pcclose"J~pccloseJdevflagL8r_spl4 L9X_getc _spl0 L7v_pcread"z~pcreadzcL16L20001L18L19_passc _pcwrite"~pcwritecL21L20003_pcoutpu"t_cpass _pcstart"~pcstartcL23_pcrint"~pcrintL26L25TL280L29L_putc _wakeup _pcpint"X~pcpintXL31p~pcoutputcL34L33L35~pcleadeiL39rf.ot*w D5 t -U 4  707  ww 8 t&6& ewjw fb$b7X 080& %09 3 U7)7( zww f eww  f ew9yyyyyyyyyy8yyyy_buf h_bfreeli _bdevsw _nblkdev _cdevsw _nchrdev _u "_rftab _rrfbuf _rfstrat"~rfstratabpbpcsv L2_mapallo L30_iodone L1^_spl5 L4DL5LL6Z_rfstart"b_spl0 cret ~rfstartbbpL7_devstar _rfintr"~rfintrbpL8L9_deverro L20000_rfread"~rfreaddev_physio _rfwrite" ~rfwrite devrk.ow)*@w D5 e5AWp-U 4  707 t ww D e5 5N 5N  r f r tUAWt @Pww  & ~ & & eww (7 5 & %U77 zww f ewtw p f ewV(XyyyyyyxyyyyyyyHyyX_buf h_bfreeli _bdevsw _nblkdev _cdevsw _nchrdev _u "_rktab _rrkbuf _rkstrat"~_rkstracsv _abp_bp_qc_ql_dL4_mapallo L5*L6D_iodone L3r_spl5 L7XL8`L9n_rkstart"_spl0 cret _rkaddr"v~_rkaddrv_bp_p_b_d_mL13L14_lrem _ldiv ~_rkstar_bpL17 _devstar _rkintr"~_rkintr_bpL20hL21TL22,L20000d_deverro _rkread"l~_rkreadl_dev_rkstrat _physio _rkwrite"~_rkwrit_devrm.o- <dw -.# @<@6 5< N ww  < 67 ww 5@E@|EH5E@7d \  U ww(w $5<_>w|Ramtek errorRamtek int errorRamtek error:y y y H yYyYyyHY Y y H yXiY Y H yXiiHXHYYYyy yYyy yXi y  YYY_u "_bdevsw _nblkdev _cdevsw _nchrdev _buf h_bfreeli _rm _rmbuf _rmopen"~_rmopencsv _dev_flagL4L3X_spl5 _rmrdy"L6RL7_prdev cret _rmclose"\~_rmclos\_dev_rmint"t~_rmintt_devL14_wakeup L13L16 _rmread"L10002L22L23L24~_rmread_dev_wL19_rmstrat _physio L20001_directi L26_clearpr _wrrm"_setpre"_rdrm"L10000$L272_suword _sleep _spl0 _rmwrite"dL10004L33|L34L35~_rmwritd_devL30_directi"L10007L46L43~_direct_flag_count_baseL10005L39L38L44L47_fuword ~_rmrdy_nL52VL20007 L54XL20009$L59D_lbolt L57tL58~_setpreL63_clearpr"~_clearpL66_rmstrat"~_rmstra_abp_bp_cmdL71L72L73_rmsgtty"~_rmsgtt_dev_av_v_wL77L78$L76L80~_rdrmL84~_wrrm_wL89rp.o2 $w D5  Ete2@ "U L4      rWtPt r4` vx7r3-, 3-,34  *w&w "$ t&& eww :7 && %5 ߕ  5~ 5~ U77 Nwpw lN  f ewDw @N   f eww B >e `@Et0!2 w##hN<_iodone L1_lrem _ldiv _spl5 L6L5L7L10001L8L9_rpstart"_spl0 cret ~rpstartbpL10 _devstar _rpintr"~rpintrctrbpL11L12r_deverro L13PL14FL16XL17bL20000_rpread"~rpreaddev_rpphys"L19_physio _rpwrite"~rpwritedevL21~rpphysdevc_lshift L24,L23(sys.ow  f&Wp %ww b &Wp  ww @ &Wp  ww  f&Wp %wpw lwV((((II_bdevsw _nblkdev _cdevsw _nchrdev _u "_partab _proc L_syopen"~syopendevflagtpcsv _syttyp"L1"cret _syread"&~syread&devtpL3D_sywrite"H~sywriteHdevtpL5f_sysgtty"j~sysgttyjdevflagtpL7~syttyptpL10tc.ow N @E0ww D5 %B EU 4  707  w|w x 7v˕U ^' EE @ ˕/( tUC5U ww 585 & %5 E7E U77! (!5EU˕Cw~v  xߕ  - -؂"" Et5 @PUA e-LHxyyyyyyxyyyyyHyyyyyyyyxy_bdevsw _nblkdev _cdevsw _nchrdev _buf h_bfreeli _u "_tctab _tcper _tcclose"~tcclosedevcsv _bflush cret _tcstrat"~tcstratabpbpL30_mapallo L10000FL4R_iodone L2_spl6 L5fL6nL7|_tcstart"_spl0 ~tcstarttccmpcombpL9L20001L11L8L12L13_tcintr"L10004L29L30L19L~tcintrtccmptcdtpbpL15L16$_deverro L17:L18^L27L28L23pL21dL22zL14~L10001L10002tm.o  hw D#  0  ww D4 & ^ & ^ ww  5R@t@]U`Rwhw dD e - - U  !55 4   707   ww U7 W 5 @5RtEWt@PU@`--U   UU TRV TV57 PRw w J R(5Z5P   7*%5@PU7 77 T 0 w~w zN f el 7wLw HN  f e7 fw"w DB    wiII(yI yyyyyYIyyyyyIyyyyyyyyyyIXiIXiIhI_buf h_bfreeli _bdevsw _nblkdev _cdevsw _nchrdev _u "_tmtab _rtmbuf _t_openf _t_blkno _t_nxrec _tmopen"~tmopendevdminorflagcsv L2L1,cret _tmclose"0~tmclose0devdminorflagL5N_tcomman"^~tcomman^comunitL7rL10000d_lbolt _sleep _tmstrat"~tmstratabppbpL10L11L20002L20004_clrbuf _iodone L9 L13_spl5 L14L15L16_tmstart"_spl0 ~tmstartblknocomunitbpL18(L10001L17L20L21L20006L23L22L10002L10003L10004_tmintr"~tmintrunitbpL25~L26DL27L29&L31:L34zL33p_tmread"~tmreaddev_tmphys"_physio _tmwrite"~tmwritedev~tmphysdevaunit_lshift tty.oi> P w Ce & e& e& ww x 7ne 7be 7V ww | E%  fWp %wtE5%ʋt&e % tE5%&@ P%  e &U w5@tE5%% w ^D wBw >B 753/e (5 !%EP4E%Ձ E %ww D     e  wxw tD# b @&e %2  8  * ww DC 33  7w  |#`{}@~ABCDEFGHIJKLMNOPQRSTUVWXYZJLft({)}!|^~'`(((x8Y8II8HHhhH8YHhx H H 8Y _canonb _coremap _swapmap _rootdir _cputype _execnt _lbolt _time _tout _callout x_mount _mpid _runin _runout _runrun _curpri _maxmem _lks _rootdev _swapdev _swplo _nswap _updlock _rablock _regloc _u "_partab _proc L_inode _file _bdevsw _nblkdev _cdevsw _nchrdev _maptab#P_cfree @_cfreeli _gtty"~gttyvupvpcsv _sgtty"L1D_suword cret _stty"H~sttyHup_fuword ~sgttyvfpip_getf L3L4_wflusht"~wflushtatptp_spl5 L6L8_ttrstrt"L20001_sleep _flushtt"X_spl0 _cinit"~cinitccpcdpcpL118L20003,L14LL20005F~flushttXatpspstpL18`_getc L20n_wakeup L22_ttstart"_canon"~canonbp1atpcbptpL25L20007L27L24L28L29L30L31L32L332L40L41_putc L34\L35LL10000rL39~_ttyinpu"~ttyinput_flagsatpcactpL430L44L45L10001L10002L10003_signal L20012L42L46L10004L20010L20014L10005RL51rL10006nL53_ttyoutp"L54L10009L71JL69LL73L75L80L83fL85t~ttyoutpctypertpccolpactpL57L20016\L10007 L56bL58FL61.L62|L63L64RL65lL68L76L78_max L81FL86~ttrstrtatptpL90~ttstartatpcaddrtpL92L91FL94L95L97._timeout _ttread"J~ttreadJatptpL99L101j_passc _ttwrite"~ttwriteatpctpL104L103L20020L106L20018_cpass _ttystty"~ttysttyatpvavtpL109.L10012L10011L10013"L108*vlp.o fFw 5 L U7@L ww  x7 7 ww  x ww DEf7 y reE7fwV7 \ n7 TB nS n >-66 n7 &%" n -  n w   N5L ww LN  %2  ww %d  f f p ^wZw V  5HEU@H7*E$w w 55 H7U5 U@H7E ww 7 7 7 ww D4  707  zwvw rt5 H`FEtB@4 w~vlclose>devflagL3\_vlcanon"x_vlwrite"`~vlwrite`cL5lL20001f_cpass L10004fL10005rL14L10L12L13L15L16~vlcanonxcc1c2L10006L7_vloutpu"nL17L19L20003_vlstart"~vlstartcL22$L10007_getc L212_vlint"6~vlint6devL25PL26_prdev L10008bL24j_wakeup ~vloutpuncL29_sleep _putc _spl4 _spl0 _vpctl"~vpctlL31L20007_vpopen"~vpopendevflagL10010L10009L34L33.L10011L10012_vpclose"2~vpclose2devflagL35L_vpstrat"P~vpstratPabpbpL37lL38tL39_vpstart"~vpstartbpL40_vpint"~vpintdevbpL43L44L20009L42_iodone _vpwrite"~vpwritedevL47(_physio L48NL20011@vs.ozw YhXl jww  jE@h ww   < j j  jww 5x@  0  %<nf  PwLw Hl5(%E7 05EU5 7n% ww     Ez ww j% &  w?0*#?546?213?879?YyYyYYyYyYyYyYy_partab _vs _vsopen"~vsopendevcsv _vschar"jcret _vsclose"~vsclosedevL3*_getc _vswrite":~vswrite:countdevcL6XL20001BL8R_cpass ~vscharjc_spl5 L10L20003_vsxintr"_sleep _putc _spl0 ~vsxintrL13lcharcxcsrL12L15L16 L17L18_wakeup _vsread"~vsreaddevcL21.L20005 L23z_passc _vsrintr"R~vsrintrRcL25nvt.ohw ' ww Uww EU  5 %  5   ~wxw tE j7 d wXi ii)ii_u "_vtflag _vtopen"~vtopendevflagcsv L2L1cret _vtclose"~vtclose_vtwrite"0~vtwrite0countcL6FL200016_cpass L5L8NL20003P_spl5 L14~_sleep _spl0 _vtintr"~vtintrL15_wakeup xx.otdw AWp*De $$ww AWp*CeuEE3"t E@`3&ww AWp*De 4$4"4&wXiii_canonb _coremap _swapmap _rootdir _cputype _execnt _lbolt _time _tout _callout x_mount _mpid _runin _runout _runrun _curpri _maxmem _lks _rootdev _swapdev _swplo _nswap _updlock _rablock _regloc _u "_partab _proc L_ka6 _bdevsw _nblkdev _cdevsw _nchrdev _kl11 *_xxopen"~xxopendevtpcsv L2 L1&cret _xxread"*~xxread*devnbtp_xxclose"z~xxclosezdevtpt _callout x_mount _mpid _runin _runout _runrun _curpri _maxmem _lks _rootdev _swapdev _swplo _nswap _updlock _rablock _regloc _u "_partab _proc L_ka6 _bdevsw _nblkdev _cdevsw _nchrdev _kl11 *_xxopen"~xxopendevtpcsv L2 L1&cret _xxread"*~xxread*devnb# /* * UNIX device driver for the Megatek 7000 : * * * Computer Aided Design and Graphics Lab * School of Mechanical Engineering * Purdue University * W. Lafayette, IN 47907 * (317) 493-9385 * * 11/30/79 * */ #include "../param.h" #include "../user.h" #include "../conf.h" #include "../buf.h" #include "../tty.h" #include "../proc.h" #define ADDR 0166000 /* location of megatek on unibus */ #define MEMSIZE 037777 /* GXST bits: */ #define STARTW 01 /* initiate a write DMA operation */ #define STARTR 02 /* initiate a read DMA operation */ #define RESET 04 /* bus reset */ #define IE 0100 /* interrupt enable */ #define RDY 0200 /* ready */ #define PIOER 010000 /* PIO error */ #define INTER 020000 /* interface error */ #define TOER 040000 /* bus time-out error */ #define ER 0100000 /* error bit (means one of the previous 3 should have been set) */ /* GPST (peripherals) bits: */ #define START 01 #define CLEAR 02 #define PULSE 04 /* IE 0100 */ #define MPDONE 0200 #define MPBUSY 04000 /* Peripheral Control / Select: */ #define IPCU 064 #define INPUT 0100 /* * general definitions: */ #define MEGPRI 9 /* sleeping priority */ #define NTRIES 50 #define BUFSIZE 20 /* size of peripheral circular buffer */ #define KEYFLAG 0100000 /* minor devices: */ #define DMA 0 #define PIO 1 #define PERIPH 2 #define TTY 3 struct { /* unibus structure */ int gxst; int gxmsd; /* most significant word of 32 bit data */ int gxlsd; /* least significant word of 32 bit data */ int gxpda; int gxwct; /* 2's comp of # of 16-bit words */ int gxsad; /* megatek start address */ int gpst; int gpd; /* peripheral data xfer word */ int gpcs; /* peripheral control word */ }; struct { /* bookkeeping */ int flags; /* status for interrupt waiting */ int procp; } mg , mgp; struct buf megbuf; int megaddr; /* megatek address */ int mgmode; /* TTY or PERIPH for keyboard keys */ int mcircbuf[BUFSIZE]; /* for peripheral circular buffer */ int *mget , *mput; /* * tty defines and data: */ /* Megatek opcodes */ #define DJMS 0176200 #define DNOP 0177000 #define DRET 0177100 /* IPCU kb commands */ #define TCLEAR 0141600 #define WTEXT 0140400 #define OPENNEW 0141603 /* character size and constants */ #define CSIZE 3 #define NCPL 72 #define NLPP 55 #define CHGT 48 #define CWTH 48 /* address constants */ #define TCBA 044 /* Text control block address */ #define BSTART (040000-1024) /* buffer start, 16k */ #define BEND 037777 /* buffer end, 16k */ #define ASEGTAB 0400 /* address of segment table */ /* etc. */ #define CURSOR '0' /* cursor character */ #define TMODE 0201 #define GMODE 0202 struct tty mgtty; int bufhead[] = { /* buffer header */ 0140000+(-2047&07777), 0040000+2000, /* abs vector to x,y */ DJMS+0100, 2, /* rel djms .+2 */ DRET, 0, /* dret */ }; int tcb[] = { /* text control block */ BSTART+(sizeof(bufhead)/4), BEND, CURSOR<<8, (NCPL<<8) + NLPP, 0175400+(CSIZE<<4)+017, -CHGT, }; int segtab[] = { /* short seg table for tty */ 0177000, 000044, /* display one */ 0177200, 010000, /* set z origin=0 */ 0150000, 070000, /* set x y origins=0 */ DJMS , BSTART, /* seg table start */ 0177000, 040000, /* sync and restart */ }; /* open the megatek: */ megopen(dev,flag) { register char *p; register struct tty *tp; if( dev.d_minor == TTY ){ mgtopen(dev,flag); return; } if( mg.procp != 0 ) { if( mg.procp!=u.u_procp ) { u.u_error = ENXIO; return; } if( dev.d_minor!=PERIPH ) return; } tp = &mgtty; if( tp->t_state&ISOPEN ) if( u.u_procp->p_ttyp != tp){ u.u_error = ENXIO; return; } if( dev.d_minor==PERIPH ) { /* want to init peripherals */ if( mg.procp==0 ) { /* must setup others first */ u.u_error = ENXIO; return; } wrmg( 0100, 0, 3); /* setup button for int. */ wrmg( 0105, 0140000, 040000); /* blank vector */ wrmg( 0110, 0, 3); /* tablet strike ints. */ wrmg( 0115, 0140000, 040000); /* blank vector */ mget = mput = mcircbuf; /* setup peripheral circular buffer */ mgrdy(); /* be sure megatek is ready again */ mgpinit(0006000); /* tablet */ mgpinit(0030000); /* init joystick */ if( (tp->t_state&ISOPEN)==0) mgpinit(0140000); /* init kb if tty not open */ mgmode = PERIPH; return; } if( tp->t_state&ISOPEN == 0) if( mgreset() ) return; /* error during reset */ mg.procp = u.u_procp; } mgreset() { mgrdy(); /* be sure megatek is ready */ ADDR->gxst = RESET; mgrdy(); if( mgerr() ) { u.u_error = ENXIO; /* something wrong with interface */ return(1); } return(0); /* ok */ } megclose(dev) { register char *p; mgrdy(); p = ADDR; switch( dev.d_minor ){ case DMA: p->gxst = mg.procp = 0; break; case PERIPH: if( mgtty.t_state&ISOPEN ){ mgmode = TTY; /* reset mode if tty open */ wrmg(ASEGTAB+3,DJMS, BSTART); /* reenable display */ }else p->gpst = mgp.flags = 0; break; case TTY: if( mg.procp ) mgmode = PERIPH; mgtclose(dev); break; } } megwrite(dev) { int mgstrategy(); register char *p; if( dev.d_minor == TTY){ ttwrite(&mgtty); return; } megaddr = fuword(u.u_base); u.u_base += 2; u.u_count -= 2; if( megaddr == -1 || u.u_count&03 ){ u.u_error = EIO; return; } mgrdy(); switch( dev.d_minor ) { case DMA: physio( &mgstrategy , &megbuf , dev , B_WRITE ); break; case PIO: mdirectio( B_WRITE ); break; case PERIPH: mgprdy(); p = ADDR; if( u.u_count || mgerr() ){ u.u_error = EIO; return; } p->gpcs = IPCU; p->gpd = megaddr; /* first word is data */ p->gpst |= START; break; } } megread(dev) { int mgstrategy(); if( dev.d_minor == TTY){ ttread(&mgtty); return; } if( dev.d_minor != PERIPH){ megaddr = fuword(u.u_base); if( megaddr == -1 || u.u_count&03){ u.u_error = EIO; return; } } mgrdy(); switch( dev.d_minor ) { case DMA: physio( &mgstrategy , &megbuf , dev , B_READ ); break; case PIO: mdirectio( B_READ ); break; case PERIPH: if(u.u_count != 2){ u.u_error= EIO; return; } suword( u.u_base, mbufread() ); /* immediate return of data */ break; } } /* strategy for dma xfer (this routine combines strategy and start): */ mgstrategy(abp) struct buf *abp; { register struct buf *bp; register int cmd; register char *p; bp=abp; p = ADDR; p->gxsad = megaddr; p->gxpda = bp->b_addr; cmd = (bp->b_xmem&03) << 4; p->gxst = cmd|IE; p->gxwct = -( (u.u_count>>1) & ~1 ); if( bp->b_flags&B_READ ) p->gxst |= STARTR; else p->gxst |= STARTW; } /* handle interrupts from i/o interface: */ megintr(dev) { mg.flags &= ~IE; ADDR->gxst &= ~IE; megbuf.b_flags |= B_DONE; wakeup( &megbuf ); } /* handle interrupts from the peripherals: */ megpintr(dev) { register w,c; register char *p; p = ADDR; if( ((c = p->gpcs)&077) == IPCU ) { /* this was a peripheral interrupt */ p->gpcs = IPCU; /* echo it back */ if( c & INPUT ){ w = p->gpd; /* read input */ if( w&KEYFLAG) /* key */ if(mgmode==TTY){ ttyinput(w,&mgtty); goto out; } if( ++mput >= &mcircbuf[BUFSIZE] ) mput = mcircbuf; if( mput==mget ) { /* buffer overflow! */ mput = mget = mcircbuf; mput++; /* wipe out buffer and start over */ } *mput = w; out: p->gpst |= CLEAR; /* clear ipcu */ }else{ /* write interrupt */ p->gpst |= (PULSE|CLEAR); if( mgtty.t_state&ISOPEN) ttstart( &mgtty ); } } if( mgp.flags&IE){ mgp.flags &= ~IE; wakeup( &mgp ); } } /* handle programmed i/o (PIO): */ mdirectio( flag ) { register int count , *base; register maddr; int w[2]; base = u.u_base; maddr = megaddr; if( (char *)base&1 || u.u_count&3 ){ u.u_error = EIO; return; } count = u.u_count>>2; switch( flag ) { case B_READ: while( count-- ) { rdmg(maddr++, w); suword(base++, w[0]); suword(base++, w[1]); } break; case B_WRITE: while( count-- ) { w[0] = fuword(base++); w[1] = fuword(base++); wrmg(maddr++, w[0], w[1]); } break; } } /* be sure megatek interface is ready: */ mgrdy() { register int n; register char *p; p = ADDR; for(;;){ for(n=0; n<=NTRIES; n++) if( p->gxst&RDY ){ mgerr(); return; } spl5(); mg.flags |= IE; p->gxst |= IE; sleep(&megbuf, MEGPRI); spl0(); } } /* be sure megatek peripheral interface is ready: */ mgprdy() { register int n; register char *p; p = ADDR; for(;;) { for(n=0; n<=NTRIES; n++) if( (p->gpst&MPBUSY) == 0 ) return; spl4(); mgp.flags |= IE; p->gpst |= IE; sleep(&mgp, MEGPRI); spl0(); } } /* do PIO to/from megatek: */ rdmg(maddr,aw) int *aw; { register int *w; register char *p; mgrdy(); p = ADDR; w = aw; p->gxsad = maddr; *w++ = p->gxmsd; *w = p->gxlsd; } wrmg(maddr, w1, w2) { register char *p; mgrdy(); p = ADDR; p->gxsad = maddr; p->gxmsd = w1; p->gxlsd = w2; } /* detect megatek errors: */ mgerr() { register int stat; if( (stat=ADDR->gxst)&ER ) { printf("Megatek DMA Error,gxst=%o\n",stat); return(1); } return(0); } /* handle the initiation of a megatek peripheral: */ mgpinit( idev ) { register char *p; mgprdy(); /* NOTE: interrupts not enabled at this point */ p = ADDR; p->gpcs = IPCU; p->gpd = idev; /* which device */ p->gpst |= (START|IE); mgprdy(); p->gpcs = IPCU; p->gpd = idev; p->gpst |= (PULSE|CLEAR); } /* * stty: * do nothing * * gtty: * wait to read anything from a peripheral. * NOTE: a 'gtty' is only legal if /dev/mgper has been opened! * */ mgsgtty(dev , av) int *av; { register int *v; if( dev.d_minor == TTY){ ttystty(&mgtty, av); return; } if( (v=av) != 0 ) { /* stty */ if( dev.d_minor!=PERIPH ) { u.u_error = EIO; return; } for(;;){ mgprdy(); if( v[0] = mbufread() ) return; /* something was read, so return */ spl4(); ADDR->gpst |= IE; /* be sure interrupts are enabled */ mgp.flags |= IE; sleep(&mgp , MEGPRI); spl0(); } } } /* read from circular buffer */ mbufread() { if( mget==mput ) return(0); /* nothing there worth reading */ if( ++mget >= &mcircbuf[BUFSIZE] ) mget = mcircbuf; return( *mget); } /* * Megatek 7000 TTY driver routines */ /* open megatek tty: */ mgtopen(dev, flag) { register char *p; register struct tty *tp; int mgtstart(); if( mg.procp != 0){ u.u_error = ENXIO; return; } tp = &mgtty; if (u.u_procp->p_ttyp == 0) { u.u_procp->p_ttyp = tp; tp->t_dev = dev; } p = ADDR; if ((tp->t_state&ISOPEN) == 0) { if( mgreset() ) return; tp->t_state = ISOPEN|CARR_ON | SSTART; tp->t_flags = XTABS|ECHO|CRMOD; tp->t_erase = CERASE; tp->t_kill = CKILL; tp->t_tabexp = TABLEN; tp->t_addr = &mgtstart; mgdma( ASEGTAB, segtab, sizeof segtab); mgdma( TCBA, tcb, sizeof tcb); mgdma( BSTART, bufhead, sizeof bufhead); wrmg(1, 0, ASEGTAB); mgpinit( 0140000 ) ; /* init kb */ mgprdy(); p->gpcs = IPCU; p->gpd = TCLEAR; /*clear text */ p->gpst |= START; mgprdy(); p->gpcs = IPCU; p->gpd = OPENNEW; /* open new text buffer */ p->gpst |= START; mgprdy(); wrmg( 0177761, 5, 0); /* start micro */ wrmg(2, 1, BSTART); /* tell grafic we're here */ mgmode = TTY; } } /* close Megatek tty */ mgtclose(dev) { register struct tty *tp; register char *p; p = ADDR; tp = &mgtty; wflushtty(tp); tp->t_state = 0; wrmg(2, 0, 0); if( mgp.procp == 0 ) p->gpst = 0; } /* write chars to megatek from output queue: * called by ttstart */ mgtstart(atp) struct tty *atp; { register c; register char *p; p = ADDR; if( p->gpst & MPBUSY ) return; if( (c=getc(&atp->t_outq)) >= 0){ p->gpcs = IPCU; p->gpd = (WTEXT | c); p->gpst |= (START | IE); } } /* dma output to megatek: */ mgdma(maddr, baddr, nbytes) { register char *p; mgrdy(); p = ADDR; p->gxsad = maddr; p->gxpda = baddr; p->gxwct = -(nbytes>>1); p->gxst = IE; p->gxst |= STARTW; } p->gpst = 0; } /* write chars to megatek from output queue: * called by ttstart */ mgtstart(atp) struct tty *atp; { register c; register char *p; p = ADDR; if( p->gpst & MPBUSY ) return; if( (c=getc(&atp->t_outq)) >= 0){ p->gpcs = IPCU; p->gpd = (WTEXT | c); p->gpst |= (START | # /* * UNIX device driver for the Megatek 7000 series: * * * Mike Bailey * Computer Aided Design and Graphics Lab * School of Mechanical Engineering * Purdue University * W. Lafayette, IN 47907 * (317) 493-9385 * * 06/27/79 * */ #include "../param.h" #include "../user.h" #include "../conf.h" #include "../buf.h" #define ADDR 0166000 /* location of megatek on unibus */ /* GXST bits: */ #define STARTW 01 /* initiate a write DMA operation */ #define STARTR 02 /* initiate a read DMA operation */ #define RESET 04 /* bus reset */ #define IE 0100 /* interrupt enable */ #define RDY 0200 /* ready */ #define PIOER 010000 /* PIO error */ #define INTER 020000 /* interface error */ #define TOER 040000 /* bus time-out error */ #define ER 0100000 /* error bit (means one of the previous 3 should have been set) */ /* GPST (peripherals) bits: */ #define START 01 #define CLEAR 02 #define PULSE 04 /* IE 0100 */ #define DONE 0200 #define BUSY 04000 /* Peripheral Control / Select: */ #define IPCU 064 /* we've only got the one */ #define INPUT 0100 /* * general definitions: */ #define MEGPRI 10 /* sleeping priority */ #define NTRIES 50 #define BUFSIZE 20 /* size of peripheral circular buffer */ /* minor devices: */ #define DMA 0 #define PIO 1 #define PERIPH 2 /* stty flags: */ #define WAIT 0100000 struct { /* unibus structure */ int gxst; int gxmsd; /* most significant word of 32 bit data */ int gxlsd; /* least significant word of 32 bit data */ int gxpda; int gxwct; /* 2's comp of # of 16-bit words */ int gxsad; /* megatek start address */ int gpst; int gpd; /* peripheral data xfer word */ int gpcs; /* peripheral control word */ }; struct { /* bookkeeping */ int flags; /* status for interrupt waiting */ int procp; } mg , mgp; struct buf megbuf; int meg_addr; /* 7000 address */ struct { int half; /* to tell what half on */ int lsh,msh; /* least/most significant halves */ } mgpio; int mcircbuf[BUFSIZE]; /* for peripheral circular buffer */ int *mget , *mput; /* handle interrupts from i/o interface: */ megintr(dev) { mg.flags=& ~IE; ADDR->gxst=& ~IE; megbuf.b_flags=| B_DONE; /* gives physio a goose */ wakeup( &megbuf ); } /* handle interrupts from the peripherals: */ megpintr(dev) { spl5(); /* be sure can not interrupt me here */ if( (ADDR->gpcs&0177) == (IPCU|INPUT) ) { /* this was a peripheral interrupt */ if( ++mput >= &mcircbuf[BUFSIZE] ) mput = &mcircbuf[0]; if( mput==mget ) { /* buffer overflow! */ mput = mget = &mcircbuf[0]; mput++; /* wipe out buffer and start over */ } *mput = ADDR->gpd; ADDR->gpcs = IPCU; ADDR->gpst=| CLEAR; /* clear ipcu */ } wakeup( &mgp ); mgp.flags=& ~IE; spl0(); } /* open the megatek: */ megopen(dev,flag) { if( mg.procp != 0 ) { if( mg.procp!=u.u_procp ) { u.u_error = ENXIO; return; } if( dev.d_minor!=PERIPH ) return; } if( dev.d_minor==PERIPH ) { /* want to init peripherals */ if( mg.procp==0 ) { /* must setup others first */ u.u_error = ENXIO; return; } meg_addr = 0100; /* setup button for int. */ wrmg(0); wrmg(3); meg_addr = 0105; wrmg(0140000); wrmg(0040000); /* blanked vector */ meg_addr = 0110; wrmg(0); wrmg(3); /* setup tablet strike for interrupt */ meg_addr = 0115; wrmg(0140000); wrmg(0040000); /* blanked vector */ mgrdy(); /* be sure megatek is ready again */ mget = mput = &mcircbuf[0]; /* setup peripheral circular buffer */ mdv_init(0006000); /* tablet */ mdv_init(0030000); /* init joystick */ mdv_init(0140000); /* init kb */ return; } mgrdy(); /* be sure megatek is ready */ mg.flags=IE; ADDR->gxst=RESET; ADDR->gxst=IE; mgrdy(); if( mgerr() ) { u.u_error = ENXIO; /* something wrong with interface */ return; } mg.procp = u.u_procp; } megclose(dev,flag) { mgrdy(); ADDR->gxst = ADDR->gpst = mg.procp = mg.flags = mgp.flags = 0; } /* strategy for dma xfer (this routine combines strategy and start): */ mgstrategy(abp) struct buf *abp; { register struct buf *bp; register int cmd; bp=abp; ADDR->gxsad = meg_addr; ADDR->gxpda = bp->b_addr; cmd = (bp->b_xmem&03) << 4; ADDR->gxst = cmd|IE; ADDR->gxwct = -( (u.u_count>>1) & ~1 ); if( bp->b_flags&B_READ ) ADDR->gxst=| STARTR; else ADDR->gxst=| STARTW; } megwrite(dev) { meg_addr = fuword(u.u_base); u.u_base=+ 2; u.u_count=- 2; mgrdy(); switch( dev.d_minor ) { case DMA: physio( &mgstrategy , &megbuf , dev , B_WRITE ); break; case PIO: mdirectio( B_WRITE ); break; case PERIPH: u.u_error = EIO; break; } } megread(dev) { meg_addr = fuword(u.u_base); mgrdy(); switch( dev.d_minor ) { case DMA: physio( &mgstrategy , &megbuf , dev , B_READ ); break; case PIO: mdirectio( B_READ ); break; case PERIPH: u.u_error = EIO; break; } } /* handle programmed i/o (PIO): */ mdirectio( flag ) { register int count , *base; if( (count=u.u_count)<=0 || (count&01)!=0 ) { u.u_error = EIO; return; } count=>> 2; /* # bytes -> # 32 bit words */ base = u.u_base; switch( flag ) { case B_READ: while( count-- ) { suword(base++ , rdmg() ); suword(base++ , rdmg() ); meg_addr++; } break; case B_WRITE: while( count-- ) { wrmg( fuword(base++) ); wrmg( fuword(base++) ); meg_addr++; } break; } } /* be sure megatek interface is ready: */ mgrdy() { register int n; extern int lbolt; for(;;) { for(n=0; n<=NTRIES; n++) if( ADDR->gxst&RDY ) return; if( mg.flags&IE ) { spl5(); sleep(&megbuf , MEGPRI); spl0(); } else sleep(&lbolt , MEGPRI); } } /* be sure megatek peripheral interface is ready: */ mgprdy() { register int n; extern int lbolt; for(;;) { for(n=0; n<=NTRIES; n++) if( (ADDR->gpst&BUSY) == 0 ) return; if( mgp.flags&IE ) { spl5(); sleep(&mgp , MEGPRI); spl0(); } else sleep(&lbolt , MEGPRI); } } /* do PIO to/from megatek: */ rdmg() { if( mgpio.half ) { /* just return least sig half */ mgpio.half = 0; return( mgpio.lsh ); } /* read and return the most sig half: */ mgpio.half++; mgrdy(); ADDR->gxsad = meg_addr; mgpio.lsh = ADDR->gxlsd; return( ADDR->gxmsd ); } wrmg(w) { if( mgpio.half ) { /* given the least sig half, so send word */ mgrdy(); mgpio.half = 0; ADDR->gxsad = meg_addr; ADDR->gxmsd = mgpio.msh; ADDR->gxlsd = w; return; } /* just gobble up most sig half */ mgpio.msh = w; mgpio.half++; } /* detect megatek errors: */ mgerr() { register int stat , dev; if( (stat=ADDR->gxst)&ER ) { dev = (stat>>12) &01; /* 0=DMA / 1=PIO */ if( stat&TOER ) { prdev("Megatek Bus Timeout",dev); return(1); } if( stat&INTER ) { prdev("Megatek Interface Error",dev); return(1); } } return(0); } /* handle the initiation of a megatek peripheral: */ mdv_init( idev ) { register int gpcs; mgprdy(); /* NOTE: interrupts not enabled at this point */ ADDR->gpcs = IPCU; ADDR->gpd = idev; /* which device */ mgp.flags=| IE; ADDR->gpst=| (START|IE); mgprdy(); if( (gpcs=ADDR->gpcs&077) != IPCU ) { /* should be a 064 */ prdev("Megatek Peripheral Init Error",idev); return; } ADDR->gpcs = gpcs; ADDR->gpd = idev; ADDR->gpst=| PULSE; ADDR->gpcs = gpcs; ADDR->gpst=| CLEAR; } /* do some extra stuff with stty/gtty: */ /* * stty: * he's setting "mgp.flags". * * gtty: * he is trying to read anything from a peripheral. * (he may wait for it if the proper flag has been set, or * if nothing's there he'll return) * NOTE: a 'gtty' is only legal if /dev/mgper has been opened! * */ mgsgtty(dev , av) int *av; { register int *v , w; if( (v=av) == 0 ) { /* stty */ /* he's setting the flags: */ w = u.u_arg[0]; if( w == 0 ) { mgp.flags=& ~WAIT; /* clear wait flag */ return; } mgp.flags=| w; /* set the flag */ return; } else { /* gtty */ if( dev.d_minor!=PERIPH ) { u.u_error = EIO; return; } loop: mgprdy(); if( mbufread(v) ) return; /* something was read, so return */ /* nothing from peripherals yet - should I wait? */ if( (mgp.flags&WAIT) == 0 ) { /* no - return a zero */ *v = 0; return; } /* else, sleep till something turns up: */ spl5(); ADDR->gpst=| IE; /* be sure interrupts are enabled */ mgp.flags=| IE; sleep(&mgp , MEGPRI-1); spl0(); goto loop; } } /* attempt to read from the circular buffer - return a 1 if could read: */ mbufread(ip) int *ip; { if( mget==mput ) return(0); /* nothing there worth reading */ if( ++mget >= &mcircbuf[BUFSIZE] ) mget = &mcircbuf[0]; *ip = *mget; return(1); } ags&WAIT) == 0 ) { /* no - return a zero */ *v = 0; return; } /* else, sleep till something turns up: */ spl5(); ADDR->gpst=| IE; /* be sure interrupts are enabled */ mgp.flags=| IE; sleep(&mgp , MEGPRI-1); spl0(); goto loop; } } /* attempt to read from the circular buffer - return a 1 if could read: */ mbufread(ip) int *ip; { if( mget==mput ) return(0); /* nothing there worth reading */ if( ++mget >= &mcircbuf[BUFSIZE]/* * Megatek 7000 TTY driver routines */ /* Megatek opcodes */ #define DJMS 0176200 #define DNOP 0177000 #define DRET 0177100 /* IPCU commands */ #define TCLEAR 0141600 #define WTEXT 0140400 #define OPENNEW 0141603 /* character size and constants */ #define CSIZE 3 #define NCPL 72 #define NLPP 56 #define CHGT 48 #define CWTH 48 /* address constants */ #define TCBA 044 /* Text control block address */ #define BSTART (040000-1024) /* buffer start, 16k */ #define BEND 037777 /* buffer end, 16k */ #define ASEGTAB 0400 /* address of segment table */ /* etc. */ #define CURSOR '_' /* cursor character */ struct tty mgtty; int bufhead[] = { /* buffer header */ 0140000+(-2047&07777), 0140000+2000, /* abs vector to x,y */ DJMS+0100, 2, /* rel djms .+2 */ DRET, 0, /* dret */ }; int tcb[] = { /* text control block */ BSTART+(sizeof(bufhead)/4), BEND, CURSOR<<8, (NCPL<<8) + NLPP, (0766<<7) + (CSIZE<<4) + 017, CHGT, }; int segtab[] = { /* seg table entry */ 0177000, 000044, /* display one */ 0177200, 010000, /* set z origin=0 */ 0150000, 070000, /* set x y origins=0 */ DJMS , BSTART, 0177000, 040000, /* sync and restart */ }; /* open megatek tty: */ mgtopen(dev, flag) { register char *addr; register struct tty *tp; int mgtstart(); if( mg.procp != 0){ u.u_error = ENXIO; return; } mgrdy(); /* be sure megatek is ready */ mg.flags=IE; ADDR->gxst = (RESET | IE); mgrdy(); if( mgerr() ) { u.u_error = ENXIO; /* something wrong with interface */ return; } tp = &mgtty; if (u.u_procp->p_ttyp == 0) { u.u_procp->p_ttyp = tp; tp->t_dev = dev; } tp->t_addr = addr = ADDR; if ((tp->t_state&ISOPEN) == 0) { tp->t_state = ISOPEN|CARR_ON; tp->t_flags = XTABS|LCASE|ECHO|CRMOD; tp->t_erase = CERASE; tp->t_kill = CKILL; tp->t_tabexp = TABLEN; tp->t_addr = &mgtstart; mgdma( ASEGTAB, segtab, sizeof segtab); mgdma( TCBA, tcb, sizeof tcb); mgdma( BSTART, bufhead, sizeof bufhead); wrmg(1, 0, ASEGTAB); mdv_init( 0140000 ) ; /* init kb */ mgprdy(); ADDR->gpcs = IPCU; ADDR->gpd = TCLEAR; /*clear text */ mgprdy(); ADDR->gpcs = IPCU; ADDR->gpd = OPENNEW; /* open new text buffer */ mgprdy(); wrmg( 0177761, 5, 0); /* start micro */ } } /* close Megatek tty */ mgtclose(dev) { register struct tty *tp; tp = &mgtty; wflushtty(tp); tp->t_state = 0; wrmg( ASEGTAB+3, DNOP, 0); wrmg( 0177761, 0, 0,); /* stop micro */ } mgtread(dev) { ttread(&mgtty); } mgtwrite(dev) { ttwrite(&mgtty); } mgtsgtty(dev, v) int *v; { register struct tty *tp; tp = &mgtty; ttystty(tp, v); } /* write chars to megatek from output queue: * called by ttstart */ mgtstart(atp) struct tty *atp; { register struct tty *tp; register c; if( (ADDR->gxst & RDY) == 0) return; tp = atp; if( (c=getc( &tp->t_outq)) >= 0){ ADDR->gpcs = IPCU; ADDR->gpd = (WTEXT | c); } } /* dma output to megatek: */ mgdma(maddr, baddr, nbytes) char *maddr, *baddr; { mgrdy(); ADDR->gxsad = maddr; ADDR->gxpda = baddr; ADDR->gxst = IE; ADDR->gxwct = -(nbytes>>1); ADDR->gxst |= STARTW; } ystty(tp, v); } /* write chars to megatek from output queue: * called by ttstart */ mgtstart(atp) struct tty *atp; { register struct tty *tp; register c; if( (ADDR->gxst & RDY) == 0) return; tp = atp; if( (c=getc( &tp->t_outq)) >= 0){ ADDR->gpcs = IPCU; ADDR->gpd = (WTEXT | c); } } /* dma output to megatek: */ mgdma(maddr, baddr, nbytes) char *maddr, *baddr; { mgrdy(); ADDR->gxsad = maddr; ADDR->gxpda = baddr; ADDR->gxst = IE; ADDR->gxwct = -(nbytes>>1); ADDR->gxs