1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-01-13 15:27:04 +00:00

IBM360: Changed storage protection, and misc cleanup.

This commit is contained in:
Richard Cornwell 2020-03-06 21:24:19 -05:00
parent 81f824681b
commit 5ae42ddddd
7 changed files with 328 additions and 300 deletions

View File

@ -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;
}
/*

View File

@ -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 */

View File

@ -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)) {

View File

@ -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;

View File

@ -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:

View File

@ -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;
}

View File

@ -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;
}