1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-01-21 10:12:30 +00:00

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.
This commit is contained in:
AZBevier 2020-08-27 15:34:10 -07:00
parent 5d1c01fcc9
commit 84c38215da
12 changed files with 1162 additions and 346 deletions

View File

@ -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 */

View File

@ -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 <clt>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 */

View File

@ -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 */

View File

@ -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;

View File

@ -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,

View File

@ -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 */

View File

@ -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",

View File

@ -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 <file.tap >stdout
input - stdin <file to remove sdt from
command: cutostap <file.tap >stdout
input - stdin <file to remove sdt from
output - stdout >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 <file.tap >stdout
input - stdin <file to dump
command: filelist <file.tap >stdout
input - stdin <file to dump
output - stdout
fmgrcopy - This program reads a MPX 1.x filemgr save tape. The tape
@ -58,8 +58,8 @@ fmgrcopy - This program reads a MPX 1.x filemgr save tape. The tape
as binary data to the named file. The .tap file MUST be
a filemgr save tape and not a MPX-1.x SDT 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
@ -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.txt >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 <q> will terminate the display, and hitting <s>
will skip to the next file on the simulated tape.
command tapdump <file.tap >stdout
input - stdin <file to dump
command: tapdump <file.tap >stdout
input - stdin <file to dump
output - stdout
tape2disk - This program reads a tape assigned as input device. It
@ -142,8 +169,8 @@ tape2disk - This program reads a tape assigned as input device. It
MPX 3.x volmgr save tapes contain three EOFs so comment out
the define for that case.
command - tape2disk mt00 [file.tap]
input - mag tape device being read
command: tape2disk mt00 [file.tap]
input - mag tape device being read
output - list of files and sizes read from input tape
output - metadata .tap file optionally specified
@ -151,8 +178,8 @@ tapscan - 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 - tapscan file.tap >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 <filein >fileout
command: mpxblk <filein >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 <filein >fileout
command: renum <filein >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 <filein >fileout
command: small <filein >fileout
input - read ascii file from stdin
output - write stripped ascii file to stdout
James C. Bevier
04/21/2020
08/21/2020

View File

@ -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 $@

276
SEL32/taptools/mkdiagtape.c Normal file
View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#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);
}

View File

@ -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);
}

View File

@ -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 */