From e3e31337600d18aeaf9f53fd55411edb01df2826 Mon Sep 17 00:00:00 2001 From: AZBevier Date: Thu, 3 Dec 2020 20:25:20 -0700 Subject: [PATCH] SEL32: Add iocl processing support per device. SEL32: Correct booting from devices other than 800 & 1000. SEL32: Add label support to HSDP & UDP disk controllers. SEL32: Add ECC support to HSDP & UDP disks for diagnostics. --- SEL32/sel32_chan.c | 1378 +++++++++++++++++++++----------- SEL32/sel32_clk.c | 14 +- SEL32/sel32_com.c | 16 +- SEL32/sel32_con.c | 286 ++++--- SEL32/sel32_cpu.c | 1017 +++++++++++++----------- SEL32/sel32_defs.h | 163 ++-- SEL32/sel32_disk.c | 1786 ++++++++++++++++++++++++++++++++++------- SEL32/sel32_ec.c | 328 +++++++- SEL32/sel32_hsdp.c | 1900 +++++++++++++++++++++++++++++++++++++++----- SEL32/sel32_iop.c | 8 +- SEL32/sel32_lpr.c | 8 +- SEL32/sel32_mfp.c | 8 +- SEL32/sel32_mt.c | 16 +- SEL32/sel32_scfi.c | 1363 +++++++++++++++++++++++-------- SEL32/sel32_scsi.c | 25 +- SEL32/sel32_sys.c | 4 +- 16 files changed, 6323 insertions(+), 1997 deletions(-) diff --git a/SEL32/sel32_chan.c b/SEL32/sel32_chan.c index 134353b..ee6f673 100644 --- a/SEL32/sel32_chan.c +++ b/SEL32/sel32_chan.c @@ -65,7 +65,7 @@ /* 05 - Reset channel (RSCHNL) */ /* 06 - Halt I/O (HIO) */ /* 07 - Grab controller (GRIO) Not supported */ -/* 08 - Reset channel (RSCTL) */ +/* 08 - Reset controller (RSCTL) */ /* 09 - Enable write channel WCS (ECWCS) Not supported */ /* 0A - Unassigned */ /* 0B - Write channel WCS (WCWCS) Not supported */ @@ -82,16 +82,9 @@ uint32 channels = MAX_CHAN; /* maximum number of channel int subchannels = SUB_CHANS; /* maximum number of subchannel devices */ int irq_pend = 0; /* pending interrupt flag */ -#define GEERT_UNDO -#ifndef GEERT_UNDO -int ScanCycles = 0; -int DoNextCycles = 0; -#include -#endif - extern uint32 CPUSTATUS; /* CPU status word */ extern uint32 INTS[]; /* Interrupt status flags */ -extern uint32 TPSD[]; /*Temp save of PSD from memory 0&4 */ +extern uint32 TPSD[]; /* Temp save of PSD from memory 0&4 */ extern uint8 waitqcnt; /* # of instructions to xeq b4 int */ extern uint8 waitrdyq; /* # of instructions to xeq b4 rdy */ extern uint32 inbusy; @@ -101,8 +94,6 @@ DIB *dib_unit[MAX_DEV]; /* Pointer to Device info bl DIB *dib_chan[MAX_CHAN]; /* pointer to channel mux dib */ uint16 loading; /* set when booting */ -#define get_chan(chsa) ((chsa>>8)&0x7f) /* get channel number from ch/sa */ - /* forward definitions */ CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */ UNIT *find_unit_ptr(uint16 chsa); /* find unit pointer */ @@ -150,6 +141,7 @@ int16 post_csw(CHANP *chp, uint32 rstat); /* add an entry to the FIFO */ int32 FIFO_Put(uint16 chsa, uint32 entry) { + int32 num; /* number of entries */ DIB *dibp = dib_chan[get_chan(chsa)]; /* get DIB pointer for channel */ if (dibp == NULL) { sim_debug(DEBUG_EXP, &cpu_dev, @@ -158,19 +150,24 @@ int32 FIFO_Put(uint16 chsa, uint32 entry) } if (dibp->chan_fifo_in == ((dibp->chan_fifo_out-1+FIFO_SIZE) % FIFO_SIZE)) { + num = (dibp->chan_fifo_in - dibp->chan_fifo_out + FIFO_SIZE) % FIFO_SIZE; sim_debug(DEBUG_EXP, &cpu_dev, - "FIFO_Put ERR FIFO full for chsa %04x\n", chsa); + "FIFO_Put ERR FIFO full for chsa %04x count %02x\n", chsa, num); return -1; /* FIFO Full */ } dibp->chan_fifo[dibp->chan_fifo_in] = entry; /* add new entry */ dibp->chan_fifo_in += 1; /* next entry */ dibp->chan_fifo_in %= FIFO_SIZE; /* modulo FIFO size */ - return 0; /* all OK */ + num = (dibp->chan_fifo_in - dibp->chan_fifo_out + FIFO_SIZE) % FIFO_SIZE; +// sim_debug(DEBUG_EXP, &cpu_dev, +// "FIFO_Put FIFO put entry %04x for chsa %04x count %02x\n", entry, chsa, num); + return SCPE_OK; /* all OK */ } /* get the next entry from the FIFO */ int32 FIFO_Get(uint16 chsa, uint32 *old) { +// int32 num; /* number of entries */ DIB *dibp = dib_chan[get_chan(chsa)]; /* get DIB pointer for channel */ if (dibp == NULL) { sim_debug(DEBUG_EXP, &cpu_dev, @@ -185,7 +182,10 @@ int32 FIFO_Get(uint16 chsa, uint32 *old) *old = dibp->chan_fifo[dibp->chan_fifo_out]; /* get the next entry */ dibp->chan_fifo_out += 1; /* next entry */ dibp->chan_fifo_out %= FIFO_SIZE; /* modulo FIFO size */ - return 0; /* all OK */ +// num = (dibp->chan_fifo_in - dibp->chan_fifo_out + FIFO_SIZE) % FIFO_SIZE; +// sim_debug(DEBUG_EXP, &cpu_dev, +// "FIFO_Get FIFO get entry %04x for chsa %04x leaving count %02x\n", *old, chsa, num); + return SCPE_OK; /* all OK */ } /* get number of entries in FIFO for channel */ @@ -206,42 +206,109 @@ int32 FIFO_Num(uint16 chsa) /* add an entry to the RDYQ */ int32 RDYQ_Put(uint32 entry) { - /* see if FIFO is full */ +// int32 num; /* number of entries */ + /* see if RDYQ FIFO is full */ if (RDYQIN == ((RDYQOUT-1+RDYQ_SIZE) % RDYQ_SIZE)) { +// num = (RDYQIN - RDYQOUT + RDYQ_SIZE) % RDYQ_SIZE; /* number of entries */ +// sim_debug(DEBUG_XIO, &cpu_dev, "RDYQ_Put queue FULL count %02x\n", num); 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 */ +// num = (RDYQIN - RDYQOUT + RDYQ_SIZE) % RDYQ_SIZE; /* number of entries */ +// sim_debug(DEBUG_XIO, &cpu_dev, "RDYQ_Put entry %04x count %02x\n", entry, num); irq_pend = 1; /* do a scan */ #ifdef USE_RDYQ // waitrdyq = 5; //25waitrdyq = 2; waitrdyq = 1; /* wait at least 1 instruction */ #endif - return 0; /* all OK */ + return SCPE_OK; /* all OK */ } /* get the next entry from the RDYQ */ int32 RDYQ_Get(uint32 *old) { +// int32 num; /* number of entries */ /* 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 */ +// num = (RDYQIN - RDYQOUT + RDYQ_SIZE) % RDYQ_SIZE; /* number of entries */ +// sim_debug(DEBUG_XIO, &cpu_dev, "RDYQ_Get entry %04x leaving %02x\n", *old, num); + return SCPE_OK; /* all OK */ } /* get number of entries in RDYQ for channel */ int32 RDYQ_Num(void) { /* calc entries */ - return ((RDYQIN - RDYQOUT + RDYQ_SIZE) % RDYQ_SIZE); + int32 num = (RDYQIN - RDYQOUT + RDYQ_SIZE) % RDYQ_SIZE; /* number of entries */ +// sim_debug(DEBUG_XIO, &cpu_dev, "RDYQ_Num entres %04x\n", num); +// return ((RDYQIN - RDYQOUT + RDYQ_SIZE) % RDYQ_SIZE); + return num; +} + +/* add an entry to the IOCLQ */ +int32 IOCLQ_Put(IOCLQ *qptr, uint32 entry) +{ + int32 num; /* number of entries */ + if (qptr == NULL) { + sim_debug(DEBUG_EXP, &cpu_dev, "IOCLQ_Put ERROR NULL qptr\n"); + return -1; /* IOCLQ address error */ + } + + if (qptr->ioclq_in == ((qptr->ioclq_out-1+IOCLQ_SIZE) % IOCLQ_SIZE)) { + num = (qptr->ioclq_in - qptr->ioclq_out + IOCLQ_SIZE) % IOCLQ_SIZE; + sim_debug(DEBUG_EXP, &cpu_dev, "IOCLQ_Put ERROR IOCLQ full, entries %02x\n", num); + return -1; /* IOCLQ Full */ + } + qptr->ioclq_fifo[qptr->ioclq_in] = entry; /* add new entry */ + qptr->ioclq_in += 1; /* next entry */ + qptr->ioclq_in %= IOCLQ_SIZE; /* modulo IOCLQ size */ + num = (qptr->ioclq_in - qptr->ioclq_out + IOCLQ_SIZE) % IOCLQ_SIZE; +// sim_debug(DEBUG_XIO, &cpu_dev, "IOCLQ_Put entry %06x count %02x\n", entry, num); + return SCPE_OK; /* all OK */ +} + +/* get the next entry from the IOCLQ */ +int32 IOCLQ_Get(IOCLQ *qptr, uint32 *old) +{ +// int32 num; /* number of entries */ + if (qptr == NULL) { + sim_debug(DEBUG_EXP, &cpu_dev, "IOCLQ_Get ERROR NULL qptr\n"); + return -1; /* IOCLQ address error */ + } + + /* see if the IOCLQ is empty */ + if (qptr->ioclq_in == qptr->ioclq_out) { + sim_debug(DEBUG_EXP, &cpu_dev, "IOCLQ_Get IOCLQ empty\n"); + return -1; /* IOCLQ is empty, tell caller */ + } + *old = qptr->ioclq_fifo[qptr->ioclq_out]; /* get the next entry */ + qptr->ioclq_out += 1; /* next entry */ + qptr->ioclq_out %= IOCLQ_SIZE; /* modulo IOCLQ size */ +// num = (qptr->ioclq_in - qptr->ioclq_out + IOCLQ_SIZE) % IOCLQ_SIZE; +// sim_debug(DEBUG_XIO, &cpu_dev, "IOCLQ_Get entry %06x leaving %02x entries\n", *old, num); + return SCPE_OK; /* all OK */ +} + +/* get number of entries in IOCLQ for channel */ +int32 IOCLQ_Num(IOCLQ *qptr) +{ + int32 num = 0; /* number of entries */ + if (qptr == NULL) { + sim_debug(DEBUG_EXP, &cpu_dev, "IOCLQ_Num ERROR NULL qptr\n"); + return num; /* IOCLQ address error */ + } + /* calc entries */ + num = (qptr->ioclq_in - qptr->ioclq_out + IOCLQ_SIZE) % IOCLQ_SIZE; +// sim_debug(DEBUG_EXP, &cpu_dev, "IOCLQ_Num #entries %02x\n", num); + return num; /* one words/entry */ } /* Set INCH buffer address for channel */ @@ -314,7 +381,8 @@ uint32 find_int_lev(uint16 chsa) } inta = ((~spadent)>>16)&0x7f; /* get interrupt level */ - sim_debug(DEBUG_IRQ, &cpu_dev, +// sim_debug(DEBUG_IRQ, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "find_int_lev class F SPADC %08x chsa %04x lev %02x SPADI %08x INTS %08x\n", spadent, chsa, inta, SPAD[inta+0x80], INTS[inta]); return(inta); /* return the level*/ @@ -346,7 +414,8 @@ uint32 find_int_icb(uint16 chsa) "find_int_icb ERR chsa %04x icba %02x\n", chsa, icba); return 0; /* not found */ } - sim_debug(DEBUG_IRQ, &cpu_dev, +// sim_debug(DEBUG_IRQ, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "find_int_icb icba %06x SPADC %08x chsa %04x lev %02x SPADI %08x INTS %08x\n", icba, spadent, chsa, inta, SPAD[inta+0x80], INTS[inta]); return(icba); /* return the address */ @@ -455,7 +524,8 @@ int readbuff(CHANP *chp) "readbuff PCHK addr %08x to big mem %08x status %04x\n", addr, MEMSIZE, chp->chan_status); chp->chan_byte = BUFF_CHNEND; /* force channel end & busy */ -sim_debug(DEBUG_EXP, &cpu_dev, "readbuff BUFF_CHNEND chp %p chan_byte %04x\n", chp, chp->chan_byte); +//sim_debug(DEBUG_EXP, &cpu_dev, +//"readbuff BUFF_CHNEND chp %p chan_byte %04x\n", chp, chp->chan_byte); return 1; /* done, with error */ } chp->chan_buf = RMB(addr&MASK24); /* get 1 byte */ @@ -476,7 +546,8 @@ int writebuff(CHANP *chp) "writebuff PCHK addr %08x to big mem %08x status %04x\n", addr, MEMSIZE, chp->chan_status); chp->chan_byte = BUFF_CHNEND; /* force channel end & busy */ -sim_debug(DEBUG_EXP, &cpu_dev, "writebuff BUFF_CHNEND chp %p chan_byte %04x\n", chp, chp->chan_byte); +//sim_debug(DEBUG_EXP, &cpu_dev, +//"writebuff BUFF_CHNEND chp %p chan_byte %04x\n", chp, chp->chan_byte); return 1; } addr &= MASK24; /* good address, write the byte */ @@ -494,14 +565,45 @@ int32 load_ccw(CHANP *chp, int32 tic_ok) { uint32 word1 = 0; uint32 word2 = 0; - int docmd = 0; + int32 docmd = 0; + DIB *dibp = dib_unit[chp->chan_dev]; /* get the DIB pointer */ UNIT *uptr = chp->unitptr; /* get the unit ptr */ uint16 chan = get_chan(chp->chan_dev); /* our channel */ uint16 devstat = 0; + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw @%06x entry chan_status[%04x] %04x\n", chp->chan_caw, chan, chp->chan_status); + /* determine if channel DIB has a pre iocl processor */ + if (dibp->iocl_io != NULL) { /* NULL if no function */ + /* call the device controller to process the iocl */ + int32 tempa = dibp->iocl_io(chp, tic_ok); /* process IOCL */ + if (tempa != SCPE_OK) { /* see if OK */ + sim_debug(DEBUG_XIO, &cpu_dev, + "load_ccw iocl_io call return ERROR chan %04x cstat %01x\n", chan, tempa); + } else { + sim_debug(DEBUG_XIO, &cpu_dev, + "load_ccw iocl_io call return OK chan %04x cstat %01x\n", chan, tempa); + } + return tempa; /* just return status */ + } + /* check for valid iocd address if 1st iocd */ + if (chp->chan_info & INFO_SIOCD) { /* see if 1st IOCD in channel prog */ + if (chp->chan_caw & 0x3) { /* must be word bounded */ + sim_debug(DEBUG_XIO, &cpu_dev, + "load_ccw iocd bad address chan %02x caw %06x\n", + chan, chp->chan_caw); + /* the disk returns the bad iocl in sw1 */ + chp->ccw_addr = chp->chan_caw & MASK24; /* set the bad IOCL address */ + chp->chan_status |= STATUS_PCHK; /* program check for invalid iocd addr */ +//** uptr->SNS |= SNS_INAD; /* invalid address status */ + return 1; /* error return */ + } + } + loop: sim_debug(DEBUG_EXP, &cpu_dev, "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 & STATUS_ERROR) { /* check channel error status */ sim_debug(DEBUG_EXP, &cpu_dev, @@ -509,11 +611,13 @@ loop: return 1; } +#ifdef WHATISTHIS /* Check if we have status modifier set */ if (chp->chan_status & STATUS_MOD) { chp->chan_caw += 8; /* move to next IOCD */ chp->chan_status &= ~STATUS_MOD; /* turn off status modifier flag */ } +#endif /* Read in first CCW */ if (readfull(chp, chp->chan_caw, &word1) != 0) { /* read word1 from memory */ @@ -535,28 +639,67 @@ loop: "load_ccw @%06x read ccw chan %02x IOCD wd 1 %08x wd 2 %08x\n", chp->chan_caw, chan, word1, word2); -#ifdef FOR_DEBUG - if ((word2>>16) & (FLAG_CC|FLAG_DC)) { - uint32 word3 = 0; - uint32 word4 = 0; - readfull(chp, chp->chan_caw+8, &word3); /* read word3 from memory */ - readfull(chp, chp->chan_caw+12, &word4); /* read word4 from memory */ - sim_debug(DEBUG_XIO, &cpu_dev, - "load_ccw @%06x read ccw chan %02x IOCD wd 3 %08x wd 4 %08x\n", - chp->chan_caw, chan, word3, word4); + chp->chan_caw = (chp->chan_caw & 0xfffffc) + 8; /* point to next IOCD */ + chp->ccw_cmd = (word1 >> 24) & 0xff; /* set command from IOCD wd 1 */ + + if (!MEM_ADDR_OK(word1 & MASK24)) { /* see if memory address invalid */ + chp->chan_status |= STATUS_PCHK; /* bad, program check */ +//** uptr->SNS |= SNS_INAD; /* invalid address status */ + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw bad IOCD1 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + +#ifdef PROVIDE_FOR_DEVICE + /* validate the commands for the disk */ + switch (chp->ccw_cmd) { + case DSK_WD: case DSK_RD: case DSK_INCH: case DSK_NOP: case DSK_ICH: + case DSK_SCK: case DSK_XEZ: case DSK_LMR: case DSK_WSL: case DSK_RSL: + case DSK_IHA: case DSK_WTL: case DSK_RTL: case DSK_RAP: case DSK_TESS: + case DSK_FNSK: + /* reset status to on cyl & ready */ +// uptr->SNS2 = (SNS_UNR|SNS_ONC|SNS_USEL); + uptr->SNS2 = 0; + case DSK_SNS: + break; + default: + chp->chan_status |= STATUS_PCHK; /* program check for invalid cmd */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected */ + sim_debug(DEBUG_EXP, &cpu_dev, + "disk_iocl bad cmd chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ } #endif + chp->ccw_count = word2 & 0xffff; /* get 16 bit byte count from IOCD WD 2*/ + + if (chp->chan_info & INFO_SIOCD) { /* see if 1st IOCD in channel prog */ +//** /* 1st command can not be a TIC or NOP */ +//** if ((chp->ccw_cmd == 0x03) || (chp->ccw_cmd == CMD_TIC)) { + /* 1st command can not be a TIC */ + if (chp->ccw_cmd == CMD_TIC) { + chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ +//** uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw TIC/NOP bad cmd chan_status[%04x] %04x\n", + chan, chp->chan_status); + return 1; /* error return */ + } + } + /* TIC can't follow TIC or be first in command chain */ /* diags send bad commands for testing. Use all of op */ - if (((word1 >> 24) & 0xff) == CMD_TIC) { + if (chp->ccw_cmd == CMD_TIC) { if (tic_ok) { -/*25*/ if (((word1 & MASK24) == 0) || (word1 & 0x3)) { + if (((word1 & MASK24) == 0) || (word1 & 0x3)) { sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw tic cmd bad address chan %02x tic caw %06x IOCD wd 1 %08x\n", chan, chp->chan_caw, word1); chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ - chp->ccw_count = word2 & 0xffff; /* get 16 bit byte count from IOCD WD 2*/ +// chp->chan_caw = word1; /* get new IOCD address */ + chp->chan_caw = word1 & MASK24; /* get new IOCD address */ +//** uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ +//** uptr->SNS |= SNS_INAD; /* invalid address status */ return 1; /* error return */ } tic_ok = 0; /* another tic not allowed */ @@ -566,49 +709,61 @@ loop: chan, chp->chan_caw, word1); goto loop; /* restart the IOCD processing */ } +// chp->chan_caw = word1; /* get new IOCD address */ + chp->chan_caw = word1 & MASK24; /* get new IOCD address */ chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ +//** uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ +//** if (((word1 & MASK24) == 0) || (word1 & 0x3)) +//** uptr->SNS |= SNS_INAD; /* invalid address status */ sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw TIC ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); return 1; /* error return */ } - /* validate parts of IOCD that is reserved */ - if (word2 & 0x07ff0000) { - chp->chan_status |= STATUS_PCHK; /* program check for invalid iocd */ - sim_debug(DEBUG_EXP, &cpu_dev, - "load_ccw bad IOCD2 chan_status[%04x] %04x\n", chan, chp->chan_status); - return 1; /* error return */ - } - if (!MEM_ADDR_OK(word1 & MASK24)) { /* see if memory address invalid */ - chp->chan_status |= STATUS_PCHK; /* bad, program check */ - sim_debug(DEBUG_EXP, &cpu_dev, - "load_ccw bad IOCD1 chan_status[%04x] %04x\n", chan, chp->chan_status); - return 1; /* error return */ - } - /* Check if not chaining data */ - if ((chp->ccw_flags & FLAG_DC) == 0) { - chp->ccw_cmd = (word1 >> 24) & 0xff; /* not DC, so set command from IOCD wd 1 */ + /* Check if we had data chaining in previous iocd */ + if ((chp->chan_info & INFO_SIOCD) || /* see if 1st IOCD in channel prog */ + ((chp->ccw_flags & FLAG_DC) == 0)) { /* last IOCD have DC set? */ sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw @%06x DO CMD No DC, ccw_flags %04x cmd %02x\n", chp->chan_caw, chp->ccw_flags, chp->ccw_cmd); docmd = 1; /* show we have a command */ } - /* added next line 051220 */ - chp->chan_status = 0; /* clear status for next IOCD */ /* Set up for this command */ + chp->ccw_flags = (word2 >> 16) & 0xfc00; /* get flags from bits 0-6 of WD 2 of IOCD */ + chp->chan_status = 0; /* clear status for next IOCD */ /* make a 24 bit address */ chp->ccw_addr = word1 & MASK24; /* set the data/seek address */ - chp->chan_caw = (chp->chan_caw & 0xfffffc) + 8; /* point to next IOCD */ - chp->ccw_count = word2 & 0xffff; /* get 16 bit byte count from IOCD WD 2*/ - chp->chan_byte = BUFF_BUSY; /* busy & no bytes transferred yet */ -//sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw BUFF_BUSY chp %p chan_byte %04x\n", chp, chp->chan_byte); - chp->ccw_flags = (word2 >> 16) & 0xfc00; /* 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 */ } + /* validate parts of IOCD2 that is reserved, bits 5-15 */ + if (word2 & 0x07ff0000) { + chp->chan_status |= STATUS_PCHK; /* program check for invalid iocd */ + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw bad IOCD2 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + +#ifndef NOT_FOR_EVERYONE + /* DC can only be used with a read/write cmd */ + if (chp->ccw_flags & FLAG_DC) { +// if ((chp->ccw_cmd != DSK_RD) && (chp->ccw_cmd != DSK_WD)) { + if ((chp->ccw_cmd != 0x02) && (chp->ccw_cmd != 0x01)) { + chp->chan_status |= STATUS_PCHK; /* program check for invalid DC */ +//** uptr->SNS |= SNS_CHER; /* chaining error */ + sim_debug(DEBUG_EXP, &cpu_dev, + "disk_iocl DC ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + } +#endif + + chp->chan_byte = BUFF_BUSY; /* busy & no bytes transferred yet */ + sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw @%06x read docmd %01x addr %06x count %04x chan %04x ccw_flags %04x\n", chp->chan_caw, docmd, chp->ccw_addr, chp->ccw_count, chan, chp->ccw_flags); @@ -628,9 +783,10 @@ loop: /* call the device startcmd function to process the current command */ /* just replace device status bits */ + chp->chan_info &= ~INFO_CEND; /* show chan_end not called yet */ devstat = dibp->start_cmd(uptr, chan, chp->ccw_cmd); chp->chan_status = (chp->chan_status & 0xff00) | devstat; - chp->chan_info &= ~INFO_SIOCD; /* show not first IOCD in channel prog */ + chp->chan_info &= ~INFO_SIOCD; /* not first IOCD in channel prog */ sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw @%06x after start_cmd chan %04x status %08x count %04x\n", @@ -640,11 +796,10 @@ loop: if (chp->chan_status & (STATUS_ATTN|STATUS_ERROR)) { chp->chan_status |= STATUS_CEND; /* channel end status */ chp->ccw_flags = 0; /* no flags */ -// chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ -// chp->ccw_cmd = 0; /* stop IOCD processing */ -//25 chp->ccw_count = 0; /* make count zero */ +// /* see if chan_end already called */ +// if (chp->chan_byte == BUFF_NEXT) { /* see if chan_end already called */ - if (chp->chan_byte == BUFF_NEXT) { + if (chp->chan_info & INFO_CEND) { sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw BUFF_NEXT ERROR chp %p chan_byte %04x\n", chp, chp->chan_byte); @@ -663,6 +818,7 @@ loop: /* NOTE this code needed for MPX 1.X to run! */ /* see if command completed */ /* we have good status */ + /* TODO Test if chan_end called? */ if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { uint16 chsa = GET_UADDR(uptr->u3); /* get channel & sub address */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ @@ -671,7 +827,7 @@ loop: chp->chan_caw, FIFO_Num(chsa), chan, chp->chan_status, chp->ccw_count); } } - /* the device processor return OK (0), so wait for I/O to complete */ + /* the device processor returned OK (0), so wait for I/O to complete */ /* nothing happening, so return */ sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw @%06x return, chan %04x status %04x count %04x irq_pend %1x\n", @@ -697,7 +853,8 @@ int chan_read_byte(uint16 chsa, uint8 *data) if (chp->ccw_count == 0) { /* see if more data required */ if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if Data Chain */ chp->chan_byte = BUFF_CHNEND; /* buffer end too */ -sim_debug(DEBUG_EXP, &cpu_dev, "chan_read BUFF_CHNEND chp %p chan_byte %04x\n", chp, chp->chan_byte); +//sim_debug(DEBUG_EXP, &cpu_dev, +//"chan_read BUFF_CHNEND chp %p chan_byte %04x\n", chp, chp->chan_byte); sim_debug(DEBUG_XIO, &cpu_dev, "chan_read_byte no DC chan end, cnt %04x addr %06x chan %04x\n", chp->ccw_count, chp->ccw_addr, chan); @@ -725,6 +882,23 @@ sim_debug(DEBUG_EXP, &cpu_dev, "chan_read BUFF_CHNEND chp %p chan_byte %04x\n", sim_debug(DEBUG_DATA, &cpu_dev, "chan_read_byte transferred %02x\n", byte); chp->ccw_addr += 1; /* next byte address */ chp->ccw_count--; /* one char less to process */ +#ifdef CAUSES_HALT_ON_LOAD + /* see if count is zero now */ + if (chp->ccw_count == 0) { /* see if more data required */ + if ((chp->ccw_flags & FLAG_DC) != 0) { /* see if Data Chain */ + /* we have data chaining, process iocl */ + 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 IOCD loaded, cnt %04x addr %06x chan %04x\n", + chp->ccw_count, chp->ccw_addr, chan); + } + } +#endif return 0; /* good return */ } @@ -738,11 +912,29 @@ int test_write_byte_end(uint16 chsa) return 1; /* return done */ if (chp->ccw_count == 0) { if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if we have data chaining */ - chp->chan_status |= STATUS_CEND; /* no, end of data */ - chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ -sim_debug(DEBUG_EXP, &cpu_dev, "test_write_byte BUFF_CHNEND chp %p chan_byte %04x\n", chp, chp->chan_byte); +//1003 chp->chan_status |= STATUS_CEND; /* no, end of data */ +//1003 chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ +/*122320*/ chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ +//sim_debug(DEBUG_EXP, &cpu_dev, +//"test_write_byte BUFF_CHNEND chp %p chan_byte %04x\n", chp, chp->chan_byte); return 1; /* return done */ } +#ifdef OLD_WAY_112320 + else { + /* we have data chaining, process iocl */ + sim_debug(DEBUG_EXP, &cpu_dev, + "test_write_byte got DC, calling load_ccw chan %04x\n", chsa); + if (load_ccw(chp, 1)) { /* process data chaining */ + sim_debug(DEBUG_EXP, &cpu_dev, + "test_write_byte with DC error, cnt %04x addr %06x chan %04x\n", + chp->ccw_count, chp->ccw_addr, chsa); + return 1; /* return error */ + } + sim_debug(DEBUG_EXP, &cpu_dev, + "test_write_byte with DC IOCD loaded cnt %04x addr %06x chan %04x\n", + chp->ccw_count, chp->ccw_addr, chsa); + } +#endif } return 0; /* not done yet */ } @@ -780,7 +972,9 @@ int chan_write_byte(uint16 chsa, uint8 *data) "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 */ -sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte BUFF_CHNEND chp %p chan_byte %04x\n", chp, chp->chan_byte); + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_write_byte BUFF_CHNEND chp %p chan_byte %04x\n", + chp, chp->chan_byte); return 1; /* return done error */ } else { /* we have data chaining, process iocl */ @@ -802,7 +996,8 @@ sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte BUFF_CHNEND chp %p chan_byte %04 if (chp->ccw_flags & FLAG_SKIP) { chp->ccw_count--; /* decrement skip count */ chp->chan_byte = BUFF_BUSY; /* busy, but no data */ -sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte1 BUFF_BUSY chp %p chan_byte %04x\n", chp, chp->chan_byte); + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_write_byte1 BUFF_BUSY chp %p chan_byte %04x\n", chp, chp->chan_byte); if ((chp->ccw_cmd & 0xff) == CMD_RDBWD) chp->ccw_addr--; /* backward */ else @@ -823,6 +1018,28 @@ sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte1 BUFF_BUSY chp %p chan_byte %04x chp->ccw_addr -= 1; /* no, use previous address */ else chp->ccw_addr += 1; /* yes, use next address */ +#ifdef CAUSES_HALT_ON_LOAD + /* see if count is zero now */ + if (chp->ccw_count == 0) { + if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if we have data chaining */ + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_write_byte ZERO chan %04x ccw_count %04x addr %06x\n", + chan, chp->ccw_count, chp->ccw_addr); + /* we have data chaining, process iocl */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "chan_write_byte got DC, calling load_ccw chan %04x\n", chan); + 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 IOCD loaded cnt %04x addr %06x chan %04x\n", + chp->ccw_count, chp->ccw_addr, chan); + } + } +#endif return 0; } @@ -891,7 +1108,7 @@ void chan_end(uint16 chsa, uint16 flags) { sim_debug(DEBUG_XIO, &cpu_dev, "chan_end setting SLI chsa %04x count %04x ccw_flags %04x status %04x\n", chsa, chp->ccw_count, chp->ccw_flags, chp->chan_status); - chp->ccw_flags = 0; /* no flags */ + chp->ccw_flags = 0; /* no iocl flags */ } } @@ -915,7 +1132,8 @@ 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_BUSY; /* we are empty & still busy now */ -//sim_debug(DEBUG_EXP, &cpu_dev, "chan_end2 BUFF_BUSY chp %p chan_byte %04x\n", chp, chp->chan_byte); + + /* see if we have DC to finish */ while ((chp->ccw_flags & FLAG_DC)) { /* handle data chaining */ if (load_ccw(chp, 1)) /* continue channel program */ break; /* error */ @@ -925,7 +1143,6 @@ void chan_end(uint16 chsa, uint16 flags) { } } chp->chan_byte = BUFF_BUSY; /* we are empty & still busy now */ -//sim_debug(DEBUG_EXP, &cpu_dev, "chan_end3 BUFF_BUSY chp %p chan_byte %04x\n", chp, chp->chan_byte); sim_debug(DEBUG_XIO, &cpu_dev, "chan_end FIFO #%1x IOCL done chsa %04x ccw_flags %04x status %04x\n", FIFO_Num(chsa), chsa, chp->ccw_flags, chp->chan_status); @@ -957,14 +1174,23 @@ void chan_end(uint16 chsa, uint16 flags) { chsa, chp->chan_status, chp->chan_caw); /* Queue us to continue from cpu level */ chp->chan_byte = BUFF_NEXT; /* have main pick us up */ -// sim_debug(DEBUG_EXP, &cpu_dev, -// "chan_end4 BUFF_NEXT chp %p chan_byte %04x\n", chp, chp->chan_byte); + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_end set RDYQ %04x No CC BUFF_NEXT chp %p chan_byte %04x\n", + chsa, chp, chp->chan_byte); RDYQ_Put(chsa); /* queue us up */ } /* just return */ + goto goout; } else { - /* we have channel end and no CC flag, end command */ - chsa = chp->chan_dev; /* get the chan/sa */ + UNIT *uptr = chp->unitptr; /* get the unit ptr */ + DEVICE *dptr = get_dev(uptr); + uint16 chsa = GET_UADDR(uptr->u3); + int unit = (uptr-dptr->units); /* get the UNIT number */ + DIB* dibp = (DIB *)dptr->ctxt; /* get the DIB pointer */ + IOCLQ *qp = &dibp->ioclq_ptr[unit]; /* IOCLQ pointer */ + uint32 iocla; + + /* we have channel end and no CC flag, end this iocl command */ sim_debug(DEBUG_XIO, &cpu_dev, "chan_end chan end & no CC chsa %04x status %04x cmd %02x\n", chsa, chp->chan_status, chp->ccw_cmd); @@ -973,26 +1199,67 @@ void chan_end(uint16 chsa, uint16 flags) { /* 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_DETAIL, &cpu_dev, + sim_debug(DEBUG_CMD, &cpu_dev, "chan_end call store_csw dev/chan end chsa %04x cpustat %08x iocla %08x\n", chsa, CPUSTATUS, chp->chan_caw); } else { /* we are loading, so keep moving */ - sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_CMD, &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 channel FIFO to continue from cpu level */ chp->chan_byte = BUFF_DONE; /* we are done */ -//sim_debug(DEBUG_EXP, &cpu_dev, "chan_end1 BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); store_csw(chp); /* store the status */ /* change chan_byte to BUFF_POST */ chp->chan_byte = BUFF_POST; /* show done with data */ -//sim_debug(DEBUG_EXP, &cpu_dev, "chan_end2 BUFF_POST chp %p chan_byte %04x\n", chp, chp->chan_byte); - chp->chan_status = 0; /* no status anymore */ +// chp->chan_status = 0; /* no status anymore */ chp->ccw_cmd = 0; /* no command anymore */ + + if (chp->chan_status & STATUS_ERROR) { /* check channel error status */ + qp = &dibp->ioclq_ptr[unit]; /* IOCLQ pointer */ + /* we have an error, so delete all other IOCLQ entries */ + while ((dibp->ioclq_ptr != NULL) && (qp != NULL) && IOCLQ_Get(qp, &iocla) == SCPE_OK) { + sim_debug(DEBUG_XIO, &cpu_dev, + "$$ CHEND removed IOCL from IOCLQ processing chsa %04x iocla %06x\n", + chsa, iocla); + } + chp->chan_status = 0; /* no channel status yet */ + } else + /* no error, see if we have a queued IOCL to start */ + if ((dibp->ioclq_ptr != NULL) && (qp != NULL) && IOCLQ_Get(qp, &iocla) == SCPE_OK) { + /* channel not busy and ready to go, so start a new command */ + chp->chan_status = 0; /* no channel status yet */ + chp->chan_caw = iocla; /* get iocla address in memory */ + /* added 09/25/20 to fix hangs in iocl processing */ + chp->ccw_flags = 0; /* clear flags */ + + /* set status words in memory to first IOCD information */ + sim_debug(DEBUG_XIO, &cpu_dev, + "$$ CHEND start IOCL processing chsa %04x iocla %06x\n", + chsa, iocla); + + /* We are queueing the SIO */ + /* Queue us to continue IOCL from cpu level & make busy */ + chp->chan_byte = BUFF_NEXT; /* have main pick us up */ + chp->chan_info = INFO_SIOCD; /* show first IOCD in channel prog */ + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_end BUFF_NEXT chas %04x from IOCLQ chp %p chan_byte %04x\n", + chsa, chp, chp->chan_byte); + RDYQ_Put(chsa); /* queue us up */ + sim_debug(DEBUG_XIO, &cpu_dev, + "$$$ CHEND SIO queued chsa %04x iocla %06x IOCD1 %08x IOCD2 %08x\n", + chsa, iocla, RMW(iocla), RMW(iocla+4)); + +#ifndef TRY_UTX_DELAY + if (waitqcnt == 0) +// waitqcnt = 25; /* tell cpu to wait 20 instructions before int */ + waitqcnt = 20; /* tell cpu to wait 20 instructions before int */ +#endif + } } } +goout: sim_debug(DEBUG_XIO, &cpu_dev, "chan_end done chsa %04x chp %p status %08x chan_byte %02x\n", chsa, chp, chp->chan_status, chp->chan_byte); @@ -1013,7 +1280,12 @@ int16 post_csw(CHANP *chp, uint32 rstat) /* check channel FIFO for status to post */ if ((FIFO_Num(chsa)) && ((FIFO_Get(chsa, &sw1) == 0) && (FIFO_Get(chsa, &sw2) == 0))) { +#ifdef OLDCODE uint32 chan_icb = find_int_icb(chsa); /* get icb address */ +#else + /* get chan_icb address */ + uint32 chan_icb = RMW(SPAD[0xf1] + (chp->chan_int<<2)); +#endif if (chan_icb == 0) { sim_debug(DEBUG_EXP, &cpu_dev, @@ -1023,18 +1295,12 @@ int16 post_csw(CHANP *chp, uint32 rstat) } if (chp->chan_byte != BUFF_POST) { sim_debug(DEBUG_EXP, &cpu_dev, - "post_csw %04x CHP %p not BUFF_POST status, ERROR FIFO #%1x inch %06x chan_icb %06x\n", - chsa, chp, FIFO_Num(chsa), incha, chan_icb); + "post_csw %04x CHP %p not BUFF_POST byte %04x, ERROR FIFO #%1x inch %06x chan_icb %06x\n", + chsa, chp, chp->chan_byte, FIFO_Num(chsa), incha, chan_icb); } /* remove user specified bits */ sw2 &= ~rstat; /* remove bits */ /* we have status to post, do it now */ -#ifdef NOT_HERE_082420 - /* change status from BUFF_POST to BUFF_DONE */ - chp->chan_byte = BUFF_DONE; /* show done & not busy */ -#endif -//sim_debug(DEBUG_EXP, &cpu_dev, -//"post_csw BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); /* 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 */ @@ -1071,19 +1337,77 @@ void store_csw(CHANP *chp) sim_debug(DEBUG_XIO, &cpu_dev, "store_csw FIFO #%1x write chsa %04x sw1 %08x sw2 %08x incha %08x cmd %02x\n", FIFO_Num(chsa), chsa, stwd1, stwd2, chp->chan_inch_addr, chp->ccw_cmd); -#ifdef NOT_HERE_082420 - chp->chan_status = 0; /* no status anymore */ - chp->ccw_cmd = 0; /* no command anymore */ - /* we are done with SIO, but status still needs to be posted */ - /* UTX does not like waiting, so show we are done */ -//715chp->chan_byte = BUFF_DONE; /* show done with data */ - chp->chan_byte = BUFF_POST; /* show done with data */ -sim_debug(DEBUG_EXP, &cpu_dev, -"store_csw BUFF_POST chp %p chan_byte %04x\n", chp, chp->chan_byte); -#endif irq_pend = 1; /* wakeup controller */ } +/* check an XIO operation */ +/* logical chan channel number 0-7f */ +/* suba unit address within channel 0-ff */ +/* Condition codes to return 0-f as specified above */ +t_stat checkxio(uint16 lchsa, uint32 *status) { + DIB *dibp; /* device information pointer */ + UNIT *uptr; /* pointer to unit in channel */ + CHANP *chp; /* channel program pointer */ + uint16 lchan = get_chan(lchsa); /* get the logical channel number */ + DEVICE *dptr; /* DEVICE pointer */ + uint32 inta; + uint32 spadent; + uint16 rchan, rchsa; /* the real channel number */ + + sim_debug(DEBUG_CMD, &cpu_dev, "checkxio entry lchsa %04x\n", lchsa); + + /* get the device entry for the logical channel in SPAD */ + spadent = SPAD[lchan]; /* get spad device entry for logical channel */ + rchan = (spadent & 0x7f00) >> 8; /* get real channel */ + rchsa = (rchan << 8) | (lchsa & 0xff); /* get the read chan & suba */ + + dibp = dib_chan[rchan]; /* get DIB pointer for channel */ + if (dibp == 0) goto nothere; + + chp = dibp->chan_prg; /* find the chanp pointer */ + if (chp == 0) goto nothere; + + uptr = dibp->units; /* find pointer to 1st unit on channel */ + if (uptr == 0) { /* if no dib or unit ptr, CC3 on return */ +nothere: + *status = CC3BIT; /* not found, so CC3 */ + sim_debug(DEBUG_EXP, &cpu_dev, + "checkxio lchsa %04x rchan %04x is not found, CC3 return\n", lchsa, rchan); + return SCPE_OK; /* not found, CC3 */ + } + inta = ((~spadent)>>16)&0x7f; /* get channel interrupt level */ + chp->chan_int = inta; /* make sure it is set in channel */ + +#ifdef NOT_NEEDED + if (uptr->flags & UNIT_ATTABLE) { + sim_debug(DEBUG_EXP, &cpu_dev, + "checkxio rchsa %04x flags UNIT_ATTABLE %1x UNIT_ATT %1x UNIT_DIS %1x\n", + rchsa, (uptr->flags & UNIT_ATTABLE)?1:0, (uptr->flags & UNIT_ATT)?1:0, + (uptr->flags & UNIT_DIS)?1:0); + } +#endif + + /* check for the device being defined and attached in simh */ + if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { + sim_debug(DEBUG_EXP, &cpu_dev, + "checkxio lchsa %04x rchsa %04x is not attached, CC3 return\n", lchsa, rchsa); + *status = CC3BIT; /* not attached, so error CC3 */ + return SCPE_OK; /* not found, CC3 */ + } + + dptr = get_dev(uptr); /* pointer to DEVICE structure */ + /* try this as MFP says it returns 0 on OK */ + if (dptr->flags & DEV_CHAN) + *status = 0; /* CCs = 0, OK return */ + else + /* return CC1 for non iop/mfp devices */ +//1003 *status = CC1BIT; /* CCs = 1, not busy */ + *status = 0; /* CCs = 0, OK return */ + sim_debug(DEBUG_XIO, &cpu_dev, "checkxio lchsa %04x rchsa %04x done CC status %08x\n", + lchsa, rchsa, *status); + return SCPE_OK; /* No CC's all OK */ +} + /* SIO CC status returned to caller */ /* val condition */ /* 0 command accepted, will echo status - no CC's */ @@ -1103,96 +1427,6 @@ sim_debug(DEBUG_EXP, &cpu_dev, /* e unassigned */ /* f unassigned */ -/* check an XIO operation */ -/* chan channel number 0-7f */ -/* suba unit address within channel 0-ff */ -/* Condition codes to return 0-f as specified above */ -t_stat checkxio(uint16 chsa, uint32 *status) { - DIB *dibp; /* device information pointer */ - UNIT *uptr; /* pointer to unit in channel */ - uint32 chan_icb; /* Interrupt level context block address */ - CHANP *chp; /* channel program pointer */ - uint16 chan = get_chan(chsa); /* get the logical channel number */ - uint32 inta; - DEVICE *dptr; /* DEVICE pointer */ - - sim_debug(DEBUG_XIO, &cpu_dev, "checkxio entry chsa %04x\n", chsa); - - dibp = dib_chan[chan]; /* get DIB pointer for channel */ - if (dibp == 0) goto nothere; - - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - if (chp == 0) goto nothere; - - uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ - - if (uptr == 0) { /* if no dib or unit ptr, CC3 on return */ -nothere: - *status = CC3BIT; /* not found, so CC3 */ - sim_debug(DEBUG_EXP, &cpu_dev, - "checkxio chsa %04x is not found, CC3 return\n", chsa); - return SCPE_OK; /* not found, CC3 */ - } - - sim_debug(DEBUG_EXP, &cpu_dev, - "checkxio chsa %04x flags UNIT_ATTABLE %1x UNIT_ATT %1x UNIT_DIS %1x\n", - chsa, (uptr->flags & UNIT_ATTABLE)?1:0, (uptr->flags & UNIT_ATT)?1:0, - (uptr->flags & UNIT_DIS)?1:0); - - /* check for the device being defined and attached in simh */ - if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { - sim_debug(DEBUG_EXP, &cpu_dev, - "checkxio chsa %04x is not attached, CC3 return\n", chsa); - *status = CC3BIT; /* not attached, so error CC3 */ - return SCPE_OK; /* not found, CC3 */ - } - - inta = find_int_lev(chsa&0x7f00); /* Interrupt Level for channel */ - chan_icb = find_int_icb(chsa&0x7f00); /* Interrupt level context block address */ -// sim_debug(DEBUG_XIO, &cpu_dev, - sim_debug(DEBUG_DETAIL, &cpu_dev, - "checkxio int spad %08x icb %06x inta %02x chan %04x chan_byte %02x\n", - SPAD[inta+0x80], chan_icb, inta, chan, chp->chan_byte); - -#ifdef FOR_DEBUG_ONLY - /* get the address of the interrupt IVL in main memory */ - iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ - incha = RMW(chan_icb+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, incha, RMW(incha), RMW(incha+4)); -#endif - -#ifdef NOT_FOR_CHANNEL - /* check for a Command or data chain operation in progresss */ -//715 if (chp->chan_byte & BUFF_BUSY) { - if ((chp->chan_byte & BUFF_BUSY) && chp->chan_byte != BUFF_POST) { - sim_debug(DEBUG_EXP, &cpu_dev, - "checkxio busy return CC3&CC4 chsa %04x chp %p cmd %02x flags %04x byte %02x\n", - chsa, chp, chp->ccw_cmd, chp->ccw_flags, chp->chan_byte); - //TODO return busy status for EC device - //use same code as PPCI, but be busy - *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ - return SCPE_OK; /* just busy CC3&CC4 */ - } -#endif - - dptr = get_dev(uptr); /* pointer to DEVICE structure */ - /* try this as MFP says it returns 0 on OK */ - if (dptr->flags & DEV_CHAN) - *status = 0; /* CCs = 0, OK return */ - else - /* return CC1 for non iop/mfp devices */ - *status = CC1BIT; /* CCs = 1, not busy */ -// sim_debug(DEBUG_XIO, &cpu_dev, "checkxio done CC status %08x\n", *status); - return SCPE_OK; /* No CC's all OK */ -} - /* start an XIO operation */ /* when we get here the cpu has verified that there is a valid channel address */ /* and an interrupt entry in spad for the channel. The IOCL address in the ICB */ @@ -1200,24 +1434,49 @@ nothere: /* chan channel number 0-7f */ /* suba unit address within channel 0-ff */ /* Condition codes to return 0-f as specified above */ -t_stat startxio(uint16 chsa, uint32 *status) { +t_stat startxio(uint16 lchsa, uint32 *status) { DIB *dibp; /* device information pointer */ UNIT *uptr; /* pointer to unit in channel */ uint32 chan_icb; /* Interrupt level context block address */ uint32 iocla; /* I/O channel IOCL address int ICB */ CHANP *chp; /* channel program pointer */ - uint16 chan = get_chan(chsa); /* get the channel number */ - uint32 tempa, inta, incha; - uint32 word1, word2, cmd; + uint16 lchan = get_chan(lchsa); /* get the logical channel number */ + uint16 chsa; + uint32 tempa, inta, spadent, chan, incha; + uint32 word1, word2, cmd, itva; + DEVICE *dptr; - sim_debug(DEBUG_XIO, &cpu_dev, "startxio entry chsa %04x\n", chsa); -#ifdef DEBUG_DISK - chan_icb = find_int_icb(chsa); /* Interrupt level context block address */ + sim_debug(DEBUG_XIO, &cpu_dev, "startxio entry logical chsa %04x\n", lchsa); + + /* get the device entry for the logical channel in SPAD */ + spadent = SPAD[lchan]; /* get spad device entry for logical channel */ + inta = ((~spadent)>>16)&0x7f; /* get interrupt level */ + chan = (spadent & 0x7f00) >> 8; /* get real channel */ + chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ + sim_debug(DEBUG_XIO, &cpu_dev, + "startxio entry inta %02x lchan %04x spadent %08x rchsa %04x\n", + inta, lchan, spadent, chsa); + dibp = dib_unit[chsa & 0x7f00]; /* get the device information pointer */ + chp = find_chanp_ptr(chsa); /* find the chanp pointer */ +// uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ + + uptr = find_unit_ptr(chsa&0x7f00); /* get unit 0 unit pointer */ + if (uptr != NULL) { + dptr = get_dev(uptr); /* get device address */ + if ((dptr != NULL) && + (DEV_TYPE(dptr) == DEV_DISK)) { /* see if this is a disk */ + chsa = chsa & 0x7ffe; /* clear the odd subaddress */ + } + } +#ifndef DEBUG_DISK +// chan_icb = find_int_icb(lchsa); /* Interrupt level context block address */ + itva = SPAD[0xf1] + (inta<<2); /* int vector address */ + chan_icb = RMW(itva); /* Interrupt context block addr */ iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ incha = RMW(chan_icb+20); /* post inch addr in ICB+5w */ sim_debug(DEBUG_XIO, &cpu_dev, - "startxio debug chsa %04x iocla %06x incha %06x IOCD1 %08x IOCD2 %08x\n", - chsa, iocla, incha, RMW(iocla), RMW(iocla+4)); + "startxio debug itva %04x icba %04x iocla %06x incha %06x IOCD1 %08x IOCD2 %08x\n", + itva, chan_icb, iocla, incha, RMW(iocla), RMW(iocla+4)); #endif /* check if we have a valid unit */ dibp = dib_chan[chan]; /* get DIB pointer for channel */ @@ -1236,6 +1495,9 @@ missing: return SCPE_OK; /* not found, CC3 */ } + inta = ((~spadent)>>16)&0x7f; /* get channel interrupt level */ + chp->chan_int = inta; /* make sure it is set in channel */ + sim_debug(DEBUG_EXP, &cpu_dev, "startxio chsa %04x chp %p flags UNIT_ATTABLE %1x UNIT_ATT %1x UNIT_DIS %1x\n", chsa, chp, (uptr->flags & UNIT_ATTABLE)?1:0, (uptr->flags & UNIT_ATT)?1:0, @@ -1249,7 +1511,7 @@ missing: return SCPE_OK; /* not found, CC3 */ } - inta = find_int_lev(chsa); /* Interrupt Level for channel */ +// inta = find_int_lev(chsa); /* Interrupt Level for channel */ #ifndef FOR_DEBUG if ((INTS[inta]&INTS_ACT) || (SPAD[inta+0x80]&SINT_ACT)) { /* look for level active */ /* just output a warning */ @@ -1259,7 +1521,6 @@ missing: } #endif -#ifndef NOTHERE /* check for a Command or data chain operation in progresss */ if ((chp->chan_byte & BUFF_BUSY) && chp->chan_byte != BUFF_POST) { uint16 tstat = chp->chan_status; /* save status */ @@ -1270,7 +1531,9 @@ missing: "startxio busy return CC3&CC4 chsa %04x chp %p cmd %02x flags %04x byte %02x\n", chsa, chp, chp->ccw_cmd, chp->ccw_flags, chp->chan_byte); /* ethernet controller wants an interrupt for busy status */ - if (DEV_TYPE(dptr) == DEV_ETHER) { + if ((dptr != NULL) && + (DEV_TYPE(dptr) == DEV_ETHER)) { /* see if this is ethernet */ +// if (DEV_TYPE(dptr) == DEV_ETHER) { *status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */ /* handle an Ethernet controller busy by sending interrupt/status */ chp->chan_status = STATUS_BUSY|STATUS_CEND|STATUS_DEND; /* set busy status */ @@ -1281,23 +1544,21 @@ missing: sim_debug(DEBUG_XIO, &cpu_dev, "startxio done BUSY/INT chp %p chsa %04x ccw_flags %04x stat %04x cnt %04x\n", chp, chsa, chp->ccw_flags, tstat, tcnt); - } else { + return SCPE_OK; /* just busy CC3&CC4 */ + } +#ifdef NOTHERE + else { /* everyone else just gets a busy return */ *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ sim_debug(DEBUG_XIO, &cpu_dev, "startxio done BUSY chp %p chsa %04x ccw_flags %04x stat %04x cnt %04x\n", chp, chsa, chp->ccw_flags, tstat, tcnt); } -#ifdef DO_DYNAMIC_DEBUG - /* start debugging */ - if (chsa == 0x0c00) - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_TRAP | DEBUG_EXP | DEBUG_IRQ); -#endif return SCPE_OK; /* just busy CC3&CC4 */ - } #endif + } - chan_icb = find_int_icb(chsa); /* Interrupt level context block address */ +// chan_icb = find_int_icb(chsa); /* Interrupt level context block address */ sim_debug(DEBUG_XIO, &cpu_dev, "startxio int spad %08x icb %06x inta %02x chan %04x\n", SPAD[inta+0x80], chan_icb, inta, chan); @@ -1306,7 +1567,7 @@ missing: /* before calling load_ccw which does it again for each IOCL step */ iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ word1 = RMW(iocla & MASK24); /* get 1st IOCL word */ - incha = word1 & MASK24; /* should be inch addr */ +// incha = word1 & MASK24; /* should be inch addr */ word2 = RMW((iocla + 4) & MASK24); /* get 2nd IOCL word */ cmd = (word1 >> 24) & 0xff; /* get channel cmd from IOCL */ chp = find_chanp_ptr(chsa&0x7f00); /* find the parent chanp pointer */ @@ -1322,29 +1583,78 @@ missing: "startxio test chsa %04x iocla %06x IOCD1 %08x IOCD2 %08x\n", chsa, iocla, RMW(iocla), RMW(iocla+4)); + iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ +// incha = chp->chan_inch_addr; /* get inch address */ + sim_debug(DEBUG_CMD, &cpu_dev, "$$$ SIO %04x %04x cmd %02x ccw_flags %04x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags); + chsa, chan, cmd, word2>>16); /* determine if channel DIB has a pre startio command processor */ if (dibp->pre_io != NULL) { /* NULL if no startio function */ + DEVICE *dptr = get_dev(uptr); /* get device ptr */ + int unit = uptr-dptr->units; /* get unit number */ /* call the device controller to get prestart_io status */ tempa = dibp->pre_io(uptr, chan); /* get status from device */ - if (tempa != SCPE_OK) { /* see if sub channel status is ready */ + /* SCPE_OK if unit not busy and IOCLQ is not full */ + /* SNS_BSY if unit IOCLQ is full */ + /* SNS_SMS if unit IOCLQ is not full, but device is busy */ + if (tempa == SNS_BSY) { /* 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); + "startxio pre_io call return busy1 chan %04x cstat %08x\n", chan, tempa); *status = CC3BIT|CC4BIT; /* sub channel busy, so CC3|CC4 */ return SCPE_OK; /* just busy or something, CC3|CC4 */ } + if (tempa == SNS_SMS) { /* see if sub channel status is ready */ + if (dibp->ioclq_ptr == NULL) { /* see if device has IOCL queue */ + /* The device must be busy or something, but it is not ready. Return busy */ + /* This should not happen for SNS_SMS status */ + sim_debug(DEBUG_XIO, &cpu_dev, + "startxio pre_io call return busy2 chan %04x cstat %08x\n", chan, tempa); + *status = CC3BIT|CC4BIT; /* sub channel busy, so CC3|CC4 */ + return SCPE_OK; /* just busy or something, CC3|CC4 */ + } + /* device has IOCLQ, queue up the iocla */ + if (IOCLQ_Put(&dibp->ioclq_ptr[unit], iocla) == -1) { + sim_debug(DEBUG_XIO, &cpu_dev, + "startxio IOCLQ_Put error return chsa %04x unit %02x\n", chsa, unit); + *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 IOCLQ call sucessful chan %04x unit %02x\n", + chan, unit); + *status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */ + return SCPE_OK; /* CC1 all OK */ + } + /* device is not busy */ sim_debug(DEBUG_XIO, &cpu_dev, "startxio pre_io call return not busy chan %04x cstat %08x\n", chan, tempa); + } else + + /* check for a Command or data chain operation in progresss */ + if ((chp->chan_byte & BUFF_BUSY) && chp->chan_byte != BUFF_POST) { + uint16 tstat = chp->chan_status; /* save status */ + uint16 tcnt = chp->ccw_count; /* save count */ + + sim_debug(DEBUG_EXP, &cpu_dev, + "startxio busy return CC3&CC4 chsa %04x chp %p cmd %02x flags %04x byte %02x\n", + chsa, chp, chp->ccw_cmd, chp->ccw_flags, chp->chan_byte); + /* everyone else just gets a busy return */ + *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ + sim_debug(DEBUG_XIO, &cpu_dev, + "startxio done BUSY chp %p chsa %04x ccw_flags %04x stat %04x cnt %04x\n", + chp, chsa, chp->ccw_flags, tstat, tcnt); + return SCPE_OK; /* just busy CC3&CC4 */ } /* channel not busy and ready to go, so start a new command */ chp->chan_int = inta; /* save interrupt level in channel */ chp->chan_status = 0; /* no channel status yet */ chp->chan_caw = iocla; /* get iocla address in memory */ + /* added 09/25/20 to fix hangs in iocl processing */ + chp->ccw_flags = 0; /* clear flags */ /* set status words in memory to first IOCD information */ sim_debug(DEBUG_XIO, &cpu_dev, @@ -1363,12 +1673,11 @@ missing: chsa, iocla, RMW(iocla), RMW(iocla+4)); #ifndef TRY_UTX_DELAY + /* a value < 25 gets error ioi: sio at 801 failed, cc2 in UTX 21B */ if (waitqcnt == 0) // waitqcnt = 20; /* tell cpu to wait 20 instructions before int */ waitqcnt = 25; /* tell cpu to wait 20 instructions before int */ -// waitqcnt = 30; /* tell cpu to wait 20 instructions before int */ // waitqcnt = 35; /* tell cpu to wait 20 instructions before int */ -// waitqcnt = 50; /* tell cpu to wait 20 instructions before int */ #endif *status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */ @@ -1378,19 +1687,28 @@ missing: } /* TIO - I/O status */ -t_stat testxio(uint16 chsa, uint32 *status) { /* test XIO */ +t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */ DIB *dibp; /* device information pointer */ UNIT *uptr; /* pointer to unit in channel */ uint32 chan_icb; /* Interrupt level context block address */ - uint32 iocla; /* I/O channel IOCL address int ICB */ +// uint32 iocla; /* I/O channel IOCL address int ICB */ CHANP *chp; /* Channel prog pointers */ - uint16 chan = get_chan(chsa); /* get the channel number */ - uint32 inta, incha; + uint32 inta, incha, itva; + uint16 lchan = get_chan(lchsa); /* get the logical channel number */ + uint32 spadent; + uint16 rchan, rchsa; /* the real channel number, chsa */ + + lchsa &= 0x7f00; /* use just chan and sa of 0 */ + /* get the real channel entry for the logical channel in SPAD */ + spadent = SPAD[lchan]; /* get spad device entry for logical channel */ + rchsa = (spadent & 0x7f00); /* get real channel suba of zero */ + rchan = rchsa >> 8; /* get real channel */ + + sim_debug(DEBUG_XIO, &cpu_dev, "$$ TIO entry lchsa %04x rchsa %02x\n", lchsa, rchsa); - sim_debug(DEBUG_XIO, &cpu_dev, "testxio entry chsa %04x\n", chsa); /* get the device entry for the channel in SPAD */ - dibp = dib_unit[chsa]; /* get the DIB pointer */ - chp = find_chanp_ptr(chsa); /* find the device chanp pointer */ + dibp = dib_chan[rchan]; /* get the DIB pointer */ + chp = find_chanp_ptr(rchan << 8); /* find the device chanp pointer */ #ifndef TRY_UTX_DELAY if (waitqcnt != 0) @@ -1399,89 +1717,137 @@ t_stat testxio(uint16 chsa, uint32 *status) { /* test XIO */ if (dibp == 0 || chp == 0) { /* if no dib or channel ptr, CC3 return */ *status = CC3BIT; /* not found, so CC3 */ sim_debug(DEBUG_EXP, &cpu_dev, - "testxio chsa %04x device not present, CC3 returned\n", chsa); + "TIO lchsa %04x rchsa %04x device not present, CC3 returned\n", lchsa, rchsa); return SCPE_OK; /* Not found, CC3 */ } - uptr = chp->unitptr; /* get the unit ptr */ - if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ + uptr = chp->unitptr; /* get the unit 0 ptr */ + /* is unit attached? */ + if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { *status = CC3BIT; /* not attached, so error CC3 */ sim_debug(DEBUG_EXP, &cpu_dev, - "testxio chsa %04x device not attached, CC3 returned\n", chsa); + "TIO lchsa %04x rchsa %04x device not attached, CC3 returned\n", lchsa, rchsa); return SCPE_OK; /* Not found, CC3 */ } - /* check for a Command or data chain operation in progresss */ +#ifdef NOT_HERE + /* check for a Command or data chain operation in progress */ if ((chp->chan_byte & BUFF_BUSY) && chp->chan_byte != BUFF_POST) { sim_debug(DEBUG_EXP, &cpu_dev, - "testxio busy return CC3&CC4 chsa %04x chp %p cmd %02x flags %04x byte %02x\n", + "TIO busy return CC3&CC4 chsa %04x chp %p cmd %02x flags %04x byte %02x\n", chsa, chp, chp->ccw_cmd, chp->ccw_flags, chp->chan_byte); *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ return SCPE_OK; /* just busy CC3&CC4 */ } +#endif /* the XIO opcode processing software has already checked for F class */ - inta = find_int_lev(chsa); /* Interrupt Level for channel */ - chan_icb = find_int_icb(chsa); /* Interrupt level context block address */ + inta = ((~spadent)>>16)&0x7f; /* get channel interrupt level */ + chp->chan_int = inta; /* make sure it is set in channel */ + itva = SPAD[0xf1] + (inta<<2); /* int vector address */ + chan_icb = RMW(itva); /* Interrupt context block addr */ +// inta = find_int_lev(chsa); /* Interrupt Level for channel */ +// chan_icb = find_int_icb(chsa); /* Interrupt level context block address */ sim_debug(DEBUG_XIO, &cpu_dev, - "testxio int spad %08x icb %06x inta %04x chan %04x\n", - SPAD[inta+0x80], chan_icb, inta, chan); + "TIO int spad %08x icb %06x inta %04x rchan %04x\n", + SPAD[inta+0x80], chan_icb, inta, rchan); - iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ +// iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ incha = chp->chan_inch_addr; /* get inch address */ +#ifdef NOT_HERE sim_debug(DEBUG_XIO, &cpu_dev, - "testxio test1 chsa %04x cmd %02x ccw_flags %04x IOCD1 %08x IOCD2 %08x IOCLA %06x\n", + "TIO 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 ICB incha %08x SW1 %08x SW2 %08x\n", + "TIO test2 chsa %04x ICB incha %08x SW1 %08x SW2 %08x\n", chsa, incha, RMW(incha), RMW(incha+4)); - - /* the channel is not busy, see if any status to post */ - if (post_csw(chp, 0)) { -#ifdef DO_DYNAMIC_DEBUG - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_TRAP | DEBUG_EXP | DEBUG_IRQ); #endif - *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 */ - /* change status from BUFF_POST to BUFF_DONE */ -/*082420*/ if (chp->chan_byte == BUFF_POST) { -/*082420*/ chp->chan_byte = BUFF_DONE; /* show done & not busy */ -sim_debug(DEBUG_EXP, &cpu_dev, "testxio BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); + +// chan = chan << 8; /* make zero unit channel */ + /* see if any status ready to post */ + if (FIFO_Num(rchsa)) { +#ifdef NOT_HERE + /* find actual device with the channel program */ + uint32 tempa = dibp->chan_fifo[dibp->chan_fifo_out]; /* get SW1 of FIFO entry */ + chsa = (chan) | (tempa >> 24); /* find device address for requesting chan prog */ + chp = find_chanp_ptr(chsa); /* find the chanp pointer for channel */ +#endif + sim_debug(DEBUG_IRQ, &cpu_dev, + "TIO rchsa %04x LOOK FIFO #%1x irq %02x inch %06x chp %p icba %06x chan_byte %02x\n", + rchsa, FIFO_Num(rchsa), inta, chp->chan_inch_addr, chp, chan_icb, chp->chan_byte); + if (post_csw(chp, 0)) { +//120120/*112120*/ chp->chan_byte = BUFF_DONE; /* show done & not busy */ + sim_debug(DEBUG_IRQ, &cpu_dev, + "TIO rchsa %04x POST FIFO #%1x irq %02x inch %06x chan_icba+20 %08x chan_byte %02x\n", + rchsa, FIFO_Num(rchsa), inta, chp->chan_inch_addr, RMW(chan_icb+20), chp->chan_byte); + /* change status from BUFF_POST to BUFF_DONE */ + /* if not BUFF_POST we have a PPCI or channel busy interrupt */ + /* so leave the channel status alone */ + if (chp->chan_byte == BUFF_POST) { + chp->chan_byte = BUFF_DONE; /* show done & not busy */ } - return SCPE_OK; /* CC2 and OK */ + sim_debug(DEBUG_XIO, &cpu_dev, + "TIO END status stored incha %06x rchsa %04x sw1 %08x sw2 %08x\n", + incha, rchsa, RMW(incha), RMW(incha+4)); +#ifndef FIX_SPARE_INT_IN_DPDIAG + if (FIFO_Num(rchsa) == 0) + INTS[inta] &= ~INTS_REQ; /* clear any level request if no status */ +#else + INTS[inta] &= ~INTS_REQ; /* clear any level request if no status */ +#endif + *status = CC2BIT; /* status stored from SIO, so CC2 */ + return SCPE_OK; /* No CC's all OK */ + } else { + sim_debug(DEBUG_IRQ, &cpu_dev, + "TIO rchsa %04x NOT POSTED FIFO #%1x irq %02x inch %06x chan_icba %06x chan_byte %02x\n", + rchsa, FIFO_Num(rchsa), inta, chp->chan_inch_addr, chan_icb, chp->chan_byte); + /* now store the status dw address into word 5 of the ICB for the channel */ + WMW(chan_icb+20, 0); /* post sw addr 0 in ICB+5w & reset CCs */ + *status = 0; /* no status stored from TIO, so no CC */ + return SCPE_OK; /* No CC's all OK */ + } } + /* nothing going on, so say all OK */ +// *status = CC1BIT; /* request accepted, no status, so CC1 */ + WMW(chan_icb+20, 0); /* post sw addr 0 in ICB+5w & reset CCs */ +// *status = 0; /* no status stored from TIO, so no CC */ *status = CC1BIT; /* request accepted, no status, so CC1 */ + INTS[inta] &= ~INTS_REQ; /* clear any level request if no status */ 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); + "$$$ TIO END rchsa %04x rchan %04x ccw_flags %04x chan_stat %04x CCs %08x\n", + rchsa, rchan, chp->ccw_flags, chp->chan_status, *status); return SCPE_OK; /* No CC's all OK */ } /* Stop XIO */ -t_stat stopxio(uint16 chsa, uint32 *status) { /* stop XIO */ +t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */ DIB *dibp; /* device information pointer */ UNIT *uptr; /* pointer to unit in channel */ uint32 chan_icb; /* Interrupt level context block address */ - uint32 iocla; /* I/O channel IOCL address int ICB */ + uint32 iocla, inta, itva; /* I/O channel IOCL address int ICB */ CHANP *chp; /* Channel prog pointers */ - uint16 chan = get_chan(chsa); /* get the channel number */ + uint16 lchan = get_chan(lchsa); /* get the logical channel number */ + uint32 spadent; + uint16 rchan, rchsa; /* the real channel number, chsa */ - sim_debug(DEBUG_XIO, &cpu_dev, "stopxio entry chsa %04x\n", chsa); /* get the device entry for the logical channel in SPAD */ - dibp = dib_unit[chsa]; /* get the DIB pointer */ - chp = find_chanp_ptr(chsa); /* find the device chanp pointer */ + spadent = SPAD[lchan]; /* get spad device entry for logical channel */ + rchan = (spadent & 0x7f00) >> 8; /* get real channel */ + rchsa = (rchan << 8) | (lchsa & 0xff); /* get the read chan & suba */ + + sim_debug(DEBUG_XIO, &cpu_dev, "STPIO entry lchsa %04x rchsa %04x\n", lchsa, rchsa); + + /* get the device entry for the logical channel in SPAD */ + dibp = dib_unit[rchsa]; /* get the DIB pointer */ + chp = find_chanp_ptr(rchsa); /* find the device chanp pointer */ if (dibp == 0 || chp == 0) { /* if no dib or channel ptr, CC3 return */ *status = CC3BIT; /* not found, so CC3 */ sim_debug(DEBUG_EXP, &cpu_dev, - "stopxio test 1 chsa %04x device not present, CC3 returned\n", chsa); + "STPIO test 1 rchsa %04x device not present, CC3 returned\n", rchsa); return SCPE_OK; /* not found CC3 */ } @@ -1489,53 +1855,127 @@ t_stat stopxio(uint16 chsa, uint32 *status) { /* stop XIO */ if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ *status = CC3BIT; /* not attached, so error CC3 */ sim_debug(DEBUG_EXP, &cpu_dev, - "stopxio test 2 chsa %04x device not present, CC3 returned\n", chsa); + "STPIO test 2 rchsa %04x device not present, CC3 returned\n", rchsa); return SCPE_OK; /* not found CC3 */ } - chan_icb = find_int_icb(chsa); /* Interrupt level context block address */ + /* the XIO opcode processing software has already checked for F class */ + inta = ((~spadent)>>16)&0x7f; /* get channel interrupt level */ + chp->chan_int = inta; /* make sure it is set in channel */ + itva = SPAD[0xf1] + (inta<<2); /* int vector address */ + chan_icb = RMW(itva); /* Interrupt context block addr */ +// chan_icb = find_int_icb(chsa); /* Interrupt level context block address */ +// inta = find_int_lev(chsa); /* Interrupt Level for channel */ iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ sim_debug(DEBUG_CMD, &cpu_dev, - "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]); + "STPIO busy test rchsa %04x cmd %02x ccw_flags %04x IOCD1 %08x IOCD2 %08x\n", + rchsa, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); - sim_debug(DEBUG_CMD, &cpu_dev, "$$$ STOPIO %04x %02x %04x\n", - chsa, chp->ccw_cmd, chp->ccw_flags); +// sim_debug(DEBUG_CMD, &cpu_dev, "$$$ STPIO %04x %02x %04x\n", +// chsa, chp->ccw_cmd, chp->ccw_flags); - /* check for a Command or data chain operation in progresss */ - if ((chp->chan_byte & BUFF_BUSY) && chp->chan_byte != BUFF_POST) { - sim_debug(DEBUG_CMD, &cpu_dev, "stopxio busy return CC1 chsa %04x chan %04x\n", chsa, chan); - /* reset the DC or CC bits to force completion after current IOCD */ - chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ + if ((chp->chan_byte & BUFF_BUSY) == 0) { + /* the channel is not busy, so return OK */ *status = CC1BIT; /* request accepted, no status, so CC1 */ - return SCPE_OK; /* go wait CC1 */ + sim_debug(DEBUG_CMD, &cpu_dev, + "$$$ STPIO not busy return rchsa %04x cmd %02x ccw_flags %04x status %04x\n", + rchsa, chp->ccw_cmd, chp->ccw_flags, *status); + return SCPE_OK; /* No CC's all OK */ } - /* the channel is not busy, so return OK */ + + /* the channel is busy, so process */ + /* see if we have a stopio device entry */ + if (dibp->stop_io != NULL) { /* NULL if no stop_io function */ + /* call the device controller to get stop_io status */ + int32 tempa = dibp->stop_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, + "stopxio stop_io call return ERROR FIFO #%1x rchan %04x retstat %08x cstat %08x\n", + FIFO_Num(rchsa), rchan, tempa, chp->chan_status); + + /* chan_end is called in stop device service routine */ + /* the device is no longer busy, post status */ + /* remove PPCI status. Unit check should not be set */ + if (tempa == 1) { /* see if console HIO */ + chp->ccw_count = 0; /* zero the count */ + /* post status for UTX */ + if (post_csw(chp, ((STATUS_PCI) << 16))) { +//120120/*112120*/ chp->chan_byte = BUFF_DONE; /* show done & not busy */ + INTS[inta] &= ~INTS_REQ; /* clear any level request */ + *status = CC2BIT; /* status stored */ + sim_debug(DEBUG_CMD, &cpu_dev, + "$$$ STOPXIO END2 rchsa %04x rchan %04x cmd %02x ccw_flags %04x status %04x\n", + rchsa, rchan, chp->ccw_cmd, chp->ccw_flags, *status); + /* change status from BUFF_POST to BUFF_DONE */ +/*082420*/ if (chp->chan_byte == BUFF_POST) { +/*082420*/ chp->chan_byte = BUFF_DONE; /* show done & not busy */ +sim_debug(DEBUG_EXP, &cpu_dev, "STPIO BUFF_DONE1 chp %p chan_byte %04x\n", chp, chp->chan_byte); + } + return SCPE_OK; /* CC2 & all OK */ + } + } else { + chp->ccw_count = 0; /* zero the count */ + /* The diags want the interrupt for the disk */ + *status = CC1BIT; /* request accepted, no status, so CC1 */ + sim_debug(DEBUG_CMD, &cpu_dev, + "$$$ STOPXIO END2 ECHO rchsa %04x cmd %02x ccw_flags %04x status %04x\n", + rchsa, chp->ccw_cmd, chp->ccw_flags, *status); + return SCPE_OK; /* CC1 & all OK */ + } + } + /* the device is not busy, so cmd has not started */ + sim_debug(DEBUG_EXP, &cpu_dev, + "STPIO BUFF_DONE2 chp %p chan_byte %04x\n", chp, chp->chan_byte); + /* the channel is not busy, so return OK */ + *status = CC1BIT; /* request accepted, no status, so CC1 */ + sim_debug(DEBUG_CMD, &cpu_dev, + "$$$ STOPXIO END3 rchsa %04x cmd %02x ccw_flags %04x status %04x\n", + rchsa, chp->ccw_cmd, chp->ccw_flags, *status); + return SCPE_OK; /* No CC's all OK */ + } + /* device does not have stop_io entry, so stop the I/O */ + /* check for a Command or data chain operation in progresss */ *status = CC1BIT; /* request accepted, no status, so CC1 */ + /* reset the DC or CC bits to force completion after current IOCD */ + chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ sim_debug(DEBUG_CMD, &cpu_dev, - "$$$ 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 */ + "STPIO busy return CC1 %08x rchsa %04x status %08x flags %04x\n", + CC1BIT, rchsa, *status, chp->ccw_flags); + return SCPE_OK; /* go wait CC1 */ } /* Reset Channel XIO */ -t_stat rschnlxio(uint16 chsa, uint32 *status) { /* reset channel XIO */ +t_stat rschnlxio(uint16 lchsa, uint32 *status) { /* reset channel XIO */ DIB *dibp; /* device information pointer */ UNIT *uptr; /* pointer to unit in channel */ CHANP *chp; /* Channel prog pointers */ - uint16 chan = chsa & 0x7f00; /* get just the channel number */ - uint32 lev; int i; + uint16 lchan = get_chan(lchsa); /* get the logical channel number */ + uint32 inta; + uint32 spadent; + uint16 rchan, rchsa; /* the real channel number */ - sim_debug(DEBUG_XIO, &cpu_dev, "rschnlxio entry chan %04x\n", chan); /* get the device entry for the logical channel in SPAD */ - dibp = dib_chan[get_chan(chan)]; /* get the channel device information pointer */ - chp = find_chanp_ptr(chan); /* find the channel chanp pointer */ + spadent = SPAD[lchan]; /* get spad device entry for logical channel */ + rchan = (spadent & 0x7f00) >> 8; /* get real channel */ + rchsa = rchan << 8; /* get the real chan & zero suba */ + + sim_debug(DEBUG_XIO, &cpu_dev, "rschnlxio entry lchan %04x rchan %04x\n", lchan, rchan); + + /* get the device entry for the logical channel in SPAD */ +// dibp = dib_chan[get_chan(rchsa)]; /* get the channel device information pointer */ + dibp = dib_unit[rchsa]; /* get the channel device information pointer */ +// chp = find_chanp_ptr(rchan); /* find the channel chanp pointer */ + chp = find_chanp_ptr(rchsa); /* find the channel chanp pointer */ if (dibp == 0 || chp == 0) { /* if no dib or channel ptr, CC3 return */ *status = CC3BIT; /* not found, so CC3 */ sim_debug(DEBUG_EXP, &cpu_dev, - "rschnlxio test 1 chsa %04x device not present, CC3 returned\n", chsa); + "rschnlxio test 1 dibp %p chp %p lchsa %04x rchsa %04x device not present, CC3 returned\n", + dibp, chp, lchsa, rchsa); return SCPE_OK; /* not found CC3 */ } @@ -1543,30 +1983,34 @@ t_stat rschnlxio(uint16 chsa, uint32 *status) { /* reset channel XIO */ if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ *status = CC3BIT; /* not attached, so error CC3 */ sim_debug(DEBUG_EXP, &cpu_dev, - "rschnlxio test 2 chsa %04x device not present, CC3 returned\n", chsa); + "rschnlxio test 2 lchsa %04x rchsa %04x device not present, CC3 returned\n", + lchsa, rchsa); return SCPE_OK; /* not found CC3 */ } + inta = ((~spadent)>>16)&0x7f; /* get channel interrupt level */ + chp->chan_int = inta; /* make sure it is set in channel */ + /* reset this channel */ dibp->chan_fifo_in = 0; /* reset the FIFO pointers */ dibp->chan_fifo_out = 0; /* reset the FIFO pointers */ chp->chan_inch_addr = 0; /* remove inch status buffer address */ - lev = find_int_lev(chan); /* Interrupt Level for channel */ - INTS[lev] &= ~INTS_ACT; /* clear level active */ - SPAD[lev+0x80] &= ~SINT_ACT; /* clear in spad too */ +// lev = find_int_lev(chan); /* Interrupt Level for channel */ + INTS[inta] &= ~INTS_ACT; /* clear level active */ + SPAD[inta+0x80] &= ~SINT_ACT; /* clear in spad too */ /* 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 = dib_unit[chsa]; /* get the DIB pointer */ + rchsa = rchan | i; /* merge sa to real channel */ + dibp = dib_unit[rchsa]; /* get the DIB pointer */ if (dibp == 0) continue; /* not used */ - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + chp = find_chanp_ptr(rchsa); /* find the chanp pointer */ if (chp == 0) continue; /* not used */ chp->chan_status = 0; /* clear the channel status */ chp->chan_byte = BUFF_EMPTY; /* no data yet */ -sim_debug(DEBUG_EXP, &cpu_dev, "chan_set_devs BUFF_EMPTY chp %p chan_byte %04x\n", chp, chp->chan_byte); +//sim_debug(DEBUG_EXP, &cpu_dev, "chan_set_devs BUFF_EMPTY chp %p chan_byte %04x\n", chp, chp->chan_byte); chp->ccw_addr = 0; /* clear buffer address */ chp->chan_caw = 0x0; /* clear IOCD address */ chp->ccw_count = 0; /* channel byte count 0 bytes*/ @@ -1574,62 +2018,70 @@ sim_debug(DEBUG_EXP, &cpu_dev, "chan_set_devs BUFF_EMPTY chp %p chan_byte %04x\n chp->ccw_cmd = 0; /* read command */ chp->chan_inch_addr = 0; /* clear inch addr */ } - sim_debug(DEBUG_XIO, &cpu_dev, "rschnlxio return CC1 chan %04x lev %04x\n", chan, lev); + sim_debug(DEBUG_XIO, &cpu_dev, "rschnlxio return CC1 lchan %02x lchan %02x inta %04x\n", + lchan, rchan, inta); *status = CC1BIT; /* request accepted, no status, so CC1 TRY THIS */ return SCPE_OK; /* All OK */ } /* HIO - Halt I/O */ -t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ - int chan = get_chan(lchsa); +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, tempa; - uint16 chsa; + uint32 inta, spadent, tempa, itva; + uint16 lchan = get_chan(lchsa); + uint16 rchan, rchsa; CHANP *chp; /* Channel prog pointers */ /* 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 = dib_unit[chsa]; /* get the device DIB pointer */ - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - uptr = chp->unitptr; /* get the unit ptr */ + spadent = SPAD[lchan]; /* get spad device entry for logical channel */ + rchan = (spadent & 0x7f00) >> 8; /* get real channel */ + rchsa = (rchan << 8) | (lchsa & 0xff); /* merge sa to real channel */ + dibp = dib_unit[rchsa]; /* get the device DIB pointer */ + chp = find_chanp_ptr(rchsa); /* find the chanp pointer */ - if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ + if (dibp == 0 || chp == 0) { /* if no dib or chan ptr, CC3 on return */ *status = CC3BIT; /* not found, so CC3 */ + sim_debug(DEBUG_EXP, &cpu_dev, + "HIO lchsa %04x rchsa %04x device not present, CC3 returned\n", lchsa, rchsa); return SCPE_OK; /* not found, CC3 */ } + uptr = chp->unitptr; /* get the unit ptr */ if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ + sim_debug(DEBUG_EXP, &cpu_dev, + "HIO lchsa %04x rchsa %04x device not attached, CC3 returned\n", lchsa, rchsa); *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, "haltxio dev spad %08x chsa %04x chan %04x\n", spadent, chsa, chan); + sim_debug(DEBUG_XIO, &cpu_dev, "HIO dev spad %08x lchsa %04x rchsa %04x\n", spadent, lchsa, rchsa); /* the haltio opcode processing software has already checked for F class */ - inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ - inta = 127 - inta; /* get positive int level */ - spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ - sim_debug(DEBUG_XIO, &cpu_dev, "haltxio int spad %08x inta %02x chan %04x\n", spadent, inta, chan); + inta = ((~spadent)>>16)&0x7f; /* get channel interrupt level */ + chp->chan_int = inta; /* make sure it is set in channel */ +// inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ +// inta = 127 - inta; /* get positive int level */ +// spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ + sim_debug(DEBUG_XIO, &cpu_dev, "HIO int spad %08x inta %02x rchan %04x\n", spadent, inta, rchan); /* 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 = 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 */ + itva = SPAD[0xf1] + (inta<<2); /* int vector address */ + chan_icb = RMW(itva); /* Interrupt context block addr */ + iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ +// incha = RMW(chan_icb+20); /* post inch addr in ICB+5w */ + sim_debug(DEBUG_XIO, &cpu_dev, - "$$ HIO 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]); + "$$ HIO busy test rchsa %04x cmd %02x ccw_flags %04x IOCD1 %08x IOCD2 %08x\n", + rchsa, chp->ccw_cmd, chp->ccw_flags, RMW(iocla), RMW(iocla+4)); if ((chp->chan_byte & BUFF_BUSY) == 0) { /* the channel is not busy, so return OK */ *status = CC1BIT; /* request accepted, no status, so CC1 */ sim_debug(DEBUG_CMD, &cpu_dev, - "$$$ HIO END1 chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + "$$$ HIO END1 rchsa %04x cmd %02x ccw_flags %04x status %04x\n", + rchsa, chp->ccw_cmd, chp->ccw_flags, *status); chp->chan_byte = BUFF_DONE; /* we are done */ sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); chp->chan_status = (STATUS_DEND|STATUS_CEND); @@ -1653,8 +2105,8 @@ sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_POST chp %p chan_byte %04x\n", chp, 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 FIFO #%1x chan %04x retstat %08x cstat %08x\n", - FIFO_Num(chsa), chan, tempa, chp->chan_status); + "HIO halt_io call return ERROR FIFO #%1x rchsa %04x retstat %08x cstat %08x\n", + FIFO_Num(rchsa), rchsa, tempa, chp->chan_status); /* chan_end is called in hio device service routine */ /* the device is no longer busy, post status */ @@ -1663,15 +2115,17 @@ sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_POST chp %p chan_byte %04x\n", chp, chp->ccw_count = 0; /* zero the count */ /* post status for UTX */ if (post_csw(chp, ((STATUS_PCI) << 16))) { +//120120/*112120*/ chp->chan_byte = BUFF_DONE; /* show done & not busy */ INTS[inta] &= ~INTS_REQ; /* clear any level request */ *status = CC2BIT; /* status stored */ sim_debug(DEBUG_CMD, &cpu_dev, - "$$$ HIO END2 chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + "$$$ HIO END2 rchsa %04x cmd %02x ccw_flags %04x status %04x\n", + rchsa, chp->ccw_cmd, chp->ccw_flags, *status); /* change status from BUFF_POST to BUFF_DONE */ /*082420*/ if (chp->chan_byte == BUFF_POST) { /*082420*/ chp->chan_byte = BUFF_DONE; /* show done & not busy */ -sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE1 chp %p chan_byte %04x\n", chp, chp->chan_byte); + sim_debug(DEBUG_EXP, &cpu_dev, + "HIO BUFF_DONE1 chp %p chan_byte %04x\n", chp, chp->chan_byte); } return SCPE_OK; /* CC2 & all OK */ } @@ -1679,87 +2133,122 @@ sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE1 chp %p chan_byte %04x\n", chp chp->ccw_count = 0; /* zero the count */ /* The diags want the interrupt for the disk */ *status = CC1BIT; /* request accepted, no status, so CC1 */ +//BAD *status = 0; /* request accepted, no status, so CC1 */ sim_debug(DEBUG_CMD, &cpu_dev, - "$$$ HIO END2 ECHO chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + "$$$ HIO END2 ECHO rchsa %04x cmd %02x ccw_flags %04x status %04x\n", + rchsa, chp->ccw_cmd, chp->ccw_flags, *status); return SCPE_OK; /* CC1 & all OK */ } } /* the device is not busy, so cmd has not started */ sim_debug(DEBUG_EXP, &cpu_dev, - "haltxio BUFF_DONE2 chp %p chan_byte %04x\n", chp, chp->chan_byte); + "HIO BUFF_DONE2 chp %p chan_byte %04x\n", chp, chp->chan_byte); /* the channel is not busy, so return OK */ *status = CC1BIT; /* request accepted, no status, so CC1 */ sim_debug(DEBUG_CMD, &cpu_dev, - "$$$ HIO END3 chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + "$$$ HIO END3 rchsa %04x cmd %02x ccw_flags %04x status %04x\n", + rchsa, chp->ccw_cmd, chp->ccw_flags, *status); return SCPE_OK; /* No CC's all OK */ } /* device does not have a HIO entry, so terminate the I/O */ /* a haltxio entry should be provided for a device so busy can be cleared */ /* check for a Command or data chain operation in progresss */ if (chp->chan_byte & BUFF_BUSY) { - sim_debug(DEBUG_XIO, &cpu_dev, "haltxio device busy chsa %04x chan %04x\n", chsa, chan); + sim_debug(DEBUG_XIO, &cpu_dev, "HIO device busy lchsa %04x rchsa %04x\n", lchsa, rchsa); /* reset the DC or CC bits to force completion */ chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ chp->chan_byte = BUFF_BUSY; /* wait for post_csw to be done */ -sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE3 chp %p chan_byte %04x\n", chp, chp->chan_byte); +sim_debug(DEBUG_EXP, &cpu_dev, "HIO BUFF_DONE3 chp %p chan_byte %04x\n", chp, chp->chan_byte); // chp->ccw_count = 0; /* zero the count */ sim_cancel(uptr); /* cancel timer service */ chp->chan_status &= ~STATUS_BUSY; /* remove BUSY status bit */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ + chan_end(rchsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ /* post the channel status */ chp->ccw_count = 0; /* zero the count */ /* remove SLI, PPCI and Unit check status bits */ if (post_csw(chp, ((STATUS_PCI) << 16))) { +//120120/*112120*/ chp->chan_byte = BUFF_DONE; /* show done & not busy */ INTS[inta] &= ~INTS_REQ; /* clear any level request */ *status = CC2BIT; /* status stored from SIO, so CC2 */ sim_debug(DEBUG_CMD, &cpu_dev, - "$$$ HIO END4 chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + "$$$ HIO END4 rchsa %04x cmd %02x ccw_flags %04x status %04x\n", + rchsa, chp->ccw_cmd, chp->ccw_flags, *status); /* change status from BUFF_POST to BUFF_DONE */ -/*082420*/ if (chp->chan_byte == BUFF_DONE) { +/*082420*/ if (chp->chan_byte == BUFF_POST) { /*082420*/ chp->chan_byte = BUFF_DONE; /* show done & not busy */ -sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE4 chp %p chan_byte %04x\n", chp, chp->chan_byte); +sim_debug(DEBUG_EXP, &cpu_dev, "HIO BUFF_DONE4 chp %p chan_byte %04x\n", chp, chp->chan_byte); } return SCPE_OK; /* CC2 & all OK */ } } chp->chan_byte = BUFF_DONE; /* chan prog done */ -sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE5 chp %p chan_byte %04x\n", chp, chp->chan_byte); +sim_debug(DEBUG_EXP, &cpu_dev, "HIO BUFF_DONE5 chp %p chan_byte %04x\n", chp, chp->chan_byte); /* the channel is not busy, so return OK */ *status = CC1BIT; /* request accepted, no status, so CC1 */ sim_debug(DEBUG_CMD, &cpu_dev, - "$$$ HIO END5 chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + "$$$ HIO END5 rchsa %04x cmd %02x ccw_flags %04x status %04x\n", + rchsa, chp->ccw_cmd, chp->ccw_flags, *status); return SCPE_OK; /* No CC's all OK */ } /* grab controller n/u */ /* TODO return unimplemented function error, not busy */ -t_stat grabxio(uint16 lchsa, uint32 *status) { /* grab controller XIO n/u */ - int chan = get_chan(lchsa); - uint32 spadent; - uint16 chsa; +t_stat grabxio(uint16 lchsa, uint32 *status) { /* grab controller XIO n/u */ + DIB *dibp; /* device information pointer */ + UNIT *uptr; /* pointer to unit in channel */ CHANP *chp; + uint16 lchan = get_chan(lchsa); /* get the logical channel number */ + uint32 spadent; + uint16 rchan, rchsa; /* the real channel number, chsa */ /* 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 */ - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + spadent = SPAD[lchan]; /* get spad device entry for logical channel */ + rchan = (spadent & 0x7f00) >> 8; /* get real channel */ + rchsa = (rchan << 8) | (lchsa & 0xff); /* merge sa to real channel */ + + sim_debug(DEBUG_XIO, &cpu_dev, "GRIO entry lchsa %04x rchsa %04x\n", lchsa, rchsa); + + /* get the device entry for the logical channel in SPAD */ + dibp = dib_unit[rchsa]; /* get the DIB pointer */ + chp = find_chanp_ptr(rchsa); /* find the device chanp pointer */ + + if (dibp == 0 || chp == 0) { /* if no dib or channel ptr, CC3 return */ + *status = CC3BIT; /* not found, so CC3 */ + sim_debug(DEBUG_EXP, &cpu_dev, + "GRIO test 1 rchsa %04x device not present, CC3 returned\n", rchsa); + return SCPE_OK; /* not found CC3 */ + } + + uptr = chp->unitptr; /* get the unit ptr */ + if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ + *status = CC3BIT; /* not attached, so error CC3 */ + sim_debug(DEBUG_EXP, &cpu_dev, + "GRIO test 2 lchsa %04x rchsa %04x device not present, CC3 returned\n", lchsa, rchsa); + return SCPE_OK; /* not found CC3 */ + } /* 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, "grabxio busy return CC4 chsa %04x chan %04x\n", chsa, chan); *status = CC4BIT; /* busy, so CC4 */ + sim_debug(DEBUG_CMD, &cpu_dev, + "GRIO busy return CC4 lchsa %04x rchsa %04x status %08x\n", + lchsa, rchsa, *status); return SCPE_OK; /* CC4 all OK */ } - *status = CC2BIT|CC4BIT; /* unsupported transaction */ - sim_debug(DEBUG_CMD, &cpu_dev, "grabxio chsa %04x chan %04x\n", chsa, chan); - return 0; + + /* If this is console, debuger wants CC3 & CC4 = 0 */ + if (rchan == 0x7e) { + *status = 0; /* return no CC's */ +// *status = CC1BIT; /* return no CC's */ + } else { + /* diags want unsupported transaction for disk */ + *status = CC2BIT|CC4BIT; /* unsupported transaction */ + } + sim_debug(DEBUG_CMD, &cpu_dev, + "GRIO lchsa %04x rchsa %04x status %08x\n", lchsa, rchsa, *status); + return SCPE_OK; /* dono */ } /* reset controller XIO */ @@ -1790,9 +2279,6 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller 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; lev = find_int_lev(chan); /* get our int level */ INTS[lev] &= ~INTS_ACT; /* clear level active */ SPAD[lev+0x80] &= ~SINT_ACT; /* clear spad too */ @@ -1800,18 +2286,37 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */ /* now go through all the sa for the channel and stop any IOCLs */ for (i=0; i<256; i++) { + int j; + IOCLQ *qp; /* IOCLQ pointer */ chsa = chan | i; /* merge sa to real channel */ dibp = dib_unit[chsa]; /* get the DIB pointer */ if (dibp == 0) { continue; /* not used */ } + /* reset the FIFO pointers */ + dibp->chan_fifo_in = 0; /* set no FIFO entries */ + dibp->chan_fifo_out = 0; /* set no FIFO entries */ +// qp = &dibp->ioclq_ptr[0]; /* IOCLQ pointer */ + if ((dibp->ioclq_ptr != NULL) && (qp != NULL)) { + for (j=0; jnumunits; j++) { + qp = &dibp->ioclq_ptr[j]; /* IOCLQ pointer */ + qp->ioclq_in = 0; /* clear any entries */ + qp->ioclq_out = 0; /* clear any entries */ + } + } chp = find_chanp_ptr(chsa); /* find the chanp pointer */ if (chp == 0) { continue; /* not used */ } + uptr = chp->unitptr; /* get the unit ptr */ + /* see if we have a rsctl device entry */ + if (dibp->rsctl_io != NULL) { /* NULL if no haltio function */ + /* call the device controller to process rsctl */ + j = dibp->rsctl_io(uptr); /* get status from device */ + } chp->chan_status = 0; /* clear the channel status */ chp->chan_byte = BUFF_EMPTY; /* no data yet */ -sim_debug(DEBUG_EXP, &cpu_dev, "rsctlxio BUFF_EMPTY chp %p chan_byte %04x\n", chp, chp->chan_byte); +//sim_debug(DEBUG_EXP, &cpu_dev, "rsctlxio BUFF_EMPTY chp %p chan_byte %04x\n", chp, chp->chan_byte); chp->ccw_addr = 0; /* clear buffer address */ chp->chan_caw = 0x0; /* clear IOCD address */ chp->ccw_count = 0; /* channel byte count 0 bytes*/ @@ -1819,7 +2324,8 @@ sim_debug(DEBUG_EXP, &cpu_dev, "rsctlxio BUFF_EMPTY chp %p chan_byte %04x\n", ch chp->ccw_cmd = 0; /* read command */ } sim_debug(DEBUG_CMD, &cpu_dev, "rsctlxio return CC1 chan %04x lev %04x\n", chan, lev); - *status = CC1BIT; /* request accepted, no status, so CC1 TRY THIS */ +// *status = CC1BIT; /* request accepted, no status, so CC1 TRY THIS */ + *status = 0; /* request accepted, no status, return 0 */ return SCPE_OK; /* All OK */ } @@ -1859,7 +2365,7 @@ t_stat chan_boot(uint16 chsa, DEVICE *dptr) { 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 */ -sim_debug(DEBUG_EXP, &cpu_dev, "chan_boot BUFF_EMPTY chp %p chan_byte %04x\n", chp, chp->chan_byte); +//sim_debug(DEBUG_EXP, &cpu_dev, "chan_boot BUFF_EMPTY chp %p chan_byte %04x\n", chp, chp->chan_byte); 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*/ @@ -1906,7 +2412,7 @@ uint32 cont_chan(uint16 chsa) if (chp->chan_byte == BUFF_NEXT) { uint32 chan = get_chan(chsa); sim_debug(DEBUG_EXP, &cpu_dev, - "cont_chan resume chan prog chsa %04x iocl %06x\n", + "cont_chan resume chan prog chsa %04x iocla %06x\n", chsa, chp->chan_caw); /* start a channel program */ @@ -1931,16 +2437,16 @@ uint32 cont_chan(uint16 chsa) /* other error, stop the show */ chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ - sim_debug(DEBUG_EXP, &cpu_dev, - "cont_chan Error2 FIFO #%1x store_csw CC1 chan %04x status %08x\n", - FIFO_Num(chsa), chan, chp->chan_status); + sim_debug(DEBUG_EXP, &cpu_dev, + "cont_chan Error2 FIFO #%1x store_csw CC1 chan %04x status %08x\n", + FIFO_Num(chsa), chan, chp->chan_status); return SCPE_OK; /* done */ } /* we get here when the start cmd has been processed without error */ /* go wait for the cmd to finish */ sim_debug(DEBUG_EXP, &cpu_dev, - "cont_chan continue wait chsa %04x status %08x iocla %06x\n", - chsa, chp->chan_status, chp->chan_caw); + "cont_chan continue wait chsa %04x status %08x iocla %06x byte %02x\n", + chsa, chp->chan_status, chp->chan_caw, chp->chan_byte); return SCPE_OK; /* done, status stored */ } /* must be more IOCBs, wait for them */ @@ -1955,10 +2461,6 @@ uint32 cont_chan(uint16 chsa) */ uint32 scan_chan(uint32 *ilev) { int i; -#ifndef GEERT_UNDO - void CatchSig(); - void ReportIRQs(); -#endif uint32 chsa; /* No device */ uint32 chan; /* channel num 0-7f */ uint32 tempa; /* icb address */ @@ -1992,34 +2494,24 @@ uint32 scan_chan(uint32 *ilev) { TPSD[0] = M[0]; /* save PSD from loc 0&4 */ TPSD[1] = M[1]; /* save the status double word to memory */ - WMW(tempa, sw1); /* save sa & IOCD address in status WD 1 loc */ +// WMW(tempa, sw1); /* save sa & IOCD address in status WD 1 loc */ + /* sete BIT 1 to show status stored */ + WMW(tempa, sw1|BIT1); /* save sa & IOCD address in status WD 1 loc */ WMW(tempa+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 */ /* there is no icb when we are ipl booting, so skip this */ //NO_GOOD WMW(chan_icb+20, tempa|BIT1); /* post sw addr in ICB+5w & set CC2 in INCH addr */ #endif chp->chan_byte = BUFF_DONE; /* we are done */ -sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); +//sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); 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); + chp->chan_caw, chan, FIFO_Num(chan), tempa, sw1|BIT1, sw2); return loading; } return 0; /* not ready, return */ } -#ifndef GEERT_UNDO - ScanCycles++; - - /* install signal handler after say 100 ScanCycles */ - if (ScanCycles == 100) - signal(SIGQUIT, CatchSig); - - if (DoNextCycles) { - ReportIRQs(); - DoNextCycles--; - } -#endif /* see if we are able to look for ints */ if (irq_pend == 0) /* pending int? */ return 0; /* no, done */ @@ -2056,21 +2548,26 @@ sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan BUFF_DONE chp %p chan_byte %04x\n", ch sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan FIFO REQ FIFO #%1x irq %02x SPAD %08x INTS %08x\n", FIFO_Num(SPAD[i+0x80] & 0x7f00), i, SPAD[i+0x80], INTS[i]); +//1003/*092520*/ irq_pend = 1; /* we have pending interrupt */ continue; } } /* cannot make anyone active if ints are blocked */ #ifndef TRY_UTX_DELAY - if ((CPUSTATUS & 0x80) || (waitqcnt)) { /* interrupts blocked? */ + if ((CPUSTATUS & BIT24) || (waitqcnt)) { /* interrupts blocked? */ #else - if (CPUSTATUS & 0x80) { /* interrupts blocked? */ + if (CPUSTATUS & BIT24) { /* interrupts blocked? */ #endif - sim_debug(DEBUG_DETAIL, &cpu_dev, -// sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan INTS blocked!\n"); + if (waitqcnt) /* interrupts blocked? */ +// sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_IRQ, &cpu_dev, + "scan_chan waitqcnt %02x\n", waitqcnt); + if (CPUSTATUS & BIT24) /* interrupts blocked? */ +// sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_IRQ, &cpu_dev, + "scan_chan INTS blocked!\n"); goto tryme; /* needed for MPX */ -//718 return 0; /* yes, done */ } /* now go process the highest requesting interrupt */ @@ -2083,8 +2580,8 @@ sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan BUFF_DONE chp %p chan_byte %04x\n", ch if (SPAD[i+0x80] == 0xefffffff) /* 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, -// sim_debug(DEBUG_IRQ, &cpu_dev, +// sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_IRQ, &cpu_dev, "scan_chan INTS ACT irq %02x SPAD %08x INTS %08x\n", i, SPAD[i+0x80], INTS[i]); return 0; /* this level active, so stop looking */ @@ -2137,6 +2634,7 @@ sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan BUFF_DONE chp %p chan_byte %04x\n", ch "scan_chan %04x LOOK FIFO #%1x irq %02x inch %06x chp %p icba %06x chan_byte %02x\n", chsa, FIFO_Num(chan), i, chp->chan_inch_addr, chp, chan_icba, chp->chan_byte); if (post_csw(chp, 0)) { +//120120/*112120*/ chp->chan_byte = BUFF_DONE; /* show done & not busy */ sim_debug(DEBUG_IRQ, &cpu_dev, "scan_chanx %04x POST FIFO #%1x irq %02x inch %06x chan_icba+20 %08x chan_byte %02x\n", chan, FIFO_Num(chan), i, chp->chan_inch_addr, RMW(chan_icba+20), chp->chan_byte); @@ -2172,28 +2670,6 @@ sim_debug(DEBUG_EXP, &cpu_dev, "scan_chanx BUFF_DONE chp %p chan_byte %04x\n", c tryme: /* if the interrupt is not zero'd here, we get SPAD error */ irq_pend = 0; /* not pending anymore */ -//25irq_pend = 0; /* not pending anymore */ -#ifndef TEST_082520 - if (RDYQ_Num()) { -#ifdef USE_RDYQ - if (waitrdyq > 0) { - waitrdyq--; - irq_pend = 1; /* still pending */ - } else -#endif - /* we have entries, continue channel program */ - if (RDYQ_Get(&chsa) == SCPE_OK) { /* get chsa for program */ - int32 stat; -//25 irq_pend = 0; /* not pending anymore */ - sim_debug(DEBUG_XIO, &cpu_dev, - "scan_chan CPU RDYQ entry for chsa %04x starting\n", chsa); - stat = cont_chan(chsa); /* resume the channel program */ - if (stat == SCPE_OK) /* done, status stored */ - sim_debug(DEBUG_XIO, &cpu_dev, - "CPU RDYQ entry for chsa %04x processed\n", chsa); - } - } -#endif return 0; /* done */ } @@ -2272,7 +2748,7 @@ t_stat chan_set_devs() { 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 */ -sim_debug(DEBUG_EXP, &cpu_dev, "chan_set_devs BUFF_EMPTY chp %p chan_byte %04x\n", chp, chp->chan_byte); +//sim_debug(DEBUG_EXP, &cpu_dev, "chan_set_devs BUFF_EMPTY chp %p chan_byte %04x\n", chp, chp->chan_byte); chp->ccw_addr = 0; /* start loading at loc 0 */ chp->chan_caw = 0; /* set IOCD address to memory location 0 */ chp->ccw_count = 0; /* channel byte count 0 bytes*/ @@ -2359,7 +2835,7 @@ t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { t_value chan; /* new channel addr */ t_stat r; /* return status */ int i; /* temp */ - int chsa; /* dev addr */ + int chsa, ochsa; /* dev addr */ // fprintf(stderr, "Set dev entry DEVICE ptr %s\r\n", cptr); if (cptr == NULL) /* is there a UNIT name specified */ @@ -2390,19 +2866,20 @@ t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { /* change all the unit addresses with the new channel, but keep sub address */ /* Clear out existing entries for all units on this device */ tuptr = dptr->units; /* get pointer to units defined for this device */ -// fprintf(stderr, "Set dev new addr %s chan %02x units %02x\r\n", cptr, chan, dibp->numunits); + fprintf(stderr, "Set dev new addr %s chan %04X units %02X\r\n", cptr, chan, dibp->numunits); /* 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 */ - 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 */ + ochsa = GET_UADDR(tuptr->u3); /* get old chsa for this unit */ + dib_unit[ochsa] = NULL; /* clear sa dib pointer */ + dib_unit[ochsa&0x7f00] = NULL; /* clear the channel dib address */ + chsa = chan | (ochsa & 0xff); /* merge new channel with old sa */ tuptr->u3 &= ~UNIT_ADDR_MASK; /* clear old chsa for this unit */ - tuptr->u3 |= UNIT_ADDR(chsa); /* clear old chsa for this unit */ + tuptr->u3 |= UNIT_ADDR(chsa); /* set new chsa for this unit */ 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); + fprintf(stderr, "Set old chsa %04X to new addr %04X new chsa %04X\r\n", + ochsa, GET_UADDR(tuptr->u3), chsa); tuptr++; /* next unit pointer */ } return SCPE_OK; @@ -2423,62 +2900,3 @@ t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc) { return SCPE_OK; /* we done */ } -#ifndef GEERT_UNDO -void CatchSig() { - void ReportIRQs(); - - /* re-install signal handler */ - signal(SIGQUIT, CatchSig); - - sim_debug(DEBUG_IRQ, &cpu_dev, "SIG[%d] CPUSTATUS=%08x\n", - ScanCycles, CPUSTATUS); - - ReportIRQs(); - DoNextCycles = 20; -} - -void ReportIRQs() { - int i, irqs = 0; - int levels[5]; - char *s; - - for (i=0; i<112; i++) - if (INTS[i] & INTS_REQ) { - if (irqs < 5) - levels[irqs] = i; - irqs++; - } - - if (CPUSTATUS & 0x80) - s = " BLOCKED"; - else - s = ""; - - switch (irqs) { - case 1: - sim_debug(DEBUG_IRQ, &cpu_dev, - "SIG[%d]%s irq_pend=%d, ACT=%d: %x\n", - ScanCycles, s, irq_pend, irqs, levels[0]); - break; - case 2: - sim_debug(DEBUG_IRQ, &cpu_dev, - "SIG[%d]%s irq_pend=%d, ACT=%d: %x, %x\n", - ScanCycles, s, irq_pend, irqs, levels[0], levels[1]); - break; - case 3: - sim_debug(DEBUG_IRQ, &cpu_dev, - "SIG[%d]%s irq_pend=%d, ACT=%d: %x, %x, %x\n", - ScanCycles, s, irq_pend, irqs, levels[0], levels[1], levels[2]); - break; - case 4: - sim_debug(DEBUG_IRQ, &cpu_dev, - "SIG[%d]%s irq_pend=%d, ACT=%d: %x, %x, %x, %x\n", - ScanCycles, s, irq_pend, irqs, levels[0], levels[1], levels[2], levels[3]); - break; - default: - sim_debug(DEBUG_IRQ, &cpu_dev, - "SIG[%d]%s irq_pend=%d, ACT=%d\n", - ScanCycles, s, irq_pend, irqs); - } -} -#endif diff --git a/SEL32/sel32_clk.c b/SEL32/sel32_clk.c index f401942..9343194 100644 --- a/SEL32/sel32_clk.c +++ b/SEL32/sel32_clk.c @@ -128,7 +128,7 @@ t_stat rtc_srv (UNIT *uptr) ((SPAD[rtc_lvl+0x80] & SINT_ACT) == 0))) { /* in spad too */ /* HACK for console I/O stopping */ /* This reduces the number of console I/O stopping errors */ - /* need tp find real cause of I/O stopping on clock interrupt */ + /* need to find real cause of I/O stopping on clock interrupt */ if ((outbusy==0) && (inbusy==0)) /* skip interrupt if con I/O in busy wait */ INTS[rtc_lvl] |= INTS_REQ; /* request the interrupt */ irq_pend = 1; /* make sure we scan for int */ @@ -247,9 +247,9 @@ const char *itm_desc(DEVICE *dptr); itm_reg Interval Timer ITM register list */ -/* Mike suggested I remove the UNIT_IDLE flag from ITM. This causes SEL32 */ +/* Mark suggested I remove the UNIT_IDLE flag from ITM. This causes SEL32 */ /* to use 100% of the CPU instead of waiting and running 10% cpu usage */ -//BAD Mike UNIT itm_unit = { UDATA (&itm_srv, 0, 0), 26042, UNIT_ADDR(0x7F04)}; +//BAD Mark UNIT itm_unit = { UDATA (&itm_srv, UNIT_IDLE, 0), 26042, UNIT_ADDR(0x7F04)}; UNIT itm_unit = { UDATA (&itm_srv, 0, 0), 26042, UNIT_ADDR(0x7F04)}; REG itm_reg[] = { @@ -493,7 +493,7 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) if (itm_run) { /* if we were running save curr cnt */ /* read timer value */ temp = (uint32)(100.0*sim_activate_time_usecs(&itm_unit)/itm_tick_size_x_100); - sim_debug(DEBUG_CMD, &itm_dev, "Intv 0x%2x temp value %08x (%d)\n", cmd, temp, temp); + sim_debug(DEBUG_CMD, &itm_dev, "Intv 0x%2x read value %08x (%d)\n", cmd, temp, temp); if (itm_strt) { /* see if running neg */ /* we only get here if timer ran out and no reload value */ /* get simulated negative start time in counts */ @@ -510,7 +510,7 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) if (itm_run) { /* if we were running save curr cnt */ /* read timer value */ temp = (uint32)(100.0*sim_activate_time_usecs(&itm_unit)/itm_tick_size_x_100); - sim_debug(DEBUG_CMD, &itm_dev, "Intv 0x%2x temp value %08x (%d)\n", cmd, temp, temp); + sim_debug(DEBUG_CMD, &itm_dev, "Intv 0x%2x read value %08x (%d)\n", cmd, temp, temp); if (itm_strt) { /* see if running neg */ /* we only get here if timer ran out and no reload value */ /* get simulated negative start time in counts */ @@ -534,7 +534,7 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) if (itm_run) { /* if we were running save curr cnt */ /* read timer value */ temp = (uint32)(100.0*sim_activate_time_usecs(&itm_unit)/itm_tick_size_x_100); - sim_debug(DEBUG_CMD, &itm_dev, "Intv 0x%2x temp value %08x (%d)\n", cmd, temp, temp); + sim_debug(DEBUG_CMD, &itm_dev, "Intv 0x%2x read value %08x (%d)\n", cmd, temp, temp); if (itm_strt) { /* see if running neg */ /* we only get here if timer ran out and no reload value */ /* get simulated negative start time in counts */ @@ -565,7 +565,7 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) if (itm_run) { /* if we were running save curr cnt */ /* read timer value */ temp = (uint32)(100.0*sim_activate_time_usecs(&itm_unit)/itm_tick_size_x_100); - sim_debug(DEBUG_CMD, &itm_dev, "Intv 0x%2x temp value %08x (%d)\n", cmd, temp, temp); + sim_debug(DEBUG_CMD, &itm_dev, "Intv 0x%2x read value %08x (%d)\n", cmd, temp, temp); if (itm_strt) { /* see if running neg */ /* we only get here if timer ran out and no reload value */ /* get simulated negative start time in counts */ diff --git a/SEL32/sel32_com.c b/SEL32/sel32_com.c index c7c7946..c8f341b 100644 --- a/SEL32/sel32_com.c +++ b/SEL32/sel32_com.c @@ -242,12 +242,16 @@ UNIT com_unit[] = { DIB com_dib = { NULL, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ com_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ + NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + NULL, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ com_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ com_unit, /* UNIT* units */ /* Pointer to units structure */ com_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NULL, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ COM_UNITS, /* uint8 numunits */ /* number of units defined */ 0xFF, /* uint8 mask */ /* 16 devices - device mask */ 0x7E00, /* uint16 chan_addr */ /* parent channel address */ @@ -314,12 +318,16 @@ UNIT coml_unit[] = { DIB coml_dib = { NULL, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ com_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ + NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + NULL, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ coml_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ coml_unit, /* UNIT* units */ /* Pointer to units structure */ coml_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NULL, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ COM_LINES*2, /* uint8 numunits */ /* number of units defined */ 0xff, /* uint8 mask */ /* 16 devices - device mask */ 0x7E00, /* uint16 chan_addr */ /* parent channel address */ diff --git a/SEL32/sel32_con.c b/SEL32/sel32_con.c index 56acf83..cf83085 100644 --- a/SEL32/sel32_con.c +++ b/SEL32/sel32_con.c @@ -45,6 +45,7 @@ #define CON_NOP 0x03 /* No op command */ #define CON_SNS 0x04 /* Sense command */ #define CON_ECHO 0x0a /* Read with Echo */ +#define CON_RDBWD 0x0c /* Read backward */ #define CON_CON 0x1f /* connect line */ #define CON_DIS 0x23 /* disconnect line */ #define CON_RWD 0x37 /* TOF and write line */ @@ -53,10 +54,10 @@ /* Status held in u3 */ /* controller/unit address in upper 16 bits */ -#define CON_INPUT 0x100 /* Input ready for unit */ -#define CON_CR 0x200 /* Output at beginning of line */ -#define CON_REQ 0x400 /* Request key pressed */ -#define CON_EKO 0x800 /* Echo input character */ +#define CON_INPUT 0x0100 /* Input ready for unit */ +#define CON_CR 0x0200 /* Output at beginning of line */ +#define CON_REQ 0x0400 /* Request key pressed */ +#define CON_EKO 0x0800 /* Echo input character */ #define CON_OUTPUT 0x1000 /* Output ready for unit */ #define CON_READ 0x2000 /* Read mode selected */ #define CON_ATAT 0x4000 /* working on @@A input */ @@ -119,12 +120,16 @@ UNIT con_unit[] = { DIB con_dib = { con_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Start I/O */ con_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - con_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + con_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ + NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + NULL, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ con_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ con_unit, /* UNIT* units */ /* Pointer to units structure */ con_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NULL, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ NUM_UNITS_CON, /* uint8 numunits */ /* number of units defined */ 0x0f, /* uint8 mask */ /* 2 devices - device mask */ 0x7e00, /* uint16 chan_addr */ /* parent channel address */ @@ -165,13 +170,13 @@ uint16 con_preio(UNIT *uptr, uint16 chan) { } sim_debug(DEBUG_CMD, &con_dev, "con_preio unit=%02x OK\n", unit); - return 0; /* good to go */ + return SCPE_OK; /* good to go */ } /* start an I/O operation */ uint16 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { int unit = (uptr - con_unit); /* unit 0 is read, unit 1 is write */ - uint8 ch; +// uint8 ch; if ((uptr->CMD & CON_MSK) != 0) { /* is unit busy */ sim_debug(DEBUG_CMD, &con_dev, @@ -182,69 +187,42 @@ uint16 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { sim_debug(DEBUG_CMD, &con_dev, "con_startcmd unit %01x chan %02x cmd %02x enter\n", unit, chan, cmd); + + /* substitute CON_INCH2 for CON_INCH for pprocessing */ + if (cmd == CON_INCH) + cmd = CON_INCH2; /* save INCH command as 0xf0 */ + +// uptr->CMD &= LMASK; /* leave only chsa */ /* process the commands */ switch (cmd & 0xFF) { - case CON_INCH: /* 0x00 */ /* INCH command */ - sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %04x: Cmd INCH\n", chan); - 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 */ - if (unit == 1) -//720 sim_activate(uptr, 240); /* start us off */ - sim_activate(uptr, 200); /* start us off */ - return 0; /* no status change */ - break; - + case CON_ECHO: /* 0x0a */ /* Read command w/ECHO */ + uptr->CMD |= CON_EKO; /* save echo status */ + case CON_RD: /* 0x02 */ /* Read command */ + atbuf = 0; /* reset attention buffer */ + uptr->CMD |= CON_READ; /* show read mode */ + /* fall through */ + case CON_INCH2: /* 0xf0 */ /* INCH command */ case CON_RWD: /* 0x37 */ /* TOF and write line */ case CON_WR: /* 0x01 */ /* Write command */ - /* if input requested for output device, give error */ - uptr->CMD &= LMASK; /* leave only chsa */ - uptr->CMD |= (cmd & CON_MSK); /* save command */ - uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ - if (unit == 1) -//720 sim_activate(uptr, 240); /* start us off */ - sim_activate(uptr, 200); /* start us off */ - return 0; /* no status change */ - break; - - case CON_RD: /* 0x02 */ /* Read command */ - case CON_ECHO: /* 0x0a */ /* Read command w/ECHO */ - /* if output requested for input device, give error */ - uptr->CMD &= ~CON_MSK; /* remove old CMD */ - uptr->CMD |= (cmd & CON_MSK); /* save command */ - if (cmd == CON_ECHO) /* echo command? */ - uptr->CMD |= CON_EKO; /* save echo status */ - uptr->CMD |= CON_READ; /* show read mode */ - atbuf = 0; /* reset attention buffer */ - uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ - if (unit == 1) -//720 sim_activate(uptr, 240); /* start us off */ - sim_activate(uptr, 200); /* start us off */ - return 0; - break; - case CON_NOP: /* 0x03 */ /* NOP has do nothing */ - uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ + case CON_RDBWD: /* 0x0c */ /* Read Backward */ + uptr->SNS |= (SNS_RDY|SNS_ONLN); /* status is online & ready */ + case CON_CON: /* 0x1f */ /* Connect, return Data Set ready */ + case CON_DIS: /* 0x23 */ /* Disconnect has do nothing */ + case CON_SNS: /* 0x04 */ /* Sense */ uptr->CMD &= ~CON_MSK; /* remove old CMD */ uptr->CMD |= (cmd & CON_MSK); /* save command */ - if (unit == 1) -//720 sim_activate(uptr, 240); /* start us off */ - sim_activate(uptr, 200); /* start us off */ - return 0; /* no status change */ - break; - - case 0x0C: /* 0x0C */ /* Unknown command */ - uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ - uptr->CMD &= LMASK; /* leave only chsa */ - uptr->CMD |= (cmd & CON_MSK); /* save command */ - if (unit == 1) -//720 sim_activate(uptr, 240); /* start us off */ - sim_activate(uptr, 200); /* start us off */ - return 0; /* no status change */ + if (unit == 0) + sim_cancel(uptr); /* stop input poll */ +// sim_activate(uptr, 400); /* start us off */ +// sim_activate(uptr,1000); /* start us off */ + sim_activate(uptr, 500); /* start us off */ + return SCPE_OK; /* no status change */ break; +#ifdef NONO case CON_CON: /* 0x1f */ /* Connect, return Data Set ready */ - sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %04x: Cmd %02x CON\n", chan, cmd); + sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %04x: Cmd %02xN\n", chan, cmd); uptr->SNS |= (SNS_DSR|SNS_DCD); /* Data set ready, Data Carrier detected */ return SNS_CHNEND|SNS_DEVEND; /* good return */ break; @@ -264,6 +242,7 @@ uint16 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { chan_write_byte(GET_UADDR(uptr->CMD), &ch); /* write status */ return SNS_CHNEND|SNS_DEVEND; /* good return */ break; +#endif default: /* invalid command */ break; @@ -273,7 +252,7 @@ uint16 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %04x: Invalid command %02x Sense %02x\n", chan, cmd, uptr->SNS); - return SNS_CHNEND|STATUS_PCHK; + return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; } /* Handle output transfers for console */ @@ -296,7 +275,7 @@ t_stat con_srvo(UNIT *uptr) { /* if input tried from output device, error */ case CON_RD: /* 0x02 */ /* Read command */ case CON_ECHO: /* 0x0a */ /* Read command w/ECHO */ - case 0x0C: /* 0x0C */ /* Unknown command */ + case CON_RDBWD: /* 0x0c */ /* Read Backward */ /* if input requested for output device, give error */ uptr->SNS |= SNS_CMDREJ; /* command rejected */ uptr->CMD &= LMASK; /* nothing left, command complete */ @@ -305,6 +284,22 @@ t_stat con_srvo(UNIT *uptr) { chan_end(chsa, SNS_CHNEND|SNS_UNITCHK); /* unit check */ break; + case CON_CON: /* 0x1f */ /* Connect, return Data Set ready */ + uptr->SNS |= (SNS_DSR|SNS_DCD); /* Data set ready, Data Carrier detected */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvo CON CMD %08x chsa %04x cmd = %02x\n", uptr->CMD, chsa, cmd); + uptr->CMD &= ~CON_MSK; /* remove old CMD */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case CON_DIS: /* 0x23 */ /* Disconnect has do nothing */ + uptr->SNS &= ~(SNS_DSR|SNS_DCD); /* Data set not ready */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvo DIS CMD %08x chsa %04x cmd = %02x\n", uptr->CMD, chsa, cmd); + uptr->CMD &= ~CON_MSK; /* remove old CMD */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + case CON_INCH2: /* 0xf0 */ /* INCH command */ uptr->CMD &= LMASK; /* nothing left, command complete */ sim_debug(DEBUG_CMD, &con_dev, @@ -324,28 +319,53 @@ t_stat con_srvo(UNIT *uptr) { } sim_debug(DEBUG_CMD, &con_dev, "con_srvo INCH CMD %08x chsa %04x len %02x inch %06x\n", uptr->CMD, chsa, len, mema); - chan_end(chsa, SNS_CHNEND); /* return OK */ + /* WARNING, if SNS_DEVEND is not set, diags fail by looping in CON diag */ +//1003 chan_end(chsa, SNS_CHNEND); /* return OK */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; case CON_NOP: /* 0x03 */ /* NOP has do nothing */ - uptr->CMD &= LMASK; /* nothing left, command complete */ - sim_debug(DEBUG_CMD, &con_dev, - "con_srvo NOP unit %02x: CMD %08x cmd %02x incnt %02x u4 %02x\n", - unit, uptr->CMD, cmd, con_data[unit].incnt, uptr->u4); +//1003 uptr->CMD &= LMASK; /* nothing left, command complete */ + uptr->CMD &= ~CON_MSK; /* remove old CMD */ sim_debug(DEBUG_CMD, &con_dev, "con_srvo NOP CMD %08x chsa %04x cmd = %02x\n", uptr->CMD, chsa, cmd); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; + case CON_SNS: /* 0x04 */ /* Sense */ + /* value 4 is Data Set Ready */ + /* value 5 is Data carrier detected n/u */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvo cmd %04x: Cmd Sense %02x\n", chsa, uptr->SNS); + /* value 4 is Data Set Ready */ + /* value 5 is Data carrier detected n/u */ + ch = uptr->SNS & 0xff; /* Sense byte 3 */ + if (chan_write_byte(chsa, &ch)) { /* write byte to memory */ + /* write error */ + cmd = 0; /* no cmd now */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvo write error unit %02x: CMD %08x read %02x u4 %02x ccw_count %02x\n", + unit, uptr->CMD, ch, uptr->u4, chp->ccw_count); + uptr->CMD &= LMASK; /* nothing left, command complete */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ + break; + } + uptr->CMD &= LMASK; /* nothing left, command complete */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* good return */ + break; + case CON_RWD: /* 0x37 */ /* TOF and write line */ case CON_WR: /* 0x01 */ /* Write command */ +#ifdef OLDWAY /* see if write complete */ if (uptr->CMD & CON_OUTPUT) { /* write is complete, post status */ sim_debug(DEBUG_CMD, &con_dev, "con_srvo write CMD %08x chsa %04x cmd %02x complete\n", uptr->CMD, chsa, cmd); - uptr->CMD &= LMASK; /* nothing left, command complete */ +//1003 uptr->CMD &= LMASK; /* nothing left, command complete */ + uptr->CMD &= ~CON_MSK; /* remove old CMD */ + uptr->CMD &= ~CON_OUTPUT; /* remove output command */ /*RTC*/ outbusy = 0; /* output done */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ break; @@ -362,13 +382,31 @@ t_stat con_srvo(UNIT *uptr) { uptr->CMD |= CON_OUTPUT; /* output command complete */ sim_debug(DEBUG_CMD, &con_dev, "con_srvo write wait %03x CMD %08x chsa %04x cmd %02x to complete\n", -// 41*cnt+47, uptr->CMD, chsa, cmd); - 19*cnt+23, uptr->CMD, chsa, cmd); + 41*cnt+47, uptr->CMD, chsa, cmd); +// 19*cnt+23, uptr->CMD, chsa, cmd); // sim_activate(uptr, 19*cnt+23); /* wait for a while */ // sim_activate(uptr, 31*cnt+47); /* wait for a while */ /*719*/ sim_activate(uptr, 41*cnt+47); /* wait for a while */ //719 sim_activate(uptr, 81*cnt+87); /* wait for a while */ break; +#else +/*RTC*/ outbusy = 1; /* tell clock output waiting */ + /* Write to device */ + while (chan_read_byte(chsa, &ch) == SCPE_OK) { /* get byte from memory */ + /* HACK HACK HACK */ + ch &= 0x7f; /* make 7 bit w/o parity */ + sim_putchar(ch); /* output next char to device */ + cnt++; /* count chars output */ + } + /* write is complete, post status */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvo write CMD %08x chsa %04x cmd %02x complete\n", + uptr->CMD, chsa, cmd); + uptr->CMD &= LMASK; /* nothing left, command complete */ +/*RTC*/ outbusy = 0; /* output done */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ + break; +#endif } return SCPE_OK; } @@ -384,9 +422,10 @@ t_stat con_srvi(UNIT *uptr) { uint32 tstart; uint8 ch; t_stat r; + int32 wait_time=10000; // sim_clock_coschedule(uptr, tmxr_poll); /* keep polling the input */ - sim_clock_coschedule(uptr, 10000); /* keep polling the input */ +// sim_clock_coschedule(uptr, 10000); /* keep polling the input */ sim_debug(DEBUG_CMD, &con_dev, "con_srvi enter CMD %08x chsa %04x cmd %02x incnt %02x u4 %02x\n", @@ -397,7 +436,6 @@ t_stat con_srvi(UNIT *uptr) { /* if output tried to input device, error */ case CON_RWD: /* 0x37 */ /* TOF and write line */ case CON_WR: /* 0x01 */ /* Write command */ - case 0x0C: /* 0x0C */ /* Unknown command */ /* if input requested for output device, give error */ uptr->SNS |= SNS_CMDREJ; /* command rejected */ uptr->CMD &= LMASK; /* nothing left, command complete */ @@ -427,23 +465,61 @@ t_stat con_srvi(UNIT *uptr) { uptr->u4 = 0; /* no I/O yet */ sim_debug(DEBUG_CMD, &con_dev, "con_srvi INCH CMD %08x chsa %04x len %02x inch %06x\n", uptr->CMD, chsa, len, mema); + /* WARNING, if SNS_DEVEND is not set, diags fail by looping in CON diag */ +//1003 chan_end(chsa, SNS_CHNEND); /* return OK */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ /* drop through to poll input */ break; case CON_NOP: /* 0x03 */ /* NOP has do nothing */ - uptr->CMD &= LMASK; /* nothing left, command complete */ - sim_debug(DEBUG_CMD, &con_dev, - "con_srvi NOP unit %02x: CMD %08x cmd %02x incnt %02x u4 %02x\n", - unit, uptr->CMD, cmd, con_data[unit].incnt, uptr->u4); +//1003 uptr->CMD &= LMASK; /* nothing left, command complete */ + uptr->CMD &= ~CON_MSK; /* remove old CMD */ sim_debug(DEBUG_CMD, &con_dev, "con_srvi NOP CMD %08x chsa %04x cmd = %02x\n", uptr->CMD, chsa, cmd); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ /* drop through to poll input */ break; - case CON_RD: /* 0x02 */ /* read from device */ + case CON_CON: /* 0x1f */ /* Connect, return Data Set ready */ + uptr->SNS |= (SNS_DSR|SNS_DCD); /* Data set ready, Data Carrier detected */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi CON CMD %08x chsa %04x cmd = %02x\n", uptr->CMD, chsa, cmd); + uptr->CMD &= ~CON_MSK; /* remove old CMD */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case CON_DIS: /* 0x23 */ /* Disconnect has do nothing */ + uptr->SNS &= ~(SNS_DSR|SNS_DCD); /* Data set not ready */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi DIS CMD %08x chsa %04x cmd = %02x\n", uptr->CMD, chsa, cmd); + uptr->CMD &= ~CON_MSK; /* remove old CMD */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case CON_SNS: /* 0x04 */ /* Sense */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi cmd %04x: Cmd Sense %02x\n", chsa, uptr->SNS); + /* value 4 is Data Set Ready */ + /* value 5 is Data carrier detected n/u */ + ch = uptr->SNS & 0xff; /* Sense byte 3 */ + if (chan_write_byte(chsa, &ch)) { /* write byte to memory */ + /* write error */ + cmd = 0; /* no cmd now */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi write error unit %02x: CMD %08x read %02x u4 %02x ccw_count %02x\n", + unit, uptr->CMD, ch, uptr->u4, chp->ccw_count); + uptr->CMD &= LMASK; /* nothing left, command complete */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ + break; + } + uptr->CMD &= LMASK; /* nothing left, command complete */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ + break; + case CON_ECHO: /* 0x0a */ /* read from device w/ECHO */ + uptr->CMD |= CON_EKO; /* save echo status */ + case CON_RD: /* 0x02 */ /* read from device */ + case CON_RDBWD: /* 0x0c */ /* Read Backward */ if ((uptr->u4 != con_data[unit].incnt) || /* input empty */ (uptr->CMD & CON_INPUT)) { /* input waiting? */ @@ -457,46 +533,51 @@ t_stat con_srvi(UNIT *uptr) { ch = con_data[unit].ibuff[uptr->u4]; /* get char from read buffer */ #ifndef ECHO_ON_READ_092220 /* this fixes mpx1x time entry on startup */ - if (uptr->CMD & CON_EKO) /* ECHO requested */ - sim_putchar(ch); /* ECHO the char */ + if (uptr->CMD & CON_EKO) /* ECHO requested */ + sim_putchar(ch); /* ECHO the char */ #endif - if (chan_write_byte(chsa, &ch)) { /* write byte to memory */ /* write error */ cmd = 0; /* no cmd now */ sim_debug(DEBUG_CMD, &con_dev, "con_srvi write error unit %02x: CMD %08x read %02x u4 %02x ccw_count %02x\n", unit, uptr->CMD, ch, uptr->u4, chp->ccw_count); - uptr->CMD &= LMASK; /* nothing left, command complete */ +// uptr->CMD &= LMASK; /* nothing left, command complete */ + uptr->CMD &= ~CON_MSK; /* remove old CMD */ + uptr->CMD &= ~CON_INPUT; /* input waiting? */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; } + /* character accepted, bump buffer pointer */ + uptr->u4++; /* next char position */ + sim_debug(DEBUG_CMD, &con_dev, "con_srvi write to mem unit %02x: CMD %08x read %02x u4 %02x incnt %02x\n", unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt); - /* character accepted, bump buffer pointer */ - uptr->u4++; /* next char position */ /* see if at end of buffer */ - if (uptr->u4 >= sizeof(con_data[unit].ibuff)) + if (uptr->u4 >= (int32)sizeof(con_data[unit].ibuff)) uptr->u4 = 0; /* reset pointer */ /* user want more data? */ if ((test_write_byte_end(chsa)) == 0) { sim_debug(DEBUG_CMD, &con_dev, - "con_srvi need more unit %02x CMD %08x u4 %02x incnt %02x ccw_count %02x\n", - unit, uptr->CMD, uptr->u4, con_data[unit].incnt, chp->ccw_count); + "con_srvi need more unit %02x CMD %08x u4 %02x ccw_count %02x incnt %02x\n", + unit, uptr->CMD, uptr->u4, chp->ccw_count, con_data[unit].incnt); /* user wants more, look next time */ if (uptr->u4 == con_data[unit].incnt) { /* input empty */ uptr->CMD &= ~CON_INPUT; /* no input available */ } +// wait_time = 200; /* process next time */ +// wait_time = 400; /* process next time */ + wait_time = 800; /* process next time */ break; } /* command is completed */ cmd = 0; /* no cmd now */ sim_debug(DEBUG_CMD, &con_dev, - "con_srvi read done unit %02x: CMD %08x read %02x u4 %02x incnt %02x ccw_count %02x\n", - unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt, chp->ccw_count); + "con_srvi read done unit %02x CMD %08x read %02x u4 %02x ccw_count %02x incnt %02x\n", + unit, uptr->CMD, ch, uptr->u4, chp->ccw_count, con_data[unit].incnt); uptr->CMD &= LMASK; /* nothing left, command complete */ if (uptr->u4 != con_data[unit].incnt) { /* input empty */ uptr->CMD |= CON_INPUT; /* input still available */ @@ -504,7 +585,9 @@ t_stat con_srvi(UNIT *uptr) { chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; } + break; } + default: break; } @@ -512,7 +595,8 @@ t_stat con_srvi(UNIT *uptr) { r = sim_poll_kbd(); /* poll for a char */ if (r & SCPE_KFLAG) { /* got a char */ ch = r & 0xff; /* drop any extra bits */ - if ((uptr->CMD & CON_INPUT) == 0) { /* looking for input? */ +//1003 if ((uptr->CMD & CON_INPUT) == 0) { /* looking for input? */ + if ((uptr->CMD & CON_READ)) { /* looking for input? */ atbuf = 0; /* reset attention buffer */ uptr->CMD &= ~CON_ATAT; /* no @@A input */ if (ch == '@') { /* maybe for console int */ @@ -521,16 +605,9 @@ t_stat con_srvi(UNIT *uptr) { } if (ch == '\n') /* convert newline */ ch = '\r'; /* make newline into carriage return */ -#ifdef TESTING - if (ch == 3) { /* see if C */ sim_debug(DEBUG_CMD, &con_dev, - "con_srvi ctrl^C readch unit %02x: CMD %08x read %02x u4 %02x incnt %02x\n", - unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt); - } -#endif - sim_debug(DEBUG_CMD, &con_dev, - "con_srvi handle readch unit %02x: CMD %08x read %02x u4 %02x incnt %02x\n", - unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt); + "con_srvi handle readch unit %02x: CMD %08x read %02x u4 %02x incnt %02x r %x\n", + unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt, r); #ifdef ECHO_ON_READ_092220 /* this fixes mpx1x time entry on startup */ @@ -549,6 +626,8 @@ t_stat con_srvi(UNIT *uptr) { sim_debug(DEBUG_CMD, &con_dev, "con_srvi readch unit %02x: CMD %08x read %02x u4 %02x incnt %02x\n", unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt); + sim_activate(uptr, 400); /* do this again */ +// sim_activate(uptr, 800); /* do this again */ // return sim_activate (uptr, 30); /* come back real soon */ return SCPE_OK; } @@ -577,6 +656,8 @@ t_stat con_srvi(UNIT *uptr) { uptr->u4 = 0; /* no input count */ con_data[unit].incnt = 0; /* no input data */ } +// sim_activate(uptr, wait_time); /* do this again */ + sim_activate(uptr, 400); /* do this again */ return SCPE_OK; } /* char not for us, so keep looking */ @@ -594,17 +675,20 @@ t_stat con_srvi(UNIT *uptr) { if (con_data[unit].incnt >= sizeof(con_data[unit].ibuff)) con_data[unit].incnt = 0; /* reset buffer cnt */ +#ifdef ECHO_ON_READ_092220 if (uptr->CMD & CON_EKO) /* ECHO requested */ sim_putchar(ch); /* ECHO the char */ +#endif /* put char in buffer */ con_data[unit].ibuff[con_data[unit].incnt++] = ch; uptr->CMD |= CON_INPUT; /* we have a char available */ sim_debug(DEBUG_CMD, &con_dev, - "con_srvi readch2 unit %02x: CMD %08x read %02x u4 %02x incnt %02x\n", - unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt); + "con_srvi readch2 unit %02x: CMD %08x read %02x u4 %02x incnt %02x r %x\n", + unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt, r); } + sim_activate(uptr, wait_time); /* do this again */ return SCPE_OK; } diff --git a/SEL32/sel32_cpu.c b/SEL32/sel32_cpu.c index 7a9949a..63f9cb6 100644 --- a/SEL32/sel32_cpu.c +++ b/SEL32/sel32_cpu.c @@ -24,6 +24,8 @@ #include "sel32_defs.h" +#define DO_DYNAMIC_DEBUG + /* 32/7x PSW/PSD Mode Trap/Interrupt Priorities */ /* Relative Logical Int Vect TCW IOCD Description */ /* Priority Priority Location Addr Addr */ @@ -196,6 +198,7 @@ uint32 BPIX=0; /* # pages loaded for O/S */ uint32 CPIXPL=0; /* highest page loaded for User */ uint32 CPIX=0; /* CPIX user MPL offset */ uint32 HIWM=0; /* max maps loaded so far */ +uint32 MODES=0; /* Operating modes, bits 0, 5, 6, 7 of PSD1 */ uint32 TLB[2048]; /* Translated addresses for each map entry */ /* bits 0-4 are bits 0-4 from map entry */ /* bit 0 valid */ @@ -210,7 +213,6 @@ uint32 TLB[2048]; /* Translated addresses for each map /* bit 19-31 is zero for page offset of zero */ uint32 dummy2=0; -uint32 modes; /* Operating modes, bits 0, 5, 6, 7 of PSD1 */ uint8 wait4int = 0; /* waiting for interrupt if set */ int32 irq_auto = 0; /* auto reset interrupt processing flag */ @@ -222,7 +224,6 @@ uint32 RDYQIN; /* fifo input index */ uint32 RDYQOUT; /* fifo output index */ uint32 RDYQ[128]; /* channel ready queue */ uint8 waitqcnt = 0; /* # instructions before start */ -uint8 waitrdyq = 0; /* # instructions before post inturrupt */ struct InstHistory { @@ -343,6 +344,7 @@ REG cpu_reg[] = { {HRDATAD(CPUSTATUS, CPUSTATUS, 32, "CPU Status Word"), REG_FIT}, {HRDATAD(TRAPSTATUS, TRAPSTATUS, 32, "TRAP Status Word"), REG_FIT}, {HRDATAD(CC, CC, 32, "Condition Codes"), REG_FIT}, + {HRDATAD(MODES, MODES, 32, "Mode bits"), REG_FIT}, {BRDATAD(INTS, INTS, 16, 32, 112, "Interrupt Status"), REG_FIT}, {HRDATAD(CMCR, CMCR, 32, "Cache Memory Control Register"), REG_FIT}, {HRDATAD(SMCR, SMCR, 32, "Shared Memory Control Register"), REG_FIT}, @@ -710,7 +712,7 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) if (CPU_MODEL < MODEL_27) { MAXMAP = MAX32; /* 32 maps for 32/77 */ /* 32/7x machine, 8KW maps 32 maps total */ - modes &= ~BASEBIT; /* no basemode on 7x */ + MODES &= ~BASEBIT; /* no basemode on 7x */ if ((thepsd[1] & 0xc0000000) == 0) /* mapped mode? */ return ALLOK; /* no, all OK, no mapping required */ @@ -850,7 +852,7 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) /* V6 and V9 must load O/S maps and have user maps allocated and loaded on access */ /* See if any mapping to take place */ - if ((modes & MAPMODE) == 0) /* mapped mode? */ + if ((MODES & MAPMODE) == 0) /* mapped mode? */ return ALLOK; /* no, all OK, no mapping required */ /* set maximum maps for 32/27 and 32/87 processors */ @@ -864,7 +866,7 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) /* master process list is in 0xf3 of spad for concept machines */ mpl = SPAD[0xf3]; /* get mpl from spad address */ - /* diags want the mpl entries checked to make sure valid dbl wowrd address */ + /* diags want the mpl entries checked to make sure valid dbl word address */ if (mpl & 0x7) { /* test for double word address */ sim_debug(DEBUG_TRAP, &cpu_dev, "load_maps MPL not on double word boundry %06x\n", mpl); @@ -891,7 +893,7 @@ npmem: return NPMEM; /* non present memory error */ } - /* output O/S and User MPX entries */ + /* output O/S and User MPL entries */ sim_debug(DEBUG_DETAIL, &cpu_dev, "#MEMORY %06x MPL %06x MPL[0] %08x %06x MPL[%04x] %08x %06x\n", MEMSIZE, mpl, RMW(mpl), RMW(mpl+4), cpix, @@ -1231,11 +1233,11 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) /* see what machine we have */ if (CPU_MODEL < MODEL_27) { /* 32/7x machine with 8KW maps */ - if (modes & EXTDBIT) + if (MODES & EXTDBIT) word = addr & 0xfffff; /* get 20 bit logical word address */ else word = addr & 0x7ffff; /* get 19 bit logical word address */ - if ((modes & MAPMODE) == 0) { + if ((MODES & MAPMODE) == 0) { /* check if valid real address */ if (!MEM_ADDR_OK(word)) { /* see if address is within our memory */ return NPMEM; /* no, none present memory error */ @@ -1259,7 +1261,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) /* check if valid real address */ if (!MEM_ADDR_OK(word)) /* see if address is within our memory */ return NPMEM; /* no, none present memory error */ - if ((modes & PRIVBIT) == 0) { /* see if we are in unprivileged mode */ + if ((MODES & PRIVBIT) == 0) { /* see if we are in unprivileged mode */ if (map & 0x2000) /* check if protect bit is set in map entry */ *prot = 1; /* return memory write protection status */ } @@ -1271,12 +1273,12 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) /* Everyone else has 2KW maps */ /* do common processing */ /* diag wants the address to be 19 or 24 bit, use masked address */ - if (modes & (BASEBIT | EXTDBIT)) + if (MODES & (BASEBIT | EXTDBIT)) word = addr & 0xffffff; /* get 24 bit address */ else word = addr & 0x7ffff; /* get 19 bit address */ - if ((modes & MAPMODE) == 0) { + if ((MODES & MAPMODE) == 0) { /* we are in unmapped mode, check if valid real address */ if (!MEM_ADDR_OK(word)) { /* see if address is within our memory */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { @@ -1375,7 +1377,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) } word = (raddr & 0xffe000) | offset; /* combine real addr and offset */ *realaddr = word; /* return the real address */ - if (modes & BIT0) /* all OK if privledged */ + if (MODES & PRIVBIT) /* all OK if privledged */ return ALLOK; /* all OK, return instruction */ /* get user protection status of map */ @@ -1421,7 +1423,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) if (CPU_MODEL < MODEL_V6) { /* process 32/67 & 32/97 load map on access */ /* handle 32/67 & 32/97 */ - if (modes & BIT0) /* all OK if privledged */ + if (MODES & PRIVBIT) /* all OK if privledged */ return ALLOK; /* all OK, return instruction */ /* get protection status of map */ @@ -1438,7 +1440,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) /* handle valid V6 & V9 HIT bit on */ /* get protection status of map */ offset = ((map >> 12) & 0x6); /* get bits p1 & p2 from map into bits 13 & 14 */ - if (modes & BIT0) /* all access if privledged */ + if (MODES & PRIVBIT) /* all access if privledged */ *prot = offset | 0x8; /* set priv bit */ else *prot = offset; /* return memory write protection status */ @@ -1554,7 +1556,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) if ((CPU_MODEL == MODEL_67) || (CPU_MODEL == MODEL_97)) { /* get protection status of map */ - if ((modes & BIT0) == 0) { /* OK if privledged */ + if ((MODES & PRIVBIT) == 0) { /* OK if privledged */ /* otherwise check protection bit */ offset = (word >> 11) & 0x3; /* see which 1/4 page we are in */ if ((BIT1 >> offset) & raddr) /* is 1/4 page write protected */ @@ -1563,7 +1565,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) } else { /* get protection status of map */ offset = ((map >> 12) & 0x6); /* get bits p1 & p2 from map into bits 13 & 14 */ - if (modes & BIT0) /* all access if privledged */ + if (MODES & PRIVBIT) /* all access if privledged */ *prot = offset | 0x8; /* set priv bit */ else *prot = offset; /* return memory write protection status */ @@ -1671,7 +1673,7 @@ t_stat Mem_read(uint32 addr, uint32 *data) if (status == ALLOK) { *data = RMW(realaddr); /* valid address, get physical address contents */ if (((CPU_MODEL >= MODEL_V6) || (CPU_MODEL == MODEL_97) || - (CPU_MODEL == MODEL_67)) && (modes & MAPMODE)) { + (CPU_MODEL == MODEL_67)) && (MODES & MAPMODE)) { page = (addr >> 13) & 0x7ff; /* get 11 bit value */ if (CPU_MODEL >= MODEL_V6) { @@ -1681,7 +1683,7 @@ t_stat Mem_read(uint32 addr, uint32 *data) /* O/S or user has no read/execute access, do protection violation */ sim_debug(DEBUG_EXP, &cpu_dev, "Mem_readA protect error @ %06x prot %02x modes %08x page %04x\n", - addr, prot, modes, page); + addr, prot, MODES, page); if (CPU_MODEL == MODEL_V9) TRAPSTATUS |= BIT2; /* set bit 2 of trap status */ else @@ -1691,7 +1693,7 @@ t_stat Mem_read(uint32 addr, uint32 *data) /* O/S or user has read/execute access, no protection violation */ sim_debug(DEBUG_DETAIL, &cpu_dev, "Mem_readB protect is ok @ %06x prot %02x modes %08x page %04x\n", - addr, prot, modes, page); + addr, prot, MODES, page); } mpl = SPAD[0xf3]; /* get mpl from spad address */ nix = page & 0x7ff; /* map # or mapc index */ @@ -1759,7 +1761,7 @@ t_stat Mem_write(uint32 addr, uint32 *data) if (status == ALLOK) { if (((CPU_MODEL >= MODEL_V6) || (CPU_MODEL == MODEL_97) || - (CPU_MODEL == MODEL_67)) && (modes & MAPMODE)) { + (CPU_MODEL == MODEL_67)) && (MODES & MAPMODE)) { page = (addr >> 13) & 0x7ff; /* get 11 bit value */ if (CPU_MODEL >= MODEL_V6) { /* check for v6 & v9 if we have write access */ @@ -1767,7 +1769,7 @@ t_stat Mem_write(uint32 addr, uint32 *data) case 0x0: case 0x2: case 0x6: case 0xa: case 0xe: /* O/S or user has read/execute access, do protection violation */ sim_debug(DEBUG_DETAIL, &cpu_dev, - "Mem_writeA protect error @ %06x prot %02x modes %08x\n", addr, prot, modes); + "Mem_writeA protect error @ %06x prot %02x modes %08x\n", addr, prot, MODES); if (CPU_MODEL == MODEL_V9) TRAPSTATUS |= BIT1; /* set bit 1 of trap status */ else @@ -1776,7 +1778,7 @@ t_stat Mem_write(uint32 addr, uint32 *data) case 0x4: case 0x8: case 0xc: /* O/S or user has write access, no protection violation */ sim_debug(DEBUG_DETAIL, &cpu_dev, - "Mem_writeB protect is ok @ %06x prot %02x modes %08x\n", addr, prot, modes); + "Mem_writeB protect is ok @ %06x prot %02x modes %08x\n", addr, prot, MODES); } map = RMR((page<<1)); /* read the map reg contents */ raddr = TLB[page]; /* get the base address & bits */ @@ -1800,8 +1802,8 @@ t_stat Mem_write(uint32 addr, uint32 *data) addr, page, TLB[page], map, nmap, raddr); } sim_debug(DEBUG_DETAIL, &cpu_dev, - "Mem_write Xaddr %06x page %04x MA bits set TLB %08x map %04x prot %04x mode %04x\n", - addr, page, TLB[page], map, prot, modes); + "Mem_write Xaddr %06x page %04x MA bits set TLB %08x map %04x prot %04x modes %04x\n", + addr, page, TLB[page], map, prot, MODES); } else { if (prot) { /* check for write protected memory */ sim_debug(DEBUG_TRAP, &cpu_dev, @@ -1896,6 +1898,7 @@ t_stat sim_instr(void) { uint16 chan; /* I/O channel address */ uint16 lchan; /* Logical I/O channel address */ uint16 suba; /* I/O subaddress */ + uint16 lchsa; /* logical I/O channel & subaddress */ uint16 rchsa; /* real I/O channel & subaddress */ uint8 FC; /* Current F&C bits */ uint8 EXM_EXR=0; /* PC Increment for EXM/EXR instructions */ @@ -1910,7 +1913,7 @@ t_stat sim_instr(void) { int32 int32a; /* temp int */ int32 int32b; /* temp int */ int32 int32c; /* temp int */ -#ifdef DO_DYNAMIC_DEBUG +#ifdef DO_DYNAMIC_DEBUG1 int32 event = 0; #endif @@ -1922,16 +1925,30 @@ wait_loop: reason = sim_process_event(); /* process */ if (reason != SCPE_OK) { if (reason == SCPE_STEP) { + sim_debug(DEBUG_EXP, &cpu_dev, "Process Event step reason %08x interval %08x\n", + reason, sim_interval); //FORSTEP stopnext = 1; + return reason; break; - } else + } else { + sim_debug(DEBUG_EXP, &cpu_dev, "Process Event other reason %08x interval %08x\n", + reason, sim_interval); + return reason; break; /* process */ + } } } + if (sim_brk_summ) + sim_debug(DEBUG_EXP, &cpu_dev, "Process Event sim_brk_summ = %08x\n", + sim_brk_summ); + PC = PSD1 & 0xfffffe; /* get 24 bit addr from PSD1 */ /* stop simulator if user break requested */ if (sim_brk_summ && sim_brk_test(PC, SWMASK('E'))) { reason = STOP_IBKPT; + sim_debug(DEBUG_EXP, &cpu_dev, "Process Event test reason %08x interval %08x\n", + reason, sim_interval); + sim_interval= 0; /* count down */ break; } @@ -1939,16 +1956,11 @@ wait_loop: if (drop_nop) { /* need to drop a nop? */ PSD1 = (PSD1 + 2) | (((PSD1 & 2) >> 1) & 1); /* skip this instruction */ - PSD1 &= ~1; /* clear bit 31, no lr */ + PSD1 &= ~BIT31; /* clear bit 31, no lr */ drop_nop = 0; /* we dropped the nop */ } if (skipinstr) { /* need to skip interrupt test? */ -#ifdef NOTNOW - sim_debug(DEBUG_IRQ, &cpu_dev, - "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 */ } @@ -1956,8 +1968,6 @@ wait_loop: #ifndef TRY_UTX_DELAY if (waitqcnt > 0) waitqcnt--; /* wait b4 ints */ - if (wait4int) /* if waiting let the ints in */ - waitqcnt = 0; /* let in the ints */ #endif /* we are booting the system, so see if boot channel prog is completed */ @@ -1968,22 +1978,24 @@ wait_loop: /* take interrupt, store the PSD, fetch new PSD */ PSD1 = TPSD[0]; /* PSD1 from location 0 */ PSD2 = TPSD[1]; /* PSD2 from location 4 */ - modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + 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 */ + CPUSTATUS |= MODES; /* now insert into CPUSTATUS */ sim_debug(DEBUG_IRQ, &cpu_dev, "Boot Loading PSD1 %.8x PSD2 %.8x\n", PSD1, PSD2); + /* set interrupt blocking state in CPUSTATUS */ - CPUSTATUS |= 0x80; /* set blocked state in cpu status, bit 24 too */ + CPUSTATUS |= BIT24; /* set blocked state in cpu status, bit 24 too */ + MODES |= BLKMODE; /* set blocked in mode to */ PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + PSD2 &= ~RETBBIT; /* turn off retain block mode bit in PSD2 */ + SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ loading = 0; /* we are done loading */ sim_debug(DEBUG_IRQ, &cpu_dev, "Load Skipinstr %1x set loading PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", skipinstr, PSD1, PSD2, CPUSTATUS); -#ifdef NO_SKIP_HERE - skipinstr = 1; /* skip next interrupt test only once */ -#endif goto skipi; /* skip int test */ } /* process any channel programs that are queued */ @@ -1991,34 +2003,36 @@ wait_loop: uint32 chsa; /* channel/sub adddress */ int32 stat; /* return status 0/1 from loadccw */ -#ifdef USE_RDYQ - if (waitrdyq > 0) { - waitrdyq--; - } else -#endif /* we have entries, continue channel program */ if (RDYQ_Get(&chsa) == SCPE_OK) { /* get chsa for program */ sim_debug(DEBUG_XIO, &cpu_dev, - "CPU RDYQ entry for chsa %04x starting irq_pend %01x irq_auto %01x\n", + "CPU RDYQ entry loading for chsa %04x starting irq_pend %01x irq_auto %01x\n", chsa, irq_pend, irq_auto); stat = cont_chan(chsa); /* resume the channel program */ - if (stat) - sim_debug(DEBUG_XIO, &cpu_dev, - "CPU RDYQ entry for chsa %04x processed\n", chsa); if (stat == SCPE_OK) /* done, status stored */ sim_debug(DEBUG_XIO, &cpu_dev, - "CPU RDYQ entry for chsa %04x processed\n", chsa); - } + "CPU RDYQ entry loading for chsa %04x processed\n", chsa); } +#ifdef XXXXX goto wait_loop; /* continue waiting for boot */ +#endif + } +#ifdef XXXXX + /* see if in wait instruction */ + if (wait4int) { /* keep waiting */ + /* tell simh we will be waiting */ +//0905 sim_idle(TMR_RTC, 1); /* wait for clock tick */ + sim_idle(TMR_RTC, 1); /* wait for clock tick */ + } +#endif + goto wait_loop; /* continue waiting */ } /* we get here when not booting */ /* process any pending interrupts */ -// if (!loading && (irq_auto==0) && (wait4int || irq_pend)) { /* see if ints are pending */ -// if (!loading && (irq_auto==0) && (irq_pend)) { /* see if ints are pending */ - if (irq_pend || wait4int) { /* see if ints are pending */ + if ((irq_pend || wait4int) && (irq_auto == 0)) { /* see if ints are pending */ uint32 ilev; + uint32 oldstatus = CPUSTATUS; /* keep for retain blocking state */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ int_icb = scan_chan(&ilev); /* no, go scan for I/O int pending */ @@ -2034,23 +2048,27 @@ wait_loop: 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] & ~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 */ + MODES = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + CPUSTATUS &= ~0x87000080; /* reset bits in CPUSTATUS */ + CPUSTATUS |= MODES; /* now insert into CPUSTATUS */ if (PSD2 & MAPBIT) { - CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ - modes |= MAPMODE; /* set mapped mode */ - } else - CPUSTATUS &= 0xff7fffff; /* reset bit 8 of cpu status */ + CPUSTATUS |= BIT8; /* set bit 8 of cpu status to mapped */ + MODES |= MAPMODE; /* set mapped mode */ + } else { + CPUSTATUS &= ~BIT8; /* reset bit 8 of cpu status */ + MODES &= ~MAPMODE; /* reset set mapped mode */ + } - 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*/ + if ((PSD2 & RETBBIT) == 0) { /* is it retain blocking state, bit 48 set */ + /* retain blocking state is off, use bit 49 to set new blocking state */ + if (PSD2 & SETBBIT) { /* 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 */ + CPUSTATUS |= BIT24; /* yes, set blk state in cpu status bit 24 */ + MODES |= BLKMODE; /* set blocked mode */ /* This test fixed the hangs on terminal input for diags & UTX! */ t = SPAD[il+0x80]; /* get spad entry for interrupt */ @@ -2061,6 +2079,11 @@ wait_loop: ((t & 0x0f00ffff) == 0x03007f04)) { /* Interval timer */ /* if this is F class I/O interrupt, clear the active level */ /* SPAD entries for interrupts begin at 0x80 */ + if ((irq_auto) != 0) { + sim_debug(DEBUG_IRQ, &cpu_dev, + "<|>Auto-reset irq_auto NOT zero %x INTS[%02x] %08x SPAD[%02x] %08x\n", + irq_auto, il, INTS[il], il+0x80, SPAD[il+0x80]); + } irq_auto = il; /* show processing in blocked mode */ #ifdef LEAVE_AUTO_INT_ACT_051020 INTS[il] &= ~INTS_ACT; /* deactivate specified int level */ @@ -2074,13 +2097,25 @@ wait_loop: 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 */ + CPUSTATUS &= ~BIT24; /* no, reset blk state in cpu status bit 24 */ + MODES &= ~BLKMODE; /* reset blocked mode */ + } +#ifndef DO_DYNAMIC_DEBUG + /* start debugging */ + cpu_dev.dctrl |= DEBUG_INST; +#endif + } else { + /* handle retain blocking state */ + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + /* set new blocking state in PSD2 */ + PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ + MODES &= ~(BLKMODE|RETMODE);/* reset blocked & retain mode bits */ + if (oldstatus & BIT24) { /* see if old mode is blocked */ + PSD2 |= SETBBIT; /* set to blocked state */ + MODES |= BLKMODE; /* set blocked mode */ } } - PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ - if (CPUSTATUS & 0x80) /* see if old mode is blocked */ - PSD2 |= 0x00004000; /* set to blocked state */ - 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_IRQ, &cpu_dev, @@ -2096,46 +2131,67 @@ wait_loop: il, int_icb, RMW(int_icb+16), RMW(int_icb+20), RMW(bc), RMW(bc+4)); wait4int = 0; /* wait is over for int */ /*917*/ drop_nop = 0; /* no nop skipping */ -#ifdef NOTNOW - sim_debug(DEBUG_IRQ, &cpu_dev, - "<|> Skipinstr %1x set intr %02x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - skipinstr, il, PSD1, PSD2, CPUSTATUS); -#endif -#ifdef NO_SKIP_HERE - skipinstr = 1; /* skip next inter test after this instr */ -#endif goto skipi; /* skip int test */ } } -#ifdef TEST_082520 -/*25*/ irq_pend = 0; /* not pending anymore */ +#ifndef NEEDS_FIXING if (RDYQ_Num()) { uint32 chsa; /* channel/sub adddress */ -#ifdef USE_RDYQ - if (waitrdyq > 0) { - waitrdyq--; - irq_pend = 1; /* still pending */ - } else -#endif - /* we have entries, continue channel program */ - if (RDYQ_Get(&chsa) == SCPE_OK) { /* get chsa for program */ - int32 stat; -//25 irq_pend = 0; /* not pending anymore */ - sim_debug(DEBUG_XIO, &cpu_dev, - "scan_chan CPU RDYQ entry for chsa %04x starting\n", chsa); - stat = cont_chan(chsa); /* resume the channel program */ - if (stat) + CHANP *chp; /* get channel prog pointer */ + chsa = RDYQ[RDYQOUT]; /* get the next entry */ + chp = find_chanp_ptr(chsa); /* get channel prog pointer */ + if (chp->chan_byte == BUFF_NEXT) { + /* we have entries, continue channel program */ + if (RDYQ_Get(&chsa) == SCPE_OK) { /* get chsa for program */ + int32 stat; + CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ sim_debug(DEBUG_XIO, &cpu_dev, - "CPU RDYQ entry for chsa %04x processed\n", chsa); + "scan_chan CPU RDYQ entry for chsa %04x starting byte %02x\n", + chsa, chp->chan_byte); + stat = cont_chan(chsa); /* resume the channel program */ + if (stat == SCPE_OK) + sim_debug(DEBUG_XIO, &cpu_dev, + "scan_chan CPU RDYQ entry for chsa %04x processed byte %04x\n", + chsa, chp->chan_byte); + else + sim_debug(DEBUG_XIO, &cpu_dev, + "scan_chan CPU RDYQ entry for chsa %04x processed w/error byte %04x\n", + chsa, chp->chan_byte); + } +// goto wait_loop; /*1119*/ /* continue waiting */ } } +#else + if (RDYQ_Num()) { + uint32 chsa; /* channel/sub adddress */ + int32 stat; + + /* we have entries, continue channel program */ + if (RDYQ_Get(&chsa) == SCPE_OK) { /* get chsa for program */ + CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ + sim_debug(DEBUG_XIO, &cpu_dev, + "scan_chan CPU RDYQ entry for chsa %04x starting byte %02x\n", + chsa, chp->chan_byte); + stat = cont_chan(chsa); /* resume the channel program */ + if (stat == SCPE_OK) + sim_debug(DEBUG_XIO, &cpu_dev, + "scan_chan CPU RDYQ entry for chsa %04x processed byte %04x\n", + chsa, chp->chan_byte); + else + sim_debug(DEBUG_XIO, &cpu_dev, + "scan_chan CPU RDYQ entry for chsa %04x processed w/error byte %04x\n", + chsa, chp->chan_byte); + } +// goto wait_loop; /*1119*/ /* continue waiting */ + } #endif + /* see if in wait instruction */ if (wait4int) { /* keep waiting */ /* tell simh we will be waiting */ //0905 sim_idle(TMR_RTC, 1); /* wait for clock tick */ - sim_idle(TMR_RTC, 0); /* wait for clock tick */ -/*722*/ irq_pend = 1; /* start scanning interrupts again */ + sim_idle(TMR_RTC, 1); /* wait for clock tick */ + irq_pend = 1; /* start scanning interrupts again */ goto wait_loop; /* continue waiting */ } @@ -2145,14 +2201,6 @@ wait_loop: TRAPME = attention_trap; /* get trap number */ attention_trap = 0; /* clear flag */ sim_debug(DEBUG_XIO, &cpu_dev, "Attention TRAP %04x\n", TRAPME); -#ifdef NOTNOW - sim_debug(DEBUG_IRQ, &cpu_dev, - "Skipinstr %1x set @ attn int PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - skipinstr, PSD1, PSD2, CPUSTATUS); -#endif -#ifdef NO_SKIP_HERE - skipinstr = 1; /* skip next interrupt test only once */ -#endif goto newpsd; /* got process trap */ } @@ -2160,6 +2208,12 @@ skipi: i_flags = 0; /* do not update pc if MF or NPM */ TRAPSTATUS = CPUSTATUS & 0x57; /* clear all trap status except cpu type */ + /* check for breakpoint request */ + if (sim_brk_summ && sim_brk_test(PC, SWMASK('E'))) { + reason = STOP_IBKPT; + break; + } + /* fill IR from logical memory address */ if ((TRAPME = read_instruction(PSD, &IR))) { sim_debug(DEBUG_TRAP, &cpu_dev, @@ -2169,7 +2223,7 @@ skipi: (CPU_MODEL == MODEL_87) || (CPU_MODEL == MODEL_97)) { if ((TRAPME == MAPFLT) || (TRAPME == NPMEM)) { i_flags |= HLF; /* assume half word instr */ -/*DIAG*/ PSD1 &= ~1; /* force off last right */ +/*DIAG*/ PSD1 &= ~BIT31; /* force off last right */ // fix for 32/67 test 32/3 in MMM diag if ((CPU_MODEL == MODEL_27) || (CPU_MODEL == MODEL_67)) i_flags |= BT; /* do not update pc if MF or NPM */ @@ -2181,7 +2235,7 @@ skipi: i_flags |= HLF; /* assume half word instr */ drop_nop = 0; i_flags &= ~BT; /* no branch taken */ -/*DIAG*/ PSD1 &= ~1; /* force off last right */ +/*DIAG*/ PSD1 &= ~BIT31; /* force off last right */ } } sim_debug(DEBUG_TRAP, &cpu_dev, @@ -2250,11 +2304,13 @@ exec: sim_debug(DEBUG_DETAIL, &cpu_dev, "-----Instr @ PC %08x PSD1 %08x PSD2 %08x IR %08x\n", PC, PSD1, PSD2, IR); +#ifdef OLDPLACE /* check for breakpoint request */ if (sim_brk_summ && sim_brk_test(PC, SWMASK('E'))) { reason = STOP_IBKPT; break; } +#endif /* Update history for this instruction */ if (hst_lnt) { @@ -2275,14 +2331,13 @@ exec: ovr = 0; /* no overflow or arithmetic exception either */ dest = (t_uint64)IR; /* assume memory address specified */ CC = PSD1 & 0x78000000; /* save CC's if any */ - /* changed for diags 052719*/ - modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + MODES = PSD1 & 0x87000000; /* insert bits 0, 5, 6, 7 from PSD 1 */ CPUSTATUS &= ~0x87000000; /* reset those bits in CPUSTATUS */ - CPUSTATUS |= modes; /* now insert them into CPUSTATUS */ + CPUSTATUS |= MODES; /* now insert them into CPUSTATUS */ if (PSD2 & MAPBIT) - modes |= MAPMODE; /* set mapped mode */ + MODES |= MAPMODE; /* set mapped mode */ - if (modes & BASEBIT) { + if (MODES & BASEBIT) { i_flags = base_mode[OP>>2]; /* set the instruction processing flags */ addr = IR & RMASK; /* get address offset from instruction */ sim_debug(DEBUG_DETAIL, &cpu_dev, @@ -2334,7 +2389,7 @@ exec: (CPU_MODEL == MODEL_87) || (CPU_MODEL == MODEL_97)) { // DIAG fix for 32/87 test 33/2, clear psd bit 31 if ((CPU_MODEL == MODEL_87)) -/*DIAG*/ PSD1 &= ~1; /* force off last right */ +/*DIAG*/ PSD1 &= ~BIT31; /* force off last right */ // DIAG fix 32/27 32/67 for diag MMM test 33/2 if ((CPU_MODEL <= MODEL_27) || (CPU_MODEL == MODEL_67)) i_flags |= BT; /* do not update pc if MAPFAULT on 27 */ @@ -2450,7 +2505,7 @@ exec: "case RM Mem_read status %02x @ %08x\n", TRAPME, addr); // DIAG add 97 for correct PSD address CN.MMM test 32, subtest 1 fails if ((TRAPME == MAPFLT) || (TRAPME == NPMEM) || (TRAPME == MPVIOL)) -/*DIAG*/ PSD1 &= ~1; /* force off last right */ +/*DIAG*/ PSD1 &= ~BIT31; /* force off last right */ goto newpsd; /* memory read error or map fault */ } source = (t_uint64)temp; /* make into 64 bit value */ @@ -2462,10 +2517,10 @@ exec: source >>= 16; /* move left hw to right hw*/ /* Fall through */ case 3: /* right hw or right shifted left hw */ - source &= 0xffff; /* use just the right hw */ + source &= RMASK; /* use just the right hw */ if (source & 0x8000) { /* check sign of 16 bit value */ /* sign extend the value to leftmost 48 bits */ - source = 0xFFFF0000 | (source & 0xFFFF); /* extend low 32 bits */ + source = LMASK | (source & RMASK); /* extend low 32 bits */ source |= (D32LMASK); /* extend hi bits */ } break; @@ -2510,7 +2565,7 @@ exec: source >>= 16; /* move left hw to right hw*/ /* Fall through */ case 3: /* right hw or right shifted left hw */ - source &= 0xffff; /* use just the right hw */ + source &= RMASK; /* use just the right hw */ break; case 2: /* double word address */ if ((addr & 7) != 2) { /* must be double word adddress */ @@ -2595,7 +2650,7 @@ exec: case 0x00>>2: /* HLF - HLF */ /* CPU General operations */ switch(opr & 0xF) { /* switch on aug code */ case 0x0: /* HALT */ - if ((modes & PRIVBIT) == 0) { /* must be privileged to halt */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged to halt */ TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ @@ -2603,7 +2658,7 @@ exec: TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ goto newpsd; /* Privlege violation trap */ } - if (CPUSTATUS & 0x00000100) { /* Priv mode halt must be enabled */ + if (CPUSTATUS & BIT23) { /* Priv mode halt must be enabled */ TRAPME = PRIVHALT_TRAP; /* set the trap to take */ goto newpsd; /* Privlege mode halt trap */ } @@ -2623,7 +2678,7 @@ exec: for (ix=0; ix<8; ix+=2) { fprintf(stdout, "GPR[%d] %.8x GPR[%d] %.8x\r\n", ix, GPR[ix], ix+1, GPR[ix+1]); } - if (modes & BASEBIT) { /* see if based */ + if (MODES & BASEBIT) { /* see if based */ for (ix=0; ix<8; ix+=2) { fprintf(stdout, "BR[%d] %.8x BR[%d] %.8x\r\n", ix, BR[ix], ix+1, BR[ix+1]); } @@ -2633,7 +2688,7 @@ exec: ///*TEST DIAG*/ return STOP_HALT; /* exit to simh for halt */ break; case 0x1: /* WAIT */ - if ((modes & PRIVBIT) == 0) { /* must be privileged to wait */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged to wait */ TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ @@ -2642,7 +2697,7 @@ exec: goto newpsd; /* Privlege violation trap */ } /* if interrupts are blocked, system check trap */ - if (CPUSTATUS & 0x80) { /* status word bit 24 says blocked */ + if (CPUSTATUS & BIT24) { /* status word bit 24 says blocked */ TRAPME = SYSTEMCHK_TRAP; /* trap condition if F class */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT12; /* set bit 0 of trap status */ @@ -2652,7 +2707,8 @@ exec: } if (wait4int == 0) { time_t result = time(NULL); - sim_debug(DEBUG_DETAIL, &cpu_dev, +// sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_IRQ, &cpu_dev, "Starting WAIT mode %08x\n", (uint32)result); } wait4int = 1; /* show we are waiting for interrupt */ @@ -2703,13 +2759,13 @@ exec: /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ goto newpsd; /* handle trap */ } break; case 0x6: /* BEI */ - if ((modes & PRIVBIT) == 0) { /* must be privileged to BEI */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged to BEI */ TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ @@ -2722,14 +2778,17 @@ sim_debug(DEBUG_IRQ, &cpu_dev, "bei int was %01x at PSD1 %08x PSD2 %08x\n", CPUSTATUS&0x80 ? 1 : 0, PSD1, PSD2); #endif - CPUSTATUS |= 0x80; /* into status word bit 24 too */ - PSD2 &= ~0x0000c000; /* clear bit 48 & 49 */ - PSD2 |= 0x00004000; /* set bit 49 only */ + CPUSTATUS |= BIT24; /* into status word bit 24 too */ + PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 */ + MODES &= ~(BLKMODE|RETMODE);/* reset blocked & retain mode bits */ + PSD2 |= SETBBIT; /* set to blocked state */ + MODES |= BLKMODE; /* set blocked mode */ + SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ break; case 0x7: /* UEI */ - if ((modes & PRIVBIT) == 0) { /* must be privileged to UEI */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged to UEI */ TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ @@ -2742,7 +2801,7 @@ sim_debug(DEBUG_IRQ, &cpu_dev, "uei int was %01x at PSD1 %08x PSD2 %08x\n", CPUSTATUS&0x80 ? 1 : 0, PSD1, PSD2); #endif - if (CPUSTATUS & 0x80) { /* see if old mode is blocked */ + if (CPUSTATUS & BIT24) { /* see if old mode is blocked */ irq_pend = 1; /* start scanning interrupts again */ if (irq_auto) { /*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ @@ -2751,26 +2810,28 @@ CPUSTATUS&0x80 ? 1 : 0, PSD1, PSD2); "<|>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 */ +/*103020*/ skipinstr = 1; /* skip interrupt test */ +#ifndef DO_DYNAMIC_DEBUG + /* stop debugging */ + cpu_dev.dctrl &= ~DEBUG_INST; +#endif } } - CPUSTATUS &= ~0x80; /* into status word bit 24 too */ - PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ + CPUSTATUS &= ~BIT24; /* clear status word bit 24 */ + MODES &= ~(BLKMODE|RETMODE);/* reset blocked & retain mode bits */ + PSD2 &= ~(SETBBIT|RETBBIT); /* clear bits 48 & 49 to be unblocked */ SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ break; case 0x8: /* EAE */ PSD1 |= AEXPBIT; /* set the enable AEXP flag in PSD */ CPUSTATUS |= AEXPBIT; /* into status word too */ - modes |= AEXPBIT; /* ensable arithmetic exception in modes & PSD */ + MODES |= AEXPBIT; /* enable arithmetic exception in modes & PSD */ 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]); -#ifdef DO_DYNAMIC_DEBUG - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_TRAP | DEBUG_EXP | DEBUG_IRQ); -#endif break; case 0xA: /* SIPU */ /* ignore for now */ sim_debug(DEBUG_CMD, &cpu_dev, @@ -2804,22 +2865,22 @@ CPUSTATUS&0x80 ? 1 : 0, PSD1, PSD2); /* Maybe TODO copy something to WCS */ break; case 0xD: /* SEA */ - if (modes & BASEBIT) /* see if based */ + if (MODES & BASEBIT) /* see if based */ goto inv; /* invalid instruction in based mode */ - modes |= EXTDBIT; /* set new extended flag (bit 5) in modes & PSD */ - PSD1 |= EXTDBIT; /* set the enable AEXP flag in PSD */ + MODES |= EXTDBIT; /* set new extended flag (bit 5) in modes & PSD */ + PSD1 |= EXTDBIT; /* set the enable AEXP flag in PSD1 */ CPUSTATUS |= EXTDBIT; /* into status word too */ break; case 0xE: /* DAE */ - modes &= ~AEXPBIT; /* disable arithmetic exception in modes & PSD */ + MODES &= ~AEXPBIT; /* disable arithmetic exception in modes & PSD */ PSD1 &= ~AEXPBIT; /* disable AEXP flag in PSD */ CPUSTATUS &= ~AEXPBIT; /* into status word too */ break; case 0xF: /* CEA */ - if (modes & BASEBIT) /* see if based */ + if (MODES & BASEBIT) /* see if based */ goto inv; /* invalid instruction in based mode */ - modes &= ~EXTDBIT; /* disable extended mode in modes and PSD */ + MODES &= ~EXTDBIT; /* disable extended mode in modes and PSD */ PSD1 &= ~EXTDBIT; /* disable extended mode (bit 5) flag in PSD */ CPUSTATUS &= ~EXTDBIT; /* into status word too */ break; @@ -3022,11 +3083,12 @@ CPUSTATUS&0x80 ? 1 : 0, PSD1, PSD2); } else if ((GPR[reg] & BIT0) == 0x00000000) { /* if bit 0 of reg not set, return PSD2 */ - /* make sure bit 49 (block state is current stat */ + /* make sure bit 49 (block state is current state */ dest = SPAD[0xf5]; /* get PSD2 for user from SPAD 0xf5 */ - dest &= ~0x0000c000; /* clear bits 48 & 49 */ - if (modes & BLKMODE) /* set to current mode */ - dest |= 0x00004000; /* set bit 49 for blocked */ + dest &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ + if (CPUSTATUS & BIT24) { /* see if old mode is blocked */ + dest |= SETBBIT; /* set bit 49 for blocked */ + } } break; @@ -3097,7 +3159,7 @@ CPUSTATUS&0x80 ? 1 : 0, PSD1, PSD2); PSD1 &= 0x87FFFFFE; /* clear the old CC's */ PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ } else { - if ((modes & BASEBIT) == 0) { /* if not basemode, error */ + if ((MODES & BASEBIT) == 0) { /* if not basemode, error */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ @@ -3152,7 +3214,7 @@ sacz: /* non basemode SCZ enters here */ break; case 0x18>>2: /* 0x18 HLF - HLF */ /* SBR, (basemode ZBR, ABR, TBR */ - if (modes & BASEBIT) { /* handle basemode ZBR, ABR, TBR */ + if (MODES & BASEBIT) { /* handle basemode ZBR, ABR, TBR */ if ((opr & 0xC) == 0x0) /* SBR instruction */ goto sbr; /* use nonbase SBR code */ if ((opr & 0xC) == 0x4) /* ZBR instruction */ @@ -3189,7 +3251,7 @@ 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 */ + 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 */ @@ -3223,7 +3285,7 @@ sbr: /* handle basemode too */ /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ goto newpsd; /* go execute the trap now */ } @@ -3256,7 +3318,7 @@ zbr: /* handle basemode too */ break; case 0x20>>2: /* 0x20 HLF - HLF */ /* ABR (basemode SRAD, SRLD, SLAD, SLLD) */ - if (modes & BASEBIT) { /* handle basemode SRAD, SRLD, SLAD, SLLD */ + if (MODES & BASEBIT) { /* handle basemode SRAD, SRLD, SLAD, SLLD */ if (reg & 1) { /* see if odd reg specified */ TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ goto newpsd; /* go execute the trap now */ @@ -3294,7 +3356,7 @@ zbr: /* handle basemode too */ /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ goto newpsd; /* go execute the trap now */ } @@ -3335,7 +3397,7 @@ abr: /* basemode ABR too */ /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ goto newpsd; /* handle trap */ } @@ -3343,7 +3405,7 @@ abr: /* basemode ABR too */ break; case 0x24>>2: /* 0x24 HLF - HLF */ /* TBR (basemode SRC) */ - if (modes & BASEBIT) { /* handle SRC basemode */ + if (MODES & BASEBIT) { /* handle SRC basemode */ bc = opr & 0x1f; /* get bit shift count */ temp = GPR[reg]; /* get reg value to shift */ if ((opr & 0x60) == 0x40) { /* SLC instruction */ @@ -3386,7 +3448,7 @@ tbr: /* handle basemode TBR too * switch(opr & 0xF) { case 0x0: /* TRSW */ - if (modes & BASEBIT) + if (MODES & BASEBIT) temp = 0x78FFFFFE; /* bits 1-4 and 24 bit addr for based mode */ else temp = 0x7807FFFE; /* bits 1-4 and 19 bit addr for non based mode */ @@ -3397,12 +3459,12 @@ tbr: /* handle basemode TBR too * PSD1 |= (addr & temp); /* insert the CC's and address */ sim_debug(DEBUG_DETAIL, &cpu_dev, "TRSW REG %01x PSD %08x %08x modes %08x temp %06x\n", - reg, PSD1, PSD2, modes, temp); + reg, PSD1, PSD2, MODES, temp); i_flags |= BT; /* we branched, so no PC update */ break; case 0x2: /* XCBR */ /* Exchange base registers */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ goto inv; /* invalid instruction in nonbased mode */ temp = BR[reg]; /* get dest reg value */ BR[reg] = BR[sreg]; /* put source reg value int dest reg */ @@ -3410,23 +3472,23 @@ tbr: /* handle basemode TBR too * break; case 0x4: /* TCCR */ /* Transfer condition codes to GPR bits 28-31 */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ goto inv; /* invalid instruction in nonbased mode */ temp = CC >> 27; /* right justify CC's in reg */ GPR[reg] = temp; /* put dest reg value into src reg */ break; case 0x5: /* TRCC */ /* Transfer GPR bits 28-31 to condition codes */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ + 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 */ sim_debug(DEBUG_EXP, &cpu_dev, "TRCC REG %01x PSD %08x %08x modes %08x temp %06x\n", - reg, PSD1, PSD2, modes, GPR[reg]); + reg, PSD1, PSD2, MODES, GPR[reg]); break; case 0x8: /* BSUB */ /* Procedure call */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ + 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 */ @@ -3496,13 +3558,13 @@ tbr: /* handle basemode TBR too * break; case 0xC: /* TPCBR */ /* Transfer program Counter to Base Register */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ + 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 */ + 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 */ @@ -3553,13 +3615,13 @@ tbr: /* handle basemode TBR too * break; case 0x1: /* TRBR */ /* Transfer GPR to BR */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ goto inv; /* invalid instruction in nonbased mode */ BR[reg] = GPR[sreg]; /* copy GPR to BR */ break; case 0x2: /* TBRR */ /* transfer BR to GPR */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ goto inv; /* invalid instruction in nonbased mode */ temp = BR[sreg]; /* set base reg value */ bc = 1; /* set CC's at end */ @@ -3591,7 +3653,7 @@ tbr: /* handle basemode TBR too * break; case 0x7: /* LMAP */ /* Load map reg - Diags only */ - if ((modes & PRIVBIT) == 0) { /* must be privileged */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged */ TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ @@ -3600,7 +3662,7 @@ tbr: /* handle basemode TBR too * goto newpsd; /* handle trap */ } /* cpu must be unmapped */ - if (modes & MAPMODE) { /* must be unmapped cpu */ + if (MODES & MAPMODE) { /* must be unmapped cpu */ TRAPME = MAPFAULT_TRAP; /* Map Fault Trap */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT8; /* set bit 8 of trap status */ @@ -3615,23 +3677,23 @@ tbr: /* handle basemode TBR too * DPSD[1] = RMW(temp+4); /* get word two of psd */ sim_debug(DEBUG_CMD, &cpu_dev, "LMAP PSD %08x %08x DPSD %08x %08x modes %08x temp %06x\n", - PSD1, PSD2, DPSD[0], DPSD[1], modes, temp); + PSD1, PSD2, DPSD[0], DPSD[1], MODES, temp); if ((DPSD[1] & MAPBIT) == 0) /* if PSD2 is unmapped, treat as NOP */ goto skipit; if (PSD2 & RETMBIT) /* don't load maps if retain bit set */ goto skipit; - temp2 = modes; /* save modes bits through load_maps call */ - modes = DPSD[0] & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ - modes |= MAPMODE; /* set mapped mode flag for load_maps call */ + temp2 = MODES; /* save modes bits through load_maps call */ + MODES = DPSD[0] & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + MODES |= MAPMODE; /* set mapped mode flag for load_maps call */ sim_debug(DEBUG_CMD, &cpu_dev, "LMAP PSD %08x %08x DPSD %08x %08x modes %08x temp2 %08x\n", - PSD1, PSD2, DPSD[0], DPSD[1], modes, temp2); + PSD1, PSD2, DPSD[0], DPSD[1], MODES, temp2); /* we need to load the new maps */ TRAPME = load_maps(DPSD, 1); /* load maps for new PSD */ sim_debug(DEBUG_CMD, &cpu_dev, "LMAP TRAPME %08x MAPC[8-c] %08x %08x %08x %08x %08x %08x\n", TRAPME, MAPC[7], MAPC[8], MAPC[9], MAPC[10], MAPC[11], MAPC[12]); - modes = temp2; /* restore modes flags */ + MODES = temp2; /* restore modes flags */ if (TRAPME) { /* DIAGS wants the cpix for the psd to be the requested one */ PSD2 = (PSD2 & 0xffffc000) | (DPSD[1] & 0x3ff8); @@ -3662,7 +3724,7 @@ tbr: /* handle basemode TBR too * /* =1 Enable software trap handling */ /* Bits 26-31 reserved */ case 0x9: /* SETCPU */ - if ((modes & PRIVBIT) == 0) { /* must be privileged */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged */ TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ @@ -3671,20 +3733,20 @@ tbr: /* handle basemode TBR too * goto newpsd; /* handle trap */ } temp2 = CPUSTATUS; /* save original */ -// sim_debug(DEBUG_EXP, &cpu_dev, - sim_debug(DEBUG_CMD, &cpu_dev, - "SETCPU orig %08x user bits %08x New CPUSTATUS %08x\n", - temp2, temp, CPUSTATUS); /* bits 20-23 and bit 25 can change */ CPUSTATUS &= 0xfffff0bf; /* zero bits that can change */ CPUSTATUS |= (temp & 0x0f40); /* or in the new status bits */ CPUSTATUS |= BIT22; /* HS Floating is set to off */ /* make sure WCS is off and prom mode set to 0 (on) */ CPUSTATUS &= ~(BIT20|BIT21); /* make zero */ +// sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_CMD, &cpu_dev, + "SETCPU orig %08x user bits %08x New CPUSTATUS %08x\n", + temp2, temp, CPUSTATUS); break; case 0xA: /* TMAPR */ /* Transfer map to Reg - Diags only */ - if ((modes & PRIVBIT) == 0) { /* must be privileged */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged */ TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ @@ -3693,7 +3755,7 @@ tbr: /* handle basemode TBR too * goto newpsd; /* handle trap */ } if (CPU_MODEL <= MODEL_27) { /* 7X & 27 must be unmapped */ - if (modes & MAPMODE) { /* must be unmapped cpu */ + if (MODES & MAPMODE) { /* must be unmapped cpu */ TRAPME = MAPFAULT_TRAP; /* Map Fault Trap */ goto newpsd; /* handle trap */ } @@ -3752,7 +3814,7 @@ tbr: /* handle basemode TBR too * break; case 0xE: /* TRSC */ /* transfer reg to SPAD */ - if ((modes & PRIVBIT) == 0) { /* must be privileged */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged */ TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ @@ -3768,7 +3830,7 @@ tbr: /* handle basemode TBR too * break; case 0xF: /* TSCR */ /* Transfer scratchpad to register */ - if ((modes & PRIVBIT) == 0) { /* must be privileged */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged */ TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ @@ -3788,16 +3850,18 @@ tbr: /* handle basemode TBR too * /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ goto newpsd; /* handle trap */ } skipit: + /* for retain, leave PSD2 alone */ break; case 0x30>>2: /* 0x30 */ /* CALM */ /* Process CALM for 32/27 when in left hw, else invalid */ if ((CPU_MODEL <= MODEL_87) && (CPU_MODEL != MODEL_67)) { + uint32 oldstatus = CPUSTATUS; /* keep for retain blocking state */ /* DIAG error for 32/27 or 32/87 only */ if ((PSD1 & 2) != 0) /* is it lf hw instruction */ goto inv; /* invalid instr if in rt hw */ @@ -3820,23 +3884,28 @@ skipit: PSD1 = M[(t>>2)+2]; /* get new PSD 1 */ 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 */ - modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + 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 map mode and interrupt blocking state in CPUSTATUS */ if (PSD2 & MAPBIT) { - CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ - modes |= MAPMODE; /* set mapped mode */ + CPUSTATUS |= BIT8; /* set bit 8 of cpu status */ + MODES |= MAPMODE; /* set mapped mode */ } else - CPUSTATUS &= 0xff7fffff; /* reset bit 8 of cpu status */ + CPUSTATUS &= ~BIT8; /* reset bit 8 of cpu status */ + /* set interrupt blocking state */ - if ((PSD2 & 0x8000) == 0) { /* is it retain blocking state */ - if (PSD2 & 0x4000) /* no, is it set blocking state */ - CPUSTATUS |= 0x80; /* yes, set blk state in cpu status bit 24 */ - else { - CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ + if ((PSD2 & RETBBIT) == 0) { /* is it retain blocking state */ + if (PSD2 & SETBBIT) { /* no, is it set blocking state */ + CPUSTATUS |= BIT24; /* yes, set blk state in cpu status bit 24 */ + MODES |= BLKMODE; /* set blocked mode */ + } else { + CPUSTATUS &= ~BIT24; /* no, reset blk state in cpu status bit 24 */ + MODES &= ~BLKMODE; /* reset blocked mode */ irq_pend = 1; /* start scanning interrupts again */ if (irq_auto) { /*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ @@ -3845,17 +3914,25 @@ skipit: "<|>IntX deactivate level %02x at CALM PSD1 %08x\n", irq_auto, PSD1); /*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ -#ifdef NO_SKIP_HERE -/*051920*/ skipinstr = 1; /* skip interrupt test */ +/*103020*/ skipinstr = 1; /* skip interrupt test */ +#ifndef DO_DYNAMIC_DEBUG + /* stop debugging */ + cpu_dev.dctrl &= ~DEBUG_INST; #endif } } + } else { + /* handle retain blocking state */ + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + /* set new blocking state in PSD2 */ + PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ + MODES &= ~(BLKMODE|RETMODE);/* reset blocked & retain mode bits */ + if (oldstatus & BIT24) { /* see if old mode is blocked */ + PSD2 |= SETBBIT; /* set to blocked state */ + MODES |= BLKMODE; /* set blocked mode */ + } } - PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ - if (CPUSTATUS & 0x80) /* see if old mode is blocked */ - PSD2 |= 0x00004000; /* set to blocked state */ - PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ TRAPME = 0; /* not to be processed as trap */ @@ -3867,9 +3944,9 @@ skipit: break; case 0x34>>2: /* 0x34 SD|ADR - inv */ /* LA non-basemode */ - if (modes & BASEBIT) /* see if based */ + if (MODES & BASEBIT) /* see if based */ goto inv; /* invalid instruction in based mode */ - if (modes & EXTDBIT) { /* see if extended mode */ + if (MODES & EXTDBIT) { /* see if extended mode */ dest = (t_uint64)(addr&MASK24); /* just pure 24 bit address */ } else { /* use bits 13-31 */ dest = (t_uint64)((addr&0x7ffff) | ((FC & 4) << 17)); /* F bit to bit 12 */ @@ -3912,7 +3989,7 @@ skipit: if (CC & CC1BIT) { /* check for arithmetic exception */ ovr = 1; /* exception */ /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (modes & AEXPBIT) { + if (MODES & AEXPBIT) { TRAPME = AEXPCEPT_TRAP; /* trap the system now */ goto newpsd; /* process the trap */ } @@ -3924,7 +4001,7 @@ skipit: case 0x2: /* MPRBR */ /* TODO not on 32/27 */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ goto inv; /* invalid instruction in nonbased mode */ if (reg & 1) { /* Spec fault if not even reg */ @@ -3956,7 +4033,7 @@ skipit: if (CC & CC1BIT) { /* check for arithmetic exception */ ovr = 1; /* exception */ /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (modes & AEXPBIT) { + if (MODES & AEXPBIT) { TRAPME = AEXPCEPT_TRAP; /* trap the system now */ goto newpsd; /* process the trap */ } @@ -3979,7 +4056,7 @@ skipit: if (CC & CC1BIT) { /* check for arithmetic exception */ ovr = 1; /* exception */ /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (modes & AEXPBIT) { + if (MODES & AEXPBIT) { TRAPME = AEXPCEPT_TRAP; /* trap the system now */ goto newpsd; /* process the trap */ } @@ -4003,7 +4080,7 @@ skipit: if (CC & CC1BIT) { /* check for arithmetic exception */ ovr = 1; /* exception */ /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (modes & AEXPBIT) { + if (MODES & AEXPBIT) { TRAPME = AEXPCEPT_TRAP; /* trap the system now */ goto newpsd; /* process the trap */ } @@ -4064,7 +4141,7 @@ skipit: if (CC & CC1BIT) { /* check for arithmetic exception */ ovr = 1; /* exception */ /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (modes & AEXPBIT) { + if (MODES & AEXPBIT) { TRAPME = AEXPCEPT_TRAP; /* trap the system now */ goto newpsd; /* process the trap */ } @@ -4077,7 +4154,7 @@ skipit: case 0xA: /* DVRBR */ /* TODO not on 32/27 */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ goto inv; /* invalid instruction in nonbased mode */ if (reg & 1) { /* Spec fault if not even reg */ @@ -4103,7 +4180,7 @@ doovr4: /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ } /* the original regs must be returned unchanged if aexp */ @@ -4134,7 +4211,7 @@ doovr4: if (CC & CC1BIT) { /* check for arithmetic exception */ ovr = 1; /* exception */ /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (modes & AEXPBIT) { + if (MODES & AEXPBIT) { TRAPME = AEXPCEPT_TRAP; /* trap the system now */ goto newpsd; /* process the trap */ } @@ -4164,7 +4241,7 @@ doovr4: if (CC & CC1BIT) { /* check for arithmetic exception */ ovr = 1; /* exception */ /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (modes & AEXPBIT) { + if (MODES & AEXPBIT) { TRAPME = AEXPCEPT_TRAP; /* trap the system now */ goto newpsd; /* process the trap */ } @@ -4194,7 +4271,7 @@ doovr4: if (CC & CC1BIT) { /* check for arithmetic exception */ ovr = 1; /* exception */ /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (modes & AEXPBIT) { + if (MODES & AEXPBIT) { TRAPME = AEXPCEPT_TRAP; /* trap the system now */ goto newpsd; /* process the trap */ } @@ -4230,7 +4307,7 @@ doovr4: /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ goto newpsd; /* go execute the trap now */ } @@ -4280,14 +4357,14 @@ doovr4: /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ goto newpsd; /* go execute the trap now */ } break; case 0x40>>2: /* 0x40 SCC|SD|HLF - INV */ /* MPR */ - if (modes & BASEBIT) + if (MODES & BASEBIT) goto inv; /* invalid instruction in basemode */ if (reg & 1) { /* odd reg specified? */ /* Spec fault */ @@ -4361,7 +4438,7 @@ doovr3: /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ } /* the original regs must be returned unchanged if aexp */ @@ -4392,13 +4469,13 @@ doovr3: break; case 0x50>>2: /* 0x50 INV - SD|ADR */ /* LA basemode LABRM */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ goto inv; /* invalid instruction in nonbased mode */ dest = (t_uint64)(addr&MASK24); /* just pure 24 bit address */ break; case 0x54>>2: /* 0x54 SM|ADR - INV */ /* (basemode STWBR) */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ goto inv; /* invalid instruction in nonbased mode */ if (FC != 0) { /* word address only */ TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ @@ -4410,7 +4487,7 @@ doovr3: break; case 0x58>>2: /* 0x58 SB|ADR - INV */ /* (basemode SUABR and LABR) */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ goto inv; /* invalid instruction in nonbased mode */ if ((FC & 4) == 0) { /* see if SUABR F=0 0x5800 */ dest = BR[reg] - addr; /* subtract addr from the BR and store back to BR */ @@ -4419,7 +4496,7 @@ doovr3: } break; case 0x5C>>2: /* 0x5C RM|ADR - INV */ /* (basemode LWBR and BSUBM) */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ goto inv; /* invalid instruction in nonbased mode */ if ((FC & 3) != 0) { /* word address only */ TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ @@ -4528,7 +4605,7 @@ doovr3: break; case 0x60>>2: /* 0x60 HLF - INV */ /* NOR Rd,Rs */ - if ((modes & BASEBIT)) { /* only for nonbased mode */ + if ((MODES & BASEBIT)) { /* only for nonbased mode */ TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ @@ -4550,7 +4627,7 @@ doovr3: break; case 0x64>>2: /* 0x64 SD|HLF - INV */ /* NORD */ - if ((modes & BASEBIT)) { /* only for nonbased mode */ + if ((MODES & BASEBIT)) { /* only for nonbased mode */ TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ @@ -4579,7 +4656,7 @@ doovr3: break; case 0x68>>2: /* 0x68 HLF - INV */ /* non basemode SCZ */ - if (modes & BASEBIT) + if (MODES & BASEBIT) goto inv; /* invalid instruction */ if (opr & 0xf) { /* any subop not zero is error */ TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ @@ -4590,7 +4667,7 @@ doovr3: goto sacz; /* use basemode sacz instruction */ case 0x6C>>2: /* 0x6C HLF - INV */ /* non basemode SRA & SLA */ - if (modes & BASEBIT) + if (MODES & BASEBIT) goto inv; /* invalid instruction */ bc = opr & 0x1f; /* get bit shift count */ temp = GPR[reg]; /* get reg value to shift */ @@ -4611,7 +4688,7 @@ doovr3: /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ goto newpsd; /* go execute the trap now */ } @@ -4625,7 +4702,7 @@ doovr3: break; case 0x70>>2: /* 0x70 SD|HLF - INV */ /* non-basemode SRL & SLL */ - if (modes & BASEBIT) + if (MODES & BASEBIT) goto inv; /* invalid instruction in basemode */ bc = opr & 0x1f; /* get bit shift count */ if (opr & 0x0040) /* is this SLL, bit 9 set */ @@ -4635,7 +4712,7 @@ doovr3: break; case 0x74>>2: /* 0x74 SD|HLF - INV */ /* non-basemode SRC & SLC */ - if (modes & BASEBIT) + if (MODES & BASEBIT) goto inv; /* invalid instruction in basemode */ bc = opr & 0x1f; /* get bit shift count */ temp = GPR[reg]; /* get reg value to shift */ @@ -4658,7 +4735,7 @@ doovr3: break; case 0x78>>2: /* 0x78 HLF - INV */ /* non-basemode SRAD & SLAD */ - if (modes & BASEBIT) /* Base mode? */ + if (MODES & BASEBIT) /* Base mode? */ goto inv; /* invalid instruction in basemode */ if (reg & 1) { /* see if odd reg specified */ TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ @@ -4685,7 +4762,7 @@ doovr3: /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ goto newpsd; /* go execute the trap now */ } @@ -4700,7 +4777,7 @@ doovr3: break; case 0x7C>>2: /* 0x7C HLF - INV */ /* non-basemode SRLD & SLLD */ - if (modes & BASEBIT) + if (MODES & BASEBIT) goto inv; /* invalid instruction in basemode */ if (reg & 1) { /* see if odd reg specified */ TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ @@ -4727,7 +4804,7 @@ doovr3: goto newpsd; /* memory read error or map fault */ } /* set access bit for mapped addresses */ - if ((CPU_MODEL >= MODEL_V6) && (modes & MAPMODE)) { + if ((CPU_MODEL >= MODEL_V6) && (MODES & MAPMODE)) { uint32 map, mix, nix, msdl, mpl, mmap; nix = (addr >> 13) & 0x7ff; /* get 11 bit map value */ @@ -4737,7 +4814,7 @@ doovr3: /* O/S or user has no read/execute access, do protection violation */ sim_debug(DEBUG_TRAP, &cpu_dev, "LEAR readI protect error @ %06x prot %02x modes %08x page %04x\n", - addr, t, modes, nix); + addr, t, MODES, nix); if (CPU_MODEL == MODEL_V9) TRAPSTATUS |= BIT1; /* set bit 1 of trap status */ else @@ -4747,7 +4824,7 @@ doovr3: /* O/S or user has read/execute access, no protection violation */ sim_debug(DEBUG_DETAIL, &cpu_dev, "LEAR readJ protect is ok @ %06x prot %02x modes %08x page %04x\n", - addr, t, modes, nix); + addr, t, MODES, nix); } /* we have read access, so go set the access bit in the map entry */ mpl = SPAD[0xf3]; /* get mpl from spad address */ @@ -5024,7 +5101,7 @@ meoa: /* merge point for eor, and, or */ /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ goto newpsd; /* handle trap */ } @@ -5085,7 +5162,7 @@ meoa: /* merge point for eor, and, or */ hst[hst_p].opsd1 = OPSD1; /* update the CC in opsd1 */ hst[hst_p].npsd1 = PSD1; /* save new psd1 */ hst[hst_p].npsd2 = PSD2; /* save new psd2 */ - hst[hst_p].modes = modes; /* save current mode bits */ + hst[hst_p].modes = MODES; /* save current mode bits */ for (ix=0; ix<8; ix++) { hst[hst_p].reg[ix] = GPR[ix]; /* save reg */ hst[hst_p].reg[ix+8] = BR[ix]; /* save breg */ @@ -5096,13 +5173,13 @@ meoa: /* merge point for eor, and, or */ OPSD1 &= 0x87FFFFFE; /* clear the old CC's */ OPSD1 |= PSD1 & 0x78000000; /* update the CC's in the PSD */ /* output mapped/unmapped */ - if (modes & BASEBIT) { - if (modes & MAPMODE) + if (MODES & BASEBIT) { + if (MODES & MAPMODE) sim_debug(DEBUG_INST, &cpu_dev, "BM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); else sim_debug(DEBUG_INST, &cpu_dev, "BU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); } else { - if (modes & MAPMODE) + if (MODES & MAPMODE) sim_debug(DEBUG_INST, &cpu_dev, "NM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); else sim_debug(DEBUG_INST, &cpu_dev, "NU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); @@ -5119,7 +5196,7 @@ meoa: /* merge point for eor, and, or */ "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 */ +/*DIAG*/ //1106 skipinstr = 0; /* only test this once */ goto exec; /* go execute the instruction */ break; @@ -5152,7 +5229,7 @@ meoa: /* merge point for eor, and, or */ /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (dest != 0 && ovr && (modes & AEXPBIT)) { + if (dest != 0 && ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ } break; @@ -5219,7 +5296,7 @@ meoa: /* merge point for eor, and, or */ /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ } break; @@ -5283,7 +5360,7 @@ doovr: /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (modes & AEXPBIT) + if (MODES & AEXPBIT) TRAPME = AEXPCEPT_TRAP; /* set the trap type */ } else { GPR[reg] = (uint32)(td & FMASK); /* reg gets remainder, reg+1 quotient */ @@ -5321,7 +5398,7 @@ doovr: /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ goto newpsd; /* go execute the trap now */ } @@ -5371,7 +5448,7 @@ doovr2: /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (modes & AEXPBIT) + if (MODES & AEXPBIT) TRAPME = AEXPCEPT_TRAP; /* set the trap type */ /* the original regs must be returned unchanged if aexp */ /* put reg values back in dest for CC test */ @@ -5406,6 +5483,7 @@ doovr2: /* |-------+-------+-------+-------+-------+-------+-------+-------| */ /* */ case 0x6: /* SVC none - none */ /* Supervisor Call Trap */ + int32c = CPUSTATUS; /* keep for retain blocking state */ addr = SPAD[0xf0]; /* get trap table memory address from SPAD (def 80) */ if (addr == 0 || addr == 0xffffffff) { /* see if secondary vector table set up */ TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ @@ -5429,34 +5507,32 @@ doovr2: PSD1 = M[(t>>2)+2]; /* get new PSD 1 */ PSD2 = (M[(t>>2)+3] & ~0x3ff8) | bc; /* get new PSD 2 w/old cpix */ M[(t>>2)+4] = IR&0xFFF; /* store call number */ - -#ifdef DO_DYNAMIC_DEBUG - if ((temp2 == 0) && ((IR&0xFFF) == 0xa11)) - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_TRAP | DEBUG_EXP | DEBUG_IRQ); -#endif +#ifdef NOT_NOW sim_debug(DEBUG_IRQ, &cpu_dev, "SVC #%02x call #%03x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); +#endif /* set the mode bits and CCs from the new PSD */ CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ - modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + 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 map mode and interrupt blocking state in CPUSTATUS */ if (PSD2 & MAPBIT) { - CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ - modes |= MAPMODE; /* set mapped mode */ + CPUSTATUS |= BIT8; /* set bit 8 of cpu status */ + MODES |= MAPMODE; /* set mapped mode */ } else - CPUSTATUS &= 0xff7fffff; /* reset bit 8 of cpu status */ + CPUSTATUS &= ~BIT8; /* reset bit 8 of cpu status */ /* set interrupt blocking state */ - if ((PSD2 & 0x8000) == 0) { /* is it retain blocking state */ - if (PSD2 & 0x4000) /* no, is it set blocking state */ - CPUSTATUS |= 0x80; /* yes, set blk state in cpu status bit 24 */ - else { - CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ + if ((PSD2 & RETBBIT) == 0) { /* is it retain blocking state */ + if (PSD2 & SETBBIT) { /* no, is it set blocking state */ + CPUSTATUS |= BIT24; /* yes, set blk state in cpu status bit 24 */ + MODES |= BLKMODE; /* set blocked mode */ + } else { + CPUSTATUS &= ~BIT24; /* no, reset blk state in cpu status bit 24 */ + MODES &= ~BLKMODE; /* reset blocked mode */ irq_pend = 1; /* start scanning interrupts again */ if (irq_auto) { /*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ @@ -5465,19 +5541,28 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); "<|>IntX deactivate level %02x at SVC #%2x PSD1 %08x\n", irq_auto, temp2, PSD1); /*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ -#ifdef NO_SKIP_HERE -/*051920*/ skipinstr = 1; /* skip interrupt test */ +/*103020*/ skipinstr = 1; /* skip interrupt test */ +#ifndef DO_DYNAMIC_DEBUG + /* stop debugging */ + cpu_dev.dctrl &= ~DEBUG_INST; #endif } } + } else { + /* handle retain blocking state */ + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + /* set new blocking state in PSD2 */ + PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ + MODES &= ~(BLKMODE|RETMODE);/* reset blocked & retain mode bits */ + if (int32c & BIT24) { /* see if old mode is blocked */ + PSD2 |= SETBBIT; /* set to blocked state */ + MODES |= BLKMODE; /* set blocked mode */ + } } - PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ - if (CPUSTATUS & 0x80) /* see if old mode is blocked */ - PSD2 |= 0x00004000; /* set to blocked state */ - PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ + TRAPME = 0; /* not to be processed as trap */ goto newpsd; /* new psd loaded */ break; @@ -5502,7 +5587,7 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); hst[hst_p].opsd1 = OPSD1; /* update the CC in opsd1 */ hst[hst_p].npsd1 = PSD1; /* save new psd1 */ hst[hst_p].npsd2 = PSD2; /* save new psd2 */ - hst[hst_p].modes = modes; /* save current mode bits */ + hst[hst_p].modes = MODES; /* save current mode bits */ for (ix=0; ix<8; ix++) { hst[hst_p].reg[ix] = GPR[ix]; /* save reg */ hst[hst_p].reg[ix+8] = BR[ix]; /* save breg */ @@ -5512,13 +5597,13 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); OPSD1 &= 0x87FFFFFE; /* clear the old CC's */ OPSD1 |= PSD1 & 0x78000000; /* update the CC's in the PSD */ /* output mapped/unmapped */ - if (modes & BASEBIT) { - if (modes & MAPMODE) + if (MODES & BASEBIT) { + if (MODES & MAPMODE) sim_debug(DEBUG_INST, &cpu_dev, "BM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); else sim_debug(DEBUG_INST, &cpu_dev, "BU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); } else { - if (modes & MAPMODE) + if (MODES & MAPMODE) sim_debug(DEBUG_INST, &cpu_dev, "NM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); else sim_debug(DEBUG_INST, &cpu_dev, "NU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); @@ -5535,7 +5620,7 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); "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 */ +/*DIAG*/ //1106 skipinstr = 0; /* only test this once */ goto exec; /* go execute the instruction */ break; @@ -5589,7 +5674,7 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); break; case 0xD0>>2: /* 0xD0 SD|ADR - INV */ /* LEA none basemode only */ - if (modes & BASEBIT) + if (MODES & BASEBIT) goto inv; /* invalid instruction in basemode */ /* bc has last bits 0,1 for indirect addr of both 1 for no indirection */ addr &= 0x3fffffff; /* clear bits 0-1 */ @@ -5687,7 +5772,7 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); ovr = 1; PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ /* check if we had an arithmetic exception on the last instruction*/ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { /* leave regs unchanged */ TRAPME = AEXPCEPT_TRAP; /* trap the system now */ goto newpsd; /* process the trap */ @@ -5717,7 +5802,7 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); ovr = 1; PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ /* check if we had an arithmetic exception on the last instruction */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { /* leave regs unchanged */ TRAPME = AEXPCEPT_TRAP; /* trap the system now */ goto newpsd; /* process the trap */ @@ -5764,7 +5849,7 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); ovr = 1; PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ /* check if we had an arithmetic exception on the last instruction*/ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { /* leave regs unchanged */ TRAPME = AEXPCEPT_TRAP; /* trap the system now */ goto newpsd; /* process the trap */ @@ -5794,7 +5879,7 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); ovr = 1; PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ /* check if we had an arithmetic exception on the last instruction*/ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { /* leave regs unchanged */ TRAPME = AEXPCEPT_TRAP; /* trap the system now */ goto newpsd; /* process the trap */ @@ -5883,7 +5968,7 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ } break; @@ -5915,9 +6000,9 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); /* 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 wanted */ + 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*/ if ((MODES & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ /*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ } /* branch not taken, go do next instruction */ @@ -5950,9 +6035,9 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); /* 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 wanted */ + 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*/ if ((MODES & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ /*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ } break; @@ -5971,10 +6056,10 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); } #endif PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ - if (((modes & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect 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*/ if ((MODES & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ /*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ } break; @@ -5988,15 +6073,15 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); 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 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) + if (MODES & BASEBIT) PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* bit 8-30 */ 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*/ if ((MODES & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ /*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ break; @@ -6004,7 +6089,7 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); /* fall through */; case 0x5: /* LPSDCM FA80 */ /*0904*/ irq_pend = 1; /* start scanning interrupts again */ - if ((modes & PRIVBIT) == 0) { /* must be privileged */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged */ TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ @@ -6033,15 +6118,10 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); bc = CPUSTATUS; /* save the CPU STATUS */ TPSD[0] = PSD1; /* save the PSD for the instruction */ TPSD[1] = PSD2; - t = modes; /* save modes too */ + t = MODES; /* save modes too */ ix = SPAD[0xf5]; /* save the current PSD2 */ reg = irq_pend; /* save intr status */ -#ifdef DO_DYNAMIC_DEBUG - /* start debugging */ - if (PC == 0x1e59c) - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_TRAP | DEBUG_EXP | DEBUG_IRQ); -#endif if (opr & 0x0200) { /* Was it LPSDCM? */ if ((TRAPME = Mem_read(addr+4, &temp2))) { /* get PSD2 from memory */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { @@ -6068,57 +6148,59 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); PSD1 = temp; /* PSD1 good, so set it */ /* set the mode bits and CCs from the new PSD */ CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ - modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + MODES = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */ - CPUSTATUS |= modes; /* now insert into CPUSTATUS */ -#ifdef NOTNEEDED - /* set new arithmetic trap state in CPUSTATUS */ - if (PSD1 & AEXPBIT) { - CPUSTATUS |= AEXPBIT; /* set bit 7 of cpu status */ - modes |= AEXPBIT; /* set arithmetic exception mode */ - } else - CPUSTATUS &= ~AEXPBIT; /* reset bit 7 of cpu status */ - /* set new extended state in CPUSTATUS */ - if (PSD1 & EXTDBIT) { - CPUSTATUS |= EXTDBIT; /* set bit 5 of cpu status */ - modes |= EXTDBIT; /* set extended mode */ - } else - CPUSTATUS &= ~EXTDBIT; /* reset bit 5 of cpu status */ -#endif + CPUSTATUS |= MODES; /* now insert into CPUSTATUS */ + /* set new map mode and interrupt blocking state in CPUSTATUS */ if (PSD2 & MAPBIT) { - CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ - modes |= MAPMODE; /* set mapped mode */ + CPUSTATUS |= BIT8; /* set bit 8 of cpu status */ + MODES |= MAPMODE; /* set mapped mode */ } else - CPUSTATUS &= 0xff7fffff; /* reset bit 8 of cpu status */ + CPUSTATUS &= ~BIT8; /* reset bit 8 of cpu status */ + /* set interrupt blocking state */ - if ((PSD2 & 0x8000) == 0) { /* is it retain blocking state */ - if (PSD2 & 0x4000) /* no, is it set blocking state */ - CPUSTATUS |= 0x80; /* yes, set blk state in cpu status bit 24 */ - else { - CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ + if ((PSD2 & RETBBIT) == 0) { /* is it retain blocking state */ + if (PSD2 & SETBBIT) { /* no, is it set blocking state */ + CPUSTATUS |= BIT24; /* yes, set blk state in cpu status bit 24 */ + MODES |= BLKMODE; /* set blocked mode */ + } else { + CPUSTATUS &= ~BIT24; /* no, reset blk state in cpu status bit 24 */ + MODES &= ~BLKMODE; /* reset blocked mode */ irq_pend = 1; /* start scanning interrupts again */ if (irq_auto) { /*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ /*AIR*/ SPAD[irq_auto+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ sim_debug(DEBUG_IRQ, &cpu_dev, - "<|>IntX deactivate level %02x at LPSD(CM) %08x\n", irq_auto, PSD1); + "<|>IntX deactivate level %02x at LPSD(CM) %08x %08x\n", + irq_auto, PSD1, PSD2); /*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ -#ifdef NO_SKIP_HERE - skipinstr = 1; /* skip interrupt test */ +/*103020*/ skipinstr = 1; /* skip interrupt test */ +#ifndef DO_DYNAMIC_DEBUG + /* stop debugging */ + cpu_dev.dctrl &= ~DEBUG_INST; #endif } } + } else { +#ifdef NOTRIGHT + /* handle retain blocking state */ + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ +#endif + /* set new blocking state in PSD2 */ + PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ + MODES &= ~(BLKMODE|RETMODE);/* reset blocked & retain mode bits */ + if (bc & BIT24) { /* see if old mode is blocked */ + PSD2 |= SETBBIT; /* set to blocked state */ + MODES |= BLKMODE; /* set blocked mode */ + } } - PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ - if (CPUSTATUS & 0x80) /* see if old mode is blocked */ - PSD2 |= 0x00004000; /* set to blocked state */ if (opr & 0x0200) { /* Was it LPSDCM? */ /* map bit must be on to load maps */ if (PSD2 & MAPBIT) { /* set mapped mode in cpu status */ - CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ + CPUSTATUS |= BIT8; /* set bit 8 of cpu status */ sim_debug(DEBUG_DETAIL, &cpu_dev, "B4 LPSDCM temp %06x TPSD %08x %08x PSD %08x %08x\n", temp, TPSD[0], TPSD[1], PSD1, PSD2); @@ -6142,10 +6224,10 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); uint32 mpl = SPAD[0xf3]; /* get mpl from spad address */ uint32 cpix = PSD2 & 0x3ff8; /* get cpix 11 bit offset from psd wd 2 */ uint32 midl = RMW(mpl+cpix); /* get midl entry for given user cpix */ - int spc = midl & MASK16; /* get 16 bit user segment description count */ + uint32 spc = midl & MASK16; /* get 16 bit user segment description count */ if (spc != CPIXPL) { PSD2 &= ~RETMBIT; /* no, turn off retain bit in PSD2 */ -#ifndef NOTNOW +#ifdef NOT_NOW sim_debug(DEBUG_IRQ, &cpu_dev, "LPSD(CM) RESET RETAIN OPSD %08x %08x NPSD %08x %08x TRAPME %02x\n", TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); @@ -6156,16 +6238,20 @@ TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); if ((PSD2 & RETMBIT) == 0) { /* don't load maps if retain bit set */ /* we need to load the new maps */ TRAPME = load_maps(PSD, 0); /* load maps for new PSD */ - sim_debug(DEBUG_DETAIL, &cpu_dev, +// sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_IRQ, &cpu_dev, "AF LPSDCM TPSD %08x %08x PSD %08x %08x TRAPME %02x\n", TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); - sim_debug(DEBUG_DETAIL, &cpu_dev, +// sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_IRQ, &cpu_dev, "AF LPSDCM BPIX %04x CPIX %04x CPIXPL %04x\n", BPIX, CPIX, CPIXPL); - sim_debug(DEBUG_DETAIL, &cpu_dev, +// sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_IRQ, &cpu_dev, "AF LPSDCM OS MAPC[0-5] %08x %08x %08x %08x %08x %08x\n", MAPC[0], MAPC[1], MAPC[2], MAPC[3], MAPC[4], MAPC[5]); - sim_debug(DEBUG_DETAIL, &cpu_dev, +// sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_IRQ, &cpu_dev, "AF LPSDCM US MAPC[%x-%x] %08x %08x %08x %08x %08x %08x\n", BPIX, BPIX+5, MAPC[BPIX], MAPC[BPIX+1], MAPC[BPIX+2], MAPC[BPIX+3], MAPC[BPIX+4], MAPC[BPIX+5]); @@ -6174,18 +6260,18 @@ TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ sim_debug(DEBUG_IRQ, &cpu_dev, - "LPSDCM MAPS LOADED TRAPME = %02x PSD1 %08x PSD2 %08x BPIX %02x CPIXPL %02x\n", + "LPSDCM MAPS LOADED TRAPME %02x PSD1 %08x PSD2 %08x BPIX %02x CPIXPL %02x\n", TRAPME, PSD1, PSD2, BPIX, CPIXPL); } PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ } else { /* LPSD */ /* if cpix is zero, copy cpix from PSD2 in SPAD[0xf5] */ - if ((PSD2 & 0x3fff) == 0) { - PSD2 |= (SPAD[0xf5] & 0x3fff); /* use new cpix */ + if ((PSD2 & 0x3ff8) == 0) { + PSD2 |= (SPAD[0xf5] & 0x3ff8); /* use new cpix */ } } -#ifdef NOTNOW +#ifdef NOT_NOW sim_debug(DEBUG_IRQ, &cpu_dev, "At LPSD(CM) OPSD %08x %08x NPSD %08x %08x TRAPME %02x\n", TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); @@ -6201,7 +6287,7 @@ TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); /* if old one was used, we fail test 21/0 in cn.mmm for 32/67 */ //DIAG PSD2 = TPSD[1]; /* restore PSD2 */ CPUSTATUS = bc; /* restore the CPU STATUS */ - modes = t; /* restore modes too */ + MODES = t; /* restore modes too */ SPAD[0xf5] = ix; /* restore the current PSD2 to SPAD */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ irq_pend = reg; /* restore intr status */ @@ -6213,7 +6299,7 @@ TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); goto newpsd; /* go process error */ } drop_nop = 0; /* nothing to drop */ -#ifndef NOTNOW +#ifdef NOT_NOW sim_debug(DEBUG_IRQ, &cpu_dev, "LPSD(CM) END OPSD %08x %08x NPSD %08x %08x CPUSTAT %08x irq %1x BLK %1x\n", TPSD[0], TPSD[1], PSD1, PSD2, CPUSTATUS, irq_pend, CPUSTATUS&0x80?1:0); @@ -6249,7 +6335,7 @@ TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); /* */ case 0xFC>>2: /* 0xFC IMM - IMM */ /* XIO, CD, TD, Interrupt Control */ /*0904*/ irq_pend = 1; /* start scanning interrupts again */ - if ((modes & PRIVBIT) == 0) { /* must be privileged to do I/O */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged to do I/O */ TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ @@ -6478,6 +6564,7 @@ TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); temp2 = (IR & 0x7fff); /* set new chan/suba into IR */ lchan = (temp2 & 0x7F00) >> 8; /* get 7 bit logical channel address */ suba = temp2 & 0xFF; /* get 8 bit subaddress */ + lchsa = (lchan << 8) | suba; /* logical address */ /* 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 */ @@ -6534,34 +6621,15 @@ mcheck: /* t is SPAD entry contents for chan device */ /* temp2 has logical channel address */ /* lchan - logical channel address */ + /* lchsa - logical channel & subaddress */ /* chan - channel address */ /* suba - channel device subaddress */ /* rchsa - real chan & sub address from spad for logical channel */ /* ix - positive interrupt level */ /* addr - ICBA for specified interrupt level, points to 6 wd block */ /* temp - First IOCD address */ -#ifdef DO_DYNAMIC_DEBUG - /* start debugging */ - if (rchsa == 0x0801) { -// GPR[5] &= ~1; -// GPR[5] |= 2; -// rchsa &= ~1; -// rchsa |= 2; - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_TRAP | DEBUG_EXP | DEBUG_IRQ); - sim_debug(DEBUG_XIO, &cpu_dev, - "\n\tR0=%.8x R1=%.8x R2=%.8x R3=%.8x", GPR[0], GPR[1], GPR[2], GPR[3]); - sim_debug(DEBUG_XIO, &cpu_dev, - " R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]); - if (modes & BASEBIT) { - sim_debug(DEBUG_XIO, &cpu_dev, - "\tB0=%.8x B1=%.8x B2=%.8x B3=%.8x", BR[0], BR[1], BR[2], BR[3]); - sim_debug(DEBUG_XIO, &cpu_dev, - " B4=%.8x B5=%.8x B6=%.8x B7=%.8x\n", BR[4], BR[5], BR[6], BR[7]); - } - } -#endif sim_debug(DEBUG_XIO, &cpu_dev, - "XIO switch %02x lchan %02x irq %02x chsa %04x IOCDa %08x CPUSTATUS %08x BLK %1x\n", + "XIO switch %02x lchan %02x irq %02x rchsa %04x IOCDa %08x CPUSTATUS %08x BLK %1x\n", ((opr>>3)&0x0f), lchan, ix, rchsa, temp, CPUSTATUS, CPUSTATUS&0x80?1:0); switch((opr >> 3) & 0xf) { /* use bits 9-12 to determine I/O instruction */ @@ -6592,89 +6660,102 @@ mcheck: break; case 0x02: /* Start I/O SIO */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "XIO SIO b4 call PSD1 %08x chan %04x chsa %04x BLK %1x\n", - PSD1, chan, rchsa, CPUSTATUS&0x80?1:0); - if ((TRAPME = startxio(rchsa, &rstatus))) +// chsa = temp2 & 0x7fff; /* logical address */ + sim_debug(DEBUG_XIO, &cpu_dev, + "XIO SIO b4 call PSD1 %08x rchsa %04x lchsa %04x BLK %1x\n", + PSD1, rchsa, lchsa, CPUSTATUS&0x80?1:0); +// PSD1, lchan, lchsa, CPUSTATUS&0x80?1:0); + if ((TRAPME = startxio(lchsa, &rstatus))) goto newpsd; /* error returned, trap cpu */ PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "XIO SIO ret PSD1 %08x chan %04x chsa %04x status %08x BLK %1x\n", - PSD1, chan, rchsa, rstatus, CPUSTATUS&0x80?1:0); + PSD1, rchsa, lchsa, rstatus, CPUSTATUS&0x80?1:0); break; case 0x03: /* Test I/O TIO */ - if ((TRAPME = testxio(rchsa, &rstatus))) { +// lchsa = (lchan << 8) | suba; /* logical address */ + if ((TRAPME = testxio(lchsa, &rstatus))) { sim_debug(DEBUG_TRAP, &cpu_dev, - "XIO TIO ret PSD1 %x chan %x chsa %x status %x BLK %1x\n", - PSD1, chan, rchsa, rstatus, CPUSTATUS&0x80?1:0); + "XIO TIO ret PSD1 %x rchsa %x lchsa %x status %x BLK %1x\n", + PSD1, rchsa, lchsa, rstatus, CPUSTATUS&0x80?1:0); goto newpsd; /* error returned, trap cpu */ } PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ sim_debug(DEBUG_XIO, &cpu_dev, - "XIO TIO ret PSD1 %08x chsa %04x status %08x spad %08x INTS[%02x] %08x BLK %1x\n", - PSD1, rchsa, rstatus, t, ix, INTS[ix], CPUSTATUS&0x80?1:0); + "XIO TIO ret PSD1 %08x lchsa %04x stat %08x spad %08x INTS[%02x] %08x BLK %1x\n", + PSD1, lchsa, rstatus, t, ix, INTS[ix], CPUSTATUS&0x80?1:0); break; case 0x04: /* Stop I/O STPIO */ - if ((TRAPME = stopxio(rchsa, &rstatus))) +// lchsa = (lchan << 8) | suba; /* logical address */ + if ((TRAPME = stopxio(lchsa, &rstatus))) goto newpsd; /* error returned, trap cpu */ PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - sim_debug(DEBUG_XIO, &cpu_dev, "XIO STPIO ret chan %04x chsa %04x status %08x\n", - chan, rchsa, rstatus); + sim_debug(DEBUG_XIO, &cpu_dev, "XIO STPIO ret rchsa %04x lchsa %04x status %08x\n", + rchsa, lchsa, rstatus); break; /* TODO Finish XIO */ case 0x05: /* Reset channel RSCHNL */ +// lchsa = (lchan << 8) | suba; /* logical address */ /* TODO Maybe we need to disable int too???? */ - if ((TRAPME = rschnlxio(rchsa, &rstatus))) + if ((TRAPME = rschnlxio(lchsa, &rstatus))) 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 */ PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - sim_debug(DEBUG_XIO, &cpu_dev, "XIO RSCHNL ret chan %04x chsa %04x status %08x\n", - chan, rchsa, rstatus); + sim_debug(DEBUG_XIO, &cpu_dev, "XIO RSCHNL ret rchsa %04x lchsa %04x status %08x\n", + rchsa, lchsa, rstatus); break; case 0x06: /* Halt I/O HIO */ - if ((TRAPME = haltxio(rchsa, &rstatus))) +// lchsa = (lchan << 8) | suba; /* logical address */ + if ((TRAPME = haltxio(lchsa, &rstatus))) goto newpsd; /* error returned, trap cpu */ PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ sim_debug(DEBUG_XIO, &cpu_dev, - "HIO HALTXIO ret chan %04x chsa %04x status %08x\n", - chan, rchsa, rstatus); + "HIO HALTXIO ret rchsa %04x lchsa %04x status %08x\n", + rchsa, lchsa, rstatus); break; case 0x07: /* Grab controller GRIO n/u */ - if ((TRAPME = grabxio(rchsa, &rstatus))) + lchsa = (lchan << 8) | suba; /* logical address */ + if ((TRAPME = grabxio(lchsa, &rstatus))) goto newpsd; /* error returned, trap cpu */ PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - sim_debug(DEBUG_XIO, &cpu_dev, "XIO GRIO ret chan %04x chsa %04x status %08x\n", - chan, rchsa, rstatus); + sim_debug(DEBUG_XIO, &cpu_dev, "XIO GRIO ret rchsa %04x lchsa %04x status %08x\n", + rchsa, lchsa, rstatus); break; case 0x08: /* Reset controller RSCTL */ - if ((TRAPME = rsctlxio(rchsa, &rstatus))) +// lchsa = (lchan << 8) | suba; /* logical address */ + if ((TRAPME = rsctlxio(lchsa, &rstatus))) goto newpsd; /* error returned, trap cpu */ PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - sim_debug(DEBUG_XIO, &cpu_dev, "XIO RSCTL ret chan %04x chsa %04x status %08x\n", - chan, rchsa, rstatus); + sim_debug(DEBUG_XIO, &cpu_dev, "XIO RSCTL ret rchsa %04x lchsa %04x status %08x\n", + rchsa, lchsa, rstatus); break; case 0x0C: /* Enable channel interrupt ECI */ /* disable int only */ - sim_debug(DEBUG_XIO, &cpu_dev, "ECI entry chan %04x suba %04x\n", chan, suba); +// lchsa = (lchan << 8) | suba; /* logical address */ sim_debug(DEBUG_XIO, &cpu_dev, - "XIO ECI rchsa %04x spad %08x INTS[%02x] %08x\n", - rchsa, t, ix, INTS[ix]); + "XIO ECI chsa %04x lchsa %04x spad %08x INTS[%02x] %08x\n", + rchsa, lchsa, t, ix, INTS[ix]); - if ((TRAPME = checkxio(rchsa, &rstatus))) + if ((TRAPME = checkxio(lchsa, &rstatus))) goto newpsd; /* error returned, trap cpu */ sim_debug(DEBUG_XIO, &cpu_dev, - "ECI after checkxio chan %04x suba %04x status %08x\n", chan, suba, rstatus); + "ECI after checkxio rchsa %04x suba %04x status %08x\n", + rchsa, suba, rstatus); + if ((INTS[ix] & INTS_ACT) == 0) + sim_debug(DEBUG_XIO, &cpu_dev, + "ECI INT %02x is NOT set rchsa %04x lchsa %04x status %08x\n", + ix, rchsa, lchsa, rstatus); /* SPAD entries for interrupts begin at 0x80 */ INTS[ix] |= INTS_ENAB; /* enable specified int level */ SPAD[ix+0x80] |= SINT_ENAB; /* enable in SPAD too */ @@ -6685,32 +6766,20 @@ mcheck: case 0x0D: /* Disable channel interrupt DCI */ /* disable int, leave req */ +// lchsa = (lchan << 8) | suba; /* logical address */ sim_debug(DEBUG_XIO, &cpu_dev, - "XIO DCI chan %04x chsa %04x spad %08x INTS[%02x] %08x\n", - chan, rchsa, t, ix, INTS[ix]); + "XIO DCI rchsa %04x lchsa %04x spad %08x INTS[%02x] %08x\n", + rchsa, lchsa, t, ix, INTS[ix]); - if ((TRAPME = checkxio(rchsa, &rstatus))) + if ((TRAPME = checkxio(lchsa, &rstatus))) goto newpsd; /* error returned, trap cpu */ sim_debug(DEBUG_XIO, &cpu_dev, "DCI After checkxio call rstatus %08x\n", rstatus); /* doc says we need to drop 1 queued status entry too */ -#ifdef TEST - { - DIB *dibp = dib_chan[chan]; /* get channel dib pointer */ -//?? CHANP *chp = dibp->chan_prg; /* get channel prog pointer */ - CHANP *chp = find_chanp_ptr(chan<<8); /* get channel prog pointer */ - if (dibp != 0) { - if ((chp != 0) && post_csw(chp, 0)) { - sim_debug(DEBUG_XIO, &cpu_dev, - "DCI After checkxio call removed FIFO entry chp %p\n", chp); - } - } - } -#endif if ((INTS[ix] & INTS_ACT) == 0) sim_debug(DEBUG_XIO, &cpu_dev, - "DCI INT %02x is NOT set chan %04x suba %04x status %08x\n", - ix, chan, suba, rstatus); + "DCI INT %02x is NOT set rchsa %04x lchsa %04x status %08x\n", + ix, rchsa, lchsa, rstatus); /* SPAD entries for interrupts begin at 0x80 */ INTS[ix] &= ~INTS_ENAB; /* disable specified int level */ SPAD[ix+0x80] &= ~SINT_ENAB; /* disable in SPAD too */ @@ -6721,31 +6790,32 @@ mcheck: case 0x0E: /* Activate channel interrupt ACI */ /* Set int active, clear request */ +// lchsa = (lchan << 8) | suba; /* logical address */ sim_debug(DEBUG_XIO, &cpu_dev, - "XIO ACI chan %04x chsa %04x spad %08x INTS[%02x] %08x\n", - chan, rchsa, t, ix, INTS[ix]); + "XIO ACI rchsa %04x lchsa %04x spad %08x INTS[%02x] %08x\n", + rchsa, lchsa, t, ix, INTS[ix]); - if ((TRAPME = checkxio(rchsa, &rstatus))) + if ((TRAPME = checkxio(lchsa, &rstatus))) goto newpsd; /* error returned, trap cpu */ if ((INTS[ix] & INTS_ACT) == 0) sim_debug(DEBUG_XIO, &cpu_dev, - "ACI INT %02x is NOT set chan %04x suba %04x status %08x\n", - ix, chan, suba, rstatus); + "ACI INT %02x is NOT set rchsa %04x lchsa %04x status %08x\n", + ix, rchsa, lchsa, rstatus); /* SPAD entries for interrupts begin at 0x80 */ INTS[ix] |= INTS_ACT; /* activate specified int level */ SPAD[ix+0x80] |= SINT_ACT; /* enable in SPAD too */ -//WAS NOT DONE INTS[ix] &= ~INTS_REQ; /* clears any requests also */ /*917*/ /* tech manual says to remove any request */ -/*917*/ INTS[ix] &= ~INTS_REQ; /* clears any requests also */ +//BAD/*1030*/ INTS[ix] &= ~INTS_REQ; /* clears any requests also */ PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ break; case 0x0F: /* Deactivate channel interrupt DACI */ /* Clear active and leave any request */ /* Note, instruction following DACI is not interruptable */ +// lchsa = (lchan << 8) | suba; /* logical address */ sim_debug(DEBUG_XIO, &cpu_dev, - "XIO DACI chan %04x chsa %04x spad %08x INTS[%02x] %08x BLK %1x\n", - chan, rchsa, t, ix, INTS[ix], CPUSTATUS&0x80?1:0); + "XIO DACI rchsa %04x lchsa %04x spad %08x INTS[%02x] %08x\n", + rchsa, lchsa, t, ix, INTS[ix]); if ((TRAPME = checkxio(rchsa, &rstatus))) goto newpsd; /* error returned, trap cpu */ @@ -6759,6 +6829,13 @@ mcheck: irq_pend = 1; /* start scanning interrupts again */ skipinstr = 1; /* skip interrupt test */ PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ + sim_debug(DEBUG_XIO, &cpu_dev, + "XIO DACI ret lchsa %04x status %08x spad %08x INTS[%02x] %08x BLK %1x\n", + lchsa, rstatus, t, ix, INTS[ix], CPUSTATUS&0x80?1:0); +#ifndef DO_DYNAMIC_DEBUG + /* stop debugging */ + cpu_dev.dctrl &= ~DEBUG_INST; +#endif break; } /* end of XIO switch */ break; @@ -6873,7 +6950,7 @@ mcheck: } /* check if we had an arithmetic exception on the last instruction*/ - if (ovr && (modes & AEXPBIT)) { + if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* trap the system now */ goto newpsd; /* process the trap */ } @@ -6902,7 +6979,7 @@ mcheck: hst[hst_p].opsd1 = OPSD1; /* update the CC in opsd1 */ hst[hst_p].npsd1 = PSD1; /* save new psd1 */ hst[hst_p].npsd2 = PSD2; /* save new psd2 */ - hst[hst_p].modes = modes; /* save current mode bits */ + hst[hst_p].modes = MODES; /* save current mode bits */ for (ix=0; ix<8; ix++) { hst[hst_p].reg[ix] = GPR[ix]; /* save reg */ hst[hst_p].reg[ix+8] = BR[ix]; /* save breg */ @@ -6911,13 +6988,13 @@ mcheck: /* DEBUG_INST support code */ /* output mapped/unmapped */ - if (modes & BASEBIT) { - if (modes & MAPMODE) + if (MODES & BASEBIT) { + if (MODES & MAPMODE) sim_debug(DEBUG_INST, &cpu_dev, "BM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); else sim_debug(DEBUG_INST, &cpu_dev, "BU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); } else { - if (modes & MAPMODE) + if (MODES & MAPMODE) sim_debug(DEBUG_INST, &cpu_dev, "NM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); else sim_debug(DEBUG_INST, &cpu_dev, "NU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); @@ -6928,7 +7005,7 @@ mcheck: "\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]); - if (modes & BASEBIT) { + if (MODES & BASEBIT) { sim_debug(DEBUG_INST, &cpu_dev, "\tB0=%.8x B1=%.8x B2=%.8x B3=%.8x", BR[0], BR[1], BR[2], BR[3]); sim_debug(DEBUG_INST, &cpu_dev, @@ -7014,12 +7091,12 @@ newpsd: //DIAG fix for test 34/10 in MMM diag, reset bit 31 if ((CPU_MODEL == MODEL_87) || (CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - PSD1 &= ~1; /* force off last right */ + PSD1 &= ~BIT31; /* force off last right */ } } else { EXM_EXR = 0; /* reset PC increment for EXR */ if ((drop_nop) && ((CPU_MODEL == MODEL_67) || (CPU_MODEL >= MODEL_V6))) - PSD1 &= ~1; /* force off last right */ + PSD1 &= ~BIT31; /* force off last right */ drop_nop = 0; sim_debug(DEBUG_TRAP, &cpu_dev, "##GOT BT TRAPME %04x LOAD MAPS PSD1 %08x PSD2 %08x\n", @@ -7031,7 +7108,7 @@ newpsd: if (TRAPME == DEMANDPG_TRAP) { /* 0xC4 Demand Page Fault Trap (V6&V9 Only) */ /* Set map number */ if (CPU_MODEL >= MODEL_V9) - PSD1 &= ~1; /* force off last right */ + PSD1 &= ~BIT31; /* force off last right */ /* pfault will have 11 bit page number and bit 0 set if op fetch */ sim_debug(DEBUG_TRAP, &cpu_dev, "##PAGEFAULT TRAPS %04x page# %04x LOAD MAPS PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", @@ -7045,7 +7122,7 @@ newpsd: TRAPME, IR, PSD1, PSD2, CPUSTATUS, ovr, drop_nop); tta = tta + (TRAPME - 0x80); /* tta has mem addr of trap vector */ - if (modes & (BASEBIT | EXTDBIT)) + if (MODES & (BASEBIT | EXTDBIT)) tvl = M[tta>>2] & 0xFFFFFC; /* get 24 bit trap address from trap vector loc */ else tvl = M[tta>>2] & 0x7FFFC; /* get 19 bit trap address from trap vector loc */ @@ -7073,7 +7150,7 @@ newpsd: for (ix=0; ix<8; ix+=2) { fprintf(stderr, "GPR[%d] %08x GPR[%d] %08x\r\n", ix, GPR[ix], ix+1, GPR[ix+1]); } - if (modes & BASEBIT) { + if (MODES & BASEBIT) { for (ix=0; ix<8; ix+=2) { fprintf(stderr, "BR[%d] %08x BR[%d] %08x\r\n", ix, BR[ix], ix+1, BR[ix+1]); } @@ -7081,6 +7158,7 @@ newpsd: fprintf(stderr, "[][][][][][][][][][] HALT TRAP [][][][][][][][][][]\r\n"); return STOP_HALT; /* exit to simh for halt */ } else { + uint32 oldstatus = CPUSTATUS; /* keep for retain blocking state */ /* valid vector, so store the PSD, fetch new PSD */ bc = PSD2 & 0x3ff8; /* get copy of cpix */ if ((TRAPME) && ((CPU_MODEL <= MODEL_27) )) @@ -7101,41 +7179,38 @@ newpsd: /* set the mode bits and CCs from the new PSD */ CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ - modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + MODES = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */ - CPUSTATUS |= modes; /* not insert into CPUSTATUS */ -#ifdef NOTNEEDED - /* set new arithmetic trap state in CPUSTATUS */ -/*917*/ if (PSD1 & AEXPBIT) { - CPUSTATUS |= AEXPBIT; /* set bit 7 of cpu status */ - modes |= AEXPBIT; /* set arithmetic exception mode */ - } else - CPUSTATUS &= ~AEXPBIT; /* reset bit 7 of cpu status */ -/*917*/ /* set new extended state in CPUSTATUS */ - if (PSD1 & EXTDBIT) { - CPUSTATUS |= EXTDBIT; /* set bit 5 of cpu status */ - modes |= EXTDBIT; /* set extended mode */ - } else - CPUSTATUS &= ~EXTDBIT; /* reset bit 5 of cpu status */ -#endif + CPUSTATUS |= MODES; /* now insert into CPUSTATUS */ + /* set new map mode and interrupt blocking state in CPUSTATUS */ if (PSD2 & MAPBIT) { - CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ - modes |= MAPMODE; /* set mapped mode */ + CPUSTATUS |= BIT8; /* set bit 8 of cpu status */ + MODES |= MAPMODE; /* set mapped mode */ } else - CPUSTATUS &= 0xff7fffff; /* reset bit 8 of cpu status */ - /* set interrupt blocking state */ - if ((PSD2 & 0x8000) == 0) { /* is it retain blocking state */ - if (PSD2 & 0x4000) /* no, is it set blocking state */ - CPUSTATUS |= 0x80; /* yes, set blk state in cpu status bit 24 */ - else - 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 */ - PSD2 |= 0x00004000; /* set to blocked state */ + CPUSTATUS &= ~BIT8; /* reset bit 8 of cpu status */ + + /* set interrupt blocking state */ + if ((PSD2 & RETBBIT) == 0) { /* is it retain blocking state */ + if (PSD2 & SETBBIT) { /* no, is it set blocking state */ + CPUSTATUS |= BIT24; /* yes, set blk state in cpu status bit 24 */ + MODES |= BLKMODE; /* set blocked mode */ + } else { + CPUSTATUS &= ~BIT24; /* no, reset blk state in cpu status bit 24 */ + MODES &= ~BLKMODE; /* reset blocked mode */ + } + } else { + /* handle retain blocking state */ + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + /* set new blocking state in PSD2 */ + PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ + MODES &= ~(BLKMODE|RETMODE);/* reset blocked & retain mode bits */ + if (oldstatus & BIT24) { /* see if old mode is blocked */ + PSD2 |= SETBBIT; /* set to blocked state */ + MODES |= BLKMODE; /* set blocked mode */ + } + } - PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ @@ -7166,7 +7241,7 @@ newpsd: hst[hst_p].opsd1 = OPSD1; /* update the CC in opsd1 */ hst[hst_p].npsd1 = PSD1; /* save new psd1 */ hst[hst_p].npsd2 = PSD2; /* save new psd2 */ - hst[hst_p].modes = modes; /* save current mode bits */ + hst[hst_p].modes = MODES; /* save current mode bits */ for (ix=0; ix<8; ix++) { hst[hst_p].reg[ix] = GPR[ix]; /* save reg */ hst[hst_p].reg[ix+8] = BR[ix]; /* save breg */ @@ -7175,13 +7250,13 @@ newpsd: /* DEBUG_INST support code */ /* output mapped/unmapped */ - if (modes & BASEBIT) { - if (modes & MAPMODE) + if (MODES & BASEBIT) { + if (MODES & MAPMODE) sim_debug(DEBUG_INST, &cpu_dev, "BM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); else sim_debug(DEBUG_INST, &cpu_dev, "BU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); } else { - if (modes & MAPMODE) + if (MODES & MAPMODE) sim_debug(DEBUG_INST, &cpu_dev, "NM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); else sim_debug(DEBUG_INST, &cpu_dev, "NU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); @@ -7192,7 +7267,7 @@ newpsd: "\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]); - if (modes & BASEBIT) { + if (MODES & BASEBIT) { sim_debug(DEBUG_INST, &cpu_dev, "\tB0=%.8x B1=%.8x B2=%.8x B3=%.8x", BR[0], BR[1], BR[2], BR[3]); sim_debug(DEBUG_INST, &cpu_dev, @@ -7221,12 +7296,12 @@ t_stat cpu_reset(DEVICE *dptr) /* leave regs alone so values can be passed to boot code */ PSD1 = 0x80000000; /* privileged, non mapped, non extended, address 0 */ PSD2 = 0x00004000; /* blocked interrupts mode */ - modes = (PRIVBIT | BLKMODE); /* set modes to privileged and blocked interrupts */ + MODES = (PRIVBIT | BLKMODE); /* set modes to privileged and blocked interrupts */ CC = 0; /* no CCs too */ CPUSTATUS = CPU_MODEL; /* clear all cpu status except cpu type */ - CPUSTATUS |= 0x80000000; /* set privleged state bit 0 */ - CPUSTATUS |= 0x00000080; /* set blocked mode state bit 24 */ - CPUSTATUS |= 0x00000200; /* set HS floating point unit not present bit 22 */ + CPUSTATUS |= PRIVBIT; /* set privleged state bit 0 */ + CPUSTATUS |= BIT24; /* set blocked mode state bit 24 */ + CPUSTATUS |= BIT22; /* set HS floating point unit not present bit 22 */ TRAPSTATUS = CPU_MODEL; /* clear all trap status except cpu type */ CMCR = 0; /* No Cache Enabled */ SMCR = 0; /* No Shared Memory Enabled */ @@ -7371,7 +7446,7 @@ t_stat cpu_set_size(UNIT *uptr, int32 sval, CONST char *cptr, void *desc) t_addr msize; val >>= UNIT_V_MSIZE; /* shift index right 19 bits */ - if (val >= (sizeof(memwds)/sizeof(uint32))) /* is size valid */ + if (val >= (int32)(sizeof(memwds)/sizeof(uint32))) /* is size valid */ return SCPE_ARG; /* nope, argument error */ sz = memwds[val]; /* (128KB/4) << index == memory size in KW */ if ((sz <= 0) || (sz > MAXMEMSIZE)) /* is size valid */ @@ -7448,13 +7523,13 @@ t_stat cpu_show_hist(FILE *st, UNIT *uptr, int32 val, CONST void *desc) for (k = 0; k < lnt; k++) { /* print specified entries */ h = &hst[(++di) % hst_lnt]; /* entry pointer */ /* display the instruction and results */ - if (modes & BASEBIT) { - if (modes & MAPMODE) + if (MODES & BASEBIT) { + if (MODES & MAPMODE) fprintf(st, "BM%.8x %.8x %.8x ", h->opsd1, h->npsd2, h->oir); else fprintf(st, "BU%.8x %.8x %.8x ", h->opsd1, h->npsd2, h->oir); } else { - if (modes & MAPMODE) + if (MODES & MAPMODE) fprintf(st, "NM%.8x %.8x %.8x ", h->opsd1, h->npsd2, h->oir); else fprintf(st, "NU%.8x %.8x %.8x ", h->opsd1, h->npsd2, h->oir); diff --git a/SEL32/sel32_defs.h b/SEL32/sel32_defs.h index 6cecb6b..d2d366e 100644 --- a/SEL32/sel32_defs.h +++ b/SEL32/sel32_defs.h @@ -42,72 +42,73 @@ /* I/O equates */ /* Channel sense bytes set by device */ -#define SNS_BSY 0x80 /* Unit Busy */ -#define SNS_SMS 0x40 /* Status modified */ -#define SNS_CTLEND 0x20 /* Control unit end */ -#define SNS_ATTN 0x10 /* Unit attention */ -#define SNS_CHNEND 0x08 /* Channel end */ -#define SNS_DEVEND 0x04 /* Device end */ -#define SNS_UNITCHK 0x02 /* Unit check */ -#define SNS_UNITEXP 0x01 /* Unit exception */ +#define SNS_BSY 0x80 /* Unit Busy */ +#define SNS_SMS 0x40 /* Status modified */ +#define SNS_CTLEND 0x20 /* Control unit end */ +#define SNS_ATTN 0x10 /* Unit attention */ +#define SNS_CHNEND 0x08 /* Channel end */ +#define SNS_DEVEND 0x04 /* Device end */ +#define SNS_UNITCHK 0x02 /* Unit check */ +#define SNS_UNITEXP 0x01 /* Unit exception */ /* Command masks */ -#define CCMDMSK 0xff000000 /* Mask for command */ -#define CMD_CHAN 0x00 /* Channel control */ -#define CMD_SENSE 0x04 /* Sense channel command */ -#define CMD_TIC 0x08 /* Transfer in channel */ -#define CMD_RDBWD 0x0c /* Read backward (not used) */ +#define CCMDMSK 0xff000000 /* Mask for command */ +#define CMD_CHAN 0x00 /* Channel control */ +#define CMD_SENSE 0x04 /* Sense channel command */ +#define CMD_TIC 0x08 /* Transfer in channel */ +#define CMD_RDBWD 0x0c /* Read backward */ /* operation types */ -#define CMD_TYPE 0x03 /* Type mask */ -#define CMD_WRITE 0x01 /* Write command */ -#define CMD_READ 0x02 /* Read command */ -#define CMD_CTL 0x03 /* Control command */ +#define CMD_TYPE 0x03 /* Type mask */ +#define CMD_WRITE 0x01 /* Write command */ +#define CMD_READ 0x02 /* Read command */ +#define CMD_CTL 0x03 /* Control command */ /* IOCD word 2 status bits */ -#define STATUS_ECHO 0x8000 /* Halt I/O and Stop I/O function */ -#define STATUS_PCI 0x4000 /* Program controlled interrupt */ -#define STATUS_LENGTH 0x2000 /* Incorrect length */ -#define STATUS_PCHK 0x1000 /* Channel program check */ -#define STATUS_CDATA 0x0800 /* Channel data check */ -#define STATUS_CCNTL 0x0400 /* Channel control check */ -#define STATUS_INTER 0x0200 /* Channel interface check */ -#define STATUS_CHAIN 0x0100 /* Channel chain check */ -#define STATUS_BUSY 0x0080 /* Device busy */ -#define STATUS_MOD 0x0040 /* Status modified */ -#define STATUS_CTLEND 0x0020 /* Controller end */ -#define STATUS_ATTN 0x0010 /* Device raised attention */ -#define STATUS_CEND 0x0008 /* Channel end */ -#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_ECHO 0x8000 /* Halt I/O and Stop I/O function */ +#define STATUS_PCI 0x4000 /* Program controlled interrupt */ +#define STATUS_LENGTH 0x2000 /* Incorrect length */ +#define STATUS_PCHK 0x1000 /* Channel program check */ +#define STATUS_CDATA 0x0800 /* Channel data check */ +#define STATUS_CCNTL 0x0400 /* Channel control check */ +#define STATUS_INTER 0x0200 /* Channel interface check */ +#define STATUS_CHAIN 0x0100 /* Channel chain check */ +#define STATUS_BUSY 0x0080 /* Device busy */ +#define STATUS_MOD 0x0040 /* Status modified */ +#define STATUS_CTLEND 0x0020 /* Controller end */ +#define STATUS_ATTN 0x0010 /* Device raised attention */ +#define STATUS_CEND 0x0008 /* Channel end */ +#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) */ /* ccw_flags bit assignment */ -#define FLAG_DC 0x8000 /* Data chain */ -#define FLAG_CC 0x4000 /* Chain command */ -#define FLAG_SLI 0x2000 /* Suppress length indicator */ -#define FLAG_SKIP 0x1000 /* Suppress memory write */ -#define FLAG_PCI 0x0800 /* Program controlled interrupt */ -#define FLAG_RTO 0x0400 /* Real-Time Option */ +#define FLAG_DC 0x8000 /* Data chain */ +#define FLAG_CC 0x4000 /* Chain command */ +#define FLAG_SLI 0x2000 /* Suppress length indicator */ +#define FLAG_SKIP 0x1000 /* Suppress memory write */ +#define FLAG_PCI 0x0800 /* Program controlled interrupt */ +#define FLAG_RTO 0x0400 /* Real-Time Option */ /* chan_byte bit assignments */ -#define BUFF_EMPTY 0x0 /* Buffer is empty */ -#define BUFF_BUSY 0x4 /* Channel program busy & empty */ -#define BUFF_NEXT 0xC /* 0x08|0x04 Continue Channel with next IOCB */ -#define BUFF_CHNEND 0x14 /* 0x10|0x04 Channel end */ -#define BUFF_DONE 0x20 /* 0x20 Channel ready for new command */ -#define BUFF_POST 0x24 /* 0x20|0x04 Waiting for status to be posted */ +#define BUFF_EMPTY 0x00 /* Buffer is empty */ +#define BUFF_BUSY 0x04 /* Channel program busy & empty */ +#define BUFF_NEXT 0x0C /* 0x08|0x04 Continue Channel with next IOCB */ +#define BUFF_CHNEND 0x14 /* 0x10|0x04 Channel end */ +#define BUFF_DONE 0x20 /* 0x20 Channel ready for new command */ +#define BUFF_POST 0x24 /* 0x20|0x04 Waiting for status to be posted */ /* chan_info bit flags */ -#define INFO_SIOCD 0x01 /* Initial IOCD from SIO if set */ -/* bits 0-6 unused */ +#define INFO_SIOCD 0x01 /* Initial IOCD from SIO if set */ +#define INFO_CEND 0x02 /* Channel End (chan_end) called if set */ +/* bits 0-5 unused */ -#define MAX_CHAN 128 /* max channels that can be defined */ -#define SUB_CHANS 256 /* max sub channels that can be defined */ +#define MAX_CHAN 128 /* max channels that can be defined */ +#define SUB_CHANS 256 /* max sub channels that can be defined */ #define MAX_DEV (MAX_CHAN * SUB_CHANS) /* max possible */ /* simulator devices configuration */ @@ -127,7 +128,7 @@ //#define NUM_UNITS_DISK 2 /* 2 disk drive devices */ #define NUM_UNITS_DISK 4 /* 4 disk drive devices */ #define NUM_DEVS_SCFI 1 /* 1 scfi (SCSI) disk drive units */ -#define NUM_UNITS_SCFI 1 /* 1 of 4 disk drive devices */ +#define NUM_UNITS_SCFI 2 /* 1 of 4 disk drive devices */ #define NUM_DEVS_SCSI 2 /* 2 scsi (MFP SCSI) scsi buss units */ #define NUM_UNITS_SCSI 2 /* 2 scsi disk drive devices */ #define NUM_DEVS_RTOM 1 /* 1 IOP RTOM channel */ @@ -135,7 +136,7 @@ #define NUM_DEVS_LPR 1 /* 1 IOP Line printer */ #define NUM_UNITS_LPR 1 /* 1 IOP Line printer device */ #define NUM_DEVS_ETHER 1 /* 1 Ethernet controller */ -#define NUM_UNITS_ETHER 1 /* 1 Ethernet controller */ +#define NUM_UNITS_ETHER 10 /* 10 Ethernet devices */ extern DEVICE cpu_dev; /* cpu device */ extern UNIT cpu_unit; /* the cpu unit */ @@ -203,7 +204,7 @@ extern DEVICE ec_dev; typedef struct chp { /* channel program values */ UNIT *unitptr; /* Back pointer to units structure */ - uint32 chan_inch_addr; /* Channel status dw in memory */ + uint32 chan_inch_addr; /* Channel status dw addr in memory */ uint32 chan_caw; /* Channel command address word */ uint32 ccw_addr; /* Channel address */ uint32 chan_buf; /* Channel data buffer */ @@ -219,31 +220,54 @@ typedef struct chp { /* Device information block */ #define FIFO_SIZE 256 /* fifo to hold 128 double words of status */ +extern int32 FIFO_Put(uint16 chsa, uint32 entry); +extern int32 FIFO_Get(uint16 chsa, uint32 *old); +extern int32 FIFO_Num(uint16 chsa); + +#define IOCLQ_SIZE 32 /* fifo to hold 32 iocl cmds */ + +typedef struct ioclq { + uint32 ioclq_fifo[IOCLQ_SIZE]; + int16 ioclq_in; + int16 ioclq_out; +} IOCLQ; + +extern int32 IOCLQ_Put(IOCLQ *qptr, uint32 entry); +extern int32 IOCLQ_Get(IOCLQ *qptr, uint32 *old); +extern int32 IOCLQ_Num(IOCLQ *qptr); + typedef struct dib { /* Pre start I/O operation */ uint16 (*pre_io)(UNIT *uptr, uint16 chan); /* Start a channel command SIO */ uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd); /* Halt I/O HIO */ - uint16 (*halt_io)(UNIT *uptr); + uint16 (*halt_io)(UNIT *uptr); /* Halt I/O */ + /* Test I/O STOPIO */ + uint16 (*stop_io)(UNIT *uptr); /* Stop I/O */ /* Test I/O TESTIO */ - uint16 (*test_io)(UNIT *uptr); + uint16 (*test_io)(UNIT *uptr); /* Test I/O */ + /* Reset Controller RSCTL */ + uint16 (*rsctl_io)(UNIT *uptr); /* Reset Controller */ + /* Reset Controller RSCHNL */ + uint16 (*rschnl_io)(UNIT *uptr); /* Reset Channel */ /* Post I/O processing */ - uint16 (*post_io)(UNIT *uptr); + uint16 (*iocl_io)(CHANP *chp, int32 tic_ok); /* IOCL processing */ /* Controller init */ void (*dev_ini)(UNIT *, t_bool); /* init function */ - UNIT *units; /* Pointer to units structure */ - CHANP *chan_prg; /* Pointer to channel program */ - uint8 numunits; /* number of units */ - uint8 mask; /* device mask */ - uint16 chan_addr; /* parent channel address */ - uint32 chan_fifo_in; /* fifo input index */ - uint32 chan_fifo_out; /* fifo output index */ + UNIT *units; /* Pointer to units structure */ + CHANP *chan_prg; /* Pointer to channel program */ + IOCLQ *ioclq_ptr; /* pointer to array of IOCLQ entries */ + uint8 numunits; /* number of units */ + uint8 mask; /* device mask */ + uint16 chan_addr; /* parent channel address */ + uint32 chan_fifo_in; /* fifo input index */ + uint32 chan_fifo_out; /* fifo output index */ uint32 chan_fifo[FIFO_SIZE]; /* interrupt status fifo for each channel */ } DIB; -extern DIB *dib_unit[MAX_DEV]; /* Pointer to Device info block */ -extern DIB *dib_chan[MAX_CHAN]; /* Pointer to channel mux dib */ +extern DIB *dib_unit[MAX_DEV]; /* Pointer to Device info block */ +extern DIB *dib_chan[MAX_CHAN]; /* Pointer to channel mux dib */ #define DEV_CHAN (1 << DEV_V_UF) /* Device is channel mux if set */ #define DEV_V_UF2 (DEV_V_UF+1) /* current usage */ @@ -324,7 +348,7 @@ extern DEBTAB dev_debug[]; #define MODEL_V6 6 /* V6 CPU */ #define MODEL_V9 7 /* V9 CPU */ -#define TMR_RTC 1 +#define TMR_RTC 1 /* RTC will not work if set to 0!! */ //#define TMR_RTC 0 #define HIST_MIN 64 @@ -348,7 +372,7 @@ extern DEBTAB dev_debug[]; #define BASEBIT 0x02000000 /* Base Mode PSD 1 bit 6 */ #define AEXPBIT 0x01000000 /* Arithmetic exception PSD 1 bit 7 */ -#define BLKEDBIT 0x00004000 /* Set blocked mode, PSD 2 bit 17 */ +#define SETBBIT 0x00004000 /* Set blocked mode, PSD 2 bit 17 */ #define RETBBIT 0x00008000 /* Retain current blocking state, PSD 2 bit 16 */ #define RETMBIT 0x00010000 /* Retain current maps, PSD 2 bit 15 */ #define MAPBIT 0x80000000 /* Map mode, PSD 2 bit 0 */ @@ -431,11 +455,10 @@ extern DEBTAB dev_debug[]; /* INTS int entry equates, entries accessed by interrupt level number */ #define INTS_NU1 0x80000000 /* Not used */ -#define INTS_NU2 0x40000000 /* Not used */ +#define INTS_REQ 0x40000000 /* Interrupt is requesting (use bit 1) */ #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 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 */ @@ -493,3 +516,5 @@ extern int32 RDYQ_Put(uint32 entry); extern int32 RDYQ_Get(uint32 *old); extern int32 RDYQ_Num(void); +#define get_chan(chsa) ((chsa>>8)&0x7f) /* get channel number from ch/sa */ + diff --git a/SEL32/sel32_disk.c b/SEL32/sel32_disk.c index 9a69fb8..2777795 100644 --- a/SEL32/sel32_disk.c +++ b/SEL32/sel32_disk.c @@ -36,17 +36,19 @@ /* Fill STAR value from cyl, trk, sec data */ #define CHS2STAR(c,h,s) (((c<<16) & LMASK)|((h<<8) & 0xff00)|(s & 0xff)) /* convert STAR value to number of sectors */ -#define STAR2SEC(star,spt,spc) ((star&0xff)+(((star>>8)&0xff)*spt)+((star>>16)*spc)) +#define STAR2SEC(star,spt,spc) ((star&0xff)+(((star>>8)&0xff)*spt)+(((star>>16)&0xffff)*spc)) /* convert STAR value to number of heads or tracks */ -#define STAR2TRK(star,tpc) ((star >> 16) * tpc + ((star >> 8) & 0x0ff)) +#define STAR2TRK(star,tpc) (((star>>16)&0xffff)*tpc+((star>>8)&0x0ff)) /* convert STAR value to number of cylinders */ -#define STAR2CYL(star) ((star >> 16) & RMASK) +#define STAR2CYL(star) ((star>>16)&RMASK) /* convert byte value to number of sectors mod sector size */ #define BYTES2SEC(bytes,ssize) (((bytes) + (ssize-1)) >> 10) /* get sectors per track for specified type */ #define SPT(type) (disk_type[type].spt) -/* get sectors per cylinderfor specified type */ +/* get sectors per cylinder for specified type */ #define SPC(type) (disk_type[type].spt*disk_type[type].nhds) +/* get number of tracks for specified type */ +#define TRK(type) (disk_type[type].cyl*disk_type[type].nhds) /* get number of cylinders for specified type */ #define CYL(type) (disk_type[type].cyl) /* get number of heads for specified type */ @@ -237,6 +239,7 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option #define DSK_XRM 0x5F /* Reset reserve track mode */ #define DSK_RAP 0xA2 /* Read angular positions */ #define DSK_TESS 0xAB /* Test STAR (subchannel target address register) */ +#define DSK_REC 0xB2 /* Read ECC correction mask */ #define DSK_ICH 0xFF /* Initialize Controller */ #define STAR u4 @@ -336,6 +339,9 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option /* Not Used up7 */ +static uint8 obuf[1024], bbuf[1024]; +static uint32 decc[512] = {0}; + /* disk definition structure */ struct disk_t { @@ -375,12 +381,14 @@ disk_type[] = {"8858", 24, 256, 16, 707, 711, 0x41}, /* 8 711 340M */ {"8887", 10, 256, 35, 819, 823, 0x41}, /* 9 823 340M */ {"8155", 40, 256, 16, 839, 843, 0x41}, /* 10 843 675M */ + {"8888", 16, 256, 43, 861, 865, 0x41}, /* 11 823 674M 8888 DP689 */ {NULL, 0} }; uint16 disk_preio(UNIT *uptr, uint16 chan) ; uint16 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; uint16 disk_haltio(UNIT *uptr); +uint16 disk_iocl(CHANP *chp, int32 tic_ok); t_stat disk_srv(UNIT *uptr); t_stat disk_boot(int32 unitnum, DEVICE *dptr); void disk_ini(UNIT *, t_bool); @@ -393,6 +401,10 @@ t_stat disk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *c const char *disk_description (DEVICE *dptr); extern uint32 inbusy; extern uint32 outbusy; +extern uint32 readfull(CHANP *chp, uint32 maddr, uint32 *word); +extern int irq_pend; /* go scan for pending int or I/O */ +extern UNIT itm_unit; +extern uint32 PSD[]; /* PSD */ /* channel program information */ CHANP dda_chp[NUM_UNITS_DISK] = {0}; @@ -421,11 +433,15 @@ DIB dda_dib = { disk_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ disk_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ disk_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ + NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + disk_iocl, /* uint16 (*iocl_io)(CHANP *chp, int32 tik_ok)) */ /* Process IOCL */ disk_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ dda_unit, /* UNIT* units */ /* Pointer to units structure */ dda_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NULL, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ NUM_UNITS_DISK, /* uint8 numunits */ /* number of units defined */ 0x0F, /* uint8 mask */ /* 8 devices - device mask */ 0x0800, /* uint16 chan_addr */ /* parent channel address */ @@ -462,12 +478,16 @@ UNIT ddb_unit[] = { DIB ddb_dib = { disk_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ disk_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - disk_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + disk_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ + NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + disk_iocl, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ disk_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ ddb_unit, /* UNIT* units */ /* Pointer to units structure */ ddb_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NULL, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ NUM_UNITS_DISK, /* uint8 numunits */ /* number of units defined */ 0x0F, /* uint8 mask */ /* 8 devices - device mask */ 0x0C00, /* uint16 chan_addr */ /* parent channel address */ @@ -486,18 +506,130 @@ DEVICE ddb_dev = { }; #endif +uint32 dmle_ecc32(uint8 *str, int32 len) +{ + int i, j; + uint32 ch, ecc = 0; + uint32 pmask = 0x7e11f439; /* SEL LE poly mask */ + + ecc = (~ecc & MASK32); /* initialize ecc to all bits (~0) */ + for (j=0; j>= 1; /* just shift out the bit */ + ecc ^= pmask; /* eor with poly mask */ + } else + ecc >>= 1; /* just shift out the bit */ + ch >>= 1; /* next bit */ + } + } + return (~ecc & MASK32); /* return ecc value */ +} + +uint32 dmbe_ecc32(uint8 *str, int32 len) +{ + int i, j; + uint32 ch, ecc = 0; + uint32 pmask = 0x9C2F887E; /* SEL BE poly mask */ + + ecc = (~ecc & MASK32); /* initialize ecc to all bits (~0) */ + for (j=0; jflags); + DEVICE *dptr = get_dev(uptr); + int len, i; + + /* zero the Track Label Buffer */ + for (i = 0; i < 30; i++) + buf[i] = 0; + + /* get file offset in sectors */ + tstart = STAR2SEC(star, SPT(type), SPC(type)); + /* convert sector number back to chs value to sync disk for diags */ + nstar = disksec2star(tstart, type); + + cyl = (nstar >> 16) & 0xffff; /* get the cylinder */ + trk = (nstar >> 8) & 0xff; /* get the track */ + sec = nstar & 0xff; /* save sec if any */ + + /* get track number */ + tstart = (cyl * HDS(type)) + trk; + sim_debug(DEBUG_EXP, dptr, "get_dmatrk RTL cyl %4x(%d) trk %x sec# %06x\n", + cyl, cyl, trk, tstart); + + /* calc offset in file to track label */ + tstart = CAPB(type) + (tstart * 30); + + /* file offset in bytes */ + sim_debug(DEBUG_EXP, dptr, "get_dmatrk RTL SEEK on seek to %06x\n", tstart); + + /* seek to the location where we will r/w track label */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ + sim_debug(DEBUG_EXP, dptr, "get_dmatrk RTL, Error on seek to %04x\n", tstart); + return 0; + } + + /* read in a track label from disk */ + if ((len=sim_fread(buf, 1, 30, uptr->fileref)) != 30) { + sim_debug(DEBUG_CMD, dptr, + "get_dmatrk Error %08x on read %04x of diskfile cyl %04x hds %02x sec 00\n", + len, 30, cyl, trk); + return 0; + } + + /* now write track label data to log */ + sim_debug(DEBUG_DETAIL, dptr, "Track %08x label", nstar); + for (i = 0; i < 30; i++) { + if (i == 16) + sim_debug(DEBUG_DETAIL, dptr, "\nTrack %08x label", nstar); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + if (buf[4] == 0x08) { /* see if defective track */ + uptr->SNS |= SNS_DEFTRK; /* flag as defective */ + tstart = nstar; /* save orginal track */ + /* get the alternate track address */ + cyl = (buf[22] << 8) | buf[23]; /* get the cylinder */ + trk = buf[24]; /* get the track */ +//bad sec = 0; /* sec is zero */ + nstar = CHS2STAR(cyl, trk, sec); + sim_debug(DEBUG_DETAIL, dptr, + "Track %08x is defective, new track %08x\n", tstart, nstar); + } + return nstar; /* return track address */ +} + /* start a disk operation */ uint16 disk_preio(UNIT *uptr, uint16 chan) { @@ -514,11 +646,262 @@ uint16 disk_preio(UNIT *uptr, uint16 chan) return SCPE_OK; /* good to go */ } +/* load in the IOCD and process the commands */ +/* return = 0 OK */ +/* return = 1 error, chan_status will have reason */ +uint16 disk_iocl(CHANP *chp, int32 tic_ok) +{ + uint32 word1 = 0; + uint32 word2 = 0; + int32 docmd = 0; +// DIB *dibp = dib_unit[chp->chan_dev];/* get the DIB pointer */ + UNIT *uptr = chp->unitptr; /* get the unit ptr */ + uint16 chan = get_chan(chp->chan_dev); /* our channel */ + uint16 devstat = 0; + DEVICE *dptr = get_dev(uptr); + + /* check for valid iocd address if 1st iocd */ + if (chp->chan_info & INFO_SIOCD) { /* see if 1st IOCD in channel prog */ + if (chp->chan_caw & 0x3) { /* must be word bounded */ + sim_debug(DEBUG_EXP, dptr, + "disk_iocl iocd bad address chan %02x caw %06x\n", + chan, chp->chan_caw); + chp->ccw_addr = chp->chan_caw; /* set the bad iocl address */ + chp->chan_status |= STATUS_PCHK; /* program check for invalid iocd addr */ + uptr->SNS |= SNS_INAD; /* invalid address status */ + return 1; /* error return */ + } + } +loop: + sim_debug(DEBUG_EXP, dptr, + "disk_iocl @%06x entry PSD %08x chan_status[%04x] %04x\n", + chp->chan_caw, PSD[0], chan, chp->chan_status); + + /* Abort if we have any errors */ + if (chp->chan_status & STATUS_ERROR) { /* check channel error status */ + sim_debug(DEBUG_EXP, dptr, + "disk_iocl ERROR1 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* return error */ + } + +#ifdef WHATISTHIS + /* Check if we have status modifier set */ + if (chp->chan_status & STATUS_MOD) { + chp->chan_caw += 8; /* move to next IOCD */ + chp->chan_status &= ~STATUS_MOD; /* turn off status modifier flag */ + } +#endif + + /* 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, dptr, + "disk_iocl ERROR2 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, dptr, + "disk_iocl ERROR3 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + + sim_debug(DEBUG_CMD, dptr, + "disk_iocl @%06x read ccw chan %02x IOCD wd 1 %08x wd 2 %08x\n", + chp->chan_caw, chan, word1, word2); + + chp->chan_caw = (chp->chan_caw & 0xfffffc) + 8; /* point to next IOCD */ + chp->ccw_cmd = (word1 >> 24) & 0xff; /* set command from IOCD wd 1 */ + + if (!MEM_ADDR_OK(word1 & MASK24)) { /* see if memory address invalid */ + chp->chan_status |= STATUS_PCHK; /* bad, program check */ + uptr->SNS |= SNS_INAD; /* invalid address status */ + sim_debug(DEBUG_EXP, dptr, + "disk_iocl bad IOCD1 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + + chp->ccw_count = word2 & 0xffff; /* get 16 bit byte count from IOCD WD 2 */ + + /* validate the commands for the disk */ + switch (chp->ccw_cmd) { + case DSK_WD: case DSK_RD: case DSK_INCH: case DSK_NOP: case DSK_ICH: + case DSK_SCK: case DSK_XEZ: case DSK_LMR: case DSK_WSL: case DSK_RSL: + case DSK_IHA: case DSK_WTL: case DSK_RTL: case DSK_RAP: case DSK_TESS: + case DSK_FNSK: case DSK_REL: case DSK_RES: case DSK_POR: case DSK_TIC: + case DSK_REC: + /* reset status to on cyl & ready */ +// uptr->SNS2 = (SNS_UNR|SNS_ONC|SNS_USEL); +// uptr->SNS2 = 0; + case DSK_SNS: + break; + default: + chp->chan_status |= STATUS_PCHK; /* program check for invalid cmd */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected */ + sim_debug(DEBUG_EXP, dptr, + "disk_iocl bad cmd chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + +//28chp->ccw_count = word2 & 0xffff; /* get 16 bit byte count from IOCD WD 2 */ + + if (chp->chan_info & INFO_SIOCD) { /* see if 1st IOCD in channel prog */ + /* 1st command can not be a TIC or NOP */ + if ((chp->ccw_cmd == DSK_NOP) || (chp->ccw_cmd == CMD_TIC)) { + chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ + sim_debug(DEBUG_EXP, dptr, + "disk_iocl TIC/NOP bad cmd chan_status[%04x] %04x\n", + chan, chp->chan_status); + return 1; /* error return */ + } + } + + /* TIC can't follow TIC or be first in command chain */ + /* diags send bad commands for testing. Use all of op */ + if (chp->ccw_cmd == CMD_TIC) { + if (tic_ok) { + if (((word1 & MASK24) == 0) || (word1 & 0x3)) { + sim_debug(DEBUG_EXP, dptr, + "disk_iocl tic cmd bad address chan %02x tic caw %06x IOCD wd 1 %08x\n", + chan, chp->chan_caw, word1); + chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ +// chp->chan_caw = word1; /* get new IOCD address */ + chp->chan_caw = word1 & MASK24; /* get new IOCD address */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ + uptr->SNS |= SNS_INAD; /* invalid address status */ + return 1; /* error return */ + } + tic_ok = 0; /* another tic not allowed */ + chp->chan_caw = word1 & MASK24; /* get new IOCD address */ + sim_debug(DEBUG_CMD, dptr, + "disk_iocl 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_caw = word1; /* get new IOCD address */ + chp->chan_caw = word1 & MASK24; /* get new IOCD address */ + chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ + if (((word1 & MASK24) == 0) || (word1 & 0x3)) + uptr->SNS |= SNS_INAD; /* invalid address status */ + sim_debug(DEBUG_EXP, dptr, + "disk_iocl TIC ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + + /* Check if we had data chaining in previous iocd */ + if ((chp->chan_info & INFO_SIOCD) || /* see if 1st IOCD in channel prog */ + ((chp->ccw_flags & FLAG_DC) == 0)) { /* last IOCD have DC set? */ + sim_debug(DEBUG_CMD, dptr, + "disk_iocl @%06x DO CMD 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 */ + chp->ccw_flags = (word2 >> 16) & 0xf000; /* get flags from bits 0-4 of WD 2 of IOCD */ + chp->chan_status = 0; /* clear status for next IOCD */ + /* make a 24 bit address */ + chp->ccw_addr = word1 & MASK24; /* set the data/seek address */ + + /* validate parts of IOCD2 that are reserved */ + if (word2 & 0x0fff0000) { /* bits 5-15 must be zero */ + chp->chan_status |= STATUS_PCHK; /* program check for invalid iocd */ + sim_debug(DEBUG_EXP, dptr, + "disk_iocl IOCD2 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + +#ifndef NOT_FOR_EVERYONE + /* DC can only be used with a read/write cmd */ + if (chp->ccw_flags & FLAG_DC) { + if ((chp->ccw_cmd != DSK_RD) && (chp->ccw_cmd != DSK_WD)) { + chp->chan_status |= STATUS_PCHK; /* program check for invalid DC */ + uptr->SNS |= SNS_CHER; /* chaining error */ + sim_debug(DEBUG_EXP, dptr, + "disk_iocl DC ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + } +#endif + + chp->chan_byte = BUFF_BUSY; /* busy & no bytes transferred yet */ + + sim_debug(DEBUG_XIO, dptr, + "disk_iocl @%06x read docmd %01x addr %06x count %04x chan %04x ccw_flags %04x\n", + chp->chan_caw, docmd, chp->ccw_addr, chp->ccw_count, chan, chp->ccw_flags); + + if (docmd) { /* see if we need to process a command */ + DIB *dibp = dib_unit[chp->chan_dev]; /* get the DIB pointer */ + + uptr = chp->unitptr; /* get the unit ptr */ + if (dibp == 0 || uptr == 0) { + chp->chan_status |= STATUS_PCHK; /* program check if it is */ + return 1; /* if none, error */ + } + + sim_debug(DEBUG_XIO, dptr, + "disk_iocl @%06x before start_cmd chan %04x status %04x count %04x SNS %08x\n", + chp->chan_caw, chan, chp->chan_status, chp->ccw_count, uptr->u5); + + /* call the device startcmd function to process the current command */ + /* just replace device status bits */ + devstat = dibp->start_cmd(uptr, chan, chp->ccw_cmd); + chp->chan_status = (chp->chan_status & 0xff00) | devstat; + chp->chan_info &= ~INFO_SIOCD; /* show not first IOCD in channel prog */ + + sim_debug(DEBUG_XIO, dptr, + "disk_iocl @%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_ERROR)) { + chp->chan_status |= STATUS_CEND; /* channel end status */ + chp->ccw_flags = 0; /* no flags */ + /* see if chan_end already called */ + if (chp->chan_byte == BUFF_NEXT) { + sim_debug(DEBUG_EXP, dptr, + "disk_iocl BUFF_NEXT ERROR chp %p chan_byte %04x\n", + chp, chp->chan_byte); + } else { + chp->chan_byte = BUFF_NEXT; /* have main pick us up */ + sim_debug(DEBUG_EXP, dptr, + "disk_iocl bad status chan %04x status %04x cmd %02x\n", + chan, chp->chan_status, chp->ccw_cmd); + RDYQ_Put(chp->chan_dev); /* queue us up */ + sim_debug(DEBUG_EXP, dptr, + "disk_iocl continue wait chsa %04x status %08x\n", + chp->chan_dev, chp->chan_status); + } + } else + + /* NOTE this code needed for MPX 1.X to run! */ + /* see if command completed */ + /* we have good status */ + if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { + uint16 chsa = GET_UADDR(uptr->u3); /* get channel & sub address */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ + sim_debug(DEBUG_XIO, dptr, + "disk_iocl @%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); + } + } + /* the device processor returned OK (0), so wait for I/O to complete */ + /* nothing happening, so return */ + sim_debug(DEBUG_XIO, dptr, + "disk_iocl @%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 */ +} + uint16 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uint16 chsa = GET_UADDR(uptr->CMD); DEVICE *dptr = get_dev(uptr); - int unit = (uptr - dptr->units); + int32 unit = (uptr - dptr->units); CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ sim_debug(DEBUG_CMD, dptr, @@ -537,7 +920,8 @@ uint16 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) return SNS_BSY; } uptr->SNS2 |= SNS_USEL; /* unit selected */ - sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD continue unit=%02x cmd %02x\n", unit, cmd); + sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD continue unit=%02x cmd %02x iocla %06x cnt %04x\n", + unit, cmd, chp->chan_caw, chp->ccw_count); /* Unit is online, so process a command */ switch (cmd) { @@ -555,7 +939,8 @@ uint16 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) // sim_activate(uptr, 40); /* start things off */ sim_activate(uptr, 30); /* start things off */ #else - sim_activate(uptr, 250); /* start things off */ +// sim_activate(uptr, 250); /* start things off */ + sim_activate(uptr, 500); /* start things off */ #endif return SCPE_OK; /* good to go */ break; @@ -582,6 +967,10 @@ uint16 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) case DSK_RTL: /* RTL 0x52 */ case DSK_RAP: /* 0xA2 Read angular positions */ case DSK_TESS: /* TESS 0xAB Test STAR */ + case DSK_FNSK: /* 0x0B Format for no skip */ + case DSK_REC: /* 0xB2 Read ECC correction mask */ + case DSK_RES: /* 0x23 Reserve */ + case DSK_REL: /* 0x33 Release */ uptr->SNS &= ~MASK24; /* clear data & leave mode */ uptr->SNS2 = (SNS_UNR|SNS_ONC|SNS_USEL);/* reset status to on cyl & ready */ case DSK_SNS: /* Sense 0x04 */ @@ -595,7 +984,8 @@ uint16 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) // sim_activate(uptr, 40); /* start things off */ sim_activate(uptr, 30); /* start things off */ #else - sim_activate(uptr, 250); /* start things off */ +// sim_activate(uptr, 250); /* start things off */ + sim_activate(uptr, 500); /* start things off */ #endif return SCPE_OK; /* good to go */ break; @@ -651,14 +1041,15 @@ t_stat disk_srv(UNIT *uptr) CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ int cmd = uptr->CMD & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); - uint32 tcyl=0, trk=0, cyl=0, sec=0; + uint32 tcyl=0, trk=0, cyl=0, sec=0, tempt=0; int unit = (uptr - dptr->units); int len = chp->ccw_count; - int i,j; - uint32 mema; /* memory address */ + int i,j,k; + uint32 mema, ecc, cecc; /* memory address / ecc */ uint8 ch; uint16 ssize = disk_type[type].ssiz * 4; /* disk sector size in bytes */ uint32 tstart; + uint8 lbuf[32]; uint8 buf[1024]; uint8 buf2[1024]; @@ -707,7 +1098,7 @@ t_stat disk_srv(UNIT *uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; - case DSK_INCH2: /* used 0xF0 for inch, just need int */ + case DSK_INCH2: /* use 0xF0 for inch, just need int */ len = chp->ccw_count; /* INCH command count */ mema = chp->ccw_addr; /* get inch or buffer addr */ sim_debug(DEBUG_CMD, dptr, @@ -759,8 +1150,8 @@ t_stat disk_srv(UNIT *uptr) } } /* now call set_inch() function to write and test inch buffer addresses */ - tstart = set_inch(uptr, mema); /* new address */ - if ((tstart == SCPE_MEM) || (tstart == SCPE_ARG)) { /* any error */ + i = set_inch(uptr, mema); /* new address */ + if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ /* we have error, bail out */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ; @@ -774,60 +1165,8 @@ t_stat disk_srv(UNIT *uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; - case DSK_WSL: /* WSL 0x31 make into NOP */ - uptr->CMD &= 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); - - sim_debug(DEBUG_DETAIL, dptr, "Sector %x label", uptr->CHS); - /* now read sector label data */ - len = chp->ccw_count; - for (i = 0; i < len; i++) { -//0906 for (i = 0; i < 30; i++) { - if (chan_read_byte(chsa, &buf[i])) { - if (chp->chan_status & STATUS_PCHK) /* test for memory error */ - uptr->SNS |= SNS_INAD; /* invalid address */ - /* we have write error, bail out */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; - break; - } - if ((i%16) == 0) - sim_debug(DEBUG_DETAIL, dptr, "\nSector %x label", uptr->CHS); - sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); - } - sim_debug(DEBUG_DETAIL, dptr, "\n"); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ - break; - - case DSK_WTL: /* WTL 0x51 make into NOP */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ - sim_debug(DEBUG_CMD, dptr, - "disk_srv cmd WTL chsa %04x count %04x completed\n", - chsa, chp->ccw_count); - - sim_debug(DEBUG_DETAIL, dptr, "Track %08x label", uptr->CHS); - /* now read track label data */ - for (i = 0; i < 30; i++) { - if (chan_read_byte(chsa, &buf[i])) { - if (chp->chan_status & STATUS_PCHK) /* test for memory error */ - uptr->SNS |= SNS_INAD; /* invalid address */ - /* we have read error, bail out */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; - break; - } - if (i == 16) - sim_debug(DEBUG_DETAIL, dptr, "\nTrack %x label", uptr->CHS); - sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); - } - sim_debug(DEBUG_DETAIL, dptr, "\n"); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ - break; - + case DSK_RES: /* 0x23 Reserve */ + case DSK_REL: /* 0x33 Release */ case DSK_NOP: /* NOP 0x03 */ /* diags want chan prog check and cmd reject if 1st cmd of IOCL */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ @@ -844,14 +1183,14 @@ t_stat disk_srv(UNIT *uptr) trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ sec = uptr->CHS & 0xff; /* set sec */ - ch = ((sec * 2) % SPT(type)) & 0x3f; /* get index cnt */ + ch = ((2*SPT(type))-1) & 0x3f; /* get index cnt */ uptr->SNS2 = (uptr->SNS2 & 0xc0ff) | ((((uint32)ch) & 0x3f) << 8); - sim_debug(DEBUG_DETAIL, dptr, + sim_debug(DEBUG_CMD, dptr, "disk_srv RAP %02x cyl %04x trk %02x sec %02x\n", ch, cyl&0xffff, trk, sec); if (chan_write_byte(chsa, &ch)) { /* put a byte to memory */ - sim_debug(DEBUG_DATA, dptr, + sim_debug(DEBUG_CMD, dptr, "DISK RAP %02x for addr /%04x/%02x/%02x\n", ch, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); if (chp->chan_status & STATUS_PCHK) { /* test for memory error */ @@ -872,7 +1211,7 @@ t_stat disk_srv(UNIT *uptr) trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ sec = 0; /* set sec to zero for this head */ - sim_debug(DEBUG_DETAIL, dptr, + sim_debug(DEBUG_CMD, dptr, "disk_srv IHA cyl %04x trk %02x sec %02x unit=%02x\n", cyl&0xffff, trk, sec, unit); @@ -897,22 +1236,111 @@ t_stat disk_srv(UNIT *uptr) /* set new STAR value using new values */ uptr->CHS = CHS2STAR(cyl, trk, sec); + /* get alternate track if this one is defective */ + tempt = get_dmatrk(uptr, uptr->CHS, lbuf); + /* file offset in bytes to std or alt track */ + tstart = STAR2SEC(tempt, SPT(type), SPC(type)) * SSB(type); - /* file offset in bytes */ - tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)) * SSB(type); + if ((tempt == 0) && (uptr->CHS != 0)) { + /* we have error */ + sim_debug(DEBUG_EXP, dptr, + "disk_srv IHA get_dmatrk return error tempt %06x tstart %06x CHS %08x\n", + tempt, tstart, uptr->CHS); + goto iha_error; + } /* just seek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ +iha_error: + uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_DADE; /* set error status */ uptr->SNS2 |= (SNS_SKER|SNS_SEND); sim_debug(DEBUG_EXP, dptr, "disk_srv IHA error on seek to %04x\n", tstart); chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; -// return SCPE_OK; } chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; + case DSK_REC: /* 0xB2 */ /* Read ECC correction code */ + sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD REC Read ECC\n"); + /* count must be 4, if not prog check */ + if (len != 4) { + sim_debug(DEBUG_CMD, dptr, + "disk_srv REC bad count unit=%02x count%04x CHS %08x\n", + unit, len, uptr->CHS); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK|STATUS_LENGTH); + break; + } + /* create offset and mask */ + ecc = dmle_ecc32(obuf, ssize); /* calc ecc for original sector */ + sim_debug(DEBUG_CMD, dptr, + "disk_srv DEC old obuf data %02x%02x%02x%02x %02x%02x%02x%02x\n", + obuf[1016], obuf[1017], obuf[1018], obuf[1019], + obuf[1020], obuf[1021], obuf[1022], obuf[1023]); + cecc = dmle_ecc32(bbuf, ssize); /* calc ecc for bad sector */ + sim_debug(DEBUG_CMD, dptr, + "disk_srv DEC bad bbuf data %02x%02x%02x%02x %02x%02x%02x%02x\n", + bbuf[1016], bbuf[1017], bbuf[1018], bbuf[1019], + bbuf[1020], bbuf[1021], bbuf[1022], bbuf[1023]); + mema = 0; + for (i=0, j=0; i>= 1; /* move mask right */ + } + tcyl = (k * 8) + sec; /* starting bit# */ + sim_debug(DEBUG_CMD, dptr, + "disk_srv REC sb# %04x byte# %04x mask %06x start %08x\n", + sec, k, mema, tcyl); + /* 16 bit sector offset and 9 of 16 bit mask */ + /* tcyl - fake 14 bit offset */ + /* mema - fake 9 bit mask */ + buf[0] = (tcyl & 0x3f00) >> 8; /* upper 6 bits */ + buf[1] = tcyl & 0xff; /* lower 8 bits */ + buf[2] = (mema & 0x100) >> 8; /* upper 1 bits */ + buf[3] = mema & 0xff; /* lower 8 bits */ + /* write the offset and mask data */ + for (i=0; i<4; i++) { + ch = buf[i]; /* get a char from buffer */ + if (chan_write_byte(chsa, &ch)) { /* put a byte to memory */ + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + sim_debug(DEBUG_CMD, dptr, + "disk_srv DEC read %04x bytes of %04x\n", + i, chp->ccw_count); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + return SCPE_OK; + } + } + sim_debug(DEBUG_CMD, dptr, + "disk_srv wrote DEC offset %04x mask %04x CHS %08x\n", + tcyl & 0x3fff, mema & 0x1ff, uptr->CHS); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; + case DSK_SNS: /* 0x04 */ /* Sense */ sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD sense\n"); @@ -997,7 +1425,7 @@ t_stat disk_srv(UNIT *uptr) chan_write_byte(chsa, &ch); // ch = 0x30; /* drive on cylinder and ready for now */ - uptr->SNS2 &= uptr->SNS2; /* clean out old status */ +// uptr->SNS2 &= ~uptr->SNS2; /* clean out old status */ uptr->SNS2 |= (SNS_ONC|SNS_UNR); /* on cylinder & ready */ ch = uptr->SNS2 & 0xff; /* drive on cylinder and ready for now */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv dsr unit=%02x 2 %02x\n", @@ -1005,7 +1433,8 @@ t_stat disk_srv(UNIT *uptr) chan_write_byte(chsa, &ch); } uptr->SNS &= 0xff000000; /* reset status */ - uptr->SNS2 = (SNS_UNR|SNS_ONC); /* reset status to on cyl & ready */ +//28 uptr->SNS2 = (SNS_UNR|SNS_ONC); /* reset status to on cyl & ready */ + uptr->SNS2 = 0; /* reset status */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; @@ -1039,7 +1468,8 @@ t_stat disk_srv(UNIT *uptr) // sim_activate(uptr, 20); /* start things off */ sim_activate(uptr, 15); /* start things off */ #else - sim_activate(uptr, 150); /* start things off */ +// sim_activate(uptr, 150); /* start things off */ + sim_activate(uptr, 300); /* start things off */ #endif break; } @@ -1059,8 +1489,9 @@ t_stat disk_srv(UNIT *uptr) if (len > 4) { sim_debug(DEBUG_CMD, dptr, - "disk_srv SEEK bad count unit=%02x count%04x\n", unit, len); + "disk_srv SEEK bad count unit %02x count %04x\n", unit, len); uptr->CMD &= LMASK; /* remove old status bits & cmd */ +//?? uptr->SNS2 |= SNS_SKER; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK|STATUS_LENGTH); break; } @@ -1096,14 +1527,15 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "disk_srv STAR unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); - sim_debug(DEBUG_DETAIL, dptr, - "disk_srv seek unit=%02x star %02x %02x %02x %02x\n", - unit, buf[0], buf[1], buf[2], buf[3]); +// sim_debug(DEBUG_DETAIL, dptr, +// "disk_srv seek unit=%02x star %02x %02x %02x %02x\n", +// unit, buf[0], buf[1], buf[2], buf[3]); /* save STAR (target sector) data in STAR */ uptr->STAR = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]); cyl = STAR2CYL(uptr->STAR); /* get the cylinder */ trk = buf[2]; /* get the track */ + sec = buf[3]; /* get sec */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv NEW SEEK cyl %04x trk %02x sec %02x unit=%02x\n", @@ -1122,7 +1554,7 @@ t_stat disk_srv(UNIT *uptr) uptr->SNS |= SNS_DADE; /* set error status */ uptr->SNS2 |= (SNS_SKER|SNS_SEND); - /* set new STAR value */ + /* set new STAR value, even if invalid */ uptr->CHS = CHS2STAR(cyl, trk, buf[3]); /* we have an error, tell user */ @@ -1130,16 +1562,35 @@ t_stat disk_srv(UNIT *uptr) break; } + /* set new STAR value using new values */ + tempt = CHS2STAR(cyl, trk, sec); + /* get alternate track if this one is defective */ + tempt = get_dmatrk(uptr, tempt, lbuf); + /* file offset in bytes to std or alt track */ + tstart = STAR2SEC(tempt, SPT(type), SPC(type)) * SSB(type); + + if ((tempt == 0) && (uptr->STAR != 0)) { + /* we have error */ + sim_debug(DEBUG_EXP, dptr, + "disk_srv SEEK get_dmatrk return error tempt %06x tstart %06x, STAR %08x\n", + tempt, tstart, uptr->STAR); + } + /* calc the new sector address of data */ /* calculate file position in bytes of requested sector */ /* file offset in bytes */ - tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type); +//29 tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type); /* set new STAR value using old cyl value */ - uptr->CHS = CHS2STAR(STAR2CYL(uptr->CHS), trk, buf[3]); +// uptr->CHS = CHS2STAR(STAR2CYL(uptr->CHS), trk, buf[3]); + + /* set new STAR value using new values */ +/*05*/ uptr->STAR = CHS2STAR(cyl, trk, sec); + /* file offset in bytes to std or alt track */ +/*05*/ tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type); sim_debug(DEBUG_DETAIL, dptr, - "disk_srv seek start %04x cyl %04x trk %02x sec %02x\n", - tstart, cyl, trk, buf[3]); + "disk_srv seek start %04x cyl %04x trk %02x sec %02x CHS %08x\n", + tstart, cyl, trk, buf[3], uptr->CHS); /* just seek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ @@ -1159,7 +1610,7 @@ t_stat disk_srv(UNIT *uptr) /* Do a fake seek to kill time */ uptr->CMD |= DSK_SEEKING; /* show we are seeking */ sim_debug(DEBUG_EXP, dptr, - "disk_srv seeking unit=%02x to /%04x/%02x/%02x from cyl %04x (%04x)\n", + "disk_srv seeking unit=%02x to %04x/%02x/%02x from cyl %04x (%04x)\n", unit, cyl, trk, buf[3], tcyl, diff); #ifdef FAST_FOR_UTX // sim_activate(uptr, 20); /* start us off */ @@ -1167,13 +1618,16 @@ t_stat disk_srv(UNIT *uptr) // sim_activate(uptr, 20); /* start things off */ sim_activate(uptr, 15); /* start things off */ #else - sim_activate(uptr, 200+diff); /* start us off */ +// sim_activate(uptr, 200+diff); /* start us off */ + sim_activate(uptr, 400+diff); /* start us off */ #endif } 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]); + /* set new STAR value */ + uptr->CHS = CHS2STAR(cyl, trk, buf[3]); uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); } @@ -1182,7 +1636,7 @@ t_stat disk_srv(UNIT *uptr) case DSK_XEZ: /* 0x37 */ /* Rezero & Read IPL record */ - sim_debug(DEBUG_CMD, dptr, "RD REZERO IPL unit=%02x seek 0\n", unit); + sim_debug(DEBUG_CMD, dptr, "XEZ REZERO IPL unit=%02x seek 0\n", unit); /* Do a seek to 0 */ uptr->STAR = 0; /* set STAR to 0, 0, 0 */ uptr->CHS = 0; /* set current CHS to 0, 0, 0 */ @@ -1305,7 +1759,40 @@ t_stat disk_srv(UNIT *uptr) // return SCPE_OK; break; - case DSK_RD: /* Read Data */ + case DSK_FNSK: /* 0x0B Format for no skip */ + /* buffer must be on halfword boundry if not STATUS_PCHK and SNS_CMDREJ status */ +// chp->chan_status |= STATUS_PCHK; /* program check for invalid cmd */ +// uptr->SNS |= SNS_CMDREJ; /* cmd rejected */ + /* byte count can not exceed 20160 for the track */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + sim_debug(DEBUG_CMD, dptr, + "DISK Format starting CMD %08x chsa %04x buffer %06x count %04x\n", + uptr->CMD, chsa, chp->ccw_addr, chp->ccw_count); + sim_debug(DEBUG_DETAIL, dptr, "Format %x label", uptr->CHS); + /* now read sector label data */ + len = chp->ccw_count; + for (i = 0; i < len; i++) { +//0906 for (i = 0; i < 30; i++) { + if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + /* we have write error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } + if ((i%16) == 0) + sim_debug(DEBUG_DETAIL, dptr, "\nFormat %x label", uptr->CHS); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); +// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); +// return SCPE_OK; + break; + + case DSK_RD: /* Read Data command 0x02 */ if ((uptr->CMD & DSK_READING) == 0) { /* see if we are reading data */ uptr->CMD |= DSK_READING; /* read from disk starting */ sim_debug(DEBUG_CMD, dptr, @@ -1318,8 +1805,42 @@ t_stat disk_srv(UNIT *uptr) tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); /* convert sector number back to chs value to sync disk for diags */ uptr->CHS = disksec2star(tstart, type); - /* file offset in bytes */ - tstart = tstart * SSB(type); + + /* get alternate track if this one is defective */ + tempt = get_dmatrk(uptr, uptr->CHS, lbuf); + /* file offset in bytes to std or alt track */ + tstart = STAR2SEC(tempt, SPT(type), SPC(type)) * SSB(type); + + if ((tempt == 0) && (uptr->STAR != 0)) { + /* we have error */ + sim_debug(DEBUG_EXP, dptr, + "disk_srv READ get_dmatrk return error tempt %06x tstart %06x\n", tempt, tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_DADE; /* set error status */ + uptr->SNS2 |= (SNS_SKER|SNS_SEND); + sim_debug(DEBUG_EXP, dptr, "disk_srv READ error on seek to %04x\n", tstart); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + uptr->SNS &= ~SNS_DEFTRK; /* remove defective flag */ + /* see if spare track */ + if (lbuf[4] & 0x20) { /* see if spare track */ + uptr->SNS |= SNS_DADE; /* disk addr error */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + sim_debug(DEBUG_EXP, dptr, + "disk_srv READ get_dmatrk return spare tempt %06x tstart %06x\n", tempt, tstart); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } + + /* see if reserved track */ + if (lbuf[4] & 0x10) { /* see if reserved track */ + uptr->SNS |= SNS_MOCK; /* mode check error */ + uptr->SNS |= SNS_RTAE; /* reserved track access error */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } /* just seek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ @@ -1347,6 +1868,11 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "disk_srv after READ chsa %04x buffer %06x count %04x\n", chsa, chp->ccw_addr, chp->ccw_count); + sim_debug(DEBUG_CMD, dptr, + "disk_srv after READ buffer %06x count %04x data %02x%02x%02x%02x %02x%02x%02x%02x\n", +// chp->ccw_addr, chp->ccw_count, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); + chp->ccw_addr, chp->ccw_count, buf[1016], buf[1017], buf[1018], buf[1019], + buf[1020], buf[1021], buf[1022], buf[1023]); uptr->CHS++; /* next sector number */ /* process the next sector of data */ @@ -1356,8 +1882,8 @@ t_stat disk_srv(UNIT *uptr) if (chan_write_byte(chsa, &ch)) { /* put a byte to memory */ if (chp->chan_status & STATUS_PCHK) /* test for memory error */ uptr->SNS |= SNS_INAD; /* invalid address */ - sim_debug(DEBUG_DATA, dptr, - "DISK Read %04x bytes leaving %04x from diskfile /%04x/%02x/%02x\n", + sim_debug(DEBUG_CMD, dptr, + "DISK Read %04x bytes leaving %04x from diskfile %04x/%02x/%02x\n", i, chp->ccw_count, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); uptr->CMD &= LMASK; /* remove old status bits & cmd */ @@ -1369,11 +1895,60 @@ t_stat disk_srv(UNIT *uptr) } } + /* get current sector offset */ + j = STAR2SEC(tempt, SPT(type), SPC(type)); /* current sector */ + i = ((CYL(type) - 3) * HDS(type)) * SPT(type); /* diag start */ sim_debug(DEBUG_CMD, dptr, - "DISK READ %04x bytes leaving %4x to be read to %06x from diskfile /%04x/%02x/%02x\n", - ssize, chp->ccw_count, chp->ccw_addr+4, + "disk_srv after READ j %04x i %04x j-i %04x CAP %06x DIAG %06x\n", + j, i, j-i, CAP(type), (((CYL(type) - 3) * HDS(type)) * SPT(type))); /* diag start */ + if (j >= i) { /* only do diag sectors */ + cecc = dmle_ecc32(buf, ssize); /* calc ecc for sector */ + sim_debug(DEBUG_CMD, dptr, + "ECC j %02x i %02x data calc Old %08x Cur %08x cyl %04x hds %02x sec %02x\n", + j, i, decc[j-i], cecc, STAR2CYL(tempt), ((tempt) >> 8)&0xff, (tempt&0xff)); + if ((decc[j-i] != 0) && (cecc != decc[j-i])) { /* test against old */ + /* checksum error */ + sim_debug(DEBUG_CMD, dptr, + "ECC j %02x i %02x data error Old %08x New %08x cyl %04x hds %02x sec %02x\n", + j, i, decc[j-i], cecc, STAR2CYL(tempt), ((tempt) >> 8)&0xff, (tempt&0xff)); + uptr->SNS |= SNS_ECCD; /* data ECC error */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_CHECK|STATUS_EXPT); + return SCPE_OK; + } + } + + /* see if this is a read ECC from diag */ + /* mode byte will be 0x08 and remaining count will be 4 */ + if ((uptr->SNS & SNS_DIAGMOD) && (chp->ccw_count == 4)) { + for (i=0; iCHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + /* set ECC value here */ + for (i=0; i<4; i++) { + ch = (ecc >> ((3-i)*8)) & 0xff; /* get a char from buffer */ + if (chan_write_byte(chsa, &ch)) { /* put a byte to memory */ + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + return SCPE_OK; + } + } + sim_debug(DEBUG_CMD, dptr, + "Read ECC %04x for diags 4 bytes to ECC REG cyl %04x hds %02x sec %02x\n", + ecc, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + } + + sim_debug(DEBUG_CMD, dptr, + "DISK READ %04x bytes leaving %4x to be read to %06x from diskfile %04x/%02x/%02x\n", + ssize, chp->ccw_count, chp->ccw_addr, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); +//// uptr->CHS++; /* next sector number */ /* get sector offset */ tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); @@ -1391,16 +1966,16 @@ t_stat disk_srv(UNIT *uptr) /* see if we are done reading data */ if (test_write_byte_end(chsa)) { - sim_debug(DEBUG_DATA, dptr, - "DISK Read complete for read from diskfile /%04x/%02x/%02x\n", + sim_debug(DEBUG_CMD, dptr, + "DISK Read complete for read from diskfile %04x/%02x/%02x\n", STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; } - sim_debug(DEBUG_DATA, dptr, - "DISK sector read complete, %x bytes to go from diskfile /%04x/%02x/%02x\n", + sim_debug(DEBUG_CMD, 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)); //J sim_activate(uptr, 10); /* wait to read next sector */ #ifdef FAST_FOR_UTX @@ -1409,20 +1984,29 @@ t_stat disk_srv(UNIT *uptr) // sim_activate(uptr, 20); /* start things off */ sim_activate(uptr, 15); /* start things off */ #else - sim_activate(uptr, 150); /* wait to read next sector */ +// sim_activate(uptr, 150); /* wait to read next sector */ + sim_activate(uptr, 300); /* wait to read next sector */ #endif break; } uptr->CMD &= LMASK; /* remove old status bits & cmd */ break; - case DSK_WD: /* Write Data */ + case DSK_WD: /* Write Data command 0x01 */ if ((uptr->CMD & DSK_WRITING) == 0) { /* see if we are writing data */ - uptr->CMD |= DSK_WRITING; /* write to disk starting */ sim_debug(DEBUG_CMD, dptr, "DISK WRITE starting unit=%02x CMD %08x write %04x from %06x to %03x/%02x/%02x\n", unit, uptr->CMD, chp->ccw_count, chp->ccw_addr, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + + if (uptr->SNS & 0xf0000000) { /* see if any mode bit 0-3 is set */ + uptr->SNS |= SNS_MOCK; /* mode check error */ + chp->chan_status |= STATUS_PCHK; /* channel prog check */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } + uptr->CMD |= DSK_WRITING; /* write to disk starting */ } if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */ /* get file offset in sectors */ @@ -1430,6 +2014,42 @@ t_stat disk_srv(UNIT *uptr) /* file offset in bytes */ tstart = tstart * SSB(type); + /* get alternate track if this one is defective */ + tempt = get_dmatrk(uptr, uptr->CHS, lbuf); + /* file offset in bytes to std or alt track */ + tstart = STAR2SEC(tempt, SPT(type), SPC(type)) * SSB(type); + + if ((tempt == 0) && (uptr->STAR != 0)) { + /* we have error */ + sim_debug(DEBUG_EXP, dptr, + "disk_srv WRITE get_dmatrk return error tempt %06x tstart %06x\n", tempt, tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_DADE; /* set error status */ + uptr->SNS2 |= (SNS_SKER|SNS_SEND); + sim_debug(DEBUG_EXP, dptr, "disk_srv WRITE error on seek to %04x\n", tstart); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + + uptr->SNS &= ~SNS_DEFTRK; /* remove defective flag */ + /* see if spare track */ +//was if (lbuf[4] & 0x30) { /* see if spare or reserved track */ + if (lbuf[4] & 0x20) { /* see if spare track */ + uptr->SNS |= SNS_DADE; /* disk addr error */ + chp->chan_status |= STATUS_PCHK; /* channel prog check */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } + /* see if reserved track */ + if (lbuf[4] & 0x10) { /* see if reserved track */ + uptr->SNS |= SNS_MOCK; /* mode check error */ + uptr->SNS |= SNS_RTAE; /* reserved track access error */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } + /* 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 WRITE, Error on seek to %04x\n", tstart); @@ -1477,19 +2097,74 @@ t_stat disk_srv(UNIT *uptr) break; } + sim_debug(DEBUG_CMD, dptr, + "disk_srv after WRITE buffer %06x count %04x data %02x%02x%02x%02x %02x%02x%02x%02x\n", +// chp->ccw_addr, chp->ccw_count, +// buf2[0], buf2[1], buf2[2], buf2[3], buf2[4], buf2[5], buf2[6], buf2[7]); + chp->ccw_addr, chp->ccw_count, buf2[1016], buf2[1017], buf2[1018], buf2[1019], + buf2[1020], buf2[1021], buf2[1022], buf2[1023]); + sim_debug(DEBUG_CMD, dptr, + "disk_srv after WRITE CAP %06x DIAG %06x\n", + CAP(type), (((CYL(type) - 3) * HDS(type)) * SPT(type))); /* diag start */ + + /* get current sector offset */ + j = STAR2SEC(tempt, SPT(type), SPC(type)); /* current sector */ + i = ((CYL(type) - 3) * HDS(type)) * SPT(type); /* diag start */ + sim_debug(DEBUG_CMD, dptr, + "disk_srv after WRITE j %04x i %04x j-i %04x CAP %06x DIAG %06x\n", + j, i, j-i, CAP(type), (((CYL(type) - 3) * HDS(type)) * SPT(type))); /* diag start */ + if (j >= i) { /* only do diag sectors */ + cecc = dmle_ecc32(buf2, ssize); /* calc ecc for sector */ + sim_debug(DEBUG_CMD, dptr, + "ECC j %02x i %02x data write Old %08x Cur %08x cyl %04x hds %02x sec %02x\n", + j, i, decc[j-i], cecc, STAR2CYL(tempt), ((tempt) >> 8)&0xff, (tempt&0xff)); + decc[j-i] = cecc; /* set new ecc */ + } + j = j-i; /* save index */ + + /* see if this is a write ECC from diag */ + /* mode byte will be 0x08 and remaining count will be 4 */ + if ((uptr->SNS & SNS_DIAGMOD) && (chp->ccw_count == 4)) { + for (i=0; iCHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + /* set ECC value here */ + for (i=0; i<4; i++) { + if (chan_read_byte(chsa, &ch)) {/* get a byte from memory */ + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + return SCPE_OK; + } + /* get an ECC byte */ + buf[i] = ch; /* put a char to buffer */ + ecc |= ((ch & 0xff) << ((3-i)*8)); + } + tcyl++; /* show we have no more data to write */ + sim_debug(DEBUG_CMD, dptr, + "Write decc[%04x] ECC=%08x from diags, calc ECC=%08x cyl %04x hds %02x sec %02x\n", + j, ecc, cecc, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + decc[j] = ecc; /* set new ecc from diag */ + } + + sim_debug(DEBUG_CMD, dptr, + "DISK WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x\n", + len, ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CHS++; /* next sector number */ if (tcyl != 0) { /* see if done with write command */ - sim_debug(DEBUG_DATA, dptr, + sim_debug(DEBUG_CMD, dptr, "DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; } - sim_debug(DEBUG_CMD, dptr, - "DISK WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x\n", - len, ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); - /* get sector offset */ tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); @@ -1497,13 +2172,24 @@ t_stat disk_srv(UNIT *uptr) if (tstart >= (uint32)CAP(type)) { /* EOM reached, abort */ sim_debug(DEBUG_CMD, dptr, - "DISK Write reached EOM for write to disk @ /%04x/%02x/%02x\n", + "DISK Write reached EOM for write to disk @ %04x/%02x/%02x\n", STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->CHS = 0; /* reset cylinder position */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } + + /* see if we are done reading data */ + if (test_write_byte_end(chsa)) { + sim_debug(DEBUG_CMD, dptr, + "DISK Write complete for read from diskfile %04x/%02x/%02x\n", + STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; + } + //J sim_activate(uptr, 10); /* keep writing */ #ifdef FAST_FOR_UTX // sim_activate(uptr, 15); /* keep writing */ @@ -1511,7 +2197,8 @@ t_stat disk_srv(UNIT *uptr) // sim_activate(uptr, 20); /* start things off */ sim_activate(uptr, 15); /* start things off */ #else - sim_activate(uptr, 150); /* wait to read next sector */ +// sim_activate(uptr, 150); /* wait to read next sector */ + sim_activate(uptr, 300); /* wait to read next sector */ #endif break; } @@ -1525,89 +2212,57 @@ t_stat disk_srv(UNIT *uptr) for (i = 0; i < 30; i++) buf[i] = 0; - len = chp->ccw_count; /* get number of sectors per track */ + len = chp->ccw_count; /* get number bytes to read */ + mema = uptr->CHS+(len/30); /* save address */ + + sim_debug(DEBUG_DETAIL, dptr, "before RSL Sector %x len %x\n", uptr->CHS, len); /* read a 30 byte track label for each sector on track */ /* for 16 sectors per track, that is 480 bytes */ /* for 20 sectors per track, that is 600 bytes */ for (j=0; jCHS, SPT(type), SPC(type)); /* convert sector number back to chs value to sync disk for diags */ uptr->CHS = disksec2star(tstart, type); - /* the dmap pointer is placed by the vendor or diag into the */ - /* track zero label in word 3 of the 30 byte label. */ - /* The disk address is the last track of the user area. The vendor */ - /* reserves the last cylinder, SEL diags reserve the next two, so the */ - /* addr is CYL-4/HDS-1/0 and is VDT. The UTX/MPX media table is on */ - /* previous track, so MDT = VDT-SPT is CYL-4/HDS-2/0 */ - /* The UTX flaw map is at DMAP = MDT-SPT CYL-4/HDS-3/0 */ - /* UTX media map is 1 track lower at UMAP=DMAP-SPT CYL-4/HDS-4/0 */ - /* The UTX media map is pointed to by sector label 1 */ - /* simulate pointers here, set wd[3] in label to UMAP */ + cyl = (uptr->CHS >> 16) & 0xffff; /* get the cylinder */ + trk = (uptr->CHS >> 8) & 0xff; /* get the track */ + sec = uptr->CHS & 0xff; /* get sec */ + seeksec = tstart; /* save sector number */ - /* VDT 249264 (819/18/0) 0x3cdb0 for 9346 - 823/19/16 */ - /* MDT 249248 (819/17/0) 0x3cda0 for 9346 - 823/19/16 */ - /* DMAP 249232 (819/16/0) 0x3cd90 for 9346 - 823/19/16 */ - /* UMAP 249216 (819/15/0) 0x3cd80 for 9346 - 823/19/16 */ + sim_debug(DEBUG_EXP, dptr, "disk_srv RSL cyl %04x trk %02x sec %02x sector# %06x\n", + cyl, trk, sec, seeksec); - sim_debug(DEBUG_CMD, dptr, - "disk_startcmd RSL STAR %08x disk geom %08x\n", - uptr->CHS, GEOM(type)); + /* seek sector label area after end of track label area */ + tstart = CAPB(type) + (CYL(type)*HDS(type)*30) + (tstart*30); - /* set buf data to current STAR values */ - cyl = STAR2CYL(uptr->CHS); /* get current cyl */ - buf[0] = (cyl >> 8) & 0xff; /* split cylinder */ - buf[1] = cyl & 0xff; - buf[2] = (uptr->CHS >> 8) & 0xff; /* get trk/head */ - buf[3] = uptr->CHS & 0xff; /* get sec */ - buf[4] = 0x80; /* set lflg1 to show good sector */ + /* file offset in bytes to sector label */ + sim_debug(DEBUG_EXP, dptr, "disk_srv RSL SEEK on seek to %08x\n", tstart); - sim_debug(DEBUG_DETAIL, dptr, - "disk_srv RSL unit=%02x star %02x %02x %02x %02x\n", - unit, buf[0], buf[1], buf[2], buf[3]); - - /* get sector address of UMAP */ - /* UMAP 249216 (819/15/0) 0x3cd80 for 9346 - 823/19/16 */ - tstart = ((CYL(type)-4) * SPC(type)) + - ((HDS(type)-4) * SPT(type)); - - sim_debug(DEBUG_CMD, dptr, - "disk_srv SL1 RSL sector %d %x star %02x %02x %02x %02x\n", - tstart, tstart, buf[0], buf[1], buf[2], buf[3]); - - /* on UDP & DPII DMAP is in wd 3 on label 0 */ - /* on UDP & DPII UMAP is in wd 4 on label 0 */ - /* UMAP 249216 (819/15/0) 0x3cd80 for 9346 - 823/19/16 */ - - /* the address must be physical for UDP */ - /* store into sec 1 label */ - /* diags want these values to be zero for all others*/ - if (uptr->CHS == 1) { /* test for sec 1, trk 0, cyl 0 */ - buf[16] = (tstart >> 24) & 0xff; /* UMAP pointer */ - buf[17] = (tstart >> 16) & 0xff; - buf[18] = (tstart >> 8) & 0xff; - buf[19] = (tstart) & 0xff; - } else { - buf[16] = 0; /* UMAP pointer */ - buf[17] = 0; - buf[18] = 0; - buf[19] = 0; + /* seek to the location where we will read sector label */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { + sim_debug(DEBUG_CMD, dptr, + "Error seeking sector label area at sect %06x offset %08x\n", + seeksec, tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; } - /* the tech doc shows the cyl/trk/sec data is in the first 4 bytes */ - /* of the track label, BUT it is really in the configuration data */ - /* area are too. That is where UTX looks. Byte 27 is sectors/track */ - /* and byte 28 is number of heads. Byte 25 is copy of byte 27. */ - buf[25] = disk_type[type].spt & 0xff; /* sect per track 35 */ - /* The UDP/DPII controllers do not use these bits, so UTX keys */ - /* on these bits to determine type of controller. Bit 31 is set */ - /* for a HSDP and not set for the UDP/DPII */ - buf[26] = disk_type[type].type & 0xfc; /* sector size bits not used in UDP/DPII */ - buf[27] = disk_type[type].spt & 0xff; /* sec per track 35 */ - buf[28] = disk_type[type].nhds & 0xff; /* num heads 10 */ + /* read in a sector label from disk */ + if (sim_fread(buf, 1, 30, uptr->fileref) != 30) { + sim_debug(DEBUG_CMD, dptr, + "Error %08x on read %04x of diskfile cyl %04x hds %02x sec %02x\n", + len, 30, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } sim_debug(DEBUG_DETAIL, dptr, "Sector %x label", uptr->CHS); /* now write sector label data */ @@ -1615,7 +2270,9 @@ t_stat disk_srv(UNIT *uptr) if (chan_write_byte(chsa, &buf[i])) { /* we have write error, bail out */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ + sim_debug(DEBUG_DETAIL, dptr, "\n"); chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; break; } if (i == 16) @@ -1625,121 +2282,195 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_DETAIL, dptr, "\n"); /* leave STAR "unnormalized" for diags */ - uptr->CHS++; /* bump to next track */ + uptr->CHS++; /* bump to next sector */ + if ((uptr->CHS & 0xff) == SPC(type)) + break; /* stop at last sector */ len -= 30; /* count 1 sector label size */ if (len > 0) continue; break; /* done */ } + uptr->CHS = mema; /* restore address */ + + sim_debug(DEBUG_DETAIL, dptr, "after RSL Sector %x len %x\n", uptr->CHS, chp->ccw_count); + /* command done */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ - sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd RSL done chsa %04x count %04x completed\n", + sim_debug(DEBUG_CMD, dptr, "disk_srv cmd RSL done chsa %04x count %04x completed\n", + chsa, chp->ccw_count); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case DSK_WSL: /* WSL 0x31 write sector labels */ + /* Write sector label to disk */ + /* write 30 bytes, b0-b1=cyl, b1=trk, b2=sec */ + len = chp->ccw_count; /* get number bytes to read */ +// mema = uptr->CHS+(len/30); /* save address */ + mema = uptr->CHS; /* save address */ + + sim_debug(DEBUG_DETAIL, dptr, "before WSL Sector %x len %x\n", uptr->CHS, len); + + /* read a 30 byte sector label for each sector on track */ + /* for 16 sectors per track, that is 480 bytes */ + /* for 20 sectors per track, that is 600 bytes */ + for (j=0; jCHS); + /* now read sector label data */ + for (i = 0; i < 30; i++) { + if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + /* we have read error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } + if ((i%16) == 0) + sim_debug(DEBUG_DETAIL, dptr, "\nSector %x label", uptr->CHS); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + /* see if user trying to set invalid bit pattern */ + if ((buf[4] & 0x48) == 0x48) { /* see if setting defective alternate trk */ + uptr->SNS |= SNS_DSKFERR; /* disk formating error */ + uptr->CHS = mema; /* restore address */ + chp->ccw_count = len; /* restore number bytes to read */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); +// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_LENGTH); + return SCPE_OK; + break; + } + + /* get file offset in sectors */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + + /* convert sector number back to chs value to sync disk for diags */ + uptr->CHS = disksec2star(tstart, type); + + cyl = (uptr->CHS >> 16) & 0xffff; /* get the cylinder */ + trk = (uptr->CHS >> 8) & 0xff; /* get the track */ + sec = uptr->CHS & 0xff; /* get sec */ + seeksec = tstart; /* save sector number */ + + sim_debug(DEBUG_EXP, dptr, "disk_srv WSL cyl %04x trk %02x sec %02x sector# %06x\n", + cyl, trk, sec, seeksec); + + /* seek sector label area after end of track label area */ + tstart = CAPB(type) + (CYL(type)*HDS(type)*30) + (tstart*30); + + /* file offset in bytes to sector label */ + sim_debug(DEBUG_EXP, dptr, "disk_srv WSL SEEK on seek to %08x\n", tstart); + + /* seek to the location where we will write sector label */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { + sim_debug(DEBUG_CMD, dptr, + "Error seeking sector label area at sect %06x offset %08x\n", + seeksec, tstart); + uptr->CHS = mema; /* restore address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } + + /* write sector label to disk */ + if (sim_fwrite(buf, 1, 30, uptr->fileref) != 30) { + sim_debug(DEBUG_CMD, dptr, + "Error %08x on write %04x of diskfile cyl %04x hds %02x sec %02x\n", + len, 30, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + uptr->CHS = mema; /* restore address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } + + /* leave STAR "unnormalized" for diags */ + uptr->CHS++; /* bump to next sector */ + if ((uptr->CHS & 0xff) == SPC(type)) + break; /* stop at last sector */ + len -= 30; /* count 1 sector label size */ + if (len > 0) + continue; + break; /* done */ + } + + uptr->CHS = mema; /* restore address */ + + sim_debug(DEBUG_DETAIL, dptr, "after WSL Sector %x len %x\n", uptr->CHS, chp->ccw_count); + + /* command done */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + sim_debug(DEBUG_CMD, dptr, "disk_srv cmd RSL done chsa %04x count %04x completed\n", chsa, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; case DSK_RTL: /* RTL 0x52 */ /* Read track zero to get disk geometry */ - /* write 30 bytes, b0-b1=cyl, b1=trk, b2=sec */ + /* read 30 bytes, b0-b1=cyl, b1=trk, b2=sec */ /* zero the Track Label Buffer */ for (i = 0; i < 30; i++) buf[i] = 0; + uptr->CHS &= 0xffffff00; /* zero sector for trk read */ + mema = uptr->CHS; /* get file offset in sectors */ - tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + tstart = STAR2SEC(mema, SPT(type), SPC(type)); + /* convert sector number back to chs value to sync disk for diags */ - uptr->CHS = disksec2star(tstart, type); + mema = disksec2star(tstart, type); + cyl = (mema >> 16) & 0xffff; /* get the cylinder */ + trk = (mema >> 8) & 0xff; /* get the track */ - /* set buf data to current CHS values */ - if (uptr->CHS == 0) { /* write last address on trk 0 */ - cyl = CYL(type)-1; /* lcyl cyl upper 8 bits */ - trk = HDS(type)-1; /* ltkn trk */ - sec = SPT(type)-1; /* lid sector ID */ - } else { - /* write current address on other tracks */ - cyl = (uptr->CHS >> 16) & 0xffff; /* get the cylinder */ - trk = (uptr->CHS >> 8) & 0xff; /* get the track */ - sec = (uptr->CHS) & 0xff; /* get the sector */ + /* get track number */ + tstart = (cyl * HDS(type)) + trk; + sim_debug(DEBUG_EXP, dptr, "disk_srv RTL cyl %4x(%d) trk %x sec# %06x\n", + cyl, cyl, trk, tstart); + + /* calc offset in file to track label */ + tstart = CAPB(type) + (tstart * 30); + + /* file offset in bytes */ + sim_debug(DEBUG_EXP, dptr, "disk_srv RTL SEEK on seek to %06x\n", tstart); + + /* seek to the location where we will r/w track label */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ + sim_debug(DEBUG_EXP, dptr, "disk_srv RTL, Error on seek to %04x\n", tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; } - sim_debug(DEBUG_CMD, dptr, "disk_srv RTL STAR %08x disk geom %08x\n", - uptr->CHS, GEOM(type)); - - /* set buf data to current STAR values */ - buf[0] = (cyl >> 8) & 0xff; /* lcyl cyl upper 8 bits */ - buf[1] = cyl & 0xff; /* lcyl cyl lower 8 bits */ - buf[2] = trk & 0xff; /* ltkn trk */ -// buf[3] = sec & 0xff; /* lid sector ID */ - buf[3] = 0xff; /* lid show as track label */ - buf[4] = 0x80; /* show good sector */ - - sim_debug(DEBUG_DETAIL, dptr, - "disk_srv RTL unit=%02x star %02x %02x %02x %02x\n", - unit, buf[0], buf[1], buf[2], buf[3]); - - /* the dmap pointer is placed by the vendor or diag into the */ - /* track zero label in word 3 of the 30 byte label. */ - /* The disk address is the last track of the user area. The vendor */ - /* reserves the last cylinder, SEL diags reserve the next two, so the */ - /* addr is CYL-4/HDS-1/0 and is VDT. The UTX/MPX media table is on */ - /* previous track, so MDT = VDT-SPT is CYL-4/HDS-2/0 */ - /* The UTX flaw map is at DMAP = MDT-SPT CYL-4/HDS-3/0 */ - /* UTX media map is 1 track lower at UMAP=FMAP-SPT CYL-4/HDS-4/0 */ - /* The UTX media map is pointed to by sector label 1 */ - /* simulate pointers here, set wd[3] in label to VDT */ - - /* get sector address of media defect table */ - /* VDT 249264 (819/18/0) 0x3cdb0 for 9346 - 823/19/16 */ - /* MDT 249248 (819/17/0) 0x3cda0 for 9346 - 823/19/16 Trk 0 */ - /* DMAP 249232 (819/16/0) 0x3cd90 for 9346 - 823/19/16 */ - /* UMAP 249216 (819/15/0) 0x3cd80 for 9346 - 823/19/16 Trk 0/Sec 1 */ - - tstart = (CYL(type)-4) * SPC(type) + (HDS(type)-2) * SPT(type); - - cyl = disk_type[type].cyl-1; /* last cyl */ - trk = disk_type[type].nhds-1; /* last head number */ - - sim_debug(DEBUG_CMD, dptr, - "disk_srv RTL STAR %04x/%02x/%02x Dmap pointer 0x%08x %d\n", - cyl-3, trk-1, 0, tstart, tstart); - sim_debug(DEBUG_CMD, dptr, - "disk_srv TRK0 RTL sector %d %x star %02x %02x %02x %02x\n", - tstart, tstart, buf[0], buf[1], buf[2], buf[3]); - - if (uptr->CHS == 0) { /* only write dmap address in trk 0 */ - /* output last sector address of disk */ - buf[12] = (tstart >> 24) & 0xff; /* lumapp DMAP pointer */ - buf[13] = (tstart >> 16) & 0xff; - buf[14] = (tstart >> 8) & 0xff; - buf[15] = (tstart) & 0xff; + /* read in a track label from disk */ + if ((len=sim_fread(buf, 1, 30, uptr->fileref)) != 30) { + sim_debug(DEBUG_CMD, dptr, + "Error %08x on read %04x of diskfile cyl %04x hds %02x sec %02x\n", + len, 30, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; } - /* get sector address of umap table */ - /* UMAP 249216 (819/15/0) 0x3cd80 for 9346 - 823/19/16 */ - tstart -= (2*SPT(type)); /* calc umap address */ - - /* the address must be physical for UDP/DPII */ - if (uptr->CHS == 0) { /* only write umap address on trk 0 */ - buf[16] = (tstart >> 24) & 0xff; /* ldeallp UMAP */ - buf[17] = (tstart >> 16) & 0xff; - buf[18] = (tstart >> 8) & 0xff; - buf[19] = (tstart) & 0xff; + if (buf[4] == 0x08) { /* see if defective track */ + uptr->SNS |= SNS_DEFTRK; /* flag as defective */ + sim_debug(DEBUG_DETAIL, dptr, "Track %08x is defective\n", uptr->CHS); } - /* the tech doc shows the cyl/trk/sec data is in the first 4 bytes */ - /* of the track label, BUT it is really in the configuration data */ - /* area too. That is where UTX looks. Byte 27 is sectors/track */ - /* and byte 28 is number of heads. Byte 26 is mode. */ - /* Byte 25 is copy of byte 27. */ - buf[25] = disk_type[type].spt & 0xff; - buf[26] = disk_type[type].type & 0xfc; /* zero bits 6 & 7 in type byte */ - buf[27] = disk_type[type].spt & 0xff; - buf[28] = disk_type[type].nhds & 0xff; + if (buf[4] == 0x40) { /* see if alternate track */ + uptr->SNS |= SNS_AATT; /* flag as alternate */ + sim_debug(DEBUG_DETAIL, dptr, "Track %08x is alternate\n", uptr->CHS); + } - sim_debug(DEBUG_DETAIL, dptr, "Track %x label", uptr->CHS); - /* now write track label data */ + /* now write track label data to memory */ + sim_debug(DEBUG_DETAIL, dptr, "Track %08x label", uptr->CHS); for (i = 0; i < 30; i++) { if (chan_write_byte(chsa, &buf[i])) { /* we have write error, bail out */ @@ -1748,14 +2479,16 @@ t_stat disk_srv(UNIT *uptr) break; } if (i == 16) - sim_debug(DEBUG_DETAIL, dptr, "\nTrack %x label", uptr->CHS); + sim_debug(DEBUG_DETAIL, dptr, "\nTrack %08x label", uptr->CHS); sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); } sim_debug(DEBUG_DETAIL, dptr, "\n"); +#ifdef NONO /* leave STAR "unnormalized" for diags */ if (uptr->CHS != 0) /* only incr address if not trk 0 */ uptr->CHS += 0x10; /* bump to next track */ +#endif /* command done */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ @@ -1764,6 +2497,105 @@ t_stat disk_srv(UNIT *uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; + case DSK_WTL: /* WTL 0x51 */ + /* Write track zero to set disk geometry */ + /* write 30 bytes, b0-b1=cyl, b1=trk, b2=sec */ + + sim_debug(DEBUG_EXP, dptr, "disk_srv WTL start cnt %04x CHS %08x\n", + chp->ccw_count, uptr->CHS); + +#ifdef NONO + /* see if user trying to write other than 30 bytes */ + if (chp->ccw_count != 30 && chp->ccw_count != 34) { /* see if wrong byte count */ +// uptr->SNS |= SNS_DEFTRK; /* disk formating error */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } +#endif + + /* get file offset in sectors */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* convert sector number back to chs value to sync disk for diags */ + uptr->CHS = disksec2star(tstart, type); + uptr->CHS &= 0xffffff00; /* zero sector for trk read */ + mema = uptr->CHS; + + cyl = (uptr->CHS >> 16) & 0xffff; /* get the cylinder */ + trk = (uptr->CHS >> 8) & 0xff; /* get the track */ + + /* get track number */ + tstart = (cyl * HDS(type)) + trk; + sim_debug(DEBUG_EXP, dptr, "disk_srv WTL cyl %4x trk %x track# %06x CHS %08x\n", + cyl, trk, tstart, uptr->CHS); + + /* calc offset in file to track label */ + tstart = CAPB(type) + (tstart * 30); + + /* file offset in bytes */ + sim_debug(DEBUG_EXP, dptr, "disk_srv WTL SEEK on seek to %06x\n", tstart); + + /* get alternate track info */ + tempt = get_dmatrk(uptr, uptr->CHS, lbuf); + uptr->SNS &= ~SNS_DEFTRK; /* remove any defective track flag */ + /* file offset in bytes to std or alt track */ +//// tstart = STAR2SEC(tempt, SPT(type), SPC(type)) * SSB(type); + + /* seek to the location where we will write track label */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ + sim_debug(DEBUG_EXP, dptr, "disk_srv WTL, Error on seek to %04x\n", tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + } + + sim_debug(DEBUG_DETAIL, dptr, "Track %08x label", uptr->CHS); + /* now read track label data from memory */ + for (i = 0; i < 30; i++) { + if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + /* we have read error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } + if (i == 16) + sim_debug(DEBUG_DETAIL, dptr, "\nTrack %08x label", uptr->CHS); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + /* see if user trying to set invalid bit pattern */ + if ((buf[4] & 0x48) == 0x48) { /* see if setting defective alternate trk */ + uptr->SNS |= SNS_DSKFERR; /* disk formating error */ + uptr->CHS = mema; /* restore address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } + + /* write out a track label to disk */ + if ((len=sim_fwrite(buf, 1, 30, uptr->fileref)) != 30) { + sim_debug(DEBUG_CMD, dptr, + "Error %08x on write %04x of diskfile cyl %04x hds %02x sec %02x\n", + len, 30, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + uptr->CHS = mema; /* restore address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + + uptr->CHS = mema; /* restore address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + sim_debug(DEBUG_CMD, dptr, + "disk_srv cmd WTL chsa %04x count %04x completed CHS %08x\n", + chsa, chp->ccw_count, uptr->CHS); + + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + default: sim_debug(DEBUG_CMD, dptr, "invalid command %02x unit %02x\n", cmd, unit); uptr->SNS |= SNS_CMDREJ; @@ -1800,24 +2632,217 @@ t_stat disk_reset(DEVICE *dptr) return SCPE_OK; } +/* add track and sector labels to disk */ +int disk_label(UNIT *uptr) { + int type = GET_TYPE(uptr->flags); + DEVICE *dptr = get_dev(uptr); + uint32 trk, cyl, sec; + uint32 ssize = SSB(type); /* disk sector size in bytes */ + uint32 tsize = SPT(type); /* get track size in sectors */ + uint32 tot_tracks = TRK(type); /* total tracks on disk */ + uint32 tot_sectors = CAP(type); /* total number of sectors on disk */ + uint32 cap = CAP(type); /* disk capacity in sectors */ + uint32 CHS; /* cyl, hds, sec format */ + uint8 label[34]; /* track/sector label */ + int32 i, j; + /* get sector address of utx diag map (DMAP) track 0 pointer */ + /* put data = 0xf0000000 + (cyl-1), 0x8a000000 + daddr, */ + /* 0x9a000000 + (cyl-1), 0xf4000008 */ + int32 daddr = (CYL(type)-4) * SPC(type) + (HDS(type)-2) * SPT(type); + /* get sector address of utx flaw map sec 1 pointer */ + /* use this address for sec 1 label pointer */ + int32 uaddr = (CYL(type)-4) * SPC(type) + (HDS(type)-4) * SPT(type); + + /* write 30 byte track labels for all tracks on disk */ + /* tot_tracks entries will be created starting at end of disk */ + /* seek first sector after end of disk data */ + if ((sim_fseek(uptr->fileref, CAPB(type), SEEK_SET)) != 0) { + sim_debug(DEBUG_CMD, dptr, + "Error seeking track label area at sect %06x offset %06x\n", + CAP(type), CAPB(type)); + return 1; + } + /* write track labels */ + for (i=0; i> 16) & 0xffff; /* get the cylinder */ + trk = (CHS >> 8) & 0xff; /* get the track */ + sec = (CHS) & 0xff; /* get the sector */ + } + + sim_debug(DEBUG_CMD, dptr, "disk_format WTL STAR %08x disk geom %08x\n", + CHS, GEOM(type)); + + /* set buf data to current STAR values */ + label[0] = (cyl >> 8) & 0xff; /* lcyl cyl upper 8 bits */ + label[1] = cyl & 0xff; /* lcyl cyl lower 8 bits */ + label[2] = trk & 0xff; /* ltkn trk */ + label[3] = sec & 0xff; /* lid sector ID */ + label[4] = 0x80; /* show good sector */ + if (i == (tot_tracks-1)) { /* last track? */ + label[3] = 0xff; /* lid show as last track label */ + label[4] |= 0x04; /* set last track flag */ + } + + sim_debug(DEBUG_DETAIL, dptr, + "disk_format RTL star %02x %02x %02x %02x\n", + label[0], label[1], label[2], label[3]); + + /* daddr has dmap value for track zero label */ + if (CHS == 0) { /* only write dmap address in trk 0 */ + /* output last sector address of disk */ + label[12] = (daddr >> 24) & 0xff; /* lumapp DMAP pointer */ + label[13] = (daddr >> 16) & 0xff; + label[14] = (daddr >> 8) & 0xff; + label[15] = (daddr) & 0xff; + } + + /* uaddr has umap value for track zero label */ + if (CHS == 0) { /* only write dmap address in trk 0 */ + /* output last sector address of disk */ + label[16] = (uaddr >> 24) & 0xff; /* lumapp DMAP pointer */ + label[17] = (uaddr >> 16) & 0xff; + label[18] = (uaddr >> 8) & 0xff; + label[19] = (uaddr) & 0xff; + } + + /* the tech doc shows the cyl/trk/sec data is in the first 4 bytes */ + /* of the track label, BUT it is really in the configuration data */ + /* area too. Byte 27 is sectors/track and byte 28 is number of heads. */ + /* Byte 26 is mode. Byte 25 is copy of byte 27. */ + label[25] = SPT(type) & 0xff; + label[26] = disk_type[type].type & 0xfc; /* zero bits 6 & 7 in type byte */ + label[27] = SPT(type) & 0xff; + label[28] = HDS(type) & 0xff; + + if ((sim_fwrite((char *)&label, sizeof(uint8), 30, uptr->fileref)) != 30) { + sim_debug(DEBUG_CMD, dptr, + "Error writing track label to sect %06x offset %06x\n", + cap+(i*tsize), cap*ssize+(i*tsize*ssize)); + return 1; + } + } + + /* write 30 byte sector labels for all sectors on disk */ + /* tot_sector entries will be created starting at end of disk */ + /* plus the track label area size. seek first sector after end */ + /* of disk track label area */ + if ((sim_fseek(uptr->fileref, CAPB(type)+TRK(type)*30, SEEK_SET)) != 0) { + sim_debug(DEBUG_CMD, dptr, + "Error seeking sector label area at sect %06x offset %06x\n", + CAP(type)+TRK(type), CAPB(type)+TRK(type)*30); + return 1; + } + + /* zero the Sector Label Buffer */ + for (j = 0; j < 30; j++) + label[j] = 0; + + /* convert sector number to CHS value for label */ + /* write sector labels */ + for (i=0; i> 16) & 0xffff; /* get the cylinder */ + trk = (CHS >> 8) & 0xff; /* get the track */ + sec = (CHS) & 0xff; /* get the sector */ + + sim_debug(DEBUG_CMD, dptr, "disk_format WSL STAR %08x disk geom %08x\n", + CHS, GEOM(type)); + + /* set buf data to current STAR values */ + label[0] = (cyl >> 8) & 0xff; /* lcyl cyl upper 8 bits */ + label[1] = cyl & 0xff; /* lcyl cyl lower 8 bits */ + label[2] = trk & 0xff; /* ltkn trk */ + label[3] = sec & 0xff; /* lid sector ID */ + label[4] = 0x80; /* show good sector */ + + sim_debug(DEBUG_DETAIL, dptr, + "disk_format WSL star %02x %02x %02x %02x\n", + label[0], label[1], label[2], label[3]); + + /* uaddr has umap value for sector one label */ + if (CHS == 1) { /* only write dmap address in trk 0 */ + /* output last sector address of disk */ + label[16] = (uaddr >> 24) & 0xff; /* lumapp UMAP pointer */ + label[17] = (uaddr >> 16) & 0xff; + label[18] = (uaddr >> 8) & 0xff; + label[19] = (uaddr) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, + "disk_format WSL uaddr star %02x %02x %02x %02x\n", + label[16], label[17], label[18], label[19]); + + } else { + label[16] = 0; + label[17] = 0; + label[18] = 0; + label[19] = 0; + } + + /* the tech doc shows the cyl/trk/sec data is in the first 4 bytes */ + /* of the track label, BUT it is really in the configuration data */ + /* area too. Byte 27 is sectors/track and byte 28 is number of heads. */ + /* Byte 26 is mode. Byte 25 is copy of byte 27. */ + label[25] = disk_type[type].spt & 0xff; + /* The UDP/DPII controllers do not use these bits, so UTX keys */ + /* on these bits to determine type of controller. Bit 31 is set */ + /* for a HSDP and not set for the UDP/DPII */ + label[26] = disk_type[type].type & 0xfc; /* zero bits 6 & 7 in type byte */ + label[27] = disk_type[type].spt & 0xff; + label[28] = disk_type[type].nhds & 0xff; + + if ((sim_fwrite((char *)&label, sizeof(uint8), 30, uptr->fileref)) != 30) { + sim_debug(DEBUG_CMD, dptr, + "Error writing sector label to sect %06x offset %06x\n", + i, CAPB(type)+TRK(type)*30+i*ssize); + return 1; + } + } + + /* seek home again */ + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + fprintf (stderr, "Error on seek to 0\r\n"); + return 1; + } + return SCPE_OK; /* good to go */ +} + /* create the disk file for the specified device */ 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 ssize = SSB(type); /* disk sector size in bytes */ + uint32 tsize = SPT(type); /* get track size in sectors */ + uint32 csize = SPC(type); /* get cylinder size in sectors */ + uint32 cyl = CYL(type); /* get # cylinders */ + uint32 cap = CAP(type); /* disk capacity in sectors */ uint32 cylv = cyl; /* number of cylinders */ uint8 *buff; - int i; + int32 i; /* last sector address of disk (cyl * hds * spt) - 1 */ 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 track of disk */ /* get sector address of vendor defect table VDT */ /* put data = 0xf0000000 0xf4000000 */ @@ -1999,27 +3024,33 @@ int disk_format(UNIT *uptr) { } if ((sim_fwrite((char *)&umap, sizeof(uint32), 256, uptr->fileref)) != 256) { sim_debug(DEBUG_CMD, dptr, - "Error writing UMAP to sect %06x offsewt %06x\n", + "Error writing UMAP to sect %06x offset %06x\n", uaddr, uaddr*ssize); return 1; } - printf("writing to vmap sec %x (%d) bytes %x (%d)\n", + printf("Disk %s has %x (%d) cyl, %x (%d) hds, %x (%d) sec\r\n", + disk_type[type].name, CYL(type), CYL(type), HDS(type), HDS(type), + SPT(type), SPT(type)); + printf("writing to vmap sec %x (%d) bytes %x (%d)\r\n", vaddr, vaddr, (vaddr)*ssize, (vaddr)*ssize); - printf("writing to flaw map sec %x (%d) bytes %x (%d)\n", + printf("writing to flaw map sec %x (%d) bytes %x (%d)\r\n", faddr, faddr, (faddr)*ssize, (faddr)*ssize); - printf("writing dmap to %x %d %x %d dmap to %x %d %x %d\n", + printf("writing dmap to %x %d %x %d dmap to %x %d %x %d\r\n", cap-1, cap-1, (cap-1)*ssize, (cap-1)*ssize, daddr, daddr, daddr*ssize, daddr*ssize); - printf("writing to umap sec %x (%d) bytes %x (%d)\n", + printf("writing to umap sec %x (%d) bytes %x (%d)\r\n", uaddr, uaddr, (uaddr)*ssize, (uaddr)*ssize); + /* create labels for disk */ + i = disk_label(uptr); /* label disk */ + /* seek home again */ if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ fprintf (stderr, "Error on seek to 0\r\n"); return 1; } - return SCPE_OK; /* good to go */ + return i; /* good or error */ } /* attach the selected file to the disk */ @@ -2030,9 +3061,26 @@ t_stat disk_attach(UNIT *uptr, CONST char *file) int type = GET_TYPE(uptr->flags); DEVICE *dptr = get_dev(uptr); DIB *dibp = 0; - t_stat r; + t_stat r,s; uint32 ssize; /* sector size in bytes */ + uint32 info, good; uint8 buff[1024]; + int i, j; + + /* last sector address of disk (cyl * hds * spt) - 1 */ + uint32 laddr = CAP(type) - 1; /* last sector of disk */ + /* get sector address of utx diag map (DMAP) track 0 pointer */ + /* put data = 0xf0000000 + (cyl-1), 0x8a000000 + daddr, */ + /* 0x9a000000 + (cyl-1), 0xf4000008 */ + int32 daddr = (CYL(type)-4) * SPC(type) + (HDS(type)-2) * SPT(type); + /* defect map */ + uint32 dmap[4] = {0xf0000000 | (CAP(type)-1), 0x8a000000 | daddr, + 0x9a000000 | (CAP(type)-1), 0xf4000000}; + + for (i=0; i<4; i++) { /* byte swap data for last sector */ + dmap[i] = (((dmap[i] & 0xff) << 24) | ((dmap[i] & 0xff00) << 8) | + ((dmap[i] & 0xff0000) >> 8) | ((dmap[i] >> 24) & 0xff)); + } /* see if valid disk entry */ if (disk_type[type].name == 0) { /* does the assigned disk have a name */ @@ -2046,11 +3094,121 @@ t_stat disk_attach(UNIT *uptr, CONST char *file) uptr->capac = CAP(type); /* disk capacity in sectors */ ssize = SSB(type); /* get sector size in bytes */ + for (i=0; icapac); /* disk capacity */ + disk_type[type].spt, ssize, uptr->capac); /* disk capacity */ + printf( + "Disk %s cyl %d hds %d sec %d ssiz %d capacity %d\r\n", + disk_type[type].name, disk_type[type].cyl, disk_type[type].nhds, + disk_type[type].spt, ssize, uptr->capac); /* disk capacity */ +#ifndef FIXUP_MPX1X_DISK + /* seek to end of disk */ + if ((sim_fseek(uptr->fileref, 0, SEEK_END)) != 0) { + sim_debug(DEBUG_CMD, dptr, "SCFI Disk attach SEEK end failed\n"); + printf("Disk attach SEEK end failed\r\n"); + goto fmt; /* not setup, go format */ + } + + s = ftell(uptr->fileref); /* get current file position */ + if (s == 0) { + sim_debug(DEBUG_CMD, dptr, "SCFI Disk attach ftell failed s=%06d\n", s); + printf("Disk attach ftell failed s=%06d\r\n", s); + goto fmt; /* not setup, go format */ + } + sim_debug(DEBUG_CMD, dptr, "SCFI Disk attach ftell value s=%06d b=%06d CAP %06d\n", s/ssize, s, CAP(type)); + printf("Disk attach ftell value s=%06d b=%06d CAP %06d\r\n", s/ssize, s, CAP(type)); + + if ((s/ssize) < (CAP(type))) { /* full sized disk? */ + j = (CAP(type) - (s/ssize)); /* get # sectors to write */ + sim_debug(DEBUG_CMD, dptr, + "Disk attach for MPX 1.X needs %04d more sectors added to disk\n", j); + printf( + "Disk attach for MPX 1.X needs %04d more sectors added to disk\r\n", j); + /* must be MPX 1.X disk, extend to MPX 3.X size */ + /* write sectors of zero to end of disk to fill it out */ + for (i=0; ifileref) != ssize)) { + sim_debug(DEBUG_CMD, dptr, "Disk attach fread ret = %04d\n", r); + printf("Disk attach fread ret = %04d\r\n", r); + goto fmt; /* not setup, go format */ + } + } + s = ftell(uptr->fileref); /* get current file position */ + sim_debug(DEBUG_CMD, dptr, + "Disk attach MPX 1.X file extended & sized secs %06d bytes %06d\n", s/ssize, s); + printf("Disk attach MPX 1.X file extended & sized secs %06d bytes %06d\r\n", s/ssize, s); + } + +#ifndef FIXUP_MPX1X_DISK + /* seek last sector of disk */ + if ((sim_fseek(uptr->fileref, (CAP(type)-1)*ssize, SEEK_SET)) != 0) { + sim_debug(DEBUG_CMD, dptr, "Disk attach SEEK last sector failed\n"); + printf( "Disk attach SEEK last sector failed\r\n"); + goto fmt; + } + + /* see if there is disk size-1 in last sector of disk, if not add it */ + if ((r = sim_fread(buff, sizeof(uint8), ssize, uptr->fileref) != ssize)) { + sim_debug(DEBUG_CMD, dptr, "Disk format fread error = %04d\n", r); + printf( "Disk format fread error = %04d\r\n", r); +add_size: + if (ssize == 768) { + /* assume we have MPX 1x, and go on */ +// goto dompx1x; + /* write dmap data to last sector on disk for mpx 1.x */ + if ((sim_fseek(uptr->fileref, laddr*ssize, SEEK_SET)) != 0) { /* seek last sector */ + sim_debug(DEBUG_CMD, dptr, + "Disk Error on last sector seek to sect %06d offset %06d bytes\n", + (CAP(type)-1), (CAP(type)-1)*ssize); + printf( + "Disk Error on last sector seek to sect %06d offset %06d bytes\r\n", + (CAP(type)-1), (CAP(type)-1)*ssize); + goto fmt; + } + if ((sim_fwrite((char *)&dmap, sizeof(uint32), 4, uptr->fileref)) != 4) { + sim_debug(DEBUG_CMD, dptr, + "Disk Error writing DMAP to sect %06x offset %06d bytes\n", + (CAP(type)-1), (CAP(type)-1)*ssize); + printf( + "Disk Error writing DMAP to sect %06x offset %06d bytes\r\n", + (CAP(type)-1), (CAP(type)-1)*ssize); + goto fmt; + } + + /* seek last sector of disk */ + if ((sim_fseek(uptr->fileref, (CAP(type))*ssize, SEEK_SET)) != 0) { + sim_debug(DEBUG_CMD, dptr, "Disk attach SEEK last sector failed\n"); + printf( "Disk attach SEEK last sector failed\r\n"); + goto fmt; + } + s = ftell(uptr->fileref); /* get current file position */ + sim_debug(DEBUG_CMD, dptr, + "Disk attach MPX file extended & sized secs %06d bytes %06d\n", s/ssize, s); + printf("Disk attach MPX file extended & sized secs %06d bytes %06d\r\n", s/ssize, s); + goto ldone; + } else { + /* error if UTX */ + detach_unit(uptr); /* if error, abort */ + return SCPE_FMT; /* error */ + } + } else { + /* if not disk size, go add it in for MPX, error if UTX */ + if ((buff[0] | buff[1] | buff[2] | buff[3]) == 0) { + sim_debug(DEBUG_CMD, dptr, + "Disk format0 buf0 %02x buf1 %02x buf2 %02x buf3 %02x\n", + buff[0], buff[1], buff[2], buff[3]); + goto add_size; + } + } +#endif +#endif + +#ifdef JUNK if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ detach_unit(uptr); /* if no space, error */ return SCPE_UNATT; /* error */ @@ -2061,10 +3219,17 @@ t_stat disk_attach(UNIT *uptr, CONST char *file) sim_debug(DEBUG_CMD, dptr, "Disk format fread ret = %04x\n", r); goto fmt; } +#endif - if ((buff[0] | buff[1] | buff[2] | buff[3]) == 0) { + info = (buff[0]<<24) | (buff[1]<<16) | (buff[2]<<8) | buff[3]; + good = 0xf0000000 | (CAP(type)-1); + /* check for 0xf0ssssss where ssssss is disk size-1 in sectors */ + if (info != good) { sim_debug(DEBUG_CMD, dptr, - "Disk format buf0 %02x buf1 %02x buf2 %02x buf3 %02x\n", + "Disk format error buf0 %02x buf1 %02x buf2 %02x buf3 %02x\n", + buff[0], buff[1], buff[2], buff[3]); + printf( + "Disk format error buf0 %02x buf1 %02x buf2 %02x buf3 %02x\r\n", buff[0], buff[1], buff[2], buff[3]); fmt: /* format the drive */ @@ -2074,7 +3239,31 @@ fmt: } } - /* there is data on sector 0, so already formatted */ +ldone: + /* see if disk has labels already, seek to sector past end of disk */ + if ((sim_fseek(uptr->fileref, CAP(type)*ssize, SEEK_SET)) != 0) { /* seek end */ + detach_unit(uptr); /* detach if error */ + return SCPE_FMT; /* error */ + } + + i = SCPE_OK; + /* see if disk has labels already, seek to sector past end of disk */ + if ((r = sim_fread(buff, sizeof(uint8), 30, uptr->fileref) != 30)) { + /* the disk does not have labels, add them on */ + /* create labels for disk */ + sim_debug(DEBUG_CMD, dptr, + "File %s attached to %s creating labels\n", + file, disk_type[type].name); + printf( + "File %s attached to %s creating labels\r\n", + file, disk_type[type].name); + i = disk_label(uptr); /* label disk */ + if (i != 0) { + detach_unit(uptr); /* detach if error */ + return SCPE_FMT; /* error */ + } + } + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ detach_unit(uptr); /* detach if error */ return SCPE_FMT; /* error */ @@ -2084,20 +3273,29 @@ fmt: 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", + "Disk Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\n", + disk_type[type].name, CYL(type), HDS(type), SPT(type), SPC(type), + CAP(type), CAPB(type)); + printf( + "Disk Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\r\n", disk_type[type].name, CYL(type), HDS(type), SPT(type), SPC(type), CAP(type), CAPB(type)); - sim_debug(DEBUG_CMD, dptr, "File %s attached to %s\r\n", + sim_debug(DEBUG_CMD, dptr, + "File %s attached to %s with labels\n", + file, disk_type[type].name); + printf( + "File %s attached to %s with labels\r\n", file, disk_type[type].name); /* check for valid configured disk */ /* must have valid DIB and Channel Program pointer */ dibp = (DIB *)dptr->ctxt; /* get the DIB pointer */ if ((dib_unit[chsa] == NULL) || (dibp == NULL) || (chp == NULL)) { - sim_debug(DEBUG_CMD, dptr, "ERROR===ERROR\nDISK device %s not configured on system, aborting\n", + sim_debug(DEBUG_CMD, dptr, + "ERROR===ERROR\nDISK device %s not configured on system, aborting\n", dptr->name); - printf("ERROR===ERROR\nDISK device %s not configured on system, aborting\n", + printf("ERROR===ERROR\nDISK device %s not configured on system, aborting\r\n", dptr->name); detach_unit(uptr); /* detach if error */ return SCPE_UNATT; /* error */ diff --git a/SEL32/sel32_ec.c b/SEL32/sel32_ec.c index c4a88dd..6457894 100644 --- a/SEL32/sel32_ec.c +++ b/SEL32/sel32_ec.c @@ -207,19 +207,21 @@ struct ec_device { int poll; /* Need to poll receiver */ } ec_data; -int8 conf[12] = {0}; /* user specified configuration */ +uint8 conf[12] = {0}; /* user specified configuration */ -extern int32 tmxr_poll; +extern int32 tmxr_poll; +extern uint32 readfull(CHANP *chp, uint32 maddr, uint32 *word); static CONST ETH_MAC broadcast_ethaddr = {0xff,0xff,0xff,0xff,0xff,0xff}; /* channel program information */ //CHANP ec_chp[8] = {0}; -CHANP ec_chp[10] = {0}; +CHANP ec_chp[NUM_UNITS_ETHER] = {0}; -uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; +uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); t_stat ec_srv(UNIT *uptr); uint16 ec_haltio(UNIT *uptr); +uint16 ec_iocl(CHANP *chp, int32 tic_ok); void ec_packet_debug(struct ec_device *ec, const char *action, ETH_PACK *packet); t_stat ec_reset (DEVICE *dptr); void ec_ini(UNIT *, t_bool); @@ -260,14 +262,18 @@ UNIT ec_unit[] = { DIB ec_dib = { NULL, /* Pre start I/O */ ec_startcmd, /* Start a command */ - ec_haltio, /* Halt I/O */ - NULL, /* Test I/O */ - NULL, /* Post I/O */ - ec_ini, /* init function */ - ec_unit, /* Pointer to units structure */ - ec_chp, /* Pointer to chan_prg structure */ + ec_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ + NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ + NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + ec_iocl, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ + ec_ini, /* void (*dev_ini)(UNIT *uptr) */ /* init function */ + ec_unit, /* UNIT *units */ /* Pointer to units structure */ + ec_chp, /* CHANP *chan_prg */ /* Pointer to chan_prg structure */ + NULL, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ // 8, /* number of units defined */ - 10, /* number of units defined */ + NUM_UNITS_ETHER, /* number of units defined */ 0x0F, /* device mask */ 0x0E00, /* parent channel address */ 0, /* fifo input index */ @@ -311,12 +317,274 @@ DEBTAB ec_debug[] = { DEVICE ec_dev = { "EC", ec_unit, NULL, ec_mod, // 8, 16, 24, 4, 16, 32, - 10, 16, 24, 4, 16, 32, + NUM_UNITS_ETHER, 16, 24, 4, 16, 32, NULL, NULL, &ec_reset, NULL, &ec_attach, &ec_detach, &ec_dib, DEV_DISABLE | DEV_DEBUG | DEV_ETHER, 0, ec_debug, NULL, NULL, &ec_help, NULL, NULL, &ec_description }; +/* load in the IOCD and process the commands */ +/* return = 0 OK */ +/* return = 1 error, chan_status will have reason */ +uint16 ec_iocl(CHANP *chp, int32 tic_ok) +{ + uint32 word1 = 0; + uint32 word2 = 0; + int32 docmd = 0; +// DIB *dibp = dib_unit[chp->chan_dev];/* get the DIB pointer */ + UNIT *uptr = chp->unitptr; /* get the unit ptr */ + uint16 chan = get_chan(chp->chan_dev); /* our channel */ + uint16 devstat = 0; + DEVICE *dptr = get_dev(uptr); + + /* check for valid iocd address if 1st iocd */ + if (chp->chan_info & INFO_SIOCD) { /* see if 1st IOCD in channel prog */ + if (chp->chan_caw & 0x3) { /* must be word bounded */ + sim_debug(DEBUG_EXP, dptr, + "ec_iocl iocd bad address chan %02x caw %06x\n", + chan, chp->chan_caw); + chp->ccw_addr = chp->chan_caw; /* set the bad iocl address */ + chp->chan_status |= STATUS_PCHK; /* program check for invalid iocd addr */ +// uptr->SNS |= SNS_INAD; /* invalid address status */ + return 1; /* error return */ + } + } +loop: + sim_debug(DEBUG_EXP, dptr, + "ec_iocl @%06x entry chan_status[%04x] %04x SNS %08x\n", + chp->chan_caw, chan, chp->chan_status, uptr->SNS); + + /* Abort if we have any errors */ + if (chp->chan_status & STATUS_ERROR) { /* check channel error status */ + sim_debug(DEBUG_EXP, dptr, + "ec_iocl ERROR1 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* return error */ + } + +#ifdef WHATISTHIS + /* Check if we have status modifier set */ + if (chp->chan_status & STATUS_MOD) { + chp->chan_caw += 8; /* move to next IOCD */ + chp->chan_status &= ~STATUS_MOD; /* turn off status modifier flag */ + } +#endif + + /* 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, dptr, + "ec_iocl ERROR2 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, dptr, + "ec_iocl ERROR3 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + + sim_debug(DEBUG_CMD, dptr, + "ec_iocl @%06x read ccw chan %02x IOCD wd 1 %08x wd 2 %08x SNS %08x\n", + chp->chan_caw, chan, word1, word2, uptr->SNS); + + chp->chan_caw = (chp->chan_caw & 0xfffffc) + 8; /* point to next IOCD */ + chp->ccw_cmd = (word1 >> 24) & 0xff; /* set command from IOCD wd 1 */ + + if (!MEM_ADDR_OK(word1 & MASK24)) { /* see if memory address invalid */ + chp->chan_status |= STATUS_PCHK; /* bad, program check */ +// uptr->SNS |= SNS_INAD; /* invalid address status */ + sim_debug(DEBUG_EXP, dptr, + "ec_iocl bad IOCD1 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + + chp->ccw_count = 0; + + /* this switch is here to satisify the SEL diag who wants a program */ + /* check error instead of a unit check error for these cmd values??? */ + /* validate the commands for the ethernet */ + switch (chp->ccw_cmd) { + case 0x18: case 0x20: case 0x28: case 0x30: case 0x38: case 0x40: case 0x48: + case 0x50: case 0x58: case 0x60: case 0x68: case 0x70: case 0x78: case 0x80: + case 0x88: case 0x90: case 0x98: case 0xa0: case 0xa8: case 0xb0: case 0xb8: + case 0xc0: case 0xc8: case 0xd0: case 0xd8: case 0xe0: case 0xe8: case 0xf0: + case 0xf8: +// uptr->SNS |= SNS_CMDREJ; + uptr->SNS &= ~SNS_CMDREJ; /* remove CMD reject status */ + sim_debug(DEBUG_CMD, dptr, + "ec_startcmd illegal at ec_startcmd %02x SNS %08x\n", + chp->ccw_cmd, uptr->SNS); + chp->ccw_count = 0; /* diags want zero count */ + chp->chan_status |= STATUS_PCHK; /* program check for invalid cmd */ + return 1; /* error return */ + + case EC_INCH: case EC_WRITE: case EC_READ: case EC_NOP: case EC_SNS: + case EC_LIA: case EC_TIC: case EC_CGA: case EC_LGA: case EC_LCC: + case EC_STATS: case EC_CSTATS: + break; + default: + uptr->SNS |= SNS_CMDREJ; + chp->chan_status |= STATUS_CHECK; /* diags want unit check */ + sim_debug(DEBUG_CMD, dptr, + "ec_startcmd illegal cmd %02x SNS %08x\n", + chp->ccw_cmd, uptr->SNS); + return 1; /* error return */ + break; + } + + chp->ccw_count = word2 & 0xffff; /* get 16 bit byte count from IOCD WD 2 */ + + if (chp->chan_info & INFO_SIOCD) { /* see if 1st IOCD in channel prog */ + /* 1st command can not be a TIC */ + if (chp->ccw_cmd == CMD_TIC) { + chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ + sim_debug(DEBUG_EXP, dptr, + "ec_iocl TIC bad cmd chan_status[%04x] %04x\n", + chan, chp->chan_status); + return 1; /* error return */ + } + } + + /* TIC can't follow TIC or be first in command chain */ + /* diags send bad commands for testing. Use all of op */ + if (chp->ccw_cmd == CMD_TIC) { + if (tic_ok) { + if (((word1 & MASK24) == 0) || (word1 & 0x3)) { + sim_debug(DEBUG_EXP, dptr, + "ec_iocl tic cmd bad address chan %02x tic caw %06x IOCD wd 1 %08x\n", + chan, chp->chan_caw, word1); + chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ +// chp->chan_caw = word1; /* get new IOCD address */ + chp->chan_caw = word1 & MASK24; /* get new IOCD address */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ +// uptr->SNS |= SNS_INAD; /* invalid address status */ + return 1; /* error return */ + } + tic_ok = 0; /* another tic not allowed */ + chp->chan_caw = word1 & MASK24; /* get new IOCD address */ + sim_debug(DEBUG_CMD, dptr, + "ec_iocl 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_caw = word1; /* get new IOCD address */ + chp->chan_caw = word1 & MASK24; /* get new IOCD address */ + chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ +// if (((word1 & MASK24) == 0) || (word1 & 0x3)) +// uptr->SNS |= SNS_INAD; /* invalid address status */ + sim_debug(DEBUG_EXP, dptr, + "ec_iocl TIC ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + + /* Check if we had data chaining in previous iocd */ + if ((chp->chan_info & INFO_SIOCD) || /* see if 1st IOCD in channel prog */ + ((chp->ccw_flags & FLAG_DC) == 0)) { /* last IOCD have DC set? */ + sim_debug(DEBUG_CMD, dptr, + "ec_iocl @%06x DO CMD 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 */ + chp->ccw_flags = (word2 >> 16) & 0xf800; /* get flags from bits 0-4 of WD 2 of IOCD */ + chp->chan_status = 0; /* clear status for next IOCD */ + /* make a 24 bit address */ + chp->ccw_addr = word1 & MASK24; /* set the data/seek address */ + + /* validate parts of IOCD2 that are reserved */ + if (word2 & 0x07ff0000) { /* bits 5-15 must be zero */ + chp->chan_status |= STATUS_PCHK; /* program check for invalid iocd */ + sim_debug(DEBUG_EXP, dptr, + "ec_iocl IOCD2 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + + /* DC can only be used with a read/write cmd */ + if (chp->ccw_flags & FLAG_DC) { + if ((chp->ccw_cmd == EC_INCH) || (chp->ccw_cmd == EC_NOP) || + (chp->ccw_cmd == EC_CGA) || (chp->ccw_cmd == EC_CSTATS)) { + chp->chan_status |= STATUS_PCHK; /* program check for invalid DC */ +// uptr->SNS |= SNS_CHER; /* chaining error */ + sim_debug(DEBUG_EXP, dptr, + "ec_iocl DC ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + } + + chp->chan_byte = BUFF_BUSY; /* busy & no bytes transferred yet */ + + sim_debug(DEBUG_XIO, dptr, + "ec_iocl @%06x read docmd %01x addr %06x count %04x chan %04x ccw_flags %04x\n", + chp->chan_caw, docmd, chp->ccw_addr, chp->ccw_count, chan, chp->ccw_flags); + + if (docmd) { /* see if we need to process a command */ + DIB *dibp = dib_unit[chp->chan_dev]; /* get the DIB pointer */ + + uptr = chp->unitptr; /* get the unit ptr */ + if (dibp == 0 || uptr == 0) { + chp->chan_status |= STATUS_PCHK; /* program check if it is */ + return 1; /* if none, error */ + } + + sim_debug(DEBUG_XIO, dptr, + "ec_iocl @%06x before start_cmd chan %04x status %04x count %04x SNS %08x\n", + chp->chan_caw, chan, chp->chan_status, chp->ccw_count, uptr->u5); + + /* call the device startcmd function to process the current command */ + /* just replace device status bits */ + devstat = dibp->start_cmd(uptr, chan, chp->ccw_cmd); + chp->chan_status = (chp->chan_status & 0xff00) | devstat; + chp->chan_info &= ~INFO_SIOCD; /* show not first IOCD in channel prog */ + + sim_debug(DEBUG_XIO, dptr, + "ec_iocl @%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_ERROR)) { + chp->chan_status |= STATUS_CEND; /* channel end status */ + chp->ccw_flags = 0; /* no flags */ + /* see if chan_end already called */ + if (chp->chan_byte == BUFF_NEXT) { + sim_debug(DEBUG_EXP, dptr, + "ec_iocl BUFF_NEXT ERROR chp %p chan_byte %04x\n", + chp, chp->chan_byte); + } else { + chp->chan_byte = BUFF_NEXT; /* have main pick us up */ + sim_debug(DEBUG_EXP, dptr, + "ec_iocl bad status chan %04x status %04x cmd %02x\n", + chan, chp->chan_status, chp->ccw_cmd); + RDYQ_Put(chp->chan_dev); /* queue us up */ + sim_debug(DEBUG_EXP, dptr, + "ec_iocl continue wait chsa %04x status %08x\n", + chp->chan_dev, chp->chan_status); + } + } else + + /* NOTE this code needed for MPX 1.X to run! */ + /* see if command completed */ + /* we have good status */ + if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { + uint16 chsa = GET_UADDR(uptr->u3); /* get channel & sub address */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ + sim_debug(DEBUG_XIO, dptr, + "ec_iocl @%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); + } + } + /* the device processor returned OK (0), so wait for I/O to complete */ + /* nothing happening, so return */ + sim_debug(DEBUG_XIO, dptr, + "ec_iocl @%06x return, chan %04x status %04x count %04x\n", + chp->chan_caw, chan, chp->chan_status, chp->ccw_count); + return 0; /* good return */ +} + /* Start ethernet command */ uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) @@ -332,25 +600,6 @@ uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) sim_debug(DEBUG_CMD, dptr, "ec_startcmd busy\n"); return SNS_BSY; } - /* this switch is here to satisify the SEL diag who wants a program */ - /* check error instead of a unit check error for these cmd values??? */ - switch (cmd) { - case 0x18: case 0x20: case 0x28: case 0x30: case 0x38: case 0x40: case 0x48: - case 0x50: case 0x58: case 0x60: case 0x68: case 0x70: case 0x78: case 0x80: - case 0x88: case 0x90: case 0x98: case 0xa0: case 0xa8: case 0xb0: case 0xb8: - case 0xc0: case 0xc8: case 0xd0: case 0xd8: case 0xe0: case 0xe8: case 0xf0: - case 0xf8: -// uptr->SNS |= SNS_CMDREJ; - uptr->SNS &= ~SNS_CMDREJ; /* remove CMD reject status */ - sim_debug(DEBUG_CMD, dptr, - "ec_startcmd illegal at ec_startcmd %02x SNS %08x\n", - cmd, uptr->SNS); - chp->ccw_count = 0; /* diags want zero count */ - return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; /* diags want prog check */ -// return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* diags want unit check */ - default: - break; - } /* Unit is online, so process a command */ switch (cmd) { @@ -368,7 +617,7 @@ uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) case EC_LGA: /* Load Multicast address */ uptr->SNS &= 0xffff0000; // uptr->SNS &= 0x7fff0000; /* remove invalid cmd status */ - uptr->SNS &= ~SNS_CMDREJ; /* remove CMD reject status */ +// uptr->SNS &= ~SNS_CMDREJ; /* remove CMD reject status */ /* Fall through */ case EC_SNS: /* Sense 0x04 */ /* nop must have non zero count */ @@ -386,7 +635,6 @@ uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) cmd, uptr->SNS); chp->ccw_count = 0; /* diags want zero count */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* diags want unit check */ -// return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; /* diags want prog check */ } /* Handle processing of ethernet requests. */ @@ -415,7 +663,7 @@ t_stat ec_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "ec_srv starting INCH %06x cmd, chsa %04x addr %06x cnt %04x\n", chp->chan_inch_addr, chsa, chp->ccw_addr, chp->ccw_count); - uptr->CMD &= LMASK; /* remove old status bits & */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ /* now call set_inch() function to write and test inch buffer addresses */ i = set_inch(uptr, mema); /* new address */ @@ -429,7 +677,6 @@ t_stat ec_srv(UNIT *uptr) for (i=0; i < len; i++) { if (chan_read_byte(chsa, &buf[i])) { /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -724,7 +971,10 @@ runt: "ec_startcmd CMD sense excess cnt %02x\n", chp->ccw_count); break; } - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + + uptr->SNS &= ~(SNS_CMDREJ|SNS_EQUCHK); /* clear old status */ + + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ break; default: @@ -734,7 +984,7 @@ runt: uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); #else - sim_debug(DEBUG_CMD, dptr, "allow unknown command %02x\n", cmd); + sim_debug(DEBUG_CMD, dptr, "for testing, allow unknown command %02x\n", cmd); #endif } sim_debug(DEBUG_DETAIL, dptr, @@ -760,7 +1010,6 @@ uint16 ec_haltio(UNIT *uptr) { "ec_haltio HIO chsa %04x cmd = %02x ccw_count %02x\n", chsa, cmd, chp->ccw_count); // 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_count = 0; /* zero the count */ chp->ccw_count = 0; /* zero the count */ chp->ccw_flags &= ~(FLAG_DC|FLAG_CC);/* stop any chaining */ uptr->CMD &= LMASK; /* make non-busy */ @@ -768,7 +1017,6 @@ uint16 ec_haltio(UNIT *uptr) { sim_cancel(uptr); /* clear the input timer */ sim_debug(DEBUG_CMD, dptr, "ec_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd); -// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* force error */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* force end */ return SCPE_IOERR; } @@ -978,7 +1226,7 @@ t_stat ec_set_mode (UNIT* uptr, int32 val, CONST char* cptr, void* desc) if (!cptr) return SCPE_IERR; - newmode = get_uint (cptr, 10, 4, &r); + newmode = get_uint(cptr, 10, 4, &r); if (r != SCPE_OK) return r; diff --git a/SEL32/sel32_hsdp.c b/SEL32/sel32_hsdp.c index 065fb75..8b4e9f4 100644 --- a/SEL32/sel32_hsdp.c +++ b/SEL32/sel32_hsdp.c @@ -36,17 +36,19 @@ /* Fill STAR value from cyl, trk, sec data */ #define CHS2STAR(c,h,s) (((c<<16) & LMASK)|((h<<8) & 0xff00)|(s & 0xff)) /* convert STAR value to number of sectors */ -#define STAR2SEC(star,spt,spc) ((star&0xff)+(((star>>8)&0xff)*spt)+((star>>16)*spc)) +#define STAR2SEC(star,spt,spc) ((star&0xff)+(((star>>8)&0xff)*spt)+(((star>>16)&0xffff)*spc)) /* convert STAR value to number of heads or tracks */ -#define STAR2TRK(star,tpc) ((star >> 16) * tpc + ((star >> 8) & 0x0ff)) +#define STAR2TRK(star,tpc) (((star>>16)&0xffff)*tpc+((star>>8)&0x0ff)) /* convert STAR value to number of cylinders */ -#define STAR2CYL(star) ((star >> 16) & RMASK) +#define STAR2CYL(star) ((star>>16)&RMASK) /* convert byte value to number of sectors mod sector size */ #define BYTES2SEC(bytes,ssize) (((bytes) + (ssize-1)) >> 10) /* get sectors per track for specified type */ #define SPT(type) (hsdp_type[type].spt) -/* get sectors per cylinderfor specified type */ +/* get sectors per cylinder for specified type */ #define SPC(type) (hsdp_type[type].spt*hsdp_type[type].nhds) +/* get number of tracks for specified type */ +#define TRK(type) (hsdp_type[type].cyl*hsdp_type[type].nhds) /* get number of cylinders for specified type */ #define CYL(type) (hsdp_type[type].cyl) /* get number of heads for specified type */ @@ -190,6 +192,107 @@ Byte 1 bits 7-15 /* 8 words of retry counters (1/channel) */ /* 22 words reserved */ +/************************************/ +/* track label definations 34 bytes */ + /* for track 0, write max cyl/head/sec values in 0-3 */ + /* otherwise write current values */ +/* +0 short lcyl; cylinder +2 char ltkn; head or track number +3 char lid; track label id (0xff means last track) +4 char lflg1; track status flags + bit 0 good trk + 1 alternate trk + 2 spare trk + 3 reserved trk + 4 defective trk + 5 last track + 6-7 n/u = 0 +5 char lflg2; + bit 0 write lock + 1 write protected + 2-7 n/u = 0 +6 short lspar1; n/u = 0 +8 short lspar2; n/u = 0 +10 short ldef1; defect #1 sec and byte position + * for track 0 write DMAP + * write sector number of cyl-4, hds-2, sec 0 value in 12-15 + * otherwise write current values +12 short ldef2; defect #2 sec and byte position +14 short ldef3; defect #3 sec and byte position + * for track 0 write UMAP which is DMAP - 2 * SPT + * write sector number of cyl-4, hds-4, sec 0 value in 16-19 + * otherwise write current values +16 short ladef1; defect #1 abs position +18 short ladef2; defect #2 abs position +20 short ladef3; defect #3 abs position +22 short laltcyl; alternate cylinder number or return cyl num +24 char lalttk; alrernate track number or return track num +25 char ldscnt; data sector count 16/20 +26 char ldatrflg; device attributes + bit 0 n/u + 1 disk is mhd + 2 n/u + 3 n/u + 4 n/u + 5 dual ported + 6/7 00 768 bytes/blk + 01 1024 bytes/blk + 10 2048 bytes/blk +27 char ldatrscnt; sectors per track (again) +28 char ldatrmhdc; MHD head count +29 char ldatrfhdc; FHD head count +30 uint32 lcrc; Label CRC-32 value + */ + +/*************************************/ +/* sector label definations 34 bytes */ +/* +0 short lcyl; cylinder number +2 char lhd; head number +3 char lsec; sec # 0-15 or 0-19 for 16/20 format +4 char lflg1; track/sector status flags + bit 0 good sec + 1 alternate sec + 2 spare sec + 3 reserved sec + 4 defective sec + 5 last sec + 6-7 n/u = 0 +5 char lflg2; + bit 0 write lock + 1 write protected + 2-7 n/u = 0 +6 short lspar1; n/u = 0 +8 short lspar2; n/u = 0 +10 short ldef1; defect #1 sec and byte position +12 short ldef2; defect #2 sec and byte position +14 short ldef3; defect #3 sec and byte position + * for track 0 write UMAP which is DMAP - 2 * SPT + * write sector number of cyl-4, hds-4, sec 0 value in 16-19 + * otherwise write zeros +16 short lspar3; n/u = 0 +18 short lspar4; n/u = 0 +20 short lspar5; n/u = 0 +22 short laltcyl; alternate cylinder number or return cyl num +24 char lalttk; alrernate track number or return track num +25 char ldscnt; data sector count 16/20 +26 char ldatrflg; device attributes + bit 0 n/u + 1 disk is mhd + 2 n/u + 3 n/u + 4 n/u + 5 dual ported + 6/7 00 768 bytes/blk + 01 1024 bytes/blk + 10 2048 bytes/blk +27 char ldatrscnt; sectors per track (again) +28 char ldatrmhdc; MHD head count +29 char ldatrfhdc; FHD head count +30 uint32 lcrc; Label CRC-32 value + */ + #define CMD u3 /* u3 */ /* in u3 is device command code and status */ @@ -209,7 +312,7 @@ Byte 1 bits 7-15 #define DSK_RD 0x02 /* Read data */ #define DSK_NOP 0x03 /* No operation */ #define DSK_SNS 0x04 /* Sense */ -#define DSK_SCK 0x07 /* Seek cylinder, track, sector */ +#define DSK_SKC 0x07 /* Seek cylinder, track, sector */ #define DSK_TIC 0x08 /* Transfer in channel */ #define DSK_FMT 0x0B /* Format track */ #define DSK_RE 0x12 /* Read express bus with ECC */ @@ -231,7 +334,7 @@ Byte 1 bits 7-15 //#define DSK_XRM 0x5F /* Reset reserve track mode */ #define DSK_RAP 0xA2 /* Read angular position */ //#define DSK_TESS 0xAB /* Test STAR (subchannel target address register) */ -#define DSK_REC 0xB2 /* Read ECC */ +#define DSK_REC 0xB2 /* Read ECC correction mask */ #define DSK_INC 0xFF /* Initialize Controller */ #define STAR u4 @@ -244,44 +347,44 @@ Byte 1 bits 7-15 #define SNS u5 /* u5 */ /* Sense byte 0 - mode register */ -#define SNS_DROFF 0x80000000 /* Drive Carriage will be offset */ -#define SNS_TRKOFF 0x40000000 /* Track offset: 0=positive, 1=negative */ -#define SNS_RDTMOFF 0x20000000 /* Read timing offset = 1 */ -#define SNS_RDSTRBT 0x10000000 /* Read strobe timing: 1=positive, 0=negative */ -#define SNS_DIAGMOD 0x08000000 /* Diagnostic Mode ECC Code generation and checking */ -#define SNS_RSVTRK 0x04000000 /* Reserve Track mode: 1=OK to write, 0=read only */ -#define SNS_FHDOPT 0x02000000 /* FHD or FHD option = 1 */ -#define SNS_RES1 0x01000000 /* Reserved */ +#define SNS_DROFF 0x80000000 /* Drive Carriage will be offset */ +#define SNS_TRKOFF 0x40000000 /* Track offset: 0=positive, 1=negative */ +#define SNS_RDTMOFF 0x20000000 /* Read timing offset = 1 */ +#define SNS_RDSTRBT 0x10000000 /* Read strobe timing: 1=positive, 0=negative */ +#define SNS_DIAGMOD 0x08000000 /* Diagnostic Mode ECC read/write 0/1=disab;e/enable */ +#define SNS_XPBUS 0x04000000 /* Express Bus ID 0/1=enable/disable */ +#define SNS_AUTORT 0x02000000 /* Auto retry 0/1=disable/enable */ +#define SNS_DIAG 0x01000000 /* Diagnostic mode 0/1=disable/enable */ /* Sense byte 1 */ -#define SNS_CMDREJ 0x800000 /* Command reject */ -#define SNS_INTVENT 0x400000 /* Unit intervention required */ -#define SNS_USELE 0x200000 /* Unit Select Error */ -#define SNS_EQUCHK 0x100000 /* Equipment check */ -#define SNS_RES2 0x080000 /* Reserved */ -#define SNS_RES3 0x040000 /* Reserved */ -#define SNS_DSKFERR 0x020000 /* Disk format error */ -#define SNS_DEFTRK 0x010000 /* Defective track encountered */ +#define SNS_CMDREJ 0x800000 /* Command reject */ +#define SNS_INTVENT 0x400000 /* Unit intervention required */ +#define SNS_USELE 0x200000 /* Unit Select Error */ +#define SNS_EQUCHK 0x100000 /* Equipment check */ +#define SNS_RES2 0x080000 /* Reserved */ +#define SNS_RES3 0x040000 /* Reserved */ +#define SNS_DSKFERR 0x020000 /* Disk format error */ +#define SNS_DEFTRK 0x010000 /* Defective track encountered */ /* Sense byte 2 */ -#define SNS_RES4 0x8000 /* Reserved */ -#define SNS_AATT 0x4000 /* At Alternate track */ -#define SNS_WPER 0x2000 /* Write protection error */ -#define SNS_WRL 0x1000 /* Write lock error */ -#define SNS_MOCK 0x0800 /* Mode check */ -#define SNS_INAD 0x0400 /* Invalid memory address */ -#define SNS_RELF 0x0200 /* Release fault */ -#define SNS_CHER 0x0100 /* Chaining error */ +#define SNS_RES4 0x8000 /* Reserved */ +#define SNS_AATT 0x4000 /* At Alternate track */ +#define SNS_WPER 0x2000 /* Write protection error */ +#define SNS_WRL 0x1000 /* Write lock error */ +#define SNS_MOCK 0x0800 /* Mode check */ +#define SNS_INAD 0x0400 /* Invalid memory address */ +#define SNS_RELF 0x0200 /* Release fault */ +#define SNS_CHER 0x0100 /* Chaining error */ /* Sense byte 3 */ -#define SNS_REVL 0x80 /* Revolution lost */ -#define SNS_DADE 0x40 /* Disc addressing or seek error */ -#define SNS_RES5 0x20 /* Reserved */ -#define SNS_RES6 0x10 /* Reserved */ -#define SNS_ECCD 0x08 /* ECC error in data */ -#define SNS_RES7 0x04 /* Reserved */ -#define SNS_RES8 0x02 /* Reserved */ -#define SNS_UESS 0x01 /* Uncorrectable ECC error */ +#define SNS_REVL 0x80 /* Revolution lost */ +#define SNS_DADE 0x40 /* Disc addressing or seek error */ +#define SNS_RES5 0x20 /* Reserved */ +#define SNS_RES6 0x10 /* Reserved */ +#define SNS_ECCD 0x08 /* ECC error in data */ +#define SNS_RES7 0x04 /* Reserved */ +#define SNS_RES8 0x02 /* Reserved */ +#define SNS_UESS 0x01 /* Uncorrectable ECC error */ #define SNS2 us9 /* us9 */ @@ -330,6 +433,9 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option /* Not Used up7 */ +static uint8 obuf[1024], bbuf[1024]; +static uint32 decc[512] = {0}; + /* disk definition structure */ struct hsdp_t { @@ -370,6 +476,8 @@ hsdp_type[] = uint16 hsdp_preio(UNIT *uptr, uint16 chan) ; uint16 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; uint16 hsdp_haltio(UNIT *uptr); +uint16 hsdp_rsctl(UNIT *uptr); +uint16 hsdp_iocl(CHANP *chp, int32 tic_ok); t_stat hsdp_srv(UNIT *); t_stat hsdp_boot(int32 unitnum, DEVICE *); void hsdp_ini(UNIT *, t_bool); @@ -380,9 +488,17 @@ t_stat hsdp_set_type(UNIT * uptr, int32 val, CONST char *cptr, void *desc); t_stat hsdp_get_type(FILE * st, UNIT * uptr, int32 v, CONST void *desc); t_stat hsdp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); const char *hsdp_description (DEVICE *dptr); +extern uint32 inbusy; +extern uint32 outbusy; +extern uint32 readfull(CHANP *chp, uint32 maddr, uint32 *word); +extern int irq_pend; /* go scan for pending int or I/O */ +extern UNIT itm_unit; +extern uint32 PSD[]; /* PSD */ /* channel program information */ -CHANP dpa_chp[NUM_UNITS_HSDP] = {0}; +CHANP dpa_chp[NUM_UNITS_HSDP] = {0}; +/* IOCL queue */ +IOCLQ dpa_ioclq[NUM_UNITS_HSDP] = {0}; MTAB hsdp_mod[] = { {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "TYPE", "TYPE", @@ -408,12 +524,16 @@ UNIT dpa_unit[] = { DIB dpa_dib = { hsdp_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ hsdp_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - hsdp_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + hsdp_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ + hsdp_haltio, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + hsdp_rsctl, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + hsdp_iocl, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ hsdp_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ dpa_unit, /* UNIT* units */ /* Pointer to units structure */ dpa_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + dpa_ioclq, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ NUM_UNITS_HSDP, /* uint8 numunits */ /* number of units defined */ 0x0F, /* uint8 mask */ /* 8 devices - device mask */ 0x0800, /* uint16 chan_addr */ /* parent channel address */ @@ -433,7 +553,9 @@ DEVICE dpa_dev = { #if NUM_DEVS_HSDP > 1 /* channel program information */ -CHANP dpb_chp[NUM_UNITS_HSDP] = {0}; +CHANP dpb_chp[NUM_UNITS_HSDP] = {0}; +/* IOCL queue */ +IOCPQ dpb_ioclq[NUM_UNITS_HSDP] = {0}; UNIT dpb_unit[] = { /* SET_TYPE(3) DM300 */ @@ -451,12 +573,16 @@ UNIT dpb_unit[] = { DIB dpb_dib = { hsdp_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ hsdp_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - hsdp_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + hsdp_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ + hsdp_haltio, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + hsdp_rsctl, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + hsdp_iocl, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ hsdp_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ dpb_unit, /* UNIT* units */ /* Pointer to units structure */ dpb_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + dpb_ioclq, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ NUM_UNITS_HSDP, /* uint8 numunits */ /* number of units defined */ 0x0F, /* uint8 mask */ /* 8 devices - device mask */ 0x0C00, /* uint16 chan_addr */ /* parent channel address */ @@ -475,6 +601,48 @@ DEVICE dpb_dev = { }; #endif +uint32 dple_ecc32(uint8 *str, int32 len) +{ + int i, j; + uint32 ch, ecc = 0; + uint32 pmask = 0x7e11f439; /* SEL LE poly mask */ + + ecc = (~ecc & MASK32); /* initialize ecc to all bits (~0) */ + for (j=0; j>= 1; /* just shift out the bit */ + ecc ^= pmask; /* eor with poly mask */ + } else + ecc >>= 1; /* just shift out the bit */ + ch >>= 1; /* next bit */ + } + } + return (~ecc & MASK32); /* return ecc value */ +} + +uint32 dpbe_ecc32(uint8 *str, int32 len) +{ + int i, j; + uint32 ch, ecc = 0; + uint32 pmask = 0x9C2F887E; /* SEL BE poly mask */ + + ecc = (~ecc & MASK32); /* initialize ecc to all bits (~0) */ + for (j=0; jflags); + DEVICE *dptr = get_dev(uptr); + int len, i; + + /* zero the Track Label Buffer */ + for (i = 0; i < 30; i++) + buf[i] = 0; + + /* get file offset in sectors */ + tstart = STAR2SEC(star, SPT(type), SPC(type)); + /* convert sector number back to chs value to sync disk for diags */ + nstar = hsdpsec2star(tstart, type); + + cyl = (nstar >> 16) & 0xffff; /* get the cylinder */ + trk = (nstar >> 8) & 0xff; /* get the track */ + sec = nstar & 0xff; /* save sec if any */ + + /* get track number */ + tstart = (cyl * HDS(type)) + trk; + sim_debug(DEBUG_EXP, dptr, "get_dpatrk RTL cyl %4x(%d) trk %xec# %06x\n", + cyl, cyl, trk, tstart); + + /* calc offset in file to track label */ + tstart = CAPB(type) + (tstart * 30); + + /* file offset in bytes */ + sim_debug(DEBUG_EXP, dptr, "get_dpatrk RTL SEEK on seek to %06x\n", tstart); + + /* seek to the location where we will r/w track label */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ + sim_debug(DEBUG_EXP, dptr, "get_dpatrk RTL, Error on seek to %04x\n", tstart); + return 0; + } + + /* read in a track label from disk */ + if ((len=sim_fread(buf, 1, 30, uptr->fileref)) != 30) { + sim_debug(DEBUG_CMD, dptr, + "get_dpatrk Error %08x on read %04x of diskfile cyl %04x hds %02x sec 00\n", + len, 30, cyl, trk); + return 0; + } + + /* now write track label data to log */ + sim_debug(DEBUG_DETAIL, dptr, "Track %08x label", nstar); + for (i = 0; i < 30; i++) { + if (i == 16) + sim_debug(DEBUG_DETAIL, dptr, "\nTrack %08x label", nstar); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + if (buf[4] == 0x08) { /* see if defective track */ + uptr->SNS |= SNS_DEFTRK; /* flag as defective */ + tstart = nstar; /* save orginal track */ + /* get the alternate track address */ + cyl = (buf[22] << 8) | buf[23]; /* get the cylinder */ + trk = buf[24]; /* get the track */ +//bad sec = 0; /* sec is zero */ + nstar = CHS2STAR(cyl, trk, sec); + sim_debug(DEBUG_DETAIL, dptr, + "Track %08x is defective, new track %08x\n", tstart, nstar); + } + return nstar; /* return track address */ +} + /* start a disk operation */ uint16 hsdp_preio(UNIT *uptr, uint16 chan) { DEVICE *dptr = get_dev(uptr); uint16 chsa = GET_UADDR(uptr->CMD); - int unit = (uptr - dptr->units); + int unit = (uptr - dptr->units); /* get the UNIT number */ + DIB* dibp = (DIB *)dptr->ctxt; /* get the DIB pointer */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_preio CMD %08x unit %02x\n", uptr->CMD, unit); - if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */ - return SNS_BSY; + if (IOCLQ_Num(&dibp->ioclq_ptr[unit]) == IOCLQ_SIZE) { + return SNS_BSY; /* IOCLQ is full, return busy */ + } + if ((uptr->CMD & 0xff) != 0) { /* just return if busy */ + return SNS_SMS; /* busy, but IOCLQ is not full */ } sim_debug(DEBUG_DETAIL, dptr, "hsdp_preio unit %02x chsa %04x OK\n", unit, chsa); - return 0; /* good to go */ + return SCPE_OK; /* not busy and IOCLQ not full */ +} + +/* load in the IOCD and process the commands */ +/* return = 0 OK */ +/* return = 1 error, chan_status will have reason */ +uint16 hsdp_iocl(CHANP *chp, int32 tic_ok) +{ + uint32 word1 = 0; + uint32 word2 = 0; + int32 docmd = 0; +// DIB *dibp = dib_unit[chp->chan_dev];/* get the DIB pointer */ + UNIT *uptr = chp->unitptr; /* get the unit ptr */ + uint16 chan = get_chan(chp->chan_dev); /* our channel */ + uint16 devstat = 0; + DEVICE *dptr = get_dev(uptr); + + /* check for valid iocd address if 1st iocd */ + if (chp->chan_info & INFO_SIOCD) { /* see if 1st IOCD in channel prog */ + if (chp->chan_caw & 0x3) { /* must be word bounded */ + sim_debug(DEBUG_EXP, dptr, + "hsdp_iocl iocd bad address chan %02x caw %06x\n", + chan, chp->chan_caw); + chp->ccw_addr = chp->chan_caw; /* set the bad iocl address */ + chp->chan_status |= STATUS_PCHK; /* program check for invalid iocd addr */ + uptr->SNS |= SNS_INAD; /* invalid address status */ + return 1; /* error return */ + } + } +loop: + sim_debug(DEBUG_EXP, dptr, + "hsdp_iocl @%06x entry chan_status[%04x] %04x SNS %08x\n", + chp->chan_caw, chan, chp->chan_status, uptr->SNS); + + /* Abort if we have any errors */ + if (chp->chan_status & STATUS_ERROR) { /* check channel error status */ + sim_debug(DEBUG_EXP, dptr, + "hsdp_iocl ERROR1 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* return error */ + } + +#ifdef WHATISTHIS + /* Check if we have status modifier set */ + if (chp->chan_status & STATUS_MOD) { + chp->chan_caw += 8; /* move to next IOCD */ + chp->chan_status &= ~STATUS_MOD; /* turn off status modifier flag */ + } +#endif + + /* 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, dptr, + "hsdp_iocl ERROR2 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, dptr, + "hsdp_iocl ERROR3 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + + sim_debug(DEBUG_CMD, dptr, + "hsdp_iocl @%06x read ccw chan %02x IOCD wd 1 %08x wd 2 %08x SNS %08x\n", + chp->chan_caw, chan, word1, word2, uptr->SNS); + + chp->chan_caw = (chp->chan_caw & 0xfffffc) + 8; /* point to next IOCD */ + chp->ccw_cmd = (word1 >> 24) & 0xff; /* set command from IOCD wd 1 */ + + if (!MEM_ADDR_OK(word1 & MASK24)) { /* see if memory address invalid */ + chp->chan_status |= STATUS_PCHK; /* bad, program check */ + uptr->SNS |= SNS_INAD; /* invalid address status */ + sim_debug(DEBUG_EXP, dptr, + "hsdp_iocl bad IOCD1 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + + chp->ccw_count = word2 & 0xffff; /* get 16 bit byte count from IOCD WD 2 */ + + /* validate the commands for the disk */ + switch (chp->ccw_cmd) { + case DSK_WD: case DSK_RD: case DSK_INCH: case DSK_NOP: case DSK_INC: + case DSK_SKC: case DSK_XEZ: case DSK_LMR: case DSK_WSL: case DSK_RSL: + case DSK_IHA: case DSK_WTL: case DSK_RTL: case DSK_RAP: case DSK_WTF: + case DSK_FMT: case DSK_RE: case DSK_RENO: case DSK_REL: case DSK_RES: + case DSK_RVL: case DSK_POR: case DSK_REC: case DSK_TIC: + /* reset status to on cyl & ready */ +// uptr->SNS2 = (SNS_UNR|SNS_ONC|SNS_USEL); + case DSK_SNS: + break; + default: + chp->chan_status |= STATUS_PCHK; /* program check for invalid cmd */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected */ + sim_debug(DEBUG_EXP, dptr, + "hsdp_iocl bad cmd %02x chan_status[%04x] %04x SNS %08x\n", + chp->ccw_cmd, chan, chp->chan_status, uptr->SNS); + return 1; /* error return */ + } + + if (chp->chan_info & INFO_SIOCD) { /* see if 1st IOCD in channel prog */ + /* 1st command can not be a TIC */ + if (chp->ccw_cmd == CMD_TIC) { + chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ + sim_debug(DEBUG_EXP, dptr, + "hsdp_iocl TIC bad cmd chan_status[%04x] %04x\n", + chan, chp->chan_status); + return 1; /* error return */ + } + } + + /* TIC can't follow TIC or be first in command chain */ + /* diags send bad commands for testing. Use all of op */ + if (chp->ccw_cmd == CMD_TIC) { + if (tic_ok) { + if (((word1 & MASK24) == 0) || (word1 & 0x3)) { + sim_debug(DEBUG_EXP, dptr, + "hsdp_iocl tic cmd bad address chan %02x tic caw %06x IOCD wd 1 %08x\n", + chan, chp->chan_caw, word1); + chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ +// chp->chan_caw = word1; /* get new IOCD address */ + chp->chan_caw = word1 & MASK24; /* get new IOCD address */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ + uptr->SNS |= SNS_INAD; /* invalid address status */ + return 1; /* error return */ + } + tic_ok = 0; /* another tic not allowed */ + chp->chan_caw = word1 & MASK24; /* get new IOCD address */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_iocl 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_caw = word1; /* get new IOCD address */ + chp->chan_caw = word1 & MASK24; /* get new IOCD address */ + chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ + if (((word1 & MASK24) == 0) || (word1 & 0x3)) + uptr->SNS |= SNS_INAD; /* invalid address status */ + sim_debug(DEBUG_EXP, dptr, + "hsdp_iocl TIC ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + + /* Check if we had data chaining in previous iocd */ + if ((chp->chan_info & INFO_SIOCD) || /* see if 1st IOCD in channel prog */ + ((chp->ccw_flags & FLAG_DC) == 0)) { /* last IOCD have DC set? */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_iocl @%06x DO CMD 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 */ + chp->ccw_flags = (word2 >> 16) & 0xf000; /* get flags from bits 0-3 of WD 2 of IOCD */ + chp->chan_status = 0; /* clear status for next IOCD */ + /* make a 24 bit address */ + chp->ccw_addr = word1 & MASK24; /* set the data/seek address */ + + /* validate parts of IOCD2 that are reserved */ + if (word2 & 0x0fff0000) { /* bits 4-15 must be zero */ + chp->chan_status |= STATUS_PCHK; /* program check for invalid iocd */ + sim_debug(DEBUG_EXP, dptr, + "hsdp_iocl IOCD2 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + +#ifndef NOT_FOR_EVERYONE + /* DC can only be used with a read/write cmd */ + if (chp->ccw_flags & FLAG_DC) { + if ((chp->ccw_cmd != DSK_RD) && (chp->ccw_cmd != DSK_WD)) { + chp->chan_status |= STATUS_PCHK; /* program check for invalid DC */ + uptr->SNS |= SNS_CHER; /* chaining error */ + sim_debug(DEBUG_EXP, dptr, + "hsdp_iocl DC ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + } +#endif + + chp->chan_byte = BUFF_BUSY; /* busy & no bytes transferred yet */ + + sim_debug(DEBUG_XIO, dptr, + "hsdp_iocl @%06x read docmd %01x addr %06x count %04x chan %04x ccw_flags %04x\n", + chp->chan_caw, docmd, chp->ccw_addr, chp->ccw_count, chan, chp->ccw_flags); + + if (docmd) { /* see if we need to process a command */ + DIB *dibp = dib_unit[chp->chan_dev]; /* get the DIB pointer */ + + uptr = chp->unitptr; /* get the unit ptr */ + if (dibp == 0 || uptr == 0) { + chp->chan_status |= STATUS_PCHK; /* program check if it is */ + return 1; /* if none, error */ + } + + sim_debug(DEBUG_XIO, dptr, + "hsdp_iocl @%06x before start_cmd chan %04x status %04x count %04x SNS %08x\n", + chp->chan_caw, chan, chp->chan_status, chp->ccw_count, uptr->u5); + + /* call the device startcmd function to process the current command */ + /* just replace device status bits */ + devstat = dibp->start_cmd(uptr, chan, chp->ccw_cmd); + chp->chan_status = (chp->chan_status & 0xff00) | devstat; + chp->chan_info &= ~INFO_SIOCD; /* show not first IOCD in channel prog */ + + sim_debug(DEBUG_XIO, dptr, + "hsdp_iocl @%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_ERROR)) { + chp->chan_status |= STATUS_CEND; /* channel end status */ + chp->ccw_flags = 0; /* no flags */ + /* see if chan_end already called */ + if (chp->chan_byte == BUFF_NEXT) { + sim_debug(DEBUG_EXP, dptr, + "hsdp_iocl BUFF_NEXT ERROR chp %p chan_byte %04x\n", + chp, chp->chan_byte); + } else { + chp->chan_byte = BUFF_NEXT; /* have main pick us up */ + sim_debug(DEBUG_EXP, dptr, + "hsdp_iocl bad status chan %04x status %04x cmd %02x\n", + chan, chp->chan_status, chp->ccw_cmd); + RDYQ_Put(chp->chan_dev); /* queue us up */ + sim_debug(DEBUG_EXP, dptr, + "hsdp_iocl continue wait chsa %04x status %08x\n", + chp->chan_dev, chp->chan_status); + } + } else + + /* NOTE this code needed for MPX 1.X to run! */ + /* see if command completed */ + /* we have good status */ + if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { + uint16 chsa = GET_UADDR(uptr->u3); /* get channel & sub address */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ + sim_debug(DEBUG_XIO, dptr, + "hsdp_iocl @%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); + } + } + /* the device processor returned OK (0), so wait for I/O to complete */ + /* nothing happening, so return */ + sim_debug(DEBUG_XIO, dptr, + "hsdp_iocl @%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 */ } uint16 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uint16 chsa = GET_UADDR(uptr->CMD); DEVICE *dptr = get_dev(uptr); - int unit = (uptr - dptr->units); + int32 unit = (uptr - dptr->units); CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ sim_debug(DEBUG_CMD, dptr, @@ -543,23 +1034,17 @@ uint16 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) sim_activate(uptr, 30); /* start things off */ #else sim_activate(uptr, 250); /* start things off */ +// sim_activate(uptr, 500); /* start things off */ #endif return SCPE_OK; /* good to go */ break; - case DSK_NOP: /* NOP 0x03 */ -#ifdef NOT4HSDP - if ((cmd == DSK_NOP) && - (chp->chan_info & INFO_SIOCD)) { /* is NOP 1st IOCD? */ - chp->chan_caw -= 8; /* backup iocd address for diags */ - break; /* yes, can't be 1st */ - } -#endif case DSK_INC: /* 0xFF Initialize controller */ if ((cmd == DSK_INC) && (chp->ccw_count != 0x20)) /* count must be 32 to be valid */ break; - case DSK_SCK: /* Seek command 0x07 */ + case DSK_NOP: /* NOP 0x03 */ + case DSK_SKC: /* Seek command 0x07 */ case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ case DSK_WD: /* Write command 0x01 */ case DSK_RD: /* Read command 0x02 */ @@ -569,7 +1054,12 @@ uint16 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) case DSK_IHA: /* 0x47 Increment head address */ case DSK_WTL: /* WTL 0x51 */ case DSK_RTL: /* RTL 0x52 */ + case DSK_RVL: /* 0x42 Read vendor label */ + case DSK_WTF: /* 0x41 Write track format */ case DSK_RAP: /* 0xA2 Read angular positions */ + case DSK_FMT: /* 0x0B Format for no skip */ + case DSK_RES: /* 0x23 Reserve */ + case DSK_REL: /* 0x33 Release */ uptr->SNS &= ~MASK24; /* clear data & leave mode */ uptr->SNS2 = (SNS_UNR|SNS_ONC|SNS_USEL);/* reset status to on cyl & ready */ case DSK_SNS: /* Sense 0x04 */ @@ -582,6 +1072,7 @@ uint16 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) sim_activate(uptr, 30); /* start things off */ #else sim_activate(uptr, 250); /* start things off */ +// sim_activate(uptr, 500); /* start things off */ #endif return SCPE_OK; /* good to go */ break; @@ -615,7 +1106,8 @@ uint16 hsdp_haltio(UNIT *uptr) { "hsdp_haltio HIO chsa %04x cmd = %02x ccw_count %02x\n", chsa, cmd, chp->ccw_count); /* 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_count = 0; /* zero the count */ + chp->ccw_count = 0; /* zero the count */ + chp->chan_caw = 0; /* zero iocd address for diags */ chp->ccw_flags &= ~(FLAG_DC|FLAG_CC);/* stop any chaining */ uptr->CMD &= LMASK; /* make non-busy */ uptr->SNS2 |= (SNS_ONC|SNS_UNR); /* on cylinder & ready */ @@ -632,6 +1124,28 @@ uint16 hsdp_haltio(UNIT *uptr) { return SCPE_OK; /* not busy */ } +/* Handle rsctl command for disk */ +uint16 hsdp_rsctl(UNIT *uptr) { + DEVICE *dptr = get_dev(uptr); + uint16 chsa = GET_UADDR(uptr->CMD); + int cmd = uptr->CMD & DSK_CMDMSK; + CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + + if ((uptr->CMD & DSK_CMDMSK) != 0) { /* is unit busy */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_rsctl RSCTL chsa %04x cmd %02x ccw_count %02x\n", chsa, cmd, chp->ccw_count); + sim_cancel(uptr); /* clear the input timer */ + chp->ccw_count = 0; /* zero the count */ + chp->chan_caw = 0; /* zero iocd address for diags */ + chp->ccw_flags &= ~(FLAG_DC|FLAG_CC);/* stop any chaining */ + } + uptr->CMD &= LMASK; /* make non-busy */ + uptr->SNS2 |= (SNS_ONC|SNS_UNR); /* on cylinder & ready */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_rsctl RSCTL I/O not busy chsa %04x cmd %02x\n", chsa, cmd); + return SCPE_OK; /* not busy */ +} + /* Handle processing of hsdp requests. */ t_stat hsdp_srv(UNIT *uptr) { @@ -640,14 +1154,15 @@ t_stat hsdp_srv(UNIT *uptr) CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ int cmd = uptr->CMD & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); - uint32 tcyl=0, trk=0, cyl=0, sec=0; + uint32 tcyl=0, trk=0, cyl=0, sec=0, tempt=0; int unit = (uptr - dptr->units); int len = chp->ccw_count; - int i,j; - uint32 mema; /* memory address */ + int i,j,k; + uint32 mema, ecc, cecc; /* memory address */ uint8 ch; uint16 ssize = hsdp_type[type].ssiz * 4; /* disk sector size in bytes */ uint32 tstart; + uint8 lbuf[32]; uint8 buf2[1024]; uint8 buf[1024]; @@ -676,7 +1191,7 @@ t_stat hsdp_srv(UNIT *uptr) len = chp->ccw_count; /* INCH command count */ mema = chp->ccw_addr; /* get inch or buffer addr */ sim_debug(DEBUG_CMD, dptr, - "disk_srv cmd CONT INC %06x chsa %04x addr %06x count %04x completed\n", + "hsdp_srv cmd CONT INC %06x chsa %04x addr %06x count %04x completed\n", chp->chan_inch_addr, chsa, mema, chp->ccw_count); /* to use this inch method, byte count must be 0x20 */ if (len != 0x20) { @@ -718,8 +1233,8 @@ t_stat hsdp_srv(UNIT *uptr) len = chp->ccw_count; /* INCH command count */ mema = chp->ccw_addr; /* get inch or buffer addr */ sim_debug(DEBUG_CMD, dptr, - "hsdp_srv starting INCH cmd, chsa %04x MemBuf %06x cnt %04x\n", - chsa, chp->ccw_addr, chp->ccw_count); + "hsdp_srv starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n", + chp->chan_inch_addr, chsa, chp->ccw_addr, chp->ccw_count); /* mema has IOCD word 1 contents. For the disk processor it contains */ /* a pointer to the INCH buffer followed by 8 drive attribute words that */ @@ -765,7 +1280,7 @@ t_stat hsdp_srv(UNIT *uptr) | (buf[i-1]<<8) | (buf[i]); } } - /* now call set_inch() function to write and test inch bybber addresses */ + /* now call set_inch() function to write and test inch buffer addresses */ i = set_inch(uptr, mema); /* new address */ if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ /* we have error, bail out */ @@ -776,67 +1291,14 @@ t_stat hsdp_srv(UNIT *uptr) } uptr->CMD &= LMASK; /* remove old cmd */ sim_debug(DEBUG_CMD, dptr, - "hsdp_srv cmd INCH chsa %04x chsa %06x count %04x completed\n", - chsa, mema, chp->ccw_count); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ - break; - - case DSK_WSL: /* WSL 0x31 make into NOP */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ - sim_debug(DEBUG_CMD, dptr, - "hsdp_srv cmd WSL chsa %04x count %04x completed\n", - chsa, chp->ccw_count); - - sim_debug(DEBUG_DETAIL, dptr, "Sector 1 label"); - /* now read sector label data */ - len = chp->ccw_count; - for (i = 0; i < len; i++) { -// for (i = 0; i < 30; i++) { - if (chan_read_byte(chsa, &buf[i])) { - if (chp->chan_status & STATUS_PCHK) /* test for memory error */ - uptr->SNS |= SNS_INAD; /* invalid address */ - /* we have write error, bail out */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; - break; - } - if ((i%16) == 0) - sim_debug(DEBUG_DETAIL, dptr, "\nSector 1 label"); - sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); - } - sim_debug(DEBUG_DETAIL, dptr, "\n"); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ - break; - - case DSK_WTL: /* WTL 0x51 make into NOP */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ - sim_debug(DEBUG_CMD, dptr, - "hsdp_srv cmd WTL chsa %04x count %04x completed\n", - chsa, chp->ccw_count); - - sim_debug(DEBUG_DETAIL, dptr, "Track %08x label", uptr->CHS); - /* now read track label data */ - for (i = 0; i < 30; i++) { - if (chan_read_byte(chsa, &buf[i])) { - if (chp->chan_status & STATUS_PCHK) /* test for memory error */ - uptr->SNS |= SNS_INAD; /* invalid address */ - /* we have read error, bail out */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; - break; - } - if (i == 16) - sim_debug(DEBUG_DETAIL, dptr, "\nTrack %08x label", uptr->CHS); - sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); - } - sim_debug(DEBUG_DETAIL, dptr, "\n"); + "hsdp_srv cmd INCH %06x chsa %04x addr %06x count %04x completed\n", + chp->chan_inch_addr, chsa, mema, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; + case DSK_RES: /* 0x23 Reserve */ + case DSK_REL: /* 0x33 Release */ case DSK_NOP: /* NOP 0x03 */ - /* diags want chan prog check and cmd reject if 1st cmd of IOCL */ uptr->CMD &= LMASK; /* remove old cmd */ sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd NOP chsa %04x count %04x completed\n", @@ -904,15 +1366,25 @@ t_stat hsdp_srv(UNIT *uptr) /* set new STAR value using new values */ uptr->CHS = CHS2STAR(cyl, trk, sec); + /* get alternate track if this one is defective */ + tempt = get_dpatrk(uptr, uptr->CHS, lbuf); + /* file offset in bytes to std or alt track */ + tstart = STAR2SEC(tempt, SPT(type), SPC(type)) * SSB(type); - /* file offset in bytes */ - tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)) * SSB(type); + if ((tempt == 0) && (uptr->CHS != 0)) { + /* we have error */ + sim_debug(DEBUG_EXP, dptr, + "hsdp_srv IHA get_dpatrk return error tempt %06x tstart %06x CHS %08x\n", + tempt, tstart, uptr->CHS); + goto iha_error; + } /* just seek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ +iha_error: uptr->SNS |= SNS_DADE; /* set error status */ uptr->SNS2 |= (SNS_SKER|SNS_SEND); - sim_debug(DEBUG_EXP, dptr, "disk_srv IHA error on seek to %04x\n", tstart); + sim_debug(DEBUG_EXP, dptr, "hsdp_srv IHA error on seek to %04x\n", tstart); chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; // return SCPE_OK; @@ -920,6 +1392,85 @@ t_stat hsdp_srv(UNIT *uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; + case DSK_REC: /* 0xB2 */ /* Read ECC correction code */ + sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd CMD REC Read ECC\n"); + /* count must be 4, if not prog check */ + if (len != 4) { + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv REC bad count unit=%02x count%04x CHS %08x\n", + unit, len, uptr->CHS); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK|STATUS_LENGTH); + break; + } + /* create offset and mask */ + ecc = dple_ecc32(obuf, ssize); /* calc ecc for original sector */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv DEC old obuf data %02x%02x%02x%02x %02x%02x%02x%02x\n", + obuf[1016], obuf[1017], obuf[1018], obuf[1019], + obuf[1020], obuf[1021], obuf[1022], obuf[1023]); + cecc = dple_ecc32(bbuf, ssize); /* calc ecc for bad sector */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv DEC bad bbuf data %02x%02x%02x%02x %02x%02x%02x%02x\n", + bbuf[1016], bbuf[1017], bbuf[1018], bbuf[1019], + bbuf[1020], bbuf[1021], bbuf[1022], bbuf[1023]); + mema = 0; + for (i=0, j=0; i>= 1; /* move mask right */ + } + tcyl = (k * 8) + sec; /* starting bit# */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv REC sb# %04x byte# %04x mask %06x start %08x\n", + sec, k, mema, tcyl); + /* 16 bit sector offset and 9 of 16 bit mask */ + /* tcyl - fake 14 bit offset */ + /* mema - fake 9 bit mask */ + buf[0] = (tcyl & 0x3f00) >> 8; /* upper 6 bits */ + buf[1] = tcyl & 0xff; /* lower 8 bits */ + buf[2] = (mema & 0x100) >> 8; /* upper 1 bits */ + buf[3] = mema & 0xff; /* lower 8 bits */ + /* write the offset and mask data */ + for (i=0; i<4; i++) { + ch = buf[i]; /* get a char from buffer */ + if (chan_write_byte(chsa, &ch)) { /* put a byte to memory */ + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv DEC read %04x bytes of %04x\n", + i, chp->ccw_count); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + return SCPE_OK; + } + } + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv wrote DEC offset %04x mask %04x CHS %08x\n", + tcyl & 0x3fff, mema & 0x1ff, uptr->CHS); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; + case DSK_SNS: /* 0x4 */ sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd CMD sense\n"); @@ -1004,7 +1555,7 @@ t_stat hsdp_srv(UNIT *uptr) chan_write_byte(chsa, &ch); // ch = 0x30; /* drive on cylinder and ready for now */ - uptr->SNS2 &= uptr->SNS2; /* clean out old status */ +// uptr->SNS2 &= ~uptr->SNS2; /* clean out old status */ uptr->SNS2 |= (SNS_ONC|SNS_UNR); /* on cylinder & ready */ ch = uptr->SNS2 & 0xff; /* drive on cylinder and ready for now */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv dsr unit=%02x 2 %02x\n", @@ -1012,19 +1563,20 @@ t_stat hsdp_srv(UNIT *uptr) chan_write_byte(chsa, &ch); } uptr->SNS &= 0xff000000; /* reset status */ - uptr->SNS2 = (SNS_UNR|SNS_ONC); /* reset status to on cyl & ready */ +//28 uptr->SNS2 = (SNS_UNR|SNS_ONC); /* reset status to on cyl & ready */ + uptr->SNS2 = 0; /* reset status */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case DSK_SCK: /* Seek cylinder, track, sector 0x07 */ + case DSK_SKC: /* Seek cylinder, track, sector 0x07 */ /* If we are waiting on seek to finish, check if there yet. */ if (uptr->CMD & DSK_SEEKING) { /* see if on cylinder yet */ if (STAR2CYL(uptr->STAR) == STAR2CYL(uptr->CHS)) { /* we are on cylinder, seek is done */ sim_debug(DEBUG_CMD, dptr, - "hsdp_srv seek on cylinder unit=%02x %04x %04x\n", + "hsdp_srv seek on cylinder unit %02x new %04x old %04x\n", unit, uptr->STAR >> 16, uptr->CHS >> 16); uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->SNS2 |= (SNS_SEND|SNS_ONC); /* On cylinder & seek done */ @@ -1044,6 +1596,7 @@ t_stat hsdp_srv(UNIT *uptr) sim_activate(uptr, 20); /* start things off */ #else sim_activate(uptr, 150); /* start things off */ +// sim_activate(uptr, 300); /* start things off */ #endif break; } @@ -1100,15 +1653,15 @@ t_stat hsdp_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "hsdp_srv STAR unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); -//rezero: - sim_debug(DEBUG_DETAIL, dptr, - "hsdp_srv seek unit=%02x star %02x %02x %02x %02x\n", - unit, buf[0], buf[1], buf[2], buf[3]); +// sim_debug(DEBUG_DETAIL, dptr, +// "hsdp_srv seek unit=%02x star %02x %02x %02x %02x\n", +// unit, buf[0], buf[1], buf[2], buf[3]); /* save STAR (target sector) data in STAR */ uptr->STAR = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]); cyl = STAR2CYL(uptr->STAR); /* get the cylinder */ trk = buf[2]; /* get the track */ + sec = buf[3]; /* get sec */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv NEW SEEK cyl %04x trk %02x sec %02x unit=%02x\n", @@ -1135,16 +1688,35 @@ t_stat hsdp_srv(UNIT *uptr) break; } + /* set new STAR value using new values */ + tempt = CHS2STAR(cyl, trk, sec); + /* get alternate track if this one is defective */ + tempt = get_dpatrk(uptr, tempt, lbuf); + /* file offset in bytes to std or alt track */ + tstart = STAR2SEC(tempt, SPT(type), SPC(type)) * SSB(type); + + if ((tempt == 0) && (uptr->STAR != 0)) { + /* we have error */ + sim_debug(DEBUG_EXP, dptr, + "hsdp_srv SEEK get_dpatrk return error tempt %06x tstart %06x, STAR %08x\n", + tempt, tstart, uptr->STAR); + } + /* calc the new sector address of data */ /* calculate file position in bytes of requested sector */ /* file offset in bytes */ - tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type); +// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type); /* set new STAR value using old cyl value */ - uptr->CHS = CHS2STAR(STAR2CYL(uptr->CHS), trk, buf[3]); +// uptr->CHS = CHS2STAR(STAR2CYL(uptr->CHS), trk, buf[3]); + + /* set new STAR value using new values */ +/*05*/ uptr->STAR = CHS2STAR(cyl, trk, sec); + /* file offset in bytes to std or alt track */ +/*05*/ tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type); sim_debug(DEBUG_DETAIL, dptr, - "hsdp_srv seek start %04x cyl %04x trk %02x sec %02x\n", - tstart, cyl, trk, buf[3]); + "hsdp_srv seek start %04x cyl %04x trk %02x sec %02x CHS %08x\n", + tstart, cyl, trk, buf[3], uptr->CHS); /* just seek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* seek home */ @@ -1164,21 +1736,24 @@ t_stat hsdp_srv(UNIT *uptr) /* Do a fake seek to kill time */ uptr->CMD |= DSK_SEEKING; /* show we are seeking */ sim_debug(DEBUG_DETAIL, dptr, - "hsdp_srv seek unit=%02x cyl %04x trk %02x sec %02x\n", - unit, cyl, trk, buf[3]); + "hsdp_srv seeking unit=%02x to %04x/%02x/%02x from cyl %04x (%04x)\n", + unit, cyl, trk, buf[3], tcyl, diff); #ifdef FAST_FOR_UTX -// sim_activate(uptr, 15); - sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 15); +// sim_activate(uptr, 20); /* start things off */ // sim_activate(uptr, 20+diff); /* start us off */ #else // sim_activate(uptr, 150); /* start things off */ sim_activate(uptr, 200+diff); /* start us off */ +// sim_activate(uptr, 400+diff); /* start us off */ #endif } else { /* we are on cylinder/track/sector, so go on */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv done seeking to %04x cyl %04x trk %02x sec %02x\n", tstart, cyl, trk, buf[3]); + /* set new STAR value */ + uptr->CHS = CHS2STAR(cyl, trk, buf[3]); uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); } @@ -1192,7 +1767,7 @@ t_stat hsdp_srv(UNIT *uptr) uptr->STAR = 0; /* set STAR to 0, 0, 0 */ uptr->CHS = 0; /* set current CHS to 0, 0, 0 */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ - uptr->CMD |= DSK_SCK; /* show as seek command */ + uptr->CMD |= DSK_SKC; /* show as seek command */ tstart = 0; /* byte offset is 0 */ /* just seek to the location where we will r/w data */ @@ -1225,14 +1800,48 @@ t_stat hsdp_srv(UNIT *uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; } - sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x old %x new %x\n", - unit, (uptr->SNS)&0xff, buf[0]); + sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x old %02x new %02x\n", + unit, (uptr->SNS>>24)&0xff, buf[0]); uptr->CMD &= LMASK; /* remove old status bits & cmd */ - uptr->SNS &= 0x00ffffff; /* clear old mode data */ + 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_WTF: /* 0x41 Write track format */ + case DSK_FMT: /* 0x0B Format for no skip */ + /* buffer must be on halfword boundry if not STATUS_PCHK and SNS_CMDREJ status */ +// chp->chan_status |= STATUS_PCHK; /* program check for invalid cmd */ +// uptr->SNS |= SNS_CMDREJ; /* cmd rejected */ + /* byte count can not exceed 20160 for the track */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + sim_debug(DEBUG_CMD, dptr, + "HSDP Format starting CMD %08x chsa %04x buffer %06x count %04x\n", + uptr->CMD, chsa, chp->ccw_addr, chp->ccw_count); + sim_debug(DEBUG_DETAIL, dptr, "Format %x label", uptr->CHS); + /* now read sector label data */ + len = chp->ccw_count; + for (i = 0; i < len; i++) { +//0906 for (i = 0; i < 30; i++) { + if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + /* we have write error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } + if ((i%16) == 0) + sim_debug(DEBUG_DETAIL, dptr, "\nFormat %x label", uptr->CHS); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); +// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); +// return SCPE_OK; + break; + case DSK_RD: /* Read Data */ if ((uptr->CMD & DSK_READING) == 0) { /* see if we are reading data */ uptr->CMD |= DSK_READING; /* read from disk starting */ @@ -1246,8 +1855,43 @@ t_stat hsdp_srv(UNIT *uptr) tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); /* convert sector number back to chs value to sync disk for diags */ uptr->CHS = hsdpsec2star(tstart, type); - /* file offset in bytes */ - tstart = tstart * SSB(type); + + /* get alternate track if this one is defective */ + tempt = get_dpatrk(uptr, uptr->CHS, lbuf); + /* file offset in bytes to std or alt track */ + tstart = STAR2SEC(tempt, SPT(type), SPC(type)) * SSB(type); + + if ((tempt == 0) && (uptr->STAR != 0)) { + /* we have error */ + sim_debug(DEBUG_EXP, dptr, + "hsdp_srv READ get_dpatrk return error tempt %06x tstart %06x\n", tempt, tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_DADE; /* set error status */ + uptr->SNS2 |= (SNS_SKER|SNS_SEND); + sim_debug(DEBUG_EXP, dptr, "hsdp_srv READ error on seek to %04x\n", tstart); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + uptr->SNS &= ~SNS_DEFTRK; /* remove defective flag */ + /* see if spare track */ + if (lbuf[4] & 0x20) { /* see if spare track */ + uptr->SNS |= SNS_DADE; /* disk addr error */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + sim_debug(DEBUG_EXP, dptr, + "hsdp_srv READ get_dpatrk return spare tempt %06x tstart %06x\n", tempt, tstart); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } + + /* see if reserved track */ + if (lbuf[4] & 0x10) { /* see if reserved track */ + uptr->SNS |= SNS_MOCK; /* mode check error */ +// uptr->SNS |= SNS_RTAE; /* reserved track access error */ + uptr->SNS |= SNS_RES8; /* reserved track access error */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } /* just seek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ @@ -1275,6 +1919,11 @@ t_stat hsdp_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "hsdp_srv after READ chsa %04x buffer %06x count %04x\n", chsa, chp->ccw_addr, chp->ccw_count); + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv after READ buffer %06x count %04x data %02x%02x%02x%02x %02x%02x%02x%02x\n", +// chp->ccw_addr, chp->ccw_count, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); + chp->ccw_addr, chp->ccw_count, buf[1016], buf[1017], buf[1018], buf[1019], + buf[1020], buf[1021], buf[1022], buf[1023]); uptr->CHS++; /* next sector number */ /* process the next sector of data */ @@ -1296,31 +1945,67 @@ t_stat hsdp_srv(UNIT *uptr) } } + /* get current sector offset */ + j = STAR2SEC(tempt, SPT(type), SPC(type)); /* current sector */ + i = ((CYL(type) - 3) * HDS(type)) * SPT(type); /* diag start */ sim_debug(DEBUG_CMD, dptr, - "HSDP READ %04x bytes leaving %4x to be read to %06x from diskfile /%04x/%02x/%02x\n", - ssize, chp->ccw_count, chp->ccw_addr+4, + "hsdp_srv after READ j %04x i %04x j-i %04x CAP %06x DIAG %06x\n", + j, i, j-i, CAP(type), (((CYL(type) - 3) * HDS(type)) * SPT(type))); /* diag start */ + if (j >= i) { /* only do diag sectors */ + cecc = dple_ecc32(buf, ssize); /* calc ecc for sector */ + sim_debug(DEBUG_CMD, dptr, + "ECC j %02x i %02x data calc Old %08x Cur %08x cyl %04x hds %02x sec %02x\n", + j, i, decc[j-i], cecc, STAR2CYL(tempt), ((tempt) >> 8)&0xff, (tempt&0xff)); + if ((decc[j-i] != 0) && (cecc != decc[j-i])) { /* test against old */ + /* checksum error */ + sim_debug(DEBUG_CMD, dptr, + "ECC j %02x i %02x data error Old %08x New %08x cyl %04x hds %02x sec %02x\n", + j, i, decc[j-i], cecc, STAR2CYL(tempt), ((tempt) >> 8)&0xff, (tempt&0xff)); + uptr->SNS |= SNS_ECCD; /* data ECC error */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_CHECK|STATUS_EXPT); + return SCPE_OK; + } + } + + /* see if this is a read ECC from diag */ + /* mode byte will be 0x08 and remaining count will be 4 */ + if ((uptr->SNS & SNS_DIAGMOD) && (chp->ccw_count == 4)) { + for (i=0; iCHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + /* set ECC value here */ + for (i=0; i<4; i++) { + ch = (ecc >> ((3-i)*8)) & 0xff; /* get a char from buffer */ + if (chan_write_byte(chsa, &ch)) { /* put a byte to memory */ + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + return SCPE_OK; + } + } + sim_debug(DEBUG_CMD, dptr, + "Read ECC %04x for diags 4 bytes to ECC REG cyl %04x hds %02x sec %02x\n", + ecc, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + } + + sim_debug(DEBUG_CMD, dptr, + "HSDP READ %04x bytes leaving %4x to be read to %06x from diskfile %04x/%02x/%02x\n", + ssize, chp->ccw_count, chp->ccw_addr, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); /* get sector offset */ tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); - /* see if we are done reading data */ - if (test_write_byte_end(chsa)) { - /* EOM reached, abort */ - sim_debug(DEBUG_DATA, dptr, - "HSDP Read complete for read from disk @ /%04x/%02x/%02x\n", - STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); - uptr->CMD &= LMASK; /* remove old status bits & cmd */ - uptr->CHS = 0; /* reset cylinder position */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - - /* see of over end of disk */ + /* see if over end of disk */ if (tstart >= (uint32)CAP(type)) { /* EOM reached, abort */ sim_debug(DEBUG_CMD, dptr, - "HSDP Read reached EOM for read from disk @ /%04x/%02x/%02x\n", + "HSDP Read reached EOM for read from disk @ %04x/%02x/%02x\n", STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->CHS = 0; /* reset cylinder position */ @@ -1330,10 +2015,11 @@ t_stat hsdp_srv(UNIT *uptr) /* see if we are done reading data */ if (test_write_byte_end(chsa)) { + /* EOM reached, abort */ sim_debug(DEBUG_DATA, dptr, - "HSDP Read complete for read from diskfile /%04x/%02x/%02x\n", + "HSDP Read complete for read from disk @ %04x/%02x/%02x\n", STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; } @@ -1343,10 +2029,11 @@ t_stat hsdp_srv(UNIT *uptr) chp->ccw_count, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); #ifdef FAST_FOR_UTX // sim_activate(uptr, 10); /* wait to read next sector */ -// sim_activate(uptr, 15); /* wait to read next sector */ - sim_activate(uptr, 20); /* wait to read next sector */ + sim_activate(uptr, 15); /* wait to read next sector */ +// sim_activate(uptr, 20); /* wait to read next sector */ #else sim_activate(uptr, 150); /* wait to read next sector */ +// sim_activate(uptr, 300); /* wait to read next sector */ #endif break; } @@ -1355,18 +2042,63 @@ t_stat hsdp_srv(UNIT *uptr) case DSK_WD: /* Write Data */ if ((uptr->CMD & DSK_WRITING) == 0) { /* see if we are writing data */ - uptr->CMD |= DSK_WRITING; /* write to disk starting */ sim_debug(DEBUG_CMD, dptr, "HSDP WRITE starting unit=%02x CMD %08x write %04x from %06x to %03x/%02x/%02x\n", unit, uptr->CMD, chp->ccw_count, chp->ccw_addr, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + + if (uptr->SNS & 0xf0000000) { /* see if any mode bit 0-3 is set */ + uptr->SNS |= SNS_MOCK; /* mode check error */ + chp->chan_status |= STATUS_PCHK; /* channel prog check */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } + uptr->CMD |= DSK_WRITING; /* write to disk starting */ } if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */ - /* get sector offset in sectors */ + /* get file offset in sectors */ tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); /* file offset in bytes */ tstart = tstart * SSB(type); + /* get alternate track if this one is defective */ + tempt = get_dpatrk(uptr, uptr->CHS, lbuf); + /* file offset in bytes to std or alt track */ + tstart = STAR2SEC(tempt, SPT(type), SPC(type)) * SSB(type); + + if ((tempt == 0) && (uptr->STAR != 0)) { + /* we have error */ + sim_debug(DEBUG_EXP, dptr, + "hsdp_srv WRITE get_dpatrk return error tempt %06x tstart %06x\n", tempt, tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_DADE; /* set error status */ + uptr->SNS2 |= (SNS_SKER|SNS_SEND); + sim_debug(DEBUG_EXP, dptr, "hsdp_srv WRITE error on seek to %04x\n", tstart); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + + uptr->SNS &= ~SNS_DEFTRK; /* remove defective flag */ + /* see if spare track */ +//was if (lbuf[4] & 0x30) { /* see if spare or reserved track */ + if (lbuf[4] & 0x20) { /* see if spare track */ + uptr->SNS |= SNS_DADE; /* disk addr error */ + chp->chan_status |= STATUS_PCHK; /* channel prog check */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } + /* see if reserved track */ + if (lbuf[4] & 0x10) { /* see if reserved track */ + uptr->SNS |= SNS_MOCK; /* mode check error */ +// uptr->SNS |= SNS_RTAE; /* reserved track access error */ + uptr->SNS |= SNS_RES8; /* reserved track access error */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } + /* 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, "hsdp_srv WRITE, Error on seek to %04x\n", tstart); @@ -1414,6 +2146,65 @@ t_stat hsdp_srv(UNIT *uptr) break; } + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv after WRITE buffer %06x count %04x data %02x%02x%02x%02x %02x%02x%02x%02x\n", +// chp->ccw_addr, chp->ccw_count, +// buf2[0], buf2[1], buf2[2], buf2[3], buf2[4], buf2[5], buf2[6], buf2[7]); + chp->ccw_addr, chp->ccw_count, buf2[1016], buf2[1017], buf2[1018], buf2[1019], + buf2[1020], buf2[1021], buf2[1022], buf2[1023]); + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv after WRITE CAP %06x DIAG %06x\n", + CAP(type), (((CYL(type) - 3) * HDS(type)) * SPT(type))); /* diag start */ + + /* get current sector offset */ + j = STAR2SEC(tempt, SPT(type), SPC(type)); /* current sector */ + i = ((CYL(type) - 3) * HDS(type)) * SPT(type); /* diag start */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv after WRITE j %04x i %04x j-i %04x CAP %06x DIAG %06x\n", + j, i, j-i, CAP(type), (((CYL(type) - 3) * HDS(type)) * SPT(type))); /* diag start */ + if (j >= i) { /* only do diag sectors */ + cecc = dple_ecc32(buf2, ssize); /* calc ecc for sector */ + sim_debug(DEBUG_CMD, dptr, + "ECC j %02x i %02x data write Old %08x Cur %08x cyl %04x hds %02x sec %02x\n", + j, i, decc[j-i], cecc, STAR2CYL(tempt), ((tempt) >> 8)&0xff, (tempt&0xff)); + decc[j-i] = cecc; /* set new ecc */ + } + j = j-i; /* save index */ + + /* see if this is a write ECC from diag */ + /* mode byte will be 0x08 and remaining count will be 4 */ + if ((uptr->SNS & SNS_DIAGMOD) && (chp->ccw_count == 4)) { + for (i=0; iCHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + /* set ECC value here */ + for (i=0; i<4; i++) { + if (chan_read_byte(chsa, &ch)) {/* get a byte from memory */ + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + return SCPE_OK; + } + /* get an ECC byte */ + buf[i] = ch; /* put a char to buffer */ + ecc |= ((ch & 0xff) << ((3-i)*8)); + } + tcyl++; /* show we have no more data to write */ + sim_debug(DEBUG_CMD, dptr, + "Write decc[%04x] ECC=%08x from diags, calc ECC=%08x cyl %04x hds %02x sec %02x\n", + j, ecc, cecc, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + decc[j] = ecc; /* set new ecc from diag */ + } + + sim_debug(DEBUG_CMD, dptr, + "DISK WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x\n", + len, ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CHS++; /* next sector number */ if (tcyl != 0) { /* see if done with write command */ sim_debug(DEBUG_DATA, dptr, @@ -1423,10 +2214,6 @@ t_stat hsdp_srv(UNIT *uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; } - sim_debug(DEBUG_CMD, dptr, - "HSDP WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x\n", - len, ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); - /* get sector offset */ tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); @@ -1441,11 +2228,23 @@ t_stat hsdp_srv(UNIT *uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } + + /* see if we are done reading data */ + if (test_write_byte_end(chsa)) { + sim_debug(DEBUG_CMD, dptr, + "DISK Write complete for read from diskfile %04x/%02x/%02x\n", + STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; + } + #ifdef FAST_FOR_UTX // sim_activate(uptr, 10); /* keep writing */ sim_activate(uptr, 15); /* keep writing */ #else sim_activate(uptr, 150); /* wait to read next sector */ +// sim_activate(uptr, 300); /* wait to read next sector */ #endif break; } @@ -1460,17 +2259,58 @@ t_stat hsdp_srv(UNIT *uptr) buf[i] = 0; len = chp->ccw_count; /* get number of sectors per track */ + mema = uptr->CHS+(len/30); /* save address */ + + sim_debug(DEBUG_DETAIL, dptr, "before RSL Sector %x len %x\n", uptr->CHS, len); /* read a 30 byte track label for each sector on track */ /* for 16 sectors per track, that is 480 bytes */ /* for 20 sectors per track, that is 600 bytes */ for (j=0; jCHS, SPT(type), SPC(type)); /* convert sector number back to chs value to sync disk for diags */ uptr->CHS = hsdpsec2star(tstart, type); + cyl = (uptr->CHS >> 16) & 0xffff; /* get the cylinder */ + trk = (uptr->CHS >> 8) & 0xff; /* get the track */ + sec = uptr->CHS & 0xff; /* get sec */ + seeksec = tstart; /* save sector number */ + + sim_debug(DEBUG_EXP, dptr, "hsdp_srv RSL cyl %04x trk %02x sec %02x sector# %06x\n", + cyl, trk, sec, seeksec); + + /* seek sector label area after end of track label area */ + tstart = CAPB(type) + (CYL(type)*HDS(type)*30) + (tstart*30); + + /* file offset in bytes to sector label */ + sim_debug(DEBUG_EXP, dptr, "hsdp_srv RSL SEEK on seek to %08x\n", tstart); + + /* seek to the location where we will read sector label */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { + sim_debug(DEBUG_CMD, dptr, + "Error seeking sector label area at sect %06x offset %08x\n", + seeksec, tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } + + /* read in a sector label from disk */ + if (sim_fread(buf, 1, 30, uptr->fileref) != 30) { + sim_debug(DEBUG_CMD, dptr, + "Error %08x on read %04x of diskfile cyl %04x hds %02x sec %02x\n", + len, 30, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } + +#ifdef OLDCODE /* the dmap pointer is placed by the vendor or diag into the */ /* track zero label in word 3 of the 30 byte label. */ /* The disk address is the last track of the user area. The vendor */ @@ -1555,30 +2395,39 @@ t_stat hsdp_srv(UNIT *uptr) buf[26] = hsdp_type[type].type | 1; /* mode data is 0x41 */ buf[27] = hsdp_type[type].spt & 0xff; /* sec per track 35 */ buf[28] = hsdp_type[type].nhds & 0xff; /* num heads 10 */ +#endif - sim_debug(DEBUG_DETAIL, dptr, "Sector 1 label"); + sim_debug(DEBUG_DETAIL, dptr, "Sector %x label", uptr->CHS); /* now write sector label data */ for (i = 0; i < 30; i++) { if (chan_write_byte(chsa, &buf[i])) { /* we have write error, bail out */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ + sim_debug(DEBUG_DETAIL, dptr, "\n"); chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; break; } if (i == 16) - sim_debug(DEBUG_DETAIL, dptr, "\nSector 1 label"); + sim_debug(DEBUG_DETAIL, dptr, "\nSector %x label", uptr->CHS); sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); } sim_debug(DEBUG_DETAIL, dptr, "\n"); /* leave STAR "unnormalized" for diags */ uptr->CHS++; /* bump to next track */ + if ((uptr->CHS & 0xff) == SPC(type)) + break; /* stop at last sector */ len -= 30; /* count 1 sector label size */ if (len > 0) continue; break; /* done */ } + uptr->CHS = mema; /* restore address */ + + sim_debug(DEBUG_DETAIL, dptr, "after RSL Sector %x len %x\n", uptr->CHS, chp->ccw_count); + /* command done */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd RSL done chsa %04x count %04x completed\n", @@ -1586,6 +2435,222 @@ t_stat hsdp_srv(UNIT *uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; + case DSK_WSL: /* WSL 0x31 */ + len = chp->ccw_count; /* get number bytes to read */ +// mema = uptr->CHS+(len/30); /* save address */ + mema = uptr->CHS; /* save address */ + + sim_debug(DEBUG_DETAIL, dptr, "before WSL Sector %x len %x\n", uptr->CHS, len); + + /* read a 30 byte sector label for each sector on track */ + /* for 16 sectors per track, that is 480 bytes */ + /* for 20 sectors per track, that is 600 bytes */ + for (j=0; jCHS); + /* now read sector label data */ + for (i = 0; i < 30; i++) { + if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + /* we have read error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } + if ((i%16) == 0) + sim_debug(DEBUG_DETAIL, dptr, "\nSector %x label", uptr->CHS); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + /* see if user trying to set invalid bit pattern */ + if ((buf[4] & 0x48) == 0x48) { /* see if setting defective alternate trk */ + uptr->SNS |= SNS_DSKFERR; /* disk formating error */ + uptr->CHS = mema; /* restore address */ + chp->ccw_count = len; /* restore number bytes to read */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); +// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_LENGTH); + return SCPE_OK; + break; + } + + /* get file offset in sectors */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + + /* convert sector number back to chs value to sync disk for diags */ + uptr->CHS = hsdpsec2star(tstart, type); + + cyl = (uptr->CHS >> 16) & 0xffff; /* get the cylinder */ + trk = (uptr->CHS >> 8) & 0xff; /* get the track */ + sec = uptr->CHS & 0xff; /* get sec */ + seeksec = tstart; /* save sector number */ + + sim_debug(DEBUG_EXP, dptr, "hsdp_srv WSL cyl %04x trk %02x sec %02x sector# %06x\n", + cyl, trk, sec, seeksec); + + /* seek sector label area after end of track label area */ + tstart = CAPB(type) + (CYL(type)*HDS(type)*30) + (tstart*30); + + /* file offset in bytes to sector label */ + sim_debug(DEBUG_EXP, dptr, "hsdp_srv WSL SEEK on seek to %08x\n", tstart); + + /* seek to the location where we will write sector label */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { + sim_debug(DEBUG_CMD, dptr, + "Error seeking sector label area at sect %06x offset %08x\n", + seeksec, tstart); + uptr->CHS = mema; /* restore address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } + + /* write sector label to disk */ + if (sim_fwrite(buf, 1, 30, uptr->fileref) != 30) { + sim_debug(DEBUG_CMD, dptr, + "Error %08x on write %04x of diskfile cyl %04x hds %02x sec %02x\n", + len, 30, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + uptr->CHS = mema; /* restore address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } + + /* leave STAR "unnormalized" for diags */ + uptr->CHS++; /* bump to next sector */ + if ((uptr->CHS & 0xff) == SPC(type)) + break; /* stop at last sector */ + len -= 30; /* count 1 sector label size */ + if (len > 0) + continue; + break; /* done */ + } + + uptr->CHS = mema; /* restore address */ + + sim_debug(DEBUG_DETAIL, dptr, "after WSL Sector %x len %x\n", uptr->CHS, chp->ccw_count); + + /* command done */ + uptr->CMD &= 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); +#ifdef OLDWAY + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv cmd WSL chsa %04x count %04x started\n", + chsa, chp->ccw_count); + + sim_debug(DEBUG_DETAIL, dptr, "Sector 1 label"); + /* now read sector label data */ + len = chp->ccw_count; + for (i = 0; i < len; i++) { +// for (i = 0; i < 30; i++) { + if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + /* we have write error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } + if ((i%16) == 0) + sim_debug(DEBUG_DETAIL, dptr, "\nSector 1 label"); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); +#endif + + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case DSK_RVL: /* 0x42 Read vendor label */ + /* Read track zero to get disk geometry */ + /* write 30 bytes, b0-b1=cyl, b1=trk, b2=sec */ + + /* zero the Track Label Buffer */ + for (i = 0; i < 30; i++) + buf[i] = 0; + + uptr->CHS &= 0xffffff00; /* zero sector for trk read */ + mema = uptr->CHS; + + /* get file offset in sectors */ + tstart = STAR2SEC(mema, SPT(type), SPC(type)); + + /* convert sector number back to chs value to sync disk for diags */ + mema = hsdpsec2star(tstart, type); + cyl = (mema >> 16) & 0xffff; /* get the cylinder */ + trk = (mema >> 8) & 0xff; /* get the track */ + + /* get track number */ + tstart = (cyl * HDS(type)) + trk; + sim_debug(DEBUG_EXP, dptr, "hsdp_srv RVL cyl %4x(%d) trk %x sec# %06x\n", + cyl, cyl, trk, tstart); + + /* calc offset in file to track label */ + tstart = CAPB(type) + (tstart * 30); + + /* file offset in bytes */ + sim_debug(DEBUG_EXP, dptr, "hsdp_srv RVL SEEK on seek to %06x\n", tstart); + + /* seek to the location where we will r/w track label */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ + sim_debug(DEBUG_EXP, dptr, "hsdp_srv RVL, Error on seek to %04x\n", tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + } + + /* read in a track label from disk */ + if ((len=sim_fread(buf, 1, 30, uptr->fileref)) != 30) { + sim_debug(DEBUG_CMD, dptr, + "Error %08x on read %04x of diskfile cyl %04x hds %02x sec %02x\n", + len, 30, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + + if (buf[4] == 0x08) { /* see if defective track */ + uptr->SNS |= SNS_DEFTRK; /* flag as defective */ + sim_debug(DEBUG_DETAIL, dptr, "Track %08x is defective\n", uptr->CHS); + } + + if (buf[4] == 0x40) { /* see if alternate track */ + uptr->SNS |= SNS_AATT; /* flag as alternate */ + sim_debug(DEBUG_DETAIL, dptr, "Track %08x is alternate\n", uptr->CHS); + } + + /* now write track label data to memory */ + sim_debug(DEBUG_DETAIL, dptr, "Track %08x label", uptr->CHS); + for (i = 0; i < 30; i++) { + if (chan_write_byte(chsa, &buf[i])) { + /* we have write error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (i == 16) + sim_debug(DEBUG_DETAIL, dptr, "\nTrack %08x label", uptr->CHS); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + /* command done */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd RVL done chsa %04x count %04x completed\n", + chsa, chp->ccw_count); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case DSK_RTL: /* RTL 0x52 */ /* Read track zero to get disk geometry */ /* write 30 bytes, b0-b1=cyl, b1=trk, b2=sec */ @@ -1594,6 +2659,78 @@ t_stat hsdp_srv(UNIT *uptr) for (i = 0; i < 30; i++) buf[i] = 0; + uptr->CHS &= 0xffffff00; /* zero sector for trk read */ + mema = uptr->CHS; + + /* get file offset in sectors */ + tstart = STAR2SEC(mema, SPT(type), SPC(type)); + + /* convert sector number back to chs value to sync disk for diags */ + mema = hsdpsec2star(tstart, type); + cyl = (mema >> 16) & 0xffff; /* get the cylinder */ + trk = (mema >> 8) & 0xff; /* get the track */ + + /* get track number */ + tstart = (cyl * HDS(type)) + trk; + sim_debug(DEBUG_EXP, dptr, "hsdp_srv RTL cyl %4x(%d) trk %x sec# %06x\n", + cyl, cyl, trk, tstart); + + /* calc offset in file to track label */ + tstart = CAPB(type) + (tstart * 30); + + /* file offset in bytes */ + sim_debug(DEBUG_EXP, dptr, "hsdp_srv RTL SEEK on seek to %06x\n", tstart); + + /* seek to the location where we will r/w track label */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ + sim_debug(DEBUG_EXP, dptr, "hsdp_srv RTL, Error on seek to %04x\n", tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + } + + /* read in a track label from disk */ + if ((len=sim_fread(buf, 1, 30, uptr->fileref)) != 30) { + sim_debug(DEBUG_CMD, dptr, + "Error %08x on read %04x of diskfile cyl %04x hds %02x sec %02x\n", + len, 30, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + + if (buf[4] == 0x08) { /* see if defective track */ + uptr->SNS |= SNS_DEFTRK; /* flag as defective */ + sim_debug(DEBUG_DETAIL, dptr, "Track %08x is defective\n", uptr->CHS); + } + + if (buf[4] == 0x40) { /* see if alternate track */ + uptr->SNS |= SNS_AATT; /* flag as alternate */ + sim_debug(DEBUG_DETAIL, dptr, "Track %08x is alternate\n", uptr->CHS); + } + + /* now write track label data to memory */ + sim_debug(DEBUG_DETAIL, dptr, "Track %08x label", uptr->CHS); + for (i = 0; i < 30; i++) { + if (chan_write_byte(chsa, &buf[i])) { + /* we have write error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (i == 16) + sim_debug(DEBUG_DETAIL, dptr, "\nTrack %08x label", uptr->CHS); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + +#ifdef NONO + /* leave STAR "unnormalized" for diags */ + if (uptr->CHS != 0) /* only incr address if not trk 0 */ + uptr->CHS += 0x10; /* bump to next track */ +#endif + +#ifdef OLDWAY /* get file offset in sectors */ tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); /* convert sector number back to chs value to sync disk for diags */ @@ -1718,6 +2855,7 @@ t_stat hsdp_srv(UNIT *uptr) /* leave STAR "unnormalized" for diags */ uptr->CHS += 0x10; /* bump to next track */ +#endif /* command done */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ @@ -1726,6 +2864,129 @@ t_stat hsdp_srv(UNIT *uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; + case DSK_WTL: /* WTL 0x51 */ + /* Write track zero to set disk geometry */ + /* write 30 bytes, b0-b1=cyl, b1=trk, b2=sec */ + + sim_debug(DEBUG_EXP, dptr, "hsdp_srv WTL start cnt %04x CHS %08x\n", + chp->ccw_count, uptr->CHS); + +#ifdef NONO + /* see if user trying to write other than 30 bytes */ + if (chp->ccw_count != 30 && chp->ccw_count != 34) { /* see if wrong byte count */ +// uptr->SNS |= SNS_DEFTRK; /* disk formating error */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } +#endif + + /* get file offset in sectors */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* convert sector number back to chs value to sync disk for diags */ + uptr->CHS = hsdpsec2star(tstart, type); + uptr->CHS &= 0xffffff00; /* zero sector for trk read */ + mema = uptr->CHS; + + cyl = (uptr->CHS >> 16) & 0xffff; /* get the cylinder */ + trk = (uptr->CHS >> 8) & 0xff; /* get the track */ + + /* get track number */ + tstart = (cyl * HDS(type)) + trk; + sim_debug(DEBUG_EXP, dptr, "hsdp_srv WTL cyl %4x trk %x track# %06x CHS %08x\n", + cyl, trk, tstart, uptr->CHS); + + /* calc offset in file to track label */ + tstart = CAPB(type) + (tstart * 30); + + /* file offset in bytes */ + sim_debug(DEBUG_EXP, dptr, "hsdp_srv WTL SEEK on seek to %06x\n", tstart); + + /* get alternate track info */ + tempt = get_dpatrk(uptr, uptr->CHS, lbuf); + uptr->SNS &= ~SNS_DEFTRK; /* remove any defective track flag */ + /* file offset in bytes to std or alt track */ +//// tstart = STAR2SEC(tempt, SPT(type), SPC(type)) * SSB(type); + + /* seek to the location where we will write track label */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ + sim_debug(DEBUG_EXP, dptr, "hsdp_srv WTL, Error on seek to %04x\n", tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + } + + sim_debug(DEBUG_DETAIL, dptr, "Track %08x label", uptr->CHS); + /* now read track label data from memory */ + for (i = 0; i < 30; i++) { + if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + /* we have read error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } + if (i == 16) + sim_debug(DEBUG_DETAIL, dptr, "\nTrack %08x label", uptr->CHS); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + /* see if user trying to set invalid bit pattern */ + if ((buf[4] & 0x48) == 0x48) { /* see if setting defective alternate trk */ + uptr->SNS |= SNS_DSKFERR; /* disk formating error */ + uptr->CHS = mema; /* restore address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } + + /* write out a track label to disk */ + if ((len=sim_fwrite(buf, 1, 30, uptr->fileref)) != 30) { + sim_debug(DEBUG_CMD, dptr, + "Error %08x on write %04x of diskfile cyl %04x hds %02x sec %02x\n", + len, 30, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + uptr->CHS = mema; /* restore address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + + uptr->CHS = mema; /* restore address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv cmd WTL chsa %04x count %04x completed CHS %08x\n", + chsa, chp->ccw_count, uptr->CHS); + +#ifdef OLDWAY + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv cmd WTL chsa %04x count %04x completed\n", + chsa, chp->ccw_count); + + sim_debug(DEBUG_DETAIL, dptr, "Track %08x label", uptr->CHS); + /* now read track label data */ + for (i = 0; i < 30; i++) { + if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + /* we have read error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } + if (i == 16) + sim_debug(DEBUG_DETAIL, dptr, "\nTrack %08x label", uptr->CHS); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); +#endif + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + default: sim_debug(DEBUG_CMD, dptr, "invalid command %02x unit %02x\n", cmd, unit); uptr->SNS |= SNS_CMDREJ; @@ -1762,6 +3023,199 @@ t_stat hsdp_reset(DEVICE *dptr) return SCPE_OK; } +/* add track and sector labels to disk */ +int hsdp_label(UNIT *uptr) { + int type = GET_TYPE(uptr->flags); + DEVICE *dptr = get_dev(uptr); + uint32 trk, cyl, sec; + uint32 ssize = SSB(type); /* disk sector size in bytes */ + uint32 tsize = SPT(type); /* get track size in sectors */ + uint32 tot_tracks = TRK(type); /* total tracks on disk */ + uint32 tot_sectors = CAP(type); /* total number of sectors on disk */ + uint32 cap = CAP(type); /* disk capacity in sectors */ + uint32 CHS; /* cyl, hds, sec format */ + uint8 label[34]; /* track/sector label */ + int32 i, j; + /* get sector address of utx diag map (DMAP) track 0 pointer */ + /* put data = 0xf0000000 + (cyl-1), 0x8a000000 + daddr, */ + /* 0x9a000000 + (cyl-1), 0xf4000008 */ + int32 daddr = (CYL(type)-4) * SPC(type) + (HDS(type)-2) * SPT(type); + /* get sector address of utx flaw map sec 1 pointer */ + /* use this address for sec 1 label pointer */ + int32 uaddr = (CYL(type)-4) * SPC(type) + (HDS(type)-4) * SPT(type); + + /* write 30 byte track labels for all tracks on disk */ + /* tot_tracks entries will be created starting at end of disk */ + /* seek first sector after end of disk data */ + if ((sim_fseek(uptr->fileref, CAPB(type), SEEK_SET)) != 0) { + sim_debug(DEBUG_CMD, dptr, + "Error seeking track label area at sect %06x offset %06x\n", + CAP(type), CAPB(type)); + return 1; + } + /* write track labels */ + for (i=0; i> 16) & 0xffff; /* get the cylinder */ + trk = (CHS >> 8) & 0xff; /* get the track */ + sec = (CHS) & 0xff; /* get the sector */ + } + + sim_debug(DEBUG_CMD, dptr, "hsdp_format WTL STAR %08x disk geom %08x\n", + CHS, GEOM(type)); + + /* set buf data to current STAR values */ + label[0] = (cyl >> 8) & 0xff; /* lcyl cyl upper 8 bits */ + label[1] = cyl & 0xff; /* lcyl cyl lower 8 bits */ + label[2] = trk & 0xff; /* ltkn trk */ + label[3] = sec & 0xff; /* lid sector ID */ + label[4] = 0x80; /* show good sector */ + if (i == (tot_tracks-1)) { /* last track? */ + label[3] = 0xff; /* lid show as last track label */ + label[4] |= 0x04; /* set last track flag */ + } + + sim_debug(DEBUG_DETAIL, dptr, + "hsdp_format RTL star %02x %02x %02x %02x\n", + label[0], label[1], label[2], label[3]); + + /* daddr has dmap value for track zero label */ + if (CHS == 0) { /* only write dmap address in trk 0 */ + /* output last sector address of disk */ + label[12] = (daddr >> 24) & 0xff; /* lumapp DMAP pointer */ + label[13] = (daddr >> 16) & 0xff; + label[14] = (daddr >> 8) & 0xff; + label[15] = (daddr) & 0xff; + } + + /* uaddr has umap value for track zero label */ + if (CHS == 0) { /* only write dmap address in trk 0 */ + /* output last sector address of disk */ + label[16] = (uaddr >> 24) & 0xff; /* lumapp DMAP pointer */ + label[17] = (uaddr >> 16) & 0xff; + label[18] = (uaddr >> 8) & 0xff; + label[19] = (uaddr) & 0xff; + } + + /* the tech doc shows the cyl/trk/sec data is in the first 4 bytes */ + /* of the track label, BUT it is really in the configuration data */ + /* area too. Byte 27 is sectors/track and byte 28 is number of heads. */ + /* Byte 26 is mode. Byte 25 is copy of byte 27. */ + label[25] = SPT(type) & 0xff; + label[26] = hsdp_type[type].type & 0xfc; /* zero bits 6 & 7 in type byte */ + label[27] = SPT(type) & 0xff; + label[28] = HDS(type) & 0xff; + + if ((sim_fwrite((char *)&label, sizeof(uint8), 30, uptr->fileref)) != 30) { + sim_debug(DEBUG_CMD, dptr, + "Error writing track label to sect %06x offset %06x\n", + cap+(i*tsize), cap*ssize+(i*tsize*ssize)); + return 1; + } + } + + /* write 30 byte sector labels for all sectors on disk */ + /* tot_sector entries will be created starting at end of disk */ + /* plus the track label area size. seek first sector after end */ + /* of disk track label area */ + if ((sim_fseek(uptr->fileref, CAPB(type)+TRK(type)*30, SEEK_SET)) != 0) { + sim_debug(DEBUG_CMD, dptr, + "Error seeking sector label area at sect %06x offset %06x\n", + CAP(type)+TRK(type), CAPB(type)+TRK(type)*30); + return 1; + } + + /* zero the Sector Label Buffer */ + for (j = 0; j < 30; j++) + label[j] = 0; + + /* convert sector number to CHS value for label */ + /* write sector labels */ + for (i=0; i> 16) & 0xffff; /* get the cylinder */ + trk = (CHS >> 8) & 0xff; /* get the track */ + sec = (CHS) & 0xff; /* get the sector */ + + sim_debug(DEBUG_CMD, dptr, "hsdp_format WSL STAR %08x disk geom %08x\n", + CHS, GEOM(type)); + + /* set buf data to current STAR values */ + label[0] = (cyl >> 8) & 0xff; /* lcyl cyl upper 8 bits */ + label[1] = cyl & 0xff; /* lcyl cyl lower 8 bits */ + label[2] = trk & 0xff; /* ltkn trk */ + label[3] = sec & 0xff; /* lid sector ID */ + label[4] = 0x80; /* show good sector */ + + sim_debug(DEBUG_DETAIL, dptr, + "hsdp_format WSL star %02x %02x %02x %02x\n", + label[0], label[1], label[2], label[3]); + + /* uaddr has umap value for sector one label */ + if (CHS == 1) { /* only write dmap address in trk 0 */ + /* output last sector address of disk */ + label[16] = (uaddr >> 24) & 0xff; /* lumapp UMAP pointer */ + label[17] = (uaddr >> 16) & 0xff; + label[18] = (uaddr >> 8) & 0xff; + label[19] = (uaddr) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, + "hsdp_format WSL uaddr star %02x %02x %02x %02x\n", + label[16], label[17], label[18], label[19]); + + } else { + label[16] = 0; + label[17] = 0; + label[18] = 0; + label[19] = 0; + } + + /* the tech doc shows the cyl/trk/sec data is in the first 4 bytes */ + /* of the track label, BUT it is really in the configuration data */ + /* area too. Byte 27 is sectors/track and byte 28 is number of heads. */ + /* Byte 26 is mode. Byte 25 is copy of byte 27. */ + label[25] = hsdp_type[type].spt & 0xff; + /* The UDP/DPII controllers do not use these bits, so UTX keys */ + /* on these bits to determine type of controller. Bit 31 is set */ + /* for a HSDP and not set for the UDP/DPII */ + label[26] = hsdp_type[type].type & 0xfc; /* zero bits 6 & 7 in type byte */ + label[27] = hsdp_type[type].spt & 0xff; + label[28] = hsdp_type[type].nhds & 0xff; + + if ((sim_fwrite((char *)&label, sizeof(uint8), 30, uptr->fileref)) != 30) { + sim_debug(DEBUG_CMD, dptr, + "Error writing sector label to sect %06x offset %06x\n", + i, CAPB(type)+TRK(type)*30+i*ssize); + return 1; + } + } + + /* seek home again */ + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + fprintf (stderr, "Error on seek to 0\r\n"); + return 1; + } + return SCPE_OK; /* good to go */ +} + /* create the disk file for the specified device */ int hsdp_format(UNIT *uptr) { int type = GET_TYPE(uptr->flags); @@ -1960,6 +3414,9 @@ int hsdp_format(UNIT *uptr) { return 1; } + printf("Disk %s has %x (%d) cyl, %x (%d) hds, %x (%d) sec\r\n", + hsdp_type[type].name, CYL(type), CYL(type), HDS(type), HDS(type), + SPT(type), SPT(type)); printf("writing to vmap sec %x (%d) bytes %x (%d)\n", vaddr, vaddr, (vaddr)*ssize, (vaddr)*ssize); printf("writing dmap to %x %d %x %d dmap to %x %d %x %d\n", @@ -1968,6 +3425,9 @@ int hsdp_format(UNIT *uptr) { printf("writing to umap sec %x (%d) bytes %x (%d)\n", uaddr, uaddr, (uaddr)*ssize, (uaddr)*ssize); + /* create labels for disk */ + i = hsdp_label(uptr); /* label disk */ + /* seek home again */ if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ fprintf (stderr, "Error on seek to 0\r\n"); @@ -1986,7 +3446,9 @@ t_stat hsdp_attach(UNIT *uptr, CONST char *file) DIB *dibp = 0; t_stat r; uint32 ssize; /* sector size in bytes */ + uint32 info, good; uint8 buff[1024]; + int i; /* see if valid disk entry */ if (hsdp_type[type].name == 0) { /* does the assigned disk have a name */ @@ -2001,10 +3463,16 @@ t_stat hsdp_attach(UNIT *uptr, CONST char *file) uptr->capac = CAP(type); /* size in sectors */ ssize = SSB(type); /* disk sector size in bytes */ - sim_debug(DEBUG_CMD, dptr, "Disk %s cyl %d hds %d sec %d ssiz %d capacity %d\n", + sim_debug(DEBUG_CMD, dptr, + "Disk %s cyl %d hds %d sec %d ssiz %d capacity %d\n", hsdp_type[type].name, hsdp_type[type].cyl, hsdp_type[type].nhds, hsdp_type[type].spt, ssize, uptr->capac); /* hsdp capacity */ + printf( + "Disk %s cyl %d hds %d sec %d ssiz %d capacity %d\r\n", + hsdp_type[type].name, hsdp_type[type].cyl, hsdp_type[type].nhds, + hsdp_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_UNATT; /* error */ @@ -2020,6 +3488,39 @@ t_stat hsdp_attach(UNIT *uptr, CONST char *file) sim_debug(DEBUG_CMD, dptr, "Disk format buf0 %02x buf1 %02x buf2 %02x buf3 %02x\n", buff[0], buff[1], buff[2], buff[3]); + goto fmt; + } + + /* seek last sector of disk */ + if ((sim_fseek(uptr->fileref, (CAP(type)-1)*ssize, SEEK_SET)) != 0) { + goto fmt; + } + + /* see if there is disk size-1 in last sector of disk, if not format it */ + if ((r = sim_fread(buff, sizeof(uint8), ssize, uptr->fileref) != ssize)) { + sim_debug(DEBUG_CMD, dptr, + "Disk format fread error = %04x\n", r); + printf( + "Disk format fread error = %04x\r\n", r); + if (ssize == 768) { + /* assume we have MPX 1x, and go on */ + goto dompx1x; + } + /* error if UTX */ + detach_unit(uptr); /* if error, abort */ + return SCPE_FMT; /* error */ + } + + info = (buff[0]<<24) | (buff[1]<<16) | (buff[2]<<8) | buff[3]; + good = 0xf0000000 | (CAP(type)-1); + /* check for 0xf0ssssss where ssssss is disk size-1 in sectors */ + if (info != good) { + sim_debug(DEBUG_CMD, dptr, + "Disk format error buf0 %02x buf1 %02x buf2 %02x buf3 %02x\n", + buff[0], buff[1], buff[2], buff[3]); + printf( + "Disk format error buf0 %02x buf1 %02x buf2 %02x buf3 %02x\r\n", + buff[0], buff[1], buff[2], buff[3]); fmt: /* format the drive */ if (hsdp_format(uptr)) { @@ -2028,9 +3529,32 @@ fmt: } } - /* there is data on sector 0, so already formatted */ + /* see if disk has labels already, seek to sector past end of disk */ + if ((sim_fseek(uptr->fileref, CAP(type)*ssize, SEEK_SET)) != 0) { /* seek end */ + detach_unit(uptr); /* detach if error */ + return SCPE_FMT; /* error */ + } + i = SCPE_OK; + /* see if disk has labels already, seek to sector past end of disk */ + if ((r = sim_fread(buff, sizeof(uint8), 30, uptr->fileref) != 30)) { + /* the disk does not have labels, add them on */ + /* create labels for disk */ + sim_debug(DEBUG_CMD, dptr, + "File %s attached to %s creating labels\n", + file, hsdp_type[type].name); + printf( + "File %s attached to %s creating labels\r\n", + file, hsdp_type[type].name); + i = hsdp_label(uptr); /* label disk */ + if (i != 0) { + detach_unit(uptr); /* detach if error */ + return SCPE_FMT; /* error */ + } + } + +dompx1x: if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ - detach_unit(uptr); /* if no space, error */ + detach_unit(uptr); /* detach if error */ return SCPE_FMT; /* error */ } @@ -2041,22 +3565,30 @@ fmt: "Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\n", hsdp_type[type].name, CYL(type), HDS(type), SPT(type), SPC(type), CAP(type), CAPB(type)); + printf( + "Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\r\n", + hsdp_type[type].name, CYL(type), HDS(type), SPT(type), SPC(type), + CAP(type), CAPB(type)); - sim_debug(DEBUG_CMD, dptr, "File %s attached to %s\r\n", + sim_debug(DEBUG_CMD, dptr, + "File %s attached to %s\n", + file, hsdp_type[type].name); + printf( + "File %s attached to %s\r\n", file, hsdp_type[type].name); /* check for valid configured disk */ /* must have valid DIB and Channel Program pointer */ - dibp = (DIB *)dptr->ctxt; /* get the DIB pointer */ + dibp = (DIB *)dptr->ctxt; /* get the DIB pointer */ //??if ((dib_unit[chsa] == NULL) || (dibp == NULL) || (dibp->chan_prg == NULL)) { if ((dib_unit[chsa] == NULL) || (dibp == NULL) || (chp == NULL)) { sim_debug(DEBUG_CMD, dptr, "ERROR===ERROR\nHSDP device %s not configured on system, aborting\n", dptr->name); - printf("ERROR===ERROR\nHSDP device %s not configured on system, aborting\n", + printf("ERROR===ERROR\nHSDP device %s not configured on system, aborting\r\n", dptr->name); - detach_unit(uptr); /* detach if error */ - return SCPE_UNATT; /* error */ + detach_unit(uptr); /* detach if error */ + return SCPE_UNATT; /* error */ } set_devattn(chsa, SNS_DEVEND); return SCPE_OK; diff --git a/SEL32/sel32_iop.c b/SEL32/sel32_iop.c index 75b6b92..c401528 100644 --- a/SEL32/sel32_iop.c +++ b/SEL32/sel32_iop.c @@ -101,12 +101,16 @@ UNIT iop_unit[] = { DIB iop_dib = { NULL, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Start I/O */ iop_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command SIO */ - NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O HIO */ + NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O HIO */ + NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O HIO */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O TIO */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + NULL, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ iop_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ iop_unit, /* UNIT* units */ /* Pointer to units structure */ iop_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NULL, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ NUM_UNITS_IOP, /* uint8 numunits */ /* number of units defined */ 0xff, /* uint8 mask */ /* 16 devices - device mask */ 0x7e00, /* uint16 chan_addr */ /* parent channel address */ diff --git a/SEL32/sel32_lpr.c b/SEL32/sel32_lpr.c index b0e34d5..0c41983 100644 --- a/SEL32/sel32_lpr.c +++ b/SEL32/sel32_lpr.c @@ -172,12 +172,16 @@ UNIT lpr_unit[] = { DIB lpr_dib = { NULL, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Start I/O */ lpr_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ + NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + NULL, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ lpr_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ lpr_unit, /* UNIT* units */ /* Pointer to units structure */ lpr_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NULL, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ NUM_DEVS_LPR, /* uint8 numunits */ /* number of units defined */ 0xff, /* uint8 mask */ /* 2 devices - device mask */ 0x7e00, /* uint16 chan_addr */ /* parent channel address */ diff --git a/SEL32/sel32_mfp.c b/SEL32/sel32_mfp.c index 70ace5b..e617b24 100644 --- a/SEL32/sel32_mfp.c +++ b/SEL32/sel32_mfp.c @@ -104,12 +104,16 @@ UNIT mfp_unit[] = { DIB mfp_dib = { NULL, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Start I/O */ mfp_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O HIO */ + NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O HIO */ + NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O HIO */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O TIO */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + NULL, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ mfp_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ mfp_unit, /* UNIT* units */ /* Pointer to units structure */ mfp_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NULL, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ NUM_UNITS_MFP, /* uint8 numunits */ /* number of units defined */ 0xff, /* uint8 mask */ /* 16 devices - device mask */ 0x7600, /* uint16 chan_addr */ /* parent channel address */ diff --git a/SEL32/sel32_mt.c b/SEL32/sel32_mt.c index 173abc8..ba9a3aa 100644 --- a/SEL32/sel32_mt.c +++ b/SEL32/sel32_mt.c @@ -293,12 +293,16 @@ CHANP mta_chp[NUM_UNITS_MT] = {0}; DIB mta_dib = { NULL, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ mt_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ + NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + NULL, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ mt_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ mta_unit, /* UNIT* units */ /* Pointer to units structure */ mta_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NULL, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ NUM_UNITS_MT, /* uint8 numunits */ /* number of units defined */ 0x07, /* uint8 mask */ /* 8 devices - device mask */ 0x1000, /* uint16 chan_addr */ /* parent channel address */ @@ -337,12 +341,16 @@ UNIT mtb_unit[] = { DIB mtb_dib = { NULL, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ mt_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ + NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + NULL, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ mt_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ mtb_unit, /* UNIT* units */ /* Pointer to units structure */ mtb_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NULL, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ NUM_UNITS_MT, /* uint8 numunits */ /* number of units defined */ 0x07, /* uint8 mask */ /* 8 devices - device mask */ 0x1800, /* uint16 chan_addr */ /* parent channel address */ diff --git a/SEL32/sel32_scfi.c b/SEL32/sel32_scfi.c index 5b84816..71a6e5a 100644 --- a/SEL32/sel32_scfi.c +++ b/SEL32/sel32_scfi.c @@ -1,6 +1,6 @@ -/* sel32_scfi.c: SEL-32 SCFI SCSI Disk controller +/* sel32_scfi.c: SEL-32 SCFI SCSI Disk Controller - Copyright (c) 2018-2020, James C. Bevier + Copyright (c) 2018-2021, James C. Bevier Portions provided by Richard Cornwell and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a @@ -23,25 +23,32 @@ #include "sel32_defs.h" +/* uncomment to use fast sim_activate times when running UTX */ +/* UTX gets an ioi error for dm0801 if slow times are used */ +/* dm0801 is not even a valid unit number for UDP controller */ +#define FAST_FOR_UTX + #if NUM_DEVS_SCFI > 0 #define UNIT_SCFI UNIT_ATTABLE | UNIT_IDLE | UNIT_DISABLE /* useful conversions */ /* Fill STAR value from cyl, trk, sec data */ -#define CHS2STAR(c,h,s) (((c<<16) & 0xffff0000)|((h<<8) & 0xff00)|(s & 0xff)) +#define CHS2STAR(c,h,s) (((c<<16) & LMASK)|((h<<8) & 0xff00)|(s & 0xff)) /* convert STAR value to number of sectors */ -#define STAR2SEC(star,spt,spc) ((star&0xff)+(((star>>8)&0xff)*spt)+((star>>16)*spc)) +#define STAR2SEC(star,spt,spc) ((star&0xff)+(((star>>8)&0xff)*spt)+(((star>>16)&0xffff)*spc)) /* convert STAR value to number of heads or tracks */ -#define STAR2TRK(star,tpc) ((star >> 16) * tpc + ((star >> 8) & 0x0ff)) +#define STAR2TRK(star,tpc) (((star>>16)&0xffff)*tpc+((star>>8)&0x0ff)) /* convert STAR value to number of cylinders */ -#define STAR2CYL(star) ((star >> 16) & 0xffff) +#define STAR2CYL(star) ((star>>16)&RMASK) /* convert byte value to number of sectors mod sector size */ #define BYTES2SEC(bytes,ssize) (((bytes) + (ssize-1)) >> 10) /* get sectors per track for specified type */ #define SPT(type) (scfi_type[type].spt) -/* get sectors per cylinderfor specified type */ +/* get sectors per cylinder for specified type */ #define SPC(type) (scfi_type[type].spt*scfi_type[type].nhds) +/* get number of tracks for specified type */ +#define TRK(type) (scfi_type[type].cyl*scfi_type[type].nhds) /* get number of cylinders for specified type */ #define CYL(type) (scfi_type[type].cyl) /* get number of heads for specified type */ @@ -77,22 +84,20 @@ bits 0-7 - Flags bit 3 - 0=Reserved bit 4 - 1=Drive not present bit 5 - 1=Dual Port - bit 6 - 0=Reserved - bit 7 - 0=Reserved + bit 6&7 - 0=Reserved bits 8-15 - sector count (sectors per track)(F16=16, F20=20) bits 16-23 - MHD Head count (number of heads on MHD) bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option of mini-module) */ - /* 224 word INCH Buffer layout */ /* 128 word subchannel status storage (SST) */ /* 66 words of program status queue (PSQ) */ /* 26 words of scratchpad */ /* 4 words of label buffer registers */ -#define CMD u3 +#define CMD u3 /* u3 */ /* in u3 is device command code and status */ #define DSK_CMDMSK 0x00ff /* Command being run */ @@ -106,7 +111,8 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option #define DSK_BUSY 0x8000 /* Disk is busy */ /* commands */ #define DSK_INCH 0x00 /* Initialize channel */ -#define DSK_INCH2 0xf0 /* Initialize channel for processing */ +#define DSK_ICH 0xFF /* Initialize controller */ +#define DSK_INCH2 0xF0 /* Initialize channel for processing */ #define DSK_WD 0x01 /* Write data */ #define DSK_RD 0x02 /* Read data */ #define DSK_NOP 0x03 /* No operation */ @@ -129,6 +135,7 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option #define DSK_XRM 0x5F /* Reset reserve track mode */ #define DSK_RAP 0xA2 /* Read angular positions */ #define DSK_TESS 0xAB /* Test STAR (subchannel target address register) */ +#define DSK_REC 0xB2 /* Read ECC correction mask */ #define DSK_ICH 0xFF /* Initialize Controller */ #define STAR u4 @@ -175,17 +182,41 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option #define SNS_DADE 0x40 /* Disc addressing or seek error */ #define SNS_BUCK 0x20 /* Buffer check */ #define SNS_ECCS 0x10 /* ECC error in sector label */ -#define SNS_ECCD 0x08 /* ECC error iin data */ +#define SNS_ECCD 0x08 /* ECC error in data */ #define SNS_ECCT 0x04 /* ECC error in track label */ #define SNS_RTAE 0x02 /* Reserve track access error */ #define SNS_UESS 0x01 /* Uncorrectable ECC error */ +#define SNS2 us9 +/* us9 */ +/* us9 holds bytes 4 & 5 of the status for the drive */ + +/* Sense byte 4 */ +#define SNS_SEND 0x8000 /* Seek End */ +#define SNS_USEL 0x4000 /* Unit Selected */ +#define SNS_SPC0 0x2000 /* Sector Pulse Count B0 */ +#define SNS_SPC1 0x1000 /* Sector Pulse Count B1 */ +#define SNS_SPC2 0x0800 /* Sector Pulse Count B2 */ +#define SNS_SPC3 0x0400 /* Sector Pulse Count B3 */ +#define SNS_SPC4 0x0200 /* Sector Pulse Count B4 */ +#define SNS_SPC5 0x0100 /* Sector Pulse Count B5 */ + +/* Sense byte 5 */ +#define SNS_FLT 0x80 /* Disk Drive fault */ +#define SNS_SKER 0x40 /* Seek error */ +#define SNS_ONC 0x20 /* On Cylinder */ +#define SNS_UNR 0x10 /* Unit Ready */ +#define SNS_WRP 0x08 /* Write Protected */ +#define SNS_BUSY 0x04 /* Drive is busy */ +#define SNS_NU1 0x02 /* Spare 1 */ +#define SNS_NU2 0x01 /* Spare 2 */ + #define CHS u6 /* u6 holds the current cyl, hd, sec for the drive */ /* this attribute information is provided by the INCH command */ /* for each device and is not used. It is reconstructed from */ -/* the disk_t structure data for the assigned disk */ +/* the scfi_t structure data for the assigned disk */ /* bits 0-7 - Flags bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option @@ -209,7 +240,7 @@ struct scfi_t const char *name; /* Device ID Name */ uint16 nhds; /* Number of heads */ uint16 ssiz; /* sector size in words */ - uint16 spt; /* # sectors per track(cylinder) */ + uint16 spt; /* # sectors per track(head) */ uint16 ucyl; /* Number of cylinders used */ uint16 cyl; /* Number of cylinders on disk */ uint8 type; /* Device type code */ @@ -218,30 +249,44 @@ struct scfi_t /* = 1 1024 byte blk */ /* not used on UDP/DPII */ } +/* BM SIZ TOT AL U */ +/* DF0B, 1, 8, 20, 192, 1, 1712, 54760, SF336 */ +/* DF0C, 1, 8, 20, 192, 1, 4082, 130612, SG102 */ +/* DF0D, 1, 8, 20, 192, 1, 3491, 111705, SG654 */ +/* DF0B, 1, 8, 20, 192, 1, 1711, 54752, SG038 */ +/* DF0C, 1, 8, 20, 192, 1, 5464, 174848, SG120 */ +/* DF0D, 1, 8, 20, 192, 1, 3491, 111680, SG076 */ scfi_type[] = { /* Class F Disc Devices */ /* MPX SCSI disks for SCFI controller */ - {"MH1GB", 1, 192, 40, 34960, 34960, 0x40}, /*0 69920 1000M */ - {"SG038", 1, 192, 20, 21900, 21900, 0x40}, /*1 21900 38M */ - {"SG120", 1, 192, 40, 34970, 34970, 0x40}, /*2 69940 1200M */ - {"SG076", 1, 192, 20, 46725, 46725, 0x40}, /*3 46725 760M */ + {"MH1GB", 1, 192, 40, 34960, 34960, 0x40}, /*0 69920 1000M */ + {"SG038", 1, 192, 20, 21900, 21900, 0x40}, /*1 21900 38M */ + {"SG120", 1, 192, 40, 34970, 34970, 0x40}, /*2 69940 1200M */ + {"SG076", 1, 192, 20, 46725, 46725, 0x40}, /*3 46725 760M */ {NULL, 0} }; uint16 scfi_preio(UNIT *uptr, uint16 chan); -uint16 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); +uint16 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); uint16 scfi_haltio(UNIT *uptr); -t_stat scfi_srv(UNIT *); -t_stat scfi_boot(int32 unitnum, DEVICE *); +uint16 scfi_iocl(CHANP *chp, int32 tic_ok); +t_stat scfi_srv(UNIT *uptr); +t_stat scfi_boot(int32 unitnum, DEVICE *dptr); void scfi_ini(UNIT *, t_bool); t_stat scfi_reset(DEVICE *); t_stat scfi_attach(UNIT *, CONST char *); t_stat scfi_detach(UNIT *); t_stat scfi_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc); -t_stat scfi_get_type(FILE * st, UNIT *uptr, int32 v, CONST void *desc); +t_stat scfi_get_type(FILE *st, UNIT *uptr, int32 v, CONST void *desc); t_stat scfi_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); const char *scfi_description (DEVICE *dptr); +extern uint32 inbusy; +extern uint32 outbusy; +extern uint32 readfull(CHANP *chp, uint32 maddr, uint32 *word); +extern int irq_pend; /* go scan for pending int or I/O */ +extern UNIT itm_unit; +extern uint32 PSD[]; /* PSD */ /* channel program information */ CHANP sda_chp[NUM_UNITS_SCFI] = {0}; @@ -251,7 +296,7 @@ MTAB scfi_mod[] = { &scfi_set_type, &scfi_get_type, NULL, "Type of disk"}, {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, &show_dev_addr, NULL, "Device channel address"}, - {0} + {0}, }; UNIT sda_unit[] = { @@ -266,31 +311,33 @@ UNIT sda_unit[] = { {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x470)}, /* 7 */ }; -//DIB sda_dib = {scfi_preio, scfi_startcmd, NULL, NULL, NULL, scfi_ini, sda_unit, sda_chp, NUM_UNITS_SCFI, 0x0f, 0x0400, 0, 0, 0}; - DIB sda_dib = { scfi_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ scfi_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + scfi_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ + NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + scfi_iocl, /* uint16 (*iocl_io)(CHANP *chp, int32 tik_ok)) */ /* Process IOCL */ scfi_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 */ + NULL, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ NUM_UNITS_SCFI, /* uint8 numunits */ /* number of units defined */ - 0xF0, /* uint8 mask */ /* 16 devices - device mask */ + 0x70, /* uint8 mask */ /* 16 devices - device mask */ 0x0400, /* uint16 chan_addr */ /* parent channel address */ 0, /* uint32 chan_fifo_in */ /* fifo input index */ 0, /* uint32 chan_fifo_out */ /* fifo output index */ - {0} /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ + {0}, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ }; DEVICE sda_dev = { - "SDA", sda_unit, NULL, scfi_mod, + "SDA", sda_unit, NULL/*sda_reg*/, scfi_mod, NUM_UNITS_SCFI, 16, 24, 4, 16, 32, NULL, NULL, &scfi_reset, &scfi_boot, &scfi_attach, &scfi_detach, /* ctxt is the DIB pointer */ - &sda_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, + &sda_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS|DEV_DISK, 0, dev_debug, NULL, NULL, &scfi_help, NULL, NULL, &scfi_description }; @@ -310,31 +357,33 @@ UNIT sdb_unit[] = { {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC70)}, /* 7 */ }; -//DIB sdb_dib = {scfi_preio, scfi_startcmd, NULL, NULL, NULL, scfi_ini, sdb_unit, sdb_chp, NUM_UNITS_SCFI, 0x0f, 0x0c00, 0, 0, 0}; - DIB sdb_dib = { scfi_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ scfi_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + scfi_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ + NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + scfi_iocl, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ scfi_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ sdb_unit, /* UNIT* units */ /* Pointer to units structure */ sdb_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NULL, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ NUM_UNITS_SCFI, /* uint8 numunits */ /* number of units defined */ - 0xF0, /* uint8 mask */ /* 16 devices - device mask */ + 0x70, /* uint8 mask */ /* 16 devices - device mask */ 0x0C00, /* uint16 chan_addr */ /* parent channel address */ 0, /* uint32 chan_fifo_in */ /* fifo input index */ 0, /* uint32 chan_fifo_out */ /* fifo output index */ - 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ + {0}, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ }; DEVICE sdb_dev = { - "SDB", sdb_unit, NULL, scfi_mod, + "SDB", sdb_unit, NULL, /*sdb_reg*/, scfi_mod, NUM_UNITS_SCFI, 16, 24, 4, 16, 32, NULL, NULL, &scfi_reset, &scfi_boot, &scfi_attach, &scfi_detach, /* ctxt is the DIB pointer */ - &sdb_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, + &sdb_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS|DEV_DISK, 0, dev_debug, NULL, NULL, &scfi_help, NULL, NULL, &scfi_description }; #endif @@ -342,10 +391,10 @@ DEVICE sdb_dev = { /* convert sector disk address to star values (c,h,s) */ uint32 scfisec2star(uint32 daddr, int type) { - int32 sec = daddr % scfi_type[type].spt; /* get sector value */ - int32 spc = scfi_type[type].nhds * scfi_type[type].spt; /* sec per cyl */ - int32 cyl = daddr / spc; /* cylinders */ - int32 hds = (daddr % spc) / scfi_type[type].spt; /* heads */ + uint32 sec = daddr % scfi_type[type].spt; /* get sector value */ + uint32 spc = scfi_type[type].nhds * scfi_type[type].spt; /* sec per cyl */ + uint32 cyl = daddr / spc; /* cylinders */ + uint32 hds = (daddr % spc) / scfi_type[type].spt; /* heads */ /* now return the star value */ return (CHS2STAR(cyl,hds,sec)); /* return STAR */ @@ -358,73 +407,375 @@ uint16 scfi_preio(UNIT *uptr, uint16 chan) uint16 chsa = GET_UADDR(uptr->CMD); int unit = (uptr - dptr->units); - sim_debug(DEBUG_CMD, dptr, "scfi_preio CMD %08x unit=%02x\n", uptr->CMD, unit); + sim_debug(DEBUG_CMD, dptr, "scfi_preio CMD %08x unit %02x\n", uptr->CMD, unit); if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */ return SNS_BSY; } + sim_debug(DEBUG_CMD, dptr, "scfi_preio unit %02x chsa %04x OK\n", unit, chsa); - return 0; /* good to go */ + return SCPE_OK; /* good to go */ +} + +/* load in the IOCD and process the commands */ +/* return = 0 OK */ +/* return = 1 error, chan_status will have reason */ +uint16 scfi_iocl(CHANP *chp, int32 tic_ok) +{ + uint32 word1 = 0; + uint32 word2 = 0; + int32 docmd = 0; +// DIB *dibp = dib_unit[chp->chan_dev];/* get the DIB pointer */ + UNIT *uptr = chp->unitptr; /* get the unit ptr */ + uint16 chan = get_chan(chp->chan_dev); /* our channel */ + uint16 devstat = 0; + DEVICE *dptr = get_dev(uptr); + + /* check for valid iocd address if 1st iocd */ + if (chp->chan_info & INFO_SIOCD) { /* see if 1st IOCD in channel prog */ + if (chp->chan_caw & 0x3) { /* must be word bounded */ + sim_debug(DEBUG_EXP, dptr, + "scfi_iocl iocd bad address chan %02x caw %06x\n", + chan, chp->chan_caw); + chp->ccw_addr = chp->chan_caw; /* set the bad iocl address */ + chp->chan_status |= STATUS_PCHK; /* program check for invalid iocd addr */ + uptr->SNS |= SNS_INAD; /* invalid address status */ + return 1; /* error return */ + } + } +loop: + sim_debug(DEBUG_EXP, dptr, + "scfi_iocl @%06x entry PSD %08x chan_status[%04x] %04x\n", + chp->chan_caw, PSD[0], chan, chp->chan_status); + + /* Abort if we have any errors */ + if (chp->chan_status & STATUS_ERROR) { /* check channel error status */ + sim_debug(DEBUG_EXP, dptr, + "scfi_iocl ERROR1 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* return error */ + } + + /* 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, dptr, + "scfi_iocl ERROR2 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, dptr, + "scfi_iocl ERROR3 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + + sim_debug(DEBUG_CMD, dptr, + "scfi_iocl @%06x read ccw chan %02x IOCD wd 1 %08x wd 2 %08x\n", + chp->chan_caw, chan, word1, word2); + + chp->chan_caw = (chp->chan_caw & 0xfffffc) + 8; /* point to next IOCD */ + chp->ccw_cmd = (word1 >> 24) & 0xff; /* set command from IOCD wd 1 */ + + if (!MEM_ADDR_OK(word1 & MASK24)) { /* see if memory address invalid */ + chp->chan_status |= STATUS_PCHK; /* bad, program check */ + uptr->SNS |= SNS_INAD; /* invalid address status */ + sim_debug(DEBUG_EXP, dptr, + "scfi_iocl bad IOCD1 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + + chp->ccw_count = word2 & 0xffff; /* get 16 bit byte count from IOCD WD 2 */ + + /* validate the commands for the disk */ + switch (chp->ccw_cmd) { + case DSK_WD: case DSK_RD: case DSK_INCH: case DSK_NOP: case DSK_ICH: + case DSK_SCK: case DSK_XEZ: case DSK_LMR: case DSK_WSL: case DSK_RSL: + case DSK_IHA: case DSK_WTL: case DSK_RTL: case DSK_RAP: case DSK_TESS: + case DSK_FNSK: case DSK_REL: case DSK_RES: case DSK_POR: case DSK_TIC: + case DSK_REC: + case DSK_SNS: + break; + default: + chp->chan_status |= STATUS_PCHK; /* program check for invalid cmd */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected */ + sim_debug(DEBUG_EXP, dptr, + "scfi_iocl bad cmd chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + + if (chp->chan_info & INFO_SIOCD) { /* see if 1st IOCD in channel prog */ + /* 1st command can not be a TIC or NOP */ + if ((chp->ccw_cmd == DSK_NOP) || (chp->ccw_cmd == CMD_TIC)) { + chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ + sim_debug(DEBUG_EXP, dptr, + "scfi_iocl TIC/NOP bad cmd chan_status[%04x] %04x\n", + chan, chp->chan_status); + return 1; /* error return */ + } + } + + /* TIC can't follow TIC or be first in command chain */ + /* diags send bad commands for testing. Use all of op */ + if (chp->ccw_cmd == CMD_TIC) { + if (tic_ok) { + if (((word1 & MASK24) == 0) || (word1 & 0x3)) { + sim_debug(DEBUG_EXP, dptr, + "scfi_iocl tic cmd bad address chan %02x tic caw %06x IOCD wd 1 %08x\n", + chan, chp->chan_caw, word1); + chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ + chp->chan_caw = word1 & MASK24; /* get new IOCD address */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ + uptr->SNS |= SNS_INAD; /* invalid address status */ + return 1; /* error return */ + } + tic_ok = 0; /* another tic not allowed */ + chp->chan_caw = word1 & MASK24; /* get new IOCD address */ + sim_debug(DEBUG_CMD, dptr, + "scfi_iocl 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_caw = word1 & MASK24; /* get new IOCD address */ + chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ + if (((word1 & MASK24) == 0) || (word1 & 0x3)) + uptr->SNS |= SNS_INAD; /* invalid address status */ + sim_debug(DEBUG_EXP, dptr, + "scfi_iocl TIC ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + + /* Check if we had data chaining in previous iocd */ + if ((chp->chan_info & INFO_SIOCD) || /* see if 1st IOCD in channel prog */ + ((chp->ccw_flags & FLAG_DC) == 0)) { /* last IOCD have DC set? */ + sim_debug(DEBUG_CMD, dptr, + "scfi_iocl @%06x DO CMD 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 */ + chp->ccw_flags = (word2 >> 16) & 0xf000; /* get flags from bits 0-4 of WD 2 of IOCD */ + chp->chan_status = 0; /* clear status for next IOCD */ + /* make a 24 bit address */ + chp->ccw_addr = word1 & MASK24; /* set the data/seek address */ + + /* validate parts of IOCD2 that are reserved */ + if (word2 & 0x0fff0000) { /* bits 5-15 must be zero */ + chp->chan_status |= STATUS_PCHK; /* program check for invalid iocd */ + sim_debug(DEBUG_EXP, dptr, + "scfi_iocl IOCD2 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + +#ifndef NOT_FOR_EVERYONE + /* DC can only be used with a read/write cmd */ + if (chp->ccw_flags & FLAG_DC) { + if ((chp->ccw_cmd != DSK_RD) && (chp->ccw_cmd != DSK_WD)) { + chp->chan_status |= STATUS_PCHK; /* program check for invalid DC */ + uptr->SNS |= SNS_CHER; /* chaining error */ + sim_debug(DEBUG_EXP, dptr, + "scfi_iocl DC ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + } +#endif + + chp->chan_byte = BUFF_BUSY; /* busy & no bytes transferred yet */ + + sim_debug(DEBUG_XIO, dptr, + "scfi_iocl @%06x read docmd %01x addr %06x count %04x chan %04x ccw_flags %04x\n", + chp->chan_caw, docmd, chp->ccw_addr, chp->ccw_count, chan, chp->ccw_flags); + + if (docmd) { /* see if we need to process a command */ + DIB *dibp = dib_unit[chp->chan_dev]; /* get the DIB pointer */ + + uptr = chp->unitptr; /* get the unit ptr */ + if (dibp == 0 || uptr == 0) { + chp->chan_status |= STATUS_PCHK; /* program check if it is */ + return 1; /* if none, error */ + } + + sim_debug(DEBUG_XIO, dptr, + "scfi_iocl @%06x before start_cmd chan %04x status %04x count %04x SNS %08x\n", + chp->chan_caw, chan, chp->chan_status, chp->ccw_count, uptr->u5); + + /* call the device startcmd function to process the current command */ + /* just replace device status bits */ + devstat = dibp->start_cmd(uptr, chan, chp->ccw_cmd); + chp->chan_status = (chp->chan_status & 0xff00) | devstat; + chp->chan_info &= ~INFO_SIOCD; /* show not first IOCD in channel prog */ + + sim_debug(DEBUG_XIO, dptr, + "scfi_iocl @%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_ERROR)) { + chp->chan_status |= STATUS_CEND; /* channel end status */ + chp->ccw_flags = 0; /* no flags */ + /* see if chan_end already called */ + if (chp->chan_byte == BUFF_NEXT) { + sim_debug(DEBUG_EXP, dptr, + "scfi_iocl BUFF_NEXT ERROR chp %p chan_byte %04x\n", + chp, chp->chan_byte); + } else { + chp->chan_byte = BUFF_NEXT; /* have main pick us up */ + sim_debug(DEBUG_EXP, dptr, + "scfi_iocl bad status chan %04x status %04x cmd %02x\n", + chan, chp->chan_status, chp->ccw_cmd); + RDYQ_Put(chp->chan_dev); /* queue us up */ + sim_debug(DEBUG_EXP, dptr, + "scfi_iocl continue wait chsa %04x status %08x\n", + chp->chan_dev, chp->chan_status); + } + } else + + /* NOTE this code needed for MPX 1.X to run! */ + /* see if command completed */ + /* we have good status */ + if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { + uint16 chsa = GET_UADDR(uptr->u3); /* get channel & sub address */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ + sim_debug(DEBUG_XIO, dptr, + "scfi_iocl @%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); + } + } + /* the device processor returned OK (0), so wait for I/O to complete */ + /* nothing happening, so return */ + sim_debug(DEBUG_XIO, dptr, + "scfi_iocl @%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 */ } uint16 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uint16 chsa = GET_UADDR(uptr->CMD); DEVICE *dptr = get_dev(uptr); - int unit = (uptr - dptr->units); + int32 unit = (uptr - dptr->units); CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ sim_debug(DEBUG_CMD, dptr, - "scfi_startcmd unit %02x cmd %04x CMD %08x\n", - unit, cmd, uptr->CMD); + "scfi_startcmd chsa %04x unit %02x cmd %02x CMD %08x\n", + chsa, unit, cmd, uptr->CMD); if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + sim_debug(DEBUG_CMD, dptr, "scfi_startcmd unit %02x not attached\n", unit); uptr->SNS |= SNS_INTVENT; /* unit intervention required */ if (cmd != DSK_SNS) /* we are completed with unit check status */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; } if ((uptr->CMD & DSK_CMDMSK) != 0) { - uptr->CMD |= DSK_BUSY; /* Flag we we are busy */ + sim_debug(DEBUG_CMD, dptr, "scfi_startcmd unit %02x busy\n", unit); + uptr->CMD |= DSK_BUSY; /* Flag we are busy */ return SNS_BSY; } - if ((uptr->CMD & 0xff00) != 0) { /* if any status info, we are busy */ - return SNS_BSY; - } - sim_debug(DEBUG_CMD, dptr, "scfi_startcmd CMD 2 unit=%02x cmd %02x\n", unit, cmd); + uptr->SNS2 |= SNS_USEL; /* unit selected */ + sim_debug(DEBUG_CMD, dptr, "scfi_startcmd CMD continue unit=%02x cmd %02x iocla %06x cnt %04x\n", + unit, cmd, chp->chan_caw, chp->ccw_count); /* Unit is online, so process a command */ switch (cmd) { - case DSK_INCH: /* INCH 0x00 */ + case DSK_INCH: /* INCH cmd 0x0 */ sim_debug(DEBUG_CMD, dptr, - "scfi_startcmd starting INCH %06x cmd, chsa %04x MemBuf %08x cnt %04x\n", - uptr->u4, chsa, chp->ccw_addr, chp->ccw_count); + "scfi_startcmd starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n", + chp->chan_inch_addr, chsa, chp->ccw_addr, chp->ccw_count); - uptr->CMD |= DSK_INCH2; /* use 0xf0 for inch, just need int */ + uptr->SNS &= ~SNS_CMDREJ; /* not rejected yet */ + uptr->CMD |= DSK_INCH2; /* use 0xF0 for inch, just need int */ +#ifdef FAST_FOR_UTX sim_activate(uptr, 20); /* start things off */ - return 0; +#else + sim_activate(uptr, 250); /* start things off */ +#endif + return SCPE_OK; /* good to go */ break; + case DSK_NOP: /* NOP 0x03 */ + if ((cmd == DSK_NOP) && + (chp->chan_info & INFO_SIOCD)) { /* is NOP 1st IOCD? */ + chp->chan_caw -= 8; /* backup iocd address for diags */ + break; /* yes, can't be 1st */ + } + case DSK_ICH: /* 0xFF Initialize controller */ + if ((cmd == DSK_ICH) && + (chp->ccw_count != 896)) /* count must be 896 to be valid */ + break; case DSK_SCK: /* Seek command 0x07 */ - case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ + case DSK_XEZ: /* Rezero & Read IPL record 0x37 */ case DSK_WD: /* Write command 0x01 */ case DSK_RD: /* Read command 0x02 */ - case DSK_LMR: /* read mode register */ - case DSK_NOP: /* NOP 0x03 */ + case DSK_LMR: /* read mode register 0x1F */ + case DSK_WSL: /* WSL 0x31 */ + case DSK_RSL: /* RSL 0x32 */ + case DSK_IHA: /* 0x47 Increment head address */ + case DSK_WTL: /* WTL 0x51 */ + case DSK_RTL: /* RTL 0x52 */ + case DSK_RAP: /* 0xA2 Read angular positions */ + case DSK_TESS: /* TESS 0xAB Test STAR */ + case DSK_FNSK: /* 0x0B Format for no skip */ + case DSK_REC: /* 0xB2 Read ECC correction mask */ + case DSK_RES: /* 0x23 Reserve */ + case DSK_REL: /* 0x33 Release */ + uptr->SNS &= ~MASK24; /* clear data & leave mode */ + uptr->SNS2 = (SNS_UNR|SNS_ONC|SNS_USEL);/* reset status to on cyl & ready */ case DSK_SNS: /* Sense 0x04 */ - sim_debug(DEBUG_CMD, dptr, - "scfi_startcmd starting disk seek r/w cmd %02x chsa %04x\n", cmd, chsa); uptr->CMD |= cmd; /* save cmd */ + sim_debug(DEBUG_CMD, dptr, + "scfi_startcmd starting disk cmd %02x chsa %04x\n", + cmd, chsa); +#ifdef FAST_FOR_UTX sim_activate(uptr, 20); /* start things off */ - return 0; +#else + sim_activate(uptr, 250); /* start things off */ +#endif + return SCPE_OK; /* good to go */ break; } + sim_debug(DEBUG_CMD, dptr, - "scfi_startcmd done with scfi_startcmd %02x chsa %04x SNS %08x\n", + "scfi_startcmd done with bad disk cmd %02x chsa %04x SNS %08x\n", cmd, chsa, uptr->SNS); - if (uptr->SNS & 0xff) /* any other cmd is error */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - sim_activate(uptr, 20); /* start things off */ - return SNS_CHNEND|SNS_DEVEND; + uptr->SNS |= SNS_CMDREJ; /* cmd rejected */ + return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; /* return error */ +} + +/* Handle haltio transfers for disk */ +uint16 scfi_haltio(UNIT *uptr) { + uint16 chsa = GET_UADDR(uptr->CMD); + DEVICE *dptr = get_dev(uptr); + int cmd = uptr->CMD & DSK_CMDMSK; + CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + + sim_debug(DEBUG_EXP, dptr, "scfi_haltio enter chsa %04x cmd = %02x\n", chsa, cmd); + + /* terminate any input command */ + /* UTX wants SLI bit, but no unit exception */ + /* status must not have an error bit set */ + /* otherwise, UTX will panic with "bad status" */ + if ((uptr->CMD & DSK_CMDMSK) != 0) { /* is unit busy */ + sim_debug(DEBUG_CMD, dptr, + "scfi_haltio HIO chsa %04x cmd = %02x ccw_count %02x\n", chsa, cmd, chp->ccw_count); + /* stop any I/O and post status and return error status */ + chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* stop any chaining */ + uptr->CMD &= LMASK; /* make non-busy */ + uptr->SNS2 |= (SNS_ONC|SNS_UNR); /* on cylinder & ready */ + sim_cancel(uptr); /* clear the input timer */ + sim_debug(DEBUG_CMD, dptr, + "scfi_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* force end */ + return SCPE_IOERR; + } + uptr->CMD &= LMASK; /* make non-busy */ + uptr->SNS2 |= (SNS_ONC|SNS_UNR); /* on cylinder & ready */ + sim_debug(DEBUG_CMD, dptr, + "scfi_haltio HIO I/O not busy chsa %04x cmd = %02x\n", chsa, cmd); + return SCPE_OK; /* not busy */ } /* Handle processing of disk requests. */ @@ -432,65 +783,86 @@ t_stat scfi_srv(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->CMD); DEVICE *dptr = get_dev(uptr); - /* get pointer to Dev Info Blk for this device */ - CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ + CHANP *chp = find_chanp_ptr(chsa);/* get channel prog pointer */ int cmd = uptr->CMD & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); - uint32 trk, cyl, sec; + uint32 tcyl=0, trk=0, cyl=0, sec=0; int unit = (uptr - dptr->units); - int len=0; + int len = chp->ccw_count; int i; + uint32 mema; /* memory address */ uint8 ch; - uint16 ssize = scfi_type[type].ssiz*4; /* Size of one sector in bytes */ - int32 tstart = 0; /* Location of start of cyl/track/sect in data */ - uint8 buf2[1024]; + uint16 ssize = scfi_type[type].ssiz * 4; /* disk sector size in bytes */ + uint32 tstart; uint8 buf[1024]; + uint8 buf2[1024]; - sim_debug(DEBUG_DETAIL, &sda_dev, + sim_debug(DEBUG_CMD, dptr, "scfi_srv entry unit %02x CMD %08x chsa %04x count %04x %x/%x/%x \n", unit, uptr->CMD, chsa, chp->ccw_count, STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ uptr->SNS |= SNS_INTVENT; /* unit intervention required */ - if (cmd != DSK_SNS) /* we are completed with unit check status */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + if (cmd != DSK_SNS) { /* we are completed with unit check status */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + } } sim_debug(DEBUG_CMD, dptr, "scfi_srv cmd=%02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); + switch (cmd) { case 0: /* No command, stop disk */ break; - case DSK_INCH2: /* use 0xff for inch, just need int */ - { - uint32 mema; /* memory address */ -// uint32 i, j; - uint32 i; - + case DSK_ICH: /* 0xFF Initialize controller */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ len = chp->ccw_count; /* INCH command count */ mema = chp->ccw_addr; /* get inch or buffer addr */ sim_debug(DEBUG_CMD, dptr, - "scfi_srv starting INCH cmd, chsa %04x MemBuf %06x cnt %04x\n", - chsa, chp->ccw_addr, chp->ccw_count); + "scfi_srv cmd CONT INCH %06x chsa %04x addr %06x count %04x completed\n", + chp->chan_inch_addr, chsa, mema, chp->ccw_count); + /* to use this inch method, byte count must be 897 */ + if (len != 896) { + /* we have invalid count, error, bail out */ + uptr->SNS |= SNS_CMDREJ; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + /* now call set_inch() function to write and test inch buffer addresses */ + tstart = set_inch(uptr, mema); /* new address */ + if ((tstart == SCPE_MEM) || (tstart == SCPE_ARG)) { /* any error */ + /* we have error, bail out */ + uptr->SNS |= SNS_CMDREJ; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case DSK_INCH2: /* use 0xF0 for inch, just need int */ + len = chp->ccw_count; /* INCH command count */ + mema = chp->ccw_addr; /* get inch or buffer addr */ + sim_debug(DEBUG_CMD, dptr, + "scfi_srv starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n", + chp->chan_inch_addr, chsa, chp->ccw_addr, chp->ccw_count); /* mema has IOCD word 1 contents. For the disk processor it contains */ /* a pointer to the INCH buffer followed by 8 drive attribute words that */ /* contains the flags, sector count, MHD head count, and FHD count */ /* len has the byte count from IOCD wd2 and should be 0x24 (36) */ - /* the INCH buffer address must be set for the parrent channel as well */ + /* the INCH buffer address must be set for the parent channel as well */ /* as all other devices on the channel. Call set_inch() to do this for us */ /* just return OK and channel software will use u4 as status buffer addr */ - len = chp->ccw_count; /* INCH command count */ - if (len != 36) { - /* we have invalid count, error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; + /* we have invalid count, error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; } /* read all 36 bytes, stopping every 4 bytes to make words */ @@ -498,12 +870,13 @@ t_stat scfi_srv(UNIT *uptr) /* the next 8 words have drive data for each unit */ /* WARNING 8 drives must be defined for this controller */ /* so we will not have a map fault */ -// for (i=0, j=0; i < 36; i++) { for (i=0; i < 36; i++) { if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -514,58 +887,140 @@ t_stat scfi_srv(UNIT *uptr) (buf[2]<<8) | (buf[3]); else /* drive attribute registers */ -// daws[j++] = (buf[i-3]<<24) | (buf[i-2]<<16) -// | (buf[i-1]<<8) | (buf[i]); - /* may want to use this later */ + /* may want to use this later */ /* clear warning errors */ tstart = (buf[i-3]<<24) | (buf[i-2]<<16) | (buf[i-1]<<8) | (buf[i]); } } - /* now call set_inch() function to write and test inch bybber addresses */ + /* now call set_inch() function to write and test inch buffer addresses */ i = set_inch(uptr, mema); /* new address */ -#ifdef NOTYET - if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ + if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } -#endif - uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, - "scfi_srv cmd INCH chsa %04x addr %06x count %04x completed\n", - chsa, mema, chp->ccw_count); + "scfi_srv cmd INCH %06x chsa %04x addr %06x count %04x completed\n", + chp->chan_inch_addr, chsa, mema, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ - } break; + case DSK_RES: /* 0x23 Reserve */ + case DSK_REL: /* 0x33 Release */ + case DSK_POR: /* 0x43 Priority Override */ + case DSK_REC: /* 0xB2 Read ECC correction mask */ + case DSK_TESS: /* 0xAB Test STAR (subchannel target address register) */ + case DSK_FNSK: /* 0x0B Format for no skip */ + case DSK_RAP: /* 0xA2 Read angular positions */ + case DSK_IHA: /* 0x47 Increment head address */ + case DSK_RSL: /* RSL 0x32 */ + case DSK_WSL: /* WSL 0x31 write sector labels */ + case DSK_RTL: /* RTL 0x52 */ + case DSK_WTL: /* WTL 0x51 */ case DSK_NOP: /* NOP 0x03 */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ + /* diags want chan prog check and cmd reject if 1st cmd of IOCL */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "scfi_srv cmd NOP chsa %04x count %04x completed\n", chsa, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; - case DSK_SNS: /* 0x4 */ - ch = uptr->SNS & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv sense unit=%02x 1 %02x\n", unit, ch); - chan_write_byte(chsa, &ch) ; + case DSK_SNS: /* 0x04 */ /* Sense */ + sim_debug(DEBUG_CMD, dptr, "scfi_startcmd CMD sense\n"); + + /* count must be 12 or 14, if not prog check */ + if (len != 12 && len != 14) { + sim_debug(DEBUG_CMD, dptr, + "scfi_srv Sense bad count unit=%02x count%04x\n", unit, len); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK|STATUS_LENGTH); + break; + } + /* bytes 0,1 - Cyl entry from CHS reg */ + ch = (uptr->CHS >> 24) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv sense CHS b0 unit=%02x 1 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + ch = (uptr->CHS >> 16) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv sense CHS b1 unit=%02x 2 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + /* byte 2 - Track entry from CHS reg */ + ch = (uptr->CHS >> 8) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv sense CHS b2 unit=%02x 3 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + /* byte 3 - Sector entry from CHS reg */ + ch = (uptr->CHS) & 0xff; + sec = ch; + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv sense CHS b3 unit=%02x 4 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + + /* bytes 4 - mode reg, byte 0 of SNS */ + ch = (uptr->SNS >> 24) & 0xff; /* return the sense data */ + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv sense unit=%02x 1 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + /* bytes 5-7 - status bytes, bytes 1-3 of SNS */ + ch = (uptr->SNS >> 16) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv sense unit=%02x 2 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); ch = (uptr->SNS >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv sense unit=%02x 2 %02x\n", unit, ch); - chan_write_byte(chsa, &ch) ; - ch = 0; - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv sense unit=%02x 3 %02x\n", unit, ch); - chan_write_byte(chsa, &ch) ; - ch = unit; - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv sense unit=%02x 4 %02x\n", unit, ch); - chan_write_byte(chsa, &ch) ; - ch = 4; - sim_debug(DEBUG_CMD, dptr, "DISK SENSE %02x chars complete %08x, unit %02x\n", - ch, uptr->SNS, unit); - uptr->CMD &= ~(0xff00); + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv sense unit=%02x 3 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + ch = (uptr->SNS) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv sense unit=%02x 4 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + + /* bytes 8-11 - drive mode register entries from assigned disk */ + ch = scfi_type[type].type & 0x40; /* zero bits 0, 2-7 in type byte */ + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv datr unit=%02x 1 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + ch = scfi_type[type].spt & 0xff; /* get sectors per track */ + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv datr unit=%02x 2 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + ch = scfi_type[type].nhds & 0xff; /* get # MHD heads */ + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv datr unit=%02x 3 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + ch = 0; /* no FHD heads */ + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv datr unit=%02x 4 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + + /* bytes 12 & 13 are optional, so check if read done */ + /* TODO add drive status bits here */ + if ((test_write_byte_end(chsa)) == 0) { + /* bytes 12 & 13 contain drive related status */ + uptr->SNS2 |= (SNS_SEND|SNS_USEL); /* selected & seek end */ + /* bits 2-7 have sector pulse count */ + ch = ((sec * 2) % SPT(type)) & 0x3f;/* get index cnt */ + uptr->SNS2 = (uptr->SNS2 & 0xc0ff) | ((((uint32)ch) & 0x3f) << 8); + ch = (uptr->SNS2 >> 8) & 0xff; /* seek end and unit selected for now */ + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv dsr unit=%02x 1 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + + uptr->SNS2 |= (SNS_ONC|SNS_UNR); /* on cylinder & ready */ + ch = uptr->SNS2 & 0xff; /* drive on cylinder and ready for now */ + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv dsr unit=%02x 2 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + } + uptr->SNS &= 0xff000000; /* reset status */ + uptr->SNS2 = 0; /* reset status */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; @@ -575,64 +1030,101 @@ t_stat scfi_srv(UNIT *uptr) /* see if on cylinder yet */ if (STAR2CYL(uptr->STAR) == STAR2CYL(uptr->CHS)) { /* we are on cylinder, seek is done */ - sim_debug(DEBUG_CMD, dptr, "scfi_srv seek on cylinder unit=%02x %04x %04x\n", - unit, uptr->STAR >> 16, uptr->CHS >> 16); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + sim_debug(DEBUG_CMD, dptr, + "scfi_srv seek on cylinder unit %02x new %04x old %04x\n", + unit, uptr->STAR>>16, uptr->CHS>>16); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS2 |= (SNS_SEND|SNS_ONC); /* On cylinder & seek done */ /* we have already seeked to the required sector */ /* we do not need to seek again, so move on */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); - sim_activate(uptr, 20); +// return SCPE_OK; break; } else { - /* we have wasted enough time, we there */ + /* we have wasted enough time, we are there */ + /* we are on cylinder, seek is done */ + sim_debug(DEBUG_CMD, dptr, "scfi_srv seek over on cylinder unit=%02x %04x %04x\n", + unit, uptr->STAR >> 16, uptr->CHS >> 16); uptr->CHS = uptr->STAR; /* we are there */ - sim_activate(uptr, 10); +#ifdef FAST_FOR_UTX + sim_activate(uptr, 15); /* start things off */ +#else + sim_activate(uptr, 150); /* start things off */ +#endif break; } } /* not seeking, so start a new seek */ - /* Read in 4 character seek code */ + /* set buf data to current STAR values */ + tcyl = STAR2CYL(uptr->CHS); /* get current cyl */ + + /* the value is really a sector offset for the disk */ + /* but will treat as c/h/s for processing */ + /* the cyl, trk, and sect are ready to update */ + sim_debug(DEBUG_CMD, dptr, + "scfi_srv current STAR unit=%02x star %02x %02x %02x %02x\n", + unit, (uptr->CHS >> 24) & 0xff, (uptr->CHS >> 16) & 0xff, + (uptr->CHS >> 8) & 0xff, (uptr->CHS) & 0xff); + + if (len != 4) { + sim_debug(DEBUG_CMD, dptr, + "scfi_srv SEEK bad count unit %02x count %04x\n", unit, len); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK|STATUS_LENGTH); + break; + } + + /* Read in 4 character required seek code */ for (i = 0; i < 4; i++) { if (chan_read_byte(chsa, &buf[i])) { - /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + if (i == 0) { + sim_debug(DEBUG_DETAIL, dptr, + "scfi_srv seek error unit=%02x\n", unit); + /* we have error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_DADE; /* Disc addressing or seek error */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + chp->ccw_count = len; /* restore count, huh? */ + return SCPE_OK; + break; + } + /* just read the next byte */ } } + chp->ccw_count = len; /* restore count for diag, huh? */ /* the value is really a sector offset for the disk */ /* but will treat as c/h/s for processing */ /* the cyl, trk, and sect are ready to update */ sim_debug(DEBUG_CMD, dptr, "scfi_srv STAR unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); -rezero: - sim_debug(DEBUG_DETAIL, dptr, - "scfi_srv seek unit=%02x star %02x %02x %02x %02x\n", - unit, buf[0], buf[1], buf[2], buf[3]); /* save STAR (target sector) data in STAR */ uptr->STAR = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]); cyl = STAR2CYL(uptr->STAR); /* get the cylinder */ trk = buf[2]; /* get the track */ + sec = buf[3]; /* get sec */ sim_debug(DEBUG_DETAIL, dptr, - "scfi_srv SEEK %08x cyl %04x trk %02x sec %02x unit=%02x\n", - uptr->CMD, cyl&0xffff, trk, buf[3], unit); + "scfi_srv NEW SEEK cyl %04x trk %02x sec %02x unit=%02x\n", + cyl&0xffff, trk, buf[3], unit); /* Check if seek valid */ - if (cyl >= scfi_type[type].cyl || - trk >= scfi_type[type].nhds || - buf[3] >= scfi_type[type].spt) { + if (uptr->STAR >= CAP(type)) { - sim_debug(DEBUG_CMD, dptr, - "dsk_srv seek ERROR cyl %04x trk %02x sec %02x unit=%02x\n", + sim_debug(DEBUG_EXP, dptr, + "scfi_srv seek ERROR cyl %04x trk %02x sec %02x unit=%02x\n", cyl, trk, buf[3], unit); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; /* set error status */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_DADE; /* set error status */ + uptr->SNS2 |= (SNS_SKER|SNS_SEND); + + /* set new STAR value, even if invalid */ + uptr->CHS = uptr->STAR; /* we have an error, tell user */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* end command */ @@ -642,136 +1134,179 @@ rezero: /* calc the new sector address of data */ /* calculate file position in bytes of requested sector */ /* file offset in bytes */ - tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type); - uptr->CHS = CHS2STAR(STAR2CYL(uptr->CHS), trk, buf[3]); + tstart = uptr->STAR * SSB(type); + uptr->CHS = uptr->STAR; sim_debug(DEBUG_DETAIL, dptr, - "scfi_srv seek start %08x trk %04x sec %02x\n", + "scfi_srv seek start %06x trk %04x sec %02x\n", tstart, trk, buf[3]); /* just seek to the location where we will r/w data */ - if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* seek home */ - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv Error on seek to %08x\n", tstart); + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ + sim_debug(DEBUG_EXP, dptr, "scfi_srv Error on seek to %04x\n", tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; + break; } /* Check if already on correct cylinder */ /* if not, do a delay to slow things down */ - if (STAR2CYL(uptr->STAR) != STAR2CYL(uptr->CHS)) { + if (tcyl != cyl) { + int diff = ((int)tcyl - (int)cyl); + if (diff < 0) + diff = -diff; /* Do a fake seek to kill time */ uptr->CMD |= DSK_SEEKING; /* show we are seeking */ - sim_debug(DEBUG_DETAIL, dptr, - "scfi_srv seeking unit=%02x to cyl %04x trk %04x sec %04x\n", - unit, cyl, trk, buf[3]); - sim_activate(uptr, 20); + sim_debug(DEBUG_EXP, dptr, + "scfi_srv seeking unit=%02x to %04x/%02x/%02x from cyl %04x (%04x)\n", + unit, cyl, trk, buf[3], tcyl, cyl); +#ifdef FAST_FOR_UTX + sim_activate(uptr, 15); /* start things off */ +#else + sim_activate(uptr, 200+diff); /* start us off */ +#endif } else { /* we are on cylinder/track/sector, so go on */ sim_debug(DEBUG_DETAIL, dptr, - "scfi_srv calc sect addr seek start %08x cyl %04x trk %04x sec %02x\n", + "scfi_srv done seeking to %04x cyl %04x trk %02x sec %02x\n", tstart, cyl, trk, buf[3]); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + /* set new STAR value */ + uptr->CHS = uptr->STAR; + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); } - return SCPE_OK; + break; - case DSK_XEZ: /* Rezero & Read IPL record */ + case DSK_XEZ: /* 0x37 */ /* Rezero & Read IPL record */ - sim_debug(DEBUG_CMD, dptr, "RD REZERO IPL unit=%02x seek 0\n", unit); + sim_debug(DEBUG_CMD, dptr, "XEZ REZERO IPL unit=%02x seek 0\n", unit); /* Do a seek to 0 */ + tcyl = STAR2CYL(uptr->CHS); /* get current cyl */ uptr->STAR = 0; /* set STAR to 0, 0, 0 */ uptr->CHS = 0; /* set current CHS to 0, 0, 0 */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->CMD |= DSK_SCK; /* show as seek command */ tstart = 0; /* byte offset is 0 */ - /* Read in 1 dummy character for length to inhibit SLI posting */ - if (chan_read_byte(chsa, &buf[0])) { - /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + + /* 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, "scfi_srv Error on seek to %04x\n", tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } - /* zero stuff */ - buf[0] = buf[1] = buf[2] = buf[3] = 0; - goto rezero; /* merge with seek code */ + /* we are on cylinder/track/sector zero, so go on */ + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv done seek trk 0\n"); + uptr->CMD |= DSK_SEEKING; /* show we are seeking */ + sim_debug(DEBUG_EXP, dptr, + "scfi_srv XEZ seeking unit=%02x to cyl 0000 from cyl %04x\n", + unit, tcyl); + sim_activate(uptr, 15); /* start things off */ break; - case DSK_LMR: + case DSK_LMR: /* 0x1F */ sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x\n", unit); /* Read in 1 character of mode data */ if (chan_read_byte(chsa, &buf[0])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ; + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; } sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x old %x new %x\n", unit, (uptr->SNS)&0xff, buf[0]); - uptr->CMD &= ~(0xffff); /* remove old cmd */ - uptr->SNS &= 0x00ffffff; /* clear old mode data */ + uptr->CMD &= 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 */ - /* tstart has start of sector address in bytes */ + case DSK_RD: /* Read Data command 0x02 */ if ((uptr->CMD & DSK_READING) == 0) { /* see if we are reading data */ uptr->CMD |= DSK_READING; /* read from disk starting */ sim_debug(DEBUG_CMD, dptr, - "DISK READ starting unit=%02x CMD %08x count %04x\n", - unit, uptr->CMD, chp->ccw_count); + "DISK READ starting CMD %08x chsa %04x buffer %06x count %04x\n", + uptr->CMD, chsa, chp->ccw_addr, chp->ccw_count); } if (uptr->CMD & DSK_READING) { /* see if we are reading data */ - cyl = STAR2CYL(uptr->CHS); /* get current cyl */ - trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ - sec = uptr->CHS & 0xff; /* get sec */ - /* get sector offset */ - tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* get file offset in sectors */ + tstart = uptr->CHS; + /* file offset in bytes */ + tstart = tstart * SSB(type); + + /* 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, "scfi_srv READ, Error on seek to %04x\n", tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + + sim_debug(DEBUG_CMD, dptr, + "DISK READ reading CMD %08x chsa %04x tstart %04x buffer %06x count %04x\n", + uptr->CMD, chsa, tstart, chp->ccw_addr, chp->ccw_count); /* read in a sector of data from disk */ if ((len=sim_fread(buf, 1, ssize, uptr->fileref)) != ssize) { sim_debug(DEBUG_CMD, dptr, "Error %08x on read %04x of diskfile cyl %04x hds %02x sec %02x\n", - len, ssize, cyl, trk, sec); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + len, ssize, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } - sim_debug(DEBUG_CMD, dptr, "scfi_srv after READ chsa %04x count %04x\n", - chsa, chp->ccw_count); + sim_debug(DEBUG_CMD, dptr, + "scfi_srv after READ chsa %04x buffer %06x count %04x\n", + chsa, chp->ccw_addr, chp->ccw_count); + sim_debug(DEBUG_CMD, dptr, + "scfi_srv after READ buffer %06x count %04x data %02x%02x%02x%02x %02x%02x%02x%02x\n", +// chp->ccw_addr, chp->ccw_count, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); + chp->ccw_addr, chp->ccw_count, buf[1016], buf[1017], buf[1018], buf[1019], + buf[1020], buf[1021], buf[1022], buf[1023]); + uptr->CHS++; /* next sector number */ /* process the next sector of data */ for (i=0; iCMD &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - goto rddone; + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + sim_debug(DEBUG_CMD, dptr, + "SCFI Read %04x bytes leaving %04x from diskfile %04x/%02x/%02x\n", + i, chp->ccw_count, ((uptr->CHS)>>16)&0xffff, + ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + return SCPE_OK; } } sim_debug(DEBUG_CMD, dptr, - "DISK READ from sec end %04x bytes end %04x from diskfile /%04x/%02x/%02x tstart %08x\n", - len, ssize, cyl, trk, sec, tstart); + "SCFI READ %04x bytes leaving %4x to be read to %06x from diskfile %04x/%02x/%02x\n", + ssize, chp->ccw_count, chp->ccw_addr, + ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + + /* get sector offset */ + tstart = uptr->CHS; - /* tstart has file offset in sectors */ - tstart++; /* bump to next sector */ - /* convert sect back to chs value */ - uptr->CHS = scfisec2star(tstart, type); /* see if over end of disk */ - if (tstart >= CAP(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", STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->CHS = 0; /* reset cylinder position */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -779,111 +1314,157 @@ rezero: /* see if we are done reading data */ if (test_write_byte_end(chsa)) { - sim_debug(DEBUG_DATA, dptr, - "DISK Read complete Read %04x bytes from diskfile /%04x/%02x/%02x tstart %08x\n", - ssize, cyl, trk, sec, tstart); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + sim_debug(DEBUG_CMD, dptr, + "DISK Read complete for read from diskfile %04x/%02x/%02x\n", + STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - } else { - sim_debug(DEBUG_DATA, dptr, - "DISK sector read complete, %x bytes to go from diskfile /%04x/%02x/%02x\n", - chp->ccw_count, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); - sim_activate(uptr, 10); /* wait to read next sector */ - break; } -rddone: - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + + sim_debug(DEBUG_CMD, 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)); +#ifdef FAST_FOR_UTX + sim_activate(uptr, 15); /* start things off */ +#else + sim_activate(uptr, 150); /* wait to read next sector */ +#endif + break; } + uptr->CMD &= LMASK; /* remove old status bits & cmd */ break; - case DSK_WD: /* Write Data */ - /* tstart has start of sector address in bytes */ - + case DSK_WD: /* Write Data command 0x01 */ if ((uptr->CMD & DSK_WRITING) == 0) { /* see if we are writing data */ - uptr->CMD |= DSK_WRITING; /* write to disk starting */ sim_debug(DEBUG_CMD, dptr, - "DISK WRITE starting unit=%02x CMD %08x bytes %04x\n", - unit, uptr->CMD, len); + "DISK WRITE starting unit=%02x CMD %08x write %04x from %06x to %03x/%02x/%02x\n", + unit, uptr->CMD, chp->ccw_count, chp->ccw_addr, + ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + + if (uptr->SNS & 0xf0000000) { /* see if any mode bit 0-3 is set */ + uptr->SNS |= SNS_MOCK; /* mode check error */ + chp->chan_status |= STATUS_PCHK; /* channel prog check */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } + uptr->CMD |= DSK_WRITING; /* write to disk starting */ } if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */ - cyl = STAR2CYL(uptr->CHS); /* get current cyl */ - trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ - sec = uptr->CHS & 0xff; /* get sec */ - /* get sector offset */ - tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* get file offset in sectors */ + tstart = uptr->CHS; + /* file offset in bytes */ + tstart = tstart * SSB(type); + + /* 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, "scfi_srv WRITE, Error on seek to %04x\n", tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + } /* process the next sector of data */ - len = 0; /* used here as a flag for short read */ + tcyl = 0; /* used here as a flag for short read */ for (i=0; ichan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ /* if error on reading 1st byte, we are done writing */ - if (i == 0) { - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - sim_debug(DEBUG_DATA, dptr, - "DISK Wrote %04x bytes to diskfile cyl %04x hds %02x sec %02x tstart %08x\n", - ssize, cyl, trk, sec, tstart); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - goto wrdone; + if ((i == 0) || (chp->chan_status & STATUS_PCHK)) { + uptr->CMD &= 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, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + return SCPE_OK; } ch = 0; /* finish out the sector with zero */ - len++; /* show we have no more data to write */ + tcyl++; /* show we have no more data to write */ } buf2[i] = ch; /* save the char */ } + /* get file offset in sectors */ + tstart = uptr->CHS; + /* write the sector to disk */ if ((i=sim_fwrite(buf2, 1, ssize, uptr->fileref)) != ssize) { sim_debug(DEBUG_CMD, dptr, - "Error %08x on write %04x to diskfile cyl %04x hds %02x sec %02x\n", - i, ssize, cyl, trk, sec); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + "Error %08x on write %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", + i, ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } - if (len != 0) { /* see if done with write command */ - sim_debug(DEBUG_DATA, dptr, - "DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x tstart %08x\n", - ssize, cyl, trk, sec, tstart); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + + sim_debug(DEBUG_CMD, dptr, + "scfi_srv after WRITE buffer %06x count %04x data %02x%02x%02x%02x %02x%02x%02x%02x\n", + chp->ccw_addr, chp->ccw_count, buf2[1016], buf2[1017], buf2[1018], buf2[1019], + buf2[1020], buf2[1021], buf2[1022], buf2[1023]); + + sim_debug(DEBUG_CMD, dptr, + "DISK WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x\n", + len, ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + + uptr->CHS++; /* next sector number */ + if (tcyl != 0) { /* see if done with write command */ + sim_debug(DEBUG_CMD, dptr, + "DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", + ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; } - sim_debug(DEBUG_CMD, dptr, - "DISK WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x tstart %08x\n", - len, ssize, cyl, trk, sec, tstart); + /* get sector offset */ + tstart = uptr->CHS; - /* tstart has file offset in sectors */ - tstart++; /* bump to next sector */ - /* convert sect back to chs value */ - uptr->CHS = scfisec2star(tstart, type); /* see if over end of disk */ - if (tstart >= CAP(type)) { + if (tstart >= (uint32)CAP(type)) { /* EOM reached, abort */ sim_debug(DEBUG_CMD, dptr, - "DISK Write reached EOM for write to disk @ /%04x/%02x/%02x\n", + "DISK Write reached EOM for write to disk @ %04x/%02x/%02x\n", STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= 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 */ + + /* see if we are done reading data */ + if (test_write_byte_end(chsa)) { + sim_debug(DEBUG_CMD, dptr, + "DISK Write complete for read from diskfile %04x/%02x/%02x\n", + STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; + } + +#ifdef FAST_FOR_UTX + sim_activate(uptr, 15); /* start things off */ +#else + sim_activate(uptr, 150); /* wait to read next sector */ +#endif break; -wrdone: - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ } + uptr->CMD &= LMASK; /* remove old status bits & cmd */ break; default: sim_debug(DEBUG_CMD, dptr, "invalid command %02x unit %02x\n", cmd, unit); uptr->SNS |= SNS_CMDREJ; - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - return SNS_CHNEND|STATUS_PCHK; + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|STATUS_PCHK); /* return Prog Check */ break; } - sim_debug(DEBUG_CMD, dptr, - "scfi_srv done cmd %02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); + sim_debug(DEBUG_DETAIL, dptr, + "scfi_srv done cmd %02x chsa %04x chs %04x/%02x/%02x\n", + cmd, chsa, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); return SCPE_OK; } @@ -893,16 +1474,18 @@ void scfi_ini(UNIT *uptr, t_bool f) DEVICE *dptr = get_dev(uptr); int i = GET_TYPE(uptr->flags); - uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ -// uptr->SNS = ((uptr->SNS & 0x00ffffff) | (scfi_type[i].type << 24)); /* save mode value */ + /* start out at sector 0 */ + uptr->CHS = 0; /* set CHS to cyl/hd/sec = 0 */ + uptr->STAR = 0; /* set STAR to cyl/hd/sec = 0 */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ /* total sectors on disk */ - uptr->capac = CAP(i); /* disk size in sectors */ + uptr->capac = CAP(i); /* size in sectors */ - sim_debug(DEBUG_EXP, &sda_dev, "SDA init device %s on unit SDA%.1x cap %x\n", - dptr->name, GET_UADDR(uptr->CMD), uptr->CMD); + sim_debug(DEBUG_EXP, &sda_dev, "SDA init device %s on unit SDA%04x cap %x %d\n", + dptr->name, GET_UADDR(uptr->CMD), uptr->capac, uptr->capac); } -t_stat scfi_reset(DEVICE * dptr) +t_stat scfi_reset(DEVICE *dptr) { /* add reset code here */ return SCPE_OK; @@ -912,12 +1495,12 @@ t_stat scfi_reset(DEVICE * dptr) int scfi_format(UNIT *uptr) { int type = GET_TYPE(uptr->flags); DEVICE *dptr = get_dev(uptr); - int32 ssize = scfi_type[type].ssiz * 4; /* disk sector size in bytes */ - uint32 tsize = scfi_type[type].spt; /* get track size in sectors */ - uint32 csize = scfi_type[type].nhds * tsize; /* get cylinder size in sectors */ - uint32 cyl = scfi_type[type].cyl; /* get # cyl */ - uint32 cap = scfi_type[type].cyl * csize; /* disk capacity in sectors */ - uint32 cylv = cyl; /* number of cylinders */ + uint32 ssize = SSB(type); /* disk sector size in bytes */ + uint32 tsize = SPT(type); /* get track size in sectors */ + uint32 csize = SPC(type); /* get cylinder size in sectors */ + uint32 cyl = CYL(type); /* get # cylinders */ + uint32 cap = CAP(type); /* disk capacity in sectors */ + uint32 cylv = cyl; /* number of cylinders */ uint8 *buff; /* see if user wants to initialize the disk */ @@ -931,8 +1514,8 @@ int scfi_format(UNIT *uptr) { return 1; } - /* get buffer for track data */ - if ((buff = (uint8 *)calloc(tsize*ssize, sizeof(uint8))) == 0) { + /* get buffer for track data in bytes */ + if ((buff = (uint8 *)calloc(csize*ssize, sizeof(uint8))) == 0) { detach_unit(uptr); return SCPE_ARG; } @@ -944,11 +1527,15 @@ int scfi_format(UNIT *uptr) { sim_debug(DEBUG_CMD, dptr, "Creating disk file of trk size %04x bytes, capacity %d\n", tsize*ssize, cap*ssize); + /* write zeros to each track of the disk */ for (cyl = 0; cyl < cylv; cyl++) { - if ((sim_fwrite(buff, 1, tsize*ssize, uptr->fileref)) != tsize*ssize) { + 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 */ + buff = 0; + return 1; } if (cyl == 0) { buff[0] = 0; @@ -956,31 +1543,52 @@ int scfi_format(UNIT *uptr) { buff[2] = 0; buff[3] = 0; } + if ((cyl % 100) == 0) + fputc('.', stderr); } - if ((cyl % 100) == 0) - fputc('.', stderr); fputc('\r', stderr); fputc('\n', stderr); + free(buff); /* free cylinder buffer */ + buff = 0; + /* seek home again */ if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ fprintf (stderr, "Error on seek to 0\r\n"); return 1; } - free(buff); /* free cylinder buffer */ - return 0; + return 0; /* good or error */ } /* attach the selected file to the disk */ -t_stat scfi_attach(UNIT *uptr, CONST char *file) { +t_stat scfi_attach(UNIT *uptr, CONST char *file) +{ uint16 chsa = GET_UADDR(uptr->CMD); - CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ + CHANP *chp = find_chanp_ptr(chsa);/* get channel prog pointer */ int type = GET_TYPE(uptr->flags); DEVICE *dptr = get_dev(uptr); DIB *dibp = 0; - t_stat r; + t_stat r, s; uint32 ssize; /* sector size in bytes */ + uint32 info, good; uint8 buff[1024]; + int i, j; + /* last sector address of disk (cyl * hds * spt) - 1 */ + uint32 laddr = CAP(type) - 1; /* last sector of disk */ + /* get sector address of utx diag map (DMAP) track 0 pointer */ + /* put data = 0xf0000000 + (cyl-1), 0x8a000000 + daddr, */ + /* 0x9a000000 + (cyl-1), 0xf4000008 */ + int32 daddr = (CYL(type)-4) * SPC(type) + (HDS(type)-2) * SPT(type); + /* defect map */ + uint32 dmap[4] = {0xf0000000 | (CAP(type)-1), 0x8a000000 | daddr, + 0x9a000000 | (CAP(type)-1), 0xf4000000}; + + for (i=0; i<4; i++) { /* byte swap data for last sector */ + dmap[i] = (((dmap[i] & 0xff) << 24) | ((dmap[i] & 0xff00) << 8) | + ((dmap[i] & 0xff0000) >> 8) | ((dmap[i] >> 24) & 0xff)); + } + + /* see if valid disk entry */ if (scfi_type[type].name == 0) { /* does the assigned disk have a name */ detach_unit(uptr); /* no, reject */ return SCPE_FMT; /* error */ @@ -992,27 +1600,125 @@ t_stat scfi_attach(UNIT *uptr, CONST char *file) { uptr->capac = CAP(type); /* disk capacity in sectors */ ssize = SSB(type); /* get sector size in bytes */ + for (i=0; icapac); /* disk capacity */ + printf( + "SCFI Disk %s cyl %d hds %d sec %d ssiz %d capacity %d\r\n", + scfi_type[type].name, scfi_type[type].cyl, scfi_type[type].nhds, scfi_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 */ + /* seek to end of disk */ + if ((sim_fseek(uptr->fileref, 0, SEEK_END)) != 0) { + sim_debug(DEBUG_CMD, dptr, "SCFI Disk attach SEEK end failed\n"); + printf( "SCFI Disk attach SEEK end failed\r\n"); + goto fmt; /* not setup, go format */ } - /* 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); + s = ftell(uptr->fileref); /* get current file position */ + if (s == 0) { + sim_debug(DEBUG_CMD, dptr, "SCFI Disk attach ftell failed s=%06d\n", s); + printf("SCFI Disk attach ftell failed s=%06d\r\n", s); + goto fmt; /* not setup, go format */ + } + sim_debug(DEBUG_CMD, dptr, "SCFI Disk attach ftell value s=%06d b=%06d CAP %06d\n", s/ssize, s, CAP(type)); + printf("SCFI Disk attach ftell value s=%06d b=%06d CAP %06d\r\n", s/ssize, s, CAP(type)); + + if ((s/ssize) < (CAP(type))) { /* full sized disk? */ + j = (CAP(type) - (s/ssize)); /* get # sectors to write */ + sim_debug(DEBUG_CMD, dptr, + "SCFI Disk attach for MPX 1.X needs %04d more sectors added to disk\n", j); + printf( + "SCFI Disk attach for MPX 1.X needs %04d more sectors added to disk\r\n", j); + /* must be MPX 1.X disk, extend to MPX 3.X size */ + /* write sectors of zero to end of disk to fill it out */ + for (i=0; ifileref) != ssize)) { + sim_debug(DEBUG_CMD, dptr, "SCFI Disk attach fread ret = %04d\n", r); + printf("SCFI Disk attach fread ret = %04d\r\n", r); + goto fmt; /* not setup, go format */ + } + } + s = ftell(uptr->fileref); /* get current file position */ + sim_debug(DEBUG_CMD, dptr, + "SCFI Disk attach MPX 1.X file extended & sized secs %06d bytes %06d\n", s/ssize, s); + printf("SCFI Disk attach MPX 1.X file extended & sized secs %06d bytes %06d\r\n", s/ssize, s); + } + + /* seek last sector of disk */ + if ((sim_fseek(uptr->fileref, (CAP(type)-1)*ssize, SEEK_SET)) != 0) { + sim_debug(DEBUG_CMD, dptr, "SCFI Disk attach SEEK last sector failed\n"); + printf( "SCFI Disk attach SEEK last sector failed\r\n"); goto fmt; } - if ((buff[0] | buff[1] | buff[2] | buff[3]) == 0) { - sim_debug(DEBUG_CMD, &sda_dev, - "Disk format buf0 %02x buf1 %02x buf2 %02x buf3 %02x\n", - buff[0], buff[1], buff[2], buff[3]); + /* see if there is disk size-1 in last sector of disk, if not add it */ + if ((r = sim_fread(buff, sizeof(uint8), ssize, uptr->fileref) != ssize)) { + sim_debug(DEBUG_CMD, dptr, "SCFI Disk format fread error = %04d\n", r); + printf( "SCFI Disk format fread error = %04d\r\n", r); +add_size: + if (ssize == 768) { + /* assume we have MPX 1x, and go on */ + /* write dmap data to last sector on disk for mpx 1.x */ + if ((sim_fseek(uptr->fileref, laddr*ssize, SEEK_SET)) != 0) { /* seek last sector */ + sim_debug(DEBUG_CMD, dptr, + "SCFI Error on last sector seek to sect %06d offset %06d bytes\n", + (CAP(type)-1), (CAP(type)-1)*ssize); + printf( + "SCFI Error on last sector seek to sect %06d offset %06d bytes\r\n", + (CAP(type)-1), (CAP(type)-1)*ssize); + goto fmt; + } + if ((sim_fwrite((char *)&dmap, sizeof(uint32), 4, uptr->fileref)) != 4) { + sim_debug(DEBUG_CMD, dptr, + "SCFI Error writing DMAP to sect %06x offset %06d bytes\n", + (CAP(type)-1), (CAP(type)-1)*ssize); + printf( + "SCFI Error writing DMAP to sect %06x offset %06d bytes\r\n", + (CAP(type)-1), (CAP(type)-1)*ssize); + goto fmt; + } + + /* seek last sector of disk */ + if ((sim_fseek(uptr->fileref, (CAP(type))*ssize, SEEK_SET)) != 0) { + sim_debug(DEBUG_CMD, dptr, "SCFI Disk attach SEEK last sector failed\n"); + printf( "SCFI Disk attach SEEK last sector failed\r\n"); + goto fmt; + } + s = ftell(uptr->fileref); /* get current file position */ + sim_debug(DEBUG_CMD, dptr, + "SCFI Disk attach MPX file extended & sized secs %06d bytes %06d\n", s/ssize, s); + printf("SCFI Disk attach MPX file extended & sized secs %06d bytes %06d\r\n", s/ssize, s); + goto ldone; + } else { + /* error if UTX */ + detach_unit(uptr); /* if error, abort */ + return SCPE_FMT; /* error */ + } + } else { + /* if not disk size, go add it in for MPX, error if UTX */ + if ((buff[0] | buff[1] | buff[2] | buff[3]) == 0) { + sim_debug(DEBUG_CMD, dptr, + "SCFI Disk format0 buf0 %02x buf1 %02x buf2 %02x buf3 %02x\n", + buff[0], buff[1], buff[2], buff[3]); + goto add_size; + } + } + + info = (buff[0]<<24) | (buff[1]<<16) | (buff[2]<<8) | buff[3]; + good = 0xf0000000 | (CAP(type)-1); + /* check for 0xf0ssssss where ssssss is disk size-1 in sectors */ + if (info != good) { + sim_debug(DEBUG_CMD, dptr, + "SCFI Disk format error buf0 %02x buf1 %02x buf2 %02x buf3 %02x\n", + buff[0], buff[1], buff[2], buff[3]); + printf( + "SCFI Disk format error buf0 %02x buf1 %02x buf2 %02x buf3 %02x\r\n", + buff[0], buff[1], buff[2], buff[3]); fmt: /* format the drive */ if (scfi_format(uptr)) { @@ -1020,31 +1726,32 @@ fmt: return SCPE_FMT; /* error */ } } - +ldone: if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ - detach_unit(uptr); /* if no space, 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 */ - sim_debug(DEBUG_CMD, &sda_dev, - "Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\n", - scfi_type[type].name, CYL(type), HDS(type), SPT(type), SPC(type), + sim_debug(DEBUG_CMD, dptr, + "SCFI Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\n", + scfi_type[type].name, CYL(type), HDS(type), SPT(type), SPC(type), + CAP(type), CAPB(type)); + printf( + "SCFI Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\r\n", + scfi_type[type].name, CYL(type), HDS(type), SPT(type), SPC(type), CAP(type), CAPB(type)); - - sim_debug(DEBUG_CMD, &sda_dev, "File %s attached to %s\r\n", - file, scfi_type[type].name); /* check for valid configured disk */ /* must have valid DIB and Channel Program pointer */ dibp = (DIB *)dptr->ctxt; /* get the DIB pointer */ -//??if ((dib_unit[chsa] == NULL) || (dibp == NULL) || (dibp->chan_prg == NULL)) { if ((dib_unit[chsa] == NULL) || (dibp == NULL) || (chp == NULL)) { sim_debug(DEBUG_CMD, dptr, "ERROR===ERROR\nSCFI device %s not configured on system, aborting\n", dptr->name); - printf("ERROR===ERROR\nSCFI device %s not configured on system, aborting\n", + printf("ERROR===ERROR\nSCFI device %s not configured on system, aborting\r\n", dptr->name); detach_unit(uptr); /* detach if error */ return SCPE_UNATT; /* error */ @@ -1056,7 +1763,7 @@ fmt: /* detach a disk device */ t_stat scfi_detach(UNIT *uptr) { uptr->SNS = 0; /* clear sense data */ - uptr->CMD &= ~0xffff; /* no cmd and flags */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ return detach_unit(uptr); /* tell simh we are done with disk */ } @@ -1064,15 +1771,22 @@ t_stat scfi_detach(UNIT *uptr) { t_stat scfi_boot(int32 unit_num, DEVICE *dptr) { UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */ - sim_debug(DEBUG_CMD, &sda_dev, "SCFI Disk Boot dev/unit %04x\n", GET_UADDR(uptr->CMD)); + sim_debug(DEBUG_CMD, dptr, "SCFI Disk Boot dev/unit %x\n", GET_UADDR(uptr->CMD)); + if ((uptr->flags & UNIT_ATT) == 0) { + sim_debug(DEBUG_EXP, dptr, "SCFI Disk Boot attach error dev/unit %04x\n", + GET_UADDR(uptr->CMD)); + return SCPE_UNATT; /* attached? */ + } SPAD[0xf4] = GET_UADDR(uptr->CMD); /* put boot device chan/sa into spad */ SPAD[0xf8] = 0xF000; /* show as F class device */ - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_UNATT; /* attached? */ - return chan_boot(GET_UADDR(uptr->CMD), dptr); /* boot the ch/sa */ + + /* now boot the disk */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + return chan_boot(GET_UADDR(uptr->CMD), dptr); /* boot the ch/sa */ } /* Disk option setting commands */ +/* set the disk type attached to unit */ t_stat scfi_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { int i; @@ -1097,7 +1811,7 @@ t_stat scfi_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) return SCPE_ARG; } -t_stat scfi_get_type(FILE * st, UNIT *uptr, int32 v, CONST void *desc) +t_stat scfi_get_type(FILE *st, UNIT *uptr, int32 v, CONST void *desc) { if (uptr == NULL) return SCPE_IERR; @@ -1121,9 +1835,9 @@ t_stat scfi_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cp } fprintf (st, ".\nEach drive has the following storage capacity:\r\n"); for (i = 0; scfi_type[i].name != 0; i++) { - int32 size = CAPB(i); /* disk capacity in bytes */ - size /= 1024; /* make KB */ - size = (10 * size) / 1024; /* size in MB * 10 */ + int32 size = CAPB(i); /* disk capacity in bytes */ + size /= 1024; /* make KB */ + size = (10 * size) / 1024; /* size in MB * 10 */ fprintf(st, " %-8s %4d.%1d MB cyl %3d hds %3d sec %3d blk %3d\r\n", scfi_type[i].name, size/10, size%10, CYL(i), HDS(i), SPT(i), SSB(i)); } @@ -1136,4 +1850,5 @@ const char *scfi_description (DEVICE *dptr) { return "SEL-32 SCFI Disk Processor"; } + #endif diff --git a/SEL32/sel32_scsi.c b/SEL32/sel32_scsi.c index 366104e..3f6c954 100644 --- a/SEL32/sel32_scsi.c +++ b/SEL32/sel32_scsi.c @@ -324,12 +324,16 @@ UNIT sba_unit[] = { DIB sba_dib = { scsi_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ scsi_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ + NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + NULL, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ scsi_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ sba_unit, /* UNIT* units */ /* Pointer to units structure */ sba_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NULL, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ NUM_UNITS_SCSI, /* uint8 numunits */ /* number of units defined */ 0x0f, /* uint8 mask */ /* 8 devices - device mask */ 0x7600, /* uint16 chan_addr */ /* parent channel address */ @@ -363,18 +367,22 @@ UNIT sbb_unit[] = { DIB sbb_dib = { scsi_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ scsi_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ + NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ + NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ + NULL, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ scsi_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ sbb_unit, /* UNIT* units */ /* Pointer to units structure */ sbb_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NULL, /* IOCLQ *ioclq_ptr */ /* IOCL entries, 1 per UNIT */ NUM_UNITS_SCSI, /* uint8 numunits */ /* number of units defined */ 0x0f, /* uint8 mask */ /* 2 devices - device mask */ 0x7600, /* uint16 chan_addr */ /* parent channel address */ 0, /* uint32 chan_fifo_in */ /* fifo input index */ 0, /* uint32 chan_fifo_out */ /* fifo output index */ - {0}, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ + {0} /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ }; DEVICE sbb_dev = { @@ -509,6 +517,7 @@ t_stat scsi_srv(UNIT *uptr) int len=0; int i; uint32 cap = CAP(type); + uint32 mema; /* memory address */ uint8 ch; int32 ssize = scsi_type[type].ssiz*4; /* Size of one sector in bytes */ uint32 tstart = 0; /* Location of start of cyl/track/sect in data */ @@ -534,9 +543,6 @@ t_stat scsi_srv(UNIT *uptr) break; case DSK_INCH2: /* use 0xF0 for inch, just need int */ - { - uint32 mema; /* memory address */ - len = chp->ccw_count; /* INCH command count */ mema = chp->ccw_addr; /* get inch or buffer addr */ sim_debug(DEBUG_CMD, dptr, @@ -551,7 +557,6 @@ t_stat scsi_srv(UNIT *uptr) /* now call set_inch() function to write and test inch buffer addresses */ i = set_inch(uptr, mema); /* new address */ -#ifdef NOTYET if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ /* we have error, bail out */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ @@ -559,13 +564,11 @@ t_stat scsi_srv(UNIT *uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } -#endif uptr->CMD &= LMASK; /* remove old cmd */ sim_debug(DEBUG_CMD, dptr, "scsi_srv cmd INCH chsa %04x chsa %06x count %04x completed\n", chsa, mema, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ - } break; case DSK_NOP: /* NOP 0x03 */ diff --git a/SEL32/sel32_sys.c b/SEL32/sel32_sys.c index fdc77bb..e1639ac 100644 --- a/SEL32/sel32_sys.c +++ b/SEL32/sel32_sys.c @@ -847,7 +847,7 @@ int fprint_inst(FILE *of, uint32 val, int32 sw) i = (val & 3) | ((inst >> 1) & 04); if (((inst&0xfc00) == 0xe000) || ((inst&0xfc00) == 0xe400)) - i &= ~4; /* remode f bit from fpt instr */ + i &= ~4; /* remove f bit from fpt instr */ if (((inst&0xfc00) != 0xdc00) && ((inst&0xfc00) != 0xd000) && ((inst&0xfc00) != 0x5400) && @@ -1050,7 +1050,7 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) if (sw & SWMASK ('C')) { fputc('\'', of); /* opening apostorphe */ for(i = 0; i < l; i++) { - char ch = val[i] & 0xff; /* get the char */ + int ch = val[i] & 0xff; /* get the char */ if (ch >= 0x20 && ch <= 0x7f) /* see if printable */ fprintf(of, "%c", ch); /* output the ascii char */ else