From 5ae42ddddd972c0eec9f0f05431c678bd4e13f14 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Fri, 6 Mar 2020 21:24:19 -0500 Subject: [PATCH] IBM360: Changed storage protection, and misc cleanup. --- IBM360/ibm360_chan.c | 36 +++- IBM360/ibm360_com.c | 8 +- IBM360/ibm360_con.c | 17 +- IBM360/ibm360_cpu.c | 130 +++++++------ IBM360/ibm360_dasd.c | 11 +- IBM360/ibm360_lpr.c | 2 - IBM360/ibm360_mt.c | 424 ++++++++++++++++++++++--------------------- 7 files changed, 328 insertions(+), 300 deletions(-) diff --git a/IBM360/ibm360_chan.c b/IBM360/ibm360_chan.c index 10461e0..3b7bd2b 100644 --- a/IBM360/ibm360_chan.c +++ b/IBM360/ibm360_chan.c @@ -825,6 +825,7 @@ int haltio(uint16 addr) { int chan = find_subchan(addr); DIB *dibp = dev_unit[addr]; UNIT *uptr; + int cc; /* Find channel this device is on, if no none return cc=3 */ if (chan < 0 || dibp == 0) { @@ -839,16 +840,35 @@ int haltio(uint16 addr) { sim_debug(DEBUG_CMD, &cpu_dev, "HIO %x %x %x %x\n", addr, chan, ccw_cmd[chan], ccw_flags[chan]); - /* If channel busy, set end of buffer, return cc=2 */ - if (ccw_cmd[chan]) { - chan_byte[chan] = BUFF_CHNEND; - return 2; + /* Generic halt I/O, tell device to stop and + /* If any error pending save csw and return cc=1 */ + if (chan_status[chan] & (STATUS_PCI|STATUS_ATTN|STATUS_CHECK|\ + STATUS_PROT|STATUS_PCHK|STATUS_EXPT)) { + sim_debug(DEBUG_CMD, &cpu_dev, "HIO %x %x %x cc=0\n", addr, chan, + chan_status[chan]); + return 0; } - /* Not executing a command, issue halt if available */ - if (dibp->halt_io != NULL) - chan_status[chan] = dibp->halt_io(uptr) << 8; - return 0; + /* Ask device to halt if it knows how to */ + if (dibp->halt_io != NULL) { + /* Let device do it's thing */ + cc = dibp->halt_io(uptr); + sim_debug(DEBUG_CMD, &cpu_dev, "HIO %x %x cc=%d\n", addr, chan, cc); + if (cc == 1) + M[0x44 >> 2] = (((uint32)chan_status[chan]) << 16) | + (M[0x44 >> 2] & 0xffff); + return cc; + } + + /* If channel busy, set end of buffer, return cc=2 */ + if (ccw_cmd[chan]) + chan_byte[chan] = BUFF_CHNEND; + + /* Store CSW and return 1. */ + sim_debug(DEBUG_CMD, &cpu_dev, "HIO %x %x cc=1\n", addr, chan); + M[0x44 >> 2] = (((uint32)chan_status[chan]) << 16) | + (M[0x44 >> 2] & 0xffff); + return 1; } /* diff --git a/IBM360/ibm360_com.c b/IBM360/ibm360_com.c index e999a20..2feeceb 100644 --- a/IBM360/ibm360_com.c +++ b/IBM360/ibm360_com.c @@ -275,14 +275,16 @@ uint8 coml_haltio(UNIT *uptr) { int cmd = uptr->u3 & 0xff; sim_debug(DEBUG_CMD, dptr, "HLTIO unit=%d %x\n", unit, cmd); + if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return 3; switch (cmd) { case 0: case CMD_DIS: /* Disable line */ case CMD_DIAL: /* Dial call */ case 0x4: - /* Short commands nothing to do */ - return 0; + /* Short commands nothing to do */ + break; case CMD_INH: /* Read data without timeout */ case CMD_RD: /* Read in data from com line */ @@ -300,7 +302,7 @@ uint8 coml_haltio(UNIT *uptr) { uptr->u3 &= ~0xffff; break; } - return SNS_CHNEND|SNS_DEVEND; + return 1; } /* Handle per unit commands */ diff --git a/IBM360/ibm360_con.c b/IBM360/ibm360_con.c index 388ac1a..cabe19d 100644 --- a/IBM360/ibm360_con.c +++ b/IBM360/ibm360_con.c @@ -116,7 +116,6 @@ con_ini(UNIT *uptr, t_bool f) { uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { int u = (uptr - con_unit); - uint8 ch; if ((uptr->u3 & CON_MSK) != 0) return SNS_BSY; @@ -171,11 +170,8 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { break; case 4: /* Sense */ - sim_debug(DEBUG_CMD, &con_dev, "%d: Cmd SNS %02x\n", u, uptr->u5); - /* Check if request pending */ - ch = uptr->u5; - chan_write_byte(GET_UADDR(uptr->u3), &ch); - return SNS_CHNEND|SNS_DEVEND; + uptr->u3 |= cmd & CON_MSK; + return 0; default: /* invalid command */ uptr->u5 |= SNS_CMDREJ; @@ -199,6 +195,15 @@ con_srv(UNIT *uptr) { switch (cmd) { + case 0x4: + sim_debug(DEBUG_CMD, &con_dev, "%d: Cmd SNS %02x\n", u, uptr->u5); + /* Check if request pending */ + ch = uptr->u5; + chan_write_byte(addr, &ch); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); + uptr->u3 &= ~(CON_MSK); + break; + case CON_WR: case CON_ACR: if (chan_read_byte(addr, &ch)) { diff --git a/IBM360/ibm360_cpu.c b/IBM360/ibm360_cpu.c index 152469a..c7f72da 100644 --- a/IBM360/ibm360_cpu.c +++ b/IBM360/ibm360_cpu.c @@ -472,50 +472,53 @@ int TransAddr(uint32 va, uint32 *pa) { * success. */ int ReadFull(uint32 addr, uint32 *data) { - uint32 temp; + uint32 pa; int offset; - uint8 k; /* Validate address */ - if (TransAddr(addr, &addr)) + if (TransAddr(addr, &pa)) return 1; - offset = addr & 0x3; - addr >>= 2; - /* Check storage key */ if (st_key != 0) { + uint8 k; + if ((cpu_unit[0].flags & FEAT_PROT) == 0) { storepsw(OPPSW, IRC_PROT); return 1; } - k = key[addr >> 9]; + k = key[pa >> 11]; if ((k & 0x8) != 0 && (k & 0xf0) != st_key) { storepsw(OPPSW, IRC_PROT); return 1; } } - *data = M[addr]; + offset = pa & 0x3; + if (offset != 0 && (cpu_unit[0].flags & FEAT_STOR) == 0) { + storepsw(OPPSW, IRC_SPEC); + return 1; + } + pa >>= 2; + *data = M[pa]; if (offset != 0) { - if ((cpu_unit[0].flags & FEAT_STOR) == 0) { - storepsw(OPPSW, IRC_SPEC); - return 1; - } - temp = addr + 1; - /* Check if possible next page */ - if ((temp & 0x3ff) == 0) { - if (TransAddr(temp << 2, &temp)) - return 1; - temp >>= 2; - } - if ((temp & 0x1ff) == 0 && st_key != 0) { - k = key[temp >> 9]; - if ((k & 0x8) != 0 && (k & 0xf0) != st_key) { - storepsw(OPPSW, IRC_PROT); + uint32 temp; + uint8 k; + + temp = pa + 4; + if ((temp & 0x7FC) == 0) { + /* Check if possible next page */ + if (TransAddr(addr + 4, &temp)) return 1; + if (st_key != 0) { + k = key[temp >> 11]; + if ((k & 0x8) != 0 && (k & 0xf0) != st_key) { + storepsw(OPPSW, IRC_PROT); + return 1; + } } } + temp >>= 2; temp = M[temp]; *data <<= 8 * offset; temp >>= 8 * (4 - offset); @@ -576,7 +579,10 @@ int WriteFull(uint32 addr, uint32 data) { return 1; offset = pa & 0x3; - pa >>= 2; + if (offset != 0 && (cpu_unit[0].flags & FEAT_STOR) == 0) { + storepsw(OPPSW, IRC_SPEC); + return 1; + } /* Check storage key */ if (st_key != 0) { @@ -584,36 +590,29 @@ int WriteFull(uint32 addr, uint32 data) { storepsw(OPPSW, IRC_PROT); return 1; } - k = key[pa >> 9]; + k = key[pa >> 11]; if ((k & 0xf0) != st_key) { storepsw(OPPSW, IRC_PROT); return 1; } } + pa2 = pa + 4; /* Check if we handle unaligned access */ - if (offset != 0) { - if ((cpu_unit[0].flags & FEAT_STOR) == 0) { - storepsw(OPPSW, IRC_SPEC); + if (offset != 0 && (pa2 & 0x7FC) == 0) { + /* Validate address */ + if (TransAddr(addr + 4, &pa2)) return 1; + if (st_key != 0) { + k = key[(pa2) >> 11]; + if ((k & 0xf0) != st_key) { + storepsw(OPPSW, IRC_PROT); + return 1; + } } - - /* Check if new page or new protection zone */ - if ((pa & 0x1ff) == 0x1ff) { - /* Validate address */ - if (TransAddr(addr + 4, &pa2)) - return 1; - pa2 >>= 2; - if (st_key != 0) { - k = key[(pa2) >> 9]; - if ((k & 0xf0) != st_key) { - storepsw(OPPSW, IRC_PROT); - return 1; - } - } - } else - pa2 = pa + 1; } + pa >>= 2; + pa2 >>= 2; switch (offset) { case 0: @@ -651,22 +650,21 @@ int WriteByte(uint32 addr, uint32 data) { if (TransAddr(addr, &pa)) return 1; - offset = 8 * (3 - (pa & 0x3)); - pa >>= 2; - /* Check storage key */ if (st_key != 0) { if ((cpu_unit[0].flags & FEAT_PROT) == 0) { storepsw(OPPSW, IRC_PROT); return 1; } - k = key[pa >> 9]; + k = key[pa >> 11]; if ((k & 0xf0) != st_key) { storepsw(OPPSW, IRC_PROT); return 1; } } + offset = 8 * (3 - (pa & 0x3)); + pa >>= 2; mask = 0xff; data &= mask; data <<= offset; @@ -688,44 +686,40 @@ int WriteHalf(uint32 addr, uint32 data) { return 1; offset = pa & 0x3; - pa >>= 2; - /* Check if we handle unaligned access */ if ((offset & 1) != 0 && (cpu_unit[0].flags & FEAT_STOR) == 0) { storepsw(OPPSW, IRC_SPEC); return 1; } - + /* Check storage key */ if (st_key != 0) { if ((cpu_unit[0].flags & FEAT_PROT) == 0) { storepsw(OPPSW, IRC_PROT); return 1; } - k = key[pa >> 9]; + k = key[pa >> 11]; if ((k & 0xf0) != st_key) { storepsw(OPPSW, IRC_PROT); return 1; } } - if (offset == 3) { - /* Check if new page or new protection zone */ - if ((pa & 0x1ff) == 0x1ff) { - /* Validate address */ - if (TransAddr(addr + 4, &pa2)) - return 1; - pa2 >>= 2; - if (st_key != 0) { - k = key[(pa2) >> 9]; - if ((k & 0xf0) != st_key) { - storepsw(OPPSW, IRC_PROT); - return 1; - } - } - } else - pa2 = pa + 1; + pa2 = pa + 4; + if (offset == 3 && (pa2 & 0x7FC) == 0) { + /* Validate address */ + if (TransAddr(addr + 4, &pa2)) + return 1; + if (st_key != 0) { + k = key[(pa2) >> 11]; + if ((k & 0xf0) != st_key) { + storepsw(OPPSW, IRC_PROT); + return 1; + } + } } + pa >>= 2; + pa2 >>= 2; mask = 0xffff; data &= mask; diff --git a/IBM360/ibm360_dasd.c b/IBM360/ibm360_dasd.c index 3c1043e..a27dfc2 100644 --- a/IBM360/ibm360_dasd.c +++ b/IBM360/ibm360_dasd.c @@ -185,7 +185,7 @@ struct dasd_t uint16 tpos; /* Track position */ uint16 rpos; /* Start of current record */ uint16 dlen; /* remaining in data */ - uint16 tsize; /* Size of one track include rounding */ + uint32 tsize; /* Size of one track include rounding */ uint8 state; /* Current state */ uint8 klen; /* remaining in key */ uint8 filemsk; /* Current file mask */ @@ -723,7 +723,7 @@ index: } switch (cmd) { - case 0: /* No command, stop tape */ + case 0: /* No command */ break; case 0x14: case 0x34: @@ -1560,6 +1560,13 @@ wrckd: break; + case DK_NOP: + sim_debug(DEBUG_DETAIL, dptr, "NOP=%d %x\n", unit, cmd); + (void)chan_read_byte(addr, &ch); + uptr->u6 = 0; + uptr->u3 &= ~(0xff); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); + break; case DK_WR_SCKD: /* Write special count, key and data */ default: diff --git a/IBM360/ibm360_lpr.c b/IBM360/ibm360_lpr.c index 4108497..26c1c6b 100644 --- a/IBM360/ibm360_lpr.c +++ b/IBM360/ibm360_lpr.c @@ -256,8 +256,6 @@ lpr_srv(UNIT *uptr) { print_line(uptr); uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK); uptr->u6 = 0; - if (cmd == 0x3) - chan_end(addr, SNS_CHNEND); set_devattn(addr, SNS_DEVEND); return SCPE_OK; } diff --git a/IBM360/ibm360_mt.c b/IBM360/ibm360_mt.c index 48a31c6..8942dfa 100644 --- a/IBM360/ibm360_mt.c +++ b/IBM360/ibm360_mt.c @@ -386,7 +386,7 @@ t_stat mt_srv(UNIT * uptr) } } - switch (cmd) { + switch (cmd & 0xf) { case 0: /* No command, stop tape */ sim_debug(DEBUG_DETAIL, dptr, "Idle unit=%d\n", unit); break; @@ -631,232 +631,234 @@ t_stat mt_srv(UNIT * uptr) sim_activate(uptr, 20); } break; - - case MT_WTM: - if (uptr->u4 == 0) { - if (sim_tape_wrp(uptr)) { - uptr->u5 |= SNS_CMDREJ; - uptr->u3 &= ~MT_CMDMSK; - mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1; - set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; - } - uptr->u4 ++; - sim_activate(uptr, 500); - } else { - sim_debug(DEBUG_DETAIL, dptr, "Write Mark unit=%d\n", unit); - uptr->u3 &= ~(MT_CMDMSK); - r = sim_tape_wrtmk(uptr); - set_devattn(addr, SNS_DEVEND); - mt_busy[bufnum] &= ~1; - } - break; - - case MT_BSR: - switch (uptr->u4 ) { - case 0: - if (sim_tape_bot(uptr)) { - uptr->u3 &= ~MT_CMDMSK; - mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1; - set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; - } - uptr->u4 ++; - sim_activate(uptr, 500); - break; - case 1: - uptr->u4++; - sim_debug(DEBUG_DETAIL, dptr, "Backspace rec unit=%d ", unit); - r = sim_tape_sprecr(uptr, &reclen); - /* We don't set EOF on BSR */ - if (r == MTSE_TMK) { - uptr->u4++; - sim_debug(DEBUG_DETAIL, dptr, "MARK\n"); - sim_activate(uptr, 50); + case 0x7: + case 0xf: + switch (cmd) { + case MT_WTM: + if (uptr->u4 == 0) { + if (sim_tape_wrp(uptr)) { + uptr->u5 |= SNS_CMDREJ; + uptr->u3 &= ~MT_CMDMSK; + mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1; + set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + } + uptr->u4 ++; + sim_activate(uptr, 500); } else { - sim_debug(DEBUG_DETAIL, dptr, "%d \n", reclen); - sim_activate(uptr, 10 + (10 * reclen)); + sim_debug(DEBUG_DETAIL, dptr, "Write Mark unit=%d\n", unit); + uptr->u3 &= ~(MT_CMDMSK); + r = sim_tape_wrtmk(uptr); + set_devattn(addr, SNS_DEVEND); + mt_busy[bufnum] &= ~1; } break; - case 2: - uptr->u3 &= ~(MT_CMDMSK); - set_devattn(addr, SNS_DEVEND); - mt_busy[bufnum] &= ~1; - break; - case 3: - uptr->u3 &= ~(MT_CMDMSK); - set_devattn(addr, SNS_DEVEND|SNS_UNITEXP); - mt_busy[bufnum] &= ~1; - break; - } - break; - case MT_BSF: - switch(uptr->u4) { - case 0: - if (sim_tape_bot(uptr)) { - uptr->u3 &= ~MT_CMDMSK; - mt_busy[bufnum] &= ~1; - set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); - break; - } - uptr->u4 ++; - sim_activate(uptr, 500); - break; - case 1: - sim_debug(DEBUG_DETAIL, dptr, "Backspace file unit=%d\n", unit); - r = sim_tape_sprecr(uptr, &reclen); - if (r == MTSE_TMK) { - uptr->u4++; - sim_debug(DEBUG_DETAIL, dptr, "MARK\n"); - sim_activate(uptr, 50); - } else if (r == MTSE_BOT) { - uptr->u4+= 2; - sim_activate(uptr, 50); - } else { - sim_activate(uptr, 10 + (10 * reclen)); - } - break; - case 2: - uptr->u3 &= ~(MT_CMDMSK); - set_devattn(addr, SNS_DEVEND|SNS_UNITEXP); - mt_busy[bufnum] &= ~1; - break; - case 3: - uptr->u3 &= ~(MT_CMDMSK); - set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); - mt_busy[bufnum] &= ~1; - break; - } - break; - - case MT_FSR: - switch(uptr->u4) { - case 0: - uptr->u4 ++; - sim_activate(uptr, 500); - break; - case 1: - uptr->u4++; - sim_debug(DEBUG_DETAIL, dptr, "Skip rec unit=%d ", unit); - r = sim_tape_sprecf(uptr, &reclen); - if (r == MTSE_TMK) { - uptr->u4 = 3; - sim_debug(DEBUG_DETAIL, dptr, "MARK\n"); - sim_activate(uptr, 50); - } else if (r == MTSE_EOM) { - uptr->u4 = 4; - sim_activate(uptr, 50); - } else { - sim_debug(DEBUG_DETAIL, dptr, "%d\n", reclen); - sim_activate(uptr, 10 + (10 * reclen)); + case MT_BSR: + switch (uptr->u4 ) { + case 0: + if (sim_tape_bot(uptr)) { + uptr->u3 &= ~MT_CMDMSK; + mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1; + set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + } + uptr->u4 ++; + sim_activate(uptr, 500); + break; + case 1: + uptr->u4++; + sim_debug(DEBUG_DETAIL, dptr, "Backspace rec unit=%d ", unit); + r = sim_tape_sprecr(uptr, &reclen); + /* We don't set EOF on BSR */ + if (r == MTSE_TMK) { + uptr->u4++; + sim_debug(DEBUG_DETAIL, dptr, "MARK\n"); + sim_activate(uptr, 50); + } else { + sim_debug(DEBUG_DETAIL, dptr, "%d \n", reclen); + sim_activate(uptr, 10 + (10 * reclen)); + } + break; + case 2: + uptr->u3 &= ~(MT_CMDMSK); + set_devattn(addr, SNS_DEVEND); + mt_busy[bufnum] &= ~1; + break; + case 3: + uptr->u3 &= ~(MT_CMDMSK); + set_devattn(addr, SNS_DEVEND|SNS_UNITEXP); + mt_busy[bufnum] &= ~1; + break; } break; - case 2: - uptr->u3 &= ~(MT_CMDMSK); - set_devattn(addr, SNS_DEVEND); - mt_busy[bufnum] &= ~1; - break; - case 3: - uptr->u3 &= ~(MT_CMDMSK); - set_devattn(addr, SNS_DEVEND|SNS_UNITEXP); - mt_busy[bufnum] &= ~1; - break; - case 4: - uptr->u3 &= ~(MT_CMDMSK); - set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); - mt_busy[bufnum] &= ~1; - break; - } - break; - case MT_FSF: - switch(uptr->u4) { - case 0: - uptr->u4 ++; - sim_activate(uptr, 500); - break; - case 1: - sim_debug(DEBUG_DETAIL, dptr, "Skip rec unit=%d ", unit); - r = sim_tape_sprecf(uptr, &reclen); - if (r == MTSE_TMK) { - uptr->u4++; - sim_debug(DEBUG_DETAIL, dptr, "MARK\n"); - sim_activate(uptr, 50); - } else if (r == MTSE_EOM) { - uptr->u4+= 2; - sim_activate(uptr, 50); - } else { - sim_debug(DEBUG_DETAIL, dptr, "%d\n", reclen); - sim_activate(uptr, 10 + (10 * reclen)); + case MT_BSF: + switch(uptr->u4) { + case 0: + if (sim_tape_bot(uptr)) { + uptr->u3 &= ~MT_CMDMSK; + mt_busy[bufnum] &= ~1; + set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); + break; + } + uptr->u4 ++; + sim_activate(uptr, 500); + break; + case 1: + sim_debug(DEBUG_DETAIL, dptr, "Backspace file unit=%d\n", unit); + r = sim_tape_sprecr(uptr, &reclen); + if (r == MTSE_TMK) { + uptr->u4++; + sim_debug(DEBUG_DETAIL, dptr, "MARK\n"); + sim_activate(uptr, 50); + } else if (r == MTSE_BOT) { + uptr->u4+= 2; + sim_activate(uptr, 50); + } else { + sim_activate(uptr, 10 + (10 * reclen)); + } + break; + case 2: + uptr->u3 &= ~(MT_CMDMSK); + set_devattn(addr, SNS_DEVEND|SNS_UNITEXP); + mt_busy[bufnum] &= ~1; + break; + case 3: + uptr->u3 &= ~(MT_CMDMSK); + set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); + mt_busy[bufnum] &= ~1; + break; } break; - case 2: - uptr->u3 &= ~(MT_CMDMSK); - set_devattn(addr, SNS_DEVEND); - mt_busy[bufnum] &= ~1; - sim_debug(DEBUG_DETAIL, dptr, "Skip done unit=%d\n", unit); - break; - case 3: - uptr->u3 &= ~(MT_CMDMSK); - set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); - mt_busy[bufnum] &= ~1; - break; - } - break; + case MT_FSR: + switch(uptr->u4) { + case 0: + uptr->u4 ++; + sim_activate(uptr, 500); + break; + case 1: + uptr->u4++; + sim_debug(DEBUG_DETAIL, dptr, "Skip rec unit=%d ", unit); + r = sim_tape_sprecf(uptr, &reclen); + if (r == MTSE_TMK) { + uptr->u4 = 3; + sim_debug(DEBUG_DETAIL, dptr, "MARK\n"); + sim_activate(uptr, 50); + } else if (r == MTSE_EOM) { + uptr->u4 = 4; + sim_activate(uptr, 50); + } else { + sim_debug(DEBUG_DETAIL, dptr, "%d\n", reclen); + sim_activate(uptr, 10 + (10 * reclen)); + } + break; + case 2: + uptr->u3 &= ~(MT_CMDMSK); + set_devattn(addr, SNS_DEVEND); + mt_busy[bufnum] &= ~1; + break; + case 3: + uptr->u3 &= ~(MT_CMDMSK); + set_devattn(addr, SNS_DEVEND|SNS_UNITEXP); + mt_busy[bufnum] &= ~1; + break; + case 4: + uptr->u3 &= ~(MT_CMDMSK); + set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); + mt_busy[bufnum] &= ~1; + break; + } + break; - case MT_ERG: - switch (uptr->u4) { - case 0: - if (sim_tape_wrp(uptr)) { - uptr->u5 |= SNS_CMDREJ; - uptr->u3 &= ~MT_CMDMSK; - mt_busy[bufnum] &= ~1; - set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); - } else { + case MT_FSF: + switch(uptr->u4) { + case 0: + uptr->u4 ++; + sim_activate(uptr, 500); + break; + case 1: + sim_debug(DEBUG_DETAIL, dptr, "Skip rec unit=%d ", unit); + r = sim_tape_sprecf(uptr, &reclen); + if (r == MTSE_TMK) { + uptr->u4++; + sim_debug(DEBUG_DETAIL, dptr, "MARK\n"); + sim_activate(uptr, 50); + } else if (r == MTSE_EOM) { + uptr->u4+= 2; + sim_activate(uptr, 50); + } else { + sim_debug(DEBUG_DETAIL, dptr, "%d\n", reclen); + sim_activate(uptr, 10 + (10 * reclen)); + } + break; + case 2: + uptr->u3 &= ~(MT_CMDMSK); + set_devattn(addr, SNS_DEVEND); + mt_busy[bufnum] &= ~1; + sim_debug(DEBUG_DETAIL, dptr, "Skip done unit=%d\n", unit); + break; + case 3: + uptr->u3 &= ~(MT_CMDMSK); + set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); + mt_busy[bufnum] &= ~1; + break; + } + break; + + case MT_ERG: + switch (uptr->u4) { + case 0: + if (sim_tape_wrp(uptr)) { + uptr->u5 |= SNS_CMDREJ; + uptr->u3 &= ~MT_CMDMSK; + mt_busy[bufnum] &= ~1; + set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); + } else { + uptr->u4 ++; + sim_activate(uptr, 500); + } + break; + case 1: + sim_debug(DEBUG_DETAIL, dptr, "Erase unit=%d\n", unit); + r = sim_tape_wrgap(uptr, 35); + sim_activate(uptr, 5000); + uptr->u4++; + break; + case 2: + uptr->u3 &= ~(MT_CMDMSK); + set_devattn(addr, SNS_DEVEND); + mt_busy[bufnum] &= ~1; + } + break; + + case MT_REW: + if (uptr->u4 == 0) { uptr->u4 ++; - sim_activate(uptr, 500); + sim_activate(uptr, 30000); + mt_busy[bufnum] &= ~1; + } else { + sim_debug(DEBUG_DETAIL, dptr, "Rewind unit=%d\n", unit); + uptr->u3 &= ~(MT_CMDMSK); + r = sim_tape_rewind(uptr); + set_devattn(addr, SNS_DEVEND); } break; - case 1: - sim_debug(DEBUG_DETAIL, dptr, "Erase unit=%d\n", unit); - r = sim_tape_wrgap(uptr, 35); - sim_activate(uptr, 5000); - uptr->u4++; + + case MT_RUN: + if (uptr->u4 == 0) { + uptr->u4 ++; + mt_busy[bufnum] &= ~1; + sim_activate(uptr, 30000); + } else { + sim_debug(DEBUG_DETAIL, dptr, "Unload unit=%d\n", unit); + uptr->u3 &= ~(MT_CMDMSK); + r = sim_tape_detach(uptr); + set_devattn(addr, SNS_DEVEND); + } break; - case 2: - uptr->u3 &= ~(MT_CMDMSK); - set_devattn(addr, SNS_DEVEND); - mt_busy[bufnum] &= ~1; } - break; - - case MT_REW: - if (uptr->u4 == 0) { - uptr->u4 ++; - sim_activate(uptr, 30000); - mt_busy[bufnum] &= ~1; - } else { - sim_debug(DEBUG_DETAIL, dptr, "Rewind unit=%d\n", unit); - uptr->u3 &= ~(MT_CMDMSK); - r = sim_tape_rewind(uptr); - set_devattn(addr, SNS_DEVEND); - } - break; - - case MT_RUN: - if (uptr->u4 == 0) { - uptr->u4 ++; - mt_busy[bufnum] &= ~1; - sim_activate(uptr, 30000); - } else { - sim_debug(DEBUG_DETAIL, dptr, "Unload unit=%d\n", unit); - uptr->u3 &= ~(MT_CMDMSK); - r = sim_tape_detach(uptr); - set_devattn(addr, SNS_DEVEND); - } - break; } return SCPE_OK; }