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