1 /*
2  * Z80SIM  -  a Z80-CPU simulator
3  *
4  * Copyright (C) 1987-2019 by Udo Munk
5  *
6  * This module contains a complex I/O-simulation for running
7  * CP/M, MP/M, UCSD p-System, Fuzix ...
8  *
9  * Please note this doesn't emulate any hardware which
10  * ever existed, we've got all virtual circuits in here!
11  *
12  * History:
13  * 28-SEP-1987 Development on TARGON/35 with AT&T Unix System V.3
14  * 19-MAY-1989 Additions for CP/M 3.0 and MP/M
15  * 23-DEC-1990 Ported to COHERENT 3.0
16  * 10-JUN-1992 Some optimisation done
17  * 25-JUN-1992 Flush output of stdout only at every OUT to port 0
18  * 25-JUN-1992 Comments in english and ported to COHERENT 4.0
19  * 05-OCT-2006 modified to compile on modern POSIX OS's
20  * 18-NOV-2006 added a second harddisk
21  * 08-DEC-2006 modified MMU so that segment size can be configured
22  * 10-DEC-2006 started adding serial port for a passive TCP/IP socket
23  * 14-DEC-2006 started adding serial port for a client TCP/IP socket
24  * 25-DEC-2006 CPU speed option and 100 ticks interrupt
25  * 19-FEB-2007 improved networking
26  * 22-JUL-2007 added second FDC sector port for implementing large harddisks
27  * 30-OCT-2007 printer port returns EOF on input
28  * 03-SEP-2007 improved the clock chip for support of other OS's
29  * 19-SEP-2007 delay circuit modified to delay x * 10ms
30  * 05-DEC-2007 fixed socket shutdown issues for NetBSD
31  * 06-DEC-2007 added hardware control port to reset I/O, CPU and reboot and such
32  * 07-DEC-2007 conditional compile pipes for aux device, problems with Cygwin
33  * 17-DEC-2007 conditional compile async TCP/IP server, problems with Cygwin
34  * 03-FEB-2008 added hardware control port to reset CPU, MMU and abort sim
35  * 07-APR-2008 added port to set/get CPU speed
36  * 13-AUG-2008 work on console I/O busy waiting detection
37  * 24-AUG-2008 changed terminal line discipline to not add CR if LF send
38  * xx-OCT-2008 some improvements here and there
39  * xx-JAN-2014 some improvements here and there
40  * 02-MAR-2014 source cleanup and improvements
41  * 03-MAI-2014 improved network code, telnet negotiation rewritten
42  * 16-JUL-2014 unused I/O ports need to return FF, see survey.mac
43  * 17-SEP-2014 FDC error 8 for DMA overrun, as reported by Alan Cox
44  * 17-SEP-2014 fixed bug in MMU bank select, as reported by Alan Cox
45  * 31-JAN-2015 took over some improvements made for the Z-1 emulation
46  * 28-FEB-2015 cleanup for 1.25 release
47  * 09-MAR-2016 moved pipes to /tmp/.z80pack
48  * 14-MAR-2016 renamed the used disk images to drivex.dsk
49  * 12-MAY-2016 find disk images at -d <path>, ./disks and DISKSDIR
50  * 22-JUL-2016 added support for read only disks
51  * 21-DEC-2016 moved MMU out to the new memory interface module
52  * 20-MAR-2017 renamed pipes for auxin/auxout
53  * 29-JUN-2017 system reset overworked
54  * 24-APR-2018 cleanup
55  * 17-MAY-2018 improved hardware control
56  * 10-JUN-2018 modified boot code for early loading of files
57  * 30-MAR-2019 added two more 4MB HD's
58  * 08-OCT-2019 (Mike Douglas) added OUT 161 trap to simbdos.c for host file I/O
59  * 24-OCT-2019 move RTC to I/O module for usage by any machine
60  */
61 
62 /*
63  *	This module contains the I/O handlers for a simulation
64  *	of the hardware required for a CP/M / MP/M system.
65  *
66  *	Used I/O ports:
67  *
68  *	 0 - console status
69  *	 1 - console data
70  *
71  *	 2 - printer status
72  *	 3 - printer data
73  *
74  *	 4 - auxiliary status
75  *	 5 - auxiliary data
76  *
77  *	10 - FDC drive
78  *	11 - FDC track
79  *	12 - FDC sector (low)
80  *	13 - FDC command
81  *	14 - FDC status
82  *
83  *	15 - DMA destination address low
84  *	16 - DMA destination address high
85  *
86  *	17 - FDC sector high
87  *
88  *	20 - MMU initialisation
89  *	21 - MMU bank select
90  *	22 - MMU select segment size (in pages a 256 bytes)
91  *	23 - MMU write protect/unprotect common memory segment
92  *
93  *	25 - clock command
94  *	26 - clock data
95  *	27 - 10ms timer causing maskable interrupt
96  *	28 - x * 10ms delay circuit for busy waiting loops
97  *	30 - CPU speed low
98  *	31 - CPU speed high
99  *
100  *	40 - passive socket #1 status
101  *	41 - passive socket #1 data
102  *	42 - passive socket #2 status
103  *	43 - passive socket #2 data
104  *	44 - passive socket #3 status
105  *	45 - passive socket #3 data
106  *	46 - passive socket #4 status
107  *	47 - passive socket #4 data
108  *
109  *	50 - client socket #1 status
110  *	51 - client socket #1 data
111  *
112  *	160 - hardware control
113  */
114 
115 #include <unistd.h>
116 #include <stdlib.h>
117 #include <stdio.h>
118 #include <errno.h>
119 #include <string.h>
120 #include <signal.h>
121 #include <fcntl.h>
122 #include <netdb.h>
123 #include <sys/stat.h>
124 #include <sys/file.h>
125 #include <sys/time.h>
126 #include <sys/types.h>
127 #include <sys/socket.h>
128 #include <sys/poll.h>
129 #include <netinet/in.h>
130 #include <netinet/tcp.h>
131 #include "sim.h"
132 #include "simglb.h"
133 #include "simbdos.h"
134 #include "memory.h"
135 /* #define LOG_LOCAL_LEVEL LOG_DEBUG */
136 #include "log.h"
137 #include "../../iodevices/rtc.h"
138 
139 #define BUFSIZE 256		/* max line length of command buffer */
140 #define MAX_BUSY_COUNT 10	/* max counter to detect I/O busy waiting
141 				   on the console status port */
142 
143 extern int boot(int);
144 extern void reset_cpu(void);
145 
146 static const char *TAG = "IO";
147 
148 static BYTE drive;		/* current drive A..P (0..15) */
149 static BYTE track;		/* current track (0..255) */
150 static unsigned int sector;	/* current sector (0..65535) */
151 static BYTE status;		/* status of last I/O operation on FDC */
152 static BYTE dmadl;		/* current DMA address destination low */
153 static BYTE dmadh;		/* current DMA address destination high */
154 static BYTE timer;		/* 10ms timer */
155 static int drivea;		/* fd for file "drivea.dsk" */
156 static int driveb;		/* fd for file "driveb.dsk" */
157 static int drivec;		/* fd for file "drivec.dsk" */
158 static int drived;		/* fd for file "drived.dsk" */
159 static int drivee;		/* fd for file "drivee.dsk" */
160 static int drivef;		/* fd for file "drivef.dsk" */
161 static int driveg;		/* fd for file "driveg.dsk" */
162 static int driveh;		/* fd for file "driveh.dsk" */
163 static int drivei;		/* fd for file "drivei.dsk" */
164 static int drivej;		/* fd for file "drivej.dsk" */
165 static int drivek;		/* fd for file "drivek.dsk" */
166 static int drivel;		/* fd for file "drivel.dsk" */
167 static int drivem;		/* fd for file "drivem.dsk" */
168 static int driven;		/* fd for file "driven.dsk" */
169 static int driveo;		/* fd for file "driveo.dsk" */
170 static int drivep;		/* fd for file "drivep.dsk" */
171 static int printer;		/* fd for file "printer.txt" */
172 static char fn[MAX_LFN];	/* path/filename for disk images */
173 static int speed;		/* to reset CPU speed */
174 static BYTE hwctl_lock = 0xff;	/* lock status hardware control port */
175 
176 #ifdef PIPES
177 static int auxin;		/* fd for pipe "auxin" */
178 static int auxout;		/* fd for pipe "auxout" */
179 static int aux_in_eof;		/* status of pipe "auxin" (<>0 means EOF) */
180 static int pid_rec;		/* PID of the receiving process for auxiliary */
181 #else
182 static int aux_in;		/* fd for file "auxiliaryin.txt" */
183 static int aux_in_lf;		/* linefeed flag for aux_in */
184 static int aux_out;		/* fd for file "auxiliaryout.txt" */
185 #endif
186 
187 #ifdef NETWORKING
188 
189 #define TELNET_TIMEOUT 800	/* telnet negotiation timeout in milliseconds */
190 
191 static int ss[NUMSOC];		/* server socket descriptors */
192 static int ssc[NUMSOC];		/* connected server socket descriptors */
193 static int ss_port[NUMSOC];	/* TCP/IP port for server sockets */
194 static int ss_telnet[NUMSOC];	/* telnet protocol flag for server sockets */
195 static int cs;			/* client socket #1 descriptor */
196 static int cs_port;		/* TCP/IP port for cs */
197 static char cs_host[BUFSIZE];	/* hostname for cs */
198 
199 #ifdef CNETDEBUG
200 static int cdirection = -1; /* protocol direction, 0 = send, 1 = receive */
201 #endif
202 
203 #ifdef SNETDEBUG
204 static int sdirection = -1; /* protocol direction, 0 = send 1 = receive */
205 #endif
206 
207 #endif
208 
209 struct dskdef disks[16] = {
210 	{ "drivea.dsk", &drivea, 77, 26 },
211 	{ "driveb.dsk", &driveb, 77, 26 },
212 	{ "drivec.dsk", &drivec, 77, 26 },
213 	{ "drived.dsk", &drived, 77, 26 },
214 	{ "drivee.dsk", &drivee, -1, -1 },
215 	{ "drivef.dsk", &drivef, -1, -1 },
216 	{ "driveg.dsk", &driveg, -1, -1 },
217 	{ "driveh.dsk", &driveh, -1, -1 },
218 	{ "drivei.dsk", &drivei, 255, 128 },
219 	{ "drivej.dsk", &drivej, 255, 128 },
220 	{ "drivek.dsk", &drivek, 255, 128 },
221 	{ "drivel.dsk", &drivel, 255, 128 },
222 	{ "drivem.dsk", &drivem, -1, -1 },
223 	{ "driven.dsk", &driven, -1, -1 },
224 	{ "driveo.dsk", &driveo, -1, -1 },
225 	{ "drivep.dsk", &drivep, 256, 16384 }
226 };
227 
228 /*
229  *	Forward declaration of the I/O handlers for all used ports
230  */
231 static BYTE io_trap_in(void);
232 static void io_trap_out(BYTE);
233 static BYTE cond_in(void), cons_in(void);
234 static void cond_out(BYTE), cons_out(BYTE);
235 static BYTE prtd_in(void), prts_in(void);
236 static void prtd_out(BYTE), prts_out(BYTE);
237 static BYTE auxd_in(void), auxs_in(void);
238 static void auxd_out(BYTE), auxs_out(BYTE);
239 static BYTE fdcd_in(void);
240 static void fdcd_out(BYTE);
241 static BYTE fdct_in(void);
242 static void fdct_out(BYTE);
243 static BYTE fdcs_in(void);
244 static void fdcs_out(BYTE);
245 static BYTE fdcsh_in(void);
246 static void fdcsh_out(BYTE);
247 static BYTE fdco_in(void);
248 static void fdco_out(BYTE);
249 static BYTE fdcx_in(void);
250 static void fdcx_out(BYTE);
251 static BYTE dmal_in(void);
252 static void dmal_out(BYTE);
253 static BYTE dmah_in(void);
254 static void dmah_out(BYTE);
255 static BYTE mmui_in(void), mmus_in(void), mmuc_in(void);
256 static void mmui_out(BYTE), mmus_out(BYTE), mmuc_out(BYTE);
257 static BYTE mmup_in(void);
258 static void mmup_out(BYTE);
259 static BYTE time_in(void);
260 static void time_out(BYTE);
261 static BYTE delay_in(void);
262 static void delay_out(BYTE);
263 static BYTE hwctl_in(void);
264 static void hwctl_out(BYTE);
265 static BYTE speedl_in(void), speedh_in(void);
266 static void speedl_out(BYTE), speedh_out(BYTE);
267 static BYTE cond1_in(void), cons1_in(void);
268 static void cond1_out(BYTE), cons1_out(BYTE);
269 static BYTE cond2_in(void), cons2_in(void);
270 static void cond2_out(BYTE), cons2_out(BYTE);
271 static BYTE cond3_in(void), cons3_in(void);
272 static void cond3_out(BYTE), cons3_out(BYTE);
273 static BYTE cond4_in(void), cons4_in(void);
274 static void cond4_out(BYTE), cons4_out(BYTE);
275 static BYTE netd1_in(void), nets1_in(void);
276 static void netd1_out(BYTE), nets1_out(BYTE);
277 
278 /*
279  *	Forward declaration of support functions
280  */
281 static void int_timer(int);
282 
283 #ifdef NETWORKING
284 static void net_server_config(void), net_client_config(void);
285 static void init_server_socket(int), telnet_negotiation(int);
286 #ifdef TCPASYNC
287 static void int_io(int);
288 #endif
289 #endif
290 
291 /*
292  *	This array contains function pointers for every
293  *	input port.
294  */
295 static BYTE (*port_in[256]) (void) = {
296 	cons_in,		/* port 0 */
297 	cond_in,		/* port 1 */
298 	prts_in,		/* port 2 */
299 	prtd_in,		/* port 3 */
300 	auxs_in,		/* port 4 */
301 	auxd_in,		/* port 5 */
302 	io_trap_in,		/* port 6 */
303 	io_trap_in,		/* port 7 */
304 	io_trap_in,		/* port 8 */
305 	io_trap_in,		/* port 9 */
306 	fdcd_in,		/* port 10 */
307 	fdct_in,		/* port 11 */
308 	fdcs_in,		/* port 12 */
309 	fdco_in,		/* port 13 */
310 	fdcx_in,		/* port 14 */
311 	dmal_in,		/* port 15 */
312 	dmah_in,		/* port 16 */
313 	fdcsh_in,		/* port 17 */
314 	io_trap_in,		/* port 18 */
315 	io_trap_in,		/* port 19 */
316 	mmui_in,		/* port 20 */
317 	mmus_in,		/* port 21 */
318 	mmuc_in,		/* port 22 */
319 	mmup_in,		/* port 23 */
320 	io_trap_in,		/* port 24 */
321 	clkc_in,		/* port 25 */
322 	clkd_in,		/* port 26 */
323 	time_in,		/* port 27 */
324 	delay_in,		/* port 28 */
325 	io_trap_in,		/* port 29 */
326 	speedl_in,		/* port 30 */
327 	speedh_in,		/* port 31 */
328 	io_trap_in,		/* port 32 */
329 	io_trap_in,		/* port 33 */
330 	io_trap_in,		/* port 34 */
331 	io_trap_in,		/* port 35 */
332 	io_trap_in,		/* port 36 */
333 	io_trap_in,		/* port 37 */
334 	io_trap_in,		/* port 38 */
335 	io_trap_in,		/* port 39 */
336 	cons1_in,		/* port 40 */
337 	cond1_in,		/* port 41 */
338 	cons2_in,		/* port 42 */
339 	cond2_in,		/* port 43 */
340 	cons3_in,		/* port 44 */
341 	cond3_in,		/* port 45 */
342 	cons4_in,		/* port 46 */
343 	cond4_in,		/* port 47 */
344 	io_trap_in,		/* port 48 */
345 	io_trap_in,		/* port 49 */
346 	nets1_in,		/* port 50 */
347 	netd1_in,		/* port 51 */
348 	io_trap_in,		/* port 52 */
349 	io_trap_in,		/* port 53 */
350 	io_trap_in,		/* port 54 */
351 	io_trap_in,		/* port	55 */
352 	io_trap_in,		/* port	56 */
353 	io_trap_in,		/* port	57 */
354 	io_trap_in,		/* port	58 */
355 	io_trap_in,		/* port	59 */
356 	io_trap_in,		/* port	60 */
357 	io_trap_in,		/* port	61 */
358 	io_trap_in,		/* port	62 */
359 	io_trap_in,		/* port	63 */
360 	io_trap_in,		/* port	64 */
361 	io_trap_in,		/* port	65 */
362 	io_trap_in,		/* port	66 */
363 	io_trap_in,		/* port	67 */
364 	io_trap_in,		/* port	68 */
365 	io_trap_in,		/* port	69 */
366 	io_trap_in,		/* port	70 */
367 	io_trap_in,		/* port	71 */
368 	io_trap_in,		/* port	72 */
369 	io_trap_in,		/* port	73 */
370 	io_trap_in,		/* port	74 */
371 	io_trap_in,		/* port	75 */
372 	io_trap_in,		/* port	76 */
373 	io_trap_in,		/* port	77 */
374 	io_trap_in,		/* port	78 */
375 	io_trap_in,		/* port	79 */
376 	io_trap_in,		/* port	80 */
377 	io_trap_in,		/* port	81 */
378 	io_trap_in,		/* port	82 */
379 	io_trap_in,		/* port	83 */
380 	io_trap_in,		/* port	84 */
381 	io_trap_in,		/* port	85 */
382 	io_trap_in,		/* port	86 */
383 	io_trap_in,		/* port	87 */
384 	io_trap_in,		/* port	88 */
385 	io_trap_in,		/* port	89 */
386 	io_trap_in,		/* port	90 */
387 	io_trap_in,		/* port	91 */
388 	io_trap_in,		/* port	92 */
389 	io_trap_in,		/* port	93 */
390 	io_trap_in,		/* port	94 */
391 	io_trap_in,		/* port	95 */
392 	io_trap_in,		/* port	96 */
393 	io_trap_in,		/* port	97 */
394 	io_trap_in,		/* port	98 */
395 	io_trap_in,		/* port	99 */
396 	io_trap_in,		/* port	100 */
397 	io_trap_in,		/* port 101 */
398 	io_trap_in,		/* port	102 */
399 	io_trap_in,		/* port	103 */
400 	io_trap_in,		/* port	104 */
401 	io_trap_in,		/* port	105 */
402 	io_trap_in,		/* port	106 */
403 	io_trap_in,		/* port	107 */
404 	io_trap_in,		/* port	108 */
405 	io_trap_in,		/* port	109 */
406 	io_trap_in,		/* port	110 */
407 	io_trap_in,		/* port	111 */
408 	io_trap_in,		/* port	112 */
409 	io_trap_in,		/* port	113 */
410 	io_trap_in,		/* port	114 */
411 	io_trap_in,		/* port	115 */
412 	io_trap_in,		/* port	116 */
413 	io_trap_in,		/* port	117 */
414 	io_trap_in,		/* port	118 */
415 	io_trap_in,		/* port	119 */
416 	io_trap_in,		/* port	120 */
417 	io_trap_in,		/* port	121 */
418 	io_trap_in,		/* port	122 */
419 	io_trap_in,		/* port	123 */
420 	io_trap_in,		/* port	124 */
421 	io_trap_in,		/* port	125 */
422 	io_trap_in,		/* port	126 */
423 	io_trap_in,		/* port	127 */
424 	io_trap_in,		/* port	128 */
425 	io_trap_in,		/* port	129 */
426 	io_trap_in,		/* port	130 */
427 	io_trap_in,		/* port	131 */
428 	io_trap_in,		/* port	132 */
429 	io_trap_in,		/* port	133 */
430 	io_trap_in,		/* port	134 */
431 	io_trap_in,		/* port	135 */
432 	io_trap_in,		/* port	136 */
433 	io_trap_in,		/* port	137 */
434 	io_trap_in,		/* port	138 */
435 	io_trap_in,		/* port	139 */
436 	io_trap_in,		/* port	140 */
437 	io_trap_in,		/* port	141 */
438 	io_trap_in,		/* port	142 */
439 	io_trap_in,		/* port	143 */
440 	io_trap_in,		/* port	144 */
441 	io_trap_in,		/* port	145 */
442 	io_trap_in,		/* port	146 */
443 	io_trap_in,		/* port	147 */
444 	io_trap_in,		/* port	148 */
445 	io_trap_in,		/* port	149 */
446 	io_trap_in,		/* port	150 */
447 	io_trap_in,		/* port	151 */
448 	io_trap_in,		/* port	152 */
449 	io_trap_in,		/* port	153 */
450 	io_trap_in,		/* port	154 */
451 	io_trap_in,		/* port	155 */
452 	io_trap_in,		/* port	156 */
453 	io_trap_in,		/* port	157 */
454 	io_trap_in,		/* port	158 */
455 	io_trap_in,		/* port	159 */
456 	hwctl_in,		/* port	160 */	/* virtual hardware control */
457 	io_trap_in,		/* port	161 */
458 	io_trap_in,		/* port	162 */
459 	io_trap_in,		/* port	163 */
460 	io_trap_in,		/* port	164 */
461 	io_trap_in,		/* port	165 */
462 	io_trap_in,		/* port	166 */
463 	io_trap_in,		/* port	167 */
464 	io_trap_in,		/* port	168 */
465 	io_trap_in,		/* port	169 */
466 	io_trap_in,		/* port	170 */
467 	io_trap_in,		/* port	171 */
468 	io_trap_in,		/* port	172 */
469 	io_trap_in,		/* port	173 */
470 	io_trap_in,		/* port	174 */
471 	io_trap_in,		/* port	175 */
472 	io_trap_in,		/* port	176 */
473 	io_trap_in,		/* port	177 */
474 	io_trap_in,		/* port	178 */
475 	io_trap_in,		/* port	179 */
476 	io_trap_in,		/* port	180 */
477 	io_trap_in,		/* port	181 */
478 	io_trap_in,		/* port	182 */
479 	io_trap_in,		/* port	183 */
480 	io_trap_in,		/* port	184 */
481 	io_trap_in,		/* port	185 */
482 	io_trap_in,		/* port	186 */
483 	io_trap_in,		/* port	187 */
484 	io_trap_in,		/* port	188 */
485 	io_trap_in,		/* port	189 */
486 	io_trap_in,		/* port	190 */
487 	io_trap_in,		/* port	191 */
488 	io_trap_in,		/* port	192 */
489 	io_trap_in,		/* port	193 */
490 	io_trap_in,		/* port	194 */
491 	io_trap_in,		/* port	195 */
492 	io_trap_in,		/* port	196 */
493 	io_trap_in,		/* port	197 */
494 	io_trap_in,		/* port	198 */
495 	io_trap_in,		/* port	199 */
496 	io_trap_in,		/* port	200 */
497 	io_trap_in,		/* port 201 */
498 	io_trap_in,		/* port	202 */
499 	io_trap_in,		/* port	203 */
500 	io_trap_in,		/* port	204 */
501 	io_trap_in,		/* port	205 */
502 	io_trap_in,		/* port	206 */
503 	io_trap_in,		/* port	207 */
504 	io_trap_in,		/* port	208 */
505 	io_trap_in,		/* port	209 */
506 	io_trap_in,		/* port	210 */
507 	io_trap_in,		/* port	211 */
508 	io_trap_in,		/* port	212 */
509 	io_trap_in,		/* port	213 */
510 	io_trap_in,		/* port	214 */
511 	io_trap_in,		/* port	215 */
512 	io_trap_in,		/* port	216 */
513 	io_trap_in,		/* port	217 */
514 	io_trap_in,		/* port	218 */
515 	io_trap_in,		/* port	219 */
516 	io_trap_in,		/* port	220 */
517 	io_trap_in,		/* port	221 */
518 	io_trap_in,		/* port	222 */
519 	io_trap_in,		/* port	223 */
520 	io_trap_in,		/* port	224 */
521 	io_trap_in,		/* port	225 */
522 	io_trap_in,		/* port	226 */
523 	io_trap_in,		/* port	227 */
524 	io_trap_in,		/* port	228 */
525 	io_trap_in,		/* port	229 */
526 	io_trap_in,		/* port	230 */
527 	io_trap_in,		/* port	231 */
528 	io_trap_in,		/* port	232 */
529 	io_trap_in,		/* port	233 */
530 	io_trap_in,		/* port	234 */
531 	io_trap_in,		/* port	235 */
532 	io_trap_in,		/* port	236 */
533 	io_trap_in,		/* port	237 */
534 	io_trap_in,		/* port	238 */
535 	io_trap_in,		/* port	239 */
536 	io_trap_in,		/* port	240 */
537 	io_trap_in,		/* port	241 */
538 	io_trap_in,		/* port	242 */
539 	io_trap_in,		/* port	243 */
540 	io_trap_in,		/* port	244 */
541 	io_trap_in,		/* port	245 */
542 	io_trap_in,		/* port	246 */
543 	io_trap_in,		/* port	247 */
544 	io_trap_in,		/* port	248 */
545 	io_trap_in,		/* port	249 */
546 	io_trap_in,		/* port	250 */
547 	io_trap_in,		/* port	251 */
548 	io_trap_in,		/* port	252 */
549 	io_trap_in,		/* port	253 */
550 	io_trap_in,		/* port	254 */
551 	io_trap_in		/* port	255 */
552 };
553 
554 /*
555  *	This array contains function pointers for every
556  *	output port.
557  */
558 static void (*port_out[256]) (BYTE) = {
559 	cons_out,		/* port 0 */
560 	cond_out,		/* port 1 */
561 	prts_out,		/* port 2 */
562 	prtd_out,		/* port 3 */
563 	auxs_out,		/* port 4 */
564 	auxd_out,		/* port 5 */
565 	io_trap_out,		/* port 6 */
566 	io_trap_out,		/* port 7 */
567 	io_trap_out,		/* port 8 */
568 	io_trap_out,		/* port 9 */
569 	fdcd_out,		/* port 10 */
570 	fdct_out,		/* port 11 */
571 	fdcs_out,		/* port 12 */
572 	fdco_out,		/* port 13 */
573 	fdcx_out,		/* port 14 */
574 	dmal_out,		/* port 15 */
575 	dmah_out,		/* port 16 */
576 	fdcsh_out,		/* port 17 */
577 	io_trap_out,		/* port 18 */
578 	io_trap_out,		/* port 19 */
579 	mmui_out,		/* port 20 */
580 	mmus_out,		/* port 21 */
581 	mmuc_out,		/* port 22 */
582 	mmup_out,		/* port 23 */
583 	io_trap_out,		/* port 24 */
584 	clkc_out,		/* port 25 */
585 	clkd_out,		/* port 26 */
586 	time_out,		/* port 27 */
587 	delay_out,		/* port 28 */
588 	io_trap_out,		/* port 29 */
589 	speedl_out,		/* port 30 */
590 	speedh_out,		/* port 31 */
591 	io_trap_out,		/* port 32 */
592 	io_trap_out,		/* port 33 */
593 	io_trap_out,		/* port 34 */
594 	io_trap_out,		/* port 35 */
595 	io_trap_out,		/* port 36 */
596 	io_trap_out,		/* port 37 */
597 	io_trap_out,		/* port 38 */
598 	io_trap_out,		/* port 39 */
599 	cons1_out,		/* port 40 */
600 	cond1_out,		/* port 41 */
601 	cons2_out,		/* port 42 */
602 	cond2_out,		/* port 43 */
603 	cons3_out,		/* port 44 */
604 	cond3_out,		/* port 45 */
605 	cons4_out,		/* port 46 */
606 	cond4_out,		/* port 47 */
607 	io_trap_out,		/* port 48 */
608 	io_trap_out,		/* port 49 */
609 	nets1_out,		/* port 50 */
610 	netd1_out,		/* port 51 */
611 	io_trap_out,		/* port 52 */
612 	io_trap_out,		/* port 53 */
613 	io_trap_out,		/* port 54 */
614 	io_trap_out,		/* port	55 */
615 	io_trap_out,		/* port	56 */
616 	io_trap_out,		/* port	57 */
617 	io_trap_out,		/* port	58 */
618 	io_trap_out,		/* port	59 */
619 	io_trap_out,		/* port	60 */
620 	io_trap_out,		/* port	61 */
621 	io_trap_out,		/* port	62 */
622 	io_trap_out,		/* port	63 */
623 	io_trap_out,		/* port	64 */
624 	io_trap_out,		/* port	65 */
625 	io_trap_out,		/* port	66 */
626 	io_trap_out,		/* port	67 */
627 	io_trap_out,		/* port	68 */
628 	io_trap_out,		/* port	69 */
629 	io_trap_out,		/* port	70 */
630 	io_trap_out,		/* port	71 */
631 	io_trap_out,		/* port	72 */
632 	io_trap_out,		/* port	73 */
633 	io_trap_out,		/* port	74 */
634 	io_trap_out,		/* port	75 */
635 	io_trap_out,		/* port	76 */
636 	io_trap_out,		/* port	77 */
637 	io_trap_out,		/* port	78 */
638 	io_trap_out,		/* port	79 */
639 	io_trap_out,		/* port	80 */
640 	io_trap_out,		/* port	81 */
641 	io_trap_out,		/* port	82 */
642 	io_trap_out,		/* port	83 */
643 	io_trap_out,		/* port	84 */
644 	io_trap_out,		/* port	85 */
645 	io_trap_out,		/* port	86 */
646 	io_trap_out,		/* port	87 */
647 	io_trap_out,		/* port	88 */
648 	io_trap_out,		/* port	89 */
649 	io_trap_out,		/* port	90 */
650 	io_trap_out,		/* port	91 */
651 	io_trap_out,		/* port	92 */
652 	io_trap_out,		/* port	93 */
653 	io_trap_out,		/* port	94 */
654 	io_trap_out,		/* port	95 */
655 	io_trap_out,		/* port	96 */
656 	io_trap_out,		/* port	97 */
657 	io_trap_out,		/* port	98 */
658 	io_trap_out,		/* port	99 */
659 	io_trap_out,		/* port	100 */
660 	io_trap_out,		/* port 101 */
661 	io_trap_out,		/* port	102 */
662 	io_trap_out,		/* port	103 */
663 	io_trap_out,		/* port	104 */
664 	io_trap_out,		/* port	105 */
665 	io_trap_out,		/* port	106 */
666 	io_trap_out,		/* port	107 */
667 	io_trap_out,		/* port	108 */
668 	io_trap_out,		/* port	109 */
669 	io_trap_out,		/* port	110 */
670 	io_trap_out,		/* port	111 */
671 	io_trap_out,		/* port	112 */
672 	io_trap_out,		/* port	113 */
673 	io_trap_out,		/* port	114 */
674 	io_trap_out,		/* port	115 */
675 	io_trap_out,		/* port	116 */
676 	io_trap_out,		/* port	117 */
677 	io_trap_out,		/* port	118 */
678 	io_trap_out,		/* port	119 */
679 	io_trap_out,		/* port	120 */
680 	io_trap_out,		/* port	121 */
681 	io_trap_out,		/* port	122 */
682 	io_trap_out,		/* port	123 */
683 	io_trap_out,		/* port	124 */
684 	io_trap_out,		/* port	125 */
685 	io_trap_out,		/* port	126 */
686 	io_trap_out,		/* port	127 */
687 	io_trap_out,		/* port	128 */
688 	io_trap_out,		/* port	129 */
689 	io_trap_out,		/* port	130 */
690 	io_trap_out,		/* port	131 */
691 	io_trap_out,		/* port	132 */
692 	io_trap_out,		/* port	133 */
693 	io_trap_out,		/* port	134 */
694 	io_trap_out,		/* port	135 */
695 	io_trap_out,		/* port	136 */
696 	io_trap_out,		/* port	137 */
697 	io_trap_out,		/* port	138 */
698 	io_trap_out,		/* port	139 */
699 	io_trap_out,		/* port	140 */
700 	io_trap_out,		/* port	141 */
701 	io_trap_out,		/* port	142 */
702 	io_trap_out,		/* port	143 */
703 	io_trap_out,		/* port	144 */
704 	io_trap_out,		/* port	145 */
705 	io_trap_out,		/* port	146 */
706 	io_trap_out,		/* port	147 */
707 	io_trap_out,		/* port	148 */
708 	io_trap_out,		/* port	149 */
709 	io_trap_out,		/* port	150 */
710 	io_trap_out,		/* port	151 */
711 	io_trap_out,		/* port	152 */
712 	io_trap_out,		/* port	153 */
713 	io_trap_out,		/* port	154 */
714 	io_trap_out,		/* port	155 */
715 	io_trap_out,		/* port	156 */
716 	io_trap_out,		/* port	157 */
717 	io_trap_out,		/* port	158 */
718 	io_trap_out,		/* port	159 */
719 	hwctl_out,		/* port	160 */	/* virtual hardware control */
720 	host_bdos_out,		/* port 161 */  /* host file I/O hook */
721 	io_trap_out,		/* port	162 */
722 	io_trap_out,		/* port	163 */
723 	io_trap_out,		/* port	164 */
724 	io_trap_out,		/* port	165 */
725 	io_trap_out,		/* port	166 */
726 	io_trap_out,		/* port	167 */
727 	io_trap_out,		/* port	168 */
728 	io_trap_out,		/* port	169 */
729 	io_trap_out,		/* port	170 */
730 	io_trap_out,		/* port	171 */
731 	io_trap_out,		/* port	172 */
732 	io_trap_out,		/* port	173 */
733 	io_trap_out,		/* port	174 */
734 	io_trap_out,		/* port	175 */
735 	io_trap_out,		/* port	176 */
736 	io_trap_out,		/* port	177 */
737 	io_trap_out,		/* port	178 */
738 	io_trap_out,		/* port	179 */
739 	io_trap_out,		/* port	180 */
740 	io_trap_out,		/* port	181 */
741 	io_trap_out,		/* port	182 */
742 	io_trap_out,		/* port	183 */
743 	io_trap_out,		/* port	184 */
744 	io_trap_out,		/* port	185 */
745 	io_trap_out,		/* port	186 */
746 	io_trap_out,		/* port	187 */
747 	io_trap_out,		/* port	188 */
748 	io_trap_out,		/* port	189 */
749 	io_trap_out,		/* port	190 */
750 	io_trap_out,		/* port	191 */
751 	io_trap_out,		/* port	192 */
752 	io_trap_out,		/* port	193 */
753 	io_trap_out,		/* port	194 */
754 	io_trap_out,		/* port	195 */
755 	io_trap_out,		/* port	196 */
756 	io_trap_out,		/* port	197 */
757 	io_trap_out,		/* port	198 */
758 	io_trap_out,		/* port	199 */
759 	io_trap_out,		/* port	200 */
760 	io_trap_out,		/* port 201 */
761 	io_trap_out,		/* port	202 */
762 	io_trap_out,		/* port	203 */
763 	io_trap_out,		/* port	204 */
764 	io_trap_out,		/* port	205 */
765 	io_trap_out,		/* port	206 */
766 	io_trap_out,		/* port	207 */
767 	io_trap_out,		/* port	208 */
768 	io_trap_out,		/* port	209 */
769 	io_trap_out,		/* port	210 */
770 	io_trap_out,		/* port	211 */
771 	io_trap_out,		/* port	212 */
772 	io_trap_out,		/* port	213 */
773 	io_trap_out,		/* port	214 */
774 	io_trap_out,		/* port	215 */
775 	io_trap_out,		/* port	216 */
776 	io_trap_out,		/* port	217 */
777 	io_trap_out,		/* port	218 */
778 	io_trap_out,		/* port	219 */
779 	io_trap_out,		/* port	220 */
780 	io_trap_out,		/* port	221 */
781 	io_trap_out,		/* port	222 */
782 	io_trap_out,		/* port	223 */
783 	io_trap_out,		/* port	224 */
784 	io_trap_out,		/* port	225 */
785 	io_trap_out,		/* port	226 */
786 	io_trap_out,		/* port	227 */
787 	io_trap_out,		/* port	228 */
788 	io_trap_out,		/* port	229 */
789 	io_trap_out,		/* port	230 */
790 	io_trap_out,		/* port	231 */
791 	io_trap_out,		/* port	232 */
792 	io_trap_out,		/* port	233 */
793 	io_trap_out,		/* port	234 */
794 	io_trap_out,		/* port	235 */
795 	io_trap_out,		/* port	236 */
796 	io_trap_out,		/* port	237 */
797 	io_trap_out,		/* port	238 */
798 	io_trap_out,		/* port	239 */
799 	io_trap_out,		/* port	240 */
800 	io_trap_out,		/* port	241 */
801 	io_trap_out,		/* port	242 */
802 	io_trap_out,		/* port	243 */
803 	io_trap_out,		/* port	244 */
804 	io_trap_out,		/* port	245 */
805 	io_trap_out,		/* port	246 */
806 	io_trap_out,		/* port	247 */
807 	io_trap_out,		/* port	248 */
808 	io_trap_out,		/* port	249 */
809 	io_trap_out,		/* port	250 */
810 	io_trap_out,		/* port	251 */
811 	io_trap_out,		/* port	252 */
812 	io_trap_out,		/* port	253 */
813 	io_trap_out,		/* port	254 */
814 	io_trap_out		/* port	255 */
815 };
816 
817 /*
818  *	This function initialises the I/O handlers:
819  *	1. Open the files which emulate the disk drives.
820  *	   Errors for opening one of the drives results
821  *	   in a NULL pointer for fd in the dskdef structure,
822  *	   so that this drive can't be used.
823  *	2. Creates the named pipes under /tmp/.z80pack, if they don't
824  *	   exist.
825  *	3. Fork the process for receiving from the auxiliary serial port.
826  *	4. Open the named pipes "auxin" and "auxout" for simulation
827  *	   of the auxiliary serial port.
828  *	5. Prepare TCP/IP sockets for serial port simulation
829  */
init_io(void)830 void init_io(void)
831 {
832 	register int i;
833 	struct stat sbuf;
834 #if defined(NETWORKING) && defined(TCPASYNC)
835 	static struct sigaction newact;
836 #endif
837 
838 	for (i = 0; i <= 15; i++) {
839 
840 		/* if option -d is used disks are there */
841 		if (diskdir != NULL) {
842 			strcpy(fn, diskd);
843 		} else {
844 			/* if not first try ./disks */
845 			if ((stat("./disks", &sbuf) == 0) &&
846 			    S_ISDIR(sbuf.st_mode)) {
847 				strcpy(fn, "./disks");
848 			/* nope, then DISKSDIR as set in Makefile */
849 			} else {
850 				strcpy(fn, DISKSDIR);
851 			}
852 		}
853 
854 		strcat(fn, "/");
855 		strcat(fn, disks[i].fn);
856 
857 		if ((*disks[i].fd = open(fn, O_RDWR)) == -1)
858 			if ((*disks[i].fd = open(fn, O_RDONLY)) == -1)
859 				disks[i].fd = NULL;
860 	}
861 
862 #ifdef PIPES
863 	/* check if /tmp/.z80pack exists */
864 	if (stat("/tmp/.z80pack", &sbuf) != 0)
865 		mkdir("/tmp/.z80pack", 0777);	/* no, create it */
866 	/* and then the pipes */
867 	if (stat("/tmp/.z80pack/cpmsim.auxin", &sbuf) != 0)
868 		mknod("/tmp/.z80pack/cpmsim.auxin", 0666 | S_IFIFO, 0);
869 	if (stat("/tmp/.z80pack/cpmsim.auxout", &sbuf) != 0)
870 		mknod("/tmp/.z80pack/cpmsim.auxout", 0666 | S_IFIFO, 0);
871 
872 	pid_rec = fork();
873 	switch (pid_rec) {
874 	case -1:
875 		LOGE(TAG, "can't fork");
876 		exit(1);
877 	case 0:
878 		/* . might not be in path, so check that first */
879 		if (access("./receive", X_OK) == 0)
880 			execlp("./receive", "receive", "auxiliaryout.txt",
881 				(char *) NULL);
882 		/* should be in path somewhere */
883 		else
884 			execlp("receive", "receive", "auxiliaryout.txt",
885 				(char *) NULL);
886 		/* if not cry and die */
887 		LOGE(TAG, "can't exec receive process, compile/install the tools dude");
888 		kill(0, SIGQUIT);
889 		exit(1);
890 	}
891 	if ((auxin = open("/tmp/.z80pack/cpmsim.auxin", O_RDONLY | O_NDELAY)) == -1) {
892 		LOGE(TAG, "can't open pipe auxin");
893 		exit(1);
894 	}
895 	if ((auxout = open("/tmp/.z80pack/cpmsim.auxout", O_WRONLY)) == -1) {
896 		LOGE(TAG, "can't open pipe auxout");
897 		exit(1);
898 	}
899 #endif
900 
901 #ifdef NETWORKING
902 	net_server_config();
903 	net_client_config();
904 
905 #ifdef TCPASYNC
906 	newact.sa_handler = int_io;
907 	memset((void *) &newact.sa_mask, 0, sizeof(newact.sa_mask));
908 	newact.sa_flags = 0;
909 	sigaction(SIGIO, &newact, NULL);
910 #endif
911 
912 	for (i = 0; i < NUMSOC; i++)
913 		init_server_socket(i);
914 #endif
915 }
916 
917 #ifdef NETWORKING
918 /*
919  * initialise a server socket
920  */
init_server_socket(int n)921 static void init_server_socket(int n)
922 {
923 	struct sockaddr_in sin;
924 	int on = 1;
925 #ifdef TCPASYNC
926 	int i;
927 #endif
928 
929 	if (ss_port[n] == 0)
930 		return;
931 	if ((ss[n] = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
932 		LOGE(TAG, "can't create server socket");
933 		exit(1);
934 	}
935 	if (setsockopt(ss[n], SOL_SOCKET, SO_REUSEADDR, (void *) &on,
936 	    sizeof(on)) == -1) {
937 		LOGE(TAG, "can't setsockopt SO_REUSEADDR on server socket");
938 		exit(1);
939 	}
940 #ifdef TCPASYNC
941 	fcntl(ss[n], F_SETOWN, getpid());
942 	i = fcntl(ss[n], F_GETFL, 0);
943 	if (fcntl(ss[n], F_SETFL, i | FASYNC) == -1) {
944 		LOGE(TAG, "can't fcntl FASYNC on server socket");
945 		exit(1);
946 	}
947 #endif
948 	memset((void *) &sin, 0, sizeof(sin));
949 	sin.sin_family = AF_INET;
950 	sin.sin_addr.s_addr = INADDR_ANY;
951 	sin.sin_port = htons(ss_port[n]);
952 	if (bind(ss[n], (struct sockaddr *) &sin, sizeof(sin)) == -1) {
953 		LOGE(TAG, "can't bind server socket");
954 		exit(1);
955 	}
956 	if (listen(ss[n], 0) == -1) {
957 		LOGE(TAG, "can't listen on server socket");
958 		exit(1);
959 	}
960 }
961 
962 /*
963  * Read and process network server configuration file
964  */
net_server_config(void)965 static void net_server_config(void)
966 {
967 	register int i;
968 	FILE *fp;
969 	char buf[BUFSIZE];
970 	char *s;
971 	char fn[MAX_LFN];
972 
973 	strcpy(&fn[0], &confdir[0]);
974 	strcat(&fn[0], "/net_server.conf");
975 
976 	if ((fp = fopen(fn, "r")) != NULL) {
977 		LOG(TAG, "Server network configuration:\n");
978 		s = &buf[0];
979 		while (fgets(s, BUFSIZE, fp) != NULL) {
980 			if ((*s == '\n') || (*s == '#'))
981 				continue;
982 			i = atoi(s);
983 			if ((i < 1) || (i > 4)) {
984 				LOGW(TAG, "console %d not supported", i);
985 				continue;
986 			}
987 			while((*s != ' ') && (*s != '\t'))
988 				s++;
989 			while((*s == ' ') || (*s == '\t'))
990 				s++;
991 			ss_telnet[i - 1] = atoi(s);
992 			while((*s != ' ') && (*s != '\t'))
993 				s++;
994 			while((*s == ' ') || (*s == '\t'))
995 				s++;
996 			ss_port[i - 1] = atoi(s);
997 			LOG(TAG, "console %d listening on port %d, telnet = %s\n",
998 			    i, ss_port[i - 1],
999 			    ((ss_telnet[i - 1] > 0) ? "on" : "off"));
1000 		}
1001 		fclose(fp);
1002 	}
1003 }
1004 
1005 /*
1006  * Read and process network client configuration file
1007  */
net_client_config(void)1008 static void net_client_config(void)
1009 {
1010 	FILE *fp;
1011 	char buf[BUFSIZE];
1012 	char *s, *d;
1013 	char fn[MAX_LFN];
1014 
1015 	strcpy(&fn[0], &confdir[0]);
1016 	strcat(&fn[0], "/net_client.conf");
1017 
1018 	if ((fp = fopen(fn, "r")) != NULL) {
1019 		LOG(TAG, "Client network configuration:\n");
1020 		s = &buf[0];
1021 		while (fgets(s, BUFSIZE, fp) != NULL) {
1022 			if ((*s == '\n') || (*s == '#'))
1023 				continue;
1024 			while((*s != ' ') && (*s != '\t'))
1025 				s++;
1026 			while((*s == ' ') || (*s == '\t'))
1027 				s++;
1028 			d = &cs_host[0];
1029 			while ((*s != ' ') && (*s != '\t'))
1030 				*d++ = *s++;
1031 			*d = '\0';
1032 			while((*s == ' ') || (*s == '\t'))
1033 				s++;
1034 			cs_port = atoi(s);
1035 			LOG(TAG, "Connecting to %s at port %d\n", cs_host,
1036 			    cs_port);
1037 		}
1038 		fclose(fp);
1039 	}
1040 }
1041 #endif
1042 
1043 /*
1044  *	This function stops the I/O handlers:
1045  *
1046  *	1. The files emulating the disk drives are closed.
1047  *	2. The file "printer.txt" emulating a printer is closed.
1048  *	3. The named pipes "auxin" and "auxout" are closed.
1049  *	4. All connected sockets are closed
1050  *	5. The receiving process for the aux serial port is stopped.
1051  */
exit_io(void)1052 void exit_io(void)
1053 {
1054 	register int i;
1055 
1056 	for (i = 0; i <= 15; i++)
1057 		if (disks[i].fd != NULL)
1058 			close(*disks[i].fd);
1059 
1060 	if (printer != 0)
1061 		close(printer);
1062 
1063 #ifdef PIPES
1064 	close(auxin);
1065 	close(auxout);
1066 	kill(pid_rec, SIGHUP);
1067 #endif
1068 
1069 #ifdef NETWORKING
1070 	for (i = 0; i < NUMSOC; i++)
1071 		if (ssc[i])
1072 			close(ssc[i]);
1073 	if (cs)
1074 		close(cs);
1075 #endif
1076 }
1077 
1078 /*
1079  *	reset the CPU and I/O system
1080  */
reset_system(void)1081 void reset_system(void)
1082 {
1083 	extern BYTE *wrk_ram;
1084 	register int i;
1085 
1086 	/* reset hardware */
1087 	time_out(0);			/* stop timer */
1088 
1089 	for (i = 1; i < MAXSEG; i++) {	/* reset MMU */
1090 		if (memory[i] != NULL) {
1091 			free(memory[i]);
1092 			memory[i] = NULL;
1093 		}
1094 	}
1095 	selbnk = 0;
1096 	segsize = SEGSIZ;
1097 
1098 	/* lock hardware control port */
1099 	hwctl_lock = 0xff;
1100 
1101 	/* reset CPU */
1102 	reset_cpu();
1103 	wrk_ram	= mem_base();
1104 
1105 	/* reboot */
1106 	boot(1);
1107 }
1108 
1109 /*
1110  *	This function is called for every IN opcode from the
1111  *	CPU emulation. It calls the handler for the port,
1112  *	from which input is wanted.
1113  */
io_in(BYTE addrl,BYTE addrh)1114 BYTE io_in(BYTE addrl, BYTE addrh)
1115 {
1116 	addrh = addrh;	/* to avoid compiler warning */
1117 
1118 	io_port = addrl;
1119 	io_data = (*port_in[addrl]) ();
1120 	return(io_data);
1121 }
1122 
1123 /*
1124  *	This function is called for every OUT opcode from the
1125  *	CPU emulation. It calls the handler for the port,
1126  *	to which output is wanted.
1127  */
io_out(BYTE addrl,BYTE addrh,BYTE data)1128 void io_out(BYTE addrl, BYTE addrh, BYTE data)
1129 {
1130 	addrh = addrh;	/* to avoid compiler warning */
1131 
1132 	io_port = addrl;
1133 	io_data = data;
1134 
1135 	busy_loop_cnt[0] = 0;
1136 
1137 	(*port_out[addrl]) (data);
1138 }
1139 
1140 /*
1141  *	I/O input trap handler
1142  */
io_trap_in(void)1143 static BYTE io_trap_in(void)
1144 {
1145 	if (i_flag) {
1146 		cpu_error = IOTRAPIN;
1147 		cpu_state = STOPPED;
1148 	}
1149 	return((BYTE) 0xff);
1150 }
1151 
1152 /*
1153  *	I/O output trap handler
1154  */
io_trap_out(BYTE data)1155 static void io_trap_out(BYTE data)
1156 {
1157 	data = data;	/* to avoid compiler warning */
1158 
1159 	if (i_flag) {
1160 		cpu_error = IOTRAPOUT;
1161 		cpu_state = STOPPED;
1162 	}
1163 }
1164 
1165 /*
1166  *	I/O handler for read console 0 status:
1167  *	0xff : input available
1168  *	0x00 : no input available
1169  */
cons_in(void)1170 static BYTE cons_in(void)
1171 {
1172 	struct pollfd p[1];
1173 
1174 	if (++busy_loop_cnt[0] >= MAX_BUSY_COUNT) {
1175 		SLEEP_MS(1);
1176 		busy_loop_cnt[0] = 0;
1177 	}
1178 
1179 	p[0].fd = fileno(stdin);
1180 	p[0].events = POLLIN;
1181 	p[0].revents = 0;
1182 	poll(p, 1, 0);
1183 	if (p[0].revents & POLLIN)
1184 		return((BYTE) 0xff);
1185 	else
1186 		return((BYTE) 0x00);
1187 }
1188 
1189 /*
1190  *	I/O handler for read console 1 status:
1191  *	bit 0 = 1: input available
1192  *	bit 1 = 1: output writable
1193  */
cons1_in(void)1194 static BYTE cons1_in(void)
1195 {
1196 	BYTE status = 0;
1197 #ifdef NETWORKING
1198 	struct pollfd p[1];
1199 
1200 #ifndef TCPASYNC
1201 	socklen_t alen;
1202 	struct sockaddr_in fsin;
1203 	int go_away;
1204 	int on = 1;
1205 
1206 	if (ss[0] == 0)
1207 		return(status);
1208 
1209 	p[0].fd = ss[0];
1210 	p[0].events = POLLIN;
1211 	p[0].revents = 0;
1212 	poll(p, 1, 0);
1213 
1214 	if (p[0].revents) {
1215 
1216 		alen = sizeof(fsin);
1217 
1218 		if (ssc[0] != 0) {
1219 			go_away = accept(ss[0],
1220 					 (struct sockaddr *)&fsin, &alen);
1221 			close(go_away);
1222 			goto ss0_done;
1223 		}
1224 
1225 		if ((ssc[0] = accept(ss[0], (struct sockaddr *)&fsin,
1226 		    &alen)) == -1) {
1227 			LOGW(TAG, "can't accept server socket");
1228 			ssc[0] = 0;
1229 		}
1230 
1231 		if (setsockopt(ssc[0], IPPROTO_TCP, TCP_NODELAY,
1232 		    (void *)&on, sizeof(on)) == -1) {
1233 			LOGW(TAG, "can't setsockopt TCP_NODELAY on server socket");
1234 		}
1235 
1236 		if (ss_telnet[0])
1237 			telnet_negotiation(ssc[0]);
1238 	}
1239 ss0_done:
1240 #endif
1241 
1242 	if (ssc[0] != 0) {
1243 		p[0].fd = ssc[0];
1244 		p[0].events = POLLIN | POLLOUT;
1245 		p[0].revents = 0;
1246 		poll(p, 1, 0);
1247 		if (p[0].revents & POLLHUP) {
1248 			close(ssc[0]);
1249 			ssc[0] = 0;
1250 			return(0);
1251 		}
1252 		if (p[0].revents & POLLIN)
1253 			status |= 1;
1254 		if (p[0].revents & POLLOUT)
1255 			status |= 2;
1256 	}
1257 #endif
1258 	return(status);
1259 }
1260 
1261 /*
1262  *	I/O handler for read console 2 status:
1263  *	bit 0 = 1: input available
1264  *	bit 1 = 1: output writable
1265  */
cons2_in(void)1266 static BYTE cons2_in(void)
1267 {
1268 	BYTE status = 0;
1269 #ifdef NETWORKING
1270 	struct pollfd p[1];
1271 
1272 #ifndef TCPASYNC
1273 	socklen_t alen;
1274 	struct sockaddr_in fsin;
1275 	int go_away;
1276 	int on = 1;
1277 
1278 	if (ss[1] == 0)
1279 		return(status);
1280 
1281 	p[0].fd = ss[1];
1282 	p[0].events = POLLIN;
1283 	p[0].revents = 0;
1284 	poll(p, 1, 0);
1285 
1286 	if (p[0].revents) {
1287 
1288 		alen = sizeof(fsin);
1289 
1290 		if (ssc[1] != 0) {
1291 			go_away = accept(ss[1],
1292 					 (struct sockaddr *)&fsin, &alen);
1293 			close(go_away);
1294 			goto ss1_done;
1295 		}
1296 
1297 		if ((ssc[1] = accept(ss[1], (struct sockaddr *)&fsin,
1298 		    &alen)) == -1) {
1299 			LOGW(TAG, "can't accept server socket");
1300 			ssc[1] = 0;
1301 		}
1302 
1303 		if (setsockopt(ssc[1], IPPROTO_TCP, TCP_NODELAY,
1304 		    (void *)&on, sizeof(on)) == -1) {
1305 			LOGW(TAG, "can't setsockopt TCP_NODELAY on server socket");
1306 		}
1307 
1308 		if (ss_telnet[1])
1309 			telnet_negotiation(ssc[1]);
1310 	}
1311 ss1_done:
1312 #endif
1313 
1314 	if (ssc[1] != 0) {
1315 		p[0].fd = ssc[1];
1316 		p[0].events = POLLIN | POLLOUT;
1317 		p[0].revents = 0;
1318 		poll(p, 1, 0);
1319 		if (p[0].revents & POLLHUP) {
1320 			close(ssc[1]);
1321 			ssc[1] = 0;
1322 			return(0);
1323 		}
1324 		if (p[0].revents & POLLIN)
1325 			status |= 1;
1326 		if (p[0].revents & POLLOUT)
1327 			status |= 2;
1328 	}
1329 #endif
1330 	return(status);
1331 }
1332 
1333 /*
1334  *	I/O handler for read console 3 status:
1335  *	bit 0 = 1: input available
1336  *	bit 1 = 1: output writable
1337  */
cons3_in(void)1338 static BYTE cons3_in(void)
1339 {
1340 	BYTE status = 0;
1341 #ifdef NETWORKING
1342 	struct pollfd p[1];
1343 
1344 #ifndef TCPASYNC
1345 	socklen_t alen;
1346 	struct sockaddr_in fsin;
1347 	int go_away;
1348 	int on = 1;
1349 
1350 	if (ss[2] == 0)
1351 		return(status);
1352 
1353 	p[0].fd = ss[2];
1354 	p[0].events = POLLIN;
1355 	p[0].revents = 0;
1356 	poll(p, 1, 0);
1357 
1358 	if (p[0].revents) {
1359 
1360 		alen = sizeof(fsin);
1361 
1362 		if (ssc[2] != 0) {
1363 			go_away = accept(ss[2],
1364 					 (struct sockaddr *)&fsin, &alen);
1365 			close(go_away);
1366 			goto ss2_done;
1367 		}
1368 
1369 		if ((ssc[2] = accept(ss[2], (struct sockaddr *)&fsin,
1370 		    &alen)) == -1) {
1371 			LOGW(TAG, "can't accept server socket");
1372 			ssc[2] = 0;
1373 		}
1374 
1375 		if (setsockopt(ssc[2], IPPROTO_TCP, TCP_NODELAY,
1376 		    (void *)&on, sizeof(on)) == -1) {
1377 			LOGW(TAG, "can't setsockopt TCP_NODELAY on server socket");
1378 		}
1379 
1380 		if (ss_telnet[2])
1381 			telnet_negotiation(ssc[2]);
1382 	}
1383 ss2_done:
1384 #endif
1385 
1386 	if (ssc[2] != 0) {
1387 		p[0].fd = ssc[2];
1388 		p[0].events = POLLIN | POLLOUT;
1389 		p[0].revents = 0;
1390 		poll(p, 1, 0);
1391 		if (p[0].revents & POLLHUP) {
1392 			close(ssc[2]);
1393 			ssc[2] = 0;
1394 			return(0);
1395 		}
1396 		if (p[0].revents & POLLIN)
1397 			status |= 1;
1398 		if (p[0].revents & POLLOUT)
1399 			status |= 2;
1400 	}
1401 #endif
1402 	return(status);
1403 }
1404 
1405 /*
1406  *	I/O handler for read console 4 status:
1407  *	bit 0 = 1: input available
1408  *	bit 1 = 1: output writable
1409  */
cons4_in(void)1410 static BYTE cons4_in(void)
1411 {
1412 	BYTE status = 0;
1413 #ifdef NETWORKING
1414 	struct pollfd p[1];
1415 
1416 #ifndef TCPASYNC
1417 	socklen_t alen;
1418 	struct sockaddr_in fsin;
1419 	int go_away;
1420 	int on = 1;
1421 
1422 	if (ss[3] == 0)
1423 		return(status);
1424 
1425 	p[0].fd = ss[3];
1426 	p[0].events = POLLIN;
1427 	p[0].revents = 0;
1428 	poll(p, 1, 0);
1429 
1430 	if (p[0].revents) {
1431 
1432 		alen = sizeof(fsin);
1433 
1434 		if (ssc[3] != 0) {
1435 			go_away = accept(ss[3],
1436 					 (struct sockaddr *)&fsin, &alen);
1437 			close(go_away);
1438 			goto ss3_done;
1439 		}
1440 
1441 		if ((ssc[3] = accept(ss[3], (struct sockaddr *)&fsin,
1442 		    &alen)) == -1) {
1443 			LOGW(TAG, "can't accept server socket");
1444 			ssc[3] = 0;
1445 		}
1446 
1447 		if (setsockopt(ssc[3], IPPROTO_TCP, TCP_NODELAY,
1448 		    (void *)&on, sizeof(on)) == -1) {
1449 			LOGW(TAG, "can't setsockopt TCP_NODELAY on server socket");
1450 		}
1451 
1452 		if (ss_telnet[3])
1453 			telnet_negotiation(ssc[3]);
1454 	}
1455 ss3_done:
1456 #endif
1457 
1458 	if (ssc[3] != 0) {
1459 		p[0].fd = ssc[3];
1460 		p[0].events = POLLIN | POLLOUT;
1461 		p[0].revents = 0;
1462 		poll(p, 1, 0);
1463 		if (p[0].revents & POLLHUP) {
1464 			close(ssc[3]);
1465 			ssc[3] = 0;
1466 			return(0);
1467 		}
1468 		if (p[0].revents & POLLIN)
1469 			status |= 1;
1470 		if (p[0].revents & POLLOUT)
1471 			status |= 2;
1472 	}
1473 #endif
1474 	return(status);
1475 }
1476 
1477 /*
1478  *	I/O handler for read client socket 1 status:
1479  *	bit 0 = 1: input available
1480  *	bit 1 = 1: output writable
1481  */
nets1_in(void)1482 static BYTE nets1_in(void)
1483 {
1484 	BYTE status = 0;
1485 #ifdef NETWORKING
1486 	struct sockaddr_in sin;
1487 	struct hostent *host;
1488 	struct pollfd p[1];
1489 	int on = 1;
1490 
1491 	if ((cs == 0) && (cs_port != 0)) {
1492 		host = gethostbyname(&cs_host[0]);
1493 		if ((cs = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
1494 			LOGE(TAG, "can't create client socket");
1495 			cpu_error = IOERROR;
1496 			cpu_state = STOPPED;
1497 			return((BYTE) 0);
1498 		}
1499 		memset((void *) &sin, 0, sizeof(sin));
1500 		memcpy((void *) &sin.sin_addr, (void *) host->h_addr, host->h_length);
1501 		sin.sin_family = AF_INET;
1502 		sin.sin_port = htons(cs_port);
1503 		if (connect(cs, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
1504 			LOGE(TAG, "can't connect client socket");
1505 			cpu_error = IOERROR;
1506 			cpu_state = STOPPED;
1507 			return((BYTE) 0);
1508 		}
1509 		if (setsockopt(cs, IPPROTO_TCP, TCP_NODELAY,
1510 		    (void *)&on, sizeof(on)) == -1) {
1511 			LOGW(TAG, "can't setsockopt TCP_NODELAY on client socket");
1512 		}
1513 	}
1514 
1515 	if (cs != 0) {
1516 		p[0].fd = cs;
1517 		p[0].events = POLLIN | POLLOUT;
1518 		p[0].revents = 0;
1519 		poll(p, 1, 0);
1520 		if (p[0].revents & POLLHUP) {
1521 			close(cs);
1522 			cs = 0;
1523 			return((BYTE) 0);
1524 		}
1525 		if (p[0].revents & POLLIN)
1526 			status |= 1;
1527 		if (p[0].revents & POLLOUT)
1528 			status |= 2;
1529 	}
1530 #endif
1531 	return(status);
1532 }
1533 
1534 /*
1535  *	I/O handler for write console 0 status:
1536  *	no function
1537  */
cons_out(BYTE data)1538 static void cons_out(BYTE data)
1539 {
1540 	data = data; /* to avoid compiler warning */
1541 }
1542 
1543 /*
1544  *	I/O handler for write console 1 status:
1545  *	no function
1546  */
cons1_out(BYTE data)1547 static void cons1_out(BYTE data)
1548 {
1549 	data = data; /* to avoid compiler warning */
1550 }
1551 
1552 /*
1553  *	I/O handler for write console 2 status:
1554  *	no function
1555  */
cons2_out(BYTE data)1556 static void cons2_out(BYTE data)
1557 {
1558 	data = data; /* to avoid compiler warning */
1559 }
1560 
1561 /*
1562  *	I/O handler for write console 3 status:
1563  *	no function
1564  */
cons3_out(BYTE data)1565 static void cons3_out(BYTE data)
1566 {
1567 	data = data; /* to avoid compiler warning */
1568 }
1569 
1570 /*
1571  *	I/O handler for write console 4 status:
1572  *	no function
1573  */
cons4_out(BYTE data)1574 static void cons4_out(BYTE data)
1575 {
1576 	data = data; /* to avoid compiler warning */
1577 }
1578 
1579 /*
1580  *	I/O handler for write client socket 1 status:
1581  *	no function
1582  */
nets1_out(BYTE data)1583 static void nets1_out(BYTE data)
1584 {
1585 	data = data; /* to avoid compiler warning */
1586 }
1587 
1588 /*
1589  *	I/O handler for read console 0 data
1590  */
cond_in(void)1591 static BYTE cond_in(void)
1592 {
1593 	char c;
1594 
1595 	busy_loop_cnt[0] = 0;
1596 	read(0, &c, 1);
1597 	return((BYTE) c);
1598 }
1599 
1600 /*
1601  *	I/O handler for read console 1 data
1602  */
cond1_in(void)1603 static BYTE cond1_in(void)
1604 {
1605 	char c;
1606 #ifdef NETWORKING
1607 	char x;
1608 
1609 	if (read(ssc[0], &c, 1) != 1) {
1610 		if ((errno == EAGAIN) || (errno == EINTR)) {
1611 			close(ssc[0]);
1612 			ssc[0] = 0;
1613 			return((BYTE) 0);
1614 		} else {
1615 			LOGE(TAG, "can't read console 1");
1616 			cpu_error = IOERROR;
1617 			cpu_state = STOPPED;
1618 			return((BYTE) 0);
1619 		}
1620 	}
1621 	if (ss_telnet[0] && (c == '\r'))
1622 		read(ssc[0], &x, 1);
1623 #ifdef SNETDEBUG
1624 	if (sdirection != 1) {
1625 		printf("\n<- ");
1626 		sdirection = 1;
1627 	}
1628 	printf("%02x ", (BYTE) c);
1629 #endif
1630 #else
1631 	c = 0;
1632 #endif
1633 	return((BYTE) c);
1634 }
1635 
1636 /*
1637  *	I/O handler for read console 2 data
1638  */
cond2_in(void)1639 static BYTE cond2_in(void)
1640 {
1641 	char c;
1642 #ifdef NETWORKING
1643 	char x;
1644 
1645 	if (read(ssc[1], &c, 1) != 1) {
1646 		if ((errno == EAGAIN) || (errno == EINTR)) {
1647 			close(ssc[1]);
1648 			ssc[1] = 0;
1649 			return((BYTE) 0);
1650 		} else {
1651 			LOGE(TAG, "can't read console 2");
1652 			cpu_error = IOERROR;
1653 			cpu_state = STOPPED;
1654 			return((BYTE) 0);
1655 		}
1656 	}
1657 	if (ss_telnet[1] && (c == '\r'))
1658 		read(ssc[1], &x, 1);
1659 #ifdef SNETDEBUG
1660 	if (sdirection != 1) {
1661 		printf("\n<- ");
1662 		sdirection = 1;
1663 	}
1664 	printf("%02x ", (BYTE) c);
1665 #endif
1666 #else
1667 	c = 0;
1668 #endif
1669 	return((BYTE) c);
1670 }
1671 
1672 /*
1673  *	I/O handler for read console 3 data
1674  */
cond3_in(void)1675 static BYTE cond3_in(void)
1676 {
1677 	char c;
1678 #ifdef NETWORKING
1679 	char x;
1680 
1681 	if (read(ssc[2], &c, 1) != 1) {
1682 		if ((errno == EAGAIN) || (errno == EINTR)) {
1683 			close(ssc[2]);
1684 			ssc[2] = 0;
1685 			return((BYTE) 0);
1686 		} else {
1687 			LOGE(TAG, "can't read console 3");
1688 			cpu_error = IOERROR;
1689 			cpu_state = STOPPED;
1690 			return((BYTE) 0);
1691 		}
1692 	}
1693 	if (ss_telnet[2] && (c == '\r'))
1694 		read(ssc[2], &x, 1);
1695 #ifdef SNETDEBUG
1696 	if (sdirection != 1) {
1697 		printf("\n<- ");
1698 		sdirection = 1;
1699 	}
1700 	printf("%02x ", (BYTE) c);
1701 #endif
1702 #else
1703 	c = 0;
1704 #endif
1705 	return((BYTE) c);
1706 }
1707 
1708 /*
1709  *	I/O handler for read console 4 data
1710  */
cond4_in(void)1711 static BYTE cond4_in(void)
1712 {
1713 	char c;
1714 #ifdef NETWORKING
1715 	char x;
1716 
1717 	if (read(ssc[3], &c, 1) != 1) {
1718 		if ((errno == EAGAIN) || (errno == EINTR)) {
1719 			close(ssc[3]);
1720 			ssc[3] = 0;
1721 			return((BYTE) 0);
1722 		} else {
1723 			LOGE(TAG, "can't read console 4");
1724 			cpu_error = IOERROR;
1725 			cpu_state = STOPPED;
1726 			return((BYTE) 0);
1727 		}
1728 	}
1729 	if (ss_telnet[3] && (c == '\r'))
1730 		read(ssc[3], &x, 1);
1731 #ifdef SNETDEBUG
1732 	if (sdirection != 1) {
1733 		printf("\n<- ");
1734 		sdirection = 1;
1735 	}
1736 	printf("%02x ", (BYTE) c);
1737 #endif
1738 #else
1739 	c = 0;
1740 #endif
1741 	return((BYTE) c);
1742 }
1743 
1744 /*
1745  *	I/O handler for read client socket 1 data
1746  */
netd1_in(void)1747 static BYTE netd1_in(void)
1748 {
1749 	char c;
1750 
1751 #ifdef NETWORKING
1752 	if (read(cs, &c, 1) != 1) {
1753 		LOGE(TAG, "can't read client socket");
1754 		cpu_error = IOERROR;
1755 		cpu_state = STOPPED;
1756 		return((BYTE) 0);
1757 	}
1758 #ifdef CNETDEBUG
1759 	if (cdirection != 1) {
1760 		printf("\n<- ");
1761 		cdirection = 1;
1762 	}
1763 	printf("%02x ", (BYTE) c);
1764 #endif
1765 #else
1766 	c = 0;
1767 #endif
1768 	return((BYTE) c);
1769 }
1770 
1771 /*
1772  *	I/O handler for write console 0 data:
1773  *	the output is written to the terminal
1774  */
cond_out(BYTE data)1775 static void cond_out(BYTE data)
1776 {
1777 again:
1778 	if (write(fileno(stdout), (char *) &data, 1) != 1) {
1779 		if (errno == EINTR) {
1780 			goto again;
1781 		} else {
1782 			LOGE(TAG, "can't write console 0");
1783 			cpu_error = IOERROR;
1784 			cpu_state = STOPPED;
1785 		}
1786 	}
1787 }
1788 
1789 /*
1790  *	I/O handler for write console 1 data:
1791  *	the output is written to the socket
1792  */
cond1_out(BYTE data)1793 static void cond1_out(BYTE data)
1794 {
1795 #ifdef NETWORKING
1796 #ifdef SNETDEBUG
1797 	if (sdirection != 0) {
1798 		printf("\n-> ");
1799 		sdirection = 0;
1800 	}
1801 	printf("%02x ", (BYTE) data);
1802 #endif
1803 again:
1804 	if (write(ssc[0], (char *) &data, 1) != 1) {
1805 		if (errno == EINTR) {
1806 			goto again;
1807 		} else {
1808 			LOGE(TAG, "can't write console 1");
1809 			cpu_error = IOERROR;
1810 			cpu_state = STOPPED;
1811 		}
1812 	}
1813 #endif
1814 }
1815 
1816 /*
1817  *	I/O handler for write console 2 data:
1818  *	the output is written to the socket
1819  */
cond2_out(BYTE data)1820 static void cond2_out(BYTE data)
1821 {
1822 #ifdef NETWORKING
1823 #ifdef SNETDEBUG
1824 	if (sdirection != 0) {
1825 		printf("\n-> ");
1826 		sdirection = 0;
1827 	}
1828 	printf("%02x ", (BYTE) data);
1829 #endif
1830 again:
1831 	if (write(ssc[1], (char *) &data, 1) != 1) {
1832 		if (errno == EINTR) {
1833 			goto again;
1834 		} else {
1835 			LOGE(TAG, "can't write console 2");
1836 			cpu_error = IOERROR;
1837 			cpu_state = STOPPED;
1838 		}
1839 	}
1840 #endif
1841 }
1842 
1843 /*
1844  *	I/O handler for write console 3 data:
1845  *	the output is written to the socket
1846  */
cond3_out(BYTE data)1847 static void cond3_out(BYTE data)
1848 {
1849 #ifdef NETWORKING
1850 #ifdef SNETDEBUG
1851 	if (sdirection != 0) {
1852 		printf("\n-> ");
1853 		sdirection = 0;
1854 	}
1855 	printf("%02x ", (BYTE) data);
1856 #endif
1857 again:
1858 	if (write(ssc[2], (char *) &data, 1) != 1) {
1859 		if (errno == EINTR) {
1860 			goto again;
1861 		} else {
1862 			LOGE(TAG, "can't write console 3");
1863 			cpu_error = IOERROR;
1864 			cpu_state = STOPPED;
1865 		}
1866 	}
1867 #endif
1868 }
1869 
1870 /*
1871  *	I/O handler for write console 4 data:
1872  *	the output is written to the socket
1873  */
cond4_out(BYTE data)1874 static void cond4_out(BYTE data)
1875 {
1876 #ifdef NETWORKING
1877 #ifdef SNETDEBUG
1878 	if (sdirection != 0) {
1879 		printf("\n-> ");
1880 		sdirection = 0;
1881 	}
1882 	printf("%02x ", (BYTE) data);
1883 #endif
1884 again:
1885 	if (write(ssc[3], (char *) &data, 1) != 1) {
1886 		if (errno == EINTR) {
1887 			goto again;
1888 		} else {
1889 			LOGE(TAG, "can't write console 4");
1890 			cpu_error = IOERROR;
1891 			cpu_state = STOPPED;
1892 		}
1893 	}
1894 #endif
1895 }
1896 
1897 /*
1898  *	I/O handler for write client socket 1 data:
1899  *	the output is written to the socket
1900  */
netd1_out(BYTE data)1901 static void netd1_out(BYTE data)
1902 {
1903 #ifdef NETWORKING
1904 #ifdef CNETDEBUG
1905 	if (cdirection != 0) {
1906 		printf("\n-> ");
1907 		cdirection = 0;
1908 	}
1909 	printf("%02x ", (BYTE) data);
1910 #endif
1911 again:
1912 	if (write(cs, (char *) &data, 1) != 1) {
1913 		if (errno == EINTR) {
1914 			goto again;
1915 		} else {
1916 			LOGE(TAG, "can't write client socket");
1917 			cpu_error = IOERROR;
1918 			cpu_state = STOPPED;
1919 		}
1920 	}
1921 #endif
1922 }
1923 
1924 /*
1925  *	I/O handler for read printer status:
1926  *	the printer is ready all the time
1927  */
prts_in(void)1928 static BYTE prts_in(void)
1929 {
1930 	return((BYTE) 0xff);
1931 }
1932 
1933 /*
1934  *	I/O handler for write printer status:
1935  *	no function
1936  */
prts_out(BYTE data)1937 static void prts_out(BYTE data)
1938 {
1939 	data = data; /* to avoid compiler warning */
1940 }
1941 
1942 /*
1943  *	I/O handler for read printer data:
1944  *	always read an EOF from the printer
1945  */
prtd_in(void)1946 static BYTE prtd_in(void)
1947 {
1948 	return((BYTE) 0x1a);	/* CP/M EOF */
1949 }
1950 
1951 /*
1952  *	I/O handler for write printer data:
1953  *	the output is written to file "printer.txt"
1954  */
prtd_out(BYTE data)1955 static void prtd_out(BYTE data)
1956 {
1957 	if (printer == 0)
1958 		printer = creat("printer.txt", 0664);
1959 
1960 	if (data != '\r') {
1961 again:
1962 		if (write(printer, (char *) &data, 1) != 1) {
1963 			if (errno == EINTR) {
1964 				goto again;
1965 			} else {
1966 				LOGE(TAG, "can't write printer");
1967 				cpu_error = IOERROR;
1968 				cpu_state = STOPPED;
1969 			}
1970 		}
1971 	}
1972 }
1973 
1974 /*
1975  *	I/O handler for read aux status:
1976  *	return EOF status of the aux device
1977  */
auxs_in(void)1978 static BYTE auxs_in(void)
1979 {
1980 #ifdef PIPES
1981 	return((BYTE) aux_in_eof);
1982 #else
1983 	return((BYTE) 0xff);
1984 #endif
1985 }
1986 
1987 /*
1988  *	I/O handler for write aux status:
1989  *	change EOF status of the aux device
1990  */
auxs_out(BYTE data)1991 static void auxs_out(BYTE data)
1992 {
1993 #ifdef PIPES
1994 	aux_in_eof = data;
1995 #else
1996 	data = data; /* to avoid compiler warning */
1997 #endif
1998 }
1999 
2000 /*
2001  *	I/O handler for read aux data:
2002  *	read next byte from pipe "auxin" or from file "auxiliaryin.txt"
2003  */
auxd_in(void)2004 static BYTE auxd_in(void)
2005 {
2006 	char c;
2007 
2008 #ifdef PIPES
2009 	if (read(auxin, &c, 1) == 1)
2010 		return((BYTE) c);
2011 	else {
2012 		aux_in_eof = 0xff;
2013 		return((BYTE) 0x1a);	/* CP/M EOF */
2014 	}
2015 #else
2016 	if (aux_in == 0) {
2017 		if ((aux_in = open("auxiliaryin.txt", O_RDONLY)) == -1){
2018 			LOGE(TAG, "can't open auxiliaryin.txt");
2019 			cpu_error = IOERROR;
2020 			cpu_state = STOPPED;
2021 			return((BYTE) 0);
2022 		}
2023 	}
2024 
2025 	if (aux_in_lf) {
2026 		aux_in_lf = 0;
2027 		return((BYTE) '\n');
2028 	}
2029 
2030 	if (read(aux_in, &c, 1) != 1) {
2031 		close(aux_in);
2032 		aux_in = 0;
2033 		return((BYTE) 0x1a);
2034 	}
2035 
2036 	if (c == '\n') {
2037 		aux_in_lf = 1;
2038 		return((BYTE) '\r');
2039 	}
2040 
2041 	return((BYTE) c);
2042 #endif
2043 }
2044 
2045 /*
2046  *	I/O handler for write aux data:
2047  *	write output to pipe "auxout" or to file "auxiliaryout.txt"
2048  */
auxd_out(BYTE data)2049 static void auxd_out(BYTE data)
2050 {
2051 #ifdef PIPES
2052 	if ((data == 0) || (data == 0x1a))
2053 		return;
2054 
2055 	if (data != '\r')
2056 		write(auxout, (char *) &data, 1);
2057 #else
2058 	if (data == 0)
2059 		return;
2060 
2061 	if (aux_out == 0) {
2062 		if ((aux_out = creat("auxiliaryout.txt", 0644)) == -1) {
2063 			LOGE(TAG, "can't open auxiliaryout.txt");
2064 			cpu_error = IOERROR;
2065 			cpu_state = STOPPED;
2066 			return;
2067 		}
2068 	}
2069 
2070 	if (data == 0x1a) {
2071 		close(aux_out);
2072 		aux_out = 0;
2073 		return;
2074 	}
2075 
2076 	if (data != '\r')
2077 		write(aux_out, (char *) &data, 1);
2078 #endif
2079 }
2080 
2081 /*
2082  *	I/O handler for read FDC drive:
2083  *	return the current drive
2084  */
fdcd_in(void)2085 static BYTE fdcd_in(void)
2086 {
2087 	return((BYTE) drive);
2088 }
2089 
2090 /*
2091  *	I/O handler for write FDC drive:
2092  *	set the current drive
2093  */
fdcd_out(BYTE data)2094 static void fdcd_out(BYTE data)
2095 {
2096 	drive = data;
2097 }
2098 
2099 /*
2100  *	I/O handler for read FDC track:
2101  *	return the current track
2102  */
fdct_in(void)2103 static BYTE fdct_in(void)
2104 {
2105 	return((BYTE) track);
2106 }
2107 
2108 /*
2109  *	I/O handler for write FDC track:
2110  *	set the current track
2111  */
fdct_out(BYTE data)2112 static void fdct_out(BYTE data)
2113 {
2114 	track = data;
2115 }
2116 
2117 /*
2118  *	I/O handler for read FDC sector low
2119  *	return low byte of the current sector
2120  */
fdcs_in(void)2121 static BYTE fdcs_in(void)
2122 {
2123 	return((BYTE) sector & 0xff);
2124 }
2125 
2126 /*
2127  *	I/O handler for write FDC sector low
2128  *	set low byte of the current sector
2129  */
fdcs_out(BYTE data)2130 static void fdcs_out(BYTE data)
2131 {
2132 	sector = (sector & 0xff00) + data;
2133 }
2134 
2135 /*
2136  *	I/O handler for read FDC sector high
2137  *	return high byte of the current sector
2138  */
fdcsh_in(void)2139 static BYTE fdcsh_in(void)
2140 {
2141 	return((BYTE) (sector >> 8));
2142 }
2143 
2144 /*
2145  *	I/O handler for write FDC sector high
2146  *	set high byte of the current sector
2147  */
fdcsh_out(BYTE data)2148 static void fdcsh_out(BYTE data)
2149 {
2150 	sector = (sector & 0xff) + (data << 8);
2151 }
2152 
2153 /*
2154  *	I/O handler for read FDC command:
2155  *	always returns 0
2156  */
fdco_in(void)2157 static BYTE fdco_in(void)
2158 {
2159 	return((BYTE) 0);
2160 }
2161 
2162 /*
2163  *	I/O handler for write FDC command:
2164  *	transfer one sector in the wanted direction,
2165  *	0 = read, 1 = write
2166  *
2167  *	The status byte of the FDC is set as follows:
2168  *	  0 - ok
2169  *	  1 - illegal drive
2170  *	  2 - illegal track
2171  *	  3 - illegal sector
2172  *	  4 - seek error
2173  *	  5 - read error
2174  *	  6 - write error
2175  *	  7 - illegal command to FDC
2176  */
fdco_out(BYTE data)2177 static void fdco_out(BYTE data)
2178 {
2179 	register int i;
2180 	unsigned long pos;
2181 	static char buf[128];
2182 
2183 	if (disks[drive].fd == NULL) {
2184 		status = 1;
2185 		return;
2186 	}
2187 	if (track > disks[drive].tracks) {
2188 		status = 2;
2189 		return;
2190 	}
2191 	if (sector > disks[drive].sectors) {
2192 		status = 3;
2193 		return;
2194 	}
2195 	pos = (((long)track) * ((long)disks[drive].sectors) + sector - 1) << 7;
2196 	if (lseek(*disks[drive].fd, pos, SEEK_SET) == -1L) {
2197 		status = 4;
2198 		return;
2199 	}
2200 	switch (data) {
2201 	case 0:	/* read */
2202 		if (read(*disks[drive].fd, buf, 128) != 128)
2203 			status = 5;
2204 		else {
2205 			for (i = 0; i < 128; i++)
2206 				dma_write((dmadh << 8) + dmadl + i, buf[i]);
2207 			status = 0;
2208 		}
2209 		break;
2210 	case 1:	/* write */
2211 		for (i = 0; i < 128; i++)
2212 			buf[i] = dma_read((dmadh << 8) + dmadl + i);
2213 		if (write(*disks[drive].fd, buf, 128) != 128)
2214 			status = 6;
2215 		else
2216 			status = 0;
2217 		break;
2218 	default:		/* illegal command */
2219 		status = 7;
2220 		break;
2221 	}
2222 }
2223 
2224 /*
2225  *	I/O handler for read FDC status:
2226  *	returns status of last FDC operation,
2227  *	0 = ok, else some error
2228  */
fdcx_in(void)2229 static BYTE fdcx_in(void)
2230 {
2231 	return((BYTE) status);
2232 }
2233 
2234 /*
2235  *	I/O handler for write FDC status:
2236  *	no function
2237  */
fdcx_out(BYTE data)2238 static void fdcx_out(BYTE data)
2239 {
2240 	data = data; /* to avoid compiler warning */
2241 }
2242 
2243 /*
2244  *	I/O handler for read lower byte of DMA address:
2245  *	return lower byte of current DMA address
2246  */
dmal_in(void)2247 static BYTE dmal_in(void)
2248 {
2249 	return((BYTE) dmadl);
2250 }
2251 
2252 /*
2253  *	I/O handler for write lower byte of DMA address:
2254  *	set lower byte of DMA address
2255  */
dmal_out(BYTE data)2256 static void dmal_out(BYTE data)
2257 {
2258 	dmadl = data;
2259 }
2260 
2261 /*
2262  *	I/O handler for read higher byte of DMA address:
2263  *	return higher byte of current DMA address
2264  */
dmah_in(void)2265 static BYTE dmah_in(void)
2266 {
2267 	return((BYTE) dmadh);
2268 }
2269 
2270 /*
2271  *	I/O handler for write higher byte of DMA address:
2272  *	set higher byte of the DMA address
2273  */
dmah_out(BYTE data)2274 static void dmah_out(BYTE data)
2275 {
2276 	dmadh = data;
2277 }
2278 
2279 /*
2280  *	I/O handler for read MMU initialisation:
2281  *	return number of initialised MMU banks
2282  */
mmui_in(void)2283 static BYTE mmui_in(void)
2284 {
2285 	return((BYTE) maxbnk);
2286 }
2287 
2288 /*
2289  *	I/O handler for write MMU initialisation:
2290  *	for the FIRST call the memory for the wanted number of banks
2291  *	is allocated and pointers to the memory is stored in the MMU array
2292  *
2293  *	The number of banks is the total, including bank 0 which already
2294  *	is allocated
2295  */
mmui_out(BYTE data)2296 static void mmui_out(BYTE data)
2297 {
2298 	register int i;
2299 
2300 	/* do nothing if MMU initialised already */
2301 	if (memory[1] != NULL)
2302 		return;
2303 
2304 	if (data > MAXSEG) {
2305 		LOGE(TAG, "Try to init %d banks, available %d banks",
2306 		     data, MAXSEG);
2307 		cpu_error = IOERROR;
2308 		cpu_state = STOPPED;
2309 		return;
2310 	}
2311 
2312 	for (i = 1; i < data; i++) {
2313 		if ((memory[i] = malloc(segsize)) == NULL) {
2314 			LOGE(TAG, "can't allocate memory for bank %d", i);
2315 			cpu_error = IOERROR;
2316 			cpu_state = STOPPED;
2317 			return;
2318 		}
2319 	}
2320 
2321 	maxbnk = data;
2322 }
2323 
2324 /*
2325  *	I/O handler for read MMU bank select:
2326  *	return current selected MMU bank
2327  */
mmus_in(void)2328 static BYTE mmus_in(void)
2329 {
2330 	return((BYTE) selbnk);
2331 }
2332 
2333 /*
2334  *	I/O handler for write MMU bank select:
2335  *	make the new bank the current one
2336  */
mmus_out(BYTE data)2337 static void mmus_out(BYTE data)
2338 {
2339 	if (data > maxbnk - 1) {
2340 		LOGE(TAG, "%04x: try to select unallocated bank %d", PC, data);
2341 		cpu_error = IOERROR;
2342 		cpu_state = STOPPED;
2343 		return;
2344 	}
2345 	selbnk = data;
2346 }
2347 
2348 /*
2349  *	I/O handler for read MMU segment size configuration:
2350  *	returns size of the bank segments in pages a 256 bytes
2351  */
mmuc_in(void)2352 static BYTE mmuc_in(void)
2353 {
2354 	return((BYTE) (segsize >> 8));
2355 }
2356 
2357 /*
2358  *	I/O handler for write MMU segment size configuration:
2359  *	set the size of the bank segments in pages a 256 bytes
2360  *	must be done before any banks are allocated
2361  */
mmuc_out(BYTE data)2362 static void mmuc_out(BYTE data)
2363 {
2364 	if (memory[1] != NULL) {
2365 		LOGE(TAG, "Not possible to resize already allocated segments");
2366 		cpu_error = IOERROR;
2367 		cpu_state = STOPPED;
2368 		return;
2369 	}
2370 	segsize = data << 8;
2371 }
2372 
2373 /*
2374  *	I/O handler to read status of MMU protect/unprotect common segment
2375  */
mmup_in(void)2376 static BYTE mmup_in(void)
2377 {
2378 	return(wp_common);
2379 }
2380 
2381 /*
2382  *	I/O handler for MMU protect/unprotect common segment
2383  */
mmup_out(BYTE data)2384 static void mmup_out(BYTE data)
2385 {
2386 	wp_common = data;
2387 }
2388 
2389 /*
2390  *	I/O handler for write timer
2391  *	start or stop the 10ms interrupt timer
2392  */
time_out(BYTE data)2393 static void time_out(BYTE data)
2394 {
2395 	static struct itimerval tim;
2396 	static struct sigaction newact;
2397 
2398 	if (data == 1) {
2399 		timer = 1;
2400 		newact.sa_handler = int_timer;
2401 		memset((void *) &newact.sa_mask, 0, sizeof(newact.sa_mask));
2402 		newact.sa_flags = 0;
2403 		sigaction(SIGALRM, &newact, NULL);
2404 		tim.it_value.tv_sec = 0;
2405 		tim.it_value.tv_usec = 10000;
2406 		tim.it_interval.tv_sec = 0;
2407 		tim.it_interval.tv_usec = 10000;
2408 		setitimer(ITIMER_REAL, &tim, NULL);
2409 	} else {
2410 		timer = 0;
2411 		newact.sa_handler = SIG_IGN;
2412 		memset((void *) &newact.sa_mask, 0, sizeof(newact.sa_mask));
2413 		newact.sa_flags = 0;
2414 		sigaction(SIGALRM, &newact, NULL);
2415 		tim.it_value.tv_sec = 0;
2416 		tim.it_value.tv_usec = 0;
2417 		setitimer(ITIMER_REAL, &tim, NULL);
2418 	}
2419 }
2420 
2421 /*
2422  *	I/O handler for read timer
2423  *	return current status of 10ms interrupt timer,
2424  *	1 = enabled, 0 = disabled
2425  */
time_in(void)2426 static BYTE time_in(void)
2427 {
2428 	return(timer);
2429 }
2430 
2431 /*
2432  *	I/O handler for write delay
2433  *	delay CPU for data * 10ms
2434  */
delay_out(BYTE data)2435 static void delay_out(BYTE data)
2436 {
2437 	SLEEP_MS(data * 10);
2438 
2439 #ifdef CNETDEBUG
2440 	printf(". ");
2441 #endif
2442 }
2443 
2444 /*
2445  *	I/O handler for read delay
2446  *	returns 0
2447  */
delay_in(void)2448 static BYTE delay_in(void)
2449 {
2450 	return((BYTE) 0);
2451 }
2452 
2453 /*
2454  *	Port is locked until magic number 0xaa is received!
2455  *
2456  *	I/O handler for write hardware control after unlocking:
2457  *	bit 6 = 1	reset CPU, MMU and reboot
2458  *	bit 7 = 1	halt emulation via I/O
2459  */
hwctl_out(BYTE data)2460 static void hwctl_out(BYTE data)
2461 {
2462 	/* if port is locked do nothing */
2463 	if (hwctl_lock && (data != 0xaa))
2464 		return;
2465 
2466 	/* unlock port ? */
2467 	if (hwctl_lock && (data == 0xaa)) {
2468 		hwctl_lock = 0;
2469 		return;
2470 	}
2471 
2472 	/* process output to unlocked port */
2473 
2474 	if (data & 128) {	/* halt system */
2475 		cpu_error = IOHALT;
2476 		cpu_state = STOPPED;
2477 		return;
2478 	}
2479 
2480 	if (data & 64) {	/* reset system */
2481 		reset_system();
2482 		return;
2483 	}
2484 }
2485 
2486 /*
2487  *	I/O handler for read hardware control
2488  *	returns lock status of the port
2489  */
hwctl_in(void)2490 static BYTE hwctl_in(void)
2491 {
2492 	return(hwctl_lock);
2493 }
2494 
2495 /*
2496  *	I/O handler for write CPU speed low
2497  */
speedl_out(BYTE data)2498 static void speedl_out(BYTE data)
2499 {
2500 	speed = data;
2501 }
2502 
2503 /*
2504  *	I/O handler for read CPU speed low
2505  */
speedl_in(void)2506 static BYTE speedl_in(void)
2507 {
2508 	return(f_flag & 0xff);
2509 }
2510 
2511 /*
2512  *	I/O handler for write CPU speed high
2513  */
speedh_out(BYTE data)2514 static void speedh_out(BYTE data)
2515 {
2516 	speed += data << 8;
2517 	tmax = speed * 10000;
2518 	f_flag = speed;
2519 }
2520 
2521 /*
2522  *	I/O handler for read CPU speed high
2523  */
speedh_in(void)2524 static BYTE speedh_in(void)
2525 {
2526 	return(f_flag  >> 8);
2527 }
2528 
2529 /*
2530  *	timer interrupt causes maskable CPU interrupt
2531  */
int_timer(int sig)2532 static void int_timer(int sig)
2533 {
2534 	sig = sig;	/* to avoid compiler warning */
2535 
2536 	int_int = 1;
2537 	int_data = 0xff;	/* RST 38H for IM 0, 0FFH for IM 2 */
2538 }
2539 
2540 #if defined(NETWORKING) && defined(TCPASYNC)
2541 /*
2542  *	SIGIO interrupt handler
2543  */
int_io(int sig)2544 static void int_io(int sig)
2545 {
2546 	register int i;
2547 	struct sockaddr_in fsin;
2548 	socklen_t alen;
2549 	struct pollfd p[NUMSOC];
2550 	int go_away;
2551 	int on = 1;
2552 
2553 	sig = sig;	/* to avoid compiler warning */
2554 
2555 	for (i = 0; i < NUMSOC; i++) {
2556 		p[i].fd = ss[i];
2557 		p[i].events = POLLIN;
2558 		p[i].revents = 0;
2559 	}
2560 
2561 	poll(p, NUMSOC, 0);
2562 
2563 	for (i = 0; i < NUMSOC; i++) {
2564 		if ((ss[i] != 0) && (p[i].revents)) {
2565 			alen = sizeof(fsin);
2566 
2567 			if (ssc[i] != 0) {
2568 				go_away = accept(ss[i],
2569 						 (struct sockaddr *) &fsin,
2570 						 &alen);
2571 				close(go_away);
2572 				return;
2573 			}
2574 
2575 			if ((ssc[i] = accept(ss[i], (struct sockaddr *) &fsin,
2576 			    &alen)) == -1) {
2577 				LOGW(TAG, "can't accept on server socket");
2578 				ssc[i] = 0;
2579 			}
2580 
2581 			if (setsockopt(ssc[i], IPPROTO_TCP, TCP_NODELAY,
2582 			    (void *) &on, sizeof(on)) == -1) {
2583 				LOGW(TAG, "can't setsockopt TCP_NODELAY on server socket");
2584 			}
2585 
2586 			if (ss_telnet[i])
2587 				telnet_negotiation(ssc[i]);
2588 		}
2589 	}
2590 }
2591 #endif
2592 
2593 #ifdef NETWORKING
2594 /*
2595  *	do the telnet option negotiation
2596  */
telnet_negotiation(int fd)2597 void telnet_negotiation(int fd)
2598 {
2599 	static char will_echo[3] = {255, 251, 1};
2600 	static char char_mode[3] = {255, 251, 3};
2601 	struct pollfd p[1];
2602 	BYTE c[3];
2603 
2604 	/* send the telnet options we need */
2605 	write(fd, &char_mode, 3);
2606 	write(fd, &will_echo, 3);
2607 
2608 	/* and reject all others offered */
2609 	p[0].fd = fd;
2610 	p[0].events = POLLIN;
2611 	while (1) {
2612 		/* wait for input */
2613 		p[0].revents = 0;
2614 		poll(p, 1, TELNET_TIMEOUT);
2615 
2616 		/* done if no more input */
2617 		if (! p[0].revents)
2618 			break;
2619 
2620 		/* else read the option */
2621 		read(fd, &c, 3);
2622 		LOGD(TAG, "telnet: %d %d %d\r\n", c[0], c[1], c[2]);
2623 		if (c[2] == 1 || c[2] == 3)
2624 			continue;	/* ignore answers to our requests */
2625 		if (c[1] == 251)	/* and reject other options */
2626 			c[1] = 254;
2627 		else if (c[1] == 253)
2628 			c[1] = 252;
2629 		write(fd, &c, 3);
2630 	}
2631 }
2632 #endif
2633