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