From fb4ba5f856adbbdd5ab2903f4cbbab76c21456d8 Mon Sep 17 00:00:00 2001 From: AZBevier Date: Thu, 10 Sep 2020 17:05:35 -0700 Subject: [PATCH] SEL32: Add support for ethernet and disk processor diagnostics. SEL32: Update error status information for ethernet and disks. SEL32: Update channel program processing. SEL32: Some minor code cleanup. --- SEL32/sel32_chan.c | 291 +++++++------- SEL32/sel32_clk.c | 10 +- SEL32/sel32_con.c | 12 +- SEL32/sel32_cpu.c | 91 +++-- SEL32/sel32_defs.h | 14 +- SEL32/sel32_disk.c | 978 +++++++++++++++++++++++++++++++-------------- SEL32/sel32_ec.c | 108 +++-- SEL32/sel32_hsdp.c | 750 +++++++++++++++++++++++----------- SEL32/sel32_mt.c | 3 +- 9 files changed, 1494 insertions(+), 763 deletions(-) diff --git a/SEL32/sel32_chan.c b/SEL32/sel32_chan.c index aa88652..4d9806b 100644 --- a/SEL32/sel32_chan.c +++ b/SEL32/sel32_chan.c @@ -89,19 +89,17 @@ int DoNextCycles = 0; #include #endif -extern uint32 CPUSTATUS; /* CPU status word */ -extern uint32 INTS[]; /* Interrupt status flags */ -extern uint32 TPSD[]; /*Temp save of PSD from memory 0&4 */ -#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 +extern uint32 CPUSTATUS; /* CPU status word */ +extern uint32 INTS[]; /* Interrupt status flags */ +extern uint32 TPSD[]; /*Temp save of PSD from memory 0&4 */ +extern uint8 waitqcnt; /* # of instructions to xeq b4 int */ +extern uint8 waitrdyq; /* # of instructions to xeq b4 rdy */ +extern uint32 inbusy; +extern uint32 outbusy; -DIB *dib_unit[MAX_DEV]; /* Pointer to Device info block */ -DIB *dib_chan[MAX_CHAN]; /* pointer to channel mux dib */ -uint16 loading; /* set when booting */ +DIB *dib_unit[MAX_DEV]; /* Pointer to Device info block */ +DIB *dib_chan[MAX_CHAN]; /* pointer to channel mux dib */ +uint16 loading; /* set when booting */ #define get_chan(chsa) ((chsa>>8)&0x7f) /* get channel number from ch/sa */ @@ -217,11 +215,9 @@ 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; +// waitrdyq = 5; //25waitrdyq = 2; - waitrdyq = 1; -#endif + waitrdyq = 1; /* wait at least 1 instruction */ return 0; /* all OK */ } @@ -497,7 +493,7 @@ int32 load_ccw(CHANP *chp, int32 tic_ok) uint16 devstat = 0; loop: - sim_debug(DEBUG_DETAIL, &cpu_dev, + sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw @%06x entry chan_status[%04x] %04x\n", chp->chan_caw, chan, chp->chan_status); /* Abort if we have any errors */ if (chp->chan_status & STATUS_ERROR) { /* check channel error status */ @@ -545,20 +541,19 @@ loop: #endif /* TIC can't follow TIC or be first in command chain */ -//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 */ + chp->ccw_count = word2 & 0xffff; /* get 16 bit byte count from IOCD WD 2*/ return 1; /* error return */ } - chp->chan_caw = word1 & MASK24; /* get new IOCD address */ tic_ok = 0; /* another tic not allowed */ + chp->chan_caw = word1 & MASK24; /* get new IOCD address */ sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw tic cmd ccw chan %02x tic caw %06x IOCD wd 1 %08x\n", chan, chp->chan_caw, word1); @@ -570,6 +565,19 @@ loop: return 1; /* error return */ } + /* validate parts of IOCD that is reserved */ + if (word2 & 0x07ff0000) { + chp->chan_status |= STATUS_PCHK; /* program check for invalid iocd */ + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw bad IOCD2 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } + if (!MEM_ADDR_OK(word1 & MASK24)) { /* see if memory address invalid */ + chp->chan_status |= STATUS_PCHK; /* bad, program check */ + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw bad IOCD1 chan_status[%04x] %04x\n", chan, chp->chan_status); + return 1; /* error return */ + } /* Check if not chaining data */ if ((chp->ccw_flags & FLAG_DC) == 0) { chp->ccw_cmd = (word1 >> 24) & 0xff; /* not DC, so set command from IOCD wd 1 */ @@ -584,11 +592,11 @@ loop: /* Set up for this command */ /* make a 24 bit address */ chp->ccw_addr = word1 & MASK24; /* set the data/seek address */ - chp->chan_caw += 8; /* point to to next IOCD */ + chp->chan_caw = (chp->chan_caw & 0xfffffc) + 8; /* point to next IOCD */ chp->ccw_count = word2 & 0xffff; /* get 16 bit byte count from IOCD WD 2*/ chp->chan_byte = BUFF_BUSY; /* busy & no bytes transferred yet */ //sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw BUFF_BUSY chp %p chan_byte %04x\n", chp, chp->chan_byte); - chp->ccw_flags = (word2 >> 16) & 0xffff; /* get flags from bits 0-7 of WD 2 of IOCD */ + chp->ccw_flags = (word2 >> 16) & 0xfc00; /* get flags from bits 0-7 of WD 2 of IOCD */ if (chp->ccw_flags & FLAG_PCI) { /* do we have prog controlled int? */ chp->chan_status |= STATUS_PCI; /* set PCI flag in status */ irq_pend = 1; /* interrupt pending */ @@ -615,28 +623,34 @@ loop: /* just replace device status bits */ devstat = dibp->start_cmd(uptr, chan, chp->ccw_cmd); chp->chan_status = (chp->chan_status & 0xff00) | devstat; + chp->chan_info &= ~INFO_SIOCD; /* show not first IOCD in channel prog */ sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw @%06x after start_cmd chan %04x status %08x count %04x\n", chp->chan_caw, chan, chp->chan_status, chp->ccw_count); /* see if bad status */ -// if (chp->chan_status & (STATUS_ATTN|STATUS_CHECK|STATUS_EXPT)) { if (chp->chan_status & (STATUS_ATTN|STATUS_ERROR)) { chp->chan_status |= STATUS_CEND; /* channel end status */ chp->ccw_flags = 0; /* no flags */ // chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ // chp->ccw_cmd = 0; /* stop IOCD processing */ //25 chp->ccw_count = 0; /* make count zero */ - 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); + /* see if chan_end already called */ + if (chp->chan_byte == BUFF_NEXT) { + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw BUFF_NEXT ERROR chp %p chan_byte %04x\n", + chp, chp->chan_byte); + } else { + chp->chan_byte = BUFF_NEXT; /* have main pick us up */ + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw bad status chan %04x status %04x cmd %02x\n", + chan, chp->chan_status, chp->ccw_cmd); + RDYQ_Put(chp->chan_dev); /* queue us up */ + sim_debug(DEBUG_EXP, &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! */ @@ -850,11 +864,11 @@ 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_end1 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_XIO, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end SLI test1 chsa %04x ccw_flags %04x count %04x status %04x\n", chsa, chp->ccw_flags, chp->ccw_count, chp->chan_status); @@ -894,7 +908,7 @@ sim_debug(DEBUG_EXP, &cpu_dev, "chan_end1 BUFF_BUSY chp %p chan_byte %04x\n", ch /* 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 */ @@ -904,7 +918,7 @@ sim_debug(DEBUG_EXP, &cpu_dev, "chan_end2 BUFF_BUSY chp %p chan_byte %04x\n", ch } } 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); @@ -936,8 +950,8 @@ sim_debug(DEBUG_EXP, &cpu_dev, "chan_end3 BUFF_BUSY chp %p chan_byte %04x\n", ch 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 */ @@ -952,29 +966,29 @@ sim_debug(DEBUG_EXP, &cpu_dev, "chan_end3 BUFF_BUSY chp %p chan_byte %04x\n", ch /* handle case where we are loading the O/S on boot */ /* if loading, store status to be discovered by scan_chan */ if (!loading) { - sim_debug(DEBUG_XIO, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end call store_csw dev/chan end chsa %04x cpustat %08x iocla %08x\n", chsa, CPUSTATUS, chp->chan_caw); } else { /* we are loading, so keep moving */ - sim_debug(DEBUG_XIO, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end we are loading O/S with DE & CE, keep status chsa %04x status %08x\n", chsa, chp->chan_status); } /* store the status in channel FIFO to continue from cpu level */ chp->chan_byte = BUFF_DONE; /* we are done */ -sim_debug(DEBUG_EXP, &cpu_dev, "chan_end1 BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); +//sim_debug(DEBUG_EXP, &cpu_dev, "chan_end1 BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); store_csw(chp); /* store the status */ /* change chan_byte to BUFF_POST */ chp->chan_byte = BUFF_POST; /* show done with data */ -sim_debug(DEBUG_EXP, &cpu_dev, "chan_end2 BUFF_POST chp %p chan_byte %04x\n", chp, chp->chan_byte); +//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); } } + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end done chsa %04x chp %p status %08x chan_byte %02x\n", + chsa, chp, chp->chan_status, chp->chan_byte); /* following statement required for boot to work */ irq_pend = 1; /* flag to test for int condition */ } @@ -1002,8 +1016,8 @@ int16 post_csw(CHANP *chp, uint32 rstat) } if (chp->chan_byte != BUFF_POST) { sim_debug(DEBUG_EXP, &cpu_dev, - "post_csw %04x CHP not BUFF_POST status, ERROR FIFO #%1x inch %06x chan_icb %06x\n", - chsa, FIFO_Num(chsa), incha, chan_icb); + "post_csw %04x CHP %p not BUFF_POST status, ERROR FIFO #%1x inch %06x chan_icb %06x\n", + chsa, chp, FIFO_Num(chsa), incha, chan_icb); } /* remove user specified bits */ sw2 &= ~rstat; /* remove bits */ @@ -1015,11 +1029,6 @@ int16 post_csw(CHANP *chp, uint32 rstat) //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 */ @@ -1031,8 +1040,8 @@ int16 post_csw(CHANP *chp, uint32 rstat) } // 717 added sim_debug(DEBUG_EXP, &cpu_dev, - "post_csw %04x READ FIFO #%1x inch %06x No Status chan_byte %02x\n", - chsa, FIFO_Num(chsa), incha, chp->chan_byte); + "post_csw %04x chp %p READ FIFO #%1x inch %06x No Status chan_byte %02x\n", + chsa, chp, FIFO_Num(chsa), incha, chp->chan_byte); return 0; /* no status to post */ } @@ -1100,7 +1109,7 @@ t_stat checkxio(uint16 chsa, uint32 *status) { uint32 inta; DEVICE *dptr; /* DEVICE pointer */ -// sim_debug(DEBUG_XIO, &cpu_dev, "checkxio entry chsa %04x\n", chsa); + sim_debug(DEBUG_XIO, &cpu_dev, "checkxio entry chsa %04x\n", chsa); dibp = dib_chan[chan]; /* get DIB pointer for channel */ if (dibp == 0) goto nothere; @@ -1152,15 +1161,19 @@ nothere: chsa, incha, RMW(incha), RMW(incha+4)); #endif +#ifdef NOT_FOR_CHANNEL /* check for a Command or data chain operation in progresss */ //715 if (chp->chan_byte & BUFF_BUSY) { if ((chp->chan_byte & BUFF_BUSY) && chp->chan_byte != BUFF_POST) { sim_debug(DEBUG_EXP, &cpu_dev, - "checkxio busy return CC3&CC4 chsa %04x chan %04x cmd %02x flags %04x byte %02x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags, chp->chan_byte); + "checkxio busy return CC3&CC4 chsa %04x chp %p cmd %02x flags %04x byte %02x\n", + chsa, chp, chp->ccw_cmd, chp->ccw_flags, chp->chan_byte); + //TODO return busy status for EC device + //use same code as PPCI, but be busy *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ return SCPE_OK; /* just busy CC3&CC4 */ } +#endif dptr = get_dev(uptr); /* pointer to DEVICE structure */ /* try this as MFP says it returns 0 on OK */ @@ -1199,21 +1212,26 @@ t_stat startxio(uint16 chsa, uint32 *status) { "startxio debug chsa %04x iocla %06x incha %06x IOCD1 %08x IOCD2 %08x\n", chsa, iocla, incha, RMW(iocla), RMW(iocla+4)); #endif - dibp = dib_unit[chsa]; /* get the DIB pointer */ - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + /* check if we have a valid unit */ + dibp = dib_chan[chan]; /* get DIB pointer for channel */ + if (dibp == 0) goto missing; - if (dibp == 0 || chp == 0) { /* if no dib or channel ptr, CC3 return */ + chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + if (chp == 0) goto missing; + + uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ + + if (uptr == 0) { /* if no dib or unit ptr, CC3 on return */ +missing: *status = CC3BIT; /* not found, so CC3 */ sim_debug(DEBUG_EXP, &cpu_dev, - "startxio chsa %04x device not present, CC3 returned\n", chsa); + "startxio chsa %04x is not found, CC3 returned\n", chsa); return SCPE_OK; /* not found, CC3 */ } - uptr = chp->unitptr; /* get the unit ptr */ - sim_debug(DEBUG_EXP, &cpu_dev, - "startxio chsa %04x flags UNIT_ATTABLE %1x UNIT_ATT %1x UNIT_DIS %1x\n", - chsa, (uptr->flags & UNIT_ATTABLE)?1:0, (uptr->flags & UNIT_ATT)?1:0, + "startxio chsa %04x chp %p flags UNIT_ATTABLE %1x UNIT_ATT %1x UNIT_DIS %1x\n", + chsa, chp, (uptr->flags & UNIT_ATTABLE)?1:0, (uptr->flags & UNIT_ATT)?1:0, (uptr->flags & UNIT_DIS)?1:0); if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0) && @@ -1236,14 +1254,28 @@ t_stat startxio(uint16 chsa, uint32 *status) { #ifndef NOTHERE /* check for a Command or data chain operation in progresss */ -//25if (chp->chan_byte & BUFF_BUSY) { if ((chp->chan_byte & BUFF_BUSY) && chp->chan_byte != BUFF_POST) { + uint16 tstat, tcnt; + 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); + "startxio busy return CC3&CC4 chsa %04x chp %p cmd %02x flags %04x byte %02x\n", + chsa, chp, chp->ccw_cmd, chp->ccw_flags, chp->chan_byte); +#ifdef OLDWAY *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ +#else + *status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */ + /* handle an Ethernet controller busy by sending interrupt/status */ + tstat = chp->chan_status; /* save status */ + tcnt = chp->ccw_count; /* save count */ + chp->chan_status = STATUS_BUSY|STATUS_CEND|STATUS_DEND; /* set busy 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, + "startxio done BUSY chp %p chsa %04x ccw_flags %04x stat %04x cnt %04x\n", + chp, chsa, chp->ccw_flags, tstat, tcnt); +#endif #ifdef DO_DYNAMIC_DEBUG /* start debugging */ if (chsa == 0x0c00) @@ -1260,23 +1292,12 @@ t_stat startxio(uint16 chsa, uint32 *status) { /* We have to validate all the addresses and parameters for the SIO */ /* before calling load_ccw which does it again for each IOCL step */ -// inta = find_int_lev(chsa); /* Interrupt Level for channel */ -// chan_icb = find_int_icb(chsa); /* Interrupt level context block address */ - iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ word1 = RMW(iocla & MASK24); /* get 1st IOCL word */ incha = word1 & MASK24; /* should be inch addr */ word2 = RMW((iocla + 4) & MASK24); /* get 2nd IOCL word */ cmd = (word1 >> 24) & 0xff; /* get channel cmd from IOCL */ chp = find_chanp_ptr(chsa&0x7f00); /* find the parent chanp pointer */ - if (cmd == 0) { /* INCH command? */ - if ((word2 & MASK16) == 36) /* see if disk with 224 wd buffer */ - incha = RMW(incha); /* 224 word buffer is inch addr */ - dibp = dib_chan[chan]; /* get the channel DIB pointer */ - chp = dibp->chan_prg; /* get first unit channel prog ptr */ - chp->chan_inch_addr = incha; /* set the inch addr for channel */ - } - incha = chp->chan_inch_addr; /* get inch address */ sim_debug(DEBUG_XIO, &cpu_dev, @@ -1284,12 +1305,6 @@ t_stat startxio(uint16 chsa, uint32 *status) { chsa, iocla, incha, RMW(iocla), RMW(iocla+4)); iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ -// incha = chp->chan_inch_addr; /* get inch address */ -#ifdef LEAVE_IT_ALONE - /* now store the inch status address into word 5 of the ICB for the channel */ - WMW(chan_icb+20, incha); /* post inch addr in ICB+5w */ -#endif - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ sim_debug(DEBUG_XIO, &cpu_dev, "startxio test chsa %04x iocla %06x IOCD1 %08x IOCD2 %08x\n", @@ -1327,6 +1342,7 @@ t_stat startxio(uint16 chsa, uint32 *status) { /* We are queueing the SIO */ /* Queue us to continue IOCL from cpu level & make busy */ chp->chan_byte = BUFF_NEXT; /* have main pick us up */ + chp->chan_info = INFO_SIOCD; /* show first IOCD in channel prog */ sim_debug(DEBUG_EXP, &cpu_dev, "startxio BUFF_NEXT chp %p chan_byte %04x\n", chp, chp->chan_byte); RDYQ_Put(chsa); /* queue us up */ @@ -1386,10 +1402,8 @@ 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_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); + "testxio busy return CC3&CC4 chsa %04x chp %p cmd %02x flags %04x byte %02x\n", + chsa, chp, chp->ccw_cmd, chp->ccw_flags, chp->chan_byte); *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ return SCPE_OK; /* just busy CC3&CC4 */ } @@ -1473,7 +1487,6 @@ 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 */ -//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 */ @@ -1599,7 +1612,7 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ /* 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", + "$$$ HIO END1 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); @@ -1630,37 +1643,39 @@ sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_POST chp %p chan_byte %04x\n", chp, /* chan_end is called in hio device service routine */ /* the device is no longer busy, post status */ /* 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 */ - 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); + if (tempa == 1) { /* see if console HIO */ + chp->ccw_count = 0; /* zero the count */ + /* post status for UTX */ + if (post_csw(chp, ((STATUS_PCI) << 16))) { + INTS[inta] &= ~INTS_REQ; /* clear any level request */ + *status = CC2BIT; /* status stored */ + sim_debug(DEBUG_CMD, &cpu_dev, + "$$$ HIO END2 chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + /* change status from BUFF_POST to BUFF_DONE */ +/*082420*/ if (chp->chan_byte == BUFF_POST) { +/*082420*/ chp->chan_byte = BUFF_DONE; /* show done & not busy */ +sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE1 chp %p chan_byte %04x\n", chp, chp->chan_byte); + } + return SCPE_OK; /* CC2 & all OK */ } - return SCPE_OK; /* CC2 & all OK */ + } else { + chp->ccw_count = 0; /* zero the count */ + /* The diags want the interrupt for the disk */ + *status = CC1BIT; /* request accepted, no status, so CC1 */ + sim_debug(DEBUG_CMD, &cpu_dev, + "$$$ HIO END2 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; /* CC1 & all OK */ } -#else - *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); + "haltxio BUFF_DONE2 chp %p chan_byte %04x\n", chp, chp->chan_byte); /* the channel is not busy, so return OK */ *status = CC1BIT; /* request accepted, no status, so CC1 */ sim_debug(DEBUG_CMD, &cpu_dev, - "$$$ HIO END chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", + "$$$ HIO END3 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 */ } @@ -1673,12 +1688,10 @@ sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE chp %p chan_byte %04x\n", chp, /* 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, "haltxiocan BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); -//082020chp->chan_status |= STATUS_ECHO; /* show we stopped the cmd */ +sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE3 chp %p chan_byte %04x\n", chp, chp->chan_byte); // chp->ccw_count = 0; /* zero the count */ sim_cancel(uptr); /* cancel timer service */ chp->chan_status &= ~STATUS_BUSY; /* remove BUSY status bit */ -// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* show I/O complete */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ /* post the channel status */ @@ -1688,23 +1701,22 @@ sim_debug(DEBUG_EXP, &cpu_dev, "haltxiocan BUFF_DONE chp %p chan_byte %04x\n", c INTS[inta] &= ~INTS_REQ; /* clear any level request */ *status = CC2BIT; /* status stored from SIO, so CC2 */ sim_debug(DEBUG_CMD, &cpu_dev, - "$$$ HIO END chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", + "$$$ HIO END4 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); +sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE4 chp %p chan_byte %04x\n", chp, chp->chan_byte); } return SCPE_OK; /* CC2 & all OK */ } } -//hiogret: chp->chan_byte = BUFF_DONE; /* chan prog done */ -sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); +sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE5 chp %p chan_byte %04x\n", chp, chp->chan_byte); /* the channel is not busy, so return OK */ *status = CC1BIT; /* request accepted, no status, so CC1 */ sim_debug(DEBUG_CMD, &cpu_dev, - "$$$ HIO END chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", + "$$$ HIO END5 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 */ } @@ -1729,7 +1741,7 @@ t_stat grabxio(uint16 lchsa, uint32 *status) { /* grab controller XIO n/u *status = CC4BIT; /* busy, so CC4 */ return SCPE_OK; /* CC4 all OK */ } - *status = 0; /* not busy, no CC */ + *status = CC2BIT|CC4BIT; /* unsupported transaction */ sim_debug(DEBUG_CMD, &cpu_dev, "grabxio chsa %04x chan %04x\n", chsa, chan); return 0; } @@ -1765,9 +1777,6 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */ /* reset the FIFO pointers */ dibp->chan_fifo_in = 0; dibp->chan_fifo_out = 0; -#ifdef NOT4CONTROLLER - chp->chan_inch_addr = 0; /* remove inch status buffer address */ -#endif lev = find_int_lev(chan); /* get our int level */ INTS[lev] &= ~INTS_ACT; /* clear level active */ SPAD[lev+0x80] &= ~SINT_ACT; /* clear spad too */ @@ -1839,6 +1848,7 @@ sim_debug(DEBUG_EXP, &cpu_dev, "chan_boot BUFF_EMPTY chp %p chan_byte %04x\n", c chp->chan_caw = 0x0; /* set IOCD address to memory location 0 */ chp->ccw_count = 0; /* channel byte count 0 bytes*/ chp->ccw_flags = 0; /* Command chain and supress incorrect length */ + chp->chan_info = INFO_SIOCD; /* show first IOCD in channel prog */ chp->ccw_cmd = 0; /* read command */ loading = chsa; /* show we are loading from the boot device */ @@ -1876,17 +1886,15 @@ uint32 cont_chan(uint16 chsa) "cont_chan chan_byte %02x is NOT BUFF_NEXT chsa %04x addr %06x\n", chp->chan_byte, chsa, chp->ccw_addr); return 1; -//chp->chan_byte = BUFF_NEXT; -//716 return 1; } if (chp->chan_byte == BUFF_NEXT) { uint32 chan = get_chan(chsa); sim_debug(DEBUG_EXP, &cpu_dev, "cont_chan resume chan prog chsa %04x iocl %06x\n", chsa, chp->chan_caw); + /* start a channel program */ stat = load_ccw(chp, 1); /* resume the channel program */ -// 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 */ @@ -1920,6 +1928,9 @@ uint32 cont_chan(uint16 chsa) return SCPE_OK; /* done, status stored */ } /* must be more IOCBs, wait for them */ + sim_debug(DEBUG_EXP, &cpu_dev, + "cont_chan continue not next chsa %04x status %08x iocla %06x\n", + chsa, chp->chan_status, chp->chan_caw); return SCPE_OK; } @@ -1954,9 +1965,6 @@ uint32 scan_chan(uint32 *ilev) { if ((FIFO_Num(chan)) && ((FIFO_Get(chan, &sw1) == 0) && (FIFO_Get(chan, &sw2) == 0))) { /* the SPAD entries are not set up, so no access to icb or ints */ -#if NOT_SETUP_YET - uint32 chan_icb = find_int_icb(chan); /* get icb address */ -#endif /* get the status from the FIFO and throw it away */ /* we really should post it to the current inch address */ /* there is really no need to post, but it might be helpfull */ @@ -2009,8 +2017,10 @@ sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan BUFF_DONE chp %p chan_byte %04x\n", ch /* this is a bug fix for MPX 1.x restart command */ // if (SPAD[i+0x80] == 0xefffffff) /* not initialize? */ // continue; /* skip this one */ +#ifdef CAN_BE_DISABLED_090720 if ((INTS[i] & INTS_ENAB) == 0) /* ints must be enabled */ continue; /* skip this one */ +#endif if (INTS[i] & INTS_REQ) /* if already requesting, skip */ continue; /* skip this one */ @@ -2108,13 +2118,15 @@ sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan BUFF_DONE chp %p chan_byte %04x\n", ch chsa = chan | (tempa >> 24); /* find device address for requesting chan prog */ chp = find_chanp_ptr(chsa); /* find the chanp pointer for channel */ sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan %04x LOOK FIFO #%1x irq %02x inch %06x chsa %04x chan_icba %06x chan_byte %02x\n", - chan, FIFO_Num(chan), i, chp->chan_inch_addr, chsa, chan_icba, chp->chan_byte); + "scan_chan %04x LOOK FIFO #%1x irq %02x inch %06x chp %p icba %06x chan_byte %02x\n", + chsa, FIFO_Num(chan), i, chp->chan_inch_addr, chp, chan_icba, chp->chan_byte); if (post_csw(chp, 0)) { 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 */ + /* change status from BUFF_POST to BUFF_DONE */ + /* if not BUFF_POST we have a PPCI or channel busy interrupt */ + /* so leave the channel status alone */ /*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); @@ -2136,9 +2148,10 @@ tryme: //25irq_pend = 0; /* not pending anymore */ #ifndef TEST_082520 if (RDYQ_Num()) { -#ifdef NOTNOW +#ifndef NOTNOW if (waitrdyq > 0) { waitrdyq--; + irq_pend = 1; /* still pending */ } else #endif /* we have entries, continue channel program */ @@ -2148,7 +2161,7 @@ tryme: 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) + if (stat == SCPE_OK) /* done, status stored */ sim_debug(DEBUG_XIO, &cpu_dev, "CPU RDYQ entry for chsa %04x processed\n", chsa); } diff --git a/SEL32/sel32_clk.c b/SEL32/sel32_clk.c index 5d16e5d..f401942 100644 --- a/SEL32/sel32_clk.c +++ b/SEL32/sel32_clk.c @@ -119,8 +119,9 @@ t_stat rtc_srv (UNIT *uptr) #endif /* if clock disabled, do not do interrupts */ if (((rtc_dev.flags & DEV_DIS) == 0) && rtc_pie) { - time_t result = time(NULL); - sim_debug(DEBUG_CMD, &rtc_dev, "RT Clock int time %08x\n", (uint32)result); + sim_debug(DEBUG_CMD, &rtc_dev, + "RT Clock int INTS[%02x] %08x SPAD[%02x] %08x\n", + rtc_lvl, INTS[rtc_lvl], rtc_lvl+0x80, SPAD[rtc_lvl+0x80]); if (((INTS[rtc_lvl] & INTS_ENAB) || /* make sure enabled */ (SPAD[rtc_lvl+0x80] & SINT_ENAB)) && /* in spad too */ (((INTS[rtc_lvl] & INTS_ACT) == 0) || /* and not active */ @@ -132,10 +133,13 @@ t_stat rtc_srv (UNIT *uptr) INTS[rtc_lvl] |= INTS_REQ; /* request the interrupt */ irq_pend = 1; /* make sure we scan for int */ } + sim_debug(DEBUG_CMD, &rtc_dev, + "RT Clock int INTS[%02x] %08x SPAD[%02x] %08x\n", + rtc_lvl, INTS[rtc_lvl], rtc_lvl+0x80, SPAD[rtc_lvl+0x80]); } // temp = sim_rtcn_calb(rtc_tps, TMR_RTC); /* timer 0 for RTC */ sim_rtcn_calb(rtc_tps, TMR_RTC); /* timer 0 for RTC */ - sim_activate_after(&rtc_unit, 1000000/rtc_tps); /* reactivate 16666 tics / sec */ + sim_activate_after(uptr, 1000000/rtc_tps); /* reactivate 16666 tics / sec */ return SCPE_OK; } diff --git a/SEL32/sel32_con.c b/SEL32/sel32_con.c index 81959aa..af80c35 100644 --- a/SEL32/sel32_con.c +++ b/SEL32/sel32_con.c @@ -340,7 +340,7 @@ t_stat con_srvo(UNIT *uptr) { return SCPE_OK; } //Comment out clock flag 072020 -//*RTC*/ outbusy = 1; /* tell clock output waiting */ +/*RTC*/ outbusy = 1; /* tell clock output waiting */ /* Write to device */ while (chan_read_byte(chsa, &ch) == SCPE_OK) { /* get byte from memory */ /* HACK HACK HACK */ @@ -597,9 +597,9 @@ uint16 con_haltio(UNIT *uptr) { 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_count = 0; /* zero the count */ + /* stop any I/O and post status and return error status */ +// chp->chan_byte = BUFF_EMPTY; /* there is no data to read/store */ +/*0906*/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 */ @@ -607,9 +607,9 @@ uint16 con_haltio(UNIT *uptr) { 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); /* force end */ - return SCPE_IOERR; +// return SCPE_IOERR; + return 1; /* tell chan code to post status */ } uptr->u4 = 0; /* no I/O yet */ con_data[unit].incnt = 0; /* no input data */ diff --git a/SEL32/sel32_cpu.c b/SEL32/sel32_cpu.c index fa2f479..88dd528 100644 --- a/SEL32/sel32_cpu.c +++ b/SEL32/sel32_cpu.c @@ -221,12 +221,8 @@ 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 +uint8 waitrdyq = 0; /* # instructions before post inturrupt */ struct InstHistory { @@ -985,13 +981,6 @@ nomaps: } else { TLB[num] = 0; /* clear the TLB for non valid maps */ } -#ifdef FOR_DEBUG - if ((num < 0x20) || (num > (spc - 0x10))) - sim_debug(DEBUG_DETAIL, &cpu_dev, - "OS pad %06x=%04x map #%4x, %04x, map2 %08x, TLB %08x MAPC %08x\n", - pad, map, num, map, (((map << 16) & 0xf8000000) | ((map & 0x7ff) << 13)), - TLB[num], MAPC[num/2]); -#endif } BPIX = num; /* save the # maps loaded in O/S */ CPIXPL = 0; /* no user pages */ @@ -1138,15 +1127,6 @@ loaduser: } else TLB[num] = 0; /* clear the TLB for non valid maps */ WMR((num<<1), map); /* store map unmodified into cache */ - -#ifdef FOR_DEBUG - /* do partial map dump */ - if ((num < 0x20) || (num > (spc+BPIX) - 0x10)) - sim_debug(DEBUG_DETAIL, &cpu_dev, - "UserN pad %06x=%04x map #%4x, %04x, map2 %08x, TLB %08x, MAPC %08x\n", - pad, map, num, map, (((map << 16) & 0xf8000000) | ((map & 0x7ff) << 13)), - TLB[num], MAPC[num/2]); -#endif } if (num == 0) { /* see if any maps loaded */ sim_debug(DEBUG_TRAP, &cpu_dev, @@ -2023,9 +2003,12 @@ wait_loop: if (stat) sim_debug(DEBUG_XIO, &cpu_dev, "CPU RDYQ entry for chsa %04x processed\n", chsa); + if (stat == SCPE_OK) /* done, status stored */ + sim_debug(DEBUG_XIO, &cpu_dev, + "CPU RDYQ entry for chsa %04x processed\n", chsa); + } } - } - goto wait_loop; /* continue waiting for boot */ + goto wait_loop; /* continue waiting for boot */ } /* we get here when not booting */ @@ -2123,9 +2106,10 @@ wait_loop: /*25*/ irq_pend = 0; /* not pending anymore */ if (RDYQ_Num()) { uint32 chsa; /* channel/sub adddress */ -#ifdef NOTNOW +#ifndef NOTNOW if (waitrdyq > 0) { waitrdyq--; + irq_pend = 1; /* still pending */ } else #endif /* we have entries, continue channel program */ @@ -2144,8 +2128,8 @@ wait_loop: /* 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 */ +//0905 sim_idle(TMR_RTC, 1); /* wait for clock tick */ + sim_idle(TMR_RTC, 0); /* wait for clock tick */ /*722*/ irq_pend = 1; /* start scanning interrupts again */ goto wait_loop; /* continue waiting */ } @@ -2666,8 +2650,8 @@ exec: } wait4int = 1; /* show we are waiting for interrupt */ /* tell simh we will be waiting */ -// sim_idle(TMR_RTC, 0); /* wait for next pending device event */ - sim_idle(0, 0); /* wait for clock tick */ +//0905 sim_idle(TMR_RTC, 1); /* wait for clock tick */ + sim_idle(TMR_RTC, 0); /* wait for next pending device event */ /*719*/ irq_pend = 1; /* start scanning interrupts again */ i_flags |= BT; /* keep PC from being incremented while waiting */ break; @@ -6008,6 +5992,7 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); case 0x3: /* LPSD F980 */ /* fall through */; case 0x5: /* LPSDCM FA80 */ +/*0904*/ irq_pend = 1; /* start scanning interrupts again */ if ((modes & PRIVBIT) == 0) { /* must be privileged */ TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) @@ -6139,8 +6124,14 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); uint32 cpix = PSD2 & 0x3ff8; /* get cpix 11 bit offset from psd wd 2 */ uint32 midl = RMW(mpl+cpix); /* get midl entry for given user cpix */ int spc = midl & MASK16; /* get 16 bit user segment description count */ - if (spc != CPIXPL) + if (spc != CPIXPL) { PSD2 &= ~RETMBIT; /* no, turn off retain bit in PSD2 */ +#ifndef NOTNOW +sim_debug(DEBUG_IRQ, &cpu_dev, +"LPSD(CM) RESET RETAIN OPSD %08x %08x NPSD %08x %08x TRAPME %02x\n", +TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); +#endif + } } if ((PSD2 & RETMBIT) == 0) { /* don't load maps if retain bit set */ @@ -6175,6 +6166,11 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); PSD2 |= (SPAD[0xf5] & 0x3fff); /* use new cpix */ } } +#ifdef NOTNOW +sim_debug(DEBUG_IRQ, &cpu_dev, +"At LPSD(CM) OPSD %08x %08x NPSD %08x %08x TRAPME %02x\n", +TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); +#endif /* TRAPME can be error from LPSDCM or OK here */ if (TRAPME) { /* if we have an error, restore old PSD */ sim_debug(DEBUG_TRAP, &cpu_dev, @@ -6198,10 +6194,10 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); goto newpsd; /* go process error */ } drop_nop = 0; /* nothing to drop */ -#ifdef NOTNOW +#ifndef NOTNOW sim_debug(DEBUG_IRQ, &cpu_dev, - "LPSD(CM) Done PSD1 %08x PSD2 %08x CPUSTATUS %08x irq %1x BLK %1x\n", - PSD1, PSD2, CPUSTATUS, irq_pend, CPUSTATUS&0x80?1:0); + "LPSD(CM) END OPSD %08x %08x NPSD %08x %08x CPUSTAT %08x irq %1x BLK %1x\n", + TPSD[0], TPSD[1], PSD1, PSD2, CPUSTATUS, irq_pend, CPUSTATUS&0x80?1:0); #endif goto newpsd; /* load the new psd, or process error */ break; @@ -6233,6 +6229,7 @@ temp2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); /* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ /* */ case 0xFC>>2: /* 0xFC IMM - IMM */ /* XIO, CD, TD, Interrupt Control */ +/*0904*/ irq_pend = 1; /* start scanning interrupts again */ if ((modes & PRIVBIT) == 0) { /* must be privileged to do I/O */ TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) @@ -6512,7 +6509,7 @@ mcheck: } sim_debug(DEBUG_XIO, &cpu_dev, - "XIO rdy PSD1 %08x chan %02x irq %02x icb %06x iocla %06x iocd1 %08x iocd2 %08x\n", + "XIO rdy PSD1 %08x chan %02x irq %02x icb %06x iocla %06x iocd %08x %08x\n", PSD1, chan, ix, addr, addr+16, RMW(temp), RMW(temp+4)); /* at this point, the channel has a valid SPAD channel entry */ /* t is SPAD entry contents for chan device */ @@ -6524,6 +6521,26 @@ mcheck: /* ix - positive interrupt level */ /* addr - ICBA for specified interrupt level, points to 6 wd block */ /* temp - First IOCD address */ +#ifdef DO_DYNAMIC_DEBUG + /* start debugging */ + if (rchsa == 0x0801) { +// GPR[5] &= ~1; +// GPR[5] |= 2; +// rchsa &= ~1; +// rchsa |= 2; + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_TRAP | DEBUG_EXP | DEBUG_IRQ); + sim_debug(DEBUG_XIO, &cpu_dev, + "\n\tR0=%.8x R1=%.8x R2=%.8x R3=%.8x", GPR[0], GPR[1], GPR[2], GPR[3]); + sim_debug(DEBUG_XIO, &cpu_dev, + " R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]); + if (modes & BASEBIT) { + sim_debug(DEBUG_XIO, &cpu_dev, + "\tB0=%.8x B1=%.8x B2=%.8x B3=%.8x", BR[0], BR[1], BR[2], BR[3]); + sim_debug(DEBUG_XIO, &cpu_dev, + " B4=%.8x B5=%.8x B6=%.8x B7=%.8x\n", BR[4], BR[5], BR[6], BR[7]); + } + } +#endif sim_debug(DEBUG_XIO, &cpu_dev, "XIO switch %02x lchan %02x irq %02x chsa %04x IOCDa %08x CPUSTATUS %08x BLK %1x\n", ((opr>>3)&0x0f), lchan, ix, rchsa, temp, CPUSTATUS, CPUSTATUS&0x80?1:0); @@ -6547,20 +6564,22 @@ mcheck: "XIO unsupported WCS chan %04x chsa %04x status %08x\n", chan, rchsa, rstatus); /* just give unsupported transaction */ +#ifdef JUST_RETURN_STATUS TRAPME = SYSTEMCHK_TRAP; /* trap condition if F class */ TRAPSTATUS |= BIT0; /* class F error bit */ TRAPSTATUS &= ~BIT1; /* I/O processing error */ goto newpsd; /* undefined instruction trap */ +#endif break; case 0x02: /* Start I/O SIO */ - sim_debug(DEBUG_XIO, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "XIO SIO b4 call PSD1 %08x chan %04x chsa %04x BLK %1x\n", PSD1, chan, rchsa, CPUSTATUS&0x80?1:0); if ((TRAPME = startxio(rchsa, &rstatus))) goto newpsd; /* error returned, trap cpu */ PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - sim_debug(DEBUG_XIO, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "XIO SIO ret PSD1 %08x chan %04x chsa %04x status %08x BLK %1x\n", PSD1, chan, rchsa, rstatus, CPUSTATUS&0x80?1:0); break; @@ -7376,7 +7395,7 @@ t_stat cpu_show_hist(FILE *st, UNIT *uptr, int32 val, CONST void *desc) struct InstHistory *h; if (hst_lnt == 0) /* see if show history is enabled */ - return SCPE_NOFNC; /* no, so are out of here */ + return SCPE_NOFNC; /* no, so we are out of here */ if (cptr) { /* see if user provided a display count */ lnt = (int32)get_uint(cptr, 10, hst_lnt, &r); /* get the count */ if ((r != SCPE_OK) || (lnt == 0)) /* if error or 0 count */ diff --git a/SEL32/sel32_defs.h b/SEL32/sel32_defs.h index 7d6676a..6cecb6b 100644 --- a/SEL32/sel32_defs.h +++ b/SEL32/sel32_defs.h @@ -86,6 +86,7 @@ /* Class F channel bits */ /* bit 32 - 37 of IOCD word 2 (0-5) */ +/* ccw_flags bit assignment */ #define FLAG_DC 0x8000 /* Data chain */ #define FLAG_CC 0x4000 /* Chain command */ #define FLAG_SLI 0x2000 /* Suppress length indicator */ @@ -93,6 +94,7 @@ #define FLAG_PCI 0x0800 /* Program controlled interrupt */ #define FLAG_RTO 0x0400 /* Real-Time Option */ +/* chan_byte bit assignments */ #define BUFF_EMPTY 0x0 /* Buffer is empty */ #define BUFF_BUSY 0x4 /* Channel program busy & empty */ #define BUFF_NEXT 0xC /* 0x08|0x04 Continue Channel with next IOCB */ @@ -100,6 +102,10 @@ #define BUFF_DONE 0x20 /* 0x20 Channel ready for new command */ #define BUFF_POST 0x24 /* 0x20|0x04 Waiting for status to be posted */ +/* chan_info bit flags */ +#define INFO_SIOCD 0x01 /* Initial IOCD from SIO if set */ +/* bits 0-6 unused */ + #define MAX_CHAN 128 /* max channels that can be defined */ #define SUB_CHANS 256 /* max sub channels that can be defined */ #define MAX_DEV (MAX_CHAN * SUB_CHANS) /* max possible */ @@ -118,8 +124,8 @@ #define NUM_DEVS_HSDP 1 /* 1 hspd disk drive controller */ #define NUM_UNITS_HSDP 2 /* 2 disk drive devices */ #define NUM_DEVS_DISK 1 /* 1 dp02 disk drive controller */ -#define NUM_UNITS_DISK 2 /* 2 disk drive devices */ -//#define NUM_UNITS_DISK 4 /* 4 disk drive devices */ +//#define NUM_UNITS_DISK 2 /* 2 disk drive devices */ +#define NUM_UNITS_DISK 4 /* 4 disk drive devices */ #define NUM_DEVS_SCFI 1 /* 1 scfi (SCSI) disk drive units */ #define NUM_UNITS_SCFI 1 /* 1 of 4 disk drive devices */ #define NUM_DEVS_SCSI 2 /* 2 scsi (MFP SCSI) scsi buss units */ @@ -196,9 +202,7 @@ extern DEVICE ec_dev; /* channel program data for a chan/sub-address */ typedef struct chp { /* channel program values */ -#ifndef OLD_CHAN UNIT *unitptr; /* Back pointer to units structure */ -#endif uint32 chan_inch_addr; /* Channel status dw in memory */ uint32 chan_caw; /* Channel command address word */ uint32 ccw_addr; /* Channel address */ @@ -210,6 +214,7 @@ typedef struct chp { uint8 ccw_cmd; /* Channel command and flags */ uint8 chan_byte; /* Current byte, empty/full */ uint8 chan_int; /* channel interrupt level */ + uint8 chan_info; /* misc flags for channel */ } CHANP; /* Device information block */ @@ -320,6 +325,7 @@ extern DEBTAB dev_debug[]; #define MODEL_V9 7 /* V9 CPU */ #define TMR_RTC 1 +//#define TMR_RTC 0 #define HIST_MIN 64 #define HIST_MAX 10000 diff --git a/SEL32/sel32_disk.c b/SEL32/sel32_disk.c index 341024f..69f844a 100644 --- a/SEL32/sel32_disk.c +++ b/SEL32/sel32_disk.c @@ -23,6 +23,11 @@ #include "sel32_defs.h" +/* uncomment to use fast sim_activate times when running UTX */ +/* UTX gets an ioi error for dm0801 if slow times are used */ +/* dm0801 is not even a valid unit number for UDP controller */ +#define FAST_FOR_UTX + #if NUM_DEVS_DISK > 0 #define UNIT_DISK UNIT_ATTABLE | UNIT_IDLE | UNIT_DISABLE @@ -77,8 +82,10 @@ bits 0-7 - Flags bit 3 - 0=Reserved bit 4 - 1=Drive not present bit 5 - 1=Dual Port - bit 6 - 0=Blk size 00=768 byte blk - bit 7 - 0=Blk size 01=1024 byte blk + bit 6&7 - 0=Blk size 00=768 byte blk + 01=1024 byte blk + 10=2048 byte blk + 11=Unassigned bits 8-15 - sector count (sectors per track)(F16=16, F20=20) bits 16-23 - MHD Head count (number of heads on MHD) bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option of @@ -129,7 +136,7 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option char ldatrfhdc; FHD head count */ -#define CMDu3 u3 +#define CMD u3 /* u3 */ /* in u3 is device command code and status */ #define DSK_CMDMSK 0x00ff /* Command being run */ @@ -143,6 +150,7 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option #define DSK_BUSY 0x8000 /* Disk is busy */ /* commands */ #define DSK_INCH 0x00 /* Initialize channel */ +#define DSK_ICH 0xFF /* Initialize controller */ #define DSK_INCH2 0xF0 /* Initialize channel for processing */ #define DSK_WD 0x01 /* Write data */ #define DSK_RD 0x02 /* Read data */ @@ -217,6 +225,30 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option #define SNS_RTAE 0x02 /* Reserve track access error */ #define SNS_UESS 0x01 /* Uncorrectable ECC error */ +#define SNS2 us9 +/* us9 */ +/* us9 holds bytes 4 & 5 of the status for the drive */ + +/* Sense byte 4 */ +#define SNS_SEND 0x8000 /* Seek End */ +#define SNS_USEL 0x4000 /* Unit Selected */ +#define SNS_SPC0 0x2000 /* Sector Pulse Count B0 */ +#define SNS_SPC1 0x1000 /* Sector Pulse Count B1 */ +#define SNS_SPC2 0x0800 /* Sector Pulse Count B2 */ +#define SNS_SPC3 0x0400 /* Sector Pulse Count B3 */ +#define SNS_SPC4 0x0200 /* Sector Pulse Count B4 */ +#define SNS_SPC5 0x0100 /* Sector Pulse Count B5 */ + +/* Sense byte 5 */ +#define SNS_FLT 0x80 /* Disk Drive fault */ +#define SNS_SKER 0x40 /* Seek error */ +#define SNS_ONC 0x20 /* On Cylinder */ +#define SNS_UNR 0x10 /* Unit Ready */ +#define SNS_WRP 0x08 /* Write Protected */ +#define SNS_BUSY 0x04 /* Drive is busy */ +#define SNS_NU1 0x02 /* Spare 1 */ +#define SNS_NU2 0x01 /* Spare 2 */ + #define CHS u6 /* u6 */ /* u6 holds the current cyl, hd, sec for the drive */ @@ -239,7 +271,7 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option mini-module) */ -/* INCH addr up7 */ +/* Not Used up7 */ /* disk definition structure */ struct disk_t @@ -260,11 +292,11 @@ disk_type[] = { /* Class F Disc Devices */ /* For MPX */ - {"MH040", 5, 192, 20, 400, 411, 0x40}, /* 0 411 40M XXXX */ - {"MH080", 5, 192, 20, 800, 823, 0x40}, /* 1 823 80M 8138 */ - {"MH160", 10, 192, 20, 800, 823, 0x40}, /* 2 823 160M 8148 */ - {"MH300", 19, 192, 20, 800, 823, 0x40}, /* 3 823 300M 8127 */ - {"MH600", 40, 192, 20, 800, 843, 0x40}, /* 4 843 600M 8155 */ + {"MH040", 5, 192, 20, 407, 411, 0x40}, /* 0 411 40M XXXX */ + {"MH080", 5, 192, 20, 819, 823, 0x40}, /* 1 823 80M 8138 */ + {"MH160", 10, 192, 20, 819, 823, 0x40}, /* 2 823 160M 8148 */ + {"MH300", 19, 192, 20, 819, 823, 0x40}, /* 3 823 300M 8127 */ + {"MH600", 40, 192, 20, 839, 843, 0x40}, /* 4 843 600M 8155 */ /* For UTX */ {"9342", 5, 256, 16, 819, 823, 0x41}, /* 5 823 80M XXXX */ {"8148", 10, 256, 16, 819, 823, 0x41}, /* 6 823 160M 8148 */ @@ -288,6 +320,8 @@ t_stat disk_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat disk_get_type(FILE *st, UNIT *uptr, int32 v, CONST void *desc); t_stat disk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); const char *disk_description (DEVICE *dptr); +extern uint32 inbusy; +extern uint32 outbusy; /* channel program information */ CHANP dda_chp[NUM_UNITS_DISK] = {0}; @@ -307,22 +341,22 @@ UNIT dda_unit[] = { {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x804)}, /* 2 */ {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x806)}, /* 3 */ {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x808)}, /* 4 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x80a)}, /* 5 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x80c)}, /* 6 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x80e)}, /* 7 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x80A)}, /* 5 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x80C)}, /* 6 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x80E)}, /* 7 */ }; DIB dda_dib = { disk_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ disk_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + disk_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ disk_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ dda_unit, /* UNIT* units */ /* Pointer to units structure */ dda_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ NUM_UNITS_DISK, /* uint8 numunits */ /* number of units defined */ - 0x07, /* uint8 mask */ /* 8 devices - device mask */ + 0x0F, /* uint8 mask */ /* 8 devices - device mask */ 0x0800, /* uint16 chan_addr */ /* parent channel address */ 0, /* uint32 chan_fifo_in */ /* fifo input index */ 0, /* uint32 chan_fifo_out */ /* fifo output index */ @@ -334,7 +368,6 @@ DEVICE dda_dev = { NUM_UNITS_DISK, 16, 24, 4, 16, 32, NULL, NULL, &disk_reset, &disk_boot, &disk_attach, &disk_detach, /* ctxt is the DIB pointer */ -// &dda_dib, DEV_DISABLE|DEV_DEBUG|DEV_DISK, 0, dev_debug, &dda_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS|DEV_DISK, 0, dev_debug, NULL, NULL, &disk_help, NULL, NULL, &disk_description }; @@ -346,26 +379,26 @@ CHANP ddb_chp[NUM_UNITS_DISK] = {0}; UNIT ddb_unit[] = { /* SET_TYPE(3) DM300 */ {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC00)}, /* 0 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC01)}, /* 1 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC02)}, /* 2 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC03)}, /* 3 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC04)}, /* 4 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC05)}, /* 5 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC06)}, /* 6 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC07)}, /* 7 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC02)}, /* 1 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC04)}, /* 2 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC06)}, /* 3 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC08)}, /* 4 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC0A)}, /* 5 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC0C)}, /* 6 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC0E)}, /* 7 */ }; DIB ddb_dib = { disk_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ disk_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + disk_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ disk_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ ddb_unit, /* UNIT* units */ /* Pointer to units structure */ ddb_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ NUM_UNITS_DISK, /* uint8 numunits */ /* number of units defined */ - 0x07, /* uint8 mask */ /* 8 devices - device mask */ + 0x0F, /* uint8 mask */ /* 8 devices - device mask */ 0x0C00, /* uint16 chan_addr */ /* parent channel address */ 0, /* uint32 chan_fifo_in */ /* fifo input index */ 0, /* uint32 chan_fifo_out */ /* fifo output index */ @@ -378,7 +411,6 @@ DEVICE ddb_dev = { NULL, NULL, &disk_reset, &disk_boot, &disk_attach, &disk_detach, /* ctxt is the DIB pointer */ &ddb_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS|DEV_DISK, 0, dev_debug, -// &ddb_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, NULL, NULL, &disk_help, NULL, NULL, &disk_description }; #endif @@ -399,41 +431,41 @@ uint32 disksec2star(uint32 daddr, int type) uint16 disk_preio(UNIT *uptr, uint16 chan) { DEVICE *dptr = get_dev(uptr); - uint16 chsa = GET_UADDR(uptr->CMDu3); + uint16 chsa = GET_UADDR(uptr->CMD); int unit = (uptr - dptr->units); - sim_debug(DEBUG_DETAIL, dptr, "disk_preio CMD %08x unit %02x\n", uptr->CMDu3, unit); - if ((uptr->CMDu3 & 0xff00) != 0) { /* just return if busy */ + sim_debug(DEBUG_DETAIL, dptr, "disk_preio CMD %08x unit %02x\n", uptr->CMD, unit); + if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */ return SNS_BSY; } sim_debug(DEBUG_DETAIL, dptr, "disk_preio unit %02x chsa %04x OK\n", unit, chsa); - return 0; /* good to go */ + return SCPE_OK; /* good to go */ } uint16 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { - uint16 chsa = GET_UADDR(uptr->CMDu3); + uint16 chsa = GET_UADDR(uptr->CMD); DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ sim_debug(DEBUG_CMD, dptr, "disk_startcmd chsa %04x unit %02x cmd %02x CMD %08x\n", - chsa, unit, cmd, uptr->CMDu3); + chsa, unit, cmd, uptr->CMD); if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + sim_debug(DEBUG_CMD, dptr, "disk_startcmd unit %02x not attached\n", unit); uptr->SNS |= SNS_INTVENT; /* unit intervention required */ if (cmd != DSK_SNS) /* we are completed with unit check status */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; } - if ((uptr->CMDu3 & DSK_CMDMSK) != 0) { - uptr->CMDu3 |= DSK_BUSY; /* Flag we are busy */ - return SNS_BSY; - } - if ((uptr->CMDu3 & 0xff00) != 0) { /* if any status info, we are busy */ + if ((uptr->CMD & DSK_CMDMSK) != 0) { + sim_debug(DEBUG_CMD, dptr, "disk_startcmd unit %02x busy\n", unit); + uptr->CMD |= DSK_BUSY; /* Flag we are busy */ return SNS_BSY; } + uptr->SNS2 |= SNS_USEL; /* unit selected */ sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD continue unit=%02x cmd %02x\n", unit, cmd); /* Unit is online, so process a command */ @@ -442,75 +474,134 @@ uint16 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) case DSK_INCH: /* INCH cmd 0x0 */ sim_debug(DEBUG_CMD, dptr, "disk_startcmd starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n", - uptr->u4, chsa, chp->ccw_addr, chp->ccw_count); + chp->chan_inch_addr, chsa, chp->ccw_addr, chp->ccw_count); - uptr->CMDu3 |= DSK_INCH2; /* use 0xF0 for inch, just need int */ + uptr->SNS &= ~SNS_CMDREJ; /* not rejected yet */ + uptr->CMD |= DSK_INCH2; /* use 0xF0 for inch, just need int */ //J sim_activate(uptr, 20); /* start things off */ - sim_activate(uptr, 50); /* start things off */ - return 0; +#ifdef FAST_FOR_UTX +// sim_activate(uptr, 50); /* start things off */ +// sim_activate(uptr, 40); /* start things off */ + sim_activate(uptr, 30); /* start things off */ +#else + sim_activate(uptr, 250); /* start things off */ +#endif + return SCPE_OK; /* good to go */ break; + case DSK_NOP: /* NOP 0x03 */ + if ((cmd == DSK_NOP) && + (chp->chan_info & INFO_SIOCD)) { /* is NOP 1st IOCD? */ + chp->chan_caw -= 8; /* backup iocd address for diags */ + break; /* yes, can't be 1st */ + } + case DSK_ICH: /* 0xFF Initialize controller */ + if ((cmd == DSK_ICH) && + (chp->ccw_count != 896)) /* count must be 896 to be valid */ + break; case DSK_SCK: /* Seek command 0x07 */ case DSK_XEZ: /* Rezero & Read IPL record 0x37 */ case DSK_WD: /* Write command 0x01 */ case DSK_RD: /* Read command 0x02 */ case DSK_LMR: /* read mode register 0x1F */ - case DSK_NOP: /* NOP 0x03 */ - case DSK_SNS: /* Sense 0x04 */ case DSK_WSL: /* WSL 0x31 */ case DSK_RSL: /* RSL 0x32 */ + case DSK_IHA: /* 0x47 Increment head address */ case DSK_WTL: /* WTL 0x51 */ case DSK_RTL: /* RTL 0x52 */ - uptr->CMDu3 |= cmd; /* save cmd */ + case DSK_RAP: /* 0xA2 Read angular positions */ + case DSK_TESS: /* TESS 0xAB Test STAR */ + uptr->SNS &= ~MASK24; /* clear data & leave mode */ + uptr->SNS2 = (SNS_UNR|SNS_ONC|SNS_USEL);/* reset status to on cyl & ready */ + case DSK_SNS: /* Sense 0x04 */ + uptr->CMD |= cmd; /* save cmd */ sim_debug(DEBUG_CMD, dptr, - "disk_startcmd starting disk seek r/w cmd %02x chsa %04x\n", + "disk_startcmd starting disk cmd %02x chsa %04x\n", cmd, chsa); //J sim_activate(uptr, 20); /* start things off */ +#ifdef FAST_FOR_UTX +// sim_activate(uptr, 50); /* start things off */ +// sim_activate(uptr, 40); /* start things off */ sim_activate(uptr, 30); /* start things off */ - return 0; +#else + sim_activate(uptr, 250); /* start things off */ +#endif + return SCPE_OK; /* good to go */ break; } sim_debug(DEBUG_CMD, dptr, "disk_startcmd done with bad disk cmd %02x chsa %04x SNS %08x\n", cmd, chsa, uptr->SNS); -//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 */ -//25return SNS_CHNEND|SNS_DEVEND; - return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; + uptr->SNS |= SNS_CMDREJ; /* cmd rejected */ + return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; /* return error */ +} + +/* Handle haltio transfers for disk */ +uint16 disk_haltio(UNIT *uptr) { + uint16 chsa = GET_UADDR(uptr->CMD); + DEVICE *dptr = get_dev(uptr); + int cmd = uptr->CMD & DSK_CMDMSK; + CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + + sim_debug(DEBUG_EXP, dptr, "disk_haltio enter chsa %04x cmd = %02x\n", chsa, cmd); + + /* terminate any input command */ + /* UTX wants SLI bit, but no unit exception */ + /* status must not have an error bit set */ + /* otherwise, UTX will panic with "bad status" */ + if ((uptr->CMD & DSK_CMDMSK) != 0) { /* is unit busy */ + sim_debug(DEBUG_CMD, dptr, + "disk_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->SNS2 |= (SNS_ONC|SNS_UNR); /* on cylinder & ready */ + sim_cancel(uptr); /* clear the input timer */ + sim_debug(DEBUG_CMD, dptr, + "disk_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* force end */ + return SCPE_IOERR; + } + uptr->CMD &= LMASK; /* make non-busy */ + uptr->SNS2 |= (SNS_ONC|SNS_UNR); /* on cylinder & ready */ + sim_debug(DEBUG_CMD, dptr, + "disk_haltio HIO I/O not busy chsa %04x cmd = %02x\n", chsa, cmd); + return SCPE_OK; /* not busy */ } /* Handle processing of disk requests. */ t_stat disk_srv(UNIT *uptr) { - uint16 chsa = GET_UADDR(uptr->CMDu3); + uint16 chsa = GET_UADDR(uptr->CMD); DEVICE *dptr = get_dev(uptr); CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ - int cmd = uptr->CMDu3 & DSK_CMDMSK; + int cmd = uptr->CMD & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); - uint32 trk=0, cyl=0, sec=0; + uint32 tcyl=0, trk=0, cyl=0, sec=0; int unit = (uptr - dptr->units); - int len; - int i; + int len = chp->ccw_count; + int i,j; + uint32 mema; /* memory address */ uint8 ch; uint16 ssize = disk_type[type].ssiz * 4; /* disk sector size in bytes */ uint32 tstart; - uint8 buf2[1024]; uint8 buf[1024]; + uint8 buf2[1024]; sim_debug(DEBUG_CMD, dptr, "disk_srv entry unit %02x CMD %08x chsa %04x count %04x %x/%x/%x \n", - unit, uptr->CMDu3, chsa, chp->ccw_count, + unit, uptr->CMD, chsa, chp->ccw_count, STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ uptr->SNS |= SNS_INTVENT; /* unit intervention required */ - if (cmd != DSK_SNS) /* we are completed with unit check status */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + if (cmd != DSK_SNS) { /* we are completed with unit check status */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + } } sim_debug(DEBUG_CMD, dptr, @@ -520,16 +611,37 @@ t_stat disk_srv(UNIT *uptr) case 0: /* No command, stop disk */ break; - case DSK_INCH2: /* used 0xF0 for inch, just need int */ - { - uint32 mema; /* memory address */ - uint32 i; - + case DSK_ICH: /* 0xFF Initialize controller */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ len = chp->ccw_count; /* INCH command count */ mema = chp->ccw_addr; /* get inch or buffer addr */ sim_debug(DEBUG_CMD, dptr, - "disk_srv starting INCH cmd, chsa %04x MemBuf %06x cnt %04x\n", - chsa, chp->ccw_addr, chp->ccw_count); + "disk_srv cmd CONT INCH %06x chsa %04x addr %06x count %04x completed\n", + chp->chan_inch_addr, chsa, mema, chp->ccw_count); + /* to use this inch method, byte count must be 897 */ + if (len != 896) { + /* we have invalid count, error, bail out */ + uptr->SNS |= SNS_CMDREJ; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + /* now call set_inch() function to write and test inch buffer addresses */ + tstart = set_inch(uptr, mema); /* new address */ + if ((tstart == SCPE_MEM) || (tstart == SCPE_ARG)) { /* any error */ + /* we have error, bail out */ + uptr->SNS |= SNS_CMDREJ; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case DSK_INCH2: /* used 0xF0 for inch, just need int */ + len = chp->ccw_count; /* INCH command count */ + mema = chp->ccw_addr; /* get inch or buffer addr */ + sim_debug(DEBUG_CMD, dptr, + "disk_srv starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n", + chp->chan_inch_addr, chsa, chp->ccw_addr, chp->ccw_count); /* mema has IOCD word 1 contents. For the disk processor it contains */ /* a pointer to the INCH buffer followed by 8 drive attribute words that */ @@ -539,15 +651,12 @@ t_stat disk_srv(UNIT *uptr) /* as all other devices on the channel. Call set_inch() to do this for us */ /* just return OK and channel software will use u4 as status buffer addr */ - len = chp->ccw_count; /* INCH command count */ - if (len != 36) { - /* we have invalid count, error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ -//25 uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; - uptr->SNS |= SNS_CMDREJ; - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; + /* we have invalid count, error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; } /* read all 36 bytes, stopping every 4 bytes to make words */ @@ -557,9 +666,10 @@ t_stat disk_srv(UNIT *uptr) /* so we will not have a map fault */ for (i=0; i < 36; i++) { if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ /* we have error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ -//25 uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -578,27 +688,23 @@ t_stat disk_srv(UNIT *uptr) } } /* now call set_inch() function to write and test inch buffer addresses */ - i = set_inch(uptr, mema); /* new address */ -#ifdef NOTYET - if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ + tstart = set_inch(uptr, mema); /* new address */ + if ((tstart == SCPE_MEM) || (tstart == SCPE_ARG)) { /* any error */ /* we have error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ -//25 uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } -#endif - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, - "disk_srv cmd INCH chsa %04x addr %06x count %04x completed\n", - chsa, mema, chp->ccw_count); + "disk_srv cmd INCH %06x chsa %04x addr %06x count %04x completed\n", + chp->chan_inch_addr, chsa, mema, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ - } break; case DSK_WSL: /* WSL 0x31 make into NOP */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "disk_srv cmd WSL chsa %04x count %04x completed\n", chsa, chp->ccw_count); @@ -607,9 +713,12 @@ t_stat disk_srv(UNIT *uptr) /* now read sector label data */ len = chp->ccw_count; for (i = 0; i < len; i++) { +//0906 for (i = 0; i < 30; i++) { if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ /* we have write error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SCPE_OK; break; @@ -623,17 +732,19 @@ t_stat disk_srv(UNIT *uptr) break; case DSK_WTL: /* WTL 0x51 make into NOP */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "disk_srv cmd WTL chsa %04x count %04x completed\n", chsa, chp->ccw_count); - sim_debug(DEBUG_DETAIL, dptr, "Track %x label", uptr->CHS); + sim_debug(DEBUG_DETAIL, dptr, "Track %08x label", uptr->CHS); /* now read track label data */ for (i = 0; i < 30; i++) { if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ /* we have read error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SCPE_OK; break; @@ -647,16 +758,101 @@ t_stat disk_srv(UNIT *uptr) break; case DSK_NOP: /* NOP 0x03 */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + /* diags want chan prog check and cmd reject if 1st cmd of IOCL */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "disk_srv cmd NOP chsa %04x count %04x completed\n", chsa, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; - case DSK_SNS: /* 0x4 */ + case DSK_RAP: /* 0xA2 Read angular positions */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + /* get STAR (target sector) data in STAR */ + cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ + sec = uptr->CHS & 0xff; /* set sec */ + + ch = ((sec * 2) % SPT(type)) & 0x3f; /* get index cnt */ + uptr->SNS2 = (uptr->SNS2 & 0xc0ff) | ((((uint32)ch) & 0x3f) << 8); + sim_debug(DEBUG_DETAIL, dptr, + "disk_srv RAP %02x cyl %04x trk %02x sec %02x\n", + ch, cyl&0xffff, trk, sec); + + if (chan_write_byte(chsa, &ch)) { /* put a byte to memory */ + sim_debug(DEBUG_DATA, dptr, + "DISK RAP %02x for addr /%04x/%02x/%02x\n", + ch, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + if (chp->chan_status & STATUS_PCHK) { /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + } else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; +// return SCPE_OK; + } + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case DSK_IHA: /* 0x47 Increment head address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + /* get STAR (target sector) data in STAR */ + cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ + sec = 0; /* set sec to zero for this head */ + + sim_debug(DEBUG_DETAIL, dptr, + "disk_srv IHA cyl %04x trk %02x sec %02x unit=%02x\n", + cyl&0xffff, trk, sec, unit); + + /* Check if head increment valid */ + trk += 1; /* increment the head # */ + if (trk >= disk_type[type].nhds) { /* see if too big */ + trk = 0; /* back to trk 0 */ + cyl += 1; /* next cylinder */ + if (cyl >= disk_type[type].cyl) { /* see if too big */ + /* set new STAR value using new values */ + uptr->CHS = CHS2STAR(cyl, trk, sec); + sim_debug(DEBUG_EXP, dptr, + "disk_srv IHA ERROR cyl %04x trk %02x sec %02x unit=%02x\n", + cyl, trk, sec, unit); + uptr->SNS |= SNS_DADE; /* set error status */ + uptr->SNS2 |= (SNS_SKER|SNS_SEND); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* error */ + break; +// return SCPE_OK; + } + } + + /* set new STAR value using new values */ + uptr->CHS = CHS2STAR(cyl, trk, sec); + + /* file offset in bytes */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)) * SSB(type); + + /* just seek to the location where we will r/w data */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ + uptr->SNS |= SNS_DADE; /* set error status */ + uptr->SNS2 |= (SNS_SKER|SNS_SEND); + sim_debug(DEBUG_EXP, dptr, "disk_srv IHA error on seek to %04x\n", tstart); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; +// return SCPE_OK; + } + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case DSK_SNS: /* 0x04 */ /* Sense */ sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD sense\n"); + /* count must be 12 or 14, if not prog check */ + if (len != 12 && len != 14) { + sim_debug(DEBUG_CMD, dptr, + "disk_srv Sense bad count unit=%02x count%04x\n", unit, len); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK|STATUS_LENGTH); + break; + } /* bytes 0,1 - Cyl entry from CHS reg */ ch = (uptr->CHS >> 24) & 0xff; sim_debug(DEBUG_DETAIL, dptr, "disk_srv sense CHS b0 unit=%02x 1 %02x\n", @@ -673,11 +869,12 @@ t_stat disk_srv(UNIT *uptr) chan_write_byte(chsa, &ch); /* byte 3 - Sector entry from CHS reg */ ch = (uptr->CHS) & 0xff; + sec = ch; sim_debug(DEBUG_DETAIL, dptr, "disk_srv sense CHS b3 unit=%02x 4 %02x\n", unit, ch); chan_write_byte(chsa, &ch); - /* bytes 4 - mode reg, byte 0 of SNS */ + /* bytes 4 - mode reg, byte 0 of SNS */ ch = (uptr->SNS >> 24) & 0xff; /* return the sense data */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv sense unit=%02x 1 %02x\n", unit, ch); @@ -697,7 +894,7 @@ t_stat disk_srv(UNIT *uptr) chan_write_byte(chsa, &ch); /* bytes 8-11 - drive mode register entries from assigned disk */ - ch = disk_type[type].type & 0xfc; /* zero bits 6 & 7 in type byte */ + ch = disk_type[type].type & 0x40; /* zero bits 0, 2-7 in type byte */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv datr unit=%02x 1 %02x\n", unit, ch); chan_write_byte(chsa, &ch); @@ -718,60 +915,68 @@ 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 = 0xc0; /* seek end and unit selected for now */ +// ch = 0xc0; /* seek end and unit selected for now */ + uptr->SNS2 |= (SNS_SEND|SNS_USEL); /* selected & seek end */ + /* bits 2-7 have sector pulse count */ + ch = ((sec * 2) % SPT(type)) & 0x3f;/* get index cnt */ + uptr->SNS2 = (uptr->SNS2 & 0xc0ff) | ((((uint32)ch) & 0x3f) << 8); + ch = (uptr->SNS2 >> 8) & 0xff; /* seek end and unit selected for now */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv dsr unit=%02x 1 %02x\n", unit, ch); chan_write_byte(chsa, &ch); - ch = 0x30; /* drive on cylinder and ready for now */ +// ch = 0x30; /* drive on cylinder and ready for now */ + uptr->SNS2 &= uptr->SNS2; /* clean out old status */ + uptr->SNS2 |= (SNS_ONC|SNS_UNR); /* on cylinder & ready */ + ch = uptr->SNS2 & 0xff; /* drive on cylinder and ready for now */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv dsr unit=%02x 2 %02x\n", unit, ch); chan_write_byte(chsa, &ch); } - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->SNS &= 0xff000000; /* reset status */ + uptr->SNS2 = (SNS_UNR|SNS_ONC); /* reset status to on cyl & ready */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; case DSK_SCK: /* Seek cylinder, track, sector 0x07 */ /* If we are waiting on seek to finish, check if there yet. */ - if (uptr->CMDu3 & DSK_SEEKING) { + if (uptr->CMD & DSK_SEEKING) { /* see if on cylinder yet */ if (STAR2CYL(uptr->STAR) == STAR2CYL(uptr->CHS)) { /* we are on cylinder, seek is done */ - sim_debug(DEBUG_CMD, dptr, "disk_srv seek on cylinder unit=%02x %04x %04x\n", - unit, uptr->STAR >> 16, uptr->CHS >> 16); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + sim_debug(DEBUG_CMD, dptr, + "disk_srv seek on cylinder unit %02x new %04x old %04x\n", + unit, uptr->STAR>>16, uptr->CHS>>16); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS2 |= (SNS_SEND|SNS_ONC); /* On cylinder & seek done */ /* we have already seeked to the required sector */ /* we do not need to seek again, so move on */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); - return SCPE_OK; +// return SCPE_OK; break; } else { /* we have wasted enough time, we are there */ -#ifdef DO_SEEK_AGAIN - /* calculate file position in bytes of requested sector */ - /* file offset in bytes */ - tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type); - /* just reseek to the location where we will r/w data */ - if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ - sim_debug(DEBUG_DETAIL, dptr, "disk_srv Error on seek to %04x\n", tstart); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; - } -#endif /* we are on cylinder, seek is done */ sim_debug(DEBUG_CMD, dptr, "disk_srv seek over on cylinder unit=%02x %04x %04x\n", unit, uptr->STAR >> 16, uptr->CHS >> 16); uptr->CHS = uptr->STAR; /* we are there */ //J sim_activate(uptr, 10); - sim_activate(uptr, 15); +#ifdef FAST_FOR_UTX +// sim_activate(uptr, 15); +// sim_activate(uptr, 25); /* start things off */ +// sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 15); /* start things off */ +#else + sim_activate(uptr, 150); +#endif break; } } /* not seeking, so start a new seek */ /* set buf data to current STAR values */ - cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + tcyl = cyl = STAR2CYL(uptr->CHS); /* get current cyl */ buf[0] = (cyl >> 8) & 0xff; /* split cylinder */ buf[1] = cyl & 0xff; buf[2] = (uptr->CHS >> 8) & 0xff; /* get trk/head */ @@ -781,18 +986,28 @@ t_stat disk_srv(UNIT *uptr) "disk_srv current STAR unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); + if (len > 4) { + sim_debug(DEBUG_CMD, dptr, + "disk_srv SEEK bad count unit=%02x count%04x\n", unit, len); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK|STATUS_LENGTH); + break; + } + /* Read in 1-4 character seek code */ for (i = 0; i < 4; i++) { if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ if (i == 0) { sim_debug(DEBUG_DETAIL, dptr, "disk_srv seek error unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); /* we have error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ -//25 uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; - uptr->SNS |= SNS_CMDREJ; + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_DADE; /* Disc addressing or seek error */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + chp->ccw_count = len; /* restore count, huh? */ return SCPE_OK; break; } @@ -805,7 +1020,8 @@ t_stat disk_srv(UNIT *uptr) /* just read the next byte */ } } - /* else the cyl, trk, and sect are ready to update */ + chp->ccw_count = len; /* restore count for diag, huh? */ + /* else the cyl, trk, and sec are ready to update */ sim_debug(DEBUG_CMD, dptr, "disk_srv STAR unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); @@ -831,9 +1047,12 @@ t_stat disk_srv(UNIT *uptr) "disk_srv seek ERROR cyl %04x trk %02x sec %02x unit=%02x\n", cyl, trk, buf[3], unit); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ -//25 uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; /* set error status */ - uptr->SNS |= SNS_CMDREJ; /* set error status */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_DADE; /* set error status */ + uptr->SNS2 |= (SNS_SKER|SNS_SEND); + + /* set new STAR value */ + uptr->CHS = CHS2STAR(cyl, trk, buf[3]); /* we have an error, tell user */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* end command */ @@ -854,99 +1073,202 @@ t_stat disk_srv(UNIT *uptr) /* just seek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ sim_debug(DEBUG_EXP, dptr, "disk_srv Error on seek to %04x\n", tstart); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; + break; +// return SCPE_OK; } /* Check if already on correct cylinder */ /* if not, do a delay to slow things down */ if (STAR2CYL(uptr->STAR) != STAR2CYL(uptr->CHS)) { + int diff = ((int)tcyl - (int)cyl); + if (diff < 0) + diff = -diff; /* Do a fake seek to kill time */ - uptr->CMDu3 |= DSK_SEEKING; /* show we are seeking */ + uptr->CMD |= DSK_SEEKING; /* show we are seeking */ sim_debug(DEBUG_EXP, dptr, - "disk_srv seeking unit=%02x to cyl %04x trk %02x sec %02x\n", - unit, cyl, trk, buf[3]); -//J sim_activate(uptr, 20); /* start us off */ - sim_activate(uptr, 20); /* start us off */ + "disk_srv seeking unit=%02x to /%04x/%02x/%02x from cyl %04x (%04x)\n", + unit, cyl, trk, buf[3], tcyl, diff); +#ifdef FAST_FOR_UTX +// sim_activate(uptr, 20); /* start us off */ +// sim_activate(uptr, 25); /* start things off */ +// sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 15); /* start things off */ +#else + sim_activate(uptr, 200+diff); /* start us off */ +#endif } else { /* we are on cylinder/track/sector, so go on */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv done seeking to %04x cyl %04x trk %02x sec %02x\n", tstart, cyl, trk, buf[3]); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); } - return SCPE_OK; + break; +// return SCPE_OK; - case DSK_XEZ: /* Rezero & Read IPL record */ + case DSK_XEZ: /* 0x37 */ /* Rezero & Read IPL record */ sim_debug(DEBUG_CMD, dptr, "RD REZERO IPL unit=%02x seek 0\n", unit); /* Do a seek to 0 */ uptr->STAR = 0; /* set STAR to 0, 0, 0 */ uptr->CHS = 0; /* set current CHS to 0, 0, 0 */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ - uptr->CMDu3 |= DSK_SCK; /* show as seek command */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->CMD |= DSK_SCK; /* show as seek command */ tstart = 0; /* byte offset is 0 */ /* just seek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ sim_debug(DEBUG_EXP, dptr, "disk_srv Error on seek to %04x\n", tstart); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; + break; +// return SCPE_OK; } /* we are on cylinder/track/sector zero, so go on */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv done seek trk 0\n"); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); - return SCPE_OK; +// return SCPE_OK; break; - case DSK_LMR: + case DSK_LMR: /* 0x1F */ sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x\n", unit); /* Read in 1 character of mode data */ if (chan_read_byte(chsa, &buf[0])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ /* we have error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ -//25 uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ; - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; } sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x old %x new %x\n", unit, (uptr->SNS)&0xff, buf[0]); - uptr->CMDu3 &= LMASK; /* remove old cmd */ + uptr->CMD &= LMASK; /* remove old cmd */ uptr->SNS &= MASK24; /* clear old mode data */ uptr->SNS |= (buf[0] << 24); /* save mode value */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; + case DSK_TESS: /* 0xAB */ /* Test STAR (subchannel target address register) */ + len = chp->ccw_count; + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + + /* set position data for current STAR values */ + cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ + sec = uptr->CHS & 0xff; /* get sec */ + buf[0] = (cyl >> 8) & 0xff; /* split cylinder */ + buf[1] = cyl & 0xff; + buf[2] = trk; /* get trk/head */ + buf[3] = sec; /* get sec */ + + sim_debug(DEBUG_CMD, dptr, + "disk_srv TESS STAR unit=%02x star %04x %02x %02x\n", + unit, cyl, trk, sec); + + /* a count of 0,1 is prog check */ + if (len <= 1) { + uptr->SNS |= SNS_CMDREJ; /* cmd rejected */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); +// return SCPE_OK; + break; + } + /* Read in 2-4 character tess code */ + for (i = 0; i < 4; i++) { + if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + if (i <= 1) { + sim_debug(DEBUG_DETAIL, dptr, + "disk_srv TESS error unit=%02x star %04x %02x %02x\n", + unit, cyl, trk, sec); + /* we have error, bail out */ + uptr->SNS |= SNS_CMDREJ; /* cmd rejected */ + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); +// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + return SCPE_OK; + break; + } + /* just read the next byte */ + } + } + tstart = SNS_CHNEND|SNS_DEVEND; /* set default status */ + /* if len = 2, set SNS_SM if tcyl > cyl */ + if (len == 2) { + tcyl = (buf[0] << 8) | buf[1]; /* test cyl */ + if (tcyl > cyl) + tstart |= SNS_SMS; /* set status modifier bit */ + } else + /* if len = 3, set SNS_SM if tcyl > cyl or tcyl == cyl & buf[2] >= trk */ + if (len == 3) { + tcyl = (buf[0] << 8) | buf[1]; /* test cyl */ + if ((tcyl > cyl) || ((tcyl == cyl) && (buf[2] >= trk))) + tstart |= SNS_SMS; /* set status modifier bit */ + } else + /* if len = 4, set SNS_SM if tcyl > cyl or */ + /* if (tcyl == cyl and buf[2] >= trk) */ + /* or if (tcyl == cyl and buf[2] == trk and buf[3] >= sec) */ + if (len >= 4) { + tcyl = (buf[0] << 8) | buf[1]; /* test cyl */ + if ((tcyl > cyl) || ((tcyl == cyl) && (buf[2] >= trk)) || + ((tcyl == cyl) && (buf[2] == trk) && (buf[3] >= sec))) + tstart |= SNS_SMS; /* set status modifier bit */ + } + /* else the cyl, trk, and sect are ready to update */ + sim_debug(DEBUG_CMD, dptr, + "disk_srv tess STAR unit=%02x star %02x %02x %02x %02x\n", + unit, buf[0], buf[1], buf[2], buf[3]); + + chan_end(chsa, tstart); +// return SCPE_OK; + break; + case DSK_RD: /* Read Data */ - if ((uptr->CMDu3 & DSK_READING) == 0) { /* see if we are reading data */ - uptr->CMDu3 |= DSK_READING; /* read from disk starting */ + if ((uptr->CMD & DSK_READING) == 0) { /* see if we are reading data */ + uptr->CMD |= DSK_READING; /* read from disk starting */ sim_debug(DEBUG_CMD, dptr, "DISK READ starting CMD %08x chsa %04x buffer %06x count %04x\n", - uptr->CMDu3, chsa, chp->ccw_addr, chp->ccw_count); + uptr->CMD, chsa, chp->ccw_addr, chp->ccw_count); } - if (uptr->CMDu3 & DSK_READING) { /* see if we are reading data */ - cyl = STAR2CYL(uptr->CHS); /* get current cyl */ - trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ - sec = uptr->CHS & 0xff; /* get sec */ - /* get sector offset */ + if (uptr->CMD & DSK_READING) { /* see if we are reading data */ + /* get file offset in sectors */ tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* convert sector number back to chs value to sync disk for diags */ + uptr->CHS = disksec2star(tstart, type); + /* file offset in bytes */ + tstart = tstart * SSB(type); + + /* just seek to the location where we will r/w data */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ + sim_debug(DEBUG_EXP, dptr, "disk_srv READ, Error on seek to %04x\n", tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; +// return SCPE_OK; + } sim_debug(DEBUG_CMD, dptr, "DISK READ reading CMD %08x chsa %04x tstart %04x buffer %06x count %04x\n", - uptr->CMDu3, chsa, tstart, chp->ccw_addr, chp->ccw_count); + uptr->CMD, chsa, tstart, chp->ccw_addr, chp->ccw_count); /* read in a sector of data from disk */ if ((len=sim_fread(buf, 1, ssize, uptr->fileref)) != ssize) { sim_debug(DEBUG_CMD, dptr, "Error %08x on read %04x of diskfile cyl %04x hds %02x sec %02x\n", - len, ssize, cyl, trk, sec); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + len, ssize, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -955,131 +1277,174 @@ t_stat disk_srv(UNIT *uptr) "disk_srv after READ chsa %04x buffer %06x count %04x\n", chsa, chp->ccw_addr, chp->ccw_count); + uptr->CHS++; /* next sector number */ /* process the next sector of data */ for (i=0; ichan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ sim_debug(DEBUG_DATA, dptr, "DISK Read %04x bytes leaving %04x from diskfile /%04x/%02x/%02x\n", - i, chp->ccw_count, cyl, trk, sec); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + i, chp->ccw_count, ((uptr->CHS)>>16)&0xffff, + ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); return SCPE_OK; } } sim_debug(DEBUG_CMD, dptr, "DISK READ %04x bytes leaving %4x to be read to %06x from diskfile /%04x/%02x/%02x\n", - ssize, chp->ccw_count, chp->ccw_addr+4, cyl, trk, sec); + ssize, chp->ccw_count, chp->ccw_addr+4, + ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); - /* see if we are done reading data */ - if (test_write_byte_end(chsa)) { - sim_debug(DEBUG_DATA, dptr, - "DISK Read complete for read from diskfile /%04x/%02x/%02x\n", - STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - break; - } + /* get sector offset */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); - /* tstart has file offset in sectors */ - tstart++; /* bump to next sector */ - /* convert sect back to chs value */ - uptr->CHS = disksec2star(tstart, type); /* see if over end of disk */ if (tstart >= (uint32)CAP(type)) { /* EOM reached, abort */ sim_debug(DEBUG_CMD, dptr, "DISK Read reached EOM for read from disk @ /%04x/%02x/%02x\n", STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->CHS = 0; /* reset cylinder position */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } + /* see if we are done reading data */ + if (test_write_byte_end(chsa)) { + sim_debug(DEBUG_DATA, dptr, + "DISK Read complete for read from diskfile /%04x/%02x/%02x\n", + STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; + } + sim_debug(DEBUG_DATA, dptr, "DISK sector read complete, %x bytes to go from diskfile /%04x/%02x/%02x\n", chp->ccw_count, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); //J sim_activate(uptr, 10); /* wait to read next sector */ - sim_activate(uptr, 15); /* wait to read next sector */ +#ifdef FAST_FOR_UTX +// sim_activate(uptr, 15); /* wait to read next sector */ +// sim_activate(uptr, 25); /* start things off */ +// sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 15); /* start things off */ +#else + sim_activate(uptr, 150); /* wait to read next sector */ +#endif break; } + uptr->CMD &= LMASK; /* remove old status bits & cmd */ break; case DSK_WD: /* Write Data */ - if ((uptr->CMDu3 & DSK_WRITING) == 0) { /* see if we are writing data */ - cyl = STAR2CYL(uptr->CHS); /* get current cyl */ - trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ - sec = uptr->CHS & 0xff; /* get sec */ - uptr->CMDu3 |= DSK_WRITING; /* write to disk starting */ + if ((uptr->CMD & DSK_WRITING) == 0) { /* see if we are writing data */ + uptr->CMD |= DSK_WRITING; /* write to disk starting */ sim_debug(DEBUG_CMD, dptr, - "DISK WRITE starting unit=%02x CMD %02x write %4x from %06x to %03x/%02x/%02x\n", - unit, uptr->CMDu3, chp->ccw_count, chp->ccw_addr, cyl, trk, sec); + "DISK WRITE starting unit=%02x CMD %08x write %04x from %06x to %03x/%02x/%02x\n", + unit, uptr->CMD, chp->ccw_count, chp->ccw_addr, + ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); } - if (uptr->CMDu3 & DSK_WRITING) { /* see if we are writing data */ - /* get sector offset */ + if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */ + /* get file offset in sectors */ tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* file offset in bytes */ + tstart = tstart * SSB(type); + + /* just seek to the location where we will r/w data */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ + sim_debug(DEBUG_EXP, dptr, "disk_srv WRITE, Error on seek to %04x\n", tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + } /* process the next sector of data */ - len = 0; /* used here as a flag for short read */ + tcyl = 0; /* used here as a flag for short read */ for (i=0; ichan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ /* if error on reading 1st byte, we are done writing */ - if (i == 0) { - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + if ((i == 0) || (chp->chan_status & STATUS_PCHK)) { + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "DISK Wrote %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", - ssize, cyl, trk, sec); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); return SCPE_OK; } ch = 0; /* finish out the sector with zero */ - len++; /* show we have no more data to write */ + tcyl++; /* show we have no more data to write */ } buf2[i] = ch; /* save the char */ } + /* get file offset in sectors */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* convert sector number back to chs value to sync disk for diags */ + uptr->CHS = disksec2star(tstart, type); + /* write the sector to disk */ if ((i=sim_fwrite(buf2, 1, ssize, uptr->fileref)) != ssize) { sim_debug(DEBUG_CMD, dptr, "Error %08x on write %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", - i, ssize, cyl, trk, sec); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + i, ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } - if (len != 0) { /* see if done with write command */ + + uptr->CHS++; /* next sector number */ + if (tcyl != 0) { /* see if done with write command */ sim_debug(DEBUG_DATA, dptr, "DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", - ssize, cyl, trk, sec); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; } sim_debug(DEBUG_CMD, dptr, "DISK WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x\n", - len, ssize, cyl, trk, sec); + len, ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + + /* get sector offset */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); - /* tstart has file offset in sectors */ - tstart++; /* bump to next sector */ - /* convert sect back to chs value */ - uptr->CHS = disksec2star(tstart, type); /* see if over end of disk */ if (tstart >= (uint32)CAP(type)) { /* EOM reached, abort */ sim_debug(DEBUG_CMD, dptr, "DISK Write reached EOM for write to disk @ /%04x/%02x/%02x\n", STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->CHS = 0; /* reset cylinder position */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } //J sim_activate(uptr, 10); /* keep writing */ - sim_activate(uptr, 15); /* keep writing */ +#ifdef FAST_FOR_UTX +// sim_activate(uptr, 15); /* keep writing */ +// sim_activate(uptr, 25); /* start things off */ +// sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 15); /* start things off */ +#else + sim_activate(uptr, 150); /* wait to read next sector */ +#endif break; } + uptr->CMD &= LMASK; /* remove old status bits & cmd */ break; case DSK_RSL: /* RSL 0x32 */ @@ -1089,89 +1454,117 @@ t_stat disk_srv(UNIT *uptr) for (i = 0; i < 30; i++) buf[i] = 0; - /* the dmap pointer is placed by the vendor or diag into the */ - /* track zero label in word 3 of the 30 byte label. */ - /* The disk address is the last track of the user area. The vendor */ - /* reserves the last cylinder, SEL diags reserve the next two, so the */ - /* addr is CYL-4/HDS-1/0 and is VDT. The UTX/MPX media table is on */ - /* previous track, so MDT = VDT-SPT is CYL-4/HDS-2/0 */ - /* The UTX flaw map is at DMAP = MDT-SPT CYL-4/HDS-3/0 */ - /* UTX media map is 1 track lower at UMAP=DMAP-SPT CYL-4/HDS-4/0 */ - /* The UTX media map is pointed to by sector label 1 */ - /* simulate pointers here, set wd[3] in label to UMAP */ + len = chp->ccw_count; /* get number of sectors per track */ - /* VDT 249264 (819/18/0) 0x3cdb0 for 9346 - 823/19/16 */ - /* MDT 249248 (819/17/0) 0x3cda0 for 9346 - 823/19/16 */ - /* DMAP 249232 (819/16/0) 0x3cd90 for 9346 - 823/19/16 */ - /* UMAP 249216 (819/15/0) 0x3cd80 for 9346 - 823/19/16 */ + /* read a 30 byte track label for each sector on track */ + /* for 16 sectors per track, that is 480 bytes */ + /* for 20 sectors per track, that is 600 bytes */ + for (j=0; jCHS, GEOM(type)); + /* get file offset in sectors */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* convert sector number back to chs value to sync disk for diags */ + uptr->CHS = disksec2star(tstart, type); - /* set buf data to current STAR values */ - cyl = STAR2CYL(uptr->CHS); /* get current cyl */ - buf[0] = (cyl >> 8) & 0xff; /* split cylinder */ - buf[1] = cyl & 0xff; - buf[2] = (uptr->CHS >> 8) & 0xff; /* get trk/head */ - buf[3] = uptr->CHS & 0xff; /* get sec */ - buf[4] = 0x80; /* set lflg1 to show good sector */ + /* the dmap pointer is placed by the vendor or diag into the */ + /* track zero label in word 3 of the 30 byte label. */ + /* The disk address is the last track of the user area. The vendor */ + /* reserves the last cylinder, SEL diags reserve the next two, so the */ + /* addr is CYL-4/HDS-1/0 and is VDT. The UTX/MPX media table is on */ + /* previous track, so MDT = VDT-SPT is CYL-4/HDS-2/0 */ + /* The UTX flaw map is at DMAP = MDT-SPT CYL-4/HDS-3/0 */ + /* UTX media map is 1 track lower at UMAP=DMAP-SPT CYL-4/HDS-4/0 */ + /* The UTX media map is pointed to by sector label 1 */ + /* simulate pointers here, set wd[3] in label to UMAP */ - sim_debug(DEBUG_DETAIL, dptr, - "disk_srv RSL unit=%02x star %02x %02x %02x %02x\n", - unit, buf[0], buf[1], buf[2], buf[3]); + /* VDT 249264 (819/18/0) 0x3cdb0 for 9346 - 823/19/16 */ + /* MDT 249248 (819/17/0) 0x3cda0 for 9346 - 823/19/16 */ + /* DMAP 249232 (819/16/0) 0x3cd90 for 9346 - 823/19/16 */ + /* UMAP 249216 (819/15/0) 0x3cd80 for 9346 - 823/19/16 */ - /* get sector address of UMAP */ - /* UMAP 249216 (819/15/0) 0x3cd80 for 9346 - 823/19/16 */ - tstart = ((CYL(type)-4) * SPC(type)) + - ((HDS(type)-4) * SPT(type)); + sim_debug(DEBUG_CMD, dptr, + "disk_startcmd RSL STAR %08x disk geom %08x\n", + uptr->CHS, GEOM(type)); - sim_debug(DEBUG_CMD, dptr, - "disk_srv SL1 RSL sector %d %x star %02x %02x %02x %02x\n", - tstart, tstart, buf[0], buf[1], buf[2], buf[3]); + /* set buf data to current STAR values */ + cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + buf[0] = (cyl >> 8) & 0xff; /* split cylinder */ + buf[1] = cyl & 0xff; + buf[2] = (uptr->CHS >> 8) & 0xff; /* get trk/head */ + buf[3] = uptr->CHS & 0xff; /* get sec */ + buf[4] = 0x80; /* set lflg1 to show good sector */ - /* on UDP & DPII DMAP is in wd 3 on label 0 */ - /* on UDP & DPII UMAP is in wd 4 on label 0 */ - /* UMAP 249216 (819/15/0) 0x3cd80 for 9346 - 823/19/16 */ + sim_debug(DEBUG_DETAIL, dptr, + "disk_srv RSL unit=%02x star %02x %02x %02x %02x\n", + unit, buf[0], buf[1], buf[2], buf[3]); - /* the address must be physical for UDP */ - /* store into sec 1 label */ - buf[16] = (tstart >> 24) & 0xff; /* UMAP pointer */ - buf[17] = (tstart >> 16) & 0xff; - buf[18] = (tstart >> 8) & 0xff; - buf[19] = (tstart) & 0xff; + /* get sector address of UMAP */ + /* UMAP 249216 (819/15/0) 0x3cd80 for 9346 - 823/19/16 */ + tstart = ((CYL(type)-4) * SPC(type)) + + ((HDS(type)-4) * SPT(type)); - /* the tech doc shows the cyl/trk/sec data is in the first 4 bytes */ - /* of the track label, BUT it is really in the configuration data */ - /* area are too. That is where UTX looks. Byte 27 is sectors/track */ - /* and byte 28 is number of heads. Byte 25 is copy of byte 27. */ - buf[25] = disk_type[type].spt & 0xff; /* sect per track 35 */ - /* The UDP/DPII controllers do not use these bits, so UTX keys */ - /* on these bits to determine type of controller. Bit 31 is set */ - /* for a HSDP and not set for the UDP/DPII */ - buf[26] = disk_type[type].type & 0xfc; /* sector size bits not used in UDP/DPII */ - buf[27] = disk_type[type].spt & 0xff; /* sec per track 35 */ - buf[28] = disk_type[type].nhds & 0xff; /* num heads 10 */ + sim_debug(DEBUG_CMD, dptr, + "disk_srv SL1 RSL sector %d %x star %02x %02x %02x %02x\n", + tstart, tstart, buf[0], buf[1], buf[2], buf[3]); - sim_debug(DEBUG_DETAIL, dptr, "Sector %x label", uptr->CHS); - /* now write sector label data */ - for (i = 0; i < 30; i++) { - if (chan_write_byte(chsa, &buf[i])) { - /* we have write error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; + /* on UDP & DPII DMAP is in wd 3 on label 0 */ + /* on UDP & DPII UMAP is in wd 4 on label 0 */ + /* UMAP 249216 (819/15/0) 0x3cd80 for 9346 - 823/19/16 */ + + /* the address must be physical for UDP */ + /* store into sec 1 label */ + /* diags want these values to be zero for all others*/ + if (uptr->CHS == 1) { /* test for sec 1, trk 0, cyl 0 */ + buf[16] = (tstart >> 24) & 0xff; /* UMAP pointer */ + buf[17] = (tstart >> 16) & 0xff; + buf[18] = (tstart >> 8) & 0xff; + buf[19] = (tstart) & 0xff; + } else { + buf[16] = 0; /* UMAP pointer */ + buf[17] = 0; + buf[18] = 0; + buf[19] = 0; } - if (i == 16) - sim_debug(DEBUG_DETAIL, dptr, "\nSector %x label", uptr->CHS); - sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + + /* the tech doc shows the cyl/trk/sec data is in the first 4 bytes */ + /* of the track label, BUT it is really in the configuration data */ + /* area are too. That is where UTX looks. Byte 27 is sectors/track */ + /* and byte 28 is number of heads. Byte 25 is copy of byte 27. */ + buf[25] = disk_type[type].spt & 0xff; /* sect per track 35 */ + /* The UDP/DPII controllers do not use these bits, so UTX keys */ + /* on these bits to determine type of controller. Bit 31 is set */ + /* for a HSDP and not set for the UDP/DPII */ + buf[26] = disk_type[type].type & 0xfc; /* sector size bits not used in UDP/DPII */ + buf[27] = disk_type[type].spt & 0xff; /* sec per track 35 */ + buf[28] = disk_type[type].nhds & 0xff; /* num heads 10 */ + + sim_debug(DEBUG_DETAIL, dptr, "Sector %x label", uptr->CHS); + /* now write sector label data */ + for (i = 0; i < 30; i++) { + if (chan_write_byte(chsa, &buf[i])) { + /* we have write error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (i == 16) + sim_debug(DEBUG_DETAIL, dptr, "\nSector %x label", uptr->CHS); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + /* leave STAR "unnormalized" for diags */ + uptr->CHS++; /* bump to next track */ + len -= 30; /* count 1 sector label size */ + if (len > 0) + continue; + break; /* done */ } - sim_debug(DEBUG_DETAIL, dptr, "\n"); /* command done */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd RSL done chsa %04x count %04x completed\n", chsa, chp->ccw_count); -/*25*/ chp->ccw_count = 0; chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; @@ -1183,6 +1576,11 @@ t_stat disk_srv(UNIT *uptr) for (i = 0; i < 30; i++) buf[i] = 0; + /* get file offset in sectors */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* convert sector number back to chs value to sync disk for diags */ + uptr->CHS = disksec2star(tstart, type); + /* set buf data to current CHS values */ if (uptr->CHS == 0) { /* write last address on trk 0 */ cyl = CYL(type)-1; /* lcyl cyl upper 8 bits */ @@ -1195,7 +1593,7 @@ t_stat disk_srv(UNIT *uptr) sec = (uptr->CHS) & 0xff; /* get the sector */ } - sim_debug(DEBUG_CMD, dptr, "disk_startcmd RTL STAR %08x disk geom %08x\n", + sim_debug(DEBUG_CMD, dptr, "disk_srv RTL STAR %08x disk geom %08x\n", uptr->CHS, GEOM(type)); /* set buf data to current STAR values */ @@ -1273,7 +1671,7 @@ t_stat disk_srv(UNIT *uptr) for (i = 0; i < 30; i++) { if (chan_write_byte(chsa, &buf[i])) { /* we have write error, bail out */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -1283,8 +1681,11 @@ t_stat disk_srv(UNIT *uptr) } sim_debug(DEBUG_DETAIL, dptr, "\n"); + /* leave STAR "unnormalized" for diags */ + uptr->CHS += 0x10; /* bump to next track */ + /* command done */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "disk_srv cmd RTL done chsa %04x count %04x completed\n", chsa, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ @@ -1293,12 +1694,13 @@ t_stat disk_srv(UNIT *uptr) default: sim_debug(DEBUG_CMD, dptr, "invalid command %02x unit %02x\n", cmd, unit); uptr->SNS |= SNS_CMDREJ; - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ - return SNS_CHNEND|STATUS_PCHK; + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|STATUS_PCHK); /* return Prog Check */ break; } sim_debug(DEBUG_DETAIL, dptr, - "disk_srv done cmd=%02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); + "disk_srv done cmd %02x chsa %04x chs %04x/%02x/%02x\n", + cmd, chsa, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); return SCPE_OK; } @@ -1311,13 +1713,12 @@ void disk_ini(UNIT *uptr, t_bool f) /* start out at sector 0 */ uptr->CHS = 0; /* set CHS to cyl/hd/sec = 0 */ uptr->STAR = 0; /* set STAR to cyl/hd/sec = 0 */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ -// uptr->SNS = ((uptr->SNS & MASK24) | (disk_type[i].type << 24)); /* save mode value */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ /* total sectors on disk */ uptr->capac = CAP(i); /* size in sectors */ sim_debug(DEBUG_EXP, &dda_dev, "DMA init device %s on unit DMA%04x cap %x %d\n", - dptr->name, GET_UADDR(uptr->CMDu3), uptr->capac, uptr->capac); + dptr->name, GET_UADDR(uptr->CMD), uptr->capac, uptr->capac); } t_stat disk_reset(DEVICE *dptr) @@ -1545,13 +1946,13 @@ int disk_format(UNIT *uptr) { fprintf (stderr, "Error on seek to 0\r\n"); return 1; } - return 0; + return SCPE_OK; /* good to go */ } /* attach the selected file to the disk */ t_stat disk_attach(UNIT *uptr, CONST char *file) { - uint16 chsa = GET_UADDR(uptr->CMDu3); + uint16 chsa = GET_UADDR(uptr->CMD); CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ int type = GET_TYPE(uptr->flags); DEVICE *dptr = get_dev(uptr); @@ -1620,7 +2021,6 @@ fmt: /* check for valid configured disk */ /* must have valid DIB and Channel Program pointer */ dibp = (DIB *)dptr->ctxt; /* get the DIB pointer */ -//??if ((dib_unit[chsa] == NULL) || (dibp == NULL) || (dibp->chan_prg == NULL)) { if ((dib_unit[chsa] == NULL) || (dibp == NULL) || (chp == NULL)) { sim_debug(DEBUG_CMD, dptr, "ERROR===ERROR\nDISK device %s not configured on system, aborting\n", dptr->name); @@ -1636,7 +2036,7 @@ fmt: /* detach a disk device */ t_stat disk_detach(UNIT *uptr) { uptr->SNS = 0; /* clear sense data */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ return detach_unit(uptr); /* tell simh we are done with disk */ } @@ -1644,19 +2044,19 @@ t_stat disk_detach(UNIT *uptr) { t_stat disk_boot(int32 unit_num, DEVICE *dptr) { UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */ - sim_debug(DEBUG_CMD, dptr, "Disk Boot dev/unit %x\n", GET_UADDR(uptr->CMDu3)); + sim_debug(DEBUG_CMD, dptr, "Disk Boot dev/unit %x\n", GET_UADDR(uptr->CMD)); if ((uptr->flags & UNIT_ATT) == 0) { sim_debug(DEBUG_EXP, dptr, "Disk Boot attach error dev/unit %04x\n", - GET_UADDR(uptr->CMDu3)); + GET_UADDR(uptr->CMD)); return SCPE_UNATT; /* attached? */ } - SPAD[0xf4] = GET_UADDR(uptr->CMDu3); /* put boot device chan/sa into spad */ + SPAD[0xf4] = GET_UADDR(uptr->CMD); /* put boot device chan/sa into spad */ SPAD[0xf8] = 0xF000; /* show as F class device */ /* now boot the disk */ - uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ - return chan_boot(GET_UADDR(uptr->CMDu3), dptr); /* boot the ch/sa */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + return chan_boot(GET_UADDR(uptr->CMD), dptr); /* boot the ch/sa */ } /* Disk option setting commands */ diff --git a/SEL32/sel32_ec.c b/SEL32/sel32_ec.c index 42b39ed..c4a88dd 100644 --- a/SEL32/sel32_ec.c +++ b/SEL32/sel32_ec.c @@ -207,6 +207,7 @@ struct ec_device { int poll; /* Need to poll receiver */ } ec_data; +int8 conf[12] = {0}; /* user specified configuration */ extern int32 tmxr_poll; @@ -344,6 +345,7 @@ uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) sim_debug(DEBUG_CMD, dptr, "ec_startcmd illegal at ec_startcmd %02x SNS %08x\n", cmd, uptr->SNS); + chp->ccw_count = 0; /* diags want zero count */ return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; /* diags want prog check */ // return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* diags want unit check */ default: @@ -358,7 +360,7 @@ uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) 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_LCC: /* Configure LCC 0x10 */ case EC_STATS: /* Read Statistics */ case EC_CSTATS: /* Clear software counters */ case EC_NOP: /* NOP 0x03 */ @@ -369,34 +371,25 @@ uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->SNS &= ~SNS_CMDREJ; /* remove CMD reject status */ /* Fall through */ 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 */ + /* nop must have non 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 */ + 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 cmd %02x SNS %08x\n", cmd, uptr->SNS); + chp->ccw_count = 0; /* diags want zero count */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* diags want unit check */ // return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; /* diags want prog check */ } -/* Handle processing of disk requests. */ +/* Handle processing of ethernet requests. */ t_stat ec_srv(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->CMD); @@ -412,16 +405,16 @@ t_stat ec_srv(UNIT *uptr) struct ec_eth_hdr *hdr; sim_debug(DEBUG_CMD, dptr, - "ec_srv cmd=%02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); + "ec_srv chp %p cmd=%02x chsa %04x count %04x\n", chp, cmd, chsa, chp->ccw_count); switch (cmd) { // 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 */ + sim_debug(DEBUG_CMD, dptr, + "ec_srv starting INCH %06x cmd, chsa %04x addr %06x cnt %04x\n", + chp->chan_inch_addr, chsa, chp->ccw_addr, chp->ccw_count); uptr->CMD &= LMASK; /* remove old status bits & */ /* now call set_inch() function to write and test inch buffer addresses */ @@ -459,24 +452,28 @@ t_stat ec_srv(UNIT *uptr) memcpy(&ec_data.mac, &buf[0], sizeof (ETH_MAC)); eth_mac_fmt(&ec_data.mac, (char *)&buf[0]); sim_debug(DEBUG_CMD, dptr, "ec_srv setting mac %s\n", buf); + i = buf[0] & 1; /* set/reset promiscuous mode */ n = ec_data.macs_n + 2; memcpy(&ec_data.macs[0], &ec_data.mac, sizeof (ETH_MAC)); memcpy(&ec_data.macs[1], &broadcast_ethaddr, sizeof (ETH_MAC)); if (ec_master_uptr->flags & UNIT_ATT) - eth_filter (&ec_data.etherface, n, ec_data.macs, ec_data.amc, 0); +//DIAGS eth_filter (&ec_data.etherface, n, ec_data.macs, ec_data.amc, 0); + /* set promiscuous if bit 7 of byte zero of mac address is set */ + eth_filter (&ec_data.etherface, n, ec_data.macs, ec_data.amc, i); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case EC_CGA: /* Disable multicast address */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + case EC_CGA: /* Disable multicast address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ ec_data.macs_n = 0; + ec_data.amc = 0; if (ec_master_uptr->flags & UNIT_ATT) - eth_filter (&ec_data.etherface, 1, ec_data.macs, ec_data.amc, 0); + eth_filter (&ec_data.etherface, 1, ec_data.macs, ec_data.amc, 0); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case EC_LGA: /* Load Multicast address */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + case EC_LGA: /* Load Multicast address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ ec_data.macs_n = 0; for(n = 2; n < (int)(sizeof(ec_data.macs_n) / sizeof (ETH_MAC)); n++) { for(i = 0; i < sizeof (ETH_MAC); i++) { @@ -489,14 +486,17 @@ t_stat ec_srv(UNIT *uptr) memcpy(&ec_data.macs[n], &buf[0], sizeof (ETH_MAC)); } ec_data.macs_n = n - 2; + ec_data.amc = 1; - for(i = 0; i< n; i++) { + 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",i,buf); } if (ec_master_uptr->flags & UNIT_ATT) - eth_filter (&ec_data.etherface, n, ec_data.macs, ec_data.amc, 0); +//DIAGS eth_filter (&ec_data.etherface, n, ec_data.macs, ec_data.amc, 0); + /* multicast on means promiscous is too */ + eth_filter (&ec_data.etherface, n, ec_data.macs, ec_data.amc, ec_data.amc); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; @@ -543,27 +543,43 @@ t_stat ec_srv(UNIT *uptr) break; } } + /* see if too many bytes */ + if (chp->ccw_count != 0) { + sim_debug(DEBUG_DETAIL, &ec_dev, + "ec_srv WRITE error user 2manybytes %0x\n", chp->ccw_count); + goto runt; + } ec_data.snd_buff.len = i + sizeof(struct ec_eth_hdr); ec_packet_debug(&ec_data, "send", &ec_data.snd_buff); if (eth_write(&ec_data.etherface, &ec_data.snd_buff, NULL) != SCPE_OK) { runt: - sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv short packet %d\n\r",i); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); + sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv short packet %d\n",i); +//DIAGS chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); + /* diags wants prog check instead of unit check */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); break; } - sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv sent packet %d bytes\n\r",i); + sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv sent packet %d bytes\n",i); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case EC_READ: /* Read command 0x02 */ + case EC_READ: /* Read command 0x02 */ + /* min size is 78 */ + if (chp->ccw_count < (ETH_MIN_PACKET+sizeof(struct ec_eth_hdr))) { + sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv short read size %x\n",chp->ccw_count); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + /* diags wants prog check instead of unit check */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } 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; } + uptr->CMD &= LMASK; /* remove old status bits & cmd */ ec_packet_debug(&ec_data, "recv", &ec_data.rec_buff); ec_data.rx_count++; - 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)) { @@ -607,14 +623,18 @@ runt: chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case EC_LCC: /* Configure LCC */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ - /* Read up to 12 bytes */ + case EC_LCC: /* Configure LCC 0x10 */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + /* Read up to 12 bytes of configuration data */ for (i = 0; i < 12; i++) { - if (chan_read_byte(chsa, &ch)) { + if (chan_read_byte(chsa, &conf[0])) { break; } } + sim_debug(DEBUG_CMD, &ec_dev, + "ec_srv LCC CONF: %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n", + conf[0], conf[1], conf[2], conf[3], conf[4], conf[5], conf[6], conf[7], + conf[8], conf[9], conf[10], conf[11]); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; @@ -729,7 +749,7 @@ uint16 ec_haltio(UNIT *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); + sim_debug(DEBUG_EXP, dptr, "ec_haltio enter chsa %04x chp %p cmd %02x\n", chsa, chp, cmd); /* terminate any input command */ /* UTX wants SLI bit, but no unit exception */ @@ -741,11 +761,12 @@ uint16 ec_haltio(UNIT *uptr) { // 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 */ + 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, + sim_debug(DEBUG_CMD, dptr, "ec_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd); // chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* force error */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* force end */ @@ -753,6 +774,8 @@ uint16 ec_haltio(UNIT *uptr) { } uptr->CMD &= LMASK; /* make non-busy */ uptr->SNS = SNS_RCV_RDY; /* status is online & ready */ + sim_debug(DEBUG_CMD, dptr, + "ec_haltio HIO I/O not busy chsa %04x cmd = %02x\n", chsa, cmd); return SCPE_OK; /* not busy */ } @@ -764,8 +787,8 @@ void ec_ini(UNIT *uptr, t_bool f) uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->SNS = 0; /* save mode value */ - sim_debug(DEBUG_EXP, &dda_dev, - "EC init device %s on unit EC%04x\n", dptr->name, GET_UADDR(uptr->CMD)); + sim_debug(DEBUG_EXP, dptr, + "EC init device %s on unit EC%04X\n", dptr->name, GET_UADDR(uptr->CMD)); } static char * @@ -1034,7 +1057,6 @@ t_stat ec_attach(UNIT* uptr, CONST char* cptr) ec_dev.name, buf); } if (SCPE_OK != eth_filter(&ec_data.etherface, 2, ec_data.macs, 0, 0)) { -// if (SCPE_OK != eth_filter(&ec_data.etherface, 2, ec_data.macs, 0, 1)) { eth_close(&ec_data.etherface); free(tptr); return sim_messagef (SCPE_NOATT, diff --git a/SEL32/sel32_hsdp.c b/SEL32/sel32_hsdp.c index bcc95c4..c88793e 100644 --- a/SEL32/sel32_hsdp.c +++ b/SEL32/sel32_hsdp.c @@ -278,6 +278,30 @@ Byte 1 bits 7-15 #define SNS_RTAE 0x02 /* Reserve track access error */ #define SNS_UESS 0x01 /* Uncorrectable ECC error */ +#define SNS2 us9 +/* us9 */ +/* us9 holds bytes 4 & 5 of the status for the drive */ + +/* Sense byte 4 */ +#define SNS_SEND 0x8000 /* Seek End */ +#define SNS_USEL 0x4000 /* Unit Selected */ +#define SNS_SPC0 0x2000 /* Sector Pulse Count B0 */ +#define SNS_SPC1 0x1000 /* Sector Pulse Count B1 */ +#define SNS_SPC2 0x0800 /* Sector Pulse Count B2 */ +#define SNS_SPC3 0x0400 /* Sector Pulse Count B3 */ +#define SNS_SPC4 0x0200 /* Sector Pulse Count B4 */ +#define SNS_SPC5 0x0100 /* Sector Pulse Count B5 */ + +/* Sense byte 5 */ +#define SNS_FLT 0x80 /* Disk Drive fault */ +#define SNS_SKER 0x40 /* Seek error */ +#define SNS_ONC 0x20 /* On Cylinder */ +#define SNS_UNR 0x10 /* Unit Ready */ +#define SNS_WRP 0x08 /* Write Protected */ +#define SNS_BUSY 0x04 /* Drive is busy */ +#define SNS_NU1 0x02 /* Spare 1 */ +#define SNS_NU2 0x01 /* Spare 2 */ + #define CHS u6 /* u6 holds the current cyl, hd, sec for the drive */ @@ -320,17 +344,17 @@ hsdp_type[] = { /* Class F Disc Devices */ /* For MPX */ - {"MH040", 5, 192, 20, 400, 411, 0x40}, /* 0 411 40M XXXX */ - {"MH080", 5, 192, 20, 800, 823, 0x40}, /* 1 823 80M 8138 */ - {"MH160", 10, 192, 20, 800, 823, 0x40}, /* 2 823 160M 8148 */ - {"MH300", 19, 192, 20, 800, 823, 0x40}, /* 3 823 300M 9346 */ + {"MH040", 5, 192, 20, 407, 411, 0x40}, /* 0 411 40M XXXX */ + {"MH080", 5, 192, 20, 819, 823, 0x40}, /* 1 823 80M 8138 */ + {"MH160", 10, 192, 20, 819, 823, 0x40}, /* 2 823 160M 8148 */ + {"MH300", 19, 192, 20, 819, 823, 0x40}, /* 3 823 300M 9346 */ {"MH600", 40, 192, 20, 839, 843, 0x40}, /* 4 843 600M 8155 */ /* For UTX */ {"9342", 5, 256, 16, 819, 823, 0x41}, /* 5 823 80M 9342 MH080 */ {"8148", 10, 256, 16, 819, 823, 0x41}, /* 6 823 160M 8146 MH160 */ - {"9346", 19, 256, 16, 800, 823, 0x41}, /* 7 823 300M 9344 MH300 */ - {"8887", 10, 256, 35, 819, 823, 0x41}, /* 8 823 337M 8887 DP337 */ - {"8858", 24, 256, 16, 704, 711, 0x41}, /* 9 711 340M 8858 DC340 */ + {"9346", 19, 256, 16, 819, 823, 0x41}, /* 7 823 300M 9344 MH300 */ + {"8858", 24, 256, 16, 707, 711, 0x41}, /* 8 711 340M 8858 DC340 */ + {"8887", 10, 256, 35, 819, 823, 0x41}, /* 9 823 337M 8887 DP337 */ {"8155", 40, 256, 16, 839, 843, 0x41}, /* 10 843 600M 8155 MH600 */ {NULL, 0} }; @@ -376,14 +400,14 @@ UNIT dpa_unit[] = { DIB dpa_dib = { hsdp_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ hsdp_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + hsdp_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ hsdp_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ dpa_unit, /* UNIT* units */ /* Pointer to units structure */ dpa_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ NUM_UNITS_HSDP, /* uint8 numunits */ /* number of units defined */ - 0x0E, /* uint8 mask */ /* 8 devices - device mask */ + 0x0F, /* uint8 mask */ /* 8 devices - device mask */ 0x0800, /* uint16 chan_addr */ /* parent channel address */ 0, /* uint32 chan_fifo_in */ /* fifo input index */ 0, /* uint32 chan_fifo_out */ /* fifo output index */ @@ -419,14 +443,14 @@ UNIT dpb_unit[] = { DIB dpb_dib = { hsdp_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ hsdp_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ - NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + hsdp_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ NULL, /* uint16 (*post_io)(UNIT *uptr) */ /* Post I/O */ hsdp_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ dpb_unit, /* UNIT* units */ /* Pointer to units structure */ dpb_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ NUM_UNITS_HSDP, /* uint8 numunits */ /* number of units defined */ - 0x0E, /* uint8 mask */ /* 8 devices - device mask */ + 0x0F, /* uint8 mask */ /* 8 devices - device mask */ 0x0C00, /* uint16 chan_addr */ /* parent channel address */ 0, /* uint32 chan_fifo_in */ /* fifo input index */ 0, /* uint32 chan_fifo_out */ /* fifo output index */ @@ -493,10 +517,7 @@ uint16 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->CMD |= DSK_BUSY; /* Flag we are busy */ return SNS_BSY; } - if ((uptr->CMD & 0xff00) != 0) { /* if any status info, we are busy */ - sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd unit %02x busy2\n", unit); - return SNS_BSY; - } + uptr->SNS2 |= SNS_USEL; /* unit selected */ sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd CMD continue unit=%02x cmd %02x\n", unit, cmd); /* Unit is online, so process a command */ @@ -507,28 +528,38 @@ uint16 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) "hsdp_startcmd starting INCH %06x cmd, chsa %04x MemBuf %08x cnt %04x\n", uptr->u4, chsa, chp->ccw_addr, chp->ccw_count); + uptr->SNS &= ~SNS_CMDREJ; /* not rejected yet */ uptr->CMD |= DSK_INCH2; /* use 0xF0 for inch, just need int */ sim_activate(uptr, 20); /* start things off */ - return 0; + return SCPE_OK; /* good to go */ break; + case DSK_NOP: /* NOP 0x03 */ + if ((cmd == DSK_NOP) && + (chp->chan_info & INFO_SIOCD)) { /* is NOP 1st IOCD? */ + chp->chan_caw -= 8; /* backup iocd address for diags */ + break; /* yes, can't be 1st */ + } case DSK_SCK: /* Seek command 0x07 */ case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ case DSK_WD: /* Write command 0x01 */ case DSK_RD: /* Read command 0x02 */ case DSK_LMR: /* read mode register */ - case DSK_NOP: /* NOP 0x03 */ - case DSK_SNS: /* Sense 0x04 */ case DSK_WSL: /* WSL 0x31 */ case DSK_RSL: /* RSL 0x32 */ + case DSK_IHA: /* 0x47 Increment head address */ case DSK_WTL: /* WTL 0x51 */ case DSK_RTL: /* RTL 0x52 */ + case DSK_RAP: /* 0xA2 Read angular positions */ + uptr->SNS &= ~MASK24; /* clear data & leave mode */ + uptr->SNS2 = (SNS_UNR|SNS_ONC|SNS_USEL);/* reset status to on cyl & ready */ + case DSK_SNS: /* Sense 0x04 */ uptr->CMD |= cmd; /* save cmd */ sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd starting disk cmd %02x chsa %04x\n", cmd, chsa); sim_activate(uptr, 20); /* start things off */ - return 0; + return SCPE_OK; /* good to go */ break; } @@ -536,13 +567,46 @@ uint16 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd done with hsdp_startcmd %02x chsa %04x SNS %08x\n", cmd, chsa, uptr->SNS); - if (uptr->SNS & 0xff) /* any other cmd is error */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - sim_activate(uptr, 20); /* start things off */ - return SNS_CHNEND|SNS_DEVEND; + uptr->SNS |= SNS_CMDREJ; /* cmd rejected */ + return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; /* return error */ } -/* Handle processing of disk requests. */ +/* Handle haltio transfers for disk */ +uint16 hsdp_haltio(UNIT *uptr) { + uint16 chsa = GET_UADDR(uptr->CMD); + DEVICE *dptr = get_dev(uptr); + int cmd = uptr->CMD & DSK_CMDMSK; + CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + + sim_debug(DEBUG_EXP, dptr, "hsdp_haltio enter chsa %04x cmd = %02x\n", chsa, cmd); + + /* terminate any input command */ + /* UTX wants SLI bit, but no unit exception */ + /* status must not have an error bit set */ + /* otherwise, UTX will panic with "bad status" */ + if ((uptr->CMD & DSK_CMDMSK) != 0) { /* is unit busy */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_haltio HIO chsa %04x cmd = %02x ccw_count %02x\n", chsa, cmd, chp->ccw_count); + /* stop any I/O and post status and return error status */ +// chp->chan_byte = BUFF_EMPTY; /* there is no data to read/store */ +// chp->ccw_count = 0; /* zero the count */ + chp->ccw_flags &= ~(FLAG_DC|FLAG_CC);/* stop any chaining */ + uptr->CMD &= LMASK; /* make non-busy */ + uptr->SNS2 |= (SNS_ONC|SNS_UNR); /* on cylinder & ready */ + sim_cancel(uptr); /* clear the input timer */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* force end */ + return SCPE_IOERR; + } + uptr->CMD &= LMASK; /* make non-busy */ + uptr->SNS2 |= (SNS_ONC|SNS_UNR); /* on cylinder & ready */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_haltio HIO I/O not busy chsa %04x cmd = %02x\n", chsa, cmd); + return SCPE_OK; /* not busy */ +} + +/* Handle processing of hsdp requests. */ t_stat hsdp_srv(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->CMD); @@ -550,10 +614,11 @@ t_stat hsdp_srv(UNIT *uptr) CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ int cmd = uptr->CMD & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); - uint32 trk, cyl, sec; + uint32 tcyl=0, trk=0, cyl=0, sec=0; int unit = (uptr - dptr->units); - int len; - int i; + int len = chp->ccw_count; + int i,j; + uint32 mema; /* memory address */ uint8 ch; uint16 ssize = hsdp_type[type].ssiz * 4; /* disk sector size in bytes */ uint32 tstart; @@ -567,8 +632,10 @@ t_stat hsdp_srv(UNIT *uptr) if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ uptr->SNS |= SNS_INTVENT; /* unit intervention required */ - if (cmd != DSK_SNS) /* we are completed with unit check status */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + if (cmd != DSK_SNS) { /* we are completed with unit check status */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + } } sim_debug(DEBUG_CMD, dptr, @@ -578,11 +645,7 @@ t_stat hsdp_srv(UNIT *uptr) case 0: /* No command, stop disk */ break; - case DSK_INCH2: /* use 0xc0 for inch, just need int */ - { - uint32 mema; /* memory address */ - uint32 i; - + case DSK_INCH2: /* use 0xF0 for inch, just need int */ len = chp->ccw_count; /* INCH command count */ mema = chp->ccw_addr; /* get inch or buffer addr */ sim_debug(DEBUG_CMD, dptr, @@ -597,14 +660,12 @@ t_stat hsdp_srv(UNIT *uptr) /* as all other devices on the channel. Call set_inch() to do this for us */ /* just return OK and channel software will use u4 as status buffer addr */ - len = chp->ccw_count; /* INCH command count */ - if (len != 36) { - /* we have invalid count, error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; + /* we have invalid count, error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; } /* read all 36 bytes, stopping every 4 bytes to make words */ @@ -614,9 +675,11 @@ t_stat hsdp_srv(UNIT *uptr) /* so we will not have a map fault */ for (i=0; i < 36; i++) { if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -635,25 +698,22 @@ t_stat hsdp_srv(UNIT *uptr) } /* now call set_inch() function to write and test inch bybber addresses */ i = set_inch(uptr, mema); /* new address */ -#ifdef NOTYET if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } -#endif uptr->CMD &= LMASK; /* remove old cmd */ sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd INCH chsa %04x chsa %06x count %04x completed\n", chsa, mema, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ - } break; case DSK_WSL: /* WSL 0x31 make into NOP */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd WSL chsa %04x count %04x completed\n", chsa, chp->ccw_count); @@ -662,11 +722,14 @@ t_stat hsdp_srv(UNIT *uptr) /* now read sector label data */ len = chp->ccw_count; for (i = 0; i < len; i++) { +// for (i = 0; i < 30; i++) { if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ /* we have write error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - goto goout; + return SCPE_OK; break; } if ((i%16) == 0) @@ -675,35 +738,36 @@ t_stat hsdp_srv(UNIT *uptr) } sim_debug(DEBUG_DETAIL, dptr, "\n"); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ -goout: break; case DSK_WTL: /* WTL 0x51 make into NOP */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd WTL chsa %04x count %04x completed\n", chsa, chp->ccw_count); - sim_debug(DEBUG_DETAIL, dptr, "Track 0 label"); + sim_debug(DEBUG_DETAIL, dptr, "Track %08x label", uptr->CHS); /* now read track label data */ for (i = 0; i < 30; i++) { if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ /* we have read error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - goto goout; + return SCPE_OK; break; } if (i == 16) - sim_debug(DEBUG_DETAIL, dptr, "\nTrack 0 label"); + sim_debug(DEBUG_DETAIL, dptr, "\nTrack %08x label", uptr->CHS); sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); } sim_debug(DEBUG_DETAIL, dptr, "\n"); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; case DSK_NOP: /* NOP 0x03 */ + /* diags want chan prog check and cmd reject if 1st cmd of IOCL */ uptr->CMD &= LMASK; /* remove old cmd */ sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd NOP chsa %04x count %04x completed\n", @@ -711,9 +775,93 @@ goout: chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; + case DSK_RAP: /* 0xA2 Read angular positions */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + /* get STAR (target sector) data in STAR */ + cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ + sec = uptr->CHS & 0xff; /* set sec */ + + ch = ((sec * 2) % SPT(type)) & 0x3f; /* get index cnt */ + uptr->SNS2 = (uptr->SNS2 & 0xc0ff) | ((((uint32)ch) & 0x3f) << 8); + sim_debug(DEBUG_DETAIL, dptr, + "hsdp_srv RAP %02x cyl %04x trk %02x sec %02x\n", + ch, cyl&0xffff, trk, sec); + + if (chan_write_byte(chsa, &ch)) { /* put a byte to memory */ + sim_debug(DEBUG_DATA, dptr, + "HSDP RAP %02x for addr /%04x/%02x/%02x\n", + ch, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + if (chp->chan_status & STATUS_PCHK) { /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + } else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; +// return SCPE_OK; + } + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case DSK_IHA: /* 0x47 Increment head address */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + /* get STAR (target sector) data in STAR */ + cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ + sec = 0; /* set sec to zero for this head */ + + sim_debug(DEBUG_DETAIL, dptr, + "hsdp_srv IHA cyl %04x trk %02x sec %02x unit=%02x\n", + cyl&0xffff, trk, sec, unit); + + /* Check if head increment valid */ + trk += 1; /* increment the head # */ + if (trk >= hsdp_type[type].nhds) { /* see if too big */ + trk = 0; /* back to trk 0 */ + cyl += 1; /* next cylinder */ + if (cyl >= hsdp_type[type].cyl) { /* see if too big */ + /* set new STAR value using new values */ + uptr->CHS = CHS2STAR(cyl, trk, sec); + sim_debug(DEBUG_EXP, dptr, + "hsdp_srv IHA ERROR cyl %04x trk %02x sec %02x unit=%02x\n", + cyl, trk, sec, unit); + uptr->SNS |= SNS_DADE; /* set error status */ + uptr->SNS2 |= (SNS_SKER|SNS_SEND); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* error */ + break; +// return SCPE_OK; + } + } + + /* set new STAR value using new values */ + uptr->CHS = CHS2STAR(cyl, trk, sec); + + /* file offset in bytes */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)) * SSB(type); + + /* just seek to the location where we will r/w data */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ + uptr->SNS |= SNS_DADE; /* set error status */ + uptr->SNS2 |= (SNS_SKER|SNS_SEND); + sim_debug(DEBUG_EXP, dptr, "disk_srv IHA error on seek to %04x\n", tstart); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; +// return SCPE_OK; + } + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + case DSK_SNS: /* 0x4 */ sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd CMD sense\n"); + /* count must be 12 or 14, if not prog check */ + if (len != 12 && len != 14) { + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv Sense bad count unit=%02x count%04x\n", unit, len); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK|STATUS_LENGTH); + break; + } /* bytes 0,1 - Cyl entry from CHS reg */ ch = (uptr->CHS >> 24) & 0xff; sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv sense CHS b0 unit=%02x 1 %02x\n", @@ -730,6 +878,7 @@ goout: chan_write_byte(chsa, &ch); /* byte 3 - Sector entry from CHS reg */ ch = (uptr->CHS) & 0xff; + sec = ch; /* save sec num for later */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv sense CHS b3 unit=%02x 4 %02x\n", unit, ch); chan_write_byte(chsa, &ch); @@ -775,60 +924,60 @@ goout: /* 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 */ + uptr->SNS2 |= (SNS_SEND|SNS_USEL); /* selected & seek end */ + /* bits 2-7 have sector pulse count */ + ch = ((sec * 2) % SPT(type)) & 0x3f;/* get index cnt */ + uptr->SNS2 = (uptr->SNS2 & 0xc0ff) | ((((uint32)ch) & 0x3f) << 8); + ch = (uptr->SNS2 >> 8) & 0xff; /* seek end and unit selected for now */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv dsr unit=%02x 1 %02x\n", unit, ch); chan_write_byte(chsa, &ch); - ch = 0x30; /* drive on cylinder and ready for now */ +// ch = 0x30; /* drive on cylinder and ready for now */ + uptr->SNS2 &= uptr->SNS2; /* clean out old status */ + uptr->SNS2 |= (SNS_ONC|SNS_UNR); /* on cylinder & ready */ + ch = uptr->SNS2 & 0xff; /* drive on cylinder and ready for now */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv dsr unit=%02x 2 %02x\n", unit, ch); chan_write_byte(chsa, &ch); } - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->SNS &= 0xff000000; /* reset status */ + uptr->SNS2 = (SNS_UNR|SNS_ONC); /* reset status to on cyl & ready */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; case DSK_SCK: /* Seek cylinder, track, sector 0x07 */ - /* If we are waiting on seek to finish, check if there yet. */ if (uptr->CMD & DSK_SEEKING) { /* see if on cylinder yet */ if (STAR2CYL(uptr->STAR) == STAR2CYL(uptr->CHS)) { /* we are on cylinder, seek is done */ - sim_debug(DEBUG_CMD, dptr, "hsdp_srv seek on cylinder unit=%02x %04x %04x\n", + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv seek on cylinder unit=%02x %04x %04x\n", unit, uptr->STAR >> 16, uptr->CHS >> 16); uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS2 |= (SNS_SEND|SNS_ONC); /* On cylinder & seek done */ /* we have already seeked to the required sector */ /* we do not need to seek again, so move on */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); - return SCPE_OK; +// return SCPE_OK; break; } else { /* we have wasted enough time, we there */ -#ifdef DO_SEEK_AGAIN - /* calculate file position in bytes of requested sector */ - /* file offseet in bytes */ - tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type); - /* just reseek to the location where we will r/w data */ - if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ - sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv Error on seek to %04x\n", tstart); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; - } -#endif /* we are on cylinder, seek is done */ sim_debug(DEBUG_CMD, dptr, "hsdp_srv seek over on cylinder unit=%02x %04x %04x\n", unit, uptr->STAR >> 16, uptr->CHS >> 16); uptr->CHS = uptr->STAR; /* we are there */ - sim_activate(uptr, 10); + sim_activate(uptr, 15); break; } } /* not seeking, so start a new seek */ /* set buf data to current STAR values */ - cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + tcyl = cyl = STAR2CYL(uptr->CHS); /* get current cyl */ buf[0] = (cyl >> 8) & 0xff; /* split cylinder */ buf[1] = cyl & 0xff; buf[2] = (uptr->CHS >> 8) & 0xff; /* get trk/head */ @@ -838,17 +987,28 @@ goout: "hsdp_srv current STAR unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); + if (len > 4) { + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv SEEK bad count unit=%02x count%04x\n", unit, len); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK|STATUS_LENGTH); + break; + } + /* Read in 1-4 character seek code */ for (i = 0; i < 4; i++) { if (chan_read_byte(chsa, &buf[i])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ if (i == 0) { sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv seek error unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_DADE; /* Disc addressing or seek error */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + chp->ccw_count = len; /* restore count, huh? */ return SCPE_OK; break; } @@ -861,6 +1021,7 @@ goout: } } } + chp->ccw_count = len; /* restore count for diag, huh? */ /* else the cyl, trk, and sect are ready to update */ sim_debug(DEBUG_CMD, dptr, "hsdp_srv STAR unit=%02x star %02x %02x %02x %02x\n", @@ -888,8 +1049,12 @@ goout: "hsdp_srv seek ERROR cyl %04x trk %02x sec %02x unit=%02x\n", cyl, trk, buf[3], unit); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; /* set error status */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_DADE; /* set error status */ + uptr->SNS2 |= (SNS_SKER|SNS_SEND); + + /* set new STAR value */ + uptr->CHS = CHS2STAR(cyl, trk, buf[3]); /* we have an error, tell user */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* end command */ @@ -898,6 +1063,7 @@ goout: /* calc the new sector address of data */ /* calculate file position in bytes of requested sector */ + /* file offset in bytes */ tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type); /* set new STAR value using old cyl value */ uptr->CHS = CHS2STAR(STAR2CYL(uptr->CHS), trk, buf[3]); @@ -911,18 +1077,23 @@ goout: sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv Error on seek to %08x\n", tstart); uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; + break; +// return SCPE_OK; } /* Check if already on correct cylinder */ /* if not, do a delay to slow things down */ if (STAR2CYL(uptr->STAR) != STAR2CYL(uptr->CHS)) { + int diff = ((int)tcyl - (int)cyl); + if (diff < 0) + diff = -diff; /* Do a fake seek to kill time */ uptr->CMD |= DSK_SEEKING; /* show we are seeking */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv seek unit=%02x cyl %04x trk %02x sec %02x\n", unit, cyl, trk, buf[3]); sim_activate(uptr, 20); /* start us off */ +// sim_activate(uptr, 20+diff); /* start us off */ } else { /* we are on cylinder/track/sector, so go on */ sim_debug(DEBUG_DETAIL, dptr, @@ -931,15 +1102,16 @@ goout: uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); } - return SCPE_OK; + break; +// return SCPE_OK; - case DSK_XEZ: /* Rezero & Read IPL record */ + case DSK_XEZ: /* 0x37 */ /* Rezero & Read IPL record */ sim_debug(DEBUG_CMD, dptr, "RD REZERO IPL unit=%02x seek 0\n", unit); /* Do a seek to 0 */ uptr->STAR = 0; /* set STAR to 0, 0, 0 */ uptr->CHS = 0; /* set current CHS to 0, 0, 0 */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->CMD |= DSK_SCK; /* show as seek command */ tstart = 0; /* byte offset is 0 */ @@ -948,28 +1120,34 @@ goout: sim_debug(DEBUG_EXP, dptr, "hsdp_srv Error on seek to %04x\n", tstart); uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; + break; +// return SCPE_OK; } /* we are on cylinder/track/sector zero, so go on */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv done seek trk 0\n"); uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); - return SCPE_OK; +// return SCPE_OK; break; - case DSK_LMR: + case DSK_LMR: /* 0x1F */ sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x\n", unit); /* Read in 1 character of mode data */ if (chan_read_byte(chsa, &buf[0])) { + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ; + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; } sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x old %x new %x\n", unit, (uptr->SNS)&0xff, buf[0]); - uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->SNS &= 0x00ffffff; /* clear old mode data */ uptr->SNS |= (buf[0] << 24); /* save mode value */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); @@ -979,24 +1157,37 @@ goout: if ((uptr->CMD & DSK_READING) == 0) { /* see if we are reading data */ uptr->CMD |= DSK_READING; /* read from disk starting */ sim_debug(DEBUG_CMD, dptr, - "DISK READ starting CMD %08x chsa %04x buffer %06x count %04x\n", + "HSDP READ starting CMD %08x chsa %04x buffer %06x count %04x\n", uptr->CMD, chsa, chp->ccw_addr, chp->ccw_count); } if (uptr->CMD & DSK_READING) { /* see if we are reading data */ - cyl = STAR2CYL(uptr->CHS); /* get current cyl */ - trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ - sec = uptr->CHS & 0xff; /* get sec */ /* get sector offset */ -// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)); tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* convert sector number back to chs value to sync disk for diags */ + uptr->CHS = hsdpsec2star(tstart, type); + /* file offset in bytes */ + tstart = tstart * SSB(type); + + /* just seek to the location where we will r/w data */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ + sim_debug(DEBUG_EXP, dptr, "hsdp_srv READ, Error on seek to %04x\n", tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; +// return SCPE_OK; + } + + sim_debug(DEBUG_CMD, dptr, + "HSDP READ reading CMD %08x chsa %04x tstart %04x buffer %06x count %04x\n", + uptr->CMD, chsa, tstart, chp->ccw_addr, chp->ccw_count); /* read in a sector of data from disk */ if ((len=sim_fread(buf, 1, ssize, uptr->fileref)) != ssize) { sim_debug(DEBUG_CMD, dptr, "Error %08x on read %04x of diskfile cyl %04x hds %02x sec %02x\n", - len, ssize, cyl, trk, sec); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + len, ssize, ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -1005,132 +1196,172 @@ goout: "hsdp_srv after READ chsa %04x buffer %06x count %04x\n", chsa, chp->ccw_addr, chp->ccw_count); + uptr->CHS++; /* next sector number */ /* process the next sector of data */ for (i=0; ichan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ sim_debug(DEBUG_DATA, dptr, - "DISK Read %04x bytes leaving %04x from diskfile /%04x/%02x/%02x\n", - i, chp->ccw_count, cyl, trk, sec); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - goto rddone; + "HSDP Read %04x bytes leaving %04x from diskfile /%04x/%02x/%02x\n", + i, chp->ccw_count, ((uptr->CHS)>>16)&0xffff, + ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + return SCPE_OK; } } sim_debug(DEBUG_CMD, dptr, - "DISK READ %04x bytes leaving %4x to be read to %06x from diskfile /%04x/%02x/%02x\n", - ssize, chp->ccw_count, chp->ccw_addr, cyl, trk, sec); + "HSDP READ %04x bytes leaving %4x to be read to %06x from diskfile /%04x/%02x/%02x\n", + ssize, chp->ccw_count, chp->ccw_addr+4, + ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); + + /* get sector offset */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); /* see if we are done reading data */ if (test_write_byte_end(chsa)) { - sim_debug(DEBUG_DATA, dptr, - "DISK Read complete for read from disk @ /%04x/%02x/%02x\n", - STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - break; - } - - /* tstart has file offset in sectors */ - tstart++; /* bump to next sector */ - /* convert sect back to chs value */ - uptr->CHS = hsdpsec2star(tstart, type); - /* see of over end of disk */ - if (tstart >= (uint32)CAP(type)) { /* EOM reached, abort */ - sim_debug(DEBUG_CMD, dptr, - "DISK Read reached EOM for read from disk @ /%04x/%02x/%02x\n", + sim_debug(DEBUG_DATA, dptr, + "HSDP Read complete for read from disk @ /%04x/%02x/%02x\n", STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->CHS = 0; /* reset cylinder position */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } + /* get sector offset */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + + /* see of over end of disk */ + if (tstart >= (uint32)CAP(type)) { + /* EOM reached, abort */ + sim_debug(DEBUG_CMD, dptr, + "HSDP Read reached EOM for read from disk @ /%04x/%02x/%02x\n", + STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->CHS = 0; /* reset cylinder position */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + + /* see if we are done reading data */ + if (test_write_byte_end(chsa)) { + sim_debug(DEBUG_DATA, dptr, + "HSDP Read complete for read from diskfile /%04x/%02x/%02x\n", + STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; + } + sim_debug(DEBUG_DATA, dptr, - "DISK sector read complete, %x bytes to go from diskfile /%04x/%02x/%02x\n", + "HSDP sector read complete, %x bytes to go from diskfile /%04x/%02x/%02x\n", chp->ccw_count, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); - sim_activate(uptr, 10); /* wait to read next sector */ + sim_activate(uptr, 10); /* wait to read next sector */ break; -rddone: - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ } + uptr->CMD &= LMASK; /* remove old status bits & cmd */ break; case DSK_WD: /* Write Data */ if ((uptr->CMD & DSK_WRITING) == 0) { /* see if we are writing data */ uptr->CMD |= DSK_WRITING; /* write to disk starting */ sim_debug(DEBUG_CMD, dptr, - "DISK WRITE starting unit=%02x CMD %02x\n", unit, uptr->CMD); + "HSDP WRITE starting unit=%02x CMD %08x write %04x from %06x to %03x/%02x/%02x\n", + unit, uptr->CMD, chp->ccw_count, chp->ccw_addr, + ((uptr->CHS)>>16)&0xffff, ((uptr->CHS)>>8)&0xff, (uptr->CHS)&0xff); } if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */ - cyl = STAR2CYL(uptr->CHS); /* get current cyl */ - trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ - sec = uptr->CHS & 0xff; /* get sec */ - /* get sector offset */ + /* get sector offset in sectors */ tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* file offset in bytes */ + tstart = tstart * SSB(type); + + /* just seek to the location where we will r/w data */ + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */ + sim_debug(DEBUG_EXP, dptr, "hsdp_srv WRITE, Error on seek to %04x\n", tstart); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + } /* process the next sector of data */ - len = 0; /* used here as a flag for short read */ + tcyl = 0; /* used here as a flag for short read */ for (i=0; ichan_status & STATUS_PCHK) /* test for memory error */ + uptr->SNS |= SNS_INAD; /* invalid address */ /* if error on reading 1st byte, we are done writing */ - if (i == 0) { - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + if ((i == 0) || (chp->chan_status & STATUS_PCHK)) { + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, - "DISK Wrote %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", - ssize, cyl, trk, sec); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - goto wrdone; + "HSDP Wrote %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", + ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + if (chp->chan_status & STATUS_PCHK) /* test for memory error */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + return SCPE_OK; } ch = 0; /* finish out the sector with zero */ - len++; /* show we have no more data to write */ + tcyl++; /* show we have no more data to write */ } buf2[i] = ch; /* save the char */ } + /* get file offset in sectors */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* convert sector number back to chs value to sync disk for diags */ + uptr->CHS = hsdpsec2star(tstart, type); + /* write the sector to disk */ if ((i=sim_fwrite(buf2, 1, ssize, uptr->fileref)) != ssize) { sim_debug(DEBUG_CMD, dptr, "Error %08x on write %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", - i, ssize, cyl, trk, sec); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + i, ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } - if (len != 0) { /* see if done with write command */ + + uptr->CHS++; /* next sector number */ + if (tcyl != 0) { /* see if done with write command */ sim_debug(DEBUG_DATA, dptr, - "DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", - ssize, cyl, trk, sec); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + "HSDP WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", + ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; } sim_debug(DEBUG_CMD, dptr, - "DISK WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x\n", - len, ssize, cyl, trk, sec); + "HSDP WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x\n", + len, ssize, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); - /* tstart has file offset in sectors */ - tstart++; /* bump to next sector */ - /* convert sect back to chs value */ - uptr->CHS = hsdpsec2star(tstart, type); - /* see of over end of disk */ + /* get sector offset */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + + /* see if over end of disk */ if (tstart >= (uint32)CAP(type)) { /* EOM reached, abort */ sim_debug(DEBUG_CMD, dptr, - "DISK Write reached EOM for write to disk @ /%04x/%02x/%02x\n", + "HSDP Write reached EOM for write to disk @ /%04x/%02x/%02x\n", STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->CHS = 0; /* reset cylinder position */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } sim_activate(uptr, 10); /* keep writing */ break; -wrdone: - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ } + uptr->CMD &= LMASK; /* remove old status bits & cmd */ break; case DSK_RSL: /* RSL 0x32 */ @@ -1140,100 +1371,128 @@ wrdone: for (i = 0; i < 30; i++) buf[i] = 0; - /* the dmap pointer is placed by the vendor or diag into the */ - /* track zero label in word 3 of the 30 byte label. */ - /* The disk address is the last track of the user area. The vendor */ - /* reserves the last cylinder, SEL diags reserve the next two, so the */ - /* addr is CYL-4/HDS-1/0 and is VDT. The UTX/MPX media table is on */ - /* previous track, so MDT = VDT-SPT is CYL-4/HDS-2/0 */ - /* The UTX flaw map is at DMAP = MDT-SPT CYL-4/HDS-3/0 */ - /* UTX media map is 1 track lower at UMAP=DMAP-SPT CYL-4/HDS-4/0 */ - /* The UTX med map is pointed to by sector label 1 */ - /* simulate pointers here, set wd[3] in label to VDT */ + len = chp->ccw_count; /* get number of sectors per track */ - /* get physical sector address of media defect table */ - /* VDT 286965 (819/9/0) 0x460f5 for 8887 - 823/10/35 */ - /* DMAP 286930 (819/8/0) 0x460d2 for 8887 - 823/10/35 Trk 0 ptr */ - /* UMAP 286895 (819/7/0) 0x460af for 8887 - 823/10/35 */ + /* read a 30 byte track label for each sector on track */ + /* for 16 sectors per track, that is 480 bytes */ + /* for 20 sectors per track, that is 600 bytes */ + for (j=0; jCHS, SPT(type), SPC(type)); + /* convert sector number back to chs value to sync disk for diags */ + uptr->CHS = hsdpsec2star(tstart, type); - sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd RSL STAR %08x disk geom %08x\n", - uptr->CHS, GEOM(type)); + /* the dmap pointer is placed by the vendor or diag into the */ + /* track zero label in word 3 of the 30 byte label. */ + /* The disk address is the last track of the user area. The vendor */ + /* reserves the last cylinder, SEL diags reserve the next two, so the */ + /* addr is CYL-4/HDS-1/0 and is VDT. The UTX/MPX media table is on */ + /* previous track, so MDT = VDT-SPT is CYL-4/HDS-2/0 */ + /* The UTX flaw map is at DMAP = MDT-SPT CYL-4/HDS-3/0 */ + /* UTX media map is 1 track lower at UMAP=DMAP-SPT CYL-4/HDS-4/0 */ + /* The UTX med map is pointed to by sector label 1 */ + /* simulate pointers here, set wd[3] in label to VDT */ - /* set buf data to current STAR values */ - cyl = STAR2CYL(uptr->CHS); /* get current cyl */ - buf[0] = (cyl >> 8) & 0xff; /* split cylinder */ - buf[1] = cyl & 0xff; - buf[2] = (uptr->CHS >> 8) & 0xff; /* get trk/head */ - buf[3] = uptr->CHS & 0xff; /* get sec */ - buf[4] = 0x80; /* set lflg1 to show good sector */ + /* get physical sector address of media defect table */ + /* VDT 286965 (819/9/0) 0x460f5 for 8887 - 823/10/35 */ + /* DMAP 286930 (819/8/0) 0x460d2 for 8887 - 823/10/35 Trk 0 ptr */ + /* UMAP 286895 (819/7/0) 0x460af for 8887 - 823/10/35 */ - sim_debug(DEBUG_CMD, dptr, - "hsdp_srv RSL unit=%0x2x star %02x %02x %02x %02x\n", - unit, buf[0], buf[1], buf[2], buf[3]); + /* get logical sector address of media defect table */ + /* VDT 278766 (819/9/0) 0x440ee for 8887 - 823/10/34 */ + /* DMAP 278732 (819/8/0) 0x440cc for 8887 - 823/10/34 */ + /* UMAP 278698 (819/7/0) 0x440aa for 8887 - 823/10/34 Sec 0 ptr */ - /* get physical sector address of UMAP */ - /* UMAP 278698 (819/7/0) 0x440aa for 8887 - 823/10/34 Sec 0 ptr */ - tstart = ((CYL(type)-4) * SPC(type)) + - ((HDS(type)-3) * (SPT(type))); + sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd RSL STAR %08x disk geom %08x\n", + uptr->CHS, GEOM(type)); - /* get physical sector address of UMAP */ - sim_debug(DEBUG_CMD, dptr, - "hsdp_srv SL1 RSL sector %d %x star %02x %02x %02x %02x\n", - tstart, tstart, buf[0], buf[1], buf[2], buf[3]); + /* set buf data to current STAR values */ + cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + buf[0] = (cyl >> 8) & 0xff; /* split cylinder */ + buf[1] = cyl & 0xff; + buf[2] = (uptr->CHS >> 8) & 0xff; /* get trk/head */ + buf[3] = uptr->CHS & 0xff; /* get sec */ + buf[4] = 0x80; /* set lflg1 to show good sector */ - /* on HSDP DMAP is in wd 3 on label 0 */ - /* on HSDP UMAP is in wd 4 on label 1 */ - /* UMAP 278698 (819/7/0) 0x440aa for 8887 - 823/10/34 Sec 0 ptr */ - tstart = (tstart * (SPT(type)-1))/SPT(type); /* make logical */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv RSL unit=%0x2x star %02x %02x %02x %02x\n", + unit, buf[0], buf[1], buf[2], buf[3]); - /* the address must be logical for HSDP */ - /* store into sec 1 label */ - buf[12] = (tstart >> 24) & 0xff; /* UMAP pointer */ - buf[13] = (tstart >> 16) & 0xff; - buf[14] = (tstart >> 8) & 0xff; - buf[15] = (tstart) & 0xff; + /* get physical sector address of UMAP */ + /* UMAP 278698 (819/7/0) 0x440aa for 8887 - 823/10/34 Sec 0 ptr */ + tstart = ((CYL(type)-4) * SPC(type)) + + ((HDS(type)-3) * (SPT(type))); - buf[16] = (tstart >> 24) & 0xff; /* UMAP pointer too */ - buf[17] = (tstart >> 16) & 0xff; - buf[18] = (tstart >> 8) & 0xff; - buf[19] = (tstart) & 0xff; + /* get physical sector address of UMAP */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv SL1 RSL sector %d %x star %02x %02x %02x %02x\n", + tstart, tstart, buf[0], buf[1], buf[2], buf[3]); - /* the tech doc shows the cyl/trk/sec data is in the first 4 bytes */ - /* of the track label, BUT it is really in the configuration data */ - /* area are too. That is where UTX looks. Byte 27 is sectors/track */ - /* and byte 28 is number of heads. Byte 25 is copy of byte 27. */ - buf[25] = hsdp_type[type].spt & 0xff; /* sect per track 35 */ + /* on HSDP DMAP is in wd 3 on label 0 */ + /* on HSDP UMAP is in wd 4 on label 1 */ + /* UMAP 278698 (819/7/0) 0x440aa for 8887 - 823/10/34 Sec 0 ptr */ + tstart = (tstart * (SPT(type)-1))/SPT(type); /* make logical */ - /* UTX looks at bit 6 & 7 to determine if UDP or HSDP controller */ - /* The UDP/DPII controllers do not use these bits, so UTX keys */ - /* on these bits to determine type of controller. Bit 31 is set */ - /* for a HSDP and not set for the UDP/DPII. MPX has this bit cleared. */ - buf[26] = hsdp_type[type].type | 1; /* mode data is 0x41 */ - buf[27] = hsdp_type[type].spt & 0xff; /* sec per track 35 */ - buf[28] = hsdp_type[type].nhds & 0xff; /* num heads 10 */ + /* the address must be logical for HSDP */ + /* store into sec 1 label */ + buf[12] = (tstart >> 24) & 0xff; /* UMAP pointer */ + buf[13] = (tstart >> 16) & 0xff; + buf[14] = (tstart >> 8) & 0xff; + buf[15] = (tstart) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "Sector 1 label"); - /* now write sector label data */ - for (i = 0; i < 30; i++) { - if (chan_write_byte(chsa, &buf[i])) { - /* we have write error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; + /* diags want these values to be zero for all others*/ + if (uptr->CHS == 1) { /* test for sec 1, trk 0, cyl 0 */ + buf[16] = (tstart >> 24) & 0xff; /* UMAP pointer */ + buf[17] = (tstart >> 16) & 0xff; + buf[18] = (tstart >> 8) & 0xff; + buf[19] = (tstart) & 0xff; + } else { + buf[16] = 0; /* UMAP pointer */ + buf[17] = 0; + buf[18] = 0; + buf[19] = 0; } - if (i == 16) - sim_debug(DEBUG_DETAIL, dptr, "\nSector 1 label"); - sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + + /* the tech doc shows the cyl/trk/sec data is in the first 4 bytes */ + /* of the track label, BUT it is really in the configuration data */ + /* area are too. That is where UTX looks. Byte 27 is sectors/track */ + /* and byte 28 is number of heads. Byte 25 is copy of byte 27. */ + buf[25] = hsdp_type[type].spt & 0xff; /* sect per track 35 */ + + /* UTX looks at bit 6 & 7 to determine if UDP or HSDP controller */ + /* The UDP/DPII controllers do not use these bits, so UTX keys */ + /* on these bits to determine type of controller. Bit 31 is set */ + /* for a HSDP and not set for the UDP/DPII. MPX has this bit cleared. */ + buf[26] = hsdp_type[type].type | 1; /* mode data is 0x41 */ + buf[27] = hsdp_type[type].spt & 0xff; /* sec per track 35 */ + buf[28] = hsdp_type[type].nhds & 0xff; /* num heads 10 */ + + sim_debug(DEBUG_DETAIL, dptr, "Sector 1 label"); + /* now write sector label data */ + for (i = 0; i < 30; i++) { + if (chan_write_byte(chsa, &buf[i])) { + /* we have write error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (i == 16) + sim_debug(DEBUG_DETAIL, dptr, "\nSector 1 label"); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + /* leave STAR "unnormalized" for diags */ + uptr->CHS++; /* bump to next track */ + len -= 30; /* count 1 sector label size */ + if (len > 0) + continue; + break; /* done */ } - sim_debug(DEBUG_DETAIL, dptr, "\n"); /* command done */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd RSL done chsa %04x count %04x completed\n", chsa, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ @@ -1247,6 +1506,11 @@ wrdone: for (i = 0; i < 30; i++) buf[i] = 0; + /* get file offset in sectors */ + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* convert sector number back to chs value to sync disk for diags */ + uptr->CHS = hsdpsec2star(tstart, type); + /* set buf data to current CHS values */ if (uptr->CHS == 0) { /* write last address on trk 0 */ cyl = CYL(type)-1; /* lcyl cyl upper 8 bits */ @@ -1354,7 +1618,7 @@ wrdone: for (i = 0; i < 30; i++) { if (chan_write_byte(chsa, &buf[i])) { /* we have write error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -1364,8 +1628,11 @@ wrdone: } sim_debug(DEBUG_DETAIL, dptr, "\n"); + /* leave STAR "unnormalized" for diags */ + uptr->CHS += 0x10; /* bump to next track */ + /* command done */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd RTL done chsa %04x count %04x completed\n", chsa, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ @@ -1374,7 +1641,7 @@ wrdone: default: sim_debug(DEBUG_CMD, dptr, "invalid command %02x unit %02x\n", cmd, unit); uptr->SNS |= SNS_CMDREJ; - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ return SNS_CHNEND|STATUS_PCHK; break; } @@ -1393,7 +1660,6 @@ void hsdp_ini(UNIT *uptr, t_bool f) uptr->CHS = 0; /* set CHS to cyl/hd/sec = 0 */ uptr->STAR = 0; /* set STAR to cyl/hd/sec = 0 */ uptr->CMD &= LMASK; /* clear out the flags but leave ch/sa */ -// uptr->SNS = ((uptr->SNS & MASK24) | (hsdp_type[i].type << 24)); /* save mode value */ /* total sectors on disk */ uptr->capac = CAP(i); /* size in sectors */ @@ -1618,7 +1884,7 @@ int hsdp_format(UNIT *uptr) { fprintf (stderr, "Error on seek to 0\r\n"); return 1; } - return 0; + return SCPE_OK; } /* attach the selected file to the disk */ @@ -1652,7 +1918,7 @@ t_stat hsdp_attach(UNIT *uptr, CONST char *file) if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ detach_unit(uptr); /* if no space, error */ - return SCPE_FMT; /* error */ + return SCPE_UNATT; /* error */ } /* see if there is any data on sector zero of disk, if not format it */ @@ -1710,7 +1976,7 @@ fmt: /* detach a disk device */ t_stat hsdp_detach(UNIT *uptr) { uptr->SNS = 0; /* clear sense data */ - uptr->CMD &= ~0xffff; /* no cmd and flags */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ return detach_unit(uptr); /* tell simh we are done with disk */ } @@ -1725,11 +1991,11 @@ t_stat hsdp_boot(int32 unit_num, DEVICE * dptr) { GET_UADDR(uptr->CMD)); return SCPE_UNATT; /* attached? */ } - SPAD[0xf4] = GET_UADDR(uptr->CMD); /* put boot device chan/sa into spad */ SPAD[0xf8] = 0xF000; /* show as F class device */ /* now boot the disk */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ return chan_boot(GET_UADDR(uptr->CMD), dptr); /* boot the ch/sa */ } diff --git a/SEL32/sel32_mt.c b/SEL32/sel32_mt.c index a7d0301..173abc8 100644 --- a/SEL32/sel32_mt.c +++ b/SEL32/sel32_mt.c @@ -620,7 +620,8 @@ t_stat mt_srv(UNIT *uptr) case MT_SENSE: /* 0x04 */ /* get sense data */ /* write requested status */ len = chp->ccw_count; /* command count */ - for (i=0; iSNS >> (24-(i*8))) & 0xff; /* get 8 bits of status */