|
|
1.1 root 1: #define SWANFIX 1
2: #define GREEKFIX 1
3:
4: /*
5: * User configurable AT keyboard/display driver.
6: * 286/386 AT COHERENT
7: */
8: #include <sys/coherent.h>
9: #ifdef _I386
10: #include <sys/reg.h>
11: #else
12: #include <sys/i8086.h>
13: #endif
14: #include <sys/con.h>
15: #include <errno.h>
16: #include <sys/stat.h>
17: #include <sys/tty.h>
18: #include <signal.h>
19: #include <sys/seg.h>
20: #include <sys/sched.h>
21: #include <sys/kb.h>
22: #include <sys/devices.h>
23: #include <sys/silo.h>
24:
25: #include <sys/vt.h>
26:
27: #define ISVEC 1 /* Keyboard interrupt vector */
28: #define DEBUG 0
29:
30: #define KBDEBUG(x) T_CON(1,printf(x)); /* debugging output */
31: #define KBDEBUG2(x,y) T_CON(1,printf(x,y)); /* debugging output */
32: #define KBDEBUG3(x,y,z) T_CON(1,printf(x,y,z)); /* debugging output */
33:
34: /*
35: * values for kbstate
36: */
37: #define KB_IDLE 0 /* nothing going on right now */
38: #define KB_SINGLE 1 /* sent a single byte cmd to the kbd */
39: #define KB_DOUBLE_1 2 /* sent 1st byte of 2-byte cmd to kbd */
40: #define KB_DOUBLE_2 3 /* sent 2nd byte of 2-byte cmd to kbd */
41:
42: /*
43: * patchable params for non-standard keyboards
44: */
45: int KBDATA = 0x60; /* Keyboard data */
46: int KBCTRL = 0x61; /* Keyboard control */
47: int KBSTS_CMD = 0x64; /* Keyboard status/command */
48: int KBFLAG = 0x80; /* Keyboard reset flag */
49: int KBBOOT = 1; /* 0: disallow reboot from keyboard */
50: int KBTIMEOUT = 10000; /* shouldn't need this much */
51: int KBCMDBYTE = 0x05; /* no translation */
52:
53: /*
54: * KBSTATUS bits
55: */
56: #define STS_OBUF_FULL 0x01 /* kbd output buffer full */
57: #define STS_IBUF_FULL 0x02 /* kbd input buffer full */
58: #define STS_SYSTEM 0x04
59: #define STS_CMD_DATA 0x08 /* 1: command or status */
60: #define STS_INHIBIT 0x10 /* 0: keyboard inhibited */
61: #define STS_AUX_OBUF_FULL 0x20
62: #define STS_TIMEOUT 0x40 /* general timeout */
63: #define STS_PAR_ERR 0x80 /* parity error */
64:
65: /*
66: * The following are magic commands which read from or write to the
67: * controller command byte. These get output to the KBSTS_CMD port.
68: */
69: #define C_READ_CMD 0x20 /* read controller command byte */
70: #define C_WRITE_CMD 0x60 /* write controller command byte */
71: #define C_TRANSLATE 0x40 /* translate enable bit in cmd byte */
72:
73: /*
74: * Globals:
75: * The 286 keyboard mapping table is too large to fit into kernel data space,
76: * so we need to allocate a segment to it. 386 is easy.
77: * The function keys tend to be small and tend to change substantially
78: * more often than the mapping table, so we keep them in the kernel data space.
79: */
80: static unsigned shift; /* state of all shift/lock keys */
81: static unsigned char **funkeyp = 0; /* ptr to array of func. keys ptrs */
82: static FNKEY *fnkeys = 0; /* pointer to structure of values */
83: static unsigned fklength; /* length of k_fnval field in fnkeys */
84: static unsigned prev_cmd; /* previous command sent to KBD */
85: static unsigned cmd2; /* 2nd byte of command to KBD */
86: static unsigned sh_index; /* shift/lock state index */
87: #ifdef _I386
88: static KBTBL kb[MAX_KEYS]; /* keyboard table */
89: #else
90: static SEG *kbsegp; /* keyboard table segment */
91: #endif
92:
93: /*
94: * State variables.
95: */
96: int islock; /* Keyboard locked flag */
97: int isbusy; /* Raw input conversion busy */
98: static char table_loaded; /* true == keyboard table resident */
99: static char fk_loaded; /* true == function keys resident */
100: static int kbstate = KB_IDLE; /* current keyboard state */
101:
102: /*
103: * Functions.
104: */
105: int isrint();
106: int istime();
107: void isbatch();
108: int mmstart();
109: int isopen();
110: int isclose();
111: int isread();
112: int mmwrite();
113: int isioctl();
114: void mmwatch();
115: int isload();
116: int isuload();
117: int ispoll();
118: int nulldev();
119: int nonedev();
120: int updleds();
121:
122: /*
123: * Configuration table.
124: */
125: CON iscon ={
126: DFCHR|DFPOL, /* Flags */
127: KB_MAJOR, /* Major index */
128: isopen, /* Open */
129: isclose, /* Close */
130: nulldev, /* Block */
131: isread, /* Read */
132: mmwrite, /* Write */
133: isioctl, /* Ioctl */
134: nulldev, /* Powerfail */
135: mmwatch, /* Timeout */
136: isload, /* Load */
137: isuload, /* Unload */
138: ispoll /* Poll */
139: };
140:
141: /*
142: ==============================================================================
143: ==============================================================================
144: */
145: /* constants for vtdata[] */
146: #define VT_VGAPORT 0x3D4
147: #define VT_MONOPORT 0x3B4
148:
149: #ifdef _I386
150: #define VT_MONOBASE (SEG_VIDEOa|DPL_1)
151: #define VT_VGABASE (SEG_VIDEOb|DPL_1)
152: #else
153: #define VT_MONOBASE 0xB000
154: #define VT_VGABASE 0xB800
155: #endif
156:
157: /*
158: Patchable table entrys,
159: we go indirect in order to produce a label which can be addressed
160: */
161: #if SWANFIX
162: int VTSWAN = 0; /* patch to 1 for epstein's fix for Swan keyboard */
163: #endif
164:
165: #if GREEKFIX
166: static void ToggleGreek();
167: static int ToGreek();
168: int VTGREEK = 0; /* patch to 1 for TECOP Greek mod */
169: #endif
170:
171: HWentry VTVGA = { 4, 0, VT_VGAPORT, { 0, VT_VGABASE }, { 25, 80 } };
172: HWentry VTMONO = { 4, 0, VT_MONOPORT, { 0, VT_MONOBASE }, { 25, 80 } };
173:
174: HWentry *vtHWtable[] = {
175: VTVGA, /* VGA followed by MONO is compatible to DOS */
176: VTMONO,
177: 0 /* MUST STAY AS LAST ELEMENT !!! */
178: };
179:
180: extern int mminit();
181: static VTDATA const_vtdata = {
182: mminit, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 23, 24, 0, 0, 0, 23, 0, 0, 1
183: };
184:
185: /* later this should be dynamic */
186: VTDATA *vtconsole, **vtdata;
187:
188: int vtcount, vtmax;
189: extern int vtactive;
190: int vt_verbose = { 0 };
191: int vt_opened = { 0 };
192:
193: /* Terminal structure. */
194: TTY **vttty;
195:
196: /*
197: ==============================================================================
198: ==============================================================================
199: */
200:
201: static silo_t in_silo;
202:
203: /*
204: * Given hw pointer for one of four types of adapters, see if
205: * device is present by write/readback of video memory.
206: *
207: * return 1 if present, else 0
208: */
209: int
210: hwpresent( hw )
211: HWentry *hw;
212: {
213: int save, present = 1;
214:
215: PRINTV( "hwpresent: %x:%x",
216: hw->vidmemory.seg, hw->vidmemory.off );
217: save = ffword( hw->vidmemory.off, hw->vidmemory.seg );
218:
219: sfword( hw->vidmemory.off, hw->vidmemory.seg, 0xAA55 );
220: if( ffword( hw->vidmemory.off, hw->vidmemory.seg ) != 0xAA55 )
221: present = 0;
222:
223: sfword( hw->vidmemory.off, hw->vidmemory.seg, 0x55AA );
224: if( ffword( hw->vidmemory.off, hw->vidmemory.seg ) != 0x55AA )
225: present = 0;
226:
227: sfword( hw->vidmemory.off, hw->vidmemory.seg, save );
228: PRINTV( "%s present\n", present ? "" : " NOT" );
229: return present;
230: }
231:
232: /*
233: * Load entry point.
234: */
235: isload()
236: {
237: register int i;
238: register HWentry **hw;
239: register VTDATA *vp;
240:
241: PRINTV("vtload:\n");
242: fk_loaded = 0;
243: table_loaded = 0;
244: kbstate = KB_IDLE;
245:
246: /* figure out what our current max is */
247: for( vtmax = 0, hw = vtHWtable; *hw; ++hw ) {
248: vtmax += (*hw)->count;
249: (*hw)->found = 0; /* assume non-exist */
250: }
251: PRINTV( "vtload: %d screens possible\n", vtmax );
252:
253: vtdata = (VTDATA **) kalloc( vtmax * sizeof( *vtdata ) );
254: if( vtdata == NULL ) {
255: printf( "vtload: unable to obtain vtdata[%d]\n", vtmax );
256: u.u_error = -1;
257: return;
258: }
259: PRINTV( "vtload: obtained vtdata[%d] @%x\n", vtmax, vtdata );
260:
261: vttty = (TTY **) kalloc( vtmax * sizeof( *vttty ) );
262: if( vttty == NULL ) {
263: printf( "vtload: unable to obtain vttty[%d]\n", vtmax );
264: u.u_error = -1;
265: return;
266: }
267: PRINTV( "vtload: obtained vttty[%d] @%x\n", vtmax, vttty );
268:
269: /* determine which video adaptors are present */
270: for( vtcount = 0, hw = vtHWtable; *hw; ++hw ) {
271: /* suppress board sensing since it seems to confuse some equipment */
272: #if 0
273: if( !hwpresent(*hw) )
274: continue;
275: #endif
276:
277: /* remember our logical start */
278: (*hw)->start = vtcount;
279: PRINTV( ", start %d\n", vtcount );
280:
281: /* allocate the necessary memory */
282: for ( i = 0; i < (*hw)->count; ++i ) {
283: vp = vtdata[vtcount] = kalloc( sizeof(VTDATA) );
284: PRINTV( " vtdata[%d] = @%x\n", vtcount, vp );
285: if( vp == NULL || !VTttyinit(vtcount) ) {
286: printf("not enough memory for VTDATA\n" );
287: break;
288: }
289:
290: /* fill in appropriately */
291: *vp = const_vtdata;
292: vp->vmm_port = (*hw)->port;
293: vp->vmm_vseg = (*hw)->vidmemory.seg;
294: vp->vmm_voff = (*hw)->vidmemory.off;
295:
296: vp->vt_ind = vtcount;
297: vtdatainit(vp);
298: if (i == 0 ) {
299: vp->vmm_visible = VNKB_TRUE;
300: vp->vmm_seg = vp->vmm_vseg;
301: vp->vmm_off = vp->vmm_voff;
302: updscreen(vtcount);
303: }
304: (*hw)->found++;
305: vtcount++;
306: }
307: }
308:
309: /*
310: * initialize vtconsole
311: */
312: vtconsole = vtdata[vtactive = 0];
313: vtconsole->vmm_invis = 0; /* vtconsole cursor visible */
314:
315: /*
316: * Seize keyboard interrupt.
317: */
318: #ifdef _I386
319: setivec(ISVEC, isrint);
320: #else
321: #if VT_MAJOR == KB_MAJOR
322: setivec(1, isrint);
323: #else
324: /*
325: * Map table and vector to us
326: */
327: i = sphi();
328: PRINTV( "VTload: unload old vector\n" );
329: kcall( Kclrivec, 1 );
330: setivec(1, isrint);
331: spl( i );
332: #endif
333: #endif /* _I386 */
334:
335: /*
336: * Enable mmwatch() invocation every second.
337: */
338: drvl[VT_MAJOR].d_time = 1;
339:
340: /*
341: * Initialize video display.
342: */
343: for ( i = 0; i < vtcount; ++i )
344: mmstart( vttty[i] );
345:
346:
347: #ifndef _I386
348: /*
349: * Allocate a segment to store the in-core keyboard table.
350: * This would be a lot more convenient in kernel data space,
351: * but small model COHERENT doesn't have that luxury.
352: */
353: kbsegp = salloc((fsize_t)MAX_TABLE_SIZE, SFSYST|SFNSWP|SFHIGH);
354: if (kbsegp == (SEG *)0)
355: printf("kb: unable to allocate keyboard table segment\n");
356: KBDEBUG("Exiting kbload()\n");
357: #endif
358: fklength = 0;
359: }
360:
361: /*
362: * Unload entry point.
363: */
364: isuload()
365: {
366: register int i;
367: register level = sphi();
368:
369: clrivec(ISVEC);
370: #ifndef _I386
371: #if VT_MAJOR != KB_MAJOR
372: kcall( Ksetivec, ISVEC, &Kisrint );
373: #endif
374: #endif
375: spl( level );
376:
377: /* Restore pointers to original state. */
378: vtconsole = vtdata[0];
379: vtconsole->vmm_invis = 0;
380: vtconsole->vmm_visible = VNKB_TRUE;
381:
382: if( vt_opened )
383: printf( "VTclose with %d open screens\n", vt_opened );
384: if( kbstate != KB_IDLE )
385: printf("kb: keyboard busy during unload\n");
386: #ifndef _I386
387: if (kbsegp != (SEG *)0) {
388: table_loaded = 0;
389: sfree(kbsegp);
390: }
391: #endif
392:
393: #ifndef _I386
394: for( i = 0; i < vtcount; ++i ) {
395: PRINTV( "VTuload: free far %x:%x, tty %x\n",
396: vttty[i]->t_buffer->s_faddr, vttty[i] );
397: sfree( vttty[i]->t_buffer );
398: kfree( vttty[i] );
399: sfree( vtdata[i].vt_buffer );
400: }
401: #endif
402: }
403:
404: /*
405: * Open routine.
406: */
407: isopen(dev, mode)
408: dev_t dev;
409: unsigned int mode;
410: {
411: register int s;
412: register TTY *tp;
413: int index = vtindex(dev);
414:
415: PRINTV("isopen: %x\n", dev);
416: if (index < 0 || index >= vtcount) {
417: u.u_error = ENXIO;
418: return;
419: }
420:
421: tp = vttty[index];
422: if ((tp->t_flags&T_EXCL) != 0 && !super()) {
423: u.u_error = ENODEV;
424: return;
425: }
426: ttsetgrp(tp, dev, mode);
427:
428: s = sphi();
429: if (tp->t_open++ == 0) {
430: tp->t_flags = T_CARR; /* indicate "carrier" */
431: ttopen(tp);
432: }
433: spl(s);
434: #if 0
435: updleds(); /* update keyboard status LEDS */
436: #endif
437: }
438:
439:
440: void isvtswitch();
441:
442: /*
443: * Close a tty.
444: */
445: isclose(dev)
446: {
447: register int s;
448: int index = vtindex(dev);
449: register TTY *tp = vttty[index];
450:
451: #if 0
452: s = sphi();
453: if (--tp->t_open == 0) {
454: ttclose(tp);
455: spl(s);
456: if( index == vtactive )
457: isvtswitch( VTKEY_HOME );
458: } else
459: spl(s);
460: #else
461: if (--tp->t_open == 0)
462: ttclose(tp);
463: #endif
464: }
465:
466: /*
467: * Read routine.
468: */
469: isread(dev, iop)
470: dev_t dev;
471: IO *iop;
472: {
473: int index = vtindex(dev);
474: register TTY *tp = vttty[index];
475:
476: ttread(tp, iop, 0);
477: if (tp->t_oq.cq_cc)
478: mmtime(tp);
479: }
480:
481: /*
482: * Ioctl routine.
483: * nb: archaic TIOCSHIFT and TIOCCSHIFT no longer needed/supported.
484: */
485: isioctl(dev, com, vec)
486: dev_t dev;
487: struct sgttyb *vec;
488: {
489: register int s;
490:
491: switch (com) {
492: case TIOCSETF:
493: case TIOCGETF:
494: isfunction(com, (char *)vec);
495: break;
496: case TIOCSETKBT:
497: issettable(vec);
498: break;
499: case TIOCGETKBT:
500: isgettable(vec);
501: break;
502: default: /* pass to TTY driver */
503: s = sphi();
504: ttioctl(vttty[vtindex(dev)], com, vec);
505: spl(s);
506: break;
507: }
508: }
509:
510: /*
511: * Set the in-core keyboard mapping table.
512: * The table is sorted by scan code prior to calling ioctl().
513: * All unused table entries (holes in the scan code map) have
514: * a zero for the k_key field.
515: * This makes key lookup at interrupt time fast by using the scan code
516: * as an index into the table.
517: */
518: issettable(vec)
519: char *vec;
520: {
521: register unsigned i;
522: register int s;
523: int timeout;
524: static KBTBL this_key; /* current key from kbd table */
525: unsigned int cmd_byte;
526: #ifndef _I386
527: register faddr_t faddr; /* address of keyboard table */
528: #endif
529:
530: PRINTV(" TIOCSETKBT");
531: kb_cmd2(K_SCANCODE_CMD, 3); /* select set 3 */
532: kb_cmd(K_ALL_TMB_CMD); /* default: TMB for all keys */
533: #ifndef _I386
534: faddr = kbsegp->s_faddr;
535: #endif
536: for (i = 0; i < MAX_KEYS; ++i) {
537: ukcopy(vec, &this_key, sizeof(this_key));
538: #ifdef _I386
539: kb[i] = this_key; /* store away */
540: #else
541: kfcopy(&this_key, faddr, sizeof(this_key));
542: faddr += sizeof(this_key);
543: #endif
544: vec += sizeof(this_key);
545: if (this_key.k_key != i && this_key.k_key != 0) {
546: printf("kb: incorrect or unsorted table entry %d\n", i);
547: #ifdef _I386
548: u.u_error = EINVAL;
549: #else
550: u.u_error = EBADFMT;
551: #endif
552: return;
553: }
554: if (this_key.k_key != i)
555: continue; /* no key */
556: switch (this_key.k_flags&TMODE) {
557: case T: /* typematic */
558: kb_cmd2(K_KEY_T_CMD, i);
559: break;
560: case M: /* make only */
561: kb_cmd2(K_KEY_M_CMD, i);
562: break;
563: case MB: /* make/break */
564: kb_cmd2(K_KEY_MB_CMD, i);
565: break;
566: case TMB: /* typematic make/break */
567: break; /* this is the default */
568: default:
569: printf("kb: bad key mode\n");
570: }
571: }
572: updleds();
573: kb_cmd2(K_SCANCODE_CMD, 3); /* select set 3 */
574: kb_cmd(K_ENABLE_CMD); /* start scanning */
575: /*
576: * The following code disables translation from the on-board
577: * keyboard/aux controller. Without disabling translation, the
578: * received scan codes still look like code set 1 codes even
579: * though we put the keyboard controller in scan code set 3.
580: * Yes, this is progress....
581: */
582: #if 0
583: while (inb(KBSTS_CMD) & STS_IBUF_FULL)
584: ;
585: outb(KBSTS_CMD, C_READ_CMD); /* read controller cmd byte */
586: while (!(inb(KBSTS_CMD) & STS_OBUF_FULL))
587: ;
588: cmd_byte = inb(KBDATA);
589: KBDEBUG2(" cmd_byte=%x", cmd_byte);
590: #endif
591: timeout = KBTIMEOUT;
592: s = sphi();
593: while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0)
594: ;
595: outb(KBSTS_CMD, C_WRITE_CMD); /* write controller cmd byte */
596: for (timeout = 50; --timeout > 0;)
597: ;
598: timeout = KBTIMEOUT;
599: while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0)
600: ;
601: outb(KBDATA, KBCMDBYTE); /* turn off translation */
602: timeout = KBTIMEOUT;
603: while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0)
604: ;
605: spl(s);
606: #if DEBUG || 1
607: kb_cmd2(K_SCANCODE_CMD, 0); /* query s.c. mode */
608: #endif
609: ++table_loaded;
610: PRINTV("... TIOCSETKBT\n");
611: }
612:
613: /*
614: * Get the in-core keyboard mapping table and pass it to the user.
615: */
616: isgettable(vec)
617: char *vec;
618: {
619: #ifdef _I386
620: KBDEBUG(" TIOCGETKBT");
621: kucopy(kb, vec, sizeof(kb));
622: #else
623: register unsigned i;
624: register faddr_t faddr; /* address of keyboard table */
625: static KBTBL this_key; /* current key from kbd table */
626:
627: KBDEBUG(" TIOCGETKBT");
628: faddr = kbsegp->s_faddr;
629: for (i = 0; i < MAX_KEYS; ++i) {
630: fkcopy(faddr, &this_key, sizeof(this_key));
631: kucopy(&this_key, vec, sizeof(this_key));
632: faddr += sizeof(this_key);
633: vec += sizeof(this_key);
634: }
635: #endif
636: }
637:
638:
639: /*
640: * Set and receive the function keys.
641: */
642: isfunction(c, v)
643: int c;
644: FNKEY *v;
645: {
646: register unsigned char *cp;
647: register unsigned i;
648: unsigned char numkeys = 0;
649:
650: if (c == TIOCGETF) {
651: KBDEBUG(" TIOCGETF");
652: if (!fk_loaded)
653: u.u_error = EINVAL;
654: else
655: kucopy(fnkeys, v, fklength); /* copy ours to user */
656: } else { /* TIOCSETF */
657: /*
658: * If we had a previous function key arena, free it up.
659: * Since we don't know how large the function key arena will
660: * be, we must size it in the user data space prior to
661: * (re)kalloc()'ing it. This is ugly, but a helluva lot better
662: * than the old driver which used a hard coded limit of 150!
663: */
664: KBDEBUG(" TIOCSETF");
665: fk_loaded = 0;
666: if (fnkeys != (FNKEY *)0)
667: kfree(fnkeys); /* free old arena */
668: if (funkeyp != NULL)
669: kfree(funkeyp); /* free old ptr array */
670: ukcopy(&v->k_nfkeys, &numkeys, sizeof(numkeys));
671: fklength = sizeof(FNKEY);
672: cp = v->k_fnval;
673: for (i = 0; i < numkeys; i++) {
674: do {
675: ++fklength;
676: } while (getubd(cp++) != DELIM);
677: }
678: fnkeys = (FNKEY *)kalloc(fklength);
679: funkeyp = (unsigned char **)kalloc(numkeys * sizeof(char *));
680: if (fnkeys == (FNKEY *)0 || funkeyp == NULL) {
681: if (fnkeys != (FNKEY *)0) {
682: kfree(fnkeys);
683: fnkeys = 0;
684: }
685: if (funkeyp != NULL) {
686: kfree(funkeyp);
687: funkeyp = 0;
688: }
689: u.u_error = ENOMEM;
690: return;
691: }
692: cp = fnkeys->k_fnval; /* point to Fn ... */
693: v = v->k_fnval; /* ... key arena */
694: for (i = 0; i < numkeys; i++) {
695: funkeyp[i] = cp; /* save pointer */
696: while ((*cp++ = getubd(v++)) != DELIM) /* copy key */
697: ;
698: }
699: fnkeys->k_nfkeys = numkeys;
700: fk_loaded = 1;
701: }
702: }
703:
704:
705: /*
706: * Poll routine.
707: */
708: ispoll(dev, ev, msec)
709: dev_t dev;
710: int ev;
711: int msec;
712: {
713: register TTY *tp = vttty[vtindex(dev)];
714:
715: return ttpoll(tp, ev, msec);
716: }
717:
718: /*
719: * Receive interrupt.
720: */
721: #define K_E0ESC 0xE0 /* Swan Keyboard, Strange Escape Byte */
722:
723: isrint()
724: {
725: register unsigned c;
726: register unsigned r;
727: static char keyup;
728: #if SWANFIX
729: static char e0esc;
730: #endif
731:
732: /*
733: * Schedule raw input handler if not already active.
734: */
735: if (!isbusy) {
736: defer(isbatch, vttty[vtactive]);
737: isbusy = 1;
738: }
739:
740: /*
741: * Pull character from the data
742: * port. Pulse the KBFLAG in the control
743: * port to reset the data buffer.
744: */
745: r = inb(KBDATA) & 0xFF;
746: c = inb(KBCTRL);
747: outb(KBCTRL, c|KBFLAG);
748: outb(KBCTRL, c);
749:
750: /*
751: * check returned value from keyboard to see if it's a command
752: * or status back to us. If not, it we assume that it's a key code.
753: */
754: KBDEBUG2("\nintr(%x) ", r);
755: switch (r) {
756: case K_BREAK:
757: keyup = 1; /* key going up */
758: break;
759: case K_ECHO_R:
760: case K_BAT_OK:
761: break; /* very nice, but ignored */
762: case K_BAT_BAD:
763: printf("kb: keyboard BAT failed\n");
764: break;
765: case K_RESEND:
766: KBDEBUG("\nkb: request to resend command\n");
767: outb(KBDATA, prev_cmd);
768: break;
769: case K_OVERRUN_23:
770: printf("kb: keyboard buffer overrun\n");
771: break;
772: case K_ACK:
773: /*
774: * we received an ACKnowledgement from the keyboard.
775: * advance the state machine and continue.
776: */
777: KBDEBUG(" ACK ");
778: switch (kbstate) {
779: case KB_IDLE: /* shouldn't happen */
780: printf("vtnkb: ACK while idle ");
781: break;
782: case KB_SINGLE: /* done with 1-byte command */
783: case KB_DOUBLE_2: /* done w/ 2nd of 2-byte cmd */
784: kbstate = KB_IDLE;
785: wakeup(&kbstate);
786: break;
787: case KB_DOUBLE_1:
788: kbstate = KB_DOUBLE_2;
789: outb(KBDATA, cmd2);
790: break;
791: default:
792: printf("kb: bad kbstate %d\n", kbstate);
793: break;
794: }
795: break;
796: #if SWANFIX
797: case K_E0ESC:
798: if (VTSWAN) {
799: e0esc = 1;
800: break;
801: }
802: #endif
803: default:
804: #if SWANFIX
805: process_key(r, keyup, e0esc);
806: e0esc = 0;
807: #else
808: process_key(r, keyup);
809: #endif
810: keyup = 0;
811: }
812: }
813:
814: /*
815: * Process a key given its scan code and direction.
816: *
817: * In this table driven version of the keyboard driver, we trade off the
818: * code complexity associated with all the black magic that used to be
819: * performed on a per-key basis with the increased memory requirements
820: * associated with the table driven approach.
821: */
822: #if SWANFIX 1
823: process_key(key, up, e0esc)
824: unsigned key;
825: char up, e0esc;
826: #else
827: process_key(key, up)
828: unsigned key;
829: int up;
830: #endif
831: {
832: register unsigned char *cp;
833: KBTBL key_vals; /* table values for this key */
834: unsigned val;
835: unsigned char flags;
836: register TTY *tp = vttty[vtactive];
837: VTDATA *vp = vtdata[vtactive];
838:
839: KBDEBUG3(" proc(%x %s)", key, (up ? "up" : "down"));
840: if (!table_loaded)
841: return; /* throw away key */
842: #ifdef _I386
843: /*
844: * It's ugly but, if e0esc, then we use the ALT_GR field to point
845: * at the actual table entry we want. We weren't really using the
846: * ALT_GR field anyway. Trouble remapping shift keys because
847: * loader requires all entries to be identical, thus ALT_GR is
848: * by default being used.
849: */
850:
851: #if SWANFIX
852: if ( VTSWAN && e0esc && !(kb[key].k_flags&S) )
853: key = kb[key].k_val[ALT_GR]; /* Ugly kludge */
854: #endif
855: key_vals = kb[key];
856: #else
857: fkcopy(kbsegp->s_faddr + (key * sizeof(KBTBL)),
858: &key_vals, sizeof(key_vals));
859: #endif
860: if (key_vals.k_key != key) /* empty entry */
861: return;
862: flags = key_vals.k_flags;
863:
864: if (flags & S) { /* some shift/lock key ? */
865: switch (key_vals.k_val[BASE]) {
866: case caps:
867: case num:
868: if (!up) {
869: shift ^= (1 << key_vals.k_val[BASE]);
870: updleds2();
871: }
872: break;
873: case scroll:
874: if (!up) {
875: shift ^= (1 << key_vals.k_val[BASE]);
876: updleds2();
877: if (!(tp->t_sgttyb.sg_flags&RAWIN)) {
878: if (tp->t_flags & T_STOP) {
879: isin(tp->t_tchars.t_startc);
880: } else {
881: isin(tp->t_tchars.t_stopc);
882: }
883: }
884: }
885: break;
886: default:
887: if (up)
888: shift &= ~(1 << key_vals.k_val[BASE]);
889: else
890: shift |= (1 << key_vals.k_val[BASE]);
891: break;
892: }
893: /*
894: * Calculate the shift index based upon the state of
895: * the shift and lock keys.
896: */
897: sh_index = BASE; /* default condition */
898: if (shift & (1 << altgr))
899: sh_index = ALT_GR;
900: else {
901: if (shift & ((1 << lalt)|(1 << ralt)))
902: sh_index |= ALT;
903: if (shift & ((1 << lctrl)|(1 << rctrl)))
904: sh_index |= CTRL;
905: if (shift & ((1 << lshift)|(1 << rshift)))
906: sh_index |= SHIFT;
907: }
908: T_CON(2, printf("shift=%x sh_index=%d\n", shift, sh_index));
909: return;
910: } /* if (flags & S) */
911:
912: /*
913: * If the key has no value in the current
914: * shift state, the key is just tossed away.
915: */
916: if (up || key_vals.k_val[sh_index] == none)
917: return;
918:
919: if (((flags & C) && (shift & (1 << caps)))
920: || ((flags & N) && (shift & (1 << num))))
921: val = key_vals.k_val[sh_index^SHIFT];
922: else
923: val = key_vals.k_val[sh_index];
924:
925: /*
926: * Check for function key or special key implemented as
927: * a function key (reboot == f0, tab and back-tab, etc).
928: */
929: if (flags & F) {
930: PRINTV( "<{F%d}>", val );
931: if (VTKEY(val)) {
932: T_CON(4,
933: printf( "<{F%d !!}>\b\b\b\b\b\b\b\b\b\b", val));
934: defer( isvtswitch, val );
935: return;
936: }
937: /* If the tty is not open, ignore it */
938: if( !tp->t_open )
939: return;
940: #if GREEKFIX
941: if (VTGREEK && val == fgk) {
942: ToggleGreek();
943: return;
944: }
945: #endif /* GREEKFIX */
946: if (val == 0 && !up && KBBOOT)
947: boot();
948: if (!fk_loaded || val >= fnkeys->k_nfkeys)
949: return;
950: if ((cp = funkeyp[val]) == NULL) /* has a value? */
951: return;
952: while (*cp != DELIM)
953: isin(*cp++); /* queue up Fn key value */
954: return;
955: }
956:
957: /*
958: * Normal key processing.
959: */
960: /* If the tty is not open, ignore it */
961: #if GREEKFIX
962: if( tp->t_open )
963: if (VTGREEK) {
964: if (ToGreek(&val))
965: isin(val);
966: } else
967: isin(val);
968: #else
969: if( tp->t_open )
970: isin(val); /* send the char */
971: #endif /* GREEKFIX */
972: }
973:
974: /**
975: *
976: * void
977: * ismmfunc(c) -- process keyboard related output escape sequences
978: * char c;
979: */
980: void
981: ismmfunc(c)
982: register int c;
983: {
984:
985: switch (c) {
986: case 't': /* Enter numlock */
987: shift |= (1 << num);
988: updleds(); /* update LED status */
989: break;
990: case 'u': /* Leave numlock */
991: shift &= ~(1 << num);
992: updleds(); /* update LED status */
993: break;
994: case '=': /* Enter alternate keypad -- ignored */
995: case '>': /* Exit alternate keypad -- ignored */
996: break;
997: case 'c': /* Reset terminal */
998: islock = 0;
999: break;
1000: }
1001: }
1002:
1003: /**
1004: *
1005: * void
1006: * isin(c) -- append character to raw input silo
1007: * char c;
1008: */
1009: static
1010: isin(c)
1011: register int c;
1012: {
1013: int cache_it = 1;
1014: TTY * tp = vttty[vtactive];
1015: void ttstart();
1016:
1017: /*
1018: * If using software incoming flow control, process and
1019: * discard t_stopc and t_startc.
1020: */
1021: if (ISIXON) {
1022: #if _I386
1023: if (ISSTART || (ISIXANY && ISXSTOP)) {
1024: tp->t_flags &= ~(T_STOP | T_XSTOP);
1025: ttstart(tp);
1026: cache_it = 0;
1027: } else if (ISSTOP) {
1028: if ((tp->t_flags&T_STOP) == 0)
1029: tp->t_flags |= (T_STOP | T_XSTOP);
1030: cache_it = 0;
1031: }
1032: #else
1033: if (ISSTOP) {
1034: if ((tp->t_flags&T_STOP) == 0)
1035: tp->t_flags |= T_STOP;
1036: cache_it = 0;
1037: }
1038: if (ISSTART) {
1039: tp->t_flags &= ~T_STOP;
1040: ttstart(tp);
1041: cache_it = 0;
1042: }
1043: #endif
1044: }
1045:
1046: /*
1047: * Cache received character.
1048: */
1049: if (cache_it) {
1050: in_silo.si_buf[ in_silo.si_ix ] = c;
1051:
1052: if (++in_silo.si_ix >= sizeof(in_silo.si_buf))
1053: in_silo.si_ix = 0;
1054: }
1055: }
1056:
1057: /**
1058: *
1059: * void
1060: * isbatch() -- raw input conversion routine
1061: *
1062: * Action: Enable the video display.
1063: * Canonize the raw input silo.
1064: *
1065: * Notes: isbatch() was scheduled as a deferred process by isrint().
1066: */
1067: static void
1068: isbatch(tp)
1069: register TTY * tp;
1070: {
1071: register int c;
1072: static int lastc;
1073: VTDATA *vp = tp->t_ddp;
1074:
1075: /*
1076: * Ensure video display is enabled.
1077: */
1078: if( vp->vmm_visible ) {
1079: mm_von(vp);
1080: }
1081: isbusy = 0;
1082:
1083: /*
1084: * Process all cached characters.
1085: */
1086: while (in_silo.si_ix != in_silo.si_ox) {
1087: /*
1088: * Get next cached char.
1089: */
1090: c = in_silo.si_buf[ in_silo.si_ox ];
1091:
1092: if (in_silo.si_ox >= sizeof(in_silo.si_buf) - 1)
1093: in_silo.si_ox = 0;
1094: else
1095: in_silo.si_ox++;
1096:
1097: if ((islock == 0) || ISINTR || ISQUIT) {
1098: ttin(tp, c);
1099: } else if ((c == 'b') && (lastc == '\033')) {
1100: islock = 0;
1101: ttin(tp, lastc);
1102: ttin(tp, c);
1103: } else if ((c == 'c') && (lastc == '\033')) {
1104: ttin(tp, lastc);
1105: ttin(tp, c);
1106: } else
1107: putchar('\007');
1108: lastc = c;
1109: }
1110: }
1111:
1112: /*
1113: * update the keyboard status LEDS.
1114: * we chose the shift/lock key positions so this would be easy.
1115: * this flavor of routine is called while processing a system call on
1116: * behalf of the user.
1117: */
1118: updleds()
1119: {
1120: kb_cmd2(K_LED_CMD, (shift >> 1) & 0x7);
1121: }
1122:
1123: /*
1124: * same as above, but callable from interrupt routines and other places
1125: * which cannot sleep() waiting for the state machine to go idle.
1126: */
1127: updleds2()
1128: {
1129: register timeout;
1130: register int s;
1131:
1132: timeout = KBTIMEOUT;
1133: s = sphi();
1134: while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL))
1135: ;
1136: kbstate = KB_DOUBLE_1;
1137: cmd2 = (shift >> 1) & 0x7;
1138: prev_cmd = K_LED_CMD;
1139: outb(KBDATA, K_LED_CMD);
1140: spl(s);
1141: }
1142:
1143: /*
1144: * unlock the scroll in case an interrupt character is received
1145: */
1146: kbunscroll()
1147: {
1148: shift &= ~(1 << scroll);
1149: updleds();
1150: }
1151:
1152: /*
1153: * ship a single byte command to the keyboard
1154: */
1155: kb_cmd(cmd)
1156: unsigned cmd;
1157: {
1158: register int timeout;
1159: register int s;
1160:
1161: s = sphi();
1162: KBDEBUG2(" kb_cmd(%x)", cmd);
1163: while (kbstate != KB_IDLE)
1164: #ifdef _I386
1165: x_sleep(&kbstate, pritty, slpriSigCatch, "kb a");
1166: #else
1167: v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "kb a");
1168: #endif
1169: kbstate = KB_SINGLE;
1170: timeout = KBTIMEOUT;
1171: while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL))
1172: ;
1173: if (!timeout)
1174: printf("kb: command timeout\n");
1175: else {
1176: outb(KBDATA, cmd);
1177: while (kbstate != KB_IDLE)
1178: #ifdef _I386
1179: x_sleep(&kbstate, pritty, slpriSigCatch, "kb b");
1180: #else
1181: v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "kb b");
1182: #endif
1183: }
1184: spl(s);
1185: }
1186:
1187: /*
1188: * ship a two byte command to the keyboard
1189: */
1190: kb_cmd2(cmd, arg)
1191: unsigned cmd, arg;
1192: {
1193: register int timeout;
1194: register int s;
1195:
1196: s = sphi();
1197: KBDEBUG3(" kb_cmd2(%x, %x)", cmd, arg);
1198: while (kbstate != KB_IDLE)
1199: #ifdef _I386
1200: x_sleep(&kbstate, pritty, slpriSigCatch, "kb c");
1201: #else
1202: v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "kb c");
1203: #endif
1204: kbstate = KB_DOUBLE_1;
1205: cmd2 = arg;
1206: prev_cmd = cmd;
1207: timeout = KBTIMEOUT;
1208: while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL))
1209: ;
1210: if (!timeout)
1211: printf("kb: command timeout\n");
1212: else {
1213: outb(KBDATA, cmd);
1214: while (kbstate != KB_IDLE)
1215: #ifdef _I386
1216: x_sleep(&kbstate, pritty, slpriSigCatch, "kb d");
1217: #else
1218: v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "kb d");
1219: #endif
1220: }
1221: spl(s);
1222: }
1223:
1224: /*
1225: ==============================================================================
1226: ==============================================================================
1227: */
1228:
1229: int
1230: VTttyinit(i)
1231: int i;
1232: {
1233: TTY *tp;
1234:
1235: /*
1236: * get pointer to TTY structure from kernal memory space
1237: */
1238: if( (tp = vttty[i] = (TTY *)kalloc(sizeof (TTY))) == NULL )
1239: return(0);
1240: PRINTV( " vttty[%d]: @%x, ", i, tp );
1241:
1242: #if FAR_TTY
1243: /*
1244: * get pointers to the buffers pointed to by the TTY structure
1245: * from user memory space
1246: */
1247: tp->t_buffer = salloc( (fsize_t)NCIB+2*SI_BUFSIZ, SFSYST|SFNSWP );
1248: tp->t_ib = 0;
1249: tp->t_rawin.si_buf = NCIB;
1250: tp->t_rawout.si_buf = NCIB+SI_BUFSIZ;
1251: #endif
1252: tp->t_param = NULL;
1253: tp->t_start = &mmstart;
1254:
1255: #ifndef _I386
1256: #if VT_MAJOR == KB_MAJOR
1257: tp->t_cs_sel = 0;
1258: #else
1259: tp->t_cs_sel = cs_sel();
1260: #endif
1261: #endif
1262: tp->t_ddp = vtdata[i];
1263: PRINTV( "data @%lx\n", tp->t_ddp );
1264: return(1);
1265: }
1266:
1267: vtdatainit(vp)
1268: VTDATA *vp;
1269: {
1270: #ifndef _I386
1271: VT_FARSEG vt_farseg;
1272: #endif
1273: /*
1274: * vtdata init - vmm part
1275: */
1276: vp->vmm_invis = -1; /* cursor invisible */
1277:
1278: #ifdef _I386
1279: vp->vt_buffer = kalloc( TEXTBLOCK );
1280: vp->vmm_seg = vp->vmm_mseg = ds_sel();
1281: vp->vmm_off = vp->vmm_moff = vp->vt_buffer;
1282: #else
1283: vp->vt_buffer = salloc ( (fsize_t)TEXTBLOCK, SFSYST|SFNSWP|SFHIGH );
1284: vp->vmm_seg = vp->vmm_mseg = FP_SEG( vp->vt_buffer->vt_faddr );
1285: vp->vmm_off = vp->vmm_moff = FP_OFF( vp->vt_buffer->vt_faddr );
1286: #endif
1287: PRINTV( "vt@%x init index %d,%d), seg %x, off %x\n",
1288: vp, vp->vt_ind, vp->vmm_mseg, vp->vmm_moff );
1289: /*
1290: * vtdata init - vnkb part
1291: */
1292: /* Make the first memory block active, if present */
1293: vp->vnkb_lastc = 0;
1294: vp->vnkb_fnkeys = 0;
1295: vp->vnkb_funkeyp = 0;
1296: vp->vnkb_fk_loaded = 0; /* no Fn keys yet */
1297: }
1298:
1299: /*
1300: * Given device number, return index for vtdata[], vttty[], etc.
1301: *
1302: * Major number must be VT_MAJOR for CPU to get here.
1303: *
1304: * Minor Number Index Value
1305: * ----- ------ ----- -----
1306: * 0000 0000 vtactive ... device (2,0) is the active screen
1307: * 0000 0001 0
1308: * 0000 0010 1
1309: * 0000 0011 2
1310: * ....
1311: * 0000 1111 14
1312: *
1313: * 0100 xxxx xxxx ... color devices only
1314: * 0101 xxxx xxxx - (# of color devices found) ... monochrome only
1315: *
1316: * Return value is in range 0 to vtcount-1 for valid minor numbers,
1317: * -1 for invalid minor numbers.
1318: */
1319: int
1320: vtindex( dev )
1321: dev_t dev;
1322: {
1323: register int ret = -1;
1324:
1325: if ( dev & VT_PHYSICAL ) {
1326: int hw = ( dev >> 4 ) & 3;
1327: int hw_index = dev & 0x0F;
1328:
1329: if( hw_index < vtHWtable[hw]->found )
1330: ret = vtHWtable[hw]->start + hw_index;
1331: } else {
1332: int lg_index = dev & 0x0F;
1333:
1334: if (lg_index == 0)
1335: ret = vtactive;
1336: if (lg_index > 0 && lg_index <= vtcount )
1337: ret = lg_index-1;
1338: }
1339: if (ret >= 0)
1340: ret %= vtcount;
1341: else
1342: PRINTV( "vtindex: (%x) %d. invalid !\n", dev, ret );
1343: return ret;
1344: }
1345:
1346: /*
1347: *
1348: * void
1349: * isvtswitch() -- deferred virtual terminal switch
1350: *
1351: * Action: - save current shift key status
1352: * - determine new active virtual terminal
1353: * - deactivate shift key status of the current virtual terminal
1354: * - deactivate current virtual terminal
1355: * - activate shift key status of the new virtual terminal with
1356: * the previously saved shift key status
1357: * - activate new virtual terminal
1358: *
1359: * Notes: isvtswitch() was scheduled as a deferred process by
1360: * process_key() which is a function called by isrint().
1361: */
1362: void
1363: isvtswitch(key_val)
1364: {
1365: register int new_index, i;
1366: unsigned lockshift, nolockshift;
1367: VTDATA *vp = vtdata[vtactive];
1368: VTDATA *vp_old, *vp_new;
1369: static int vtprevious;
1370:
1371: T_CON(2, printf("old shift=%x sh_index=%d\n", shift, sh_index));
1372: lockshift = shift & ((1<<scroll)|(1<<num)|(1<<caps));
1373: nolockshift = shift & ~((1<<scroll)|(1<<num)|(1<<caps));
1374:
1375: PRINTV( "F%d: %d", key_val, vtactive );
1376: #if 0
1377: if( key_val == VTKEY_HOME )
1378: new_index = 0;
1379: else if( key_val == VTKEY_NEXT ) {
1380: new_index = vtactive;
1381: for( i = 0; i < vtcount; ++i ) {
1382: new_index = ++new_index % vtcount;
1383: if( vttty[new_index]->t_open )
1384: break;
1385: }
1386: } else {
1387: new_index = vtindex(vtkey_to_dev(key_val));
1388: if( new_index < 0) {
1389: putchar( '\007' );
1390: return;
1391: }
1392: }
1393: #else
1394: switch (key_val) {
1395: case VTKEY_HOME:
1396: new_index = 0;
1397: break;
1398: case VTKEY_NEXT:
1399: new_index = vtactive;
1400: for( i = 0; i < vtcount; ++i ) {
1401: new_index = ++new_index % vtcount;
1402: if( vttty[new_index]->t_open )
1403: break;
1404: }
1405: break;
1406: case VTKEY_PREV:
1407: new_index = vtactive;
1408: for( i = 0; i < vtcount; ++i ) {
1409: new_index = (--new_index+vtcount) % vtcount;
1410: if( vttty[new_index]->t_open )
1411: break;
1412: }
1413: break;
1414: case VTKEY_TOGL:
1415: new_index = vtprevious;
1416: break;
1417: default:
1418: new_index = vtindex(vtkey_to_dev(key_val));
1419: if( new_index < 0) {
1420: putchar( '\007' );
1421: return;
1422: }
1423: }
1424: #endif
1425: T_CON(8, printf("%d->%d ", vtactive, new_index));
1426: if( new_index == vtactive )
1427: return;
1428:
1429: /* Save which locking shift states are in effect. */
1430:
1431: vp_old = vtdata[vtactive];
1432: vp_new = vtdata[new_index];
1433:
1434: vp_old->vnkb_shift = lockshift;
1435: vtdeactivate(vp_new, vp_old); /* deactivate old virtual terminal */
1436:
1437: /* Restore shift lock state, append current momentary shift state. */
1438: shift = vp_new->vnkb_shift | nolockshift;
1439: T_CON(2, printf("new shift=%x sh_index=%d\n", shift, sh_index));
1440: vtactivate(vp_new); /* activate new virtual terminal */
1441: updterminal(new_index);
1442: vtprevious = vtactive;
1443: vtactive = new_index; /* update vtactive */
1444: }
1445:
1446: vtdeactivate(vp_new, vp_old)
1447: register VTDATA *vp_new, *vp_old;
1448: {
1449: register i;
1450: VTDATA *vpi;
1451:
1452: /* store old screen contents in memory segment */
1453: FFCOPY( vp_old->vmm_voff, vp_old->vmm_vseg,
1454: vp_old->vmm_moff, vp_old->vmm_mseg, TEXTBLOCK );
1455:
1456: /*
1457: * if changing to another screen on same video board
1458: * for all screens on same board as new screen
1459: * deactivate, but don't update
1460: * else - changing to a screen on different board
1461: * for all screens NOT on same board as new screen
1462: * deactivate, but don't update
1463: */
1464: if ( vp_old->vmm_port == vp_new->vmm_port ) {
1465: T_CON(8, printf("deactivate on %x ", vp_new->vmm_port));
1466: for (i = 0; i < vtcount; ++i) {
1467: vpi = vtdata[i];
1468: if ( vpi->vmm_port == vp_new->vmm_port ) {
1469: /* deactivate, but don't update */
1470: vpi->vmm_invis = ~0;
1471: vpi->vmm_visible = VNKB_FALSE;
1472: vpi->vmm_seg = vpi->vmm_mseg;
1473: vpi->vmm_off = vpi->vmm_moff;
1474: if( vpi->vmm_seg == 0 )
1475: printf( "[1]vpi->vmm_seg = 0\n" );
1476: PRINTV( "vt.back %d. seg %x off %x\n", i,
1477: vpi->vmm_seg, vpi->vmm_off );
1478: }
1479: }
1480: } else {
1481: T_CON(8, printf("deactivate %x->%x ",
1482: vp_old->vmm_port, vp_new->vmm_port));
1483: for (i = 0; i < vtcount; ++i) {
1484: vpi = vtdata[i];
1485: if ( (vpi->vmm_port != vp_new->vmm_port)
1486: && (vpi->vmm_invis == 0) ) {
1487: /* update, but don't deactivate */
1488: vpi->vmm_invis = ~0;
1489: updscreen(i);
1490: }
1491: }
1492: }
1493: }
1494:
1495: vtactivate(vp)
1496: VTDATA *vp;
1497: {
1498: register VTDATA *vpi;
1499: register i;
1500:
1501: /*
1502: * copy from screen contents from heap segment to video memory
1503: * only if necessary
1504: */
1505: if ( vp->vmm_visible == VNKB_FALSE )
1506: FFCOPY( vp->vmm_moff, vp->vmm_mseg,
1507: vp->vmm_voff, vp->vmm_vseg, TEXTBLOCK );
1508:
1509: for (i = 0; i < vtcount; ++i) {
1510: vpi = vtdata[i];
1511: if (vpi->vmm_port == vp->vmm_port) {
1512: vpi->vmm_invis = -1;
1513: vpi->vmm_visible = VNKB_FALSE;
1514: vpi->vmm_seg = vpi->vmm_mseg;
1515: vpi->vmm_off = vpi->vmm_moff;
1516: if( vpi->vmm_seg == 0 )
1517: printf( "[2]vpi->vmm_seg = 0\n" );
1518: PRINTV( "vt.back seg %x off %x\n",
1519: vpi->vmm_seg, vpi->vmm_off );
1520: }
1521: }
1522: /*
1523: * Set new active terminal
1524: */
1525: vp->vmm_invis = 0;
1526: vp->vmm_visible = VNKB_TRUE;
1527: vp->vmm_seg = vp->vmm_vseg;
1528: vp->vmm_off = vp->vmm_voff;
1529: if( vp->vmm_seg == 0 )
1530: printf( "vp->vmm_seg = 0\n" );
1531: }
1532:
1533: /*
1534: * update the terminal to match vtactive
1535: */
1536: updterminal(index)
1537: int index;
1538: {
1539: updscreen(index);
1540: updleds2();
1541: }
1542:
1543: #undef si
1544: asmdump( cs, ds, es, di, si, bp, sp, bx, dx, cx, i, ip, ax )
1545: int cs, ds, es, di, si, bp, sp, bx, dx, cx, i, ip, ax;
1546: {
1547: if( vt_verbose < 2 )
1548: return;
1549:
1550: printf( "asmdump %d: es %x, ds %x, cs:ip %x:%x\n", i, es, ds, cs, ip );
1551: printf( " ax %x, bx %x, cx %x, dx %x\n", ax, bx, cx, dx );
1552: printf( " di %x, si %x, bp %x, sp %d\n", di, si, bp, sp );
1553: #if USING_RS232
1554: if( vt_verbose > 2 )
1555: getchar();
1556: #endif
1557: }
1558:
1559: vtdataprint( vp )
1560: register VTDATA *vp;
1561: {
1562: if( vt_verbose < 2 )
1563: return;
1564:
1565: printf( "VTDATA: @%x, esc %x, func %x()\n",
1566: vp, vp->vmm_esc, vp->vmm_func );
1567: printf( " hw: port %x, seg %x, off %x\n",
1568: vp->vmm_port, vp->vmm_vseg, vp->vmm_voff );
1569: printf( " memory: size %x, seg %x, off %x\n",
1570: 0/*vp->vmm_size*/, vp->vmm_mseg, vp->vmm_moff );
1571: printf( " cursor: seg %x, off %x, visible %d\n",
1572: vp->vmm_seg, vp->vmm_off, !vp->vmm_invis );
1573: printf( " row %d, col %d = offset %d.\n",
1574: vp->vmm_rowl, vp->vmm_col, vp->vmm_pos );
1575: printf( " saved row %d, col %d\n",
1576: vp->vmm_srow, vp->vmm_scol );
1577: printf( " screen: visible %d, attr %x, wrap %d, slow %d\n",
1578: vp->vmm_visible, vp->vmm_attr, vp->vmm_wrap, vp->vmm_slow );
1579: printf( " row base %d, end %d, limit %d\n",
1580: vp->vmm_brow, vp->vmm_erow, vp->vmm_lrow );
1581: printf( " row initial base %d, initial end %d\n",
1582: vp->vmm_ibrow, vp->vmm_ierow );
1583: #if USING_RS232
1584: if( vt_verbose > 2 )
1585: getchar();
1586: #endif
1587: }
1588:
1589: FFCOPY( src_off, src_seg, dst_off, dst_seg, count )
1590: {
1591: register i;
1592:
1593: #if 0
1594: i = ffcopy( src_off, src_seg, dst_off, dst_seg, count );
1595: #else
1596: for( i = 0; i < count; i += 2 ) {
1597: register word = ffword( src_off, src_seg );
1598: sfword( dst_off, dst_seg, word );
1599: src_off += 2;
1600: dst_off += 2;
1601: }
1602: #endif
1603: return i;
1604: }
1605:
1606: /*
1607: * Given a function key number (e.g. vt0),
1608: * return the corresponding minor device number.
1609: *
1610: * Assume valid key number (VTKEY(fnum) is true) by the time we get here.
1611: */
1612: int
1613: vtkey_to_dev(fnum)
1614: int fnum;
1615: {
1616: if (fnum >=vt0 && fnum <= vt15)
1617: return fnum-vt0+1;
1618: if (fnum >=color0 && fnum <= color15)
1619: return (fnum-color0)|(VT_PHYSICAL|VT_HW_COLOR);
1620: if (fnum >=mono0 && fnum <= mono15)
1621: return (fnum-mono0)|(VT_PHYSICAL|VT_HW_MONO);
1622: printf("vtkey_to_dev(%d)! ", fnum);
1623: return 0;
1624: }
1625:
1626: #if GREEKFIX
1627: /*
1628: * ToggleGreek() must be called every time Alt+Enter is pressed.
1629: * It toggles the "InGreek" flag and resets all others.
1630: *
1631: * ToGreek(unsigned *) returns FALSE if val is a dead key (Greek
1632: * accent key) that must NOT be processed, TRUE otherwise.
1633: */
1634:
1635: static int InGreek=0;
1636: static int Tonos=0;
1637: static int Dialytika=0;
1638:
1639: static int UpperG[26] = {
1640: 128,129,150,131,132,148,130,134,136,141,137,138,139,
1641: 140,142,143,58,144,145,146,135,151,145,149,147,133};
1642:
1643: static int LowerG[26] = {
1644: 152,153,175,155,156,173,154,158,160,165,161,162,163,
1645: 164,166,167,59,168,169,171,159,224,170,174,172,157};
1646:
1647: static int VoyelG[7] = {152,156,158,160,166,172,224};
1648: static int TonedG[7] = {225,226,227,229,230,231,233};
1649:
1650: void
1651: ToggleGreek()
1652: {
1653: InGreek ^= 1;
1654: Tonos = 0;
1655: Dialytika = 0;
1656: return;
1657: }
1658:
1659: int
1660: ToGreek(ip)
1661: unsigned *ip;
1662: {
1663: unsigned i,j;
1664:
1665: i = *ip;
1666:
1667: /* If Not Greek exit */
1668: if(!InGreek)
1669: return 1;
1670:
1671: /* Capture dead keys */
1672: if(i == ';') {
1673: Tonos ^= 1;
1674: return 0;
1675: }
1676:
1677: if(i == ':') {
1678: Dialytika ^= 1;
1679: return 0;
1680: }
1681:
1682: /* Check if character translation needed */
1683: if ((i >= 'A') && (i <= 'Z'))
1684: i = UpperG[i - 'A'];
1685: else if ((i >= 'a') && (i <= 'z'))
1686: i = LowerG[i - 'a'];
1687: else
1688: return 1;
1689:
1690: /* Check if any accent has to be added */
1691: if (Tonos) {
1692: Tonos = 0;
1693: for(j = 0;j < 7;j++)
1694: if (i == VoyelG[j]) {
1695: i = TonedG[j];
1696: break;
1697: }
1698: } else if (Dialytika) {
1699: Dialytika=0;
1700: if (i == 160)
1701: i = 228;
1702: else if (i == 172)
1703: i = 232;
1704: }
1705:
1706: /* Exit point for translated characters */
1707: *(ip) = i;
1708: return 1;
1709: }
1710:
1711: #endif /* GREEKFIX */
1712: /* End of nkb.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.