From 00d3dfefe7f0c8beabde3b30eb98d0a8c1a28c5e Mon Sep 17 00:00:00 2001 From: AZBevier Date: Mon, 4 May 2020 19:18:47 -0700 Subject: [PATCH] SEL32: Modify MFC SCSI disk support for UTX. SEL32: Add floating point normalize function. SEL32: Provide MFC support for UTX and MPX3.X. SEL32: Rewrite console support for type-ahead support. SEL32: Revise SIO support to always queue I/O request. SEL32: Allow IOP/MFP address reconfiguration. SEL32: Add more device reconfigurations. --- SEL32/sel32_chan.c | 304 ++++++++++++++++++++++--------- SEL32/sel32_clk.c | 68 +++++-- SEL32/sel32_com.c | 5 +- SEL32/sel32_con.c | 310 +++++++++++++++++++------------ SEL32/sel32_cpu.c | 309 ++++++++++++++++++++++--------- SEL32/sel32_defs.h | 3 + SEL32/sel32_disk.c | 14 +- SEL32/sel32_fltpt.c | 361 ++++++++++++++++++++++++++++++++++++- SEL32/sel32_hsdp.c | 4 +- SEL32/sel32_iop.c | 4 +- SEL32/sel32_mfp.c | 54 +++++- SEL32/sel32_mt.c | 18 +- SEL32/sel32_scsi.c | 24 +-- SEL32/tests/diag.ini | 33 +++- SEL32/tests/sel32_test.ini | 175 +++++++++++++++++- 15 files changed, 1326 insertions(+), 360 deletions(-) diff --git a/SEL32/sel32_chan.c b/SEL32/sel32_chan.c index 9e6b472..e8ea6a7 100644 --- a/SEL32/sel32_chan.c +++ b/SEL32/sel32_chan.c @@ -87,8 +87,6 @@ extern uint32 INTS[]; /* Interrupt status flags */ DIB *dib_unit[MAX_DEV]; /* Pointer to Device info block */ DIB *dib_chan[MAX_CHAN]; /* pointer to channel mux dib */ -//0401/* device status */ -//0401 uint16 dev_status[MAX_DEV]; /* last device status flags */ uint16 loading; /* set when booting */ #define get_chan(chsa) ((chsa>>8)&0x7f) /* get channel number from ch/sa */ @@ -139,8 +137,20 @@ void store_csw(CHANP *chp); /* add an entry to the FIFO */ int32 FIFO_Put(uint16 chsa, uint32 entry) { +//#define OLD_CHAN +#ifdef OLD_CHAN DIB *dibp = dib_unit[chsa & 0x7f00]; /* get DIB pointer for channel */ +#else + DIB *dibp = dib_chan[get_chan(chsa)]; /* get DIB pointer for channel */ + if (dibp == NULL) { + sim_debug(DEBUG_EXP, &cpu_dev, + "FIFO_Put NULL dib ptr for chsa %04x\n", chsa); + return -1; /* FIFO address error */ + } +#endif if (dibp->chan_fifo_in == ((dibp->chan_fifo_out-1+FIFO_SIZE) % FIFO_SIZE)) { + sim_debug(DEBUG_EXP, &cpu_dev, + "FIFO_Put FIFO full for chsa %04x\n", chsa); return -1; /* FIFO Full */ } dibp->chan_fifo[dibp->chan_fifo_in] = entry; /* add new entry */ @@ -152,7 +162,16 @@ int32 FIFO_Put(uint16 chsa, uint32 entry) /* get the next entry from the FIFO */ int32 FIFO_Get(uint16 chsa, uint32 *old) { +#ifdef OLD_CHAN DIB *dibp = dib_unit[chsa & 0x7f00]; /* get DIB pointer for channel */ +#else + DIB *dibp = dib_chan[get_chan(chsa)]; /* get DIB pointer for channel */ + if (dibp == NULL) { + sim_debug(DEBUG_EXP, &cpu_dev, + "FIFO_Get NULL dib ptr for chsa %04x\n", chsa); + return -1; /* FIFO address error */ + } +#endif /* see if the FIFO is empty */ if (dibp->chan_fifo_in == dibp->chan_fifo_out) { return -1; /* FIFO is empty, tell caller */ @@ -167,12 +186,16 @@ int32 FIFO_Get(uint16 chsa, uint32 *old) int32 FIFO_Num(uint16 chsa) { int32 num; /* number of entries */ +#ifdef OLD_CHAN DIB *dibp = dib_unit[chsa & 0x7f00]; /* get DIB pointer for channel */ +#else + DIB *dibp = dib_chan[get_chan(chsa)]; /* get DIB pointer for channel */ if (dibp == NULL) { -// sim_debug(DEBUG_DETAIL, &cpu_dev, -// "FIFO_Num NULL dibp for chsa %04x\n", chsa); - return 0; + sim_debug(DEBUG_EXP, &cpu_dev, + "FIFO_Num NULL dib ptr for chsa %04x\n", chsa); + return 0; /* FIFO address error */ } +#endif /* calc entries */ num = (dibp->chan_fifo_in - dibp->chan_fifo_out + FIFO_SIZE) % FIFO_SIZE; return (num>1); /* two words/entry */ @@ -218,14 +241,19 @@ int32 RDYQ_Num(void) 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 prog ptr */ - DIB *dibp; /* get DIB pointer for channel */ CHANP *chp; - int i; + int i, j; + DIB *dibp = dib_chan[chan>>8]; /* get channel dib ptr */ + CHANP *pchp = 0; /* for channel prog ptr */ sim_debug(DEBUG_XIO, &cpu_dev, "set_inch chan %04x inch addr %06x\n", chan, inch_addr); + /* must be valid DIB pointer */ + if (dibp == NULL) + return SCPE_MEM; /* return memory error */ + pchp = dibp->chan_prg; /* get parent channel prog ptr */ + /* must be valid channel pointer */ if (pchp == NULL) return SCPE_MEM; /* return memory error */ @@ -234,28 +262,27 @@ t_stat set_inch(UNIT *uptr, uint32 inch_addr) { if (!MEM_ADDR_OK(inch_addr)) /* see if mem addr >= MEMSIZE */ return SCPE_MEM; /* return memory error */ -#ifdef NOT_YET - /* see if inch_addr is already defined */ - if (pchp->chan_inch_addr != 0) - return SCPE_ARG; /* inch already defined */ -#endif - - /* set parent */ - pchp->chan_inch_addr = inch_addr; /* set the inch addr */ + /* set INCH address for all units on master channel */ + chp = pchp; + for (i=0; inumunits; i++) { + chp->chan_inch_addr = inch_addr; /* set the inch addr */ + chp++; /* next unit channel */ + } /* now go through all the sub addresses for the channel and set inch addr */ for (i=0; i<256; i++) { chsa = chan | i; /* merge sa to real channel */ - dibp = dib_unit[chsa]; /* get the DIB pointer */ - if (dibp == 0) + if (dib_unit[chsa] == dibp) /* if same dibp already done */ + continue; + if (dib_unit[chsa] == 0) /* make sure good address */ continue; /* must have a DIB, so not used */ - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - if (chp == 0) - continue; /* not used */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "set_inch2 chsa %04x inch addr %06x\n", chsa, inch_addr); - /* set the inch buffer addr */ - chp->chan_inch_addr = inch_addr; /* set inch buffer address */ + dibp = dib_unit[chsa]; /* finally get the new dib adddress */ + chp = dibp->chan_prg; /* get first unit channel prog ptr */ + /* set INCH address for all units on channel */ + for (j=0; jnumunits; j++) { + chp->chan_inch_addr = inch_addr; /* set the inch addr */ + chp++; /* next unit channel */ + } } return SCPE_OK; /* All OK */ } @@ -272,7 +299,7 @@ uint32 find_int_lev(uint16 chsa) return 0; /* not found */ inta = ((~spadent)>>16)&0x7f; /* get interrupt level */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_IRQ, &cpu_dev, "find_int_lev class F SPADC %08x chsa %04x lev %02x SPADI %08x INTS %08x\n", spadent, chsa, inta, SPAD[inta+0x80], INTS[inta]); return(inta); /* return the level*/ @@ -288,9 +315,12 @@ uint32 find_int_icb(uint16 chsa) inta = find_int_lev(chsa); /* find the int level */ if (inta == 0) return 0; /* not found */ + /* add interrupt vector table base address plus int # byte address offset */ icba = SPAD[0xf1] + (inta<<2); /* interrupt vector address in memory */ + if (!MEM_ADDR_OK(icba)) /* needs to be valid address in memory */ + return 0; /* not found */ icba = RMW(icba); /* get address of ICB from memory */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_IRQ, &cpu_dev, "find_int_icb icba %06x SPADC %08x chsa %04x lev %02x SPADI %08x INTS %08x\n", icba, spadent, chsa, inta, SPAD[inta+0x80], INTS[inta]); return(icba); /* return the address */ @@ -321,7 +351,7 @@ UNIT *find_unit_ptr(uint16 chsa) return NULL; /* device not found on system */ } -/* Find chanp pointer for given device (ch/sa) */ +/* Find channel program pointer for given device (ch/sa) */ CHANP *find_chanp_ptr(uint16 chsa) { struct dib *dibp; /* DIB pointer */ @@ -364,7 +394,7 @@ int readfull(CHANP *chp, uint32 maddr, uint32 *word) return 1; /* show we have error */ } *word = RMW(maddr); /* get 1 word */ - sim_debug(DEBUG_EXP, &cpu_dev, "READFULL read %08x from addr %08x\n", *word, maddr); + sim_debug(DEBUG_XIO, &cpu_dev, "READFULL read %08x from addr %08x\n", *word, maddr); return 0; /* return OK */ } @@ -545,13 +575,25 @@ loop: chp->chan_status |= STATUS_CEND; /* channel end status */ chp->ccw_flags = 0; /* no flags */ chp->ccw_cmd = 0; /* stop IOCD processing */ - irq_pend = 1; /* int coming */ +////XXX irq_pend = 1; /* int coming */ sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw bad status chan %04x status %04x\n", chan, chp->chan_status); +#ifndef XXX + chp->chan_byte = BUFF_NEXT; /* have main pick us up */ + RDYQ_Put(chp->chan_dev); /* queue us up */ + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw continue wait chsa %04x status %08x\n", + chp->chan_dev, chp->chan_status); +//// irq_pend = 1; /* show pending int */ +#else return 1; /* error return */ +#endif } +#ifdef XXX042320_042720_ADD_BACK + /* NOTE this code needed for MPX 1.X to run! */ /* see if command completed */ + /* we have good status */ if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { uint16 chsa = GET_UADDR(uptr->u3); /* get channel & sub address */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ @@ -559,6 +601,16 @@ loop: "load_ccw @%06x FIFO #%1x cmd complete chan %04x status %04x count %04x\n", chp->chan_caw, FIFO_Num(chsa), chan, chp->chan_status, chp->ccw_count); } +#else + /* we have good status */ + if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { + chp->chan_byte = BUFF_NEXT; /* have main pick us up */ + RDYQ_Put(chp->chan_dev); /* queue us up */ + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw good status chan %04x status %04x\n", + chan, chp->chan_status); + } +#endif } /* nothing happening, so return */ sim_debug(DEBUG_XIO, &cpu_dev, @@ -587,7 +639,7 @@ int chan_read_byte(uint16 chsa, uint8 *data) //040120 chp->chan_status |= STATUS_CEND; /* no, end of data */ /*BACK*/ chp->chan_status |= STATUS_CEND; /* no, end of data */ chp->chan_byte = BUFF_CHNEND; /* buffer end too */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "chan_read_byte no DC chan end, cnt %04x addr %06x chan %04x\n", chp->ccw_count, chp->ccw_addr, chan); return 1; /* return error */ @@ -749,8 +801,6 @@ void set_devattn(uint16 chsa, uint16 flags) if (chp->chan_dev == chsa && (chp->chan_status & STATUS_CEND) != 0 && (flags & SNS_DEVEND) != 0) { chp->chan_status |= ((uint16)flags); } -//0401 else -//0401 dev_status[chsa] = flags; /* save device status flags */ sim_debug(DEBUG_CMD, &cpu_dev, "set_devattn(%04x, %04x) %04x\n", chsa, flags, chp->chan_dev); irq_pend = 1; } @@ -759,13 +809,13 @@ void set_devattn(uint16 chsa, uint16 flags) void chan_end(uint16 chsa, uint16 flags) { CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "chan_end entry chsa %04x flags %04x status %04x cmd %02x\n", chsa, flags, chp->chan_status, chp->ccw_cmd); // if (chp->chan_byte & BUFF_DIRTY) { if (chp->chan_byte == BUFF_DIRTY) { - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "chan_end writing DIRTY chsa %04x flags %04x status %04x cmd %02x\n", chsa, flags, chp->chan_status, chp->ccw_cmd); if (writebuff(chp)) /* write remaining data */ @@ -937,8 +987,8 @@ void store_csw(CHANP *chp) "store_csw FIFO Overflow ERROR on chsa %04x\n", chsa); } sim_debug(DEBUG_IRQ, &cpu_dev, - "store_csw FIFO #%1x write chsa %04x sw1 %08x sw2 %08x CPU stat %08x \n", - FIFO_Num(chsa), chsa, stwd1, stwd2, SPAD[0xf9]); + "store_csw FIFO #%1x write chsa %04x sw1 %08x sw2 %08x incha %08x\n", + FIFO_Num(chsa), chsa, stwd1, stwd2, chp->chan_inch_addr); chp->chan_status = 0; /* no status anymore */ chp->chan_byte = BUFF_CHNEND; /* show done */ irq_pend = 1; /* wakeup controller */ @@ -975,11 +1025,13 @@ t_stat checkxio(uint16 chsa, uint32 *status) { CHANP *chp; /* channel program pointer */ uint16 chan = get_chan(chsa); /* get the logical channel number */ uint32 inta, incha; + DEVICE *dptr; /* DEVICE pointer */ sim_debug(DEBUG_XIO, &cpu_dev, "checkxio entry chsa %04x\n", chsa); dibp = dib_unit[chsa]; /* get the DIB pointer */ chp = find_chanp_ptr(chsa); /* find the chanp pointer */ uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ + dptr = get_dev(uptr); /* pointer to DEVICE structure */ if (dibp == 0 || uptr == 0 || chp == 0) { /* if no dib or unit ptr, CC3 on return */ *status = CC3BIT; /* not found, so CC3 */ @@ -1021,12 +1073,20 @@ t_stat checkxio(uint16 chsa, uint32 *status) { *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ return SCPE_OK; /* just busy CC3&CC4 */ } - *status = CC1BIT; /* CCs = 1, not busy */ - sim_debug(DEBUG_XIO, &cpu_dev, "checkxio done CC1 status %08x\n", *status); + /* try this as MFP says it returns 0 on OK */ + if (dptr->flags & DEV_CHAN) + *status = 0; /* CCs = 0, OK return */ + else + /* return CC1 for non iop/mfp devices */ + *status = CC1BIT; /* CCs = 1, not busy */ + sim_debug(DEBUG_XIO, &cpu_dev, "checkxio done CC status %08x\n", *status); return SCPE_OK; /* No CC's all OK */ } /* start an XIO operation */ +/* when we get here the cpu has verified that there is a valid channel address */ +/* and an interrupt entry in spad for the channel. The IOCL address in the ICB */ +/* has also been verified as present */ /* chan channel number 0-7f */ /* suba unit address within channel 0-ff */ /* Condition codes to return 0-f as specified above */ @@ -1039,6 +1099,37 @@ t_stat startxio(uint16 chsa, uint32 *status) { uint16 chan = get_chan(chsa); /* get the channel number */ uint32 tempa, inta, incha; +#ifndef OLD_CHAN + uint32 word1, word2, cmd; + + sim_debug(DEBUG_XIO, &cpu_dev, "startxio entry chsa %04x\n", chsa); + inta = find_int_lev(chsa); /* Interrupt Level for channel */ + chan_icb = find_int_icb(chsa); /* Interrupt level context block address */ + sim_debug(DEBUG_XIO, &cpu_dev, + "startxio int spad %08x icb %06x inta %02x chan %04x\n", + SPAD[inta+0x80], chan_icb, inta, chan); + + iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ + word1 = RMW(iocla & MASK24); /* get 1st IOCL word */ + incha = word1 & MASK24; /* should be inch addr */ + word2 = RMW((iocla + 4) & MASK24); /* get 2nd IOCL word */ + cmd = (word1 >> 24) & 0xff; /* get channel cmd from IOCL */ + if (cmd == 0) { /* INCH command? */ + tempa = word2 & MASK16; /* get count */ + if ((word2 & MASK16) == 36) /* see if disk with 224 wd buffer */ + incha = RMW(incha); /* 224 word buffer is inch addr */ + dibp = dib_chan[chan]; /* get the channel DIB pointer */ + chp = dibp->chan_prg; /* get first unit channel prog ptr */ + chp->chan_inch_addr = incha; /* set the inch addr for channel */ + } + + incha = chp->chan_inch_addr; /* get inch address */ + + sim_debug(DEBUG_XIO, &cpu_dev, + "startxio do normal chsa %04x iocla %06x IOCD1 %08x IOCD2 %08x\n", + chsa, iocla, RMW(iocla), RMW(iocla+4)); +#endif + sim_debug(DEBUG_XIO, &cpu_dev, "startxio entry chsa %04x\n", chsa); dibp = dib_unit[chsa]; /* get the DIB pointer */ chp = find_chanp_ptr(chsa); /* find the chanp pointer */ @@ -1050,6 +1141,7 @@ t_stat startxio(uint16 chsa, uint32 *status) { "startxio chsa %04x device not present, CC3 returned\n", chsa); return SCPE_OK; /* not found, CC3 */ } + if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ sim_debug(DEBUG_EXP, &cpu_dev, "startxio chsa %04x device not present, CC3 returned flags %08x\n", chsa, uptr->flags); @@ -1057,6 +1149,17 @@ t_stat startxio(uint16 chsa, uint32 *status) { return SCPE_OK; /* not found, CC3 */ } + inta = find_int_lev(chsa); /* Interrupt Level for channel */ +#ifdef NONO + if ((INTS[inta]&INTS_ACT) || (SPAD[inta+0x80]&SINT_ACT)) { /* look for level active */ + sim_debug(DEBUG_XIO, &cpu_dev, + "SIO Busy INTS ACT FIFO #%1x irq %02x SPAD %08x INTS %08x\n", + FIFO_Num(SPAD[inta+0x80] & 0x7f00), inta, SPAD[inta+0x80], INTS[inta]); + *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ + return SCPE_OK; /* just busy CC3&CC4 */ + } +#endif + /* 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_XIO, &cpu_dev, @@ -1065,7 +1168,6 @@ t_stat startxio(uint16 chsa, uint32 *status) { return SCPE_OK; /* just busy CC3&CC4 */ } - inta = find_int_lev(chsa); /* Interrupt Level for channel */ chan_icb = find_int_icb(chsa); /* Interrupt level context block address */ sim_debug(DEBUG_XIO, &cpu_dev, "startxio int spad %08x icb %06x inta %02x chan %04x\n", @@ -1073,8 +1175,10 @@ t_stat startxio(uint16 chsa, uint32 *status) { iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ incha = chp->chan_inch_addr; /* get inch address */ +#ifdef LEAVE_IT /* now store the inch status address into word 5 of the ICB for the channel */ WMW(chan_icb+20, incha); /* post inch addr in ICB+5w */ +#endif sim_debug(DEBUG_XIO, &cpu_dev, "startxio test chsa %04x iocla %06x IOCD1 %08x IOCD2 %08x\n", @@ -1110,12 +1214,23 @@ t_stat startxio(uint16 chsa, uint32 *status) { "$$ SIO start IOCL processing chsa %04x iocla %08x incha %08x\n", chsa, iocla, incha); +#ifndef QUEUE_IO + /* try queueing the SIO */ + /* Queue us to continue from cpu level */ + chp->chan_byte = BUFF_NEXT; /* have main pick us up */ + RDYQ_Put(chsa); /* queue us up */ + sim_debug(DEBUG_XIO, &cpu_dev, + "$$$ SIO queued chsa %04x iocla %06x IOCD1 %08x IOCD2 %08x\n", + chsa, iocla, RMW(iocla), RMW(iocla+4)); +#endif + +#ifdef QUEUE_IO /* start processing the IOCL */ if (load_ccw(chp, 0) || (chp->chan_status & STATUS_PCI)) { /* we have an error or user requested interrupt, return status */ sim_debug(DEBUG_EXP, &cpu_dev, "startxio FIFO #%1x store_csw CC2 chan %04x status %08x\n", FIFO_Num(chsa), chan, chp->chan_status); -#ifndef DISABLE_041320 +#ifdef DISABLE_041320 /* DIAG's want CC1 with memory access error */ if (chp->chan_status & STATUS_PCHK) { chp->chan_status &= ~STATUS_LENGTH; /* clear incorrect length */ @@ -1124,7 +1239,7 @@ t_stat startxio(uint16 chsa, uint32 *status) { "startxio Error1 FIFO #%1x store_csw CC1 chan %04x status %08x\n", FIFO_Num(chsa), chan, chp->chan_status); *status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */ - irq_pend = 1; /* still pending int */ +// irq_pend = 1; /* still pending int */ return SCPE_OK; /* CC2 (0x20) status stored */ } #endif @@ -1134,28 +1249,22 @@ t_stat startxio(uint16 chsa, uint32 *status) { chan_end(chsa, SNS_CHNEND); /* show I/O complete & store status in FIFO */ // store_csw(chp); /* store the status in the inch status dw */ /* try 041920 for dexp */ - if (FIFO_Num(chsa)) /* post the status */ + if (FIFO_Num(chsa)) { /* post the status */ post_csw(chp, 0); - *status = CC2BIT; /* status stored, so CC2 */ - sim_debug(DEBUG_EXP, &cpu_dev, - "startxio Error2 FIFO #%1x store_csw CC2 chan %04x status %08x\n", - FIFO_Num(chsa), chan, chp->chan_status); - irq_pend = 1; /* still pending int */ - return SCPE_OK; /* CC2 (0x20) status stored */ + *status = CC2BIT; /* status stored, so CC2 */ + sim_debug(DEBUG_EXP, &cpu_dev, + "startxio Error2 FIFO #%1x store_csw CC2 chan %04x status %08x\n", + FIFO_Num(chsa), chan, chp->chan_status); + irq_pend = 1; /* still pending int */ + return SCPE_OK; /* CC2 (0x20) status stored */ + } } -#ifdef NOTNOW - /* try 041920 for dexp */ - if (FIFO_Num(chsa)) { - post_csw(chp, 0); - *status = CC2BIT; /* status stored, so CC2 */ - irq_pend = 1; /* still pending int */ - return SCPE_OK; /* CC2 (0x20) status stored */ - } #endif *status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */ - sim_debug(DEBUG_CMD, &cpu_dev, "$$$ SIO done chsa %04x status %08x iocla %08x\n", - chsa, chp->chan_status, iocla); +// *status = 0; /*TRY*/ /* CCs = 1, SIO accepted & queued, no echo status */ + sim_debug(DEBUG_XIO, &cpu_dev, "$$$ SIO done chsa %04x status %08x iocla %08x CC's %08x\n", + chsa, chp->chan_status, iocla, *status); return SCPE_OK; /* No CC's all OK */ } @@ -1289,7 +1398,6 @@ t_stat stopxio(uint16 chsa, uint32 *status) { /* stop XIO */ sim_debug(DEBUG_CMD, &cpu_dev, "stopxio busy return CC1 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 */ -//0401 dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */ *status = CC1BIT; /* request accepted, no status, so CC1 */ return SCPE_OK; /* go wait CC1 */ } @@ -1347,7 +1455,6 @@ t_stat rschnlxio(uint16 chsa, uint32 *status) { /* reset channel XIO */ chp = find_chanp_ptr(chsa); /* find the chanp pointer */ if (chp == 0) continue; /* not used */ -//0401 dev_status[chsa] = 0; /* clear device status */ chp->chan_status = 0; /* clear the channel status */ chp->chan_byte = BUFF_NEWCMD; /* no data yet */ chp->ccw_addr = 0; /* clear buffer address */ @@ -1551,7 +1658,6 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */ /* reset the FIFO pointers */ dibp->chan_fifo_in = 0; dibp->chan_fifo_out = 0; -//0401 dev_status[chan] = 0; /* clear the channel status location */ 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 */ @@ -1569,7 +1675,6 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */ if (chp == 0) { continue; /* not used */ } -//0401 dev_status[chsa] = 0; /* clear device status */ chp->chan_status = 0; /* clear the channel status */ chp->chan_byte = BUFF_NEWCMD; /* no data yet */ chp->ccw_addr = 0; /* clear buffer address */ @@ -1597,8 +1702,6 @@ t_stat chan_boot(uint16 chsa, DEVICE *dptr) { return SCPE_IOERR; /* error */ chp = find_chanp_ptr(chsa); /* find the chanp pointer */ -//0401 dev_status[chsa&0x7f00] = 0; /* clear the channel status location */ -//0401 dev_status[chsa] = 0; /* device status too */ chp->chan_status = 0; /* clear the channel status */ chp->chan_dev = chsa; /* save our address (ch/sa) */ chp->chan_byte = BUFF_NEWCMD; /* no data yet */ @@ -1616,7 +1719,6 @@ t_stat chan_boot(uint16 chsa, DEVICE *dptr) { if (load_ccw(chp, 0)) { /* load IOCL starting from location 0 */ sim_debug(DEBUG_XIO, &cpu_dev, "Channel Boot Error return from load_ccw chan %04x status %08x\n", chan, chp->chan_status); -//0401 dev_status[chsa] = 0; /* no device status */ chp->ccw_flags = 0; /* clear the command flags */ chp->chan_byte = BUFF_CHNEND; /* done */ loading = 0; /* show we are done loading from the boot device */ @@ -1658,7 +1760,6 @@ uint32 cont_chan(uint16 chsa) chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ // store_csw(chp); /* store the status in the inch status dw */ // chp->chan_byte = BUFF_NEWCMD; /* read for new cmd */ -//0401 dev_status[chsa] = 0; /* no device status */ irq_pend = 1; /* show pending int */ return SCPE_OK; /* done */ } @@ -1675,7 +1776,6 @@ uint32 cont_chan(uint16 chsa) chsa, chp->chan_status); // store_csw(chp); /* store the status in the inch status dw */ chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ -//0401 dev_status[chsa] = 0; /* no device status */ chp->chan_byte = BUFF_NEWCMD; /* we are done */ irq_pend = 1; /* show pending int */ return SCPE_OK; /* done, status stored */ @@ -1813,8 +1913,8 @@ uint32 scan_chan(uint32 *ilev) { chan_icba = RMW(chan_ivl); /* get the interrupt context block addr in memory */ sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan INTS REQ FIFO #%1x irq %02x found chan_icba %08x INTS %08x\n", - FIFO_Num(SPAD[i+0x80]&0x7f00), i, chan_icba, INTS[i]); + "scan_chan INTS REQ irq %02x found chan_icba %08x INTS %08x\n", + i, chan_icba, INTS[i]); sim_debug(DEBUG_IRQ, &cpu_dev, "scan_chan OPSD1 %08x OPSD2 %08x NPSD1 %08x NPSD2 %08x\n", RMW(chan_icba), RMW(chan_icba+4), RMW(chan_icba+8), RMW(chan_icba+12)); @@ -1881,10 +1981,10 @@ DEVICE *get_dev(UNIT *uptr) t_stat chan_set_devs() { uint32 i, j; - for(i = 0; i < MAX_DEV; i++) { + for (i = 0; i < MAX_DEV; i++) { dib_unit[i] = NULL; /* clear DIB pointer array */ } - for(i = 0; i < MAX_CHAN; i++) { + for (i = 0; i < MAX_CHAN; i++) { dib_chan[i] = NULL; /* clear DIB pointer array */ } /* Build channel & device arrays */ @@ -1904,23 +2004,22 @@ t_stat chan_set_devs() { if (dibp == NULL) /* If no DIB, not channel device */ continue; - if (dptr->flags & DEV_DIS) { /* Skip disabled devices */ + if ((dptr->flags & DEV_DIS) || /* Skip disabled devices */ + ((dibp->chan_prg) == NULL)) { /* must have channel info for each device */ + chsa = GET_UADDR(uptr->u3); /* ch/sa value */ - printf("Device %s chsa %04x not set up dptr %p\n", - dptr->name, chsa, (void *)uptr->dptr); + printf("Device %s chsa %04x not set up dibp %p\n", dptr->name, chsa, dibp); continue; } - if ((chp = (CHANP *)dibp->chan_prg) == NULL)/* must have channel information for each device */ - continue; + chp = (CHANP *)dibp->chan_prg; /* must have channel information for each device */ /* Check if address is in unit or dev entry */ for (j = 0; j < dptr->numunits; j++) { /* loop through unit entries */ chsa = GET_UADDR(uptr->u3); /* ch/sa value */ -printf("Setup device %s%d chsa %04x type %03d dptr %p\n", - dptr->name, j, chsa, GET_TYPE(uptr->flags), (void *)uptr->dptr); + printf("Setup device %s%d chsa %04x type %03d dibp %p\n", + dptr->name, j, chsa, GET_TYPE(uptr->flags), dibp); /* zero some channel data loc's for device */ -//0401 dev_status[chsa] = 0; /* zero device status flags */ -//0401 dev_status[chsa&0x7f00] = 0; /* clear the channel status location */ + chp->unitptr = uptr; /* set the unit back pointer */ chp->chan_status = 0; /* clear the channel status */ chp->chan_dev = chsa; /* save our address (ch/sa) */ chp->chan_byte = BUFF_EMPTY; /* no data yet */ @@ -1930,28 +2029,32 @@ printf("Setup device %s%d chsa %04x type %03d dptr %p\n", chp->ccw_flags = 0; /* Command chain and supress incorrect length */ chp->ccw_cmd = 0; /* read command */ chp->chan_inch_addr = 0; /* clear address of stat dw in memory */ -#ifdef NEWCODE +#ifndef OLD_CHAN if ((uptr->flags & UNIT_DIS) == 0) { /* is unit marked disabled? */ /* see if this is unit zero */ if ((chsa & 0xff) == 0) { /* we have channel mux or dev 0 of units */ if (dptr->flags & DEV_CHAN) { - /* see if address already defined */ + /* see if channel address already defined */ if (dib_chan[get_chan(chsa)] != 0) { printf("Channel mux %04x already defined, aborting\n", chsa); return SCPE_IERR; /* no, arg error */ } - printf("Setting Channel mux %04x\n", chsa); + printf("Setting Channel mux %04x dibp %p\n", chsa, dibp); /* channel mux, save dib for channel */ dib_chan[get_chan(chsa)] = dibp; + if (dibp->dev_ini != NULL) /* if there is an init routine, call it now */ + dibp->dev_ini(uptr, 1); /* init the channel */ } else { + /* we have unit 0 of non-IOP/MFP device */ if (dib_unit[chsa] != 0) { printf("Channel/Dev %04x already defined\n", chsa); + return SCPE_IERR; /* no, arg error */ } else { /* channel mux, save dib for channel */ /* for now, save any zero dev as chan */ if (chsa) { - printf("Setting Channel zero unit 0 device %04x\n", chsa); + printf("Setting Channel zero unit 0 device %04x dibp %p\n", chsa, dibp); dib_unit[chsa] = dibp; /* no, save the dib address */ if (dibp->dev_ini != NULL) /* if there is an init routine, call it now */ dibp->dev_ini(uptr, 1); /* init the channel */ @@ -1970,20 +2073,41 @@ printf("Setup device %s%d chsa %04x type %03d dptr %p\n", #else if ((uptr->flags & UNIT_DIS) == 0) { /* is unit marked disabled? */ if ((dptr->flags & DEV_CHAN) == 0) { - if (dib_unit[chsa] != 0) { - printf("Channel/SubAddress %04x multiple defined, aborting\n", chsa); - return SCPE_IERR; /* no, arg error */ - } + if (dib_unit[chsa] != 0) { + printf("Channel/SubAddress %04x multiply defined, aborting\n", chsa); + return SCPE_IERR; /* no, arg error */ + } } dib_unit[chsa] = dibp; /* no, save the dib address */ } #endif - if (dibp->dev_ini != NULL) /* if there is an init routine, call it now */ + if (dibp->dev_ini != NULL) /* call channel init if defined */ dibp->dev_ini(uptr, 1); /* init the channel */ uptr++; /* next UNIT pointer */ chp++; /* next CHANP pointer */ } } + /* now make another pass through the channels and see which integrated */ + /* channel/controllers are defined and add them to the dib_chan definitions */ + /* this will handle non-MFP/IOP channel controllers */ + for (i = 0; i < MAX_CHAN; i++) { + if (dib_chan[i] == 0) { + /* channel not defined, see if defined in dib_unit array */ + /* check device zero for suspected channel */ + if (dib_unit[i<<8]) { + /* write dibp to channel array */ + dib_chan[i] = dib_unit[i<<8]; /* save the channel dib */ + printf("Chan_set_dev new Channel %04x defined at dibp %p\n", i<<8, dib_unit[i<<8]); + } + } else { + printf("Chan_set_dev Channel %04x defined at dibp %p\n", i<<8, dib_chan[i]); + /* channel is defined, see if defined in dib_unit array */ + if ((dib_unit[i<<8]) == 0) { + /* write dibp to units array */ + dib_unit[i<<8] = dib_chan[i]; /* save the channel dib */ + } + } + } return SCPE_OK; /* all is OK */ } diff --git a/SEL32/sel32_clk.c b/SEL32/sel32_clk.c index beed08e..c16781f 100644 --- a/SEL32/sel32_clk.c +++ b/SEL32/sel32_clk.c @@ -35,7 +35,7 @@ #if NUM_DEVS_RTOM > 0 -#define UNIT_CLK UNIT_ATTABLE|UNIT_IDLE|UNIT_DISABLE +#define UNIT_CLK UNIT_IDLE|UNIT_DISABLE void rtc_setup (uint32 ss, uint32 level); t_stat rtc_srv (UNIT *uptr); @@ -61,7 +61,7 @@ int32 rtc_lvl = 0x18; /* rtc interrupt level */ rtc_reg RTC register list */ -/* clock is attached all the time */ +/* clock can be enabled / disabled */ /* default to 60 HZ RTC */ UNIT rtc_unit = { UDATA (&rtc_srv, UNIT_IDLE, 0), 16666, UNIT_ADDR(0x7F06)}; //UNIT rtc_unit = { UDATA (&rtc_srv, UNIT_CLK, 0), 16666, UNIT_ADDR(0x7F06)}; @@ -93,7 +93,7 @@ DEVICE rtc_dev = { NULL, NULL, &rtc_reset, /* examine, deposit, reset */ NULL, NULL, NULL, /* boot, attach, detach */ // NULL, 0, 0, NULL, /* dib, dev flags, debug flags, debug */ - NULL, DEV_DEBUG, 0, dev_debug, /* dib, dev flags, debug flags, debug */ + NULL, DEV_DEBUG|DEV_DISABLE, 0, dev_debug, /* dib, dev flags, debug flags, debug */ NULL, NULL, &rtc_help, /* ?, ?, help */ NULL, NULL, &rtc_desc, /* ?, ?, description */ }; @@ -115,7 +115,9 @@ t_stat rtc_srv (UNIT *uptr) /* stop clock interrupts for dexp debugging */ rtc_pie = 0; #endif - if (rtc_pie) { /* set pulse intr */ + /* id clock sisabled, do not do interrupts */ + if (((uptr->flags & DEV_DIS) == 0) && rtc_pie) { +// if (rtc_pie) { /* set pulse intr */ time_t result = time(NULL); sim_debug(DEBUG_CMD, &rtc_dev, "RT Clock int time %08x\n", (uint32)result); #ifdef DO_TIME @@ -137,7 +139,13 @@ t_stat rtc_srv (UNIT *uptr) irq_pend = 1; /* make sure we scan for int */ } } +#define FOR_MIKE +#ifdef FOR_MIKE +//Mike rtc_unit.wait = sim_rtcn_calb (rtc_tps, TMR_RTC); /* calibrate */ rtc_unit.wait = sim_rtcn_calb (rtc_tps, TMR_RTC); /* calibrate */ +#else + rtc_unit.wait = sim_rtcn_calb (rtc_tps, TMR_RTC); /* calibrate */ +#endif sim_activate_after (&rtc_unit, 1000000/rtc_tps);/* reactivate 16666 tics / sec */ return SCPE_OK; } @@ -160,6 +168,10 @@ void rtc_setup(uint32 ss, uint32 level) sim_debug(DEBUG_CMD, &rtc_dev, "RT Clock setup enable int %02x rtc_pie %01x ss %01x\n", rtc_lvl, rtc_pie, ss); +#ifdef DO_DYNAMIC_DEBUG + /* start debugging */ + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); +#endif } else { INTS[level] &= ~INTS_ENAB; /* make sure disabled */ SPAD[level+0x80] &= ~SINT_ENAB; /* in spad too */ @@ -178,7 +190,12 @@ t_stat rtc_reset(DEVICE *dptr) { rtc_pie = 0; /* disable pulse */ /* initialize clock calibration */ +#ifdef FOR_MIKE +//Mike rtc_unit.wait = sim_rtcn_init_unit(&rtc_unit, rtc_unit.wait, TMR_RTC); rtc_unit.wait = sim_rtcn_init_unit(&rtc_unit, rtc_unit.wait, TMR_RTC); +#else + rtc_unit.wait = sim_rtcn_init_unit(&rtc_unit, rtc_unit.wait, TMR_RTC); +#endif sim_activate (&rtc_unit, rtc_unit.wait); /* activate unit */ return SCPE_OK; } @@ -208,7 +225,7 @@ t_stat rtc_show_freq (FILE *st, UNIT *uptr, int32 val, CONST void *desc) /* sho help rtc */ t_stat rtc_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr) { - fprintf(st, "SEL 32 IOP realtime clock at 0x7F06\r\n"); + fprintf(st, "SEL 32 IOP/MFP realtime clock at 0x7F06\r\n"); fprintf(st, "Use:\r\n"); fprintf(st, " sim> SET RTC [50][60][100][120]\r\n"); fprintf(st, "to set clock interrupt rate in HZ\r\n"); @@ -220,7 +237,7 @@ t_stat rtc_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr /* device description */ const char *rtc_desc(DEVICE *dptr) { - return "SEL IOP realtime clock @ address 0x7F06"; + return "SEL IOP/MFP realtime clock @ address 0x7F06"; } /************************************************************************/ @@ -250,7 +267,14 @@ const char *itm_desc(DEVICE *dptr); itm_reg Interval Timer ITM register list */ +#ifdef FOR_MIKE +/* Mike suggested I remove the UNIT_IDLE flag from ITM. This causes SEL32 */ +/* to use 100% of the CPU instead of waiting amd ruinning 10% cpu usage */ +//BAD Mike UNIT itm_unit = { UDATA (&itm_srv, 0, 0), 26042, UNIT_ADDR(0x7F04)}; +UNIT itm_unit = { UDATA (&itm_srv, 0, 0), 26042, UNIT_ADDR(0x7F04)}; +#else UNIT itm_unit = { UDATA (&itm_srv, UNIT_IDLE, 0), 26042, UNIT_ADDR(0x7F04)}; +#endif REG itm_reg[] = { { FLDATA (PIE, itm_pie, 0) }, @@ -312,7 +336,8 @@ t_stat itm_srv (UNIT *uptr) itm_lvl, itm_cnt); /* restart timer with value from user */ if (itm_src) /* use specified src freq */ - sim_activate_after_abs_d(&itm_unit, ((double)itm_cnt*400000)/rtc_tps); + sim_activate_after_abs_d(&itm_unit, ((double)itm_cnt*350000)/rtc_tps); +// sim_activate_after_abs_d(&itm_unit, ((double)itm_cnt*400000)/rtc_tps); // sim_activate_after_abs_d(&itm_unit, ((double)itm_cnt*1000000)/rtc_tps); else sim_activate_after_abs_d(&itm_unit, ((double)itm_cnt*itm_tick_size_x_100)/100.0); @@ -386,8 +411,7 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) itm_run = 0; /* timer is not running */ itm_cnt = 0; /* no count reset value */ itm_load = temp; /* last loaded value */ -//TRY*/ itm_load = 0; /* last loaded value */ -/*TRY*/ itm_strt = 0; /* not restarted neg */ + itm_strt = 0; /* not restarted neg */ return 0; /* does not matter, no value returned */ break; @@ -399,6 +423,11 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) case 0x39: /* load timer with new value and start lo rate */ case 0x3a: /* load timer with new value and start hi rate */ case 0x3b: /* load timer with new value and start lo rate */ +#ifdef DO_DYNAMIC_DEBUG + if (itm_cmd == 0x38) + /* start debugging */ + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); +#endif // sim_activate_after (&rtc_unit, 1000000/rtc_tps);/* reactivate 16666 tics / sec */ if (itm_run) /* if we were running stop timer */ sim_cancel (&itm_unit); /* cancel timer */ @@ -448,11 +477,11 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) } sim_cancel (&itm_unit); /* cancel timer */ } - if (cmd & 0x40) { - /* timer value already read into temp */ - ; - } - if (cmd & 0x80) { +// if (cmd & 0x40) { +// /* timer value already read into temp */ +// ; +// } + if (cmd & 0x08) { /* use value from user to load timer */ temp = cnt; /* set user count */ } @@ -487,8 +516,8 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) /* if bits 30-31 == 20, use RTC freq */ itm_src = (cmd>>1)&1; /* set src */ if (itm_src) /* use specified src freq */ -// sim_activate_after_abs_d(&itm_unit, ((double)cnt*400000)/rtc_tps); - sim_activate_after_abs_d(&itm_unit, ((double)cnt*1000000)/rtc_tps); + sim_activate_after_abs_d(&itm_unit, ((double)cnt*700000)/rtc_tps); +// sim_activate_after_abs_d(&itm_unit, ((double)cnt*1000000)/rtc_tps); else sim_activate_after_abs_d(&itm_unit, ((double)cnt*itm_tick_size_x_100)/100.0); itm_run = 1; /* set timer running */ @@ -500,7 +529,7 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) itm_strt = 0; /* not restarted neg */ itm_load = cnt; /* now loaded */ sim_debug(DEBUG_CMD, &itm_dev, "Intv 0x%02x return value %08x (%08d)\n", cmd, cnt, cnt); - return temp; /* return curr count */ + return 0; /* does not matter, no value returned */ break; case 0x40: /* read the current timer value */ @@ -518,6 +547,7 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) } sim_debug(DEBUG_CMD, &itm_dev, "Intv 0x40 return value %08x (%d)\n", temp, temp); return temp; +//TRIED return temp << 6; break; case 0x60: /* read and stop timer */ @@ -682,7 +712,7 @@ t_stat itm_show_freq (FILE *st, UNIT *uptr, int32 val, CONST void *desc) /* sho help rtc */ t_stat itm_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr) { - fprintf(st, "SEL 32 IOP interval timer at 0x7F04\r\n"); + fprintf(st, "SEL 32 IOP/MFP interval timer at 0x7F04\r\n"); fprintf(st, "Use:\r\n"); fprintf(st, " sim> SET ITM [3840][7680]\r\n"); fprintf(st, "to set interval timer clock rate in us x 100\r\n"); @@ -694,7 +724,7 @@ t_stat itm_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr /* device description */ const char *itm_desc(DEVICE *dptr) { - return "SEL IOP Interval Timer @ address 0x7F04"; + return "SEL IOP/MFP Interval Timer @ address 0x7F04"; } #endif diff --git a/SEL32/sel32_com.c b/SEL32/sel32_com.c index 13cd028..a43e573 100644 --- a/SEL32/sel32_com.c +++ b/SEL32/sel32_com.c @@ -237,7 +237,8 @@ MTAB com_mod[] = { }; UNIT com_unit[] = { - {UDATA(&comi_srv, UNIT_ATTABLE|UNIT_IDLE, 0), COM_WAIT, UNIT_ADDR(0x0000)}, /* 0 */ +// {UDATA(&comi_srv, UNIT_ATTABLE|UNIT_IDLE, 0), COM_WAIT, UNIT_ADDR(0x0000)}, /* 0 */ + {UDATA(&comi_srv, UNIT_ATTABLE|UNIT_IDLE, 0), COM_WAIT, UNIT_ADDR(0x4747)}, /* dummy */ }; //DIB com_dib = {NULL, com_startcmd, NULL, NULL, com_ini, com_unit, com_chp, COM_UNITS, 0x0f, 0x7e00, 0, 0, 0}; @@ -679,7 +680,7 @@ t_stat comi_srv(UNIT *uptr) return SCPE_OK; /* return */ } - /* handle SACE, 3 char alread read, so we are done */ + /* 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, diff --git a/SEL32/sel32_con.c b/SEL32/sel32_con.c index 665731a..5a299fd 100644 --- a/SEL32/sel32_con.c +++ b/SEL32/sel32_con.c @@ -40,7 +40,7 @@ #if NUM_DEVS_CON > 0 //#define UNIT_CON UNIT_ATTABLE | UNIT_IDLE | UNIT_DISABLE -#define UNIT_CON UNIT_IDLE +#define UNIT_CON UNIT_IDLE | UNIT_DISABLE #define CMD u3 /* Held in u3 is the device command and status */ @@ -65,6 +65,7 @@ #define CON_EKO 0x800 /* Echo input character */ #define CON_OUTPUT 0x1000 /* Output ready for unit */ #define CON_READ 0x2000 /* Read mode selected */ +#define CON_ATAT 0x4000 /* working on @@A input */ /* Input buffer pointer held in u4 */ @@ -141,8 +142,9 @@ DEVICE con_dev = { "CON", con_unit, NULL, con_mod, NUM_UNITS_CON, 8, 15, 1, 8, 8, NULL, NULL, &con_reset, NULL, NULL, NULL, - &con_dib, DEV_DISABLE|DEV_DEBUG, 0, dev_debug +// &con_dib, DEV_DISABLE|DEV_DEBUG, 0, dev_debug // &con_dib, DEV_UADDR|DEV_DISABLE|DEV_DEBUG, 0, dev_debug + &con_dib, DEV_DIS|DEV_DISABLE|DEV_DEBUG, 0, dev_debug }; /* @@ -155,8 +157,7 @@ void con_ini(UNIT *uptr, t_bool f) { 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 */ + uptr->CMD &= LMASK; /* leave only chsa */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ sim_activate(uptr, 1000); /* time increment */ } @@ -167,7 +168,8 @@ uint16 con_preio(UNIT *uptr, uint16 chan) DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); - if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */ +// if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */ + if ((uptr->CMD & CON_MSK) != 0) { /* just return if busy */ sim_debug(DEBUG_CMD, &con_dev, "con_preio unit=%02x BUSY\n", unit); return SNS_BSY; } @@ -178,7 +180,7 @@ uint16 con_preio(UNIT *uptr, uint16 chan) /* start an I/O operation */ uint16 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { - int unit = (uptr - con_unit); /* unit 0,1 */ + int unit = (uptr - con_unit); /* unit 0 is read, unit 1 is write */ uint8 ch; if ((uptr->CMD & CON_MSK) != 0) { /* is unit busy */ @@ -197,7 +199,8 @@ uint16 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uptr->CMD &= LMASK; /* leave only chsa */ 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 */ + if (unit == 1) +/*#*/ sim_activate(uptr, 40); /* start us off */ //@41 sim_activate(uptr, 40); /* start us off */ return 0; /* no status change */ break; @@ -208,51 +211,49 @@ uint16 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uptr->CMD &= LMASK; /* leave only chsa */ uptr->CMD |= (cmd & CON_MSK); /* save command */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ - sim_activate(uptr, 20); /* start us off */ + if (unit == 1) +/*#*/ sim_activate(uptr, 40); /* start us off */ //@41 sim_activate(uptr, 40); /* start us off */ -//@41 sim_activate(uptr, 20); /* start us off */ return 0; /* no status change */ break; case CON_RD: /* 0x02 */ /* Read command */ case CON_ECHO: /* 0x0a */ /* Read command w/ECHO */ /* if output requested for input device, give error */ - uptr->CMD &= LMASK; /* leave only chsa */ +// uptr->CMD &= LMASK; /* leave only chsa */ + uptr->CMD &= ~CON_MSK; /* remove old CMD */ uptr->CMD |= (cmd & CON_MSK); /* save command */ if (cmd == CON_ECHO) /* echo command? */ uptr->CMD |= CON_EKO; /* save echo status */ uptr->CMD |= CON_READ; /* show read mode */ atbuf = 0; /* reset attention buffer */ - uptr->u4 = 0; /* no I/O yet */ - con_data[unit].incnt = 0; /* clear any input data */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ - sim_activate(uptr, 20); /* start us off */ + if (unit == 1) +/*#*/ sim_activate(uptr, 40); /* start us off */ //@41 sim_activate(uptr, 40); /* start us off */ -//@41 sim_activate(uptr, 140); /* start us off */ return 0; break; case CON_NOP: /* 0x03 */ /* NOP has do nothing */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ - uptr->CMD &= LMASK; /* leave only chsa */ +// uptr->CMD &= LMASK; /* leave only chsa */ + uptr->CMD &= ~CON_MSK; /* remove old 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, 20); /* start us off */ + if (unit == 1) +/*#*/ sim_activate(uptr, 40); /* start us off */ //@41 sim_activate(uptr, 40); /* start us off */ return 0; /* no status change */ break; -#ifndef JUNK case 0x0C: /* 0x0C */ /* Unknown command */ 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, 20); /* start us off */ + if (unit == 1) +/*#*/ sim_activate(uptr, 40); /* start us off */ //@41 sim_activate(uptr, 40); /* start us off */ return 0; /* no status change */ break; -#endif case CON_CON: /* 0x1f */ /* Connect, return Data Set ready */ sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %04x: Cmd %02x CON\n", chan, cmd); @@ -280,9 +281,7 @@ uint16 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { break; } /* invalid command */ - uptr->SNS |= SNS_CMDREJ; /* command rejected */ -// uptr->u4 = 0; /* no I/O yet */ -// con_data[unit].incnt = 0; /* clear any input data */ + uptr->SNS |= SNS_CMDREJ; /* command rejected */ sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %04x: Invalid command %02x Sense %02x\n", chan, cmd, uptr->SNS); @@ -300,9 +299,14 @@ t_stat con_srvo(UNIT *uptr) { int unit = (uptr - con_unit); /* unit 0 is read, unit 1 is write */ int cmd = uptr->CMD & CON_MSK; CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ +#ifdef DO_ALL_CHS uint8 ch, cp; +#else + uint8 ch; +#endif - sim_debug(DEBUG_CMD, &con_dev, "con_srvo enter chsa %04x cmd = %02x\n", chsa, cmd); + sim_debug(DEBUG_CMD, &con_dev, + "con_srvo enter CMD %08x chsa %04x cmd = %02x\n", uptr->CMD, chsa, cmd); /* if input tried from output device, error */ if ((cmd == CON_RD) || (cmd == CON_ECHO) || (cmd == 0xC0)) { /* check for output */ @@ -313,7 +317,7 @@ t_stat con_srvo(UNIT *uptr) { uptr->SNS |= SNS_CMDREJ; /* command rejected */ 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); + "con_srvo Read to output device CMD %08x chsa %04x cmd = %02x\n", uptr->CMD, chsa, cmd); chan_end(chsa, SNS_CHNEND|SNS_UNITCHK); /* unit check */ return SCPE_OK; } @@ -322,8 +326,8 @@ t_stat con_srvo(UNIT *uptr) { if ((cmd == CON_NOP) || (cmd == CON_INCH2)) { /* NOP has to do nothing */ uptr->CMD &= LMASK; /* nothing left, command complete */ sim_debug(DEBUG_CMD, &con_dev, - "con_srvo INCH/NOP unit %02x: cmd %02x incnt %02x u4 %02x\n", - unit, cmd, con_data[unit].incnt, uptr->u4); + "con_srvo INCH/NOP unit %02x: CMD %08x cmd %02x incnt %02x u4 %02x\n", + unit, uptr->CMD, cmd, con_data[unit].incnt, uptr->u4); if (cmd == CON_INCH2) { /* Channel end only for INCH */ int len = chp->ccw_count; /* INCH command count */ uint32 mema = chp->ccw_addr; /* get inch or buffer addr */ @@ -332,11 +336,11 @@ t_stat con_srvo(UNIT *uptr) { set_inch(uptr, mema); /* new address */ sim_debug(DEBUG_CMD, &con_dev, - "con_srvo INCH chsa %04x len %02x inch %06x\n", chsa, len, mema); + "con_srvo INCH CMD %08x chsa %04x len %02x inch %06x\n", uptr->CMD, chsa, len, mema); chan_end(chsa, SNS_CHNEND); /* INCH done */ } else { sim_debug(DEBUG_CMD, &con_dev, - "con_srvo NOP chsa %04x cmd = %02x\n", chsa, cmd); + "con_srvo NOP CMD %08x chsa %04x cmd = %02x\n", uptr->CMD, chsa, cmd); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ } return SCPE_OK; @@ -347,12 +351,13 @@ t_stat con_srvo(UNIT *uptr) { if (chan_read_byte(chsa, &ch)) { /* get byte from memory */ uptr->CMD &= LMASK; /* nothing left, command complete */ sim_debug(DEBUG_CMD, &con_dev, - "con_srvo write %02x chsa %04x cmd %02x complete\n", - ch, chsa, cmd); + "con_srvo write %02x CMD %08x chsa %04x cmd %02x complete\n", + ch, uptr->CMD, chsa, cmd); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ } else { /* HACK HACK HACK */ ch &= 0x7f; /* make 7 bit w/o parity */ +#ifdef DO_ALL_CHS /* simh stops outputting chars to debug file if it is passed a null????? */ if (ch == 0) /* do not pass a null char */ //WAS ch = '@'; /* stop simh abort .... */ @@ -363,23 +368,25 @@ t_stat con_srvo(UNIT *uptr) { else cp = '^'; sim_debug(DEBUG_CMD, &con_dev, - "con_srvo write %01x: putch 0x%02x %c\n", unit, ch, cp); + "con_srvo write %01x: CMD %08x putch 0x%02x %c\n", unit, uptr->CMD, ch, cp); sim_putchar(ch); /* output next char to device */ #ifdef DO_DYNAMIC_DEBUG - last2 = ((last2 << 8) & 0xffff) | cp; /* get last 2 chars */ - if (last2 == 0x503e) { /* check for DXP> */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); - con_dev.dctrl |= (DEBUG_CMD | DEBUG_EXP | DEBUG_DETAIL); +// last2 = ((last2 << 8) & 0xffff) | cp; /* get last 2 chars */ +// if (last2 == 0x503e) { /* check for DXP> */ + last2 = ((last2 << 8) & 0xffffff) | cp; /* get last 3 chars */ + if (last2 == 0x273637) { /* check for '67 */ + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); +// con_dev.dctrl |= (DEBUG_CMD | DEBUG_EXP | DEBUG_DETAIL); } #endif -//OLD sim_putchar(cp); /* output next char to device */ #else sim_putchar(ch); /* output next char to device */ -//WAS sim_putchar(cp); /* output next char to device */ #endif - sim_activate(uptr, 20); /* keep going */ -//@41 sim_activate(uptr, 30); /* start us off */ -//@41 sim_activate(uptr, 50); /* start us off */ +#else + /* do not output to debug file */ + sim_putchar(ch); /* output next char to device */ +#endif + sim_activate(uptr, 30); /* start us off */ } } return SCPE_OK; @@ -395,28 +402,30 @@ t_stat con_srvi(UNIT *uptr) { t_stat r; sim_debug(DEBUG_CMD, &con_dev, - "con_srvi enter chsa %04x cmd %02x ccw_count %02x\n", chsa, cmd, chp->ccw_count); + "con_srvi enter CMD %08x chsa %04x cmd %02x incnt %02x u4 %02x\n", + uptr->CMD, chsa, cmd, con_data[unit].incnt, uptr->u4); /* if output tried to input device, error */ if ((cmd == CON_RWD) || (cmd == CON_WR) || (cmd == 0x0C)) { /* check for output */ - /* CON_RWD: 0x37 */ /* TOF and write line */ - /* CON_WR: 0x01 */ /* Write command */ + /* CON_RWD: 0x37 */ /* TOF and write line */ + /* CON_WR: 0x01 */ /* Write command */ /* if input requested for output device, give error */ if (unit == 0) { uptr->SNS |= SNS_CMDREJ; /* command rejected */ 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); + "con_srvi Write to input device CMD %08x chsa %04x cmd = %02x\n", uptr->CMD, chsa, cmd); chan_end(chsa, SNS_CHNEND|SNS_UNITCHK); /* unit check */ // fall thru return SCPE_OK; } +// return sim_activate (uptr, 20); } if ((cmd == CON_NOP) || (cmd == CON_INCH2)) { /* NOP is do nothing */ uptr->CMD &= LMASK; /* nothing left, command complete */ sim_debug(DEBUG_CMD, &con_dev, - "con_srvi INCH/NOP unit %02x: cmd %02x incnt %02x u4 %02x\n", - unit, cmd, con_data[unit].incnt, uptr->u4); + "con_srvi INCH/NOP unit %02x: CMD %08x cmd %02x incnt %02x u4 %02x\n", + unit, uptr->CMD, cmd, con_data[unit].incnt, uptr->u4); if (cmd == CON_INCH2) { /* Channel end only for INCH */ int len = chp->ccw_count; /* INCH command count */ uint32 mema = chp->ccw_addr; /* get inch or buffer addr */ @@ -424,53 +433,80 @@ t_stat con_srvi(UNIT *uptr) { // int i = set_inch(uptr, mema); /* new address */ set_inch(uptr, mema); /* new address */ + con_data[unit].incnt = 0; /* buffer empty */ + uptr->u4 = 0; /* no I/O yet */ sim_debug(DEBUG_CMD, &con_dev, - "con_srvi INCH chsa %04x len %02x inch %06x\n", chsa, len, mema); + "con_srvi INCH CMD %08x chsa %04x len %02x inch %06x\n", uptr->CMD, chsa, len, mema); //TRY228 chan_end(chsa, SNS_CHNEND); /* INCH done */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ } else { sim_debug(DEBUG_CMD, &con_dev, - "con_srvi NOP chsa %04x cmd = %02x\n", chsa, cmd); + "con_srvi NOP CMD %08x chsa %04x cmd = %02x\n", uptr->CMD, chsa, cmd); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* NOP done */ } /* drop through to poll input */ - return sim_activate (uptr, 20); +// return sim_activate (uptr, 20); } switch (cmd) { case CON_RD: /* 0x02 */ /* read from device */ case CON_ECHO: /* 0x0a */ /* read from device w/ECHO */ - if (uptr->CMD & CON_INPUT) { /* input waiting? */ - int len = chp->ccw_count; /* get command count */ - ch = con_data[unit].ibuff[uptr->u4++]; /* get char from read buffer */ - sim_debug(DEBUG_CMD, &con_dev, - "con_srvi readbuf unit %02x: read %02x incnt %02x u4 %02x len %02x\n", - unit, ch, con_data[unit].incnt, uptr->u4, len); - if (chan_write_byte(chsa, &ch)) { /* write byte to memory */ - con_data[unit].incnt = 0; /* buffer empty */ - cmd = 0; /* no cmd either */ + if ((uptr->u4 != con_data[unit].incnt) || /* input empty */ + (uptr->CMD & CON_INPUT)) { /* input waiting? */ +// if (uptr->CMD & CON_INPUT) { /* input waiting? */ + ch = con_data[unit].ibuff[uptr->u4]; /* get char from read buffer */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi readbuf unit %02x: CMD %08x read %02x incnt %02x u4 %02x len %02x\n", + unit, uptr->CMD, ch, con_data[unit].incnt, uptr->u4, chp->ccw_count); + + /* process any characters */ + if (uptr->u4 != con_data[unit].incnt) { /* input available */ + ch = con_data[unit].ibuff[uptr->u4]; /* get char from read buffer */ + if (chan_write_byte(chsa, &ch)) { /* write byte to memory */ + /* write error */ + cmd = 0; /* no cmd now */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi write error unit %02x: CMD %08x read %02x u4 %02x ccw_count %02x\n", + unit, uptr->CMD, ch, uptr->u4, chp->ccw_count); + uptr->CMD &= LMASK; /* nothing left, command complete */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ + break; + } sim_debug(DEBUG_CMD, &con_dev, - "con_srvi write to mem unit %02x: read %02x u4 %02x ccw_count %02x\n", - unit, ch, uptr->u4, chp->ccw_count); - uptr->u4 = 0; /* no I/O yet */ + "con_srvi write to mem unit %02x: CMD %08x read %02x u4 %02x incnt %02x\n", + unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt); + + /* character accepted, bump buffer pointer */ + uptr->u4++; /* next char position */ + /* see if at end of buffer */ + if (uptr->u4 >= sizeof(con_data[unit].ibuff)) + uptr->u4 = 0; /* reset pointer */ + + /* user want more data? */ + if ((test_write_byte_end(chsa)) == 0) { + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi need more unit %02x CMD %08x u4 %02x incnt %02x ccw_count %02x\n", + unit, uptr->CMD, uptr->u4, con_data[unit].incnt, chp->ccw_count); + /* user wants more, look next time */ + if (uptr->u4 == con_data[unit].incnt) { /* input empty */ + uptr->CMD &= ~CON_INPUT; /* no input available */ + } + break; + } + /* command is completed */ + cmd = 0; /* no cmd now */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi read done unit %02x: CMD %08x read %02x u4 %02x incnt %02x ccw_count %02x\n", + unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt, chp->ccw_count); uptr->CMD &= LMASK; /* nothing left, command complete */ + if (uptr->u4 != con_data[unit].incnt) { /* input empty */ + uptr->CMD |= CON_INPUT; /* input still available */ + } chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ + break; } - return sim_activate (uptr, 20); -#ifdef NOTNOW - if (test_write_byte_end(chsa)) { /* see if read request complete */ - con_data[unit].incnt = 0; /* buffer is empty */ - cmd = 0; /* no cmd either */ - sim_debug(DEBUG_CMD, &con_dev, - "con_srvi nothing to write to mem unit %02x: u4 %02x ccw_count %02x\n", - unit, uptr->u4, chp->ccw_count); - uptr->u4 = 0; /* no I/O yet */ - uptr->CMD &= LMASK; /* nothing left, command complete */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ - } -#endif } break; } @@ -479,59 +515,99 @@ t_stat con_srvi(UNIT *uptr) { r = sim_poll_kbd(); /* poll for a char */ if (r & SCPE_KFLAG) { /* got a char */ ch = r & 0xff; /* drop any extra bits */ - if ((cmd == CON_RD) || (cmd == CON_ECHO)) { /* looking for input? */ +// if (ch == 0x1b) /* esc is bad */ +// goto goout; /* skip control char */ +// if ((cmd == CON_RD) || (cmd == CON_ECHO)) { /* looking for input? */ + if ((uptr->CMD & CON_INPUT) == 0) { /* looking for input? */ atbuf = 0; /* reset attention buffer */ + uptr->CMD &= ~CON_ATAT; /* no @@A input */ + if (ch == '@') { /* maybe for console int */ + atbuf = (ch)<<8; /* start anew */ + uptr->CMD |= CON_ATAT; /* show getting @ */ + } if (ch == '\n') /* convert newline */ ch = '\r'; /* make newline into carriage return */ - /* Handle end of buffer */ - switch (ch) { - case '\r': /* return */ - case '\n': /* newline */ - uptr->CMD |= CON_CR; /* C/R received */ - /* fall through */ - default: - if (con_data[unit].incnt < sizeof(con_data[unit].ibuff)) { - if (uptr->CMD & CON_EKO) /* ECHO requested */ - sim_putchar(ch); /* ECHO the char */ - con_data[unit].ibuff[con_data[unit].incnt++] = ch; - uptr->CMD |= CON_INPUT; /* we have a char available */ - sim_debug(DEBUG_CMD, &con_dev, - "con_srvi readch unit %02x: read %02x u4 %02x ccw_count %02x\n", - unit, ch, uptr->u4, chp->ccw_count); - } - return sim_activate (uptr, 20); - } - } else { - /* look for attention sequence '@@A' */ - if (ch == '@' || ch == 'A' || ch == 'a') { - if (ch == 'a') - ch = 'A'; - atbuf = (atbuf|ch)<<8; + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi handle readch unit %02x: CMD %08x read %02x u4 %02x incnt %02x\n", + unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt); + +//MOVED /* see if count at max, if so reset to start */ +//AFTER if (con_data[unit].incnt >= sizeof(con_data[unit].ibuff)) +//incnt++ con_data[unit].incnt = 0; /* reset buffer cnt */ + + if (uptr->CMD & CON_EKO) /* ECHO requested */ sim_putchar(ch); /* ECHO the char */ + + /* put char in buffer */ + con_data[unit].ibuff[con_data[unit].incnt++] = ch; + +/*GEERT*/ /* see if count at max, if so reset to start */ +/*MOVED*/ if (con_data[unit].incnt >= sizeof(con_data[unit].ibuff)) +/*HERE**/ con_data[unit].incnt = 0; /* reset buffer cnt */ + + uptr->CMD |= CON_INPUT; /* we have a char available */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi readch unit %02x: CMD %08x read %02x u4 %02x incnt %02x\n", + unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt); + return sim_activate (uptr, 30); /* come back real soon */ +// return sim_activate (uptr, 300); /* come back real soon */ + } + /* not looking for input, look for attn or wakeup */ + if (ch == '?') { + /* set ring bit? */ + set_devwake(chsa, SNS_ATTN|SNS_DEVEND|SNS_CHNEND); /* tell user */ + } + /* not wanting input, but we have a char, look for @@A */ + if (uptr->CMD & CON_ATAT) { /* looking for @@A */ + /* we have at least one @, look for another */ + if (ch == '@' || ch == 'A' || ch == 'a') { + uint8 cc = ch; + if (cc == 'a') + cc = 'A'; /* make uppercase */ + sim_putchar(ch); /* ECHO the char */ + atbuf = (atbuf|cc)<<8; /* merge new char */ if (atbuf == 0x40404100) { attention_trap = CONSOLEATN_TRAP; /* console attn (0xb4) */ atbuf = 0; /* reset attention buffer */ + uptr->CMD &= ~CON_ATAT; /* no @@A input */ sim_putchar('\r'); /* return char */ sim_putchar('\n'); /* line feed char */ sim_debug(DEBUG_CMD, &con_dev, - "con_srvi unit %02x: read @@A Console Trap\n", unit); - } - } else { - if (ch == '?') { - /* set ring bit? */ - set_devwake(chsa, SNS_ATTN|SNS_DEVEND|SNS_CHNEND); /* tell user */ + "con_srvi unit %02x: CMD %08x read @@A Console Trap\n", unit, uptr->CMD); + uptr->u4 = 0; /* no input count */ + con_data[unit].incnt = 0; /* no input data */ } + goto goout; } + /* char not for us, so keep looking */ + atbuf = 0; /* reset attention buffer */ + uptr->CMD &= ~CON_ATAT; /* no @@A input */ } + /* not looking for input, look for attn or wakeup */ + if (ch == '@') { + atbuf = (atbuf|ch)<<8; /* merge in char */ + uptr->CMD |= CON_ATAT; /* show getting @ */ + sim_putchar(ch); /* ECHO the char */ + } + /* assume it is for next read request, so save it */ + /* see if count at max, if so reset to start */ + if (con_data[unit].incnt >= sizeof(con_data[unit].ibuff)) + con_data[unit].incnt = 0; /* reset buffer cnt */ + + if (uptr->CMD & CON_EKO) /* ECHO requested */ + sim_putchar(ch); /* ECHO the char */ + + /* put char in buffer */ + con_data[unit].ibuff[con_data[unit].incnt++] = ch; + + uptr->CMD |= CON_INPUT; /* we have a char available */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi readch2 unit %02x: CMD %08x read %02x u4 %02x incnt %02x\n", + unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt); } - if ((r & SCPE_KFLAG) && /* got something and */ - ((cmd == CON_RD) || (cmd == CON_ECHO))) /* looking for input */ -//LAST return sim_activate (uptr, 200); - return sim_activate (uptr, 40); -//@ return sim_activate(uptr, 80); /* keep going */ -// return sim_activate(uptr, 200); /* keep going */ -// return sim_activate (uptr, 5000); - return tmxr_clock_coschedule_tmr (uptr, TMR_RTC, 1); /* come back soon */ +goout: +// return sim_activate (uptr, 5000); + return tmxr_clock_coschedule_tmr (uptr, TMR_RTC, 1); /* come back soon */ } t_stat con_reset(DEVICE *dptr) { @@ -543,7 +619,7 @@ t_stat con_reset(DEVICE *dptr) { uint16 con_haltio(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->CMD); int cmd = uptr->CMD & CON_MSK; -// int unit = (uptr - con_unit); /* unit # 0 is read, 1 is write */ + int unit = (uptr - con_unit); /* unit # 0 is read, 1 is write */ CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ sim_debug(DEBUG_EXP, &con_dev, "con_haltio enter chsa %04x cmd = %02x\n", chsa, cmd); @@ -558,12 +634,14 @@ uint16 con_haltio(UNIT *uptr) { chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* force error */ uptr->CMD &= LMASK; /* make non-busy */ uptr->u4 = 0; /* no I/O yet */ + con_data[unit].incnt = 0; /* no input data */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ sim_debug(DEBUG_CMD, &con_dev, "con_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd); return SCPE_IOERR; } uptr->u4 = 0; /* no I/O yet */ + con_data[unit].incnt = 0; /* no input data */ uptr->CMD &= LMASK; /* make non-busy */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ return SCPE_OK; /* not busy */ diff --git a/SEL32/sel32_cpu.c b/SEL32/sel32_cpu.c index 0d0f711..2937864 100644 --- a/SEL32/sel32_cpu.c +++ b/SEL32/sel32_cpu.c @@ -283,6 +283,8 @@ extern uint32 s_mpfw(uint32 reg, uint32 mem, uint32 *cc); extern t_uint64 s_dvfw(uint32 reg, uint32 mem, uint32 *cc); extern uint32 s_mpfd(t_uint64 reg, t_uint64 mem, uint32 *cc); extern t_uint64 s_dvfd(t_uint64 reg, t_uint64 mem, uint32 *cc); +extern uint32 s_normfw(uint32 mem, uint32 *cc); +extern t_uint64 s_normfd(t_uint64 mem, uint32 *cc); /* History information */ int32 hst_p = 0; /* History pointer */ @@ -526,8 +528,7 @@ int nobase_mode[] = { int base_mode[] = { /* 00 04 08 0C */ /* 00 AND, OR, EOR */ -// HLF, SCC|R1|RR|SD|HLF, SCC|R1|RR|SD|HLF, SCC|R1|RR|SD|HLF, - HLF, R1|RR|SD|HLF, SCC|R1|RR|SD|HLF, SCC|R1|RR|SD|HLF, + HLF, SCC|R1|RR|SD|HLF, SCC|R1|RR|SD|HLF, SCC|R1|RR|SD|HLF, /* 10 14 18 1C */ /* SACZ CMR xBR SRx */ @@ -896,13 +897,13 @@ npmem: } /* output O/S and User MPX entries */ -//041420 sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_EXP, &cpu_dev, +// sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "#MEMORY %06x MPL %06x MPL[0] %08x %06x MPL[%04x] %08x %06x\n", MEMSIZE, mpl, RMW(mpl), RMW(mpl+4), cpix, RMW(cpix+mpl), RMW(cpix+mpl+4)); -//041420 sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_EXP, &cpu_dev, +// sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "MEMORY2 %06x BPIX %04x cpix %04x CPIX %04x CPIXPL %04x HIWM %04x\n", MEMSIZE, BPIX, cpix, CPIX, CPIXPL, HIWM); @@ -1765,11 +1766,11 @@ t_stat Mem_read(uint32 addr, uint32 *data) } /* everybody else has read access */ } - sim_debug(DEBUG_DETAIL, &cpu_dev, "Mem_read addr %06x realaddr %08x data %08x prot %02x\n", + sim_debug(DEBUG_DETAIL, &cpu_dev, "Mem_read addr %06x realaddr %06x data %08x prot %02x\n", addr, realaddr, *data, prot); } else { /* RealAddr returned an error */ - sim_debug(DEBUG_EXP, &cpu_dev, "Mem_read error addr %.8x realaddr %.8x data %.8x prot %02x status %04x\n", + sim_debug(DEBUG_EXP, &cpu_dev, "Mem_read error addr %06x realaddr %06x data %08x 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)) { @@ -1929,8 +1930,8 @@ uint32 OPSD2=0; /* Original PSD2 */ /* called from simulator */ t_stat sim_instr(void) { t_stat reason = 0; /* reason for stopping */ - t_uint64 dest; /* Holds destination/source register */ - t_uint64 source; /* Holds source or memory data */ + t_uint64 dest = 0; /* Holds destination/source register */ + t_uint64 source = 0; /* Holds source or memory data */ t_uint64 td; /* Temporary */ t_int64 int64a; /* temp int */ t_int64 int64b; /* temp int */ @@ -1952,7 +1953,7 @@ t_stat sim_instr(void) { uint8 EXM_EXR=0; /* PC Increment for EXM/EXR instructions */ uint32 reg; /* GPR or Base register bits 6-8 */ uint32 sreg; /* Source reg in from bits 9-11 reg-reg instructions */ - uint32 ix; /* index register */ + uint32 ix = 0; /* index register */ uint32 dbl; /* Double word */ uint32 ovr=0; /* Overflow flag */ //FORSTEP uint32 stopnext = 0; /* Stop on next instruction */ @@ -2035,11 +2036,14 @@ wait_loop: sim_debug(DEBUG_IRQ, &cpu_dev, "CPU RDYQ entry for chsa %04x processed\n", chsa); } + waitqcnt = 20; /* wait 10 instructions */ +// waitqcnt = 50; /* wait 10 instructions */ } else waitqcnt -= 1; /* wait another instruction */ } else +// waitqcnt = 50; /* wait 10 instructions */ waitqcnt = 20; /* wait 10 instructions */ //040120 waitqcnt = 10; /* wait 10 instructions */ // @@ -2333,7 +2337,7 @@ exec: case IMM: if (PC & 02) { /* if pc is on HW boundry, bad address */ TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC1 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } @@ -2345,7 +2349,7 @@ exec: case WRD: if (PC & 02) { /* if pc is on HW boundry, bad address */ TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC2 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } @@ -2416,7 +2420,7 @@ exec: case IMM: /* Immediate mode */ if (PC & 02) { /* if pc is on HW boundry, bad address */ TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC3 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } @@ -2561,7 +2565,7 @@ exec: case 2: /* double word address */ if ((addr & 7) != 2) { /* must be double word adddress */ TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC5 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } @@ -2590,7 +2594,7 @@ exec: if (dbl) { /* is it double regs */ if (reg & 1) { /* check for odd reg load */ TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC6 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } @@ -2613,7 +2617,7 @@ exec: if (dbl) { if (sreg & 1) { TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC7 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } @@ -2860,6 +2864,7 @@ sim_debug(DEBUG_CMD, &cpu_dev, } break; case 0x04>>2: /* 0x04 RR|R1|SD|HLF - SD|HLF */ /* ANR, SMC, CMC, RPSWT */ + i_flags &= ~SCC; /* make sure we do not set CC's for dest value */ switch(opr & 0xF) { case 0x0: /* ANR */ dest &= source; /* just an and reg to reg */ @@ -2918,7 +2923,8 @@ sim_debug(DEBUG_CMD, &cpu_dev, /* 7 - Read & Lock Enabled (=1)/Disabled (=0) */ /* 8-12 - Lower Bound of Shared Memory */ /* 3-31 - Reserved and must be zero */ - sim_debug(DEBUG_EXP, &cpu_dev, +// sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_CMD, &cpu_dev, "SMC V6/67 GPR[%02x] = %08x SMCR = %08x CPU STATUS SPAD[f9] = %08x\n", reg, GPR[reg], SMCR, SPAD[0xf9]); SMCR = GPR[reg]; /* write reg bits 0-12 to shared memory controller */ @@ -3427,7 +3433,7 @@ tbr: /* handle basemode TBR too * /* update the PSD with new address from reg */ PSD1 &= ~temp; /* clean the bits to be changed */ PSD1 |= (addr & temp); /* insert the CC's and address */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_CMD, &cpu_dev, "TRSW REG %01x PSD %08x %08x modes %08x temp %06x\n", reg, PSD1, PSD2, modes, temp); i_flags |= BT; /* we branched, so no PC update */ @@ -3703,7 +3709,8 @@ tbr: /* handle basemode TBR too * goto newpsd; /* handle trap */ } temp2 = CPUSTATUS; /* save original */ - sim_debug(DEBUG_EXP, &cpu_dev, +// sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_CMD, &cpu_dev, "SETCPU orig %08x user bits %08x New CPUSTATUS %08x\n", temp2, temp, CPUSTATUS); /* bits 20-23 and bit 25 can change */ @@ -3933,12 +3940,44 @@ skipit: temp = GPR[reg]; /* reg contents specified by Rd */ addr = GPR[sreg]; /* reg contents specified by Rs */ /* temp has Rd (GPR[reg]), addr has Rs (GPR[sreg]) */ - if ((opr & 0xF) == 0x3) + if ((opr & 0xF) == 0x3) { addr = NEGATE32(addr); /* subtract, so negate source */ - temp2 = s_adfw(temp, addr, &CC); /* all add float numbers */ - sim_debug(DEBUG_CMD, &cpu_dev, - "%s GPR[%d] %08x addr %08x result %08x\n", - (opr&0xf)==3 ? "SURFW":"ADRFW", reg, GPR[reg], GPR[sreg], temp2); + } +// temp2 = s_adfw(temp, addr, &CC); /* add float numbers */ +// } else { /* handle add */ +// } + /* test for zero reg value */ + if (temp == 0) { /* reg value is zero */ + temp2 = s_normfw(addr, &CC); /* normalize addr value */ + if (CC & CC1BIT) { + CC = 0; /* remove addr except */ + if (temp2 & FSIGN) + CC |= CC3BIT; /* CC3 for neg */ + else if (temp2 == 0) + CC |= CC4BIT; /* CC4 for zero */ + else + CC |= CC2BIT; /* CC2 for greater than zero */ + } + } + else + if (addr == 0) { /* mem value is zero */ + temp2 = s_normfw(temp, &CC); /* normalize addr value */ + if (CC & CC1BIT) { + CC = 0; /* remove addr except */ + if (temp2 & FSIGN) + CC |= CC3BIT; /* CC3 for neg */ + else if (temp2 == 0) + CC |= CC4BIT; /* CC4 for zero */ + else + CC |= CC2BIT; /* CC2 for greater than zero */ + } + } + else + temp2 = s_adfw(temp, addr, &CC); /* do ADFW */ + sim_debug(DEBUG_EXP, &cpu_dev, + "%s GPR[%d] %08x addr %08x result %08x CC %08x\n", + (opr&0xf)==3 ? "SURFW":"ADRFW", + reg, GPR[reg], GPR[sreg], temp2, CC); PSD1 &= 0x87FFFFFE; /* clear the old CC's */ PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ if (CC & CC1BIT) { /* check for arithmetic exception */ @@ -3980,7 +4019,7 @@ skipit: addr = GPR[sreg]; /* reg contents specified by Rs */ /* temp has Rd (GPR[reg]), addr has Rs (GPR[sreg]) */ temp2 = (uint32)s_dvfw(temp, addr, &CC); /* divide reg by sreg */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_EXP, &cpu_dev, "DVRFW GPR[%d] %08x src %08x result %08x\n", reg, GPR[reg], addr, temp2); PSD1 &= 0x87FFFFFE; /* clear the old CC's */ @@ -4003,7 +4042,7 @@ skipit: /* convert from 32 bit float to 32 bit fixed */ addr = GPR[sreg]; /* reg contents specified by Rs */ temp2 = s_fixw(addr, &CC); /* do conversion */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_EXP, &cpu_dev, "FIXW GPR[%d] %08x result %08x\n", sreg, GPR[sreg], temp2); PSD1 &= 0x87FFFFFE; /* clear the old CC's */ @@ -4027,7 +4066,7 @@ skipit: addr = GPR[sreg]; /* reg contents specified by Rs */ /* temp has Rd (GPR[reg]), addr has Rs (GPR[sreg]) */ temp2 = s_mpfw(temp, addr, &CC); /* mult reg by sreg */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_EXP, &cpu_dev, "MPRFW GPR[%d] %08x src %08x result %08x\n", reg, GPR[reg], addr, temp2); PSD1 &= 0x87FFFFFE; /* clear the old CC's */ @@ -4050,7 +4089,7 @@ skipit: /* convert from 32 bit integer to 32 bit float */ addr = GPR[sreg]; /* reg contents specified by Rs */ GPR[reg] = s_fltw(addr, &CC); /* do conversion & set CC's */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_EXP, &cpu_dev, "FLTW GPR[%d] %08x result %08x\n", sreg, GPR[sreg], GPR[reg]); PSD1 &= 0x87FFFFFE; /* clear the old CC's */ @@ -4082,12 +4121,39 @@ skipit: td = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ td |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ source = (((t_uint64)GPR[sreg]) << 32); /* get upper reg value */ - source |= (t_uint64)GPR[sreg+1]; /* insert low order reg value */ - if ((opr & 0xF) == 0x9) - dest = s_adfd(td, source, &CC); /* add */ - else - dest = s_sufd(td, source, &CC); /* subtract */ - sim_debug(DEBUG_CMD, &cpu_dev, + source |= (t_uint64)GPR[sreg+1]; /* insert low order reg value */ + if ((opr & 0xF) == 0xb) { + td = NEGATE32(td); /* make negative for subtract */ + } + if (td == 0) { /* is reg value zero */ + dest = s_normfd(source, &CC); /* normalize addr value */ + if (CC & CC1BIT) { + CC = 0; /* remove addr except */ + if (dest & DMSIGN) + CC |= CC3BIT; /* CC3 for neg */ + else if (dest == 0) + CC |= CC4BIT; /* CC4 for zero */ + else + CC |= CC2BIT; /* CC2 for greater than zero */ + } + } + else + if (source == 0) { /* memory value zero? */ + dest = s_normfd(td, &CC); /* normalize reg value */ + if (CC & CC1BIT) { + CC = 0; /* remove addr except */ + if (dest & DMSIGN) + CC |= CC3BIT; /* CC3 for neg */ + else if (dest == 0) + CC |= CC4BIT; /* CC4 for zero */ + else + CC |= CC2BIT; /* CC2 for greater than zero */ + } + } + else + dest = s_adfd(td, source, &CC); /* do ADFD */ + + sim_debug(DEBUG_EXP, &cpu_dev, "%s GPR[%d] %08x %08x src %016llx result %016llx\n", (opr&0xf)==8 ? "ADRFD":"SURFD", reg, GPR[reg], GPR[reg+1], source, dest); PSD1 &= 0x87FFFFFE; /* clear the old CC's */ @@ -4157,7 +4223,7 @@ doovr4: source = (((t_uint64)GPR[sreg]) << 32); /* get upper reg value */ source |= (t_uint64)GPR[sreg+1]; /* insert low order reg value */ dest = s_dvfd(td, source, &CC); /* divide double values */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_EXP, &cpu_dev, "DVRFD GPR[%d] %08x %08x src %016llx result %016llx\n", reg, GPR[reg], GPR[reg+1], source, dest); PSD1 &= 0x87FFFFFE; /* clear the old CC's */ @@ -4187,7 +4253,7 @@ doovr4: source = (((t_uint64)GPR[sreg]) << 32) | ((t_uint64)GPR[sreg+1]); /* convert from 64 bit double to 64 bit int */ dest = s_fixd(source, &CC); - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_EXP, &cpu_dev, "FIXD GPR[%d] %08x %08x result %016llx\n", sreg, GPR[sreg], GPR[sreg+1], dest); PSD1 &= 0x87FFFFFE; /* clear the old CC's */ @@ -4217,7 +4283,7 @@ doovr4: source = (((t_uint64)GPR[sreg]) << 32); /* get upper reg value */ source |= (t_uint64)GPR[sreg+1]; /* insert low order reg value */ dest = s_mpfd(td, source, &CC); /* multiply double values */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_EXP, &cpu_dev, "MPRFD GPR[%d] %08x %08x src %016llx result %016llx\n", reg, GPR[reg], GPR[reg+1], source, dest); PSD1 &= 0x87FFFFFE; /* clear the old CC's */ @@ -4246,7 +4312,7 @@ doovr4: source = (((t_uint64)GPR[sreg]) << 32); /* get upper reg value */ source |= (t_uint64)GPR[sreg+1]; /* insert low order reg value */ dest = s_fltd(source, &CC); /* do conversion & set CC's */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_EXP, &cpu_dev, "FLTD GPR[%d] %08x %08x result %016llx\n", sreg, GPR[sreg], GPR[sreg+1], dest); PSD1 &= 0x87FFFFFE; /* clear the old CC's */ @@ -4437,7 +4503,7 @@ doovr3: goto inv; /* invalid instruction in nonbased mode */ if (FC != 0) { /* word address only */ TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC8 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } @@ -4458,7 +4524,7 @@ doovr3: goto inv; /* invalid instruction in nonbased mode */ if ((FC & 3) != 0) { /* word address only */ TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC9 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } @@ -4578,8 +4644,8 @@ doovr3: /* exponent must not be zero or all 1's */ /* normalize the value Rd in GPR[reg] and put exponent into Rs GPR[sreg] */ temp = s_nor(GPR[reg], &GPR[sreg]); - sim_debug(DEBUG_CMD, &cpu_dev, - "NOR GPR[%d] %08x result %08x exp %08x\n", + sim_debug(DEBUG_EXP, &cpu_dev, + "NOR GPR[%d] %08x result %08x exp %02x\n", reg, GPR[reg], temp, GPR[sreg]); GPR[reg] = temp; break; @@ -4606,8 +4672,8 @@ doovr3: td = (((t_uint64)GPR[reg]) << 32) | ((t_uint64)GPR[reg+1]); /* normalize the value Rd in GPR[reg] and put exponent into Rs GPR[sreg] */ dest = s_nord(td, &GPR[sreg]); - sim_debug(DEBUG_CMD, &cpu_dev, - "NORD GPR[%d] %08x %08x result %016llx exp %08x\n", + sim_debug(DEBUG_EXP, &cpu_dev, + "NORD GPR[%d] %08x %08x result %016llx exp %02x\n", reg, GPR[reg], GPR[reg+1], dest, GPR[sreg]); GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ @@ -5100,9 +5166,14 @@ meoa: /* merge point for eor, and, or */ IR = temp; /* get instruction from memory */ if (FC == 3) /* see if right halfword specified */ IR <<= 16; /* move over the HW instruction */ - if ((IR & 0xFC7F0000) == 0xC8070000 || - (IR & 0xFF800000) == 0xA8000000 || +#ifdef DIAG_SAYS_OK_TO_EXECUTE_ANOTHER_EXECUTE + if ((IR & 0xFC7F0000) == 0xC8070000 || /* No EXR target */ + (IR & 0xFF800000) == 0xA8000000 || /* No EXM target */ (IR & 0xFC000000) == 0x80000000) { +#else + /* 32/67 diag says execute of execute is OK */ + if ((IR & 0xFC000000) == 0x80000000) { +#endif /* Fault, attempt to execute another EXR, EXRR, EXM, or LEAR */ goto inv; /* invalid instruction */ } @@ -5505,11 +5576,14 @@ doovr2: /* if bit 30 set, instruction is in right hw, do EXRR */ if (addr & 2) IR <<= 16; /* move instruction to left HW */ +#ifdef DIAG_SAYS_OK_TO_EXECUTE_ANOTHER_EXECUTE + /* 32/67 diag says execute of execute is OK */ if ((IR & 0xFC7F0000) == 0xC8070000 || (IR & 0xFF800000) == 0xA8000000) { /* Fault, attempt to execute another EXR, EXRR, or EXM */ goto inv; /* invalid instruction */ } +#endif EXM_EXR = 4; /* set PC increment for EXR */ OPSD1 &= 0x87FFFFFE; /* clear the old CC's */ OPSD1 |= PSD1 & 0x78000000; /* update the CC's in the PSD */ @@ -5691,15 +5765,47 @@ doovr2: /* do ADFW or SUFW instructions */ temp2 = GPR[reg]; /* dest - reg contents specified by Rd */ addr = (uint32)(source & D32RMASK); /* get 32 bits from source memory */ - if (opr & 8) { /* Was it ADFW? */ - temp = s_adfw(temp2, addr, &CC); /* do ADFW */ - } else { - /* s_sufw will negate the value before calling add */ - temp = s_sufw(temp2, addr, &CC); /* do SUFW */ + if ((opr & 8) == 0) { /* Was it SUFW? */ + addr = NEGATE32(addr); /* take negative for add */ } - sim_debug(DEBUG_CMD, &cpu_dev, - "%s GPR[%d] %08x addr %08x result %08x\n", - (opr&8) ? "ADFW":"SUFW", reg, GPR[reg], addr, temp); +// if (opr & 8) { /* Was it ADFW? */ + /* test for zero reg value */ +// if ((temp2 == 0) && ((addr & 0x80000000) == 0)) { /* is reg value zero */ + if (temp2 == 0) { /* reg value is zero */ + temp = s_normfw(addr, &CC); /* normalize addr value */ + if (CC & CC1BIT) { + CC = 0; /* remove addr except */ + if (temp & FSIGN) + CC |= CC3BIT; /* CC3 for neg */ + else if (temp == 0) + CC |= CC4BIT; /* CC4 for zero */ + else + CC |= CC2BIT; /* CC2 for greater than zero */ + } + } + else +// if ((addr == 0) && ((temp2 & 0x80000000) == 0)) { /* is reg value zero */ + if (addr == 0) { /* mem value is zero */ + temp = s_normfw(temp2, &CC); /* normalize addr value */ + if (CC & CC1BIT) { + CC = 0; /* remove addr except */ + if (temp & FSIGN) + CC |= CC3BIT; /* CC3 for neg */ + else if (temp == 0) + CC |= CC4BIT; /* CC4 for zero */ + else + CC |= CC2BIT; /* CC2 for greater than zero */ + } + } + else + temp = s_adfw(temp2, addr, &CC); /* do ADFW */ +// } else { +// /* s_sufw will negate the value before calling add */ +// temp = s_sufw(temp2, addr, &CC); /* do SUFW */ +// } + sim_debug(DEBUG_EXP, &cpu_dev, + "%s GPR[%d] %08x addr %08x result %08x CC %08x\n", + (opr&8) ? "ADFW":"SUFW", reg, GPR[reg], addr, temp, CC); ovr = 0; if (CC & CC1BIT) ovr = 1; @@ -5723,15 +5829,45 @@ doovr2: td = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ td |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ /* source has 64 bit memory data */ - if (opr & 8) { /* Was it ADFD? */ - dest = s_adfd(td, source, &CC); /* do ADFD */ - } else { - /* s_sufd will negate the memory value before calling add */ - dest = s_sufd(td, source, &CC); /* do SUFD */ + if ((opr & 8) == 0) { /* Was it SUFD? */ + td = NEGATE32(td); /* make negative for subtract */ } - sim_debug(DEBUG_CMD, &cpu_dev, - "%s GPR[%d] %08x %08x src %016llx result %016llx\n", - (opr&8) ? "ADFD":"SUFD", reg, GPR[reg], GPR[reg+1], source, dest); + /* test for zero reg value */ +// if ((td == 0) && ((GPR[reg] & 0x80000000) == 0)) { /* is reg value zero */ + if (td == 0) { /* is reg value zero */ + dest = s_normfd(source, &CC); /* normalize addr value */ + if (CC & CC1BIT) { + CC = 0; /* remove addr except */ + if (dest & DMSIGN) + CC |= CC3BIT; /* CC3 for neg */ + else if (dest == 0) + CC |= CC4BIT; /* CC4 for zero */ + else + CC |= CC2BIT; /* CC2 for greater than zero */ + } + } + else + if (source == 0) { /* memory value zero? */ + dest = s_normfd(td, &CC); /* normalize reg value */ + if (CC & CC1BIT) { + CC = 0; /* remove addr except */ + if (dest & DMSIGN) + CC |= CC3BIT; /* CC3 for neg */ + else if (dest == 0) + CC |= CC4BIT; /* CC4 for zero */ + else + CC |= CC2BIT; /* CC2 for greater than zero */ + } + } + else + dest = s_adfd(td, source, &CC); /* do ADFD */ +// } else { +// /* s_sufd will negate the memory value before calling add */ +// dest = s_sufd(td, source, &CC); /* do SUFD */ +// } + sim_debug(DEBUG_EXP, &cpu_dev, + "%s GPR[%d] %08x %08x src %016llx result %016llx CC %08x\n", + (opr&8) ? "ADFD":"SUFD", reg, GPR[reg], GPR[reg+1], source, dest, CC); ovr = 0; if (CC & CC1BIT) /* test for overflow detection */ ovr = 1; @@ -5769,7 +5905,7 @@ doovr2: CC = 0; /* clear the CC'ss */ /* handle float or double mul/div instructions */ if (dbl == 0) { - /* do MPFW or DIVW instructions */ + /* do MPFW or DVFW instructions */ temp2 = GPR[reg]; /* dest - reg contents specified by Rd */ addr = (uint32)(source & D32RMASK); /* get 32 bits from source memory */ if (opr & 8) { /* Was it MPFW? */ @@ -5777,7 +5913,7 @@ doovr2: } else { temp = (uint32)s_dvfw(temp2, addr, &CC); /* do DVFW */ } - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_EXP, &cpu_dev, "%s GPR[%d] %08x addr %08x result %08x\n", (opr&8) ? "MPFW":"DVFW", reg, GPR[reg], addr, temp); if (CC & CC1BIT) @@ -5807,7 +5943,7 @@ doovr2: } else { dest = s_dvfd(td, source, &CC); /* do DVFD */ } - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_EXP, &cpu_dev, "%s GPR[%d] %08x %08x src %016llx result %016llx\n", (opr&8) ? "MPFD":"DVFD", reg, GPR[reg], GPR[reg+1], source, dest); if (CC & CC1BIT) /* test for overflow detection */ @@ -5914,7 +6050,7 @@ doovr2: /* if ((FC & 5) != 0) { */ if ((FC & 4) != 0) { TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC10 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } @@ -5949,7 +6085,7 @@ doovr2: /* if ((FC & 5) != 0) { */ if ((FC & 4) != 0) { TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC11 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } @@ -6036,7 +6172,7 @@ doovr2: if ((FC & 04) != 0 || FC == 2) { /* can not be byte or doubleword */ /* Fault */ TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC12 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } @@ -6127,12 +6263,12 @@ doovr2: if (PSD2 & MAPBIT) { /* set mapped mode in cpu status */ CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ -//041420 sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_EXP, &cpu_dev, +// sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "B4 LPSDCM temp %06x TPSD %08x %08x PSD %08x %08x\n", temp, TPSD[0], TPSD[1], PSD1, PSD2); -//041420 sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_EXP, &cpu_dev, +// sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "B4 LPSDCM BPIX %04x CPIX %04x CPIXPL %04x\n", BPIX, CPIX, CPIXPL); #ifdef FOR_DEBUG_MPX_041420 @@ -6199,20 +6335,20 @@ doovr2: if ((PSD2 & RETMBIT) == 0) { /* don't load maps if retain bit set */ /* we need to load the new maps */ TRAPME = load_maps(PSD, 0); /* load maps for new PSD */ -//041420 sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_EXP, &cpu_dev, +// sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "AF LPSDCM TPSD %08x %08x PSD %08x %08x TRAPME %02x\n", TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); -//041420 sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_EXP, &cpu_dev, +// sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "AF LPSDCM BPIX %04x CPIX %04x CPIXPL %04x\n", BPIX, CPIX, CPIXPL); -//041420 sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_EXP, &cpu_dev, +// sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "AF LPSDCM OS MAPC[0-5] %08x %08x %08x %08x %08x %08x\n", MAPC[0], MAPC[1], MAPC[2], MAPC[3], MAPC[4], MAPC[5]); -//041420 sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_EXP, &cpu_dev, +// sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "AF LPSDCM US MAPC[%x-%x] %08x %08x %08x %08x %08x %08x\n", BPIX, BPIX+5, MAPC[BPIX], MAPC[BPIX+1], MAPC[BPIX+2], MAPC[BPIX+3], MAPC[BPIX+4], MAPC[BPIX+5]); @@ -6797,7 +6933,7 @@ mcheck: if (dbl) { /* if double reg, store 2nd reg */ if (reg & 1) { /* is it double regs into odd reg */ TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC13 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } @@ -7223,7 +7359,8 @@ uint32 def_floppy = 0x7ef0; /* IOP floppy disk channel 7e, device f0 /* do any one time initialization here for cpu */ t_stat cpu_reset(DEVICE *dptr) { - int i; + int i; + t_stat devs = SCPE_OK; /* leave regs alone so values can be passed to boot code */ PSD1 = 0x80000000; /* privileged, non mapped, non extended, address 0 */ @@ -7246,7 +7383,7 @@ t_stat cpu_reset(DEVICE *dptr) ISMCW = 0; /* No V9 IPU Shadow Memory Configuration */ RDYQIN = RDYQOUT = 0; /* initialize cheannel ready queue */ - chan_set_devs(); /* set up the defined devices on the simulator */ + devs = chan_set_devs(); /* set up the defined devices on the simulator */ /* set default breaks to execution tracing */ sim_brk_types = sim_brk_dflt = SWMASK('E'); @@ -7306,7 +7443,9 @@ t_stat cpu_reset(DEVICE *dptr) M[4] = 0x02000000; /* 0x10 IOCD 3 Read into address 0 */ M[5] = 0x000006EC; /* 0x14 IOCD 3 Read 0x6EC bytes */ loading = 0; /* not loading yet */ - /* we are good to go */ + /* we are good to go or error from device setup */ + if (devs != SCPE_OK) + return devs; return SCPE_OK; } diff --git a/SEL32/sel32_defs.h b/SEL32/sel32_defs.h index 09a6e4f..9316066 100644 --- a/SEL32/sel32_defs.h +++ b/SEL32/sel32_defs.h @@ -191,6 +191,9 @@ extern DEVICE lpr_dev; /* channel program data for a chan/sub-address */ typedef struct chp { /* channel program values */ +#ifndef OLD_CHAN + UNIT *unitptr; /* Back pointer to units structure */ +#endif uint32 chan_inch_addr; /* Channel status dw in memory */ uint32 chan_caw; /* Channel command address word */ uint32 ccw_addr; /* Channel address */ diff --git a/SEL32/sel32_disk.c b/SEL32/sel32_disk.c index c02275d..7b70dd4 100644 --- a/SEL32/sel32_disk.c +++ b/SEL32/sel32_disk.c @@ -266,12 +266,12 @@ disk_type[] = {"MH300", 19, 192, 20, 800, 823, 0x40}, /* 3 823 300M 8127 */ {"MH600", 40, 192, 20, 800, 843, 0x40}, /* 4 843 600M 8155 */ /* For UTX */ - {"9342", 5, 256, 16, 819, 823, 0x40}, /* 5 823 80M XXXX */ - {"8148", 10, 256, 16, 819, 823, 0x40}, /* 6 823 160M 8148 */ - {"9346", 19, 256, 16, 819, 823, 0x40}, /* 7 823 300M */ - {"8858", 24, 256, 16, 707, 711, 0x40}, /* 8 711 340M */ - {"8887", 10, 256, 35, 819, 823, 0x40}, /* 9 823 340M */ - {"8155", 40, 256, 16, 839, 843, 0x40}, /* 10 843 675M */ + {"9342", 5, 256, 16, 819, 823, 0x41}, /* 5 823 80M XXXX */ + {"8148", 10, 256, 16, 819, 823, 0x41}, /* 6 823 160M 8148 */ + {"9346", 19, 256, 16, 819, 823, 0x41}, /* 7 823 300M */ + {"8858", 24, 256, 16, 707, 711, 0x41}, /* 8 711 340M */ + {"8887", 10, 256, 35, 819, 823, 0x41}, /* 9 823 340M */ + {"8155", 40, 256, 16, 839, 843, 0x41}, /* 10 843 675M */ {NULL, 0} }; @@ -527,7 +527,7 @@ t_stat disk_srv(UNIT *uptr) CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */ int cmd = uptr->CMDu3 & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); - uint32 trk, cyl, sec; + uint32 trk=0, cyl=0, sec=0; int unit = (uptr - dptr->units); int len; int i; diff --git a/SEL32/sel32_fltpt.c b/SEL32/sel32_fltpt.c index 71b1c52..189fbb0 100644 --- a/SEL32/sel32_fltpt.c +++ b/SEL32/sel32_fltpt.c @@ -71,19 +71,24 @@ uint32 s_mpfw(uint32 reg, uint32 mem, uint32 *cc); uint32 s_dvfw(uint32 reg, uint32 mem, uint32 *cc); t_uint64 s_mpfd(t_uint64 reg, t_uint64 mem, uint32 *cc); t_uint64 s_dvfd(t_uint64 reg, t_uint64 mem, uint32 *cc); +uint32 s_normfw(uint32 mem, uint32 *cc); +t_uint64 s_normfd(t_uint64 mem, uint32 *cc); #define NORMASK 0xf8000000 /* normalize 5 bit mask */ #define DNORMASK 0xf800000000000000ll /* double normalize 5 bit mask */ -#define EXMASK 0x7f000000 /* exponent mask */ -#define FRMASK 0x80ffffff /* fraction mask */ +#define EXMASK 0x7f000000 /* exponent mask */ +#define FRMASK 0x80ffffff /* fraction mask */ #define DEXMASK 0x7f00000000000000ll /* exponent mask */ +#define DFSVAL 0xff00000000000000ll /* minus full scale value */ #define DFRMASK 0x80ffffffffffffffll /* fraction mask */ #define NEGATE32(val) ((~val) + 1) /* negate a value 16/32/64 bits */ -/* normalize floating point number */ +/* normalize floating point fraction */ uint32 s_nor(uint32 reg, uint32 *exp) { uint32 texp = 0; /* no exponent yet */ + sim_debug(DEBUG_EXP, &cpu_dev, + "s_nor entry reg %08x texp %08x\n", reg, texp); if (reg != 0) { /* do nothing if reg is already zero */ uint32 mv = reg & NORMASK; /* mask off bits 0-4 */ while ((mv == 0) || (mv == NORMASK)) { @@ -94,9 +99,11 @@ uint32 s_nor(uint32 reg, uint32 *exp) { } /* bits 0-4 of reg is neither 0 nor all ones */ /* show that reg is normalized */ - texp = 0x40 - texp; /* subtract shift count from 0x40 */ + texp = (uint32)(0x40-(int32)texp); /* subtract shift count from 0x40 */ } *exp = texp; /* return exponent */ + sim_debug(DEBUG_EXP, &cpu_dev, + "s_nor exit reg %08x texp %08x\n", reg, texp); return (reg); /* return normalized register */ } @@ -104,6 +111,8 @@ uint32 s_nor(uint32 reg, uint32 *exp) { t_uint64 s_nord(t_uint64 reg, uint32 *exp) { uint32 texp = 0; /* no exponent yet */ + sim_debug(DEBUG_EXP, &cpu_dev, + "s_nord entry regs %016llx texp %08x\n", reg, texp); if (reg != 0) { /* do nothing if reg is already zero */ t_uint64 mv = reg & DNORMASK; /* mask off bits 0-4 */ while ((mv == 0) || (mv == DNORMASK)) { @@ -114,23 +123,311 @@ t_uint64 s_nord(t_uint64 reg, uint32 *exp) { } /* bits 0-4 of reg is neither 0 nor all ones */ /* show that reg is normalized */ - texp = 0x40 - texp; /* subtract shift count from 0x40 */ + texp = (uint32)(0x40-(int32)texp); /* subtract shift count from 0x40 */ } *exp = texp; /* return exponent */ + sim_debug(DEBUG_EXP, &cpu_dev, + "s_nord exit reg %016llx texp %08x\n", reg, texp); return (reg); /* return normalized double register */ } +/************************************************************** +* This routine unpacks the floating point number in (r6,r7). * +* The unbiased, right justified, two's complement exponent * +* is returned in r1. If xxfw is set, the two's complement * +* fraction (with the binary point to the left of bit 8) is * +* returned in r6, and r7 is cleared. if xxfd is reset, the * +* two's complement double precision fraction is returned in * +* (r6,r7). * +***************************************************************/ +struct fpnum { + int32 msw; /* most significent word */ + int32 lsw; /* least significient word */ + int32 exp; /* exponent */ + int32 CCs; /* condition codes */ +}; + +/* unpack single precision floating point number */ +void unpacks(struct fpnum *np) { + uint32 ex = np->msw & 0xff000000; /* get exponent & sign from msw */ + + sim_debug(DEBUG_EXP, &cpu_dev, + "unpacks entry msw %08x exp %08x\n", np->msw, ex); + np->lsw = 0; /* 1 word for single precision */ +// ex = np->msw & 0xff000000; /* get exponent & sign from msw */ + if (ex & 0x80000000) /* check for negative */ + ex ^= 0xff000000; /* reset sign & complement exponent */ + np->msw ^= ex; /* replace exponent with sign extension */ + ex = ((uint32)ex) >> 24; /* right justify the exponent */ + ex -= 0x40; /* unbias exponent */ + np->exp = ex; /* save the exponent */ + np->CCs = 0; /* zero CCs for later */ + sim_debug(DEBUG_EXP, &cpu_dev, + "unpacks return msw %08x exp %08x\n", np->msw, ex); + return; +} + +/* unpack double precision floating point number */ +void unpackd(struct fpnum *np) { + int32 ex = np->msw & 0xff000000; /* get exponent & sign from msw */ + if (ex & 0x80000000) /* check for negative */ + ex ^= 0xff000000; /* reset sign & complement exponent */ + np->msw ^= ex; /* replace exponent with sign extension */ + ex = ((uint32)ex) >> 24; /* right justify the exponent */ + ex -= 0x40; /* unbias exponent */ + np->exp = ex; /* save exponent */ + np->CCs = 0; /* zero CCs for later */ + return; +} + +/************************************************************** +* Common routine for finishing the various F.P. instruction * +* simulations. at this point, r1 = raw exponent, and * +* (r6,r7) = unnormalized fraction, with the binary point to * +* the left of r6[8]. The simulated condition codes will be * +* returned in bits 1 through 4 of "sim.flag." * +* * +* Floating point operations not terminating with an arith- * +* metic exception produce the following condition codes: * +* * +* CC1 CC2 CC3 CC4 Definition * +* ------------------------------------------------------- * +* 0 1 0 0 no exception, fraction positive * +* 0 0 1 0 no exception, fraction negative * +* 0 0 0 1 no exception, fraction = zero * +* * +* * +* an arithmetic exception produces the follwing condition * +* code settings: * +* * +* CC1 CC2 CC3 CC4 Definition * +* -------------------------------------------------------- * +* 1 0 1 0 exp underflow, fraction negative * +* 1 0 1 1 exp overflow, fraction negative * +* 1 1 0 0 exp underflow, fraction positive * +* 1 1 0 1 exp overflow, fraction positive * +* * +**************************************************************/ +/** Normalization and rounding of single precision number */ +void packs(struct fpnum *np) { + uint32 ex, tmp, tmp2; + + t_uint64 num = ((t_uint64)np->msw << 32) | np->lsw; /* make 64 bit num */ + + sim_debug(DEBUG_EXP, &cpu_dev, + "pack entry msw %08x lsw %08x exp %08x num %016llx\n", + np->msw, np->lsw, np->exp, num); + + num = ((t_int64)num) << 3; /* slad 3 to align for normalization */ + + sim_debug(DEBUG_EXP, &cpu_dev, + "pack pl 0 num %016llx ex %08x exp %08x\n", num, ex, np->exp); + + num = s_nord(num, &ex); /* normalize the number with cnt in ex */ + + sim_debug(DEBUG_EXP, &cpu_dev, + "pack pl 1 num %016llx ex %08x exp %08x\n", num, ex, np->exp); + + num = ((t_int64)num) >> 7; /* srad 7 to align & sign extend number */ + + sim_debug(DEBUG_EXP, &cpu_dev, + "pack pl 2 num %016llx ex %08x exp %08x\n", num, ex, np->exp); + + if (num & DMSIGN) /* test for negative fraction */ + np->CCs = CC3BIT; /* show fraction negative */ + else + if (num == 0) { + np->CCs = CC4BIT; /* show fraction zero */ + np->msw = 0; /* save msw */ + np->lsw = 0; /* save lsw */ + np->exp = 0; /* save exp */ + return; /* done if zero */ + } + else + np->CCs = CC2BIT; /* show fraction positive */ + + sim_debug(DEBUG_EXP, &cpu_dev, + "pack pl 3 CC %08x num = %016llx ex = %08x\n", np->CCs, num, ex); + /* we need to round single precision number */ + tmp = (num >> 32) & 0xffffffff; /* get msw */ + tmp2 = num & 0xffffffff; /* get lsw */ + if ((int32)tmp >= 0x00ffffff) { /* if at max, no rounding */ + if (tmp2 & 0x80000000) /* round if set */ + tmp += 1; /* round fraction */ + } + num = (((t_uint64)tmp) << 32); /* make 64 bit num with lo 32 bits zero */ + + sim_debug(DEBUG_EXP, &cpu_dev, + "pack pl 4 num %016llx msw %08x exp %08x ex %08x\n", num, np->msw, np->exp, ex); +//4110000 bad if ((t_int64)num <= DFSVAL) { /* see if > 0xff00000000000000 */ +//4110000 bad if ((t_int64)num == DFSVAL) { /* see if > 0xff00000000000000 */ +//80000001 has cc bad if ((t_int64)num >= DFSVAL) { /* see if > 0xff00000000000000 */ +//needs >= for BEF -> BEF is EQ to DFSVAL + if (((t_int64)num) >= DFSVAL) { /* see if > 0xff00000000000000 */ + /* fixup fraction to not have -1 in results */ + num = ((t_int64)num) >> 4; /* sra 4 shift over 4 bits */ + ex += 1; /* bump exponent */ + sim_debug(DEBUG_EXP, &cpu_dev, + "pack pl 4a num = %016llx exp = %08x ex = %08x\n", num, np->exp, ex); + } + /* end normalization and rounding */ + np->exp += ex; /* normalized, biased exp */ + np->exp += 1; /* correct shift count */ + + sim_debug(DEBUG_EXP, &cpu_dev, + "pack n&r num %016llx msw %08x exp %08x ex %08x\n", num, np->msw, np->exp, ex); + if (((int32)(np->exp)) < 0) { /* check for exp neg underflow */ + np->CCs |= CC1BIT; /* set CC1 & return zero */ + np->msw = 0; + np->lsw = 0; + return; + } + sim_debug(DEBUG_EXP, &cpu_dev, + "pack exp num %016llx msw %08x exp %08x ex %08x\n", num, np->msw, np->exp, ex); + /* if no exponent overflow merge exp & fraction and return */ + if (((int32)(np->exp)) <= 0x7f) { + np->msw = (num >> 32); /* get msw */ + np->lsw = num & 0xffffffff; /* get lsw */ + sim_debug(DEBUG_EXP, &cpu_dev, + "packs ret msw %08x exp %08x\n", np->msw, np->exp); + ex = np->exp << 24; /* put exponent in bits 1-7 */ + sim_debug(DEBUG_EXP, &cpu_dev, + "packs ret msw %08x exp %08x ex %08x\n", np->msw, np->exp, ex); + np->msw ^= ex; /* merge exponent & fraction */ + sim_debug(DEBUG_EXP, &cpu_dev, + "packs ret CCs %08x msw %08x exp %08x ex %08x\n", np->CCs, np->msw, np->exp, ex); + return; /* CCs already set */ + } + /* process overflow exponent */ + np->CCs |= CC1BIT; /* set CC1 */ + np->CCs |= CC4BIT; /* set CC4 */ + /* do SP max value */ + if (np->CCs & CC2BIT) { /* see if CC2 is set */ + np->msw = 0x7fffffff; /* yes, use max pos value */ + np->lsw = 0; /* zero for SP */ + sim_debug(DEBUG_EXP, &cpu_dev, + "pack SP xit1 CCs %08x msw %08x exp %08x ex %08x\n", + np->CCs, np->msw, np->exp, ex); + return; + } + np->msw = 0x80000001; /* set max neg value */ + np->lsw = 0; /* zero for sp */ + sim_debug(DEBUG_EXP, &cpu_dev, + "pack SP xit2 CCs %08x msw %08x exp %08x ex %08x\n", + np->CCs, np->msw, np->exp, ex); + return; +} + +/** Normalization and rounding of double precision number */ +void packd(struct fpnum *np) { + uint32 ex; + + t_uint64 num = ((t_uint64)np->msw << 32) | np->lsw; /* make 64 bit num */ + + num = ((t_int64)num) << 3; /* sla 3 to align for normalization */ + num = s_nord(num, &ex); /* normalize the number with cnt in ex */ + num = ((t_int64)num) >> 7; /* align & sign extend number */ + if (num & DMSIGN) /* test for negative fraction */ + np->CCs = CC3BIT; /* show fraction negative */ + else + if (num == 0) { + np->CCs = CC4BIT; /* show fraction zero */ + np->msw = 0; /* save msw */ + np->lsw = 0; /* save lsw */ + np->exp = 0; /* save exp */ + return; /* done if zero */ + } + else + np->CCs = CC2BIT; /* show fraction positive */ + +// if ((t_int64)num <= DFSVAL) { /* see if > 0xff00000000000000 */ + if ((t_int64)num >= DFSVAL) { /* see if > 0xff00000000000000 */ + num >>= 4; /* shift over 4 bits */ + ex += 1; /* bump exponent */ + } + /* end normalization and rounding */ + np->exp += ex; /* normalized, biased exp */ + np->exp += 1; /* correct shift count */ + if (((int32)(np->exp)) < 0) { /* check for exp neg underflow */ + np->CCs |= CC1BIT; /* set CC1 & return zero */ + np->msw = 0; + np->lsw = 0; + return; + } + /* if no exponent overflow merge exp & fraction & return */ + if (((int32)(np->exp)) <= 0x7f) { + np->msw = (num >> 32); /* get msw */ + np->lsw = num & 0xffffffff; /* get lsw */ + ex = np->exp << 24; /* put exponent in bits 1-7 */ + np->msw ^= ex; /* merge exponent & fraction */ + return; /* CCs already set */ + } + /* process overflow exponent */ + np->CCs |= CC1BIT; /* set CC1 & return zero */ + np->CCs |= CC4BIT; /* set CC4 & return zero */ + /* do DP max value */ + if (np->CCs & CC2BIT) { /* see if CC2 is set */ + np->msw = 0x7fffffff; /* CC2=1 set exp overflow, pos frac */ + np->lsw = 0xffffffff; + return; + } + np->msw = 0x80000000; /* CC2=0 set exp underflow, frac pos */ + np->lsw = 0x00000001; + return; +} + +/* normalize the memory value when adding number to zero */ +uint32 s_normfw(uint32 mem, uint32 *cc) { + struct fpnum fpn = {0}; + uint32 ret; + + if (mem == 0) { /* make sure we have a number */ + *cc = CC4BIT; /* set the cc's */ + return 0; /* return zero */ + } + sim_debug(DEBUG_EXP, &cpu_dev, + "NORMFW entry mem %08x\n", mem); + fpn.msw = mem; /* save upper 32 bits */ + fpn.lsw = 0; /* clear lower 32 bits */ + unpacks(&fpn); /* unpack number */ + packs(&fpn); /* pack it back up */ + ret = fpn.msw; /* return normalized number */ + sim_debug(DEBUG_EXP, &cpu_dev, + "NORMFW return mem %08x result %08x CC's %08x\n", mem, ret, fpn.CCs); + /* return normalized number */ + *cc = fpn.CCs; /* set the cc's */ + return ret; /* return result */ +} + /* add memory floating point number to register floating point number */ /* set CC1 if overflow/underflow */ uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) { uint32 mfrac, rfrac, frac, ret=0, oexp; uint32 CC, sc, sign, expr, expm, exp; +#ifdef DO_NORMALIZE + struct fpnum fpn = {0}; +#endif *cc = 0; /* clear the CC'ss */ CC = 0; /* clear local CC's */ + + sim_debug(DEBUG_EXP, &cpu_dev, +// "ADFW entry mem %08x reg %08x result %08x\n", mem, reg, ret); + "ADFW entry mem %08x reg %08x\n", mem, reg); /* process the memory operand value */ if (mem == 0) { /* test for zero operand */ ret = reg; /* return original register value */ +#ifdef DO_NORMALIZE + if (ret == 0) + goto goout; /* nothing + nothing = nothing */ + fpn.msw = ret; /* save upper 32 bits */ + fpn.lsw = 0; /* clear lower 32 bits */ + unpacks(&fpn); /* unpack number */ + packs(&fpn); /* pack it back up */ + ret = fpn.msw; /* return normalized number */ + CC = fpn.CCs; /* set the cc's */ + goto goout2; /* go set cc's and return */ +#endif goto goout; /* go set cc's and return */ } expm = mem & EXMASK; /* extract exponent from operand */ @@ -145,6 +442,18 @@ uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) { /* process the register operator value */ if (reg == 0) { ret = mem; /* return original mem operand value */ +#ifdef DO_NORMALIZE + if (ret == 0) + goto goout; /* nothing + nothing = nothing */ + /* reg is 0 and mem is not zero, normalize mem */ + fpn.msw = ret; /* save upper 32 bits */ + fpn.lsw = 0; /* clear lower 32 bits */ + unpacks(&fpn); /* unpack number */ + packs(&fpn); /* pack it back up */ + ret = fpn.msw; /* return normalized number */ + CC = fpn.CCs; /* set the cc's */ + goto goout2; /* go set cc's and return */ +#endif goto goout; /* go set cc's and return */ } expr = reg & EXMASK; /* extract exponent from reg operand */ @@ -157,6 +466,8 @@ uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) { rfrac = ((int32)rfrac) << 4; /* do sla 4 of fraction */ exp = expr - expm; /* subtract memory exponent from reg exponent */ + sim_debug(DEBUG_EXP, &cpu_dev, + "ADFW2 exp calc expr %04x expm %04x exp %04x\n", expr, expm, exp); if (exp & MSIGN) { /* test for negative */ /* difference is negative, so memory exponent is larger */ exp = NEGATE32(exp); /* make difference positive */ @@ -167,7 +478,8 @@ uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) { /* difference is <= 6, so adjust to smaller value for add */ /* difference is number of 4 bit right shifts to do */ /* (exp >> 24) * 4 */ - sc = exp >> (24 - 2); /* shift count down to do x4 the count */ +//42220 sc = exp >> (24 - 2); /* shift count down to do x4 the count */ +/*try*/ sc = (exp >> 24) * 4; /* shift count down to do x4 the count */ rfrac = ((int32)rfrac) >> sc; oexp = expm; /* mem is larger exponent, save for final exponent add */ } else { @@ -181,11 +493,16 @@ uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) { /* difference is <= 6, so adjust to smaller value for add */ /* difference is number of 4 bit right shifts to do */ /* (exp >> 24) * 4 */ - sc = exp >> (24 - 2); /* shift count down to do x4 the count */ - mfrac = ((int32)mfrac) >> sc; +//42220 sc = exp >> (24 - 2); /* shift count down to do x4 the count */ +/*try*/ sc = (exp >> 24) * 4; /* shift count down to do x4 the count */ + frac = ((int32)mfrac) >> sc; oexp = expr; /* reg is larger exponent, save for final exponent add */ } + sim_debug(DEBUG_EXP, &cpu_dev, + "ADFW3 after exp calc exp %04x sc %04x oexp %04x\n", exp, sc, oexp); frac = rfrac + mfrac; /* add fractions */ + sim_debug(DEBUG_EXP, &cpu_dev, + "ADFW4 frac calc rfrac %06x mfrac %06x frac %04x\n", rfrac, mfrac, frac); if (frac == 0) { /* return the zero value */ ret = frac; /* return zero to caller */ @@ -290,6 +607,8 @@ goout: else CC |= CC2BIT; /* CC2 for greater than zero */ goout2: + sim_debug(DEBUG_EXP, &cpu_dev, + "ADFW return mem %08x reg %08x result %08x CC %08x\n", mem, reg, ret, CC); /* return temp to destination reg */ *cc = CC; /* return CC's */ return ret; /* return result */ @@ -300,6 +619,27 @@ uint32 s_sufw(uint32 reg, uint32 mem, uint32 *cc) { return s_adfw(reg, NEGATE32(mem), cc); } +/* normalize the memory value when adding number to zero */ +t_uint64 s_normfd(t_uint64 mem, uint32 *cc) { + struct fpnum fpn = {0}; + t_uint64 ret; + + if (mem == 0) { /* make sure we have a number */ + *cc = CC4BIT; /* set the cc's */ + return 0; /* return zero */ + } + fpn.msw = (mem >> 32); /* get msw */ + fpn.lsw = mem & 0xffffffff; /* get lsw */ + unpackd(&fpn); /* unpack number */ + packd(&fpn); /* pack it back up */ + ret = ((t_uint64)fpn.msw << 32) | fpn.lsw; /* make 64 bit num */ + sim_debug(DEBUG_EXP, &cpu_dev, + "NORMFD return mem %016llx result %016llx CC's %08x\n", mem, ret, fpn.CCs); + /* return normalized number */ + *cc = fpn.CCs; /* set the cc's */ + return ret; /* return normalized result */ +} + /* add memory floating point number to register floating point number */ /* set CC1 if overflow/underflow */ t_uint64 s_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { @@ -308,11 +648,14 @@ t_uint64 s_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { *cc = 0; /* clear the CC'ss */ CC = 0; /* clear local CC's */ + +#ifndef DO_NORMALIZE /* process the memory operand value */ if (mem == 0) { /* test for zero operand */ ret = reg; /* return original reg value */ goto goout; /* go set cc's and return */ } +#endif /* separate mem dw into two 32 bit numbers */ /* mem value is not zero, so extract exponent and mantissa */ expm = (uint32)((mem & DEXMASK) >> 32); /* extract exponent */ @@ -323,11 +666,13 @@ t_uint64 s_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { dblmem |= DEXMASK; /* adjust the fraction */ } +#ifndef DO_NORMALIZE /* process the register operator value */ if (reg == 0) { /* see if reg value is zero */ ret = mem; /* return original mem operand value */ goto goout; /* go set cc's and return */ } +#endif /* separate reg dw into two 32 bit numbers */ /* reg value is not zero, so extract exponent and mantissa */ expr = (uint32)((reg & DEXMASK) >> 32); /* extract exponent */ diff --git a/SEL32/sel32_hsdp.c b/SEL32/sel32_hsdp.c index f94dd5d..d24d524 100644 --- a/SEL32/sel32_hsdp.c +++ b/SEL32/sel32_hsdp.c @@ -630,7 +630,7 @@ t_stat hsdp_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 */ @@ -909,7 +909,7 @@ goout: sim_debug(DEBUG_CMD, dptr, "hsdp_srv STAR unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); -rezero: +//rezero: sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv seek unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); diff --git a/SEL32/sel32_iop.c b/SEL32/sel32_iop.c index 52345ae..2f8c98e 100644 --- a/SEL32/sel32_iop.c +++ b/SEL32/sel32_iop.c @@ -123,8 +123,8 @@ DEVICE iop_dev = { NULL, NULL, &iop_reset, /* examine, deposit, reset */ NULL, NULL, NULL, /* boot, attach, detach */ /* dib ptr, dev flags, debug flags, debug */ - &iop_dib, DEV_CHAN|DEV_DISABLE|DEV_DEBUG, 0, dev_debug, -// &iop_dib, DEV_CHAN|DEV_DIS|DEV_DISABLE|DEV_DEBUG, 0, dev_debug, +// &iop_dib, DEV_CHAN|DEV_DISABLE|DEV_DEBUG, 0, dev_debug, + &iop_dib, DEV_CHAN|DEV_DIS|DEV_DISABLE|DEV_DEBUG, 0, dev_debug, // NULL, NULL, &iop_help, /* ?, ?, help */ // NULL, NULL, &iop_desc /* ?, ?, description */ }; diff --git a/SEL32/sel32_mfp.c b/SEL32/sel32_mfp.c index fff139f..7d3e247 100644 --- a/SEL32/sel32_mfp.c +++ b/SEL32/sel32_mfp.c @@ -50,6 +50,7 @@ const char *mfp_desc(DEVICE *dptr); #define MFP_INCH 0x00 /* Initialize channel command */ #define MFP_INCH2 0xf0 /* Initialize channel command after start */ #define MFP_NOP 0x03 /* NOP command */ +#define MFP_SID 0x80 /* MFP status command */ #define MFP_MSK 0xff /* Command mask */ /* Status held in u3 */ @@ -182,6 +183,16 @@ uint16 mfp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) return 0; /* no status change */ break; + case MFP_SID: /* status ID command */ + sim_debug(DEBUG_CMD, &mfp_dev, "mfp_startcmd %04x: Cmd SID\n", chan); + uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ + uptr->u3 &= LMASK; /* leave only chsa */ + uptr->u3 |= (cmd & MFP_MSK); /* save SID command */ + sim_activate(uptr, 20); /* TRY 07-13-19 */ +//@41 sim_activate(uptr, 40); /* 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", @@ -208,7 +219,7 @@ t_stat mfp_srv(UNIT *uptr) 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 */ + if ((cmd != MFP_NOP) && (cmd != MFP_INCH2) && (cmd != MFP_SID)) { /* NOP, SID 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); @@ -218,7 +229,46 @@ t_stat mfp_srv(UNIT *uptr) 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); + sim_debug(DEBUG_CMD, &mfp_dev, "mfp_srv NOP chan %02x: chnend|devend\n", chsa); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ + return SCPE_OK; + } else + + /* 3 status wds are to be returned */ + /* Wd 1 MMXXXXXX board model # assume 00 00 08 02*/ + /* Wd 2 MMXXXXXX board firmware model # assume 00 00 08 02*/ + /* Wd 3 MMXXXXXX board firmware revision # assume 00 00 00 14*/ + if (cmd == MFP_SID) { /* send 12 byte Status ID data */ + uint8 ch; + + /* Word 0 */ + ch = 0x00; + chan_write_byte(chsa, &ch); /* write byte 0 */ + chan_write_byte(chsa, &ch); /* write byte 1 */ + ch = 0x80; + chan_write_byte(chsa, &ch); /* write byte 2 */ + ch = 0x02; + chan_write_byte(chsa, &ch); /* write byte 3 */ + + /* Word 1 */ + ch = 0x00; + chan_write_byte(chsa, &ch); /* write byte 4 */ + chan_write_byte(chsa, &ch); /* write byte 5 */ + ch = 0x80; + chan_write_byte(chsa, &ch); /* write byte 6 */ + ch = 0x02; + chan_write_byte(chsa, &ch); /* write byte 7 */ + + /* Word 2 */ + ch = 0x00; + chan_write_byte(chsa, &ch); /* write byte 8 */ + chan_write_byte(chsa, &ch); /* write byte 9 */ + chan_write_byte(chsa, &ch); /* write byte 10 */ + ch = 0x14; + chan_write_byte(chsa, &ch); /* write byte 11 */ + + uptr->u3 &= LMASK; /* nothing left, command complete */ + sim_debug(DEBUG_CMD, &mfp_dev, "mfp_srv SID chan %02x: chnend|devend\n", chsa); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ return SCPE_OK; } else diff --git a/SEL32/sel32_mt.c b/SEL32/sel32_mt.c index 609edcb..c5d0b00 100644 --- a/SEL32/sel32_mt.c +++ b/SEL32/sel32_mt.c @@ -387,6 +387,10 @@ uint16 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) case 0x00: /* INCH command */ sim_debug(DEBUG_CMD, dptr, "start INCH command\n"); +#ifdef DO_DYNAMIC_DEBUG + /* start debugging */ + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); +#endif sim_debug(DEBUG_CMD, dptr, "mt_startcmd starting INCH cmd, chsa %04x MemBuf %08x cnt %04x\n", chsa, chp->ccw_addr, chp->ccw_count); @@ -581,10 +585,8 @@ t_stat mt_srv(UNIT *uptr) "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); - } + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); #endif if (len == 0) { @@ -636,11 +638,11 @@ t_stat mt_srv(UNIT *uptr) /* 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 */ + WMH(mema+(16<<1),5); /* write left HW with count */ + WMH(mema+(17<<1),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); + "mt_srv cmd INCH chsa %04x addr %06x count %04x completed INCH16 %08x\n", + addr, mema, chp->ccw_count, RMW(mema+(8<<2))); 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 */ @@ -1118,9 +1120,11 @@ t_stat mt_srv(UNIT *uptr) case 3: uptr->CMD &= ~(MT_CMDMSK); uptr->SNS &= ~SNS_LOAD; /* reset BOT */ + uptr->SNS |= SNS_EOT; /* set EOT status */ mt_busy[bufnum] &= ~1; sim_debug(DEBUG_CMD, &mta_dev, "Skip file got EOT sense %08x unit %02x\n", uptr->SNS, unit); //BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK); +//*##*/ chan_end(addr, SNS_DEVEND|SNS_UNITCHK); chan_end(addr, SNS_DEVEND|SNS_UNITEXP); break; } diff --git a/SEL32/sel32_scsi.c b/SEL32/sel32_scsi.c index 9715130..33d3527 100644 --- a/SEL32/sel32_scsi.c +++ b/SEL32/sel32_scsi.c @@ -274,10 +274,10 @@ scsi_type[] = {"SD300", 9, 192, 32, 648, 1409, 0x40}, /*1 8828 300M 396674 sec */ {"SD700", 15, 192, 35, 648, 1546, 0x40}, /*2 8833 700M 797129 sec */ {"SD1200", 15, 192, 49, 648, 1931, 0x40}, /*3 8835 1200M 1389584 sec */ - {"8820", 9, 192, 18, 324, 966, 0x40}, /*4 8820 150M */ - {"8828", 9, 192, 36, 648, 966, 0x40}, /*5 8828 300M */ - {"8833", 18, 192, 20, 648, 46725, 0x40}, /*6 8833 700M */ - {"8835", 18, 192, 20, 648, 46725, 0x40}, /*7 8835 1200M */ + {"8820", 9, 256, 18, 324, 967, 0x41}, /*4 8820 150M */ + {"8821", 9, 256, 36, 648, 967, 0x41}, /*5 8828 300M */ + {"8833", 18, 256, 20, 648, 46725, 0x41}, /*6 8833 700M */ + {"8835", 18, 256, 20, 648, 46725, 0x41}, /*7 8835 1200M */ /* For UTX */ {NULL, 0} }; @@ -385,7 +385,7 @@ DIB sbb_dib = { 0x7600, /* 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 */ + {0}, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ }; DEVICE sbb_dev = { @@ -531,8 +531,8 @@ t_stat scsi_srv(UNIT *uptr) int i; uint32 cap = CAP(type); 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 */ + int32 ssize = scsi_type[type].ssiz*4; /* Size of one sector in bytes */ + uint32 tstart = 0; /* Location of start of cyl/track/sect in data */ uint8 buf2[1024]; uint8 buf[1024]; @@ -558,7 +558,7 @@ t_stat scsi_srv(UNIT *uptr) uint32 mema; /* memory address */ // uint32 daws[8]; /* drive attribute registers */ // uint32 i, j; - uint32 i; +// uint32 i; len = chp->ccw_count; /* INCH command count */ mema = chp->ccw_addr; /* get inch or buffer addr */ @@ -858,8 +858,8 @@ t_stat scsi_srv(UNIT *uptr) buf[4] = 0x81; buf[8] = 0x91; buf[12] = 0xf4; - buf[17] = HDS(type); /* # of heads */ - buf[23] = SPT(type); /* Sect/track */ + buf[17] = (uint8)HDS(type); /* # of heads */ + buf[23] = (uint8)SPT(type); /* Sect/track */ // buf[27] = SPT(type); /* Sect/track */ for (i=0; i> ((3-i)*8)) & 0xff; + ch = (((int32)ssize) >> ((3-i)*8)) & 0xff; if (chan_write_byte(chsa, &ch)) { /* we have error, bail out */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ @@ -1077,7 +1077,7 @@ t_stat scsi_srv(UNIT *uptr) uint32 mema; /* memory address */ // uint32 daws[8]; /* drive attribute registers */ // uint32 i, j; - uint32 i; + int32 i; uptr->SNS &= ~SNS_TCMD; /* show not presessing TCMD cmd chain */ len = chp->ccw_count; /* INCH command count */ diff --git a/SEL32/tests/diag.ini b/SEL32/tests/diag.ini index e4ab7b4..0e1ab20 100644 --- a/SEL32/tests/diag.ini +++ b/SEL32/tests/diag.ini @@ -20,12 +20,12 @@ set CPU 32/67 4M ; Set instruction trace history size ;;set cpu history=10000 ; useful options -;set cpu debug=cmd;exp +;set cpu debug=exp ;set cpu debug=cmd;exp;irq;trap;xio ;set cpu debug=cmd;irq;trap;exp ;set cpu debug=irq;trap;exp;xio ;set cpu debug=irq;xio -;set cpu debug=irq;exp +;set cpu debug=irq;exp;trap ; ; RTC realtime clock set RTC 50 @@ -34,10 +34,25 @@ set RTC 50 ;set RTC debug=cmd ; ; ITM interval timer -set ITM debug=cmd +;set ITM debug=cmd ; -; IOP +; IOP at channel 7e00 +; useful options +;set iop debug=cmd;exp ;set iop debug=cmd +; make iop online +set iop enable +; set iop channel address +set iop0 dev=7e00 +; +; MFP at channel 7e00 +; useful options +;set mfp debug=cmd;exp +; make mfp online +;set mfp enable +; set mfp channel address +;set mfp0 dev=7e00 +;set mfp0 dev=7600 ; ; COM 8-Line ;set com debug=cmd; @@ -63,12 +78,18 @@ at lpr lprout ; CON Console ;set con debug=cmd;exp;detail ; useful options -;set con debug=cmd;exp; +; enable console +set con enable +; set console address +; set con0 enable +set con0 dev=7efc +; set con1 enable +set con1 dev=7efd +;set con debug=cmd;exp ; ; MTA Buffered tape processor ;set mta debug=cmd;exp;detail;data ; useful options -;set mta debug=cmd;detail;exp ; ; enable MTA to change channel set mta enable diff --git a/SEL32/tests/sel32_test.ini b/SEL32/tests/sel32_test.ini index ebb7afb..0b4e34b 100644 --- a/SEL32/tests/sel32_test.ini +++ b/SEL32/tests/sel32_test.ini @@ -1,8 +1,62 @@ cd %~p0 +; Set debug output set debug -n sel.log +;set debug stderr +; +; CPU type and memory +; Bad on UTX +;set CPU 32/27 2M +;set CPU 32/27 4M +;set CPU 32/87 4M +set CPU 32/67 4M +;End of Bad +;set CPU 32/97 4M ;set CPU V6 4M -;set CPU 32/67 4M -set CPU 32/27 4M +;set CPU V6 8M +;set CPU V9 4M +;set CPU V9 8M +; +; CPU debug options +;set cpu debug=cmd;exp;inst;detail;trap;xio;irq +; Set instruction trace history size +;;set cpu history=10000 +; useful options +;set cpu debug=exp +;set cpu debug=cmd;exp;irq;trap;xio +;set cpu debug=cmd;irq;trap;exp +;set cpu debug=irq;trap;exp;xio +;set cpu debug=irq;xio +;set cpu debug=irq;exp;trap +; +; RTC realtime clock +set RTC 50 +;set RTC 60 +; RTC debug options +;set RTC debug=cmd +; +; ITM interval timer +;set ITM debug=cmd +; +; IOP at channel 7e00 +; useful options +;set iop debug=cmd;exp +;set iop debug=cmd +; make iop online +set iop enable +; set iop channel address +set iop0 dev=7e00 +; +; MFP at channel 7e00 +; useful options +;set mfp debug=cmd;exp +; make mfp online +;set mfp enable +; set mfp channel address +;set mfp0 dev=7e00 +;set mfp0 dev=7600 +; +; COM 8-Line +;set com debug=cmd; set coml0 enable set coml1 enable set coml2 enable @@ -12,13 +66,130 @@ set coml5 enable set coml6 enable set coml7 enable ; +; Enable telnet sessions on port 4747 set comc enable +at comc 4747 +; +; LPR +;set lpr debug=cmd;detail set lpr enable +; LPR output file at lpr lprout +; +; CON Console +;set con debug=cmd;exp;detail +; useful options +; enable console +set con enable +; set console address +; set con0 enable +set con0 dev=7efc +; set con1 enable +set con1 dev=7efd +;set con debug=cmd;exp +; +; MTA Buffered tape processor +;set mta debug=cmd;exp;detail;data +; useful options +; +; enable MTA to change channel +set mta enable +; set mta channel +set mta0 dev=1000 + +; Attach in/out tape files +;at mta0 mpxsdt.tap +;at mta0 nbctape.tap +;at mta0 utx21a1.tap +;at mta0 sim32sdt.tap at mta0 diag.tap +set mta0 locked at mta1 temptape.tap at mta2 output.tap +; +; DMA disk processor II/UDP +; enable DMA to change channel +;set dma enable +; set disk chan to 0800 +;set dma0 dev=800 +; set disk type to MPX MH300 +;set dma0 type=MH300 +; set disk type to UTX 9346 +;set dma0 type=9346 +;set dma0 type=8155 +;set dma0 type=8887 +;set dma0 type=8148 +; +; Attach diskfile +;at dma0 utx0disk +;at dma0 utx1disk +;at dma0 sim32disk +;at dma debug=cmd;exp;detail;data +;at dma0 diagdisk +; useful options +;set dma debug=cmd;exp +;set dma debug=exp;cmd;detail +; +; SDA SCFI disk processor +;set sda debug=cmd;exp;data;detail +; Attach diskfiles +;at sda0 diskfile4 +;at sda1 diskfile5 +; +; DPA high speed disk processor +; enable the HSDP to change channel +;set dpa enable +; set channel addr +;set dpa dev=800 +; set disk type to UTX 8887 +;set dpa0 type=8887 +; +; Attach diskfiles +;at utxdsk.dsk +;at dpa0 utx0hsdp +;at dpa1 utx1hsdp +; +;set dpa debug=cmd;detail;exp +; useful options +;set dpa debug=cmd;exp +; +; set console switches +deposit CSW 0 +; +;UTX boot tape options +;set GPR 7 to 0x00 to boot in multi-user mode +;set GPR 7 to 0x01 to prompt for unix filename +;set GPR 7 to 0x02 to boot in single user mode +;set GPR 7 to 0x10 to disable swapping and paging +;set GPR 7 to 0x20 to boot from device specified in GPR6 +;set GPR 7 to 0x40 to allow progress messages on boot +;deposit BOOTR[7] 40 +;deposit BOOTR[7] 52 +;deposit BOOTR[7] 42 +;deposit BOOTR[7] 2 +;deposit BOOTR[6] 800 +;deposit BOOTR[0] ffffffff + +; Set register content at boot for SEL diagnostics +; uncomment next line to get diag loader prompt +;deposit bootr[0] ffffffff +deposit bootr[1] 0 +deposit bootr[2] 0 +; +; allow cpu idle +set cpu idle +; Set expect script for auto time entry on MPX at OPCOM prompt +;expect haltafter=20000 +; wait for expected output from simulator, then enter this text +;expect "??" send " %DATE_MM%/%DATE_DD%/%DATE_YY%,%TIME_HH%:%TIME_MM%:%TIME_SS%\r"; GO +; +; Boot from disk +;bo dpa0 +;bo dma0 +; +; Go to simh on completion of script expect "DOL>"^M +; Boot from mag tape bo mta0 det all rm temptape.tap