From 0385a7108c2bfdda241980338ec7da2b141e610b Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Fri, 15 May 2020 20:17:31 -0400 Subject: [PATCH] IBM360: Updated so 2703 works as a 1050. --- IBM360/ibm360_chan.c | 9 +- IBM360/ibm360_com.c | 269 ++++++++++++++++++++++++++++--------------- IBM360/ibm360_cpu.c | 23 ++-- 3 files changed, 192 insertions(+), 109 deletions(-) diff --git a/IBM360/ibm360_chan.c b/IBM360/ibm360_chan.c index 043e6d0..eec2bbe 100644 --- a/IBM360/ibm360_chan.c +++ b/IBM360/ibm360_chan.c @@ -905,6 +905,12 @@ int haltio(uint16 addr) { return 0; } + /* If channel active, tell it to terminate */ + if (ccw_cmd[chan]) { + chan_byte[chan] = BUFF_CHNEND; + ccw_flags[chan] = 0; + } + /* Not executing a command, issue halt if available */ if (dibp->halt_io != NULL) { /* Let device do it's thing */ @@ -918,9 +924,6 @@ int haltio(uint16 addr) { return cc; } - /* If channel active, tell it to terminate */ - if (ccw_cmd[chan]) - chan_byte[chan] = BUFF_CHNEND; /* Store CSW and return 1. */ sim_debug(DEBUG_CMD, &cpu_dev, "HIOx %x %x cc=1\n", addr, chan); diff --git a/IBM360/ibm360_com.c b/IBM360/ibm360_com.c index cdd6433..38df688 100644 --- a/IBM360/ibm360_com.c +++ b/IBM360/ibm360_com.c @@ -31,25 +31,30 @@ /* u3 */ -#define CMD_RD 0x02 /* Read in data from com line */ #define CMD_WR 0x01 /* Write data to com line */ +#define CMD_RD 0x02 /* Read in data from com line */ #define CMD_NOP 0x03 /* Nop command */ -#define CMD_DIAL 0x29 /* Dial call */ -#define CMD_BRK 0x0D /* Send break signal */ #define CMD_PREP 0x06 /* Wait for incoming data */ #define CMD_INH 0x0A /* Read data without timeout */ +#define CMD_BRK 0x0D /* Send break signal */ #define CMD_SRCH 0x0E /* Wait for EOT character */ #define CMD_ENB 0x27 /* Enable line */ +#define CMD_DIAL 0x29 /* Dial call */ #define CMD_DIS 0x2F /* Disable line */ /* u3 second byte */ -#define RECV 0x0100 /* Recieving data */ -#define SEND 0x0200 /* Sending data */ -#define ENAB 0x0400 /* Line enabled */ -#define POLL 0x0800 /* Waiting for connection */ -#define INPUT 0x1000 /* Need to send BOT */ +#define RECV 0x00100 /* Recieving data */ +#define SEND 0x00200 /* Sending data */ +#define ENAB 0x00400 /* Line enabled */ +#define POLL 0x00800 /* Waiting for connection */ +#define ADDR 0x01000 /* Address request recieved. */ +#define INPUT 0x02000 /* Input ready */ +#define ATTN 0x04000 /* Send attention signal */ +#define ADDR9 0x08000 /* Address char 9 recieved */ +#define BYPASS 0x10000 /* Don't echo output */ +#define BREAK 0x20000 /* Return unit exception */ -/* u5 */ +/* u4 */ /* Sense byte 0 */ #define SNS_CMDREJ 0x80 /* Command reject */ #define SNS_INTVENT 0x40 /* Unit intervention required */ @@ -60,7 +65,13 @@ #define SNS_RECV 0x02 /* Receiving */ #define SNS_TIMEOUT 0x01 /* Timeout */ +/* u5 */ +/* Where we are reading from */ +#define IPTR u5 + /* u6 */ +/* Pointer into buffer */ +#define BPTR u6 uint8 coml_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; uint8 coml_haltio(UNIT *uptr); @@ -71,7 +82,6 @@ t_stat com_scan(UNIT *uptr); t_stat com_attach(UNIT *uptr, CONST char *); t_stat com_detach(UNIT *uptr); uint8 com_buf[NUM_UNITS_COM][256]; -int com_ptr[NUM_UNITS_COM]; TMLN com_ldsc[NUM_UNITS_COM]; TMXR com_desc = { NUM_UNITS_COM, 0, 0, com_ldsc}; @@ -147,7 +157,7 @@ static const uint8 com_2741_in[128] = { /* sp ! " # $ % & ' */ 0x81, 0xD7, 0x00, 0x16, 0x57, 0x8B, 0x61, 0x8D, /* 40 - 77 */ /* ( ) * + , - . / */ - 0x93, 0x94, 0x00, 0xE1, 0x37, 0xC0, 0x00, 0x23, + 0x93, 0x95, 0x90, 0xE1, 0x37, 0xC0, 0x76, 0x23, /* 0 1 2 3 4 5 6 7 */ 0x15, 0x02, 0x04, 0x07, 0x08, 0x0B, 0x0D, 0x0E, /* 8 9 : ; < = > ? */ @@ -200,7 +210,7 @@ static const uint8 com_2741_out[256] = { /* 8, 9, A, B, C, D, E, F, */ 'd', 0xff, 0xff, 'e', 0xff, 'f', 'g', 0xff, /* 0, 1, 2, 3, 4, 5, 6, 7, */ - 'h', 0xff, 0xff, 'i', 0xff, 0xff, 0xff, 0xff, /* 0x7x */ + 'h', 0xff, 0xff, 'i', 0xff, 0xff, '.', 0xff, /* 0x7x */ /* 8, 9, A, B, C, D, E, F, */ 0xff, 0xff, 0x09, 0xff, 0xff, 0xff, 0xff, 0x7f, /* 0, 1, 2, 3, 4, 5, 6, 7, */ @@ -266,7 +276,7 @@ uint8 coml_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { } break; } - if (uptr->u5 & 0xff) + if (uptr->u4 & 0xff) return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; return SNS_CHNEND|SNS_DEVEND; } @@ -295,7 +305,7 @@ uint8 coml_haltio(UNIT *uptr) { case CMD_BRK: /* Send break signal */ case CMD_PREP: /* Wait for incoming data */ case CMD_SRCH: /* Wait for EOT character */ - uptr->u3 &= ~0xff; + uptr->u3 &= ~(ADDR9|ADDR|0xff); chan_end(addr, SNS_CHNEND|SNS_DEVEND); break; case CMD_ENB: /* Enable line */ @@ -323,7 +333,7 @@ t_stat coml_srv(UNIT * uptr) break; case 0x4: - ch = uptr->u5 & 0xff; + ch = uptr->u4 & 0xff; sim_debug(DEBUG_DETAIL, dptr, "sense unit=%d 1 %x\n", unit, ch); chan_write_byte(addr, &ch) ; uptr->u3 &= ~0xff; @@ -331,47 +341,76 @@ t_stat coml_srv(UNIT * uptr) break; case CMD_DIAL: /* Dial call */ - uptr->u5 = SNS_CMDREJ; + uptr->u4 = SNS_CMDREJ; chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; case CMD_INH: /* Read data without timeout */ case CMD_RD: /* Read in data from com line */ + uptr->u4 = 0; if (uptr->u3 & ENAB) { - if (tmxr_rqln(&com_ldsc[unit]) > 0) { - int32 data = tmxr_getc_ln (&com_ldsc[unit]); - sim_debug(DEBUG_DATA, dptr, "COML: unit=%d read '%c'\n", unit, data); - if (data & SCPE_BREAK) { - uptr->u3 &= ~0xff; - chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; - } else { - ch = sim_tt_inpcvt (data, TT_GET_MODE(uptr->flags) | - TTUF_KSR); - ch = com_2741_in[data & 0x7f]; - sim_debug(DEBUG_CMD, dptr, "COM: unit=%d read '%c'\n", unit, data & 0x7f); - if (chan_write_byte( addr, &ch)) { - uptr->u3 &= ~0xff; - chan_end(addr, SNS_CHNEND|SNS_DEVEND); - return SCPE_OK; - } - if (ch == 0x5b) { - ch = 0x1f; - (void)chan_write_byte( addr, &ch); - uptr->u3 &= ~0xff; - chan_end(addr, SNS_CHNEND|SNS_DEVEND); - return SCPE_OK; - } - ch = sim_tt_outcvt(data, TT_GET_MODE(uptr->flags) | TTUF_KSR); - tmxr_putc_ln( &com_ldsc[unit], ch); - } + if (com_ldsc[unit].conn == 0) { + uptr->u3 &= ~(0xff|BREAK|INPUT|ENAB|POLL); + uptr->u4 = SNS_INTVENT; + uptr->BPTR = 0; + uptr->IPTR = 0; + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); + return SCPE_OK; + } + if (uptr->u3 & ADDR) { + ch = 0x16; + sim_debug(DEBUG_CMD, dptr, "COM: unit=%d addr %02x\n", unit, ch); + uptr->u3 &= ~ADDR; + if (chan_write_byte( addr, &ch)) { + uptr->u3 &= ~(ADDR9|0xff); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); + return SCPE_OK; + } + if (uptr->u3 & ADDR9) { + uptr->u3 &= ~(ADDR9|0xff); + sim_debug(DEBUG_CMD, dptr, "COM: unit=%d addr9 %02x\n", unit, ch); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); + return SCPE_OK; + } + } else if (uptr->u3 & BREAK) { + uptr->u3 &= ~(0xff|BREAK|INPUT); + uptr->u4 = SNS_INTVENT; + uptr->BPTR = 0; + uptr->IPTR = 0; + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); + return SCPE_OK; + } else if (uptr->u3 & INPUT) { + if (uptr->BPTR == uptr->IPTR) { + uptr->u3 &= ~(0xff|INPUT); + uptr->BPTR = 0; + uptr->IPTR = 0; + chan_end(addr, SNS_CHNEND|SNS_DEVEND); + return SCPE_OK; + } + ch = com_buf[unit][uptr->IPTR++]; + if (chan_write_byte( addr, &ch)) { + uptr->u3 &= ~(0xff|INPUT); + uptr->IPTR = 0; + uptr->BPTR = 0; + chan_end(addr, SNS_CHNEND|SNS_DEVEND); + return SCPE_OK; + } } sim_activate(uptr, 200); } break; case CMD_WR: /* Write data to com line */ + uptr->u4 = 0; if (uptr->u3 & ENAB) { + if (com_ldsc[unit].conn == 0) { + uptr->u3 &= ~(0xff|BREAK|INPUT|ENAB|POLL); + uptr->u4 = SNS_INTVENT; + uptr->BPTR = 0; + uptr->IPTR = 0; + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); + return SCPE_OK; + } sim_debug(DEBUG_CMD, dptr, "COM: unit=%d write\n", unit); if (chan_read_byte (addr, &ch)) { uptr->u3 &= ~0xff; @@ -379,13 +418,23 @@ t_stat coml_srv(UNIT * uptr) } else { int32 data; data = com_2741_out[ch]; - if (data != 0xff) { + sim_debug(DEBUG_CMD, dptr, "COM: unit=%d send %02x %02x '%c'\n", + unit, ch, data, isprint(data)? data: '^'); + if (ch == 0x1f) { /* Check for address character */ + uptr->u3 |= ADDR; + } else if (ch == 0x16) { + uptr->u3 &= ~ADDR; + } else if (ch == 0xb8) { /* Bypass */ + uptr->u3 |= BYPASS; + } else if (ch == 0x58) { /* Restore */ + uptr->u3 &= ~(BYPASS|ADDR|ADDR9); + } else if ((uptr->u3 & ADDR) != 0 && ch == 0x13) { + uptr->u3 |= ADDR9; + } else if ((uptr->u3 & ADDR) == 0 && data != 0xff) { data = sim_tt_outcvt(data, TT_GET_MODE(uptr->flags) | TTUF_KSR); - sim_debug(DEBUG_CMD, dptr, "COM: unit=%d send '%c'\n", - unit, isprint(data)? data: '^'); tmxr_putc_ln( &com_ldsc[unit], data); - if (ch == 0x5b) + if (ch == 0x5b) tmxr_putc_ln( &com_ldsc[unit], '\r'); } sim_activate(uptr, 20000); @@ -399,16 +448,26 @@ t_stat coml_srv(UNIT * uptr) case CMD_BRK: /* Send break signal */ uptr->u3 &= ~0xff; + uptr->u4 = 0; chan_end(addr, SNS_CHNEND|SNS_DEVEND); break; case CMD_PREP: /* Wait for incoming data */ + uptr->u4 = 0; if (uptr->u3 & ENAB) { - if (tmxr_rqln(&com_ldsc[unit]) > 0) { + if (com_ldsc[unit].conn == 0) { + uptr->u3 &= ~(0xff|BREAK|INPUT|ENAB|POLL); + uptr->u4 = SNS_INTVENT; + uptr->BPTR = 0; + uptr->IPTR = 0; + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); + return SCPE_OK; + } + uptr->u3 &= ~(ADDR|ADDR9); + if (uptr->u3 & (INPUT|BREAK)) { uptr->u3 &= ~0xff; chan_end(addr, SNS_CHNEND|SNS_DEVEND); } else { - uptr->u3 |= INPUT; sim_activate(uptr, 200); } } else { @@ -419,12 +478,16 @@ t_stat coml_srv(UNIT * uptr) case CMD_SRCH: /* Wait for EOT character */ uptr->u3 &= ~0xff; + uptr->u4 = 0; chan_end(addr, SNS_CHNEND|SNS_DEVEND); break; case CMD_ENB: /* Enable line */ + uptr->u4 = 0; if ((uptr->u3 & (POLL|ENAB)) == ENAB) { uptr->u3 &= ~0xff; + uptr->BPTR = 0; + uptr->IPTR = 0; sim_debug(DEBUG_CMD, dptr, "COM: unit=%d enable connect\n", unit); chan_end(addr, SNS_CHNEND|SNS_DEVEND); } else if ((uptr->u3 & POLL) == 0) { @@ -436,6 +499,7 @@ t_stat coml_srv(UNIT * uptr) break; case CMD_DIS: /* Disable line */ + uptr->u4 = 0; sim_debug(DEBUG_CMD, dptr, "COM: unit=%d disable\n", unit); (void)tmxr_set_get_modem_bits(&com_ldsc[unit], 0, TMXR_MDM_DTR, NULL); (void)tmxr_reset_ln(&com_ldsc[unit]); @@ -444,57 +508,70 @@ t_stat coml_srv(UNIT * uptr) break; } -#if 0 - r = sim_poll_kbd(); - if (r & SCPE_KFLAG) { - ch = r & 0377; - if ((uptr->u3 & INPUT) == 0) { - /* Handle end of buffer */ - switch (ch) { - case '\r': - case '\n': - sim_debug(DEBUG_DATA, &con_dev, "%d: ent\n", u); - uptr->u3 &= ~INPUT; - tmxr_putc_ln( &com_ldsc[unit], '\r'); - tmxr_putc_ln( &com_ldsc[unit], '\n'); - break; - case 0177: - case '\b': - if (com_ptr[unit] != 0) { - com_ptr[unit].inptr--; - tmxr_putc_ln( &com_ldsc[unit], '\b'); - tmxr_putc_ln( &com_ldsc[unit], ' '); - tmxr_putc_ln( &com_ldsc[unit], '\b'); + if (uptr->u3 & ENAB) { + if (cmd == CMD_RD || cmd == CMD_PREP) { + if (tmxr_rqln(&com_ldsc[unit]) > 0) { + int32 data = tmxr_getc_ln (&com_ldsc[unit]); + ch = com_2741_in[data & 0x7f]; + sim_debug(DEBUG_DATA, dptr, "COML: unit=%d read '%c' %02x\n", unit, data, ch); + if (data & SCPE_BREAK) { + uptr->u3 |= BREAK; + return SCPE_OK; } - break; - case 03: /* ^C */ - case 025: /* ^U clear line */ - for (i = com_ptr[unit]; i> 0; i--) { - tmxr_putc_ln( &com_ldsc[unit], '\b'); - tmxr_putc_ln( &com_ldsc[unit], ' '); - tmxr_putc_ln( &com_ldsc[unit], '\b'); - } - com_ptr[unit].inptr = 0; - break; + /* Handle end of buffer */ + switch (data & 0x7f) { + case '\r': + case '\n': + com_buf[unit][uptr->BPTR++] = 0x5b; + com_buf[unit][uptr->BPTR++] = 0x1f; + uptr->u3 |= INPUT; + uptr->IPTR = 0; + tmxr_putc_ln( &com_ldsc[unit], '\r'); + tmxr_putc_ln( &com_ldsc[unit], '\n'); + break; - default: - sim_debug(DEBUG_DATA, &con_dev, "%d: key '%c'\n", u, ch); - if (com_ptr[unit] < 256) { - ch = com_2741_in[ch & 0x7f]; - if (ch == 0xff) { - sim_putchar('\007'); - break; - } - com_buf[unit][com_ptr[unit]++] = ch; - ch = com_2741_out[ch]; - tmxr_putc_ln( &com_ldsc[unit], ch); - } - } - } else { - tmxr_putc_ln( &com_ldsc[unit], '\07'); + case 0177: + case '\b': + if (uptr->BPTR != 0) { + uptr->BPTR--; + tmxr_putc_ln( &com_ldsc[unit], '\b'); + tmxr_putc_ln( &com_ldsc[unit], ' '); + tmxr_putc_ln( &com_ldsc[unit], '\b'); + } + break; + + case 025: /* ^U clear line */ + while(uptr->BPTR > 0) { + tmxr_putc_ln( &com_ldsc[unit], '\b'); + tmxr_putc_ln( &com_ldsc[unit], ' '); + tmxr_putc_ln( &com_ldsc[unit], '\b'); + uptr->BPTR--; + } + break; + + case 03: /* ^C */ + uptr->u3 |= BREAK; + break; + + default: + if (uptr->BPTR < 253) { + if (ch == 0x00) { + sim_putchar('\007'); + } else { + com_buf[unit][uptr->BPTR++] = ch; + if ((uptr->u3 & BYPASS) == 0) + tmxr_putc_ln( &com_ldsc[unit], data); + } + } else { + com_buf[unit][uptr->BPTR++] = 0x5b; + com_buf[unit][uptr->BPTR++] = 0x1f; + uptr->u3 |= INPUT; + uptr->BPTR &= 0xff; + } + } + } } } -#endif return SCPE_OK; } diff --git a/IBM360/ibm360_cpu.c b/IBM360/ibm360_cpu.c index 7e35130..6e3c5af 100644 --- a/IBM360/ibm360_cpu.c +++ b/IBM360/ibm360_cpu.c @@ -1446,12 +1446,12 @@ opr: break; ext_en = (src1 & 01) != 0; if (ec_mode) { - irq_en = (src1 & 02) != 0; if ((cpu_unit[0].flags & FEAT_370) != 0) { if (src1 & 0xb8) { storepsw(OPPSW, IRC_SPEC); break; } + irq_en = (src1 & 02) != 0; per_en = ((src1 & 0x40) != 0); dat_en = (src1 & 04) != 0; sysmsk = irq_en ? (cregs[2] >> 16) : 0; @@ -1460,6 +1460,7 @@ opr: storepsw(OPPSW, IRC_SPEC); else dat_en = (src1 & 04) != 0; + irq_en = (src1 & 02) != 0; sysmsk = irq_en ? (cregs[6] >> 16) : 0; } } else { @@ -2794,7 +2795,6 @@ save_dbl: if (dest < src1h) src1++; src1h = dest & ~0xfff; -//fprintf(stderr, "Store tod %08x %08x %d %08x %08x\r\n", tod_clock[0], tod_clock[1], (int)us, src1, src1h); } if (WriteFull(addr1, src1)) goto supress; @@ -2830,9 +2830,7 @@ save_dbl: if (sim_is_active(&cpu_unit[0])) { double nus = sim_activate_time_usecs(&cpu_unit[0]); timer_tics = (int)(nus); -//fprintf(stderr, "Set timer %08x %08x %g%d\r\n", cpu_timer[0], cpu_timer[1], nus,timer_tics); } -//fprintf(stderr, "Set timer %08x %08x %d\r\n", cpu_timer[0], cpu_timer[1], timer_tics); clk_irq = (cpu_timer[0] & MSIGN) != 0; break; case 0x9: /* STPT */ @@ -2847,7 +2845,6 @@ save_dbl: src1--; } src1h = dest; -//fprintf(stderr, "Store timer %08x %08x %d %g %d %08x %08x\r\n", cpu_timer[0], cpu_timer[1], timer_tics, nus, tics, src1, src1h ); } if (WriteFull(addr1, src1)) goto supress; @@ -2875,7 +2872,6 @@ save_dbl: } for (temp = 0; temp < 256; temp++) tlb[temp] = 0; -//fprintf(stderr, "purge tlb\r\n"); break; case 0x10: /* SPX */ storepsw(OPPSW, IRC_OPR); @@ -2902,6 +2898,7 @@ save_dbl: goto supress; } break; + case OP_STNSM: if ((cpu_unit[0].flags & FEAT_370) != 0) { if (flags & PROBLEM) { @@ -2946,6 +2943,7 @@ save_dbl: goto supress; } break; + case OP_STOSM: if ((cpu_unit[0].flags & FEAT_370) != 0) { if (flags & PROBLEM) { @@ -2990,6 +2988,7 @@ save_dbl: goto supress; } break; + case OP_SIGP: if ((cpu_unit[0].flags & FEAT_370) != 0) { if (flags & PROBLEM) { @@ -2999,6 +2998,7 @@ save_dbl: } storepsw(OPPSW, IRC_OPR); goto supress; + case OP_MC: if ((cpu_unit[0].flags & FEAT_370) != 0) { if ((reg & 0xf0) != 0) { @@ -3032,9 +3032,9 @@ save_dbl: if (ReadFull(addr1, &dest)) goto supress; cregs[reg1] = dest; - sim_debug(DEBUG_INST, &cpu_dev,"Loading: CR %x %06x %08x IC=%08x %x\n\r", - reg1, addr1, dest, PC, reg); -//fprintf(stderr, "Loading: CR %x %06x %08x IC=%08x %x\n\r", reg1, addr1, dest, PC, reg); + sim_debug(DEBUG_INST, &cpu_dev, + "Loading: CR %x %06x %08x IC=%08x %x\n\r", + reg1, addr1, dest, PC, reg); switch (reg1) { case 0x0: /* General controll register */ /* CR0 values @@ -3047,7 +3047,7 @@ save_dbl: page_shift = 0; seg_shift = 0; switch((dest >> 22) & 03) { - default: /* Generate translation exception */ + default: /* Generate translation exception */ case 1: /* 2K pages */ page_shift = 11; page_mask = 0x7ff; @@ -3186,6 +3186,7 @@ save_dbl: } } break; + case OP_SRP: if ((cpu_unit[0].flags & FEAT_370) == 0) { storepsw(OPPSW, IRC_OPR); @@ -3197,6 +3198,7 @@ save_dbl: dec_srp(op, addr1, reg1, addr2, reg & 0xf); } break; + case OP_MVCL: if ((cpu_unit[0].flags & FEAT_370) == 0) { storepsw(OPPSW, IRC_OPR); @@ -3256,6 +3258,7 @@ save_dbl: cc = 1; } break; + case OP_CLCL: if ((cpu_unit[0].flags & FEAT_370) == 0) { storepsw(OPPSW, IRC_OPR);