1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-02-12 10:58:06 +00:00

IBM360: Moved unattached unit from channel to units.

This commit is contained in:
Richard Cornwell
2024-06-14 11:31:46 -04:00
parent a2bfd9caee
commit e1b29cca25
6 changed files with 125 additions and 69 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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