mirror of
https://github.com/rcornwell/sims.git
synced 2026-04-05 05:13:22 +00:00
IBM360: Added 3270 terminal support.
This commit is contained in:
@@ -70,6 +70,8 @@
|
||||
#define NUM_UNITS_DASD 8
|
||||
#define NUM_DEVS_COM 1
|
||||
#define NUM_UNITS_COM 16
|
||||
#define NUM_DEVS_SCOM 1
|
||||
#define NUM_UNITS_SCOM 8
|
||||
|
||||
/* Device information block */
|
||||
typedef struct dib {
|
||||
@@ -381,6 +383,8 @@ extern DEVICE ddc_dev;
|
||||
extern DEVICE ddd_dev;
|
||||
extern DEVICE coml_dev;
|
||||
extern DEVICE com_dev;
|
||||
extern DEVICE scoml_dev;
|
||||
extern DEVICE scom_dev;
|
||||
extern UNIT cpu_unit[];
|
||||
|
||||
extern void fprint_inst(FILE *, uint16 *);
|
||||
|
||||
647
IBM360/ibm360_scom.c
Normal file
647
IBM360/ibm360_scom.c
Normal file
@@ -0,0 +1,647 @@
|
||||
/* ibm360_scom.c: IBM 360 3271 scommunications controller
|
||||
|
||||
Copyright (c) 2017-2020, Richard Cornwell
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "ibm360_defs.h"
|
||||
#include "sim_sock.h"
|
||||
#include "sim_tmxr.h"
|
||||
|
||||
#ifdef NUM_DEVS_COM
|
||||
#define UNIT_COM 0
|
||||
|
||||
|
||||
|
||||
/* u3 */
|
||||
#define CMD_WR 0x01 /* Write data to com line */
|
||||
#define CMD_RD 0x02 /* Read buffer */
|
||||
#define CMD_NOP 0x03 /* Nop scommand */
|
||||
#define CMD_WRER 0x05 /* Erase and write data */
|
||||
#define CMD_RDMD 0x06 /* Read modified */
|
||||
#define CMD_SEL 0x0B /* Select */
|
||||
#define CMD_EAU 0x0F /* Erase all un protected */
|
||||
|
||||
/* u3 second byte */
|
||||
#define RECV 0x00100 /* Recieving data */
|
||||
#define SEND 0x00200 /* Sending data */
|
||||
#define ENAB 0x00400 /* Line enabled */
|
||||
#define DATA 0x00800 /* Data available */
|
||||
#define INIT1 0x01000 /* Send DO EOR, waiting WILL EOR */
|
||||
#define INPUT 0x02000 /* Input ready */
|
||||
#define ATTN 0x04000 /* Send attention signal */
|
||||
#define HALT 0x08000 /* Halt operation */
|
||||
|
||||
/* Upper 11 bits of u3 hold the device address */
|
||||
|
||||
/* u4 */
|
||||
/* Where we are reading from */
|
||||
|
||||
/* u5 */
|
||||
/* Sense byte 0 */
|
||||
#define SNS_CMDREJ 0x80 /* Command reject */
|
||||
#define SNS_INTVENT 0x40 /* Unit intervention required */
|
||||
#define SNS_BUSCHK 0x20 /* Parity error on bus */
|
||||
#define SNS_EQUCHK 0x10 /* Equipment check */
|
||||
#define SNS_DATCHK 0x08 /* Data Check */
|
||||
#define SNS_UNITSPC 0x04 /* Specific to unit */
|
||||
#define SNS_CTLCHK 0x02 /* Timeout on device */
|
||||
#define SNS_OPRCHK 0x01 /* Invalid operation to device */
|
||||
|
||||
/* u6 */
|
||||
/* Pointer into buffer */
|
||||
|
||||
#define CMD u3
|
||||
#define IPTR u4
|
||||
#define SNS u5
|
||||
#define BPTR u6
|
||||
|
||||
#define TC_WILL 0x1 /* Option in will state */
|
||||
#define TC_WONT 0x2 /* Wont do option */
|
||||
#define TC_DO 0x4 /* Will do option. */
|
||||
#define TC_DONT 0x8 /* Dont do option */
|
||||
|
||||
#define IAC 255 /* Interpret as command */
|
||||
#define DONT 254 /* Dont use option */
|
||||
#define DO 253 /* Use this option */
|
||||
#define WONT 252 /* I wont use this option */
|
||||
#define WILL 251 /* I will use this option */
|
||||
#define IP 244 /* Interrupt pending */
|
||||
#define BREAK 243 /* Break */
|
||||
#define EOR 239 /* End of record */
|
||||
|
||||
/* Telnet options we care about */
|
||||
#define OPTION_BINARY 0 /* Send 8 bit data */
|
||||
#define OPTION_ECHO 1 /* Echo */
|
||||
#define OPTION_SGA 3 /* Set go ahead */
|
||||
#define OPTION_TERMINAL 24 /* Request terminal type */
|
||||
#define OPTION_EOR 25 /* Handle end of record */
|
||||
|
||||
#define TS_DATA 0 /* Regular state */
|
||||
#define TS_IAC 1 /* Have seen IAC */
|
||||
#define TS_WILL 2 /* Have seen IAC WILL */
|
||||
#define TS_WONT 3 /* Have seen IAC WONT */
|
||||
#define TS_DO 4 /* Have seen IAC DO */
|
||||
#define TS_DONT 5 /* Have seen IAC DONT */
|
||||
|
||||
/* Remove orders */
|
||||
#define REMOTE_EAU 0x6F /* Erase all unprotected */
|
||||
#define REMOTE_EW 0xF5 /* Erase/Write */
|
||||
#define REMOTE_RB 0xF2 /* Read Buffer */
|
||||
#define REMOTE_RM 0x6e /* Read Modified */
|
||||
#define REMOTE_WRT 0xF1 /* Write */
|
||||
|
||||
struct _line {
|
||||
uint16 option_state[256]; /* Current telnet state */
|
||||
uint8 state; /* Current line status */
|
||||
} line_data[NUM_UNITS_SCOM];
|
||||
|
||||
extern int32 tmxr_poll;
|
||||
|
||||
uint8 scoml_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ;
|
||||
uint8 scoml_haltio(UNIT *uptr);
|
||||
t_stat scoml_srv(UNIT *uptr);
|
||||
t_stat scom_reset(DEVICE *dptr);
|
||||
t_stat scom_scan(UNIT *uptr);
|
||||
t_stat scom_readinput(UNIT *uptr);
|
||||
void scom_sendoption(UNIT *uptr, int unit, uint8 state, uint8 opt);
|
||||
t_stat scom_attach(UNIT *uptr, CONST char *);
|
||||
t_stat scom_detach(UNIT *uptr);
|
||||
t_stat scom_help (FILE *, DEVICE *, UNIT *, int32, const char *);
|
||||
const char *scom_description (DEVICE *);
|
||||
|
||||
uint8 scom_buf[NUM_UNITS_SCOM][256];
|
||||
TMLN scom_ldsc[NUM_UNITS_SCOM];
|
||||
TMXR scom_desc = { NUM_UNITS_SCOM, 0, 0, scom_ldsc};
|
||||
|
||||
|
||||
MTAB scom_mod[] = {
|
||||
{0}
|
||||
};
|
||||
|
||||
MTAB scoml_mod[] = {
|
||||
{MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr,
|
||||
&show_dev_addr, NULL},
|
||||
{0}
|
||||
};
|
||||
|
||||
UNIT scom_unit[] = {
|
||||
{UDATA(&scom_scan, UNIT_ATTABLE | UNIT_IDLE, 0)}, /* Line scanner */
|
||||
};
|
||||
|
||||
UNIT scoml_unit[] = {
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x050)}, /* 0 */
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x051)}, /* 1 */
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x052)}, /* 2 */
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x053)}, /* 3 */
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x054)}, /* 4 */
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x055)}, /* 5 */
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x056)}, /* 6 */
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x057)}, /* 7 */
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x058)}, /* 8 */
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x059)}, /* 9 */
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x05A)}, /* A */
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x05B)}, /* B */
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x05C)}, /* C */
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x05D)}, /* D */
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x05E)}, /* E */
|
||||
{UDATA(&scoml_srv, UNIT_COM, 0), 0, UNIT_ADDR(0x05F)}, /* F */
|
||||
};
|
||||
|
||||
struct dib scom_dib = { 0xF0, NUM_UNITS_SCOM, NULL, scoml_startcmd,
|
||||
scoml_haltio, scoml_unit, NULL};
|
||||
|
||||
DEVICE scom_dev = {
|
||||
"SCOM", scom_unit, NULL, scom_mod,
|
||||
NUM_DEVS_SCOM, 8, 15, 1, 8, 8,
|
||||
NULL, NULL, scom_reset, NULL, &scom_attach, &scom_detach,
|
||||
NULL, DEV_MUX | DEV_DISABLE | DEV_DEBUG, 0, dev_debug,
|
||||
NULL, NULL, &scom_help, NULL, NULL, &scom_description
|
||||
};
|
||||
|
||||
DEVICE scoml_dev = {
|
||||
"SCOML", scoml_unit, NULL, scoml_mod,
|
||||
NUM_UNITS_SCOM, 8, 15, 1, 8, 8,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
&scom_dib, DEV_DISABLE | DEV_DEBUG, 0, dev_debug
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Issue a scommand to the 2701 controller.
|
||||
*/
|
||||
uint8 scoml_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
|
||||
uint16 addr = GET_UADDR(uptr->CMD);
|
||||
DEVICE *dptr = find_dev_from_unit(uptr);
|
||||
int unit = (uptr - dptr->units);
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr, "CMD unit=%d %x\n", unit, cmd);
|
||||
if ((uptr->CMD & 0xff) != 0) {
|
||||
return SNS_BSY;
|
||||
}
|
||||
|
||||
|
||||
switch (cmd & 0x3) {
|
||||
case 0x2: /* Read scommand */
|
||||
case 0x1: /* Write scommand */
|
||||
case 0x3: /* Control */
|
||||
if (cmd != CMD_NOP)
|
||||
uptr->SNS = 0;
|
||||
uptr->CMD |= cmd;
|
||||
sim_activate(uptr, 200);
|
||||
return 0;
|
||||
|
||||
case 0x0: /* Status */
|
||||
if (cmd == 0x4) { /* Sense */
|
||||
uptr->CMD |= cmd;
|
||||
sim_activate(uptr, 200);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (uptr->SNS & 0xff)
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
|
||||
return SNS_CHNEND|SNS_DEVEND;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle halt I/O instruction by stoping running scommand.
|
||||
*/
|
||||
uint8 scoml_haltio(UNIT *uptr) {
|
||||
uint16 addr = GET_UADDR(uptr->CMD);
|
||||
DEVICE *dptr = find_dev_from_unit(uptr);
|
||||
int unit = (uptr - dptr->units);
|
||||
int cmd = uptr->CMD & 0xff;
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr, "HLTIO unit=%d %x\n", unit, cmd);
|
||||
if ((scom_unit[0].flags & UNIT_ATT) == 0) /* attached? */
|
||||
return 3;
|
||||
|
||||
switch (cmd) {
|
||||
case 0:
|
||||
case 0x4:
|
||||
case CMD_SEL: /* Select */
|
||||
case CMD_NOP: /* Nop scommand */
|
||||
/* Short scommands nothing to do */
|
||||
break;
|
||||
|
||||
case CMD_WR: /* Write data to com line */
|
||||
case CMD_RD: /* Read buffer */
|
||||
case CMD_WRER: /* Erase and write data */
|
||||
case CMD_RDMD: /* Read modified */
|
||||
case CMD_EAU: /* Erase all un protected */
|
||||
uptr->CMD |= HALT;
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
|
||||
sim_activate(uptr, 20);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Handle per unit scommands */
|
||||
t_stat scoml_srv(UNIT * uptr)
|
||||
{
|
||||
uint16 addr = GET_UADDR(uptr->CMD);
|
||||
DEVICE *dptr = find_dev_from_unit(uptr);
|
||||
int unit = (uptr - dptr->units);
|
||||
int cmd = uptr->CMD & 0xff;
|
||||
uint8 ch;
|
||||
|
||||
if ((uptr->CMD & (RECV|DATA)) != 0) {
|
||||
sim_activate(uptr, 200);
|
||||
return scom_readinput(uptr);
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 0x4:
|
||||
ch = uptr->SNS & 0xff;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "sense unit=%d 1 %x\n", unit, ch);
|
||||
chan_write_byte(addr, &ch) ;
|
||||
uptr->CMD &= ~0xff;
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
|
||||
break;
|
||||
|
||||
case CMD_RDMD: /* Read modified */
|
||||
case CMD_RD: /* Read in data from scom line */
|
||||
uptr->SNS = 0;
|
||||
if (uptr->CMD & HALT) {
|
||||
uptr->CMD &= ~(0xFF|RECV);
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (uptr->CMD & ENAB) {
|
||||
if (scom_ldsc[unit].conn == 0) {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "unit=%d disco\n", unit);
|
||||
uptr->CMD &= ~(0xff|INPUT|ENAB|RECV|INIT1|SEND|DATA);
|
||||
uptr->SNS = SNS_CTLCHK;
|
||||
uptr->BPTR = 0;
|
||||
uptr->IPTR = 0;
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP);
|
||||
return SCPE_OK;
|
||||
}
|
||||
if ((uptr->CMD & RECV) == 0) {
|
||||
/* Send cmd IAC EOR */
|
||||
if (tmxr_rqln(&scom_ldsc[unit]) == 0) {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "unit=%d Send read cmd %x\n", unit, cmd);
|
||||
if (cmd == CMD_RD)
|
||||
tmxr_putc_ln( &scom_ldsc[unit], REMOTE_RB);
|
||||
else
|
||||
tmxr_putc_ln( &scom_ldsc[unit], REMOTE_RM);
|
||||
tmxr_putc_ln( &scom_ldsc[unit], IAC);
|
||||
tmxr_putc_ln( &scom_ldsc[unit], EOR);
|
||||
}
|
||||
uptr->CMD |= RECV;
|
||||
}
|
||||
sim_activate(uptr, 200);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case CMD_WRER: /* Erase and write data */
|
||||
ch = REMOTE_EW;
|
||||
goto write;
|
||||
|
||||
case CMD_EAU: /* Erase all un protected */
|
||||
ch = REMOTE_EAU;
|
||||
goto write;
|
||||
|
||||
case CMD_WR: /* Write data to com line */
|
||||
ch = REMOTE_WRT;
|
||||
write:
|
||||
uptr->SNS = 0;
|
||||
if (uptr->CMD & HALT) {
|
||||
uptr->CMD &= ~(0xFF|SEND);
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (uptr->CMD & ENAB) {
|
||||
if ((uptr->CMD & SEND) == 0) {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "unit=%d send write %x\n", unit, ch);
|
||||
tmxr_putc_ln( &scom_ldsc[unit], ch);
|
||||
uptr->CMD |= SEND;
|
||||
}
|
||||
if (scom_ldsc[unit].conn == 0) {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "unit=%d disco\n", unit);
|
||||
uptr->CMD &= ~(0xff|INPUT|ENAB|RECV|INIT1|SEND|DATA);
|
||||
uptr->SNS = SNS_CTLCHK;
|
||||
uptr->BPTR = 0;
|
||||
uptr->IPTR = 0;
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP);
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (chan_read_byte (addr, &ch)) {
|
||||
tmxr_putc_ln( &scom_ldsc[unit], IAC);
|
||||
tmxr_putc_ln( &scom_ldsc[unit], EOR);
|
||||
uptr->CMD &= ~(0xff| SEND);
|
||||
sim_debug(DEBUG_CMD, dptr, "COM: unit=%d eor\n", unit);
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
|
||||
} else {
|
||||
int32 data;
|
||||
data = ebcdic_to_ascii[ch];
|
||||
sim_debug(DEBUG_CMD, dptr, "COM: unit=%d send %02x '%c'\n",
|
||||
unit, ch, isprint(data)? data: '^');
|
||||
tmxr_putc_ln( &scom_ldsc[unit], ch);
|
||||
if (ch == IAC)
|
||||
tmxr_putc_ln( &scom_ldsc[unit], ch);
|
||||
sim_activate(uptr, 200);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_NOP: /* Nop scommand */
|
||||
uptr->CMD &= ~0xff;
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
|
||||
break;
|
||||
|
||||
case CMD_SEL: /* Select */
|
||||
uptr->CMD &= ~0xff;
|
||||
uptr->SNS = 0;
|
||||
sim_debug(DEBUG_CMD, dptr, "COM: unit=%d select done\n", unit);
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
|
||||
break;
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Scan for new connections, flush and poll for data */
|
||||
t_stat scom_scan(UNIT * uptr)
|
||||
{
|
||||
UNIT *line;
|
||||
int32 ln;
|
||||
struct _line *data;
|
||||
int i;
|
||||
|
||||
sim_activate(uptr, tmxr_poll); /* continue poll */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return SCPE_OK;
|
||||
ln = tmxr_poll_conn (&scom_desc); /* look for connect */
|
||||
sim_debug(DEBUG_EXP, &scom_dev, "SCOM Poll %d\n", ln);
|
||||
if (ln >= 0) { /* got one? rcv enb*/
|
||||
line = &scoml_unit[ln];
|
||||
data = (struct _line *)(line->up7);
|
||||
sim_debug(DEBUG_DETAIL, &scom_dev, "SCOM line connect %d\n", ln);
|
||||
scom_ldsc[ln].rcve = 1; /* Mark as ok */
|
||||
for (i = 0; i < 256; i++)
|
||||
data->option_state[i] = 0;
|
||||
scom_sendoption(line, ln, DO, OPTION_TERMINAL);
|
||||
scom_sendoption(line, ln, DO, OPTION_EOR);
|
||||
line->CMD |= ENAB|DATA|INIT1;
|
||||
line->CMD &= ~(RECV|SEND);
|
||||
sim_activate(line, 20000);
|
||||
}
|
||||
|
||||
/* See if a line is disconnected with no scommand on it. */
|
||||
for (ln = 0; ln < scom_desc.lines; ln++) {
|
||||
line = &scoml_unit[ln];
|
||||
if ((line->CMD & (SEND|RECV|ENAB)) == ENAB && tmxr_rqln(&scom_ldsc[ln]) > 0) {
|
||||
if ((line->CMD & (DATA|INIT1)) != 0 || (line->CMD & 0xff) != 0)
|
||||
sim_activate(line, 200);
|
||||
else
|
||||
set_devattn(GET_UADDR(line->CMD), SNS_ATTN);
|
||||
}
|
||||
}
|
||||
tmxr_poll_tx(&scom_desc);
|
||||
tmxr_poll_rx(&scom_desc);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Process characters from remote */
|
||||
t_stat
|
||||
scom_readinput(UNIT *uptr)
|
||||
{
|
||||
DEVICE *dptr = find_dev_from_unit(uptr);
|
||||
uint16 addr = GET_UADDR(uptr->CMD);
|
||||
int unit = (uptr - dptr->units);
|
||||
int cmd = uptr->CMD & 0xff;
|
||||
int32 r;
|
||||
struct _line *data = (struct _line *)(uptr->up7);
|
||||
uint8 ch;
|
||||
|
||||
while (((r = tmxr_getc_ln (&scom_ldsc[unit])) & TMXR_VALID) != 0) {
|
||||
ch = r & 0xff;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "unit=%d got %x\n", unit, ch);
|
||||
switch (data->state) {
|
||||
case TS_DATA:
|
||||
if (ch == IAC) {
|
||||
data->state = TS_IAC;
|
||||
break;
|
||||
}
|
||||
if (uptr->CMD & RECV) {
|
||||
if (chan_write_byte( addr, &ch)) {
|
||||
uptr->CMD &= ~(0xff|RECV);
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TS_IAC:
|
||||
switch (ch) {
|
||||
case WILL:
|
||||
data->state = TS_WILL;
|
||||
break;
|
||||
case WONT:
|
||||
data->state = TS_WONT;
|
||||
break;
|
||||
case DO:
|
||||
data->state = TS_DO;
|
||||
break;
|
||||
case DONT:
|
||||
data->state = TS_DONT;
|
||||
break;
|
||||
case IAC:
|
||||
data->state = TS_DATA;
|
||||
if (uptr->CMD & RECV) {
|
||||
if (chan_write_byte( addr, &ch)) {
|
||||
uptr->CMD &= ~(0xff|RECV);
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IP:
|
||||
case BREAK:
|
||||
case EOR:
|
||||
data->state = TS_DATA;
|
||||
if (uptr->CMD & RECV) {
|
||||
uptr->CMD &= ~(0xff|RECV);
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TS_WILL:
|
||||
switch (ch) {
|
||||
case OPTION_TERMINAL: /* Ignore terminal option */
|
||||
data->option_state[ch] |= TC_WILL|TC_DONT;
|
||||
break;
|
||||
|
||||
case OPTION_BINARY:
|
||||
case OPTION_ECHO:
|
||||
case OPTION_SGA:
|
||||
case OPTION_EOR:
|
||||
if ((data->option_state[ch] & TC_WILL) == 0) {
|
||||
scom_sendoption(uptr, unit, WILL, ch);
|
||||
if (ch == OPTION_EOR && (uptr->CMD & INIT1) != 0) {
|
||||
scom_sendoption(uptr, unit, DO, OPTION_BINARY);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
if ((data->option_state[ch] & TC_DONT) == 0)
|
||||
scom_sendoption(uptr, unit, DONT, ch);
|
||||
break;
|
||||
}
|
||||
data->state = TS_DATA;
|
||||
break;
|
||||
|
||||
case TS_WONT:
|
||||
if ((data->option_state[ch] & TC_WONT) == 0)
|
||||
scom_sendoption(uptr, unit, WONT, ch);
|
||||
break;
|
||||
|
||||
case TS_DO:
|
||||
switch (ch) {
|
||||
case OPTION_BINARY:
|
||||
case OPTION_ECHO:
|
||||
case OPTION_SGA:
|
||||
case OPTION_EOR:
|
||||
if ((data->option_state[ch] & TC_WILL) != 0) {
|
||||
if (ch == OPTION_BINARY) {
|
||||
uptr->CMD &= ~(DATA|INIT1);
|
||||
uptr->CMD |= ENAB;
|
||||
tmxr_putc_ln( &scom_ldsc[unit], REMOTE_EW);
|
||||
tmxr_putc_ln( &scom_ldsc[unit], 0xc1);
|
||||
tmxr_putc_ln( &scom_ldsc[unit], IAC);
|
||||
tmxr_putc_ln( &scom_ldsc[unit], EOR);
|
||||
if ((uptr->CMD & 0xff) == 0)
|
||||
set_devattn(addr, SNS_ATTN);
|
||||
else
|
||||
sim_activate(uptr, 200);
|
||||
}
|
||||
}
|
||||
if ((data->option_state[ch] & TC_DO) == 0)
|
||||
scom_sendoption(uptr, unit, DO, ch);
|
||||
break;
|
||||
default:
|
||||
if ((data->option_state[ch] & TC_WONT) == 0)
|
||||
scom_sendoption(uptr, unit, WONT, ch);
|
||||
break;
|
||||
}
|
||||
data->state = TS_DATA;
|
||||
break;
|
||||
case TS_DONT:
|
||||
if ((data->option_state[ch] & TC_WILL) != 0) {
|
||||
/* send IAC WONT option */
|
||||
data->option_state[ch] &= ~TC_WILL;
|
||||
scom_sendoption(uptr, unit, WILL, ch);
|
||||
}
|
||||
data->state = TS_DATA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
void
|
||||
scom_sendoption(UNIT *uptr, int unit, uint8 state, uint8 opt)
|
||||
{
|
||||
struct _line *data = (struct _line *)(uptr->up7);
|
||||
|
||||
tmxr_putc_ln( &scom_ldsc[unit], IAC);
|
||||
tmxr_putc_ln( &scom_ldsc[unit], state);
|
||||
tmxr_putc_ln( &scom_ldsc[unit], opt);
|
||||
tmxr_send_buffered_data(&scom_ldsc[unit]);
|
||||
switch(state) {
|
||||
case WILL:
|
||||
data->option_state[opt] |= TC_WILL;
|
||||
break;
|
||||
case WONT:
|
||||
data->option_state[opt] |= TC_WONT;
|
||||
break;
|
||||
case DO:
|
||||
data->option_state[opt] |= TC_DO;
|
||||
break;
|
||||
case DONT:
|
||||
data->option_state[opt] |= TC_DONT;
|
||||
}
|
||||
}
|
||||
|
||||
t_stat
|
||||
scom_reset(DEVICE * dptr)
|
||||
{
|
||||
int i;
|
||||
sim_activate(&scom_unit[0], tmxr_poll);
|
||||
(void)tmxr_set_notelnet (&scom_desc);
|
||||
for (i = 0; i < NUM_UNITS_SCOM; i++)
|
||||
scoml_unit[i].up7 = &line_data[i];
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
t_stat
|
||||
scom_attach(UNIT * uptr, CONST char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
int i;
|
||||
|
||||
if ((r = tmxr_attach(&scom_desc, uptr, cptr)) != SCPE_OK)
|
||||
return r;
|
||||
for (i = 0; i< scom_desc.lines; i++) {
|
||||
scoml_unit[i].CMD &= ~0xffff;
|
||||
}
|
||||
sim_activate(uptr, tmxr_poll);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat
|
||||
scom_detach(UNIT * uptr)
|
||||
{
|
||||
t_stat r;
|
||||
int i;
|
||||
|
||||
for (i = 0; i< scom_desc.lines; i++) {
|
||||
(void)tmxr_set_get_modem_bits(&scom_ldsc[i], 0, TMXR_MDM_DTR, NULL);
|
||||
(void)tmxr_reset_ln(&scom_ldsc[i]);
|
||||
scoml_unit[i].CMD &= ~0xffff;
|
||||
}
|
||||
sim_cancel(uptr);
|
||||
r = tmxr_detach(&scom_desc, uptr);
|
||||
return r;
|
||||
}
|
||||
|
||||
t_stat scom_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
|
||||
const char *cptr)
|
||||
{
|
||||
fprint_set_help (st, dptr);
|
||||
fprint_show_help (st, dptr);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
const char *scom_description (DEVICE *dptr)
|
||||
{
|
||||
return "IBM 3271 communications controller";
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -80,6 +80,10 @@ DEVICE *sim_devices[] = {
|
||||
#ifdef NUM_DEVS_COM
|
||||
&coml_dev,
|
||||
&com_dev,
|
||||
#endif
|
||||
#ifdef NUM_DEVS_SCOM
|
||||
&scoml_dev,
|
||||
&scom_dev,
|
||||
#endif
|
||||
NULL };
|
||||
|
||||
@@ -103,6 +107,7 @@ DEBTAB crd_debug[] = {
|
||||
{"DETAIL", DEBUG_DETAIL, "Show details about device"},
|
||||
{"EXP", DEBUG_EXP, "Show exception information"},
|
||||
{"CARD", DEBUG_CARD, "Show Card read/punches"},
|
||||
{"CDATA", DEBUG_CDATA, "Show channel data"},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
|
||||
@@ -230,6 +230,10 @@
|
||||
RelativePath="..\IBM360\ibm360_mt.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\IBM360\ibm360_scom.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\IBM360\ibm360_sys.c"
|
||||
>
|
||||
|
||||
@@ -229,6 +229,10 @@
|
||||
RelativePath="..\IBM360\ibm360_mt.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\IBM360\ibm360_scom.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\IBM360\ibm360_sys.c"
|
||||
>
|
||||
|
||||
BIN
doc/ibm360.doc
BIN
doc/ibm360.doc
Binary file not shown.
9
makefile
9
makefile
@@ -1987,11 +1987,10 @@ ICL1900 = ${ICL1900D}/icl1900_cpu.c ${ICL1900D}/icl1900_sys.c \
|
||||
ICL1900_OPT = -I $(ICL1900D) -DICL1900 -DUSE_SIM_CARD
|
||||
|
||||
IBM360D = ${SIMHD}/IBM360
|
||||
IBM360 = ${IBM360D}/ibm360_cpu.c ${IBM360D}/ibm360_sys.c \
|
||||
${IBM360D}/ibm360_con.c ${IBM360D}/ibm360_chan.c \
|
||||
${IBM360D}/ibm360_cdr.c ${IBM360D}/ibm360_cdp.c \
|
||||
${IBM360D}/ibm360_mt.c ${IBM360D}/ibm360_lpr.c \
|
||||
${IBM360D}/ibm360_dasd.c ${IBM360D}/ibm360_com.c
|
||||
IBM360 = ${IBM360D}/ibm360_cpu.c ${IBM360D}/ibm360_sys.c ${IBM360D}/ibm360_con.c \
|
||||
${IBM360D}/ibm360_chan.c ${IBM360D}/ibm360_cdr.c ${IBM360D}/ibm360_cdp.c \
|
||||
${IBM360D}/ibm360_mt.c ${IBM360D}/ibm360_lpr.c ${IBM360D}/ibm360_dasd.c \
|
||||
${IBM360D}/ibm360_com.c ${IBM360D}/ibm360_scom.c
|
||||
IBM360_OPT = -I $(IBM360D) -DIBM360 -DUSE_64BIT -DUSE_SIM_CARD
|
||||
IBM360_OPT32 = -I $(IBM360D) -DIBM360 -DUSE_SIM_CARD
|
||||
|
||||
|
||||
Reference in New Issue
Block a user