mirror of
https://github.com/prirun/p50em.git
synced 2026-01-14 07:29:44 +00:00
mem array is segment addressable start of boot support use CC macros and BCxx to emulate Bxyy (eg, BFLT) use CC macros and LCxx to emulate Lxyy (eg, LFLT) shift instruction work
211 lines
5.0 KiB
C
211 lines
5.0 KiB
C
/* emdev.h, Jim Wilcoxson, April 17, 2005
|
|
Device handlers for pio instructions. Use devnull as a template for
|
|
new handlers.
|
|
NOTES:
|
|
|
|
OCP instructions never skip
|
|
SKS instructions skip on specified conditions
|
|
INA/OTA instructions skip if they succeed (data was read/written)
|
|
*/
|
|
|
|
#include <fcntl.h>
|
|
|
|
void devnull (short class, short func, short device) {
|
|
|
|
switch (class) {
|
|
|
|
case 0:
|
|
fprintf(stderr," OCP '%2#0o%2#0o\n", func, device);
|
|
if (func == 0) {
|
|
;
|
|
} else {
|
|
fprintf(stderr," unimplemented OCP device %2#0o function\n", device);
|
|
exit(1);
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
fprintf(stderr," SKS '%2#0o%2#0o\n", func, device);
|
|
if (func == 0)
|
|
mem[P]++; /* assume it's always ready */
|
|
else {
|
|
fprintf(stderr," unimplemented SKS device %2#0o function\n", device);
|
|
exit(1);
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
fprintf(stderr," INA '%2#0o%2#0o\n", func, device);
|
|
if (func == 0) {
|
|
;
|
|
} else {
|
|
fprintf(stderr," unimplemented INA device %2#0o function\n", device);
|
|
exit(1);
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
fprintf(stderr," OTA '%2#0o%2#0o\n", func, device);
|
|
if (func == 0 | func == 1) {
|
|
mem[P]++; /* OTA '0004 always works on Unix */
|
|
} else {
|
|
fprintf(stderr," unimplemented OTA device %2#0o function\n", device);
|
|
exit(1);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* Device '4: system console
|
|
|
|
OCP '0004 = initialize for input only, echoplex, 110 baud, 8-bit, no parity
|
|
OCP '0104 = same, but for output only
|
|
OCP '1004 = Full duplex; software must echo
|
|
OCP '1204 = Prime normal, independent xmit and recv w/echoplex
|
|
OCP '1304 = Self test mode (internally connects transmitter to receiver)
|
|
OCP '1704 = same as above, but clears interrupt masks and dma/c enables
|
|
|
|
|
|
*/
|
|
|
|
void devasr (short class, short func, short device) {
|
|
|
|
static int ttydev=-1;
|
|
unsigned char ch;
|
|
int ttyflags, newflags;
|
|
int n;
|
|
|
|
if (ttydev < 0) {
|
|
ttydev = open("/dev/tty", O_RDWR, 0);
|
|
if (ttydev < 0) {
|
|
perror(" error opening /dev/tty");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
switch (class) {
|
|
|
|
case 0:
|
|
fprintf(stderr," OCP '%2#0o%2#0o\n", func, device);
|
|
break;
|
|
|
|
case 1:
|
|
fprintf(stderr," SKS '%2#0o%2#0o\n", func, device);
|
|
if (func <= 7)
|
|
mem[P]++; /* assume it's always ready */
|
|
else {
|
|
fprintf(stderr," unimplemented SKS '04 function\n");
|
|
exit(1);
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
fprintf(stderr," INA '%2#0o%2#0o\n", func, device);
|
|
if (func == 0 || func == 010) {
|
|
if (fcntl(ttydev, F_GETFL, ttyflags) == -1) {
|
|
perror(" unable to get tty flags");
|
|
exit(1);
|
|
}
|
|
if (mem[mem[P]] == 03776) /* JMP *-1 -> blocking read */
|
|
newflags = ttyflags & ~O_NONBLOCK;
|
|
else
|
|
newflags = ttyflags | O_NONBLOCK;
|
|
if (fcntl(ttydev, F_SETFL, newflags) == -1) {
|
|
perror(" unable to set tty flags");
|
|
exit(1);
|
|
}
|
|
n = read(ttydev, &ch, 1);
|
|
if (n < 0) {
|
|
if (errno != EAGAIN) {
|
|
perror(" error reading from tty");
|
|
exit(1);
|
|
}
|
|
} else if (n == 1) {
|
|
if (func >= 010)
|
|
mem[A] = 0;
|
|
mem[A] = mem[A] | ch | 0x80;
|
|
mem[P]++;
|
|
} else if (n != 0) {
|
|
fprintf(stderr," unexpected error reading from tty, n=%d", n);
|
|
exit(1);
|
|
}
|
|
} else if (func == 011) { /* read device id? */
|
|
mem[A] = 4;
|
|
mem[P]++;
|
|
} else if (func == 012) { /* read control word */
|
|
mem[A] = 04110;
|
|
mem[P]++;
|
|
} else {
|
|
fprintf(stderr," unimplemented INA '04 function\n");
|
|
exit(1);
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
fprintf(stderr," OTA '%2#0o%2#0o\n", func, device);
|
|
if (func == 0) {
|
|
fprintf(stderr," char to write=%o\n", mem[A]);
|
|
putchar(mem[A] & 0x7f);
|
|
fflush(stdout);
|
|
mem[P]++; /* OTA '0004 always works on Unix */
|
|
} else if (func == 1) { /* write control word */
|
|
mem[P]++;
|
|
} else {
|
|
fprintf(stderr," unimplemented OTA '04 function\n");
|
|
exit(1);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Device '20: control panel switches and lights
|
|
|
|
OTA '1720 = write to lights (sets CP fetch address)
|
|
INA '1420 = read location from CP ROM (not implemented, used to boot)
|
|
INA '1620 = read control panel switches
|
|
*/
|
|
|
|
void devcp (short class, short func, short device) {
|
|
|
|
switch (class) {
|
|
|
|
case 0:
|
|
fprintf(stderr," OCP '%2#0o%2#0o\n", func, device);
|
|
fprintf(stderr," unimplemented OCP device %2#0o function\n", device);
|
|
exit(1);
|
|
break;
|
|
|
|
case 1:
|
|
fprintf(stderr," SKS '%2#0o%2#0o\n", func, device);
|
|
fprintf(stderr," unimplemented SKS device %2#0o function\n", device);
|
|
exit(1);
|
|
break;
|
|
|
|
case 2:
|
|
fprintf(stderr," INA '%2#0o%2#0o\n", func, device);
|
|
if (func == 016) {
|
|
mem[A] = 0;
|
|
} else {
|
|
fprintf(stderr," unimplemented INA device %2#0o function\n", device);
|
|
exit(1);
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
fprintf(stderr," OTA '%2#0o%2#0o\n", func, device);
|
|
if (func == 017) { /* write lights */
|
|
mem[P]++;
|
|
} else {
|
|
fprintf(stderr," unimplemented OTA device %2#0o function\n", device);
|
|
exit(1);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|