home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / 2.9-derivatives / 2.9-pro350 / sys-dev / cn.c next >
Encoding:
C/C++ Source or Header  |  1985-02-26  |  21.7 KB  |  967 lines

  1. /*
  2.  * Driver for the pro300 screen and keyboard.
  3.  * There are a variety of capabilities here:
  4.  *    - default is emulation of a DEC VT52 terminal
  5.  *    - also a variety of ioctl's that permit raster
  6.  *    screen graphics
  7.  *    See the file <sys/cnio.h> for more info.
  8.  *    on the screen ioctl's
  9.  * The font is a fixed 96 char. ascii definition with the
  10.  * keyboard mapped into the US. ascii key caps. The only
  11.  * unusual keys are "compose" which generates alternate
  12.  * Xon/Xoff like a VT100 scroll key and the curser arrows,
  13.  * which generate VT52 sequences.
  14.  * Lots more could be done here, user loadable fonts, redefinition
  15.  * of keys on the keyboard, ioctl's to generate keyboard control
  16.  * codes...
  17.  * NOTE: Extended bit map code has NOT been tested.
  18.  * There are a few constants that may be of interest:
  19.  * XMAX - chars/line
  20.  * YMAX - lines/screen
  21.  * FNTLINE - raster lines for a font char.
  22.  * LNPEROW - raster lines for each char. line (LNPEROW >= FNTLINE)
  23.  * FNTWIDTH - width of bit field that char. is displayed in
  24.  * The interrupt service routines are;
  25.  *    kbrint - keyboard receive
  26.  *    kbxint - keyboard transmit
  27.  *    sctint - screen transfer interrupt, used for xfer completions
  28.  *    scfint - screen end of frame interrupts, used to prod output process
  29.  */
  30. #include "cn.h"
  31. #if NCN > 0
  32. #include <sys/param.h>
  33. #include <sys/conf.h>
  34. #include <sys/dir.h>
  35. #include <sys/user.h>
  36. #include <sys/tty.h>
  37. #include <sys/systm.h>
  38. #include <sys/seg.h>
  39. #include <sys/buf.h>
  40. #include <sys/ivecpos.h>
  41. #include <sys/cnreg.h>
  42. #include <sys/cnio.h>
  43.  
  44. extern struct scdevice *SCADDR;
  45. extern struct kbdevice *KBADDR;
  46. struct    tty cn11;
  47.  
  48. /* The font is an 8x10 bit matrix stored by row in top->bottom
  49.  * order. The low order bit is the leftmost bit when displayed.
  50.  */
  51. char profont[][10] = {
  52.     0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,
  53.     0020,0020,0020,0020,0020,0000,0000,0020,0020,0000,
  54.     0044,0044,0044,0000,0000,0000,0000,0000,0000,0000,
  55.     0050,0050,0050,0376,0050,0376,0050,0050,0050,0000,
  56.     0020,0374,0022,0022,0174,0220,0220,0176,0020,0000,
  57.     0016,0212,0116,0040,0020,0010,0344,0242,0340,0000,
  58.     0034,0042,0042,0024,0010,0224,0142,0142,0234,0000,
  59.     0060,0060,0020,0010,0000,0000,0000,0000,0000,0000,
  60.     0040,0020,0010,0010,0010,0010,0010,0020,0040,0000,
  61.     0010,0020,0040,0040,0040,0040,0040,0020,0010,0000,
  62.     0000,0020,0222,0124,0070,0124,0222,0020,0000,0000,
  63.     0000,0020,0020,0020,0376,0020,0020,0020,0000,0000,
  64.     0000,0000,0000,0000,0000,0000,0030,0030,0010,0004,
  65.     0000,0000,0000,0000,0174,0000,0000,0000,0000,0000,
  66.     0000,0000,0000,0000,0000,0000,0000,0030,0030,0000,
  67.     0000,0200,0100,0040,0020,0010,0004,0002,0000,0000,
  68.     0174,0202,0302,0242,0222,0212,0206,0202,0174,0000,
  69.     0020,0030,0024,0020,0020,0020,0020,0020,0174,0000,
  70.     0174,0202,0200,0100,0070,0004,0002,0002,0376,0000,
  71.     0174,0202,0200,0200,0170,0200,0200,0202,0174,0000,
  72.     0100,0140,0120,0110,0104,0102,0376,0100,0100,0000,
  73.     0376,0002,0002,0076,0100,0200,0200,0102,0074,0000,
  74.     0170,0004,0002,0002,0176,0202,0202,0202,0174,0000,
  75.     0376,0202,0100,0040,0020,0010,0010,0010,0010,0000,
  76.     0174,0202,0202,0202,0174,0202,0202,0202,0174,0000,
  77.     0174,0202,0202,0202,0374,0200,0200,0100,0074,0000,
  78.     0000,0000,0000,0030,0030,0000,0000,0030,0030,0000,
  79.     0000,0000,0030,0030,0000,0000,0030,0030,0010,0004,
  80.     0040,0020,0010,0004,0002,0004,0010,0020,0040,0000,
  81.     0000,0000,0000,0174,0000,0174,0000,0000,0000,0000,
  82.     0010,0020,0040,0100,0200,0100,0040,0020,0010,0000,
  83.     0170,0204,0204,0200,0140,0020,0020,0000,0020,0000,
  84.     0170,0204,0262,0252,0252,0172,0002,0004,0170,0000,
  85.     0070,0104,0202,0202,0202,0376,0202,0202,0202,0000,
  86.     0176,0204,0204,0204,0174,0204,0204,0204,0176,0000,
  87.     0170,0204,0002,0002,0002,0002,0002,0204,0174,0000,
  88.     0076,0104,0204,0204,0204,0204,0204,0104,0076,0000,
  89.     0376,0002,0002,0002,0036,0002,0002,0002,0376,0000,
  90.     0376,0002,0002,0002,0036,0002,0002,0002,0002,0000,
  91.     0170,0204,0002,0002,0002,0362,0202,0204,0174,0000,
  92.     0202,0202,0202,0202,0376,0202,0202,0202,0202,0000,
  93.     0174,0020,0020,0020,0020,0020,0020,0020,0174,0000,
  94.     0370,0040,0040,0040,0040,0040,0040,0042,0034,0000,
  95.     0202,0102,0042,0022,0012,0026,0042,0102,0202,0000,
  96.     0002,0002,0002,0002,0002,0002,0002,0002,0376,0000,
  97.     0202,0306,0252,0222,0222,0202,0202,0202,0202,0000,
  98.     0202,0206,0212,0222,0242,0302,0202,0202,0202,0000,
  99.     0070,0104,0202,0202,0202,0202,0202,0104,0070,0000,
  100.     0176,0202,0202,0202,0176,0002,0002,0002,0002,0000,
  101.     0070,0104,0202,0202,0202,0222,0242,0104,0270,0000,
  102.     0176,0202,0202,0202,0176,0022,0042,0102,0202,0000,
  103.     0174,0202,0002,0002,0174,0200,0200,0202,0174,0000,
  104.     0376,0020,0020,0020,0020,0020,0020,0020,0020,0000,
  105.     0202,0202,0202,0202,0202,0202,0202,0202,0174,0000,
  106.     0202,0202,0202,0104,0104,0050,0050,0020,0020,0000,
  107.     0202,0202,0202,0202,0222,0222,0252,0306,0202,0000,
  108.     0202,0202,0104,0050,0020,0050,0104,0202,0202,0000,
  109.     0202,0202,0104,0050,0020,0020,0020,0020,0020,0000,
  110.     0376,0200,0100,0040,0020,0010,0004,0002,0376,0000,
  111.     0074,0004,0004,0004,0004,0004,0004,0004,0074,0000,
  112.     0000,0002,0004,0010,0020,0040,0100,0200,0000,0000,
  113.     0074,0040,0040,0040,0040,0040,0040,0040,0074,0000,
  114.     0020,0050,0104,0202,0000,0000,0000,0000,0000,0000,
  115.     0000,0000,0000,0000,0000,0000,0000,0000,0376,0000,
  116.     0030,0030,0020,0040,0000,0000,0000,0000,0000,0000,
  117.     0000,0000,0000,0074,0100,0174,0102,0102,0274,0000,
  118.     0002,0002,0002,0072,0106,0102,0102,0106,0072,0000,
  119.     0000,0000,0000,0074,0102,0002,0002,0102,0074,0000,
  120.     0100,0100,0100,0134,0142,0102,0102,0142,0134,0000,
  121.     0000,0000,0000,0074,0102,0176,0002,0002,0074,0000,
  122.     0060,0110,0010,0010,0076,0010,0010,0010,0010,0000,
  123.     0000,0000,0000,0134,0142,0142,0134,0100,0100,0074,
  124.     0002,0002,0002,0072,0106,0102,0102,0102,0102,0000,
  125.     0000,0020,0000,0030,0020,0020,0020,0020,0070,0000,
  126.     0140,0100,0100,0100,0100,0100,0100,0104,0070,0000,
  127.     0002,0002,0002,0042,0022,0012,0026,0042,0102,0000,
  128.     0030,0020,0020,0020,0020,0020,0020,0020,0070,0000,
  129.     0000,0000,0000,0156,0222,0222,0222,0222,0222,0000,
  130.     0000,0000,0000,0072,0106,0102,0102,0102,0102,0000,
  131.     0000,0000,0000,0074,0102,0102,0102,0102,0074,0000,
  132.     0000,0000,0000,0072,0106,0102,0106,0072,0002,0002,
  133.     0000,0000,0000,0134,0142,0102,0142,0134,0100,0100,
  134.     0000,0000,0000,0072,0106,0002,0002,0002,0002,0000,
  135.     0000,0000,0000,0074,0102,0014,0060,0102,0074,0000,
  136.     0000,0010,0010,0076,0010,0010,0010,0110,0060,0000,
  137.     0000,0000,0000,0102,0102,0102,0102,0142,0134,0000,
  138.     0000,0000,0000,0202,0202,0202,0104,0050,0020,0000,
  139.     0000,0000,0000,0202,0222,0222,0222,0222,0154,0000,
  140.     0000,0000,0000,0102,0044,0030,0030,0044,0102,0000,
  141.     0000,0000,0000,0102,0102,0102,0142,0134,0100,0074,
  142.     0000,0000,0000,0176,0040,0020,0010,0004,0176,0000,
  143.     0160,0010,0010,0010,0004,0010,0010,0010,0160,0000,
  144.     0020,0020,0020,0000,0000,0020,0020,0020,0000,0000,
  145.     0030,0040,0040,0040,0100,0040,0040,0040,0030,0000,
  146.     0014,0222,0140,0000,0000,0000,0000,0000,0000,0000,
  147.     0044,0222,0110,0044,0222,0110,0044,0222,0110,0000,
  148. };
  149. /* This vector maps key codes to ascii equivalents. Characters with funny
  150.  * shift values like )9 are referenced indirectly in the second table by
  151.  * 0200 + (pos in secnd table). Most unused keys are given 07 (bell) or 0.
  152.  */
  153. char prokbmap[] = {
  154.     07,    07,    07,    026,    022,    07,    07,    07,
  155.     07,    07,    07,    07,    07,    07,    027,    031,
  156.     05,    025,    04,    07,    07,    07,    07,    07,
  157.     07,    07,    07,
  158.     033,    010,    012,    07,    07,    07,    07,    07,
  159.     07,    07,    07,    07,    015,    07,    07,    07,
  160.     07,    07,    07,    07,    07,    07,    07,    07,
  161.     07,    0167,    0151,    0170,    033,    02,    06,    07,
  162.     07,    060,    07,    056,    015,    061,    062,    063,
  163.     064,    065,    066,    054,    067,    070,    071,    055,
  164.     07,    07,    07,    07,    07,    07,    07,    07,
  165.     07,    07,    07,    07,    07,    07,    07,    07,
  166.     07,    07,    07,    07,    07,    07,    0,    0,
  167.     0,    0,    07,    0177,    015,    011,    0200,    0201,
  168.     0161,    0141,    0172,    07,    0202,    0167,    0163,    0170,
  169.     0203,    07,    0204,    0145,    0144,    0143,    07,    0205,
  170.     0162,    0146,    0166,    040,    07,    0206,    0164,    0147,
  171.     0142,    07,    0207,    0171,    0150,    0156,    07,    0210,
  172.     0165,    0152,    0155,    07,    0211,    0151,    0153,    054,
  173.     07,    0212,    0157,    0154,    056,    07,    0213,    0160,
  174.     07,    0214,    0215,    07,    0216,    0217,    0220,    07,
  175.     0221,    0222,    0223,    07,    07,    07,    07,
  176. };
  177. /* Defines char. pairs for funny shift caps like 9)
  178.  */
  179. proupmap[][2] = {
  180.     0176,    0140,
  181.     041,    061,
  182.     0100,    062,
  183.     076,    074,
  184.     043,    063,
  185.     044,    064,
  186.     045,    065,
  187.     0136,    066,
  188.     046,    067,
  189.     052,    070,
  190.     050,    071,
  191.     051,    060,
  192.     072,    073,
  193.     077,    057,
  194.     053,    075,
  195.     0175,    0135,
  196.     0174,    0134,
  197.     0137,    055,
  198.     0173,    0133,
  199.     042,    047,
  200. };
  201.  
  202. char kblastc, kbmode, backtodo, backlog, scstate;
  203. unsigned int kbbell, scxpos, scypos, scflash, scflags, scoffset, ot_flags;
  204.  
  205. int    cnstart();
  206. int    sctimer();
  207. int    ttrstrt();
  208.  
  209. cnattach(addr, unit)
  210. struct scdevice *addr;
  211. {
  212.     if ((unsigned)unit >= NCN)
  213.         return(0);
  214.     SCADDR = addr;
  215.     return(1);
  216. }
  217.  
  218. cnopen(dev, flag)
  219. dev_t dev;
  220. {
  221.     register struct tty *tp;
  222.     int s;
  223.  
  224.     if (minor(dev) >= NCN) {
  225.         u.u_error = EINVAL;
  226.         return;
  227.     }
  228.     if (SCADDR == (struct scdevice *)NULL ||
  229.         KBADDR == (struct kbdevice *)NULL) {
  230.         u.u_error = ENXIO;
  231.         return;
  232.     }
  233.     tp = &cn11;
  234.     tp->t_oproc = cnstart;
  235.     if ((tp->t_state&ISOPEN) == 0) {
  236.         tp->t_state = ISOPEN|CARR_ON;
  237.         tp->t_flags = ODDP|EVENP|ECHO|CRMOD;
  238.         tp->t_ispeed = tp->t_ospeed = B9600;
  239.         tp->t_line = DFLT_LDISC;
  240.         ttychars(tp);
  241.     } else if (tp->t_state&XCLUDE && u.u_uid != 0) {
  242.         u.u_error = EBUSY;
  243.         return;
  244.     }
  245.     /* Initialize screen and keyboard port */
  246.     s = spl4();
  247.     if ((scflags & SCSET) == 0) {
  248.         SCADDR->mbr = 0170;
  249.         SCADDR->p1c = 041;
  250.         if ((SCADDR->scsr & 020000) == 0)
  251.             SCADDR->opc = 020441;
  252.         SCADDR->scsr = 040100;
  253.         scflags |= SCSET;
  254.     }
  255.     /* Start timer, used to generate blinking curser. */
  256.     if ((scflags & TIMER) == 0) {
  257.         scflags |= TIMER;
  258.         sctimer();
  259.     }
  260.     scflags |= CURSER;
  261.     splx(s);
  262.     ienable(IVEC(SCADDR, APOS));
  263.     ienable(IVEC(SCADDR, BPOS));
  264.     KBADDR->csr = GOCMD;
  265.     ienable(KBRPOS);
  266.     ienable(KBXPOS);
  267.     ttyopen(dev, tp);
  268. }
  269.  
  270. cnclose(dev, flag)
  271. dev_t dev;
  272. int flag;
  273. {
  274.  
  275.     ttyclose(&cn11);
  276. }
  277.  
  278. cnread(dev)
  279. dev_t dev;
  280. {
  281.     register struct tty *tp;
  282.  
  283.     tp = &cn11;
  284.     (*linesw[tp->t_line].l_read)(tp);
  285. }
  286.  
  287. /* If PLOT flag set, put raster data directly to the screen, else
  288.  * map onto ascii font.
  289.  */
  290. cnwrite(dev)
  291. dev_t dev;
  292. {
  293.     register struct tty *tp;
  294.     unsigned size;
  295.     char *ptr;
  296.     long tmp;
  297.     segm save;
  298.  
  299.     if (scflags & PLOT) {
  300.         saveseg5(save);
  301.         scoffset = (scypos<<7)+(scxpos>>3);
  302.         while (u.u_count) {
  303.             size = 0100000-scoffset;
  304.             size = MIN(size, 8192);
  305.             size = MIN(size, u.u_count);
  306.             tmp = scoffset;
  307.             ptr = BITMAP|(tmp & 077);
  308.             tmp = (tmp>>6)&0777;
  309.             mapseg5((BITBASE|tmp), 077406);
  310.             iomove(ptr, size, B_WRITE);
  311.             if (u.u_error) {
  312.                 restorseg5(save);
  313.                 return;
  314.             }
  315.             scoffset = (scoffset+size)&077777;
  316.         }
  317.         restorseg5(save);
  318.         scxpos = (scoffset & 0177) << 3;
  319.         scypos = scoffset>>7;
  320.         return;
  321.     }
  322.     tp = &cn11;
  323.     (*linesw[tp->t_line].l_write)(tp);
  324. }
  325.  
  326. kbrint(dev)
  327. dev_t dev;
  328. {
  329.     register int c;
  330.     register struct tty *tp;
  331.  
  332.     if ((KBADDR->stat & RXDONE) == 0)
  333.         return;
  334.     tp = &cn11;
  335.     c = KBADDR->dbuf;
  336.     if (KBADDR->stat & RXERR)
  337.         KBADDR->csr = GOCMD;
  338.     while ((c = promapkb(c&0377)) != 0) {
  339.         (*linesw[tp->t_line].l_input)(c, tp);
  340.         c = 0;
  341.     }
  342. }
  343.  
  344. kbxint(dev)
  345. dev_t dev;
  346. {
  347.     if ((KBADDR->stat & TXDONE) == 0)
  348.         return;
  349.     if ((--kbbell) > 0)
  350.         KBADDR->dbuf = 0xa7;
  351.     else
  352.         kbbell = 0;
  353. }
  354.  
  355. cnioctl(dev, cmd, addr, flag)
  356. caddr_t addr;
  357. dev_t dev;
  358. int cmd, flag;
  359. {
  360.     register struct tty *tp = &cn11;
  361.     register int tmp;
  362.     int s;
  363.  
  364.     switch(cmd) {
  365.     case SIOCPLOT:
  366.         if ((scflags & PLOT) == 0) {
  367.             s = spl4();
  368.             ot_flags = tp->t_flags;
  369.             tp->t_flags &= ~ECHO;
  370.             scflags |= PLOT;
  371.             scxpos = scypos = 0;
  372.             scflags &= ~CURSER;
  373.             if (scflags & CURSON) {
  374.                 scurser();
  375.                 scflags |= XFERSLP;
  376.                 while (scflags & XFERSLP)
  377.                     sleep((caddr_t)&scflags, TTOPRI);
  378.             }
  379.             scleary(0, 256);
  380.             if ((tmp = fuword(addr)) >= 0) {
  381.                 SCADDR->scsr = (tmp&02)|((tmp&01)<<10)|040100;
  382.                 tmp = (tmp&014)>>2;
  383.                 SCADDR->p1c = (tmp<<3)|041;
  384.                 if ((SCADDR->scsr & 020000) == 0)
  385.                     SCADDR->opc = (tmp<<3)|(tmp<<11)|0401;
  386.             }
  387.             splx(s);
  388.         }
  389.         break;
  390.     case SIOCPRNT:
  391.         if (scflags & PLOT) {
  392.             s = spl4();
  393.             tp->t_flags = ot_flags;
  394.             if ((SCADDR->scsr & XFERDONE) == 0) {
  395.                 scflags |= XFERSLP;
  396.                 while (scflags & XFERSLP)
  397.                     sleep((caddr_t)&scflags, TTOPRI);
  398.             }
  399.             scxpos = scypos = 0;
  400.             SCADDR->p1c = 041;
  401.             if ((SCADDR->scsr & 020000) == 0)
  402.                 SCADDR->opc = 020441;
  403.             SCADDR->scsr = 040100;
  404.             scleary(0, 256);
  405.             scflags |= CURSER;
  406.             scflags &= ~PLOT;
  407.             splx(s);
  408.         }
  409.         break;
  410.     case SIOCCSP:
  411.         if (scflags & PLOT) {
  412.             s = spl4();
  413.             if (scflags & CURSON) {
  414.                 scurser();
  415.                 scflags |= XFERSLP;
  416.                 while (scflags & XFERSLP)
  417.                     sleep((caddr_t)&scflags, TTOPRI);
  418.             }
  419.             scxpos = fuword(addr)&01777;
  420.             scypos = fuword(++addr)&0377;
  421.             splx(s);
  422.         }
  423.         break;
  424.     case SIOCCSN:
  425.         s = spl4();
  426.         scflags |= CURSER;
  427.         splx(s);
  428.         break;
  429.     case SIOCCSF:
  430.         s = spl4();
  431.         scflags &= ~CURSER;
  432.         if (scflags & CURSON) {
  433.             scurser();
  434.             scflags |= XFERSLP;
  435.             while (scflags & XFERSLP)
  436.                 sleep((caddr_t)&scflags, TTOPRI);
  437.         }
  438.         splx(s);
  439.         break;
  440.     case SIOCSCRL:
  441.         s = spl4();
  442.         if ((SCADDR->scsr & XFERDONE) == 0) {
  443.             scflags |= XFERSLP;
  444.             while (scflags & XFERSLP)
  445.                 sleep((caddr_t)&scflags, TTOPRI);
  446.         }
  447.         tmp = SCADDR->scroll&0377;
  448.         SCADDR->scroll = tmp+fuword(addr);
  449.         splx(s);
  450.         break;
  451.     case SIOCGRPH:
  452.         if ((scflags & PLOT) == 0) {
  453.             u.u_error = ENOTTY;
  454.             return;
  455.         }
  456.         s = spl4();
  457.         while ((SCADDR->scsr & XFERDONE) == 0) ;
  458.         SCADDR->p1c = (SCADDR->p1c&070)|02;
  459.         if ((SCADDR->scsr & 020000) == 0)
  460.             SCADDR->opc = (SCADDR->opc&034070)|01002;
  461.         SCADDR->pat = fuword(addr);
  462.         SCADDR->x = fuword(++addr);
  463.         SCADDR->y = fuword(++addr);
  464.         SCADDR->cnt = fuword(++addr);
  465.         scflags |= XFERSLP;
  466.         while (scflags & XFERSLP)
  467.             sleep((caddr_t)&scflags, TTOPRI);
  468.         SCADDR->p1c = (SCADDR->p1c&070)|01;
  469.         if ((SCADDR->scsr & 020000) == 0)
  470.             SCADDR->opc = (SCADDR->opc&034070)|0401;
  471.         splx(s);
  472.         break;
  473.     case SIOCPLEN:
  474.         if ((scflags & PLOT) == 0) {
  475.             u.u_error = ENOTTY;
  476.             return;
  477.         }
  478.         s = spl4();
  479.         tmp = fuword(addr) & 07;
  480.         SCADDR->p1c = (SCADDR->p1c&037)|((tmp&01)<<5);
  481.         if ((SCADDR->scsr & 020000) == 0)
  482.             SCADDR->opc = (SCADDR->opc&017437)|((tmp&02)<<4)|
  483.                 ((tmp&04)<<11);
  484.         splx(s);
  485.         break;
  486.     case SIOCSCM:
  487.         if ((scflags & PLOT) == 0) {
  488.             u.u_error = ENOTTY;
  489.             return;
  490.         }
  491.         s = spl4();
  492.         SCADDR->cmp = fuword(addr) & 03777;
  493.         splx(s);
  494.         break;
  495.     default:
  496.         switch (ttioctl(tp, cmd, addr, flag)) {
  497.         case TIOCSETN:
  498.         case TIOCSETP:
  499.         case 0:
  500.             break;
  501.         default:
  502.             u.u_error = ENOTTY;
  503.         }
  504.     };
  505. }
  506.  
  507. cnstart(tp)
  508. register struct tty *tp;
  509. {
  510.     register c;
  511.  
  512.      while ((c=getc(&tp->t_outq)) >= 0) {
  513.         proputc(c&0177);
  514.     }
  515. }
  516.  
  517. char    *msgbufp = msgbuf;    /* Next saved printf character */
  518. /*
  519.  * Print a character on console.
  520.  *
  521.  * Whether or not printing is inhibited,
  522.  * the last MSGBUFS characters
  523.  * are saved in msgbuf for inspection later.
  524.  */
  525. putchar(c)
  526. register c;
  527. {
  528.     int s;
  529.  
  530.     if (c != '\0' && c != '\r' && c != 0177) {
  531.         *msgbufp++ = c;
  532.         if(msgbufp >= &msgbuf[MSGBUFS])
  533.             msgbufp = msgbuf;
  534.     }
  535.     if(c == 0)
  536.         return;
  537.     /* Do not print if screen in plot mode. */
  538.     s = spl4();
  539.     if ((scflags & PLOT) == 0) {
  540.         if ((scflags & SCSET) == 0) {
  541.             SCADDR->mbr = 0170;
  542.             SCADDR->p1c = 041;
  543.             if ((SCADDR->scsr & 020000) == 0)
  544.                 SCADDR->opc = 020441;
  545.             SCADDR->scsr = 040100;
  546.             scleary(0, 256);
  547.             scflags |= SCSET;
  548.         }
  549.         proputc(c&0177);
  550.     }
  551.     splx(s);
  552.     if(c == '\n') {
  553.         putchar('\r');
  554.     }
  555. }
  556.  
  557. /* This function displays a charcter on the bit mapped screen using
  558.  * a vt52 emulation of control sequences.
  559.  */
  560. proputc(c)
  561. char c;
  562. {
  563.     register int val, i;
  564.  
  565.     /* Turn off the blinking!! curser */
  566.     scflags &= ~CURSER;
  567.     if (scflags & CURSON)
  568.         scurser();
  569.  
  570.     /* Now update the screen as required by the next char. */
  571.     if (scstate)
  572.         checkesc(c);
  573.     else if (c >= 040 && c <= 0177)
  574.         scputc(c);
  575.     else
  576.         switch(c) {
  577.         case 011:
  578.             val = 8-(scxpos%8);
  579.             for (i = 0; i < val; i++)
  580.                 scputc(' ');
  581.             break;
  582.         case 010:
  583.             if (scxpos > 0)
  584.                 scxpos--;
  585.             break;
  586.         case 012:
  587.             if (scypos >= YMAX)
  588.                 scroll(LNPEROW);
  589.             else
  590.                 scypos++;
  591.             break;
  592.         case 015:
  593.             scxpos = 0;
  594.             break;
  595.         case 033:
  596.             scstate = GETESC;
  597.             break;
  598.         case 07:
  599.             kbring();
  600.             break;
  601.         default:
  602.             ;
  603.         };
  604.     /* Done so turn the curser back on. */
  605.     scflags |= CURSER;
  606. }
  607.  
  608. /* This function validates and performs a vt52 escape sequence. */
  609. checkesc(c)
  610. char c;
  611. {
  612.     register int val;
  613.  
  614.     switch(scstate) {
  615.     case GETX:
  616.         val = c-' ';
  617.         if (val >= 0 && val <= XMAX)
  618.             scxpos = val;
  619.         scstate = ESCDONE;
  620.         break;
  621.     case GETY:
  622.         val = c-' ';
  623.         if (val >= 0 && val <= YMAX)
  624.             scypos = val;
  625.         scstate = GETX;
  626.         break;
  627.     default:
  628.         scstate = ESCDONE;
  629.         switch(c) {
  630.         case 'A':
  631.             if (scypos > 0)
  632.                 scypos--;
  633.             break;
  634.         case 'B':
  635.             if (scypos < YMAX)
  636.                 scypos++;
  637.             break;
  638.         case 'C':
  639.             if (scxpos < XMAX)
  640.                 scxpos++;
  641.             break;
  642.         case 'D':
  643.             if (scxpos > 0)
  644.                 scxpos--;
  645.             break;
  646.         case 'F':
  647.         case 'G':
  648.             break;
  649.         case 'H':
  650.             scypos = scxpos = 0;
  651.             break;
  652.         case 'I':
  653.             if (scypos > 0)
  654.                 scypos--;
  655.             else
  656.                 scroll(-LNPEROW);
  657.             break;
  658.         case 'J':
  659.             scleary(scypos, (YMAX-scypos)*LNPEROW);
  660.             break;
  661.         case 'K':
  662.             sclearx();
  663.             break;
  664.         case 'Y':
  665.             scstate = GETY;
  666.             break;
  667.         default:
  668.             scputc(c);
  669.         };
  670.     };
  671. }
  672.  
  673. /* This function copies the font for one char. onto the bitmap
  674.  * at the current position.
  675.  */
  676. scputc(c)
  677. char c;
  678. {
  679.     register char *ptr, *ptr2;
  680.     register int i;
  681.     unsigned int tmp2;
  682.     union {
  683.         unsigned int word;
  684.         char byte[2];
  685.     } tmp3;
  686.     segm save;
  687.     long tmp;
  688.  
  689.     ptr = &profont[c-040][0];
  690.     tmp = scypos*1280l+((scxpos*FNTWIDTH)>>3);
  691.     tmp2 = (scxpos*FNTWIDTH)&07;
  692.     ptr2 = BITMAP|(tmp&077);
  693.     tmp = (tmp>>6)&0777;
  694.     saveseg5(save);
  695.     mapseg5((BITBASE|tmp), 077406);
  696.     for (i = 0; i < FNTLINE; i++) {
  697.         if (tmp2) {
  698.             tmp3.byte[0] = *ptr2;
  699.             tmp3.byte[1] = *(ptr2+1);
  700.             tmp3.word &= ~(0377<<(8-tmp2));
  701.             tmp3.word |= ((unsigned)(*ptr++))<<(8-tmp2);
  702.             *ptr2 = tmp3.byte[0];
  703.             *(ptr2+1) = tmp3.byte[1];
  704.         } else {
  705.             *ptr2 = *ptr++;
  706.         }
  707.         ptr2 += 128;
  708.     }
  709.     restorseg5(save);
  710.     if (scxpos < XMAX) {
  711.         scxpos++;
  712.     }
  713. }
  714.  
  715. /* This function clears the current line from the curser to the end. */
  716. sclearx() {
  717.     register int i, j;
  718.     register char *ptr2;
  719.     char *ptr;
  720.     int tmp2, tmp3;
  721.     long tmp;
  722.     segm save;
  723.  
  724.     tmp = scypos*1280l+((scxpos*FNTWIDTH)>>3);
  725.     tmp2 = (scxpos*FNTWIDTH)&07;
  726.     ptr = BITMAP|(tmp&077);
  727.     tmp = (tmp>>6)&0777;
  728.     saveseg5(save);
  729.     mapseg5((BITBASE|tmp), 077406);
  730.     for (i = 0; i < FNTLINE; i++) {
  731.         ptr2 = ptr;
  732.         if (tmp2) {
  733.             tmp3 = *ptr2;
  734.             tmp3 &= ~(0377<<(8-tmp2));
  735.             *ptr2++ = tmp3;
  736.         }
  737.         for (j = 0; j < ((1024-scxpos*FNTWIDTH)>>3); j++)
  738.             *ptr2++ = 0;
  739.         ptr += 128;
  740.     }
  741.     restorseg5(save);
  742. }
  743.  
  744. /* This function clears the screen from the y pos. given for lines
  745.  * raster lines.
  746.  */
  747. scleary(ypos, lines)
  748. int ypos, lines;
  749. {
  750.     register int i, j, *ptr;
  751.     segm save;
  752.  
  753.     saveseg5(save);
  754.     for (i = 0; i < lines; i++) {
  755.         ptr = (int *)BITMAP;
  756.         mapseg5((BITBASE|(((128l*ypos)>>6)&0777)), 077406);
  757.         for (j = 0; j < 64; j++)
  758.             *ptr++ = 0;
  759.         ypos++;
  760.     }
  761.     restorseg5(save);
  762. }
  763.  
  764. /* This function scrolls the screen up/down the num. of raster lines
  765.  * given.
  766.  */
  767. scroll(lines)
  768. int lines;
  769. {
  770.     register int i, tmp;
  771.  
  772.     if (lines > 0) {
  773.         for (i = 0; i < lines; i++) {
  774.             scleary(240, 1);
  775.             tmp = SCADDR->scroll & 0377;
  776.             SCADDR->scroll = ++tmp;
  777.         }
  778.     } else {
  779.         for (i = 0; i > lines; i--) {
  780.             scleary(255, 1);
  781.             tmp = SCADDR->scroll & 0377;
  782.             SCADDR->scroll = --tmp;
  783.         }
  784.     }
  785. }
  786.  
  787. /* This function toggles the blinking curser on/off each call. */
  788. scurser()
  789. {
  790.  
  791.     /* Toggle the curser on/off flag and then toggle the curser */
  792.     if (scflags & CURSON)
  793.         scflags &= ~CURSON;
  794.     else
  795.         scflags |= CURSON;
  796.     while ((SCADDR->scsr & XFERDONE) == 0) ;
  797.     SCADDR->scsr &= 0176377;
  798.     SCADDR->p1c = (SCADDR->p1c&070)|01;
  799.     if ((SCADDR->scsr & 020000) == 0)
  800.         SCADDR->opc = (SCADDR->opc&034070)|0401;
  801.     SCADDR->pat = 0177777;
  802.     if (scflags & PLOT) {
  803.         SCADDR->x = scxpos+1;
  804.         SCADDR->y = scypos+1;
  805.         SCADDR->cnt = 3;
  806.     } else {
  807.         SCADDR->x = scxpos*FNTWIDTH;
  808.         SCADDR->y = scypos*LNPEROW+LNPEROW-1;
  809.         SCADDR->cnt = FNTWIDTH;
  810.     }
  811. }
  812.  
  813. /* This timer routine blinks the curser on/off as required. */
  814. unsigned sctimcnt;
  815. sctimer()
  816. {
  817.  
  818.     timeout(sctimer, (caddr_t)0, hz/5);
  819.     sctimcnt++;
  820.     if (scflags & CURSER) {
  821.         if (SCADDR->scsr & XFERDONE) {
  822.             scurser();
  823.         } else {
  824.             scflash++;
  825.         }
  826.     }
  827. }
  828.  
  829. sctint()
  830. {
  831.  
  832.     if (scflash && (scflags & CURSER)) {
  833.         scurser();
  834.         scflash = 0;
  835.         return;
  836.     }
  837.     if (scflags & XFERSLP) {
  838.         scflags &= ~XFERSLP;
  839.         wakeup((caddr_t)&scflags);
  840.     }
  841. }
  842.  
  843. /* End of frame interrupts are used to prod. the output process.
  844.  * Of historical interest, the original driver synchronized updates
  845.  * with end of frames, but this made things too slow.
  846.  */
  847. scfint(dev)
  848. dev_t dev;
  849. {
  850.     register struct tty *tp;
  851.  
  852.     tp = &cn11;
  853.     ttstart(tp);
  854.     if (tp->t_state&ASLEEP && tp->t_outq.c_cc<=TTLOWAT(tp))
  855. #ifdef MPX_FILS
  856.         if (tp->t_chan)
  857.             mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
  858.         else
  859. #endif
  860.             wakeup((caddr_t)&tp->t_outq);
  861.     if ((scflags & XFERSLP) && (SCADDR->scsr & XFERDONE)) {
  862.         scflags &= ~XFERSLP;
  863.         wakeup((caddr_t)&scflags);
  864.     }
  865. }
  866.  
  867. /* This function maps the kb codes to appropriate ascii codes.
  868.  * This is specific to the US keyboard layout.
  869.  */
  870. promapkb(c)
  871. int c;
  872. {
  873.     if (c == 0) {
  874.         if (backtodo) {
  875.             backtodo = 0;
  876.             return(backlog);
  877.         } else {
  878.             return(0);
  879.         }
  880.     }
  881.     if (c == MTRNOME) {
  882.         if (kblastc == ESC)
  883.             backtodo = 1;
  884.         return(kblastc);
  885.     }
  886.     switch(c) {
  887.     case KSHIFT:
  888.         if (kbmode & SHIFT)
  889.             kbmode &= ~SHIFT;
  890.         else
  891.             kbmode |= SHIFT;
  892.         return(0);
  893.     case KCNTL:
  894.         if (kbmode & CNTL)
  895.             kbmode &= ~CNTL;
  896.         else
  897.             kbmode |= CNTL;
  898.         return(0);
  899.     case KLOCK:
  900.         if (kbmode & LOCK)
  901.             kbmode &= ~LOCK;
  902.         else
  903.             kbmode |= LOCK;
  904.         return(0);
  905.     case ALLUPS:
  906.         kbmode &= ~(CNTL|SHIFT);
  907.         return(0);
  908.     case UP:
  909.         backlog = 0101;
  910.         backtodo = 1;
  911.         kblastc = ESC;
  912.         return(ESC);
  913.     case DOWN:
  914.         backlog = 0102;
  915.         backtodo = 1;
  916.         kblastc = ESC;
  917.         return(ESC);
  918.     case RIGHT:
  919.         backlog = 0103;
  920.         backtodo = 1;
  921.         kblastc = ESC;
  922.         return(ESC);
  923.     case LEFT:
  924.         backlog = 0104;
  925.         backtodo = 1;
  926.         kblastc = ESC;
  927.         return(ESC);
  928.     case COMPOSE:
  929.         if (kbmode & STOPD) {
  930.             kbmode &= ~STOPD;
  931.             return(021);
  932.         } else {
  933.             kbmode |= STOPD;
  934.             return(023);
  935.         }
  936.     case KPRNT:
  937.         cnioctl(0, SIOCPRNT, 0, 0);
  938.         return(0);
  939.     default:
  940.         if (c < 86)
  941.             return(0);
  942.         c = prokbmap[c-86]&0377;
  943.         if (c & 0200) {
  944.             if (kbmode & SHIFT)
  945.                 c = proupmap[c-0200][0]&0177;
  946.             else
  947.                 c = proupmap[c-0200][1]&0177;
  948.         } else if (c >= 'a' && c <= 'z') {
  949.             if (kbmode & (SHIFT|LOCK))
  950.                 c -= 040;
  951.             else if (kbmode & CNTL)
  952.                 c -= 0140;
  953.         }
  954.         kblastc = c;
  955.         return(c);
  956.     };
  957. }
  958.  
  959. /* This function rings the kb bell. If busy, just let kbxint know... */
  960. kbring()
  961. {
  962.     kbbell++;
  963.     if (KBADDR->stat & TXDONE)
  964.         KBADDR->dbuf = 0xa7;
  965. }
  966. #endif
  967.