From e1b29cca255fa2fcc44695cccd46a03f37c192b7 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Fri, 14 Jun 2024 11:31:46 -0400 Subject: [PATCH] IBM360: Moved unattached unit from channel to units. --- IBM360/ibm360_cdp.c | 18 ++++++++++++--- IBM360/ibm360_cdr.c | 24 +++++++++++++------- IBM360/ibm360_chan.c | 44 +++++++++++++++++++++++++----------- IBM360/ibm360_com.c | 51 ++++++++++++++++++++++-------------------- IBM360/ibm360_defs.h | 4 ++-- IBM360/ibm360_lpr.c | 53 ++++++++++++++++++++++++++++---------------- 6 files changed, 125 insertions(+), 69 deletions(-) diff --git a/IBM360/ibm360_cdp.c b/IBM360/ibm360_cdp.c index 0b6ab49..98470be 100644 --- a/IBM360/ibm360_cdp.c +++ b/IBM360/ibm360_cdp.c @@ -139,19 +139,31 @@ uint8 cdp_startcmd(UNIT *uptr, uint8 cmd) { sim_debug(DEBUG_CMD, dptr, "CMD unit=%d %x\n", unit, cmd); switch (cmd & 0x7) { case CMD_WRITE: /* Write command */ + /* If nothing attached, return intervention */ + if ((uptr->flags & UNIT_ATT) == 0) { + uptr->SNS |= SNS_INTVENT; + break; + } uptr->CMD &= ~(CDP_CMDMSK); uptr->CMD |= (cmd & CDP_CMDMSK); - sim_activate(uptr, 100); /* Start unit off */ uptr->COL = 0; uptr->SNS = 0; + sim_activate(uptr, 100); /* Start unit off */ return 0; case CMD_CTL: + uptr->SNS = 0; + uptr->CMD &= ~(CDP_CMDMSK); if (cmd != 0x3) { uptr->SNS |= SNS_CMDREJ; - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + break; } - return SNS_CHNEND|SNS_DEVEND; + /* If nothing attached, return intervention */ + if ((uptr->flags & UNIT_ATT) == 0) { + uptr->SNS |= SNS_INTVENT; + break; + } + break; case 0: /* Status */ break; diff --git a/IBM360/ibm360_cdr.c b/IBM360/ibm360_cdr.c index eefcf90..9c80c56 100644 --- a/IBM360/ibm360_cdr.c +++ b/IBM360/ibm360_cdr.c @@ -121,16 +121,17 @@ uint8 cdr_startcmd(UNIT *uptr, uint8 cmd) { sim_debug(DEBUG_CMD, dptr, "CMD unit=%d %x\n", unit, cmd); - /* If not attached and not sense, return error */ - if (cmd != 4 && (uptr->flags & UNIT_ATT) == 0) { - uptr->SNS = SNS_INTVENT; - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - } switch (cmd & 0x7) { case CMD_READ: /* Read command */ uptr->SNS = 0; uptr->COL = 0; + uptr->CMD &= ~(0xff); + /* If not attached return error */ + if ((uptr->flags & UNIT_ATT) == 0) { + uptr->SNS |= SNS_INTVENT; + break; + } /* Check if there was End of file */ if ((uptr->CMD & CDR_EOF) != 0) { uint16 *image = (uint16 *)(uptr->up7); @@ -156,7 +157,6 @@ uint8 cdr_startcmd(UNIT *uptr, uint8 cmd) { uptr->SNS = SNS_INTVENT; return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; } - uptr->CMD &= ~(0xff); uptr->CMD |= (cmd & 0xff); sim_activate(uptr, 100); /* Start unit off */ return 0; @@ -164,8 +164,16 @@ uint8 cdr_startcmd(UNIT *uptr, uint8 cmd) { case CMD_CTL: /* Control */ uptr->SNS = 0; uptr->CMD &= ~(0xff); - if (cmd == 0x3) - return SNS_CHNEND|SNS_DEVEND; + /* If not attached return error */ + if ((uptr->flags & UNIT_ATT) == 0) { + uptr->SNS |= SNS_INTVENT; + break; + } + /* Nop quick return */ + if (cmd == 0x3) { + break; + } + /* Check if illegal command */ if ((cmd & 0x30) != 0x20 || (cmd & 0xc0) == 0xc0) { uptr->SNS |= SNS_CMDREJ; return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; diff --git a/IBM360/ibm360_chan.c b/IBM360/ibm360_chan.c index ccb2f2f..57627e5 100644 --- a/IBM360/ibm360_chan.c +++ b/IBM360/ibm360_chan.c @@ -127,7 +127,7 @@ UNIT chan_unit[] = { DEVICE chan_dev = { "CH", chan_unit, NULL, chan_mod, MAX_CHAN, 8, 15, 1, 8, 8, - NULL, NULL, NULL /*&chan_reset*/, NULL, NULL, NULL, + NULL, NULL, &chan_reset, NULL, NULL, NULL, NULL, DEV_DEBUG, 0, dev_debug, NULL, NULL, &chan_help, NULL, NULL, &chan_description }; @@ -366,7 +366,7 @@ loop: /* Check if we have status modifier set */ if (chan->chan_status & STATUS_MOD) { chan->caw+=8; - chan->caw &= PMASK|AMASK; /* Mask overflow bits */ + chan->caw &= AMASK; /* Mask overflow bits */ chan->chan_status &= ~STATUS_MOD; } /* Read in next CCW */ @@ -376,7 +376,7 @@ loop: /* TIC can't follow TIC nor be first in chain */ if (((word >> 24) & 0xf) == CMD_TIC) { if (tic_ok) { - chan->caw = (chan->caw & PMASK) | (word & AMASK); + chan->caw = word & AMASK; tic_ok = 0; goto loop; } @@ -773,7 +773,7 @@ chan_end(uint16 addr, uint8 flags) { */ void store_csw(struct _chanctl *chan) { - M[0x40 >> 2] = chan->caw; + M[0x40 >> 2] = ((uint32)(chan->ccw_key) << 24) | chan->caw; M[0x44 >> 2] = (((uint32)chan->ccw_count)) | ((uint32)chan->chan_status<<16); key[0] |= 0x6; if (chan->chan_status & STATUS_PCI) { @@ -787,6 +787,7 @@ store_csw(struct _chanctl *chan) { chan->daddr, M[0x40>>2], M[0x44 >> 2]); } + /* * Handle SIO instruction. */ @@ -833,8 +834,6 @@ startio(uint16 addr) { dev_status[addr] = 0; /* Check for any pending status for this device */ if (dev_status[addr] != 0) { -// if (dev_status[addr] & SNS_DEVEND) -// dev_status[addr] |= SNS_BSY; M[0x44 >> 2] = (((uint32)dev_status[addr]) << 24); M[0x40 >> 2] = 0; key[0] |= 0x6; @@ -872,6 +871,7 @@ startio(uint16 addr) { chan->dev = dev; sim_debug(DEBUG_CMD, &cpu_dev, "SIO start %03x %03x\n", addr, chan->daddr); + /* Try to load first command */ if (load_ccw(chan, 0)) { M[0x44 >> 2] = ((uint32)chan->chan_status<<16) | (M[0x44 >> 2] & 0xffff); @@ -883,7 +883,7 @@ startio(uint16 addr) { dev_status[addr] = 0; chan->daddr = NO_DEV; chan->dev = NULL; - return ((uptr->flags & UNIT_ATT) == 0) ? 3 : 1; + return 1; } /* If channel returned busy save CSW and return cc=1 */ @@ -901,7 +901,6 @@ startio(uint16 addr) { return 1; } -//#if 0 /* If immediate command and not command chaining */ if ((chan->chan_status & (STATUS_CEND)) != 0 && (chan->ccw_flags & FLAG_CC) == 0) { @@ -913,11 +912,11 @@ startio(uint16 addr) { addr, M[0x44 >> 2]); return 1; } -//#endif return 0; } + /* * Handle TIO instruction. */ @@ -984,7 +983,7 @@ int testio(uint16 addr) { if (chan_pend[ch]) { int dev; /* Check if might be false */ - for (dev = (addr & 0xf00); dev < (addr | 0xfff); dev++) { + for (dev = (addr & 0xf00); dev < (addr | 0x0ff); dev++) { if (dev_status[dev] != 0) { /* Check if same subchannel */ if (find_subchan(dev) == chan) { @@ -1117,9 +1116,8 @@ int testchan(uint16 channel) { attached. Channels 0, 4, 8 (0 on CC 1) & 12 (4 on CC 1) are multiplexer channels. */ - cc = (channel >> 11) & 0x03; channel = (channel >> 8) & 0x0f; - if (cc > 1 || channel > chan_dev.numunits) { + if (channel > chan_dev.numunits) { sim_debug(DEBUG_CMD, &cpu_dev, "TCH CC %x %x cc=3\n", cc, channel); return 3; } @@ -1181,6 +1179,7 @@ t_stat chan_boot(uint16 addr, DEVICE *dptyr) { for (i = 0; i < (MAX_CHAN * 256); i++) dev_status[i] = 0; + chan_set_devs(); dev = find_device(addr); chan = find_subchan(addr); if (dev == NULL || chan == NULL) { @@ -1282,7 +1281,7 @@ scan_chan(uint16 mask, int irq_en) { } /* If channel end, check if we should continue */ - if (chan->chan_status & STATUS_CEND) { + if (chan->chan_status & STATUS_DEND) { sim_debug(DEBUG_EXP, &cpu_dev, "Scan(%x %x %x %x) Cend\n", i, chan->daddr, chan->chan_status, chan->ccw_flags); /* Grab another command if command chainging in effect */ @@ -1405,6 +1404,24 @@ chan_set_devs() uptr->up8 = NULL; continue; } + n = 1; + if ((uptr->flags & UNIT_M_CTYPE) == UNIT_MUX) + n = UNIT_G_SCHAN(uptr->flags)+1; + if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX) + n = 32; + /* If no device array, create one */ + if (uptr->up8 == NULL) + uptr->up8 = calloc(256, sizeof(struct _dev)); + if (uptr->up7 == NULL || (uint32)uptr->schans != n) { + if (uptr->up7 != NULL) + free(uptr->up7); + uptr->up7 = calloc(n, sizeof(struct _chanctl)); + for (j = 0; j < n; j++) { + struct _chanctl *chan = &(chan_ctl[j]); + chan->daddr = NO_DEV; + } + } +#if 0 n = 1; if ((uptr->flags & UNIT_M_CTYPE) == UNIT_MUX) n = UNIT_G_SCHAN(uptr->flags)+1; @@ -1422,6 +1439,7 @@ chan_set_devs() struct _chanctl *chan = &(chan_ctl[j]); chan->daddr = NO_DEV; } +#endif uptr->schans = n; /* Initialize channel device address table to empty */ for (j = 0; j < 256; j++) { diff --git a/IBM360/ibm360_com.c b/IBM360/ibm360_com.c index b0d0495..e965d1a 100644 --- a/IBM360/ibm360_com.c +++ b/IBM360/ibm360_com.c @@ -383,11 +383,7 @@ t_stat coml_srv(UNIT * uptr) uint8 ch; int bsc = (uptr->flags & UNIT_UTYPE) == UNIT_2780; - switch (cmd) { - case 0: - break; - case CMD_SENSE: ch = uptr->SNS & 0xff; sim_debug(DEBUG_DETAIL, dptr, "sense unit=%d 1 %x\n", unit, ch); @@ -420,6 +416,7 @@ t_stat coml_srv(UNIT * uptr) uptr->CMD &= ~ADDR; if (chan_write_byte( addr, &ch)) { uptr->CMD &= ~(ADDR9|0xff); + sim_debug(DEBUG_CMD, dptr, "COM: unit=%d send err\n", unit); chan_end(addr, SNS_CHNEND|SNS_DEVEND); return SCPE_OK; } @@ -434,6 +431,7 @@ t_stat coml_srv(UNIT * uptr) uptr->SNS = SNS_INTVENT; uptr->BPTR = 0; uptr->IPTR = 0; + sim_debug(DEBUG_DETAIL, dptr, "COM: unit=%d break\n", unit); chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK|SNS_UNITEXP); return SCPE_OK; } else if (uptr->CMD & INPUT) { @@ -443,26 +441,32 @@ t_stat coml_srv(UNIT * uptr) uptr->CMD &= ~(0xff|INPUT|RECV); uptr->BPTR = 0; uptr->IPTR = 0; + chan_end(addr, SNS_CHNEND|SNS_DEVEND); return SCPE_OK; } ch = com_buf[unit][uptr->IPTR++]; - if (!bsc && ch == 0x1f) { - uptr->CMD |= ADDR; - } - if (ack && ((ch == ACK0) || (ch == ACK1))) { - uptr->CMD &= ~(0xff|INPUT|RECV); - uptr->IPTR = 0; - uptr->BPTR = 0; - chan_end(addr, SNS_CHNEND|SNS_DEVEND|(ch == ACK1 ? SNS_UNITEXP:0)); - return SCPE_OK; - } - if (bsc && ch == DLE) { - uptr->BSCSTATE |= BSCIDLE; - } else { - uptr->BSCSTATE &= ~BSCIDLE; + sim_debug(DEBUG_DETAIL, dptr, "COM: unit=%d read %02x\n", unit, ch); + if (bsc) { + if (ch == 0x1f) { + uptr->CMD |= ADDR; + } + if (ack && ((ch == ACK0) || (ch == ACK1))) { + uptr->CMD &= ~(0xff|INPUT|RECV); + uptr->IPTR = 0; + uptr->BPTR = 0; + sim_debug(DEBUG_DETAIL, dptr, "COM: unit=%d ack\n", unit); + chan_end(addr, SNS_CHNEND|SNS_DEVEND|(ch == ACK1 ? SNS_UNITEXP:0)); + return SCPE_OK; + } + if (ch == DLE) { + uptr->BSCSTATE |= BSCIDLE; + } else { + uptr->BSCSTATE &= ~BSCIDLE; + } } if (chan_write_byte( addr, &ch)) { + sim_debug(DEBUG_DETAIL, dptr, "COM: unit=%d send\n", unit); uptr->CMD &= ~(0xff|INPUT|RECV); uptr->IPTR = 0; uptr->BPTR = 0; @@ -500,7 +504,7 @@ t_stat coml_srv(UNIT * uptr) break; case CMD_POLL: - if (!bsc) { + if (bsc) { uptr->SNS = SNS_CMDREJ; uptr->CMD &= ~(0xff|BREAK|INPUT|RECV|SEND|POLL); chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); @@ -726,7 +730,7 @@ t_stat coml_srv(UNIT * uptr) com_buf[unit][uptr->BPTR++] = ch; break; } - + } } } else { ch = com_2741_in[data & 0x7f]; @@ -788,10 +792,9 @@ t_stat coml_srv(UNIT * uptr) uptr->CMD &= ~RECV; uptr->BPTR &= 0xff; } - } } - } - } + } + } } return SCPE_OK; } @@ -829,7 +832,7 @@ t_stat com_scan(UNIT * uptr) } } - /* See if a line is disconnected with no command on it. */ + /* See if any input on line with no command on it */ for (ln = 0; ln < com_desc.lines; ln++) { line = &coml_unit[ln]; if ((line->CMD & (RECV|ENAB)) == ENAB && tmxr_rqln(&com_ldsc[ln]) > 0) { diff --git a/IBM360/ibm360_defs.h b/IBM360/ibm360_defs.h index b82eaa5..29de6fc 100644 --- a/IBM360/ibm360_defs.h +++ b/IBM360/ibm360_defs.h @@ -148,8 +148,8 @@ typedef struct dib { #define OP_CLR 0x15 /* src1 = R1, src2 = R2 */ #define OP_OR 0x16 /* src1 = R1, src2 = R2 */ #define OP_XR 0x17 /* src1 = R1, src2 = R2 */ -#define OP_CR 0x19 /* src1 = R1, src2 = R2 */ #define OP_LR 0x18 /* src1 = R1, src2 = R2 */ +#define OP_CR 0x19 /* src1 = R1, src2 = R2 */ #define OP_AR 0x1A /* src1 = R1, src2 = R2 */ #define OP_SR 0x1B /* src1 = R1, src2 = R2 */ #define OP_MR 0x1C /* src1 = R1, src2 = R2 */ @@ -364,7 +364,7 @@ int chan_read_byte(uint16 addr, uint8 *data); int chan_write_byte(uint16 addr, uint8 *data); void set_devattn(uint16 addr, uint8 flags); void chan_end(uint16 addr, uint8 flags); -int startio(uint16 addr) ; +int startio(uint16 addr); int testio(uint16 addr); int haltio(uint16 addr); int testchan(uint16 channel); diff --git a/IBM360/ibm360_lpr.c b/IBM360/ibm360_lpr.c index 3df0745..fc54221 100644 --- a/IBM360/ibm360_lpr.c +++ b/IBM360/ibm360_lpr.c @@ -139,7 +139,7 @@ static CONST uint16 legacy[] = { 0x040, 0x000, 0x000, 0x000, 0x000, 0x000, 0x020, 0x000, 0x000, 0x000, /* 31 - 40 */ 0x000, 0x000, 0x010, 0x000, 0x000, 0x000, 0x000, 0x000, 0x004, 0x000, /* 41 - 50 */ 0x000, 0x000, 0x000, 0x000, 0x002, 0x000, 0x000, 0x000, 0x000, 0x000, /* 51 - 60 */ -0x001, 0x000, 0x008, 0x000, 0x000, 0x001, 0x1000 }; /* 61 - 66 */ +0x001, 0x000, 0x008, 0x000, 0x000, 0x000, 0x1000 }; /* 61 - 66 */ /* PROGRAMMMING NOTE: the below cctape value SHOULD match the same corresponding fcb value! @@ -152,7 +152,7 @@ static CONST uint16 std1[] = { 0x040, 0x000, 0x000, 0x000, 0x000, 0x000, 0x020, 0x000, 0x000, 0x000, /* 31 - 40 */ 0x000, 0x000, 0x010, 0x000, 0x000, 0x000, 0x000, 0x000, 0x008, 0x000, /* 41 - 50 */ 0x000, 0x000, 0x000, 0x000, 0x004, 0x000, 0x000, 0x000, 0x000, 0x000, /* 51 - 60 */ -0x002, 0x000, 0x001, 0x000, 0x000, 0x001, 0x1000 }; /* 61 - 66 */ +0x002, 0x000, 0x001, 0x000, 0x000, 0x000, 0x1000 }; /* 61 - 66 */ static CONST uint16 none[] = { /* 1 2 3 4 5 6 7 8 9 10 lines */ @@ -162,7 +162,7 @@ static CONST uint16 none[] = { 0x040, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, /* 31 - 40 */ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, /* 41 - 50 */ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, /* 51 - 60 */ -0x002, 0x000, 0x000, 0x000, 0x000, 0x001, 0x1000 }; /* 61 - 66 */ +0x002, 0x000, 0x000, 0x000, 0x000, 0x000, 0x1000 }; /* 61 - 66 */ static CONST uint16 *fcb_ptr[] = { legacy, std1, none, NULL}; @@ -255,9 +255,9 @@ print_line(UNIT * uptr) int i; int u = (uptr - lpr_unit); int space = (uptr->CMD >> 3) & 0x1f; - int flag; int line; int mask; + int flag; /* Dump buffer if full */ if (uptr->CMD & LPR_FULL) { @@ -282,7 +282,7 @@ print_line(UNIT * uptr) /* Print out buffer */ sim_fwrite(&out, 1, i, uptr->fileref); uptr->pos += i; - sim_debug(DEBUG_DETAIL, &lpr_dev, "%s\n", out); + sim_debug(DEBUG_DETAIL, &lpr_dev, "]%s\n", out); memset(&lpr_data[u].lbuff[0], 0, 144); } @@ -293,6 +293,10 @@ print_line(UNIT * uptr) uptr->pos += 2; flag = 1; if ((uptr->CMD & 03) == 0x1) { + uint16 fcb = lpr_data[u].fcb[uptr->LINE]; + sim_debug(DEBUG_DETAIL, &lpr_dev, "%d FCB %d %03x %d %d\n", u, uptr->LINE, fcb, + ((0x1000 >> 9) & fcb) != 0, + ((0x1000 >> 12) & fcb) != 0); if ((lpr_data[u].fcb[uptr->LINE] & (0x1000 >> 9)) != 0) { uptr->SNS |= SNS_CHN9; } @@ -306,8 +310,8 @@ print_line(UNIT * uptr) sim_fwrite("\r\n", 1, 2, uptr->fileref); uptr->pos += 2; } + sim_debug(DEBUG_DETAIL, &lpr_dev, "%d form %d\n", u, uptr->LINE); sim_fwrite("\f\r\n", 1, 3, uptr->fileref); - uptr->SNS |= SNS_CHN12; uptr->pos += 3; uptr->LINE = 0; } else { @@ -319,27 +323,20 @@ print_line(UNIT * uptr) } mask = 0x1000 >> (space & 0xf); - flag = 0; /* Flag if we skipped to new page */ line = 0; /* What line we should be on */ for (i = uptr->LINE; (lpr_data[u].fcb[i] & mask) == 0; i++) { line++; if ((lpr_data[u].fcb[i] & 0x1000) != 0 || ((uint32)i) >= uptr->capac) { + sim_debug(DEBUG_DETAIL, &lpr_dev, "%d form1 %d %d %d\n", u, uptr->LINE, i, uptr->capac); sim_fwrite("\r\n\f\r\n", 1, 5, uptr->fileref); uptr->pos += 5; - uptr->SNS |= SNS_CHN12; - flag = 1; line = 0; - break; + return; } } - /* If past end of form clear row */ - if (flag) { - uptr->LINE = 0; - } - if ((lpr_data[u].fcb[i] & mask) != 0) { while (line-- > 0) { sim_fwrite("\r\n", 1, 2, uptr->fileref); @@ -371,24 +368,35 @@ uint8 lpr_startcmd(UNIT * uptr, uint8 cmd) return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; } + sim_debug(DEBUG_CMD, &lpr_dev, "Cmd %02x %02x\n", cmd, (cmd >> 3) & 0x1f); switch (cmd & 0x3) { case 1: /* Write command */ + uptr->SNS = 0; + uptr->POS = 0; + /* If nothing attached, return intervention */ + if ((uptr->flags & UNIT_ATT) == 0) { + uptr->SNS |= SNS_INTVENT; + break; + } uptr->CMD &= ~(LPR_CMDMSK); uptr->CMD |= (cmd & LPR_CMDMSK); sim_activate(uptr, 10); /* Start unit off */ - uptr->SNS = 0; - uptr->POS = 0; return 0; case 3: /* Carrage control */ uptr->SNS = 0; uptr->POS = 0; - uptr->CMD &= ~(LPR_CMDMSK); /* Nop is immediate command */ if (cmd == 0x3) return SNS_CHNEND|SNS_DEVEND; + /* If nothing attached, return intervention */ + if (cmd != CMD_SENSE && (uptr->flags & UNIT_ATT) == 0) { + uptr->SNS |= SNS_INTVENT; + break; + } + uptr->CMD &= ~(LPR_CMDMSK); uptr->CMD |= (cmd & LPR_CMDMSK); sim_activate(uptr, 10); /* Start unit off */ /* Motion and not load UCS */ @@ -403,6 +411,7 @@ uint8 lpr_startcmd(UNIT * uptr, uint8 cmd) sim_activate(uptr, 10); /* Start unit off */ return 0; } + uptr->SNS |= SNS_CMDREJ; break; default: /* invalid command */ @@ -423,6 +432,7 @@ lpr_srv(UNIT *uptr) { int l = (uptr->CMD >> 3) & 0x1f; uint8 ch; + /* Handle sense */ if (cmd == 4) { ch = uptr->SNS; uptr->CMD &= ~(LPR_CMDMSK); @@ -481,7 +491,12 @@ lpr_srv(UNIT *uptr) { uptr->CMD &= ~(LPR_FULL|LPR_CMDMSK); uptr->POS = 0; if (uptr->SNS & SNS_CHN12) { - set_devattn(addr, SNS_DEVEND|SNS_UNITEXP); + sim_debug(DEBUG_DETAIL, &lpr_dev, "%d channel 12", u); + uint8 f = SNS_DEVEND|SNS_UNITEXP; + if ((uptr->SNS & 0xff) != 0) { + f |= SNS_UNITCHK; + } + set_devattn(addr, f); uptr->SNS &= 0xff; } else { if ((uptr->SNS & 0xff) != 0)