1: /*
   2:  *	SCCS id	@(#)vp.c	2.1 (Berkeley)	8/5/83
   3:  */
   4: 
   5: /*
   6:  * Versatec printer/plotter driver for model c-pdp11(dma) controller
   7:  *
   8:  * Thomas Ferrin, UCSF Computer Graphics Laboratory, April 1979
   9:  *
  10:  * Uses the same user interface as Bell Labs' driver but runs in raw
  11:  * mode, since even the small 11" versatec outputs ~53kbytes/inch!
  12:  */
  13: 
  14: /* #define NOMESG	/* no console messages if defined */
  15: /* #define VP_TWOSCOMPL	/* use two's-complement bytecount */
  16: 
  17: #include "vp.h"
  18: #if NVP > 0
  19: #include "param.h"
  20: #include <sys/dir.h>
  21: #include <sys/user.h>
  22: #include <sys/buf.h>
  23: #include <sys/proc.h>
  24: #include <sys/vcmd.h>
  25: 
  26: #define PRINTADR ((struct devregs *)0177514)    /* printer csr */
  27: #define PLOTADR  ((struct devregs *)0177510)    /* plotter csr */
  28: /*
  29:  * Note that there is really only 1 csr!  Changes to 'PRINTADR'
  30:  * csr are reflected in 'PLOTADR' csr and vice versa. Referencing
  31:  * the particular csr sets the device into that mode of operation.
  32:  */
  33: #define DMA ((struct dmaregs *)0177500) /* dma register base */
  34: 
  35: #define ERROR   0100000
  36: #define DTCENABLE 040000    /* interrupt on data xfer complete */
  37: #define IENABLE 0100        /* interrupt on ready or error */
  38: #define READY   0200        /* previous operation complete */
  39: #define REOT    010     /* remote end-of-transmission */
  40: #define RESET   02
  41: #define CMDS    076
  42: #define SPP 01      /* simultaneous print/plot mode */
  43: 
  44: struct  buf vpbuf;
  45: #ifndef NOMESG
  46: char *vperr = "\nVersatec needs attention\n";
  47: #endif
  48: 
  49: struct devregs {
  50:     short   csr;
  51: };
  52: 
  53: struct dmaregs {
  54:     short   plotbytes;
  55:     short   addrext;
  56:     short   printbytes;
  57:     unsigned short  addr;
  58: };
  59: 
  60: struct  {
  61:     int state;
  62:     unsigned bytecount;
  63:     int alive;
  64: } vp11;
  65: 
  66: /* states */
  67: #define PPLOT   0400    /* low 6 bits reserved for hardware functions */
  68: #define PLOT    0200
  69: #define PRINT   0100
  70: #define MODE    0700
  71: #define ERRMSG  01000
  72: #define NOSTART 02000
  73: #define WBUSY   04000
  74: 
  75: /*
  76:  *  This driver should be converted to use a single VPADDR pointer.
  77:  *  Until then, the attach only marks the unit as alive.
  78:  */
  79: vpattach(addr, unit)
  80: struct vpdevice *addr;
  81: {
  82:     if (((unsigned) unit == 0) || (addr == DMA)) {
  83:         vp11.alive++;
  84:         return 1;
  85:     }
  86:     return 0;
  87: }
  88: 
  89: /* ARGSUSED */
  90: vpopen(dev, flag)
  91: dev_t dev;
  92: {
  93:     register short *vpp;
  94: 
  95:     if (!vp11.alive || vp11.state&MODE) {
  96:         u.u_error = ENXIO;
  97:         return;
  98:     }
  99:     vpp = &PRINTADR->csr;
 100:     vp11.state = PRINT;
 101:     vpbuf.b_flags = B_DONE;
 102:     *vpp = IENABLE | RESET;
 103:     /*
 104: 	 * Contrary to the implication in the operator's manual, it is an
 105: 	 * error to have the bits for both an operation complete interrupt
 106: 	 * and a data transmission complete interrupt set at the same time.
 107: 	 * Doing so will cause erratic operation of 'READY' interrupts.
 108: 	 */
 109:     if (vperror())
 110:         *vpp = vp11.state = 0;
 111: }
 112: 
 113: /* ARGSUSED */
 114: vpclose(dev, flag)
 115: dev_t dev;
 116: {
 117:     register short *vpp;
 118: 
 119:     vperror();
 120:     vpp = (vp11.state&PLOT)? &PLOTADR->csr : &PRINTADR->csr;
 121:     *vpp = IENABLE | REOT;  /* page eject past toner bath */
 122:     vperror();
 123:     *vpp = vp11.state = 0;
 124: }
 125: 
 126: vpwrite(dev)
 127: dev_t dev;
 128: {
 129:     int vpstart();
 130: 
 131:     if ((vp11.bytecount=u.u_count) == 0)    /* true byte count */
 132:         return;
 133:     if (u.u_count&01)   /* avoid EFAULT error in physio() */
 134:         u.u_count++;
 135:     if (vperror())
 136:         return;
 137:     physio(vpstart, &vpbuf, dev, B_WRITE);
 138:     /* note that newer 1200A's print @ 1000 lines/min = 2.2kbytes/sec */
 139: }
 140: 
 141: #ifdef V6
 142: vpctl(dev, v)
 143: dev_t dev;
 144: int *v;
 145: {
 146:     register int ctrl;
 147:     register short *vpp;
 148: 
 149:     if (v) {
 150:         *v = vp11.state;
 151:         return;
 152:     }
 153:     if (vperror())
 154:         return;
 155:     ctrl = u.u_arg[0];
 156:     vp11.state = (vp11.state&~MODE) | (ctrl&MODE);
 157:     vpp = (ctrl&PLOT)? &PLOTADR->csr : &PRINTADR->csr;
 158:     if (ctrl&CMDS) {
 159:         *vpp = IENABLE | (ctrl&CMDS) | (vp11.state&SPP);
 160:         vperror();
 161:     }
 162:     if (ctrl&PPLOT) {
 163:         vp11.state |= SPP;
 164:         *vpp = DTCENABLE | SPP;
 165:     } else if (ctrl&PRINT) {
 166:         vp11.state &= ~SPP;
 167:         *vpp = IENABLE;
 168:     } else
 169:         *vpp = IENABLE | (vp11.state&SPP);
 170: }
 171: #else
 172: 
 173: /* ARGSUSED */
 174: vpioctl(dev, cmd, addr, flag)
 175: dev_t dev;
 176: caddr_t addr;
 177: {
 178:     register int ctrl;
 179:     register short *vpp;
 180:     register struct buf *bp;
 181: 
 182:     switch (cmd) {
 183: 
 184:     case GETSTATE:
 185:         suword(addr, vp11.state);
 186:         return;
 187: 
 188:     case SETSTATE:
 189:         ctrl = fuword(addr);
 190:         if (ctrl == -1) {
 191:             u.u_error = EFAULT;
 192:             return;
 193:         }
 194:         if (vperror())
 195:             return;
 196:         vp11.state = (vp11.state&~MODE) | (ctrl&MODE);
 197:         vpp = (ctrl&PLOT)? &PLOTADR->csr : &PRINTADR->csr;
 198:         if (ctrl&CMDS) {
 199:             *vpp = IENABLE | (ctrl&CMDS) | (vp11.state&SPP);
 200:             vperror();
 201:         }
 202:         if (ctrl&PPLOT) {
 203:             vp11.state |= SPP;
 204:             *vpp = DTCENABLE | SPP;
 205:         } else if (ctrl&PRINT) {
 206:             vp11.state &= ~SPP;
 207:             *vpp = IENABLE;
 208:         } else
 209:             *vpp = IENABLE | (vp11.state&SPP);
 210:         return;
 211: 
 212:     case BUFWRITE:
 213:         u.u_base = fuword(addr);
 214:         u.u_count = fuword(addr+NBPW);
 215:         if ((int)u.u_base == -1 || (int)u.u_count == -1) {
 216:             u.u_error = EFAULT;
 217:             return;
 218:         }
 219:         bp = &vpbuf;
 220:         if (vp11.state&WBUSY) {
 221:             /* wait for previous write */
 222:             (void) _spl4();
 223:             while ((bp->b_flags&B_DONE) == 0)
 224:                 sleep(bp, PRIBIO);
 225:             u.u_procp->p_flag &= ~SLOCK;
 226:             bp->b_flags &= ~B_BUSY;
 227:             vp11.state &= ~WBUSY;
 228:             (void) _spl0();
 229:             geterror(bp);
 230:             if (u.u_error)
 231:                 return;
 232:         }
 233:         if (u.u_count == 0)
 234:             return;
 235:         /* simulate a write without starting i/o */
 236:         (void) _spl4();
 237:         vp11.state |= NOSTART;
 238:         vpwrite(dev);
 239:         vp11.state &= ~NOSTART;
 240:         if (u.u_error) {
 241:             (void) _spl0();
 242:             return;
 243:         }
 244:         /* fake write was ok, now do it for real */
 245:         bp->b_flags = B_BUSY | B_PHYS | B_WRITE;
 246:         u.u_procp->p_flag |= SLOCK;
 247:         vp11.state |= WBUSY;
 248:         vpstart(bp);
 249:         (void) _spl0();
 250:         return;
 251: 
 252:     default:
 253:         u.u_error = ENOTTY;
 254:     }
 255: }
 256: #endif
 257: 
 258: vperror()
 259: {
 260:     register int state, err;
 261: 
 262:     state = vp11.state & PLOT;
 263:     (void) _spl4();
 264:     while ((err=(state? PLOTADR->csr : PRINTADR->csr)&(READY|ERROR))==0)
 265:         sleep((caddr_t)&vp11, PRIBIO);
 266:     (void) _spl0();
 267:     if (err&ERROR) {
 268:         u.u_error = EIO;
 269: #ifndef NOMESG
 270:         if (!(vp11.state&ERRMSG)) {
 271:             printf(vperr);
 272:             vp11.state |= ERRMSG;
 273:         }
 274: #endif
 275:     } else
 276:         vp11.state &= ~ERRMSG;
 277:     return(err&ERROR);
 278: }
 279: 
 280: vpstart(bp)
 281: register struct buf *bp;
 282: {
 283:     register struct dmaregs *vpp = DMA;
 284: 
 285:     if (vp11.state&NOSTART) {
 286:         bp->b_flags |= B_DONE;  /* fake it */
 287:         return;
 288:     }
 289: #ifdef  UNIBUS_MAP
 290:     mapalloc(bp);
 291: #endif
 292:     vpp->addr = (short)(bp->b_un.b_addr);
 293:     vpp->addrext = (bp->b_xmem & 03) << 4;
 294: #ifndef VP_TWOSCOMPL
 295:     if (vp11.state&PLOT)
 296:         vpp->plotbytes = vp11.bytecount;
 297:     else
 298:         vpp->printbytes = vp11.bytecount;
 299: #else
 300:     if (vp11.state&PLOT)
 301:         vpp->plotbytes = -vp11.bytecount;
 302:     else
 303:         vpp->printbytes = -vp11.bytecount;
 304: #endif
 305: }
 306: 
 307: vpintr()
 308: {
 309:     register struct buf *bp = &vpbuf;
 310: 
 311:     /*
 312: 	 * Hardware botch.  Interrupts occur a few usec before the 'READY'
 313: 	 * bit actually sets.  On fast processors it is unreliable to test
 314: 	 * this bit in the interrupt service routine!
 315: 	 */
 316:     if (bp->b_flags&B_DONE) {
 317:         wakeup((caddr_t)&vp11);
 318:         return;
 319:     }
 320:     if (((vp11.state&PLOT)? PLOTADR->csr : PRINTADR->csr) < 0) {
 321: #ifndef NOMESG
 322:         if (!(vp11.state&ERRMSG)) {
 323:             printf(vperr);
 324:             vp11.state |= ERRMSG;
 325:         }
 326: #endif
 327:         bp->b_flags |= B_ERROR;
 328:         bp->b_error = EIO;
 329:         wakeup((caddr_t)&vp11);
 330:     }
 331:     iodone(bp);
 332: }
 333: #endif	NVP

