blob: 464bb9589ac8a1b47b59d016aa4a9c7de39e9363 [file] [log] [blame] [raw]
/* 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;
}