1 /* ibm1130_sca.c: IBM 1130 synchronous communications adapter emulation
3 Based on the SIMH simulator package written by Robert M Supnik
10 * (C) Copyright 2005, Brian Knittel.
11 * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN
12 * RISK basis, there is no warranty of fitness for any purpose, and the rest of the
13 * usual yada-yada. Please keep this notice and the copyright in any distributions
16 * This is not a supported product, but I welcome bug reports and fixes.
17 * Mail to simh@ibm1130.org
20 /******************************************************************************************************************
22 * This module sends raw bisync data over a standard TCP port. It's meant to be
23 * used with the emulated 2703 device in Hercules.
27 * to establish an outgoing connection:
29 * attach sca host connect to named host on default port (initial default port is 2703); or
30 * attach sca host:### connect to named host on port ###. ### is also set as new default port number.
31 * >> The simulator waits until the connection is established
33 * or to set up for incoming connections:
35 * attach sca -l dummy listen for a connection on default port (initially 2703); Nonnumeric "dummy" argument is ignored; or
36 * attach sca -l ### listen for a connection on the port ###. ### is also set as the new default port
37 * >> The simulator proceeds. When another simulator connects, the READY bit is set in the DSW.
39 * If the SCA's autoanswer-enable bit has been set, an incoming connection causes an interrupt (untested)
40 * Configuration commands:
42 * set sca bsc set bisync mode (default)
43 * set sca str set synchronous transmit/recieve mode (NOT IMPLEMENTED)
45 * set sca ### set simulated baud rate to ###, where ### is 600, 1200, 2000, 2400 or 4800 (4800 is default)
47 * set sca half set simulated half-duplex mode
48 * set sca full set simulated full-duplex mode (note: 1130's SCA can't actually send and receive at the same time!)
50 * deposit sca keepalive ### send SYN packets every ### msec when suppressing SYN's, default is 0 (no keepalives)
52 * STR/BSC mode is selected by a toggle switch on the 1130, with the SET SCA BSC or SET SET STR command here.
53 * Testable with in_bsc_mode() or in_str_mode() in this module. If necessary, the SET command can be configured
54 * to call a routine when the mode is changed; or, we can just required the user to reboot the simulated 1130
55 * when switching modes.
57 * STR MODE IS NOT IMPLEMENTED!
59 * The SCA adapter appears to know nothing of the protocols used by STR and BSC. It does handle the sync/idle
60 * character specially, and between BSC and STR mode the timers are used differently. Also in STR mode it
61 * can be set to a sychronization mode where it sends SYN's without program intervention.
63 * See definition of SCA_STATE for defintion of simulator states.
65 * Rather than trying to simulate the actual baud rates, we try to keep the character service interrupts
66 * coming at about the same number of instruction intervals -- thus existing 1130 code should work correctly
67 * but the effective data transfer rate will be much higher. The "timers" however are written to run on real wall clock
68 * time, This may or may not work. If necessary they could be set to time out based on the number of calls to sca_svc
69 * which occurs once per character send/receive time; For example, at 4800 baud and an 8 bit frame, we get
70 * 600 characters/second, so the 3 second timer would expire in 1800 sca_svc calls. Well, that's something to
73 * To void blowing zillions of SYN characters across the network when the system is running but idle, we suppress
74 * them. If 100 consecutive SYN's are sent, we flush the output buffer and stop sending SYN's
75 * until some other character is sent, OR the line is turned around (e.g. INITR, INITW or an end-operation
76 * CONTROL is issued), or the number of msec set by DEPOSIT SCS KEEPALIVE has passed, if a value has
77 * been set. By default no keepalives are sent.
79 * Timer operations are not debugged. First, do timers automatically reset and re-interrupt if
80 * left alone after they timeout the first time? Does XIO_SENSE_DEV really restart all running timers?
81 * Does it touch the timer trigger (program timer?) How do 3 and 1.25 second timers really work
82 * in BSC mode? Hard to tell from the FC manual.
83 ******************************************************************************************************************/
85 #include "ibm1130_defs.h"
86 #include "sim_sock.h" /* include path must include main simh directory */
89 #define INADDR_NONE ((unsigned long)-1)
92 #define DEBUG_SCA_FLUSH 0x0001 /* debugging options */
93 #define DEBUG_SCA_TRANSMIT 0x0002
94 #define DEBUG_SCA_CHECK_INDATA 0x0004
95 #define DEBUG_SCA_RECEIVE_SYNC 0x0008
96 #define DEBUG_SCA_RECEIVE_DATA 0x0010
97 #define DEBUG_SCA_XIO_READ 0x0020
98 #define DEBUG_SCA_XIO_WRITE 0x0040
99 #define DEBUG_SCA_XIO_CONTROL 0x0080
100 #define DEBUG_SCA_XIO_INITW 0x0100
101 #define DEBUG_SCA_XIO_INITR 0x0200
102 #define DEBUG_SCA_XIO_SENSE_DEV 0x0400
103 #define DEBUG_SCA_TIMERS 0x0800
104 #define DEBUG_SCA_ALL 0xFFFF
106 /* #define DEBUG_SCA (DEBUG_SCA_TIMERS|DEBUG_SCA_FLUSH|DEBUG_SCA_TRANSMIT|DEBUG_SCA_CHECK_INDATA|DEBUG_SCA_RECEIVE_SYNC|DEBUG_SCA_RECEIVE_DATA|DEBUG_SCA_XIO_INITR|DEBUG_SCA_XIO_INITW) */
107 #define DEBUG_SCA (DEBUG_SCA_TIMERS|DEBUG_SCA_FLUSH|DEBUG_SCA_CHECK_INDATA|DEBUG_SCA_XIO_INITR|DEBUG_SCA_XIO_INITW)
109 #define SCA_DEFAULT_PORT 2703 /* default socket, This is the number of the IBM 360's BSC device */
111 #define MAX_SYNS 100 /* number of consecutive syn's after which we stop buffering them */
113 /***************************************************************************************
115 ***************************************************************************************/
117 #define SCA_DSW_READ_RESPONSE 0x8000 /* receive buffer full interrupt */
118 #define SCA_DSW_WRITE_RESPONSE 0x4000 /* transmitter buffer empty interrupt */
119 #define SCA_DSW_CHECK 0x2000 /* data overrun or character gap error */
120 #define SCA_DSW_TIMEOUT 0x1000 /* timer interrupt, mode specific */
121 #define SCA_DSW_AUTOANSWER_REQUEST 0x0800 /* dataset is ringing and autoanswer is enabled */
122 #define SCA_DSW_BUSY 0x0400 /* adapter is in either receive or transmit mode */
123 #define SCA_DSW_AUTOANSWER_ENABLED 0x0200 /* 1 when autoanswer mode has been enabled */
124 #define SCA_DSW_READY 0x0100 /* Carrier detect? Connected and ready to rcv, xmit or sync */
125 #define SCA_DSW_RECEIVE_RUN 0x0080 /* used in two-wire half-duplex STR mode only. "Slave" mode (?) */
127 #define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT)
129 typedef enum { /* ms m = mode (0 = idle, 1 = send, 2 = receive), s = substate */
130 SCA_STATE_IDLE
= 0x00, /* nothing happening */
131 SCA_STATE_TURN_SEND
= 0x10, /* line turning around to the send state */
132 SCA_STATE_SEND_SYNC
= 0x11, /* sca is sending syncs */
133 SCA_STATE_SEND1
= 0x12, /* have issued write response, waiting for write command */
134 SCA_STATE_SEND2
= 0x13, /* write command issued, "sending" byte */
135 SCA_STATE_TURN_RECEIVE
= 0x20, /* line turnaround to the receive state */
136 SCA_STATE_RECEIVE_SYNC
= 0x21, /* sca is receiving syncs */
137 SCA_STATE_RECEIVE_SYNC2
= 0x22, /* bsc mode, waiting for 2nd SYN */
138 SCA_STATE_RECEIVE_SYNC3
= 0x23, /* bsc mode, waiting for 1st non-SYN */
139 SCA_STATE_RECEIVE1
= 0x24, /* "receiving" a byte */
140 SCA_STATE_RECEIVE2
= 0x25, /* read response issued, "receiving" next byte */
143 #define in_send_state() (sca_state & 0x10)
144 #define in_receive_state() (sca_state & 0x20)
146 static t_stat
sca_svc (UNIT
*uptr
); /* prototypes */
147 static t_stat
sca_reset (DEVICE
*dptr
);
148 static t_stat
sca_attach (UNIT
*uptr
, char *cptr
);
149 static t_stat
sca_detach (UNIT
*uptr
);
150 static void sca_start_timer (int n
, int msec_now
);
151 static void sca_halt_timer (int n
);
152 static void sca_toggle_timer (int n
, int msec_now
);
153 /* timer states, chosen so any_timer_running can be calculated by oring states of all 3 timers */
154 typedef enum {SCA_TIMER_INACTIVE
= 0, SCA_TIMER_RUNNING
= 1, SCA_TIMER_INHIBITED
= 2, SCA_TIMER_TIMEDOUT
= 4} SCA_TIMER_STATE
;
156 #define TIMER_3S 0 /* 3 second timer index into sca_timer_xxx arrays */
157 #define TIMER_125S 1 /* 1.25 second timer */
158 #define TIMER_035S 2 /* 0.35 second timer */
160 static uint16 sca_dsw
= 0; /* device status word */
161 static uint32 sca_cwait
= 275; /* inter-character wait */
162 static uint32 sca_iwait
= 2750; /* idle wait */
163 static uint32 sca_state
= SCA_STATE_IDLE
;
164 static uint8 sichar
= 0; /* sync/idle character */
165 static uint8 rcvd_char
= 0; /* most recently received character */
166 static uint8 sca_frame
= 8;
167 static uint16 sca_port
= SCA_DEFAULT_PORT
; /* listening port number */
168 static int32 sca_keepalive
= 0; /* keepalive SYN packet period in msec, default = 0 (disabled) */
169 static SCA_TIMER_STATE sca_timer_state
[3]; /* current timer state */
170 static int sca_timer_endtime
[3]; /* clocktime when timeout is to occur if state is RUNNING */
171 static int sca_timer_timeleft
[3]; /* time left in msec if state is INHIBITED */
172 static t_bool any_timer_running
= FALSE
; /* TRUE if at least one timer is running */
173 static int sca_timer_msec
[3] = {3000, 1250, 350}; /* timebase in msec for the three timers: 3 sec, 1.25 sec, 0.35 sec */
174 static t_bool sca_timer_trigger
; /* if TRUE, the "timer trigger" is set, the 0.35s timer is running and the 3 sec and 1.25 sec timers are inhibited */
175 static int sca_nsyns
= 0; /* number of consecutively sent SYN's */
176 static int idles_since_last_write
= 0; /* used to detect when software has ceased sending data */
177 static SOCKET sca_lsock
= INVALID_SOCKET
;
178 static SOCKET sca_sock
= INVALID_SOCKET
;
180 #define SCA_SENDBUF_SIZE 145 /* maximum number of bytes to buffer for transmission */
181 #define SCA_RCVBUF_SIZE 256 /* max number of bytes to read from socket at a time */
182 #define SCA_SEND_THRESHHOLD 140 /* number of bytes to buffer before initiating packet send */
183 #define SCA_IDLE_THRESHHOLD 3 /* maximum number of unintentional idles to buffer before initiating send */
185 static uint8 sca_sendbuf
[SCA_SENDBUF_SIZE
]; /* bytes pending to write to socket */
186 static uint8 sca_rcvbuf
[SCA_RCVBUF_SIZE
]; /* bytes received from socket, to be given to SCA */
187 static int sca_n2send
= 0; /* number of bytes queued for transmission */
188 static int sca_nrcvd
= 0; /* number of received bytes in buffer */
189 static int sca_rcvptr
= 0; /* index of next byte to take from rcvbuf */
191 #define UNIT_V_BISYNC (UNIT_V_UF + 0) /* BSC (bisync) mode */
192 #define UNIT_V_BAUD (UNIT_V_UF + 1) /* 3 bits for baud rate encoding */
193 #define UNIT_V_FULLDUPLEX (UNIT_V_UF + 4)
194 #define UNIT_V_AUTOANSWER (UNIT_V_UF + 5)
195 #define UNIT_V_LISTEN (UNIT_V_UF + 6) /* listen socket mode */
197 #define UNIT_BISYNC (1u << UNIT_V_BISYNC)
198 #define UNIT_BAUDMASK (7u << UNIT_V_BAUD)
199 #define UNIT_BAUD600 (0u << UNIT_V_BAUD)
200 #define UNIT_BAUD1200 (1u << UNIT_V_BAUD)
201 #define UNIT_BAUD2000 (2u << UNIT_V_BAUD)
202 #define UNIT_BAUD2400 (3u << UNIT_V_BAUD)
203 #define UNIT_BAUD4800 (4u << UNIT_V_BAUD)
204 #define UNIT_FULLDUPLEX (1u << UNIT_V_FULLDUPLEX)
205 #define UNIT_AUTOANSWER (1u << UNIT_V_AUTOANSWER)
206 #define UNIT_LISTEN (1u << UNIT_V_LISTEN)
208 extern int sim_switches
; /* variable that gets bits set for -x switches on command lines */
210 t_stat
sca_set_baud (UNIT
*uptr
, int32 value
, char *cptr
, void *desc
);
212 UNIT sca_unit
= { /* default settings */
213 UDATA (sca_svc
, UNIT_ATTABLE
|UNIT_BISYNC
|UNIT_BAUD4800
|UNIT_FULLDUPLEX
, 0),
216 REG sca_reg
[] = { /* DEVICE STATE/SETTABLE PARAMETERS: */
217 { HRDATA (SCADSW
, sca_dsw
, 16) }, /* device status word */
218 { DRDATA (SICHAR
, sichar
, 8), PV_LEFT
}, /* sync/idle character */
219 { DRDATA (RCVDCHAR
, rcvd_char
, 8), PV_LEFT
}, /* most recently received character */
220 { DRDATA (FRAME
, sca_frame
, 8), PV_LEFT
}, /* frame bits (6, 7 or 8)
221 { DRDATA (SCASTATE, sca_state, 32), PV_LEFT }, /* current state */
222 { DRDATA (CTIME
, sca_cwait
, 32), PV_LEFT
}, /* inter-character wait */
223 { DRDATA (ITIME
, sca_iwait
, 32), PV_LEFT
}, /* idle wait (polling interval for socket connects) */
224 { DRDATA (SCASOCKET
, sca_port
, 16), PV_LEFT
}, /* listening port number */
225 { DRDATA (KEEPALIVE
, sca_keepalive
, 32), PV_LEFT
}, /* keepalive packet period in msec */
228 MTAB sca_mod
[] = { /* DEVICE OPTIONS */
229 { UNIT_BISYNC
, 0, "STR", "STR", NULL
}, /* mode option */
230 { UNIT_BISYNC
, UNIT_BISYNC
, "BSC", "BSC", NULL
},
231 { UNIT_BAUDMASK
, UNIT_BAUD600
, "600", "600", sca_set_baud
}, /* data rate option */
232 { UNIT_BAUDMASK
, UNIT_BAUD1200
, "1200", "1200", sca_set_baud
},
233 { UNIT_BAUDMASK
, UNIT_BAUD2000
, "2000", "2000", sca_set_baud
},
234 { UNIT_BAUDMASK
, UNIT_BAUD2400
, "2400", "2400", sca_set_baud
},
235 { UNIT_BAUDMASK
, UNIT_BAUD4800
, "4800", "4800", sca_set_baud
},
236 { UNIT_FULLDUPLEX
, 0, "HALF", "HALF", NULL
}, /* duplex option (does this matter?) */
237 { UNIT_FULLDUPLEX
, UNIT_FULLDUPLEX
, "FULL", "FULL", NULL
},
241 "SCA", &sca_unit
, sca_reg
, sca_mod
,
242 1, 16, 16, 1, 16, 16,
243 NULL
, NULL
, sca_reset
,
244 NULL
, sca_attach
, sca_detach
247 /*********************************************************************************************
248 * sca_set_baud - set baud rate handler (SET SCA.BAUD nnn)
249 *********************************************************************************************/
251 t_stat
sca_set_baud (UNIT
*uptr
, int32 value
, char *cptr
, void *desc
)
256 case 600: newbits
= UNIT_BAUD600
; break;
257 case 1200: newbits
= UNIT_BAUD1200
; break;
258 case 2000: newbits
= UNIT_BAUD2000
; break;
259 case 2400: newbits
= UNIT_BAUD2400
; break;
260 case 4800: newbits
= UNIT_BAUD4800
; break;
261 default: return SCPE_ARG
;
264 CLRBIT(sca_unit
.flags
, UNIT_BAUDMASK
);
265 SETBIT(sca_unit
.flags
, newbits
);
267 sca_cwait
= 1320000 / value
; /* intercharacter wait time in instructions (roughly) */
272 /*********************************************************************************************
274 *********************************************************************************************/
276 #define in_bsc_mode() (sca_unit.flags & UNIT_BISYNC) /* TRUE if user selected BSC mode */
277 #define in_str_mode() ((sca_unit.flags & UNIT_BISYNC) == 0) /* TRUE if user selected STR mode */
279 /*********************************************************************************************
280 * mstring - allocate a copy of a string
281 *********************************************************************************************/
283 char *mstring (char *str
)
289 if ((m
= malloc(len
)) == NULL
) {
290 printf("Out of memory!");
291 return "?"; /* this will of course cause trouble if it's subsequently freed */
297 /*********************************************************************************************
298 * sca_socket_error - call when there is an error reading from or writing to socket
299 *********************************************************************************************/
301 static void sca_socket_error (void)
305 /* print diagnostic? */
306 printf("SCA socket error, closing connection\n");
308 /* tell 1130 that connection was lost */
309 CLRBIT(sca_dsw
, SCA_DSW_READY
);
311 if (sca_sock
!= INVALID_SOCKET
) {
312 /* close socket, prepare to listen again if in listen mode. It's a "master" socket if it was an outgoing connection */
313 sim_close_sock(sca_sock
, (sca_unit
.flags
& UNIT_LISTEN
) == 0);
314 sca_sock
= INVALID_SOCKET
;
316 if (sca_unit
.filename
!= NULL
) /* reset filename string in unit record */
317 free(sca_unit
.filename
);
319 if (sca_unit
.flags
& UNIT_LISTEN
) {
320 sprintf(name
, "(Listening on port %d)", sca_port
);
321 sca_unit
.filename
= mstring(name
);
322 printf("%s\n", name
);
325 sca_unit
.filename
= mstring("(connection failed)");
329 sca_nrcvd
= sca_rcvptr
= sca_n2send
= sca_nsyns
= 0;
332 /*********************************************************************************************
333 * sca_transmit_byte, sca_flush - send data buffering mechanism
334 *********************************************************************************************/
336 static void sca_flush (void)
340 if (sca_n2send
> 0) {
341 #if (DEBUG_SCA & DEBUG_SCA_FLUSH)
342 printf("* SCA_FLUSH %d byte%s\n", sca_n2send
, (sca_n2send
== 1) ? "" : "s");
345 if (sca_sock
!= INVALID_SOCKET
) {
346 nbytes
= sim_write_sock(sca_sock
, sca_sendbuf
, sca_n2send
);
348 if (nbytes
== SOCKET_ERROR
)
350 else if (nbytes
!= sca_n2send
)
351 printf("SOCKET BLOCKED -- NEED TO REWRITE IBM1130_SCA.C");
353 /* I'm going to assume that SCA communications on the 1130 will consist entirely */
354 /* of back and forth exchanges of short records, and so we should never stuff the pipe so full that */
355 /* it blocks. If it does ever block, we'll have to come up with an asychronous buffering mechanism. */
358 sca_n2send
= 0; /* mark buffer cleared */
362 /*********************************************************************************************
363 * sca_transmit_byte - buffer a byte to be send to the socket
364 *********************************************************************************************/
366 static void sca_transmit_byte (uint8 b
)
369 static uint32 last_syn_time
, next_syn_time
;
371 #if (DEBUG_SCA & DEBUG_SCA_TRANSMIT)
372 printf("* SCA_TRANSMIT: %02x\n", b
);
375 /* write a byte to the socket. Let's assume an 8 bit frame in all cases.
376 * We buffer them up, then send the packet when (a) it fills up to a certain point
377 * and/or (b) some time has passed? We handle (b) by:
378 * checking in sva_svc if several sca_svc calls are made w/o any XIO_WRITES, and
379 * flushing send buffer on line turnaround, timeouts, or any other significant state change
382 /* on socket error, call sca_socket_error(); */
385 if (sca_nsyns
>= MAX_SYNS
) { /* we're suppressing SYN's */
386 if (sca_keepalive
> 0) { /* we're sending keepalives, though... check to see if it's time */
387 curtime
= sim_os_msec();
388 if (curtime
>= next_syn_time
|| curtime
< last_syn_time
) { /* check for < last_syn_time because sim_os_msec() can wrap when OS has been running a long time */
389 sca_sendbuf
[sca_n2send
++] = b
;
390 sca_sendbuf
[sca_n2send
++] = b
; /* send 2 of them */
392 last_syn_time
= curtime
;
393 next_syn_time
= last_syn_time
+ sca_keepalive
;
399 if (++sca_nsyns
== MAX_SYNS
) { /* we've sent a bunch of SYN's, time to stop sending them */
400 sca_sendbuf
[sca_n2send
] = b
; /* send last one */
402 last_syn_time
= sim_os_msec(); /* remember time, and note time to send next one */
403 next_syn_time
= last_syn_time
+ sca_keepalive
;
410 sca_sendbuf
[sca_n2send
] = b
; /* store character */
412 if (++sca_n2send
>= SCA_SEND_THRESHHOLD
)
413 sca_flush(); /* buffer is full, send it immediately */
416 /*********************************************************************************************
417 * sca_interrupt (utility routine) - set a bit in the device status word and initiate an interrupt
418 *********************************************************************************************/
420 static void sca_interrupt (int bit
)
422 sca_dsw
|= bit
; /* set device status word bit(s) */
423 SETBIT(ILSW
[1], ILSW_1_SCA
); /* set interrupt level status word bit */
425 calc_ints(); /* udpate simulator interrupt status (not really needed if within xio handler, since ibm1130_cpu calls it after xio handler) */
428 /*********************************************************************************************
429 * sca_reset - reset the SCA device
430 *********************************************************************************************/
432 static t_stat
sca_reset (DEVICE
*dptr
)
434 /* flush any pending data */
436 sca_nrcvd
= sca_rcvptr
= sca_n2send
= sca_nsyns
= 0;
438 /* reset sca activity */
439 sca_state
= SCA_STATE_IDLE
;
440 CLRBIT(sca_dsw
, SCA_DSW_BUSY
| SCA_DSW_AUTOANSWER_ENABLED
| SCA_DSW_RECEIVE_RUN
| SCA_DSW_READ_RESPONSE
| SCA_DSW_WRITE_RESPONSE
| SCA_DSW_CHECK
| SCA_DSW_TIMEOUT
| SCA_DSW_AUTOANSWER_REQUEST
);
441 sca_timer_state
[0] = sca_timer_state
[1] = sca_timer_state
[2] = SCA_TIMER_INACTIVE
;
442 any_timer_running
= FALSE
;
443 sca_timer_trigger
= FALSE
;
445 if (sca_unit
.flags
& UNIT_ATT
) /* if unit is attached (or listening) */
446 sim_activate(&sca_unit
, sca_iwait
); /* poll for service. Must do this here as BOOT clears activity queue before resetting all devices */
451 /*********************************************************************************************
452 * sca_attach - attach the SCA device
453 *********************************************************************************************/
455 static t_stat
sca_attach (UNIT
*uptr
, char *cptr
)
463 static SOCKET sdummy
= INVALID_SOCKET
;
464 fd_set wr_set
, err_set
;
466 do_listen
= sim_switches
& SWMASK('L'); /* -l means listen mode */
468 if (sca_unit
.flags
& UNIT_ATT
) /* if already attached, detach */
469 detach_unit(&sca_unit
);
471 if (do_listen
) { /* if listen mode, string specifies socket number (only; otherwise it's a dummy argument) */
472 if (isdigit(*cptr
)) { /* if digits specified, extract port number */
474 if (port
<= 0 || port
> 65535)
479 /* else if nondigits specified, ignore... but the command has to have something there otherwise the core scp */
480 /* attach_cmd() routine complains "too few arguments". */
482 if ((sca_lsock
= sim_master_sock(sca_port
)) == INVALID_SOCKET
)
485 SETBIT(sca_unit
.flags
, UNIT_LISTEN
); /* note that we are listening, not yet connected */
487 sprintf(name
, "(Listening on port %d)", sca_port
);
488 sca_unit
.filename
= mstring(name
);
489 printf("%s\n", name
);
493 while (*cptr
&& *cptr
<= ' ')
499 if ((colon
= strchr(cptr
, ':')) != NULL
) {
500 *colon
++ = '\0'; /* clip hostname at colon */
502 port
= atoi(colon
); /* extract port number that follows it */
503 if (port
<= 0 || port
> 65535)
509 if (sdummy
== INVALID_SOCKET
)
510 if ((sdummy
= sim_create_sock()) == INVALID_SOCKET
) /* create and keep a socket, to force initialization */
511 return SCPE_IERR
; /* of socket library (e.g on Win32 call WSAStartup), else gethostbyname fails */
513 if (get_ipaddr(cptr
, &ipaddr
, NULL
) != SCPE_OK
) { /* try to parse hostname as dotted decimal nnn.nnn.nnn.nnn */
514 if ((he
= gethostbyname(cptr
)) == NULL
) /* if not decimal, look up name through DNS */
517 if ((ipaddr
= * (unsigned long *) he
->h_addr_list
[0]) == INADDR_NONE
)
520 ipaddr
= ntohl(ipaddr
); /* convert to host byte order; gethostbyname() gives us network order */
523 if ((sca_sock
= sim_connect_sock(ipaddr
, sca_port
)) == INVALID_SOCKET
)
526 /* sim_connect_sock() sets socket to nonblocking before initiating the connect, so
527 * the connect is pending when it returns. For outgoing connections, the attach command should wait
528 * until the connection succeeds or fails. We use "accept" to wait and find out which way it goes...
531 FD_ZERO(&wr_set
); /* we are only interested in info for sca_sock */
533 FD_SET(sca_sock
, &wr_set
);
534 FD_SET(sca_sock
, &err_set
);
536 select(3, NULL
, &wr_set
, &err_set
, NULL
); /* wait for connection to complete or fail */
538 if (FD_ISSET(sca_sock
, &wr_set
)) { /* sca_sock appears in "writable" set -- connect completed */
539 sprintf(name
, "%s:%d", cptr
, sca_port
);
540 sca_unit
.filename
= mstring(name
);
541 SETBIT(sca_dsw
, SCA_DSW_READY
);
543 else if (FD_ISSET(sca_sock
, &err_set
)) { /* sca_sock appears in "error" set -- connect failed */
544 sim_close_sock(sca_sock
, TRUE
);
545 sca_sock
= INVALID_SOCKET
;
548 else { /* if we get here my assumption about how select works is wrong */
549 printf("SCA_SOCK NOT FOUND IN WR_SET -OR- ERR_SET, CODING IN IBM1130_SCA IS WRONG\n");
550 sim_close_sock(sca_sock
, TRUE
);
551 sca_sock
= INVALID_SOCKET
;
556 /* set up socket connect or listen. on success, set UNIT_ATT.
557 * If listen mode, set UNIT_LISTEN. sca_svc will poll for connection
558 * If connect mode, set dsw SCA_DSW_READY to indicate connection is up
561 SETBIT(sca_unit
.flags
, UNIT_ATT
); /* record successful socket binding */
563 sca_state
= SCA_STATE_IDLE
;
564 sim_activate(&sca_unit
, sca_iwait
); /* start polling for service */
566 sca_n2send
= 0; /* clear buffers */
574 /*********************************************************************************************
575 * sca_detach - detach the SCA device
576 *********************************************************************************************/
578 static t_stat
sca_detach (UNIT
*uptr
)
580 if ((sca_unit
.flags
& UNIT_ATT
) == 0)
585 sca_state
= SCA_STATE_IDLE
; /* stop processing during service calls */
586 sim_cancel(&sca_unit
); /* stop polling for service */
588 CLRBIT(sca_dsw
, SCA_DSW_READY
); /* indicate offline */
590 if (sca_sock
!= INVALID_SOCKET
) { /* close connected socket */
591 sim_close_sock(sca_sock
, (sca_unit
.flags
& UNIT_LISTEN
) == 0);
592 sca_sock
= INVALID_SOCKET
;
594 if (sca_lsock
!= INVALID_SOCKET
) { /* close listening socket */
595 sim_close_sock(sca_lsock
, TRUE
);
596 sca_lsock
= INVALID_SOCKET
;
599 free(sca_unit
.filename
);
600 sca_unit
.filename
= NULL
;
602 CLRBIT(sca_unit
.flags
, UNIT_ATT
|UNIT_LISTEN
);
607 /*********************************************************************************************
608 * sca_check_connect - see if an incoming socket connection has com
609 *********************************************************************************************/
611 static void sca_check_connect (void)
616 if ((sca_sock
= sim_accept_conn(sca_lsock
, &ipaddr
)) == INVALID_SOCKET
)
619 ipaddr
= htonl(ipaddr
); /* convert to network order so we can print it */
621 sprintf(name
, "%d.%d.%d.%d", ipaddr
& 0xFF, (ipaddr
>> 8) & 0xFF, (ipaddr
>> 16) & 0xFF, (ipaddr
>> 24) & 0xFF);
623 printf("(SCA connection from %s)\n", name
);
625 if (sca_unit
.filename
!= NULL
)
626 free(sca_unit
.filename
);
628 sca_unit
.filename
= mstring(name
);
630 SETBIT(sca_dsw
, SCA_DSW_READY
); /* indicate active connection */
632 if (sca_dsw
& SCA_DSW_AUTOANSWER_ENABLED
) /* if autoanswer was enabled, I guess we should give them an interrupt. Untested. */
633 sca_interrupt(SCA_DSW_AUTOANSWER_REQUEST
);
636 /*********************************************************************************************
637 * sca_check_indata - try to fill receive buffer from socket
638 *********************************************************************************************/
640 static void sca_check_indata (void)
644 sca_rcvptr
= 0; /* reset pointers and count */
649 nbytes
= 5; /* FAKE: receive SYN SYN SYN SYN DLE ACK0 */
650 sca_rcvbuf
[0] = 0x32;
651 sca_rcvbuf
[1] = 0x32;
652 sca_rcvbuf
[2] = 0x32;
653 sca_rcvbuf
[3] = 0x10;
654 sca_rcvbuf
[4] = 0x70;
657 /* read socket; 0 is returned if no data is available */
658 nbytes
= sim_read_sock(sca_sock
, sca_rcvbuf
, SCA_RCVBUF_SIZE
);
664 else /* zero or more */
667 #if (DEBUG_SCA & DEBUG_SCA_CHECK_INDATA)
669 printf("* SCA_CHECK_INDATA %d byte%s\n", sca_nrcvd
, (sca_nrcvd
== 1) ? "" : "s");
673 /*********************************************************************************************
674 * sca_svc - handled scheduled event. This will presumably be scheduled frequently, and can check
675 * for incoming data, reasonableness of initiating a write interrupt, timeouts etc.
676 *********************************************************************************************/
678 static t_stat
sca_svc (UNIT
*uptr
)
684 /* if not connected, and if in wait-for-connection mode, check for connection attempt */
685 if ((sca_unit
.flags
& UNIT_LISTEN
) && ! (sca_dsw
& SCA_DSW_READY
))
688 if (any_timer_running
) {
689 msec_now
= sim_os_msec();
692 for (i
= 0; i
< 3; i
++) {
693 if (sca_timer_state
[i
] == SCA_TIMER_RUNNING
&& msec_now
>= sca_timer_endtime
[i
]) {
695 sca_timer_state
[i
] = SCA_TIMER_TIMEDOUT
;
696 #if (DEBUG_SCA & DEBUG_SCA_TIMERS)
697 printf("+ SCA_TIMER %d timed out\n", i
);
700 if (i
== TIMER_035S
&& sca_timer_trigger
) {
701 sca_timer_trigger
= FALSE
; /* uninhibit the other two timers */
702 sca_toggle_timer(TIMER_3S
, msec_now
);
703 sca_toggle_timer(TIMER_125S
, msec_now
);
709 sca_interrupt(SCA_DSW_TIMEOUT
);
711 any_timer_running
= (sca_timer_state
[0]| sca_timer_state
[1] | sca_timer_state
[2]) & SCA_TIMER_RUNNING
;
714 if (sca_dsw
& SCA_DSW_READY
) { /* if connected */
716 /* if rcvd data buffer is empty, and if in one of the receive states, checÄk for arrival of received data */
717 if (in_receive_state() && sca_rcvptr
>= sca_nrcvd
)
724 case SCA_STATE_TURN_SEND
:
725 /* has enough time gone by yet? if so... */
726 sca_state
= SCA_STATE_SEND1
;
727 sca_interrupt(SCA_DSW_WRITE_RESPONSE
);
730 case SCA_STATE_SEND_SYNC
:
731 sca_transmit_byte(sichar
);
734 case SCA_STATE_SEND1
:
735 sca_transmit_byte(sichar
); /* character interval has passed with no character written? character gap check */
736 sca_interrupt(SCA_DSW_CHECK
); /* send an idle character (maybe? for socket IO maybe send nothing) and interrupt */
738 if (idles_since_last_write
>= 0) {
739 if (++idles_since_last_write
>= SCA_IDLE_THRESHHOLD
) {
741 idles_since_last_write
= -1; /* don't send a short packet again until real data gets written again */
742 sca_nsyns
= 0; /* resume sending syns if output starts up again */
747 case SCA_STATE_SEND2
:
748 sca_state
= SCA_STATE_SEND1
; /* character has been sent. Schedule another transmit */
749 sca_interrupt(SCA_DSW_WRITE_RESPONSE
);
752 case SCA_STATE_TURN_RECEIVE
:
753 /* has enough time gone by yet? if so... */
754 sca_state
= SCA_STATE_RECEIVE_SYNC
; /* assume a character is coming in */
757 case SCA_STATE_RECEIVE_SYNC
:
758 if (sca_rcvptr
< sca_nrcvd
) {
759 rcvd_char
= sca_rcvbuf
[sca_rcvptr
++];
760 #if (DEBUG_SCA & DEBUG_SCA_RECEIVE_SYNC)
761 printf("* SCA rcvd %02x %s\n", rcvd_char
, (rcvd_char
== sichar
) ? "sync1" : "ignored");
764 if (rcvd_char
== sichar
) /* count the SYN but don't interrupt */
765 sca_state
= SCA_STATE_RECEIVE_SYNC2
;
770 case SCA_STATE_RECEIVE_SYNC2
:
771 if (sca_rcvptr
< sca_nrcvd
) {
772 rcvd_char
= sca_rcvbuf
[sca_rcvptr
++];
773 #if (DEBUG_SCA & DEBUG_SCA_RECEIVE_SYNC)
774 printf("* SCA rcvd %02x %s\n", rcvd_char
, (rcvd_char
== sichar
) ? "sync2" : "ignored");
777 if (rcvd_char
== sichar
) /* count the SYN but don't interrupt */
778 sca_state
= SCA_STATE_RECEIVE_SYNC3
;
783 case SCA_STATE_RECEIVE_SYNC3
:
784 case SCA_STATE_RECEIVE1
:
785 if (sca_rcvptr
< sca_nrcvd
) {
786 rcvd_char
= sca_rcvbuf
[sca_rcvptr
++];
788 if (sca_state
== SCA_STATE_RECEIVE_SYNC3
&& rcvd_char
== sichar
) {
789 /* we're ready for data, but we're still seeing SYNs */
790 #if (DEBUG_SCA & DEBUG_SCA_RECEIVE_SYNC)
791 printf("* SCA rcvd %02x extra sync\n", rcvd_char
);
795 #if (DEBUG_SCA & DEBUG_SCA_RECEIVE_DATA)
796 printf("* SCA rcvd %02x\n", rcvd_char
);
798 sca_interrupt(SCA_DSW_READ_RESPONSE
);
799 sca_state
= SCA_STATE_RECEIVE2
;
802 /* otherwise remain in state until data becomes available */
805 case SCA_STATE_RECEIVE2
: /* if we are still in this state when another service interval has passed */
806 if (sca_rcvptr
< sca_nrcvd
) {
807 rcvd_char
= sca_rcvbuf
[sca_rcvptr
++];
809 sca_interrupt(SCA_DSW_CHECK
); /* overrun error */
810 sca_state
= SCA_STATE_RECEIVE1
; /* another character will come soon */
815 printf("Simulator error: unknown state %d in sca_svc\n", sca_state
);
816 sca_state
= SCA_STATE_IDLE
;
820 /* schedule service again */
821 sim_activate(&sca_unit
, (sca_state
== SCA_STATE_IDLE
) ? sca_iwait
: sca_cwait
);
826 /*********************************************************************************************
827 * sca_toggle_timer - toggle a given timer's running/inhibited state for XIO_CONTROL
828 *********************************************************************************************/
830 static void sca_toggle_timer (int n
, int msec_now
)
832 if (sca_timer_state
[n
] == SCA_TIMER_RUNNING
&& sca_timer_trigger
) {
833 sca_timer_state
[n
] = SCA_TIMER_INHIBITED
;
834 sca_timer_timeleft
[n
] = sca_timer_endtime
[n
] - msec_now
; /* save time left */
835 #if (DEBUG_SCA & DEBUG_SCA_TIMERS)
836 printf("+ SCA_TIMER %d inhibited\n", n
);
839 else if (sca_timer_state
[n
] == SCA_TIMER_INHIBITED
&& ! sca_timer_trigger
) {
840 sca_timer_state
[n
] = SCA_TIMER_RUNNING
;
841 sca_timer_endtime
[n
] = sca_timer_timeleft
[n
] + msec_now
; /* compute new endtime */
842 #if (DEBUG_SCA & DEBUG_SCA_TIMERS)
843 printf("+ SCA_TIMER %d uninhibited\n", n
);
848 static void sca_start_timer (int n
, int msec_now
)
850 sca_timer_state
[n
] = SCA_TIMER_RUNNING
;
851 sca_timer_endtime
[n
] = sca_timer_msec
[n
] + msec_now
;
852 any_timer_running
= TRUE
;
853 #if (DEBUG_SCA & DEBUG_SCA_TIMERS)
854 printf("+ SCA_TIMER %d started\n", n
);
858 static void sca_halt_timer (int n
)
860 #if (DEBUG_SCA & DEBUG_SCA_TIMERS)
861 if (sca_timer_state
[n
] != SCA_TIMER_INACTIVE
)
862 printf("+ SCA_TIMER %d stopped\n", n
);
865 sca_timer_state
[n
] = SCA_TIMER_INACTIVE
;
868 /*********************************************************************************************
869 * sca_start_transmit - initiate transmit mode, from XIO_INITR or XIO_CONTROL (sync mode)
870 *********************************************************************************************/
872 void sca_start_transmit (int32 iocc_addr
, int32 modify
)
875 sca_nsyns
= 0; /* reset SYN suppression */
877 /* Address bits are used to reset DSW conditions. */
879 if (modify
& 0x40) /* bit 9. If set, reset all conditions */
882 iocc_addr
&= 0xD800; /* look at just bits 0, 1, 3 and 4 */
883 if (iocc_addr
) { /* if set, these bits clear DSW conditions */
884 CLRBIT(sca_dsw
, iocc_addr
);
885 CLRBIT(ILSW
[1], ILSW_1_SCA
); /* and I assume clear the interrupt condition too? (Seems unlikely that INITW would */
886 } /* be used in an interrupt service routine before SENSE, but who knows?) */
888 if (! in_send_state()) {
889 sca_state
= SCA_STATE_TURN_SEND
; /* begin line turnaround */
892 sca_state
= SCA_STATE_SEND1
; /* line is */
893 sca_interrupt(SCA_DSW_WRITE_RESPONSE
);
896 SETBIT(sca_dsw
, SCA_DSW_BUSY
); /* SCA is now busy, in transmit mode */
898 sim_cancel(&sca_unit
);
899 sim_activate(&sca_unit
, sca_cwait
); /* start polling frequently */
902 /*********************************************************************************************
903 * xio_sca - handle SCA XIO command
904 *********************************************************************************************/
906 void xio_sca (int32 iocc_addr
, int32 func
, int32 modify
)
912 case XIO_READ
: /* ***** XIO_READ - store last-received character to memory */
913 #if (DEBUG_SCA & DEBUG_SCA_XIO_READ)
914 printf("SCA RD addr %04x mod %02x rcvd_char %02x\n", iocc_addr
, modify
, rcvd_char
);
916 if (modify
& 0x03) { /* bits 14 and 15 */
917 #if (DEBUG_SCA & DEBUG_SCA_XIO_READ)
918 printf("(rd diag)\n");
920 /* if either of low two modifier bits is set, reads diagnostic words. whatever that is */
923 WriteW(iocc_addr
, rcvd_char
<< 8); /* always return last received character */
925 /* note: in read mode, read w/o interrupt (or two reads after an interrupt) causes a check
926 * so here we have to check the current state and possibly cause an interrupt
927 * Failure to have read before another arrives (overrun) also causes a check.
930 if (sca_state
== SCA_STATE_RECEIVE2
)/* XIO_READ should only be done (and only once) after a character interrupt */
931 sca_state
= SCA_STATE_RECEIVE1
; /* assume another character is coming in -- wait for it */
933 sca_interrupt(SCA_DSW_CHECK
);
937 case XIO_WRITE
: /* ***** XIO_WRITE - transfer character from memory to output shift register */
938 #if (DEBUG_SCA & DEBUG_SCA_XIO_WRITE)
939 printf("SCA WRT addr %04x (%04x) mod %02x\n", iocc_addr
, M
[iocc_addr
& mem_mask
], modify
);
941 if (modify
& 0x01) { /* bit 15 */
942 /* clear audible alarm trigger */
943 #if (DEBUG_SCA & DEBUG_SCA_XIO_WRITE)
944 printf("(clr audible alarm trigger)\n");
947 /* else? or can they all operate in parallel? */
948 if (modify
& 0x02) { /* bit 14 */
949 /* set audible alarm trigger */
950 #if (DEBUG_SCA & DEBUG_SCA_XIO_WRITE)
951 printf("(set audible alarm trigger)\n");
955 if (modify
& 0x04) { /* bit 13 */
956 #if (DEBUG_SCA & DEBUG_SCA_XIO_WRITE)
957 printf("(set SYN)\n");
959 /* set sync/idle character */
960 sichar
= (uint8
) (ReadW(iocc_addr
) >> 8);
961 sca_nsyns
= 0; /* reset SYN suppression */
963 /* else? does presence of mod bit preclude sending a character? */
964 if ((modify
& 0x07) == 0) { /* no modifiers */
965 /* transmit character --
966 * note: in write mode, failure to write soon enough after a write response interrupt causes a check
967 * Also, writing w/o interrupt (or two writes after an interrupt) causes a check
968 * so again, here we have to check the state to be sure that a write is appropriate
970 * note that in this simulator, we transmit the character immediately on XIO_WRITE. Therefore,
971 * there is no need to delay an end-operation function (XIO_CONTROL bit 13) until after a character time
974 idles_since_last_write
= 0;
977 case SCA_STATE_SEND_SYNC
:
978 case SCA_STATE_SEND1
:
979 sca_transmit_byte((uint8
) (M
[iocc_addr
& mem_mask
] >> 8));
980 sca_state
= SCA_STATE_SEND2
;
981 sim_cancel(&sca_unit
);
982 sim_activate(&sca_unit
, sca_cwait
); /* schedule service after character write time */
985 case SCA_STATE_SEND2
:
986 sca_interrupt(SCA_DSW_CHECK
); /* write issued while a character is in progress out? write overrun */
989 case SCA_STATE_IDLE
: /* wrong time to issue a write, incorrect sca state */
992 sca_interrupt(SCA_DSW_CHECK
); /* ??? or does this just perform a line turnaround and start transmission? */
999 case XIO_CONTROL
: /* ***** XIO_CONTROL - manipulate interface state */
1000 #if (DEBUG_SCA & DEBUG_SCA_XIO_CONTROL)
1001 printf("SCA CTL addr %04x mod %02x\n", iocc_addr
, modify
);
1003 if (modify
& 0x80) { /* bit 8 */
1004 /* enable auto answer */
1005 #if (DEBUG_SCA & DEBUG_SCA_XIO_CONTROL)
1006 printf("(enable autoanswer)\n");
1008 SETBIT(sca_unit
.flags
, UNIT_AUTOANSWER
);
1009 SETBIT(sca_dsw
, SCA_DSW_AUTOANSWER_ENABLED
);
1012 if (modify
& 0x40) { /* bit 9 */
1013 /* disable auto answer */
1014 #if (DEBUG_SCA & DEBUG_SCA_XIO_CONTROL)
1015 printf("(disable autoanswer)\n");
1017 CLRBIT(sca_unit
.flags
, UNIT_AUTOANSWER
);
1018 CLRBIT(sca_dsw
, SCA_DSW_AUTOANSWER_ENABLED
);
1021 if (modify
& 0x20) { /* bit 10 */
1022 /* toggle timers, inhibit->run or run->inhibit */
1023 #if (DEBUG_SCA & (DEBUG_SCA_XIO_CONTROL|DEBUG_SCA_TIMERS))
1024 printf("(toggle timers)\n");
1026 msec_now
= sim_os_msec();
1029 sca_timer_trigger
= ! sca_timer_trigger
; /* toggle the timer trigger */
1030 if (sca_timer_trigger
) /* if we've just set it, we're stopping the other timers and */
1031 sca_start_timer(TIMER_035S
, msec_now
); /* starting the 0.35 sec timer */
1033 sca_halt_timer(TIMER_035S
);
1035 sca_toggle_timer(TIMER_3S
, msec_now
); /* toggle the 3 sec and 1.35 sec timers accordingly */
1036 sca_toggle_timer(TIMER_125S
, msec_now
);
1038 any_timer_running
= (sca_timer_state
[0]| sca_timer_state
[1] | sca_timer_state
[2]) & SCA_TIMER_RUNNING
;
1041 if (modify
& 0x10) { /* bit 11 */
1042 /* enable sync mode. See references to this in FC manual
1043 * In STR mode only, sends a constant stream of SYN's without any CPU intervention
1044 * In BSC mode, appears to start the 1.25 second timer and otherwise act like INITW?
1046 #if (DEBUG_SCA & DEBUG_SCA_XIO_CONTROL)
1047 printf("(enable sync mode)\n");
1050 if (in_bsc_mode()) { /* in bsc mode start the 1.25 second timer. not sure what resets it?!? */
1051 if (! in_send_state()) /* also may cause a line turnaround */
1052 sca_start_transmit(iocc_addr
, 0);
1054 sca_start_timer(TIMER_125S
, sim_os_msec());
1058 if (modify
& 0x08) { /* bit 12 */
1059 /* diagnostic mode. What does this do?!? */
1060 #if (DEBUG_SCA & DEBUG_SCA_XIO_CONTROL)
1061 printf("(diag mode)\n");
1065 if (modify
& 0x04) { /* bit 13 */
1066 /* end operation (reset adapter. See references to this in FC manual). In transmit mode the real adapter delays this
1067 * function until current character has been sent. We don't need to do that as the character got buffered for transmission
1068 * immediately on XIO_WRITE.
1071 #if (DEBUG_SCA & (DEBUG_SCA_XIO_CONTROL|DEBUG_SCA_XIO_INITR|DEBUG_SCA_XIO_INITW))
1072 printf("(end operation)\n");
1074 sca_state
= SCA_STATE_IDLE
;
1075 sca_timer_state
[0] = sca_timer_state
[1] = sca_timer_state
[2] = SCA_TIMER_INACTIVE
;
1076 any_timer_running
= FALSE
;
1077 sca_timer_trigger
= FALSE
;
1078 sca_nsyns
= 0; /* reset SYN suppression */
1079 CLRBIT(sca_dsw
, SCA_DSW_BUSY
);
1082 if (modify
& 0x02) { /* bit 14 */
1083 #if (DEBUG_SCA & DEBUG_SCA_XIO_CONTROL)
1084 printf("(6 bit frame)\n");
1086 /* set six bit character frame. This is reset to 8 bits at every line turnaround */
1090 if (modify
& 0x01) { /* bit 15 */
1091 #if (DEBUG_SCA & DEBUG_SCA_XIO_CONTROL)
1092 printf("(7 bit frame)\n");
1094 /* set seven bit character frame. This is reset to 8 bits at every line turnaround */
1101 case XIO_INITW
: /* ***** XIO_INITW - put SCA in transmit mode */
1102 #if (DEBUG_SCA & DEBUG_SCA_XIO_INITW)
1103 printf("SCA INITW addr %04x mod %02x\n", iocc_addr
, modify
);
1105 /* enter transmit mode. Causes line turnaround. Resets frame to 8 bits. */
1106 /* (may cause syncing, may involve a fixed timeout?) */
1108 sca_start_transmit(iocc_addr
, modify
); /* this code pulled out to a subroutine cuz transmit can be started from XIO_CONTROL too */
1111 case XIO_INITR
: /* ***** XIO_INITR - put SCA in receive mode */
1112 #if (DEBUG_SCA & DEBUG_SCA_XIO_INITR)
1113 printf("SCA INITR addr %04x mod %02x\n", iocc_addr
, modify
);
1117 sca_nrcvd
= sca_rcvptr
= 0; /* discard any data previously read! */
1118 sca_nsyns
= 0; /* reset SYN suppression */
1120 /* enter receive mode. Causes line turnaround (e.g. resets to 8 bit frame). Modifier bits are used here too */
1121 /* (may cause syncing, may involve a fixed timeout?) */
1124 if (! in_receive_state())
1125 sca_state
= SCA_STATE_TURN_RECEIVE
; /* begin line turnaround */
1127 sca_state
= SCA_STATE_RECEIVE_SYNC
;
1129 SETBIT(sca_dsw
, SCA_DSW_BUSY
); /* SCA is now busy, in receive mode */
1131 if (in_bsc_mode()) /* in BSC mode, start the 3 second timer when we enter receive mode */
1132 sca_start_timer(TIMER_3S
, sim_os_msec());
1136 case XIO_SENSE_DEV
: /* ***** XIO_SENSE_DEV - read device status word */
1137 #if (DEBUG_SCA & DEBUG_SCA_XIO_SENSE_DEV)
1138 printf("SCA SNS mod %02x dsw %04x\n", modify
, sca_dsw
);
1140 ACC
= sca_dsw
; /* return DSW in accumulator */
1142 if (modify
& 0x01) { /* bit 15: reset interrupts */
1143 #if (DEBUG_SCA & DEBUG_SCA_XIO_SENSE_DEV)
1144 printf("(reset interrupts)\n");
1146 CLRBIT(sca_dsw
, SCA_DSW_READ_RESPONSE
| SCA_DSW_WRITE_RESPONSE
| SCA_DSW_CHECK
| SCA_DSW_TIMEOUT
| SCA_DSW_AUTOANSWER_REQUEST
);
1147 CLRBIT(ILSW
[1], ILSW_1_SCA
);
1150 if (modify
& 0x02) { /* bit 14: restart running timers */
1151 #if (DEBUG_SCA & (DEBUG_SCA_XIO_SENSE_DEV|DEBUG_SCA_TIMERS))
1152 printf("(restart timers)\n");
1154 msec_now
= sim_os_msec(); /* restart "any running timer?" All three, really? */
1155 for (i
= 0; i
< 3; i
++)
1156 if (sca_timer_state
[i
] == SCA_TIMER_RUNNING
|| sca_timer_state
[i
] == SCA_TIMER_TIMEDOUT
)
1157 sca_start_timer(i
, msec_now
);
1162 sprintf(msg
, "Invalid SCA XIO function %x", func
);