1 /* $NetBSD: api.c,v 1.6 2002/06/13 23:41:19 wiz Exp $ */
4 * Copyright (c) 1988 The Regents of the University of California.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)api.c 4.5 (Berkeley) 4/26/91";
37 __RCSID("$NetBSD: api.c,v 1.6 2002/06/13 23:41:19 wiz Exp $");
42 * This file implements the API used in the PC version.
48 #include "../general/general.h"
50 #include "../api/disp_asc.h"
59 #include "../general/globals.h"
64 * Some defines for things we use internally.
67 #define PS_SESSION_ID 23
68 #define BUF_SESSION_ID 0
73 static void movetous(char *, int, int , int);
74 static void movetothem(int, int , char *, int);
76 #include "../sys_curses/telextrn.h"
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.
99 #define access_api(foo,length,copyin) (foo)
100 #define unaccess_api(foo,goo,length,copyout)
103 movetous(parms
, es
, di
, length
)
108 char far
*farparms
= parms
;
110 movedata(es
, di
, FP_SEG(farparms
), FP_OFF(farparms
), length
);
112 Dump('(', parms
, length
);
117 movetothem(es
, di
, parms
, length
)
122 char far
*farparms
= parms
;
124 movedata(FP_SEG(farparms
), FP_OFF(farparms
), es
, di
, length
);
126 Dump(')', parms
, length
);
129 #endif /* defined(MSDOS) */
132 * Supervisor Services.
136 name_resolution(regs
, sregs
)
140 NameResolveParms parms
;
142 movetous((char *) &parms
, sregs
->es
, regs
->x
.di
, sizeof parms
);
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
;
155 regs
->h
.cl
= 0x2e; /* Name not found */
162 * Session Information Services.
166 query_session_id(regs
, sregs
)
170 QuerySessionIdParms parms
;
172 movetous((char *)&parms
, sregs
->es
, regs
->x
.di
, sizeof parms
);
174 if ((parms
.rc
!= 0) || (parms
.function_id
!= 0)) {
176 } else if (parms
.option_code
!= 0x01) {
177 parms
.rc
= 0x0d; /* Invalid option code */
179 } else if ((parms
.data_code
!= 0x45) && (parms
.data_code
!= 0x00/*OBS*/)) {
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)) {
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
);
201 parms
.function_id
= 0x6b;
202 movetothem(sregs
->es
, regs
->x
.di
, (char *)&parms
, sizeof parms
);
206 query_session_parameters(regs
, sregs
)
210 QuerySessionParametersParms parms
;
212 movetous((char *)&parms
, sregs
->es
, regs
->x
.di
, sizeof parms
);
214 if ((parms
.rc
!=0) || (parms
.function_id
!= 0)) {
216 } else if (parms
.session_id
!= PS_SESSION_ID
) {
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
);
231 query_session_cursor(regs
, sregs
)
235 QuerySessionCursorParms parms
;
237 movetous((char *)&parms
, sregs
->es
, regs
->x
.di
, sizeof parms
);
239 if ((parms
.rc
!= 0) || (parms
.function_id
!= 0)) {
241 } else if (parms
.session_id
!= PS_SESSION_ID
) {
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
);
260 connect_to_keyboard(regs
, sregs
)
264 ConnectToKeyboardParms parms
;
266 movetous((char *)&parms
, sregs
->es
, regs
->x
.di
, sizeof parms
);
268 if ((parms
.rc
!= 0) || (parms
.function_id
!= 0)) {
270 } else if (parms
.session_id
!= PS_SESSION_ID
) {
272 } else if (parms
.intercept_options
!= 0) {
276 parms
.first_connection_identifier
= 0;
278 parms
.function_id
= 0x62;
280 movetothem(sregs
->es
, regs
->x
.di
, (char *)&parms
, sizeof parms
);
284 disconnect_from_keyboard(regs
, sregs
)
288 DisconnectFromKeyboardParms parms
;
290 movetous((char *)&parms
, sregs
->es
, regs
->x
.di
, sizeof parms
);
292 if ((parms
.rc
!= 0) || (parms
.function_id
!= 0)) {
294 } else if (parms
.session_id
!= PS_SESSION_ID
) {
296 } else if (parms
.connectors_task_id
!= 0) {
297 parms
.rc
= 04; /* XXX */
301 parms
.function_id
= 0x62;
303 movetothem(sregs
->es
, regs
->x
.di
, (char *)&parms
, sizeof parms
);
307 write_keystroke(regs
, sregs
)
311 WriteKeystrokeParms parms
;
313 movetous((char *)&parms
, sregs
->es
, regs
->x
.di
, sizeof parms
);
315 if ((parms
.rc
!= 0) || (parms
.function_id
!= 0)) {
317 } else if (parms
.session_id
!= PS_SESSION_ID
) {
319 } else if (parms
.connectors_task_id
!= 0) {
322 parms
.number_of_keys_sent
= 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
) {
334 far
*atlist
= parms
.keystroke_specifier
.keystroke_list
;
336 entry
[10], /* 10 at a time */
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
;
349 if (ourentry
> &entry
[highestof(entry
)]) {
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
;
361 if (AcceptKeystroke(ourentry
->scancode
,
362 ourentry
->shift_state
) == 0) {
363 parms
.rc
= 0x10; /* XXX needs 0x12 too! */
366 parms
.number_of_keys_sent
++;
374 parms
.function_id
= 0x62;
376 movetothem(sregs
->es
, regs
->x
.di
, (char *)&parms
, sizeof parms
);
382 disable_input(regs
, sregs
)
386 DisableInputParms parms
;
388 movetous((char *)&parms
, sregs
->es
, regs
->x
.di
, sizeof parms
);
390 if ((parms
.rc
!= 0) || (parms
.function_id
!= 0)) {
392 } else if (parms
.session_id
!= PS_SESSION_ID
) {
394 } else if (parms
.connectors_task_id
!= 0) {
397 SetOiaApiInhibit(&OperatorInformationArea
);
400 parms
.function_id
= 0x62;
402 movetothem(sregs
->es
, regs
->x
.di
, (char *)&parms
, sizeof parms
);
406 enable_input(regs
, sregs
)
410 EnableInputParms parms
;
412 movetous((char *)&parms
, sregs
->es
, regs
->x
.di
, sizeof parms
);
414 if ((parms
.rc
!= 0) || (parms
.function_id
!= 0)) {
416 } else if (parms
.session_id
!= PS_SESSION_ID
) {
418 } else if (parms
.connectors_task_id
!= 0) {
421 ResetOiaApiInhibit(&OperatorInformationArea
);
424 parms
.function_id
= 0x62;
426 movetothem(sregs
->es
, regs
->x
.di
, (char *)&parms
, sizeof parms
);
434 copy_subroutine(target
, source
, parms
, what_is_user
, length
)
435 BufferDescriptor
*target
, *source
;
436 CopyStringParms
*parms
;
439 #define USER_IS_TARGET 0
440 #define USER_IS_SOURCE 1
442 #define TARGET_NO_EAB 1
443 #define SOURCE_NO_EAB 2
446 #define NO_FIELD_ATTRIBUTES 16
449 unsigned char far
*input
;
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 */
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 */
465 needtodo
|= SOURCE_PC
; /* PC to scan codes */
468 if ((parms
->copy_mode
©_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
) {
476 input
= (unsigned char far
*) &Host
[source
->begin
];
477 access_pointer
= target
->buffer
;
478 output
= access_api(target
->buffer
, access_length
, 0);
480 if (source
->characteristics
&CHARACTERISTIC_EAB
) {
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
];
489 if (needtodo
&TARGET_PC
) {
490 *output
++ = disp_asc
[*input
++];
491 } else if (needtodo
&SOURCE_PC
) {
492 *output
++ = asc_disp
[*input
++];
494 *output
++ = *input
++;
496 if (needtodo
&TARGET_NO_EAB
) {
497 /* XXX: So why are we doing this? (bug) */
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);
506 unaccess_api(source
->buffer
, access_pointer
, access_length
, 0);
512 copy_string(regs
, sregs
)
516 CopyStringParms parms
;
517 BufferDescriptor
*target
= &parms
.target
, *source
= &parms
.source
;
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)) {
525 } else if (target
->session_id
== BUF_SESSION_ID
) { /* Target is buffer */
526 if (source
->session_id
!= PS_SESSION_ID
) { /* A no-no */
529 if ((source
->begin
< 0) || (source
->begin
> highestof(Host
))) {
530 parms
.rc
= 0x06; /* invalid source definition */
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
) {
541 movetothem(FP_SEG(target
->buffer
),
542 FP_OFF(target
->buffer
),
543 (char *)&Host
[source
->begin
], length
);
545 copy_subroutine(target
, source
, &parms
,
546 USER_IS_TARGET
, length
);
550 } else if (source
->session_id
!= BUF_SESSION_ID
) {
553 /* Send to presentation space (3270 buffer) */
554 if ((target
->begin
< 0) || (target
->begin
> highestof(Host
))) {
555 parms
.rc
= 0x07; /* invalid target definition */
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 */
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
) {
575 movetous((char *)&Host
[target
->begin
],
576 FP_SEG(source
->buffer
),
577 FP_OFF(source
->buffer
), length
);
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.
593 read_oia_group(regs
, sregs
)
597 ReadOiaGroupParms parms
;
599 movetous((char *)&parms
, sregs
->es
, regs
->x
.di
, sizeof parms
);
601 if ((parms
.rc
!= 0) || (parms
.function_id
!= 0)) {
603 } else if (parms
.session_id
!= PS_SESSION_ID
) {
606 int group
= parms
.oia_group_number
;
610 if ((group
!= API_OIA_ALL_GROUPS
) &&
611 ((group
> API_OIA_LAST_LEGAL_GROUP
) || (group
< 0))) {
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];
621 from
= ((char *)&OperatorInformationArea
)+group
;
623 movetothem(FP_SEG(parms
.oia_buffer
), FP_OFF(parms
.oia_buffer
),
627 parms
.function_id
= 0x6d;
628 movetothem(sregs
->es
, regs
->x
.di
, (char *)&parms
, sizeof parms
);
633 unknown_op(regs
, sregs
)
643 handle_api(regs
, sregs
)
648 * Do we need to log this transaction?
651 Dump('<', (char *)regs
, sizeof *regs
);
652 Dump('<', (char *)sregs
, sizeof *sregs
);
654 if (regs
->h
.ah
== NAME_RESOLUTION
) {
655 name_resolution(regs
, sregs
);
657 } else if (regs
->h
.ah
== PS_OR_OIA_MODIFIED
) {
658 while ((oia_modified
== 0) && (ps_modified
== 0)) {
661 oia_modified
= ps_modified
= 0;
662 #endif /* defined(unix) */
663 } else if (regs
->h
.ah
!= 0x09) {
665 regs
->h
.cl
= 0x0f; /* XXX Invalid environmental access */
666 } else if (regs
->x
.bx
!= 0x8020) {
668 regs
->h
.cl
= 0x08; /* XXX Invalid wait specified */
669 } else if (regs
->h
.ch
!= 0) {
670 regs
->x
.cx
= 0x1206; /* XXX Invalid priority */
672 switch (regs
->x
.dx
) {
674 switch (regs
->h
.al
) {
675 case QUERY_SESSION_ID
:
676 if (regs
->h
.cl
!= 0) {
680 query_session_id(regs
, sregs
);
683 case QUERY_SESSION_PARAMETERS
:
684 if (regs
->h
.cl
!= 0) {
688 query_session_parameters(regs
, sregs
);
691 case QUERY_SESSION_CURSOR
:
692 if ((regs
->h
.cl
!= 0xff) && (regs
->h
.cl
!= 0x00/*OBS*/)) {
696 query_session_cursor(regs
, sregs
);
700 unknown_op(regs
, sregs
);
705 if (regs
->h
.cl
!= 00) {
709 switch (regs
->h
.al
) {
710 case CONNECT_TO_KEYBOARD
:
711 connect_to_keyboard(regs
, sregs
);
714 disable_input(regs
, sregs
);
716 case WRITE_KEYSTROKE
:
717 write_keystroke(regs
, sregs
);
720 enable_input(regs
, sregs
);
722 case DISCONNECT_FROM_KEYBOARD
:
723 disconnect_from_keyboard(regs
, sregs
);
726 unknown_op(regs
, sregs
);
732 if (regs
->h
.cl
!= 0xff) {
736 switch (regs
->h
.al
) {
738 copy_string(regs
, sregs
);
741 unknown_op(regs
, sregs
);
747 if (regs
->h
.cl
!= 0xff) {
751 switch (regs
->h
.al
) {
753 read_oia_group(regs
, sregs
);
756 unknown_op(regs
, sregs
);
763 regs
->h
.cl
= 0x34; /* Invalid GATE entry */
768 * Do we need to log this transaction?
771 Dump('>', (char *)regs
, sizeof *regs
);
772 Dump('>', (char *)sregs
, sizeof *sregs
);
774 { char buf
[10]; gets(buf
); }