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