1 /*-
2 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 static char sccsid[] = "@(#)api.c 4.5 (Berkeley) 4/26/91";
36 #endif /* not lint */
37
38 /*
39 * This file implements the API used in the PC version.
40 */
41
42 #include <stdio.h>
43
44 #include "api.h"
45 #include "../general/general.h"
46
47 #include "../api/disp_asc.h"
48
49 #include "screen.h"
50 #include "hostctlr.h"
51 #include "oia.h"
52
53 #include "../general/globals.h"
54
55 int apitrace = 0;
56
57 /*
58 * Some defines for things we use internally.
59 */
60
61 #define PS_SESSION_ID 23
62 #define BUF_SESSION_ID 0
63
64 /*
65 * General utility routines.
66 */
67
68 #if defined(MSDOS)
69
70 #if defined(LINT_ARGS)
71 static void movetous(char *, int, int, int);
72 static void movetothem(int, int, char *, int);
73 #endif /* defined(LINT_ARGS) */
74
75 #define access_api(foo,length,copyin) (foo)
76 #define unaccess_api(foo,goo,length,copyout)
77
78 static void
movetous(parms,es,di,length)79 movetous(parms, es, di, length)
80 char *parms;
81 int es, di;
82 int length;
83 {
84 char far *farparms = parms;
85
86 movedata(es, di, FP_SEG(farparms), FP_OFF(farparms), length);
87 if (apitrace) {
88 Dump('(', parms, length);
89 }
90 }
91
92 static void
movetothem(es,di,parms,length)93 movetothem(es, di, parms, length)
94 int es, di;
95 char *parms;
96 int length;
97 {
98 char far *farparms = parms;
99
100 movedata(FP_SEG(farparms), FP_OFF(farparms), es, di, length);
101 if (apitrace) {
102 Dump(')', parms, length);
103 }
104 }
105 #endif /* defined(MSDOS) */
106
107 #if defined(unix)
108 extern char *access_api();
109 extern void movetous(), movetothem(), unaccess_api();
110 #endif /* defined(unix) */
111
112
113 /*
114 * Supervisor Services.
115 */
116
117 static void
name_resolution(regs,sregs)118 name_resolution(regs, sregs)
119 union REGS *regs;
120 struct SREGS *sregs;
121 {
122 NameResolveParms parms;
123
124 movetous((char *) &parms, sregs->es, regs->x.di, sizeof parms);
125
126 regs->h.cl = 0;
127 if (memcmp((char *)&parms, NAME_SESSMGR, sizeof parms.gate_name) == 0) {
128 regs->x.dx = GATE_SESSMGR;
129 } else if (memcmp((char *)&parms, NAME_KEYBOARD,
130 sizeof parms.gate_name) == 0) {
131 regs->x.dx = GATE_KEYBOARD;
132 } else if (memcmp((char *)&parms, NAME_COPY, sizeof parms.gate_name) == 0) {
133 regs->x.dx = GATE_COPY;
134 } else if (memcmp((char *)&parms, NAME_OIAM, sizeof parms.gate_name) == 0) {
135 regs->x.dx = GATE_OIAM;
136 } else {
137 regs->h.cl = 0x2e; /* Name not found */
138 }
139 regs->h.ch = 0x12;
140 regs->h.bh = 7;
141 }
142
143 /*
144 * Session Information Services.
145 */
146
147 static void
query_session_id(regs,sregs)148 query_session_id(regs, sregs)
149 union REGS *regs;
150 struct SREGS *sregs;
151 {
152 QuerySessionIdParms parms;
153
154 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
155
156 if ((parms.rc != 0) || (parms.function_id != 0)) {
157 parms.rc = 0x0c;
158 } else if (parms.option_code != 0x01) {
159 parms.rc = 0x0d; /* Invalid option code */
160 #ifdef NOTOBS
161 } else if ((parms.data_code != 0x45) && (parms.data_code != 0x00/*OBS*/)) {
162 parms.rc = 0x0b;
163 #endif /* NOTOBS */
164 } else {
165 NameArray list;
166
167 movetous((char *)&list, FP_SEG(parms.name_array),
168 FP_OFF(parms.name_array), sizeof list);
169 if ((list.length < 14) || (list.length > 170)) {
170 parms.rc = 0x12;
171 } else {
172 list.number_matching_session = 1;
173 list.name_array_element.short_name = parms.data_code;
174 list.name_array_element.type = TYPE_DFT;
175 list.name_array_element.session_id = PS_SESSION_ID;
176 memcpy(list.name_array_element.long_name, "ONLYSESS",
177 sizeof list.name_array_element.long_name);
178 movetothem(FP_SEG(parms.name_array),
179 FP_OFF(parms.name_array), (char *)&list, sizeof list);
180 parms.rc = 0;
181 }
182 }
183 parms.function_id = 0x6b;
184 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
185 }
186
187 static void
query_session_parameters(regs,sregs)188 query_session_parameters(regs, sregs)
189 union REGS *regs;
190 struct SREGS *sregs;
191 {
192 QuerySessionParametersParms parms;
193
194 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
195
196 if ((parms.rc !=0) || (parms.function_id != 0)) {
197 parms.rc = 0x0c;
198 } else if (parms.session_id != PS_SESSION_ID) {
199 parms.rc = 0x02;
200 } else {
201 parms.rc = 0;
202 parms.session_type = TYPE_DFT;
203 parms.session_characteristics = 0; /* Neither EAB nor PSS */
204 parms.rows = MaxNumberLines;
205 parms.columns = MaxNumberColumns;
206 parms.presentation_space = 0;
207 }
208 parms.function_id = 0x6b;
209 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
210 }
211
212 static void
query_session_cursor(regs,sregs)213 query_session_cursor(regs, sregs)
214 union REGS *regs;
215 struct SREGS *sregs;
216 {
217 QuerySessionCursorParms parms;
218
219 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
220
221 if ((parms.rc != 0) || (parms.function_id != 0)) {
222 parms.rc = 0x0c;
223 } else if (parms.session_id != PS_SESSION_ID) {
224 parms.rc = 0x02;
225 } else {
226 parms.rc = 0;
227 parms.cursor_type = CURSOR_BLINKING; /* XXX what is inhibited? */
228 parms.row_address = ScreenLine(CursorAddress);
229 parms.column_address = ScreenLineOffset(CursorAddress);
230 }
231
232 parms.function_id = 0x6b;
233 movetothem(sregs->es, regs->x.di, (char *) &parms, sizeof parms);
234 }
235
236 /*
237 * Keyboard Services.
238 */
239
240
241 static void
connect_to_keyboard(regs,sregs)242 connect_to_keyboard(regs, sregs)
243 union REGS *regs;
244 struct SREGS *sregs;
245 {
246 ConnectToKeyboardParms parms;
247
248 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
249
250 if ((parms.rc != 0) || (parms.function_id != 0)) {
251 parms.rc = 0x0c;
252 } else if (parms.session_id != PS_SESSION_ID) {
253 parms.rc = 0x02;
254 } else if (parms.intercept_options != 0) {
255 parms.rc = 0x01;
256 } else {
257 parms.rc = 0;
258 parms.first_connection_identifier = 0;
259 }
260 parms.function_id = 0x62;
261
262 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
263 }
264
265 static void
disconnect_from_keyboard(regs,sregs)266 disconnect_from_keyboard(regs, sregs)
267 union REGS *regs;
268 struct SREGS *sregs;
269 {
270 DisconnectFromKeyboardParms parms;
271
272 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
273
274 if ((parms.rc != 0) || (parms.function_id != 0)) {
275 parms.rc = 0x0c;
276 } else if (parms.session_id != PS_SESSION_ID) {
277 parms.rc = 0x02;
278 } else if (parms.connectors_task_id != 0) {
279 parms.rc = 04; /* XXX */
280 } else {
281 parms.rc = 0;
282 }
283 parms.function_id = 0x62;
284
285 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
286 }
287
288 static void
write_keystroke(regs,sregs)289 write_keystroke(regs, sregs)
290 union REGS *regs;
291 struct SREGS *sregs;
292 {
293 WriteKeystrokeParms parms;
294
295 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
296
297 if ((parms.rc != 0) || (parms.function_id != 0)) {
298 parms.rc = 0x0c;
299 } else if (parms.session_id != PS_SESSION_ID) {
300 parms.rc = 0x02;
301 } else if (parms.connectors_task_id != 0) {
302 parms.rc = 0x04;
303 } else {
304 parms.number_of_keys_sent = 0;
305 parms.rc = 0;
306 if (parms.options == OPTION_SINGLE_KEYSTROKE) {
307 KeystrokeEntry *entry = &parms.keystroke_specifier.keystroke_entry;
308
309 if (AcceptKeystroke(entry->scancode, entry->shift_state) == 0) {
310 parms.rc = 0x10; /* XXX needs 0x12 too! */
311 }
312 parms.number_of_keys_sent++;
313 } else if (parms.options == OPTION_MULTIPLE_KEYSTROKES) {
314 KeystrokeList
315 list,
316 far *atlist = parms.keystroke_specifier.keystroke_list;
317 KeystrokeEntry
318 entry[10], /* 10 at a time */
319 *ourentry,
320 far *theirentry;
321 int
322 todo;
323
324 movetous((char *)&list, FP_SEG(atlist),
325 FP_OFF(atlist), sizeof *atlist);
326 todo = list.length/2;
327 ourentry = entry+(highestof(entry)+1);
328 theirentry = &atlist->keystrokes;
329
330 while (todo) {
331 if (ourentry > &entry[highestof(entry)]) {
332 int thistime;
333
334 thistime = todo;
335 if (thistime > numberof(entry)) {
336 thistime = numberof(entry);
337 }
338 movetous((char *)entry, FP_SEG(theirentry),
339 FP_OFF(theirentry), thistime*sizeof *theirentry);
340 theirentry += thistime;
341 ourentry = entry;
342 }
343 if (AcceptKeystroke(ourentry->scancode,
344 ourentry->shift_state) == 0) {
345 parms.rc = 0x10; /* XXX needs 0x12 too! */
346 break;
347 }
348 parms.number_of_keys_sent++;
349 ourentry++;
350 todo--;
351 }
352 } else {
353 parms.rc = 0x01;
354 }
355 }
356 parms.function_id = 0x62;
357
358 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
359 /* XXX */
360 }
361
362
363 static void
disable_input(regs,sregs)364 disable_input(regs, sregs)
365 union REGS *regs;
366 struct SREGS *sregs;
367 {
368 DisableInputParms parms;
369
370 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
371
372 if ((parms.rc != 0) || (parms.function_id != 0)) {
373 parms.rc = 0x0c;
374 } else if (parms.session_id != PS_SESSION_ID) {
375 parms.rc = 0x02;
376 } else if (parms.connectors_task_id != 0) {
377 parms.rc = 0x04;
378 } else {
379 SetOiaApiInhibit(&OperatorInformationArea);
380 parms.rc = 0;
381 }
382 parms.function_id = 0x62;
383
384 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
385 }
386
387 static void
enable_input(regs,sregs)388 enable_input(regs, sregs)
389 union REGS *regs;
390 struct SREGS *sregs;
391 {
392 EnableInputParms parms;
393
394 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
395
396 if ((parms.rc != 0) || (parms.function_id != 0)) {
397 parms.rc = 0x0c;
398 } else if (parms.session_id != PS_SESSION_ID) {
399 parms.rc = 0x02;
400 } else if (parms.connectors_task_id != 0) {
401 parms.rc = 0x04;
402 } else {
403 ResetOiaApiInhibit(&OperatorInformationArea);
404 parms.rc = 0;
405 }
406 parms.function_id = 0x62;
407
408 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
409 }
410
411 /*
412 * Copy Services.
413 */
414
415 static
copy_subroutine(target,source,parms,what_is_user,length)416 copy_subroutine(target, source, parms, what_is_user, length)
417 BufferDescriptor *target, *source;
418 CopyStringParms *parms;
419 int what_is_user;
420 #define USER_IS_TARGET 0
421 #define USER_IS_SOURCE 1
422 {
423 #define TARGET_NO_EAB 1
424 #define SOURCE_NO_EAB 2
425 #define TARGET_PC 4
426 #define SOURCE_PC 8
427 #define NO_FIELD_ATTRIBUTES 16
428 int needtodo = 0;
429 int access_length;
430 char far *input;
431 char far *output;
432 char far *access_pointer;
433
434 if ((target->characteristics^source->characteristics)
435 &CHARACTERISTIC_EAB) {
436 if (target->characteristics&CHARACTERISTIC_EAB) {
437 needtodo |= TARGET_NO_EAB; /* Need to bump for EAB in target */
438 } else {
439 needtodo |= SOURCE_NO_EAB; /* Need to bump for EAB in source */
440 }
441 }
442 if (target->session_type != source->session_type) {
443 if (target->session_type == TYPE_PC) {
444 needtodo |= TARGET_PC; /* scan codes to PC */
445 } else {
446 needtodo |= SOURCE_PC; /* PC to scan codes */
447 }
448 }
449 if ((parms->copy_mode©_MODE_FIELD_ATTRIBUTES) == 0) {
450 needtodo |= NO_FIELD_ATTRIBUTES;
451 }
452 access_length = length;
453 if (what_is_user == USER_IS_TARGET) {
454 if (target->characteristics&CHARACTERISTIC_EAB) {
455 access_length *= 2;
456 }
457 input = (char far *) &Host[source->begin];
458 access_pointer = target->buffer;
459 output = access_api(target->buffer, access_length, 0);
460 } else {
461 if (source->characteristics&CHARACTERISTIC_EAB) {
462 access_length *= 2;
463 }
464 access_pointer = source->buffer;
465 input = access_api(source->buffer, access_length, 1);
466 output = (char far *) &Host[target->begin];
467 }
468 while (length--) {
469 if (needtodo&TARGET_PC) {
470 *output++ = disp_asc[*input++];
471 } else if (needtodo&SOURCE_PC) {
472 *output++ = asc_disp[*input++];
473 } else {
474 *output++ = *input++;
475 }
476 if (needtodo&TARGET_NO_EAB) {
477 input++;
478 } else if (needtodo&SOURCE_NO_EAB) {
479 *output++ = 0; /* Should figure out good EAB? */
480 }
481 }
482 if (what_is_user == USER_IS_TARGET) {
483 unaccess_api(target->buffer, access_pointer, access_length, 1);
484 } else {
485 unaccess_api(source->buffer, access_pointer, access_length, 0);
486 }
487 }
488
489
490 static void
copy_string(regs,sregs)491 copy_string(regs, sregs)
492 union REGS *regs;
493 struct SREGS *sregs;
494 {
495 CopyStringParms parms;
496 BufferDescriptor *target = &parms.target, *source = &parms.source;
497 int length;
498
499 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
500
501 length = 1+parms.source_end-source->begin;
502 if ((parms.rc != 0) || (parms.function_id !=0)) {
503 parms.rc = 0x0c;
504 } else if (target->session_id == BUF_SESSION_ID) { /* Target is buffer */
505 if (source->session_id != PS_SESSION_ID) { /* A no-no */
506 parms.rc = 0x2;
507 } else {
508 if ((source->begin < 0) || (source->begin > highestof(Host))) {
509 parms.rc = 0x06; /* invalid source definition */
510 } else {
511 if ((source->begin+length) > highestof(Host)) {
512 length = highestof(Host)-source->begin;
513 parms.rc = 0x0f; /* Truncate */
514 }
515 if ((source->characteristics == target->characteristics) &&
516 (source->session_type == target->session_type)) {
517 if (source->characteristics&CHARACTERISTIC_EAB) {
518 length *= 2;
519 }
520 movetothem(FP_SEG(target->buffer),
521 FP_OFF(target->buffer),
522 (char *)&Host[source->begin], length);
523 } else {
524 copy_subroutine(target, source, &parms,
525 USER_IS_TARGET, length);
526 }
527 }
528 }
529 } else if (source->session_id != BUF_SESSION_ID) {
530 parms.rc = 0xd;
531 } else {
532 /* Send to presentation space (3270 buffer) */
533 if ((target->begin < 0) || (target->begin > highestof(Host))) {
534 parms.rc = 0x07; /* invalid target definition */
535 } if (!UnLocked) {
536 parms.rc = 0x03; /* Keyboard locked */
537 } else if (parms.copy_mode != 0) {
538 parms.rc = 0x0f; /* Copy of field attr's not allowed */
539 } else if (IsProtected(target->begin) || /* Make sure no protected */
540 (WhereAttrByte(target->begin) != /* in range */
541 WhereAttrByte(target->begin+length-1))) {
542 parms.rc = 0x0e; /* Attempt to write in protected */
543 } else {
544 if ((target->begin+length) > highestof(Host)) {
545 length = highestof(Host)-target->begin;
546 parms.rc = 0x0f; /* Truncate */
547 }
548 TurnOnMdt(target->begin); /* Things have changed */
549 if ((source->characteristics == target->characteristics) &&
550 (source->session_type == target->session_type)) {
551 if (source->characteristics&CHARACTERISTIC_EAB) {
552 length *= 2;
553 }
554 movetous((char *)&Host[target->begin],
555 FP_SEG(source->buffer),
556 FP_OFF(source->buffer), length);
557 } else {
558 copy_subroutine(target, source, &parms, USER_IS_SOURCE, length);
559 }
560 }
561 }
562 parms.function_id = 0x64;
563 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
564 }
565
566
567 /*
568 * Operator Information Area Services.
569 */
570
571 static void
read_oia_group(regs,sregs)572 read_oia_group(regs, sregs)
573 union REGS *regs;
574 struct SREGS *sregs;
575 {
576 ReadOiaGroupParms parms;
577
578 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
579
580 if ((parms.rc != 0) || (parms.function_id != 0)) {
581 parms.rc = 0x0c;
582 } else if (parms.session_id != PS_SESSION_ID) {
583 parms.rc = 0x02;
584 } else {
585 int group = parms.oia_group_number;
586 char *from;
587 int size;
588
589 if ((group != API_OIA_ALL_GROUPS) &&
590 ((group > API_OIA_LAST_LEGAL_GROUP) || (group < 0))) {
591 } else {
592 if (group == API_OIA_ALL_GROUPS) {
593 size = API_OIA_BYTES_ALL_GROUPS;
594 from = (char *)&OperatorInformationArea;
595 } else if (group == API_OIA_INPUT_INHIBITED) {
596 size = sizeof OperatorInformationArea.input_inhibited;
597 from = (char *)&OperatorInformationArea.input_inhibited[0];
598 } else {
599 size = 1;
600 from = ((char *)&OperatorInformationArea)+group;
601 }
602 movetothem(FP_SEG(parms.oia_buffer), FP_OFF(parms.oia_buffer),
603 from, size);
604 }
605 }
606 parms.function_id = 0x6d;
607 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
608 }
609
610 /*ARGSUSED*/
611 static void
unknown_op(regs,sregs)612 unknown_op(regs, sregs)
613 union REGS *regs;
614 struct SREGS *sregs;
615 {
616 regs->h.ch = 0x12;
617 regs->h.cl = 0x05;
618 }
619
620
621 handle_api(regs, sregs)
622 union REGS *regs;
623 struct SREGS *sregs;
624 {
625 /*
626 * Do we need to log this transaction?
627 */
628 if (apitrace) {
629 Dump('<', (char *)regs, sizeof *regs);
630 Dump('<', (char *)sregs, sizeof *sregs);
631 }
632 if (regs->h.ah == NAME_RESOLUTION) {
633 name_resolution(regs, sregs);
634 #if defined(unix)
635 } else if (regs->h.ah == PS_OR_OIA_MODIFIED) {
636 while ((oia_modified == 0) && (ps_modified == 0)) {
637 (void) Scheduler(1);
638 }
639 oia_modified = ps_modified = 0;
640 #endif /* defined(unix) */
641 } else if (regs->h.ah != 0x09) {
642 regs->h.ch = 0x12;
643 regs->h.cl = 0x0f; /* XXX Invalid environmental access */
644 } else if (regs->x.bx != 0x8020) {
645 regs->h.ch = 0x12;
646 regs->h.cl = 0x08; /* XXX Invalid wait specified */
647 } else if (regs->h.ch != 0) {
648 regs->x.cx = 0x1206; /* XXX Invalid priority */
649 } else {
650 switch (regs->x.dx) {
651 case GATE_SESSMGR:
652 switch (regs->h.al) {
653 case QUERY_SESSION_ID:
654 if (regs->h.cl != 0) {
655 regs->x.cx = 0x1206;
656 } else {
657 regs->x.cx = 0x1200;
658 query_session_id(regs, sregs);
659 }
660 break;
661 case QUERY_SESSION_PARAMETERS:
662 if (regs->h.cl != 0) {
663 regs->x.cx = 0x1206;
664 } else {
665 regs->x.cx = 0x1200;
666 query_session_parameters(regs, sregs);
667 }
668 break;
669 case QUERY_SESSION_CURSOR:
670 if ((regs->h.cl != 0xff) && (regs->h.cl != 0x00/*OBS*/)) {
671 regs->x.cx = 0x1206;
672 } else {
673 regs->x.cx = 0x1200;
674 query_session_cursor(regs, sregs);
675 }
676 break;
677 default:
678 unknown_op(regs, sregs);
679 break;
680 }
681 break;
682 case GATE_KEYBOARD:
683 if (regs->h.cl != 00) {
684 regs->x.cx = 0x1206;
685 } else {
686 regs->x.cx = 0x1200;
687 switch (regs->h.al) {
688 case CONNECT_TO_KEYBOARD:
689 connect_to_keyboard(regs, sregs);
690 break;
691 case DISABLE_INPUT:
692 disable_input(regs, sregs);
693 break;
694 case WRITE_KEYSTROKE:
695 write_keystroke(regs, sregs);
696 break;
697 case ENABLE_INPUT:
698 enable_input(regs, sregs);
699 break;
700 case DISCONNECT_FROM_KEYBOARD:
701 disconnect_from_keyboard(regs, sregs);
702 break;
703 default:
704 unknown_op(regs, sregs);
705 break;
706 }
707 }
708 break;
709 case GATE_COPY:
710 if (regs->h.cl != 0xff) {
711 regs->x.cx = 0x1206;
712 } else {
713 regs->x.cx = 0x1200;
714 switch (regs->h.al) {
715 case COPY_STRING:
716 copy_string(regs, sregs);
717 break;
718 default:
719 unknown_op(regs, sregs);
720 break;
721 }
722 }
723 break;
724 case GATE_OIAM:
725 if (regs->h.cl != 0xff) {
726 regs->x.cx = 0x1206;
727 } else {
728 regs->x.cx = 0x1200;
729 switch (regs->h.al) {
730 case READ_OIA_GROUP:
731 read_oia_group(regs, sregs);
732 break;
733 default:
734 unknown_op(regs, sregs);
735 break;
736 }
737 }
738 break;
739 default:
740 regs->h.ch = 0x12;
741 regs->h.cl = 0x34; /* Invalid GATE entry */
742 break;
743 }
744 }
745 /*
746 * Do we need to log this transaction?
747 */
748 if (apitrace) {
749 Dump('>', (char *)regs, sizeof *regs);
750 Dump('>', (char *)sregs, sizeof *sregs);
751 #ifdef MSDOS
752 { char buf[10]; gets(buf); }
753 #endif /* MSDOS */
754 }
755 }
756