From 84c38215da079ee0bbab3aa6a948cf512a0d2f59 Mon Sep 17 00:00:00 2001 From: AZBevier Date: Thu, 27 Aug 2020 15:34:10 -0700 Subject: [PATCH] SEL32: Add workaround delay in channel processing for UTX logic errors. SEL32: Create mkdiagtape utility to generate SEL diagnostic tapes. SEL32: Update DP disk and Ethernet software for diag detected errors. SEL32: Update mkvmtape utility to correctly build MPX3X save tapes. SEL32: Modify taptools makefile for new mkdiagtape utility. SEL32: Update README.md file for taptools. --- SEL32/sel32_chan.c | 327 +++++++++++++++++-------- SEL32/sel32_con.c | 18 +- SEL32/sel32_cpu.c | 53 +++- SEL32/sel32_disk.c | 32 ++- SEL32/sel32_ec.c | 223 +++++++++++++---- SEL32/sel32_mt.c | 6 +- SEL32/sel32_scsi.c | 2 +- SEL32/taptools/README.md | 87 ++++--- SEL32/taptools/makefile | 7 + SEL32/taptools/mkdiagtape.c | 276 +++++++++++++++++++++ SEL32/taptools/mkvmtape.c | 475 +++++++++++++++++++++++++----------- SEL32/taptools/tapdump.c | 2 + 12 files changed, 1162 insertions(+), 346 deletions(-) create mode 100644 SEL32/taptools/mkdiagtape.c diff --git a/SEL32/sel32_chan.c b/SEL32/sel32_chan.c index 5e1cbdc..aa88652 100644 --- a/SEL32/sel32_chan.c +++ b/SEL32/sel32_chan.c @@ -92,6 +92,12 @@ int DoNextCycles = 0; extern uint32 CPUSTATUS; /* CPU status word */ extern uint32 INTS[]; /* Interrupt status flags */ extern uint32 TPSD[]; /*Temp save of PSD from memory 0&4 */ +#ifndef TRY_UTX_DELAY +extern uint8 waitqcnt; /* # of instructions to xeq b4 int */ +#endif +#ifdef NOT_NOW +extern uint8 waitrdyq; /* # of instructions to xeq b4 rdy */ +#endif DIB *dib_unit[MAX_DEV]; /* Pointer to Device info block */ DIB *dib_chan[MAX_CHAN]; /* pointer to channel mux dib */ @@ -211,6 +217,11 @@ int32 RDYQ_Put(uint32 entry) RDYQIN += 1; /* next entry */ RDYQIN %= RDYQ_SIZE; /* modulo RDYQ size */ irq_pend = 1; /* do a scan */ +#ifdef NOT_NOW +//25waitrdyq = 5; +//25waitrdyq = 2; + waitrdyq = 1; +#endif return 0; /* all OK */ } @@ -491,7 +502,7 @@ loop: /* Abort if we have any errors */ if (chp->chan_status & STATUS_ERROR) { /* check channel error status */ sim_debug(DEBUG_EXP, &cpu_dev, - "load_ccw ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); + "load_ccw ERROR1 chan_status[%04x] %04x\n", chan, chp->chan_status); return 1; } @@ -505,7 +516,7 @@ loop: if (readfull(chp, chp->chan_caw, &word1) != 0) { /* read word1 from memory */ chp->chan_status |= STATUS_PCHK; /* memory read error, program check */ sim_debug(DEBUG_EXP, &cpu_dev, - "load_ccw ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); + "load_ccw ERROR2 chan_status[%04x] %04x\n", chan, chp->chan_status); return 1; /* error return */ } @@ -513,7 +524,7 @@ loop: if (readfull(chp, chp->chan_caw+4, &word2) != 0) { /* read word2 from memory */ chp->chan_status |= STATUS_PCHK; /* memory read error, program check */ sim_debug(DEBUG_EXP, &cpu_dev, - "load_ccw ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); + "load_ccw ERROR3 chan_status[%04x] %04x\n", chan, chp->chan_status); return 1; /* error return */ } @@ -534,8 +545,18 @@ loop: #endif /* TIC can't follow TIC or be first in command chain */ - if (((word1 >> 24) & 0xf) == CMD_TIC) { +//25if (((word1 >> 24) & 0xf) == CMD_TIC) { + /* diags send bad commands for testing. Use all of op */ + if (((word1 >> 24) & 0xff) == CMD_TIC) { if (tic_ok) { +/*25*/ if (((word1 & MASK24) == 0) || (word1 & 0x3)) { +// if (((word1 & MASK24) == 0) || (word1 & 0x3) || ((word1 & MASK24) == (chp->chan_caw-8))) { + 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 */ + return 1; /* error return */ + } chp->chan_caw = word1 & MASK24; /* get new IOCD address */ tic_ok = 0; /* another tic not allowed */ sim_debug(DEBUG_XIO, &cpu_dev, @@ -604,17 +625,19 @@ 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_cmd = 0; /* stop IOCD processing */ - sim_debug(DEBUG_EXP, &cpu_dev, - "load_ccw bad status chan %04x status %04x\n", - chan, chp->chan_status); +// 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 */ chp->chan_byte = BUFF_NEXT; /* have main pick us up */ + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw bad status chan %04x status %04x cmd %02x\n", + chan, chp->chan_status, chp->ccw_cmd); sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw BUFF_NEXT chp %p chan_byte %04x\n", chp, chp->chan_byte); RDYQ_Put(chp->chan_dev); /* queue us up */ sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw continue wait chsa %04x status %08x\n", chp->chan_dev, chp->chan_status); - } +/*0816*/ } else /* NOTE this code needed for MPX 1.X to run! */ /* see if command completed */ @@ -758,7 +781,7 @@ 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 @@ -773,7 +796,8 @@ sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte BUFF_CHNEND chp %p chan_byte %04 chp->ccw_count--; /* reduce count */ chp->chan_byte = BUFF_BUSY; /* busy, but no data */ -//sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte2 BUFF_BUSY chp %p chan_byte %04x\n", chp, chp->chan_byte); + sim_debug(DEBUG_DETAIL, &cpu_dev, + "chan_write_byte2 BUFF_BUSY chp %p chan_byte %04x\n", chp, chp->chan_byte); if ((chp->ccw_cmd & 0xff) == CMD_RDBWD) /* see if reading backwards */ chp->ccw_addr -= 1; /* no, use previous address */ else @@ -818,6 +842,7 @@ void set_devattn(uint16 chsa, uint16 flags) /* channel operation completed */ void chan_end(uint16 chsa, uint16 flags) { + uint16 tstat, tcnt; CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ sim_debug(DEBUG_XIO, &cpu_dev, @@ -825,22 +850,23 @@ void chan_end(uint16 chsa, uint16 flags) { chsa, flags, chp->chan_status, chp->ccw_cmd); chp->chan_byte = BUFF_BUSY; /* we are empty & still busy now */ -//sim_debug(DEBUG_EXP, &cpu_dev, "chan_end BUFF_BUSY chp %p chan_byte %04x\n", chp, chp->chan_byte); +sim_debug(DEBUG_EXP, &cpu_dev, "chan_end1 BUFF_BUSY chp %p chan_byte %04x\n", chp, chp->chan_byte); chp->chan_status |= STATUS_CEND; /* set channel end */ chp->chan_status |= ((uint16)flags); /* add in the callers flags */ - sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "chan_end SLI test1 chsa %04x ccw_flags %04x count %04x status %04x\n", chsa, chp->ccw_flags, chp->ccw_count, chp->chan_status); /* read/write must have none-zero byte count */ /* all others can be zero, except NOP, which must be 0 */ - /* a NOP is Control command 0x03 with no mdifier bits */ + /* a NOP is Control command 0x03 with no modifier bits */ /* see if this is a read/write cmd */ if (((chp->ccw_cmd & 0x7) == 0x02) || ((chp->ccw_cmd & 0x7) == 0x01)) { /* test for incorrect transfer length */ if (chp->ccw_count != 0 && ((chp->ccw_flags & FLAG_SLI) == 0)) { - chp->chan_status |= STATUS_LENGTH; /* show incorrect length status */ +/*082720*/ if ((chp->chan_status & STATUS_PCHK) == 0) /* No SLI if channel prg check */ + chp->chan_status |= STATUS_LENGTH; /* show incorrect length status */ 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); @@ -868,7 +894,7 @@ void chan_end(uint16 chsa, uint16 flags) { /* test for device or controller end */ if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { chp->chan_byte = BUFF_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); +sim_debug(DEBUG_EXP, &cpu_dev, "chan_end2 BUFF_BUSY chp %p chan_byte %04x\n", chp, chp->chan_byte); while ((chp->ccw_flags & FLAG_DC)) { /* handle data chaining */ if (load_ccw(chp, 1)) /* continue channel program */ break; /* error */ @@ -878,14 +904,25 @@ 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_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); - sim_debug(DEBUG_XIO, &cpu_dev, - "chan_end chan end chsa %04x ccw_flags %04x status %04x\n", - chsa, chp->ccw_flags, chp->chan_status); + /* handle a PPCI here. DC is done and maybe have CC */ + if ((chp->chan_status & STATUS_PCI) && (chp->ccw_flags & FLAG_CC)) { + chp->chan_status &= ~STATUS_PCI; /* done with PCI */ + tstat = chp->chan_status; /* save status */ + tcnt = chp->ccw_count; /* save count */ + chp->chan_status = STATUS_PCI; /* set PCI status */ + chp->ccw_count = 0; /* zero count */ + store_csw(chp); /* store the status */ + chp->chan_status = tstat; /* restore status */ + chp->ccw_count = tcnt; /* restore count */ + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end done PCI chsa %04x ccw_flags %04x stat %04x cnt %04x\n", + chsa, chp->ccw_flags, tstat, tcnt); + } /* If channel end, check if we should continue */ if (chp->ccw_flags & FLAG_CC) { /* command chain flag */ @@ -899,7 +936,8 @@ 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_end4 BUFF_NEXT chp %p chan_byte %04x\n", chp, chp->chan_byte); RDYQ_Put(chsa); /* queue us up */ } /* just return */ @@ -925,10 +963,13 @@ sim_debug(DEBUG_EXP, &cpu_dev, "chan_end4 BUFF_NEXT chp %p chan_byte %04x\n", ch } /* store the status in channel FIFO to continue from cpu level */ chp->chan_byte = BUFF_DONE; /* we are done */ - /* store_csw will change chan_byte to BUFF_POST */ +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 */ - sim_debug(DEBUG_EXP, &cpu_dev, - "chan_end5 BUFF_POST chp %p chan_byte %04x\n", chp, chp->chan_byte); + /* 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->ccw_cmd = 0; /* no command anymore */ sim_debug(DEBUG_XIO, &cpu_dev, "chan_end after store_csw call chsa %04x status %08x chan_byte %02x\n", chsa, chp->chan_status, chp->chan_byte); @@ -967,11 +1008,18 @@ int16 post_csw(CHANP *chp, uint32 rstat) /* 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 */ +#ifdef DO_DYNAMIC_DEBUG + /* start debugging */ + if (sw2 == 0x200c0234) + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_TRAP | DEBUG_EXP | DEBUG_IRQ); +#endif WMW(incha, sw1); /* save sa & IOCD address in status WD 1 loc */ WMW(incha+4, sw2); /* save status and residual cnt in status WD 2 loc */ /* now store the status dw address into word 5 of the ICB for the channel */ @@ -1007,13 +1055,16 @@ 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); +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 */ } @@ -1183,13 +1234,24 @@ t_stat startxio(uint16 chsa, uint32 *status) { } #endif +#ifndef NOTHERE /* check for a Command or data chain operation in progresss */ - if (chp->chan_byte & BUFF_BUSY) { - sim_debug(DEBUG_XIO, &cpu_dev, - "startxio busy return CC3&CC4 chsa %04x chan %04x\n", chsa, chan); +//25if (chp->chan_byte & BUFF_BUSY) { + if ((chp->chan_byte & BUFF_BUSY) && chp->chan_byte != BUFF_POST) { + sim_debug(DEBUG_EXP, &cpu_dev, + "startxio busy return CC3&CC4 chsa %04x chan %04x cmd %02x flags %04x byte %02x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags, chp->chan_byte); +// sim_debug(DEBUG_XIO, &cpu_dev, +// "startxio busy return CC3&CC4 chsa %04x chan %04x\n", chsa, chan); *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ +#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 */ sim_debug(DEBUG_XIO, &cpu_dev, @@ -1272,6 +1334,15 @@ t_stat startxio(uint16 chsa, uint32 *status) { "$$$ 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 = 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 */ sim_debug(DEBUG_XIO, &cpu_dev, "$$$ SIO done chsa %04x status %08x iocla %08x CC's %08x\n", chsa, chp->chan_status, iocla, *status); @@ -1293,6 +1364,10 @@ t_stat testxio(uint16 chsa, uint32 *status) { /* test XIO */ dibp = dib_unit[chsa]; /* get the DIB pointer */ chp = find_chanp_ptr(chsa); /* find the device chanp pointer */ +#ifndef TRY_UTX_DELAY + if (waitqcnt != 0) + waitqcnt = 0; /* tell cpu ok to int */ +#endif 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, @@ -1310,8 +1385,11 @@ t_stat testxio(uint16 chsa, uint32 *status) { /* test XIO */ /* check for a Command or data chain operation in progresss */ if ((chp->chan_byte & BUFF_BUSY) && chp->chan_byte != BUFF_POST) { - sim_debug(DEBUG_XIO, &cpu_dev, - "testxio busy return CC4 chsa %04x chan %04x\n", chsa, chan); + sim_debug(DEBUG_EXP, &cpu_dev, + "startxio busy return CC3&CC4 chsa %04x chan %04x cmd %02x flags %04x byte %02x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags, chp->chan_byte); +// sim_debug(DEBUG_XIO, &cpu_dev, +// "testxio busy return CC3&CC4 chsa %04x chan %04x\n", chsa, chan); *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ return SCPE_OK; /* just busy CC3&CC4 */ } @@ -1341,6 +1419,11 @@ t_stat testxio(uint16 chsa, uint32 *status) { /* test XIO */ "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); + } return SCPE_OK; /* CC2 and OK */ } /* nothing going on, so say all OK */ @@ -1390,7 +1473,8 @@ t_stat stopxio(uint16 chsa, uint32 *status) { /* stop XIO */ chsa, chp->ccw_cmd, chp->ccw_flags); /* check for a Command or data chain operation in progresss */ - if (chp->chan_byte & BUFF_BUSY) { +//25if (chp->chan_byte & BUFF_BUSY) { + 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 */ @@ -1453,8 +1537,7 @@ t_stat rschnlxio(uint16 chsa, uint32 *status) { /* reset channel XIO */ 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, -//"rschnlxio 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*/ @@ -1487,12 +1570,10 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ chp = find_chanp_ptr(chsa); /* find the chanp pointer */ uptr = chp->unitptr; /* get the unit ptr */ - sim_debug(DEBUG_XIO, &cpu_dev, "haltxio 1 chsa %04x chan %04x\n", chsa, chan); if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ *status = CC3BIT; /* not found, so CC3 */ return SCPE_OK; /* not found, CC3 */ } - sim_debug(DEBUG_XIO, &cpu_dev, "haltxio 2 chsa %04x chan %04x\n", chsa, chan); if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ *status = CC3BIT; /* not attached, so error CC3 */ return SCPE_OK; /* not found, CC3 */ @@ -1500,7 +1581,7 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ /* 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); - /* the startio opcode processing software has already checked for F class */ + /* 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 */ @@ -1511,28 +1592,31 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ chan_icb = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ iocla = M[(chan_icb+16)>>2]; /* iocla is in wd 4 of ICB */ sim_debug(DEBUG_XIO, &cpu_dev, - "haltxio busy test chsa %04x chan %04x cmd %02x ccw_flags %04x IOCD1 %08x IOCD2 %08x\n", + "$$ 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]); - sim_debug(DEBUG_XIO, &cpu_dev, "$$$ HIO chsa %04x chan %04x cmd %02x ccw_flags %04x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags); - if ((chp->chan_byte & BUFF_BUSY) == 0) { /* the channel is not busy, so return OK */ - - /* diag wants an interrupt for a non busy HIO ??? */ - sim_debug(DEBUG_XIO, &cpu_dev, - "$$$ HIO DIAG chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); - irq_pend = 1; /* still pending int */ *status = CC1BIT; /* request accepted, no status, so CC1 */ - goto hiogret; /* CC1 and OK */ + sim_debug(DEBUG_CMD, &cpu_dev, + "$$$ HIO END chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + 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); + 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, "haltxio BUFF_POST chp %p chan_byte %04x\n", chp, chp->chan_byte); + chp->chan_status = 0; /* no status anymore */ + chp->ccw_cmd = 0; /* no command anymore */ + irq_pend = 1; /* flag to test for int condition */ + return SCPE_OK; /* CC1 & all OK */ } /* the channel is busy, so process */ /* see if we have a haltio device entry */ if (dibp->halt_io != NULL) { /* NULL if no haltio function */ - /* call the device controller to get halt_io status */ tempa = dibp->halt_io(uptr); /* get status from device */ @@ -1542,61 +1626,85 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ 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); -#if 1 /* 081320 */ - /* chan_end called in hio device service routine */ + + /* chan_end is called in hio device service routine */ /* the device is no longer busy, post status */ - /* remove SLI, PCI and Unit check status bits */ - if (post_csw(chp, ((STATUS_LENGTH|STATUS_PCI|STATUS_EXPT) << 16))) { -/// UTX if (post_csw(chp, ((STATUS_LENGTH|STATUS_PCI|STATUS_CHECK) << 16))) { - /* TODO clear SLI bit in status */ -// chp->chan_status &= ~STATUS_LENGTH; /* remove SLI status bit */ -// chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ + /* remove PPCI status. Unit check should not be set */ + chp->ccw_count = 0; /* zero the count */ +#ifndef TRY_THIS + if (post_csw(chp, ((STATUS_PCI) << 16))) { INTS[inta] &= ~INTS_REQ; /* clear any level request */ *status = CC2BIT; /* status stored */ - goto hioret; /* CC2 and OK */ + sim_debug(DEBUG_CMD, &cpu_dev, + "$$$ HIO END chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + /* 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_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); + } + return SCPE_OK; /* CC2 & all OK */ } #else -/*81320*/ goto hiogret; /* CC1 and OK */ + *status = 0; /* status to be echoed */ + sim_debug(DEBUG_CMD, &cpu_dev, + "$$$ HIO END ECHO chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + return SCPE_OK; /* CC2 & all OK */ #endif } /* the device is not busy, so cmd has not started */ + chp->chan_byte = BUFF_DONE; /* chan prog done */ + sim_debug(DEBUG_EXP, &cpu_dev, + "haltxioret BUFF_DONE 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 END chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + return SCPE_OK; /* No CC's all OK */ } /* 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 busy return CC4 chsa %04x chan %04x\n", chsa, chan); + sim_debug(DEBUG_XIO, &cpu_dev, "haltxio device busy chsa %04x chan %04x\n", chsa, chan); - /* reset the DC or CC bits to force completion after current IOCD */ - chp->chan_status |= STATUS_ECHO; /* show we stopped the cmd */ - chp->chan_status &= ~STATUS_LENGTH; /* remove SLI status bit */ - chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ + /* 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_BUSY chp %p chan_byte %04x\n", chp, chp->chan_byte); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* show I/O complete */ +sim_debug(DEBUG_EXP, &cpu_dev, "haltxiocan BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); +//082020chp->chan_status |= STATUS_ECHO; /* show we stopped the cmd */ +// 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|SNS_UNITEXP); /* show I/O complete */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ /* post the channel status */ - /* remove SLI, PCI and Unit check status bits */ - if (post_csw(chp, ((STATUS_LENGTH|STATUS_PCI|STATUS_EXPT) << 16))) { - /* TODO clear SLI bit in status */ -#ifdef TEST4EC_NOWORK -//81320 INTS[inta] &= ~INTS_REQ; /* clear any level request */ -//81320 *status = CC2BIT; /* status stored from SIO, so CC2 */ - *status = CC1BIT; /* request accepted */ -#else + chp->ccw_count = 0; /* zero the count */ + /* remove SLI, PPCI and Unit check status bits */ + if (post_csw(chp, ((STATUS_PCI) << 16))) { INTS[inta] &= ~INTS_REQ; /* clear any level request */ *status = CC2BIT; /* status stored from SIO, so CC2 */ -#endif - goto hioret; /* just return */ + sim_debug(DEBUG_CMD, &cpu_dev, + "$$$ HIO END chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + /* change status from BUFF_POST to BUFF_DONE */ +/*082420*/ if (chp->chan_byte == BUFF_DONE) { +/*082420*/ chp->chan_byte = BUFF_DONE; /* show done & not busy */ +sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); + } + return SCPE_OK; /* CC2 & all OK */ } } -hiogret: +//hiogret: chp->chan_byte = BUFF_DONE; /* chan prog done */ -sim_debug(DEBUG_EXP, &cpu_dev, "haltxioret BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); +sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE 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 */ -hioret: - sim_debug(DEBUG_CMD, &cpu_dev, "$$$ HIO END chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", + sim_debug(DEBUG_CMD, &cpu_dev, + "$$$ HIO END chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); return SCPE_OK; /* No CC's all OK */ } @@ -1776,18 +1884,24 @@ uint32 cont_chan(uint16 chsa) sim_debug(DEBUG_EXP, &cpu_dev, "cont_chan resume chan prog chsa %04x iocl %06x\n", chsa, chp->chan_caw); + /* start a channel program */ stat = load_ccw(chp, 1); /* resume the channel program */ - if (stat || (chp->chan_status & STATUS_PCI)) { +// if (stat || (chp->chan_status & STATUS_PCI)) { + /* we get status returned if there is an error on the startio cmd call */ + if (stat) { /* we have an error or user requested interrupt, return status */ sim_debug(DEBUG_EXP, &cpu_dev, "cont_chan error, store csw chsa %04x status %08x\n", chsa, chp->chan_status); +/*NOTE*/ /* if we have an error, we would loop forever if the CC bit was set */ + /* the only way to stop was to do a kill */ +/*082320*/ chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ /* DIAG's want CC1 with memory access error */ if (chp->chan_status & STATUS_PCHK) { chp->chan_status &= ~STATUS_LENGTH; /* clear incorrect length */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ - sim_debug(DEBUG_EXP, &cpu_dev, - "cont_chan Error1 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 Error1 FIFO #%1x store_csw CC1 chan %04x status %08x\n", + FIFO_Num(chsa), chan, chp->chan_status); return SCPE_OK; /* done */ } /* other error, stop the show */ @@ -1798,7 +1912,8 @@ uint32 cont_chan(uint16 chsa) FIFO_Num(chsa), chan, chp->chan_status); return SCPE_OK; /* done */ } - /* we get here when nothing left to do and status is stored */ + /* 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); @@ -1920,7 +2035,11 @@ sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan BUFF_DONE chp %p chan_byte %04x\n", ch } /* cannot make anyone active if ints are blocked */ +#ifndef TRY_UTX_DELAY + if ((CPUSTATUS & 0x80) || (waitqcnt)) { /* interrupts blocked? */ +#else if (CPUSTATUS & 0x80) { /* interrupts blocked? */ +#endif sim_debug(DEBUG_DETAIL, &cpu_dev, // sim_debug(DEBUG_IRQ, &cpu_dev, "scan_chan INTS blocked!\n"); @@ -1995,6 +2114,11 @@ sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan BUFF_DONE chp %p chan_byte %04x\n", ch 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); + /* 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, "scan_chanx BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); + } } else { sim_debug(DEBUG_IRQ, &cpu_dev, "scan_chanx %04x NOT POSTED FIFO #%1x irq %02x inch %06x chan_icba %06x chan_byte %02x\n", @@ -2007,18 +2131,26 @@ sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan BUFF_DONE chp %p chan_byte %04x\n", ch } } tryme: + /* if the interrupt is not zero'd here, we get SPAD error */ irq_pend = 0; /* not pending anymore */ -#ifndef TEST_071820 +//25irq_pend = 0; /* not pending anymore */ +#ifndef TEST_082520 if (RDYQ_Num()) { +#ifdef NOTNOW + if (waitrdyq > 0) { + waitrdyq--; + } 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) sim_debug(DEBUG_XIO, &cpu_dev, - "CPU RDYQ entry for chsa %04x processed\n", chsa); + "CPU RDYQ entry for chsa %04x processed\n", chsa); } } #endif @@ -2085,7 +2217,7 @@ t_stat chan_set_devs() { ((dibp->chan_prg) == NULL)) { /* must have channel info for each device */ chsa = GET_UADDR(uptr->u3); /* ch/sa value */ - printf("Device %s chsa %04x not set up dibp %p\n", dptr->name, chsa, dibp); +// printf("Device %s chsa %04x not set up dibp %p\n", dptr->name, chsa, dibp); continue; } @@ -2093,15 +2225,14 @@ t_stat chan_set_devs() { /* Check if address is in unit or dev entry */ for (j = 0; j < dptr->numunits; j++) { /* loop through unit entries */ chsa = GET_UADDR(uptr->u3); /* ch/sa value */ - printf("Setup device %s%d chsa %04x type %03d dibp %p\n", - dptr->name, j, chsa, GET_TYPE(uptr->flags), dibp); +// printf("Setup device %s%d chsa %04x type %03d dibp %p\n", +// dptr->name, j, chsa, GET_TYPE(uptr->flags), dibp); /* zero some channel data loc's for device */ chp->unitptr = uptr; /* set the unit back pointer */ chp->chan_status = 0; /* clear the channel status */ chp->chan_dev = chsa; /* save our address (ch/sa) */ chp->chan_byte = BUFF_EMPTY; /* no data yet */ -//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*/ @@ -2117,10 +2248,10 @@ t_stat chan_set_devs() { if (dptr->flags & DEV_CHAN) { /* see if channel address already defined */ if (dib_chan[get_chan(chsa)] != 0) { - printf("Channel mux %04x already defined, aborting\n", chsa); +// printf("Channel mux %04x already defined, aborting\n", chsa); return SCPE_IERR; /* no, arg error */ } - printf("Setting Channel mux %04x dibp %p\n", chsa, dibp); +// printf("Setting Channel mux %04x dibp %p\n", chsa, dibp); /* channel mux, save dib for channel */ dib_chan[get_chan(chsa)] = dibp; if (dibp->dev_ini != NULL) /* if there is an init routine, call it now */ @@ -2128,13 +2259,13 @@ t_stat chan_set_devs() { } else { /* we have unit 0 of non-IOP/MFP device */ if (dib_unit[chsa] != 0) { - printf("Channel/Dev %04x already defined\n", chsa); +// printf("Channel/Dev %04x already defined\n", chsa); return SCPE_IERR; /* no, arg error */ } else { /* channel mux, save dib for channel */ /* for now, save any zero dev as chan */ if (chsa) { - printf("Setting Channel zero unit 0 device %04x dibp %p\n", chsa, dibp); +// printf("Setting Channel zero unit 0 device %04x dibp %p\n", chsa, dibp); dib_unit[chsa] = dibp; /* no, save the dib address */ if (dibp->dev_ini != NULL) /* if there is an init routine, call it now */ dibp->dev_ini(uptr, 1); /* init the channel */ @@ -2144,7 +2275,7 @@ t_stat chan_set_devs() { } else { /* see if address already defined */ if (dib_unit[chsa] != 0) { - printf("Channel/SubAddress %04x multiple defined, aborting\n", chsa); +// printf("Channel/SubAddress %04x multiple defined, aborting\n", chsa); return SCPE_IERR; /* no, arg error */ } dib_unit[chsa] = dibp; /* no, save the dib address */ @@ -2166,10 +2297,10 @@ t_stat chan_set_devs() { if (dib_unit[i<<8]) { /* write dibp to channel array */ dib_chan[i] = dib_unit[i<<8]; /* save the channel dib */ - printf("Chan_set_dev new Channel %04x defined at dibp %p\n", i<<8, dib_unit[i<<8]); +// printf("Chan_set_dev new Channel %04x defined at dibp %p\n", i<<8, dib_unit[i<<8]); } } else { - printf("Chan_set_dev Channel %04x defined at dibp %p\n", i<<8, dib_chan[i]); +// printf("Chan_set_dev Channel %04x defined at dibp %p\n", i<<8, dib_chan[i]); /* channel is defined, see if defined in dib_unit array */ if ((dib_unit[i<<8]) == 0) { /* write dibp to units array */ diff --git a/SEL32/sel32_con.c b/SEL32/sel32_con.c index 038d938..81959aa 100644 --- a/SEL32/sel32_con.c +++ b/SEL32/sel32_con.c @@ -351,7 +351,9 @@ 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); +fflush(sim_deb); // 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 */ @@ -490,6 +492,13 @@ 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); @@ -582,19 +591,24 @@ uint16 con_haltio(UNIT *uptr) { sim_debug(DEBUG_EXP, &con_dev, "con_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 & CON_MSK) != 0) { /* is unit busy */ sim_debug(DEBUG_CMD, &con_dev, "con_haltio HIO chsa %04x cmd = %02x ccw_count %02x\n", chsa, cmd, chp->ccw_count); // stop any I/O and post status and return error status */ chp->chan_byte = BUFF_EMPTY; /* there is no data to read/store */ - chp->ccw_flags = 0; /* stop any chaining */ +// chp->ccw_count = 0; /* zero the count */ + chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ uptr->CMD &= LMASK; /* make non-busy */ uptr->u4 = 0; /* no I/O yet */ con_data[unit].incnt = 0; /* no input data */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ sim_debug(DEBUG_CMD, &con_dev, "con_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* force error */ +// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* force error */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* force end */ return SCPE_IOERR; } uptr->u4 = 0; /* no I/O yet */ diff --git a/SEL32/sel32_cpu.c b/SEL32/sel32_cpu.c index 61891e8..fa2f479 100644 --- a/SEL32/sel32_cpu.c +++ b/SEL32/sel32_cpu.c @@ -221,7 +221,12 @@ uint32 attention_trap = 0; /* set when trap is requested */ uint32 RDYQIN; /* fifo input index */ uint32 RDYQOUT; /* fifo output index */ uint32 RDYQ[128]; /* channel ready queue */ +#ifndef TRY_UTX_DELAY uint8 waitqcnt = 0; /* # instructions before start */ +#endif +#ifdef NOT_NOW +uint8 waitrdyq = 0; /* # instructions before start */ +#endif struct InstHistory { @@ -1968,6 +1973,13 @@ wait_loop: goto skipi; /* skip int test */ } +#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 */ if (loading) { uint32 il; @@ -1997,6 +2009,11 @@ wait_loop: uint32 chsa; /* channel/sub adddress */ int32 stat; /* return status 0/1 from loadccw */ +#ifdef NOT_NOW + 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, @@ -2102,14 +2119,36 @@ wait_loop: goto skipi; /* skip int test */ } } - /* see if in wait instruction */ - if (wait4int) { /* keep waiting */ - /* tell simh we will be waiting */ -// sim_idle(TMR_RTC, 1); /* wait for clock tick */ - sim_idle(0, 1); /* wait for clock tick */ -/*722*/ irq_pend = 1; /* start scanning interrupts again */ - goto wait_loop; /* continue waiting */ +#ifdef TEST_082520 +/*25*/ irq_pend = 0; /* not pending anymore */ + if (RDYQ_Num()) { + uint32 chsa; /* channel/sub adddress */ +#ifdef NOTNOW + if (waitrdyq > 0) { + waitrdyq--; + } 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) + sim_debug(DEBUG_XIO, &cpu_dev, + "CPU RDYQ entry for chsa %04x processed\n", chsa); } + } +#endif + /* see if in wait instruction */ + if (wait4int) { /* keep waiting */ + /* tell simh we will be waiting */ +// sim_idle(TMR_RTC, 1); /* wait for clock tick */ + sim_idle(0, 1); /* wait for clock tick */ +/*722*/ irq_pend = 1; /* start scanning interrupts again */ + goto wait_loop; /* continue waiting */ + } /* Check for external interrupt here */ /* see if we have an attention request from console */ diff --git a/SEL32/sel32_disk.c b/SEL32/sel32_disk.c index f4bb14d..341024f 100644 --- a/SEL32/sel32_disk.c +++ b/SEL32/sel32_disk.c @@ -454,7 +454,7 @@ uint16 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) 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 0x15 */ + case DSK_LMR: /* read mode register 0x1F */ case DSK_NOP: /* NOP 0x03 */ case DSK_SNS: /* Sense 0x04 */ case DSK_WSL: /* WSL 0x31 */ @@ -474,11 +474,14 @@ uint16 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) sim_debug(DEBUG_CMD, dptr, "disk_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; +//25if (uptr->SNS & 0xff) /* any other cmd is error */ +// return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; +/// return SNS_CHNEND|SNS_DEVEND|SNS_CHNTCHK; +//25 return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; //J sim_activate(uptr, 20); /* start things off */ sim_activate(uptr, 50); /* start things off */ - return SNS_CHNEND|SNS_DEVEND; +//25return SNS_CHNEND|SNS_DEVEND; + return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; } /* Handle processing of disk requests. */ @@ -541,7 +544,8 @@ t_stat disk_srv(UNIT *uptr) if (len != 36) { /* we have invalid count, error, bail out */ uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; +//25 uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + uptr->SNS |= SNS_CMDREJ; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -555,7 +559,8 @@ t_stat disk_srv(UNIT *uptr) if (chan_read_byte(chsa, &buf[i])) { /* we have error, bail out */ uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; +//25 uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + uptr->SNS |= SNS_CMDREJ; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -578,7 +583,8 @@ t_stat disk_srv(UNIT *uptr) if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ /* we have error, bail out */ uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; +//25 uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + uptr->SNS |= SNS_CMDREJ; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -712,7 +718,7 @@ t_stat disk_srv(UNIT *uptr) /* TODO add drive status bits here */ if ((test_write_byte_end(chsa)) == 0) { /* bytes 12 & 13 contain drive related status */ - ch = 0; /* zero for now */ + ch = 0xc0; /* seek end and unit selected for now */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv dsr unit=%02x 1 %02x\n", unit, ch); chan_write_byte(chsa, &ch); @@ -784,7 +790,8 @@ t_stat disk_srv(UNIT *uptr) unit, buf[0], buf[1], buf[2], buf[3]); /* we have error, bail out */ uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; +//25 uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + uptr->SNS |= SNS_CMDREJ; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SCPE_OK; break; @@ -825,7 +832,8 @@ t_stat disk_srv(UNIT *uptr) cyl, trk, buf[3], unit); uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; /* set error status */ +//25 uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; /* set error status */ + uptr->SNS |= SNS_CMDREJ; /* set error status */ /* we have an error, tell user */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* end command */ @@ -901,7 +909,8 @@ t_stat disk_srv(UNIT *uptr) if (chan_read_byte(chsa, &buf[0])) { /* we have error, bail out */ uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; +//25 uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + uptr->SNS |= SNS_CMDREJ; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -1162,6 +1171,7 @@ t_stat disk_srv(UNIT *uptr) uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd RSL done chsa %04x count %04x completed\n", chsa, chp->ccw_count); +/*25*/ chp->ccw_count = 0; chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; diff --git a/SEL32/sel32_ec.c b/SEL32/sel32_ec.c index acc239e..42b39ed 100644 --- a/SEL32/sel32_ec.c +++ b/SEL32/sel32_ec.c @@ -36,9 +36,10 @@ #define CMD u3 /* u3 */ /* in u3 is device command code and status */ -#define EC_CMDMSK 0x0ff /* Command being run */ +#define EC_CMDMSK 0x0ff /* Command being run */ /* commands */ #define EC_INCH 0x00 /* Initialize channel */ +#define EC_INCH2 0xf0 /* Initialize channel command for processing */ #define EC_WRITE 0x01 /* Write frame */ #define EC_READ 0x02 /* Read frame*/ #define EC_NOP 0x03 /* No operation */ @@ -212,10 +213,12 @@ extern int32 tmxr_poll; static CONST ETH_MAC broadcast_ethaddr = {0xff,0xff,0xff,0xff,0xff,0xff}; /* channel program information */ -CHANP ec_chp[8] = {0}; +//CHANP ec_chp[8] = {0}; +CHANP ec_chp[10] = {0}; uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; t_stat ec_srv(UNIT *uptr); +uint16 ec_haltio(UNIT *uptr); 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); @@ -232,6 +235,7 @@ const char *ec_description (DEVICE *dptr); UNIT ec_unit[] = { {UDATA(ec_srv, UNIT_IDLE|UNIT_ATTABLE, 0), 0, UNIT_ADDR(0xE00)}, /* 0 */ +#ifdef FOR_DIAG {UDATA(ec_srv, UNIT_IDLE|UNIT_DIS|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE01)}, /* 1 */ {UDATA(ec_srv, UNIT_IDLE|UNIT_DIS|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE02)}, /* 2 */ {UDATA(ec_srv, UNIT_IDLE|UNIT_DIS|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE03)}, /* 3 */ @@ -239,20 +243,30 @@ UNIT ec_unit[] = { {UDATA(ec_srv, UNIT_IDLE|UNIT_DIS|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE05)}, /* 5 */ {UDATA(ec_srv, UNIT_IDLE|UNIT_DIS|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE06)}, /* 6 */ {UDATA(ec_srv, UNIT_IDLE|UNIT_DIS|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE07)}, /* 7 */ +#else + {UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE01)}, /* 1 */ + {UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE02)}, /* 2 */ + {UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE03)}, /* 3 */ + {UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE04)}, /* 4 */ + {UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE05)}, /* 5 */ + {UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE06)}, /* 6 */ + {UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE07)}, /* 7 */ + {UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE08)}, /* 8 */ + {UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE09)}, /* 9 */ +#endif }; - - DIB ec_dib = { NULL, /* Pre start I/O */ ec_startcmd, /* Start a command */ - NULL, /* Stop I/O */ + 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 */ - 8, /* number of units defined */ +// 8, /* number of units defined */ + 10, /* number of units defined */ 0x0F, /* device mask */ 0x0E00, /* parent channel address */ 0, /* fifo input index */ @@ -295,7 +309,8 @@ DEBTAB ec_debug[] = { DEVICE ec_dev = { "EC", ec_unit, NULL, ec_mod, - 8, 16, 24, 4, 16, 32, +// 8, 16, 24, 4, 16, 32, + 10, 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 @@ -307,7 +322,7 @@ uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { DEVICE *dptr = get_dev(uptr); uint16 chsa = GET_UADDR(uptr->CMD); -// CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ sim_debug(DEBUG_CMD, dptr, "ec_startcmd chsa %04x unit %d cmd %02x CMD %08x\n", @@ -316,32 +331,69 @@ 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); + 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) { - case EC_WRITE: /* Write command 0x01 */ - case EC_READ: /* Read command 0x02 */ - case EC_TIC: /* Transfer in channel */ - case EC_CGA: /* Disable multicast address */ - case EC_LCC: /* Configure LCC */ - case EC_STATS: /* Read Statistics */ - case EC_CSTATS: /* Clear software counters */ - case EC_NOP: /* NOP 0x03 */ - case EC_INCH: /* INCH cmd 0x0 */ - case EC_LIA: /* Load individual address */ - case EC_LGA: /* Load Multicast address */ - uptr->SNS &= 0xff0000; + case EC_INCH: /* INCH cmd 0x0 */ + cmd = EC_INCH2; /* set dummy INCH cmd 0xf0 */ + case EC_WRITE: /* Write command 0x01 */ + case EC_READ: /* Read command 0x02 */ + case EC_TIC: /* Transfer in channel */ + case EC_CGA: /* Disable multicast address */ + case EC_LCC: /* Configure LCC */ + case EC_STATS: /* Read Statistics */ + case EC_CSTATS: /* Clear software counters */ + case EC_NOP: /* NOP 0x03 */ + case EC_LIA: /* Load individual address */ + case EC_LGA: /* Load Multicast address */ + uptr->SNS &= 0xffff0000; +// uptr->SNS &= 0x7fff0000; /* remove invalid cmd status */ + uptr->SNS &= ~SNS_CMDREJ; /* remove CMD reject status */ /* Fall through */ - case EC_SNS: /* Sense 0x04 */ + case EC_SNS: /* Sense 0x04 */ +#ifdef FIGURE_THIS_OUT + /* diags want 4 byte multiple, but if data chaining is set it can be odd */ + /* ethernet transfers must be multiple of 4 bytes */ + if ((cmd == EC_WRITE) || (cmd == EC_READ) || + (cmd == EC_STATS) || (cmd == EC_LCC)) { +// (cmd == EC_STATS) || (cmd == EC_LCC) || (cmd == EC_SNS)) { + if ((chp->ccw_count & 0x03) != 0) + return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; /* diags want prog check */ + } +#endif + /* nop must have none zero count */ + if (cmd == EC_NOP) { + if (chp->ccw_count == 0) + return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; /* diags want prog check */ + } uptr->CMD |= cmd|EC_BUSY; /* save cmd */ sim_activate(uptr, 300); /* start things off */ return 0; } uptr->SNS |= SNS_CMDREJ; - sim_debug(DEBUG_CMD, dptr, "ec_startcmd illegal with ec_startcmd %02x SNS %08x\n", + sim_debug(DEBUG_CMD, dptr, "ec_startcmd illegal cmd %02x SNS %08x\n", cmd, uptr->SNS); - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + 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 disk requests. */ @@ -353,9 +405,9 @@ t_stat ec_srv(UNIT *uptr) int cmd = uptr->CMD & EC_CMDMSK; uint32 mema; int i; - int n; + int n, len; uint8 ch; - uint8 buf[256]; + uint8 buf[1520]; uint8 *pck; struct ec_eth_hdr *hdr; @@ -363,13 +415,14 @@ t_stat ec_srv(UNIT *uptr) "ec_srv cmd=%02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); switch (cmd) { - case EC_INCH: /* INCH cmd 0x0 */ +// case EC_INCH: /* INCH cmd 0x0 */ + case EC_INCH2: /* INCH cmd 0xF0 */ + len = chp->ccw_count; /* INCH command count */ sim_debug(DEBUG_CMD, dptr, "ec_srv starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n", uptr->u4, chsa, chp->ccw_addr, chp->ccw_count); mema = chp->ccw_addr; /* get inch or buffer addr */ - - uptr->CMD &= LMASK; /* remove old status bits & */ + uptr->CMD &= LMASK; /* remove old status bits & */ /* now call set_inch() function to write and test inch buffer addresses */ i = set_inch(uptr, mema); /* new address */ @@ -379,11 +432,23 @@ t_stat ec_srv(UNIT *uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } +#ifndef DIAG_WANTS_COUNT + 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; + } + /* just dump data */ + } +#endif chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case EC_LIA: /* Load individual address */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + case EC_LIA: /* Load individual address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ for(i = 0; i < sizeof (ETH_MAC); i++) { if (chan_read_byte(chsa, &buf[i])) { chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); @@ -427,7 +492,7 @@ t_stat ec_srv(UNIT *uptr) for(i = 0; i< n; i++) { eth_mac_fmt(&ec_data.macs[i], (char *)&buf[0]); - sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv load mcast%d: %s\n\r",i,buf); + sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv load mcast%d: %s\n",i,buf); } if (ec_master_uptr->flags & UNIT_ATT) @@ -493,12 +558,12 @@ runt: case EC_READ: /* Read command 0x02 */ ec_master_uptr->SNS |= SNS_RCV_RDY; if (eth_read(&ec_data.etherface, &ec_data.rec_buff, NULL) <= 0) { - sim_clock_coschedule(uptr, 1000); /* continue poll */ + sim_clock_coschedule(uptr, 1000); /* continue poll */ return SCPE_OK; } ec_packet_debug(&ec_data, "recv", &ec_data.rec_buff); ec_data.rx_count++; - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ hdr = (struct ec_eth_hdr *)(&ec_data.rec_buff.msg[0]); pck = (uint8 *)(&ec_data.rec_buff.msg[0]); switch (GET_MODE(ec_master_uptr->flags)) { @@ -538,12 +603,12 @@ runt: break; } } - sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv received bytes %d\n\r",i); + sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv received bytes %d\n",i); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; case EC_LCC: /* Configure LCC */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ /* Read up to 12 bytes */ for (i = 0; i < 12; i++) { if (chan_read_byte(chsa, &ch)) { @@ -556,7 +621,7 @@ runt: case EC_STATS: /* Read Statistics */ ch = 0; /* First 5 words are always zero since these errors are not supported */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ for (i = 0; i < STAT_LEN * 2; i++) { if (chan_write_byte(chsa, &ch)) { break; @@ -583,53 +648,114 @@ runt: chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case EC_CSTATS: /* Clear software counters */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + case EC_CSTATS: /* Clear software counters */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ ec_data.rx_count = ec_data.tx_count = 0; chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case EC_NOP: /* NOP 0x03 */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + case EC_NOP: /* NOP 0x03 */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "ec_srv cmd NOP chsa %04x count %04x completed\n", chsa, chp->ccw_count); + /* diags want the count to be returned zero */ + chp->ccw_count = 0; /* NOP command count */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; - case EC_SNS: /* 0x4 */ - sim_debug(DEBUG_CMD, dptr, "ec_startcmd CMD sense\n"); + case EC_SNS: /* 0x4 */ + sim_debug(DEBUG_CMD, dptr, + "ec_startcmd CMD sense cnt %02x\n", chp->ccw_count); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + + /* diags want incorrect length or prog check */ + if (chp->ccw_count < 0x04) { + chp->ccw_count = 0; /* zero command count */ + if ((chp->ccw_flags & FLAG_SLI) == 0) { + /* diag wants incorrect length */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_LENGTH); + break; + } + } ch = (uptr->SNS >> 24) & 0xfc; ch |= GET_MODE(ec_master_uptr->flags); - sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense CHS b0 1 %02x\n", ch); + sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense b0 1 %02x\n", ch); chan_write_byte(chsa, &ch); ch = (ec_master_uptr->SNS >> 16) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense CHS b1 2 %02x\n", ch); + sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense b1 2 %02x\n", ch); chan_write_byte(chsa, &ch); ch = (ec_data.rec_buff.len >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense CHS b2 3 %02x\n", ch); + sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense b2 3 %02x\n", ch); chan_write_byte(chsa, &ch); ch = ec_data.rec_buff.len & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense CHS b3 4 %02x\n", ch); + sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense b3 4 %02x\n", ch); chan_write_byte(chsa, &ch); - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + if (chp->ccw_count > 0) { + if (chp->ccw_flags & FLAG_SLI) + /* diags want prog check */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + else + /* diag wants incorrect length */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_LENGTH); + sim_debug(DEBUG_CMD, dptr, + "ec_startcmd CMD sense excess cnt %02x\n", chp->ccw_count); + break; + } chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - default: +#ifdef ALLOW_0_CMD sim_debug(DEBUG_CMD, dptr, "invalid command %02x\n", cmd); uptr->SNS |= SNS_CMDREJ; 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); +#endif } sim_debug(DEBUG_DETAIL, dptr, "ec_srv done cmd=%02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); return SCPE_OK; } +/* Handle haltio transfers for ethernet */ +uint16 ec_haltio(UNIT *uptr) { + uint16 chsa = GET_UADDR(uptr->CMD); + DEVICE *dptr = get_dev(uptr); + int cmd = uptr->CMD & EC_CMDMSK; + CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + + sim_debug(DEBUG_EXP, dptr, "ec_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 & EC_CMDMSK) != 0) { /* is unit busy */ + sim_debug(DEBUG_CMD, dptr, + "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_flags &= (FLAG_DC|FLAG_CC);/* stop any chaining */ + uptr->CMD &= LMASK; /* make non-busy */ + uptr->SNS = SNS_RCV_RDY; /* status is online & ready */ + sim_cancel(uptr); /* clear the input timer */ + sim_debug(DEBUG_CMD, &con_dev, + "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; + } + uptr->CMD &= LMASK; /* make non-busy */ + uptr->SNS = SNS_RCV_RDY; /* status is online & ready */ + return SCPE_OK; /* not busy */ +} + /* initialize the ethernet */ void ec_ini(UNIT *uptr, t_bool f) { @@ -908,6 +1034,7 @@ t_stat ec_attach(UNIT* uptr, CONST char* cptr) ec_dev.name, buf); } if (SCPE_OK != eth_filter(&ec_data.etherface, 2, ec_data.macs, 0, 0)) { +// if (SCPE_OK != eth_filter(&ec_data.etherface, 2, ec_data.macs, 0, 1)) { eth_close(&ec_data.etherface); free(tptr); return sim_messagef (SCPE_NOATT, diff --git a/SEL32/sel32_mt.c b/SEL32/sel32_mt.c index 30e0c45..a7d0301 100644 --- a/SEL32/sel32_mt.c +++ b/SEL32/sel32_mt.c @@ -440,7 +440,7 @@ uint16 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) chan, cmd); uptr->SNS |= SNS_CMDREJ; /* send program check */ - return SNS_CHNEND|STATUS_PCHK; + return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; /* add DEVEND 08/16/20 */ break; } #if 0 @@ -520,7 +520,7 @@ t_stat mt_srv(UNIT *uptr) uint32 mema; uint16 len; uint8 ch; - uint8 buf[1024]; +// uint8 buf[1024]; sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv unit %04x cmd %02x\n", unit, cmd); if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ @@ -547,6 +547,7 @@ t_stat mt_srv(UNIT *uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } +#ifdef DIAG_WANTS_COUNT for (i=0; i < len; i++) { if (chan_read_byte(chsa, &buf[i])) { /* we have error, bail out */ @@ -557,6 +558,7 @@ t_stat mt_srv(UNIT *uptr) } /* just dump data */ } +#endif /* the chp->ccw_addr location contains the inch address */ /* call set_inch() to setup inch buffer */ i = set_inch(uptr, mema); /* new address */ diff --git a/SEL32/sel32_scsi.c b/SEL32/sel32_scsi.c index c3f52b6..366104e 100644 --- a/SEL32/sel32_scsi.c +++ b/SEL32/sel32_scsi.c @@ -826,7 +826,6 @@ t_stat scsi_srv(UNIT *uptr) if (uptr->SNS & SNS_TCMD) { /* we need to process a read TCMD data */ int cnt = scsi_buf[bufnum][unit][4]; /* byte count of status to send */ - ch = scsi_buf[bufnum][unit][0]; /* return TCMD cmd */ uint32 cyl = CYL(type); /* number of cylinders */ uint32 spt = SPT(type); /* sectors per track */ uint32 ssb = SSB(type); /* sector size in bytes */ @@ -834,6 +833,7 @@ t_stat scsi_srv(UNIT *uptr) /* cnt has # bytes to return (0xf0) */ uint8 pagecode = scsi_buf[bufnum][unit][2] & 0x3f; /* get page code */ uint8 pagecont = (scsi_buf[bufnum][unit][2] & 0xc0) >> 6; /* get page control */ + ch = scsi_buf[bufnum][unit][0]; /* return TCMD cmd */ uptr->SNS &= ~SNS_TCMD; /* show not presessing TCMD cmd chain */ sim_debug(DEBUG_CMD, dptr, "scsi_srv processing TCMD read cmd %02x, chsa %04x tcma %06x cnt %04x\n", diff --git a/SEL32/taptools/README.md b/SEL32/taptools/README.md index b02b069..1fedb62 100644 --- a/SEL32/taptools/README.md +++ b/SEL32/taptools/README.md @@ -24,8 +24,8 @@ cutostap - This program scans a metadata .tap file and copies files .tap sdt image. The mkfmcopy can be used to create a user sdt tape with files following the sdt image. - command filelist stdout - input - stdin stdout + input - stdin file to be written with sdt image diskload - This program reads an MPX load module and stores it into @@ -36,16 +36,16 @@ diskload - This program reads an MPX load module and stores it into command: diskload -la program diskfile option -a - add filename to diskfile option -l - list files in diskfile SMD, ignore filename - input - filename - file to copy to system disk - - diskfile - simulated system disk + input - filename - file to copy to system disk + - diskfile - simulated system disk output - modified system disk filelist - This program scans a metadata .tap file and prints the file count and sizes. Used to determine the file format contained in the metadata .tap file. - command filelist stdout - input - stdin stdout + input - stdin stdout - input - file.tap file to dump + command: fmgrcopy file.tap >stdout + input - file.tap file to dump output - stdout filelist and sizes output - directory/files extracted to current directory @@ -67,7 +67,7 @@ mkfmtape - This program creates an MPX 1.x filemgr save tape. The tape can then be used to restore files to the MPX-1.X system. The output will be in SIMH simulated .tap format. - command mkfmtape opts output.tap file1 file2 ... + command: mkfmtape opts output.tap file1 file2 ... input - list of filename to save to tape. output - output.tap a tap formatted file. options - -p = file type 0xca for programs @@ -78,12 +78,12 @@ mkfmtape - This program creates an MPX 1.x filemgr save tape. The - -u = username (directory) mkvmtape - This program reads MPX files and stores them into a - simulated volmgr save tape. The tape may then become a - MPX 3.X sdt boot tape to install MPX 3.X from or a volmgr - file restore tape for a running MPX system. The output - will be in SIMH simulated .tap format. + simulated volmgr save tape. The tape may then become + a MPX 3.X sdt boot tape to install MPX 3.X from or a + volmgr file restore tape for a running MPX system. + The output will be in SIMH simulated .tap format. - command mkfmtape [-ptloa] [-bboot] [-iimage] [-jj.vfmt] + command: mkfmtape [-ptloa] [-bboot] [-iimage] [-jj.vfmt] [-uusername] tapname file1 file2 ... intput - [options] volmtape filename, filename, etc. output - volmtape file, file list to stdout @@ -101,6 +101,33 @@ mkvmtape - This program reads MPX files and stores them into a - -j = j.vfmt filename 04/11/2020 update for mpx3.x +mkdiagtape.c - This program extracts the diag command file (file 2) + from a diagnostic tape in .tap format and replaces it + with a new command file. The rest of the tape is copied + unchanged. The original command file from the diag tape + must be extracted from the diag tape using the diagcopy + utility. This file can then be deblocked using the deblk + utility. The file can then be editied using VI or your + favorite editor. Lines must be blank filled to 80 chars + exactly after editing. The mpxblk utility must then be + used to restore the file to blocked MPX format before + installing it on the new diag tape. + + 1. mkdir temp; Create temp directory. + 2. cp diag.tap temp; Copy in current diag tape. + 3. cd temp; Move to temp directory. + 4. diagcopy diag.tap; Extract diag tape contents. + 5. deblk cmdfile >cmd.txt; Creat unblocked text file. + 6. vi cmd.txt; Edit text file with new commands and save. + 7. mpxblk cmd.blk; Restore blocked file format. + 8. mkdiagtape -c cmd.txt diag.tap newdiag.tap. + 9. copy newdiag.tap to execution directory and run sel32. + + command: mkdiagtape -c cmdfile olddiag newdiag + intput - simulated in_diagtape + output - simulated newtape + option - -c cmdfile + diagcopy - This program reads a SEL .tap diagnostic boot tape and splits the contents into multiple files. The first tape record is 204 bytes of boot code and is put into the file bootcode. @@ -116,8 +143,8 @@ diagcopy - This program reads a SEL .tap diagnostic boot tape and splits the tape. These records are all multiple of 768 bytes each and contain binary programs. - command diagcopy diag.tap - input - diag.tap file to dump + command: diagcopy diag.tap + input - diag.tap file to dump output - stdout filelist and sizes output - if tape contains a valid diag image, it will be output to files bootfile, cmdfile, dolfile and @@ -130,8 +157,8 @@ tapdump - This program reads a metadata .tap file and prints a side hitting will terminate the display, and hitting will skip to the next file on the simulated tape. - command tapdump stdout - input - stdin stdout + input - stdin stdout - input - file.tap file to scan + command: tapscan file.tap >stdout + input - file.tap file to scan output - stdout filelist and sizes volmcopy - This program reads a MPX 3.x volmgr save tape. The tape @@ -168,8 +195,8 @@ volmcopy - This program reads a MPX 3.x volmgr save tape. The tape file MUST be a volmgr save tape and not a MPX-1.x SDT/save tape. - command fmgrcopy file.tap >stdout - input - file.tap file to dump + command: fmgrcopy file.tap >stdout + input - file.tap file to dump output - stdout filelist and sizes output - directory/files extracted to current directory @@ -181,7 +208,7 @@ ddump - Create a sys by side ascii dump of a file. Same operation hex address can be input to display data at a given offset in the file. Optionall, the file data can be modified. - command - ddump -r filename + command: ddump -r filename option - -r means open file read only input - filename file to read output - side by size ascii dump of file @@ -190,7 +217,7 @@ deblk - read and convert mpx blocked ifile to unblocked unix file format. Compressed and uncompressed files records can be read. Output is an ascii string with '\n' termination. - command - deblk [filename] + command: deblk [filename] input - filename or if non specified, stdin output - ascii sting to stdout @@ -198,7 +225,7 @@ mpxblk - Create an MPX blocked file from a '\n' terminated ascii character string file. Trailing blanks are not deleted from the source file. Max line size is 254 bytes. - command - mpxblk fileout + command: mpxblk fileout input - read ascii file from stdin output - write mpx blocked file to stdout @@ -208,7 +235,7 @@ renum - Create a numbered file from a '\n' terminated ascii file. A line number in the form of XXXX.000 are appended to create 80 char '\n' terminated lines. - command - renum fileout + command: renum fileout input - read ascii file from stdin output - write numbered ascii file to stdout @@ -217,9 +244,9 @@ small - Remove line numbers and trailing blanks from an ascii '\n' stripped of trailing blanks. Output is '\n' terminated ascii files. - command - small fileout + command: small fileout input - read ascii file from stdin output - write stripped ascii file to stdout James C. Bevier -04/21/2020 +08/21/2020 diff --git a/SEL32/taptools/makefile b/SEL32/taptools/makefile index 26d12c9..527b06c 100644 --- a/SEL32/taptools/makefile +++ b/SEL32/taptools/makefile @@ -29,6 +29,7 @@ PROGS = \ $(ROOT)/mkfmtape \ $(ROOT)/mkvmtape \ $(ROOT)/sdtfmgrcopy \ + $(ROOT)/mkdiagtape \ $(ROOT)/tapdump \ $(ROOT)/tape2disk \ $(ROOT)/tapscan \ @@ -94,6 +95,12 @@ $B/sdtfmgrcopy: $D sdtfmgrcopy.c @cp $(@F) $B @echo $(@F) installed in $B +$B/mkdiagtape: $D mkdiagtape.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + $B/tapdump: $D tapdump.c @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ @chmod 755 $@ diff --git a/SEL32/taptools/mkdiagtape.c b/SEL32/taptools/mkdiagtape.c new file mode 100644 index 0000000..03a124a --- /dev/null +++ b/SEL32/taptools/mkdiagtape.c @@ -0,0 +1,276 @@ +/* + * mkdiagtape.c + * + * This program extracts the diag command file (file 2) from a + * diagnostic tape in .tap format and replaces it with a new + * command file. The rest of the tape is copied unchanged. + * intput - simulated indiagtape outdiagtape + * output - simulated newtape + * option - -c = cmdfile + * 08/22/2020 + */ + +#include +#include +#include +#include +#include + +#define BLKSIZE 768 /* MPX file sector size */ +unsigned char data[7680]; /* room for 10*768=(7680) 768 byte sectors per 7680 byte block */ + +/* write 1 file to tape in 768 byte records */ +/* mblks is the maximum blockes to write from a file, 0=all */ +/* chunks is the number of sectors to wrote at a time 1-8 */ +int writefile(FILE *tp, char *fnp, u_int32_t mblks, int32_t chunks) { + u_int32_t word, blks=mblks; /* just a temp word variable */ + u_int32_t size, bsize, csize; /* size in 768 byte sectors */ + FILE *fp; + int32_t n1, n2, hc, nw, cs; + + memset((char *)data, 0, sizeof(data)); /* zero data storage */ + /* write file to tape */ + if ((fp = fopen(fnp, "r")) == NULL) { + fprintf(stderr, "error: can't open user file %s\n", fnp); + exit(1); + } + fseek(fp, 0, SEEK_END); /* seek to end */ + word = ftell(fp); /* get filesize in bytes */ +//printf("MPX file %s is %x (%d) bytes\n", fnp, word, word); + fseek(fp, 0, SEEK_SET); /* rewind file */ + size = (word/768); /* filesize in sectors */ + if (word%768 != 0) /* see if byte left over */ + size += 1; /* partial sector, add 1 */ + if (mblks == 0) { + mblks = (word/768); /* blocks */ + if ((word%768) != 0) /* round up blks if remainder */ + mblks++; /* total block to write */ + } + blks = mblks/chunks; /* chunks */ + if (mblks%768 != 0) /* see if blks left over */ + blks += 1; /* partial blks, add 1 */ + + bsize = mblks; /* save # blks */ + +//printf("MPX file %s is %x (%d) bytes blks %d chk %d\n", +// fnp, word, word, bsize, (bsize+1)/chunks); + csize = 0; + /* read in the image file */ + while (bsize > 0) { + if (bsize > chunks) /* see if there is a chunk left to read */ + csize = chunks; /* yes, do max chunk size */ + else + csize = bsize; /* no, use what is left */ + cs = fread((char *)data, 1, csize*768, fp); + /* we have data to write */ + hc = (csize*768 + 1) & ~1; /* make byte count even */ + /* write actual byte count to 32 bit word as header */ + n1 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), tp); + /* write the data mod 2 */ + nw = fwrite((unsigned char *)data, 1, (size_t)hc, tp); + /* write the byte count in 32 bit word as footer */ + n2 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), tp); + if (n1 != sizeof(hc) || nw != hc || n2 != sizeof(hc)) + { + fprintf(stderr, "write to %s failure\n", fnp); + fprintf(stderr, "Operation aborted\n"); + exit(1); + } + bsize -= csize; /* do next chunk */ + memset((char *)data, 0, csize); /* zero data storage */ + } +//printf("write file %s (size %d bytes) (%d sect) (%d blocks) (%d chunks)\n", +// fnp, word, size, mblks, blks); + fclose(fp); +} + +/* read program file and output to a simulated diagnostic tape */ +/* mkdiagtape -c cmdfile diagtape diagtapeout */ +int main(argc, argv) +int argc; +char *argv[]; +{ + FILE *dp, *fp, *cp, *fopen(); + int targc; + char **targv; + char *p, *cmdp; + int i; + unsigned char *fnp; /* file name pointer */ + unsigned int size; /* size in 768 byte sectors */ + unsigned int word; /* just a temp word variable */ + int goteof, goteom; /* end flags */ + int writing; /* writing output */ + + memset((char *)data, 0, 4608); /* zero data storage */ + + targv = argv; /* save filename */ + if (argc <= 1) { /* see if correct # args */ + fprintf(stderr, "Usage: %s [-ptloa] [-uusername] fmgrtape file1 file2 ...\n", *argv); + exit(1); + } + while(--argc > 0) { +// printf("argc %d argv %s\n", argc, *argv); + p = *++argv; + if (*p++ == '-') { + if (*p == '\0') { + fprintf(stderr, "Error: no option specified\n"); + fprintf(stderr, "Usage: %s -c cmdfile infile outfile\n", *targv); + exit(1); + } +// printf("doing options %s\n", p); + while (*p != '\0') { + switch (*p++) { + case 'c': + case 'C': + if (*p == '\0') { + p = *++argv; /* next parameter */ + --argc; /* one less arg */ + }; + cmdp = p; /* save ptr to file name */ + while (*p != '\0') + p++; + break; + default: + fprintf(stderr, "Error: no cmd file specified\n"); + fprintf(stderr, "Usage: %s -c cmdfile infile outfile\n", *targv); + exit(1); + break; + } /* end switch */ + continue; + } /* end while */ + } + else { + if ((dp = fopen(*argv, "r")) == NULL) { + fprintf(stderr, "error: can't open input diag tape file %s\n", *argv); + exit(1); + } + printf("opening %s file for tape\n", *argv); + *++argv; + break; /* go handle files now */ + } + continue; + } + /* end while --argc */ + if ((argc-1) <= 0) { + fprintf(stderr, "Error: incorrect number of parameters\n"); + fprintf(stderr, "Usage: %s -c cmdfile infile outfile\n", *targv); + exit(1); + } + /* got input tapefile and options, handle output file now */ +// printf("AT 3 argc %d argv %s\n", argc, *argv); + if (--argc > 0) { + int blks; + + p = *argv++; + printf("argc %d argv3 %s\n", argc, p); + if ((fp = fopen(p, "w")) == NULL) { + fprintf(stderr, "error: can't open tape output file %s\n", p); + fprintf(stderr, "Usage: %s -c cmdfile infile outfile\n", *targv); + exit(1); + } + printf("opened output file %s\n", p); + } + + /* now copy input tape until 1st EOF */ + goteof = 0; /* no eof yet */ + writing = 1; /* we are copying in to out */ + while (goteof == 0) { + int n1, n2, hc, tc, n, nw; + /* read the byte count in 32 bit word as header */ + n1 = fread((char *)(&hc), 1, (size_t)4, dp); + + /* check for EOM on tape */ + if ((n1 <= 0) || (hc & 0xffff0000)) { /* check for garbage, assume EOM */ + fprintf(stderr, "Premature EOM on input file bad tape\n"); + exit(1); + } + /* see if at EOF */ + if (hc == 0) { + /* we are at tape EOF */ + if (writing == 0) + break; /* done with copy */ + writing = 0; /* stop writing */ + /* copy the EOF to the output tape */ + n1 = fwrite((char *)(&hc), 1, (size_t)4, fp); + if (n1 != 4) { + fprintf(stderr, "Error write EOF to output file\n"); + exit(1); + } + continue; /* continue processing */ + } + + /* read the data to copy to output */ + n = fread(data, 1, (size_t)hc, dp); + if (n <= 0) { + fprintf(stderr, "Read error on input file bad tape\n"); + exit(1); + } + + /* if odd byte record, read extra byte and throw it away */ + if (n & 0x1) { + n2 = fread((char *)(&tc), 1, (size_t)1, dp); + if (n2 <= 0) { + fprintf(stderr, "Read error on input file bad tape\n"); + exit(1); + } + } + /* if writing, write out the record */ + if (writing) { + int wc = n; /* get actual byte count */ + /* write actual byte count to 32 bit word as header */ + n1 = fwrite((char *)(&wc), 1, (size_t)4, fp); + /* write the data mod 2 */ + nw = fwrite(data, 1, (size_t)hc, fp); + if (n1 != 4 || nw != hc) { + fprintf(stderr, "write error to tape\n"); + exit(1); + } + } + + /* read the byte count in 32 bit word as trailer */ + n2 = fread((char *)(&tc), 1, (size_t)4, dp); + if (n2 <= 0) { + fprintf(stderr, "Read error on input file bad tape\n"); + exit(1); + } + if (writing) { + /* write the byte count in 32 bit word as footer */ + n2 = fwrite((char *)(&tc), 1, (size_t)4, fp); + if (n2 != 4) { + fprintf(stderr, "write error to tape\n"); + exit(1); + } + } + } + + /* now handle new command file */ + /* we have copied the first file and bypassed the second */ + /* copy in the new com file and write out 768 byte records */ + writefile(fp, cmdp, 0, 1); /* write command file out in 768 byte blks */ + + word = 0; + /* copy the EOF to the output tape */ + i = fwrite((char *)(&word), 1, (size_t)4, fp); + if (i != 4) { + fprintf(stderr, "Error writing EOF to output file\n"); + exit(1); + } + + while (1) { + /* read the data to copy to output */ + i = fread(data, 1, (size_t)7680, dp); + if (i <= 0) { + fprintf(stderr, "EOM input file, done\n"); + break; + } + /* write the data to output */ + i = fwrite(data, 1, (size_t)i, fp); + if (i <= 0) { + fprintf(stderr, "Error writing data to output file\n"); + break; + } + } + fclose(dp); + fclose(fp); + exit(0); +} diff --git a/SEL32/taptools/mkvmtape.c b/SEL32/taptools/mkvmtape.c index 5e5df83..7914730 100644 --- a/SEL32/taptools/mkvmtape.c +++ b/SEL32/taptools/mkvmtape.c @@ -45,20 +45,23 @@ #define BLKSIZE 768 /* MPX file sector size */ u_int32_t dir[32]; /* directory name */ u_int32_t vol[32]; /* volume name */ -unsigned char data[4608]; /* room for 6*768=(4608) 768 byte sectors per 4608 byte block */ +unsigned char data[6144]; /* room for 8*768=(6144) 768 byte sectors per 4608 byte block */ unsigned char bigdata[19200]; /* room for 6*768=(4608) 768 byte sectors per 4608 byte block */ u_int32_t M[768]; /* fake memory */ unsigned char bootcode[2048]; /* room for bootcode */ -unsigned char savelist[6144]; /* room for 8 byte flags, 127 (48 char) file names */ +u_int32_t resdes[384]; /* room for the 1536 char (two blks) resource descriptor */ +u_int32_t dirlist[1536]; /* 6144 byte directory listing */ int16_t savecnt = 0; /* entries in save list */ char sysname[16] = "SYSTEM "; /* write 1 file to tape in 768 byte records */ -int writefile(FILE *tp, char *fnp, u_int32_t mblks) { - u_int32_t word, blks; /* just a temp word variable */ - u_int32_t size, bsize; /* size in 768 byte sectors */ +/* mblks is the maximum blockes to write from a file, 0=all */ +/* chunks is the number of sectors to wrote at a time 1-8 */ +int writefile(FILE *tp, char *fnp, u_int32_t mblks, int32_t chunks) { + u_int32_t word, blks=mblks; /* just a temp word variable */ + u_int32_t size, bsize, csize; /* size in 768 byte sectors */ FILE *fp; - int32_t n1, n2, hc, nw; + int32_t n1, n2, hc, nw, cs; memset((char *)data, 0, sizeof(data)); /* zero data storage */ /* write file to tape */ @@ -68,24 +71,34 @@ int writefile(FILE *tp, char *fnp, u_int32_t mblks) { } fseek(fp, 0, SEEK_END); /* seek to end */ word = ftell(fp); /* get filesize in bytes */ -printf("MPX file %s is %x (%d) bytes\n", fnp, word, word); +//printf("MPX file %s is %x (%d) bytes\n", fnp, word, word); fseek(fp, 0, SEEK_SET); /* rewind file */ size = (word/768); /* filesize in sectors */ if (word%768 != 0) /* see if byte left over */ size += 1; /* partial sector, add 1 */ if (mblks == 0) { - blks = (word/768); /* blocks */ + mblks = (word/768); /* blocks */ if ((word%768) != 0) /* round up blks if remainder */ - blks++; - } else { - blks = mblks; /* write user specified blocks */ + mblks++; /* total block to write */ } - bsize = blks; /* save # blks */ + blks = mblks/chunks; /* chunks */ + if (mblks%768 != 0) /* see if blks left over */ + blks += 1; /* partial blks, add 1 */ + bsize = mblks; /* save # blks */ + +//printf("MPX file %s is %x (%d) bytes blks %d chk %d\n", +// fnp, word, word, bsize, (bsize+1)/chunks); + csize = 0; /* read in the image file */ - while ((bsize-- > 0) && fread((char *)data, 1, 768, fp) > 0) { + while (bsize > 0) { + if (bsize > chunks) /* see if there is a chunk left to read */ + csize = chunks; /* yes, do max chunk size */ + else + csize = bsize; /* no, use what is left */ + cs = fread((char *)data, 1, csize*768, fp); /* we have data to write */ - hc = (768 + 1) & ~1; /* make byte count even */ + hc = (csize*768 + 1) & ~1; /* make byte count even */ /* write actual byte count to 32 bit word as header */ n1 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), tp); /* write the data mod 2 */ @@ -98,10 +111,11 @@ printf("MPX file %s is %x (%d) bytes\n", fnp, word, word); fprintf(stderr, "Operation aborted\n"); exit(1); } - memset((char *)data, 0, 768); /* zero data storage */ + bsize -= csize; /* do next chunk */ + memset((char *)data, 0, csize); /* zero data storage */ } - printf("write file %s (size %d bytes) (%d sect) (%d blocks)\n", - fnp, word, size, blks); +//printf("write file %s (size %d bytes) (%d sect) (%d blocks) (%d chunks)\n", +// fnp, word, size, mblks, blks); fclose(fp); } @@ -119,7 +133,7 @@ u_int32_t readboot(char *name, char *buf, u_int32_t start, u_int32_t end) { n1 = fread(bootcode, 1, word, fp); /* read bootcode */ if (n1 <=0) /* check for read error */ exit(1); /* bad tape format */ -printf("MPX bootfile %s is %x (%d) bytes\n", name, word, word); +//printf("MPX bootfile %s is %x (%d) bytes\n", name, word, word); fclose(fp); fopen("volmboot", "w"); fwrite(bootcode, 1, word, fp); @@ -152,7 +166,7 @@ char *argv[]; unsigned char volname[32]; unsigned char dirname[32]; char *p; - int i; + int i, n, eof; #define DOPROG 1 #define DOADD 2 #define DOOTHER 4 @@ -164,6 +178,7 @@ char *argv[]; #define DOVFMT 256 #define DOVOL 512 #define DODIR 1024 +#define DOMASK (DOBOOT|DOIMG|DOVFMT) unsigned int option = DOTEXT; /* what to do */ unsigned char *fnp; /* file name pointer */ unsigned int size; /* size in 768 byte sectors */ @@ -190,7 +205,7 @@ char *argv[]; memset((char *)data, 0, 4608); /* zero data storage */ for (i=0; i<32; i++) username[i] = 0; /* use zero for system username */ - typ = 0xee000000; /* set type */ + typ = 0xee; /* set type */ if (argc <= 1) { /* see if correct # args */ fprintf(stderr, "Usage: %s [-ptloa] [-bboot] [-iimage] [-jj.vfmt] [-uusername] vmgrtape file1 file2 ...\n", @@ -198,7 +213,7 @@ char *argv[]; exit(1); } while(--argc > 0) { -// printf("argc %d argv %s\n", argc, *argv); +//printf("argc %d argv %s\n", argc, *argv); p = *++argv; if (*p++ == '-') { if (*p == '\0') { @@ -208,7 +223,7 @@ char *argv[]; *argv); exit(1); } -// printf("doing options %s\n", p); +//printf("doing options %s\n", p); while (*p != '\0') { switch (*p++) { case 'b': @@ -277,7 +292,8 @@ char *argv[]; case 'L': case 'l': option |= DOLIB; /* save library files */ - typ = 0xff; /* set type */ +// typ = 0xff; /* set type */ + typ = 0x00; /* set type */ break; case 'V': case 'v': @@ -325,7 +341,7 @@ error1: } /* end while */ } else { -// printf("option set to %x\n", option); +//printf("option set to %x\n", option); if (option & DOADD) { long bytes; /* open read/write */ @@ -342,18 +358,23 @@ error1: fseek(dp, 0, SEEK_END); /* seek to end */ bytes = ftell(dp); /* get filesize in bytes */ - printf("file length %ld bytes\n", bytes); - printf("start writing at %ld bytes offset\n", bytes-8); +//printf("1 file length %ld %lx bytes\n", bytes, bytes); +//printf("1 start writing at %ld %lx bytes offset\n", bytes-8, bytes-8); fseek(dp, 0, SEEK_SET); /* rewind file to beginning */ + /* at this point, we are at the end of the tape */ + /* we should see 3 EOF's w/ or w/o an EOM */ if (bytes > 8) { /* see if file written to already */ /* we need to find the EOT */ int32_t n1, n2, hc, tc, n; int EOFcnt = 0; readmore: + fseek(dp, bytes-4, SEEK_SET); /* seek back to EOF/EOM code */ n1 = fread((char *)(&hc), 1, (size_t)4, dp); /* read 4 byte record size */ if (n1 <=0) /* check for read error */ goto doabort; /* bad tape format */ +//printf("2 file length %ld %lx bytes\n", bytes, bytes); +//printf("2 start writing at %ld %lx bytes offset\n", bytes-8, bytes-8); if (hc & 0xffff0000) /* check for garbage */ hc = 0; /* assume EOF on disk */ @@ -362,19 +383,23 @@ readmore: if (++EOFcnt == 2) { /* we have second EOF, we need to backup 4 bytes */ backup4: - bytes = ftell(dp); /* get file position in bytes */ + /* we are setting after 2nd EOF, start writing there */ +// bytes -= 4; /* backup 4 bytes */ fseek(dp, bytes-4, SEEK_SET); /* backspace over 2nd EOF */ +//printf("3 file length %ld %lx bytes\n", bytes, bytes); +//printf("3 start writing at %ld %lx bytes offset\n", bytes-8, bytes-8); goto getout; /* start our processing */ } /* we have first EOF, keep reading */ + bytes -= 4; /* backup 4 bytes */ goto readmore; /* read more records */ } else if (hc == -1) { /* check for EOM */ - if (EOFcnt == 1) - /* see if one EOF followed by EOM (-1) */ - goto backup4; /* start write over the EOM */ - /* we have an EOM without any EOF, so bad tape */ - goto doabort; /* bad tape format */ + if (EOFcnt != 0) + /* we have an EOM before an EOF, so bad tape */ + goto doabort; /* bad tape format */ + bytes -= 4; /* backup 4 bytes */ + goto readmore; /* read more records */ } /* we have data, so no EOF */ @@ -404,10 +429,10 @@ doabort: fprintf(stderr, "error: can't create/open simulated tape disk file %s\n", *argv); exit(1); } -// printf("3 opened output in w mode, write at start\n"); +//printf("3 opened output in w mode, write at start\n"); } getout: -// printf("opening %s file for tape\n", *argv); +//printf("opening %s file for tape\n", *argv); *++argv; break; /* go handle files now */ } @@ -415,11 +440,13 @@ getout: } /* end while --argc */ - if (!((option & DOBOOT) && (option & DOIMG) && (option & DOVFMT))) { + if (!DOADD) { + if ((option & DOMASK) && ((option & DOMASK) != DOMASK)) { fprintf(stderr, "Error: incorrect number of sdt files, must be three\n"); - fprintf(stderr, "Usage: %s [-ptloa] [-uusername] fmgrtape, file1 file2 ...\n", *argv); + fprintf(stderr, "Usage: %s [-ptloa] [-uusername] vmgrtape, file1 file2 ...\n", *argv); exit(1); } + } /* process the bootfile first */ if (option & DOBOOT) { int32_t w2, n1, n2, nw, hc, blks; @@ -459,8 +486,7 @@ printf("bootfile %s is %x (%d) bytes\n", bootp, word, word); fprintf(stderr, "Operation aborted\n"); exit(1); } - printf("write boot file %s (size %d bytes)\n", - bootp, word, word); +printf("write boot file %s (size %d bytes)\n", bootp, word, word); /* setup for mpx image file */ memset((char *)data, 0, 0x800); /* zero data storage */ #ifdef USE_FILENAME @@ -499,23 +525,23 @@ printf("image file %s n1 %x (%d) n2 %x (%d) blks %x (%d)\n", fclose(fp); /* write mpx image file */ - writefile(dp, imgp, blks); /* write max of "blks" blocks to file */ + writefile(dp, imgp, blks, 1); /* write max of "blks" blocks to file */ /* write j.vfmt file */ - writefile(dp, vfmtp, 0); + writefile(dp, vfmtp, 0, 1); /* write 1 blk at a time */ /* write EOF (zero) to file */ filen = 0; /* zero count */ fwrite((char *)(&filen), 1, (size_t)sizeof(filen), dp); /* write j.mount file */ - writefile(dp, "j.mount", 0); + writefile(dp, "j.mount", 0, 1); /* one blk at a time */ /* write j.swapr file */ - writefile(dp, "j.swapr", 0); + writefile(dp, "j.swapr", 0, 1); /* one blk at a time */ /* write volmgr file */ - writefile(dp, "volmgr", 0); + writefile(dp, "volmgr", 0, 1); /* all of file 1 blk at a time */ /* write EOF (zero) to file */ filen = 0; /* zero count */ @@ -526,7 +552,7 @@ printf("image file %s n1 %x (%d) n2 %x (%d) blks %x (%d)\n", filen = -1; /* make in -1 for EOM */ /* do EOM */ fwrite((char *)(&filen), 1, (size_t)sizeof(filen), dp); -// printf("setting at %ld bytes in file after EOM\n", ftell(dp)); +//printf("setting at %ld bytes in file after EOM\n", ftell(dp)); fclose(dp); exit(0); } @@ -536,126 +562,124 @@ printf("image file %s n1 %x (%d) n2 %x (%d) blks %x (%d)\n", fprintf(stderr, "Error: incorrect number of parameters\n"); goto error1; /* we are done here */ } + /* save up to 127 file names in 6144 byte record */ + if (argc > 127) { + fprintf(stderr, "Error: only 127 files max at a time\n"); + goto error1; /* we are done here */ + } /*------------------------------------------------------------------------*/ - savecnt = 0; /* files yet */ + savecnt = 0; /* no files yet */ /* make first pass over files and get filenames and sizes */ /* got tapefile and options, handle files now */ targc = argc; /* save argc to reread list */ targv = argv; /* save argv to reread list */ -// printf("AT 3 argc %d argv %s\n", argc, *argv); +//printf("AT 3 argc %d argv %s\n", argc, *argv); filen = 0; /* no files yet */ totent = 0; /* no files yet */ /* save up to 127 file names in 6144 byte record */ + if (argc > 127) { + fprintf(stderr, "Error: only 127 files max at a time\n"); + goto error1; /* we are done here */ + } /* filename/directory/volume */ /* wd 1 is 1 for type 1 record */ /* wd 2 will be # of 48 byte pathnames */ - memset((char *)savelist, 0, sizeof(savelist)); /* zero data storage */ + memset((char *)dirlist, 0, sizeof(dirlist)); /* zero data storage */ + /* populate the 48 byte entry starting at byte 2 */ // dirp = (u_int32_t *)dir; /* get word pointer for directory */ // volp = (u_int32_t *)vol; /* get word pointer for volume */ - dirp = dirname; /* get word pointer for directory */ - volp = volname; /* get word pointer for volume */ +// dirp = dirname; /* get word pointer for directory */ +// volp = volname; /* get word pointer for volume */ +/// dirp = sysname; /* get word pointer for directory */ + volp = sysname; /* get word pointer for volume */ + n = 2; + dirlist[0] = n << 24; /* set record type to 1 */ while (--argc > 0) { - u_int32_t smd[8]; /* smd entry data */ - int blks; + u_int32_t smd[32]; /* dir entry data */ + int blks, eof; - for (i=0; i<8; i++) /* zero smd entry */ - smd[i] = 0; + for (i=0; i<16; i++) /* zero smd entry */ + smd[i] = 0x20; /* make blank */ p = *argv++; i = strlen(p); /* filename size */ - if (i == 0 || i > 8) { - fprintf(stderr, "error: Filename too long (%d>8) %s, Aborting\n", i, p); + if (i == 0 || i > 16) { + fprintf(stderr, "error: Filename too long (%d>16) %s, Aborting\n", i, p); exit(1); } -// printf("argc %d argv3 %s\n", argc, p); +//printf("argc %d argv3 %s\n", argc, p); if ((fp = fopen(p, "r")) == NULL) { fprintf(stderr, "error: can't open user file %s\n", p); exit(1); } fnp = p; /* get file name pointer */ - fseek(fp, 0, SEEK_END); /* seek to end */ - word = ftell(fp); /* get filesize in bytes */ - fseek(fp, 0, SEEK_SET); /* rewind file */ - size = (word/768); /* filesize in sectors */ - if (word%768 != 0) /* see if byte left over */ - size += 1; /* partial sector, add 1 */ - blks = (word/4608); /* blocks */ - if ((word%4608) != 0) - blks++; - printf("write SMD %s user %s size %d bytes %d sect %d blocks\n", - fnp, userp, word, size, blks); - fclose(fp); - /* create smd entry for this file */ - memset(name, ' ', 8); /* blank filename */ - for (i=0; i<8; i++) { + /* create dir entry for this file */ + /* first is 16 char filename */ + memset(name, ' ', 16); /* blank directory */ + for (i=0; i<16; i++) { if (p[i] == '\0') /* check for null termination char */ break; name[i] = toupper(p[i]); /* uppercase filename */ } - /* populate the 32 byte SMD entry */ - /* word 1 and 2 has filename */ - smd[0] = name[3] << 24 | name[2] << 16 | name[1] << 8 | name[0]; - smd[1] = name[7] << 24 | name[6] << 16 | name[5] << 8 | name[4]; - /* type and smd loc in wd 2 */ - smd[2] = typ; /* save the type of file */ - /* size now has load module size in sectors */ - size = 0x80000000 | (blks * 6); /* file flags and size */ - smd[3] = (size & 0xff) << 24 | (size & 0xff00) << 8 | - (size & 0xff0000) >> 8 | (size & 0xff000000) >> 24; - memset(name, ' ', 8); /* blank username */ - for (i=0; i<8; i++) { - if (userp[i] == '\0') /* check for null termination char */ + /* populate the 16 byte file name entry */ + dirlist[n+0] = name[3] << 24 | name[2] << 16 | name[1] << 8 | name[0]; + dirlist[n+1] = name[7] << 24 | name[6] << 16 | name[5] << 8 | name[4]; + dirlist[n+2] = name[11] << 24 | name[10] << 16 | name[9] << 8 | name[8]; + dirlist[n+3] = name[15] << 24 | name[14] << 16 | name[13] << 8 | name[12]; + n += 4; + + /* populate the 16 byte directory/user name entry */ + memset(name, ' ', 16); /* blank directory */ + for (i=0; i<16; i++) { + if (dirp[i] == '\0') /* check for null termination char */ break; - name[i] = toupper(userp[i]); /* uppercase username */ + name[i] = toupper(dirp[i]); /* uppercase directory name */ } - /* set username */ - smd[4] = name[3] << 24 | name[2] << 16 | name[1] << 8 | name[0]; - smd[5] = name[7] << 24 | name[6] << 16 | name[5] << 8 | name[4]; - if ((smd[4] == 0x20202020 && smd[5] == 0x20202020) || - (smd[4] == 0 && smd[5] == 0)) { - smd[4] = smd[5] = 0; /* use null for system */ + /* set directory name */ + dirlist[n+0] = name[3] << 24 | name[2] << 16 | name[1] << 8 | name[0]; + dirlist[n+1] = name[7] << 24 | name[6] << 16 | name[5] << 8 | name[4]; + dirlist[n+2] = name[11] << 24 | name[10] << 16 | name[9] << 8 | name[8]; + dirlist[n+3] = name[15] << 24 | name[14] << 16 | name[13] << 8 | name[12]; + n += 4; + + /* populate the 16 byte volume name entry */ + memset(name, ' ', 16); /* blank directory */ + for (i=0; i<16; i++) { + if (dirp[i] == '\0') /* check for null termination char */ + break; + name[i] = toupper(dirp[i]); /* uppercase directory name */ } - smd[6] = 0x00080000; /* no password or udt index */ - smd[7] = 0x00000080; /* fmgr has 0x80000000 in it so I will too */ - for (i=0; i<8; i++) - *dirp++ = smd[i]; /* save smd entry */ + /* set volume name */ + dirlist[n+0] = sysname[3] << 24 | sysname[2] << 16 | sysname[1] << 8 | sysname[0]; + dirlist[n+1] = sysname[7] << 24 | sysname[6] << 16 | sysname[5] << 8 | sysname[4]; + dirlist[n+2] = sysname[11] << 24 | sysname[10] << 16 | sysname[9] << 8 | sysname[8]; + dirlist[n+3] = sysname[15] << 24 | sysname[14] << 16 | sysname[13] << 8 | sysname[12]; + n += 4; + filen++; /* bump the file count */ totent++; /* bump total count */ - if (filen == 144) { /* see if entry is full */ - /* we need to write out the directory entries */ - int32_t n1, n2, nw; - /* we have data to write */ - int32_t hc = (4608 + 1) & ~1; /* make byte count even */ - /* write actual byte count to 32 bit word as header */ - n1 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), dp); - /* write the data mod 2 */ - nw = fwrite((unsigned char *)dir, 1, (size_t)hc, dp); - /* write the byte count in 32 bit word as footer */ - n2 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), dp); - if (n1 != sizeof(hc) || nw != hc || n2 != sizeof(hc)) - { - fprintf(stderr, "write (%d) failure\n", nw); - fprintf(stderr, "Operation aborted\n"); - exit(1); - } -// memset((char *)dir, 0, 4608); /* zero smd storage */ - filen = 0; /* restart count */ -// dirp = (u_int32_t *)dir; /* get word pointer for smd data */ - } } +//printf("AT write file list with %d entries\n", filen); + /* dirlist now has 1-127 filename entries to save */ /* write out the directory entries for the files to save */ if (filen != 0) { /* we need to write out the directory entries */ int32_t n1, n2, nw; - /* we have data to write */ - int32_t hc = (4608 + 1) & ~1; /* make byte count even */ + int32_t hc = (6144 + 1) & ~1; /* make byte count even */ + /* put record type 1 in dirlist[0] byte swapped */ + dirlist[0] = 0x01000000; /* record type 1 */ + /* put the number of entries into dirlist[1] */ + dirlist[1] = (filen&0xff) << 24 | (filen&0xff00) << 16 | + (filen&0xff0000) >> 8 | ((filen&0xff000000) >> 16); + + /* now output the record */ /* write actual byte count to 32 bit word as header */ n1 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), dp); /* write the data mod 2 */ - nw = fwrite((unsigned char *)dir, 1, (size_t)hc, dp); + nw = fwrite((unsigned char *)dirlist, 1, (size_t)hc, dp); /* write the byte count in 32 bit word as footer */ n2 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), dp); if (n1 != sizeof(hc) || nw != hc || n2 != sizeof(hc)) @@ -664,66 +688,223 @@ printf("image file %s n1 %x (%d) n2 %x (%d) blks %x (%d)\n", fprintf(stderr, "Operation aborted\n"); exit(1); } -// memset(dir, 0, 4608); /* zero smd storage */ - filen = 0; /* restart count */ +// filen = 0; /* restart count */ } + /* write EOF (zero) to file */ + eof = 0; /* zero count */ + fwrite((char *)(&eof), 1, (size_t)sizeof(eof), dp); + /* totcnt has total number of files to output */ memset((char *)data, 0, 4608); /* zero data storage */ argc = targc; /* restore argc for reread */ argv = targv; /* restore argv for reread */ + n = 2; /* read each file and output to save tape file in 6 sector blocks */ while (--argc > 0) { + int32_t n1, n2, nw, k; + int32_t hc = (1536 + 1) & ~1; /* make byte count even */ int blks; p = *argv++; -// printf("argc %d argv3 %s\n", argc, p); +//printf("at 4 argc %d argv %s\n", argc, p); + if ((fp = fopen(p, "r")) == NULL) { fprintf(stderr, "error: can't open user file %s\n", p); exit(1); } fnp = p; /* get file name pointer */ + + /* we need to write the resource descriptor in 2 blks to file */ + /* followed by file content is 8 blk chunks */ fseek(fp, 0, SEEK_END); /* seek to end */ word = ftell(fp); /* get filesize in bytes */ fseek(fp, 0, SEEK_SET); /* rewind file */ size = (word/768); /* filesize in sectors */ if (word%768 != 0) /* see if byte left over */ size += 1; /* partial sector, add 1 */ - blks = (word/4608); /* blocks */ - if ((word%4608) != 0) - blks++; -// rewind(fp); /* back to beginning */ - while (fread((char *)data, 1, 4608, fp) > 0) { - int32_t n1, n2, nw; - /* we have data to write */ - int32_t hc = (4608 + 1) & ~1; /* make byte count even */ - /* write actual byte count to 32 bit word as header */ - n1 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), dp); - /* write the data mod 2 */ - nw = fwrite((unsigned char *)data, 1, (size_t)hc, dp); - /* write the byte count in 32 bit word as footer */ - n2 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), dp); - if (n1 != sizeof(hc) || nw != hc || n2 != sizeof(hc)) - { - fprintf(stderr, "write (%d) failure\n", nw); - fprintf(stderr, "Operation aborted\n"); - exit(1); - } - memset((char *)data, 0, 4608); /* zero data storage */ - } - printf("write file %s user %s (size %d bytes) (%d sect) (%d blocks)\n", - fnp, userp, word, size, blks); + /* round up mod 4 */ + size += 3; + size &= ~3; fclose(fp); + /*******************************/ + memset((char *)resdes, 0, sizeof(resdes)); /* zero resource descriptor storage */ + /* wd 0 record type 2, wd 1 is zero of phase error flag n/u */ + resdes[0] = 0x02000000; /* 2 byte swapped */ + /* 48 char file/directory/volume name (122 wds) */ + /* copy name from dirlist written earlier */ + resdes[2] = dirlist[n+0]; /* file */ + resdes[3] = dirlist[n+1]; + resdes[4] = dirlist[n+2]; + resdes[5] = dirlist[n+3]; + resdes[6] = dirlist[n+4]; /* directory, system*/ + resdes[7] = dirlist[n+5]; + resdes[8] = dirlist[n+6]; + resdes[9] = dirlist[n+7]; + resdes[10] = dirlist[n+8]; /* volume, system */ + resdes[11] = dirlist[n+9]; + resdes[12]= dirlist[n+10]; + resdes[13]= dirlist[n+11]; + /* 16 word resource create block */ + resdes[14] = dirlist[n+8]; /* owner, system */ + resdes[15] = dirlist[n+9]; + resdes[16]= dirlist[n+10]; + resdes[17]= dirlist[n+11]; + resdes[18] = dirlist[n+8]; /* group, system */ + resdes[19] = dirlist[n+9]; + resdes[20]= dirlist[n+10]; + resdes[21]= dirlist[n+11]; + n += 12; + resdes[22]=flip(0x80f00000); /* owner rights */ + resdes[23]=flip(0x80b00000); /* group rights */ + resdes[24]=flip(0x80800000); /* other rights */ + if (typ == 0xca) + resdes[25]=flip(0x00040110); /* res mgmt flags */ + else + resdes[25]=flip(0x00040110); /* res mgmt flags */ +// resdes[25]=flip(0x0004011c); /* res mgmt flags */ + resdes[29]=flip(size); /* org file size */ + resdes[31]=flip(1000); /* file starting address n/u */ + resdes[33]=flip(0x00fbfeef); /* option flags */ + /* reset of block is zero */ + + /* second block is resosurce descriptor from disk */ + resdes[192] = dirlist[n+8]; /* volume, system */ + resdes[193] = dirlist[n+9]; + resdes[194]= dirlist[n+10]; + resdes[195]= dirlist[n+11]; + + resdes[196]=flip(0x00003190); /* creation date */ + resdes[197]=flip(0x0e8c8000); /* creation time */ + resdes[198]=flip(0x000003c0); /* abs blk if res des */ + resdes[199]=flip(0x0000000a); /* resource type, perm file */ + + resdes[200]=flip(0x000029cf); /* creation date */ + resdes[201]=flip(0x1dd8e074); /* creation time */ + //202 + //203 + + //204 + //205 + resdes[206]=flip(0x000029cf); /* last chge date */ + resdes[207]=flip(0x1dd8e074); /* last chge time */ + + resdes[208]=flip(0x00003190); /* creation date */ + resdes[209]=flip(0x0e8c8000); /* creation time */ + //210 + //211 + + resdes[212] = dirlist[n+8]; /* ownername last changer, system */ + resdes[213] = dirlist[n+9]; + resdes[214] = dirlist[n+8]; /* ownername creator, system */ + resdes[215] = dirlist[n+9]; + + //216 + //217 + resdes[218] = dirlist[n+8]; /* ownername of resource, system */ + resdes[219] = dirlist[n+9]; + + resdes[220] = dirlist[n+8]; /* group of resource, system */ + resdes[221] = dirlist[n+9]; + resdes[222]=flip(0xf8400000); /* owner access */ +// resdes[223]=flip(0xf8e00000); /* group access */ + resdes[223]=flip(0xf8400000); /* group access */ + + resdes[224]=flip(0x80000000); /* other access */ + //225 + resdes[226]=flip(0x00000001); /* resource link count */ + //227 + + //228-255 + + resdes[256]=flip(0xca100010); /* space definition flags */ + if (typ == 0xca) + resdes[256]=flip(0xca100010); /* space definition flags */ + else + if (typ == 0xee) + resdes[256]=flip(0xee1000f1); /* space definition flags */ + else + if (typ == 0x00) + resdes[256]=flip(0x001000f1); /* space definition flags */ + resdes[257]=flip(0x00000018); /* max extends */ + resdes[258]=flip(0x00000008); /* min incr */ + //259 + +// resdes[260]=flip(size-1); /* eof */ +// resdes[261]=flip(size); /* eom */ + resdes[260]=flip(size); /* eof */ + resdes[261]=flip(size+1); /* eom */ + resdes[262]=flip(0x00000001); /* segment */ + //263 + + resdes[264]=resdes[6]; /* directory, system*/ + resdes[265]=resdes[7]; + resdes[266]=resdes[8]; + resdes[267]=resdes[9]; + + resdes[268]=flip(0x00000100); /* parent blk number */ + resdes[269]=flip(0x00000001); /* segments at creation */ + //270 + //271 + + resdes[272]=resdes[2]; /* filename*/ + resdes[273]=resdes[3]; + resdes[274]=resdes[4]; + resdes[275]=resdes[5]; + + resdes[276]=flip(0x00000100); /* parent blk number */ + resdes[277]=flip(0x000005c0); /* parent didr index number */ + //277 + //278 + + //279-286 + + resdes[288]=flip(0x0000fda8); /* file blk number */ + resdes[289]=flip(size); /* eom */ + + /* all others are zero */ + + /* we have data to write */ + /* write actual byte count to 32 bit word as header */ + n1 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), dp); + /* write the data mod 2 */ + nw = fwrite((unsigned char *)resdes, 1, sizeof(resdes), dp); + /* write the byte count in 32 bit word as footer */ + n2 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), dp); + if (n1 != sizeof(hc) || nw != hc || n2 != sizeof(hc)) + { + fprintf(stderr, "rd write (%d) failure\n", nw); + fprintf(stderr, "Operation aborted\n"); + exit(1); + } + /*******************************/ + /* write file up to 8 blks at a time */ + writefile(dp, fnp, 0, 8); /* all of file 1 blk at a time */ + +//printf("File written at 4 argc %d argv %s\n", argc, fnp); + + /* write EOF (zero) to file */ + eof = 0; /* zero count */ + fwrite((char *)(&eof), 1, (size_t)sizeof(eof), dp); } + /* we have saved the files in the image, write 2 eof's & 1 EOM */ +// word = ftell(dp); /* get position in bytes */ +// printf("setting after file EOF write pos %x %d\n", word, word); /* write EOF (zero) to file */ filen = 0; /* zero count */ fwrite((char *)(&filen), 1, (size_t)sizeof(filen), dp); +// word = ftell(dp); /* get position in bytes */ +// printf("setting after 1st EOF file pos %x %d\n", word, word); /* do second EOF */ fwrite((char *)(&filen), 1, (size_t)sizeof(filen), dp); filen = -1; /* make in -1 for EOM */ +// word = ftell(dp); /* get position in bytes */ +// printf("setting after 2st EOF file pos %x %d\n", word, word); /* do EOM */ fwrite((char *)(&filen), 1, (size_t)sizeof(filen), dp); -// printf("setting at %ld bytes in file after EOM\n", ftell(dp)); +// word = ftell(dp); /* get position in bytes */ +// printf("setting after EOM file pos %x %d\n", word, word); +printf("setting at %lx (%ld) bytes in file after EOM\n", ftell(dp), ftell(dp)); fclose(dp); exit(0); } diff --git a/SEL32/taptools/tapdump.c b/SEL32/taptools/tapdump.c index af9cfba..f630aa1 100644 --- a/SEL32/taptools/tapdump.c +++ b/SEL32/taptools/tapdump.c @@ -50,11 +50,13 @@ int getloi(char *s, int lim) fprintf(stderr, "file %d: record %d: size %d (%x)\n", filen, lcount, ln, ln); } fprintf(stderr, "file %d: eof after %d records: %d bytes (%x)\n", filen, count, size, size); + fprintf(stderr, "file %d EOFcnt %d offset %x\n", filen, EOFcnt, tsize); #endif filen++; /* set next file number */ } else { #ifndef NOTDUMP fprintf(stderr, "second eof after %d files: %d bytes (%x)\n", filen, size, size); + fprintf(stderr, "second file %d EOFcnt %d offset %x\n", filen, EOFcnt, tsize); #endif } count = 0; /* file record count back to zero */