From 96f762e2f0b10cae264ab4496a3b8b0d36e1a56a Mon Sep 17 00:00:00 2001 From: AZBevier Date: Mon, 30 Mar 2020 20:27:27 -0700 Subject: [PATCH] SEL32: Change channel programming support code. SEL32: Correct trap status bits for 32/97 & V9 diags. SEL32: Allow I/O processing while CPU interrupts are blocked. SEL32: Rewrite testxio and haltxio processing logic. SEL32: Rewrite CPU interrupt processing logic. SEL32: Correct known Coverity errors. --- SEL32/sel32_chan.c | 1362 +++++++++++++++++++++----------------------- SEL32/sel32_clk.c | 18 +- SEL32/sel32_con.c | 118 ++-- SEL32/sel32_cpu.c | 795 ++++++++++++++++---------- SEL32/sel32_defs.h | 37 +- SEL32/sel32_disk.c | 259 +++++---- SEL32/sel32_iop.c | 14 +- SEL32/sel32_mfp.c | 14 +- SEL32/sel32_mt.c | 120 ++-- SEL32/sel32_scsi.c | 34 +- SEL32/sel32_sys.c | 3 +- 11 files changed, 1486 insertions(+), 1288 deletions(-) diff --git a/SEL32/sel32_chan.c b/SEL32/sel32_chan.c index 8975dfa..86ba039 100644 --- a/SEL32/sel32_chan.c +++ b/SEL32/sel32_chan.c @@ -91,7 +91,7 @@ extern uint32 CPUSTATUS; /* CPU status word */ extern uint32 INTS[]; /* Interrupt status flags */ /* device status */ -DIB *dev_unit[MAX_DEV]; /* Pointer to Device info block */ +DIB *dib_unit[MAX_DEV]; /* Pointer to Device info block */ uint16 dev_status[MAX_DEV]; /* last device status flags */ uint16 loading; /* set when booting */ @@ -116,7 +116,7 @@ t_stat grabxio(uint16 chsa, uint32 *status); /* grab XIO n/u */ t_stat rsctlxio(uint16 chsa, uint32 *status); /* reset controller XIO */ uint32 find_int_icb(uint16 chsa); uint32 find_int_lev(uint16 chsa); -uint32 scan_chan(int *ilev); +uint32 scan_chan(uint32 *ilev); t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */ t_stat chan_boot(uint16 chsa, DEVICE *dptr); t_stat chan_set_devs(); @@ -143,7 +143,7 @@ void store_csw(CHANP *chp); /* add an entry to the FIFO */ int32 FIFO_Put(uint16 chsa, uint32 entry) { - DIB *dibp = dev_unit[chsa & 0x7f00]; /* get DIB pointer for channel */ + DIB *dibp = dib_unit[chsa & 0x7f00]; /* get DIB pointer for channel */ if (dibp->chan_fifo_in == ((dibp->chan_fifo_out-1+FIFO_SIZE) % FIFO_SIZE)) { return -1; /* FIFO Full */ } @@ -154,9 +154,9 @@ int32 FIFO_Put(uint16 chsa, uint32 entry) } /* get the next entry from the FIFO */ -int FIFO_Get(uint16 chsa, uint32 *old) +int32 FIFO_Get(uint16 chsa, uint32 *old) { - DIB *dibp = dev_unit[chsa & 0x7f00]; /* get DIB pointer for channel */ + DIB *dibp = dib_unit[chsa & 0x7f00]; /* get DIB pointer for channel */ /* see if the FIFO is empty */ if (dibp->chan_fifo_in == dibp->chan_fifo_out) { return -1; /* FIFO is empty, tell caller */ @@ -167,6 +167,55 @@ int FIFO_Get(uint16 chsa, uint32 *old) return 0; /* all OK */ } +/* get number of entries in FIFO for channel */ +int32 FIFO_Num(uint16 chsa) +{ + DIB *dibp = dib_unit[chsa & 0x7f00]; /* 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; + } + /* calc entries */ + int32 num = (dibp->chan_fifo_in - dibp->chan_fifo_out + FIFO_SIZE) % FIFO_SIZE; + return (num>1); /* two words/entry */ +} + +/* add an entry to the RDYQ */ +int32 RDYQ_Put(uint32 entry) +{ + /* see if FIFO is full */ + if (RDYQIN == ((RDYQOUT-1+RDYQ_SIZE) % RDYQ_SIZE)) { + return -1; /* RDYQ Full */ + } + sim_debug(DEBUG_XIO, &cpu_dev, "RDYQ_Put entry %04x\n", entry); + RDYQ[RDYQIN] = entry; /* add new entry */ + RDYQIN += 1; /* next entry */ + RDYQIN %= RDYQ_SIZE; /* modulo RDYQ size */ + return 0; /* all OK */ +} + +/* get the next entry from the RDYQ */ +int32 RDYQ_Get(uint32 *old) +{ + /* see if the RDYQ is empty */ + if (RDYQIN == RDYQOUT) { + return -1; /* RDYQ is empty, tell caller */ + } + *old = RDYQ[RDYQOUT]; /* get the next entry */ + sim_debug(DEBUG_XIO, &cpu_dev, "RDYQ_Get entry %04x\n", *old); + RDYQOUT += 1; /* next entry */ + RDYQOUT %= RDYQ_SIZE; /* modulo RDYQ size */ + return 0; /* all OK */ +} + +/* get number of entries in RDYQ for channel */ +int32 RDYQ_Num(void) +{ + /* calc entries */ + return ((RDYQIN - RDYQOUT + RDYQ_SIZE) % RDYQ_SIZE); +} + /* Set INCH buffer address for channel */ /* return SCPE_OK or SCPE_MEM if invalid address or SCPE_ARG if already defined */ t_stat set_inch(UNIT *uptr, uint32 inch_addr) { @@ -200,7 +249,7 @@ t_stat set_inch(UNIT *uptr, uint32 inch_addr) { /* 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 = dev_unit[chsa]; /* get the device information pointer */ + dibp = dib_unit[chsa]; /* get the DIB pointer */ if (dibp == 0) continue; /* must have a DIB, so not used */ chp = find_chanp_ptr(chsa); /* find the chanp pointer */ @@ -218,29 +267,46 @@ t_stat set_inch(UNIT *uptr, uint32 inch_addr) { /* return 0 if not found, otherwise level number */ uint32 find_int_lev(uint16 chsa) { +#ifndef TRIED_032620 + int lchan = get_chan(chsa); /* get the logical channel number 0-7f */ + /* get the device entry for the logical channel in SPAD */ + uint32 spadent = SPAD[lchan]; /* get spad device entry for logical channel */ + uint32 inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ + + inta = 127 - inta; /* get positive int level */ + sim_debug(DEBUG_EXP, &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]); + /* get the address of the interrupt IVL in main memory */ +// chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ +// chan_icb = RMW(chan_ivl); /* get the interrupt context block addr in memory */ + return(inta); /* return the level*/ +#else uint32 chan, level, val; int i; chan = (chsa >> 8) & 0x7f; /* get channel number */ /* scan the channel entries for our chan */ for (i=0; i<128; i++) { +// for (i=0; i<112; i++) { val = SPAD[i]; /* get spad entry */ if ((val == 0) || (val == 0xffffffff)) continue; /* not valid entry */ /* look for class F devices */ - if ((val & 0x0f000000) == 0x0f000000) { + if ((val & 0x0f800000) == 0x0f000000) { /* F class only uses chan entry */ if (((val >> 8 ) & 0x7f) == chan) { /* channel matches, now get interrupt level number */ level = ((val >> 16) & 0x7f); /* 1's comp of int level */ level = 127 - level; /* get positive number level */ sim_debug(DEBUG_EXP, &cpu_dev, - "find_int_lev class F SPAD %08x chan %04x chsa %04x level %04x\n", - val, chan, chsa, level); + "find_int_lev class F SPADC %08x chsa %04x lev %02x SPADI %08x INTS %08x\n", + val, chsa, level, SPAD[level+0x80], INTS[level]); return(level); /* return the level*/ } } /* look for E class or class 3 device */ +// if (((val & 0x0f800000) == 0x0e000000) || /* E class */ if (((val & 0x0f000000) == 0x0e000000) || /* E class */ ((val & 0x0f800000) == 0x03800000)) { /* class 3 (interval timer) */ /* E class uses chan and device address */ @@ -272,6 +338,7 @@ uint32 find_int_lev(uint16 chsa) } } } +#endif return 0; /* not found */ } @@ -296,12 +363,15 @@ UNIT *find_unit_ptr(uint16 chsa) UNIT *uptr; /* UNIT pointer */ int i; - dibp = dev_unit[chsa]; /* get DIB pointer from device pointers */ + dibp = dib_unit[chsa & 0x7fff]; /* get DIB pointer from device address */ if (dibp == 0) { /* if zero, not defined on system */ return NULL; /* tell caller */ } uptr = dibp->units; /* get the pointer to the units on this channel */ + if (uptr == 0) /* if zero, no devices defined on system */ + return NULL; /* tell caller */ + for (i = 0; i < dibp->numunits; i++) { /* search through units to get a match */ if (chsa == GET_UADDR(uptr->u3)) { /* does ch/sa match? */ return uptr; /* return the pointer */ @@ -319,7 +389,7 @@ CHANP *find_chanp_ptr(uint16 chsa) CHANP *chp; /* CHANP pointer */ int i; - dibp = dev_unit[chsa&0x7fff]; /* get DIB pointer from device pointers */ + dibp = dib_unit[chsa&0x7fff]; /* get DIB pointer from unit address */ if (dibp == 0) /* if zero, not defined on system */ return NULL; /* tell caller */ if ((chp = (CHANP *)dibp->chan_prg) == NULL) { /* must have channel information for each device */ @@ -327,6 +397,9 @@ CHANP *find_chanp_ptr(uint16 chsa) } uptr = dibp->units; /* get the pointer to the units on this channel */ + if (uptr == 0) /* if zero, no devices defined on system */ + return NULL; /* tell caller */ + for (i = 0; i < dibp->numunits; i++) { /* search through units to get a match */ if (chsa == GET_UADDR(uptr->u3)) { /* does ch/sa match? */ return chp; /* return the pointer */ @@ -346,17 +419,12 @@ int readfull(CHANP *chp, uint32 maddr, uint32 *word) maddr &= MASK24; /* mask addr to 24 bits */ if (!MEM_ADDR_OK(maddr)) { /* see if mem addr >= MEMSIZE */ chp->chan_status |= STATUS_PCHK; /* program check error */ - sim_debug(DEBUG_EXP, &cpu_dev, "readfull read %08x from addr %08x ERROR\n", *word, maddr<<2); + sim_debug(DEBUG_EXP, &cpu_dev, + "readfull read %08x from addr %08x ERROR\n", *word, maddr); return 1; /* show we have error */ } -#define TEST -#ifdef TEST - maddr >>= 2; /* get 32 bit word index */ - *word = M[maddr]; /* get the contents */ -#else - *word = RMW(maddr&MASK24); /* get 1 word */ -#endif - sim_debug(DEBUG_EXP, &cpu_dev, "READFULL read %08x from addr %08x\n", *word, maddr<<2); + *word = RMW(maddr); /* get 1 word */ + sim_debug(DEBUG_EXP, &cpu_dev, "READFULL read %08x from addr %08x\n", *word, maddr); return 0; /* return OK */ } @@ -366,9 +434,7 @@ int readfull(CHANP *chp, uint32 maddr, uint32 *word) */ int readbuff(CHANP *chp) { - int k; uint32 addr = chp->ccw_addr; /* channel buffer address */ -//XXX uint16 chan = get_chan(chp->chan_dev); /* our channel */ if (!MEM_ADDR_OK(addr & MASK24)) { /* see if memory address invalid */ chp->chan_status |= STATUS_PCHK; /* bad, program check */ @@ -379,30 +445,11 @@ int readbuff(CHANP *chp) irq_pend = 1; /* and we have an interrupt */ return 1; /* done, with error */ } -#ifdef TEST - addr &= MASK24; /* address only */ - addr >>= 2; /* byte to word address */ - chp->chan_buf = M[addr]; /* get 4 bytes */ -#else chp->chan_buf = RMB(addr&MASK24); /* get 1 byte */ -#endif - -#ifdef TEST - sim_debug(DEBUG_DETAIL, &cpu_dev, - "readbuff read memory chsa %04x into buffer %06x %06x %04x [", - chp->chan_dev, chp->ccw_addr & 0xFFFFFC, chp->chan_buf, chp->ccw_count); - for (k = 24; k >= 0; k -= 8) { - char ch = (chp->chan_buf >> k) & 0xFF; - if (!isprint(ch)) - ch = '.'; - sim_debug(DEBUG_DETAIL, &cpu_dev, "%c", ch); - } - sim_debug(DEBUG_DETAIL, &cpu_dev, "]\n"); -#endif return 0; } -/* Write 32 bit channel buffer to memory. +/* Write 8 bit channel buffer to memory. * Return 1 if fail. * Return 0 if success. */ @@ -420,32 +467,29 @@ int writebuff(CHANP *chp) return 1; } addr &= MASK24; - sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_DATA, &cpu_dev, "writebuff WRITE addr %06x DATA %08x status %04x\n", addr, chp->chan_buf, chp->chan_status); -#ifdef TEST - M[addr>>2] = chp->chan_buf; /* write byte to memory */ -#else WMB(addr, chp->chan_buf); /* write byte to memory */ -#endif return 0; } /* load in the IOCD and process the commands */ /* return = 0 OK */ /* return = 1 error, chan_status will have reason */ -int load_ccw(CHANP *chp, int tic_ok) +int32 load_ccw(CHANP *chp, int32 tic_ok) { - uint32 word; + uint32 word1 = 0; + uint32 word2 = 0; int docmd = 0; UNIT *uptr = find_unit_ptr(chp->chan_dev); /* find the unit pointer */ uint16 chan = get_chan(chp->chan_dev); /* our channel */ loop: sim_debug(DEBUG_XIO, &cpu_dev, - "load_ccw entry chan_status[%04x] %04x\n", chan, chp->chan_status); + "load_ccw @%06x entry chan_status[%04x] %04x\n", chp->chan_caw, chan, chp->chan_status); /* Abort if we have any errors */ - if (chp->chan_status & 0x3f03) { /* check channel status */ + if (chp->chan_status & STATUS_ERROR) { /* check channel error status */ sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); return 1; @@ -457,8 +501,16 @@ loop: chp->chan_status &= ~STATUS_MOD; /* turn off status modifier flag */ } - /* Read in first or next CCW */ - if (readfull(chp, chp->chan_caw, &word) != 0) { /* read word from memory */ + /* Read in first CCW */ + if (readfull(chp, chp->chan_caw, &word1) != 0) { /* read word1 from memory */ + chp->chan_status |= STATUS_PCHK; /* memory read error, program check */ + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + + /* Read in second CCW */ + if (readfull(chp, chp->chan_caw+4, &word2) != 0) { /* read word2 from memory */ chp->chan_status |= STATUS_PCHK; /* memory read error, program check */ sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); @@ -466,14 +518,17 @@ loop: } sim_debug(DEBUG_XIO, &cpu_dev, - "load_ccw read ccw chan %02x caw %06x IOCD wd 1 %08x\n", - chan, chp->chan_caw, word); + "load_ccw @%06x read ccw chan %02x IOCD wd 1 %08x wd 2 %08x\n", + chp->chan_caw, chan, word1, word2); /* TIC can't follow TIC or be first in command chain */ - if (((word >> 24) & 0xf) == CMD_TIC) { + if (((word1 >> 24) & 0xf) == CMD_TIC) { if (tic_ok) { - chp->chan_caw = word & MASK24; /* get new IOCD address */ + chp->chan_caw = word1 & MASK24; /* get new IOCD address */ tic_ok = 0; /* another tic not allowed */ + sim_debug(DEBUG_XIO, &cpu_dev, + "load_ccw tic cmd ccw chan %02x tic caw %06x IOCD wd 1 %08x\n", + chan, chp->chan_caw, word1); goto loop; /* restart the IOCD processing */ } chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ @@ -482,87 +537,34 @@ loop: irq_pend = 1; /* status pending */ return 1; /* error return */ } - chp->chan_caw += 4; /* point to 2nd word of the IOCD */ /* Check if not chaining data */ if ((chp->ccw_flags & FLAG_DC) == 0) { - chp->ccw_cmd = (word >> 24) & 0xff; /* not DC, so set command from IOCD wd 1 */ + chp->ccw_cmd = (word1 >> 24) & 0xff; /* not DC, so set command from IOCD wd 1 */ sim_debug(DEBUG_XIO, &cpu_dev, - "load_ccw No DC, flags %04x cmd %02x\n", - chp->ccw_flags, chp->ccw_cmd); + "load_ccw @%06x No DC, ccw_flags %04x cmd %02x\n", + chp->chan_caw, chp->ccw_flags, chp->ccw_cmd); docmd = 1; /* show we have a command */ } /* Set up for this command */ /* make a 24 bit address */ - chp->ccw_addr = word & MASK24; /* set the data address */ - if (readfull(chp, chp->chan_caw, &word) != 0) { /* read word from memory */ - chp->chan_status |= STATUS_PCHK; /* memory read error, program check */ - sim_debug(DEBUG_EXP, &cpu_dev, - "load_ccw data addr ERROR chan_status[%04x] %04x\n", - chan, chp->chan_status); - return 1; /* error return */ - } - - sim_debug(DEBUG_EXP, &cpu_dev, - "load_ccw read ccw chan %02x caw %06x IOCD wd 2 %08x\n", - chan, chp->chan_caw, word); - chp->chan_caw += 4; /* next IOCD address */ - chp->ccw_count = word & 0xffff; /* get 16 bit byte count from IOCD WD 2*/ + chp->ccw_addr = word1 & MASK24; /* set the data/seek address */ + chp->chan_caw += 8; /* point to to next IOCD */ + chp->ccw_count = word2 & 0xffff; /* get 16 bit byte count from IOCD WD 2*/ chp->chan_byte = BUFF_EMPTY; /* no bytes transferred yet */ - -#ifdef INVALID_FOR_INCH - /* see if buffer count 0 or < 0x8000 */ - /* diags want the count from IOCD2 in status */ - if (chp->ccw_count == 0) { /* see if count is zero */ - chp->chan_status |= STATUS_PCHK; /* program check error */ - sim_debug(DEBUG_EXP, &cpu_dev, - "load_ccw excess data count %08x ERROR chan_status[%04x] %04x\n", - chp->ccw_count, chan, chp->chan_status); - irq_pend = 1; /* status pending */ - return 1; /* show we have error */ - } -#endif - - /* only test if non tic command */ - if ((chp->ccw_cmd & 0xFF) != CMD_TIC) { - /* see if buffer address is in real memory */ - /* diags want the count from IOCD2 in status */ - if (!MEM_ADDR_OK(chp->ccw_addr)) { /* see if mem addr >= MEMSIZE */ - chp->chan_status |= STATUS_PCHK; /* program check error */ - sim_debug(DEBUG_EXP, &cpu_dev, - "load_ccw data start addr %06x ERROR chan_status[%04x] %04x\n", - chp->ccw_addr, chan, chp->chan_status); - irq_pend = 1; /* status pending */ - return 1; /* show we have error */ - } - - /* see if buffer end address is in real memory */ - /* diags want the count from IOCD2 in status */ - /* MPX will fail if 1 is not subtracted from test value */ - /* when adding start + size we will be one over, so backup 1 */ - if (!MEM_ADDR_OK(chp->ccw_addr + chp->ccw_count - 1)) { /* see if mem addr > MEMSIZE*/ - chp->chan_status |= STATUS_PCHK; /* program check error */ - sim_debug(DEBUG_EXP, &cpu_dev, - "load_ccw data end addr %06x ERROR cnt %04x chan_status[%04x] %04x\n", - chp->ccw_addr, chp->ccw_count, chan, chp->chan_status); - irq_pend = 1; /* status pending */ - return 1; /* show we have error */ - } - } - - chp->ccw_flags = (word >> 16) & 0xffff; /* get flags from bits 0-7 of WD 2 of IOCD */ + chp->ccw_flags = (word2 >> 16) & 0xffff; /* get flags from bits 0-7 of WD 2 of IOCD */ if (chp->ccw_flags & FLAG_PCI) { /* do we have prog controlled int? */ chp->chan_status |= STATUS_PCI; /* set PCI flag in status */ irq_pend = 1; /* interrupt pending */ } sim_debug(DEBUG_XIO, &cpu_dev, - "load_ccw read docmd %02x irq_flag %04x count %04x chan %04x ccw_flags %04x\n", - docmd, irq_pend, chp->ccw_count, chan, chp->ccw_flags); + "load_ccw @%06x read docmd %02x addr %06x count %04x chan %04x ccw_flags %04x\n", + chp->chan_caw, docmd, chp->ccw_addr, chp->ccw_count, chan, chp->ccw_flags); - /* LPR sends CC cmd only without data addr/count */ #ifdef HACK_FOR_LPR + /* LPR sends CC cmd only without data addr/count */ /* Check invalid count */ if ((chp->ccw_count == 0) && (chp->ccw_addr != 0)) { /* see if byte count is zero */ chp->chan_status |= STATUS_PCHK; /* program check if it is */ @@ -570,33 +572,32 @@ loop: return 1; /* error return */ } #endif - if (docmd) { /* see if we need to process command */ -#ifdef TRY_THIS_TUESDAY_0301 - uint8 devstat; -#endif -// DEVICE *dptr = get_dev(uptr); /* find the device from unit pointer */ - DIB *dibp = dev_unit[chp->chan_dev]; /* get the device pointer */ + + if (docmd) { /* see if we need to process a command */ + DIB *dibp = dib_unit[chp->chan_dev]; /* get the DIB pointer */ uptr = find_unit_ptr(chp->chan_dev); /* find the unit pointer */ - if (uptr == 0) + if (dibp == 0 || uptr == 0) { + chp->chan_status |= STATUS_PCHK; /* program check if it is */ return 1; /* if none, error */ + } sim_debug(DEBUG_XIO, &cpu_dev, - "load_ccw before start_cmd chan %04x status %04x count %04x\n", - chan, chp->chan_status, chp->ccw_count); + "load_ccw @%06x before start_cmd chan %04x status %04x count %04x\n", + chp->chan_caw, chan, chp->chan_status, chp->ccw_count); /* call the device startcmd function to process the current command */ -#ifndef TRY_THIS_TUESDAY_0301 - chp->chan_status = dibp->start_cmd(uptr, chan, chp->ccw_cmd); -#else /* just replace device status bits */ +#ifdef use16bit devstat = dibp->start_cmd(uptr, chan, chp->ccw_cmd); chp->chan_status = (chp->chan_status & 0xff00) | (devstat & 0xff); +#else + chp->chan_status = dibp->start_cmd(uptr, chan, chp->ccw_cmd); #endif sim_debug(DEBUG_XIO, &cpu_dev, - "load_ccw after start_cmd chan %04x status %08x count %04x\n", - chan, chp->chan_status, chp->ccw_count); + "load_ccw @%06x after start_cmd chan %04x status %08x count %04x\n", + chp->chan_caw, chan, chp->chan_status, chp->ccw_count); /* see if bad status */ if (chp->chan_status & (STATUS_ATTN|STATUS_CHECK|STATUS_EXPT)) { @@ -609,32 +610,19 @@ loop: chan, chp->chan_status); return 1; /* error return */ } - /* see if command completed */ if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { -#ifdef NO_WORK - chp->chan_status |= STATUS_CEND; /* set channel end status */ - chp->chan_byte = BUFF_NEWCMD; /* ready for new cmd */ - chp->ccw_cmd = 0; /* stop IOCD processing */ - irq_pend = 1; /* int coming */ - sim_debug(DEBUG_XIO, &cpu_dev, - "load_ccw cmd complete chan %04x status %04x count %04x\n", - chan, chp->chan_status, chp->ccw_count); - /* we want to terminate if command is complete */ - /* go store status and return CC2 */ -/*NEW*/ return 1; /* return cmd complete */ -#else uint16 chsa = GET_UADDR(uptr->u3); /* get channel & sub address */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ sim_debug(DEBUG_XIO, &cpu_dev, - "load_ccw cmd complete chan %04x status %04x count %04x\n", - chan, chp->chan_status, chp->ccw_count); -#endif + "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); } } + /* nothing happening, so return */ sim_debug(DEBUG_XIO, &cpu_dev, - "load_ccw return, chan %04x status %04x count %04x irq %02x\n", - chan, chp->chan_status, chp->ccw_count, irq_pend); + "load_ccw @%06x return, chan %04x status %04x count %04x irq_pend %1x\n", + chp->chan_caw, chan, chp->chan_status, chp->ccw_count, irq_pend); return 0; /* good return */ } @@ -647,11 +635,12 @@ int chan_read_byte(uint16 chsa, uint8 *data) int byte; /* Abort if we have any errors */ - if (chp->chan_status & 0x3f03) /* check channel status */ + if (chp->chan_status & STATUS_ERROR) /* check channel error status */ return 1; /* return error */ if (chp->chan_byte == BUFF_CHNEND) return 1; /* return error */ + if (chp->ccw_count == 0) { /* see if more data required */ if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if Data Chain */ chp->chan_status |= STATUS_CEND; /* no, end of data */ @@ -662,32 +651,28 @@ int chan_read_byte(uint16 chsa, uint8 *data) return 1; /* return error */ } else { /* we have data chaining, process iocl */ - if (load_ccw(chp, 1)) /* process data chaining */ + if (load_ccw(chp, 1)) { /* process data chaining */ + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_read_byte with DC error, cnt %04x addr %06x chan %04x\n", + chp->ccw_count, chp->ccw_addr, chan); return 1; /* return error */ + } + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_read_byte with DC complete, cnt %04x addr %06x chan %04x\n", + chp->ccw_count, chp->ccw_addr, chan); } } if (chp->chan_byte == BUFF_EMPTY) { /* is buffer empty? */ if (readbuff(chp)) /* read next 4 chars */ return 1; /* return error */ -#ifdef TEST - chp->chan_byte = chp->ccw_addr & 0x3; /* get byte number from address */ - chp->ccw_addr += 4 - chp->chan_byte; /* next byte address */ -#else - chp->chan_byte = 0; /* show that we have data byte */ +// chp->chan_byte = 0; /* show that we have data byte */ chp->ccw_addr += 1; /* next byte address */ -#endif } chp->ccw_count--; /* one char less to process */ /* get the byte of data */ -#ifdef TEST - byte = (chp->chan_buf >> (8 * (3 - (chp->chan_byte & 0x3)))) & 0xff; - chp->chan_byte++; /* next byte offset in word */ -#else - /* get the byte of data */ byte = chp->chan_buf; /* read byte from memory */ - chp->chan_byte = BUFF_EMPTY; /* buffer empty too */ -#endif *data = byte; /* return the data */ + chp->chan_byte = BUFF_EMPTY; /* buffer empty too */ sim_debug(DEBUG_DATA, &cpu_dev, "chan_read_byte transferred %02x\n", byte); return 0; /* good return */ } @@ -703,6 +688,10 @@ int test_write_byte_end(uint16 chsa) if (chp->ccw_count == 0) { if (chp->chan_byte & BUFF_DIRTY) { writebuff(chp); /* write it */ + chp->chan_byte = BUFF_EMPTY; /* now empty */ + sim_debug(DEBUG_EXP, &cpu_dev, + "test_write_byte ZERO chsa %04x ccw_count %04x addr %06x\n", + chsa, chp->ccw_count, chp->ccw_addr); } if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if we have data chaining */ chp->chan_status |= STATUS_CEND; /* no, end of data */ @@ -719,16 +708,16 @@ int chan_write_byte(uint16 chsa, uint8 *data) { int chan = get_chan(chsa); /* get the channel number */ CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ - int offset; - uint32 mask; /* Abort if we have any errors */ - if (chp->chan_status & 0x3f03) /* check channel status */ + if (chp->chan_status & STATUS_ERROR) /* check channel error status */ return 1; /* return error */ /* see if at end of buffer */ if (chp->chan_byte == BUFF_CHNEND) { - sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte BUFF_CHNEND\n"); + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_write_byte BUFF_CHNEND ccw_flags %04x addr %06x cnt %04x\n", + chp->ccw_flags, chp->ccw_addr, chp->ccw_count); /* if SLI not set, we have incorrect length */ if ((chp->ccw_flags & FLAG_SLI) == 0) { sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte 4 setting SLI ret\n"); @@ -741,15 +730,15 @@ int chan_write_byte(uint16 chsa, uint8 *data) "chan_write_byte ZERO chan %04x ccw_count %04x addr %06x\n", chan, chp->ccw_count, chp->ccw_addr); if (chp->chan_byte & BUFF_DIRTY) { - sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte 2 BUF DIRTY ret\n"); + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_write_byte 2 BUF DIRTY ret char %02x\n", chp->chan_buf); if (writebuff(chp)) /* write it */ return 1; /* return error */ -#ifndef TEST chp->chan_byte = BUFF_EMPTY; /* no data now */ -#endif } if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if we have data chaining */ - sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte no DC\n"); + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_write_byte no DC ccw_flags %04x\n", chp->ccw_flags); chp->chan_status |= STATUS_CEND; /* no, end of data */ chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ return 1; /* return error */ @@ -757,61 +746,53 @@ int chan_write_byte(uint16 chsa, uint8 *data) /* we have data chaining, process iocl */ sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte got DC, calling load_ccw chan %04x\n", chan); - if (load_ccw(chp, 1)) /* process data chaining */ + if (load_ccw(chp, 1)) { /* process data chaining */ + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_write_byte with DC error, cnt %04x addr %06x chan %04x\n", + chp->ccw_count, chp->ccw_addr, chan); return 1; /* return error */ - } + } + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_write_byte with DC complete, cnt %04x addr %06x chan %04x\n", + chp->ccw_count, chp->ccw_addr, chan); + } } - sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_byte non zero ccw_count[%04x]=%04x\n", + sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte non zero ccw_count[%04x]=%04x\n", chan, chp->ccw_count); if (chp->ccw_flags & FLAG_SKIP) { - chp->ccw_count--; - chp->chan_byte = BUFF_EMPTY; + chp->ccw_count--; /* decrement skip count */ + chp->chan_byte = BUFF_EMPTY; /* no data */ if ((chp->ccw_cmd & 0xff) == CMD_RDBWD) - chp->ccw_addr--; + chp->ccw_addr--; /* backward */ else - chp->ccw_addr++; - sim_debug(DEBUG_CMD, &cpu_dev, "chan_write_byte SKIP ret addr %08x cnt %04x\n", + chp->ccw_addr++; /* forward */ + sim_debug(DEBUG_XIO, &cpu_dev, "chan_write_byte SKIP ret addr %08x cnt %04x\n", chp->ccw_addr, chp->ccw_count); return 0; } - if (chp->chan_byte == (BUFF_EMPTY|BUFF_DIRTY)) { +#ifndef NOT_NEEDED + if (chp->chan_byte == BUFF_DIRTY) { if (writebuff(chp)) return 1; - sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte BUF EMPTY|DIRTY ret\n"); -#ifdef TEST - if ((chp->ccw_cmd & 0xff) == CMD_RDBWD) - chp->ccw_addr -= (1 + (chp->ccw_addr & 0x3)); - else - chp->ccw_addr += (4 - (chp->ccw_addr & 0x3)); -#else + sim_debug(DEBUG_DETAIL, &cpu_dev, + "chan_write_byte %02x DIRTY addr %06x\n", *data, chp->ccw_addr); if ((chp->ccw_cmd & 0xff) == CMD_RDBWD) chp->ccw_addr -= 1; else chp->ccw_addr += 1; -#endif chp->chan_byte = BUFF_EMPTY; } -#ifdef TEST - if (chp->chan_byte == BUFF_EMPTY) - chp->chan_byte = chp->ccw_addr & 0x3; - chp->ccw_count--; - offset = 8 * (chp->chan_byte & 0x3); /* calc byte offset in word */ - mask = 0xff000000 >> offset; /* build char mask */ - chp->chan_buf &= ~mask; /* zero out the old byte */ - chp->chan_buf |= ((uint32)(*data)) << (24 - offset); /* or in the new one */ - - if ((chp->ccw_cmd & 0xff) == CMD_RDBWD) { - if (chp->chan_byte & 0x3) - chp->chan_byte--; - else - chp->chan_byte = BUFF_EMPTY; - } else - chp->chan_byte++; /* next byte */ - chp->chan_byte |= BUFF_DIRTY; /* we are used */ -#else +#endif + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_byte of data %02x to %06x\n", + *data, chp->ccw_addr); chp->chan_buf = *data; /* get data byte */ chp->ccw_count--; - chp->chan_byte |= BUFF_DIRTY; /* we are used */ +#ifdef NEWWAY + if (writebuff(chp)) + return 1; + chp->chan_byte = BUFF_EMPTY; +#else + chp->chan_byte = BUFF_DIRTY; /* we are dirty */ #endif return 0; } @@ -825,7 +806,8 @@ void set_devwake(uint16 chsa, uint16 flags) /* save 16 bit channel status and residual byte count in SW 2 */ stwd2 = (uint32)flags << 16; if ((FIFO_Put(chsa, stwd1) == -1) || (FIFO_Put(chsa, stwd2) == -1)) { - fprintf(stderr, "FIFO Overflow ERROR on chsa %04x\r\n", chsa); + sim_debug(DEBUG_EXP, &cpu_dev, + "set_devwake FIFO Overflow ERROR on chsa %04x\n", chsa); } irq_pend = 1; /* wakeup controller */ } @@ -847,34 +829,27 @@ void set_devattn(uint16 chsa, uint16 flags) /* channel operation completed */ void chan_end(uint16 chsa, uint16 flags) { - uint32 chan_icb = find_int_icb(chsa); /* get icb address */ CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ sim_debug(DEBUG_EXP, &cpu_dev, - "chan_end entry chsa %04x flags %04x chan_icb %06x status %04x cmd %02x\n", - chsa, flags, chan_icb, chp->chan_status, chp->ccw_cmd); + "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 (writebuff(chp)) /* write remaining data */ return; /* error */ - chp->chan_byte = BUFF_EMPTY; /* we are empty now */ } + chp->chan_byte = BUFF_EMPTY; /* we are empty now */ chp->chan_status |= STATUS_CEND; /* set channel end */ chp->chan_status |= ((uint16)flags); /* add in the callers flags */ -// chp->ccw_cmd = 0; /* reset the completed channel command */ sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end SLI test1 chsa %04x ccw_flags %04x count %04x status %04x\n", chsa, chp->ccw_flags, chp->ccw_count, chp->chan_status); -#ifdef HACK_HACK - /* hack - rewind had byte count of 1, so triggered this error when it is not */ - /* remove until I figure out what is required */ - /* FIXME */ - /* test for incorrect transfer length */ - if (chp->ccw_count != 0 && ((chp->ccw_flags & FLAG_SLI) == 0)) { - chp->chan_status |= STATUS_LENGTH; /* show incorrect length status */ - chp->ccw_flags = 0; /* no flags */ - } -#else + + /* read/write must have none-zero byte count */ + /* all others can be zero, except NOP, which must be 0 */ + /* a NOP is Control command 0x03 with no mdifier bits */ /* see if this is a read/write cmd */ if (((chp->ccw_cmd & 0x7) == 0x02) || ((chp->ccw_cmd & 0x7) == 0x01)) { /* test for incorrect transfer length */ @@ -886,15 +861,20 @@ void chan_end(uint16 chsa, uint16 flags) { chp->ccw_flags = 0; /* no flags */ } } -#endif + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end SLI2 test chsa %04x ccw_flags %04x status %04x\n", chsa, chp->ccw_flags, chp->chan_status); chp->ccw_cmd = 0; /* reset the completed channel command */ /* Diags do not want SLI if we have no device end status */ +#ifdef OLDWAY + if ((chp->chan_status & STATUS_LENGTH) && ((chp->chan_status & STATUS_DEND) == 0)) + chp->chan_status &= ~STATUS_LENGTH; +#else if ((chp->chan_status & FLAG_SLI) && ((chp->chan_status & STATUS_DEND) == 0)) chp->chan_status &= ~FLAG_SLI; +#endif /* no flags for attention status */ if (flags & (SNS_ATTN|SNS_UNITCHK|SNS_UNITEXP)) { @@ -907,7 +887,7 @@ void chan_end(uint16 chsa, uint16 flags) { /* test for device or controller end */ if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { - chp->chan_byte = BUFF_NEWCMD; /* clear byte flag */ + chp->chan_byte = BUFF_EMPTY; /* clear byte flag */ while ((chp->ccw_flags & FLAG_DC)) { /* handle data chaining */ if (load_ccw(chp, 1)) /* continue channel program */ break; /* error */ @@ -916,63 +896,98 @@ void chan_end(uint16 chsa, uint16 flags) { chp->ccw_flags = 0; /* no flags */ } } + chp->chan_byte = BUFF_DONE; /* clear byte flag */ sim_debug(DEBUG_XIO, &cpu_dev, - "chan_end IOCL done chsa %04x ccw_flags %04x status %04x\n", + "chan_end FIFO #%1x IOCL done chsa %04x ccw_flags %04x status %04x\n", + FIFO_Num(chsa), chsa, chp->ccw_flags, chp->chan_status); + + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end chan end chsa %04x ccw_flags %04x status %04x\n", chsa, chp->ccw_flags, chp->chan_status); -//#define NEW_METHOD -#ifdef NEW_METHOD + /* If channel end, check if we should continue */ - if (chp->chan_status & STATUS_CEND) { /* do we have channel end */ + if (chp->ccw_flags & FLAG_CC) { /* command chain flag */ + /* we have channel end and CC flag, continue channel prog */ sim_debug(DEBUG_XIO, &cpu_dev, - "chan_end chan end chsa %04x flags %04x status %04x\n", - chsa, chp->ccw_flags, chp->chan_status); - if (chp->ccw_flags & FLAG_CC) { /* command chain flag */ - /* we have channel end and CC flag, continue channel prog */ + "chan_end chan end & CC chsa %04x status %04x\n", + chsa, chp->chan_status); + if (chp->chan_status & STATUS_DEND) { /* device end? */ sim_debug(DEBUG_XIO, &cpu_dev, - "chan_end chan end & CC chsa %04x status %04x\n", + "chan_end dev end & CC chsa %04x status %04x\n", chsa, chp->chan_status); - if (chp->chan_status & STATUS_DEND) { /* device end? */ - sim_debug(DEBUG_XIO, &cpu_dev, - "chan_end dev end & CC chsa %04x status %04x\n", - chsa, chp->chan_status); - (void)load_ccw(chp, 1); /* go load the next IOCB */ - } - /* just return */ - } else { - /* we have channel end and no CC flag, end command */ - chsa = chp->chan_dev; /* get the chan/sa */ - sim_debug(DEBUG_XIO, &cpu_dev, - "chan_end chan end & no CC chsa %04x status %04x\n", - chsa, chp->chan_status); -//?? dev_status[chsa] = 0; /* no device status anymore */ - /* we have completed channel program */ - /* handle case where we are loading the O/S on boot */ - /* if loading, leave status to be discovered by scan_chan */ - if (!loading) { - sim_debug(DEBUG_DETAIL, &cpu_dev, - "chan_end call store_csw dev end & chan end chsa %04x cpustatus %08x\n", - chsa, CPUSTATUS); - store_csw(chp); /* store the status */ - } - else - sim_debug(DEBUG_DETAIL, &cpu_dev, - "chan_end we are loading with DE & CE, keep status chsa %04x status %08x\n", - chsa, chp->chan_status); -//XXX irq_pend = 1; /* still pending int */ +// (void)load_ccw(chp, 1); /* go load the next IOCB */ + /* Queue us to continue from cpu level */ + chp->chan_byte = BUFF_NEXT; /* have main pick us up */ + RDYQ_Put(chsa); /* queue us up */ } + /* just return */ + } else { + /* we have channel end and no CC flag, end command */ + chsa = chp->chan_dev; /* get the chan/sa */ + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end chan end & no CC chsa %04x status %04x\n", + chsa, chp->chan_status); + + /* we have completed channel program */ + /* handle case where we are loading the O/S on boot */ + /* if loading, store status to be discovered by scan_chan */ + if (!loading) { + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end call store_csw dev end & chan end chsa %04x cpustatus %08x\n", + chsa, CPUSTATUS); + } else { + /* we are loading, so keep moving */ + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end we are loading O/S with DE & CE, keep status chsa %04x status %08x\n", + chsa, chp->chan_status); + } + /* store the status in device fifo to continue from cpu level */ + chp->chan_byte = BUFF_DONE; /* have main pick us up */ + store_csw(chp); /* store the status */ } - else - sim_debug(DEBUG_DETAIL, &cpu_dev, - "chan_end IOCL2 done chsa %04x ccw_flags %04x status %04x\n", - chsa, chp->ccw_flags, chp->chan_status); -#endif } -//XXX irq_pend = 1; /* flag to test for int condition */ + /* following statement required for boot to work */ + irq_pend = 1; /* flag to test for int condition */ } -/* store the device status into the status DW in memory */ -/* the INCH command provides the status address in memory */ -/* return the icb address */ +/* post the device status from the channel FIFO into memory */ +/* the INCH command provides the status DW address in memory */ +/* rstat are the bits to remove from status */ +int16 post_csw(CHANP *chp, uint32 rstat) +{ + uint32 chsa = chp->chan_dev; /* get ch/sa information */ + uint32 incha = chp->chan_inch_addr; /* get inch status buffer address */ + uint32 sw1, sw2; /* status words */ + + /* check channel FIFO for status to post */ + if ((FIFO_Num(chsa)) && + ((FIFO_Get(chsa, &sw1) == 0) && (FIFO_Get(chsa, &sw2) == 0))) { + uint32 chan_icb = find_int_icb(chsa); /* get icb address */ + + if (chan_icb == 0) { + sim_debug(DEBUG_EXP, &cpu_dev, + "post_csw %04x READ FIFO #%1x inch %06x invalid chan_icb %06x\n", + chsa, FIFO_Num(chsa), incha, chan_icb); + return 0; /* no status to post */ + } + /* remove user specified bits */ + sw2 &= ~rstat; /* remove bits */ + /* we have status to post, do it now */ + chp->chan_byte = BUFF_NEWCMD; /* show done */ + /* save the status double word to memory */ + WMW(incha, sw1); /* save sa & IOCD address in status WD 1 loc */ + WMW(incha+4, sw2); /* save status and residual cnt in status WD 2 loc */ + /* now store the status dw address into word 5 of the ICB for the channel */ + WMW(chan_icb+20, incha|BIT1); /* post sw addr in ICB+5w & set CC2 in INCH addr */ + sim_debug(DEBUG_IRQ, &cpu_dev, + "post_csw %04x READ FIFO #%1x inch %06x chan_icb %06x sw1 %08x sw2 %08x\n", + chsa, FIFO_Num(chsa), incha, chan_icb, sw1, sw2); + return 1; /* show we posted status */ + } + return 0; /* no status to post */ +} + +/* store the device status into the status FIFO for the channel */ void store_csw(CHANP *chp) { uint32 stwd1, stwd2; /* words 1&2 of stored status */ @@ -980,15 +995,19 @@ void store_csw(CHANP *chp) /* put sub address in byte 0 */ stwd1 = ((chsa & 0xff) << 24) | chp->chan_caw; /* subaddress and IOCD address to SW 1 */ + /* save 16 bit channel status and residual byte count in SW 2 */ stwd2 = ((uint32)chp->chan_status << 16) | ((uint32)chp->ccw_count); + if ((FIFO_Put(chsa, stwd1) == -1) || (FIFO_Put(chsa, stwd2) == -1)) { - fprintf(stderr, "FIFO Overflow ERROR on chsa %04x\r\n", chsa); + sim_debug(DEBUG_EXP, &cpu_dev, + "store_csw FIFO Overflow ERROR on chsa %04x\n", chsa); } sim_debug(DEBUG_IRQ, &cpu_dev, - "store_csw FIFO write chsa %04x sw1 %08x sw2 %08x CPU stat %08x\n", - chsa, stwd1, stwd2, SPAD[0xf9]); + "store_csw FIFO #%1x write chsa %04x sw1 %08x sw2 %08x CPU stat %08x \n", + FIFO_Num(chsa), chsa, stwd1, stwd2, SPAD[0xf9]); chp->chan_status = 0; /* no status anymore */ + chp->chan_byte = BUFF_CHNEND; /* show done */ irq_pend = 1; /* wakeup controller */ } @@ -1020,6 +1039,7 @@ t_stat checkxio(uint16 lchsa, uint32 *status) { DIB *dibp; /* device information pointer */ UNIT *uptr; /* pointer to unit in channel */ uint32 chan_ivl; /* Interrupt Level ICB address for channel */ +// uint32 chan_icb; /* Interrupt level context block address */ uint32 iocla; /* I/O channel IOCL address int ICB */ uint32 tempa, inta, spadent, chan; uint16 chsa; @@ -1029,7 +1049,7 @@ t_stat checkxio(uint16 lchsa, uint32 *status) { spadent = SPAD[lchan]; /* get spad device entry for logical channel */ chan = (spadent & 0x7f00) >> 8; /* get real channel */ chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ - dibp = dev_unit[chsa & 0x7f00]; /* get the device information pointer */ + dibp = dib_unit[chsa & 0x7f00]; /* get the DIB pointer */ chp = find_chanp_ptr(chsa); /* find the chanp pointer */ uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ @@ -1049,22 +1069,29 @@ t_stat checkxio(uint16 lchsa, uint32 *status) { /* see if interrupt is setup in SPAD and determine IVL for channel */ sim_debug(DEBUG_DETAIL, &cpu_dev, "checkxio dev spad %08x chsa %04x\n", spadent, chsa); +#ifdef OLDWAY inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ inta = 127 - inta; /* get positive int level */ +#else + inta = ((~spadent)>>16)&0x7f; /* get positive number for interrupt */ +#endif spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ - sim_debug(DEBUG_DETAIL, &cpu_dev, "checkxio int spad %08x inta %04x chan %04x\n", spadent, inta, chan); + + sim_debug(DEBUG_XIO, &cpu_dev, "checkxio int spad %08x inta %04x chan %04x\n", spadent, inta, chan); /* get the address of the interrupt IVL in main memory */ chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ - iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ - tempa = M[(chan_ivl+20)>>2]; /* status is in wd 5 of ICB */ - sim_debug(DEBUG_CMD, &cpu_dev, - "checkxio busy ck1 chsa %04x cmd %02x iocla %06x flags %04x\n", - chsa, chp->ccw_cmd, iocla, chp->ccw_flags); - sim_debug(DEBUG_CMD, &cpu_dev, - "checkxio busy ck2 chsa %04x IOCD1 %08x IOCD2 %08x INCH %08x\n", - chsa, M[iocla>>2], M[(iocla+4)>>2], tempa); + chan_ivl = RMW(chan_ivl); /* get the interrupt context block addr in memory */ + iocla = RMW(chan_ivl+16); /* iocla is in wd 4 of ICB */ + tempa = RMW(chan_ivl+20); /* status is in wd 5 of ICB chp->chan_inch_addr */ + + sim_debug(DEBUG_XIO, &cpu_dev, + "checkxio busy ck1 chsa %04x cmd %02x ccw_flags %04x IOCD1 %08x IOCD2 %08x IOCLA %06x\n", + chsa, chp->ccw_cmd, chp->ccw_flags, RMW(iocla), RMW(iocla+4), iocla); + + sim_debug(DEBUG_XIO, &cpu_dev, + "checkxio busy ck2 chsa %04x ICBincha %08x SW1 %08x SW2 %08x\n", + chsa, tempa, RMW(tempa), RMW(tempa+4)); /* check for a Command or data chain operation in progresss */ if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { @@ -1101,48 +1128,59 @@ t_stat startxio(uint16 lchsa, uint32 *status) { DIB *dibp; /* device information pointer */ UNIT *uptr; /* pointer to unit in channel */ uint32 chan_ivl; /* Interrupt Level ICB address for channel */ + uint32 chan_icb; /* Interrupt level context block address */ uint32 iocla; /* I/O channel IOCL address int ICB */ - uint32 tempa, inta, spadent, chan; + uint32 tempa, inta, spadent, chan, incha; uint16 chsa; CHANP *chp; + sim_debug(DEBUG_XIO, &cpu_dev, "startxio entry lchsa %04x lchan %04x\n", lchsa, lchan); /* get the device entry for the logical channel in SPAD */ spadent = SPAD[lchan]; /* get spad device entry for logical channel */ chan = (spadent & 0x7f00) >> 8; /* get real channel */ chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ - dibp = dev_unit[chsa & 0x7f00]; /* get the device information pointer */ + dibp = dib_unit[chsa & 0x7f00]; /* get the DIB pointer */ chp = find_chanp_ptr(chsa); /* find the chanp pointer */ uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ - sim_debug(DEBUG_XIO, &cpu_dev, "startxio 1 chsa %04x chan %04x\n", chsa, chan); if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ *status = CC3BIT; /* not found, so CC3 */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "startxio chsa %04x device not present, CC3 returned\n", chsa); return SCPE_OK; /* not found, CC3 */ } - sim_debug(DEBUG_XIO, &cpu_dev, "startxio 2 chsa %04x chan %04x\n", chsa, chan); if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ - fprintf(stderr, "startxio chsa %04x is not attached, error return\r\n", chsa); +// fprintf(stderr, "startxio chsa %04x is not attached, ERROR return\r\n", chsa); + sim_debug(DEBUG_XIO, &cpu_dev, + "startxio chsa %04x device not present, CC3 returned flags %08x\n", chsa, uptr->flags); *status = CC3BIT; /* not attached, so error CC3 */ return SCPE_OK; /* not found, CC3 */ } /* see if interrupt is setup in SPAD and determine IVL for channel */ sim_debug(DEBUG_XIO, &cpu_dev, "startxio dev spad %08x chsa %04x chan %04x\n", spadent, chsa, chan); +#ifdef OLDWAY inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ inta = 127 - inta; /* get positive int level */ +#else + inta = ((~spadent)>>16)&0x7f; /* get positive number for interrupt */ +#endif spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ - sim_debug(DEBUG_XIO, &cpu_dev, "startxio int spad %08x inta %04x chan %04x\n", spadent, inta, chan); + sim_debug(DEBUG_XIO, &cpu_dev, "startxio int spad %08x inta %02x chan %04x\n", spadent, inta, chan); /* get the address of the interrupt IVL in main memory */ chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ - iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ + chan_icb = RMW(chan_ivl); /* get the interrupt context block addr in memory */ + iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ + incha = chp->chan_inch_addr; /* get inch address */ + /* now store the status dw address into word 5 of the ICB for the channel */ + WMW(chan_icb+20, incha); /* post inch addr in ICB+5w */ sim_debug(DEBUG_XIO, &cpu_dev, - "startxio test chsa %04x cmd %02x iocla %08x flags %04x IOCD1 %08x IOCD2 %08x\n", - chsa, chp->ccw_cmd, iocla, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); + "startxio test chsa %04x iocla %06x IOCD1 %08x IOCD2 %08x\n", + chsa, iocla, RMW(iocla), RMW(iocla+4)); - sim_debug(DEBUG_CMD, &cpu_dev, "$$$ SIO %04x %04x cmd %02x flags %04x\n", + sim_debug(DEBUG_CMD, &cpu_dev, "$$$ SIO %04x %04x cmd %02x ccw_flags %04x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); /* check for a Command or data chain operation in progresss */ @@ -1159,14 +1197,14 @@ t_stat startxio(uint16 lchsa, uint32 *status) { tempa = dibp->pre_io(uptr, chan); /* get status from device */ if (tempa != 0) { /* see if sub channel status is ready */ /* The device must be busy or something, but it is not ready. Return busy */ - sim_debug(DEBUG_XIO, &cpu_dev, "startxio pre_io call return busy chan %04x cstat %08x\n", - chan, tempa); + sim_debug(DEBUG_XIO, &cpu_dev, + "startxio pre_io call return busy chan %04x cstat %08x\n", chan, tempa); //WAS chp->chan_status = 0; /* no status anymore */ *status = CC3BIT|CC4BIT; /* sub channel busy, so CC3|CC4 */ return SCPE_OK; /* just busy or something, CC3|CC4 */ } sim_debug(DEBUG_XIO, &cpu_dev, - "startxio pre_io call return not busy ctan %04x cstat %08x\n", + "startxio pre_io call return not busy chan %04x cstat %08x\n", chan, tempa); } @@ -1174,36 +1212,30 @@ t_stat startxio(uint16 lchsa, uint32 *status) { chp->chan_status = 0; /* no channel status yet */ dev_status[chsa] = 0; /* no unit status either */ chp->chan_caw = iocla; /* get iocla address in memory */ + chp->chan_byte = BUFF_NEWCMD; /* starting a new program */ /* set status words in memory to first IOCD information */ - tempa = chp->chan_inch_addr; /* get inch status buffer address */ sim_debug(DEBUG_XIO, &cpu_dev, "$$ SIO start IOCL processing chsa %04x iocla %08x incha %08x\n", - chsa, iocla, tempa); + chsa, iocla, incha); /* 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 store csw CC2 chan %04x status %08x\n", - chan, chp->chan_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); /* DIAG's want CC1 with memory access error */ if (chp->chan_status & STATUS_PCHK) { chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ chp->chan_status &= ~STATUS_LENGTH; /* clear incorrect length */ -#ifndef NEW_METHOD -/*XXX*/ store_csw(chp); /* store the status in the inch status dw */ -#endif - dev_status[chsa] = 0; /* no device status */ -//DIAG *status = CC2BIT; /* status stored, so CC2 */ +//XXX store_csw(chp); /* store the status in the inch status dw */ *status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */ irq_pend = 1; /* still pending int */ return SCPE_OK; /* CC2 (0x20) status stored */ } -#ifndef NEW_METHOD -/*XXX*/ store_csw(chp); /* store the status in the inch status dw */ -#endif + /* TODO maybe need to do chan_end first */ + store_csw(chp); /* store the status in the inch status dw */ chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ - dev_status[chsa] = 0; /* no device status */ *status = CC2BIT; /* status stored, so CC2 */ irq_pend = 1; /* still pending int */ return SCPE_OK; /* CC2 (0x20) status stored */ @@ -1222,81 +1254,98 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */ DIB *dibp; UNIT *uptr; uint32 chan_ivl; /* Interrupt Level ICB address for channel */ + uint32 chan_icb; /* Interrupt level context block address */ uint32 iocla; /* I/O channel IOCL address int ICB */ - uint32 tempa, inta, spadent, chan; +// uint32 tempa, inta, spadent, chan, incha; + uint32 inta, spadent, chan, incha; uint16 chsa; /* chan/subaddr */ - CHANP *chp, *pchp; /* Channel prog pointers */ - uint32 sw1=0, sw2=0; /* status word 1 & 2 */ +// CHANP *chp, *pchp; /* Channel prog pointers */ + CHANP *chp; /* Channel prog pointers */ +// uint32 sw1=0, sw2=0; /* status word 1 & 2 */ /* get the device entry for the logical channel in SPAD */ spadent = SPAD[lchan]; /* get spad device entry for logical channel */ chan = (spadent & 0x7f00) >> 8; /* get real channel */ chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ - dibp = dev_unit[chsa]; /* get the device information pointer */ + dibp = dib_unit[chsa]; /* get the DIB pointer */ chp = find_chanp_ptr(chsa); /* find the device chanp pointer */ uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ - pchp = find_chanp_ptr(chsa & 0x7f00); /* find the channel chanp pointer */ +// pchp = find_chanp_ptr(chsa & 0x7f00); /* find the channel chanp pointer */ - sim_debug(DEBUG_DETAIL, &cpu_dev, "testxio 1 chsa %04x chan %04x\n", chsa, chan); if ((dibp == 0) || (uptr == 0)) { /* if non found, CC3 on return */ *status = CC3BIT; /* not found, so CC3 */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "testxio chsa %04x device not present, CC3 returned\n", chsa); goto tioret; /* not found, CC3 */ } - sim_debug(DEBUG_DETAIL, &cpu_dev, "testxio 2 chsa %04x chan %04x\n", chsa, chan); if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ *status = CC3BIT; /* not attached, so error CC3 */ + fprintf(stderr, "testxio chsa %04x is not attached, ERROR return\r\n", chsa); + sim_debug(DEBUG_DETAIL, &cpu_dev, + "testxio chsa %04x device not present, CC3 returned\n", chsa); goto tioret; /* not found, CC3 */ } /* see if interrupt is setup in SPAD and determine IVL for channel */ - sim_debug(DEBUG_DETAIL, &cpu_dev, "testxio dev spad %08x chsa %04x chan %04x\n", spadent, chsa, chan); + sim_debug(DEBUG_XIO, &cpu_dev, "testxio dev spad %08x chsa %04x chan %04x\n", spadent, chsa, chan); /* the startio opcode processing software has already checked for F class */ inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ inta = 127 - inta; /* get positive int level */ spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ - sim_debug(DEBUG_DETAIL, &cpu_dev, "testxio int spad %08x inta %04x chan %04x\n", spadent, inta, chan); + sim_debug(DEBUG_XIO, &cpu_dev, "testxio int spad %08x inta %04x chan %04x\n", spadent, inta, chan); /* get the address of the interrupt IVL in main memory */ chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ - iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ + chan_icb = RMW(chan_ivl); /* get the interrupt context block addr in memory */ + iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ + incha = chp->chan_inch_addr; /* get inch address */ sim_debug(DEBUG_XIO, &cpu_dev, - "testxio busy test chsa %04x cmd %02x flags %04x IOCD1 %08x IOCD2 %08x IOCLA %08x\n", - chsa, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2], iocla); + "testxio test1 chsa %04x cmd %02x ccw_flags %04x IOCD1 %08x IOCD2 %08x IOCLA %06x\n", + chsa, chp->ccw_cmd, chp->ccw_flags, RMW(iocla), RMW(iocla+4), iocla); + + sim_debug(DEBUG_XIO, &cpu_dev, + "testxio test2 chsa %04x ICBincha %08x SW1 %08x SW2 %08x\n", + chsa, incha, RMW(incha), RMW(incha+4)); /* check for a Command or data chain operation in progresss */ if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "testxio busy return CC4 chsa %04x chan %04x\n", chsa, chan); *status = CC4BIT; /* busy, so CC4 */ goto tioret; /* just busy CC4 */ } /* the channel is not busy, see if any status to post */ - /* see if the FIFO is empty */ - if (dibp->chan_fifo_in != dibp->chan_fifo_out) { - if ((FIFO_Get(chsa, &sw1) == 0) && (FIFO_Get(chsa, &sw2) == 0)) { - uint32 chan_icb = find_int_icb(chsa); /* get icb address */ - - sim_debug(DEBUG_IRQ, &cpu_dev, - "testxio FIFO status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2); - /* we have status to return, do it now */ - tempa = pchp->chan_inch_addr; /* get inch status buffer address */ - M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ - /* save the status to memory */ - M[(tempa+4) >> 2] = sw2; /* save status and residual cnt in status WD 2 loc */ - /* now store the status dw address into word 5 of the ICB for the channel */ - M[(chan_icb + 20) >> 2] = tempa | BIT1; /* post sw addr in ICB+5w & set CC2 in INCH addr */ + if (post_csw(chp, 0)) { *status = CC2BIT; /* status stored from SIO, so CC2 */ + sim_debug(DEBUG_XIO, &cpu_dev, + "testxio END status stored incha %06x chsa %04x sw1 %08x sw2 %08x\n", + incha, chsa, RMW(incha), RMW(incha+4)); + INTS[inta] &= ~INTS_REQ; /* clear any level request */ goto tioret; /* CC2 and OK */ } +#ifdef TESTING_032020_XXX + if ((CPUSTATUS & 0x80) != 0) { /* are interrupts blocked */ +// uint32 chan_icb = find_int_icb(chsa); /* get icb address */ +// tempa = chp->chan_inch_addr; /* get inch status buffer address */ + if (incha && (incha & BIT1)) { /* see if status was posted */ + *status = CC2BIT; /* status stored from SIO, so CC2 */ + sim_debug(DEBUG_XIO, &cpu_dev, + "testxio ECHO status stored incha %06x chsa %04x sw1 %08x sw2 %08x\n", + incha, chsa, RMW(incha), RMW(incha+4)); + goto tioret; /* CC2 and OK */ + } } +#endif /* nothing going on, so say all OK */ *status = CC1BIT; /* request accepted, no status, so CC1 */ tioret: - sim_debug(DEBUG_CMD, &cpu_dev, - "$$$ TIO END chsa %04x chan %04x cmd %02x flags %04x chan_stat %04x CCs %08x\n", + sim_debug(DEBUG_XIO, &cpu_dev, + "$$$ TIO END chsa %04x chan %04x cmd %02x ccw_flags %04x chan_stat %04x CCs %08x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags, chp->chan_status, *status); + /* test following 031920 */ + /* change following 032820 to remove */ +// irq_pend = 1; /* still pending int */ return SCPE_OK; /* No CC's all OK */ } @@ -1306,6 +1355,7 @@ t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */ DIB *dibp; UNIT *uptr; uint32 chan_ivl; /* Interrupt Level ICB address for channel */ + uint32 chan_icb; /* Interrupt level context block address */ uint32 iocla; /* I/O channel IOCL address int ICB */ uint32 inta, spadent; uint16 chsa; @@ -1315,7 +1365,7 @@ t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */ spadent = SPAD[chan]; /* get spad device entry for logical channel */ chan = (spadent & 0x7f00) >> 8; /* get real channel */ chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ - dibp = dev_unit[chsa]; /* get the device information pointer */ + dibp = 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 */ @@ -1340,10 +1390,10 @@ t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */ /* get the address of the interrupt IVL in main memory */ chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ - iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ + chan_icb = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ + iocla = M[(chan_icb+16)>>2]; /* iocla is in wd 4 of ICB */ sim_debug(DEBUG_CMD, &cpu_dev, - "stopxio busy test chsa %04x cmd %02x flags %04x IOCD1 %08x IOCD2 %08x\n", + "stopxio busy test chsa %04x cmd %02x ccw_flags %04x IOCD1 %08x IOCD2 %08x\n", chsa, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); sim_debug(DEBUG_CMD, &cpu_dev, "$$$ STOPIO %04x %02x %04x\n", @@ -1361,7 +1411,7 @@ t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */ /* the channel is not busy, so return OK */ *status = CC1BIT; /* request accepted, no status, so CC1 */ sim_debug(DEBUG_CMD, &cpu_dev, - "$$$ STOPIO good return chsa %04x chan %04x cmd %02x flags %04x status %04x\n", + "$$$ STOPIO good return chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); return SCPE_OK; /* No CC's all OK */ } @@ -1380,7 +1430,7 @@ t_stat rschnlxio(uint16 lchsa, uint32 *status) { /* reset channel XIO */ spadent = SPAD[chan]; /* get spad device entry for logical channel */ chan = spadent & 0x7f00; /* get real channel */ chsa = chan; /* use just channel */ - dibp = dev_unit[chsa]; /* get the device information pointer */ + 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 */ @@ -1394,31 +1444,29 @@ t_stat rschnlxio(uint16 lchsa, uint32 *status) { /* reset channel XIO */ *status = CC3BIT; /* not attached, so error CC3 */ return SCPE_OK; /* not found, CC3 */ } - /* reset the FIFO pointers */ - dibp->chan_fifo_in = 0; - dibp->chan_fifo_out = 0; - dev_status[chan] = 0; /* clear the channel status location */ + dibp->chan_fifo_in = 0; /* reset the FIFO pointers */ + dibp->chan_fifo_out = 0; /* reset the FIFO pointers */ +// 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 */ SPAD[lev+0x80] &= ~SINT_ACT; /* clear spad too */ +if (lev == 0) +sim_debug(DEBUG_IRQ, &cpu_dev, "XY1 Zero interrupt level found\n"); INTS[lev] &= ~INTS_REQ; /* clear level request */ /* now go through all the sa for the channel and stop any IOCLs */ for (i=0; i<256; i++) { chsa = chan | i; /* merge sa to real channel */ - dibp = dev_unit[chsa]; /* get the device information pointer */ + dibp = dib_unit[chsa]; /* get the DIB pointer */ if (dibp == 0) - { continue; /* not used */ - } chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - if (chp == 0) { + if (chp == 0) continue; /* not used */ - } - dev_status[chsa] = 0; /* clear device status */ +// dev_status[chsa] = 0; /* clear device status */ chp->chan_status = 0; /* clear the channel status */ - chp->chan_byte = BUFF_EMPTY; /* no data yet */ + chp->chan_byte = BUFF_NEWCMD; /* no data yet */ chp->ccw_addr = 0; /* clear buffer address */ chp->chan_caw = 0x0; /* clear IOCD address */ chp->ccw_count = 0; /* channel byte count 0 bytes*/ @@ -1437,20 +1485,22 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ DIB *dibp; UNIT *uptr; uint32 chan_ivl; /* Interrupt Level ICB address for channel */ + uint32 chan_icb; /* Interrupt level context block address */ uint32 iocla; /* I/O channel IOCL address int ICB */ - uint32 inta, spadent; + uint32 inta, spadent, tempa; uint16 chsa; - CHANP *chp, *pchp; /* Channel prog pointers */ - uint32 sw1=0, sw2=0; /* status word 1 & 2 */ +// CHANP *chp, *pchp; /* Channel prog pointers */ + CHANP *chp; /* Channel prog pointers */ +// uint32 sw1=0, sw2=0; /* status word 1 & 2 */ /* get the device entry for the logical channel in SPAD */ spadent = SPAD[chan]; /* get spad device entry for logical channel */ chan = (spadent & 0x7f00) >> 8; /* get real channel */ chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ - dibp = dev_unit[chsa]; /* get the device information pointer */ + dibp = 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 */ - pchp = find_chanp_ptr(chsa & 0x7f00); /* find the parent channel pointer */ +// pchp = find_chanp_ptr(chsa & 0x7f00); /* find the parent channel pointer */ sim_debug(DEBUG_XIO, &cpu_dev, "haltxio 1 chsa %04x chan %04x\n", chsa, chan); if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ @@ -1473,154 +1523,88 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ /* get the address of the interrupt IVL in main memory */ chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ - iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ + chan_icb = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ + iocla = M[(chan_icb+16)>>2]; /* iocla is in wd 4 of ICB */ sim_debug(DEBUG_XIO, &cpu_dev, - "haltxio busy test chsa %04x chan %04x cmd %02x flags %04x IOCD1 %08x IOCD2 %08x\n", + "haltxio busy test chsa %04x chan %04x cmd %02x ccw_flags %04x IOCD1 %08x IOCD2 %08x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); - sim_debug(DEBUG_XIO, &cpu_dev, "$$$ HIO %04x %04x %02x %04x\n", + sim_debug(DEBUG_XIO, &cpu_dev, "$$$ HIO chsa %04x chan %04x cmd %02x ccw_flags %04x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); if (chp->ccw_cmd == 0 && (chp->ccw_flags & (FLAG_DC|FLAG_CC)) == 0) { /* the channel is not busy, so return OK */ -#ifdef DIAGTUE - *status = CC1BIT; /* request accepted, no status, so CC1 */ - sim_debug(DEBUG_CMD, &cpu_dev, - "$$$ HIO END chsa %04x chan %04x cmd %02x flags %04x status %04x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); - return SCPE_OK; /* No CC's all OK */ -#else + /* diag wants an interrupt for a non busy HIO ??? */ sim_debug(DEBUG_XIO, &cpu_dev, - "$$$ HIO DIAG chsa %04x chan %04x cmd %02x flags %04x status %04x\n", + "$$$ HIO DIAG chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); - dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ -#ifndef NEW_METHOD -/*XXX*/ store_csw(chp); /* store the status in the inch status dw */ -#endif - dev_status[chsa] = 0; /* no device status */ irq_pend = 1; /* still pending int */ -// *status = CC2BIT; /* sub channel status posted, CC2BIT */ *status = CC1BIT; /* request accepted, no status, so CC1 */ goto hioret; /* CC2 and OK */ -#endif } + /* the channel is busy, so process */ chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ -#ifndef TRY_THIS_02282020 + /* see if we have a haltio device entry */ if (dibp->halt_io != NULL) { /* NULL if no haltio function */ + /* call the device controller to get halt_io status */ - uint32 tempa = dibp->halt_io(uptr); /* get status from device */ -#ifdef BAD_TUE - if (tempa == SNS_BSY) { - *status = CC3BIT|CC4BIT; /* sub channel busy, CC3BIT & CC4BIT */ - irq_pend = 1; /* still pending int */ - sim_debug(DEBUG_CMD, &cpu_dev, - "haltxio halt_io return busy chan %04x CC3|CC4\n", chan); - goto hioret; /* just return */ - } -#endif + tempa = dibp->halt_io(uptr); /* get status from device */ + /* test for SCPE_IOERR */ if (tempa != 0) { /* sub channel has status ready */ /* The device I/O has been terminated and status stored. */ sim_debug(DEBUG_XIO, &cpu_dev, - "haltxio halt_io call return ERROR chan %04x retstat %08x cstat %08x\n", - chan, tempa, chp->chan_status); -/*TUE*/ chp->chan_status &= ~STATUS_LENGTH; /* remove SLI status bit */ - chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ -//TUE dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */ + "haltxio halt_io call return ERROR FIFO #%1x chan %04x retstat %08x cstat %08x\n", + FIFO_Num(chsa), chan, tempa, chp->chan_status); + /* chan_end called in hio device service routine */ -#ifndef NEW_METHOD -/*XXX*/ store_csw(chp); /* store the status in the inch status dw */ -#endif - chp->ccw_count = 0; /* force zero count */ - dev_status[chsa] = 0; /* no device status */ - -#ifndef TRY_02282020 -//WAS0229 if (CPU_MODEL >= MODEL_V6) { - if (CPU_MODEL >= MODEL_27) { - /* UTX wants the status posted now, MPX wants interrupt */ - - /* the channel is not busy, see if any status to post */ - if ((FIFO_Get(chsa, &sw1) == 0) && (FIFO_Get(chsa, &sw2) == 0)) { - uint32 chan_icb = find_int_icb(chsa); /* get icb address */ - - sim_debug(DEBUG_IRQ, &cpu_dev, - "haltxio 0 FIFO status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2); -/*TUE*/ sw2 &= ~STATUS_LENGTH; /* remove SLI status bit */ -/*XXX*/ sw2 |= STATUS_ECHO; /* show we stopped the cmd */ - /* we have status to return, do it now */ - tempa = pchp->chan_inch_addr; /* get inch status buffer address */ - M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ - /* save the status to memory */ - M[(tempa+4) >> 2] = sw2; /* save status and count in status WD 2 loc */ - /* now store the status dw address into word 5 of the ICB for the channel */ - /* post sw addr in ICB+5w & set CC2 in INCH addr */ - M[(chan_icb + 20) >> 2] = tempa | BIT2; - sim_debug(DEBUG_IRQ, &cpu_dev, - "haltxio 1 FIFO status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2); - irq_pend = 1; /* still pending int */ - // UTX likes this return and does not panic */ - // The diag's want an interrupt generated, so wait - *status = CC2BIT; /* status stored from HIO, so CC2 */ - /* if 0 returned, UTX hangs on input */ - goto hioret; /* CC2 and OK */ - } - /* nothing going on, so say all OK */ - *status = CC1BIT; /* request accepted, no status, so CC1 */ -//TRYIED *status = 0; /* CCs = 0, accepted */ - goto hioret; /* CC2 and OK */ - } else -#endif - { - sim_debug(DEBUG_IRQ, &cpu_dev, - "haltxio FIFO 2 status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2); - irq_pend = 1; /* still pending int */ -/*LAST*/ *status = CC1BIT; /* request accepted, no status, so CC1 */ -//TRIED *status = CC2BIT; /* sub channel status posted, CC2BIT */ + /* the device is no longer busy, post status */ + if (post_csw(chp, ((STATUS_LENGTH|STATUS_PCI|STATUS_EXPT|STATUS_CHECK) << 16))) { + /* TODO clear SLI bit in status */ +// chp->chan_status &= ~STATUS_LENGTH; /* remove SLI status bit */ +// chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ + INTS[inta] &= ~INTS_REQ; /* clear any level request */ + *status = CC2BIT; /* status stored */ goto hioret; /* CC2 and OK */ } } else { /* we have completed the I/O without error */ /* the channel is not busy, so return OK */ -//WAS *status = 0; /* CCs = 0, accepted */ sim_debug(DEBUG_XIO, &cpu_dev, - "$$$ HALTXIO good return chsa %04x chan %04x cmd %02x flags %04x status %04x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + "$$$ HALTXIO FIFO #%1x good return chsa %04x cmd %02x ccw_flags %04x status %04x\n", + FIFO_Num(chsa), chsa, chp->ccw_cmd, chp->ccw_flags, *status); *status = CC1BIT; /* request accepted, no status, so CC1 */ goto hioret; /* just return */ } } -#endif /*TRY_THIS_02282020*/ /* device does not have a HIO entry, so terminate the I/O */ /* 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, "haltxio busy return CC4 chsa %04x chan %04x\n", chsa, chan); + /* reset the DC or CC bits to force completion after current IOCD */ chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ - dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */ -/*ADD*/ chp->ccw_count = 0; /* clear remaining count */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ -/*ADD*/ chp->chan_status &= ~STATUS_LENGTH; /* remove SLI status bit */ -#ifndef NEW_METHOD -/*XXX*/ store_csw(chp); /* store the status in the inch status dw */ -#endif - chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ - dev_status[chsa] = 0; /* no device status */ - irq_pend = 1; /* still pending int */ - *status = CC2BIT; /* sub channel status posted, CC2BIT */ -//TRY *status = CC1BIT; /* request accepted, no status, so CC1 */ - goto hioret; /* just return */ + chp->chan_byte = BUFF_EMPTY; /* done */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* show I/O complete */ + + /* post the channel status */ + if (post_csw(chp, ((STATUS_LENGTH|STATUS_PCI|STATUS_EXPT|STATUS_CHECK) << 16))) { + /* TODO clear SLI bit in status */ +// chp->chan_status &= ~STATUS_LENGTH; /* remove SLI status bit */ +// chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ + INTS[inta] &= ~INTS_REQ; /* clear any level request */ + *status = CC2BIT; /* status stored from SIO, so CC2 */ + goto hioret; /* just return */ + } } /* the channel is not busy, so return OK */ *status = CC1BIT; /* request accepted, no status, so CC1 */ - goto hioret; /* just return */ - hioret: - sim_debug(DEBUG_CMD, &cpu_dev, "$$$ HIO END chsa %04x chan %04x cmd %02x flags %04x status %04x\n", + sim_debug(DEBUG_CMD, &cpu_dev, "$$$ HIO END chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); return SCPE_OK; /* No CC's all OK */ } @@ -1664,7 +1648,7 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */ spadent = SPAD[chan]; /* get spad device entry for logical channel */ chan = spadent & 0x7f00; /* get real channel */ chsa = chan; /* use just channel */ - dibp = dev_unit[chsa]; /* get the device information pointer */ + 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 */ @@ -1686,12 +1670,14 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */ lev = find_int_lev(chan); /* get our int level */ INTS[lev] &= ~INTS_ACT; /* clear level active */ SPAD[lev+0x80] &= ~SINT_ACT; /* clear spad too */ +if (lev == 0) +sim_debug(DEBUG_IRQ, &cpu_dev, "XY2 Zero interrupt level found\n"); INTS[lev] &= ~INTS_REQ; /* clear level request */ /* now go through all the sa for the channel and stop any IOCLs */ for (i=0; i<256; i++) { chsa = chan | i; /* merge sa to real channel */ - dibp = dev_unit[chsa]; /* get the device information pointer */ + dibp = dib_unit[chsa]; /* get the DIB pointer */ if (dibp == 0) { continue; /* not used */ @@ -1702,7 +1688,7 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */ } dev_status[chsa] = 0; /* clear device status */ chp->chan_status = 0; /* clear the channel status */ - chp->chan_byte = BUFF_EMPTY; /* no data yet */ + chp->chan_byte = BUFF_NEWCMD; /* no data yet */ chp->ccw_addr = 0; /* clear buffer address */ chp->chan_caw = 0x0; /* clear IOCD address */ chp->ccw_count = 0; /* channel byte count 0 bytes*/ @@ -1718,7 +1704,6 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */ /* on CPU reset, the cpu has set the IOCD data at location 0-4 */ t_stat chan_boot(uint16 chsa, DEVICE *dptr) { int chan = get_chan(chsa); -//Z DIB *dibp = dev_unit[chsa]; DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to DIB for this device */ CHANP *chp = 0; @@ -1733,259 +1718,238 @@ t_stat chan_boot(uint16 chsa, DEVICE *dptr) { dev_status[chsa] = 0; /* device status too */ chp->chan_status = 0; /* clear the channel status */ chp->chan_dev = chsa; /* save our address (ch/sa) */ - chp->chan_byte = BUFF_EMPTY; /* no data yet */ + chp->chan_byte = BUFF_NEWCMD; /* no data yet */ chp->ccw_addr = 0; /* start loading at loc 0 */ chp->chan_caw = 0x0; /* set IOCD address to memory location 0 */ chp->ccw_count = 0; /* channel byte count 0 bytes*/ chp->ccw_flags = 0; /* Command chain and supress incorrect length */ chp->ccw_cmd = 0; /* read command */ + loading = chsa; /* show we are loading from the boot device */ sim_debug(DEBUG_CMD, &cpu_dev, "Channel Boot calling load_ccw chan %04x status %08x\n", chan, chp->chan_status); /* start processing the boot IOCL at loc 0 */ if (load_ccw(chp, 0)) { /* load IOCL starting from location 0 */ - sim_debug(DEBUG_CMD, &cpu_dev, "Channel Boot Error return from load_ccw chan %04x status %08x\n", + sim_debug(DEBUG_XIO, &cpu_dev, "Channel Boot Error return from load_ccw chan %04x status %08x\n", chan, chp->chan_status); 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 */ return SCPE_IOERR; /* return error */ } - sim_debug(DEBUG_CMD, &cpu_dev, "Channel Boot OK return from load_ccw chsa %04x status %04x\n", + sim_debug(DEBUG_XIO, &cpu_dev, "Channel Boot OK return from load_ccw chsa %04x status %04x\n", chsa, chp->chan_status); - loading = chsa; /* show we are loading from the boot device */ return SCPE_OK; /* all OK */ } +/* Continue a channel program for a device */ +uint32 cont_chan(uint16 chsa) +{ + int32 stat; /* return status 0/1 from loadccw */ + CHANP *chp = find_chanp_ptr(chsa); /* channel program */ + + /* we have entries, continue channel program */ + if (chp->chan_byte == BUFF_NEWCMD) { + /* channel program terminated already, ignore entry */ + sim_debug(DEBUG_EXP, &cpu_dev, + "cont_chan chan_byte is BUFF_NEWCMD chsa %04x addr %06x\n", + chsa, chp->ccw_addr); + return SCPE_OK; + } + if (chp->chan_byte == BUFF_NEXT) { + sim_debug(DEBUG_EXP, &cpu_dev, + "cont_chan resume chan prog chsa %04x addr %06x\n", + chsa, chp->ccw_addr); + stat = load_ccw(chp, 1); /* resume the channel program */ + if (stat || (chp->chan_status & STATUS_PCI)) { + /* we have an error or user requested interrupt, return status */ + sim_debug(DEBUG_EXP, &cpu_dev, "cont_chan error, store csw chsa %04x status %08x\n", + chsa, chp->chan_status); + /* DIAG's want CC1 with memory access error */ + if (chp->chan_status & STATUS_PCHK) { + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ + chp->chan_status &= ~STATUS_LENGTH; /* clear incorrect length */ + store_csw(chp); /* store the status in the inch status dw */ + chp->chan_byte = BUFF_NEWCMD; /* read for new cmd */ + dev_status[chsa] = 0; /* no device status */ + irq_pend = 1; /* show pending int */ + return SCPE_OK; /* done */ + } + } + if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { + sim_debug(DEBUG_EXP, &cpu_dev, + "cont_chan store csw chsa %04x status %08x\n", + chsa, chp->chan_status); + store_csw(chp); /* store the status in the inch status dw */ + chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ + dev_status[chsa] = 0; /* no device status */ + chp->chan_byte = BUFF_NEWCMD; /* we are done */ + irq_pend = 1; /* show pending int */ + return SCPE_OK; /* done, status stored */ + } +#ifdef XXX + chp->chan_byte = BUFF_NEXT; /* have main pick us up again */ + RDYQ_Put(chsa); /* queue us up */ + sim_debug(DEBUG_EXP, &cpu_dev, + "cont_chan continue wait chsa %04x status %08x\n", + chsa, chp->chan_status); + irq_pend = 1; /* show pending int */ +#endif + sim_debug(DEBUG_EXP, &cpu_dev, + "cont_chan continue wait chsa %04x status %08x\n", + chsa, chp->chan_status); + return SCPE_OK; /* done, status stored */ + } + /* must be more IOCBs, wait for them */ + return SCPE_OK; +} + /* Scan all channels and see if one is ready to start or has interrupt pending. Return icb address and interrupt level */ -uint32 scan_chan(int *ilev) { - int i,j; - uint32 chsa = 0; /* No device */ +uint32 scan_chan(uint32 *ilev) { +// int i,j; + int i; +// uint32 chsa; /* No device */ uint32 chan; /* channel num 0-7f */ uint32 tempa; /* icb address */ uint32 chan_ivl; /* int level table address */ +// uint32 chan_icb; /* Interrupt level context block address */ uint32 chan_icba; /* int level context block address */ CHANP *chp; /* channel prog pointer */ DIB *dibp; /* DIB pointer */ + uint32 sw1, sw2; /* status words */ -#ifndef NEW_METHOD - if (irq_pend == 1) { /* pending int? */ - /* see if we have a channel completed */ - /* loop through all the channels/units for channel with pending I/O completion */ - for (i = 0; sim_devices[i] != NULL; i++) { - DEVICE *dptr = sim_devices[i]; /* get pointer to configured device */ - DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to DIB for this device */ - UNIT *uptr = dptr->units; /* get pointer to units defined for this device */ - - if (dibp == NULL) /* If no DIB, not channel device */ - continue; - if (dptr->flags & DEV_DIS) { /* Skip disabled devices */ - continue; - } - if ((chp = (CHANP *)dibp->chan_prg) == NULL)/* must have channel information for each device */ - continue; - /* Check if address is in unit or dev entry */ - for (j = 0; j < dibp->numunits; j++) { /* loop through unit entries */ - chsa = GET_UADDR(uptr->u3); /* ch/sa value */ - - /* If channel end, check if we should continue */ - if (chp->chan_status & STATUS_CEND) { /* do we have channel end */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "scan_chan loading %02x chan end chsa %04x flags %04x status %04x\n", - loading, chsa, chp->ccw_flags, chp->chan_status); - if (chp->ccw_flags & FLAG_CC) { /* command chain flag */ - /* we have channel end and CC flag, continue channel prog */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "scan_chan loading %02x chan end & CC chsa %04x status %04x\n", - loading, chsa, chp->chan_status); - if (chp->chan_status & STATUS_DEND) { /* device end? */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "scan_chan loading %02x dev end & CC chsa %04x status %04x\n", - loading, chsa, chp->chan_status); - (void)load_ccw(chp, 1); /* go load the next IOCB */ - } else - irq_pend = 1; /* still pending int */ - } else { - /* we have channel end and no CC flag, end command */ - chsa = chp->chan_dev; /* get the chan/sa */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "scan_chan loading %02x chan end & no CC chsa %04x status %04x\n", - loading, chsa, chp->chan_status); - dev_status[chsa] = 0; /* no device status anymore */ - /* handle case where we are loading the O/S on boot */ - if (loading) { - if (chp->chan_status & 0x3f03) { /* check if any channel errors */ - return 0; /* yes, just return */ - } - irq_pend = 0; /* no pending int */ - chp->chan_status = 0; /* no channel status */ - return chsa; /* if loading, just channel number */ - } - /* we are not loading, but have completed channel program */ - store_csw(chp); /* store the status */ - sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan call store_csw dev end & chan end chsa %04x cpustatus %08x\n", - chsa, CPUSTATUS); - irq_pend = 1; /* still pending int */ -//WAS goto trythis; - return 0; /* just return */ - } - } - uptr++; /* next UNIT pointer */ - chp++; /* next CHANP pointer */ - } - } - } -//WAS trythis: -#else - if ((irq_pend == 1) && loading) { /* pending int? */ - /* see if we have a channel completed for the boot channel */ - chp = find_chanp_ptr(loading); /* find the chanp pointer for channel */ - /* If channel end, check if we should continue */ - if (chp->chan_status & STATUS_CEND) { /* do we have channel end */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "scan_chan loading %02x chan end chsa %04x flags %04x status %02x\n", - loading, chsa, chp->ccw_flags, chp->chan_status); - if (chp->ccw_flags & FLAG_CC) { /* command chain flag */ - /* we have channel end and CC flag, continue channel prog */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "scan_chan loading %02x chan end & CC chsa %04x status %02x\n", - loading, chsa, chp->chan_status); - if (chp->chan_status & STATUS_DEND) { /* device end? */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "scan_chan loading %02x dev end & CC chsa %04x status %02x\n", - loading, chsa, chp->chan_status); - (void)load_ccw(chp, 1); /* go load the next IOCB */ - } else - irq_pend = 1; /* still pending int */ - } else { - /* we have channel end and no CC flag, end command */ - chsa = chp->chan_dev; /* get the chan/sa */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "scan_chan loading %02x chan end & no CC chsa %04x status %02x\n", - loading, chsa, chp->chan_status); - dev_status[chsa] = 0; /* no device status anymore */ - /* handle case where we are loading the O/S on boot */ - if (chp->chan_status & 0x3f03) { /* check if any channel errors */ - return 0; /* yes, just return */ - } - irq_pend = 0; /* no pending int */ - chp->chan_status = 0; /* no channel status */ - return chsa; /* if loading, just channel number */ - } - } - } + /* see if we are loading */ + if (loading) { + /* we are loading see if chan prog complete */ + /* get the device entry for the logical channel in SPAD */ + chan = loading & 0x7f00; /* get real channel and zero sa */ + dibp = dib_unit[chan]; /* get the IOP/MFP DIB pointer */ + if (dibp == 0) + return 0; /* skip unconfigured channel */ + /* see if status s stored in FIFO */ + /* see if the FIFO is empty */ + if ((FIFO_Num(chan)) && ((FIFO_Get(chan, &sw1) == 0) && + (FIFO_Get(chan, &sw2) == 0))) { + /* fifo is not empty, so post status and request an interrupt */ + /* we have status to return, do it now */ + chp = find_chanp_ptr(chan); /* find the chanp pointer for channel */ + tempa = chp->chan_inch_addr; /* get inch status buffer address */ +#ifdef NOTUSED + /* get the address of the interrupt IVL table in main memory */ + chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */ + chan_icba = M[chan_ivl >> 2]; /* get the interrupt context blk addr in memory */ + M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ + /* save the status to memory */ + M[(tempa+4) >> 2] = sw2; /* save status and count in status WD 2 loc */ + /* now store the status dw address into word 5 of the ICB for the channel */ + /* post sw addr in ICB+5w & set CC2 in SW */ + M[(chan_icba + 20) >> 2] = tempa | BIT1; +// INTS[i] |= INTS_REQ; /* turn on channel interrupt request */ #endif + sim_debug(DEBUG_IRQ, &cpu_dev, + "LOADING %06x %04x FIFO #%1x read inch %06x sw1 %08x sw2 %08x\n", + chp->chan_caw, chan, FIFO_Num(chan), tempa, sw1, sw2); + return loading; + } + return 0; /* not ready, return */ + } + /* see if we are able to look for ints */ - if ((CPUSTATUS & 0x80) == 0) { /* are interrupts blocked */ - /* ints not blocked, so look for highest requesting interrupt */ - for (i=0; i<112; i++) { - if (SPAD[i+0x80] == 0) /* not initialize? */ - continue; /* skip this one */ - if (SPAD[i+0x80] == 0xffffffff) /* not initialize? */ - continue; /* skip this one */ - if ((INTS[i]&INTS_ACT) || (SPAD[i+0x80]&SINT_ACT)) { /* look for level active */ -//XXX if ((SPAD[i+0x80]&SINT_ACT)) { /* look for level active */ - sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan INTS ACT irq %02x SPAD %08x INTS %08x\n", - i, SPAD[i+0x80], INTS[i]); - break; /* this level active, so stop looking */ - } - -#ifndef NEW_METHOD - /* see if there is pending status for this channel */ - /* if there is and the level is not requesting, do it */ - if ((INTS[i] & INTS_ENAB) && !(INTS[i] & INTS_REQ)) { - /* get the device entry for the logical channel in SPAD */ - chan = (SPAD[i+0x80] & 0x7f00); /* get real channel and zero sa */ - dibp = dev_unit[chan]; /* get the device information pointer */ - if (dibp == 0) - continue; /* skip unconfigured channel */ - /* see if the FIFO is empty */ - if (dibp->chan_fifo_in != dibp->chan_fifo_out) { - uint32 sw1, sw2; - /* fifo is not empty, so post status and request an interrupt */ - if ((FIFO_Get(chan, &sw1) == 0) && (FIFO_Get(chan, &sw2) == 0)) { - /* we have status to return, do it now */ - chp = find_chanp_ptr(chan); /* find the chanp pointer for channel */ - /* get the address of the interrupt IVL table in main memory */ - chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_icba = M[chan_ivl >> 2]; /* get the interrupt context blk addr in memory */ - tempa = chp->chan_inch_addr; /* get inch status buffer address */ - M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ - /* save the status to memory */ - M[(tempa+4) >> 2] = sw2; /* save status and count in status WD 2 loc */ - /* now store the status dw address into word 5 of the ICB for the channel */ - /* post sw addr in ICB+5w & set CC2 in SW */ - M[(chan_icba + 20) >> 2] = tempa | BIT1; - INTS[i] |= INTS_REQ; /* turn on channel interrupt request */ - sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan %04x FIFO read, set irq %04x inch %06x chan_icba %06x sw1 %08x sw2 %08x\n", - chan, i, tempa, chan_icba, sw1, sw2); - } - } - } -#endif - - /* look for the highest requesting interrupt */ - /* that is enabled */ - if (((INTS[i] & INTS_ENAB) && (INTS[i] & INTS_REQ)) || - ((SPAD[i+0x80] & SINT_ENAB) && (INTS[i] & INTS_REQ))) { - /* requesting, make active and turn off request flag */ - INTS[i] &= ~INTS_REQ; /* turn off request */ - INTS[i] |= INTS_ACT; /* turn on active */ - SPAD[i+0x80] |= SINT_ACT; /* show active in SPAD too */ - /* get the address of the interrupt IVL table in main memory */ + if (irq_pend == 0) /* pending int? */ + return 0; /* no, done */ + if (CPUSTATUS & 0x80) { /* interrupts blocked? */ + irq_pend = 0; /* not pending anymore */ + return 0; /* yes, done */ + } +// sim_debug(DEBUG_DETAIL, &cpu_dev, +// "scan_chan SPAD[f9] %08x CPUSTATUS %08x\n", SPAD[0xf9], CPUSTATUS); + /* ints not blocked, so look for highest requesting interrupt */ + for (i=0; i<112; i++) { + if (SPAD[i+0x80] == 0) /* not initialize? */ + continue; /* skip this one */ + if (SPAD[i+0x80] == 0xffffffff) /* not initialize? */ + continue; /* skip this one */ + if ((INTS[i]&INTS_ACT) || (SPAD[i+0x80]&SINT_ACT)) { /* look for level active */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "scan_chan INTS ACT FIFO #%1x irq %02x SPAD %08x INTS %08x\n", + FIFO_Num(SPAD[i+0x80] & 0x7f00), i, SPAD[i+0x80], INTS[i]); +if (i == 0) +sim_debug(DEBUG_IRQ, &cpu_dev, "XY3 Zero interrupt level found\n"); + return 0; /* this level active, so stop looking */ + } + /* see if there is pending status for this channel */ + /* if there is and the level is not requesting, do it */ + /* get the device entry for the logical channel in SPAD */ + chan = (SPAD[i+0x80] & 0x7f00); /* get real channel and zero sa */ + dibp = dib_unit[chan]; /* get the device information pointer */ + if (dibp) { /* we have a device to check */ + /* check for pending status */ + if (FIFO_Num(chan)) { + chp = find_chanp_ptr(chan); /* find the chanp pointer for channel */ + tempa = chp->chan_inch_addr; /* get inch status buffer address */ chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_icba = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ - sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan INTS REQ irq %02x found chan_icba %08x INTS %08x\n", - i, chan_icba, INTS[i]); - *ilev = i; /* return interrupt level */ - irq_pend = 0; /* not pending anymore */ - return(chan_icba); /* return ICB address */ - } - -#ifdef NEW_METHOD - /* see if there is pending status for this channel */ - /* if there is and the level is not requesting, do it */ - if ((INTS[i] & INTS_ENAB) && !(INTS[i] & INTS_REQ)) { - /* get the device entry for the logical channel in SPAD */ - chan = (SPAD[i+0x80] & 0x7f00); /* get real channel and zero sa */ - dibp = dev_unit[chan]; /* get the device information pointer */ - if (dibp == 0) - continue; /* skip unconfigured channel */ - /* see if the FIFO is empty */ - if (dibp->chan_fifo_in != dibp->chan_fifo_out) { - uint32 sw1, sw2; - /* fifo is not empty, so post status and request an interrupt */ - if ((FIFO_Get(chan, &sw1) == 0) && (FIFO_Get(chan, &sw2) == 0)) { - /* we have status to return, do it now */ - chp = find_chanp_ptr(chan); /* find the chanp pointer for channel */ - /* get the address of the interrupt IVL table in main memory */ - chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_icba = M[chan_ivl >> 2]; /* get the interrupt context blk addr in memory */ - tempa = chp->chan_inch_addr; /* get inch status buffer address */ - M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ - /* save the status to memory */ - M[(tempa+4) >> 2] = sw2; /* save status and count in status WD 2 loc */ - /* now store the status dw address into word 5 of the ICB for the channel */ - /* post sw addr in ICB+5w & set CC2 in SW */ - M[(chan_icba + 20) >> 2] = tempa | BIT1; - INTS[i] |= INTS_REQ; /* turn on channel interrupt request */ - sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan %04x FIFO read, set irq %02x inch %06x chan_icba %06x sw1 %08x sw2 %08x\n", - chan, i, tempa, chan_icba, sw1, sw2); - irq_pend = 1; /* still pending int */ - break; /* quit looking */ - } - } - } + chan_icba = RMW(chan_ivl); /* get the interrupt context block addr in memory */ +#ifdef TRY032820 + INTS[i] |= INTS_REQ; /* turn on channel interrupt request */ +#else + if (INTS[i] & INTS_ENAB) + INTS[i] |= INTS_REQ; /* turn on channel interrupt request */ #endif + sim_debug(DEBUG_IRQ, &cpu_dev, + "scan_chan %04x READ FIFO #%1x irq %02x inch %06x chan_icba %06x\n", + chan, FIFO_Num(chan), i, tempa, chan_icba); + } + } + /* look for the highest requesting interrupt */ + /* that is enabled */ + if (((INTS[i] & INTS_ENAB) && (INTS[i] & INTS_REQ)) || + ((SPAD[i+0x80] & SINT_ENAB) && (INTS[i] & INTS_REQ))) { + + /* requesting, make active and turn off request flag */ + INTS[i] &= ~INTS_REQ; /* turn off request */ + INTS[i] |= INTS_ACT; /* turn on active */ + SPAD[i+0x80] |= SINT_ACT; /* show active in SPAD too */ +if (i == 0) +sim_debug(DEBUG_IRQ, &cpu_dev, "XY3 Zero interrupt level found\n"); + /* get the address of the interrupt IVL table in main memory */ + chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */ + chan_icba = 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]); + 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)); + + *ilev = i; /* return interrupt level */ + irq_pend = 0; /* not pending anymore */ + /* at this point this level can become active */ + /* this level is enabled and already requesting */ + if (dibp) { /* we have a device to check */ + chp = find_chanp_ptr(chan); /* find the chanp pointer for channel */ + tempa = chp->chan_inch_addr; /* get inch status buffer address */ + /* see if the FIFO is empty or has status to post */ + /* fifo is not empty, so post status and make interrupt active*/ + /* the channel is not busy, see if any status to post */ + if (post_csw(chp, 0)) { + sim_debug(DEBUG_IRQ, &cpu_dev, + "scan_chan %04x POST FIFO #%1x irq %02x inch %06x chan_icba %06x\n", + chan, FIFO_Num(chan), i, chp->chan_inch_addr, chan_icba); + } + } else { + sim_debug(DEBUG_IRQ, &cpu_dev, + "scan_chan %04x POST NON FIFO irq %02x chan_icba %06x\n", + chan, i, chan_icba); + } + return(chan_icba); /* return ICB address */ } } + irq_pend = 0; /* not pending anymore */ return 0; /* done */ } @@ -2022,7 +1986,7 @@ t_stat chan_set_devs() { uint32 i, j; for(i = 0; i < MAX_DEV; i++) { - dev_unit[i] = NULL; /* clear Device pointer array */ + dib_unit[i] = NULL; /* clear DIB pointer array */ } /* Build channel array */ for (i = 0; sim_devices[i] != NULL; i++) { @@ -2064,11 +2028,11 @@ t_stat chan_set_devs() { chp->ccw_cmd = 0; /* read command */ chp->chan_inch_addr = 0; /* clear address of stat dw in memory */ if ((uptr->flags & UNIT_DIS) == 0) { /* is unit marked disabled? */ - if (dev_unit[chsa] != 0) { + if (dib_unit[chsa] != 0) { printf("Channel/SubAddress %04x multiple defined, aborting\n", chsa); return SCPE_IERR; /* no, arg error */ } - dev_unit[chsa] = dibp; /* no, save the dib address */ + 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 */ @@ -2115,13 +2079,13 @@ t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { /* loop through all units for this device */ for (i = 0; i < dibp->numunits; i++) { chsa = GET_UADDR(tuptr->u3); /* get old chsa for this unit */ - dev_unit[chsa] = NULL; /* clear sa dib pointer */ - dev_unit[chsa&0x7f00] = NULL; /* clear the channel dib address */ + dib_unit[chsa] = NULL; /* clear sa dib pointer */ + dib_unit[chsa&0x7f00] = NULL; /* clear the channel dib address */ chsa = chan | (chsa & 0xff); /* merge new channel with new sa */ tuptr->u3 &= ~UNIT_ADDR_MASK; /* clear old chsa for this unit */ tuptr->u3 |= UNIT_ADDR(chsa); /* clear old chsa for this unit */ - dev_unit[chan&0x7f00] = dibp; /* set the channel dib address */ - dev_unit[chsa] = dibp; /* save the dib address for new chsa */ + dib_unit[chan&0x7f00] = dibp; /* set the channel dib address */ + dib_unit[chsa] = dibp; /* save the dib address for new chsa */ fprintf(stderr, "Set dev %04x to %04x\r\n", GET_UADDR(tuptr->u3), chsa); tuptr++; /* next unit pointer */ } diff --git a/SEL32/sel32_clk.c b/SEL32/sel32_clk.c index e9a7e67..19f96d2 100644 --- a/SEL32/sel32_clk.c +++ b/SEL32/sel32_clk.c @@ -35,6 +35,8 @@ #if NUM_DEVS_RTOM > 0 +#define UNIT_CLK UNIT_ATTABLE|UNIT_IDLE|UNIT_DISABLE + void rtc_setup (uint32 ss, uint32 level); t_stat rtc_srv (UNIT *uptr); t_stat rtc_reset (DEVICE *dptr); @@ -51,6 +53,8 @@ extern uint32 M[]; /* system memory */ int32 rtc_pie = 0; /* rtc pulse ie */ int32 rtc_tps = 60; /* rtc ticks/sec */ int32 rtc_lvl = 0x18; /* rtc interrupt level */ +time_t lastcresult = 0; /* last clock int time for rtc */ +time_t lastiresult = 0; /* last clock int time for tim */ /* Clock data structures @@ -62,6 +66,7 @@ int32 rtc_lvl = 0x18; /* rtc interrupt level */ /* clock is attached all the time */ /* 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)}; REG rtc_reg[] = { { FLDATA (PIE, rtc_pie, 0) }, @@ -106,11 +111,14 @@ t_stat rtc_srv (UNIT *uptr) if (rtc_pie) { /* set pulse intr */ time_t result = time(NULL); // fprintf(stderr, "Clock int time %08x\r\n", (uint32)result); - sim_debug(DEBUG_CMD, &rtc_dev, "RT Clock int time %08x\n", (uint32)result); + sim_debug(DEBUG_CMD, &rtc_dev, "RT Clock int time %08x diff from last %08x\n", + (uint32)result, (uint32)(result-lastcresult)); +// lastcresult = result; /* save last clock time */ if (((INTS[rtc_lvl] & INTS_ENAB) || /* make sure enabled */ (SPAD[rtc_lvl+0x80] & SINT_ENAB)) && /* in spad too */ (((INTS[rtc_lvl] & INTS_ACT) == 0) || /* and not active */ ((SPAD[rtc_lvl+0x80] & SINT_ACT) == 0))) { /* in spad too */ +//DIAGHELP INTS[rtc_lvl] |= INTS_REQ; /* request the interrupt */ INTS[rtc_lvl] |= INTS_REQ; /* request the interrupt */ irq_pend = 1; /* make sure we scan for int */ } @@ -142,12 +150,13 @@ void rtc_setup(uint32 ss, uint32 level) INTS[level] &= ~INTS_ENAB; /* make sure disabled */ SPAD[level+0x80] &= ~SINT_ENAB; /* in spad too */ // INTS[level] &= ~INTS_REQ; /* make sure request not requesting */ -// INTS[level] &= ~INTS_ACT; /* make sure request not active */ -// SPAD[level+0x80] &= ~SINT_ACT; /* in spad too */ + INTS[level] &= ~INTS_ACT; /* make sure request not active */ + SPAD[level+0x80] &= ~SINT_ACT; /* in spad too */ sim_debug(DEBUG_CMD, &rtc_dev, "RT Clock setup disable int %02x rtc_pie %01x ss %01x\n", rtc_lvl, rtc_pie, ss); } + lastcresult = time(NULL); /* save start time */ rtc_pie = ss; /* set new state */ } @@ -374,12 +383,13 @@ void itm_setup(uint32 ss, uint32 level) INTS[level] &= ~INTS_ENAB; /* make sure disabled */ SPAD[level+0x80] &= ~SINT_ENAB; /* in spad too */ // INTS[level] &= ~INTS_REQ; /* make sure request not requesting */ -// INTS[level] &= ~INTS_ACT; /* make sure request not active */ + INTS[level] &= ~INTS_ACT; /* make sure request not active */ SPAD[level+0x80] &= ~SINT_ACT; /* in spad too */ sim_debug(DEBUG_CMD, &itm_dev, "Intv Timer setup disable int %02x value %08x itm_pie %01x ss %01x\n", itm_lvl, itm_cnt, itm_pie, ss); } + lastiresult = time(NULL); /* save start time */ itm_pie = ss; /* set new state */ } diff --git a/SEL32/sel32_con.c b/SEL32/sel32_con.c index 44b5f8b..d307d4f 100644 --- a/SEL32/sel32_con.c +++ b/SEL32/sel32_con.c @@ -193,7 +193,8 @@ uint8 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 */ +//@ sim_activate(uptr, 20); /* start us off */ + sim_activate(uptr, 40); /* start us off */ return 0; /* no status change */ break; @@ -203,7 +204,8 @@ uint8 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 */ +//@ sim_activate(uptr, 20); /* start us off */ + sim_activate(uptr, 40); /* start us off */ return 0; /* no status change */ break; @@ -219,7 +221,8 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { 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 */ +//@ sim_activate(uptr, 20); /* start us off */ + sim_activate(uptr, 40); /* start us off */ return 0; break; @@ -229,7 +232,8 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uptr->CMD |= (cmd & CON_MSK); /* save command */ // uptr->u4 = 0; /* no I/O yet */ // con_data[unit].incnt = 0; /* clear any input data */ - sim_activate(uptr, 20); /* start us off */ +//@ sim_activate(uptr, 20); /* start us off */ + sim_activate(uptr, 40); /* start us off */ return 0; /* no status change */ break; @@ -238,7 +242,8 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ uptr->CMD &= LMASK; /* leave only chsa */ uptr->CMD |= (cmd & CON_MSK); /* save command */ - sim_activate(uptr, 20); /* start us off */ +//@ sim_activate(uptr, 20); /* start us off */ + sim_activate(uptr, 40); /* start us off */ return 0; /* no status change */ break; #endif @@ -278,6 +283,10 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ } +#ifdef DO_DYNAMIC_DEBUG +static uint32 last2 = 0; +#endif + /* Handle output transfers for console */ t_stat con_srvo(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->CMD); @@ -286,7 +295,7 @@ t_stat con_srvo(UNIT *uptr) { CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ uint8 ch, cp; - sim_debug(DEBUG_DETAIL, &con_dev, "con_srvo enter chsa %04x cmd = %02x\n", chsa, cmd); + sim_debug(DEBUG_CMD, &con_dev, "con_srvo enter chsa %04x cmd = %02x\n", chsa, cmd); /* if input tried from output device, error */ if ((cmd == CON_RD) || (cmd == CON_ECHO) || (cmd == 0xC0)) { /* check for output */ @@ -348,12 +357,20 @@ t_stat con_srvo(UNIT *uptr) { sim_debug(DEBUG_CMD, &con_dev, "con_srvo write %01x: putch 0x%02x %c\n", unit, 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); + } +#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 */ +//@ sim_activate(uptr, 20); /* keep going */ + sim_activate(uptr, 30); /* start us off */ } } return SCPE_OK; @@ -368,7 +385,7 @@ t_stat con_srvi(UNIT *uptr) { uint8 ch; t_stat r; - sim_debug(DEBUG_DETAIL, &con_dev, + sim_debug(DEBUG_CMD, &con_dev, "con_srvi enter chsa %04x cmd %02x ccw_count %02x\n", chsa, cmd, chp->ccw_count); /* if output tried to input device, error */ @@ -446,8 +463,14 @@ t_stat con_srvi(UNIT *uptr) { // if (uptr->u4 == con_data[unit].incnt) { /* read completed */ con_data[unit].incnt = 0; /* buffer is empty */ cmd = 0; /* no cmd either */ +#ifdef DO_DYNAMIC_DEBUG + if (chp->ccw_addr == 0x18d3) { + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); + con_dev.dctrl |= (DEBUG_CMD | DEBUG_EXP | DEBUG_DETAIL); + } +#endif sim_debug(DEBUG_CMD, &con_dev, - "con_srvi write nothing to mem unit %02x: u4 %02x ccw_count %02x\n", + "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 */ @@ -577,8 +600,10 @@ t_stat con_srvi(UNIT *uptr) { //WAS2 return sim_activate (uptr, 100); //WAS3 return sim_activate (uptr, 50); //LAST return sim_activate (uptr, 200); - return sim_activate (uptr, 40); -//TRY return sim_activate (uptr, 500); +//@ 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 */ } @@ -591,69 +616,30 @@ t_stat con_reset(DEVICE *dptr) { uint8 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 */ - uint8 ch = 0x20; /* dummy space char for outstanding input */ +// int unit = (uptr - con_unit); /* unit # 0 is read, 1 is write */ CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ -// int len = chp->ccw_count; /* command byte count */ sim_debug(DEBUG_EXP, &con_dev, "con_haltio enter chsa %04x cmd = %02x\n", chsa, cmd); -#ifdef DO_DYNAMIC_DEBUG - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); - con_dev.dctrl |= (DEBUG_CMD | DEBUG_EXP | DEBUG_DETAIL); -#endif /* terminate any input command */ - if ((uptr->CMD & CON_MSK) != 0) { /* is unit busy */ + if ((uptr->CMD & CON_MSK) != 0) { /* is unit busy */ sim_debug(DEBUG_CMD, &con_dev, "con_haltio HIO chsa %04x cmd = %02x ccw_count %02x\n", chsa, cmd, chp->ccw_count); - if (unit == 0) { - // new code 2/28/2020 - if (test_write_byte_end(chsa)) { /* see if read request complete */ - chan_write_byte(chsa, &ch); /* write fake byte to memory */ - con_data[unit].incnt = 0; /* buffer empty */ - uptr->CMD &= LMASK; /* nothing left, command complete */ -// chp->ccw_count = 0; /* zero command count */ - sim_debug(DEBUG_CMD, &con_dev, - "con_haltio HIO I/O stop chsa %04x cmd %02x ccw_count %02x\n", - chsa, cmd, chp->ccw_count); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ -// return SCPE_OK; /* not busy anymore */ - return SCPE_IOERR; - } -#ifdef NOT_NOW - else - if (chan_write_byte(chsa, &ch)) { /* write fake byte to memory */ - con_data[unit].incnt = 0; /* buffer is empty */ - sim_debug(DEBUG_CMD, &con_dev, - "con_haltio write nothing 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 */ -//WAS return SCPE_IOERR; - } -#endif - } else { - if (chp->ccw_count > 0) { - if (chan_read_byte(chsa, &ch)) { /* get byte from memory */ - uptr->CMD &= LMASK; /* nothing left, command complete */ - sim_debug(DEBUG_CMD, &con_dev, - "con_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ - // return SCPE_OK; /* not busy anymore */ - return SCPE_IOERR; - } - } - } - uptr->CMD &= LMASK; /* make non-busy */ - uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ - return SCPE_OK; /* not busy */ -//no work chan_end(chsa, SNS_CHNEND|SNS_UNITCHK); /* write terminated */ -// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* write terminated */ -// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* done bit 15 */ /* bad status */ -// return SCPE_IOERR; + // stop any I/O and post status and return error status */ + chp->chan_byte = BUFF_EMPTY; /* there is no data to read/store */ + chp->ccw_flags = 0; /* stop any chaining */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* force error */ + uptr->CMD &= LMASK; /* make non-busy */ + uptr->u4 = 0; /* no I/O yet */ + 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; } - return SCPE_OK; /* not busy */ + uptr->u4 = 0; /* no I/O yet */ + uptr->CMD &= LMASK; /* make non-busy */ + uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ + return SCPE_OK; /* not busy */ } #endif diff --git a/SEL32/sel32_cpu.c b/SEL32/sel32_cpu.c index 8d317cc..2fa3b27 100644 --- a/SEL32/sel32_cpu.c +++ b/SEL32/sel32_cpu.c @@ -211,12 +211,21 @@ uint32 TLB[2048]; /* Translated addresses for each map uint32 dummy2=0; uint32 modes; /* Operating modes, bits 0, 5, 6, 7 of PSD1 */ uint8 wait4int = 0; /* waiting for interrupt if set */ +#define USE_AIR +#ifdef USE_AIR int32 irq_auto = 0; /* auto reset interrupt processing flag */ +#else +//AIRint32 irq_auto = 0; /* auto reset interrupt processing flag */ +#endif /* define traps */ uint32 TRAPME = 0; /* trap to be executed */ uint32 attention_trap = 0; /* set when trap is requested */ +uint32 RDYQIN; /* fifo input index */ +uint32 RDYQOUT; /* fifo ooutput index */ +uint32 RDYQ[128]; /* channel ready queue */ + struct InstHistory { uint32 opsd1; /* original PSD1 */ @@ -254,11 +263,11 @@ extern t_stat haltxio(uint16 addr, uint32 *status); /* halt XIO */ extern t_stat grabxio(uint16 addr, uint32 *status); /* grab XIO n/u */ extern t_stat rsctlxio(uint16 addr, uint32 *status); /* reset controller XIO */ extern t_stat chan_set_devs(); /* set up the defined devices on the simulator */ -extern uint32 scan_chan(int *ilev); /* go scan for I/O int pending */ +extern uint32 scan_chan(uint32 *ilev); /* go scan for I/O int pending */ +extern uint32 cont_chan(uint16 chsa); /* continue channel program */ extern uint16 loading; /* set when doing IPL */ extern int fprint_inst(FILE *of, uint32 val, int32 sw); /* instruction print function */ extern int irq_pend; /* go scan for pending interrupt */ -extern int irq_auto; /* set when in auto reset interrupt */ extern void rtc_setup(uint32 ss, uint32 level); /* tell rtc to start/stop */ extern void itm_setup(uint32 ss, uint32 level); /* tell itm to start/stop */ extern int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level); /* read/write the interval timer */ @@ -340,6 +349,9 @@ REG cpu_reg[] = { {HRDATAD(ISMCW, ISMCW, 32, "V9 IPU Shadow Memory Configuration Word"), REG_FIT}, {HRDATAD(CCW, CCW, 32, "Computer Configuration Word"), REG_FIT}, {HRDATAD(CSW, CSW, 32, "Console Switches"), REG_FIT}, + {BRDATAD(RDYQ, RDYQ, 16, 32, 128, "Channel Program Completon Status"), REG_FIT}, + {HRDATAD(RDYQIN, RDYQIN, 32, "RDYQ input index"), REG_FIT}, + {HRDATAD(RDYQOUT, RDYQOUT, 32, "RDYQ output index"), REG_FIT}, {NULL} }; @@ -690,8 +702,8 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) uint32 cpix, bpix, i, j, map, osmsdl, osmidl; uint32 MAXMAP = MAX2048; /* default to 2048 maps */ - sim_debug(DEBUG_CMD, &cpu_dev, - "Load Maps Entry PSD %08x %08x STATUS %08x lmap %01x CPU Mode %2x\n", + sim_debug(DEBUG_TRAP, &cpu_dev, + "Load Maps Entry PSD %08x %08x STATUS %08x lmap %1x CPU Mode %2x\n", thepsd[0], thepsd[1], CPUSTATUS, lmap, CPU_MODEL); /* process 32/7X computers */ @@ -703,14 +715,11 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) return ALLOK; /* no, all OK, no mapping required */ /* we are mapped, so load the maps for this task into the cpu map cache */ -// cpix = (thepsd[1] >> 2) & 0xfff; /* get cpix 12 bit offset from psd wd 2 */ - cpix = (thepsd[1]) & 0x3ffc; /* get cpix 12 bit offset from psd wd 2 */ -// bpix = (thepsd[1] >> 18) & 0xfff; /* get bpix 12 bit offset from psd wd 2 */ - bpix = (thepsd[1] >> 16) & 0x3ffc; /* get bpix 12 bit offset from psd wd 2 */ + cpix = (thepsd[1]) & 0x3ff8; /* get cpix 12 bit offset from psd wd 2 */ + bpix = (thepsd[1] >> 16) & 0x3ff8; /* get bpix 12 bit offset from psd wd 2 */ num = 0; /* working map number */ /* master process list is in 0x83 of spad for 7x */ -// mpl = SPAD[0x83] >> 2; /* get mpl from spad address */ mpl = SPAD[0x83]; /* get mpl from spad address */ /* diags want the mpl entries checked to make sure valid dbl wowrd address */ @@ -732,14 +741,12 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) } /* mpl is ok, get the msdl for given cpix */ -// cpixmsdl = M[mpl + cpix]; /* get msdl from mpl for given cpix */ cpixmsdl = RMW(mpl+cpix); /* get msdl from mpl for given cpix */ /* if bit zero of mpl entry is set, use bpix first to load maps */ if (cpixmsdl & BIT0) { /* load bpix maps first */ -// bpixmsdl = M[mpl + bpix]; /* get msdl from mpl for given cpix */ bpixmsdl = RMW(mpl+bpix); /* get bpix msdl word address */ /* check for valid bpix msdl addr */ @@ -751,7 +758,6 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) } sdc = (bpixmsdl >> 24) & 0x3f; /* get 6 bit segment description count */ -// msdl = (bpixmsdl >> 2) & MASK24; /* get 24 bit real address of msdl */ msdl = bpixmsdl & MASK24; /* get 24 bit real address of msdl */ /* check for valid msdl addr */ if (!MEM_ADDR_OK(msdl & MASK24)) { /* see if in memory */ @@ -762,9 +768,7 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) /* process all of the msdl's */ for (i = 0; i < sdc; i++) { /* loop through the msd's */ -// spc = (M[msdl + i] >> 24) & 0xff; /* get segment page count from msdl */ spc = (RMW(msdl+i) >> 24) & 0xff; /* get segment page count from msdl */ -// midl = (M[msdl + i] >> 2) & MASK24; /* get 24 bit real word address of midl */ midl = RMW(msdl+i) & MASK24; /* get 24 bit real word address of midl */ /* check for valid midl addr */ @@ -796,7 +800,6 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) } sdc = (cpixmsdl >> 24) & 0x3f; /* get 6 bit segment description count */ -// msdl = (cpixmsdl >> 2) & 0x3fffff; /* get 24 bit real address of msdl */ msdl = cpixmsdl & 0xffffff; /* get 24 bit real address of msdl */ /* check for valid msdl addr */ if (!MEM_ADDR_OK(msdl & MASK24)) { /* see if in memory */ @@ -807,9 +810,7 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) /* process all of the msdl's */ for (i = 0; i < sdc; i++) { -// spc = (M[msdl + i] >> 24) & 0xff; /* get segment page count from msdl */ spc = (RMW(msdl+i) >> 24) & 0xff; /* get segment page count from msdl */ -// midl = (M[msdl + i] >> 2) & 0x3fffff; /* get 24 bit real word address of midl */ midl = RMW(msdl+i) & MASK24; /* get 24 bit real word address of midl */ /* check for valid midl addr */ @@ -822,7 +823,8 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) for (j = 0; j < spc; j++, num++) { /* loop through the midl's */ uint32 pad = RMW(midl+(j<<1)); /* get page descriptor address */ if (num >= MAXMAP) { - TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ +// TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ +/*96V9*/ TRAPSTATUS |= (BIT16|BIT9); /* set bit 5 of trap status */ return MAPFLT; /* map loading overflow, map fault error */ } /* load 16 bit map descriptors */ @@ -832,7 +834,8 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) } /* if none loaded, map fault */ if (num == 0) { - TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ +// TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ +/*96V9*/ TRAPSTATUS |= (BIT16|BIT9); /* set bit 5 of trap status */ return MAPFLT; /* attempt to load 0 maps, map fault error */ } /* clear the rest of the previously used maps */ @@ -882,7 +885,7 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) /* check if valid real address */ mpl &= MASK24; /* clean mpl address */ - if (!MEM_ADDR_OK(mpl)) { /* see if in our real memory */ + if (!MEM_ADDR_OK(mpl)) { /* see if in our real memory */ sim_debug(DEBUG_TRAP, &cpu_dev, "load_maps MEM SIZE1 %06x mpl %06x invalid\n", MEMSIZE, mpl); npmem: @@ -942,7 +945,8 @@ nomaps: CPIX = cpix; /* save CPIX */ HIWM = 0; /* reset high water mark */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT5; /* set bit 5 of trap status */ +// TRAPSTATUS |= BIT5; /* set bit 5 of trap status */ + TRAPSTATUS |= (BIT5|BIT9); /* set bit 5 of trap status */ else TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ return MAPFLT; /* map loading overflow, map fault error */ @@ -986,11 +990,13 @@ nomaps: } else { TLB[num] = 0; /* clear the TLB for non valid maps */ } +#ifdef FOR_DEBUG if ((num < 0x20) || (num > (spc - 0x10))) - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_TRAP, &cpu_dev, "OS pad %06x=%04x map #%4x, %04x, map2 %08x, TLB %08x MAPC %08x\n", pad, map, num, map, (((map << 16) & 0xf8000000) | ((map & 0x7ff) << 13)), TLB[num], MAPC[num/2]); +#endif } BPIX = num; /* save the # maps loaded in O/S */ CPIXPL = 0; /* no user pages */ @@ -1090,7 +1096,8 @@ loaduser: CPIX = cpix; /* save CPIX */ HIWM = 0; /* reset high water mark */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT5; /* set bit 5 of trap status */ +// TRAPSTATUS |= BIT5; /* set bit 5 of trap status */ + TRAPSTATUS |= (BIT5|BIT9); /* set bit 5 of trap status */ else TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ return MAPFLT; /* map overflow fault error */ @@ -1116,6 +1123,7 @@ loaduser: sim_debug(DEBUG_TRAP, &cpu_dev, "load_maps User page count overflow %04x, map fault\n", num); TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ +/*97&V6*/ TRAPSTATUS |= (BIT5|BIT9); /* set bit 5 of trap status */ goto nomaps; /* map overflow, map fault trap */ } if (!MEM_ADDR_OK(pad)) { /* see if address is within our memory */ @@ -1184,7 +1192,8 @@ loaduser: sim_debug(DEBUG_TRAP, &cpu_dev, "load_maps User page count overflow %04x, map fault\n", num); if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT5; /* set bit 5 of trap status */ +// TRAPSTATUS |= BIT5; /* set bit 5 of trap status */ + TRAPSTATUS |= (BIT5|BIT9); /* set bit 5 of trap status */ else TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ goto nomaps; /* map overflow, map fault trap */ @@ -1334,7 +1343,8 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) else if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { // V9 & 32/97 wants MACHINECHK for test 37/1 in CN.MMM & VM.MMM */ - TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ +// TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ +/*97&V6*/ TRAPSTATUS |= (BIT7|BIT9); /* set bit 7 of trap status */ TRAPSTATUS |= BIT28; /* set bit 28 of trap status */ return MACHINECHK_TRAP; /* diags want machine check error */ } @@ -1351,7 +1361,8 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) "RealAddr %06x word %06x loadmap gets mapfault index %04x B(%x)+C(%x) %04x\n", word, addr, index, BPIX, CPIXPL, BPIX+CPIXPL); if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT5; /* set bit 5 of trap status */ +// TRAPSTATUS |= BIT5; /* set bit 5 of trap status */ + TRAPSTATUS |= (BIT5|BIT9); /* set bit 5 of trap status */ else TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ return MAPFLT; /* map fault error */ @@ -1422,7 +1433,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) "RealAddr loadmap 2a non present memory fault addr %08x raddr %08x index %04x\n", addr, raddr, index); if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { -#ifndef TRY_AGAIN +#ifndef TRY_AGAIN_97V6 if (access == MEM_RD) TRAPSTATUS |= BIT1; /* set bit 1 of trap status */ else @@ -1431,7 +1442,8 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) /* returning this error fixes 34/2, but still fails 46/2 */ return NPMEM; /* none present memory error */ #else - TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ +// TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ +/*97&V6*/ TRAPSTATUS |= (BIT7|BIT9); /* set bit 7 of trap status */ TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ /* returning this error fails test 34/2 of mmm diag */ return MAPFLT; /* map fault error on memory access */ @@ -1499,19 +1511,9 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) if (CPU_MODEL == MODEL_97) { // 32/97 wants MAPFLT for test 37/1 in CN.MMM TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ +/*97&V6*/ TRAPSTATUS |= (BIT7|BIT9); /* set bit 7 of trap status */ +/* 97V9*/ TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ return MAPFLT; /* no, map fault error */ -/*TRY*/// return NPMEM; /* no, none present memory error */ -/*TRY*/// return MACHINECHK_TRAP; /* diags want machine check error */ -/*TRY*/// return SYSTEMCHK_TRAP; /* diags want machine check error */ -/*TRY*/// return PRIVVIOL_TRAP; /* set the trap to take */ -// if (access == MEM_RD) -// TRAPSTATUS |= BIT1; /* set bit 1 of trap status */ -// else -// if (access == MEM_WR) -// TRAPSTATUS |= BIT2; /* set bit 2 of trap status */ -// return MAPFLT; /* no, map fault error */ -// return MACHINECHK_TRAP; /* diags want machine check error */ -// return NPMEM; /* no, none present memory error */ } else if (CPU_MODEL == MODEL_V6) { // V6 wants MAPFLT for test 37/1 in CN.MMM & VM.MMM */ @@ -1524,20 +1526,9 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) /* V9 wants MAPFLT for test 37/1 in CN.MMM & VM.MMM */ /* V9 fails test 46/subtest 2 with "did not get expected map trap */ TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ +/*97&V6*/ TRAPSTATUS |= (BIT7|BIT9); /* set bit 7 of trap status */ +/* 97V9*/ TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ return MAPFLT; /* map fault error */ -// if (access == MEM_RD) -// TRAPSTATUS |= BIT1; /* set bit 1 of trap status */ -// else -// if (access == MEM_WR) -// TRAPSTATUS |= BIT2; /* set bit 2 of trap status */ -// return MAPFLT; /* map fault error */ -// if (access == MEM_RD) -// TRAPSTATUS |= 0x40000000; /* set bit 0 of trap status */ -// else -// if (access == MEM_WR) -// TRAPSTATUS |= 0x20000000; /* set bit 1 of trap status */ -// return NPMEM; /* no, none present memory error */ -// return MACHINECHK_TRAP; /* diags want machine check error */ } } @@ -1718,9 +1709,6 @@ t_stat Mem_read(uint32 addr, uint32 *data) uint32 status, realaddr, prot, page, map, mix, nix, msdl, mpl, nmap; status = RealAddr(addr, &realaddr, &prot, MEM_RD); /* convert address to real physical address */ -// if (addr != realaddr) -//sim_debug(DEBUG_EXP, &cpu_dev, -//"At Mem_read convert %06x to addr %08x\n", addr, realaddr); if (status == ALLOK) { // *data = M[realaddr >> 2]; /* valid address, get physical address contents */ @@ -1786,7 +1774,8 @@ t_stat Mem_read(uint32 addr, uint32 *data) } if (status == MAPFLT) { if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ +// TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ +/*97V9*/ TRAPSTATUS |= (BIT12|BIT16); /* set bit 12 of trap status */ else TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ } @@ -1894,7 +1883,8 @@ t_stat Mem_write(uint32 addr, uint32 *data) } if (status == MAPFLT) { if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ +// TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ +/*97V9*/ TRAPSTATUS |= (BIT12|BIT16); /* set bit 12 of trap status */ else TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ } @@ -1996,69 +1986,106 @@ wait_loop: } if (skipinstr) { /* need to skip interrupt test? */ -#ifdef NOTNOW +#ifndef NOTNOW sim_debug(DEBUG_IRQ, &cpu_dev, - "Skipinstr set to zero PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - PSD1, PSD2, CPUSTATUS); + "Skipinstr %1x zeroed after skip PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + skipinstr, PSD1, PSD2, CPUSTATUS); #endif skipinstr = 0; /* skip only once */ goto skipi; /* skip int test */ } + + /* process any channel programs */ + if (RDYQ_Num()) { + uint32 chsa; /* channel/sub adddress */ + int32 stat; /* return status 0/1 from loadccw */ + + /* we have entries, continue channel program */ + if (RDYQ_Get(&chsa) == SCPE_OK) { /* get chsa for program */ + sim_debug(DEBUG_IRQ, &cpu_dev, + "CPU RDYQ entry for chsa %04x starting\n", chsa); + stat = cont_chan(chsa); /* resume the channel program */ + if (stat) + sim_debug(DEBUG_IRQ, &cpu_dev, + "CPU RDYQ entry for chsa %04x processed\n", chsa); + } + } /* process pending I/O interrupts */ -// if (!loading && (wait4int || irq_pend)) { /* see if ints are pending */ -/*AIR*/ if (!loading && !irq_auto && (wait4int || irq_pend)) { /* see if ints are pending */ - int ilev; +#ifdef USE_AIR +/*AIR*/ if (!loading && (irq_auto==0) && (wait4int || irq_pend)) { /* see if ints are pending */ +#else + if (!loading && (wait4int || irq_pend)) { /* see if ints are pending */ +#endif + uint32 ilev; +//DIAGINT SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ + SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ int_icb = scan_chan(&ilev); /* no, go scan for I/O int pending */ if (int_icb != 0) { /* was ICB returned for an I/O or interrupt */ - int il = ilev; /* get the interrupt level */ + uint32 il = ilev; /* get the interrupt level */ sim_debug(DEBUG_IRQ, &cpu_dev, - "<>Normal int return icb %06x level %02x irq_pend %01x wait4int %01x\n", + "<|>Normal int return icb %06x level %02x irq_pend %1x wait4int %1x\n", int_icb, il, irq_pend, wait4int); +#ifdef DO_DYNAMIC_DEBUG + /* start debugging on first clock tick */ + if (il == 0x18) + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_TRAP | DEBUG_EXP | DEBUG_IRQ); +#endif /* take interrupt, store the PSD, fetch new PSD */ - bc = PSD2 & 0x3ffc; /* get copy of cpix */ + bc = PSD2 & 0x3ff8; /* get copy of cpix */ M[int_icb>>2] = PSD1&0xfffffffe; /* store PSD 1 */ M[(int_icb>>2)+1] = PSD2; /* store PSD 2 */ PSD1 = M[(int_icb>>2)+2]; /* get new PSD 1 */ - PSD2 = (M[(int_icb>>2)+3] & ~0x3ffc) | bc; /* get new PSD 2 w/old cpix */ + PSD2 = (M[(int_icb>>2)+3] & ~0x3ff8) | bc; /* get new PSD 2 w/old cpix */ /* I/O status DW address will be in WD 6 */ /* set new map mode and interrupt blocking state in CPUSTATUS */ + CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */ CPUSTATUS |= modes; /* now insert into CPUSTATUS */ if (PSD2 & MAPBIT) { - CPUSTATUS |= BIT8; /* set bit 8 of cpu status */ + CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ modes |= MAPMODE; /* set mapped mode */ } else CPUSTATUS &= 0xff7fffff; /* reset bit 8 of cpu status */ - if ((PSD2 & 0x8000) == 0) { /* is it retain blocking state */ - if (PSD2 & 0x4000) { /* no, is it set blocking state */ + + if ((PSD2 & 0x8000) == 0) { /* is it retain blocking state, bit 48 set */ + /* retain blocking state is off, use bit 49 to set new state */ + if (PSD2 & 0x4000) { /* no, is it set blocking state bit 49 set*/ + /* new blocking state is blocked when bits 48=0 & bit 49=1 */ CPUSTATUS |= 0x80; /* yes, set blk state in cpu status bit 24 */ /* This test fixed the hangs on terminal input for diags & UTX! */ -#ifdef ALLOW_RTC -/*TRY*/ t = SPAD[il+0x80]; /* get spad entry for interrupt */ -#endif - /* Class F I/O spec says to reset interrupt active if user's */ + t = SPAD[il+0x80]; /* get spad entry for interrupt */ + /* Class F I/O spec says to reset active interrupt if user's */ /* interrupt service routine runs with interrupts blocked */ -#ifdef ALLOW_RTC -/*TRY*/ if ((t & 0x0f000000) == 0x0f000000) { /* if class F clear interrupt */ -#endif + if (((t & 0x0f800000) == 0x0f000000) || /* if class F clear interrupt */ +//HANGS DEXP if (((t & 0x0f000000) == 0x0f000000) || /* if class F clear interrupt */ +//DIAGS ((t & 0x0f807fff) == 0x00807f06) || /* RT Clock */ +/*NEW*/ ((t & 0x0000ffff) == 0x00007f06) || /* RT Clock */ +//DIAGS ((t & 0x0f807fff) == 0x03007f04)) { /* Interval timer */ +/*NEW*/ ((t & 0x0f00ffff) == 0x03007f04)) { /* Interval timer */ /* if this is F class I/O interrupt, clear the active level */ /* SPAD entries for interrupts begin at 0x80 */ +#ifdef USE_AIR +/*AIR*/ irq_auto = il; /* show processing in blocked mode */ +#else +//LESS irq_pend = 1; /* scan for interrupts again */ INTS[il] &= ~INTS_ACT; /* deactivate specified int level */ SPAD[il+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ -//AIR irq_pend = 1; /* scan for interrupts again */ -/*AIR*/ irq_auto = 1; /* show processing in blocked mode */ - sim_debug(DEBUG_IRQ, &cpu_dev, - "<>Auto-reset interrupt INTS[%02x] %08x SPAD[%03x] %08x\n", - il, INTS[il], il+0x80, SPAD[il+0x80]); -#ifdef ALLOW_RT -/*TRY*/ } +if (il == 0) +sim_debug(DEBUG_IRQ, &cpu_dev, "XX1 Zero interrupt level found\n"); #endif - } - else + sim_debug(DEBUG_IRQ, &cpu_dev, + "<|>Auto-reset interrupt INTS[%02x] %08x SPAD[%02x] %08x\n", + il, INTS[il], il+0x80, SPAD[il+0x80]); +/*TRY*/ } + } else { + sim_debug(DEBUG_IRQ, &cpu_dev, + "<|>RUN ACTIVE interrupt INTS[%02x] %08x SPAD[%02x] %08x\n", + il, INTS[il], il+0x80, SPAD[il+0x80]); CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ + } } PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ if (CPUSTATUS & 0x80) /* see if old mode is blocked */ @@ -2067,25 +2094,24 @@ wait_loop: SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ sim_debug(DEBUG_IRQ, &cpu_dev, - "<>Int %03x OPSD1 %08x OPSD2 %08x NPSD1 %08x NPSD2 %08x\n", + "<|>Int %02x OPSD1 %08x OPSD2 %08x NPSD1 %08x NPSD2 %08x\n", il, RMW(int_icb), RMW(int_icb+4), PSD1, PSD2); bc = RMW(int_icb+20) & 0xffffff; if (RMW(int_icb+16) == 0) sim_debug(DEBUG_IRQ, &cpu_dev, - "<>Int2 %03x ICBA %06x IOCLA %06x\n", - il, int_icb, RMW(int_icb+16)); + "<|>Int2 %02x ICBA %06x\n", il, int_icb); else sim_debug(DEBUG_IRQ, &cpu_dev, - "<>Int2 %03x ICBA %06x IOCLA %06x STAT %08x SW1 %08x SW2 %08x\n", + "<|>Int2 %02x ICBA %06x IOCLA %06x STAT %08x SW1 %08x SW2 %08x\n", il, int_icb, RMW(int_icb+16), RMW(int_icb+20), RMW(bc), RMW(bc+4)); wait4int = 0; /* wait is over for int */ -//AIR irq_pend = 1; /* scan for interrupts again */ - skipinstr = 1; /* skip next inter test after this instr */ -#ifdef NOTNOW +//LESS irq_pend = 1; /* scan for interrupts again */ +#ifndef NOTNOW sim_debug(DEBUG_IRQ, &cpu_dev, - "Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - PSD1, PSD2, CPUSTATUS); + "<|> Skipinstr %1x set intr %02x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + skipinstr, il, PSD1, PSD2, CPUSTATUS); #endif + skipinstr = 1; /* skip next inter test after this instr */ goto skipi; /* skip int test */ } /* see if waiting at a wait instruction */ @@ -2096,7 +2122,7 @@ wait_loop: } } else { if (loading) { - int il; + uint32 il; uint32 chsa = scan_chan(&il); /* go scan for load complete pending */ if (chsa != 0) { /* see if a boot channel/subaddress were returned */ /* take interrupt, store the PSD, fetch new PSD */ @@ -2112,12 +2138,12 @@ wait_loop: SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ loading = 0; /* we are done loading */ - skipinstr = 1; /* skip next interrupt test only once */ -#ifdef NOTNOW +#ifndef NOTNOW sim_debug(DEBUG_IRQ, &cpu_dev, - "Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - PSD1, PSD2, CPUSTATUS); + "Load Skipinstr %1x set loading PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + skipinstr, PSD1, PSD2, CPUSTATUS); #endif + skipinstr = 1; /* skip next interrupt test only once */ } goto wait_loop; /* continue waiting */ } @@ -2135,12 +2161,12 @@ wait_loop: TRAPME = attention_trap; /* get trap number */ attention_trap = 0; /* clear flag */ sim_debug(DEBUG_XIO, &cpu_dev, "Attention TRAP %04x\n", TRAPME); - skipinstr = 1; /* skip next interrupt test only once */ -#ifdef NOTNOW +#ifndef NOTNOW sim_debug(DEBUG_IRQ, &cpu_dev, - "Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - PSD1, PSD2, CPUSTATUS); + "Skipinstr %1x set @ attn int PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + skipinstr, PSD1, PSD2, CPUSTATUS); #endif + skipinstr = 1; /* skip next interrupt test only once */ goto newpsd; /* got process trap */ } @@ -2152,7 +2178,7 @@ skipi: /* fill IR from logical memory address */ if ((TRAPME = read_instruction(PSD, &IR))) { sim_debug(DEBUG_TRAP, &cpu_dev, - "read_instr TRAPME %04x PSD %08x %08x i_flags %04x drop_nop %01x\n", + "read_instr TRAPME %04x PSD %08x %08x i_flags %04x drop_nop %1x\n", TRAPME, PSD1, PSD2, i_flags, drop_nop); if ((CPU_MODEL <= MODEL_27) || (CPU_MODEL == MODEL_67) || (CPU_MODEL == MODEL_87) || (CPU_MODEL == MODEL_97)) { @@ -2174,7 +2200,7 @@ skipi: } } sim_debug(DEBUG_TRAP, &cpu_dev, - "read_instr2 TRAPME %04x PSD %08x %08x i_flags %04x drop_nop %01x\n", + "read_instr2 TRAPME %04x PSD %08x %08x i_flags %04x drop_nop %1x\n", TRAPME, PSD1, PSD2, i_flags, drop_nop); goto newpsd; /* got process trap */ } @@ -2184,7 +2210,13 @@ skipi: IR <<= 16; /* put instruction in left hw */ if ((CPU_MODEL <= MODEL_27) || (CPU_MODEL == MODEL_87) || (CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { - skipinstr = 0; /* only test this once */ +//WAS032120 skipinstr = 0; /* only test this once */ +#ifndef NOTNOW + if (skipinstr) + sim_debug(DEBUG_IRQ, &cpu_dev, + "1Rt HW instruction skipinstr %1x is set PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + skipinstr, PSD1, PSD2, CPUSTATUS); +#endif drop_nop = 0; /* not dropping nop for these machines */ goto exec; /* machine does not drop nop instructions */ } @@ -2192,10 +2224,18 @@ skipi: if (IR == 0x00020000) { /* is this a NOP from rt hw? */ PSD1 = (PSD1 + 2) | (((PSD1 & 2) >> 1) & 1); /* skip this instruction */ // fprintf(stderr, "RIGHT HW skip NOP instr %x skip nop at %x\n", IR, PSD1); - skipinstr = 0; /* only test this once */ +//WAS032120 skipinstr = 0; /* only test this once */ + if (skipinstr) + sim_debug(DEBUG_IRQ, &cpu_dev, + "2Rt HW instruction skipinstr %1x is set PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + skipinstr, PSD1, PSD2, CPUSTATUS); goto skipi; /* go read next instruction */ } - skipinstr = 0; /* only test this once */ +//WAS032120 skipinstr = 0; /* only test this once */ + if (skipinstr) + sim_debug(DEBUG_IRQ, &cpu_dev, + "3Rt HW instruction skipinstr %1x is set PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + skipinstr, PSD1, PSD2, CPUSTATUS); } else { /* we have a left hw or fullword instruction */ /* see if we can drop a rt hw nop instruction */ @@ -2256,7 +2296,7 @@ exec: /* changed for diags 052719*/ modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ CPUSTATUS &= ~0x87000000; /* reset those bits in CPUSTATUS */ - CPUSTATUS |= modes; /* not insert them into CPUSTATUS */ + CPUSTATUS |= modes; /* now insert them into CPUSTATUS */ if (PSD2 & MAPBIT) modes |= MAPMODE; /* set mapped mode */ @@ -2272,6 +2312,8 @@ 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, + "ADDRSPEC1 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } break; @@ -2282,6 +2324,8 @@ 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, + "ADDRSPEC2 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } ix = (IR >> 16) & 7; /* get base reg from instruction */ @@ -2316,21 +2360,21 @@ exec: i_flags &= ~BT; /* do not update pc if MF or NPM */ i_flags |= HLF; /* assume half word instr */ } - if ((CPU_MODEL <= MODEL_27)) + if ((CPU_MODEL <= MODEL_27)) { /* 77, 27 rolls to zero, not 80000 */ PSD1 &= 0xff07ffff; /* remove overflow bits */ - else + } else { PSD1 &= 0xff0fffff; /* leave overflow bit for trap addr */ + } sim_debug(DEBUG_TRAP, &cpu_dev, - "PC over 80000 Base OP %04x i_flags %04x addr %08x PSD %08x %08x\n", - OP, i_flags, addr, PSD1, PSD2); + "PC over 80000 PC %08x Base OP %02x i_flags %04x addr %06x PSD %08x %08x\n", + PC, OP, i_flags, addr, PSD1, PSD2); if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ else TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ goto newpsd; /* handle trap */ } - sim_debug(DEBUG_DETAIL, &cpu_dev, "Non Based i_flags %04x addr %08x\n", i_flags, addr); /* non base mode instructions have bit 0 of the instruction set */ /* for word length instructions and zero for halfword instructions */ @@ -2351,6 +2395,8 @@ 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, + "ADDRSPEC3 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } break; @@ -2451,6 +2497,9 @@ exec: case 2: /* double word address */ if ((addr & 7) != 2) { /* must be double word adddress */ TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + sim_debug(DEBUG_TRAP, &cpu_dev, + "ADDRSPEC4 case RM wd 1/3 Mem_read DW status %02x @ %08x src %08x\n", + TRAPME, addr, (uint32)source); goto newpsd; /* go execute the trap now */ } if ((TRAPME = Mem_read(addr+4, &temp))) { /* get the 2nd word from memory */ @@ -2491,6 +2540,8 @@ 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, + "ADDRSPEC5 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } if ((TRAPME = Mem_read(addr+4, &temp))) { /* get the 2nd word from memory */ @@ -2518,6 +2569,8 @@ 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, + "ADDRSPEC6 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } /* merge the regs into the 64bit value */ @@ -2539,6 +2592,8 @@ exec: if (dbl) { if (sreg & 1) { TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + sim_debug(DEBUG_EXP, &cpu_dev, + "ADDRSPEC7 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } /* merge the regs into the 64bit value */ @@ -2690,11 +2745,6 @@ exec: PSD2 |= 0x00004000; /* set bit 49 only */ SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ -#ifdef NOTNOW - sim_debug(DEBUG_IRQ, &cpu_dev, - "BEI skipinstr %x irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - skipinstr, irq_pend, PSD1, PSD2, CPUSTATUS); -#endif break; case 0x7: /* UEI */ if ((modes & PRIVBIT) == 0) { /* must be privileged to UEI */ @@ -2705,15 +2755,22 @@ exec: TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ goto newpsd; /* Privlege violation trap */ } -#ifdef AIR - if (CPUSTATUS & 0x80) /* see if old mode is blocked */ - irq_pend = 1; /* start scanning interrupts again */ -#else -/*AIR*/ if (CPUSTATUS & 0x80) { /* see if old mode is blocked */ + if (CPUSTATUS & 0x80) { /* see if old mode is blocked */ irq_pend = 1; /* start scanning interrupts again */ +#ifdef USE_AIR + if (irq_auto ) { +/*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ +/*AIR*/ SPAD[irq_auto+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ + } +//if (irq_auto == 0) +//sim_debug(DEBUG_IRQ, &cpu_dev, "XX3 Zero interrupt level found\n"); + if (irq_auto) + sim_debug(DEBUG_IRQ, &cpu_dev, + "<|>IntX deactivate level %02x at UEI PSD1 %08x PSD2 %08x\n", + irq_auto, PSD1, PSD2); /*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ -/*AIR*/ } #endif + } CPUSTATUS &= ~0x80; /* into status word bit 24 too */ PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ SPAD[0xf5] = PSD2; /* save the current PSD2 */ @@ -2731,8 +2788,8 @@ exec: break; case 0x9: /* RDSTS */ GPR[reg] = CPUSTATUS; /* get CPU status word */ -//sim_debug(DEBUG_CMD, &cpu_dev, -//"RDSTS CPUSTATUS %08x SPAD[0xf9] %08x\n", CPUSTATUS, SPAD[0xf9]); +sim_debug(DEBUG_CMD, &cpu_dev, +"RDSTS CPUSTATUS %08x SPAD[0xf9] %08x\n", CPUSTATUS, SPAD[0xf9]); #ifdef DO_DYNAMIC_DEBUG /* start debugging */ cpu_dev.dctrl |= (DEBUG_INST | DEBUG_TRAP | DEBUG_EXP | DEBUG_IRQ); @@ -2824,15 +2881,15 @@ exec: sim_debug(DEBUG_EXP, &cpu_dev, "CMC V6/67 GPR[%02x] = %04x CMCR = %08x CPU STATUS SPAD[f9] = %08x\r\n", reg, GPR[reg], CMCR, SPAD[0xf9]); - CMCR = GPR[reg]; /* write reg bits 23-31 to cache memory controller */ - i_flags &= ~SD; /* turn off store dest for this instruction */ + CMCR = GPR[reg]; /* write reg bits 23-31 to cache memory controller */ + i_flags &= ~SD; /* turn off store dest for this instruction */ } else if (CPU_MODEL == MODEL_V9) { sim_debug(DEBUG_EXP, &cpu_dev, "CMC V9 GPR[%02x] = %08x CMCR = %08x CPU STATUS SPAD[f9] = %08x\r\n", reg, GPR[reg], CMCR, SPAD[0xf9]); - CMCR = GPR[reg]; /* write reg bits 23-31 to cache memory controller */ - i_flags &= ~SD; /* turn off store dest for this instruction */ + CMCR = GPR[reg]; /* write reg bits 23-31 to cache memory controller */ + i_flags &= ~SD; /* turn off store dest for this instruction */ } break; @@ -3165,48 +3222,48 @@ sbr: /* handle basemode too */ break; case 0x1C>>2: /* 0x1C HLF - HLF */ /* ZBR (basemode SRA, SRL, SLA, SLL) */ - if (modes & BASEBIT) { /* handle basemode SRA, SRL, SLA, SLL */ - bc = opr & 0x1f; /* get bit shift count */ - if ((opr & 0x60) == 0x00) { /* SRA instruction */ - temp = GPR[reg]; /* get reg value to shift */ - t = temp & FSIGN; /* sign value */ + if (modes & BASEBIT) { /* handle basemode SRA, SRL, SLA, SLL */ + bc = opr & 0x1f; /* get bit shift count */ + if ((opr & 0x60) == 0x00) { /* SRA instruction */ + temp = GPR[reg]; /* get reg value to shift */ + t = temp & FSIGN; /* sign value */ for (ix=0; ix>= 1; /* shift bit 0 right one bit */ - temp |= t; /* restore original sign bit */ + temp >>= 1; /* shift bit 0 right one bit */ + temp |= t; /* restore original sign bit */ } - GPR[reg] = temp; /* save the new value */ + GPR[reg] = temp; /* save the new value */ break; } - if ((opr & 0x60) == 0x20) { /* SRL instruction */ - GPR[reg] >>= bc; /* value to be output */ + if ((opr & 0x60) == 0x20) { /* SRL instruction */ + GPR[reg] >>= bc; /* value to be output */ break; } - if ((opr & 0x60) == 0x40) { /* SLA instruction */ - temp = GPR[reg]; /* get reg value to shift */ - t = temp & FSIGN; /* sign value */ - ovr = 0; /* set ovr off */ + if ((opr & 0x60) == 0x40) { /* SLA instruction */ + temp = GPR[reg]; /* get reg value to shift */ + t = temp & FSIGN; /* sign value */ + ovr = 0; /* set ovr off */ for (ix=0; ix> bc; /* make a bit mask of bit number */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - if (GPR[sreg] & bc) /* test the bit in src reg */ - t |= CC1BIT; /* set CC1 to the bit value */ - GPR[sreg] &= ~bc; /* reset the bit in src reg */ - PSD1 |= t; /* update the CC's in the PSD */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + if (GPR[sreg] & bc) /* test the bit in src reg */ + t |= CC1BIT; /* set CC1 to the bit value */ + GPR[sreg] &= ~bc; /* reset the bit in src reg */ + PSD1 |= t; /* update the CC's in the PSD */ } break; @@ -3389,35 +3446,35 @@ tbr: /* handle basemode TBR too * GPR[reg] = temp; /* put dest reg value into src reg */ break; - case 0x5: /* TRCC */ /* Transfer GPR bits 28-31 to condition codes */ + case 0x5: /* TRCC */ /* Transfer GPR bits 28-31 to condition codes */ if ((modes & BASEBIT) == 0) /* see if nonbased */ goto inv; /* invalid instruction in nonbased mode */ PSD1 = ((PSD1 & 0x87fffffe) | ((GPR[reg] & 0xf) << 27)); /* insert CCs from reg */ break; - case 0x8: /* BSUB */ /* Procedure call */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ + case 0x8: /* BSUB */ /* Procedure call */ + if ((modes & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ /* if Rd field is 0 (reg is b6-b8), this is a BSUB instruction */ /* otherwise it is a CALL instruction (Rd != 0) */ if (reg == 0) { /* BSUB instruction */ - uint32 cfp = BR[2]; /* get dword bounded frame pointer from BR2 */ + uint32 cfp = BR[2]; /* get dword bounded frame pointer from BR2 */ if ((BR[2] & 0x7) != 0) { /* Fault, must be dw bounded address */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ } - cfp = BR[2] & 0x00fffff8; /* clean the cfp address to 24 bit dw */ + cfp = BR[2] & 0x00fffff8; /* clean the cfp address to 24 bit dw */ M[cfp>>2] = (PSD1 + 2) & 0x01fffffe; /* save AEXP bit and PC into frame */ - M[(cfp>>2)+1] = 0x80000000; /* show frame created by BSUB instr */ - BR[1] = BR[sreg] & MASK24; /* Rs reg to BR 1 */ + M[(cfp>>2)+1] = 0x80000000; /* show frame created by BSUB instr */ + BR[1] = BR[sreg] & MASK24; /* Rs reg to BR 1 */ PSD1 = (PSD1 & 0xff000000) | (BR[1] & MASK24); /* New PSD address */ - BR[3] = GPR[0]; /* GPR 0 to BR 3 (AP) */ - BR[0] = cfp; /* set frame pointer from BR 2 into BR 0 */ - i_flags |= BT; /* we changed the PC, so no PC update */ + BR[3] = GPR[0]; /* GPR 0 to BR 3 (AP) */ + BR[0] = cfp; /* set frame pointer from BR 2 into BR 0 */ + i_flags |= BT; /* we changed the PC, so no PC update */ } else { @@ -3427,71 +3484,71 @@ tbr: /* handle basemode TBR too * /* if cfp and cfp+15w are in different maps, then addr exception error */ if ((cfp & 0xffe000) != ((cfp+0x3f) & 0xffe000)) { - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ } temp = (PSD1+2) & 0x01fffffe; /* save AEXP bit and PC from PSD1 in to frame */ if ((TRAPME = Mem_write(cfp, &temp))) { /* Save the PSD into memory */ - goto newpsd; /* memory write error or map fault */ + goto newpsd; /* memory write error or map fault */ } temp = 0x00000000; /* show frame created by CALL instr */ if ((TRAPME = Mem_write(cfp+4, &temp))) { /* Save zero into memory */ - goto newpsd; /* memory write error or map fault */ + goto newpsd; /* memory write error or map fault */ } /* Save BR 0-7 to stack */ for (ix=0; ix<8; ix++) { if ((TRAPME = Mem_write(cfp+(4*ix)+8, &BR[ix]))) { /* Save into memory */ - goto newpsd; /* memory write error or map fault */ + goto newpsd; /* memory write error or map fault */ } } /* save GPR 2-8 to stack */ for (ix=2; ix<8; ix++) { if ((TRAPME = Mem_write(cfp+(4*ix)+32, &GPR[ix]))) { /* Save into memory */ - goto newpsd; /* memory write error or map fault */ + goto newpsd; /* memory write error or map fault */ } } /* keep bits 0-7 from old PSD */ PSD1 = (PSD1 & 0xff000000) | ((BR[sreg]) & MASK24); /* New PSD address */ - BR[1] = BR[sreg]; /* Rs reg to BR 1 */ - BR[3] = GPR[reg]; /* Rd to BR 3 (AP) */ - BR[0] = cfp; /* set current frame pointer into BR[0] */ - BR[2] = cfp; /* set current frame pointer into BR[2] */ - i_flags |= BT; /* we changed the PC, so no PC update */ + BR[1] = BR[sreg]; /* Rs reg to BR 1 */ + BR[3] = GPR[reg]; /* Rd to BR 3 (AP) */ + BR[0] = cfp; /* set current frame pointer into BR[0] */ + BR[2] = cfp; /* set current frame pointer into BR[2] */ + i_flags |= BT; /* we changed the PC, so no PC update */ } break; case 0xC: /* TPCBR */ /* Transfer program Counter to Base Register */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - BR[reg] = PSD1 & 0xfffffe; /* save PC from PSD1 into BR */ + if ((modes & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + BR[reg] = PSD1 & 0xfffffe; /* save PC from PSD1 into BR */ break; case 0xE: /* RETURN */ /* procedure return for basemode calls */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - t = BR[0]; /* get frame pointer from BR[0] */ + if ((modes & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + t = BR[0]; /* get frame pointer from BR[0] */ if ((TRAPME = Mem_read(t+4, &temp))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ + goto newpsd; /* memory read error or map fault */ /* if Bit0 set, restore all saved regs, else restore only BRs */ - if ((temp & BIT0) == 0) { /* see if GPRs are to be restored */ + if ((temp & BIT0) == 0) { /* see if GPRs are to be restored */ /* Bit 0 is not set, so restore all GPRs */ for (ix=2; ix<8; ix++) if ((TRAPME = Mem_read(t+ix*4+32, &GPR[ix]))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ + goto newpsd; /* memory read error or map fault */ } for (ix=0; ix<8; ix++) if ((TRAPME = Mem_read(t+ix*4+8, &BR[ix]))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - PSD1 &= ~0x1fffffe; /* leave everything except AEXP bit and PC */ + goto newpsd; /* memory read error or map fault */ + PSD1 &= ~0x1fffffe; /* leave everything except AEXP bit and PC */ if ((TRAPME = Mem_read(t, &temp))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - PSD1 |= (temp & 0x01fffffe); /* restore AEXP bit and PC from call frame */ - i_flags |= BT; /* we changed the PC, so no PC update */ + goto newpsd; /* memory read error or map fault */ + PSD1 |= (temp & 0x01fffffe); /* restore AEXP bit and PC from call frame */ + i_flags |= BT; /* we changed the PC, so no PC update */ break; case 0x1: /* INV */ @@ -3503,10 +3560,10 @@ tbr: /* handle basemode TBR too * case 0xB: /* INV */ case 0xD: /* INV */ case 0xF: /* INV */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ break; } break; @@ -3606,7 +3663,7 @@ tbr: /* handle basemode TBR too * modes = temp2; /* restore modes flags */ if (TRAPME) { /* DIAGS wants the cpix for the psd to be the requested one */ - PSD2 = (PSD2 & 0xffffc000) | (DPSD[1] & 0x3ffc); + PSD2 = (PSD2 & 0xffffc000) | (DPSD[1] & 0x3ff8); goto newpsd; /* handle trap */ } goto skipit; @@ -3781,7 +3838,6 @@ skipit: TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ goto newpsd; /* program error */ } -//WAS bc = PSD2 & 0x3ffc; /* get copy of cpix */ bc = PSD2 & 0x3ff8; /* get copy of cpix */ #ifdef DIAG_HACK if ((IR & 0xffff) == 2 ) /* if nop in rt hw, bump pc a word */ @@ -3795,7 +3851,7 @@ skipit: M[t>>2] = PSD1 & 0xfffffffe; /* store PSD 1 + 1HW to point to next instruction */ M[(t>>2)+1] = PSD2; /* store PSD 2 */ PSD1 = M[(t>>2)+2]; /* get new PSD 1 */ - PSD2 = (M[(t>>2)+3] & ~0x3ffc) | bc; /* get new PSD 2 w/old cpix */ + PSD2 = (M[(t>>2)+3] & ~0x3ff8) | bc; /* get new PSD 2 w/old cpix */ M[(t>>2)+4] = opr & 0x03FF; /* store calm number in bits 6-15 */ /* set the mode bits and CCs from the new PSD */ CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ @@ -3815,7 +3871,18 @@ skipit: else { CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ irq_pend = 1; /* start scanning interrupts again */ +#ifdef USE_AIR + if (irq_auto) { +/*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ +/*AIR*/ SPAD[irq_auto+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ + } +if (irq_auto == 0) +sim_debug(DEBUG_IRQ, &cpu_dev, "XX3 Zero interrupt level found\n"); + if (irq_auto) + sim_debug(DEBUG_IRQ, &cpu_dev, + "<|>IntX deactivate level %02x at CALM PSD1 %08x\n", irq_auto, PSD1); /*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ +#endif } } PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ @@ -3839,7 +3906,7 @@ skipit: if (modes & EXTDBIT) { /* see if extended mode */ /*TRY*/ dest = (t_uint64)(addr&MASK24); /* just pure 24 bit address */ } else { /* use bits 13-31 */ -/*TRY*/ dest = (t_uint64)((addr&0x7ffff) | ((FC & 4) << 17)); /* F bit to bit 12 */ +/*TRY*/ dest = (t_uint64)((addr&0x7ffff) | ((FC & 4) << 17)); /* F bit to bit 12 */ } break; @@ -4086,9 +4153,9 @@ doovr4: goto newpsd; /* go execute the trap now */ } td = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ - td |= (t_uint64)GPR[reg+1]; /* insert low order 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 */ + 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, "DVRFD GPR[%d] %08x %08x src %016llx result %016llx\n", @@ -4146,9 +4213,9 @@ doovr4: goto newpsd; /* go execute the trap now */ } td = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ - td |= (t_uint64)GPR[reg+1]; /* insert low order 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 */ + 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, "MPRFD GPR[%d] %08x %08x src %016llx result %016llx\n", @@ -4370,6 +4437,8 @@ 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, + "ADDRSPEC8 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } dest = BR[reg]; /* save the BR to memory */ @@ -4389,6 +4458,8 @@ 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, + "ADDRSPEC9 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } if ((FC & 0x4) == 0) { /* this is a LWBR 0x5C00 instruction */ @@ -5069,9 +5140,10 @@ meoa: /* merge point for eor, and, or */ "\n\tR0=%.8x R1=%.8x R2=%.8x R3=%.8x", GPR[0], GPR[1], GPR[2], GPR[3]); sim_debug(DEBUG_INST, &cpu_dev, " R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]); -#ifdef NOTNOW +#ifndef NOTNOW + if (skipinstr) sim_debug(DEBUG_IRQ, &cpu_dev, - "EXM skipinstr %x irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + "EXM skipinstr %x reset irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", skipinstr, irq_pend, PSD1, PSD2, CPUSTATUS); #endif /*DIAG*/ skipinstr = 0; /* only test this once */ @@ -5378,11 +5450,11 @@ doovr2: TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ goto newpsd; /* program error */ } - bc = PSD2 & 0x3ffc; /* get copy of cpix */ + bc = PSD2 & 0x3ff8; /* get copy of cpix */ M[t>>2] = (PSD1+4) & 0xfffffffe; /* store PSD 1 + 1W to point to next instruction */ M[(t>>2)+1] = PSD2; /* store PSD 2 */ PSD1 = M[(t>>2)+2]; /* get new PSD 1 */ - PSD2 = (M[(t>>2)+3] & ~0x3ffc) | bc; /* get new PSD 2 w/old cpix */ + PSD2 = (M[(t>>2)+3] & ~0x3ff8) | bc; /* get new PSD 2 w/old cpix */ M[(t>>2)+4] = IR&0xFFF; /* store call number */ /* set the mode bits and CCs from the new PSD */ @@ -5405,7 +5477,19 @@ doovr2: else { CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ irq_pend = 1; /* start scanning interrupts again */ +#ifdef USE_AIR + if (irq_auto) { +/*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ +/*AIR*/ SPAD[irq_auto+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ + } +//if (irq_auto == 0) +//sim_debug(DEBUG_IRQ, &cpu_dev, "XX4 Zero interrupt level found\n"); + if (irq_auto) + sim_debug(DEBUG_IRQ, &cpu_dev, + "<|>IntX deactivate level %02x at SVC #%2x PSD1 %08x\n", + irq_auto, temp2, PSD1); /*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ +#endif } } PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ @@ -5456,9 +5540,10 @@ doovr2: "\n\tR0=%.8x R1=%.8x R2=%.8x R3=%.8x", GPR[0], GPR[1], GPR[2], GPR[3]); sim_debug(DEBUG_INST, &cpu_dev, " R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]); -#ifdef NOTNOW +#ifndef NOTNOW + if (skipinstr) sim_debug(DEBUG_IRQ, &cpu_dev, - "EXR skipinstr %x irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + "EXR skipinstr %x reset irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", skipinstr, irq_pend, PSD1, PSD2, CPUSTATUS); #endif /*DIAG*/ skipinstr = 0; /* only test this once */ @@ -5825,6 +5910,8 @@ doovr2: /* if ((FC & 5) != 0) { */ if ((FC & 4) != 0) { TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + sim_debug(DEBUG_EXP, &cpu_dev, + "ADDRSPEC10 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } temp2 = CC; /* save the old CC's */ @@ -5844,8 +5931,10 @@ doovr2: /* update the PSD with new address */ PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ i_flags |= BT; /* we branched, so no PC update */ - if (((modes & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect are wanted */ - PSD1 = (PSD1 & 0x87fffffe) | temp2; /* insert last indirect CCs */ + if (((modes & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect wanted */ + PSD1 = (PSD1 & 0x87fffffe) | temp2; /* insert last indirect CCs */ +/*FIX F77*/ if ((modes & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ +/*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ } /* branch not taken, go do next instruction */ break; @@ -5856,6 +5945,8 @@ doovr2: /* if ((FC & 5) != 0) { */ if ((FC & 4) != 0) { TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + sim_debug(DEBUG_EXP, &cpu_dev, + "ADDRSPEC11 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } temp2 = CC; /* save the old CC's */ @@ -5875,8 +5966,10 @@ doovr2: /* update the PSD with new address */ PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ i_flags |= BT; /* we branched, so no PC update */ - if (((modes & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect are wanted */ - PSD1 = (PSD1 & 0x87fffffe) | temp2; /* insert last indirect CCs */ + if (((modes & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect wanted */ + PSD1 = (PSD1 & 0x87fffffe) | temp2; /* insert last indirect CCs */ +/*FIX F77*/ if ((modes & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ +/*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ } break; @@ -5893,9 +5986,11 @@ doovr2: } #endif PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ - if (((modes & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect are wanted */ + if (((modes & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect wanted */ PSD1 = (PSD1 & 0x87fffffe) | CC; /* insert last CCs */ i_flags |= BT; /* we branched, so no PC update */ +/*FIX F77*/ if ((modes & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ +/*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ } break; @@ -5908,7 +6003,7 @@ doovr2: case 0x1: /* BL F880 */ /* copy CC's from instruction and PC incremented by 4 */ GPR[0] = ((PSD1 & 0xff000000) | ((PSD1 + 4) & 0xfffffe)); - if (((modes & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect are wanted */ + if (((modes & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect wanted */ PSD1 = (PSD1 & 0x87fffffe) | CC; /* insert last CCs */ /* update the PSD with new address */ if (modes & BASEBIT) @@ -5916,6 +6011,8 @@ doovr2: else PSD1 = (PSD1 & 0xff000000) | (addr & 0x07fffe); /* bit 13-30 */ i_flags |= BT; /* we branched, so no PC update */ +/*FIX F77*/ if ((modes & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ +/*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ break; case 0x3: /* LPSD F980 */ @@ -5935,6 +6032,8 @@ 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, + "ADDRSPEC12 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } if ((TRAPME = Mem_read(addr, &temp))) { /* get PSD1 from memory */ @@ -5980,7 +6079,7 @@ doovr2: CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */ - CPUSTATUS |= modes; /* not insert into CPUSTATUS */ + CPUSTATUS |= modes; /* now insert into CPUSTATUS */ /* set new arithmetic trap state in CPUSTATUS */ if (PSD1 & AEXPBIT) { CPUSTATUS |= AEXPBIT; /* set bit 7 of cpu status */ @@ -6006,7 +6105,18 @@ doovr2: else { CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ irq_pend = 1; /* start scanning interrupts again */ +#ifdef USE_AIR + if (irq_auto) { +/*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ +/*AIR*/ SPAD[irq_auto+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ + } +//if (irq_auto == 0) +//sim_debug(DEBUG_IRQ, &cpu_dev, "XX5 Zero interrupt level found\n"); + if (irq_auto) + sim_debug(DEBUG_IRQ, &cpu_dev, + "<|>IntX deactivate level %02x at LPSD(CM) %08x\n", irq_auto, PSD1); /*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ +#endif } } PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ @@ -6061,7 +6171,7 @@ doovr2: PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ - sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_IRQ, &cpu_dev, "LPSDCM MAPS LOADED TRAPME = %02x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", TRAPME, PSD1, PSD2, CPUSTATUS); } @@ -6095,17 +6205,19 @@ doovr2: TRAPSTATUS |= BIT18; /* set bit 18 of trap status */ goto newpsd; /* go process error */ } - skipinstr = 1; /* do not allow intr on next instruction */ #ifdef NOTNOW sim_debug(DEBUG_IRQ, &cpu_dev, - "Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - PSD1, PSD2, CPUSTATUS); + "Skipinstr %1x set @ LPSD(CM) PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + skipinstr, PSD1, PSD2, CPUSTATUS); + skipinstr = 1; /* do not allow intr on next instruction */ +#else +//try 032920 skipinstr = 1; /* do not allow intr on next instruction */ #endif drop_nop = 0; /* nothing to drop */ #ifdef NOTNOW sim_debug(DEBUG_IRQ, &cpu_dev, - "LPSD(CM) Done PSD1 %08x PSD2 %08x CPUSTATUS %08x irq %01x\n", - PSD1, PSD2, CPUSTATUS, irq_pend); + "LPSD(CM) Done PSD1 %08x PSD2 %08x CPUSTATUS %08x irq %1x BLK %1x\n", + PSD1, PSD2, CPUSTATUS, irq_pend, CPUSTATUS&0x80?1:0); #endif goto newpsd; /* load the new psd, or process error */ break; @@ -6170,12 +6282,13 @@ doovr2: break; /* ignore */ /* SPAD entries for interrupts begin at 0x80 */ t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - if (t == 0 || t == 0xffffffff) /* if not set up, not class F */ - goto syscheck; /* system check */ -// break; /* ignore */ - if ((t & 0x0f000000) == 0x0f000000) /* if class F ignore instruction */ + if ((t & 0x0f800000) == 0x0f000000) /* if class F ignore instruction */ break; /* ignore for F class */ + sim_debug(DEBUG_IRQ, &cpu_dev, "EI:B4 %02x ACT %1x REQ %1x ENAB %1x\n", + prior, INTS[prior]&INTS_ACT?1:0, + INTS[prior]&INTS_REQ?1:0, INTS[prior]&INTS_ENAB?1:0); + /* does not effect REQ status */ INTS[prior] |= INTS_ENAB; /* enable specified int level */ SPAD[prior+0x80] |= SINT_ENAB; /* enable in SPAD too */ @@ -6183,20 +6296,16 @@ doovr2: /* test for clock at address 0x7f06 and interrupt level 0x18 */ /* the diags want the type to be 0, others want 3, so ignore */ -//WAS bad for diag if ((SPAD[prior+0x80] & 0x0f00ffff) == 0x03007f06) { +//DIAGS if ((SPAD[prior+0x80] & 0x0f807fff) == 0x08007f06) { if ((SPAD[prior+0x80] & 0x0000ffff) == 0x00007f06) { sim_debug(DEBUG_IRQ, &cpu_dev, "Clock EI %02x Turn on\n", prior); rtc_setup(1, prior); /* tell clock to start */ } +//DIAGS if ((SPAD[prior+0x80] & 0x0f807fff) == 0x03007f04) { if ((SPAD[prior+0x80] & 0x0f00ffff) == 0x03007f04) { sim_debug(DEBUG_IRQ, &cpu_dev, "Intv Timer EI %02x Turn on\n", prior); itm_setup(1, prior); /* tell timer to start */ } -#ifndef NOTNOW - sim_debug(DEBUG_IRQ, &cpu_dev, - "EI lev %02x Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - prior, PSD1, PSD2, CPUSTATUS); -#endif break; case 0x1: /* DI FC01 */ @@ -6204,33 +6313,31 @@ doovr2: break; /* ignore */ /* SPAD entries for interrupts begin at 0x80 */ t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - if (t == 0 || t == 0xffffffff) /* if not set up, not class F */ -//RESTART goto syscheck; /* system check */ - break; /* ignore */ - if ((t & 0x0f000000) == 0x0f000000) /* if class F ignore instruction */ + if ((t & 0x0f800000) == 0x0f000000) /* if class F ignore instruction */ break; /* ignore for F class */ + sim_debug(DEBUG_IRQ, &cpu_dev, "DI:B4 %02x ACT %1x REQ %1x ENAB %1x\n", + prior, INTS[prior]&INTS_ACT?1:0, + INTS[prior]&INTS_REQ?1:0, INTS[prior]&INTS_ENAB?1:0); + /* active state is left alone */ INTS[prior] &= ~INTS_ENAB; /* disable specified int level */ SPAD[prior+0x80] &= ~SINT_ENAB; /* disable in SPAD too */ INTS[prior] &= ~INTS_REQ; /* clears any requests also */ +/*031820*/ irq_pend = 1; /* start scanning interrupts again */ /* test for clock at address 0x7f06 and interrupt level 0x18 */ /* the diags want the type to be 0, others want 3, so ignore */ -//WAS bad for diag if ((SPAD[prior+0x80] & 0x0f00ffff) == 0x03007f06) { +//DIAGS if ((SPAD[prior+0x80] & 0x0f807fff) == 0x00807f06) { if ((SPAD[prior+0x80] & 0x0000ffff) == 0x00007f06) { sim_debug(DEBUG_IRQ, &cpu_dev, "Clock DI %02x Turn off\n", prior); rtc_setup(0, prior); /* tell clock to stop */ } +//DIAGS if ((SPAD[prior+0x80] & 0x0f807fff) == 0x03007f04) { if ((SPAD[prior+0x80] & 0x0f00ffff) == 0x03007f04) { itm_setup(0, prior); /* tell timer to stop */ sim_debug(DEBUG_IRQ, &cpu_dev, "Intv Timer DI %02x Turn off\n", prior); } -#ifndef NOTNOW - sim_debug(DEBUG_IRQ, &cpu_dev, - "DI lev %02x Skipinstr set to %01x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - prior, skipinstr, PSD1, PSD2, CPUSTATUS); -#endif break; case 0x2: /* RI FC02 */ @@ -6238,18 +6345,15 @@ doovr2: break; /* ignore */ /* SPAD entries for interrupts begin at 0x80 */ t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - if (t == 0 || t == 0xffffffff) /* if not set up, not class F */ - goto syscheck; /* system check */ -// break; /* ignore */ - if ((t & 0x0f000000) == 0x0f000000) /* if class F ignore instruction */ + if ((t & 0x0f800000) == 0x0f000000) /* if class F ignore instruction */ break; /* ignore for F class */ + + sim_debug(DEBUG_IRQ, &cpu_dev, "RI:B4 %02x ACT %1x REQ %1x ENAB %1x\n", + prior, INTS[prior]&INTS_ACT?1:0, + INTS[prior]&INTS_REQ?1:0, INTS[prior]&INTS_ENAB?1:0); + INTS[prior] |= INTS_REQ; /* set the request flag for this level */ irq_pend = 1; /* start scanning interrupts again */ -#ifndef NOTNOW - sim_debug(DEBUG_IRQ, &cpu_dev, - "RI lev %02x Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - prior, PSD1, PSD2, CPUSTATUS); -#endif break; case 0x3: /* AI FC03 */ @@ -6257,18 +6361,18 @@ doovr2: break; /* ignore */ /* SPAD entries for interrupts begin at 0x80 */ t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - if (t == 0 || t == 0xffffffff) /* if not set up, not class F */ - goto syscheck; /* system check */ - if ((t & 0x0f000000) == 0x0f000000) /* if class F ignore instruction */ + if ((t & 0x0f800000) == 0x0f000000) /* if class F ignore instruction */ break; /* ignore for F class */ + + sim_debug(DEBUG_IRQ, &cpu_dev, "RI:B4 %02x ACT %1x REQ %1x ENAB %1x\n", + prior, INTS[prior]&INTS_ACT?1:0, + INTS[prior]&INTS_REQ?1:0, INTS[prior]&INTS_ENAB?1:0); + INTS[prior] |= INTS_ACT; /* activate specified int level */ SPAD[prior+0x80] |= SINT_ACT; /* activate in SPAD too */ +if (prior == 0) +sim_debug(DEBUG_IRQ, &cpu_dev, "XX6 Zero interrupt level found\n"); irq_pend = 1; /* start scanning interrupts again */ -#ifndef NOTNOW - sim_debug(DEBUG_IRQ, &cpu_dev, - "AI lev %02x Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - prior, PSD1, PSD2, CPUSTATUS); -#endif break; case 0x4: /* DAI FC04 */ @@ -6276,22 +6380,26 @@ doovr2: break; /* ignore */ /* SPAD entries for interrupts begin at 0x80 */ t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - if (t == 0 || t == 0xffffffff) /* if not set up, not class F */ - goto syscheck; /* system check */ -// break; /* ignore */ - if ((t & 0x0f000000) == 0x0f000000) /* if class F ignore instruction */ + if ((t & 0x0f800000) == 0x0f000000) /* if class F ignore instruction */ break; /* ignore for F class */ + + sim_debug(DEBUG_IRQ, &cpu_dev, "DAI:B4 %02x ACT %1x REQ %1x ENAB %1x\n", + prior, INTS[prior]&INTS_ACT?1:0, + INTS[prior]&INTS_REQ?1:0, INTS[prior]&INTS_ENAB?1:0); + INTS[prior] &= ~INTS_ACT; /* deactivate specified int level */ SPAD[prior+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ +if (prior == 0) +sim_debug(DEBUG_IRQ, &cpu_dev, "XX7 Zero interrupt level found\n"); irq_pend = 1; /* start scanning interrupts again */ /* instruction following a DAI can not be interrupted */ /* skip tests for interrupts if this is the case */ - skipinstr = 1; /* skip interrupt test */ #ifndef NOTNOW sim_debug(DEBUG_IRQ, &cpu_dev, - "DAI lev %02x Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - prior, PSD1, PSD2, CPUSTATUS); + "DAI lev %02x Skipinstr %1x set PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + prior, skipinstr, PSD1, PSD2, CPUSTATUS); #endif + skipinstr = 1; /* skip interrupt test */ drop_nop = 0; /* nothing to drop */ break; @@ -6301,10 +6409,8 @@ doovr2: /* the channel must be defined as a non class F I/O channel in SPAD */ /* if class F, the system will generate a system check trap */ t = SPAD[device]; /* get spad entry for channel */ - if (t == 0 || t == 0xffffffff) /* if not set up, die */ - goto syscheck; /* system check */ +//DIAG if ((t & 0x0f800000) == 0x0f000000) { /* class in bits 4-7 */ if ((t & 0x0f000000) == 0x0f000000) { /* class in bits 4-7 */ -syscheck: TRAPME = SYSTEMCHK_TRAP; /* trap condition if F class */ TRAPSTATUS &= ~BIT0; /* class E error bit */ TRAPSTATUS &= ~BIT1; /* I/O processing error */ @@ -6325,8 +6431,12 @@ syscheck: // t = SPAD[device]; /* get spad entry for channel */ /* t has spad entry for device */ /* get the 1's comp of interrupt address from bits 9-15 SPAD entry */ +#ifdef OLDWAY ix = (t & 0x007f0000) >> 16;/* get the 1's comp of int level */ ix = 127 - ix; /* get positive number for interrupt */ +#else + ix = ((~t)>>16)&0x7f; /* get positive number for interrupt */ +#endif temp = (IR & 0x7f); /* get cmd from instruction */ if (device == 0x7f) { status = itm_rdwr(temp, GPR[0], ix); /* read/write the interval timer */ @@ -6346,34 +6456,65 @@ syscheck: } /* Process XIO instructions */ + /* see if valid instruction */ + /* DIAGS wants this tested first */ + switch((opr >> 3) & 0xf) { /* use bits 9-12 to determine I/O instruction */ + case 0x00: /* Unassigned */ + case 0x01: /* Unassigned */ + case 0x0A: /* Unassigned */ + TRAPME = UNDEFINSTR_TRAP; /* trap condition */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* undefined instruction trap */ + } + /* if reg is non-zero, add reg to 15 bits from instruction */ if (reg) temp2 = (IR & 0x7fff) + (GPR[reg] & 0x7fff); /* set new chan/suba into IR */ else temp2 = (IR & 0x7fff); /* set new chan/suba into IR */ +#ifdef DO_DYNAMIC_DEBUG + if ((temp2 & 0xff) == 1) + /* start debugging */ + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); +//#else +// if ((temp2 & 0xff) == 1) +// temp &= ~1; +#endif lchan = (temp2 & 0x7F00) >> 8; /* get 7 bit logical channel address */ suba = temp2 & 0xFF; /* get 8 bit subaddress */ /* the channel must be defined as a class F I/O channel in SPAD */ /* if not class F, the system will generate a system check trap */ t = SPAD[lchan]; /* get spad entry for channel */ if ((t == 0 || t == 0xffffffff) || /* if not set up, system check */ - ((t & 0x0f000000) != 0x0f000000)) { /* class in bits 4-7 */ -//fprintf(stderr, "SYSCHK XIO lchan %.4x spad %.8x\r\n", lchan, t); +/* DIAGS */ ((t & 0x0f800000) != 0x0f000000)) { /* class in bits 4-7 */ +// ((t & 0x0f000000) != 0x0f000000)) { /* class in bits 4-7 */ + sim_debug(DEBUG_XIO, &cpu_dev, + "$$ XIO SYSTEMCHK lchan %04x sa %04x spad %08x BLK %1x INTS[%02x] %08x\n", + lchan, suba, t, CPUSTATUS&0x80?1:0, ix, INTS[ix]); TRAPME = SYSTEMCHK_TRAP; /* trap condition if F class */ TRAPSTATUS |= BIT0; /* class F error bit */ TRAPSTATUS &= ~BIT1; /* I/O processing error */ goto newpsd; /* undefined instruction trap */ } - sim_debug(DEBUG_XIO, &cpu_dev, - "$$ XIO lchan %04x sa %04x spad %08x\n", lchan, suba, t); /* get real channel from spad device entry */ chan = (t & 0x7f00) >> 8; /* real channel */ /* get the 1's comp of interrupt address from bits 9-15 SPAD entry */ +#ifdef OLDWAY ix = (t & 0x007f0000) >> 16; /* get the 1's comp of int level */ ix = 127 - ix; /* get positive number for interrupt */ - bc = SPAD[ix+0x80]; /* get interrupt entry for channel */ +#else + ix = ((~t)>>16)&0x7f; /* get positive number for interrupt */ +#endif + bc = SPAD[ix+0x80]; /* get interrupt spad entry for channel */ /* SPAD address F1 has interrupt table address */ temp = SPAD[0xf1] + (ix<<2); /* vector address in SPAD */ + sim_debug(DEBUG_XIO, &cpu_dev, + "$$ XIO lchan %02x sa %02x spad %08x BLK %1x INTS[%02x] %08x\n", + lchan, suba, t, CPUSTATUS&0x80?1:0, ix, INTS[ix]); + sim_debug(DEBUG_XIO, &cpu_dev, + "$$ XIO lchsa %04x PSD1 %08x PSD2 %08x IR %08x OP %02x\n", + temp2, PSD1, PSD2, IR, OP); if ((TRAPME = Mem_read(temp, &addr))) { /* get interrupt context block addr */ mcheck: /* machine check if not there */ @@ -6396,8 +6537,8 @@ mcheck: } sim_debug(DEBUG_XIO, &cpu_dev, - "XIO ready chan %04x intr %04x icb %08x iocla %08x iocd1 %08x iocd2 %08x\n", - chan, ix, addr, addr+16, RMW(temp), RMW(temp+4)); + "XIO ready PSD1 %08x chan %02x irq %02x icb %06x iocla %06x iocd1 %08x iocd2 %08x\n", + PSD1, chan, ix, addr, addr+16, RMW(temp), RMW(temp+4)); // chan, ix, addr, addr+16, M[temp>>2], M[(temp+4)>>2]); /* at this point, the channel has a valid SPAD channel entry */ /* t is SPAD entry contents for chan device */ @@ -6406,11 +6547,11 @@ mcheck: /* chan - channel address */ /* suba - channel device subaddress */ /* ix - positive interrupt level */ - /* addr - ICB for specified interrupt level, points to 6 wd block */ + /* addr - ICBA for specified interrupt level, points to 6 wd block */ /* temp - First IOCD address */ sim_debug(DEBUG_XIO, &cpu_dev, - "XIO switch %02x lchan %04x, chan %04x intr %04x chsa %04x IOCDa %08x\n", - ((opr>>3)&0x0f), lchan, chan, ix, (chan<<8)|suba, temp); + "XIO switch %02x lchan %02x chan %02x irq %02x chsa %04x IOCDa %08x CPUSTATUS %08x\n", + ((opr>>3)&0x0f), lchan, chan, ix, (chan<<8)|suba, temp, CPUSTATUS); switch((opr >> 3) & 0xf) { /* use bits 9-12 to determine I/O instruction */ uint32 status; /* status returned by various functions */ @@ -6446,22 +6587,23 @@ mcheck: goto newpsd; /* error returned, trap cpu */ PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ sim_debug(DEBUG_XIO, &cpu_dev, - "XIO SIO ret chan %04x chsa %04x status %08x\n", - chan, (chan<<8)|suba, status); + "XIO SIO ret PSD1 %08x chan %04x chsa %04x status %08x BLK %1x\n", + PSD1, chan, (chan<<8)|suba, status, CPUSTATUS&0x80?1:0); +// fflush(sim_deb); break; case 0x03: /* Test I/O TIO */ chsa = temp2 & 0x7FFF; /* get logical device address */ if ((TRAPME = testxio(chsa, &status))) { sim_debug(DEBUG_TRAP, &cpu_dev, - "XIO TIO ret PSD1 %x chan %x chsa %x status %x\n", - PSD1, chan, (chan<<8)|suba, status); + "XIO TIO ret PSD1 %x chan %x chsa %x status %x BLK %1x\n", + PSD1, chan, (chan<<8)|suba, status, CPUSTATUS&0x80?1:0); goto newpsd; /* error returned, trap cpu */ } PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ sim_debug(DEBUG_XIO, &cpu_dev, - "XIO TIO ret chan %04x sa %04x status %08x spad %08x INTS[%02x] %08x\n", - chan, suba, status, t, ix, INTS[ix]); + "XIO TIO ret PSD1 %08x chsa %04x status %08x spad %08x INTS[%02x] %08x BLK %1x\n", + PSD1, chsa, status, t, ix, INTS[ix], CPUSTATUS&0x80?1:0); #ifdef DO_DYNAMIC_DEBUG /* start debugging */ cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); @@ -6480,13 +6622,15 @@ mcheck: /* TODO Finish XIO */ case 0x05: /* Reset channel RSCHNL */ chsa = temp2 & 0x7FFF; /* get logical device address */ + /* TODO Maybe we need to disable int too???? */ + if ((TRAPME = rschnlxio(chsa, &status))) + goto newpsd; /* error returned, trap cpu */ /* SPAD entries for interrupts begin at 0x80 */ INTS[ix] &= ~INTS_REQ; /* clears any requests */ INTS[ix] &= ~INTS_ACT; /* deactivate specified int level */ SPAD[ix+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ - /* TODO Maybe we need to disable int too???? */ - if ((TRAPME = rschnlxio(chsa, &status))) - goto newpsd; /* error returned, trap cpu */ +if (ix == 0) +sim_debug(DEBUG_IRQ, &cpu_dev, "XX8 Zero interrupt level found\n"); PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ //fprintf(stderr, "XIO RSCHNL ret chan %x chsa %x status %x\n", chan, (chan<<8)|suba, status); sim_debug(DEBUG_XIO, &cpu_dev, "XIO RSCHNL ret chan %04x chsa %04x status %08x\n", @@ -6501,9 +6645,11 @@ mcheck: sim_debug(DEBUG_XIO, &cpu_dev, "HIO HALTXIO ret chan %04x chsa %04x status %08x\n", chan, (chan<<8)|suba, status); +#ifndef NOTNOW sim_debug(DEBUG_IRQ, &cpu_dev, "HIO skipinstr %x irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", skipinstr, irq_pend, PSD1, PSD2, CPUSTATUS); +#endif break; case 0x07: /* Grab controller GRIO n/u */ @@ -6530,12 +6676,18 @@ mcheck: sim_debug(DEBUG_XIO, &cpu_dev, "XIO ECI chan %04x sa %04x spad %08x INTS[%02x] %08x\n", chan, suba, t, ix, INTS[ix]); +#ifdef DO_DYNAMIC_DEBUG + if (t == 0x0f727e00) + /* start debugging */ + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); +#endif + if ((TRAPME = checkxio(chsa, &status))) + goto newpsd; /* error returned, trap cpu */ /* SPAD entries for interrupts begin at 0x80 */ INTS[ix] |= INTS_ENAB; /* enable specified int level */ SPAD[ix+0x80] |= SINT_ENAB; /* enable in SPAD too */ irq_pend = 1; /* start scanning interrupts again */ - if ((TRAPME = checkxio(chsa, &status))) - goto newpsd; /* error returned, trap cpu */ + /* return status of zero for present and functioning */ PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ break; @@ -6545,11 +6697,13 @@ mcheck: sim_debug(DEBUG_XIO, &cpu_dev, "XIO DCI chan %04x sa %04x spad %08x INTS[%02x] %08x\n", chan, suba, t, ix, INTS[ix]); + if ((TRAPME = checkxio(chsa, &status))) + goto newpsd; /* error returned, trap cpu */ /* SPAD entries for interrupts begin at 0x80 */ INTS[ix] &= ~INTS_ENAB; /* disable specified int level */ SPAD[ix+0x80] &= ~SINT_ENAB; /* disable in SPAD too */ - if ((TRAPME = checkxio(chsa, &status))) - goto newpsd; /* error returned, trap cpu */ + /* MFP doc says req is dropped, 67 cpu says no */ +// TRYING 032920 */ INTS[ix] &= ~INTS_REQ; /* clears any requests also */ PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ break; @@ -6559,12 +6713,14 @@ mcheck: sim_debug(DEBUG_XIO, &cpu_dev, "XIO ACI chan %04x sa %04x spad %08x INTS[%02x] %08x\n", chan, suba, t, ix, INTS[ix]); + if ((TRAPME = checkxio(chsa, &status))) + goto newpsd; /* error returned, trap cpu */ /* SPAD entries for interrupts begin at 0x80 */ INTS[ix] |= INTS_ACT; /* activate specified int level */ SPAD[ix+0x80] |= SINT_ACT; /* enable in SPAD too */ - INTS[ix] &= ~INTS_REQ; /* clears any requests also */ - if ((TRAPME = checkxio(chsa, &status))) - goto newpsd; /* error returned, trap cpu */ +if (ix == 0) +sim_debug(DEBUG_IRQ, &cpu_dev, "XX9 Zero interrupt level found\n"); +//WAS INTS[ix] &= ~INTS_REQ; /* clears any requests also */ PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ break; @@ -6573,20 +6729,22 @@ mcheck: /* Note, instruction following DACI is not interruptable */ chsa = temp2 & 0x7FFF; /* get logical device address */ sim_debug(DEBUG_XIO, &cpu_dev, - "XIO DACI chan %04x sa %04x spad %08x INTS[%02x] %08x\n", - chan, suba, t, ix, INTS[ix]); + "XIO DACI chan %04x sa %04x spad %08x INTS[%02x] %08x BLK %1x\n", + chan, suba, t, ix, INTS[ix], CPUSTATUS&0x80?1:0); + if ((TRAPME = checkxio(chsa, &status))) + goto newpsd; /* error returned, trap cpu */ /* SPAD entries for interrupts begin at 0x80 */ INTS[ix] &= ~INTS_ACT; /* deactivate specified int level */ SPAD[ix+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ - if ((TRAPME = checkxio(chsa, &status))) - goto newpsd; /* error returned, trap cpu */ irq_pend = 1; /* start scanning interrupts again */ - skipinstr = 1; /* skip interrupt test */ -#ifdef NOTNOW +if (ix == 0) +sim_debug(DEBUG_IRQ, &cpu_dev, "XXB Zero interrupt level found\n"); +#ifndef NOTNOW sim_debug(DEBUG_IRQ, &cpu_dev, - "Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - PSD1, PSD2, CPUSTATUS); + "DACI lev %02x Skipinstr %1x set PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + ix, skipinstr, PSD1, PSD2, CPUSTATUS); #endif + skipinstr = 1; /* skip interrupt test */ /*XXX*/ drop_nop = 0; /* nothing to drop */ PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ break; @@ -6599,11 +6757,14 @@ mcheck: /* after the instruction is done and before incrementing the PC, */ /* we will trap the cpu if ovl is set nonzero by an instruction */ +//DIAGINT SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ /* Store result to register */ if (i_flags & SD) { 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, + "ADDRSPEC13 OP %04x addr %08x\n", OP, addr); goto newpsd; /* go execute the trap now */ } GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ @@ -6781,6 +6942,7 @@ newpsd: /* Bits 1-20 Always zero */ /* Map register number (logical map block number) */ +//DIAGINT SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ /* we get here from a LPSD, LPSDCM, INTR, or TRAP */ if (TRAPME) { #ifdef DO_DYNAMIC_DEBUG @@ -6824,7 +6986,7 @@ newpsd: } #endif sim_debug(DEBUG_TRAP, &cpu_dev, - "##TRAPME %04x LOAD MAPS PSD1 %08x PSD2 %08x CPUSTATUS %08x drop_nop %01x i_flags %04x\n", + "##TRAPME %04x LOAD MAPS PSD1 %08x PSD2 %08x CPUSTATUS %08x drop_nop %1x i_flags %04x\n", TRAPME, PSD1, PSD2, CPUSTATUS, drop_nop, i_flags); /* adjust PSD1 to next instruction */ /* Update instruction pointer to next instruction */ @@ -6914,7 +7076,7 @@ newpsd: return STOP_HALT; /* exit to simh for halt */ } else { /* valid vector, so store the PSD, fetch new PSD */ - bc = PSD2 & 0x3ffc; /* get copy of cpix */ + bc = PSD2 & 0x3ff8; /* get copy of cpix */ if ((TRAPME) && ((CPU_MODEL <= MODEL_27) )) /* Privlege Mode Halt Trap on 27 has bit 31 reset */ M[tvl>>2] = PSD1 & 0xfffffffe; /* store PSD 1 */ @@ -6922,7 +7084,7 @@ newpsd: M[tvl>>2] = PSD1 & 0xffffffff; /* store PSD 1 */ M[(tvl>>2)+1] = PSD2; /* store PSD 2 */ PSD1 = M[(tvl>>2)+2]; /* get new PSD 1 */ - PSD2 = (M[(tvl>>2)+3] & ~0x3ffc) | bc; /* get new PSD 2 w/old cpix */ + PSD2 = (M[(tvl>>2)+3] & ~0x3ff8) | bc; /* get new PSD 2 w/old cpix */ M[(tvl>>2)+4] = TRAPSTATUS; /* store trap status */ if (TRAPME == DEMANDPG_TRAP) { /* 0xC4 Demand Page Fault Trap (V6&V9 Only) */ M[(tvl>>2)+5] = pfault; /* store page fault number */ @@ -7026,7 +7188,7 @@ uint32 def_floppy = 0x7ef0; /* IOP floppy disk channel 7e, device f0 /* Reset routine */ /* do any one time initialization here for cpu */ -t_stat cpu_reset(DEVICE * dptr) +t_stat cpu_reset(DEVICE *dptr) { int i; @@ -7044,6 +7206,7 @@ t_stat cpu_reset(DEVICE * dptr) CMSMC = 0xfffffe10; /* No V9 Cache/Shadow Memory Configuration */ CSMCW = 0; /* No V9 CPU Shadow Memory Configuration */ 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 */ diff --git a/SEL32/sel32_defs.h b/SEL32/sel32_defs.h index 7101b4a..a8ea153 100644 --- a/SEL32/sel32_defs.h +++ b/SEL32/sel32_defs.h @@ -80,6 +80,9 @@ #define STATUS_DEND 0x0004 /* Device end */ #define STATUS_CHECK 0x0002 /* Unit check */ #define STATUS_EXPT 0x0001 /* Unit exception */ +#define STATUS_ERROR 0x3f03 /* bad errors */ +//#define STATUS_ERROR (STATUS_LENGTH|STATUS_PCHK|STATUS_CDATA|STATUS_CCNTL| +// STATUS_INTER|STATUS_CHAIN|STATUS_CHECK|STATUS_EXPT) /* Class F channel bits */ /* bit 32 - 37 of IOCD word 2 (0-5) */ @@ -94,6 +97,8 @@ #define BUFF_DIRTY 0x8 /* Buffer is dirty flag */ #define BUFF_NEWCMD 0x10 /* Channel ready for new command */ #define BUFF_CHNEND 0x20 /* Channel end */ +#define BUFF_DONE 0x40 /* Channel program done */ +#define BUFF_NEXT 0x80 /* Continue Channel with next IOCB */ #define MAX_CHAN 128 /* max channels that can be defined */ #define SUB_CHANS 256 /* max sub channels that can be defined */ @@ -110,17 +115,15 @@ #define NUM_UNITS_CON 2 /* 2 console input & output */ #define NUM_DEVS_MT 1 /* 1 mag tape controllers */ #define NUM_UNITS_MT 4 /* 4 of 8 devices */ -#define FOR_UTX -#ifdef FOR_UTX -#define NUM_DEVS_HSDP 1 /* 1 HSPD disk drive controller */ +#define NUM_DEVS_HSDP 1 /* 1 hspd disk drive controller */ #define NUM_UNITS_HSDP 2 /* 2 disk drive devices */ -//#else -#define NUM_DEVS_DISK 1 /* 1 DP02 disk drive controller */ +#define NUM_DEVS_DISK 1 /* 1 dp02 disk drive controller */ #define NUM_UNITS_DISK 2 /* 2 disk drive devices */ //#define NUM_UNITS_DISK 4 /* 4 disk drive devices */ -#endif #define NUM_DEVS_SCFI 1 /* 1 scfi (SCSI) disk drive units */ #define NUM_UNITS_SCFI 1 /* 1 of 4 disk drive devices */ +#define NUM_DEVS_SCSI 1 /* 1 scsi (MFP SCSI) disk drive units */ +#define NUM_UNITS_SCSI 1 /* 1 of 4 disk drive devices */ #define NUM_DEVS_RTOM 1 /* 1 IOP RTOM channel */ #define NUM_UNITS_RTOM 1 /* 1 IOP RTOM device (clock & interval timer) */ #define NUM_DEVS_LPR 1 /* 1 IOP Line printer */ @@ -192,6 +195,7 @@ typedef struct chp { uint16 chan_dev; /* Device on channel */ uint8 ccw_cmd; /* Channel command and flags */ uint8 chan_byte; /* Current byte, dirty/full */ + uint8 chan_int; /* channel interrupt level */ } CHANP; /* Device information block */ @@ -394,15 +398,15 @@ extern DEBTAB dev_debug[]; #define SINT_EWCS 0x40000000 /* Enabled channel WCS executed (XIO) */ #define SINT_ACT 0x20000000 /* Interrupt active when set (copy is in INTS */ #define SINT_ENAB 0x10000000 /* Interrupt enabled when set (copy is in INTS */ -#define SINT_EXTL 0x08000000 /* IOP/RTOM ext interrupt if set, I/O if not set (copy in INTS) */ +#define SINT_EXTL 0x00800000 /* IOP/RTOM ext interrupt if set, I/O if not set (copy in INTS) */ /* INTS int entry equates, entries accessed by interrupt level number */ #define INTS_NU1 0x80000000 /* Not used */ #define INTS_NU2 0x40000000 /* Not used */ #define INTS_ACT 0x20000000 /* Interrupt active when set (copy is of SPAD */ #define INTS_ENAB 0x10000000 /* Interrupt enabled when set (copy is of SPAD */ -#define INTS_EXTL 0x08000000 /* IOP/RTOM ext interrupt if set, I/O if not set (copy of SPAD) */ -#define INTS_REQ 0x04000000 /* Interrupt is requesting */ +#define INTS_EXTL 0x00800000 /* IOP/RTOM ext interrupt if set, I/O if not set (copy of SPAD) */ +#define INTS_REQ 0x40000000 /* Interrupt is requesting (use bit 1) */ /* ReadAddr memory access requested */ #define MEM_RD 0x0 /* read memory */ @@ -417,12 +421,12 @@ extern DEBTAB dev_debug[]; /* RMW(addr) or WMW(addr, data) where addr is a byte alligned word address */ #define RMB(a) ((M[(a)>>2]>>(8*(7-(a&3))))&0xff) /* read memory addressed byte */ #define RMH(a) ((a)&2?(M[(a)>>2]&RMASK):(M[(a)>>2]>>16)&RMASK) /* read memory addressed halfword */ -#define RMW(a) (M[(a)>>2]) /* read memory addressed word */ -#define WMW(a,d) (M[(a)>>2]=d) /* write memory addressed word */ +#define RMW(a) (M[((a)&MASK24)>>2]) /* read memory addressed word */ +#define WMW(a,d) (M[((a)&MASK24)>>2]=d) /* write memory addressed word */ /* write halfword to memory address */ #define WMH(a,d) ((a)&2?(M[(a)>>2]=(M[(a)>>2]&LMASK)|((d)&RMASK)):(M[(a)>>2]=(M[(a)>>2]&RMASK)|((d)<<16))) /* write byte to memory */ -#define WMB(a,d) (M[(a)>>2]=(M[(a)>>2]&(~(0xff<<(8*(7-(a&3)))))|((d&0xff)<<(8*(7-(a&3)))))) +#define WMB(a,d) (M[(a)>>2]=(((M[(a)>>2])&(~(0xff<<(8*(7-(a&3))))))|((d&0xff)<<(8*(7-(a&3)))))) /* map register access macros */ /* The RMR and WMR macros are used to read/write the MAPC cache registers */ @@ -432,7 +436,7 @@ extern DEBTAB dev_debug[]; /* write halfword map register to MAP cache address */ #define WMR(a,d) ((a)&2?(MAPC[(a)>>2]=(MAPC[(a)>>2]&LMASK)|((d)&RMASK)):(MAPC[(a)>>2]=(MAPC[(a)>>2]&RMASK)|((d)<<16))) -/* Definitions for common used functions */ +/* Definitions for commonly used functions */ extern t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); extern t_stat show_dev_addr(FILE * st, UNIT *uptr, int32 v, CONST void *desc); extern void chan_end(uint16 chan, uint16 flags); @@ -449,4 +453,11 @@ extern CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer * extern uint32 M[]; /* our memory */ extern uint32 SPAD[]; /* cpu SPAD memory */ extern uint32 attention_trap; +extern uint32 RDYQ[]; /* ready queue */ +extern uint32 RDYQIN; /* input index */ +extern uint32 RDYQOUT; /* output index */ +#define RDYQ_SIZE 128 +extern int32 RDYQ_Put(uint32 entry); +extern int32 RDYQ_Get(uint32 *old); +extern int32 RDYQ_Num(void); diff --git a/SEL32/sel32_disk.c b/SEL32/sel32_disk.c index 7694c26..27194c1 100644 --- a/SEL32/sel32_disk.c +++ b/SEL32/sel32_disk.c @@ -272,12 +272,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 */ + {"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 */ + {"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 */ {NULL, 0} }; @@ -424,12 +424,12 @@ uint8 disk_preio(UNIT *uptr, uint16 chan) uint16 chsa = GET_UADDR(uptr->CMDu3); int unit = (uptr - dptr->units); - sim_debug(DEBUG_CMD, dptr, "disk_preio CMD %08x unit %02x\n", uptr->CMDu3, unit); - if ((uptr->CMDu3 & 0xff00) != 0) { /* just return if busy */ + sim_debug(DEBUG_DETAIL, dptr, "disk_preio CMD %08x unit %02x\n", uptr->CMDu3, unit); + if ((uptr->CMDu3 & 0xff00) != 0) { /* just return if busy */ return SNS_BSY; } - sim_debug(DEBUG_CMD, dptr, "disk_preio unit %02x chsa %04x OK\n", unit, chsa); + sim_debug(DEBUG_DETAIL, dptr, "disk_preio unit %02x chsa %04x OK\n", unit, chsa); return 0; /* good to go */ } @@ -450,10 +450,10 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) } if ((uptr->CMDu3 & DSK_CMDMSK) != 0) { - uptr->CMDu3 |= DSK_BUSY; /* Flag we are busy */ + uptr->CMDu3 |= DSK_BUSY; /* Flag we are busy */ return SNS_BSY; } - if ((uptr->CMDu3 & 0xff00) != 0) { /* if any status info, we are busy */ + if ((uptr->CMDu3 & 0xff00) != 0) { /* if any status info, we are busy */ return SNS_BSY; } sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD continue unit=%02x cmd %02x\n", unit, cmd); @@ -466,8 +466,9 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) "disk_startcmd starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n", uptr->u4, chsa, chp->ccw_addr, chp->ccw_count); - uptr->CMDu3 |= DSK_INCH2; /* use 0xf0 for inch, just need int */ - sim_activate(uptr, 20); /* start things off */ + uptr->CMDu3 |= DSK_INCH2; /* use 0xf0 for inch, just need int */ +//@ sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 40); /* start things off */ return 0; break; @@ -477,46 +478,53 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) case DSK_RD: /* Read command 0x02 */ case DSK_LMR: /* read mode register 0x15 */ - uptr->CMDu3 |= cmd; /* save cmd */ + uptr->CMDu3 |= cmd; /* save cmd */ sim_debug(DEBUG_CMD, dptr, "disk_startcmd starting disk seek r/w cmd %02x chsa %04x\n", cmd, chsa); - sim_activate(uptr, 20); /* start things off */ +//@ sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 40); /* start things off */ return 0; break; case DSK_NOP: /* NOP 0x03 */ - uptr->CMDu3 |= cmd; /* save cmd */ - sim_activate(uptr, 20); /* start things off */ + uptr->CMDu3 |= cmd; /* save cmd */ +//@ sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 40); /* start things off */ return 0; break; case DSK_SNS: /* Sense 0x04 */ - uptr->CMDu3 |= cmd; /* save cmd */ - sim_activate(uptr, 20); /* start things off */ + uptr->CMDu3 |= cmd; /* save cmd */ +//@ sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 40); /* start things off */ break; case DSK_WSL: /* WSL 0x31 */ - uptr->CMDu3 |= cmd; /* save cmd */ - sim_activate(uptr, 20); /* start things off */ + uptr->CMDu3 |= cmd; /* save cmd */ +//@ sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 40); /* start things off */ return 0; break; case DSK_RSL: /* RSL 0x32 */ - uptr->CMDu3 |= cmd; /* save cmd */ - sim_activate(uptr, 20); /* start things off */ + uptr->CMDu3 |= cmd; /* save cmd */ +//@ sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 40); /* start things off */ return 0; break; case DSK_WTL: /* WTL 0x51 */ - uptr->CMDu3 |= cmd; /* save cmd */ - sim_activate(uptr, 20); /* start things off */ + uptr->CMDu3 |= cmd; /* save cmd */ +//@ sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 40); /* start things off */ return 0; break; case DSK_RTL: /* RTL 0x52 */ - uptr->CMDu3 |= cmd; /* save cmd */ - sim_activate(uptr, 20); /* start things off */ + uptr->CMDu3 |= cmd; /* save cmd */ +//@ sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 40); /* start things off */ return 0; break; } @@ -524,9 +532,10 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) sim_debug(DEBUG_CMD, dptr, "disk_startcmd done with disk_startcmd %02x chsa %04x SNS %08x\n", cmd, chsa, uptr->SNS); - if (uptr->SNS & 0xff) /* any other cmd is error */ + if (uptr->SNS & 0xff) /* any other cmd is error */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - sim_activate(uptr, 20); /* start things off */ +//@ sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 40); /* start things off */ return SNS_CHNEND|SNS_DEVEND; } @@ -592,7 +601,7 @@ t_stat disk_srv(UNIT *uptr) if (len != 36) { /* we have invalid count, error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -607,7 +616,7 @@ t_stat disk_srv(UNIT *uptr) for (i=0; i < 36; i++) { if (chan_read_byte(chsa, &buf[i])) { /* we have error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -632,13 +641,13 @@ t_stat disk_srv(UNIT *uptr) #ifdef NOTYET if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ /* we have error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } #endif - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "disk_srv cmd INCH chsa %04x addr %06x count %04x completed\n", chsa, mema, chp->ccw_count); @@ -651,7 +660,7 @@ t_stat disk_srv(UNIT *uptr) break; case DSK_WSL: /* WSL 0x31 make into NOP */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "disk_srv cmd WSL chsa %04x count %04x completed\n", chsa, chp->ccw_count); @@ -662,7 +671,7 @@ t_stat disk_srv(UNIT *uptr) for (i = 0; i < len; i++) { if (chan_read_byte(chsa, &buf[i])) { /* we have write error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); //XXX goto goout; return SCPE_OK; @@ -703,7 +712,7 @@ t_stat disk_srv(UNIT *uptr) break; case DSK_NOP: /* NOP 0x03 */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "disk_srv cmd NOP chsa %04x count %04x completed\n", chsa, chp->ccw_count); @@ -734,7 +743,7 @@ t_stat disk_srv(UNIT *uptr) chan_write_byte(chsa, &ch); /* bytes 4 - mode reg, byte 0 of SNS */ - ch = (uptr->SNS >> 24) & 0xff; /* return the sense data */ + ch = (uptr->SNS >> 24) & 0xff; /* return the sense data */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv sense unit=%02x 1 %02x\n", unit, ch); chan_write_byte(chsa, &ch); @@ -784,7 +793,7 @@ t_stat disk_srv(UNIT *uptr) unit, ch); chan_write_byte(chsa, &ch); } - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; @@ -796,12 +805,11 @@ t_stat disk_srv(UNIT *uptr) /* we are on cylinder, seek is done */ sim_debug(DEBUG_CMD, dptr, "disk_srv seek on cylinder unit=%02x %04x %04x\n", unit, uptr->STAR >> 16, uptr->CHS >> 16); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ /* we have already seeked to the required sector */ /* we do not need to seek again, so move on */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); return SCPE_OK; -//XXX sim_activate(uptr, 20); break; } else { /* we have wasted enough time, we are there */ @@ -817,7 +825,8 @@ t_stat disk_srv(UNIT *uptr) } #endif uptr->CHS = uptr->STAR; /* we are there */ - sim_activate(uptr, 10); +//@ sim_activate(uptr, 10); + sim_activate(uptr, 20); break; } } @@ -884,7 +893,7 @@ t_stat disk_srv(UNIT *uptr) "disk_srv seek ERROR cyl %04x trk %02x sec %02x unit=%02x\n", cyl, trk, buf[3], unit); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; /* set error status */ /* we have an error, tell user */ @@ -915,17 +924,18 @@ t_stat disk_srv(UNIT *uptr) /* if not, do a delay to slow things down */ if (STAR2CYL(uptr->STAR) != STAR2CYL(uptr->CHS)) { /* Do a fake seek to kill time */ - uptr->CMDu3 |= DSK_SEEKING; /* show we are seeking */ + uptr->CMDu3 |= DSK_SEEKING; /* show we are seeking */ sim_debug(DEBUG_EXP, dptr, "disk_srv seeking unit=%02x to cyl %04x trk %02x sec %02x\n", unit, cyl, trk, buf[3]); - sim_activate(uptr, 20); /* start us off */ +//@ sim_activate(uptr, 20); /* start us off */ + sim_activate(uptr, 30); /* start us off */ } else { /* we are on cylinder/track/sector, so go on */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv done seeking to %04x cyl %04x trk %02x sec %02x\n", tstart, cyl, trk, buf[3]); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); } return SCPE_OK; @@ -936,14 +946,14 @@ t_stat disk_srv(UNIT *uptr) /* Do a seek to 0 */ uptr->STAR = 0; /* set STAR to 0, 0, 0 */ uptr->CHS = 0; /* set current CHS to 0, 0, 0 */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ - uptr->CMDu3 |= DSK_SCK; /* show as seek command */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 |= DSK_SCK; /* show as seek command */ tstart = 0; /* byte offset is 0 */ #ifdef NOT_NEEDED /* Read in 1 dummy character for length to inhibit SLI posting */ if (chan_read_byte(chsa, &buf[0])) { /* we have error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SCPE_OK; @@ -954,13 +964,13 @@ t_stat disk_srv(UNIT *uptr) /* just seek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ sim_debug(DEBUG_EXP, dptr, "disk_srv Error on seek to %04x\n", tstart); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SCPE_OK; } /* we are on cylinder/track/sector zero, so go on */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv done seek trk 0\n"); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); return SCPE_OK; #else @@ -975,28 +985,28 @@ t_stat disk_srv(UNIT *uptr) /* Read in 1 character of mode data */ if (chan_read_byte(chsa, &buf[0])) { /* we have error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x old %x new %x\n", unit, (uptr->SNS)&0xff, buf[0]); - uptr->CMDu3 &= LMASK; /* remove old cmd */ + uptr->CMDu3 &= LMASK; /* remove old cmd */ uptr->SNS &= MASK24; /* clear old mode data */ uptr->SNS |= (buf[0] << 24); /* save mode value */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; case DSK_RD: /* Read Data */ - if ((uptr->CMDu3 & DSK_READING) == 0) { /* see if we are reading data */ - uptr->CMDu3 |= DSK_READING; /* read from disk starting */ + if ((uptr->CMDu3 & DSK_READING) == 0) { /* see if we are reading data */ + uptr->CMDu3 |= DSK_READING; /* read from disk starting */ sim_debug(DEBUG_CMD, dptr, "DISK READ starting CMD %08x chsa %04x buffer %06x count %04x\n", uptr->CMDu3, chsa, chp->ccw_addr, chp->ccw_count); } - if (uptr->CMDu3 & DSK_READING) { /* see if we are reading data */ + if (uptr->CMDu3 & DSK_READING) { /* see if we are reading data */ cyl = STAR2CYL(uptr->CHS); /* get current cyl */ trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ sec = uptr->CHS & 0xff; /* get sec */ @@ -1013,7 +1023,7 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "Error %08x on read %04x of diskfile cyl %04x hds %02x sec %02x\n", len, ssize, cyl, trk, sec); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -1029,7 +1039,7 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_DATA, dptr, "DISK Read %04x bytes leaving %04x from diskfile /%04x/%02x/%02x\n", i, chp->ccw_count, cyl, trk, sec); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); return SCPE_OK; //XXX goto rddone; @@ -1061,9 +1071,10 @@ t_stat disk_srv(UNIT *uptr) // if (tstart >= CAPB(type)) { if (tstart >= (uint32)CAP(type)) { /* EOM reached, abort */ - sim_debug(DEBUG_CMD, dptr, "DISK Read reached EOM for read from disk @ /%04x/%02x/%02x\n", + sim_debug(DEBUG_CMD, dptr, + "DISK Read reached EOM for read from disk @ /%04x/%02x/%02x\n", STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->CHS = 0; /* reset cylinder position */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -1072,23 +1083,34 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_DATA, dptr, "DISK sector read complete, %x bytes to go from diskfile /%04x/%02x/%02x\n", chp->ccw_count, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); - sim_activate(uptr, 10); /* wait to read next sector */ +//@ sim_activate(uptr, 10); /* wait to read next sector */ + sim_activate(uptr, 30); /* wait to read next sector */ break; //XXXrddone: -//XXX uptr->CMDu3 &= ~(0xffff); /* remove old status bits & cmd */ +//XXX uptr->CMDu3 &= ~(0xffff); /* remove old status bits & cmd */ } break; case DSK_WD: /* Write Data */ - if ((uptr->CMDu3 & DSK_WRITING) == 0) { /* see if we are writing data */ - uptr->CMDu3 |= DSK_WRITING; /* write to disk starting */ - sim_debug(DEBUG_CMD, dptr, - "DISK WRITE starting unit=%02x CMD %02x\n", unit, uptr->CMDu3); - } - if (uptr->CMDu3 & DSK_WRITING) { /* see if we are writing data */ + if ((uptr->CMDu3 & DSK_WRITING) == 0) { /* see if we are writing data */ cyl = STAR2CYL(uptr->CHS); /* get current cyl */ trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ sec = uptr->CHS & 0xff; /* get sec */ + uptr->CMDu3 |= DSK_WRITING; /* write to disk starting */ + sim_debug(DEBUG_CMD, dptr, + "DISK WRITE starting unit=%02x CMD %02x write %4x from %06x to %03x/%02x/%02x\n", + unit, uptr->CMDu3, chp->ccw_count, chp->ccw_addr, cyl, trk, sec); + } + if (uptr->CMDu3 & DSK_WRITING) { /* see if we are writing data */ + cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ + sec = uptr->CHS & 0xff; /* get sec */ +#ifdef DO_DYNAMIC_DEBUG + if (cyl == 10 && trk == 3 && sec == 0 && + chp->ccw_count == 0x2000 && chp->ccw_addr == 0x1e7a40) + /* start debugging at test 46 of cn.mmm diag */ + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); +#endif /* get sector offset */ // tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)); tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); @@ -1096,10 +1118,10 @@ t_stat disk_srv(UNIT *uptr) /* process the next sector of data */ len = 0; /* used here as a flag for short read */ for (i=0; iCMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "DISK Wrote %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", ssize, cyl, trk, sec); @@ -1118,7 +1140,7 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "Error %08x on write %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", i, ssize, cyl, trk, sec); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -1126,7 +1148,7 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_DATA, dptr, "DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", ssize, cyl, trk, sec); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; } @@ -1145,15 +1167,14 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "DISK Write reached EOM for write to disk @ /%04x/%02x/%02x\n", STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ uptr->CHS = 0; /* reset cylinder position */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } - sim_activate(uptr, 10); /* keep writing */ +//@ sim_activate(uptr, 10); /* keep writing */ + sim_activate(uptr, 30); /* keep writing */ break; -//XXXwrdone: -//XXX uptr->CMDu3 &= ~(0xffff); /* remove old status bits & cmd */ } break; @@ -1232,7 +1253,7 @@ t_stat disk_srv(UNIT *uptr) for (i = 0; i < 30; i++) { if (chan_write_byte(chsa, &buf[i])) { /* we have write error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -1243,7 +1264,7 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_DETAIL, dptr, "\n"); /* command done */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd RSL done chsa %04x count %04x completed\n", chsa, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ @@ -1349,7 +1370,7 @@ t_stat disk_srv(UNIT *uptr) for (i = 0; i < 30; i++) { if (chan_write_byte(chsa, &buf[i])) { /* we have write error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -1360,7 +1381,7 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_DETAIL, dptr, "\n"); /* command done */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "disk_srv cmd RTL done chsa %04x count %04x completed\n", chsa, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ @@ -1369,7 +1390,7 @@ t_stat disk_srv(UNIT *uptr) default: sim_debug(DEBUG_CMD, dptr, "invalid command %02x unit %02x\n", cmd, unit); uptr->SNS |= SNS_CMDREJ; - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -1406,20 +1427,20 @@ t_stat disk_reset(DEVICE *dptr) int disk_format(UNIT *uptr) { int type = GET_TYPE(uptr->flags); DEVICE *dptr = get_dev(uptr); - uint32 ssize = disk_type[type].ssiz * 4; /* disk sector size in bytes */ - uint32 tsize = disk_type[type].spt; /* get track size in sectors */ - uint32 csize = disk_type[type].nhds * tsize; /* get cylinder size in sectors */ - uint32 cyl = disk_type[type].cyl; /* get # cylinders */ - uint32 cap = disk_type[type].cyl * csize; /* disk capacity in sectors */ - uint32 cylv = cyl; /* number of cylinders */ + uint32 ssize = disk_type[type].ssiz * 4; /* disk sector size in bytes */ + uint32 tsize = disk_type[type].spt; /* get track size in sectors */ + uint32 csize = disk_type[type].nhds * tsize; /* get cylinder size in sectors */ + uint32 cyl = disk_type[type].cyl; /* get # cylinders */ + uint32 cap = disk_type[type].cyl * csize; /* disk capacity in sectors */ + uint32 cylv = cyl; /* number of cylinders */ uint8 *buff; int i; /* last sector address of disk (cyl * hds * spt) - 1 */ - uint32 laddr = CAP(type) - 1; /* last sector of disk */ + uint32 laddr = CAP(type) - 1; /* last sector of disk */ /* last track address of disk (cyl * hds * spt) - spt */ - uint32 ltaddr = CAP(type)-SPT(type); /* last sector of disk */ + uint32 ltaddr = CAP(type)-SPT(type); /* last sector of disk */ /* get sector address of vendor defect table VDT */ /* put data = 0xf0000000 0xf4000000 */ @@ -1455,7 +1476,7 @@ int disk_format(UNIT *uptr) { 0,0x22c2813e,0,0x06020000,0xf4,0,0x431b1c,0, }; -#ifdef USEFORMPX +#ifdef USE_FOR_MPX { /* some values created by j.vfmt */ // 0xf003d14f,0x8a03cda0,0x9a03cdbf,0x8903cdc0, @@ -1530,7 +1551,7 @@ int disk_format(UNIT *uptr) { if ((sim_fwrite(buff, 1, csize*ssize, uptr->fileref)) != csize*ssize) { sim_debug(DEBUG_CMD, dptr, "Error on write to diskfile cyl %04x\n", cyl); - free(buff); /* free cylinder buffer */ + free(buff); /* free cylinder buffer */ buff = 0; return 1; } @@ -1545,7 +1566,7 @@ int disk_format(UNIT *uptr) { } fputc('\r', stderr); fputc('\n', stderr); - free(buff); /* free cylinder buffer */ + free(buff); /* free cylinder buffer */ buff = 0; /* byte swap the buffers for dmap and umap */ @@ -1664,29 +1685,29 @@ t_stat disk_attach(UNIT *uptr, CONST char *file) int type = GET_TYPE(uptr->flags); DEVICE *dptr = get_dev(uptr); t_stat r; - uint32 ssize; /* sector size in bytes */ + uint32 ssize; /* sector size in bytes */ uint8 buff[1024]; /* see if valid disk entry */ - if (disk_type[type].name == 0) { /* does the assigned disk have a name */ - detach_unit(uptr); /* no, reject */ - return SCPE_FMT; /* error */ + if (disk_type[type].name == 0) { /* does the assigned disk have a name */ + detach_unit(uptr); /* no, reject */ + return SCPE_FMT; /* error */ } /* have simulator attach the file to the unit */ if ((r = attach_unit(uptr, file)) != SCPE_OK) return r; - uptr->capac = CAP(type); /* disk capacity in sectors */ - ssize = SSB(type); /* get sector size in bytes */ + uptr->capac = CAP(type); /* disk capacity in sectors */ + ssize = SSB(type); /* get sector size in bytes */ sim_debug(DEBUG_CMD, dptr, "Disk %s cyl %d hds %d sec %d ssiz %d capacity %d\n", disk_type[type].name, disk_type[type].cyl, disk_type[type].nhds, disk_type[type].spt, ssize, uptr->capac); /* disk capacity */ if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ - detach_unit(uptr); /* if no space, error */ - return SCPE_FMT; /* error */ + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ } /* see if there is any data on sector zero of disk, if not format it */ @@ -1702,19 +1723,19 @@ t_stat disk_attach(UNIT *uptr, CONST char *file) fmt: /* format the drive */ if (disk_format(uptr)) { - detach_unit(uptr); /* if no space, error */ - return SCPE_FMT; /* error */ + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ } } /* there is data on sector 0, so already formatted */ if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ - detach_unit(uptr); /* detach if error */ - return SCPE_FMT; /* error */ + detach_unit(uptr); /* detach if error */ + return SCPE_FMT; /* error */ } /* start out at sector 0 */ - uptr->CHS = 0; /* set CHS to cyl/hd/sec = 0 */ + uptr->CHS = 0; /* set CHS to cyl/hd/sec = 0 */ sim_debug(DEBUG_CMD, dptr, "Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\n", @@ -1730,27 +1751,27 @@ fmt: /* detach a disk device */ t_stat disk_detach(UNIT *uptr) { - uptr->SNS = 0; /* clear sense data */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ - return detach_unit(uptr); /* tell simh we are done with disk */ + uptr->SNS = 0; /* clear sense data */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + return detach_unit(uptr); /* tell simh we are done with disk */ } /* boot from the specified disk unit */ t_stat disk_boot(int32 unit_num, DEVICE *dptr) { - UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */ + UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */ sim_debug(DEBUG_CMD, dptr, "Disk Boot dev/unit %x\n", GET_UADDR(uptr->CMDu3)); if ((uptr->flags & UNIT_ATT) == 0) { sim_debug(DEBUG_EXP, &mta_dev, "Disk Boot attach error dev/unit %04x\n", GET_UADDR(uptr->CMDu3)); - return SCPE_UNATT; /* attached? */ + return SCPE_UNATT; /* attached? */ } - SPAD[0xf4] = GET_UADDR(uptr->CMDu3); /* put boot device chan/sa into spad */ - SPAD[0xf8] = 0xF000; /* show as F class device */ + SPAD[0xf4] = GET_UADDR(uptr->CMDu3); /* put boot device chan/sa into spad */ + SPAD[0xf8] = 0xF000; /* show as F class device */ /* now boot the disk */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ return chan_boot(GET_UADDR(uptr->CMDu3), dptr); /* boot the ch/sa */ } @@ -1760,18 +1781,18 @@ t_stat disk_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { int i; - if (cptr == NULL) /* any disk name input? */ - return SCPE_ARG; /* arg error */ - if (uptr == NULL) /* valid unit? */ - return SCPE_IERR; /* no, error */ - if (uptr->flags & UNIT_ATT) /* is unit attached? */ - return SCPE_ALATT; /* no, error */ + if (cptr == NULL) /* any disk name input? */ + return SCPE_ARG; /* arg error */ + if (uptr == NULL) /* valid unit? */ + return SCPE_IERR; /* no, error */ + if (uptr->flags & UNIT_ATT) /* is unit attached? */ + return SCPE_ALATT; /* no, error */ /* now loop through the units and find named disk */ for (i = 0; disk_type[i].name != 0; i++) { if (strcmp(disk_type[i].name, cptr) == 0) { - uptr->flags &= ~UNIT_TYPE; /* clear the old UNIT type */ - uptr->flags |= SET_TYPE(i); /* set the new type */ + uptr->flags &= ~UNIT_TYPE; /* clear the old UNIT type */ + uptr->flags |= SET_TYPE(i); /* set the new type */ /* set capacity of disk in sectors */ uptr->capac = CAP(i); return SCPE_OK; diff --git a/SEL32/sel32_iop.c b/SEL32/sel32_iop.c index 1ecab77..a98733a 100644 --- a/SEL32/sel32_iop.c +++ b/SEL32/sel32_iop.c @@ -93,7 +93,7 @@ MTAB iop_mod[] = { }; UNIT iop_unit[] = { - {UDATA(&iop_srv, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7E00)}, /* Channel controller */ + {UDATA(&iop_srv, UNIT_IDLE|UNIT_DISABLE, 0), 0, UNIT_ADDR(0x7E00)}, /* Channel controller */ }; //DIB iop_dib = {NULL, iop_startcmd, NULL, NULL, NULL, iop_ini, iop_unit, iop_chp, NUM_UNITS_IOP, 0xff, 0x7e00,0,0,0}; @@ -163,7 +163,8 @@ uint8 iop_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) // set_inch(uptr, iop_chp[0].ccw_addr); /* new address */ uptr->u3 |= IOP_INCH2; /* save INCH command as 0xf0 */ - sim_activate(uptr, 20); /* go on */ +//@ sim_activate(uptr, 20); /* go on */ + sim_activate(uptr, 40); /* go on */ return 0; /* no status change */ break; @@ -172,7 +173,8 @@ uint8 iop_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (cmd & IOP_MSK); /* save NOP command */ - sim_activate(uptr, 20); /* TRY 07-13-19 */ +//@ sim_activate(uptr, 20); /* TRY 07-13-19 */ + sim_activate(uptr, 40); /* TRY 07-13-19 */ return 0; /* no status change */ break; @@ -182,8 +184,10 @@ uint8 iop_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) chan, cmd, uptr->u5); uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (cmd & IOP_MSK); /* save command */ - sim_activate(uptr, 20); /* force interrupt */ - return 0; /* no status change */ +//@ sim_activate(uptr, 20); /* force interrupt */ +/*UTX*/ sim_activate(uptr, 40); /* force interrupt */ +//UTX return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* not a valid cmd */ +/*UTX*/ return 0; /* no status change */ break; } diff --git a/SEL32/sel32_mfp.c b/SEL32/sel32_mfp.c index 620d8cc..13e6de8 100644 --- a/SEL32/sel32_mfp.c +++ b/SEL32/sel32_mfp.c @@ -94,7 +94,7 @@ MTAB mfp_mod[] = { }; UNIT mfp_unit[] = { - {UDATA(&mfp_srv, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7600)}, /* Channel controller */ + {UDATA(&mfp_srv, UNIT_IDLE|UNIT_DISABLE, 0), 0, UNIT_ADDR(0x7600)}, /* Channel controller */ }; //DIB mfp_dib = {NULL, mfp_startcmd, NULL, NULL, NULL, mfp_ini, mfp_unit, mfp_chp, NUM_UNITS_MFP, 0xff, 0x7e00,0,0,0}; @@ -164,7 +164,8 @@ uint8 mfp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) // set_inch(uptr, mfp_chp[0].ccw_addr); /* new address */ uptr->u3 |= MFP_INCH2; /* save INCH command as 0xf0 */ - sim_activate(uptr, 20); /* go on */ +//@ sim_activate(uptr, 20); /* go on */ + sim_activate(uptr, 40); /* go on */ return 0; /* no status change */ break; @@ -173,7 +174,8 @@ uint8 mfp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (cmd & MFP_MSK); /* save NOP command */ - sim_activate(uptr, 20); /* TRY 07-13-19 */ +//@ sim_activate(uptr, 20); /* TRY 07-13-19 */ + sim_activate(uptr, 40); /* TRY 07-13-19 */ return 0; /* no status change */ break; @@ -183,8 +185,10 @@ uint8 mfp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) chan, cmd, uptr->u5); uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (cmd & MFP_MSK); /* save command */ - sim_activate(uptr, 20); /* force interrupt */ - return 0; /* no status change */ +//@ sim_activate(uptr, 20); /* force interrupt */ +//@ sim_activate(uptr, 40); /* force interrupt */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* not a valid command */ +//WAS return 0; /* no status change */ break; } diff --git a/SEL32/sel32_mt.c b/SEL32/sel32_mt.c index 1e5ba37..76fe1a1 100644 --- a/SEL32/sel32_mt.c +++ b/SEL32/sel32_mt.c @@ -400,7 +400,15 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) /* UTX_needs_interrupt on NOP or INCH */ /* fall through */ case 0x01: /* Write command */ + if (cmd == 0x01) + sim_debug(DEBUG_EXP, &mta_dev, + "mt_startcmd WRITE chan %04x addr %06x cnt %04x\n", + chan, chp->ccw_addr, chp->ccw_count); case 0x02: /* Read command */ + if (cmd == 0x02) + sim_debug(DEBUG_EXP, &mta_dev, + "mt_startcmd READ chan %04x addr %06x cnt %04x\n", + chan, chp->ccw_addr, chp->ccw_count); case 0x0C: /* Read backward */ if (cmd != 0x03) /* if this is a nop do not zero status */ uptr->SNS = (uptr->SNS & 0x0000ff00); /* clear all but byte 2 */ @@ -414,15 +422,13 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->SNS |= (SNS_EOT); /* tape at EOM */ /* Fall through */ - case 0x4: /* Sense */ -#ifndef FIX_DIAG + case 0x04: /* Sense */ case 0x80: /* Unknown diag cmd with byte cnt of 0x0c */ #ifdef DO_DYNAMIC_DEBUG if ((cmd & 0xff) == 0x80) { /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); } -#endif #endif uptr->CMD &= ~(MT_CMDMSK); /* clear out last cmd */ uptr->CMD |= cmd & MT_CMDMSK; /* insert new cmd */ @@ -431,7 +437,8 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) mt_busy[GET_DEV_BUF(dptr->flags)] = 1; /* show we are busy */ sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd sense %08x return 0 chan %04x cmd %02x\n", uptr->SNS, chan, cmd); - sim_activate(uptr, 100); /* Start unit off */ +//@ sim_activate(uptr, 100); /* Start unit off */ + sim_activate(uptr, 150); /* Start unit off */ return 0; default: /* invalid command */ @@ -558,7 +565,7 @@ t_stat mt_srv(UNIT *uptr) } /* just dump data */ } -#ifdef CHANGE_FOR_UTX_TEST +#ifdef CHANGE_FOR_UTX_BTP_TEST /* a BTP uses a 41 word INCH memory buffer */ // for (i=0; i<41; i++) { for (i=0; i<9; i++) { @@ -577,7 +584,7 @@ t_stat mt_srv(UNIT *uptr) /* call set_inch() to setup inch buffer */ i = set_inch(uptr, mema); /* new address */ -#ifndef NOTYET +#ifdef NOTYET if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ /* we have error, bail out */ uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ @@ -614,13 +621,15 @@ t_stat mt_srv(UNIT *uptr) ch = (uptr->SNS >> 0) & 0xff; /* get sense byte 3 status */ sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 3 %02x\n", unit, ch); chan_write_byte(addr, &ch); /* write byte 3 */ -#ifdef TRYTHIS +#ifndef NO_HARDWARE_STATUS_FOR_DIAGS /* write zero extra status */ for (ch=4; ch < 0xc; ch++) { uint8 zc = 0; chan_write_byte(addr, &zc); /* write zero byte */ + sim_debug(DEBUG_CMD, &mta_dev, + "sense unit %02x byte %1x %02x\n", unit, ch, zc); } -#else +#else /* FOR UTX */ /* write status 2 more times */ ch = (uptr->SNS >> 24) & 0xff; /* get sense byte 0 status */ sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 0 %02x\n", unit, ch); @@ -684,12 +693,13 @@ t_stat mt_srv(UNIT *uptr) break; case MT_READ: /* 0x02 */ /* read a record from the device */ - sim_debug(DEBUG_DATA, &mta_dev, "mt_srv cmd 2 READ unit=%02x\n", unit); + sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv cmd 2 READ unit=%02x\n", unit); if (uptr->CMD & MT_READDONE) { /* is the read complete */ uptr->SNS &= ~(SNS_LOAD|SNS_EOT); /* reset BOT & EOT */ if (sim_tape_eot(uptr)) { /* see if at EOM */ uptr->SNS |= SNS_EOT; /* set EOT status */ } + uptr->CMD &= ~(MT_CMDMSK|MT_READDONE); /* clear all but readdone & cmd */ uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ mt_busy[bufnum] &= ~1; /* not busy anymore */ @@ -718,14 +728,17 @@ t_stat mt_srv(UNIT *uptr) /* Send character over to channel */ if (chan_write_byte(addr, &ch)) { - sim_debug(DEBUG_CMD, &mta_dev, "Read unit %02x EOR cnt %04x\n", unit, uptr->POS); + sim_debug(DEBUG_CMD, &mta_dev, + "Read unit %02x EOR cnt %04x hwm %04x\n", unit, uptr->POS, uptr->hwmark); /* If not read whole record, skip till end */ if ((uint32)uptr->POS < uptr->hwmark) { /* Send dummy character to force SLI */ chan_write_byte(addr, &ch); /* write the byte */ sim_debug(DEBUG_CMD, &mta_dev, "Read unit %02x send dump SLI\n", unit); +//@ sim_activate(uptr, (uptr->hwmark-uptr->POS) * 10); /* wait again */ sim_activate(uptr, (uptr->hwmark-uptr->POS) * 10); /* wait again */ uptr->CMD |= MT_READDONE; /* read is done */ +//NEW uptr->POS -= 1; /* uncount dummy char */ break; } sim_debug(DEBUG_CMD, &mta_dev, @@ -735,9 +748,9 @@ t_stat mt_srv(UNIT *uptr) mt_busy[bufnum] &= ~1; /* set not busy */ chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* return end status */ } else { - sim_debug(DEBUG_DATA, &mta_dev, + sim_debug(DEBUG_DETAIL, &mta_dev, "Read data @2 unit %02x cnt %04x ch %02x hwm %04x\n", unit, uptr->POS, ch, - uptr->hwmark); + uptr->hwmark); if ((uint32)uptr->POS >= uptr->hwmark) { /* In IRG */ /* Handle end of data record */ sim_debug(DEBUG_CMD, &mta_dev, @@ -749,10 +762,12 @@ t_stat mt_srv(UNIT *uptr) chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* return end status */ #else uptr->CMD |= MT_READDONE; /* read is done */ - sim_activate(uptr, 20); /* wait again */ +//@ sim_activate(uptr, 20); /* wait again */ + sim_activate(uptr, 40); /* wait again */ #endif } else - sim_activate(uptr, 20); /* wait again */ +//@ sim_activate(uptr, 20); /* wait again */ + sim_activate(uptr, 40); /* wait again */ } break; @@ -777,7 +792,8 @@ t_stat mt_srv(UNIT *uptr) sim_debug(DEBUG_CMD, &mta_dev, "Write mode data in unit %02x POS %04x ch %02x\n", unit, uptr->POS, ch); uptr->hwmark = uptr->POS; /* set high water mark */ - sim_activate(uptr, 20); /* wait time */ +//@ sim_activate(uptr, 20); /* wait time */ + sim_activate(uptr, 40); /* wait again */ } break; @@ -805,11 +821,12 @@ t_stat mt_srv(UNIT *uptr) } } else { mt_buffer[bufnum][uptr->POS++] = ch; - sim_debug(DEBUG_DATA, &mta_dev, "Write data unit=%02x %04x %02x\n", + sim_debug(DEBUG_DETAIL, &mta_dev, "Write data unit=%02x %04x %02x\n", unit, uptr->POS, ch); uptr->hwmark = uptr->POS; } - sim_activate(uptr, 20); +//@ sim_activate(uptr, 20); + sim_activate(uptr, 40); break; case MT_RDBK: /* 0x0C */ /* Read Backwards */ @@ -843,24 +860,26 @@ t_stat mt_srv(UNIT *uptr) if (chan_write_byte(addr, &ch)) { sim_debug(DEBUG_CMD, &mta_dev, "Read unit=%02x EOR cnt %04x\n", unit, uptr->POS); - /* If not read whole record, skip till end */ - if (uptr->POS >= 0) { - sim_activate(uptr, (uptr->POS) * 20); - uptr->CMD |= MT_READDONE; - return SCPE_OK; - } - uptr->CMD &= ~MT_CMDMSK; - mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_CHNEND|SNS_DEVEND); + /* If not read whole record, skip till end */ + if (uptr->POS >= 0) { +//@ sim_activate(uptr, (uptr->POS) * 20); + sim_activate(uptr, (uptr->POS) * 20); + uptr->CMD |= MT_READDONE; + return SCPE_OK; + } + uptr->CMD &= ~MT_CMDMSK; + mt_busy[bufnum] &= ~1; + chan_end(addr, SNS_CHNEND|SNS_DEVEND); } else { - sim_debug(DEBUG_DATA, &mta_dev, "Read data unit=%02x %04x %02x\n", + sim_debug(DEBUG_DETAIL, &mta_dev, "Read data unit=%02x %04x %02x\n", unit, uptr->POS, ch); if (uptr->POS == 0) { /* In IRG */ uptr->CMD &= ~MT_CMDMSK; mt_busy[bufnum] &= ~1; chan_end(addr, SNS_CHNEND|SNS_DEVEND); } else - sim_activate(uptr, 20); +//@ sim_activate(uptr, 20); + sim_activate(uptr, 40); } break; @@ -896,7 +915,8 @@ t_stat mt_srv(UNIT *uptr) return SCPE_OK; } uptr->POS++; - sim_activate(uptr, 50); +//@ sim_activate(uptr, 50); + sim_activate(uptr, 80); break; case 1: uptr->POS++; @@ -907,10 +927,12 @@ t_stat mt_srv(UNIT *uptr) if (r == MTSE_TMK) { uptr->POS++; sim_debug(DEBUG_CMD, &mta_dev, "MARK\n"); - sim_activate(uptr, 50); +//@ sim_activate(uptr, 50); + sim_activate(uptr, 80); } else { sim_debug(DEBUG_CMD, &mta_dev, "Backspace reclen %04x\n", reclen); - sim_activate(uptr, 50); +//@ sim_activate(uptr, 50); + sim_activate(uptr, 80); } break; case 2: @@ -945,12 +967,15 @@ t_stat mt_srv(UNIT *uptr) if (r == MTSE_TMK) { uptr->POS++; sim_debug(DEBUG_DETAIL, &mta_dev, "MARK\n"); - sim_activate(uptr, 50); +//@ sim_activate(uptr, 50); + sim_activate(uptr, 80); } else if (r == MTSE_BOT) { uptr->POS+= 2; - sim_activate(uptr, 50); +//@ sim_activate(uptr, 50); + sim_activate(uptr, 80); } else { - sim_activate(uptr, 20); +//@ sim_activate(uptr, 20); + sim_activate(uptr, 80); } break; case 2: /* File Mark */ @@ -971,7 +996,8 @@ t_stat mt_srv(UNIT *uptr) case 0: sim_debug(DEBUG_CMD, &mta_dev, "Skip rec entry unit=%02x ", unit); uptr->POS++; - sim_activate(uptr, 50); +//@ sim_activate(uptr, 50); + sim_activate(uptr, 80); break; case 1: uptr->POS++; @@ -981,14 +1007,17 @@ t_stat mt_srv(UNIT *uptr) uptr->POS = 3; uptr->SNS |= SNS_FMRKDT; /* file mark detected */ sim_debug(DEBUG_CMD, &mta_dev, "FSR MARK\n"); - sim_activate(uptr, 50); +//@ sim_activate(uptr, 50); + sim_activate(uptr, 80); } else if (r == MTSE_EOM) { uptr->POS = 4; uptr->SNS |= SNS_EOT; /* set EOT status */ - sim_activate(uptr, 50); +//@ sim_activate(uptr, 50); + sim_activate(uptr, 80); } else { sim_debug(DEBUG_CMD, &mta_dev, "FSR skipped %04x byte record\n", reclen); +//@ sim_activate(uptr, 10 + (10 * reclen)); sim_activate(uptr, 10 + (10 * reclen)); } break; @@ -1019,7 +1048,8 @@ t_stat mt_srv(UNIT *uptr) case 0: sim_debug(DEBUG_CMD, &mta_dev, "Skip file entry sense %08x unit %02x\n", uptr->SNS, unit); uptr->POS++; - sim_activate(uptr, 50); +//@ sim_activate(uptr, 50); + sim_activate(uptr, 80); break; case 1: sim_debug(DEBUG_CMD, &mta_dev, "Skip file unit=%02x\n", unit); @@ -1028,15 +1058,18 @@ t_stat mt_srv(UNIT *uptr) uptr->POS++; uptr->SNS |= SNS_FMRKDT; /* file mark detected */ sim_debug(DEBUG_CMD, &mta_dev, "FSF EOF MARK sense %08x\n", uptr->SNS); - sim_activate(uptr, 50); +//@ sim_activate(uptr, 50); + sim_activate(uptr, 80); } else if (r == MTSE_EOM) { uptr->SNS |= SNS_EOT; /* set EOT status */ sim_debug(DEBUG_CMD, &mta_dev, "FSF EOT sense %08x\n", uptr->SNS); uptr->POS+= 2; - sim_activate(uptr, 50); +//@ sim_activate(uptr, 50); + sim_activate(uptr, 80); } else { sim_debug(DEBUG_CMD, &mta_dev, "FSF skipped %04x byte record\n", reclen); - sim_activate(uptr, 50); +//@ sim_activate(uptr, 50); + sim_activate(uptr, 80); } break; case 2: @@ -1068,7 +1101,8 @@ t_stat mt_srv(UNIT *uptr) chan_end(addr, SNS_DEVEND|SNS_UNITEXP); } else { uptr->POS ++; - sim_activate(uptr, 500); +//@ sim_activate(uptr, 500); + sim_activate(uptr, 200); } break; case 1: diff --git a/SEL32/sel32_scsi.c b/SEL32/sel32_scsi.c index db24dc2..a8eab83 100644 --- a/SEL32/sel32_scsi.c +++ b/SEL32/sel32_scsi.c @@ -244,7 +244,7 @@ t_stat scsi_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *c const char *scsi_description (DEVICE *dptr); /* channel program information */ -CHANP sda_chp[NUM_UNITS_SCSI] = {0}; +CHANP sca_chp[NUM_UNITS_SCSI] = {0}; MTAB scsi_mod[] = { {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "TYPE", "TYPE", @@ -254,7 +254,7 @@ MTAB scsi_mod[] = { {0} }; -UNIT sda_unit[] = { +UNIT sca_unit[] = { /* SET_TYPE(2) SG120 */ {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x400)}, /* 0 */ {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x410)}, /* 1 */ @@ -266,17 +266,17 @@ UNIT sda_unit[] = { {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x470)}, /* 7 */ }; -//DIB sda_dib = {scsi_preio, scsi_startcmd, NULL, NULL, NULL, scsi_ini, sda_unit, sda_chp, NUM_UNITS_SCSI, 0x0f, 0x0400, 0, 0, 0}; +//DIB sca_dib = {scsi_preio, scsi_startcmd, NULL, NULL, NULL, scsi_ini, sca_unit, sca_chp, NUM_UNITS_SCSI, 0x0f, 0x0400, 0, 0, 0}; -DIB sda_dib = { +DIB sca_dib = { scsi_preio, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ scsi_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ scsi_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ - sda_unit, /* UNIT* units */ /* Pointer to units structure */ - sda_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + sca_unit, /* UNIT* units */ /* Pointer to units structure */ + sca_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ NUM_UNITS_SCSI, /* uint8 numunits */ /* number of units defined */ 0xF0, /* uint8 mask */ /* 16 devices - device mask */ 0x0400, /* uint16 chan_addr */ /* parent channel address */ @@ -285,12 +285,12 @@ DIB sda_dib = { {0} /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ }; -DEVICE sda_dev = { - "SDA", sda_unit, NULL, scsi_mod, +DEVICE sca_dev = { + "SCA", sca_unit, NULL, scsi_mod, NUM_UNITS_SCSI, 16, 24, 4, 16, 32, NULL, NULL, &scsi_reset, &scsi_boot, &scsi_attach, &scsi_detach, /* ctxt is the DIB pointer */ - &sda_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, + &sca_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, NULL, NULL, &scsi_help, NULL, NULL, &scsi_description }; @@ -330,7 +330,7 @@ DIB sdb_dib = { }; DEVICE sdb_dev = { - "SDB", sdb_unit, NULL, scsi_mod, + "SCB", sdb_unit, NULL, scsi_mod, NUM_UNITS_SCSI, 16, 24, 4, 16, 32, NULL, NULL, &scsi_reset, &scsi_boot, &scsi_attach, &scsi_detach, /* ctxt is the DIB pointer */ @@ -458,7 +458,7 @@ t_stat scsi_srv(UNIT *uptr) uint8 buf2[1024]; uint8 buf[1024]; - sim_debug(DEBUG_DETAIL, &sda_dev, + sim_debug(DEBUG_DETAIL, &sca_dev, "scsi_srv entry unit %02x CMD %08x chsa %04x count %04x %x/%x/%x \n", unit, uptr->CMD, chsa, chp->ccw_count, STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); @@ -917,7 +917,7 @@ void scsi_ini(UNIT *uptr, t_bool f) /* total sectors on disk */ uptr->capac = CAP(i); /* disk size in sectors */ - sim_debug(DEBUG_EXP, &sda_dev, "SDA init device %s on unit SDA%.1x cap %x\n", + sim_debug(DEBUG_EXP, &sca_dev, "SCA init device %s on unit SCA%.1x cap %x\n", dptr->name, GET_UADDR(uptr->CMD), uptr->CMD); } @@ -1022,12 +1022,12 @@ t_stat scsi_attach(UNIT *uptr, CONST char *file) { /* read in the 1st sector of the 'disk' */ if ((r = sim_fread(&buff[0], sizeof(uint8), ssize, uptr->fileref) != ssize)) { - sim_debug(DEBUG_CMD, &sda_dev, "Disk format fread ret = %04x\n", r); + sim_debug(DEBUG_CMD, &sca_dev, "Disk format fread ret = %04x\n", r); goto fmt; } if ((buff[0] | buff[1] | buff[2] | buff[3]) == 0) { - sim_debug(DEBUG_CMD, &sda_dev, + sim_debug(DEBUG_CMD, &sca_dev, "Disk format buf0 %02x buf1 %02x buf2 %02x buf3 %02x\n", buff[0], buff[1], buff[2], buff[3]); fmt: @@ -1045,12 +1045,12 @@ fmt: uptr->CHS = 0; /* set CHS to cyl/hd/sec = 0 */ - sim_debug(DEBUG_CMD, &sda_dev, + sim_debug(DEBUG_CMD, &sca_dev, "Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\n", scsi_type[type].name, CYL(type), HDS(type), SPT(type), SPC(type), CAP(type), CAPB(type)); - sim_debug(DEBUG_CMD, &sda_dev, "File %s attached to %s\r\n", + sim_debug(DEBUG_CMD, &sca_dev, "File %s attached to %s\r\n", file, scsi_type[type].name); set_devattn(addr, SNS_DEVEND); @@ -1068,7 +1068,7 @@ t_stat scsi_detach(UNIT *uptr) { t_stat scsi_boot(int32 unit_num, DEVICE *dptr) { UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */ - sim_debug(DEBUG_CMD, &sda_dev, "SCSI Disk Boot dev/unit %04x\n", GET_UADDR(uptr->CMD)); + sim_debug(DEBUG_CMD, &sca_dev, "SCSI Disk Boot dev/unit %04x\n", GET_UADDR(uptr->CMD)); SPAD[0xf4] = GET_UADDR(uptr->CMD); /* put boot device chan/sa into spad */ SPAD[0xf8] = 0xF000; /* show as F class device */ if ((uptr->flags & UNIT_ATT) == 0) diff --git a/SEL32/sel32_sys.c b/SEL32/sel32_sys.c index fc048ce..0c109bd 100644 --- a/SEL32/sel32_sys.c +++ b/SEL32/sel32_sys.c @@ -662,7 +662,8 @@ t_opcode optab[] = { { 0x2C0E, 0xFC0F, H|TYPE_F, "TRSC", }, /* Transfer Register to Scratchpad # * */ { 0x2C0F, 0xFC0F, H|TYPE_F, "TSCR", }, /* Transfer Scratchpad to Register # * */ { 0x3000, 0xFC0F, X|H|TYPE_F, "CALM", }, /* Call Monitor 32/55 # */ - { 0x3400, 0xFC08, N|TYPE_D, "LA", }, /* Load Address NBR Note! FW instruction */ +//FF{ 0x3400, 0xFC08, N|TYPE_D, "LA", }, /* Load Address NBR Note! FW instruction */ + { 0x3400, 0xFC00, N|TYPE_D, "LA", }, /* Load Address NBR Note! FW instruction */ { 0x3800, 0xFC0F, H|TYPE_F, "ADR", }, /* Add Register to Register # */ { 0x3801, 0xFC0F, H|TYPE_F, "ADRFW", }, /* Add Floating Point to Register # */ { 0x3802, 0xFC0F, B|H|TYPE_F, "MPR", }, /* Multiply Register BR # */