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:
parent
5d1c01fcc9
commit
84c38215da
@ -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 */
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
223
SEL32/sel32_ec.c
223
SEL32/sel32_ec.c
@ -36,9 +36,10 @@
|
||||
#define CMD u3
|
||||
/* u3 */
|
||||
/* in u3 is device command code and status */
|
||||
#define EC_CMDMSK 0x0ff /* Command being run */
|
||||
#define EC_CMDMSK 0x0ff /* Command being run */
|
||||
/* commands */
|
||||
#define EC_INCH 0x00 /* Initialize channel */
|
||||
#define EC_INCH2 0xf0 /* Initialize channel command for processing */
|
||||
#define EC_WRITE 0x01 /* Write frame */
|
||||
#define EC_READ 0x02 /* Read frame*/
|
||||
#define EC_NOP 0x03 /* No operation */
|
||||
@ -212,10 +213,12 @@ extern int32 tmxr_poll;
|
||||
static CONST ETH_MAC broadcast_ethaddr = {0xff,0xff,0xff,0xff,0xff,0xff};
|
||||
|
||||
/* channel program information */
|
||||
CHANP ec_chp[8] = {0};
|
||||
//CHANP ec_chp[8] = {0};
|
||||
CHANP ec_chp[10] = {0};
|
||||
|
||||
uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ;
|
||||
t_stat ec_srv(UNIT *uptr);
|
||||
uint16 ec_haltio(UNIT *uptr);
|
||||
void ec_packet_debug(struct ec_device *ec, const char *action, ETH_PACK *packet);
|
||||
t_stat ec_reset (DEVICE *dptr);
|
||||
void ec_ini(UNIT *, t_bool);
|
||||
@ -232,6 +235,7 @@ const char *ec_description (DEVICE *dptr);
|
||||
|
||||
UNIT ec_unit[] = {
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_ATTABLE, 0), 0, UNIT_ADDR(0xE00)}, /* 0 */
|
||||
#ifdef FOR_DIAG
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_DIS|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE01)}, /* 1 */
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_DIS|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE02)}, /* 2 */
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_DIS|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE03)}, /* 3 */
|
||||
@ -239,20 +243,30 @@ UNIT ec_unit[] = {
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_DIS|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE05)}, /* 5 */
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_DIS|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE06)}, /* 6 */
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_DIS|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE07)}, /* 7 */
|
||||
#else
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE01)}, /* 1 */
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE02)}, /* 2 */
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE03)}, /* 3 */
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE04)}, /* 4 */
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE05)}, /* 5 */
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE06)}, /* 6 */
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE07)}, /* 7 */
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE08)}, /* 8 */
|
||||
{UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE09)}, /* 9 */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
DIB ec_dib = {
|
||||
NULL, /* Pre start I/O */
|
||||
ec_startcmd, /* Start a command */
|
||||
NULL, /* Stop I/O */
|
||||
ec_haltio, /* Halt I/O */
|
||||
NULL, /* Test I/O */
|
||||
NULL, /* Post I/O */
|
||||
ec_ini, /* init function */
|
||||
ec_unit, /* Pointer to units structure */
|
||||
ec_chp, /* Pointer to chan_prg structure */
|
||||
8, /* number of units defined */
|
||||
// 8, /* number of units defined */
|
||||
10, /* number of units defined */
|
||||
0x0F, /* device mask */
|
||||
0x0E00, /* parent channel address */
|
||||
0, /* fifo input index */
|
||||
@ -295,7 +309,8 @@ DEBTAB ec_debug[] = {
|
||||
|
||||
DEVICE ec_dev = {
|
||||
"EC", ec_unit, NULL, ec_mod,
|
||||
8, 16, 24, 4, 16, 32,
|
||||
// 8, 16, 24, 4, 16, 32,
|
||||
10, 16, 24, 4, 16, 32,
|
||||
NULL, NULL, &ec_reset, NULL, &ec_attach, &ec_detach,
|
||||
&ec_dib, DEV_DISABLE | DEV_DEBUG | DEV_ETHER, 0, ec_debug,
|
||||
NULL, NULL, &ec_help, NULL, NULL, &ec_description
|
||||
@ -307,7 +322,7 @@ uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
{
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
uint16 chsa = GET_UADDR(uptr->CMD);
|
||||
// CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */
|
||||
CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"ec_startcmd chsa %04x unit %d cmd %02x CMD %08x\n",
|
||||
@ -316,32 +331,69 @@ uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
sim_debug(DEBUG_CMD, dptr, "ec_startcmd busy\n");
|
||||
return SNS_BSY;
|
||||
}
|
||||
/* this switch is here to satisify the SEL diag who wants a program */
|
||||
/* check error instead of a unit check error for these cmd values??? */
|
||||
switch (cmd) {
|
||||
case 0x18: case 0x20: case 0x28: case 0x30: case 0x38: case 0x40: case 0x48:
|
||||
case 0x50: case 0x58: case 0x60: case 0x68: case 0x70: case 0x78: case 0x80:
|
||||
case 0x88: case 0x90: case 0x98: case 0xa0: case 0xa8: case 0xb0: case 0xb8:
|
||||
case 0xc0: case 0xc8: case 0xd0: case 0xd8: case 0xe0: case 0xe8: case 0xf0:
|
||||
case 0xf8:
|
||||
// uptr->SNS |= SNS_CMDREJ;
|
||||
uptr->SNS &= ~SNS_CMDREJ; /* remove CMD reject status */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"ec_startcmd illegal at ec_startcmd %02x SNS %08x\n",
|
||||
cmd, uptr->SNS);
|
||||
return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; /* diags want prog check */
|
||||
// return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* diags want unit check */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unit is online, so process a command */
|
||||
switch (cmd) {
|
||||
case EC_WRITE: /* Write command 0x01 */
|
||||
case EC_READ: /* Read command 0x02 */
|
||||
case EC_TIC: /* Transfer in channel */
|
||||
case EC_CGA: /* Disable multicast address */
|
||||
case EC_LCC: /* Configure LCC */
|
||||
case EC_STATS: /* Read Statistics */
|
||||
case EC_CSTATS: /* Clear software counters */
|
||||
case EC_NOP: /* NOP 0x03 */
|
||||
case EC_INCH: /* INCH cmd 0x0 */
|
||||
case EC_LIA: /* Load individual address */
|
||||
case EC_LGA: /* Load Multicast address */
|
||||
uptr->SNS &= 0xff0000;
|
||||
case EC_INCH: /* INCH cmd 0x0 */
|
||||
cmd = EC_INCH2; /* set dummy INCH cmd 0xf0 */
|
||||
case EC_WRITE: /* Write command 0x01 */
|
||||
case EC_READ: /* Read command 0x02 */
|
||||
case EC_TIC: /* Transfer in channel */
|
||||
case EC_CGA: /* Disable multicast address */
|
||||
case EC_LCC: /* Configure LCC */
|
||||
case EC_STATS: /* Read Statistics */
|
||||
case EC_CSTATS: /* Clear software counters */
|
||||
case EC_NOP: /* NOP 0x03 */
|
||||
case EC_LIA: /* Load individual address */
|
||||
case EC_LGA: /* Load Multicast address */
|
||||
uptr->SNS &= 0xffff0000;
|
||||
// uptr->SNS &= 0x7fff0000; /* remove invalid cmd status */
|
||||
uptr->SNS &= ~SNS_CMDREJ; /* remove CMD reject status */
|
||||
/* Fall through */
|
||||
case EC_SNS: /* Sense 0x04 */
|
||||
case EC_SNS: /* Sense 0x04 */
|
||||
#ifdef FIGURE_THIS_OUT
|
||||
/* diags want 4 byte multiple, but if data chaining is set it can be odd */
|
||||
/* ethernet transfers must be multiple of 4 bytes */
|
||||
if ((cmd == EC_WRITE) || (cmd == EC_READ) ||
|
||||
(cmd == EC_STATS) || (cmd == EC_LCC)) {
|
||||
// (cmd == EC_STATS) || (cmd == EC_LCC) || (cmd == EC_SNS)) {
|
||||
if ((chp->ccw_count & 0x03) != 0)
|
||||
return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; /* diags want prog check */
|
||||
}
|
||||
#endif
|
||||
/* nop must have none zero count */
|
||||
if (cmd == EC_NOP) {
|
||||
if (chp->ccw_count == 0)
|
||||
return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; /* diags want prog check */
|
||||
}
|
||||
uptr->CMD |= cmd|EC_BUSY; /* save cmd */
|
||||
sim_activate(uptr, 300); /* start things off */
|
||||
return 0;
|
||||
}
|
||||
|
||||
uptr->SNS |= SNS_CMDREJ;
|
||||
sim_debug(DEBUG_CMD, dptr, "ec_startcmd illegal with ec_startcmd %02x SNS %08x\n",
|
||||
sim_debug(DEBUG_CMD, dptr, "ec_startcmd illegal cmd %02x SNS %08x\n",
|
||||
cmd, uptr->SNS);
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* diags want unit check */
|
||||
// return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; /* diags want prog check */
|
||||
}
|
||||
|
||||
/* Handle processing of disk requests. */
|
||||
@ -353,9 +405,9 @@ t_stat ec_srv(UNIT *uptr)
|
||||
int cmd = uptr->CMD & EC_CMDMSK;
|
||||
uint32 mema;
|
||||
int i;
|
||||
int n;
|
||||
int n, len;
|
||||
uint8 ch;
|
||||
uint8 buf[256];
|
||||
uint8 buf[1520];
|
||||
uint8 *pck;
|
||||
struct ec_eth_hdr *hdr;
|
||||
|
||||
@ -363,13 +415,14 @@ t_stat ec_srv(UNIT *uptr)
|
||||
"ec_srv cmd=%02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count);
|
||||
|
||||
switch (cmd) {
|
||||
case EC_INCH: /* INCH cmd 0x0 */
|
||||
// case EC_INCH: /* INCH cmd 0x0 */
|
||||
case EC_INCH2: /* INCH cmd 0xF0 */
|
||||
len = chp->ccw_count; /* INCH command count */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"ec_srv starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n",
|
||||
uptr->u4, chsa, chp->ccw_addr, chp->ccw_count);
|
||||
mema = chp->ccw_addr; /* get inch or buffer addr */
|
||||
|
||||
uptr->CMD &= LMASK; /* remove old status bits & */
|
||||
uptr->CMD &= LMASK; /* remove old status bits & */
|
||||
|
||||
/* now call set_inch() function to write and test inch buffer addresses */
|
||||
i = set_inch(uptr, mema); /* new address */
|
||||
@ -379,11 +432,23 @@ t_stat ec_srv(UNIT *uptr)
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
#ifndef DIAG_WANTS_COUNT
|
||||
for (i=0; i < len; i++) {
|
||||
if (chan_read_byte(chsa, &buf[i])) {
|
||||
/* we have error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK;
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
/* just dump data */
|
||||
}
|
||||
#endif
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND);
|
||||
break;
|
||||
|
||||
case EC_LIA: /* Load individual address */
|
||||
uptr->CMD &= LMASK; /* remove old status bits & cmd */
|
||||
case EC_LIA: /* Load individual address */
|
||||
uptr->CMD &= LMASK; /* remove old status bits & cmd */
|
||||
for(i = 0; i < sizeof (ETH_MAC); i++) {
|
||||
if (chan_read_byte(chsa, &buf[i])) {
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
@ -427,7 +492,7 @@ t_stat ec_srv(UNIT *uptr)
|
||||
|
||||
for(i = 0; i< n; i++) {
|
||||
eth_mac_fmt(&ec_data.macs[i], (char *)&buf[0]);
|
||||
sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv load mcast%d: %s\n\r",i,buf);
|
||||
sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv load mcast%d: %s\n",i,buf);
|
||||
}
|
||||
|
||||
if (ec_master_uptr->flags & UNIT_ATT)
|
||||
@ -493,12 +558,12 @@ runt:
|
||||
case EC_READ: /* Read command 0x02 */
|
||||
ec_master_uptr->SNS |= SNS_RCV_RDY;
|
||||
if (eth_read(&ec_data.etherface, &ec_data.rec_buff, NULL) <= 0) {
|
||||
sim_clock_coschedule(uptr, 1000); /* continue poll */
|
||||
sim_clock_coschedule(uptr, 1000); /* continue poll */
|
||||
return SCPE_OK;
|
||||
}
|
||||
ec_packet_debug(&ec_data, "recv", &ec_data.rec_buff);
|
||||
ec_data.rx_count++;
|
||||
uptr->CMD &= LMASK; /* remove old status bits & cmd */
|
||||
uptr->CMD &= LMASK; /* remove old status bits & cmd */
|
||||
hdr = (struct ec_eth_hdr *)(&ec_data.rec_buff.msg[0]);
|
||||
pck = (uint8 *)(&ec_data.rec_buff.msg[0]);
|
||||
switch (GET_MODE(ec_master_uptr->flags)) {
|
||||
@ -538,12 +603,12 @@ runt:
|
||||
break;
|
||||
}
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv received bytes %d\n\r",i);
|
||||
sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv received bytes %d\n",i);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND);
|
||||
break;
|
||||
|
||||
case EC_LCC: /* Configure LCC */
|
||||
uptr->CMD &= LMASK; /* remove old status bits & cmd */
|
||||
uptr->CMD &= LMASK; /* remove old status bits & cmd */
|
||||
/* Read up to 12 bytes */
|
||||
for (i = 0; i < 12; i++) {
|
||||
if (chan_read_byte(chsa, &ch)) {
|
||||
@ -556,7 +621,7 @@ runt:
|
||||
case EC_STATS: /* Read Statistics */
|
||||
ch = 0;
|
||||
/* First 5 words are always zero since these errors are not supported */
|
||||
uptr->CMD &= LMASK; /* remove old status bits & cmd */
|
||||
uptr->CMD &= LMASK; /* remove old status bits & cmd */
|
||||
for (i = 0; i < STAT_LEN * 2; i++) {
|
||||
if (chan_write_byte(chsa, &ch)) {
|
||||
break;
|
||||
@ -583,53 +648,114 @@ runt:
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND);
|
||||
break;
|
||||
|
||||
case EC_CSTATS: /* Clear software counters */
|
||||
uptr->CMD &= LMASK; /* remove old status bits & cmd */
|
||||
case EC_CSTATS: /* Clear software counters */
|
||||
uptr->CMD &= LMASK; /* remove old status bits & cmd */
|
||||
ec_data.rx_count = ec_data.tx_count = 0;
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND);
|
||||
break;
|
||||
|
||||
case EC_NOP: /* NOP 0x03 */
|
||||
uptr->CMD &= LMASK; /* remove old status bits & cmd */
|
||||
case EC_NOP: /* NOP 0x03 */
|
||||
uptr->CMD &= LMASK; /* remove old status bits & cmd */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"ec_srv cmd NOP chsa %04x count %04x completed\n",
|
||||
chsa, chp->ccw_count);
|
||||
/* diags want the count to be returned zero */
|
||||
chp->ccw_count = 0; /* NOP command count */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */
|
||||
break;
|
||||
|
||||
case EC_SNS: /* 0x4 */
|
||||
sim_debug(DEBUG_CMD, dptr, "ec_startcmd CMD sense\n");
|
||||
case EC_SNS: /* 0x4 */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"ec_startcmd CMD sense cnt %02x\n", chp->ccw_count);
|
||||
uptr->CMD &= LMASK; /* remove old status bits & cmd */
|
||||
|
||||
/* diags want incorrect length or prog check */
|
||||
if (chp->ccw_count < 0x04) {
|
||||
chp->ccw_count = 0; /* zero command count */
|
||||
if ((chp->ccw_flags & FLAG_SLI) == 0) {
|
||||
/* diag wants incorrect length */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_LENGTH);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ch = (uptr->SNS >> 24) & 0xfc;
|
||||
ch |= GET_MODE(ec_master_uptr->flags);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense CHS b0 1 %02x\n", ch);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense b0 1 %02x\n", ch);
|
||||
chan_write_byte(chsa, &ch);
|
||||
ch = (ec_master_uptr->SNS >> 16) & 0xff;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense CHS b1 2 %02x\n", ch);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense b1 2 %02x\n", ch);
|
||||
chan_write_byte(chsa, &ch);
|
||||
ch = (ec_data.rec_buff.len >> 8) & 0xff;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense CHS b2 3 %02x\n", ch);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense b2 3 %02x\n", ch);
|
||||
chan_write_byte(chsa, &ch);
|
||||
ch = ec_data.rec_buff.len & 0xff;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense CHS b3 4 %02x\n", ch);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense b3 4 %02x\n", ch);
|
||||
chan_write_byte(chsa, &ch);
|
||||
|
||||
uptr->CMD &= LMASK; /* remove old status bits & cmd */
|
||||
if (chp->ccw_count > 0) {
|
||||
if (chp->ccw_flags & FLAG_SLI)
|
||||
/* diags want prog check */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK);
|
||||
else
|
||||
/* diag wants incorrect length */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_LENGTH);
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"ec_startcmd CMD sense excess cnt %02x\n", chp->ccw_count);
|
||||
break;
|
||||
}
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
#ifdef ALLOW_0_CMD
|
||||
sim_debug(DEBUG_CMD, dptr, "invalid command %02x\n", cmd);
|
||||
uptr->SNS |= SNS_CMDREJ;
|
||||
uptr->CMD &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
#else
|
||||
sim_debug(DEBUG_CMD, dptr, "allow unknown command %02x\n", cmd);
|
||||
#endif
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, dptr,
|
||||
"ec_srv done cmd=%02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Handle haltio transfers for ethernet */
|
||||
uint16 ec_haltio(UNIT *uptr) {
|
||||
uint16 chsa = GET_UADDR(uptr->CMD);
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
int cmd = uptr->CMD & EC_CMDMSK;
|
||||
CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */
|
||||
|
||||
sim_debug(DEBUG_EXP, dptr, "ec_haltio enter chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
|
||||
/* terminate any input command */
|
||||
/* UTX wants SLI bit, but no unit exception */
|
||||
/* status must not have an error bit set */
|
||||
/* otherwise, UTX will panic with "bad status" */
|
||||
if ((uptr->CMD & EC_CMDMSK) != 0) { /* is unit busy */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"ec_haltio HIO chsa %04x cmd = %02x ccw_count %02x\n", chsa, cmd, chp->ccw_count);
|
||||
// stop any I/O and post status and return error status */
|
||||
chp->chan_byte = BUFF_EMPTY; /* there is no data to read/store */
|
||||
// chp->ccw_count = 0; /* zero the count */
|
||||
chp->ccw_flags &= (FLAG_DC|FLAG_CC);/* stop any chaining */
|
||||
uptr->CMD &= LMASK; /* make non-busy */
|
||||
uptr->SNS = SNS_RCV_RDY; /* status is online & ready */
|
||||
sim_cancel(uptr); /* clear the input timer */
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"ec_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* force error */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* force end */
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
uptr->CMD &= LMASK; /* make non-busy */
|
||||
uptr->SNS = SNS_RCV_RDY; /* status is online & ready */
|
||||
return SCPE_OK; /* not busy */
|
||||
}
|
||||
|
||||
/* initialize the ethernet */
|
||||
void ec_ini(UNIT *uptr, t_bool f)
|
||||
{
|
||||
@ -908,6 +1034,7 @@ t_stat ec_attach(UNIT* uptr, CONST char* cptr)
|
||||
ec_dev.name, buf);
|
||||
}
|
||||
if (SCPE_OK != eth_filter(&ec_data.etherface, 2, ec_data.macs, 0, 0)) {
|
||||
// if (SCPE_OK != eth_filter(&ec_data.etherface, 2, ec_data.macs, 0, 1)) {
|
||||
eth_close(&ec_data.etherface);
|
||||
free(tptr);
|
||||
return sim_messagef (SCPE_NOATT,
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
276
SEL32/taptools/mkdiagtape.c
Normal 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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user