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