/* ibm1130_stddev.c: IBM 1130 standard I/O devices simulator | |
Based on the SIMH simulator package written by Robert M Supnik | |
Brian Knittel | |
Revision History: | |
2002.09.13 - pulled 1132 printer out of this file into ibm1130_prt.c | |
* (C) Copyright 2002, Brian Knittel. | |
* You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN | |
* RISK basis, there is no warranty of fitness for any purpose, and the rest of the | |
* usual yada-yada. Please keep this notice and the copyright in any distributions | |
* or modifications. | |
* | |
* This is not a supported product, but I welcome bug reports and fixes. | |
* Mail to sim@ibm1130.org | |
*/ | |
#include "ibm1130_defs.h" | |
/* ---------------------------------------------------------------------------- */ | |
static void badio (char *dev) | |
{ | |
// the real 1130 just ignores attempts to use uninstalled devices. They get tested | |
// at times, so it's best to be quiet about this | |
// printf("%s I/O is not yet supported", dev); | |
// wait_state = WAIT_INVALID_OP; | |
} | |
void xio_1134_papertape (int32 addr, int32 func, int32 modify) {badio("papertape");} | |
void xio_1627_plotter (int32 addr, int32 func, int32 modify) {badio("plotter");} | |
void xio_1231_optical (int32 addr, int32 func, int32 modify) {badio("optical mark");} | |
void xio_2501_card (int32 addr, int32 func, int32 modify) {badio("2501 card");} | |
void xio_1131_synch (int32 addr, int32 func, int32 modify) {badio("SCA");} | |
void xio_system7 (int32 addr, int32 func, int32 modify) {badio("System 7");} | |
/* ---------------------------------------------------------------------------- */ | |
static int32 tti_dsw = 0; /* device status words */ | |
static int32 tto_dsw = 0; | |
static int32 con_dsw = 0; | |
static t_stat tti_svc (UNIT *uptr); | |
static t_stat tto_svc (UNIT *uptr); | |
static t_stat tti_reset (DEVICE *dptr); | |
static t_stat tto_reset (DEVICE *dptr); | |
extern t_stat sim_poll_kbd (void); | |
extern t_stat sim_wait_kbd (void); | |
extern t_stat sim_putchar (int32 out); | |
extern UNIT *sim_clock_queue; | |
extern int cgi; | |
#define CSET_MASK 1 /* character set */ | |
#define CSET_NORMAL 0 | |
#define CSET_ASCII 1 | |
#define IRQ_KEY 0x11 /* ctrl-Q */ | |
#define PROGRAM_STOP_KEY 0x10 /* ctrl-P */ | |
#include "ibm1130_conout.h" /* conout_to_ascii table */ | |
#include "ibm1130_conin.h" /* ascii_to_conin table */ | |
/* TTI data structures | |
tti_dev TTI device descriptor | |
tti_unit TTI unit descriptor | |
tti_reg TTI register list | |
*/ | |
UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }; | |
REG tti_reg[] = { | |
{ ORDATA (BUF, tti_unit.buf, 8) }, | |
{ ORDATA (DSW, tti_dsw, 16) }, | |
{ DRDATA (POS, tti_unit.pos, 31), PV_LEFT }, | |
{ DRDATA (STIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, | |
{ NULL } }; | |
MTAB tti_mod[] = { | |
{ CSET_MASK, CSET_NORMAL, NULL, "1130", NULL}, | |
{ CSET_MASK, CSET_ASCII, NULL, "ASCII", NULL}, | |
{ 0 } }; | |
DEVICE tti_dev = { | |
"KEYBOARD", &tti_unit, tti_reg, tti_mod, | |
1, 10, 31, 1, 8, 8, | |
NULL, NULL, &tti_reset, | |
NULL, NULL, NULL }; | |
/* TTO data structures | |
tto_dev TTO device descriptor | |
tto_unit TTO unit descriptor | |
tto_reg TTO register list | |
*/ | |
UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }; | |
REG tto_reg[] = { | |
{ ORDATA (BUF, tto_unit.buf, 8) }, | |
{ ORDATA (DSW, tto_dsw, 16) }, | |
{ DRDATA (POS, tto_unit.pos, 31), PV_LEFT }, | |
{ DRDATA (STIME, tto_unit.wait, 24), PV_LEFT }, | |
{ NULL } }; | |
MTAB tto_mod[] = { | |
{ CSET_MASK, CSET_NORMAL, NULL, "1130", NULL}, | |
{ CSET_MASK, CSET_ASCII, NULL, "ASCII", NULL}, | |
{ 0 } }; | |
DEVICE tto_dev = { | |
"TTO", &tto_unit, tto_reg, tto_mod, | |
1, 10, 31, 1, 8, 8, | |
NULL, NULL, &tto_reset, | |
NULL, NULL, NULL }; | |
/* Terminal input routines | |
tti_svc process event (character ready) | |
tti_reset process reset | |
tto_svc process event (print character) | |
tto_reset process reset | |
*/ | |
#define TT_DSW_PRINTER_RESPONSE 0x8000 | |
#define TT_DSW_KEYBOARD_RESPONSE 0x4000 | |
#define TT_DSW_INTERRUPT_REQUEST 0x2000 | |
#define TT_DSW_KEYBOARD_CONSOLE 0x1000 | |
#define TT_DSW_PRINTER_BUSY 0x0800 | |
#define TT_DSW_PRINTER_NOT_READY 0x0400 | |
#define TT_DSW_KEYBOARD_BUSY 0x0200 | |
void xio_1131_console (int32 iocc_addr, int32 func, int32 modify) | |
{ | |
int ch; | |
char msg[80]; | |
switch (func) { | |
case XIO_CONTROL: | |
SETBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); | |
keyboard_selected(TRUE); | |
// sim_activate(&tti_unit, tti_unit.wait); /* poll keyboard never stops */ | |
break; | |
case XIO_READ: | |
WriteW(iocc_addr, tti_unit.buf); | |
CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); | |
keyboard_selected(FALSE); | |
break; | |
case XIO_WRITE: | |
ch = (ReadW(iocc_addr) >> 8) & 0xFF; /* get character to write */ | |
if ((tto_unit.flags & CSET_MASK) == CSET_NORMAL) | |
ch = conout_to_ascii[ch]; /* convert to ASCII */ | |
if (ch == 0) | |
ch = '?'; /* hmmm, unknown character */ | |
tto_unit.buf = ch; /* save character to write */ | |
SETBIT(tto_dsw, TT_DSW_PRINTER_BUSY); | |
sim_activate(&tto_unit, tto_unit.wait); /* schedule interrupt */ | |
break; | |
case XIO_SENSE_DEV: | |
ACC = tto_dsw | tti_dsw; | |
if (modify & 0x01) { /* reset interrupts */ | |
CLRBIT(tto_dsw, TT_DSW_PRINTER_RESPONSE); | |
CLRBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE); | |
CLRBIT(ILSW[4], ILSW_4_CONSOLE); | |
} | |
break; | |
default: | |
sprintf(msg, "Invalid console XIO function %x", func); | |
xio_error(msg); | |
} | |
} | |
static void Beep (void) // notify user keyboard was locked or key was bad | |
{ | |
sim_putchar(7); | |
} | |
// tti_svc - keyboard polling (never stops) | |
t_stat tti_svc (UNIT *uptr) | |
{ | |
int32 temp; | |
sim_activate(&tti_unit, tti_unit.wait); /* continue polling */ | |
temp = sim_poll_kbd(); | |
if (temp < SCPE_KFLAG) | |
return temp; /* no char or error? */ | |
temp &= 0xFF; /* remove SCPE_KFLAG */ | |
if (temp == IRQ_KEY) { /* interrupt request key */ | |
SETBIT(tti_dsw, TT_DSW_INTERRUPT_REQUEST); /* queue interrupt */ | |
SETBIT(ILSW[4], ILSW_4_CONSOLE); | |
calc_ints(); | |
return SCPE_OK; | |
} | |
if (temp == PROGRAM_STOP_KEY) { /* simulate the program stop button */ | |
SETBIT(con_dsw, CPU_DSW_PROGRAM_STOP); | |
SETBIT(ILSW[5], ILSW_5_PROGRAM_STOP); | |
calc_ints(); | |
return SCPE_OK; | |
} | |
if (tti_dsw & TT_DSW_KEYBOARD_BUSY) { /* only store character if it was requested (keyboard unlocked) */ | |
if ((uptr->flags & CSET_MASK) == CSET_NORMAL) | |
temp = ascii_to_conin[temp]; | |
if (temp == 0) { /* ignore invalid characters */ | |
Beep(); | |
calc_ints(); | |
return SCPE_OK; | |
} | |
tti_unit.buf = temp & 0xFFFE; /* save keystroke except last bit (not defined, */ | |
tti_unit.pos = tti_unit.pos + 1; /* but it lets us distinguish 0 from no punch ' ' */ | |
CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* clear busy flag (relock keyboard) */ | |
keyboard_selected(FALSE); | |
SETBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE); /* queue interrupt */ | |
SETBIT(ILSW[4], ILSW_4_CONSOLE); | |
calc_ints(); | |
} | |
else | |
Beep(); | |
return SCPE_OK; | |
} | |
t_stat tti_reset (DEVICE *dptr) | |
{ | |
tti_unit.buf = 0; | |
tti_dsw = 0; | |
CLRBIT(ILSW[4], ILSW_4_CONSOLE); | |
calc_ints(); | |
keyboard_selected(FALSE); | |
sim_activate(&tti_unit, tti_unit.wait); /* always poll keyboard */ | |
return SCPE_OK; | |
} | |
t_bool keyboard_is_locked (void) /* return TRUE if keyboard is not expecting a character */ | |
{ | |
return (tti_dsw & TT_DSW_KEYBOARD_BUSY) == 0; | |
} | |
t_stat tto_svc (UNIT *uptr) | |
{ | |
int32 temp; | |
int ch; | |
CLRBIT(tto_dsw, TT_DSW_PRINTER_BUSY); | |
SETBIT(tto_dsw, TT_DSW_PRINTER_RESPONSE); | |
SETBIT(ILSW[4], ILSW_4_CONSOLE); | |
calc_ints(); | |
ch = tto_unit.buf & 0xFF; | |
switch (ch) { | |
case IGNR: | |
break; | |
case CRLF: | |
if (! cgi) | |
if ((temp = sim_putchar('\r')) != SCPE_OK) | |
return temp; | |
if ((temp = sim_putchar('\n')) != SCPE_OK) | |
return temp; | |
break; | |
default: | |
if ((temp = sim_putchar(ch)) != SCPE_OK) | |
return temp; | |
break; | |
} | |
tto_unit.pos = tto_unit.pos + 1; /* hmm, why do we count these? */ | |
return SCPE_OK; | |
} | |
t_stat tto_reset (DEVICE *dptr) | |
{ | |
tto_unit.buf = 0; | |
tto_dsw = 0; | |
CLRBIT(ILSW[4], ILSW_4_CONSOLE); | |
calc_ints(); | |
sim_cancel(&tto_unit); /* deactivate unit */ | |
return SCPE_OK; | |
} | |