add Berkeley specific header
[unix-history] / usr / src / usr.bin / tn3270 / ctlr / api.c
CommitLineData
992de934 1/*
ee01fcaa
KB
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
992de934 4 *
ee01fcaa
KB
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of California at Berkeley. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
992de934
GM
11 */
12
13#ifndef lint
ee01fcaa
KB
14static char sccsid[] = "@(#)api.c 3.2 (Berkeley) %G%";
15#endif /* not lint */
992de934 16
abd201e9
GM
17/*
18 * This file implements the API used in the PC version.
19 */
20
21#include <stdio.h>
abd201e9 22
abd201e9 23#include "api.h"
d4967272 24#include "../general/general.h"
abd201e9 25
4718d085 26#include "../api/disp_asc.h"
6376f1f2 27
4718d085
GM
28#include "screen.h"
29#include "oia.h"
92f7501a 30
d4967272 31#include "../general/globals.h"
65c9fa1f 32
92f7501a
GM
33/*
34 * General utility routines.
35 */
36
37#if defined(MSDOS)
ffff8f6a
GM
38
39#if defined(LINT_ARGS)
40static void movetous(char *, int, int, int);
41static void movetothem(int, int, char *, int);
42#endif /* defined(LINT_ARGS) */
92f7501a 43
ec5b8360
GM
44#define access_api(foo,length,copyin) (foo)
45#define unaccess_api(foo,goo,length,copyout)
6376f1f2 46
92f7501a
GM
47static void
48movetous(parms, es, di, length)
49char *parms;
ffff8f6a 50int es, di, length;
92f7501a 51{
ffff8f6a 52 char far *farparms = parms;
92f7501a 53
ffff8f6a 54 movedata(es, di, (int) FP_SEG(farparms), (int) FP_OFF(farparms), length);
92f7501a
GM
55}
56
57static void
ffff8f6a
GM
58movetothem(es, di, parms, length)
59int es, di;
60char *parms;
61int length;
92f7501a 62{
ffff8f6a 63 char far *farparms = parms;
92f7501a 64
ffff8f6a 65 movedata((int) FP_SEG(farparms), (int) FP_OFF(farparms), es, di, length);
92f7501a
GM
66}
67#endif /* defined(MSDOS) */
68
6376f1f2 69#if defined(unix)
4604a66c 70extern char *access_api(), *unaccess_api();
6376f1f2 71#endif /* defined(unix) */
92f7501a 72
4604a66c 73
abd201e9
GM
74/*
75 * Supervisor Services.
76 */
77
78static void
92f7501a 79name_resolution(regs, sregs)
abd201e9
GM
80union REGS *regs;
81struct SREGS *sregs;
82{
86057566 83 NameResolveParms parms;
e75c75e7 84
86057566 85 movetous((char *) &parms, sregs->es, regs->x.di, sizeof parms);
e75c75e7
GM
86
87 regs->h.cl = 0;
92f7501a 88 if (memcmp((char *)&parms, NAME_SESSMGR, sizeof parms.gate_name) == 0) {
e75c75e7 89 regs->x.dx = GATE_SESSMGR;
92f7501a
GM
90 } else if (memcmp((char *)&parms, NAME_KEYBOARD,
91 sizeof parms.gate_name) == 0) {
e75c75e7 92 regs->x.dx = GATE_KEYBOARD;
92f7501a 93 } else if (memcmp((char *)&parms, NAME_COPY, sizeof parms.gate_name) == 0) {
e75c75e7 94 regs->x.dx = GATE_COPY;
92f7501a 95 } else if (memcmp((char *)&parms, NAME_OIAM, sizeof parms.gate_name) == 0) {
e75c75e7
GM
96 regs->x.dx = GATE_OIAM;
97 } else {
98 regs->h.cl = 0x2e; /* Name not found */
99 }
100 regs->h.ch = 0x12;
101 regs->h.bh = 7;
abd201e9
GM
102}
103
104/*
105 * Session Information Services.
106 */
107
108static void
109query_session_id(regs, sregs)
110union REGS *regs;
111struct SREGS *sregs;
112{
86057566 113 QuerySessionIdParms parms;
e75c75e7 114
86057566 115 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
e75c75e7 116
ffff8f6a
GM
117 if ((parms.rc != 0) || (parms.function_id != 0)) {
118 parms.rc = 0x0c;
119 } else if (parms.option_code != 0x01) {
120 parms.rc = 0x0d; /* Invalid option code */
86057566 121 } else if (parms.data_code != 0x45) {
ffff8f6a 122 parms.rc = 0x0b;
e75c75e7 123 } else {
65c9fa1f 124 NameArray list;
86057566
GM
125 NameArrayElement element;
126
127 movetous((char *)&list, FP_SEG(parms.name_array),
92f7501a 128 FP_OFF(parms.name_array), sizeof list);
65c9fa1f 129 if ((list.length < 14) || (list.length > 170)) {
86057566 130 parms.rc = 0x12;
e75c75e7 131 } else {
86057566
GM
132 list.number_matching_session = 1;
133 list.name_array_element.short_name = parms.data_code;
134 list.name_array_element.type = TYPE_DFT;
135 list.name_array_element.session_id = 23;
136 memcpy(list.name_array_element.long_name, "ONLYSESS",
137 sizeof list.name_array_element.long_name);
138 movetothem(FP_SEG(parms.name_array),
92f7501a 139 FP_OFF(parms.name_array), (char *)&list, sizeof list);
86057566 140 parms.rc = 0;
e75c75e7
GM
141 }
142 }
ffff8f6a 143 parms.function_id = 0x6b;
86057566 144 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
abd201e9
GM
145}
146
147static void
148query_session_parameters(regs, sregs)
149union REGS *regs;
150struct SREGS *sregs;
151{
86057566
GM
152 QuerySessionParametersParms parms;
153
154 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
155
65c9fa1f 156 if ((parms.rc !=0) || (parms.function_id != 0)) {
ffff8f6a
GM
157 parms.rc = 0x0c;
158 } else if (parms.session_id != 23) {
159 parms.rc = 0x02;
86057566 160 } else {
ffff8f6a 161 parms.rc = 0;
86057566
GM
162 parms.session_type = TYPE_DFT;
163 parms.session_characteristics = 0; /* Neither EAB nor PSS */
164 parms.rows = MaxNumberLines;
165 parms.columns = MaxNumberColumns;
166 parms.presentation_space = 0;
167 }
ffff8f6a 168 parms.function_id = 0x6b;
65c9fa1f 169 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
abd201e9
GM
170}
171
172static void
173query_session_cursor(regs, sregs)
174union REGS *regs;
175struct SREGS *sregs;
176{
86057566
GM
177 QuerySessionCursorParms parms;
178
179 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
180
181 if ((parms.rc != 0) || (parms.function_id != 0)) {
182 parms.rc = 0x0c;
183 } else if (parms.session_id != 23) {
184 parms.rc = 0x02;
185 } else {
186 parms.rc = 0;
86057566
GM
187 parms.cursor_type = CURSOR_BLINKING; /* XXX what is inhibited? */
188 parms.row_address = ScreenLine(CursorAddress);
189 parms.column_address = ScreenLineOffset(CursorAddress);
190 }
191
ffff8f6a
GM
192 parms.function_id = 0x6b;
193 movetothem(sregs->es, regs->x.di, (char *) &parms, sizeof parms);
abd201e9
GM
194}
195
196/*
197 * Keyboard Services.
198 */
199
200
201static void
202connect_to_keyboard(regs, sregs)
203union REGS *regs;
204struct SREGS *sregs;
205{
86057566
GM
206 ConnectToKeyboardParms parms;
207
d4967272 208 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
86057566
GM
209
210 if ((parms.rc != 0) || (parms.function_id != 0)) {
211 parms.rc = 0x0c;
212 } else if (parms.session_id != 23) {
213 parms.rc = 0x02;
214 } else if (parms.intercept_options != 0) {
215 parms.rc = 0x01;
216 } else {
217 parms.rc = 0;
218 parms.first_connection_identifier = 0;
219 }
220 parms.function_id = 0x62;
221
222 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
abd201e9
GM
223}
224
225static void
86057566 226disconnect_from_keyboard(regs, sregs)
abd201e9
GM
227union REGS *regs;
228struct SREGS *sregs;
229{
86057566
GM
230 DisconnectFromKeyboardParms parms;
231
232 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
233
234 if ((parms.rc != 0) || (parms.function_id != 0)) {
235 parms.rc = 0x0c;
236 } else if (parms.session_id != 23) {
237 parms.rc = 0x02;
238 } else if (parms.connectors_task_id != 0) {
239 parms.rc = 04; /* XXX */
240 } else {
241 parms.rc = 0;
242 }
243 parms.function_id = 0x62;
244
245 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
abd201e9
GM
246}
247
248static void
249write_keystroke(regs, sregs)
250union REGS *regs;
251struct SREGS *sregs;
252{
cbdd0b03
GM
253 WriteKeystrokeParms parms;
254
255 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
256
257 if ((parms.rc != 0) || (parms.function_id != 0)) {
258 parms.rc = 0x0c;
259 } else if (parms.session_id != 23) {
260 parms.rc = 0x02;
261 } else if (parms.connectors_task_id != 0) {
262 parms.rc = 0x04;
263 } else {
264 parms.number_of_keys_sent = 0;
265 parms.rc = 0;
266 if (parms.options == OPTION_SINGLE_KEYSTROKE) {
267 KeystrokeEntry *entry = &parms.keystroke_specifier.keystroke_entry;
268
269 if (AcceptKeystroke(entry->scancode, entry->shift_state) == 0) {
270 parms.rc = 0x10; /* XXX needs 0x12 too! */
271 }
272 parms.number_of_keys_sent++;
273 } else if (parms.options == OPTION_MULTIPLE_KEYSTROKES) {
274 KeystrokeList
275 list,
276 far *atlist = parms.keystroke_specifier.keystroke_list;
277 KeystrokeEntry
278 entry[10], /* 10 at a time */
279 *ourentry,
280 far *theirentry;
281 int
282 todo;
283
284 movetous((char *)&list, FP_SEG(atlist),
285 FP_OFF(atlist), sizeof *atlist);
286 todo = list.length/2;
287 ourentry = entry+(highestof(entry)+1);
288
289 while (todo) {
290 if (ourentry > &entry[highestof(entry)]) {
291 int thistime;
292
293 thistime = todo;
294 if (thistime > numberof(entry)) {
295 thistime = numberof(entry);
296 }
297 movetous((char *)entry, FP_SEG(theirentry),
298 FP_OFF(theirentry), thistime*sizeof *theirentry);
299 theirentry += thistime;
300 ourentry = entry;
301 }
302 if (AcceptKeystroke(ourentry->scancode,
303 ourentry->shift_state) == 0) {
304 parms.rc = 0x10; /* XXX needs 0x12 too! */
305 break;
306 }
307 parms.number_of_keys_sent++;
308 ourentry++;
309 todo--;
310 }
311 } else {
312 parms.rc = 0x01;
313 }
314 }
315 parms.function_id = 0x62;
316
317 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
86057566
GM
318/* XXX */
319}
320
321
322static void
323disable_input(regs, sregs)
324union REGS *regs;
325struct SREGS *sregs;
326{
327 DisableInputParms parms;
328
329 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
330
331 if ((parms.rc != 0) || (parms.function_id != 0)) {
332 parms.rc = 0x0c;
333 } else if (parms.session_id != 23) {
334 parms.rc = 0x02;
335 } else if (parms.connectors_task_id != 0) {
336 parms.rc = 0x04;
337 } else {
ffff8f6a 338 SetOiaApiInhibit(&OperatorInformationArea);
86057566
GM
339 parms.rc = 0;
340 }
341 parms.function_id = 0x62;
342
343 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
abd201e9
GM
344}
345
346static void
347enable_input(regs, sregs)
348union REGS *regs;
349struct SREGS *sregs;
350{
86057566
GM
351 EnableInputParms parms;
352
353 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
354
355 if ((parms.rc != 0) || (parms.function_id != 0)) {
356 parms.rc = 0x0c;
357 } else if (parms.session_id != 23) {
358 parms.rc = 0x02;
359 } else if (parms.connectors_task_id != 0) {
360 parms.rc = 0x04;
361 } else {
ffff8f6a 362 ResetOiaApiInhibit(&OperatorInformationArea);
86057566
GM
363 parms.rc = 0;
364 }
365 parms.function_id = 0x62;
366
367 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
abd201e9
GM
368}
369
370/*
371 * Copy Services.
372 */
373
ec5b8360
GM
374static
375copy_subroutine(target, source, parms, what_is_user, length)
6376f1f2
GM
376BufferDescriptor *target, *source;
377CopyStringParms *parms;
378int what_is_user;
379#define USER_IS_TARGET 0
380#define USER_IS_SOURCE 1
381{
382#define TARGET_NO_EAB 1
383#define SOURCE_NO_EAB 2
384#define TARGET_PC 4
385#define SOURCE_PC 8
386#define NO_FIELD_ATTRIBUTES 16
387 int needtodo = 0;
6376f1f2
GM
388 int access_length;
389 char far *input;
390 char far *output;
391 char far *access_pointer;
392
393 if ((target->characteristics^source->characteristics)
394 &CHARACTERISTIC_EAB) {
395 if (target->characteristics&CHARACTERISTIC_EAB) {
396 needtodo |= TARGET_NO_EAB; /* Need to bump for EAB in target */
397 } else {
398 needtodo |= SOURCE_NO_EAB; /* Need to bump for EAB in source */
399 }
400 }
401 if (target->session_type != source->session_type) {
402 if (target->session_type == TYPE_PC) {
403 needtodo |= TARGET_PC; /* scan codes to PC */
404 } else {
405 needtodo |= SOURCE_PC; /* PC to scan codes */
406 }
407 }
408 if ((parms->copy_mode&COPY_MODE_FIELD_ATTRIBUTES) == 0) {
409 needtodo |= NO_FIELD_ATTRIBUTES;
410 }
ec5b8360 411 access_length = length;
6376f1f2
GM
412 if (what_is_user == USER_IS_TARGET) {
413 if (target->characteristics&CHARACTERISTIC_EAB) {
414 access_length *= 2;
415 }
416 input = (char far *) &Host[source->begin];
417 access_pointer = target->buffer;
ec5b8360 418 output = access_api(target->buffer, access_length, 0);
6376f1f2
GM
419 } else {
420 if (source->characteristics&CHARACTERISTIC_EAB) {
421 access_length *= 2;
422 }
423 access_pointer = source->buffer;
ec5b8360 424 input = access_api(source->buffer, access_length, 1);
6376f1f2
GM
425 output = (char far *) &Host[target->begin];
426 }
427 while (length--) {
428 if (needtodo&TARGET_PC) {
429 *output++ = disp_asc[*input++];
430 } else if (needtodo&SOURCE_PC) {
431 *output++ = asc_disp[*input++];
432 } else {
433 *output++ = *input++;
434 }
435 if (needtodo&TARGET_NO_EAB) {
436 *input++;
437 } else if (needtodo&SOURCE_NO_EAB) {
438 *output++ = 0; /* Should figure out good EAB? */
439 }
440 }
441 if (what_is_user == USER_IS_TARGET) {
ec5b8360 442 unaccess_api(target->buffer, access_pointer, access_length, 1);
6376f1f2 443 } else {
ec5b8360 444 unaccess_api(source->buffer, access_pointer, access_length, 0);
6376f1f2
GM
445 }
446}
447
448
abd201e9 449static void
86057566 450copy_string(regs, sregs)
abd201e9
GM
451union REGS *regs;
452struct SREGS *sregs;
453{
86057566 454 CopyStringParms parms;
6376f1f2
GM
455 BufferDescriptor *target = &parms.target, *source = &parms.source;
456 int length;
86057566
GM
457
458 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
abd201e9 459
ec5b8360 460 length = 1+parms.source_end-source->begin;
86057566
GM
461 if ((parms.rc != 0) || (parms.function_id !=0)) {
462 parms.rc = 0x0c;
6376f1f2
GM
463 } else if (target->session_id == 0) { /* Target is buffer */
464 if (source->session_id != 23) { /* A no-no */
465 parms.rc = 0x2;
466 } else {
ec5b8360
GM
467 if ((source->begin < 0) || (source->begin > highestof(Host))) {
468 parms.rc = 0x06; /* invalid source definition */
469 } else {
470 if ((source->begin+length) > highestof(Host)) {
471 length = highestof(Host)-source->begin;
472 parms.rc = 0x0f; /* Truncate */
473 }
474 if ((source->characteristics == target->characteristics) &&
6376f1f2 475 (source->session_type == target->session_type)) {
ec5b8360
GM
476 if (source->characteristics&CHARACTERISTIC_EAB) {
477 length *= 2;
478 }
479 movetothem( (int) FP_SEG(target->buffer),
480 (int) FP_OFF(target->buffer),
481 (char *)&Host[source->begin], length);
482 } else {
483 copy_subroutine(target, source, &parms,
484 USER_IS_TARGET, length);
6376f1f2 485 }
6376f1f2
GM
486 }
487 }
488 } else if (source->session_id != 0) {
489 parms.rc = 0xd;
490 } else {
ec5b8360
GM
491 if ((target->begin < 0) || (source->begin > highestof(Host))) {
492 parms.rc = 0x07; /* invalid source definition */
6376f1f2 493 } else {
ec5b8360
GM
494 if ((source->begin+length) > highestof(Host)) {
495 length = highestof(Host)-source->begin;
496 parms.rc = 0x0f; /* Truncate */
497 }
498 if ((source->characteristics == target->characteristics) &&
499 (source->session_type == target->session_type)) {
500 if (source->characteristics&CHARACTERISTIC_EAB) {
501 length *= 2;
502 }
503 movetous((char *)&Host[target->begin],
504 (int) FP_SEG(source->buffer),
505 (int) FP_OFF(source->buffer), length);
506 } else {
507 copy_subroutine(target, source, &parms, USER_IS_SOURCE, length);
508 }
6376f1f2 509 }
86057566 510 }
d4967272 511 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
86057566 512}
abd201e9
GM
513/*
514 * Operator Information Area Services.
515 */
516
517static void
518read_oia_group(regs, sregs)
519union REGS *regs;
520struct SREGS *sregs;
521{
86057566
GM
522 ReadOiaGroupParms parms;
523
524 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
525
526 if ((parms.rc != 0) || (parms.function_id != 0)) {
527 parms.rc = 0x0c;
528 } else if (parms.session_id != 23) {
529 parms.rc = 0x02;
530 } else {
531 int group = parms.oia_group_number;
92f7501a
GM
532 char *from;
533 int size;
86057566 534
ffff8f6a
GM
535 if ((group != API_OIA_ALL_GROUPS) &&
536 ((group > API_OIA_LAST_LEGAL_GROUP) || (group < 0))) {
92f7501a
GM
537 } else {
538 if (group == API_OIA_ALL_GROUPS) {
539 size = API_OIA_BYTES_ALL_GROUPS;
540 from = (char *)&OperatorInformationArea;
541 } else if (group == API_OIA_INPUT_INHIBITED) {
542 size = sizeof OperatorInformationArea.input_inhibited;
543 from = (char *)&OperatorInformationArea.input_inhibited[0];
544 } else {
545 size = 1;
546 from = ((char *)&OperatorInformationArea)+group;
547 }
548 movetothem(FP_SEG(parms.oia_buffer), FP_OFF(parms.oia_buffer),
549 from, size);
65c9fa1f 550 }
86057566 551 }
65c9fa1f 552 parms.function_id = 0x6d;
86057566 553 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
abd201e9
GM
554}
555\f
556static void
557unknown_op(regs, sregs)
558union REGS *regs;
559struct SREGS *sregs;
560{
561 regs->h.ch = 0x12;
562 regs->h.cl = 0x05;
563}
564
565
566handle_api(regs, sregs)
567union REGS *regs;
568struct SREGS *sregs;
569{
570 if (regs->h.ah == NAME_RESOLUTION) {
571 name_resolution(regs, sregs);
bada4bfa
GM
572#if defined(unix)
573 } else if (regs->h.ah == PS_OR_OIA_MODIFIED) {
574 while ((oia_modified == 0) && (ps_modified == 0)) {
575 (void) Scheduler(1);
576 }
577 oia_modified = ps_modified = 0;
578#endif /* defined(unix) */
65c9fa1f
GM
579 } else if (regs->h.ah != 0x09) {
580 regs->h.ch = 0x12;
581 regs->h.cl = 0x0f; /* XXX Invalid environmental access */
582 } else if (regs->x.bx != 0x8020) {
583 regs->h.ch = 0x12;
584 regs->h.cl = 0x08; /* XXX Invalid wait specified */
585 } else if (regs->h.ch != 0) {
ffff8f6a 586 regs->x.cx = 0x1206; /* XXX Invalid priority */
abd201e9
GM
587 } else {
588 switch (regs->x.dx) {
589 case GATE_SESSMGR:
590 switch (regs->h.al) {
591 case QUERY_SESSION_ID:
65c9fa1f 592 if (regs->h.cl != 0) {
ffff8f6a 593 regs->x.cx = 0x1206;
65c9fa1f 594 } else {
ffff8f6a 595 regs->x.cx = 0x1200;
65c9fa1f
GM
596 query_session_id(regs, sregs);
597 }
abd201e9 598 break;
ffff8f6a 599 case QUERY_SESSION_PARAMETERS:
65c9fa1f 600 if (regs->h.cl != 0) {
ffff8f6a 601 regs->x.cx = 0x1206;
65c9fa1f 602 } else {
ffff8f6a 603 regs->x.cx = 0x1200;
92f7501a 604 query_session_parameters(regs, sregs);
65c9fa1f 605 }
abd201e9
GM
606 break;
607 case QUERY_SESSION_CURSOR:
65c9fa1f 608 if (regs->h.cl != 0xff) {
ffff8f6a 609 regs->x.cx = 0x1206;
65c9fa1f 610 } else {
ffff8f6a 611 regs->x.cx = 0x1200;
65c9fa1f
GM
612 query_session_cursor(regs, sregs);
613 }
abd201e9
GM
614 break;
615 default:
616 unknown_op(regs, sregs);
617 break;
618 }
619 break;
620 case GATE_KEYBOARD:
65c9fa1f 621 if (regs->h.cl != 00) {
ffff8f6a 622 regs->x.cx = 0x1206;
65c9fa1f 623 } else {
ffff8f6a 624 regs->x.cx = 0x1200;
65c9fa1f
GM
625 switch (regs->h.al) {
626 case CONNECT_TO_KEYBOARD:
627 connect_to_keyboard(regs, sregs);
628 break;
629 case DISABLE_INPUT:
630 disable_input(regs, sregs);
631 break;
632 case WRITE_KEYSTROKE:
633 write_keystroke(regs, sregs);
634 break;
635 case ENABLE_INPUT:
636 enable_input(regs, sregs);
637 break;
638 case DISCONNECT_FROM_KEYBOARD:
639 disconnect_from_keyboard(regs, sregs);
640 break;
641 default:
642 unknown_op(regs, sregs);
643 break;
644 }
abd201e9
GM
645 }
646 break;
647 case GATE_COPY:
65c9fa1f 648 if (regs->h.cl != 0xff) {
ffff8f6a 649 regs->x.cx = 0x1206;
65c9fa1f 650 } else {
ffff8f6a 651 regs->x.cx = 0x1200;
65c9fa1f
GM
652 switch (regs->h.al) {
653 case COPY_STRING:
654 copy_string(regs, sregs);
655 break;
656 default:
657 unknown_op(regs, sregs);
658 break;
659 }
abd201e9
GM
660 }
661 break;
662 case GATE_OIAM:
65c9fa1f 663 if (regs->h.cl != 0xff) {
ffff8f6a 664 regs->x.cx = 0x1206;
65c9fa1f 665 } else {
ffff8f6a 666 regs->x.cx = 0x1200;
65c9fa1f
GM
667 switch (regs->h.al) {
668 case READ_OIA_GROUP:
669 read_oia_group(regs, sregs);
670 break;
671 default:
672 unknown_op(regs, sregs);
673 break;
674 }
abd201e9
GM
675 }
676 break;
677 default:
65c9fa1f
GM
678 regs->h.ch = 0x12;
679 regs->h.cl = 0x34; /* Invalid GATE entry */
abd201e9
GM
680 break;
681 }
682 }
683}