1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-02-03 23:23:32 +00:00

SEL32: Correct channel number handling.

Add check for attached channels and units. Fix sho dev addresses.
This commit is contained in:
James C. Bevier
2019-07-17 21:39:18 -04:00
committed by Richard Cornwell
parent ec4c722919
commit f643a1e264

View File

@@ -423,11 +423,13 @@ loop:
docmd, irq_pend, chp->ccw_count, chan);
/* Check invalid count */
/* HACK HACK - LPR sends CC cmd only without data addr/count */
#ifdef NONO
if ((chp->ccw_count == 0) && (chp->ccw_addr != 0)) { /* see if byte count is zero */
chp->chan_status |= STATUS_PCHK; /* program check if it is */
irq_pend = 1; /* status pending int */
return 1; /* error return */
}
#endif
if (docmd) { /* see if we need to process command */
DIB *dibp = dev_unit[chp->chan_dev]; /* get the device pointer */
uptr = find_unit_ptr(chp->chan_dev); /* find the unit pointer */
@@ -441,6 +443,7 @@ loop:
/* just drop through and call the device startcmd function */
/* the INCH buffer will be returned in uptr->u4 and uptr->us9 will be non-zero */
/* it should just return SNS_CHNEND and SNS_DEVEND status */
/*052619*/ chp->chan_inch_addr = uptr->u4; /* save INCH buffer address */
}
sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw before start_cmd chan %0x status %.8x count %x\n",
@@ -467,7 +470,8 @@ loop:
if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) {
/* INCH cmd will return here too, get INCH buffer addr from uptr->u4 */
/* see if this is an initialize channel cmd */
if ((chp->ccw_cmd & 0xFF) == 0 && (uptr->us9 != 0)) {
// if ((chp->ccw_cmd & 0xFF) == 0 && (uptr->us9 != 0)) {
if ((chp->ccw_cmd & 0xFF) == 0 && (uptr->us9 >= 0)) {
chp->chan_inch_addr = uptr->u4; /* save INCH buffer address */
sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw INCH %x saved chan %0x\n",
chp->chan_inch_addr, chan);
@@ -719,7 +723,7 @@ void store_csw(CHANP *chp)
if ((FIFO_Put(chsa, stwd1) == -1) || (FIFO_Put(chsa, stwd2) == -1)) {
fprintf(stderr, "FIFO Overflow ERROR on chsa %x\r\n", chsa);
}
//fprintf(stderr, "store_csw on chsa %x sw1 %x sw2 %x\r\n", chsa, stwd1, stwd2);
chp->chan_status = 0; /* no status anymore */
irq_pend = 1; /* wakeup controller */
}
@@ -759,9 +763,10 @@ t_stat startxio(uint16 lchsa, uint32 *status) {
/* get the device entry for the logical channel in SPAD */
spadent = SPAD[lchan]; /* get spad device entry for logical channel */
chan = (spadent & 0xff00) >> 8; /* get real channel */
// chan = (spadent & 0xff00) >> 8; /* get real channel */
chan = (spadent & 0x7f00) >> 8; /* get real channel */
chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */
dibp = dev_unit[chsa]; /* get the device information pointer */
dibp = dev_unit[chsa & 0x7f00]; /* get the device information pointer */
chp = find_chanp_ptr(chsa); /* find the chanp pointer */
uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */
@@ -771,7 +776,7 @@ t_stat startxio(uint16 lchsa, uint32 *status) {
return SCPE_OK; /* not found, CC3 */
}
sim_debug(DEBUG_CMD, &cpu_dev, "startxio 2 chsa %x chan %x\n", chsa, chan);
if ((uptr->flags & UNIT_ATT) == 0) { /* is unit attached? */
if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */
fprintf(stderr, "startxio chsa %x is not attached, error return\r\n", chsa);
*status = CC3BIT; /* not attached, so error CC3 */
return SCPE_OK; /* not found, CC3 */
@@ -820,12 +825,15 @@ t_stat startxio(uint16 lchsa, uint32 *status) {
chp->chan_caw = iocla; /* get iocla address in memory */
/* set status words in memory to first IOCD information */
tempa = chp->chan_inch_addr; /* get inch status buffer address */
if (tempa != 0) {
// if (tempa != 0) {
if (tempa >= 0) {
M[tempa >> 2] = (chsa & 0xff) << 24 | iocla; /* suba & IOCD address to status */
M[(tempa+4) >> 2] = 0; /* null status and residual byte count */
}
sim_debug(DEBUG_CMD, &cpu_dev, "$$ SIO starting IOCL processing chsa %02x\n", chsa);
//fprintf(stderr, "$$ SIO starting IOCL processing chsa %02x\n", chsa);
//fflush(stderr);
/* start processing the IOCL */
if (load_ccw(chp, 0) || (chp->chan_status & STATUS_PCI)) {
@@ -841,8 +849,12 @@ t_stat startxio(uint16 lchsa, uint32 *status) {
if ((chp->ccw_cmd & 0xFF) == 0) /* see if this is an initialize channel cmd */
*status = CC1BIT; /* request accepted, no status, so CC1 TRY THIS */
else
*status = 0; /* CCs = 0, SIO accepted, will echo status */
// *status = 0; /* CCs = 0, SIO accepted, will echo status */
*status = CC1BIT; /* CCs = 0, SIO accepted, will echo status */
// *status = CC1BIT; /* CCs = 0, SIO accepted, will echo status */
sim_debug(DEBUG_CMD, &cpu_dev, "$$$ SIO done chsa %x status %08x\n", chsa, chp->chan_status);
//fprintf(stderr, "$$$ SIO done chsa %x status %08x\n", chsa, chp->chan_status);
//fflush(stderr);
return SCPE_OK; /* No CC's all OK */
}
@@ -860,7 +872,8 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */
/* get the device entry for the logical channel in SPAD */
spadent = SPAD[chan]; /* get spad device entry for logical channel */
chan = (spadent & 0xff00) >> 8; /* get real channel */
// chan = (spadent & 0xff00) >> 8; /* get real channel */
chan = (spadent & 0x7f00) >> 8; /* get real channel */
chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */
dibp = dev_unit[chsa]; /* get the device information pointer */
chp = find_chanp_ptr(chsa); /* find the device chanp pointer */
@@ -873,7 +886,7 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */
goto tioret; /* not found, CC3 */
}
sim_debug(DEBUG_CMD, &cpu_dev, "testxio 2 chsa %x chan %x\n", chsa, chan);
if ((uptr->flags & UNIT_ATT) == 0) { /* is unit already attached? */
if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */
*status = CC3BIT; /* not attached, so error CC3 */
goto tioret; /* not found, CC3 */
}
@@ -938,7 +951,8 @@ t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */
/* get the device entry for the logical channel in SPAD */
spadent = SPAD[chan]; /* get spad device entry for logical channel */
chan = (spadent & 0xff00) >> 8; /* get real channel */
// chan = (spadent & 0xff00) >> 8; /* get real channel */
chan = (spadent & 0x7f00) >> 8; /* get real channel */
chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */
dibp = dev_unit[chsa]; /* get the device information pointer */
chp = find_chanp_ptr(chsa); /* find the chanp pointer */
@@ -950,7 +964,7 @@ t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */
return SCPE_OK; /* not found, CC3 */
}
sim_debug(DEBUG_CMD, &cpu_dev, "stopxio 2 chsa %x chan %x\n", chsa, chan);
if ((uptr->flags & UNIT_ATT) == 0) { /* is unit already attached? */
if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */
*status = CC3BIT; /* not attached, so error CC3 */
return SCPE_OK; /* not found, CC3 */
}
@@ -1012,7 +1026,7 @@ t_stat rschnlxio(uint16 lchsa, uint32 *status) { /* reset channel XIO */
return SCPE_OK; /* not found, CC3 */
}
sim_debug(DEBUG_CMD, &cpu_dev, "rschnlxio 2 chan %x, spad %x\r\n", chsa, spadent);
if ((uptr->flags & UNIT_ATT) == 0) { /* is unit already attached? */
if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */
*status = CC3BIT; /* not attached, so error CC3 */
return SCPE_OK; /* not found, CC3 */
}
@@ -1020,6 +1034,7 @@ t_stat rschnlxio(uint16 lchsa, uint32 *status) { /* reset channel XIO */
dibp->chan_fifo_in = 0;
dibp->chan_fifo_out = 0;
dev_status[chan] = 0; /* clear the channel status location */
// chp->chan_inch_addr = 0; /* remove inch status buffer address */
chp->chan_inch_addr = 0; /* remove inch status buffer address */
lev = find_int_lev(chan); /* get our int level */
INTS[lev] &= ~INTS_ACT; /* clear level active */
@@ -1065,7 +1080,8 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */
/* get the device entry for the logical channel in SPAD */
spadent = SPAD[chan]; /* get spad device entry for logical channel */
chan = (spadent & 0xff00) >> 8; /* get real channel */
// chan = (spadent & 0xff00) >> 8; /* get real channel */
chan = (spadent & 0x7f00) >> 8; /* get real channel */
chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */
dibp = dev_unit[chsa]; /* get the device information pointer */
chp = find_chanp_ptr(chsa); /* find the chanp pointer */
@@ -1077,7 +1093,7 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */
return SCPE_OK; /* not found, CC3 */
}
sim_debug(DEBUG_CMD, &cpu_dev, "haltxio 2 chsa %x chan %x\n", chsa, chan);
if ((uptr->flags & UNIT_ATT) == 0) { /* is unit already attached? */
if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */
*status = CC3BIT; /* not attached, so error CC3 */
return SCPE_OK; /* not found, CC3 */
}
@@ -1127,7 +1143,8 @@ t_stat grabxio(uint16 lchsa, uint32 *status) { /* grab controller XIO n/u
/* get the device entry for the logical channel in SPAD */
spadent = SPAD[chan]; /* get spad device entry for logical channel */
chan = (spadent & 0xff00) >> 8; /* get real channel */
// chan = (spadent & 0xff00) >> 8; /* get real channel */
chan = (spadent & 0x7f00) >> 8; /* get real channel */
chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */
chp = find_chanp_ptr(chsa); /* find the chanp pointer */
@@ -1151,7 +1168,8 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */
/* get the device entry for the logical channel in SPAD */
spadent = SPAD[chan]; /* get spad device entry for logical channel */
chan = (spadent & 0xff00) >> 8; /* get real channel */
// chan = (spadent & 0xff00) >> 8; /* get real channel */
chan = (spadent & 0x7f00) >> 8; /* get real channel */
chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */
chp = find_chanp_ptr(chsa); /* find the chanp pointer */
@@ -1226,19 +1244,30 @@ uint32 scan_chan(void) {
continue; /* skip this one */
if (SPAD[i+0x80] == 0xffffffff) /* not initialize? */
continue; /* skip this one */
//fprintf(stderr, "done checking interrupt INTS[%d] %x\n", i, INTS[i]);
//fflush(stderr);
/* see if there is pending status for this channel */
/* if there is and the level is not requesting, do it */
if ((INTS[i] & INTS_ENAB) && !(INTS[i] & INTS_REQ)) {
/* get the device entry for the logical channel in SPAD */
chan = (SPAD[i+0x80] & 0xff00); /* get real channel and zero sa */
/*070219*/ chan = (SPAD[i+0x80] & 0xff00); /* get real channel and zero sa */
chan = (SPAD[i+0x80] & 0x7f00); /* get real channel and zero sa */
//fprintf(stderr, "getting dibp chan %x\n", chan);
//fflush(stderr);
dibp = dev_unit[chan]; /* get the device information pointer */
//fprintf(stderr, "got dibp %x chan %x\n", dibp, chan);
//fflush(stderr);
if (dibp == 0)
continue; /* skip unconfigured channel */
//fprintf(stderr, "checking fifo chan %x\n", chan);
//fflush(stderr);
/* see if the FIFO is empty */
if (dibp->chan_fifo_in != dibp->chan_fifo_out) {
uint32 sw1, sw2;
/* fifo is not empty, so post status and request an interrupt */
if ((FIFO_Get(chan, &sw1) == 0) && (FIFO_Get(chan, &sw2) == 0)) {
//fprintf(stderr, "found fifo chan %x\n", chan);
//fflush(stderr);
/* we have status to return, do it now */
chp = find_chanp_ptr(chan); /* find the chanp pointer for channel */
/* get the address of the interrupt IVL table in main memory */
@@ -1256,26 +1285,42 @@ uint32 scan_chan(void) {
}
/* look for the highest requesting interrupt */
/* that is enabled */
//fprintf(stderr, "checking interrupt INTS[%d] %x\n", i, INTS[i]);
//fflush(stderr);
if (((INTS[i] & INTS_ENAB) && (INTS[i] & INTS_REQ)) ||
((SPAD[i+0x80] & INTS_ENAB) && (INTS[i] & INTS_REQ))) {
/* requesting, make active and turn off request flag */
//fprintf(stderr, "found interrupt %x\n", INTS[i]);
//fflush(stderr);
INTS[i] &= ~INTS_REQ; /* turn off request */
INTS[i] |= INTS_ACT; /* turn on active */
SPAD[i+0x80] |= SINT_ACT; /* show active in SPAD too */
//fprintf(stderr, "enable interrupt INT[%d] %x\n", i, INTS[i]);
//fflush(stderr);
/* make sure both enabled too */
INTS[i] |= INTS_ENAB; /* turn on enable */
SPAD[i+0x80] |= SINT_ENAB; /* show enabled in SPAD too */
/* get the address of the interrupt IVL table in main memory */
chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */
chan_icba = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */
//fprintf(stderr, "scan_chan INTS REQ irq %x found chan_icba %x INTS %x\n", i, chan_icba, INTS[i]);
//fflush(stderr);
sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan INTS REQ irq %x found chan_icba %x INTS %x\n",
i, chan_icba, INTS[i]);
return(chan_icba); /* return ICB address */
}
//fprintf(stderr, "done checking interrupt INTS[%d] %x\n", i, INTS[i]);
//fflush(stderr);
}
//fprintf(stderr, "done checking interrupt loop\n");
//fflush(stderr);
}
//fprintf(stderr, "scan_chan irq_pend not pending\n");
//fflush(stderr);
if (irq_pend == 0) /* pending int? */
return 0; /* no, so just return */
//fprintf(stderr, "scan_chan irq_pend %x\n", irq_pend);
//fflush(stderr);
irq_pend = 0; /* not pending anymore */
/* loop through all the channels/units for channel with pending I/O completion */
@@ -1294,9 +1339,13 @@ uint32 scan_chan(void) {
/* Check if address is in unit or dev entry */
for (j = 0; j < dibp->numunits; j++) { /* loop through unit entries */
chsa = GET_UADDR(uptr->u3); /* ch/sa value */
//fprintf(stderr, "checking chsa %x i %d j %d units %d name %s\n", chsa, i, j, dibp->numunits, dptr->name);
//fflush(stderr);
/* If channel end, check if we should continue */
if (chp->chan_status & STATUS_CEND) { /* do we have channel end */
//fprintf(stderr, "got channel end chsa %x j %d units %d status %x\n", chsa, j, dibp->numunits, chp->chan_status);
//fflush(stderr);
if (chp->ccw_flags & FLAG_CC) { /* command chain flag */
/* we have channel end and CC flag, continue channel prog */
if (chp->chan_status & STATUS_DEND) { /* device end? */
@@ -1317,8 +1366,12 @@ uint32 scan_chan(void) {
return chsa; /* if loading, just channel number */
}
/* we are not loading, but have completed channel program */
//fprintf(stderr, "chp = %x complete\n", chp);
//fflush(stderr);
store_csw(chp); /* store the status */
lev = find_int_lev(chsa); /* get interrupt level */
//fprintf(stderr, "lev = %x complete\n", lev);
//fflush(stderr);
if (lev == 0) {
irq_pend = 1; /* still pending int */
return 0; /* just return */
@@ -1363,7 +1416,7 @@ t_stat chan_set_devs() {
/* zero some channel data loc's for device */
dev_status[chsa] = 0; /* zero device status flags */
dev_status[chsa&0x7f00] = 0; /* clear the channel status location */
dev_status[chsa] = 0; /* device status too */
// dev_status[chsa] = 0; /* device status too */
chp->chan_status = 0; /* clear the channel status */
chp->chan_dev = chsa; /* save our address (ch/sa) */
chp->chan_byte = BUFF_EMPTY; /* no data yet */
@@ -1372,6 +1425,7 @@ t_stat chan_set_devs() {
chp->ccw_count = 0; /* channel byte count 0 bytes*/
chp->ccw_flags = 0; /* Command chain and supress incorrect length */
chp->ccw_cmd = 0; /* read command */
// chp->chan_inch_addr = 0; /* clear address of stat dw in memory */
chp->chan_inch_addr = 0; /* clear address of stat dw in memory */
if ((uptr->flags & UNIT_DIS) == 0) /* is unit marked disabled? */
dev_unit[chsa] = dibp; /* no, save the dib address */
@@ -1471,6 +1525,6 @@ t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc) {
if (dptr == NULL)
return SCPE_IERR;
chsa = GET_UADDR(uptr->u3);
fprintf(st, "%04x", chsa);
fprintf(st, "CHAN/SA %04x", chsa);
return SCPE_OK;
}