root/src/dps8/dps8_fnp2.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. fnpInputRetryDue
  2. fnpScheduleInputRetry

   1 /*
   2  * vim: filetype=c:tabstop=4:ai:expandtab
   3  * SPDX-License-Identifier: ICU
   4  * scspell-id: 5118dce3-f62e-11ec-8fe3-80ee73e9b8e7
   5  *
   6  * ---------------------------------------------------------------------------
   7  *
   8  * Copyright (c) 2007-2013 Michael Mondy
   9  * Copyright (c) 2012-2016 Harry Reed
  10  * Copyright (c) 2013-2016 Charles Anthony
  11  * Copyright (c) 2016 Michal Tomek
  12  * Copyright (c) 2021-2025 The DPS8M Development Team
  13  *
  14  * This software is made available under the terms of the ICU License.
  15  * See the LICENSE.md file at the top-level directory of this distribution.
  16  *
  17  * ---------------------------------------------------------------------------
  18  */
  19 
  20 #include <uv.h>
  21 #include "libtelnet.h"
  22 
  23 #define encodeline(fnp,line) ((fnp) * MAX_LINES + (line))
  24 #define decodefnp(coded) ((coded) / MAX_LINES)
  25 #define decodeline(coded) ((coded) % MAX_LINES)
  26 #define noassoc -1
  27 
  28 extern UNIT fnp_unit [N_FNP_UNITS_MAX];
  29 extern DEVICE fnp_dev;
  30 
  31 #define MAX_LINES  96  /*  max number of FNP lines - hardware  */
  32 
  33 //
  34 // MState_t state of an FNP
  35 //
  36 
  37 // memset(0) sets service to service_undefined (0)
  38 enum service_types {service_undefined = 0, service_login, service_3270, service_autocall, service_slave};
  39 
  40 typedef struct t_MState
  41   {
  42     t_bool accept_calls;
  43     // 60132445 FEP Coupler Spec Nov77 - Unknown.pdf
  44     // pg 59 (sheet 56):
  45     //   bit       0: CS BAR
  46     //             1: BT INH
  47     //        2 -  7: RFU
  48     //        8 - 15: Special L6 Intpr Level
  49     word16 configRegA;
  50     struct t_line
  51       {
  52         // From the CMF database
  53         enum service_types service;
  54 
  55         // libuv hook
  56         // For non-multiplexed lines, the connection to the remote is stored here;
  57         // For multiplexed lines (3270), the connection to the currently selected station is stored here. Used by wtx.
  58         uv_tcp_t * line_client;
  59 
  60         // libtelnet hook
  61         bool was_CR;
  62 
  63         // State as set by FNP commands
  64         t_bool listen;
  65         uint inputBufferSize;
  66         uint ctrlStrIdx;
  67         t_bool breakAll;
  68         t_bool handleQuit;
  69         t_bool fullDuplex;
  70         t_bool echoPlex;    // echoes all characters types on the terminal
  71         t_bool crecho;      // echos a CR when a LF is typed
  72         t_bool lfecho;      // echos and inserts  a LF in the users input stream when a CR is typed
  73         t_bool tabecho;     // echos the appropriate number of spaces when a TAB is typed
  74         t_bool replay;
  75         t_bool polite;
  76         t_bool prefixnl;
  77         t_bool eight_bit_out;
  78         t_bool eight_bit_in;
  79         t_bool odd_parity;
  80         t_bool output_flow_control;
  81         t_bool input_flow_control;
  82         uint block_xfer_in_frame_sz, block_xfer_out_frame_sz;
  83         uint delay_table [6];
  84 #define FC_STR_SZ 4
  85         uint inputSuspendLen;
  86         unsigned char inputSuspendStr [4];
  87         uint inputResumeLen;
  88         unsigned char inputResumeStr [4];
  89         uint outputSuspendLen;
  90         unsigned char outputSuspendStr [4];
  91         uint outputResumeLen;
  92         unsigned char outputResumeStr [4];
  93         uint frame_begin;
  94         uint frame_end;
  95 
  96         // Echonego
  97         bool echnego_break_table [256];
  98         word18 echnego_sync_ctr; // Sent by MCS
  99         word18 echnego_screen_left;
 100         uint echnego_unechoed_cnt;
 101         bool echnego_on;
 102         bool echnego_synced;
 103 
 104         uint sync_msg_size;
 105         // Pending requests
 106         bool line_break;
 107 #if defined(FNPDBG)
 108 # define SEND_OUTPUT_DELAY 100
 109 #else
 110 # define SEND_OUTPUT_DELAY 2
 111 #endif
 112         uint send_output;
 113         bool accept_new_terminal;
 114 #if defined(DISC_DELAY)
 115         uint line_disconnected;
 116 #else
 117         bool line_disconnected;
 118 #endif
 119         bool ack_echnego_init;
 120         bool ack_echnego_stop;
 121         bool acu_dial_failure;
 122         bool sendLineStatus;
 123         bool wru_timeout;
 124         uint accept_input; // If non-zero, an accept_input request is queued.
 125                            // Values above one retain the legacy poll delay.
 126         // A temporary rejection retains the original input and prevents
 127         // another accept_input before this monotonic deadline (nanoseconds).
 128         // Zero means that no temporary-rejection retry is scheduled.
 129         uint64_t input_retry_at_ns;
 130         // The 3270 controller always uses ACCEPT_INPUT
 131         bool force_accept_input;
 132 
 133         bool waitForMbxDone; // If set, the line has sent input to the CS,
 134                              // but the CS has not completed the mbx transaction;
 135                              // in order to prevent input data reordering, serialize
 136                              // the commands by waiting for this to clear before
 137                              // sending the next input.
 138         bool input_reply_pending;
 139         // Short input_in_mailbox data remains owned by the mailbox until
 140         // Multics frees it or rejects it; do not discard it on submission.
 141         bool input_in_mailbox_pending;
 142         // An in-flight input belongs to a connection which has gone away.
 143         // A subsequent reply must complete the mailbox, not deliver or retry
 144         // the cancelled connection's buffered input on a replacement line.
 145         bool input_cancelled;
 146         // Part of 'accept_input'
 147         bool input_break;
 148 
 149         // Buffer being assembled for sending to Multics
 150         unsigned char buffer[1024];   // line buffer for initial device selection and line discipline
 151         uint nPos;           // position where *next* user input is to be stored
 152 
 153         // Incoming data from the connection
 154         unsigned char * inBuffer;
 155         uint inSize; // Number of bytes in inBuffer
 156         uint inUsed; // Number of consumed bytes in buffer
 157 
 158         // Dialout hooks
 159         uv_connect_t doConnect;
 160 
 161         // Slave hooks
 162         uv_tcp_t server;
 163         int port;
 164 
 165 #if defined(TUN)
 166         // TUN hook
 167         bool is_tun;
 168         int tun_fd;
 169         bool in_frame;
 170         uint8_t frame [2+1500];
 171         uint frameLen;
 172 #endif
 173 
 174         word9 lineType;
 175         word36 lineStatus0, lineStatus1;
 176         bool sendEOT;
 177       } line [MAX_LINES];
 178   } t_MState;
 179 
 180 // DN355 dia_man schedules dretry one second after reject_request_temp.
 181 // This is a monotonic deadline, independent of the emulator's poll count.
 182 #define FNP_INPUT_RETRY_NS UINT64_C(1000000000)
 183 static inline bool fnpInputRetryDue (const struct t_line * linep, uint64_t now_ns)
     /* [previous][next][first][last][top][bottom][index][help] */
 184   {
 185     return linep->input_retry_at_ns == 0 || now_ns >= linep->input_retry_at_ns;
 186   }
 187 static inline void fnpScheduleInputRetry (struct t_line * linep)
     /* [previous][next][first][last][top][bottom][index][help] */
 188   {
 189     if ((!linep->input_reply_pending && !linep->input_in_mailbox_pending) ||
 190         linep->input_cancelled)
 191       return;
 192     linep->accept_input = 1;
 193     linep->input_retry_at_ns = uv_hrtime () + FNP_INPUT_RETRY_NS;
 194   }
 195 
 196 // for now, one controller
 197 
 198 #define IBM3270_CONTROLLERS_MAX 1
 199 #define IBM3270_STATIONS_MAX 32
 200 
 201 struct ibm3270ctlr_s
 202   {
 203     bool configured;
 204     uint fnpno;
 205     uint lineno;
 206     // polling and selection addresses
 207 
 208     unsigned char pollCtlrChar;
 209     unsigned char pollDevChar;
 210     unsigned char selCtlrChar;
 211     unsigned char selDevChar;
 212     bool sending_stn_in_buffer;
 213     uint stn_no;
 214     struct station_s
 215       {
 216         uv_tcp_t * client;
 217         bool EORReceived;
 218         bool hdr_sent;
 219         unsigned char * stn_in_buffer;
 220         uint stn_in_size; // Number of bytes in inBuffer
 221         uint stn_in_used;
 222         //uint stn_in_used; // Number of consumed bytes in buffer
 223       } stations [IBM3270_STATIONS_MAX];
 224     // Although this is nominally a per/station event, Multics will not
 225     // resume polling until after the write is complete, so only
 226     // one event would be pending at any time; moving it out of the
 227     // 'stations' structure makes it easier for the emulator event
 228     // loops to see.
 229     bool write_complete;
 230   };
 231 
 232 #define MAX_DEV_NAME_LEN 64
 233 
 234 // Indexed by sim unit number
 235 struct fnpUnitData_s
 236   {
 237     char device_name [MAX_DEV_NAME_LEN];
 238     word24 mailboxAddress;
 239     bool fnpIsRunning;
 240     bool fnpMBXinUse [4];  // 4 FNP submailboxes
 241     bool lineWaiting [4]; // If set, fnpMBXlineno is waiting for the mailbox to be marked clear.
 242     int fnpMBXlineno [4]; // Which HSLA line is using the mbx
 243     char ipcName [MAX_DEV_NAME_LEN];
 244 
 245     t_MState MState;
 246   };
 247 
 248 typedef struct s_fnpData
 249   {
 250     struct fnpUnitData_s fnpUnitData [N_FNP_UNITS_MAX];
 251     struct ibm3270ctlr_s ibm3270ctlr [IBM3270_CONTROLLERS_MAX];
 252     char * telnet_address;
 253     int telnet_port;
 254     int telnet3270_port;
 255     uv_loop_t * loop;
 256     uv_tcp_t du_server;
 257     bool du_server_inited;
 258     uv_tcp_t du3270_server;
 259     bool du3270_server_inited;
 260     int du3270_poll;
 261   } t_fnpData;
 262 
 263 extern t_fnpData fnpData;
 264 
 265 // dn355_mailbox.incl.pl1
 266 //   input_sub_mbx
 267 //       pad1:8, line_number:10, n_free_buffers:18
 268 //       n_chars:18, op_code:9, io_cmd:9
 269 //       n_buffers
 270 //       { abs_addr:24, tally:12 } [24]
 271 //       command_data
 272 
 273 //
 274 // The FNP communicates with Multics with in-memory mailboxes
 275 //
 276 
 277 struct dn355_submailbox
 278   {
 279     word36 word1; // dn355_no; is_hsla; la_no; slot_no
 280     word36 word2; // cmd_data_len; op_code; io_cmd
 281     word36 command_data [3];
 282     word36 word6; // data_addr, word_cnt;
 283     word36 pad3 [2];
 284   };
 285 
 286 struct fnp_submailbox // 28 words
 287   {
 288                                                                  // AN85
 289     word36 word1; // dn355_no; is_hsla; la_no; slot_no    // 0      word0
 290     word36 word2; // cmd_data_len; op_code; io_cmd        // 1      word1
 291     word36 mystery [26];                                         // word2...
 292   };
 293 
 294 struct input_sub_mbx
 295   {
 296     word36 word1; // dn355_no; is_hsla; la_no; slot_no    // 0      word0
 297     word36 word2; // cmd_data_len; op_code; io_cmd        // 1      word1
 298     word36 n_buffers;
 299     word36 dcws [24];
 300     word36 command_data;
 301   };
 302 
 303 struct mailbox
 304   {
 305     word36 dia_pcw;
 306     word36 mailbox_requests;
 307     word36 term_inpt_mpx_wd;
 308     word36 last_mbx_req_count;
 309     word36 num_in_use;
 310     word36 mbx_used_flags;
 311     word36 crash_data [2];
 312     struct dn355_submailbox dn355_sub_mbxes [8];
 313     struct fnp_submailbox fnp_sub_mbxes [4];
 314   };
 315 
 316 #define MAILBOX_WORDS           (sizeof (struct mailbox) / sizeof (word36))
 317 
 318 #define DIA_PCW                 (offsetof (struct mailbox, dia_pcw) / sizeof (word36))
 319 #define TERM_INPT_MPX_WD        (offsetof (struct mailbox, term_inpt_mpx_wd) / sizeof (word36))
 320 #define CRASH_DATA              (offsetof (struct mailbox, crash_data) / sizeof (word36))
 321 #define DN355_SUB_MBXES         (offsetof (struct mailbox, dn355_sub_mbxes) / sizeof (word36))
 322 #define FNP_SUB_MBXES           (offsetof (struct mailbox, fnp_sub_mbxes) / sizeof (word36))
 323 
 324 #define FNP_SUB_MBX_SIZE        (sizeof (struct fnp_submailbox) / sizeof (word36))
 325 #define DN355_SUB_MBX_SIZE      (sizeof (struct dn355_submailbox) / sizeof (word36))
 326 
 327 #define WORD1                    0
 328 #define WORD2                    1
 329 #define COMMAND_DATA             2
 330 #define MYSTERY                  2
 331 #define WORD6                    5
 332 #define N_BUFFERS                2
 333 #define DCWS                     3
 334 #define N_DCWS                  24
 335 #define INP_COMMAND_DATA        27
 336 
 337 extern const unsigned char a2e [256];
 338 extern const unsigned char e2a [256];
 339 #define ADDR_MAP_ENTRIES 32
 340 // map station number to selDevChar
 341 // addr_map [stn_no] == selDevChar
 342 extern const unsigned char addr_map [ADDR_MAP_ENTRIES];
 343 
 344 #define N_FW_ENTRIES 1024
 345 extern int n_fw_entries;
 346 struct fw_entry_s
 347   {
 348     uint line_0, line_1; // range of lines
 349     uint32_t ipaddr;
 350     uint cidr;
 351     uint32_t cidr_mask;
 352     bool accept;
 353   };
 354 extern struct fw_entry_s fw_entries [N_FW_ENTRIES];
 355 
 356 void fnpInit(void);
 357 void fnpExit (void);
 358 int lookupFnpsIomUnitNumber (int fnpUnitNum);
 359 int lookupFnpLink (int fnpUnitNum);
 360 void fnpProcessEvent (void);
 361 t_stat diaCommand (int fnpUnitNum, char *arg3);
 362 void fnpToCpuQueueMsg (int fnpUnitNum, char * msg);
 363 iom_cmd_rc_t fnp_iom_cmd (uint iomUnitIdx, uint chan);
 364 t_stat set_fnp_server_port (int32 arg, const char * buf);
 365 t_stat set_fnp_server_address (int32 arg, const char * buf);
 366 t_stat set_fnp_3270_server_port (int32 arg, const char * buf);
 367 t_stat fnp_start (UNUSED int32 arg, UNUSED const char * buf);
 368 void fnpConnectPrompt (uv_tcp_t * client);
 369 void fnp3270ConnectPrompt (uv_tcp_t * client);
 370 void processUserInput (uv_tcp_t * client, unsigned char * buf, ssize_t nread);
 371 void processLineInput (uv_tcp_t * client, unsigned char * buf, ssize_t nread);
 372 void fnpRecvEOR (uv_tcp_t * client);
 373 void process3270Input (uv_tcp_t * client, unsigned char * buf, ssize_t nread);
 374 void set_3270_write_complete (uv_tcp_t * client);
 375 void startFNPListener (void);
 376 void setTIMW (uint iom_unit_idx, uint chan, word24 mailboxAddress, int mbx);

/* [previous][next][first][last][top][bottom][index][help] */