From 37f75197271b4b6309fe66562610f1dcf8c9302a Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Mon, 29 Jun 2020 22:14:17 -0400 Subject: [PATCH] IBM360: Added 3270 terminal support. --- IBM360/ibm360_defs.h | 4 + IBM360/ibm360_scom.c | 647 ++++++++++++++++++++++++ IBM360/ibm360_sys.c | 5 + Visual Studio Projects/IBM360.vcproj | 4 + Visual Studio Projects/IBM360_32.vcproj | 4 + doc/ibm360.doc | Bin 105984 -> 114176 bytes makefile | 9 +- 7 files changed, 668 insertions(+), 5 deletions(-) create mode 100644 IBM360/ibm360_scom.c diff --git a/IBM360/ibm360_defs.h b/IBM360/ibm360_defs.h index f9e1bbd..28ca54a 100644 --- a/IBM360/ibm360_defs.h +++ b/IBM360/ibm360_defs.h @@ -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 *); diff --git a/IBM360/ibm360_scom.c b/IBM360/ibm360_scom.c new file mode 100644 index 0000000..039c75a --- /dev/null +++ b/IBM360/ibm360_scom.c @@ -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 diff --git a/IBM360/ibm360_sys.c b/IBM360/ibm360_sys.c index 533efd2..730b108 100644 --- a/IBM360/ibm360_sys.c +++ b/IBM360/ibm360_sys.c @@ -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} }; diff --git a/Visual Studio Projects/IBM360.vcproj b/Visual Studio Projects/IBM360.vcproj index 4448192..ba16729 100644 --- a/Visual Studio Projects/IBM360.vcproj +++ b/Visual Studio Projects/IBM360.vcproj @@ -230,6 +230,10 @@ RelativePath="..\IBM360\ibm360_mt.c" > + + diff --git a/Visual Studio Projects/IBM360_32.vcproj b/Visual Studio Projects/IBM360_32.vcproj index 2a5b6d5..22fa726 100644 --- a/Visual Studio Projects/IBM360_32.vcproj +++ b/Visual Studio Projects/IBM360_32.vcproj @@ -229,6 +229,10 @@ RelativePath="..\IBM360\ibm360_mt.c" > + + diff --git a/doc/ibm360.doc b/doc/ibm360.doc index 9b7d7714a91c3e6614ea5c252dfc99639d2aada4..5b3d271f97b3850f28150ab81153a2d3991bca9f 100644 GIT binary patch delta 9811 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