From d1988829809bc6977f1b34d271ebb6c84c83b25e Mon Sep 17 00:00:00 2001 From: AZBevier Date: Fri, 6 Mar 2020 21:41:59 -0700 Subject: [PATCH] SEL32: Correct real time clock interrupt processing. SEL32: start code cleanup. SEL32: add mfp and mfp scsi disk intitial support code. SEL32: add new files sel32_mfp.c and sel32_scsi.c to makefile. SEL32: modify sel32_mt.c code to define tape as BTP for UTX. --- SEL32/sel32_chan.c | 337 +++++++++-- SEL32/sel32_clk.c | 15 +- SEL32/sel32_com.c | 141 +++-- SEL32/sel32_con.c | 31 +- SEL32/sel32_cpu.c | 235 +++++--- SEL32/sel32_defs.h | 5 + SEL32/sel32_disk.c | 290 ++++++---- SEL32/sel32_fltpt.c | 10 +- SEL32/sel32_hsdp.c | 70 ++- SEL32/sel32_lpr.c | 1 + SEL32/sel32_mfp.c | 275 +++++++++ SEL32/sel32_mt.c | 126 ++-- SEL32/sel32_scfi.c | 14 +- SEL32/sel32_scsi.c | 1160 +++++++++++++++++++++++++++++++++++++ SEL32/sel32_sys.c | 5 + SEL32/taptools/filelist.c | 12 +- makefile | 2 +- 17 files changed, 2335 insertions(+), 394 deletions(-) create mode 100644 SEL32/sel32_mfp.c create mode 100644 SEL32/sel32_scsi.c diff --git a/SEL32/sel32_chan.c b/SEL32/sel32_chan.c index 39ac3d8..e49efa4 100644 --- a/SEL32/sel32_chan.c +++ b/SEL32/sel32_chan.c @@ -102,11 +102,11 @@ uint16 loading; /* set when booting */ /* forward definitions */ CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */ UNIT *find_unit_ptr(uint16 chsa); /* find unit pointer */ -int chan_read_byte(uint16 chan, uint8 *data); -int chan_write_byte(uint16 chan, uint8 *data); +int chan_read_byte(uint16 chsa, uint8 *data); +int chan_write_byte(uint16 chsa, uint8 *data); void set_devattn(uint16 chsa, uint16 flags); void set_devwake(uint16 chsa, uint16 flags); /* wakeup O/S for async line */ -void chan_end(uint16 chan, uint16 flags); +void chan_end(uint16 chsa, uint16 flags); int test_write_byte_end(uint16 chsa); t_stat checkxio(uint16 chsa, uint32 *status); /* check XIO */ t_stat startxio(uint16 chsa, uint32 *status); /* start XIO */ @@ -125,6 +125,7 @@ t_stat chan_set_devs(); t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc); DEVICE *get_dev(UNIT *uptr); +void store_csw(CHANP *chp); /* FIFO support */ /* These are FIFO queues which return an error when full. @@ -173,7 +174,7 @@ int FIFO_Get(uint16 chsa, uint32 *old) t_stat set_inch(UNIT *uptr, uint32 inch_addr) { uint16 chsa = GET_UADDR(uptr->u3); /* get channel & sub address */ uint32 chan = chsa & 0x7f00; /* get just channel address */ - CHANP *pchp = find_chanp_ptr(chan); /* get channel channel prog ptr */ + CHANP *pchp = find_chanp_ptr(chan); /* get channel prog ptr */ DIB *dibp; /* get DIB pointer for channel */ CHANP *chp; int i; @@ -320,7 +321,7 @@ CHANP *find_chanp_ptr(uint16 chsa) CHANP *chp; /* CHANP pointer */ int i; - dibp = dev_unit[chsa]; /* get DIB pointer from device pointers */ + dibp = dev_unit[chsa&0x7fff]; /* get DIB pointer from device pointers */ if (dibp == 0) /* if zero, not defined on system */ return NULL; /* tell caller */ if ((chp = (CHANP *)dibp->chan_prg) == NULL) { /* must have channel information for each device */ @@ -369,10 +370,13 @@ int readbuff(CHANP *chp) { int k; uint32 addr = chp->ccw_addr; /* channel buffer address */ - uint16 chan = get_chan(chp->chan_dev); /* our channel */ +//XXX uint16 chan = get_chan(chp->chan_dev); /* our channel */ if ((addr & MASK24) >= (MEMSIZE*4)) { /* see if memory address invalid */ chp->chan_status |= STATUS_PCHK; /* bad, program check */ + sim_debug(DEBUG_EXP, &cpu_dev, + "readbuff PCHK addr %08x to big mem %08x status %04x\n", + addr, MEMSIZE, chp->chan_status); chp->chan_byte = BUFF_CHNEND; /* force channel end */ irq_pend = 1; /* and we have an interrupt */ return 1; /* done, with error */ @@ -386,8 +390,9 @@ int readbuff(CHANP *chp) #endif #ifdef TEST - sim_debug(DEBUG_DETAIL, &cpu_dev, "readbuff read memory bytes into buffer %02x %06x %06x %04x [", - chan, chp->ccw_addr & 0xFFFFFC, chp->chan_buf, chp->ccw_count); + sim_debug(DEBUG_DETAIL, &cpu_dev, + "readbuff read memory chsa %04x into buffer %06x %06x %04x [", + chp->chan_dev, chp->ccw_addr & 0xFFFFFC, chp->chan_buf, chp->ccw_count); for(k = 24; k >= 0; k -= 8) { char ch = (chp->chan_buf >> k) & 0xFF; if (ch < 0x20 || ch == 0xff) @@ -409,7 +414,7 @@ int writebuff(CHANP *chp) if ((addr & MASK24) >= (MEMSIZE*4)) { chp->chan_status |= STATUS_PCHK; - sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_EXP, &cpu_dev, "writebuff PCHK addr %08x to big mem %08x status %04x\n", addr, MEMSIZE, chp->chan_status); chp->chan_byte = BUFF_CHNEND; @@ -423,7 +428,7 @@ int writebuff(CHANP *chp) #ifdef TEST M[addr>>2] = chp->chan_buf; #else - WMB(addr, chp->chan_buf); /* write byte to bebory */ + WMB(addr, chp->chan_buf); /* write byte to memory */ #endif return 0; } @@ -434,7 +439,6 @@ int writebuff(CHANP *chp) int load_ccw(CHANP *chp, int tic_ok) { uint32 word; -// uint8 devstat; int docmd = 0; UNIT *uptr = find_unit_ptr(chp->chan_dev); /* find the unit pointer */ uint16 chan = get_chan(chp->chan_dev); /* our channel */ @@ -567,24 +571,27 @@ loop: } #endif if (docmd) { /* see if we need to process command */ +#ifdef TRY_THIS_TUESDAY_0301 + uint8 devstat; +#endif // DEVICE *dptr = get_dev(uptr); /* find the device from unit pointer */ DIB *dibp = dev_unit[chp->chan_dev]; /* get the device pointer */ + uptr = find_unit_ptr(chp->chan_dev); /* find the unit pointer */ if (uptr == 0) return 1; /* if none, error */ sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw before start_cmd chan %04x status %04x count %04x\n", -// chan, chp->chan_status, chp->ccw_count, dptr->name); chan, chp->chan_status, chp->ccw_count); /* call the device startcmd function to process the current command */ -#ifndef TRY_THIS_TUESDAY +#ifndef TRY_THIS_TUESDAY_0301 chp->chan_status = dibp->start_cmd(uptr, chan, chp->ccw_cmd); #else /* just replace device status bits */ devstat = dibp->start_cmd(uptr, chan, chp->ccw_cmd); - chp->chan_status = (chp->chan_status & 0xffffff00) | (devstat & 0xff); + chp->chan_status = (chp->chan_status & 0xff00) | (devstat & 0xff); #endif sim_debug(DEBUG_XIO, &cpu_dev, @@ -612,6 +619,9 @@ loop: sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw cmd complete chan %04x status %04x count %04x\n", chan, chp->chan_status, chp->ccw_count); + /* we want to terminate if command is complete */ + /* go store status and return CC2 */ +/*NEW*/ return 1; /* return cmd complete */ } } sim_debug(DEBUG_XIO, &cpu_dev, @@ -720,7 +730,7 @@ int chan_write_byte(uint16 chsa, uint8 *data) } if (chp->ccw_count == 0) { sim_debug(DEBUG_EXP, &cpu_dev, - "chan_write_byte ZERO ccw_count[%04x] %04x addr %06x\n", + "chan_write_byte ZERO chan %04x ccw_count %04x addr %06x\n", chan, chp->ccw_count, chp->ccw_addr); if (chp->chan_byte & BUFF_DIRTY) { sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte 2 BUF DIRTY ret\n"); @@ -844,7 +854,7 @@ void chan_end(uint16 chsa, uint16 flags) { chp->chan_status |= ((uint16)flags); /* add in the callers flags */ // chp->ccw_cmd = 0; /* reset the completed channel command */ - sim_debug(DEBUG_XIO, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end SLI test1 chsa %04x ccw_flags %04x count %04x status %04x\n", chsa, chp->ccw_flags, chp->ccw_count, chp->chan_status); #ifdef HACK_HACK @@ -869,12 +879,12 @@ void chan_end(uint16 chsa, uint16 flags) { } } #endif - sim_debug(DEBUG_XIO, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end SLI2 test chsa %04x ccw_flags %04x status %04x\n", chsa, chp->ccw_flags, chp->chan_status); chp->ccw_cmd = 0; /* reset the completed channel command */ - /* Diags dos not want SLI if we have no device end status */ + /* Diags do not want SLI if we have no device end status */ if ((chp->chan_status & FLAG_SLI) && ((chp->chan_status & STATUS_DEND) == 0)) chp->chan_status &= ~FLAG_SLI; @@ -883,7 +893,7 @@ void chan_end(uint16 chsa, uint16 flags) { chp->ccw_flags = 0; /* no flags */ } - sim_debug(DEBUG_XIO, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end test end chsa %04x ccw_flags %04x status %04x\n", chsa, chp->ccw_flags, chp->chan_status); @@ -898,8 +908,57 @@ void chan_end(uint16 chsa, uint16 flags) { chp->ccw_flags = 0; /* no flags */ } } + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end IOCL done chsa %04x ccw_flags %04x status %04x\n", + chsa, chp->ccw_flags, chp->chan_status); +#ifndef NEW_METHOD + /* If channel end, check if we should continue */ + if (chp->chan_status & STATUS_CEND) { /* do we have channel end */ + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end chan end chsa %04x flags %04x status %04x\n", + chsa, chp->ccw_flags, chp->chan_status); + if (chp->ccw_flags & FLAG_CC) { /* command chain flag */ + /* we have channel end and CC flag, continue channel prog */ + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end chan end & CC chsa %04x status %04x\n", + chsa, chp->chan_status); + if (chp->chan_status & STATUS_DEND) { /* device end? */ + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end dev end & CC chsa %04x status %04x\n", + chsa, chp->chan_status); + (void)load_ccw(chp, 1); /* go load the next IOCB */ + } else + irq_pend = 1; /* still pending int */ + } else { + /* we have channel end and no CC flag, end command */ + chsa = chp->chan_dev; /* get the chan/sa */ + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end chan end & no CC chsa %04x status %04x\n", + chsa, chp->chan_status); + dev_status[chsa] = 0; /* no device status anymore */ + /* we have completed channel program */ + /* handle case where we are loading the O/S on boot */ + /* if loading, leave status to be discovered by scan_chan */ + if (!loading) { + sim_debug(DEBUG_DETAIL, &cpu_dev, + "chan_end call store_csw dev end & chan end chsa %04x cpustatus %08x\n", + chsa, CPUSTATUS); + store_csw(chp); /* store the status */ + } + else + sim_debug(DEBUG_DETAIL, &cpu_dev, + "chan_end we are loading with DE & CE, keep status chsa %04x status %08x\n", + chsa, chp->chan_status); +//XXX irq_pend = 1; /* still pending int */ + } + } + else + sim_debug(DEBUG_DETAIL, &cpu_dev, + "chan_end IOCL2 done chsa %04x ccw_flags %04x status %04x\n", + chsa, chp->ccw_flags, chp->chan_status); +#endif } - irq_pend = 1; /* flag to test for int condition */ +//XXX irq_pend = 1; /* flag to test for int condition */ } /* store the device status into the status DW in memory */ @@ -965,24 +1024,26 @@ t_stat checkxio(uint16 lchsa, uint32 *status) { chp = find_chanp_ptr(chsa); /* find the chanp pointer */ uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ - sim_debug(DEBUG_CMD, &cpu_dev, "checkxio 1 chsa %04x chan %04x\n", chsa, chan); + sim_debug(DEBUG_DETAIL, &cpu_dev, "checkxio 1 chsa %04x chan %04x\n", chsa, chan); if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ *status = CC3BIT; /* not found, so CC3 */ - sim_debug(DEBUG_XIO, &cpu_dev, "checkxio chsa %04x is not found, CC3 return\n", chsa); + sim_debug(DEBUG_XIO, &cpu_dev, + "checkxio chsa %04x is not found, CC3 return\n", chsa); return SCPE_OK; /* not found, CC3 */ } if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ - sim_debug(DEBUG_XIO, &cpu_dev, "checkxio chsa %04x is not attached, CC3 return\n", chsa); + sim_debug(DEBUG_XIO, &cpu_dev, + "checkxio chsa %04x is not attached, CC3 return\n", chsa); *status = CC3BIT; /* not attached, so error CC3 */ return SCPE_OK; /* not found, CC3 */ } /* see if interrupt is setup in SPAD and determine IVL for channel */ - sim_debug(DEBUG_CMD, &cpu_dev, "checkxio dev spad %08x chsa %04x\n", spadent, chsa); + sim_debug(DEBUG_DETAIL, &cpu_dev, "checkxio dev spad %08x chsa %04x\n", spadent, chsa); inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ inta = 127 - inta; /* get positive int level */ spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ - sim_debug(DEBUG_CMD, &cpu_dev, "checkxio int spad %08x inta %04x chan %04x\n", spadent, inta, chan); + sim_debug(DEBUG_DETAIL, &cpu_dev, "checkxio int spad %08x inta %04x chan %04x\n", spadent, inta, chan); /* get the address of the interrupt IVL in main memory */ chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ @@ -990,8 +1051,11 @@ t_stat checkxio(uint16 lchsa, uint32 *status) { iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ tempa = M[(chan_ivl+20)>>2]; /* status is in wd 5 of ICB */ sim_debug(DEBUG_CMD, &cpu_dev, - "checkxio busy ck chsa %04x cmd %02x iocla %08x flags %04x IOCD1 %08x IOCD2 %08x status %08x\n", - chsa, chp->ccw_cmd, iocla, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2], tempa); + "checkxio busy ck1 chsa %04x cmd %02x iocla %06x flags %04x\n", + chsa, chp->ccw_cmd, iocla, chp->ccw_flags); + sim_debug(DEBUG_CMD, &cpu_dev, + "checkxio busy ck2 chsa %04x IOCD1 %08x IOCD2 %08x INCH %08x\n", + chsa, M[iocla>>2], M[(iocla+4)>>2], tempa); /* check for a Command or data chain operation in progresss */ if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { @@ -1007,7 +1071,8 @@ t_stat checkxio(uint16 lchsa, uint32 *status) { tempa = dibp->pre_io(uptr, chan); /* get status from device */ if (tempa != 0) { /* see if sub channel status is ready */ /* The device must be busy or something, but it is not ready. Return busy */ - sim_debug(DEBUG_XIO, &cpu_dev, "checkxio CC3 & CC4 return busy chan %04x cstat %08x\n", + sim_debug(DEBUG_XIO, &cpu_dev, + "checkxio CC3 & CC4 return busy chan %04x cstat %08x\n", chan, tempa); *status = CC3BIT|CC4BIT; /* sub channel busy, so CC3|CC4 */ return SCPE_OK; /* just busy or something, CC3|CC4 */ @@ -1116,7 +1181,7 @@ t_stat startxio(uint16 lchsa, uint32 *status) { if (chp->chan_status & STATUS_PCHK) { chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ chp->chan_status &= ~STATUS_LENGTH; /* clear incorrect length */ - store_csw(chp); /* store the status in the inch status dw */ +//XXX store_csw(chp); /* store the status in the inch status dw */ dev_status[chsa] = 0; /* no device status */ //DIAG *status = CC2BIT; /* status stored, so CC2 */ *status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */ @@ -1159,24 +1224,24 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */ uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ pchp = find_chanp_ptr(chsa & 0x7f00); /* find the channel chanp pointer */ - sim_debug(DEBUG_XIO, &cpu_dev, "testxio 1 chsa %04x chan %04x\n", chsa, chan); + sim_debug(DEBUG_DETAIL, &cpu_dev, "testxio 1 chsa %04x chan %04x\n", chsa, chan); if ((dibp == 0) || (uptr == 0)) { /* if non found, CC3 on return */ *status = CC3BIT; /* not found, so CC3 */ goto tioret; /* not found, CC3 */ } - sim_debug(DEBUG_XIO, &cpu_dev, "testxio 2 chsa %04x chan %04x\n", chsa, chan); + sim_debug(DEBUG_DETAIL, &cpu_dev, "testxio 2 chsa %04x chan %04x\n", chsa, chan); 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 */ } /* see if interrupt is setup in SPAD and determine IVL for channel */ - sim_debug(DEBUG_XIO, &cpu_dev, "testxio dev spad %08x chsa %04x chan %04x\n", spadent, chsa, chan); + sim_debug(DEBUG_DETAIL, &cpu_dev, "testxio dev spad %08x chsa %04x chan %04x\n", spadent, chsa, chan); /* the startio opcode processing software has already checked for F class */ inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ inta = 127 - inta; /* get positive int level */ spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ - sim_debug(DEBUG_XIO, &cpu_dev, "testxio int spad %08x inta %04x chan %04x\n", spadent, inta, chan); + sim_debug(DEBUG_DETAIL, &cpu_dev, "testxio int spad %08x inta %04x chan %04x\n", spadent, inta, chan); /* get the address of the interrupt IVL in main memory */ chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ @@ -1187,9 +1252,6 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */ "testxio busy test chsa %04x cmd %02x flags %04x IOCD1 %08x IOCD2 %08x IOCLA %08x\n", chsa, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2], iocla); - sim_debug(DEBUG_XIO, &cpu_dev, "$$ TIO chsa %04x chan %04x cmd %02x flags %04x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags); - /* check for a Command or data chain operation in progresss */ if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { sim_debug(DEBUG_CMD, &cpu_dev, @@ -1197,7 +1259,20 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */ *status = CC4BIT; /* busy, so CC4 */ goto tioret; /* just busy CC4 */ } + +//#define NEW_LOOK +#ifdef NEW_LOOK + /* see if status already posted and requesting interrupt */ + if (INTS[inta] & INTS_REQ) { + /* we have status and a request, tell caller */ + *status = CC2BIT; /* status stored from SIO, so CC2 */ + INTS[inta] &= ~INTS_REQ; /* turn off request bit */ + goto tioret; /* CC2 and OK */ + } +#endif /* the channel is not busy, see if any status to post */ + /* see if the FIFO is empty */ + if (dibp->chan_fifo_in != dibp->chan_fifo_out) { if ((FIFO_Get(chsa, &sw1) == 0) && (FIFO_Get(chsa, &sw2) == 0)) { uint32 chan_icb = find_int_icb(chsa); /* get icb address */ @@ -1213,6 +1288,7 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */ *status = CC2BIT; /* status stored from SIO, so CC2 */ goto tioret; /* CC2 and OK */ } + } /* nothing going on, so say all OK */ *status = CC1BIT; /* request accepted, no status, so CC1 */ tioret: @@ -1323,8 +1399,8 @@ t_stat rschnlxio(uint16 lchsa, uint32 *status) { /* reset channel XIO */ 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 */ - INTS[lev] &= ~INTS_REQ; /* clear level request */ SPAD[lev+0x80] &= ~SINT_ACT; /* clear spad too */ + INTS[lev] &= ~INTS_REQ; /* clear level request */ /* now go through all the sa for the channel and stop any IOCLs */ for (i=0; i<256; i++) { @@ -1414,9 +1490,12 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ return SCPE_OK; /* No CC's all OK */ #else /* diag wants an interrupt for a non busy HIO ??? */ + sim_debug(DEBUG_XIO, &cpu_dev, + "$$$ HIO DIAG chsa %04x chan %04x cmd %02x flags %04x status %04x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ - store_csw(chp); /* store the status in the inch status dw */ +//XXX store_csw(chp); /* store the status in the inch status dw */ dev_status[chsa] = 0; /* no device status */ irq_pend = 1; /* still pending int */ // *status = CC2BIT; /* sub channel status posted, CC2BIT */ @@ -1443,14 +1522,14 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ /* test for SCPE_IOERR */ if (tempa != 0) { /* sub channel has status ready */ /* The device I/O has been terminated and status stored. */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "haltxio halt_io call return ERROR chan %04x retstat %08x cstat %08x\n", chan, tempa, chp->chan_status); /*TUE*/ chp->chan_status &= ~STATUS_LENGTH; /* remove SLI status bit */ chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ //TUE dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */ /* chan_end called in hio device service routine */ - store_csw(chp); /* store the status in the inch status dw */ +//XXX store_csw(chp); /* store the status in the inch status dw */ chp->ccw_count = 0; /* force zero count */ dev_status[chsa] = 0; /* no device status */ @@ -1465,6 +1544,8 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ sim_debug(DEBUG_IRQ, &cpu_dev, "haltxio 0 FIFO status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2); +/*TUE*/ sw2 &= ~STATUS_LENGTH; /* remove SLI status bit */ + sw2 |= STATUS_ECHO; /* show we stopped the cmd */ /* we have status to return, do it now */ tempa = pchp->chan_inch_addr; /* get inch status buffer address */ M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ @@ -1479,7 +1560,7 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ // UTX likes this return and does not panic */ // The diag's want an interrupt generated, so wait *status = CC2BIT; /* status stored from HIO, so CC2 */ - /* if 0 returned, UTX hans on input */ + /* if 0 returned, UTX hangs on input */ goto hioret; /* CC2 and OK */ } /* nothing going on, so say all OK */ @@ -1500,8 +1581,8 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ /* we have completed the I/O without error */ /* the channel is not busy, so return OK */ //WAS *status = 0; /* CCs = 0, accepted */ - sim_debug(DEBUG_CMD, &cpu_dev, - "$$$ HALTIO good return chsa %04x chan %04x cmd %02x flags %04x status %04x\n", + sim_debug(DEBUG_XIO, &cpu_dev, + "$$$ HALTXIO good return chsa %04x chan %04x cmd %02x flags %04x status %04x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); *status = CC1BIT; /* request accepted, no status, so CC1 */ goto hioret; /* just return */ @@ -1514,11 +1595,11 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ sim_debug(DEBUG_XIO, &cpu_dev, "haltxio busy return CC4 chsa %04x chan %04x\n", chsa, chan); /* reset the DC or CC bits to force completion after current IOCD */ chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ -//CHG dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */ + dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */ /*ADD*/ chp->ccw_count = 0; /* clear remaining count */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ /*ADD*/ chp->chan_status &= ~STATUS_LENGTH; /* remove SLI status bit */ - store_csw(chp); /* store the status in the inch status dw */ +//XXX store_csw(chp); /* store the status in the inch status dw */ chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ dev_status[chsa] = 0; /* no device status */ irq_pend = 1; /* still pending int */ @@ -1596,8 +1677,8 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */ 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 */ - INTS[lev] &= ~INTS_REQ; /* clear level request */ SPAD[lev+0x80] &= ~SINT_ACT; /* clear spad too */ + INTS[lev] &= ~INTS_REQ; /* clear level request */ /* now go through all the sa for the channel and stop any IOCLs */ for (i=0; i<256; i++) { @@ -1629,7 +1710,8 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */ /* on CPU reset, the cpu has set the IOCD data at location 0-4 */ t_stat chan_boot(uint16 chsa, DEVICE *dptr) { int chan = get_chan(chsa); - DIB *dibp = dev_unit[chsa]; +//Z DIB *dibp = dev_unit[chsa]; + DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to DIB for this device */ CHANP *chp = 0; sim_debug(DEBUG_EXP, &cpu_dev, "Channel Boot chan/device addr %04x\n", chsa); @@ -1671,7 +1753,8 @@ t_stat chan_boot(uint16 chsa, DEVICE *dptr) { interrupt pending. Return icb address and interrupt level */ uint32 scan_chan(int *ilev) { - int i,j; + int i; +//XXint j; uint32 chsa = 0; /* No device */ uint32 chan; /* channel num 0-7f */ uint32 tempa; /* icb address */ @@ -1680,7 +1763,9 @@ uint32 scan_chan(int *ilev) { CHANP *chp; /* channel prog pointer */ DIB *dibp; /* DIB pointer */ - if (irq_pend == 1) { /* pending int? */ +#ifdef OLD_METHOD +//WAS if (irq_pend == 1) { /* pending int? */ + if ((irq_pend == 1) && loading) { /* pending int? */ /* see if we have a channel completed */ /* loop through all the channels/units for channel with pending I/O completion */ for (i = 0; sim_devices[i] != NULL; i++) { @@ -1701,16 +1786,16 @@ uint32 scan_chan(int *ilev) { /* If channel end, check if we should continue */ if (chp->chan_status & STATUS_CEND) { /* do we have channel end */ - sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "scan_chan loading %02x chan end chsa %04x flags %04x status %04x\n", loading, chsa, chp->ccw_flags, chp->chan_status); if (chp->ccw_flags & FLAG_CC) { /* command chain flag */ /* we have channel end and CC flag, continue channel prog */ - sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "scan_chan loading %02x chan end & CC chsa %04x status %04x\n", loading, chsa, chp->chan_status); if (chp->chan_status & STATUS_DEND) { /* device end? */ - sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "scan_chan loading %02x dev end & CC chsa %04x status %04x\n", loading, chsa, chp->chan_status); (void)load_ccw(chp, 1); /* go load the next IOCB */ @@ -1719,7 +1804,7 @@ uint32 scan_chan(int *ilev) { } else { /* we have channel end and no CC flag, end command */ chsa = chp->chan_dev; /* get the chan/sa */ - sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "scan_chan loading %02x chan end & no CC chsa %04x status %04x\n", loading, chsa, chp->chan_status); dev_status[chsa] = 0; /* no device status anymore */ @@ -1748,6 +1833,105 @@ uint32 scan_chan(int *ilev) { } } //WAS trythis: +#else + if ((irq_pend == 1) && loading) { /* pending int? */ + /* see if we have a channel completed for the boot channel */ + chp = find_chanp_ptr(loading); /* find the chanp pointer for channel */ + /* If channel end, check if we should continue */ + if (chp->chan_status & STATUS_CEND) { /* do we have channel end */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "scan_chan loading %02x chan end chsa %04x flags %04x status %02x\n", + loading, chsa, chp->ccw_flags, chp->chan_status); + if (chp->ccw_flags & FLAG_CC) { /* command chain flag */ + /* we have channel end and CC flag, continue channel prog */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "scan_chan loading %02x chan end & CC chsa %04x status %02x\n", + loading, chsa, chp->chan_status); + if (chp->chan_status & STATUS_DEND) { /* device end? */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "scan_chan loading %02x dev end & CC chsa %04x status %02x\n", + loading, chsa, chp->chan_status); + (void)load_ccw(chp, 1); /* go load the next IOCB */ + } else + irq_pend = 1; /* still pending int */ + } else { + /* we have channel end and no CC flag, end command */ + chsa = chp->chan_dev; /* get the chan/sa */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "scan_chan loading %02x chan end & no CC chsa %04x status %02x\n", + loading, chsa, chp->chan_status); + dev_status[chsa] = 0; /* no device status anymore */ + /* handle case where we are loading the O/S on boot */ + if (chp->chan_status & 0x3f03) { /* check if any channel errors */ + return 0; /* yes, just return */ + } + irq_pend = 0; /* no pending int */ + chp->chan_status = 0; /* no channel status */ + return chsa; /* if loading, just channel number */ + } + } + } +#endif + +//#define NEW_LOOK +#ifdef NEW_LOOK + /* Look for channels that are not active and not requesting, */ + /* but have status to post. Store the status and make them */ + /* into an interest request. They will be found when we scan */ + /* for the highest requesting interrupt. */ + for (i=0; i<112; i++) { + if (SPAD[i+0x80] == 0) /* not initialize? */ + continue; /* skip this one */ + if (SPAD[i+0x80] == 0xffffffff) /* not initialize? */ + continue; /* skip this one */ + /* see if interrupt is enabled */ + if (!((INTS[i] & INTS_ENAB) || (SPAD[i+0x80] & SINT_ENAB))) + continue; /* skip this one */ + /* we are enabled, see if already active */ + if ((INTS[i] & INTS_ACT) || (SPAD[i+0x80] & SINT_ACT)) + continue; /* this level active, keep looking */ + /* see if status already posted and requesting */ + if (INTS[i] & INTS_REQ) + continue; /* this level requesting, keep looking */ + /* see if there is pending status for this channel */ + /* if there is, load it and request interrupt */ + /* get the device entry for the logical channel in SPAD */ + chan = (SPAD[i+0x80] & 0x7f00); /* get real channel and zero sa */ + dibp = dev_unit[chan]; /* get the device information pointer */ + /* no status for non-device entries */ + if (dibp == 0) { + sim_debug(DEBUG_DETAIL, &cpu_dev, + "scan_chan %04x int %02x no DIB pointer for requesting interrupt\n", chan, i); + continue; /* skip unconfigured channel */ + } + /* see if FIFO has status to post */ + 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)) { + /* 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 */ + 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 blk addr in memory */ + tempa = chp->chan_inch_addr; /* get inch status buffer address */ + M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ + /* save the status to memory */ + M[(tempa+4) >> 2] = sw2; /* save status and count in status WD 2 loc */ + /* now store the status dw address into word 5 of the ICB for the channel */ + /* post sw addr in ICB+5w & set CC2 in SW */ + M[(chan_icba + 20) >> 2] = tempa | BIT1; + INTS[i] |= INTS_REQ; /* turn on channel interrupt request */ + sim_debug(DEBUG_IRQ, &cpu_dev, + "scan_chan REQ %04x FIFO read, irq %02x inch %06x chan_icba %06x sw1 %08x sw2 %08x\n", + chan, i, tempa, chan_icba, sw1, sw2); + irq_pend = 1; /* still pending int */ + continue; /* keep looking */ + } + } + /* no status to post, so go on */ + } +#endif /* see if we are able to look for ints */ if ((CPUSTATUS & 0x80) == 0) { /* are interrupts blocked */ /* ints not blocked, so look for highest requesting interrupt */ @@ -1757,8 +1941,37 @@ uint32 scan_chan(int *ilev) { if (SPAD[i+0x80] == 0xffffffff) /* not initialize? */ continue; /* skip this one */ // if (INTS[i]&INTS_ACT) /* look for level active */ - if (SPAD[i+0x80] & SINT_ACT) /* look for level active */ + if (SPAD[i+0x80] & SINT_ACT) { /* look for level active */ + sim_debug(DEBUG_IRQ, &cpu_dev, + "scan_chan INTS ACT irq %02x SPAD %08x INTS %08x\n", + i, SPAD[i+0x80], INTS[i]); break; /* this level active, so stop looking */ + } +#ifndef OLD3 + /* look for the highest requesting interrupt */ + /* that is enabled */ + if (((INTS[i] & INTS_ENAB) && (INTS[i] & INTS_REQ)) || + ((SPAD[i+0x80] & SINT_ENAB) && (INTS[i] & INTS_REQ))) { + /* requesting, make active and turn off request flag */ + INTS[i] &= ~INTS_REQ; /* turn off request */ + INTS[i] |= INTS_ACT; /* turn on active */ + SPAD[i+0x80] |= SINT_ACT; /* show active in SPAD too */ + /* make sure both enabled too */ + /* should already be enabled */ +// 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 */ + sim_debug(DEBUG_IRQ, &cpu_dev, + "scan_chan INTS REQ irq %02x found chan_icba %08x INTS %08x\n", + i, chan_icba, INTS[i]); + *ilev = i; /* return interrupt level */ + irq_pend = 0; /* not pending anymore */ + return(chan_icba); /* return ICB address */ + } +#endif +#ifndef OLD1 /* 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)) { @@ -1786,11 +1999,15 @@ uint32 scan_chan(int *ilev) { M[(chan_icba + 20) >> 2] = tempa | BIT1; INTS[i] |= INTS_REQ; /* turn on channel interrupt request */ sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan %04x FIFO read, set irq %04x inch %06x chan_icba %06x sw1 %08x sw2 %08x\n", + "scan_chan %04x FIFO read, set irq %02x inch %06x chan_icba %06x sw1 %08x sw2 %08x\n", chan, i, tempa, chan_icba, sw1, sw2); + irq_pend = 1; /* still pending int */ + break; /* quit looking */ } } } +#endif +#ifdef OLD2 /* look for the highest requesting interrupt */ /* that is enabled */ if (((INTS[i] & INTS_ENAB) && (INTS[i] & INTS_REQ)) || @@ -1813,11 +2030,13 @@ uint32 scan_chan(int *ilev) { irq_pend = 0; /* not pending anymore */ return(chan_icba); /* return ICB address */ } +#endif } } return 0; /* done */ } +/* part of find_dev_from_unit(UNIT *uptr) in scp.c */ /* Find_dev pointer for a unit Input: uptr = pointer to unit Output: dptr = pointer to device @@ -1892,8 +2111,10 @@ t_stat chan_set_devs() { chp->ccw_cmd = 0; /* read command */ chp->chan_inch_addr = 0; /* clear address of stat dw in memory */ if ((uptr->flags & UNIT_DIS) == 0) { /* is unit marked disabled? */ - if (dev_unit[chsa] != 0) - printf("Channel/SubAddress %04x multiple defined\n", chsa); + if (dev_unit[chsa] != 0) { + printf("Channel/SubAddress %04x multiple defined, aborting\n", chsa); + return SCPE_IERR; /* no, arg error */ + } dev_unit[chsa] = dibp; /* no, save the dib address */ } if (dibp->dev_ini != NULL) /* if there is an init routine, call it now */ @@ -1962,7 +2183,7 @@ t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc) { return SCPE_IERR; /* no, error return */ dptr = get_dev(uptr); /* get the device pointer from unit */ if (dptr == NULL) /* valid pointer? */ - return SCPE_IERR; /* retunr error */ + return SCPE_IERR; /* return error */ chsa = GET_UADDR(uptr->u3); /* get the unit address */ fprintf(st, "CHAN/SA %04x", chsa); /* display channel/subaddress */ return SCPE_OK; /* we done */ diff --git a/SEL32/sel32_clk.c b/SEL32/sel32_clk.c index 1e22460..14e1092 100644 --- a/SEL32/sel32_clk.c +++ b/SEL32/sel32_clk.c @@ -115,8 +115,10 @@ t_stat rtc_srv (UNIT *uptr) time_t result = time(NULL); // fprintf(stderr, "Clock int time %08x\r\n", (uint32)result); sim_debug(DEBUG_CMD, &rtc_dev, "RT Clock int time %08x\n", (uint32)result); - if ((INTS[rtc_lvl] & INTS_ENAB) && /* make sure enabled */ - (INTS[rtc_lvl] & INTS_ACT) == 0) { /* and not active */ + if (((INTS[rtc_lvl] & INTS_ENAB) || /* make sure enabled */ + (SPAD[rtc_lvl+0x80] & SINT_ENAB)) && /* in spad too */ + (((INTS[rtc_lvl] & INTS_ACT) == 0) || /* and not active */ + ((SPAD[rtc_lvl+0x80] & SINT_ACT) == 0))) { /* in spad too */ INTS[rtc_lvl] |= INTS_REQ; /* request the interrupt */ irq_pend = 1; /* make sure we scan for int */ } @@ -149,6 +151,7 @@ void rtc_setup(uint32 ss, uint32 level) SPAD[level+0x80] &= ~SINT_ENAB; /* in spad too */ // INTS[level] &= ~INTS_REQ; /* make sure request not requesting */ // INTS[level] &= ~INTS_ACT; /* make sure request not active */ +// SPAD[level+0x80] &= ~SINT_ACT; /* in spad too */ sim_debug(DEBUG_CMD, &rtc_dev, "RT Clock setup disable int %02x rtc_pie %01x ss %01x\n", rtc_lvl, rtc_pie, ss); @@ -274,9 +277,11 @@ t_stat itm_srv (UNIT *uptr) sim_debug(DEBUG_CMD, &itm_dev, "Intv Timer expired status %08x interrupt %02x @ time %08x\n", INTS[itm_lvl], itm_lvl, (uint32)result); - if ((INTS[itm_lvl] & INTS_ENAB) && /* make sure enabled */ - (INTS[itm_lvl] & INTS_ACT) == 0) { /* and not active */ - INTS[itm_lvl] |= INTS_REQ; /* request the interrupt on zero value */ + if (((INTS[itm_lvl] & INTS_ENAB) || /* make sure enabled */ + (SPAD[itm_lvl+0x80] & SINT_ENAB)) && /* in spad too */ + (((INTS[itm_lvl] & INTS_ACT) == 0) || /* and not active */ + ((SPAD[itm_lvl+0x80] & SINT_ACT) == 0))) { /* in spad too */ + INTS[itm_lvl] |= INTS_REQ; /* request the interrupt */ irq_pend = 1; /* make sure we scan for int */ } if ((INTS[itm_lvl] & INTS_ENAB) && (itm_cmd == 0x3d) && (itm_cnt != 0)) { diff --git a/SEL32/sel32_com.c b/SEL32/sel32_com.c index d129c0f..2d34e03 100644 --- a/SEL32/sel32_com.c +++ b/SEL32/sel32_com.c @@ -96,10 +96,10 @@ TMXR com_desc = { COM_LINES_DFLT, 0, 0, com_ldsc }; /* com descr */ /* Status held in u3 */ /* controller/unit address in upper 16 bits */ -#define COM_INPUT 0x100 /* Input ready for unit */ -#define COM_CR 0x200 /* Output at beginning of line */ -#define COM_REQ 0x400 /* Request key pressed */ -#define COM_EKO 0x800 /* Echo input character */ +#define COM_INPUT 0x0100 /* Input ready for unit */ +#define COM_CR 0x0200 /* Output at beginning of line */ +#define COM_REQ 0x0400 /* Request key pressed */ +#define COM_EKO 0x0800 /* Echo input character */ #define COM_OUTPUT 0x1000 /* Output ready for unit */ #define COM_READ 0x2000 /* Read mode selected */ @@ -193,7 +193,7 @@ TMXR com_desc = { COM_LINES_DFLT, 0, 0, com_ldsc }; /* com descr */ /* u6 */ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); -uint8 com_haltio(uint16 addr); +uint8 com_haltio(UNIT *uptr); void com_ini(UNIT *, t_bool); void coml_ini(UNIT *, t_bool); t_stat com_reset(DEVICE *); @@ -260,7 +260,7 @@ DIB com_dib = { com_unit, /* UNIT* units */ /* Pointer to units structure */ com_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ COM_UNITS, /* uint8 numunits */ /* number of units defined */ - 0x0f, /* uint8 mask */ /* 16 devices - device mask */ + 0xFF, /* uint8 mask */ /* 16 devices - device mask */ 0x7E00, /* uint16 chan_addr */ /* parent channel address */ 0, /* uint32 chan_fifo_in */ /* fifo input index */ 0, /* uint32 chan_fifo_out */ /* fifo output index */ @@ -282,6 +282,7 @@ DEVICE com_dev = { "COMC", com_unit, com_reg, com_mod, COM_UNITS, 8, 15, 1, 8, 8, &tmxr_ex, &tmxr_dep, &com_reset, NULL, &com_attach, &com_detach, + /* ctxt is the DIB pointer */ &com_dib, DEV_NET | DEV_DISABLE | DEV_DEBUG, 0, dev_debug, NULL, NULL, NULL, NULL, NULL, &com_description }; @@ -330,7 +331,7 @@ DIB coml_dib = { coml_unit, /* UNIT* units */ /* Pointer to units structure */ coml_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ COM_LINES*2, /* uint8 numunits */ /* number of units defined */ - 0x0f, /* uint8 mask */ /* 16 devices - device mask */ + 0xff, /* uint8 mask */ /* 16 devices - device mask */ 0x7E00, /* uint16 chan_addr */ /* parent channel address */ }; @@ -358,6 +359,7 @@ DEVICE coml_dev = { COM_LINES*2, 10, 31, 1, 8, 8, NULL, NULL, &com_reset, NULL, NULL, NULL, + /* ctxt is the DIB pointer */ &coml_dib, DEV_DISABLE | DEV_DEBUG, 0, dev_debug, NULL, NULL, NULL, NULL, NULL, &com_description }; @@ -380,7 +382,7 @@ void com_ini(UNIT *uptr, t_bool f) { DEVICE *dptr = get_dev(uptr); - sim_debug(DEBUG_CMD, &com_dev, "COM init device %s controller 0x7e00\n", dptr->name); + sim_debug(DEBUG_CMD, dptr, "COM init device %s controller 0x7e00\n", dptr->name); sim_activate(uptr, 1000); /* time increment */ } @@ -395,12 +397,12 @@ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) return SNS_BSY; /* yes, return busy */ } - sim_debug(DEBUG_CMD, &com_dev, "CMD unit %04x chan %04x cmd %02x", unit, chan, cmd); + sim_debug(DEBUG_CMD, dptr, "CMD unit %04x chan %04x cmd %02x\n", unit, chan, cmd); /* process the commands */ switch (cmd & 0xFF) { case COM_INCH: /* 00 */ /* INCH command */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: CMD INCH\n", chan); + sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: CMD INCH\n", chan); uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (0x7f & COM_MSK); /* save 0x7f as INCH cmd command */ uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ @@ -412,7 +414,7 @@ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) case COM_WR: /* 0x01 */ /* Write command */ case COM_WRSCM: /* 0x05 */ /* Write w/sub channel monitor */ case COM_WRHFC: /* 0x0D */ /* Write w/hardware flow control */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd WRITE %02x\n", chan, cmd); + sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd WRITE %02x\n", chan, cmd); uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (cmd & COM_MSK); /* save command */ @@ -434,19 +436,20 @@ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) /* if bit 0 set for COM_RDFC, use DTR for flow, else use RTS for flow control */ case COM_RDFC: /* 0x0A */ /* Read command w/flow control */ case COM_RDHFC: /* 0x8E */ /* Read command w/hardware flow control only */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd read\n", chan); + sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd read\n", chan); uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (cmd & COM_MSK); /* save command */ if ((cmd & 0x06) == COM_RDECHO) /* echo command? */ uptr->u3 |= COM_EKO; /* save echo status */ uptr->u3 |= COM_READ; /* show read mode */ uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: input cnt = %04x\n", chan, coml_chp[unit].ccw_count); + sim_debug(DEBUG_CMD, dptr, + "com_startcmd %04x: input cnt = %04x\n", chan, coml_chp[unit].ccw_count); return 0; break; case COM_NOP: /* 0x03 */ /* NOP has do nothing */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd %02x NOP\n", chan, cmd); + sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x NOP\n", chan, cmd); uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (cmd & COM_MSK); /* save command */ @@ -459,7 +462,8 @@ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) com_lstat[unit][1] = 0; /* Clear status wd 1 */ /* value 4 is Data Set Ready */ /* value 5 is Data carrier detected n/u */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: unit %04x Cmd Sense %02x\n", chan, unit, uptr->u5); + sim_debug(DEBUG_CMD, dptr, + "com_startcmd %04x: unit %04x Cmd Sense %02x\n", chan, unit, uptr->u5); /* Sense byte 0 */ //#define SNS_CMDREJ 0x80000000 /* Command reject */ //#define SNS_INTVENT 0x40000000 /* Unit intervention required (N/U) */ @@ -522,51 +526,54 @@ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ ch = (com_lstat[unit][1] >> 0) & 0xff; chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ - sim_debug(DEBUG_CMD, &com_dev, + sim_debug(DEBUG_CMD, dptr, "com_startcmd Cmd SENSE return chan %04x u5-status %04x ls0 %08x ls1 %08x\n", chan, uptr->u5, com_lstat[unit][0], com_lstat[unit][1]); return SNS_CHNEND|SNS_DEVEND; /* good return */ break; case COM_DEFSC: /* 0x0B */ /* Define special char */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd %02x DEFSC\n", chan, cmd); - chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char */ + sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x DEFSC\n", chan, cmd); + if (chan_read_byte(GET_UADDR(uptr->u3), &ch)) { /* read char from memory */ + /* nothing to read, error */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* good return */ + } uptr->u5 = ~SNS_RTS; /* Request to send not ready */ return SNS_CHNEND|SNS_DEVEND; /* good return */ break; case COM_RRTS: /* 0x1B */ /* Reset RTS */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd %02x RRTS\n", chan, cmd); + sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x RRTS\n", chan, cmd); uptr->u5 &= ~SNS_RTS; /* Request to send not ready */ return SNS_CHNEND|SNS_DEVEND; /* good return */ break; case COM_SRTS: /* 0x1F */ /* Set RTS */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd %02x SRTS\n", chan, cmd); + sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x SRTS\n", chan, cmd); uptr->u5 |= SNS_RTS; /* Requestd to send ready */ return SNS_CHNEND|SNS_DEVEND; /* good return */ break; case COM_RBRK: /* 0x33 */ /* Reset BREAK */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd %02x RBRK\n", chan, cmd); + sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x RBRK\n", chan, cmd); uptr->u5 &= ~SNS_BREAK; /* Request to send not ready */ return SNS_CHNEND|SNS_DEVEND; /* good return */ break; case COM_SBRK: /* 0x37 */ /* Set BREAK */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd %02x SBRK\n", chan, cmd); + sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x SBRK\n", chan, cmd); uptr->u5 |= SNS_BREAK; /* Requestd to send ready */ return SNS_CHNEND|SNS_DEVEND; /* good return */ break; case COM_RDTR: /* 0x13 */ /* Reset DTR (ADVR) */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd %02x DTR\n", chan, cmd); + sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x RDTR\n", chan, cmd); uptr->u5 &= ~SNS_DTR; /* Data terminal not ready */ return SNS_CHNEND|SNS_DEVEND; /* good return */ break; case COM_SDTR: /* 0x17 */ /* Set DTR (ADVF) */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd %02x NOP\n", chan, cmd); + sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x SDTR\n", chan, cmd); uptr->u5 |= SNS_DTR; /* Data terminal ready */ return SNS_CHNEND|SNS_DEVEND; /* good return */ break; @@ -611,21 +618,38 @@ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) #endif case COM_SACE: /* 0xff */ /* Set ACE parameters (3 chars) */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd %02x SACE\n", chan, cmd); - chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char 0 */ + sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x SACE\n", chan, cmd); + if (chan_read_byte(GET_UADDR(uptr->u3), &ch)) { /* read char 0 */ + /* nothing to read, error */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* good return */ + } uptr->u4 = ((uint32)ch)<<24; /* byte 0 of ACE data */ - chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char 1 */ + if (chan_read_byte(GET_UADDR(uptr->u3), &ch)) { /* read char 1 */ + /* nothing to read, error */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* good return */ + } uptr->u4 |= ((uint32)ch)<<16; /* byte 1 of ACE data */ - chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char 2 */ + if (chan_read_byte(GET_UADDR(uptr->u3), &ch)) { /* read char 2 */ + /* nothing to read, error */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* good return */ + } uptr->u4 |= ((uint32)ch)<<8; /* byte 2 of ACE data */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd %02x ACE bytes %08x\n", + sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x ACE bytes %08x\n", chan, cmd, uptr->u4); +#ifdef USE_INTERUPT + uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ + uptr->u3 &= LMASK; /* leave only chsa */ + uptr->u3 |= (cmd & COM_MSK); /* save command */ + sim_activate(uptr, 20); /* start us up */ +#else return SNS_CHNEND|SNS_DEVEND; /* good return */ +#endif break; + default: /* invalid command */ uptr->u5 |= SNS_CMDREJ; /* command rejected */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd Invald %02x status %02x\n", + sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd Invald %02x status %02x\n", chan, cmd, uptr->u5); return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ break; @@ -643,23 +667,33 @@ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) t_stat comi_srv(UNIT *uptr) { uint8 ch; + DEVICE *dptr = get_dev(uptr); int32 newln, ln, c; uint16 chsa = GET_UADDR(uptr->u3); /* get channel/sub-addr */ int cmd = uptr->u3 & 0xff; // uint32 cln = (uptr - coml_unit) & 0x7; /* use line # 0-7 for 8-15 */ ln = uptr - com_unit; /* line # */ - sim_debug(DEBUG_CMD, &com_dev, "comi_srv entry chsa %04x line %04x cmd %02x\n", chsa, ln, cmd); /* handle NOP and INCH cmds */ - sim_debug(DEBUG_CMD, &com_dev, "comi_srv entry chsa %04x line %04x cmd %02x\n", chsa, ln, cmd); + sim_debug(DEBUG_CMD, dptr, "comi_srv entry chsa %04x line %02x cmd %02x\n", chsa, ln, cmd); if (cmd == COM_NOP || cmd == 0x7f) { /* check for NOP or INCH */ uptr->u3 &= LMASK; /* leave only chsa */ - sim_debug(DEBUG_CMD, &com_dev, "comi_srv NOP or INCH done chsa %04x line %04x cmd %02x\n", + sim_debug(DEBUG_CMD, dptr, "comi_srv NOP or INCH done chsa %04x line %02x cmd %02x\n", chsa, ln, cmd); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ return SCPE_OK; /* return */ } + /* handle SACE, 3 char alread read, so we are done */ + if (cmd == COM_SACE) { /* check for SACE 0xff */ + uptr->u3 &= LMASK; /* leave only chsa */ + sim_debug(DEBUG_CMD, &com_dev, + "comi_srv SACE done chsa %04x line %02x cmd %02x ACE %08x\n", + chsa, ln, cmd, uptr->u4); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ + return SCPE_OK; /* return */ + } + ln = uptr - com_unit; /* line # */ if ((com_unit[COMC].flags & UNIT_ATT) == 0){ /* attached? */ return SCPE_OK; @@ -740,6 +774,7 @@ t_stat comi_srv(UNIT *uptr) /* Unit service - output transfers */ t_stat como_srv(UNIT *uptr) { + DEVICE *dptr = get_dev(uptr); uint16 chsa = GET_UADDR(uptr->u3); /* get channel/sub-addr */ uint32 ln = (uptr - coml_unit) & 0x7; /* use line # 0-7 for 8-15 */ uint32 done; @@ -747,7 +782,7 @@ t_stat como_srv(UNIT *uptr) uint8 ch; /* handle NOP and INCH cmds */ - sim_debug(DEBUG_CMD, &com_dev, "como_srv entry chsa %04x line %04x cmd %02x\n", chsa, ln, cmd); + sim_debug(DEBUG_CMD, dptr, "como_srv entry chsa %04x line %04x cmd %02x\n", chsa, ln, cmd); if (cmd == COM_NOP || cmd == 0x7f) { /* check for NOP or INCH */ uptr->u3 &= LMASK; /* leave only chsa */ sim_debug(DEBUG_CMD, &com_dev, "como_srv NOP or INCH done chsa %04x line %04x cmd %02x\n", @@ -756,7 +791,17 @@ t_stat como_srv(UNIT *uptr) return SCPE_OK; /* return */ } - sim_debug(DEBUG_CMD, &com_dev, "como_srv entry 1 chsa %04x line %04x cmd %02x\n", chsa, ln, cmd); + /* handle SACE, 3 char already read, so we are done */ + if (cmd == COM_SACE) { /* check for SACE 0xff */ + uptr->u3 &= LMASK; /* leave only chsa */ + sim_debug(DEBUG_CMD, &com_dev, + "como_srv SACE done chsa %04x line %02x cmd %02x ACE %08x\n", + chsa, ln, cmd, uptr->u4); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ + return SCPE_OK; /* return */ + } + + sim_debug(DEBUG_CMD, dptr, "como_srv entry 1 chsa %04x line %04x cmd %02x\n", chsa, ln, cmd); if (cmd) { /* get a user byte from memory */ done = chan_read_byte(chsa, &ch); /* get byte from memory */ @@ -766,28 +811,28 @@ t_stat como_srv(UNIT *uptr) return SCPE_OK; if (com_dev.flags & DEV_DIS) { /* disabled */ - sim_debug(DEBUG_CMD, &com_dev, "como_srv chsa %04x line %04x DEV_DIS set\n", chsa, ln); + sim_debug(DEBUG_CMD, dptr, "como_srv chsa %04x line %04x DEV_DIS set\n", chsa, ln); if (done) { - sim_debug(DEBUG_CMD, &com_dev, "como_srv Write DONE %04x status %04x\n", + sim_debug(DEBUG_CMD, dptr, "como_srv Write DONE %04x status %04x\n", ln, SNS_CHNEND|SNS_DEVEND); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ } return SCPE_OK; /* return */ } - sim_debug(DEBUG_CMD, &com_dev, "como_srv poll chsa %04x line %04x DEV_DIS set\n", chsa, ln); + sim_debug(DEBUG_CMD, dptr, "como_srv poll chsa %04x line %04x DEV_DIS set\n", chsa, ln); if (com_ldsc[ln].conn) { /* connected? */ if (com_ldsc[ln].xmte) { /* xmt enabled? */ if (done) { /* are we done writing */ endit: uptr->u3 &= LMASK; /* nothing left, command complete */ - sim_debug(DEBUG_CMD, &com_dev, "com_srvo write %04x: chnend|devend\n", ln); + sim_debug(DEBUG_CMD, dptr, "com_srvo write %04x: chnend|devend\n", ln); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ return SCPE_OK; } /* send the next char out */ tmxr_putc_ln(&com_ldsc[ln], ch); /* output char */ - sim_debug(DEBUG_CMD, &com_dev, "com_srvo writing char 0x%02x to ln %04x\n", ch, ln); + sim_debug(DEBUG_CMD, dptr, "com_srvo writing char 0x%02x to ln %04x\n", ch, ln); tmxr_poll_tx(&com_desc); /* poll xmt */ sim_activate(uptr, uptr->wait); /* wait */ return SCPE_OK; @@ -796,7 +841,7 @@ endit: goto endit; /* done */ /* just dump the char */ // /* xmt disabled, just wait around */ - sim_debug(DEBUG_CMD, &com_dev, "com_srvo write dumping char 0x%02x on line %04x\n", ch, ln); + sim_debug(DEBUG_CMD, dptr, "com_srvo write dumping char 0x%02x on line %04x\n", ch, ln); tmxr_poll_tx(&com_desc); /* poll xmt */ //?? sim_activate(uptr, coml_unit[ln].wait); /* wait */ sim_activate(uptr, uptr->wait); /* wait */ @@ -805,10 +850,10 @@ endit: } else { /* not connected, so dump char on ground */ if (done) { - sim_debug(DEBUG_CMD, &com_dev, "com_srvo write dump DONE line %04x status %04x\n", + sim_debug(DEBUG_CMD, dptr, "com_srvo write dump DONE line %04x status %04x\n", ln, SNS_CHNEND|SNS_DEVEND); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ uptr->u3 &= LMASK; /* nothing left, command complete */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ } sim_activate(uptr, uptr->wait); /* wait */ return SCPE_OK; @@ -837,14 +882,16 @@ t_stat com_reset (DEVICE *dptr) /* attach master unit */ t_stat com_attach(UNIT *uptr, CONST char *cptr) { - uint16 chsa = GET_UADDR(com_unit[COMC].u3); /* get channel/subaddress */ - t_stat r; + DEVICE *dptr = get_dev(uptr); +// uint16 chsa = GET_UADDR(com_unit[COMC].u3); /* get channel/subaddress */ +// uint16 chsa = GET_UADDR(uptr->u3); /* get channel/subaddress */ + t_stat r; - chsa = GET_UADDR(com_unit[COMC].u3); /* get channel/subaddress */ +// chsa = GET_UADDR(com_unit[COMC].u3); /* get channel/subaddress */ r = tmxr_attach(&com_desc, uptr, cptr); /* attach */ if (r != SCPE_OK) /* error? */ return r; /* return error */ - sim_debug(DEBUG_CMD, &com_dev, "com_srv com is now attached chsa %04x\n", chsa); + sim_debug(DEBUG_CMD, dptr, "com_srv comc is now attached\n"); sim_activate(uptr, 0); /* start poll at once */ return SCPE_OK; } diff --git a/SEL32/sel32_con.c b/SEL32/sel32_con.c index 967f61a..002a12e 100644 --- a/SEL32/sel32_con.c +++ b/SEL32/sel32_con.c @@ -163,7 +163,7 @@ void con_ini(UNIT *uptr, t_bool f) { int unit = (uptr - con_unit); /* unit 0 */ // DEVICE *dptr = get_dev(uptr); - uptr->u4 = 0; /* no input cpunt */ + uptr->u4 = 0; /* no input count */ con_data[unit].incnt = 0; /* no input data */ // con_data[0].incnt = 0; /* no input data */ // con_data[1].incnt = 0; /* no output data */ @@ -208,7 +208,6 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uptr->CMD |= CON_INCH2; /* save INCH command as 0xf0 */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ sim_activate(uptr, 20); /* start us off */ -//WAS sim_activate(uptr, 10); /* start us off */ return 0; /* no status change */ break; @@ -219,7 +218,6 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uptr->CMD |= (cmd & CON_MSK); /* save command */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ sim_activate(uptr, 20); /* start us off */ -//TRIED sim_activate(uptr, 10); /* start us off */ return 0; /* no status change */ break; @@ -245,7 +243,7 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uptr->CMD |= (cmd & CON_MSK); /* save command */ // uptr->u4 = 0; /* no I/O yet */ // con_data[unit].incnt = 0; /* clear any input data */ - sim_activate(uptr, 10); /* start us off */ + sim_activate(uptr, 20); /* start us off */ return 0; /* no status change */ break; @@ -254,7 +252,7 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ uptr->CMD &= LMASK; /* leave only chsa */ uptr->CMD |= (cmd & CON_MSK); /* save command */ - sim_activate(uptr, 10); /* start us off */ + sim_activate(uptr, 20); /* start us off */ return 0; /* no status change */ break; #endif @@ -282,19 +280,16 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { break; default: /* invalid command */ - uptr->SNS |= SNS_CMDREJ; /* command rejected */ -// uptr->u4 = 0; /* no I/O yet */ -// con_data[unit].incnt = 0; /* clear any input data */ - sim_debug(DEBUG_CMD, &con_dev, - "con_startcmd %04x: Invalid command %02x Sense %02x\n", - chan, cmd, uptr->SNS); - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ break; } - - if (uptr->SNS & (~(SNS_RDY|SNS_ONLN|SNS_DSR))) - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - return SNS_CHNEND|SNS_DEVEND; + /* invalid command */ + uptr->SNS |= SNS_CMDREJ; /* command rejected */ +// uptr->u4 = 0; /* no I/O yet */ +// con_data[unit].incnt = 0; /* clear any input data */ + sim_debug(DEBUG_CMD, &con_dev, + "con_startcmd %04x: Invalid command %02x Sense %02x\n", + chan, cmd, uptr->SNS); + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ } /* Handle output transfers for console */ @@ -317,7 +312,6 @@ t_stat con_srvo(UNIT *uptr) { uptr->CMD &= LMASK; /* nothing left, command complete */ sim_debug(DEBUG_CMD, &con_dev, "con_srvo Read to output device chsa %04x cmd = %02x\n", chsa, cmd); -//DIAG_TUE chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* unit check */ chan_end(chsa, SNS_CHNEND|SNS_UNITCHK); /* unit check */ return SCPE_OK; } @@ -401,9 +395,8 @@ t_stat con_srvi(UNIT *uptr) { uptr->CMD &= LMASK; /* nothing left, command complete */ sim_debug(DEBUG_CMD, &con_dev, "con_srvi Write to input device chsa %04x cmd = %02x\n", chsa, cmd); -//DIAGTUE chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* unit check */ chan_end(chsa, SNS_CHNEND|SNS_UNITCHK); /* unit check */ -//fall thru return SCPE_OK; + // fall thru return SCPE_OK; } } #ifdef JUNK diff --git a/SEL32/sel32_cpu.c b/SEL32/sel32_cpu.c index 7b6710b..2224888 100644 --- a/SEL32/sel32_cpu.c +++ b/SEL32/sel32_cpu.c @@ -172,7 +172,7 @@ uint32 BR[8]; /* Base registers */ uint32 PC; /* Program counter */ uint32 CC; /* Condition codes, bits 1-4 of PSD1 */ uint32 SPAD[256]; /* Scratch pad memory */ -uint32 INTS[128]; /* Interrupt status flags */ +uint32 INTS[112]; /* Interrupt status flags */ uint32 CPUSTATUS; /* cpu status word */ uint32 TRAPSTATUS; /* trap status word */ uint32 CMCR; /* Cache Memory Control Register */ @@ -689,7 +689,7 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) uint32 MAXMAP = MAX2048; /* default to 2048 maps */ sim_debug(DEBUG_CMD, &cpu_dev, - "Load Maps Entry PSD %08x %08x STATUS %08x lmap %01x CPU Type %2x\n", + "Load Maps Entry PSD %08x %08x STATUS %08x lmap %01x CPU Mode %2x\n", thepsd[0], thepsd[1], CPUSTATUS, lmap, CPU_MODEL); /* process 32/7X computers */ @@ -887,19 +887,19 @@ npmem: BPIX = 0; /* no os maps loaded */ CPIXPL = 0; /* no user pages */ CPIX = cpix; /* save user CPIX */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { TRAPSTATUS |= BIT1; /* set bit 1 of trap status */ - else - TRAPSTATUS |= BIT8; /* set bit 8 of trap status */ + } else + TRAPSTATUS |= BIT10; /* set bit 8 of trap status */ return NPMEM; /* non present memory error */ } /* output O/S and User MPX entries */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "#MEMORY %06x MPL %06x MPL[0] %08x %06x MPL[%04x] %08x %06x\n", MEMSIZE*4, mpl, RMW(mpl), RMW(mpl+4), cpix, RMW(cpix+mpl), RMW(cpix+mpl+4)); - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "MEMORY2 %06x BPIX %04x cpix %04x CPIX %04x CPIXPL %04x HIWM %04x\n", MEMSIZE*4, BPIX, cpix, CPIX, CPIXPL, HIWM); @@ -1068,9 +1068,9 @@ loaduser: sim_debug(DEBUG_TRAP, &cpu_dev, "load_maps MEM SIZE4 %06x user page list address %06x invalid\n", MEMSIZE*4, msdl); - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { TRAPSTATUS |= BIT1; /* set bit 1 of trap status */ - else + } else TRAPSTATUS |= BIT28; /* set bit 28 of trap status */ return NPMEM; /* non present memory error */ } @@ -1101,7 +1101,7 @@ loaduser: if ((CPU_MODEL == MODEL_27) || (CPU_MODEL == MODEL_87)) { sim_debug(DEBUG_CMD, &cpu_dev, - "load_maps Processing 32/27 & 32/87 Model# %04x\n", CPU_MODEL); + "load_maps Processing 32/27 & 32/87 Model# %02x\n", CPU_MODEL); /* handle non virtual page loading or diag LMAP instruction */ /* do 32/27 and 32/87 that force load all maps */ @@ -1296,9 +1296,9 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) if (word >= (MEMSIZE*4)) { /* see if address is within our memory */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { if (access == MEM_RD) - TRAPSTATUS |= 0x40000000; /* set bit 1 of trap status */ + TRAPSTATUS |= BIT1; /* set bit 1 of trap status */ if (access == MEM_WR) - TRAPSTATUS |= 0x20000000; /* set bit 2 of trap status */ + TRAPSTATUS |= BIT2; /* set bit 2 of trap status */ } else { TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ } @@ -1333,6 +1333,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { // V9 & 32/97 wants MACHINECHK for test 37/1 in CN.MMM & VM.MMM */ TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ + TRAPSTATUS |= BIT28; /* set bit 28 of trap status */ return MACHINECHK_TRAP; /* diags want machine check error */ } } @@ -1398,7 +1399,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) if ((BIT1 >> offset) & raddr) { /* is 1/4 page write protected */ *prot = 1; /* return memory write protection status */ } - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "RealAddrRa address %08x, TLB %08x MAPC[%03x] %08x wprot %02x prot %02x\n", word, TLB[index], index/2, MAPC[index/2], (word>>11)&3, *prot); return ALLOK; /* all OK, return instruction */ @@ -1419,16 +1420,23 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) "RealAddr loadmap 2a non present memory fault addr %08x raddr %08x index %04x\n", addr, raddr, index); if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { +#ifndef TRY_AGAIN if (access == MEM_RD) TRAPSTATUS |= BIT1; /* set bit 1 of trap status */ else if (access == MEM_WR) TRAPSTATUS |= BIT2; /* set bit 2 of trap status */ - /* returning this error fails test 34/2 of mmm diag */ -/*NEW*/// return MAPFLT; /* map fault error on memory access */ -/*NEW*/// return MACHINECHK_TRAP; /* diags want machine check error */ /* returning this error fixes 34/2, but still fails 46/2 */ return NPMEM; /* none present memory error */ +#else + TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ + TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ + /* returning this error fails test 34/2 of mmm diag */ + return MAPFLT; /* map fault error on memory access */ +#endif +/*NEW*/// return MAPFLT; /* map fault error on memory access */ + /* returning this error fails test 34/2 of mmm diag */ +/*NEW*/// return MACHINECHK_TRAP; /* diags want machine check error */ } else TRAPSTATUS |= BIT28; /* set bit 28 of trap status */ return NPMEM; /* none present memory error */ @@ -1449,7 +1457,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) if ((BIT1 >> offset) & raddr) { /* is 1/4 page write protected */ *prot = 1; /* return memory write protection status */ } - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "RealAddrR address %08x, TLB %08x MAPC[%03x] %08x wprot %02x prot %02x\n", word, TLB[index], index/2, MAPC[index/2], (word>>11)&3, *prot); return ALLOK; /* all OK, return instruction */ @@ -1463,9 +1471,6 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) else *prot = offset; /* return memory write protection status */ -// if (addr != word) -//sim_debug(DEBUG_EXP, &cpu_dev, -//"At RealAddr Hit convert %06x to addr %08x\n", addr, word); sim_debug(DEBUG_DETAIL, &cpu_dev, "RealAddrX address %06x, TLB %06x MAPC[%03x] %08x wprot %02x prot %02x\n", word, TLB[index], index/2, MAPC[index/2], (word>>11)&3, *prot); @@ -1473,7 +1478,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) } /* Hit bit is off in TLB, so lets go get some maps */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "$MEMORY %06x HIT MPL %06x MPL[0] %08x %06x MPL[%04x] %08x %06x\n", MEMSIZE*4, mpl, RMW(mpl), RMW(mpl+4), CPIX, RMW(CPIX+mpl), RMW(CPIX+mpl+4)); @@ -1481,7 +1486,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) msdl = RMW(mpl+CPIX+4); /* get msdl entry for given CPIX */ if ((msdl & MASK24) >= (MEMSIZE*4)) { /* check user midl */ sim_debug(DEBUG_TRAP, &cpu_dev, - "RealAddr Non Present Memory User msdl %06x CPIX %04x\n", + "RealAddr User CPIX Non Present Memory User msdl %06x CPIX %04x\n", msdl, CPIX); if (CPU_MODEL == MODEL_67) { @@ -1550,7 +1555,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) else mix = nix-BPIX; /* get map index in memory */ map = RMH(msdl+(mix<<1)); /* map content from memory */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "Addr %06x RealAddr %06x Map0[%04x] HIT %04x TLB[%3x] %08x MAPC[%03x] %08x\n", addr, word, mix, map, nix, TLB[nix], nix/2, MAPC[nix/2]); @@ -1558,10 +1563,6 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) if ((map & 0x8000) == 0) { /* for V6 & V9 handle demand paging */ if (CPU_MODEL >= MODEL_V6) { -#ifdef DO_DYNAMIC_DEBUG - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif /* map is not valid, so we have map fault */ sim_debug(DEBUG_TRAP, &cpu_dev, "AddrMa %06x RealAddr %06x Map0 HIT %04x, TLB[%3x] %08x MAPC[%03x] %08x\n", @@ -1589,24 +1590,16 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) TLB[nix] = ((map & 0x7ff) << 13) | ((map << 16) & 0xf8000000) | 0x04000000; word = (TLB[nix] & 0xffe000) | offset; /* combine map and offset */ WMR((nix<<1), map); /* store the map reg contents into MAPC cache */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "RealAddrm RMH %04x mix %04x TLB[%04x] %08x B+C %04x RMR[nix] %04x\n", map, mix, nix, TLB[nix], BPIX+CPIXPL, RMR(nix<<1)); - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "Addr1c %06x RealAddr %06x Map1[%04x] HIT %04x, TLB[%3x] %08x MAPC[%03x] %08x RMR %04x\n", addr, word, mix, map, nix, TLB[nix], nix/2, MAPC[nix/2], RMR(nix<<1)); -#ifdef DO_DYNAMIC_DEBUG -/* start debugging */ - if(word == 0x27000) -cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_XIO); -#endif *realaddr = word; /* return the real address */ raddr = TLB[nix]; /* get the base address & bits */ -// if (addr != word) -//sim_debug(DEBUG_EXP, &cpu_dev, -//"At RealAddr Miss convert %06x to addr %08x\n", addr, word); if ((CPU_MODEL == MODEL_67) || (CPU_MODEL == MODEL_97)) { /* get protection status of map */ @@ -1644,13 +1637,13 @@ cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_XIO); nix -= 1; /* point to last map in MAPC */ } - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "RealAddrp mix %04x nix %04x TLB[%04x] %08x B+C %04x RMR[nix] %04x\n", mix, nix, nix, TLB[nix], BPIX+CPIXPL, RMR(nix<<1)); /* allow the excess map entry to be loaded, even though bad */ if (nix <= (BPIX+CPIXPL)) { /* needs to be a mapped reg */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "Addr1d BPIX %03x CPIXPL %03x RealAddr %06x TLB[%3x] %08x MAPC[%03x] %08x RMR %04x\n", BPIX, CPIXPL, word, nix, TLB[nix], nix/2, MAPC[nix/2], RMR(nix<<1)); @@ -1660,7 +1653,7 @@ cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_XIO); /* allow the excess map entry to be loaded, even though bad */ if (nix <= (BPIX+CPIXPL)) { /* needs to be a mapped reg */ map = RMH(msdl+(mix<<1)); /* map content from memory */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "Addr2a %06x MapX[%04x] HIT %04x, TLB[%3x] %08x MAPC[%03x] %08x\n", addr, mix, map, nix, TLB[nix], nix/2, MAPC[nix/2]); @@ -1669,7 +1662,7 @@ cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_XIO); TLB[nix] = ((map & 0x7ff) << 13) | ((map << 16) & 0xf8000000) | 0x04000000; word = (TLB[nix] & 0xffe000); /* combine map and offset */ WMR((nix<<1), map); /* store the map reg contents into MAPC cache */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "Addr2b %06x RealAddr %06x Map2[%04x] HIT %04x, TLB[%3x] %08x MAPC[%03x] %08x\n", addr, word, mix, map, nix, TLB[nix], nix/2, MAPC[nix/2]); } @@ -1784,14 +1777,14 @@ t_stat Mem_read(uint32 addr, uint32 *data) sim_debug(DEBUG_EXP, &cpu_dev, "Mem_read error addr %.8x realaddr %.8x data %.8x prot %02x status %04x\n", addr, realaddr, *data, prot, status); if (status == NPMEM) { /* operand nonpresent memory error */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { TRAPSTATUS |= BIT1; /* set bit 1 of trap status */ - else + } else TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ } if (status == MAPFLT) { if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT1; /* set bit 1 of trap status */ + TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ else TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ } @@ -1892,14 +1885,14 @@ t_stat Mem_write(uint32 addr, uint32 *data) "Mem_write error addr %.8x realaddr %.8x data %.8x prot %02x status %04x\n", addr, realaddr, *data, prot, status); if (status == NPMEM) { /* operand nonpresent memory error */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { TRAPSTATUS |= BIT2; /* set bit 2 of trap status */ - else + } else TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ } if (status == MAPFLT) { if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT2; /* set bit 2 of trap status */ + TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ else TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ } @@ -1999,10 +1992,10 @@ wait_loop: PSD1 &= ~1; /* clear bit 31, no lr */ drop_nop = 0; /* we dropped the nop */ } -redo: + if (skipinstr) { /* need to skip interrupt test? */ #ifdef NOTNOW - sim_debug(DEBUG_TRAP, &cpu_dev, + sim_debug(DEBUG_IRQ, &cpu_dev, "Skipinstr set to zero PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", PSD1, PSD2, CPUSTATUS); #endif @@ -2016,7 +2009,7 @@ redo: if (int_icb != 0) { /* was ICB returned for an I/O or interrupt */ int il = ilev; /* get the interrupt level */ sim_debug(DEBUG_IRQ, &cpu_dev, - "Normal int scan return icb %08x level %02x irq_pend %02x wait4int %02x\n", + "<>Normal int return icb %06x level %02x irq_pend %01x wait4int %01x\n", int_icb, il, irq_pend, wait4int); /* take interrupt, store the PSD, fetch new PSD */ @@ -2029,28 +2022,30 @@ redo: /* set new map mode and interrupt blocking state in CPUSTATUS */ modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */ - CPUSTATUS |= modes; /* not insert into CPUSTATUS */ + CPUSTATUS |= modes; /* now insert into CPUSTATUS */ if (PSD2 & MAPBIT) { - CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ + CPUSTATUS |= BIT8; /* set bit 8 of cpu status */ modes |= MAPMODE; /* set mapped mode */ } else CPUSTATUS &= 0xff7fffff; /* reset bit 8 of cpu status */ if ((PSD2 & 0x8000) == 0) { /* is it retain blocking state */ if (PSD2 & 0x4000) { /* no, is it set blocking state */ CPUSTATUS |= 0x80; /* yes, set blk state in cpu status bit 24 */ - t = SPAD[il+0x80]; /* get spad entry for interrupt */ + + /* This test fixed the hangs on terminal input for diags & UTX! */ +/*TRY*/ t = SPAD[il+0x80]; /* get spad entry for interrupt */ /* Class F I/O spec says to reset interrupt active if user's */ /* interrupt service routine runs with interrupts blocked */ -// if ((t & 0x0f000000) == 0x0f000000) { /* if class F clear interrupt */ +/*TRY*/ if ((t & 0x0f000000) == 0x0f000000) { /* if class F clear interrupt */ /* if this is F class I/O interrupt, clear the active level */ /* SPAD entries for interrupts begin at 0x80 */ INTS[il] &= ~INTS_ACT; /* deactivate specified int level */ SPAD[il+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ irq_pend = 1; /* scan for interrupts again */ sim_debug(DEBUG_IRQ, &cpu_dev, - "Auto-reset interrupt INTS[%02x] %08x SPAD[%03x] %08x\n", + "<>Auto-reset interrupt INTS[%02x] %08x SPAD[%03x] %08x\n", il, INTS[il], il+0x80, SPAD[il+0x80]); -// } +/*TRY*/ } } else CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ @@ -2062,20 +2057,25 @@ redo: SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ sim_debug(DEBUG_IRQ, &cpu_dev, - "Inter %03x OPSD1 %08x OPSD2 %08x NPSD1 %08x NPSD2 %08x\n", + "<>Int %03x OPSD1 %08x OPSD2 %08x NPSD1 %08x NPSD2 %08x\n", il, RMW(int_icb), RMW(int_icb+4), PSD1, PSD2); bc = RMW(int_icb+20) & 0xffffff; if (RMW(int_icb+16) == 0) sim_debug(DEBUG_IRQ, &cpu_dev, - "Inter2 %03x ICBA %06x IOCLA %06x\n", + "<>Int2 %03x ICBA %06x IOCLA %06x\n", il, int_icb, RMW(int_icb+16)); else sim_debug(DEBUG_IRQ, &cpu_dev, - "Inter2 %03x ICBA %06x IOCLA %06x STAT %08x SW1 %08x SW2 %08x\n", + "<>Int2 %03x ICBA %06x IOCLA %06x STAT %08x SW1 %08x SW2 %08x\n", il, int_icb, RMW(int_icb+16), RMW(int_icb+20), RMW(bc), RMW(bc+4)); wait4int = 0; /* wait is over for int */ irq_pend = 1; /* scan for interrupts again */ skipinstr = 1; /* skip next inter test after this instr */ +#ifdef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, + "Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + PSD1, PSD2, CPUSTATUS); +#endif goto skipi; /* skip int test */ } /* see if waiting at a wait instruction */ @@ -2094,7 +2094,7 @@ redo: PSD2 = M[4>>2]; /* PSD2 from location 4 */ modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */ - CPUSTATUS |= modes; /* not insert into CPUSTATUS */ + CPUSTATUS |= modes; /* now insert into CPUSTATUS */ sim_debug(DEBUG_IRQ, &cpu_dev, "Boot Loading PSD1 %.8x PSD2 %.8x\n", PSD1, PSD2); /* set interrupt blocking state in CPUSTATUS */ CPUSTATUS |= 0x80; /* set blocked state in cpu status, bit 24 too */ @@ -2103,6 +2103,11 @@ redo: SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ loading = 0; /* we are done loading */ skipinstr = 1; /* skip next interrupt test only once */ +#ifdef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, + "Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + PSD1, PSD2, CPUSTATUS); +#endif } goto wait_loop; /* continue waiting */ } @@ -2121,12 +2126,17 @@ redo: attention_trap = 0; /* clear flag */ sim_debug(DEBUG_XIO, &cpu_dev, "Attention TRAP %04x\n", TRAPME); skipinstr = 1; /* skip next interrupt test only once */ +#ifdef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, + "Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + PSD1, PSD2, CPUSTATUS); +#endif goto newpsd; /* got process trap */ } skipi: i_flags = 0; /* do not update pc if MF or NPM */ - skipinstr = 0; /* skip only once */ +//XXX skipinstr = 0; /* skip only once */ TRAPSTATUS = CPUSTATUS & 0x57; /* clear all trap status except cpu type */ /* fill IR from logical memory address */ @@ -2172,10 +2182,6 @@ skipi: if (IR == 0x00020000) { /* is this a NOP from rt hw? */ PSD1 = (PSD1 + 2) | (((PSD1 & 2) >> 1) & 1); /* skip this instruction */ // fprintf(stderr, "RIGHT HW skip NOP instr %x skip nop at %x\n", IR, PSD1); - if (skipinstr == 2) { /* last instr was lf hw and rt NOP, try ints again */ - skipinstr = 0; /* only test this once */ - goto redo; /* check for ints now */ - } skipinstr = 0; /* only test this once */ goto skipi; /* go read next instruction */ } @@ -2920,9 +2926,11 @@ exec: case 0xB: /* RPSWT */ /* Read Processor Status Word 2 (PSD2) */ if ((GPR[reg] & 0x80000000) && (CPU_MODEL < MODEL_V9)) { /* if bit 0 of reg set, return (default 0) CPU Configuration Word */ - sim_debug(DEBUG_CMD, &cpu_dev, +#ifdef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, "RPSWT READ CCW GPR[%x] %08x CCW %04x SPAD[0xf5] %08x PSD2 %08x CPUSTATUS %08x\n", reg, GPR[reg], CCW, SPAD[0xf5], PSD2, CPUSTATUS); +#endif dest = CCW; /* no cache or shared memory */ //NO WCS dest |= 0x0000c000; /* set SIM bit for DIAGS */ /* make sure bit 19 is zero saying IPU not present */ @@ -2940,31 +2948,39 @@ exec: CMSMC |= 0x00000200; /* bit 22, Access Protection ECO present */ CMSMC |= 0x00000010; /* CPU Firmware Version 1/Rev level 0 */ dest = CMSMC; /* return starus */ - sim_debug(DEBUG_CMD, &cpu_dev, +#ifdef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, "RPSWT READ Cache/Shadow CW GPR[%x] = %08x CMSMC %04x SPAD[0xf5] %x PSD2 %x\n", reg, GPR[reg], CMSMC, SPAD[0xf5], PSD2); +#endif } else if ((GPR[reg] & 0x40000000) && (CPU_MODEL == MODEL_V9)) { /* if bit 1 of reg set, return CPU Shadow Memory Configuration Word */ CSMCW = 0x00000000; /* no Shadow unit present */ - sim_debug(DEBUG_CMD, &cpu_dev, +#ifdef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, "RPSWT READ V9 CPU Shadow Memory CW GPR[%x] = %08x CSMCW %04x SPAD[0xf5] %x PSD2 %x\n", reg, GPR[reg], CSMCW, SPAD[0xf5], PSD2); +#endif dest = CSMCW; /* return starus */ } else if ((GPR[reg] & 0x20000000) && (CPU_MODEL == MODEL_V9)) { /* if bit 2 of reg set, return Cache Memory Configuration Word */ ISMCW = 0x00000000; /* no Shadow unit present */ - sim_debug(DEBUG_CMD, &cpu_dev, +#ifdef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, "RPSWT READ V9 IPU Shadow Memory CW GPR[%x] = %08x ISMCW %04x SPAD[0xf5] %x PSD2 %x\n", reg, GPR[reg], ISMCW, SPAD[0xf5], PSD2); +#endif dest = ISMCW; /* return starus */ } else if ((GPR[reg] & BIT0) == 0x00000000) { /* if bit 0 of reg not set, return PSD2 */ - sim_debug(DEBUG_CMD, &cpu_dev, +#ifdef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, "RPSWT READ PSW2 GPR[%x] %08x SPAD[0xf5] %08x PSD2 %08x CPUSTATUS %08x\n", reg, GPR[reg], SPAD[0xf5], PSD2, CPUSTATUS); +#endif /* make sure bit 49 (block state is current stat */ dest = SPAD[0xf5]; /* get PSD2 for user from SPAD 0xf5 */ dest &= ~0x0000c000; /* clear bits 48 & 49 */ @@ -4023,9 +4039,6 @@ skipit: break; } td = (t_int64)dest % (t_int64)source; /* remainder */ -// dbl = !(td >= 0); /* double reg is neg remainder */ -// dbl = ((t_int64)td < 0); /* double reg is neg remainder */ - dbl = (td < 0); /* double reg is neg remainder */ if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */ td = NEGATE32(td); /* dividend and remainder must be same sign */ dest = (t_int64)dest / (t_int64)source; /* now do the divide */ @@ -5906,9 +5919,10 @@ doovr2: goto newpsd; /* go execute the trap now */ } if ((TRAPME = Mem_read(addr, &temp))) { /* get PSD1 from memory */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ - else + TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ + } else TRAPSTATUS |= BIT18; /* set bit 18 of trap status */ goto newpsd; /* memory read error or map fault */ } @@ -5921,18 +5935,20 @@ doovr2: if (opr & 0x0200) { /* Was it LPSDCM? */ if ((TRAPME = Mem_read(addr+4, &temp2))) { /* get PSD2 from memory */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ - else + TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ + } else TRAPSTATUS |= BIT18; /* set bit 18 of trap status */ goto newpsd; /* memory read error or map fault */ } PSD2 = temp2; /* PSD2 access good, so save it */ } else { if ((TRAPME = Mem_read(addr+4, &temp2))) { /* get PSD2 from memory */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ - else + TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ + } else TRAPSTATUS |= BIT18; /* set bit 18 of trap status */ goto newpsd; /* memory read error or map fault */ } @@ -6025,7 +6041,7 @@ doovr2: PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "LPSDCM MAPS LOADED TRAPME = %02x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", TRAPME, PSD1, PSD2, CPUSTATUS); } @@ -6052,14 +6068,25 @@ doovr2: SPAD[0xf5] = ix; /* restore the current PSD2 to SPAD */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ irq_pend = reg; /* restore intr status */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ - else + TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ + } else TRAPSTATUS |= BIT18; /* set bit 18 of trap status */ goto newpsd; /* go process error */ } skipinstr = 1; /* do not allow intr on next instruction */ +#ifdef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, + "Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + PSD1, PSD2, CPUSTATUS); +#endif drop_nop = 0; /* nothing to drop */ +#ifdef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, + "LPSD(CM) Done PSD1 %08x PSD2 %08x CPUSTATUS %08x irq %01x\n", + PSD1, PSD2, CPUSTATUS, irq_pend); +#endif goto newpsd; /* load the new psd, or process error */ break; @@ -6128,6 +6155,8 @@ doovr2: // break; /* ignore */ if ((t & 0x0f000000) == 0x0f000000) /* if class F ignore instruction */ break; /* ignore for F class */ + + /* does not effect REQ status */ INTS[prior] |= INTS_ENAB; /* enable specified int level */ SPAD[prior+0x80] |= SINT_ENAB; /* enable in SPAD too */ irq_pend = 1; /* start scanning interrupts again */ @@ -6143,6 +6172,11 @@ doovr2: sim_debug(DEBUG_IRQ, &cpu_dev, "Intv Timer EI %02x Turn on\n", prior); itm_setup(1, prior); /* tell timer to start */ } +#ifndef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, + "EI lev %02x Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + prior, PSD1, PSD2, CPUSTATUS); +#endif break; case 0x1: /* DI FC01 */ @@ -6155,10 +6189,11 @@ doovr2: break; /* ignore */ if ((t & 0x0f000000) == 0x0f000000) /* if class F ignore instruction */ break; /* ignore for F class */ + /* active state is left alone */ INTS[prior] &= ~INTS_ENAB; /* disable specified int level */ - INTS[prior] &= ~INTS_REQ; /* clears any requests also */ SPAD[prior+0x80] &= ~SINT_ENAB; /* disable in SPAD too */ + INTS[prior] &= ~INTS_REQ; /* clears any requests also */ /* test for clock at address 0x7f06 and interrupt level 0x18 */ /* the diags want the type to be 0, others want 3, so ignore */ @@ -6171,6 +6206,11 @@ doovr2: itm_setup(0, prior); /* tell timer to stop */ sim_debug(DEBUG_IRQ, &cpu_dev, "Intv Timer DI %02x Turn off\n", prior); } +#ifndef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, + "DI lev %02x Skipinstr set to %01x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + prior, skipinstr, PSD1, PSD2, CPUSTATUS); +#endif break; case 0x2: /* RI FC02 */ @@ -6185,6 +6225,11 @@ doovr2: break; /* ignore for F class */ INTS[prior] |= INTS_REQ; /* set the request flag for this level */ irq_pend = 1; /* start scanning interrupts again */ +#ifndef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, + "RI lev %02x Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + prior, PSD1, PSD2, CPUSTATUS); +#endif break; case 0x3: /* AI FC03 */ @@ -6199,6 +6244,11 @@ doovr2: INTS[prior] |= INTS_ACT; /* activate specified int level */ SPAD[prior+0x80] |= SINT_ACT; /* activate in SPAD too */ irq_pend = 1; /* start scanning interrupts again */ +#ifndef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, + "AI lev %02x Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + prior, PSD1, PSD2, CPUSTATUS); +#endif break; case 0x4: /* DAI FC04 */ @@ -6217,6 +6267,11 @@ doovr2: /* instruction following a DAI can not be interrupted */ /* skip tests for interrupts if this is the case */ skipinstr = 1; /* skip interrupt test */ +#ifndef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, + "DAI lev %02x Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + prior, PSD1, PSD2, CPUSTATUS); +#endif drop_nop = 0; /* nothing to drop */ break; @@ -6503,15 +6558,17 @@ mcheck: /* SPAD entries for interrupts begin at 0x80 */ INTS[ix] &= ~INTS_ACT; /* deactivate specified int level */ SPAD[ix+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ - irq_pend = 1; /* start scanning interrupts again */ - skipinstr = 1; /* skip interrupt test */ if ((TRAPME = checkxio(chsa, &status))) goto newpsd; /* error returned, trap cpu */ - PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ -#ifdef DO_DYNAMIC_DEBUG - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); + irq_pend = 1; /* start scanning interrupts again */ + skipinstr = 1; /* skip interrupt test */ +#ifdef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, + "Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + PSD1, PSD2, CPUSTATUS); #endif +/*XXX*/ drop_nop = 0; /* nothing to drop */ + PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ break; } /* end of XIO switch */ break; diff --git a/SEL32/sel32_defs.h b/SEL32/sel32_defs.h index 4fe6ab9..b3afa5f 100644 --- a/SEL32/sel32_defs.h +++ b/SEL32/sel32_defs.h @@ -102,6 +102,8 @@ /* simulator devices configuration */ #define NUM_DEVS_IOP 1 /* 1 device IOP channel controller */ #define NUM_UNITS_IOP 1 /* 1 master IOP channel device */ +#define NUM_DEVS_MFP 1 /* 1 device MFP channel controller */ +#define NUM_UNITS_MFP 1 /* 1 master MFP channel device */ #define NUM_DEVS_COM 2 /* 8-Line async controller */ #define NUM_UNITS_COM 16 /* 8-Line async units */ #define NUM_DEVS_CON 1 /* 1 I/O console controller */ @@ -129,6 +131,9 @@ extern UNIT cpu_unit; /* the cpu unit */ #ifdef NUM_DEVS_IOP extern DEVICE iop_dev; /* IOP channel controller */ #endif +#ifdef NUM_DEVS_MFP +extern DEVICE mfp_dev; /* MFP channel controller */ +#endif #ifdef NUM_DEVS_RTOM extern DEVICE rtc_dev; /* RTOM rtc */ extern DEVICE itm_dev; /* RTOM itm */ diff --git a/SEL32/sel32_disk.c b/SEL32/sel32_disk.c index 25e241c..4e15544 100644 --- a/SEL32/sel32_disk.c +++ b/SEL32/sel32_disk.c @@ -25,7 +25,7 @@ extern t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); extern t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc); -extern void chan_end(uint16 chan, uint8 flags); +extern void chan_end(uint16 chsa, uint8 flags); extern int chan_read_byte(uint16 chsa, uint8 *data); extern int chan_write_byte(uint16 chsa, uint8 *data); extern void set_devattn(uint16 addr, uint8 flags); @@ -44,13 +44,13 @@ extern uint32 SPAD[]; /* cpu SPAD memory */ /* useful conversions */ /* Fill STAR value from cyl, trk, sec data */ -#define CHS2STAR(c,h,s) (((c<<16) & 0xffff0000)|((h<<8) & 0xff00)|(s & 0xff)) +#define CHS2STAR(c,h,s) (((c<<16) & LMASK)|((h<<8) & 0xff00)|(s & 0xff)) /* convert STAR value to number of sectors */ #define STAR2SEC(star,spt,spc) ((star&0xff)+(((star>>8)&0xff)*spt)+((star>>16)*spc)) /* convert STAR value to number of heads or tracks */ #define STAR2TRK(star,tpc) ((star >> 16) * tpc + ((star >> 8) & 0x0ff)) /* convert STAR value to number of cylinders */ -#define STAR2CYL(star) ((star >> 16) & 0xffff) +#define STAR2CYL(star) ((star >> 16) & RMASK) /* convert byte value to number of sectors mod sector size */ #define BYTES2SEC(bytes,ssize) (((bytes) + (ssize-1)) >> 10) /* get sectors per track for specified type */ @@ -144,7 +144,7 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option char ldatrfhdc; FHD head count */ -#define CMD u3 +#define CMDu3 u3 /* u3 */ /* in u3 is device command code and status */ #define DSK_CMDMSK 0x00ff /* Command being run */ @@ -254,7 +254,7 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option mini-module) */ -/* Not Used up7 */ +/* INCH addr up7 */ #ifdef NOUSED /* registers */ @@ -298,9 +298,9 @@ disk_type[] = uint8 disk_preio(UNIT *uptr, uint16 chan) ; uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; -uint8 disk_haltio(uint16 addr); -t_stat disk_srv(UNIT *); -t_stat disk_boot(int32, DEVICE *); +uint8 disk_haltio(UNIT *uptr); +t_stat disk_srv(UNIT *uptr); +t_stat disk_boot(int32 unitnum, DEVICE *dptr); void disk_ini(UNIT *, t_bool); t_stat disk_reset(DEVICE *); t_stat disk_attach(UNIT *, CONST char *); @@ -363,6 +363,7 @@ DEVICE dda_dev = { "DMA", dda_unit, NULL/*dda_reg*/, disk_mod, NUM_UNITS_DISK, 16, 24, 4, 16, 32, NULL, NULL, &disk_reset, &disk_boot, &disk_attach, &disk_detach, + /* ctxt is the DIB pointer */ &dda_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, NULL, NULL, &disk_help, NULL, NULL, &disk_description }; @@ -413,6 +414,7 @@ DEVICE ddb_dev = { "DMB", ddb_unit, NULL, /*ddb_reg*/, disk_mod, NUM_UNITS_DISK, 16, 24, 4, 16, 32, NULL, NULL, &disk_reset, &disk_boot, &disk_attach, &disk_detach, + /* ctxt is the DIB pointer */ &ddb_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, NULL, NULL, &disk_help, NULL, NULL, &disk_description }; @@ -434,11 +436,11 @@ uint32 disksec2star(uint32 daddr, int type) uint8 disk_preio(UNIT *uptr, uint16 chan) { DEVICE *dptr = get_dev(uptr); - uint16 chsa = GET_UADDR(uptr->CMD); + uint16 chsa = GET_UADDR(uptr->CMDu3); int unit = (uptr - dptr->units); - sim_debug(DEBUG_CMD, dptr, "disk_preio CMD %08x unit %02x\n", uptr->CMD, unit); - if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */ + sim_debug(DEBUG_CMD, dptr, "disk_preio CMD %08x unit %02x\n", uptr->CMDu3, unit); + if ((uptr->CMDu3 & 0xff00) != 0) { /* just return if busy */ return SNS_BSY; } @@ -448,25 +450,25 @@ uint8 disk_preio(UNIT *uptr, uint16 chan) uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { - uint16 chsa = GET_UADDR(uptr->CMD); + uint16 chsa = GET_UADDR(uptr->CMDu3); DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ sim_debug(DEBUG_CMD, dptr, "disk_startcmd chsa %04x unit %02x cmd %02x CMD %08x\n", - chsa, unit, cmd, uptr->CMD); + chsa, unit, cmd, uptr->CMDu3); if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ uptr->SNS |= SNS_INTVENT; /* unit intervention required */ if (cmd != DSK_SNS) /* we are completed with unit check status */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; } - if ((uptr->CMD & DSK_CMDMSK) != 0) { - uptr->CMD |= DSK_BUSY; /* Flag we are busy */ + if ((uptr->CMDu3 & DSK_CMDMSK) != 0) { + uptr->CMDu3 |= DSK_BUSY; /* Flag we are busy */ return SNS_BSY; } - if ((uptr->CMD & 0xff00) != 0) { /* if any status info, we are busy */ + if ((uptr->CMDu3 & 0xff00) != 0) { /* if any status info, we are busy */ return SNS_BSY; } sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD continue unit=%02x cmd %02x\n", unit, cmd); @@ -479,18 +481,18 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) "disk_startcmd starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n", uptr->u4, chsa, chp->ccw_addr, chp->ccw_count); - uptr->CMD |= DSK_INCH2; /* use 0xf0 for inch, just need int */ + uptr->CMDu3 |= DSK_INCH2; /* use 0xf0 for inch, just need int */ sim_activate(uptr, 20); /* start things off */ return 0; break; case DSK_SCK: /* Seek command 0x07 */ - case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ + case DSK_XEZ: /* Rezero & Read IPL record 0x37 */ case DSK_WD: /* Write command 0x01 */ case DSK_RD: /* Read command 0x02 */ - case DSK_LMR: /* read mode register */ + case DSK_LMR: /* read mode register 0x15 */ - uptr->CMD |= cmd; /* save cmd */ + uptr->CMDu3 |= cmd; /* save cmd */ sim_debug(DEBUG_CMD, dptr, "disk_startcmd starting disk seek r/w cmd %02x chsa %04x\n", cmd, chsa); @@ -499,36 +501,36 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) break; case DSK_NOP: /* NOP 0x03 */ - uptr->CMD |= cmd; /* save cmd */ + uptr->CMDu3 |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ return 0; break; case DSK_SNS: /* Sense 0x04 */ - uptr->CMD |= cmd; /* save cmd */ + uptr->CMDu3 |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ break; case DSK_WSL: /* WSL 0x31 */ - uptr->CMD |= cmd; /* save cmd */ + uptr->CMDu3 |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ return 0; break; case DSK_RSL: /* RSL 0x32 */ - uptr->CMD |= cmd; /* save cmd */ + uptr->CMDu3 |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ return 0; break; case DSK_WTL: /* WTL 0x51 */ - uptr->CMD |= cmd; /* save cmd */ + uptr->CMDu3 |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ return 0; break; case DSK_RTL: /* RTL 0x52 */ - uptr->CMD |= cmd; /* save cmd */ + uptr->CMDu3 |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ return 0; break; @@ -546,11 +548,11 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) /* Handle processing of disk requests. */ t_stat disk_srv(UNIT *uptr) { - uint16 chsa = GET_UADDR(uptr->CMD); + uint16 chsa = GET_UADDR(uptr->CMDu3); DEVICE *dptr = get_dev(uptr); DIB *dibp = (DIB *)dptr->ctxt; /* get DIB address */ CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */ - int cmd = uptr->CMD & DSK_CMDMSK; + int cmd = uptr->CMDu3 & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); uint32 trk, cyl, sec; int unit = (uptr - dptr->units); @@ -564,7 +566,7 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "disk_srv entry unit %02x CMD %08x chsa %04x count %04x %x/%x/%x \n", - unit, uptr->CMD, chsa, chp->ccw_count, + unit, uptr->CMDu3, chsa, chp->ccw_count, STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ @@ -597,7 +599,7 @@ t_stat disk_srv(UNIT *uptr) /* a pointer to the INCH buffer followed by 8 drive attribute words that */ /* contains the flags, sector count, MHD head count, and FHD count */ /* len has the byte count from IOCD wd2 and should be 0x24 (36) */ - /* the INCH buffer address must be set for the parrent channel as well */ + /* the INCH buffer address must be set for the parent channel as well */ /* as all other devices on the channel. Call set_inch() to do this for us */ /* just return OK and channel software will use u4 as status buffer addr */ @@ -605,7 +607,7 @@ t_stat disk_srv(UNIT *uptr) if (len != 36) { /* we have invalid count, error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -620,7 +622,7 @@ t_stat disk_srv(UNIT *uptr) for (i=0; i < 36; i++) { if (chan_read_byte(chsa, &buf[i])) { /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -645,13 +647,13 @@ t_stat disk_srv(UNIT *uptr) #ifdef NOTYET if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } #endif - uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "disk_srv cmd INCH chsa %04x addr %06x count %04x completed\n", chsa, mema, chp->ccw_count); @@ -664,7 +666,7 @@ t_stat disk_srv(UNIT *uptr) break; case DSK_WSL: /* WSL 0x31 make into NOP */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "disk_srv cmd WSL chsa %04x count %04x completed\n", chsa, chp->ccw_count); @@ -675,8 +677,10 @@ t_stat disk_srv(UNIT *uptr) for (i = 0; i < len; i++) { if (chan_read_byte(chsa, &buf[i])) { /* we have write error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); +//XXX goto goout; + return SCPE_OK; break; } if ((i%16) == 0) @@ -684,12 +688,12 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); } sim_debug(DEBUG_DETAIL, dptr, "\n"); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ +//XXXgoout: break; case DSK_WTL: /* WTL 0x51 make into NOP */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "disk_srv cmd WTL chsa %04x count %04x completed\n", chsa, chp->ccw_count); @@ -699,8 +703,10 @@ t_stat disk_srv(UNIT *uptr) for (i = 0; i < 30; i++) { if (chan_read_byte(chsa, &buf[i])) { /* we have read error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; +//XXX goto goout; break; } if (i == 16) @@ -708,12 +714,11 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); } sim_debug(DEBUG_DETAIL, dptr, "\n"); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; case DSK_NOP: /* NOP 0x03 */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "disk_srv cmd NOP chsa %04x count %04x completed\n", chsa, chp->ccw_count); @@ -794,33 +799,36 @@ t_stat disk_srv(UNIT *uptr) unit, ch); chan_write_byte(chsa, &ch); } - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; case DSK_SCK: /* Seek cylinder, track, sector 0x07 */ /* If we are waiting on seek to finish, check if there yet. */ - if (uptr->CMD & DSK_SEEKING) { + if (uptr->CMDu3 & DSK_SEEKING) { /* see if on cylinder yet */ if (STAR2CYL(uptr->STAR) == STAR2CYL(uptr->CHS)) { /* we are on cylinder, seek is done */ sim_debug(DEBUG_CMD, dptr, "disk_srv seek on cylinder unit=%02x %04x %04x\n", unit, uptr->STAR >> 16, uptr->CHS >> 16); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ /* we have already seeked to the required sector */ /* we do not need to seek again, so move on */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); - sim_activate(uptr, 20); + return SCPE_OK; +//XXX sim_activate(uptr, 20); break; } else { /* we have wasted enough time, we are there */ -#ifndef DO_SEEK_AGAIN +#ifdef DO_SEEK_AGAIN /* calculate file position in bytes of requested sector */ /* file offset in bytes */ tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type); /* just reseek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv Error on seek to %04x\n", tstart); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; } #endif uptr->CHS = uptr->STAR; /* we are there */ @@ -849,25 +857,26 @@ t_stat disk_srv(UNIT *uptr) "disk_srv seek error unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SCPE_OK; break; } + /* done reading, see how many we read */ + if (i == 1) { + /* UTX wants to set seek STAR to zero */ + buf[0] = buf[1] = buf[2] = buf[3] = 0; + break; + } /* just read the next byte */ } } - /* done reading, see how many we read */ - if (i == 1) { - /* UTX wants to set seek STAR to zero */ - buf[0] = buf[1] = buf[2] = buf[3] = 0; - } /* else the cyl, trk, and sect are ready to update */ sim_debug(DEBUG_CMD, dptr, "disk_srv STAR unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); -rezero: +//XXXrezero: sim_debug(DEBUG_DETAIL, dptr, "disk_srv seek unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); @@ -886,11 +895,11 @@ rezero: trk >= disk_type[type].nhds || buf[3] >= disk_type[type].spt) { - sim_debug(DEBUG_CMD, dptr, + sim_debug(DEBUG_EXP, dptr, "disk_srv seek ERROR cyl %04x trk %02x sec %02x unit=%02x\n", cyl, trk, buf[3], unit); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; /* set error status */ /* we have an error, tell user */ @@ -911,15 +920,18 @@ rezero: /* just seek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ - sim_debug(DEBUG_DETAIL, dptr, "disk_srv Error on seek to %04x\n", tstart); + sim_debug(DEBUG_EXP, dptr, "disk_srv Error on seek to %04x\n", tstart); + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; } /* Check if already on correct cylinder */ /* if not, do a delay to slow things down */ if (STAR2CYL(uptr->STAR) != STAR2CYL(uptr->CHS)) { /* Do a fake seek to kill time */ - uptr->CMD |= DSK_SEEKING; /* show we are seeking */ - sim_debug(DEBUG_DETAIL, dptr, + uptr->CMDu3 |= DSK_SEEKING; /* show we are seeking */ + sim_debug(DEBUG_EXP, dptr, "disk_srv seeking unit=%02x to cyl %04x trk %02x sec %02x\n", unit, cyl, trk, buf[3]); sim_activate(uptr, 20); /* start us off */ @@ -928,7 +940,7 @@ rezero: sim_debug(DEBUG_DETAIL, dptr, "disk_srv done seeking to %04x cyl %04x trk %02x sec %02x\n", tstart, cyl, trk, buf[3]); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); } return SCPE_OK; @@ -939,20 +951,38 @@ rezero: /* Do a seek to 0 */ uptr->STAR = 0; /* set STAR to 0, 0, 0 */ uptr->CHS = 0; /* set current CHS to 0, 0, 0 */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ - uptr->CMD |= DSK_SCK; /* show as seek command */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 |= DSK_SCK; /* show as seek command */ tstart = 0; /* byte offset is 0 */ +#ifdef NOT_NEEDED /* Read in 1 dummy character for length to inhibit SLI posting */ if (chan_read_byte(chsa, &buf[0])) { /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; + return SCPE_OK; +//XXX break; } +#endif +#ifndef DO_NEW_WAY + /* just seek to the location where we will r/w data */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ + sim_debug(DEBUG_EXP, dptr, "disk_srv Error on seek to %04x\n", tstart); + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + } + /* we are on cylinder/track/sector zero, so go on */ + sim_debug(DEBUG_DETAIL, dptr, "disk_srv done seek trk 0\n"); + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_DEVEND|SNS_CHNEND); + return SCPE_OK; +#else /* zero stuff */ buf[0] = buf[1] = buf[2] = buf[3] = 0; goto rezero; /* merge with seek code */ +#endif break; case DSK_LMR: @@ -960,28 +990,28 @@ rezero: /* Read in 1 character of mode data */ if (chan_read_byte(chsa, &buf[0])) { /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x old %x new %x\n", unit, (uptr->SNS)&0xff, buf[0]); - uptr->CMD &= ~(0xffff); /* remove old cmd */ - uptr->SNS &= 0x00ffffff; /* clear old mode data */ + uptr->CMDu3 &= LMASK; /* remove old cmd */ + uptr->SNS &= MASK24; /* clear old mode data */ uptr->SNS |= (buf[0] << 24); /* save mode value */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; case DSK_RD: /* Read Data */ - if ((uptr->CMD & DSK_READING) == 0) { /* see if we are reading data */ - uptr->CMD |= DSK_READING; /* read from disk starting */ + if ((uptr->CMDu3 & DSK_READING) == 0) { /* see if we are reading data */ + uptr->CMDu3 |= DSK_READING; /* read from disk starting */ sim_debug(DEBUG_CMD, dptr, "DISK READ starting CMD %08x chsa %04x buffer %06x count %04x\n", - uptr->CMD, chsa, chp->ccw_addr, chp->ccw_count); + uptr->CMDu3, chsa, chp->ccw_addr, chp->ccw_count); } - if (uptr->CMD & DSK_READING) { /* see if we are reading data */ + if (uptr->CMDu3 & DSK_READING) { /* see if we are reading data */ cyl = STAR2CYL(uptr->CHS); /* get current cyl */ trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ sec = uptr->CHS & 0xff; /* get sec */ @@ -989,12 +1019,16 @@ rezero: // tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)); tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + sim_debug(DEBUG_CMD, dptr, + "DISK READ reading CMD %08x chsa %04x tstart %04x buffer %06x count %04x\n", + uptr->CMDu3, chsa, tstart, chp->ccw_addr, chp->ccw_count); + /* read in a sector of data from disk */ if ((len=sim_fread(buf, 1, ssize, uptr->fileref)) != ssize) { sim_debug(DEBUG_CMD, dptr, "Error %08x on read %04x of diskfile cyl %04x hds %02x sec %02x\n", len, ssize, cyl, trk, sec); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -1010,10 +1044,14 @@ rezero: sim_debug(DEBUG_DATA, dptr, "DISK Read %04x bytes leaving %04x from diskfile /%04x/%02x/%02x\n", i, chp->ccw_count, cyl, trk, sec); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - goto rddone; + return SCPE_OK; +//XXX goto rddone; } +// sim_debug(DEBUG_DATA, dptr, +// "DISK Read2 %04x bytes leaving %04x from diskfile /%04x/%02x/%02x\n", +// i, chp->ccw_count, cyl, trk, sec); } sim_debug(DEBUG_CMD, dptr, @@ -1025,7 +1063,7 @@ rezero: sim_debug(DEBUG_DATA, dptr, "DISK Read complete for read from diskfile /%04x/%02x/%02x\n", STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; } @@ -1041,7 +1079,7 @@ rezero: sim_debug(DEBUG_CMD, dptr, "DISK Read reached EOM for read from disk @ /%04x/%02x/%02x\n", STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->CHS = 0; /* reset cylinder position */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -1052,18 +1090,18 @@ rezero: chp->ccw_count, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); sim_activate(uptr, 10); /* wait to read next sector */ break; -rddone: - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ +//XXXrddone: +//XXX uptr->CMDu3 &= ~(0xffff); /* remove old status bits & cmd */ } break; case DSK_WD: /* Write Data */ - if ((uptr->CMD & DSK_WRITING) == 0) { /* see if we are writing data */ - uptr->CMD |= DSK_WRITING; /* write to disk starting */ + if ((uptr->CMDu3 & DSK_WRITING) == 0) { /* see if we are writing data */ + uptr->CMDu3 |= DSK_WRITING; /* write to disk starting */ sim_debug(DEBUG_CMD, dptr, - "DISK WRITE starting unit=%02x CMD %02x\n", unit, uptr->CMD); + "DISK WRITE starting unit=%02x CMD %02x\n", unit, uptr->CMDu3); } - if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */ + if (uptr->CMDu3 & DSK_WRITING) { /* see if we are writing data */ cyl = STAR2CYL(uptr->CHS); /* get current cyl */ trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ sec = uptr->CHS & 0xff; /* get sec */ @@ -1077,12 +1115,13 @@ rddone: if (chan_read_byte(chsa, &ch)) { /* get a byte from memory */ /* if error on reading 1st byte, we are done writing */ if (i == 0) { - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "DISK Wrote %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", ssize, cyl, trk, sec); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - goto wrdone; + return SCPE_OK; +//XXX goto wrdone; } ch = 0; /* finish out the sector with zero */ len++; /* show we have no more data to write */ @@ -1095,7 +1134,7 @@ rddone: sim_debug(DEBUG_CMD, dptr, "Error %08x on write %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", i, ssize, cyl, trk, sec); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -1103,7 +1142,7 @@ rddone: sim_debug(DEBUG_DATA, dptr, "DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", ssize, cyl, trk, sec); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; } @@ -1122,15 +1161,15 @@ rddone: sim_debug(DEBUG_CMD, dptr, "DISK Write reached EOM for write to disk @ /%04x/%02x/%02x\n", STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->CHS = 0; /* reset cylinder position */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } sim_activate(uptr, 10); /* keep writing */ break; -wrdone: - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ +//XXXwrdone: +//XXX uptr->CMDu3 &= ~(0xffff); /* remove old status bits & cmd */ } break; @@ -1216,7 +1255,7 @@ wrdone: for (i = 0; i < 30; i++) { if (chan_write_byte(chsa, &buf[i])) { /* we have write error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -1227,7 +1266,7 @@ wrdone: sim_debug(DEBUG_DETAIL, dptr, "\n"); /* command done */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd RSL done chsa %04x count %04x completed\n", chsa, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ @@ -1331,7 +1370,7 @@ wrdone: for (i = 0; i < 30; i++) { if (chan_write_byte(chsa, &buf[i])) { /* we have write error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -1342,7 +1381,7 @@ wrdone: sim_debug(DEBUG_DETAIL, dptr, "\n"); /* command done */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "disk_srv cmd RTL done chsa %04x count %04x completed\n", chsa, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ @@ -1351,7 +1390,7 @@ wrdone: default: sim_debug(DEBUG_CMD, dptr, "invalid command %02x unit %02x\n", cmd, unit); uptr->SNS |= SNS_CMDREJ; - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -1366,13 +1405,16 @@ void disk_ini(UNIT *uptr, t_bool f) DEVICE *dptr = get_dev(uptr); int i = GET_TYPE(uptr->flags); - uptr->CMD &= ~0x7fff; /* clear out the flags but leave ch/sa */ + /* start out at sector 0 */ + uptr->CHS = 0; /* set CHS to cyl/hd/sec = 0 */ + uptr->STAR = 0; /* set STAR to cyl/hd/sec = 0 */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->SNS = ((uptr->SNS & 0x00ffffff) | (disk_type[i].type << 24)); /* save mode value */ /* total sectors on disk */ uptr->capac = CAP(i); /* size in sectors */ sim_debug(DEBUG_EXP, &dda_dev, "DMA init device %s on unit DMA%.1x cap %x %d\n", - dptr->name, GET_UADDR(uptr->CMD), uptr->capac, uptr->capac); + dptr->name, GET_UADDR(uptr->CMDu3), uptr->capac, uptr->capac); } t_stat disk_reset(DEVICE *dptr) @@ -1472,6 +1514,7 @@ int disk_format(UNIT *uptr) { /* seek to sector 0 */ if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ fprintf (stderr, "Error on seek to 0\r\n"); + return 1; } /* get buffer for track data in bytes */ @@ -1524,10 +1567,15 @@ int disk_format(UNIT *uptr) { /* setup dmap pointed to by track label 0 wd[3] = (cyl-4) * spt + (spt - 1) */ /* write dmap data to last sector on disk */ - sim_fseek(uptr->fileref, laddr*ssize, SEEK_SET); /* seek last sector */ + if ((sim_fseek(uptr->fileref, laddr*ssize, SEEK_SET)) != 0) { /* seek last sector */ + sim_debug(DEBUG_CMD, dptr, + "Error on last sector seek to diskfile sect %06x\n", (cap-1) * ssize); + return 1; + } if ((sim_fwrite((char *)&dmap, sizeof(uint32), 4, uptr->fileref)) != 4) { sim_debug(DEBUG_CMD, dptr, - "Error on vendor map write to diskfile sect %06x\n", (cap-1) * ssize); + "Error on last sector write to diskfile sect %06x\n", (cap-1) * ssize); + return 1; } /* 1 cylinder is saved for disk manufacture */ @@ -1537,26 +1585,41 @@ int disk_format(UNIT *uptr) { /* vaddr is (cap) - 3 cyl - 1 track */ /* seek to vendor label area */ - sim_fseek(uptr->fileref, (vaddr)*ssize, SEEK_SET); /* seek VMAP */ + if ((sim_fseek(uptr->fileref, vaddr*ssize, SEEK_SET)) != 0) { /* seek VMAP */ + sim_debug(DEBUG_CMD, dptr, + "Error on vendor map seek to diskfile sect %06x\n", (cap-1) * ssize); + return 1; + } if ((sim_fwrite((char *)&vmap, sizeof(uint32), 2, uptr->fileref)) != 2) { sim_debug(DEBUG_CMD, dptr, "Error on vendor map write to diskfile sect %06x\n", vaddr * ssize); + return 1; } /* write dmap to daddr that is the address in trk 0 label */ /* daddr is (cap) - 3 cyl - 2 tracks */ /* vaddr is daddr - spt */ - sim_fseek(uptr->fileref, (daddr)*ssize, SEEK_SET); /* seek DMAP */ + if ((sim_fseek(uptr->fileref, daddr*ssize, SEEK_SET)) != 0) { /* seek DMAP */ + sim_debug(DEBUG_CMD, dptr, + "Error on daddr seek to diskfile sect %06x\n", (cap-1) * ssize); + return 1; + } if ((sim_fwrite((char *)&dmap, sizeof(uint32), 4, uptr->fileref)) != 4) { sim_debug(DEBUG_CMD, dptr, - "Error on dmap write to diskfile sect %06x\n", daddr * ssize); + "Error on daddr write to diskfile sect %06x\n", daddr * ssize); + return 1; } - sim_fseek(uptr->fileref, (uaddr)*ssize, SEEK_SET); /* seek UMAP */ + if ((sim_fseek(uptr->fileref, uaddr*ssize, SEEK_SET)) != 0) { /* seek UMAP */ + sim_debug(DEBUG_CMD, dptr, + "Error on umap seek to diskfile sect %06x\n", (cap-1) * ssize); + return 1; + } if ((sim_fwrite((char *)&umap, sizeof(uint32), 256, uptr->fileref)) != 256) { sim_debug(DEBUG_CMD, dptr, "Error on umap write to diskfile sect %06x\n", uaddr * ssize); + return 1; } printf("writing to vmap sec %x (%d) bytes %x (%d)\n", @@ -1568,7 +1631,10 @@ int disk_format(UNIT *uptr) { daddr, daddr, daddr*ssize, daddr*ssize); /* seek home again */ - sim_fseek(uptr->fileref, 0, SEEK_SET); /* seek home */ + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + fprintf (stderr, "Error on seek to 0\r\n"); + return 1; + } free(buff); /* free cylinder buffer */ return 0; } @@ -1576,7 +1642,7 @@ int disk_format(UNIT *uptr) { /* attach the selected file to the disk */ t_stat disk_attach(UNIT *uptr, CONST char *file) { - uint16 chsa = GET_UADDR(uptr->CMD); + uint16 chsa = GET_UADDR(uptr->CMDu3); int type = GET_TYPE(uptr->flags); DEVICE *dptr = get_dev(uptr); t_stat r; @@ -1647,7 +1713,7 @@ fmt: /* detach a disk device */ t_stat disk_detach(UNIT *uptr) { uptr->SNS = 0; /* clear sense data */ - uptr->CMD &= ~0xffff; /* no cmd and flags */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ return detach_unit(uptr); /* tell simh we are done with disk */ } @@ -1655,13 +1721,19 @@ t_stat disk_detach(UNIT *uptr) { t_stat disk_boot(int32 unit_num, DEVICE *dptr) { UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */ - sim_debug(DEBUG_CMD, dptr, "Disk Boot dev/unit %x\n", GET_UADDR(uptr->CMD)); - SPAD[0xf4] = GET_UADDR(uptr->CMD); /* put boot device chan/sa into spad */ - SPAD[0xf8] = 0xF000; /* show as F class device */ - if ((uptr->flags & UNIT_ATT) == 0) + sim_debug(DEBUG_CMD, dptr, "Disk Boot dev/unit %x\n", GET_UADDR(uptr->CMDu3)); + + if ((uptr->flags & UNIT_ATT) == 0) { + sim_debug(DEBUG_EXP, &mta_dev, "Disk Boot attach error dev/unit %04x\n", + GET_UADDR(uptr->CMDu3)); return SCPE_UNATT; /* attached? */ + } + SPAD[0xf4] = GET_UADDR(uptr->CMDu3); /* put boot device chan/sa into spad */ + SPAD[0xf8] = 0xF000; /* show as F class device */ + /* now boot the disk */ - return chan_boot(GET_UADDR(uptr->CMD), dptr); /* boot the ch/sa */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + return chan_boot(GET_UADDR(uptr->CMDu3), dptr); /* boot the ch/sa */ } /* Disk option setting commands */ diff --git a/SEL32/sel32_fltpt.c b/SEL32/sel32_fltpt.c index 00de400..eb84699 100644 --- a/SEL32/sel32_fltpt.c +++ b/SEL32/sel32_fltpt.c @@ -833,7 +833,7 @@ uint32 s_dvfw(uint32 reg, uint32 mem, uint32 *cc) { if (temp2 >= 0x7fffffc0) /* check for special rounding */ goto RRND2; /* no special handling */ /* FIXME dead code */ - if (temp2 == MSIGN) { /* check for minux zero */ + if (temp2 == MSIGN) { /* check for minus zero */ temp2 = 0xF8000000; /* yes, fixup value */ expr++; /* bump exponent */ } @@ -844,9 +844,11 @@ uint32 s_dvfw(uint32 reg, uint32 mem, uint32 *cc) { if ((sign & MSIGN) == 0) goto RRND1; /* if sign set, don't round yet */ expr += temp; /* add exponent */ - if (expr < 0) /* test for underflow */ + /* FIX unsigned CMP */ +// if (expr < 0) /* test for underflow */ + if ((int32)expr < 0) /* test for underflow */ goto DUNFLO; /* go process underflow */ - if (expr > 0x7f) /* test for overflow */ + if ((int32)expr > 0x7f) /* test for overflow */ goto DOVFLO; /* go process overflow */ expr ^= FMASK; /* complement exponent */ temp2 += 0x40; /* round at bit 25 */ @@ -858,7 +860,7 @@ RRND2: if ((int32)expr < 0) { /* test for underflow */ goto DUNFLO; /* go process underflow */ } - if (expr > 0x7f) { /* test for overflow */ + if ((int32)expr > 0x7f) { /* test for overflow */ goto DOVFLO; /* go process overflow */ } if (sign & MSIGN) /* test for negative */ diff --git a/SEL32/sel32_hsdp.c b/SEL32/sel32_hsdp.c index 3c9172a..31f97bc 100644 --- a/SEL32/sel32_hsdp.c +++ b/SEL32/sel32_hsdp.c @@ -352,9 +352,9 @@ hsdp_type[] = uint8 hsdp_preio(UNIT *uptr, uint16 chan) ; uint8 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; -uint8 hsdp_haltio(uint16 addr); +uint8 hsdp_haltio(UNIT *uptr); t_stat hsdp_srv(UNIT *); -t_stat hsdp_boot(int32, DEVICE *); +t_stat hsdp_boot(int32 unitnum, DEVICE *); void hsdp_ini(UNIT *, t_bool); t_stat hsdp_reset(DEVICE *); t_stat hsdp_attach(UNIT *, CONST char *); @@ -409,6 +409,7 @@ DEVICE dpa_dev = { "DPA", dpa_unit, NULL, hsdp_mod, NUM_UNITS_HSDP, 16, 24, 4, 16, 32, NULL, NULL, &hsdp_reset, &hsdp_boot, &hsdp_attach, &hsdp_detach, + /* ctxt is the DIB pointer */ &dpa_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, NULL, NULL, &hsdp_help, NULL, NULL, &hsdp_description }; @@ -451,6 +452,7 @@ DEVICE dpb_dev = { "DPB", dpb_unit, NULL, hsdp_mod, NUM_UNITS_HSDP, 16, 24, 4, 16, 32, NULL, NULL, &hsdp_reset, &hsdp_boot, &hsdp_attach, &hsdp_detach, + /* ctxt is the DIB pointer */ &dpb_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, NULL, NULL, &hsdp_help, NULL, NULL, &hsdp_description }; @@ -723,6 +725,7 @@ t_stat hsdp_srv(UNIT *uptr) /* we have write error, bail out */ uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + goto goout; break; } if ((i%16) == 0) @@ -730,8 +733,8 @@ t_stat hsdp_srv(UNIT *uptr) sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); } sim_debug(DEBUG_DETAIL, dptr, "\n"); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ +goout: break; case DSK_WTL: /* WTL 0x51 make into NOP */ @@ -747,6 +750,7 @@ t_stat hsdp_srv(UNIT *uptr) /* we have read error, bail out */ uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + goto goout; break; } if (i == 16) @@ -857,17 +861,20 @@ t_stat hsdp_srv(UNIT *uptr) /* we have already seeked to the required sector */ /* we do not need to seek again, so move on */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); - sim_activate(uptr, 20); + return SCPE_OK; +//XXX sim_activate(uptr, 20); break; } else { /* we have wasted enough time, we there */ -#ifndef DO_SEEK_AGAIN +#ifdef DO_SEEK_AGAIN /* calculate file position in bytes of requested sector */ /* file offseet in bytes */ tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type); /* just reseek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv Error on seek to %04x\n", tstart); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; } #endif uptr->CHS = uptr->STAR; /* we are there */ @@ -903,13 +910,14 @@ t_stat hsdp_srv(UNIT *uptr) break; } /* just read the next byte */ + /* done reading, see how many we read */ + if (i == 1) { + /* UTX wants to set seek STAR to zero */ + buf[0] = buf[1] = buf[2] = buf[3] = 0; + break; + } } } - /* done reading, see how many we read */ - if (i == 1) { - /* UTX wants to set seek STAR to zero */ - buf[0] = buf[1] = buf[2] = buf[3] = 0; - } /* else the cyl, trk, and sect are ready to update */ sim_debug(DEBUG_CMD, dptr, "hsdp_srv STAR unit=%02x star %02x %02x %02x %02x\n", @@ -958,6 +966,8 @@ rezero: /* just seek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* seek home */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv Error on seek to %08x\n", tstart); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; } /* Check if already on correct cylinder */ @@ -1471,6 +1481,9 @@ void hsdp_ini(UNIT *uptr, t_bool f) DEVICE *dptr = get_dev(uptr); int i = GET_TYPE(uptr->flags); + /* start out at sector 0 */ + uptr->CHS = 0; /* set CHS to cyl/hd/sec = 0 */ + uptr->STAR = 0; /* set STAR to cyl/hd/sec = 0 */ uptr->CMD &= ~0x7fff; /* clear out the flags but leave ch/sa */ uptr->SNS = ((uptr->SNS & 0x00ffffff) | (hsdp_type[i].type << 24)); /* save mode value */ /* total sectors on disk */ @@ -1600,6 +1613,7 @@ int hsdp_format(UNIT *uptr) { /* seek to sector 0 */ if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ fprintf (stderr, "Error on seek to 0\r\n"); + return 1; } /* get buffer for track data in bytes */ @@ -1652,10 +1666,14 @@ int hsdp_format(UNIT *uptr) { /* setup dmap pointed to by track label 0 wd[3] = (cyl-4) * spt + (spt - 1) */ /* write dmap data to last sector on disk */ - sim_fseek(uptr->fileref, laddr*ssize, SEEK_SET); /* seek last sector */ + if ((sim_fseek(uptr->fileref, laddr*ssize, SEEK_SET)) != 0) { /* seek last sector */ + sim_debug(DEBUG_CMD, dptr, + "Error on last sector seek to diskfile sect %06x\n", (cap-1) * ssize); + return 1; + } if ((sim_fwrite((char *)&dmap, sizeof(uint32), 4, uptr->fileref)) != 4) { sim_debug(DEBUG_CMD, dptr, - "Error on vendor map write to diskfile sect %06x\n", (cap-1) * ssize); + "Error on last sectdor write to diskfile sect %06x\n", (cap-1) * ssize); } /* 1 cylinder is saved for disk manufacture */ @@ -1665,7 +1683,11 @@ int hsdp_format(UNIT *uptr) { /* vaddr is (cap) - 3 cyl - 1 track */ /* seek to vendor label area */ - sim_fseek(uptr->fileref, (vaddr)*ssize, SEEK_SET); /* seek UMAP */ + if ((sim_fseek(uptr->fileref, vaddr*ssize, SEEK_SET)) != 0) { /* seek VMAP */ + sim_debug(DEBUG_CMD, dptr, + "Error on vendor map seek to diskfile sect %06x\n", (cap-1) * ssize); + return 1; + } if ((sim_fwrite((char *)&vmap, sizeof(uint32), 2, uptr->fileref)) != 2) { sim_debug(DEBUG_CMD, dptr, "Error on vendor map write to diskfile sect %06x\n", vaddr * ssize); @@ -1675,16 +1697,26 @@ int hsdp_format(UNIT *uptr) { /* daddr is (cap) - 3 cyl - 2 tracks */ /* vaddr is daddr - spt */ - sim_fseek(uptr->fileref, (daddr)*ssize, SEEK_SET); /* seek DMAP */ + if ((sim_fseek(uptr->fileref, daddr*ssize, SEEK_SET)) != 0) { /* seek DMAP */ + sim_debug(DEBUG_CMD, dptr, + "Error on dmap seek to diskfile sect %06x\n", (cap-1) * ssize); + return 1; + } if ((sim_fwrite((char *)&dmap, sizeof(uint32), 4, uptr->fileref)) != 4) { sim_debug(DEBUG_CMD, dptr, "Error on dmap write to diskfile sect %06x\n", daddr * ssize); + return 1; } - sim_fseek(uptr->fileref, (uaddr)*ssize, SEEK_SET); /* seek UMAP */ + if ((sim_fseek(uptr->fileref, uaddr*ssize, SEEK_SET)) != 0) { /* seek UMAP */ + sim_debug(DEBUG_CMD, dptr, + "Error on umap seek to diskfile sect %06x\n", (cap-1) * ssize); + return 1; + } if ((sim_fwrite((char *)&umap, sizeof(uint32), 256, uptr->fileref)) != 256) { sim_debug(DEBUG_CMD, dptr, - "Error on umap write to diskfile sect %06x\n", uaddr * ssize); + "Error on umap write to diskfile sect %06x\n", uaddr * ssize); + return 1; } printf("writing to vmap sec %x (%d) bytes %x (%d)\n", @@ -1696,7 +1728,11 @@ int hsdp_format(UNIT *uptr) { daddr, daddr, daddr*ssize, daddr*ssize); /* seek home again */ - sim_fseek(uptr->fileref, 0, SEEK_SET); /* seek home */ + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + fprintf (stderr, "Error on seek to 0\r\n"); + return 1; + } + free(buff); /* free cylinder buffer */ free(buff); /* free cylinder buffer */ return 0; } diff --git a/SEL32/sel32_lpr.c b/SEL32/sel32_lpr.c index fb73beb..71ef219 100644 --- a/SEL32/sel32_lpr.c +++ b/SEL32/sel32_lpr.c @@ -190,6 +190,7 @@ DEVICE lpr_dev = { "LPR", lpr_unit, NULL, lpr_mod, NUM_DEVS_LPR, 8, 15, 1, 8, 8, NULL, NULL, NULL, NULL, &lpr_attach, &lpr_detach, + /* ctxt is the DIB pointer */ &lpr_dib, DEV_UADDR | DEV_DISABLE | DEV_DEBUG, 0, dev_debug }; diff --git a/SEL32/sel32_mfp.c b/SEL32/sel32_mfp.c new file mode 100644 index 0000000..2a2cdcf --- /dev/null +++ b/SEL32/sel32_mfp.c @@ -0,0 +1,275 @@ +/* sel32_mfp.c: SEL-32 Model 8000/8001/8002 MFP processor controller + + Copyright (c) 2018-2020, James C. Bevier + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + JAMES C. BEVIER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + This channel is the interrupt fielder for all of the MFP sub channels. It's + channel address is 7600. This code handles the INCH command for the MFP + devices and controls the status FIFO for the mfp devices on interrupts and + TIO instructions.. + + Possible devices: + The f8iop communication controller (TY76A0), (TY76B0), (TY76C0) + The ctiop console communications controller (CT76FC & CT76FD) + The lpiop line printer controller (LP76F8), (LP76F9) + The scsi SCSI disk controller (DM7600), (DM7640) + +*/ + +#include "sel32_defs.h" + +#ifdef NUM_DEVS_MFP + +extern t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +extern t_stat show_dev_addr(FILE *st, UNIT * uptr, int32 v, CONST void *desc); +extern void chan_end(uint16 chan, uint8 flags); +extern int chan_read_byte(uint16 chan, uint8 *data); +extern int chan_write_byte(uint16 chan, uint8 *data); +extern void set_devattn(uint16 addr, uint8 flags); +extern void post_extirq(void); +extern uint32 attention_trap; /* set when trap is requested */ +extern void set_devwake(uint16 addr, uint8 flags); +extern t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */ +extern CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */ + +/* forward definitions */ +uint8 mfp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); +void mfp_ini(UNIT *uptr, t_bool f); +t_stat mfp_srv(UNIT *uptr); +t_stat mfp_reset(DEVICE *dptr); +t_stat mfp_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +const char *mfp_desc(DEVICE *dptr); + +/* Held in u3 is the device command and status */ +#define MFP_INCH 0x00 /* Initialize channel command */ +#define MFP_INCH2 0xf0 /* Initialize channel command after start */ +#define MFP_NOP 0x03 /* NOP command */ +#define MFP_MSK 0xff /* Command mask */ + +/* Status held in u3 */ +/* controller/unit address in upper 16 bits */ +#define CON_INPUT 0x100 /* Input ready for unit */ +#define CON_CR 0x200 /* Output at beginning of line */ +#define CON_REQ 0x400 /* Request key pressed */ +#define CON_EKO 0x800 /* Echo input character */ +#define CON_OUTPUT 0x1000 /* Output ready for unit */ +#define CON_READ 0x2000 /* Read mode selected */ + +/* not used u4 */ + +/* in u5 packs sense byte 0,1 and 3 */ +/* Sense byte 0 */ +#define SNS_CMDREJ 0x80000000 /* Command reject */ +#define SNS_INTVENT 0x40000000 /* Unit intervention required */ +/* sense byte 3 */ +#define SNS_RDY 0x80 /* device ready */ +#define SNS_ONLN 0x40 /* device online */ + +/* std devices. data structures + + mfp_dev Console device descriptor + mfp_unit Console unit descriptor + mfp_reg Console register list + mfp_mod Console modifiers list +*/ + +struct _mfp_data +{ + uint8 ibuff[145]; /* Input line buffer */ + uint8 incnt; /* char count */ +} +mfp_data[NUM_UNITS_MFP]; + +/* channel program information */ +CHANP mfp_chp[NUM_UNITS_MFP] = {0}; + +MTAB mfp_mod[] = { + {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", + &set_dev_addr, &show_dev_addr, NULL, "Device address"}, + {0} +}; + +UNIT mfp_unit[] = { + {UDATA(&mfp_srv, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7600)}, /* Channel controller */ +}; + +//DIB mfp_dib = {NULL, mfp_startcmd, NULL, NULL, NULL, mfp_ini, mfp_unit, mfp_chp, NUM_UNITS_MFP, 0xff, 0x7e00,0,0,0}; +DIB mfp_dib = { + NULL, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Start I/O */ + mfp_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command SIO */ + NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O HIO */ + NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O TIO */ + NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ + mfp_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ + mfp_unit, /* UNIT* units */ /* Pointer to units structure */ + mfp_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NUM_UNITS_MFP, /* uint8 numunits */ /* number of units defined */ + 0xff, /* uint8 mask */ /* 16 devices - device mask */ + 0x7e00, /* uint16 chan_addr */ /* parent channel address */ + 0, /* uint32 chan_fifo_in */ /* fifo input index */ + 0, /* uint32 chan_fifo_out */ /* fifo output index */ + {0} /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ +}; + +DEVICE mfp_dev = { + "MFP", mfp_unit, NULL, mfp_mod, + NUM_UNITS_MFP, 8, 15, 1, 8, 8, + NULL, NULL, &mfp_reset, /* examine, deposit, reset */ + NULL, NULL, NULL, /* boot, attach, detach */ + &mfp_dib, DEV_UADDR|DEV_DISABLE|DEV_DEBUG, 0, dev_debug, /* dib, dev flags, debug flags, debug */ +// NULL, NULL, &mfp_help, /* ?, ?, help */ +// NULL, NULL, &mfp_desc /* ?, ?, description */ +}; + +/* MFP controller routines */ +/* initialize the console chan/unit */ +void mfp_ini(UNIT *uptr, t_bool f) +{ + int unit = (uptr - mfp_unit); /* unit 0 */ + DEVICE *dptr = &mfp_dev; /* one and only dummy device */ + + sim_debug(DEBUG_CMD, &mfp_dev, + "MFP init device %s controller/device %04x\n", + dptr->name, GET_UADDR(uptr->u3)); + mfp_data[unit].incnt = 0; /* no input data */ + uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ +} + +/* start an I/O operation */ +uint8 mfp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) +{ + sim_debug(DEBUG_CMD, &mfp_dev, + "MFP startcmd %02x controller/device %04x\n", + cmd, GET_UADDR(uptr->u3)); + if ((uptr->u3 & MFP_MSK) != 0) /* is unit busy */ + return SNS_BSY; /* yes, return busy */ + + /* process the commands */ + switch (cmd & 0xFF) { + /* UTX uses the INCH cmd to detect the MFP or MFP */ + /* MFP has INCH cmd of 0, while MFP uses 0x80 */ + case MFP_INCH: /* INCH command */ + uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ + uptr->u3 &= LMASK; /* leave only chsa */ + sim_debug(DEBUG_CMD, &mfp_dev, + "mfp_startcmd %04x: Cmd INCH iptr %06x INCHa %06x\n", + chan, mfp_chp[0].ccw_addr, /* set inch buffer addr */ + mfp_chp[0].chan_inch_addr); /* set inch buffer addr */ + + mfp_chp[0].chan_inch_addr = mfp_chp[0].ccw_addr; /* set inch buffer addr */ +// set_inch(uptr, mfp_chp[0].ccw_addr); /* new address */ + + uptr->u3 |= MFP_INCH2; /* save INCH command as 0xf0 */ + sim_activate(uptr, 20); /* go on */ + return 0; /* no status change */ + break; + + case MFP_NOP: /* NOP command */ + sim_debug(DEBUG_CMD, &mfp_dev, "mfp_startcmd %04x: Cmd NOP\n", chan); + uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ + uptr->u3 &= LMASK; /* leave only chsa */ + uptr->u3 |= (cmd & MFP_MSK); /* save NOP command */ + sim_activate(uptr, 20); /* TRY 07-13-19 */ + return 0; /* no status change */ + break; + + default: /* invalid command */ + uptr->u5 |= SNS_CMDREJ; /* command rejected */ + sim_debug(DEBUG_CMD, &mfp_dev, "mfp_startcmd %04x: Cmd Invalid %02x status %02x\n", + chan, cmd, uptr->u5); + uptr->u3 &= LMASK; /* leave only chsa */ + uptr->u3 |= (cmd & MFP_MSK); /* save command */ + sim_activate(uptr, 20); /* force interrupt */ + return 0; /* no status change */ + break; + } + + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* not reachable for now */ +} + +/* Handle transfers for other sub-channels on MFP */ +t_stat mfp_srv(UNIT *uptr) +{ + uint16 chsa = GET_UADDR(uptr->u3); + int cmd = uptr->u3 & MFP_MSK; +// CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + CHANP *chp = &mfp_chp[0]; /* find the chanp pointer */ +// int i; +// int len = chp->ccw_count; /* INCH command count */ + uint32 mema = chp->ccw_addr; /* get inch or buffer addr */ + + /* test for NOP or INCH cmds */ + if ((cmd != MFP_NOP) && (cmd != MFP_INCH2)) { /* NOP or INCH */ + uptr->u3 &= LMASK; /* nothing left, command complete */ + sim_debug(DEBUG_CMD, &mfp_dev, + "mfp_srv Unknown cmd %02x chan %02x: chnend|devend|unitexp\n", cmd, chsa); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* done */ + return SCPE_OK; + } else + + if (cmd == MFP_NOP) { /* NOP do nothing */ + uptr->u3 &= LMASK; /* nothing left, command complete */ + sim_debug(DEBUG_CMD, &mfp_dev, "mfp_srv INCH/NOP chan %02x: chnend|devend\n", chsa); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ + return SCPE_OK; + } else + + /* test for INCH cmd */ + if (cmd == MFP_INCH2) { /* INCH */ + sim_debug(DEBUG_CMD, &mfp_dev, + "mfp_srv starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n", + mema, chsa, chp->ccw_addr, chp->ccw_count); + + /* the chp->ccw_addr location contains the inch address */ + /* call set_inch() to setup inch buffer */ +// i = set_inch(uptr, mema); /* new address */ + set_inch(uptr, mema); /* new address */ +// chp->chan_inch_addr = mema; /* set inch buffer addr */ + uptr->u3 &= LMASK; /* clear the cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ +// chan_end(chsa, SNS_CHNEND); /* we are done dev|chan end */ + } + return SCPE_OK; +} + +t_stat mfp_reset(DEVICE *dptr) +{ + /* add reset code here */ + return SCPE_OK; +} + +/* sho help mfp */ +t_stat mfp_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr) +{ + fprintf(st, "SEL-32 MFP Model 8002 Channel Controller at 0x7600\r\n"); + fprintf(st, "The MFP fields all interrupts and status posting\r\n"); + fprintf(st, "for each of the controllers on the system.\r\n"); + fprintf(st, "Nothing can be configured for this Channel.\r\n"); +// fprint_set_help(st, dptr); +// fprint_show_help(st, dptr); + return SCPE_OK; +} + +const char *mfp_desc(DEVICE *dptr) +{ + return("SEL-32 MFP Model 8002 Channel Controller @ 0x7600"); +} + +#endif + diff --git a/SEL32/sel32_mt.c b/SEL32/sel32_mt.c index d3b02b5..78b36be 100644 --- a/SEL32/sel32_mt.c +++ b/SEL32/sel32_mt.c @@ -160,20 +160,19 @@ extern uint32 SPAD[]; /* cpu SPAD */ #define BUF_EMPTY(u) (u->hwmark == 0xFFFFFFFF) #define CLR_BUF(u) u->hwmark = 0xFFFFFFFF -uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; -t_stat mt_srv(UNIT *); -t_stat mt_boot(int32, DEVICE *); -void mt_ini(UNIT *, t_bool); -t_stat mt_reset(DEVICE *); -t_stat mt_attach(UNIT *, CONST char *); -t_stat mt_detach(UNIT *); -t_stat mt_boot(int32, DEVICE *); -t_stat mt_help(FILE *, DEVICE *, UNIT *, int32, const char *); -const char *mt_description(DEVICE *); +uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; +t_stat mt_srv(UNIT *uptr); +t_stat mt_boot(int32 unitnum, DEVICE *dptr); +void mt_ini(UNIT *uptr, t_bool); +t_stat mt_reset(DEVICE *dptr); +t_stat mt_attach(UNIT *uptr, CONST char *); +t_stat mt_detach(UNIT *uptr); +t_stat mt_help(FILE *, DEVICE *dptr, UNIT *uptr, int32, const char *); +const char *mt_description(DEVICE *); /* One buffer per channel */ -uint8 mt_buffer[NUM_DEVS_MT][BUFFSIZE]; -uint8 mt_busy[NUM_DEVS_MT]; +uint8 mt_buffer[NUM_DEVS_MT][BUFFSIZE]; +uint8 mt_busy[NUM_DEVS_MT]; /* Gould Buffered Tape Processor (BTP) - Model 8051 */ /* Integrated channel controller */ @@ -313,7 +312,7 @@ DIB mta_dib = { mta_unit, /* Pointer to units structure */ mta_chp, /* Pointer to chan_prg structure */ NUM_UNITS_MT, /* number of units defined */ - 0xFF, /* 256 devices - device mask */ + 0x07, /* 8 devices - device mask */ 0x1000, /* parent channel address */ 0, /* fifo input index */ 0, /* fifo output index */ @@ -356,8 +355,8 @@ DIB mtb_dib = { mtb_unit, /* Pointer to units structure */ mtb_chp, /* Pointer to chan_prg structure */ NUM_UNITS_MT, /* number of units defined */ - 0xFF, /* 256 devices - device mask */ - 0x1000, /* parent channel address */ + 0x07, /* 6 devices - device mask */ + 0x1800, /* parent channel address */ 0, /* fifo input index */ 0, /* fifo output index */ 0, /* interrupt status fifo for channel */ @@ -387,15 +386,15 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) return SNS_BSY; } - sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd processing unit %04x cmd %02x\n", unit, cmd); + sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd processing unit %01x cmd %02x\n", unit, cmd); switch (cmd & 0xFF) { case 0x00: /* INCH command */ sim_debug(DEBUG_CMD, dptr, "start INCH command\n"); sim_debug(DEBUG_CMD, dptr, - "mt_startcmd starting INCH %06x cmd, chsa %04x MemBuf %08x cnt %04x\n", - uptr->u4, chsa, chp->ccw_addr, chp->ccw_count); + "mt_startcmd starting INCH cmd, chsa %04x MemBuf %08x cnt %04x\n", + chsa, chp->ccw_addr, chp->ccw_count); /* UTX_needs_interrupt */ cmd = MT_CMDMSK; /* insert INCH cmd as 0xff */ @@ -431,17 +430,21 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) case 0x4: /* Sense */ #ifndef FIX_DIAG case 0x80: /* Unknown diag cmd with byte cnt of 0x0c */ +#ifdef DO_DYNAMIC_DEBUG + if ((cmd & 0xff) == 0x80) { + /* start debugging */ + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); + } +#endif #endif uptr->CMD &= ~(MT_CMDMSK); /* clear out last cmd */ uptr->CMD |= cmd & MT_CMDMSK; /* insert new cmd */ CLR_BUF(uptr); /* buffer is empty */ - /* INCH cmd has INCH buffer address in POS, so leave it */ - if (cmd != MT_CMDMSK) - uptr->POS = 0; /* reset buffer position pointer */ - sim_activate(uptr, 100); /* Start unit off */ + uptr->POS = 0; /* reset buffer position pointer */ mt_busy[GET_DEV_BUF(dptr->flags)] = 1; /* show we are busy */ sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd sense %08x return 0 chan %04x cmd %02x\n", uptr->SNS, chan, cmd); + sim_activate(uptr, 100); /* Start unit off */ return 0; default: /* invalid command */ @@ -465,6 +468,7 @@ t_stat mt_error(UNIT *uptr, uint16 addr, t_stat r, DEVICE *dptr) switch (r) { /* switch on return value */ case MTSE_OK: /* no error */ +/*NEW*/ chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ break; case MTSE_TMK: /* tape mark */ @@ -476,6 +480,7 @@ t_stat mt_error(UNIT *uptr, uint16 addr, t_stat r, DEVICE *dptr) case MTSE_WRP: /* write protected */ uptr->SNS |= SNS_WRP; /* write protected */ sim_debug(DEBUG_CMD, &mta_dev, "WRITE PROTECT %08x\n", r); /* operator intervention */ +/*NEW*/ chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ break; case MTSE_UNATT: /* unattached */ @@ -488,11 +493,13 @@ t_stat mt_error(UNIT *uptr, uint16 addr, t_stat r, DEVICE *dptr) case MTSE_FMT: /* invalid format */ case MTSE_RECE: /* error in record */ sim_debug(DEBUG_CMD, &mta_dev, "ERROR %08x\n", r); +/*NEW*/ chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ break; case MTSE_BOT: /* beginning of tape */ uptr->SNS |= SNS_LOAD; /* tape at BOT */ sim_debug(DEBUG_CMD, &mta_dev, "BOT\n"); +/*NEW*/ chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ break; case MTSE_INVRL: /* invalid rec lnt */ @@ -502,7 +509,7 @@ t_stat mt_error(UNIT *uptr, uint16 addr, t_stat r, DEVICE *dptr) chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); break; } - chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ +//WAS chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ return SCPE_OK; } @@ -521,7 +528,6 @@ t_stat mt_srv(UNIT *uptr) uint32 mema; uint16 len; uint8 ch; - uint8 zc = 0; uint8 buf[1024]; sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv unit %04x cmd %02x\n", unit, cmd); @@ -541,6 +547,12 @@ t_stat mt_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "mt_srv starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n", mema, addr, chp->ccw_addr, chp->ccw_count); +#ifdef DO_DYNAMIC_DEBUG + if (mema == 0x149d8) { + /* start debugging */ + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); + } +#endif if (len == 0) { /* we have invalid count, error, bail out */ @@ -559,12 +571,24 @@ t_stat mt_srv(UNIT *uptr) } /* just dump data */ } - /* uptr->POS has INCH buffer address, just leave it */ + /* a BTP uses a 41 word INCH memory buffer */ +// for (i=0; i<41; i++) { + for (i=0; i<9; i++) { + int32 data = RMW(mema+(4*i)); /* get data word */ + sim_debug(DEBUG_CMD, dptr, + "mt_srv INCH buffer addr %06x, wd %02x data %08x\n", + mema+(4*i), 4*i, data); + /* zero the data */ + if (i == 8) + WMW(mema+(4*i),0x00050005); /* show we are a BTP */ + else + WMW(mema+(4*i),0); /* zero work location */ + } /* the chp->ccw_addr location contains the inch address */ /* call set_inch() to setup inch buffer */ i = set_inch(uptr, mema); /* new address */ -#ifdef NOTYET +#ifndef NOTYET if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ /* we have error, bail out */ uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ @@ -573,6 +597,11 @@ t_stat mt_srv(UNIT *uptr) break; } #endif + /* set halfwords 16 & 17 to 5 as default retry count in inch data */ + /* UTX uses this value to see if the device is a buffered tape processor */ + /* they must be non-zero and equal to be BTP */ + WMH(mema+(16*2),5); /* write left HW with count */ + WMH(mema+(17*2),5); /* write right HW with count */ sim_debug(DEBUG_CMD, dptr, "mt_srv cmd INCH chsa %04x addr %06x count %04x completed\n", addr, mema, chp->ccw_count); @@ -596,15 +625,44 @@ t_stat mt_srv(UNIT *uptr) ch = (uptr->SNS >> 0) & 0xff; /* get sense byte 3 status */ sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 3 %02x\n", unit, ch); chan_write_byte(addr, &ch); /* write byte 3 */ +#ifdef TRYTHIS + /* write zero extra status */ for (ch=4; ch < 0xc; ch++) { -// chan_write_byte(addr, &ch); /* write byte */ + uint8 zc = 0; chan_write_byte(addr, &zc); /* write zero byte */ } +#else + /* write status 2 more times */ + ch = (uptr->SNS >> 24) & 0xff; /* get sense byte 0 status */ + sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 0 %02x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 0 */ + ch = (uptr->SNS >> 16) & 0xff; /* get sense byte 1 status */ + sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 1 %02x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 1 */ + ch = (uptr->SNS >> 8) & 0xff; /* get sense byte 2 status */ + sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 2 %02x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 2 */ + ch = (uptr->SNS >> 0) & 0xff; /* get sense byte 3 status */ + sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 3 %02x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 3 */ + ch = (uptr->SNS >> 24) & 0xff; /* get sense byte 0 status */ + sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 0 %02x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 0 */ + ch = (uptr->SNS >> 16) & 0xff; /* get sense byte 1 status */ + sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 1 %02x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 1 */ + ch = (uptr->SNS >> 8) & 0xff; /* get sense byte 2 status */ + sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 2 %02x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 2 */ + ch = (uptr->SNS >> 0) & 0xff; /* get sense byte 3 status */ + sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 3 %02x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 3 */ +#endif uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ mt_busy[bufnum] &= ~1; /* make our buffer not busy */ - chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ sim_debug(DEBUG_CMD, &mta_dev, "mt_srv DIAG SNS %08x char complete unit=%02x\n", uptr->SNS, unit); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ break; #endif @@ -631,9 +689,9 @@ t_stat mt_srv(UNIT *uptr) ch = 4; uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ mt_busy[bufnum] &= ~1; /* make our buffer not busy */ - chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ sim_debug(DEBUG_CMD, &mta_dev, "mt_srv SENSE %08x char complete unit=%02x\n", uptr->SNS, unit); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ break; case MT_READ: /* 0x02 */ /* read a record from the device */ @@ -646,10 +704,10 @@ t_stat mt_srv(UNIT *uptr) uptr->CMD &= ~(MT_CMDMSK|MT_READDONE); /* clear all but readdone & cmd */ uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ mt_busy[bufnum] &= ~1; /* not busy anymore */ - chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* set chan end, dev end status */ sim_debug(DEBUG_CMD, &mta_dev, "mt_srv READ %04x char complete unit=%02x sense %08x\n", uptr->POS, unit, uptr->SNS); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* set chan end, dev end status */ break; } /* read is not completed, get an input char */ @@ -657,7 +715,7 @@ t_stat mt_srv(UNIT *uptr) if (BUF_EMPTY(uptr)) { /* buffer is empty, so fill it with next record data */ if ((r = sim_tape_rdrecf(uptr, &mt_buffer[bufnum][0], &reclen, BUFFSIZE)) != MTSE_OK) { - sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv READ fill buffer unit=%02x\n", unit); + sim_debug(DEBUG_CMD, &mta_dev, "mt_srv READ fill buffer unit=%02x\n", unit); uptr->CMD &= ~(MT_CMDMSK|MT_READDONE); /* clear all but readdone & cmd */ return mt_error(uptr, addr, r, dptr); /* process any error & return status */ } @@ -954,8 +1012,8 @@ t_stat mt_srv(UNIT *uptr) case 3: uptr->CMD &= ~(MT_CMDMSK); mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_DEVEND|SNS_UNITEXP); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); sim_debug(DEBUG_CMD, &mta_dev, "Skip record at EOF\n"); + chan_end(addr, SNS_DEVEND|SNS_UNITEXP); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); break; case 4: uptr->CMD &= ~(MT_CMDMSK); @@ -1128,8 +1186,8 @@ t_stat mt_boot(int32 unit_num, DEVICE *dptr) sim_debug(DEBUG_EXP, &mta_dev, "MT Boot dev/unit %04x\n", GET_UADDR(uptr->CMD)); if ((uptr->flags & UNIT_ATT) == 0) { /* Is MT device already attached? */ - sim_debug(DEBUG_EXP, &mta_dev, "MT Boot attach error dev/unit %04x\n", - GET_UADDR(uptr->CMD)); + sim_debug(DEBUG_EXP, &mta_dev, + "MT Boot attach error dev/unit %04x\n", GET_UADDR(uptr->CMD)); return SCPE_UNATT; /* not attached, return error */ } SPAD[0xf4] = GET_UADDR(uptr->CMD); /* put boot device chan/sa into spad */ diff --git a/SEL32/sel32_scfi.c b/SEL32/sel32_scfi.c index 93bdff4..c2d1708 100644 --- a/SEL32/sel32_scfi.c +++ b/SEL32/sel32_scfi.c @@ -246,9 +246,9 @@ scfi_type[] = uint8 scfi_preio(UNIT *uptr, uint16 chan); uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); -uint8 scfi_haltio(uint16 addr); +uint8 scfi_haltio(UNIT *uptr); t_stat scfi_srv(UNIT *); -t_stat scfi_boot(int32, DEVICE *); +t_stat scfi_boot(int32 unitnum, DEVICE *); void scfi_ini(UNIT *, t_bool); t_stat scfi_reset(DEVICE *); t_stat scfi_attach(UNIT *, CONST char *); @@ -304,6 +304,7 @@ DEVICE sda_dev = { "SDA", sda_unit, NULL, scfi_mod, NUM_UNITS_SCFI, 16, 24, 4, 16, 32, NULL, NULL, &scfi_reset, &scfi_boot, &scfi_attach, &scfi_detach, + /* ctxt is the DIB pointer */ &sda_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, NULL, NULL, &scfi_help, NULL, NULL, &scfi_description }; @@ -347,6 +348,7 @@ DEVICE sdb_dev = { "SDB", sdb_unit, NULL, scfi_mod, NUM_UNITS_SCFI, 16, 24, 4, 16, 32, NULL, NULL, &scfi_reset, &scfi_boot, &scfi_attach, &scfi_detach, + /* ctxt is the DIB pointer */ &sdb_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, NULL, NULL, &scfi_help, NULL, NULL, &scfi_description }; @@ -682,6 +684,8 @@ rezero: /* just seek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* seek home */ sim_debug(DEBUG_DETAIL, dptr, "scfi_srv Error on seek to %08x\n", tstart); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; } /* Check if already on correct cylinder */ @@ -963,6 +967,7 @@ int scfi_format(UNIT *uptr) { /* seek to sector 0 */ if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ fprintf (stderr, "Error on seek to 0\r\n"); + return 1; } /* get buffer for track data */ @@ -996,7 +1001,10 @@ int scfi_format(UNIT *uptr) { fputc('\r', stderr); fputc('\n', stderr); /* seek home again */ - sim_fseek(uptr->fileref, 0, SEEK_SET); /* seek home */ + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + fprintf (stderr, "Error on seek to 0\r\n"); + return 1; + } free(buff); /* free cylinder buffer */ set_devattn(addr, SNS_DEVEND); /* start us up */ return 0; diff --git a/SEL32/sel32_scsi.c b/SEL32/sel32_scsi.c new file mode 100644 index 0000000..6f2a0e6 --- /dev/null +++ b/SEL32/sel32_scsi.c @@ -0,0 +1,1160 @@ +/* sel32_scsi.c: SEL-32 MFP SCSI Disk controller + + Copyright (c) 2018-2020, James C. Bevier + Portions provided by Richard Cornwell and other SIMH contributers + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + JAMES C. BEVIER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "sel32_defs.h" + +extern t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +extern t_stat show_dev_addr(FILE * st, UNIT *uptr, int32 v, CONST void *desc); +extern void chan_end(uint16 chan, uint8 flags); +extern int chan_read_byte(uint16 chsa, uint8 *data); +extern int chan_write_byte(uint16 chsa, uint8 *data); +extern void set_devattn(uint16 addr, uint8 flags); +extern t_stat chan_boot(uint16 addr, DEVICE *dptr); +extern int test_write_byte_end(uint16 chsa); +extern DEVICE *get_dev(UNIT *uptr); +extern t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */ +extern CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */ + +extern uint32 M[]; /* our memory */ +extern uint32 SPAD[]; /* cpu SPAD memory */ + +#ifdef NUM_DEVS_SCSI + +#define UNIT_SCSI UNIT_ATTABLE | UNIT_IDLE | UNIT_DISABLE + +/* useful conversions */ +/* Fill STAR value from cyl, trk, sec data */ +#define CHS2STAR(c,h,s) (((c<<16) & 0xffff0000)|((h<<8) & 0xff00)|(s & 0xff)) +/* convert STAR value to number of sectors */ +#define STAR2SEC(star,spt,spc) ((star&0xff)+(((star>>8)&0xff)*spt)+((star>>16)*spc)) +/* convert STAR value to number of heads or tracks */ +#define STAR2TRK(star,tpc) ((star >> 16) * tpc + ((star >> 8) & 0x0ff)) +/* convert STAR value to number of cylinders */ +#define STAR2CYL(star) ((star >> 16) & 0xffff) +/* convert byte value to number of sectors mod sector size */ +#define BYTES2SEC(bytes,ssize) (((bytes) + (ssize-1)) >> 10) +/* get sectors per track for specified type */ +#define SPT(type) (scsi_type[type].spt) +/* get sectors per cylinderfor specified type */ +#define SPC(type) (scsi_type[type].spt*scsi_type[type].nhds) +/* get number of cylinders for specified type */ +#define CYL(type) (scsi_type[type].cyl) +/* get number of heads for specified type */ +#define HDS(type) (scsi_type[type].nhds) +/* get disk capacity in sectors for specified type */ +#define CAP(type) (CYL(type)*HDS(type)*SPT(type)) +/* get number of bytes per sector for specified type */ +#define SSB(type) (scsi_type[type].ssiz*4) +/* get disk capacity in bytes for specified type */ +#define CAPB(type) (CAP(type)*SSB(type)) +/* get disk geometry as STAR value for specified type */ +#define GEOM(type) (CHS2STAR(CYL(type),HDS(type),SPT(type))) + +/* INCH command information */ +/* +WD 0 - Data address +WD 1 - Flags - 0 -36 byte count + +Data - 224 word INCH buffer address (SST) +WD 1 Drive 0 Attribute register +WD 2 Drive 1 Attribute register +WD 3 Drive 2 Attribute register +WD 4 Drive 3 Attribute register +WD 5 Drive 4 Attribute register +WD 6 Drive 5 Attribute register +WD 7 Drive 6 Attribute register +WD 8 Drive 7 Attribute register + +Memory attribute register layout +bits 0-7 - Flags + bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option + bit 2 - 1=Cartridge module drive + bit 3 - 0=Reserved + bit 4 - 1=Drive not present + bit 5 - 1=Dual Port + bit 6 - 0=Reserved + bit 7 - 0=Reserved +bits 8-15 - sector count (sectors per track)(F16=16, F20=20) +bits 16-23 - MHD Head count (number of heads on MHD) +bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option of + mini-module) +*/ + + +/* 224 word INCH Buffer layout */ +/* 128 word subchannel status storage (SST) */ +/* 66 words of program status queue (PSQ) */ +/* 26 words of scratchpad */ +/* 4 words of label buffer registers */ + +#define CMD u3 +/* u3 */ +/* in u3 is device command code and status */ +#define DSK_CMDMSK 0x00ff /* Command being run */ +#define DSK_STAR 0x0100 /* STAR value in u4 */ +#define DSK_NU2 0x0200 /* */ +#define DSK_READDONE 0x0400 /* Read finished, end channel */ +#define DSK_ENDDSK 0x0800 /* Sensed end of disk */ +#define DSK_SEEKING 0x1000 /* Disk is currently seeking */ +#define DSK_READING 0x2000 /* Disk is reading data */ +#define DSK_WRITING 0x4000 /* Disk is writing data */ +#define DSK_BUSY 0x8000 /* Disk is busy */ +/* commands */ +#define DSK_INCH 0x00 /* Initialize channel */ +#define DSK_INCH2 0xf0 /* Initialize channel for processing */ +#define DSK_WD 0x01 /* Write data */ +#define DSK_RD 0x02 /* Read data */ +#define DSK_NOP 0x03 /* No operation */ +#define DSK_SNS 0x04 /* Sense */ +#define DSK_SCK 0x07 /* Seek cylinder, track, sector */ +#define DSK_TIC 0x08 /* Transfer in channel */ +#define DSK_FNSK 0x0B /* Format for no skip */ +#define DSK_LPL 0x13 /* Lock protected label */ +#define DSK_LMR 0x1F /* Load mode register */ +#define DSK_RES 0x23 /* Reserve */ +#define DSK_WSL 0x31 /* Write sector label */ +#define DSK_RSL 0x32 /* Read sector label */ +#define DSK_REL 0x33 /* Release */ +#define DSK_XEZ 0x37 /* Rezero */ +#define DSK_POR 0x43 /* Priority Override */ +#define DSK_IHA 0x47 /* Increment head address */ +#define DSK_SRM 0x4F /* Set reserve track mode */ +#define DSK_WTL 0x51 /* Write track label */ +#define DSK_RTL 0x52 /* Read track label */ +#define DSK_XRM 0x5F /* Reset reserve track mode */ +#define DSK_RAP 0xA2 /* Read angular positions */ +#define DSK_TESS 0xAB /* Test STAR (subchannel target address register) */ +#define DSK_ICH 0xFF /* Initialize Controller */ + +#define STAR u4 +/* u4 - sector target address register (STAR) */ +/* Holds the current cylinder, head(track), sector */ +#define DISK_CYL 0xFFFF0000 /* cylinder mask */ +#define DISK_TRACK 0x0000FF00 /* track mask */ +#define DISK_SECTOR 0x000000ff /* sector mask */ + +#define SNS u5 +/* u5 */ +/* Sense byte 0 - mode register */ +#define SNS_DROFF 0x80000000 /* Drive Carriage will be offset */ +#define SNS_TRKOFF 0x40000000 /* Track offset: 0=positive, 1=negative */ +#define SNS_RDTMOFF 0x20000000 /* Read timing offset = 1 */ +#define SNS_RDSTRBT 0x10000000 /* Read strobe timing: 1=positive, 0=negative */ +#define SNS_DIAGMOD 0x08000000 /* Diagnostic Mode ECC Code generation and checking */ +#define SNS_RSVTRK 0x04000000 /* Reserve Track mode: 1=OK to write, 0=read only */ +#define SNS_FHDOPT 0x02000000 /* FHD or FHD option = 1 */ +#define SNS_RESERV 0x01000000 /* Reserved */ + +/* Sense byte 1 */ +#define SNS_CMDREJ 0x800000 /* Command reject */ +#define SNS_INTVENT 0x400000 /* Unit intervention required */ +#define SNS_SPARE1 0x200000 /* Spare */ +#define SNS_EQUCHK 0x100000 /* Equipment check */ +#define SNS_DATCHK 0x080000 /* Data Check */ +#define SNS_OVRRUN 0x040000 /* Data overrun/underrun */ +#define SNS_DSKFERR 0x020000 /* Disk format error */ +#define SNS_DEFTRK 0x010000 /* Defective track encountered */ + +/* Sense byte 2 */ +#define SNS_LAST 0x8000 /* Last track flag encountered */ +#define SNS_AATT 0x4000 /* At Alternate track */ +#define SNS_WPER 0x2000 /* Write protection error */ +#define SNS_WRL 0x1000 /* Write lock error */ +#define SNS_MOCK 0x0800 /* Mode check */ +#define SNS_INAD 0x0400 /* Invalid memory address */ +#define SNS_RELF 0x0200 /* Release fault */ +#define SNS_CHER 0x0100 /* Chaining error */ + +/* Sense byte 3 */ +#define SNS_REVL 0x80 /* Revolution lost */ +#define SNS_DADE 0x40 /* Disc addressing or seek error */ +#define SNS_BUCK 0x20 /* Buffer check */ +#define SNS_ECCS 0x10 /* ECC error in sector label */ +#define SNS_ECCD 0x08 /* ECC error iin data */ +#define SNS_ECCT 0x04 /* ECC error in track label */ +#define SNS_RTAE 0x02 /* Reserve track access error */ +#define SNS_UESS 0x01 /* Uncorrectable ECC error */ + +#define CHS u6 +/* u6 holds the current cyl, hd, sec for the drive */ + +/* this attribute information is provided by the INCH command */ +/* for each device and is not used. It is reconstructed from */ +/* the disk_t structure data for the assigned disk */ +/* +bits 0-7 - Flags + bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option + bit 2 - 1=Cartridge module drive + bit 3 - 0=Reserved + bit 4 - 1=Drive not present + bit 5 - 1=Dual Port + bit 6 - 0=Reserved 00 768 byte sec + bit 7 - 0=Reserved 01 1024 byte sec +bits 8-15 - sector count (sectors per track)(F16=16, F20=20) +bits 16-23 - MHD Head count (number of heads on MHD) +bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option of + mini-module) +*/ + +/* Not Used up7 */ + +/* disk definition structure */ +struct scsi_t +{ + const char *name; /* Device ID Name */ + uint16 nhds; /* Number of heads */ + uint16 ssiz; /* sector size in words */ + uint16 spt; /* # sectors per track(cylinder) */ + uint16 ucyl; /* Number of cylinders used */ + uint16 cyl; /* Number of cylinders on disk */ + uint8 type; /* Device type code */ + /* bit 1 mhd */ + /* bits 6/7 = 0 768 byte blk */ /* not used on UDP/DPII */ + /* = 1 1024 byte blk */ /* not used on UDP/DPII */ +} + +scsi_type[] = +{ + /* Class F Disc Devices */ + /* MPX SCSI disks for SCSI controller */ + {"MH1GB", 1, 192, 40, 34960, 34960, 0x40}, /*0 69920 1000M */ + {"SG038", 1, 192, 20, 2190, 2190, 0x40}, /*1 21900 38M */ + {"SG120", 1, 192, 40, 34970, 34970, 0x40}, /*2 69940 1200M */ + {"SG076", 1, 192, 20, 46725, 46725, 0x40}, /*3 46725 760M */ + {NULL, 0} +}; + +uint8 scsi_preio(UNIT *uptr, uint16 chan); +uint8 scsi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); +uint8 scsi_haltio(UNIT *uptr); +t_stat scsi_srv(UNIT *); +t_stat scsi_boot(int32 unitnum, DEVICE *); +void scsi_ini(UNIT *, t_bool); +t_stat scsi_reset(DEVICE *); +t_stat scsi_attach(UNIT *, CONST char *); +t_stat scsi_detach(UNIT *); +t_stat scsi_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat scsi_get_type(FILE * st, UNIT *uptr, int32 v, CONST void *desc); +t_stat scsi_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +const char *scsi_description (DEVICE *dptr); + +/* channel program information */ +CHANP sda_chp[NUM_UNITS_SCSI] = {0}; + +MTAB scsi_mod[] = { + {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "TYPE", "TYPE", + &scsi_set_type, &scsi_get_type, NULL, "Type of disk"}, + {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, + &show_dev_addr, NULL, "Device channel address"}, + {0} +}; + +UNIT sda_unit[] = { +/* SET_TYPE(2) SG120 */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x400)}, /* 0 */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x410)}, /* 1 */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x420)}, /* 2 */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x430)}, /* 3 */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x440)}, /* 4 */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x450)}, /* 5 */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x460)}, /* 6 */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x470)}, /* 7 */ +}; + +//DIB sda_dib = {scsi_preio, scsi_startcmd, NULL, NULL, NULL, scsi_ini, sda_unit, sda_chp, NUM_UNITS_SCSI, 0x0f, 0x0400, 0, 0, 0}; + +DIB sda_dib = { + scsi_preio, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ + scsi_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ + NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ + NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ + scsi_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ + sda_unit, /* UNIT* units */ /* Pointer to units structure */ + sda_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NUM_UNITS_SCSI, /* uint8 numunits */ /* number of units defined */ + 0xF0, /* uint8 mask */ /* 16 devices - device mask */ + 0x0400, /* uint16 chan_addr */ /* parent channel address */ + 0, /* uint32 chan_fifo_in */ /* fifo input index */ + 0, /* uint32 chan_fifo_out */ /* fifo output index */ + {0} /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ +}; + +DEVICE sda_dev = { + "SDA", sda_unit, NULL, scsi_mod, + NUM_UNITS_SCSI, 16, 24, 4, 16, 32, + NULL, NULL, &scsi_reset, &scsi_boot, &scsi_attach, &scsi_detach, + /* ctxt is the DIB pointer */ + &sda_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, + NULL, NULL, &scsi_help, NULL, NULL, &scsi_description +}; + +#if NUM_DEVS_SCSI > 1 +/* channel program information */ +CHANP sdb_chp[NUM_UNITS_SCSI] = {0}; + +UNIT sdb_unit[] = { +/* SET_TYPE(0) DM1GB */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC00)}, /* 0 */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC10)}, /* 1 */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC20)}, /* 2 */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC30)}, /* 3 */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC40)}, /* 4 */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC50)}, /* 5 */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC60)}, /* 6 */ + {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC70)}, /* 7 */ +}; + +//DIB sdb_dib = {scsi_preio, scsi_startcmd, NULL, NULL, NULL, scsi_ini, sdb_unit, sdb_chp, NUM_UNITS_SCSI, 0x0f, 0x0c00, 0, 0, 0}; + +DIB sdb_dib = { + scsi_preio, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ + scsi_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ + NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ + NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ + scsi_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ + sdb_unit, /* UNIT* units */ /* Pointer to units structure */ + sdb_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NUM_UNITS_SCSI, /* uint8 numunits */ /* number of units defined */ + 0xF0, /* uint8 mask */ /* 16 devices - device mask */ + 0x0C00, /* uint16 chan_addr */ /* parent channel address */ + 0, /* uint32 chan_fifo_in */ /* fifo input index */ + 0, /* uint32 chan_fifo_out */ /* fifo output index */ + 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ +}; + +DEVICE sdb_dev = { + "SDB", sdb_unit, NULL, scsi_mod, + NUM_UNITS_SCSI, 16, 24, 4, 16, 32, + NULL, NULL, &scsi_reset, &scsi_boot, &scsi_attach, &scsi_detach, + /* ctxt is the DIB pointer */ + &sdb_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, + NULL, NULL, &scsi_help, NULL, NULL, &scsi_description +}; +#endif + +/* convert sector disk address to star values (c,h,s) */ +uint32 scsisec2star(uint32 daddr, int type) +{ + int32 sec = daddr % scsi_type[type].spt; /* get sector value */ + int32 spc = scsi_type[type].nhds * scsi_type[type].spt; /* sec per cyl */ + int32 cyl = daddr / spc; /* cylinders */ + int32 hds = (daddr % spc) / scsi_type[type].spt; /* heads */ + + /* now return the star value */ + return (CHS2STAR(cyl,hds,sec)); /* return STAR */ +} + +/* start a disk operation */ +uint8 scsi_preio(UNIT *uptr, uint16 chan) +{ + DEVICE *dptr = get_dev(uptr); + uint16 chsa = GET_UADDR(uptr->CMD); + int unit = (uptr - dptr->units); + + sim_debug(DEBUG_CMD, dptr, "scsi_preio CMD %08x unit=%02x\n", uptr->CMD, unit); + if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */ + return SNS_BSY; + } + sim_debug(DEBUG_CMD, dptr, "scsi_preio unit %02x chsa %04x OK\n", unit, chsa); + return 0; /* good to go */ +} + +uint8 scsi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) +{ + uint16 addr = GET_UADDR(uptr->CMD); + DEVICE *dptr = get_dev(uptr); + int unit = (uptr - dptr->units); + CHANP *chp = find_chanp_ptr(addr); /* find the chanp pointer */ + + sim_debug(DEBUG_CMD, dptr, + "scsi_startcmd unit %02x cmd %04x CMD %08x\n", + unit, cmd, uptr->CMD); + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + uptr->SNS |= SNS_INTVENT; /* unit intervention required */ + if (cmd != DSK_SNS) /* we are completed with unit check status */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + } + + if ((uptr->CMD & DSK_CMDMSK) != 0) { + uptr->CMD |= DSK_BUSY; /* Flag we we are busy */ + return SNS_BSY; + } + if ((uptr->CMD & 0xff00) != 0) { /* if any status info, we are busy */ + return SNS_BSY; + } + sim_debug(DEBUG_CMD, dptr, "scsi_startcmd CMD 2 unit=%02x cmd %02x\n", unit, cmd); + + /* Unit is online, so process a command */ + switch (cmd) { + + case DSK_INCH: /* INCH 0x00 */ + sim_debug(DEBUG_CMD, dptr, + "scsi_startcmd starting INCH %06x cmd, chsa %04x MemBuf %08x cnt %04x\n", + uptr->u4, addr, chp->ccw_addr, chp->ccw_count); + + uptr->CMD |= DSK_INCH2; /* use 0xf0 for inch, just need int */ + sim_activate(uptr, 20); /* start things off */ + return 0; + break; + + case DSK_SCK: /* Seek command 0x07 */ + case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ + case DSK_WD: /* Write command 0x01 */ + case DSK_RD: /* Read command 0x02 */ + case DSK_LMR: /* read mode register */ + + uptr->CMD |= cmd; /* save cmd */ + sim_debug(DEBUG_CMD, dptr, + "scsi_startcmd starting disk seek r/w cmd %02x addr %04x\n", cmd, addr); + sim_activate(uptr, 20); /* start things off */ + return 0; + break; + + case DSK_NOP: /* NOP 0x03 */ + uptr->CMD |= cmd; /* save cmd */ + sim_activate(uptr, 20); /* start things off */ + return 0; + break; + + case DSK_SNS: /* Sense 0x04 */ + uptr->CMD |= cmd; /* save cmd */ + sim_activate(uptr, 20); /* start things off */ + return 0; + break; + } + sim_debug(DEBUG_CMD, dptr, + "scsi_startcmd done with scsi_startcmd %02x addr %04x SNS %08x\n", + cmd, addr, uptr->SNS); + if (uptr->SNS & 0xff) /* any other cmd is error */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + sim_activate(uptr, 20); /* start things off */ + return SNS_CHNEND|SNS_DEVEND; +} + +/* Handle processing of disk requests. */ +t_stat scsi_srv(UNIT *uptr) +{ + uint16 chsa = GET_UADDR(uptr->CMD); + DEVICE *dptr = get_dev(uptr); + /* get pointer to Dev Info Blk for this device */ + DIB *dibp = (DIB *)dptr->ctxt; + CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */ + int cmd = uptr->CMD & DSK_CMDMSK; + int type = GET_TYPE(uptr->flags); + uint32 trk, cyl, sec; + int unit = (uptr - dptr->units); + int len=0; + int i; + uint8 ch; + uint16 ssize = scsi_type[type].ssiz*4; /* Size of one sector in bytes */ + int32 tstart = 0; /* Location of start of cyl/track/sect in data */ + uint8 buf2[1024]; + uint8 buf[1024]; + + sim_debug(DEBUG_DETAIL, &sda_dev, + "scsi_srv entry unit %02x CMD %08x chsa %04x count %04x %x/%x/%x \n", + unit, uptr->CMD, chsa, chp->ccw_count, + STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); + + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + uptr->SNS |= SNS_INTVENT; /* unit intervention required */ + if (cmd != DSK_SNS) /* we are completed with unit check status */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + } + + sim_debug(DEBUG_CMD, dptr, + "scsi_srv cmd=%02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); + switch (cmd) { + case 0: /* No command, stop disk */ + break; + + case DSK_INCH2: /* use 0xff for inch, just need int */ + { + uint32 mema; /* memory address */ +// uint32 daws[8]; /* drive attribute registers */ +// uint32 i, j; + uint32 i; + + len = chp->ccw_count; /* INCH command count */ + mema = chp->ccw_addr; /* get inch or buffer addr */ + sim_debug(DEBUG_CMD, dptr, + "scsi_srv starting INCH cmd, chsa %04x MemBuf %06x cnt %04x\n", + chsa, chp->ccw_addr, chp->ccw_count); + + /* mema has IOCD word 1 contents. For the disk processor it contains */ + /* a pointer to the INCH buffer followed by 8 drive attribute words that */ + /* contains the flags, sector count, MHD head count, and FHD count */ + /* len has the byte count from IOCD wd2 and should be 0x24 (36) */ + /* the INCH buffer address must be set for the parrent channel as well */ + /* as all other devices on the channel. Call set_inch() to do this for us */ + /* just return OK and channel software will use u4 as status buffer addr */ + + len = chp->ccw_count; /* INCH command count */ + + if (len != 36) { + /* we have invalid count, error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + + /* read all 36 bytes, stopping every 4 bytes to make words */ + /* the first word has the inch buffer address */ + /* the next 8 words have drive data for each unit */ + /* WARNING 8 drives must be defined for this controller */ + /* so we will not have a map fault */ +// for (i=0, j=0; i < 36; i++) { + for (i=0; i < 36; i++) { + if (chan_read_byte(chsa, &buf[i])) { + /* we have error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (((i+1)%4) == 0) { /* see if we have a word yet */ + if (i == 3) + /* inch buffer address */ + mema = (buf[0]<<24) | (buf[1]<<16) | + (buf[2]<<8) | (buf[3]); + else + /* drive attribute registers */ +// daws[j++] = (buf[i-3]<<24) | (buf[i-2]<<16) +// | (buf[i-1]<<8) | (buf[i]); + /* may want to use this later */ + /* clear warning errors */ + tstart = (buf[i-3]<<24) | (buf[i-2]<<16) + | (buf[i-1]<<8) | (buf[i]); + } + } + /* now call set_inch() function to write and test inch bybber addresses */ + i = set_inch(uptr, mema); /* new address */ +#ifdef NOTYET + if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ + /* we have error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } +#endif + uptr->CMD &= ~(0xffff); /* remove old cmd */ + sim_debug(DEBUG_CMD, dptr, + "scsi_srv cmd INCH chsa %04x addr %06x count %04x completed\n", + chsa, mema, chp->ccw_count); +#ifdef FIX4MPX + chan_end(chsa, SNS_CHNEND); /* return just channel end OK */ +#else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ +#endif + } + break; + + case DSK_NOP: /* NOP 0x03 */ + uptr->CMD &= ~(0xffff); /* remove old cmd */ + sim_debug(DEBUG_CMD, dptr, + "scsi_srv cmd NOP chsa %04x count %04x completed\n", + chsa, chp->ccw_count); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case DSK_SNS: /* 0x4 */ + ch = uptr->SNS & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "scsi_srv sense unit=%02x 1 %02x\n", unit, ch); + chan_write_byte(chsa, &ch) ; + ch = (uptr->SNS >> 8) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "scsi_srv sense unit=%02x 2 %02x\n", unit, ch); + chan_write_byte(chsa, &ch) ; + ch = 0; + sim_debug(DEBUG_DETAIL, dptr, "scsi_srv sense unit=%02x 3 %02x\n", unit, ch); + chan_write_byte(chsa, &ch) ; + ch = unit; + sim_debug(DEBUG_DETAIL, dptr, "scsi_srv sense unit=%02x 4 %02x\n", unit, ch); + chan_write_byte(chsa, &ch) ; + ch = 4; + sim_debug(DEBUG_CMD, dptr, "DISK SENSE %02x chars complete %08x, unit %02x\n", + ch, uptr->SNS, unit); + uptr->CMD &= ~(0xff00); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; + + case DSK_SCK: /* Seek cylinder, track, sector 0x07 */ + /* If we are waiting on seek to finish, check if there yet. */ + if (uptr->CMD & DSK_SEEKING) { + /* see if on cylinder yet */ + if (STAR2CYL(uptr->STAR) == STAR2CYL(uptr->CHS)) { + /* we are on cylinder, seek is done */ + sim_debug(DEBUG_CMD, dptr, "scsi_srv seek on cylinder unit=%02x %04x %04x\n", + unit, uptr->STAR >> 16, uptr->CHS >> 16); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + /* we have already seeked to the required sector */ + /* we do not need to seek again, so move on */ + chan_end(chsa, SNS_DEVEND|SNS_CHNEND); + sim_activate(uptr, 20); + break; + } else { + /* we have wasted enough time, we there */ + uptr->CHS = uptr->STAR; /* we are there */ + sim_activate(uptr, 10); + break; + } + } + + /* not seeking, so start a new seek */ + /* Read in 4 character seek code */ + for (i = 0; i < 4; i++) { + if (chan_read_byte(chsa, &buf[i])) { + /* we have error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + } + /* the value is really a sector offset for the disk */ + /* but will treat as c/h/s for processing */ + /* the cyl, trk, and sect are ready to update */ + sim_debug(DEBUG_CMD, dptr, + "scsi_srv STAR unit=%02x star %02x %02x %02x %02x\n", + unit, buf[0], buf[1], buf[2], buf[3]); +rezero: + sim_debug(DEBUG_DETAIL, dptr, + "scsi_srv seek unit=%02x star %02x %02x %02x %02x\n", + unit, buf[0], buf[1], buf[2], buf[3]); + + /* save STAR (target sector) data in STAR */ + uptr->STAR = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]); + cyl = STAR2CYL(uptr->STAR); /* get the cylinder */ + trk = buf[2]; /* get the track */ + + sim_debug(DEBUG_DETAIL, dptr, + "scsi_srv SEEK %08x cyl %04x trk %02x sec %02x unit=%02x\n", + uptr->CMD, cyl&0xffff, trk, buf[3], unit); + + /* Check if seek valid */ + if (cyl >= scsi_type[type].cyl || + trk >= scsi_type[type].nhds || + buf[3] >= scsi_type[type].spt) { + + sim_debug(DEBUG_CMD, dptr, + "dsk_srv seek ERROR cyl %04x trk %02x sec %02x unit=%02x\n", + cyl, trk, buf[3], unit); + + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; /* set error status */ + + /* we have an error, tell user */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* end command */ + break; + } + + /* calc the new sector address of data */ + /* calculate file position in bytes of requested sector */ + /* file offset in bytes */ + tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type); + uptr->CHS = CHS2STAR(STAR2CYL(uptr->CHS), trk, buf[3]); + + sim_debug(DEBUG_DETAIL, dptr, + "scsi_srv seek start %08x trk %04x sec %02x\n", + tstart, trk, buf[3]); + + /* just seek to the location where we will r/w data */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* seek home */ + sim_debug(DEBUG_DETAIL, dptr, "scsi_srv Error on seek to %08x\n", tstart); + } + + /* Check if already on correct cylinder */ + /* if not, do a delay to slow things down */ + if (STAR2CYL(uptr->STAR) != STAR2CYL(uptr->CHS)) { + /* Do a fake seek to kill time */ + uptr->CMD |= DSK_SEEKING; /* show we are seeking */ + sim_debug(DEBUG_DETAIL, dptr, + "scsi_srv seeking unit=%02x to cyl %04x trk %04x sec %04x\n", + unit, cyl, trk, buf[3]); + sim_activate(uptr, 20); + } else { + /* we are on cylinder/track/sector, so go on */ + sim_debug(DEBUG_DETAIL, dptr, + "scsi_srv calc sect addr seek start %08x cyl %04x trk %04x sec %02x\n", + tstart, cyl, trk, buf[3]); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_DEVEND|SNS_CHNEND); + } + return SCPE_OK; + + case DSK_XEZ: /* Rezero & Read IPL record */ + + sim_debug(DEBUG_CMD, dptr, "RD REZERO IPL unit=%02x seek 0\n", unit); + /* Do a seek to 0 */ + uptr->STAR = 0; /* set STAR to 0, 0, 0 */ + uptr->CHS = 0; /* set current CHS to 0, 0, 0 */ + uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->CMD |= DSK_SCK; /* show as seek command */ + tstart = 0; /* byte offset is 0 */ + /* Read in 1 dummy character for length to inhibit SLI posting */ + if (chan_read_byte(chsa, &buf[0])) { + /* we have error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + /* zero stuff */ + buf[0] = buf[1] = buf[2] = buf[3] = 0; + goto rezero; /* merge with seek code */ + break; + + case DSK_LMR: + sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x\n", unit); + /* Read in 1 character of mode data */ + if (chan_read_byte(chsa, &buf[0])) { + /* we have error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x old %x new %x\n", + unit, (uptr->SNS)&0xff, buf[0]); + uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->SNS &= 0x00ffffff; /* clear old mode data */ + uptr->SNS |= (buf[0] << 24); /* save mode value */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; + + case DSK_RD: /* Read Data */ + /* tstart has start of sector address in bytes */ + if ((uptr->CMD & DSK_READING) == 0) { /* see if we are reading data */ + uptr->CMD |= DSK_READING; /* read from disk starting */ + sim_debug(DEBUG_CMD, dptr, + "DISK READ starting unit=%02x CMD %08x count %04x\n", + unit, uptr->CMD, chp->ccw_count); + } + + if (uptr->CMD & DSK_READING) { /* see if we are reading data */ + cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ + sec = uptr->CHS & 0xff; /* get sec */ + /* get sector offset */ +// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)); + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + + /* read in a sector of data from disk */ + if ((len=sim_fread(buf, 1, ssize, uptr->fileref)) != ssize) { + sim_debug(DEBUG_CMD, dptr, + "Error %08x on read %04x of diskfile cyl %04x hds %02x sec %02x\n", + len, ssize, cyl, trk, sec); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + + sim_debug(DEBUG_CMD, dptr, "scsi_srv after READ chsa %04x count %04x\n", + chsa, chp->ccw_count); + + /* process the next sector of data */ + for (i=0; iCMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + goto rddone; + } + } + + sim_debug(DEBUG_CMD, dptr, + "DISK READ from sec end %04x bytes end %04x from diskfile /%04x/%02x/%02x tstart %08x\n", + len, ssize, cyl, trk, sec, tstart); + + /* tstart has file offset in sectors */ + tstart++; /* bump to next sector */ + /* convert sect back to chs value */ + uptr->CHS = scsisec2star(tstart, type); + /* see of over end of disk */ +// if (tstart >= CAPB(type)) { + if (tstart >= CAP(type)) { + /* EOM reached, abort */ + sim_debug(DEBUG_CMD, dptr, + "DISK Read reached EOM for read from disk @ /%04x/%02x/%02x\n", + STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CHS = 0; /* reset cylinder position */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + + /* see if we are done reading data */ + if (test_write_byte_end(chsa)) { + sim_debug(DEBUG_DATA, dptr, + "DISK Read complete Read %04x bytes from diskfile /%04x/%02x/%02x tstart %08x\n", + ssize, cyl, trk, sec, tstart); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; + } else { + sim_debug(DEBUG_DATA, dptr, + "DISK sector read complete, %x bytes to go from diskfile /%04x/%02x/%02x\n", + chp->ccw_count, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + sim_activate(uptr, 10); /* wait to read next sector */ + break; + } +rddone: + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + } + break; + + case DSK_WD: /* Write Data */ + /* tstart has start of sector address in bytes */ + + if ((uptr->CMD & DSK_WRITING) == 0) { /* see if we are writing data */ + uptr->CMD |= DSK_WRITING; /* write to disk starting */ + sim_debug(DEBUG_CMD, dptr, + "DISK WRITE starting unit=%02x CMD %08x bytes %04x\n", + unit, uptr->CMD, len); + } + if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */ + cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ + sec = uptr->CHS & 0xff; /* get sec */ + /* get sector offset */ +// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)); + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + + /* process the next sector of data */ + len = 0; /* used here as a flag for short read */ + for (i=0; iCMD &= ~(0xffff); /* remove old status bits & cmd */ + sim_debug(DEBUG_DATA, dptr, + "DISK Wrote %04x bytes to diskfile cyl %04x hds %02x sec %02x tstart %08x\n", + ssize, cyl, trk, sec, tstart); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + goto wrdone; + } + ch = 0; /* finish out the sector with zero */ + len++; /* show we have no more data to write */ + } + buf2[i] = ch; /* save the char */ + } + + /* write the sector to disk */ + if ((i=sim_fwrite(buf2, 1, ssize, uptr->fileref)) != ssize) { + sim_debug(DEBUG_CMD, dptr, + "Error %08x on write %04x to diskfile cyl %04x hds %02x sec %02x\n", + i, ssize, cyl, trk, sec); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (len != 0) { /* see if done with write command */ + sim_debug(DEBUG_DATA, dptr, + "DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x tstart %08x\n", + ssize, cyl, trk, sec, tstart); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ + break; + } + sim_debug(DEBUG_CMD, dptr, + "DISK WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x tstart %08x\n", + len, ssize, cyl, trk, sec, tstart); + + /* tstart has file offset in sectors */ + tstart++; /* bump to next sector */ + /* convert sect back to chs value */ + uptr->CHS = scsisec2star(tstart, type); + /* see of over end of disk */ +// if (tstart >= CAPB(type)) { + if (tstart >= CAP(type)) { + /* EOM reached, abort */ + sim_debug(DEBUG_CMD, dptr, + "DISK Write reached EOM for write to disk @ /%04x/%02x/%02x\n", + STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CHS = 0; /* reset cylinder position */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + sim_activate(uptr, 10); /* keep writing */ + break; +wrdone: + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + } + break; + + default: + sim_debug(DEBUG_CMD, dptr, "invalid command %02x unit %02x\n", cmd, unit); + uptr->SNS |= SNS_CMDREJ; + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + sim_debug(DEBUG_CMD, dptr, + "scsi_srv done cmd %02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); + return SCPE_OK; +} + +/* initialize the disk */ +void scsi_ini(UNIT *uptr, t_bool f) +{ + DEVICE *dptr = get_dev(uptr); + int i = GET_TYPE(uptr->flags); + + uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ + uptr->SNS = ((uptr->SNS & 0x00ffffff) | (scsi_type[i].type << 24)); /* save mode value */ + /* total sectors on disk */ + uptr->capac = CAP(i); /* disk size in sectors */ + + sim_debug(DEBUG_EXP, &sda_dev, "SDA init device %s on unit SDA%.1x cap %x\n", + dptr->name, GET_UADDR(uptr->CMD), uptr->CMD); +} + +t_stat scsi_reset(DEVICE * dptr) +{ + /* add reset code here */ + return SCPE_OK; +} + +/* create the disk file for the specified device */ +int scsi_format(UNIT *uptr) { +// struct ddata_t *data = (struct ddata_t *)uptr->up7; + uint16 addr = GET_UADDR(uptr->CMD); + int type = GET_TYPE(uptr->flags); + DEVICE *dptr = get_dev(uptr); + int32 ssize = scsi_type[type].ssiz * 4; /* disk sector size in bytes */ + uint32 tsize = scsi_type[type].spt; /* get track size in sectors */ + uint32 csize = scsi_type[type].nhds * tsize; /* get cylinder size in sectors */ + uint32 cyl = scsi_type[type].cyl; /* get # cyl */ +// uint16 spc = scsi_type[type].nhds * scsi_type[type].spt; /* sectors/cyl */ + uint32 cap = scsi_type[type].cyl * csize; /* disk capacity in sectors */ + uint32 cylv = cyl; /* number of cylinders */ + uint8 *buff; + + /* see if user wants to initialize the disk */ + if (!get_yn("Initialize disk? [Y] ", TRUE)) { + return 1; + } + + /* seek to sector 0 */ + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + fprintf (stderr, "Error on seek to 0\r\n"); + } + + /* get buffer for track data */ + if ((buff = (uint8 *)calloc(tsize*ssize, sizeof(uint8))) == 0) { + detach_unit(uptr); + return SCPE_ARG; + } + /* put dummy data in first word of disk */ + buff[0] = 'Z'; + buff[1] = 'E'; + buff[2] = 'R'; + buff[3] = 'O'; + sim_debug(DEBUG_CMD, dptr, + "Creating disk file of trk size %04x bytes, capacity %d\n", + tsize*ssize, cap*ssize); + /* write zeros to each track of the disk */ + for (cyl = 0; cyl < cylv; cyl++) { + if ((sim_fwrite(buff, 1, tsize*ssize, uptr->fileref)) != tsize*ssize) { + sim_debug(DEBUG_CMD, dptr, + "Error on write to diskfile cyl %04x\n", cyl); + } + if (cyl == 0) { + buff[0] = 0; + buff[1] = 0; + buff[2] = 0; + buff[3] = 0; + } + } + if ((cyl % 100) == 0) + fputc('.', stderr); + fputc('\r', stderr); + fputc('\n', stderr); + /* seek home again */ + sim_fseek(uptr->fileref, 0, SEEK_SET); /* seek home */ + free(buff); /* free cylinder buffer */ + set_devattn(addr, SNS_DEVEND); /* start us up */ + return 0; +} + +/* attach the selected file to the disk */ +t_stat scsi_attach(UNIT *uptr, CONST char *file) { + uint16 addr = GET_UADDR(uptr->CMD); + int type = GET_TYPE(uptr->flags); + DEVICE *dptr = get_dev(uptr); + t_stat r; + uint32 ssize; /* sector size in bytes */ + uint8 buff[1024]; + + if (scsi_type[type].name == 0) { /* does the assigned disk have a name */ + detach_unit(uptr); /* no, reject */ + return SCPE_FMT; /* error */ + } + + /* have simulator attach the file to the unit */ + if ((r = attach_unit(uptr, file)) != SCPE_OK) + return r; + + uptr->capac = CAP(type); /* disk capacity in sectors */ + ssize = SSB(type); /* get sector size in bytes */ + + sim_debug(DEBUG_CMD, dptr, "Disk %s cyl %d hds %d sec %d ssiz %d capacity %d\n", + scsi_type[type].name, scsi_type[type].cyl, scsi_type[type].nhds, + scsi_type[type].spt, ssize, uptr->capac); /* disk capacity */ + + + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ + } + + /* read in the 1st sector of the 'disk' */ + if ((r = sim_fread(&buff[0], sizeof(uint8), ssize, uptr->fileref) != ssize)) { + sim_debug(DEBUG_CMD, &sda_dev, "Disk format fread ret = %04x\n", r); + goto fmt; + } + + if ((buff[0] | buff[1] | buff[2] | buff[3]) == 0) { + sim_debug(DEBUG_CMD, &sda_dev, + "Disk format buf0 %02x buf1 %02x buf2 %02x buf3 %02x\n", + buff[0], buff[1], buff[2], buff[3]); +fmt: + /* format the drive */ + if (scsi_format(uptr)) { + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ + } + } + + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ + } + + uptr->CHS = 0; /* set CHS to cyl/hd/sec = 0 */ + + sim_debug(DEBUG_CMD, &sda_dev, + "Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\n", + scsi_type[type].name, CYL(type), HDS(type), SPT(type), SPC(type), + CAP(type), CAPB(type)); + + sim_debug(DEBUG_CMD, &sda_dev, "File %s attached to %s\r\n", + file, scsi_type[type].name); + + set_devattn(addr, SNS_DEVEND); + return SCPE_OK; +} + +/* detach a disk device */ +t_stat scsi_detach(UNIT *uptr) { + uptr->SNS = 0; /* clear sense data */ + uptr->CMD &= ~0xffff; /* no cmd and flags */ + return detach_unit(uptr); /* tell simh we are done with disk */ +} + +/* boot from the specified disk unit */ +t_stat scsi_boot(int32 unit_num, DEVICE *dptr) { + UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */ + + sim_debug(DEBUG_CMD, &sda_dev, "SCSI Disk Boot dev/unit %04x\n", GET_UADDR(uptr->CMD)); + SPAD[0xf4] = GET_UADDR(uptr->CMD); /* put boot device chan/sa into spad */ + SPAD[0xf8] = 0xF000; /* show as F class device */ + if ((uptr->flags & UNIT_ATT) == 0) + return SCPE_UNATT; /* attached? */ + return chan_boot(GET_UADDR(uptr->CMD), dptr); /* boot the ch/sa */ +} + +/* Disk option setting commands */ +t_stat scsi_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + int i; + + if (cptr == NULL) /* any disk name input? */ + return SCPE_ARG; /* arg error */ + if (uptr == NULL) /* valid unit? */ + return SCPE_IERR; /* no, error */ + if (uptr->flags & UNIT_ATT) /* is unit attached? */ + return SCPE_ALATT; /* no, error */ + + /* now loop through the units and find named disk */ + for (i = 0; scsi_type[i].name != 0; i++) { + if (strcmp(scsi_type[i].name, cptr) == 0) { + uptr->flags &= ~UNIT_TYPE; /* clear the old UNIT type */ + uptr->flags |= SET_TYPE(i); /* set the new type */ + /* set capacity of disk in sectors */ + uptr->capac = CAP(i); + return SCPE_OK; + } + } + return SCPE_ARG; +} + +t_stat scsi_get_type(FILE * st, UNIT *uptr, int32 v, CONST void *desc) +{ + if (uptr == NULL) + return SCPE_IERR; + fputs("TYPE=", st); + fputs(scsi_type[GET_TYPE(uptr->flags)].name, st); + return SCPE_OK; +} + +/* help information for disk */ +t_stat scsi_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, + const char *cptr) +{ + int i; + fprintf (st, "SEL-32 MFP SCSI Disk Controller\r\n"); + fprintf (st, "Use:\r\n"); + fprintf (st, " sim> SET %sn TYPE=type\r\n", dptr->name); + fprintf (st, "Type can be: "); + for (i = 0; scsi_type[i].name != 0; i++) { + fprintf(st, "%s", scsi_type[i].name); + if (scsi_type[i+1].name != 0) + fprintf(st, ", "); + } + fprintf (st, ".\nEach drive has the following storage capacity:\r\n"); + for (i = 0; scsi_type[i].name != 0; i++) { + int32 size = CAPB(i); /* disk capacity in bytes */ + size /= 1024; /* make KB */ + size = (10 * size) / 1024; /* size in MB * 10 */ + fprintf(st, " %-8s %4d.%1d MB cyl %3d hds %3d sec %3d blk %3d\r\n", + scsi_type[i].name, size/10, size%10, CYL(i), HDS(i), SPT(i), SSB(i)); + } + fprint_set_help(st, dptr); + fprint_show_help(st, dptr); + return SCPE_OK; +} + +const char *scsi_description (DEVICE *dptr) +{ + return "SEL-32 MFP SCSI Disk Controller"; +} + +#endif diff --git a/SEL32/sel32_sys.c b/SEL32/sel32_sys.c index 830a4d5..123e244 100644 --- a/SEL32/sel32_sys.c +++ b/SEL32/sel32_sys.c @@ -62,6 +62,9 @@ DEVICE *sim_devices[] = { #ifdef NUM_DEVS_IOP &iop_dev, /* IOP channel controller */ #endif +#ifdef NUM_DEVS_MFP + &mfp_dev, /* MFP channel controller */ +#endif #ifdef NUM_DEVS_RTOM &rtc_dev, &itm_dev, @@ -532,7 +535,9 @@ t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag) case FMT_ICL: /* icl file image */ return load_icl(fileref); +#ifdef NO_TAP_FOR_NOW case FMT_NONE: /* nothing */ +#endif default: break; } diff --git a/SEL32/taptools/filelist.c b/SEL32/taptools/filelist.c index 59f638b..7a6c8a9 100644 --- a/SEL32/taptools/filelist.c +++ b/SEL32/taptools/filelist.c @@ -159,25 +159,21 @@ int main (int argc, char *argv[]) /* get lines until eof */ while ((ll=getloi(buf, buf_size)) != EOF) { - if (ll == 0) - { + if (ll == 0) { /* eof found, process new file */ skipfile = 0; file_byte_count = 0; fileaddr = 0; printf("\nfile %d:\n", filen); - } - else - { + } else { int cc = 0; buffptr = 0; char buff[257]; int ans; - -{ - /* dump first 2 words */ int w1, w2, i, j; char path[64], command[128]; + { + /* dump first 2 words */ w1 = (buf[0] & 0xff) << 24 | buf[1] << 16 | buf[2] << 8 | (buf[3] & 0xff); w2 = (buf[4] & 0xff) << 24 | buf[5] << 16 | buf[6] << 8 | (buf[7] & 0xff); if (filen > 480) diff --git a/makefile b/makefile index 75bf171..cbbf73d 100644 --- a/makefile +++ b/makefile @@ -1982,7 +1982,7 @@ SEL32 = ${SEL32D}/sel32_cpu.c ${SEL32D}/sel32_sys.c ${SEL32D}/sel32_chan.c \ ${SEL32D}/sel32_iop.c ${SEL32D}/sel32_com.c ${SEL32D}/sel32_con.c \ ${SEL32D}/sel32_clk.c ${SEL32D}/sel32_mt.c ${SEL32D}/sel32_lpr.c \ ${SEL32D}/sel32_scfi.c ${SEL32D}/sel32_fltpt.c ${SEL32D}/sel32_disk.c \ - ${SEL32D}/sel32_hsdp.c + ${SEL32D}/sel32_hsdp.c ${SEL32D}/sel32_mfp.c ${SEL32D}/sel32_scsi.c SEL32_OPT = -I $(SEL32D) -DSEL32 #SEL32_OPT = -I $(SEL32D) -DUSE_INT64 -DSEL32