Defined functions

vpattach defined in line 79; never used
vpclose defined in line 114; never used
vpctl defined in line 142; never used
vperror defined in line 258; used 8 times
vpintr defined in line 307; used 4 times
vpioctl defined in line 174; never used
vpopen defined in line 90; never used
vpstart defined in line 280; used 3 times
vpwrite defined in line 126; used 1 times

Defined variables

vpbuf defined in line 44; used 4 times
vperr defined in line 46; used 2 times

Defined struct's

devregs defined in line 49; never used
dmaregs defined in line 53; used 2 times
  • in line 283(2)

Defined macros

CMDS defined in line 41; used 4 times
DMA defined in line 33; used 2 times
DTCENABLE defined in line 36; used 2 times
ERRMSG defined in line 71; used 5 times
ERROR defined in line 35; used 3 times
IENABLE defined in line 37; used 8 times
MODE defined in line 70; used 5 times
NOSTART defined in line 72; used 3 times
PLOT defined in line 68; used 7 times
PLOTADR defined in line 27; used 5 times
PPLOT defined in line 67; used 2 times
PRINT defined in line 69; used 3 times
PRINTADR defined in line 26; used 6 times
READY defined in line 38; used 1 times
REOT defined in line 39; used 1 times
RESET defined in line 40; used 1 times
SPP defined in line 42; used 10 times
WBUSY defined in line 73; used 3 times
Last modified: 1983-08-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1003
Valid CSS Valid XHTML 1.0 Strict