From 7e3d17ef2cd3f3a694c807bf1cd9c868fcc52ec1 Mon Sep 17 00:00:00 2001 From: AZBevier Date: Mon, 17 Feb 2020 12:45:22 -0700 Subject: [PATCH] SEL32: Update console device to pass SEL diags. SEL32: Update disk devices to hold current STAR in UNIT structure. SEL32: Add new disk geometry macros. SEL32: Revise disk formatting support for UTX. SEL32: Revise INCH command support for all devices. --- SEL32/sel32_chan.c | 488 +++++++++++++++++---------- SEL32/sel32_clk.c | 2 +- SEL32/sel32_com.c | 2 +- SEL32/sel32_con.c | 193 +++++++---- SEL32/sel32_cpu.c | 84 +++-- SEL32/sel32_defs.h | 4 +- SEL32/sel32_disk.c | 738 ++++++++++++++++++----------------------- SEL32/sel32_fltpt.c | 2 +- SEL32/sel32_hsdp.c | 782 +++++++++++++++++++++----------------------- SEL32/sel32_iop.c | 99 +++--- SEL32/sel32_lpr.c | 7 +- SEL32/sel32_mt.c | 161 +++++---- SEL32/sel32_scfi.c | 607 ++++++++++++++++------------------ SEL32/sel32_sys.c | 2 +- 14 files changed, 1630 insertions(+), 1541 deletions(-) diff --git a/SEL32/sel32_chan.c b/SEL32/sel32_chan.c index 6753980..f4e0627 100644 --- a/SEL32/sel32_chan.c +++ b/SEL32/sel32_chan.c @@ -1,6 +1,6 @@ /* sel32_chan.c: SEL 32 Channel functions. - Copyright (c) 2018, James C. Bevier + Copyright (c) 2018-2020, James C. Bevier Portions provided by Richard Cornwell and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a @@ -119,6 +119,7 @@ t_stat rsctlxio(uint16 chsa, uint32 *status); /* reset controller XIO */ uint32 find_int_icb(uint16 chsa); uint32 find_int_lev(uint16 chsa); uint32 scan_chan(int *ilev); +t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */ t_stat chan_boot(uint16 chsa, DEVICE *dptr); t_stat chan_set_devs(); t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); @@ -167,6 +168,53 @@ int FIFO_Get(uint16 chsa, uint32 *old) return 0; /* all OK */ } +/* Set INCH buffer address for channel */ +/* return SCPE_OK or SCPE_MEM if invalid address or SCPE_ARG if already defined */ +t_stat set_inch(UNIT *uptr, uint32 inch_addr) { + uint16 chsa = GET_UADDR(uptr->u3); /* get channel & sub address */ + uint32 chan = chsa & 0x7f00; /* get just channel address */ + CHANP *pchp = find_chanp_ptr(chan); /* get channel channel prog ptr */ + DIB *dibp; /* get DIB pointer for channel */ + CHANP *chp; + int i; + + sim_debug(DEBUG_XIO, &cpu_dev, + "set_inch chan %04x inch addr %06x\n", chan, inch_addr); + + /* must be valid channel pointer */ + if (pchp == NULL) + return SCPE_MEM; /* return memory error */ + + /* see if valid memory address */ + if (inch_addr >= (MEMSIZE*4)) /* see if mem addr >= MEMSIZE */ + return SCPE_MEM; /* return memory error */ + +#ifdef NOT_YET + /* see if inch_addr is already defined */ + if (pchp->chan_inch_addr != 0) + return SCPE_ARG; /* inch already defined */ +#endif + + /* set parent */ + pchp->chan_inch_addr = inch_addr; /* set the inch addr */ + + /* now go through all the sub addresses for the channel and set inch addr */ + for (i=0; i<256; i++) { + chsa = chan | i; /* merge sa to real channel */ + dibp = dev_unit[chsa]; /* get the device information pointer */ + if (dibp == 0) + continue; /* must have a DIB, so not used */ + chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + if (chp == 0) + continue; /* not used */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "set_inch2 chsa %04x inch addr %06x\n", chsa, inch_addr); + /* set the inch buffer addr */ + chp->chan_inch_addr = inch_addr; /* set inch buffer address */ + } + return SCPE_OK; /* All OK */ +} + /* Find interrupt level for the given device (ch/sa) */ /* return 0 if not found, otherwise level number */ uint32 find_int_lev(uint16 chsa) @@ -297,13 +345,18 @@ CHANP *find_chanp_ptr(uint16 chsa) int readfull(CHANP *chp, uint32 maddr, uint32 *word) { maddr &= MASK24; /* mask addr to 24 bits */ - if (maddr > (MEMSIZE*4)) { /* see if mem addr > MEMSIZE */ + if (maddr >= (MEMSIZE*4)) { /* see if mem addr >= MEMSIZE */ chp->chan_status |= STATUS_PCHK; /* program check error */ sim_debug(DEBUG_EXP, &cpu_dev, "readfull read %08x from addr %08x ERROR\n", *word, maddr<<2); return 1; /* show we have error */ } +#define TEST +#ifdef TEST maddr >>= 2; /* get 32 bit word index */ *word = M[maddr]; /* get the contents */ +#else + *word = RMW(maddr&MASK24); /* get 1 word */ +#endif sim_debug(DEBUG_EXP, &cpu_dev, "READFULL read %08x from addr %08x\n", *word, maddr<<2); return 0; /* return OK */ } @@ -318,16 +371,21 @@ int readbuff(CHANP *chp) uint32 addr = chp->ccw_addr; /* channel buffer address */ uint16 chan = get_chan(chp->chan_dev); /* our channel */ - if ((addr & MASK24) > (MEMSIZE*4)) { /* see if memory address invalid */ + if ((addr & MASK24) >= (MEMSIZE*4)) { /* see if memory address invalid */ chp->chan_status |= STATUS_PCHK; /* bad, program check */ chp->chan_byte = BUFF_CHNEND; /* force channel end */ irq_pend = 1; /* and we have an interrupt */ return 1; /* done, with error */ } +#ifdef TEST addr &= MASK24; /* address only */ addr >>= 2; /* byte to word address */ chp->chan_buf = M[addr]; /* get 4 bytes */ +#else + chp->chan_buf = RMB(addr&MASK24); /* get 1 byte */ +#endif +#ifdef TEST sim_debug(DEBUG_DETAIL, &cpu_dev, "readbuff read memory bytes into buffer %02x %06x %06x %04x [", chan, chp->ccw_addr & 0xFFFFFC, chp->chan_buf, chp->ccw_count); for(k = 24; k >= 0; k -= 8) { @@ -337,6 +395,7 @@ int readbuff(CHANP *chp) sim_debug(DEBUG_DETAIL, &cpu_dev, "%c", ch); } sim_debug(DEBUG_DETAIL, &cpu_dev, "]\n"); +#endif return 0; } @@ -348,7 +407,7 @@ int writebuff(CHANP *chp) { uint32 addr = chp->ccw_addr; - if ((addr & MASK24) > (MEMSIZE*4)) { + if ((addr & MASK24) >= (MEMSIZE*4)) { chp->chan_status |= STATUS_PCHK; sim_debug(DEBUG_DETAIL, &cpu_dev, "writebuff PCHK addr %08x to big mem %08x status %04x\n", @@ -361,7 +420,11 @@ int writebuff(CHANP *chp) sim_debug(DEBUG_DETAIL, &cpu_dev, "writebuff WRITE addr %06x DATA %08x status %04x\n", addr, chp->chan_buf, chp->chan_status); +#ifdef TEST M[addr>>2] = chp->chan_buf; +#else + WMB(addr, chp->chan_buf); /* write byte to bebory */ +#endif return 0; } @@ -371,10 +434,10 @@ int writebuff(CHANP *chp) int load_ccw(CHANP *chp, int tic_ok) { uint32 word; +// uint8 devstat; int docmd = 0; - UNIT *uptr; + UNIT *uptr = find_unit_ptr(chp->chan_dev); /* find the unit pointer */ uint16 chan = get_chan(chp->chan_dev); /* our channel */ - CHANP *pchp; loop: sim_debug(DEBUG_XIO, &cpu_dev, @@ -403,14 +466,6 @@ loop: sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw read ccw chan %02x caw %06x IOCD wd 1 %08x\n", chan, chp->chan_caw, word); - sim_debug(DEBUG_XIO, &cpu_dev, - "load_ccw read data @ IOCD wd 1 %08x data wd 1 %08x\n", - word, M[(word & 0xffffff)>>2]); - -#ifdef DO_DYNAMIC_DEBUG - if ((M[(word & 0xffffff)>>2]) == 0x440a0d61) - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif /* TIC can't follow TIC or be first in command chain */ if (((word >> 24) & 0xf) == CMD_TIC) { @@ -420,7 +475,8 @@ loop: goto loop; /* restart the IOCD processing */ } chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ - sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); irq_pend = 1; /* status pending */ return 1; /* error return */ } @@ -430,20 +486,68 @@ loop: if ((chp->ccw_flags & FLAG_DC) == 0) { chp->ccw_cmd = (word >> 24) & 0xff; /* not DC, so set command from IOCD wd 1 */ sim_debug(DEBUG_XIO, &cpu_dev, - "load_ccw No DC, flags %04x cmd %02x\n", chp->ccw_flags, chp->ccw_cmd); + "load_ccw No DC, flags %04x cmd %02x\n", + chp->ccw_flags, chp->ccw_cmd); docmd = 1; /* show we have a command */ } + /* Set up for this command */ /* make a 24 bit address */ chp->ccw_addr = word & MASK24; /* set the data address */ - readfull(chp, chp->chan_caw, &word); /* get IOCD WD 2 */ + if (readfull(chp, chp->chan_caw, &word) != 0) { /* read word from memory */ + chp->chan_status |= STATUS_PCHK; /* memory read error, program check */ + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw data addr ERROR chan_status[%04x] %04x\n", + chan, chp->chan_status); + return 1; /* error return */ + } - sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw read ccw chan %02x caw %06x IOCD wd 2 %08x\n", + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw read ccw chan %02x caw %06x IOCD wd 2 %08x\n", chan, chp->chan_caw, word); chp->chan_caw += 4; /* next IOCD address */ chp->ccw_count = word & 0xffff; /* get 16 bit byte count from IOCD WD 2*/ - chp->ccw_flags = (word >> 16) & 0xffff; /* get flags from bits 0-7 of WD 2 of IOCD */ chp->chan_byte = BUFF_EMPTY; /* no bytes transferred yet */ + +#ifdef INVALID_FOR_INCH + /* see if buffer count 0 or < 0x8000 */ + /* diags want the count from IOCD2 in status */ + if (chp->ccw_count == 0) { /* see if count is zero */ + chp->chan_status |= STATUS_PCHK; /* program check error */ + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw excess data count %08x ERROR chan_status[%04x] %04x\n", + chp->ccw_count, chan, chp->chan_status); + irq_pend = 1; /* status pending */ + return 1; /* show we have error */ + } +#endif + + /* only test if non tic command */ + if ((chp->ccw_cmd & 0xFF) != CMD_TIC) { + /* see if buffer address is in real memory */ + /* diags want the count from IOCD2 in status */ + if (chp->ccw_addr >= (MEMSIZE*4)) { /* see if mem addr >= MEMSIZE */ + chp->chan_status |= STATUS_PCHK; /* program check error */ + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw data start addr %08x ERROR chan_status[%04x] %04x\n", + chp->ccw_addr, chan, chp->chan_status); + irq_pend = 1; /* status pending */ + return 1; /* show we have error */ + } + + /* see if buffer end address is in real memory */ + /* diags want the count from IOCD2 in status */ + if ((chp->ccw_addr + chp->ccw_count) > (MEMSIZE*4)) { /* see if mem addr > MEMSIZE */ + chp->chan_status |= STATUS_PCHK; /* program check error */ + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw data end addr %08x ERROR chan_status[%04x] %04x\n", + chp->ccw_addr, chan, chp->chan_status); + irq_pend = 1; /* status pending */ + return 1; /* show we have error */ + } + } + + chp->ccw_flags = (word >> 16) & 0xffff; /* 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 */ @@ -452,6 +556,7 @@ loop: sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw read docmd %02x irq_flag %04x count %04x chan %04x ccw_flags %04x\n", docmd, irq_pend, chp->ccw_count, chan, chp->ccw_flags); + /* LPR sends CC cmd only without data addr/count */ #ifdef HACK_FOR_LPR /* Check invalid count */ @@ -462,61 +567,29 @@ loop: } #endif if (docmd) { /* see if we need to process command */ +// DEVICE *dptr = get_dev(uptr); /* find the device from unit pointer */ DIB *dibp = dev_unit[chp->chan_dev]; /* get the device pointer */ uptr = find_unit_ptr(chp->chan_dev); /* find the unit pointer */ if (uptr == 0) return 1; /* if none, error */ -#ifdef DO_DYNAMIC_DEBUG -// if ((chp->chan_dev == 0x1000) && ((chp->ccw_cmd & 0xff) == 0x80)) { -// if ((chp->chan_dev == 0x0800) && ((chp->ccw_cmd & 0xff) == 0x04) && -// (chp->ccw_count == 0x0e)) { - if ((chp->chan_dev == 0x0800) && ((chp->ccw_cmd & 0xff) == 0xff)) - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); - if ((chp->chan_dev == 0x0800) && ((chp->ccw_cmd & 0xff) == 0x00) && - (chp->ccw_count == 0x24)) { - uint32 addr = chp->ccw_addr; /* set the data address */ - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -// sim_debug(DEBUG_CMD, &cpu_dev, "cmd 80 MT wds @ addr %08x %08x %08x %08x %08x\n", - sim_debug(DEBUG_CMD, &cpu_dev, "cmd 04 DP wds @ addr %08x %08x %08x %08x %08x\n", - addr, M[addr>>2], M[(addr+4)>>2], M[(addr+8)>>2], M[(addr+12)>>2]); - } -#endif -#ifndef CON_BUG -#ifdef DO_DYNAMIC_DEBUG -// if ((chp->chan_dev == 0x7efc) && ((chp->ccw_cmd & 0xff) == 0x03) && (chp->ccw_count == 0)) - if ((chp->chan_dev == 0x0800) && ((chp->ccw_cmd & 0xff) == 0x00) && (chp->ccw_count == 0x24)) - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif -#endif - /* Check if this is INCH command */ - if ((chp->ccw_cmd & 0xFF) == 0) { /* see if this is an initialize channel cmd */ - uptr->u4 = (uint32)chp->ccw_addr; /* save the memory address in wd 1 of iocd */ - if ((chp->ccw_count&0xffff) == 0) /* see if user said 0 count for INCH */ - uptr->us9 = 1; /* make non zero for later test */ - else - uptr->us9 = chp->ccw_count & 0xffff; /* get count from IOCD wd 2 */ - /* just drop through and call the device startcmd function */ - /* the INCH buffer will be returned in uptr->u4 and uptr->us9 will be non-zero */ - /* it should just return SNS_CHNEND and SNS_DEVEND status */ -/*052619*/ chp->chan_inch_addr = uptr->u4; /* save INCH buffer address */ - pchp = find_chanp_ptr(chp->chan_dev&0x7f00); /* get parent channel prog pointer */ -/*091119*/ pchp->chan_inch_addr = uptr->u4; /* save INCH buffer address */ - sim_debug(DEBUG_XIO, &cpu_dev, - "load_ccw INCH buffer save %08x chan %04x status %04x count %04x\n", - uptr->u4, chan, chp->chan_status, chp->ccw_count); - } + sim_debug(DEBUG_XIO, &cpu_dev, + "load_ccw before start_cmd chan %04x status %04x count %04x\n", +// chan, chp->chan_status, chp->ccw_count, dptr->name); + chan, chp->chan_status, chp->ccw_count); - sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw before start_cmd chan %04x status %04x count %04x\n", - chan, chp->chan_status, chp->ccw_count); - - /* call the device startcmd function to process command */ + /* call the device startcmd function to process the current command */ +#ifndef TRY_THIS_TUESDAY chp->chan_status = dibp->start_cmd(uptr, chan, chp->ccw_cmd); +#else + /* just replace device status bits */ + devstat = dibp->start_cmd(uptr, chan, chp->ccw_cmd); + chp->chan_status = (chp->chan_status & 0xffffff00) | (devstat & 0xff); +#endif - sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw after start_cmd chan %04x status %08x count %04x\n", - chan, chp->chan_status, chp->ccw_count); + sim_debug(DEBUG_XIO, &cpu_dev, + "load_ccw after start_cmd chan %04x status %08x count %04x\n", + chan, chp->chan_status, chp->ccw_count); /* see if bad status */ if (chp->chan_status & (STATUS_ATTN|STATUS_CHECK|STATUS_EXPT)) { @@ -524,30 +597,12 @@ loop: chp->ccw_flags = 0; /* no flags */ chp->ccw_cmd = 0; /* stop IOCD processing */ irq_pend = 1; /* int coming */ - sim_debug(DEBUG_CMD, &cpu_dev, "load_ccw bad status chan %04x status %04x\n", + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw bad status chan %04x status %04x\n", chan, chp->chan_status); return 1; /* error return */ } -#ifndef TRY_THIS - /* INCH cmd will return here too, get INCH buffer addr from uptr->u4 */ - /* see if this is an initialize channel cmd */ - if ((chp->ccw_cmd & 0xFF) == 0 && (uptr->us9 != 0)) { -/// if ((chp->ccw_cmd & 0xFF) == 0 && (uptr->us9 >= 0)) { - chp->chan_inch_addr = uptr->u4; /* save INCH buffer address */ - pchp = find_chanp_ptr(chp->chan_dev&0x7f00); /* get parent channel prog pointer */ - pchp->chan_inch_addr = uptr->u4; /* save INCH buffer address */ - chp->chan_status &= STATUS_DEND; /* inch has only channel end status */ - sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw INCH %08x saved chan %04x\n", - chp->chan_inch_addr, chan); -#ifdef DO_DYNAMIC_DEBUG - if (chp->chan_inch_addr == 0x8580) - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif - } -#endif - /* see if command completed */ if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { chp->chan_status |= STATUS_CEND; /* set channel end status */ @@ -559,7 +614,8 @@ loop: chan, chp->chan_status, chp->ccw_count); } } - sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw return, chan %04x status %04x count %04x irq %02x\n", + sim_debug(DEBUG_XIO, &cpu_dev, + "load_ccw return, chan %04x status %04x count %04x irq %02x\n", chan, chp->chan_status, chp->ccw_count, irq_pend); return 0; /* good return */ } @@ -582,11 +638,12 @@ int chan_read_byte(uint16 chsa, uint8 *data) if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if Data Chain */ chp->chan_status |= STATUS_CEND; /* no, end of data */ chp->chan_byte = BUFF_CHNEND; /* buffer end too */ - sim_debug(DEBUG_DATA, &cpu_dev, "chan_read_byte end status %04x\n", chp->chan_status); + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_read_byte no DC chan end, cnt %04x addr %06x chan %04x\n", + chp->ccw_count, chp->ccw_addr, chan); return 1; /* return error */ } else { /* we have data chaining, process iocl */ - sim_debug(DEBUG_DATA, &cpu_dev, "chan_read_byte calling load_ccw chan %04x\n", chan); if (load_ccw(chp, 1)) /* process data chaining */ return 1; /* return error */ } @@ -594,13 +651,24 @@ int chan_read_byte(uint16 chsa, uint8 *data) if (chp->chan_byte == BUFF_EMPTY) { /* is buffer empty? */ if (readbuff(chp)) /* read next 4 chars */ return 1; /* return error */ +#ifdef TEST chp->chan_byte = chp->ccw_addr & 0x3; /* get byte number from address */ chp->ccw_addr += 4 - chp->chan_byte; /* next byte address */ +#else + chp->chan_byte = 0; /* show that we have data byte */ + chp->ccw_addr += 1; /* next byte address */ +#endif } chp->ccw_count--; /* one char less to process */ /* get the byte of data */ +#ifdef TEST byte = (chp->chan_buf >> (8 * (3 - (chp->chan_byte & 0x3)))) & 0xff; chp->chan_byte++; /* next byte offset in word */ +#else + /* get the byte of data */ + byte = chp->chan_buf; /* read byte from memory */ + chp->chan_byte = BUFF_EMPTY; /* buffer empty too */ +#endif *data = byte; /* return the data */ sim_debug(DEBUG_DATA, &cpu_dev, "chan_read_byte transferred %02x\n", byte); return 0; /* good return */ @@ -642,30 +710,35 @@ int chan_write_byte(uint16 chsa, uint8 *data) /* see if at end of buffer */ if (chp->chan_byte == BUFF_CHNEND) { - sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte BUFF_CHNEND\n"); + sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte BUFF_CHNEND\n"); /* if SLI not set, we have incorrect length */ if ((chp->ccw_flags & FLAG_SLI) == 0) { - sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte 4 setting SLI ret\n"); + sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte 4 setting SLI ret\n"); chp->chan_status |= STATUS_LENGTH; /* set SLI */ } return 1; /* return error */ } if (chp->ccw_count == 0) { - sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_byte ccw_count is zero ccw_count[%04x] %04x\n", - chan, chp->ccw_count); + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_write_byte ZERO ccw_count[%04x] %04x addr %06x\n", + chan, chp->ccw_count, chp->ccw_addr); if (chp->chan_byte & BUFF_DIRTY) { - sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte 2 BUF DIRTY ret\n"); + sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte 2 BUF DIRTY ret\n"); if (writebuff(chp)) /* write it */ return 1; /* return error */ +#ifndef TEST + chp->chan_byte = BUFF_EMPTY; /* no data now */ +#endif } if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if we have data chaining */ - sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte no DC\n"); + sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte no DC\n"); chp->chan_status |= STATUS_CEND; /* no, end of data */ chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ return 1; /* return error */ } else { /* we have data chaining, process iocl */ - sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte calling load_ccw chan %04x\n", chan); + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_write_byte got DC, calling load_ccw chan %04x\n", chan); if (load_ccw(chp, 1)) /* process data chaining */ return 1; /* return error */ } @@ -687,12 +760,20 @@ int chan_write_byte(uint16 chsa, uint8 *data) if (writebuff(chp)) return 1; sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte BUF EMPTY|DIRTY ret\n"); +#ifdef TEST if ((chp->ccw_cmd & 0xff) == CMD_RDBWD) chp->ccw_addr -= (1 + (chp->ccw_addr & 0x3)); else chp->ccw_addr += (4 - (chp->ccw_addr & 0x3)); +#else + if ((chp->ccw_cmd & 0xff) == CMD_RDBWD) + chp->ccw_addr -= 1; + else + chp->ccw_addr += 1; +#endif chp->chan_byte = BUFF_EMPTY; } +#ifdef TEST if (chp->chan_byte == BUFF_EMPTY) chp->chan_byte = chp->ccw_addr & 0x3; chp->ccw_count--; @@ -709,6 +790,11 @@ int chan_write_byte(uint16 chsa, uint8 *data) } else chp->chan_byte++; /* next byte */ chp->chan_byte |= BUFF_DIRTY; /* we are used */ +#else + chp->chan_buf = *data; /* get data byte */ + chp->ccw_count--; + chp->chan_byte |= BUFF_DIRTY; /* we are used */ +#endif return 0; } @@ -747,8 +833,8 @@ void chan_end(uint16 chsa, uint16 flags) { CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ sim_debug(DEBUG_EXP, &cpu_dev, - "chan_end entry chsa %04x flags %04x chan_icb %06x status %04x\n", - chsa, flags, chan_icb, chp->chan_status); + "chan_end entry chsa %04x flags %04x chan_icb %06x status %04x cmd %02x\n", + chsa, flags, chan_icb, chp->chan_status, chp->ccw_cmd); if (chp->chan_byte & BUFF_DIRTY) { if (writebuff(chp)) /* write remaining data */ return; /* error */ @@ -758,8 +844,8 @@ void chan_end(uint16 chsa, uint16 flags) { chp->chan_status |= ((uint16)flags); /* add in the callers flags */ // chp->ccw_cmd = 0; /* reset the completed channel command */ - sim_debug(DEBUG_EXP, &cpu_dev, - "chan_end SLI test chsa %04x ccw_flags %04x count %04x status %04x\n", + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end SLI test1 chsa %04x ccw_flags %04x count %04x status %04x\n", chsa, chp->ccw_flags, chp->ccw_count, chp->chan_status); #ifdef HACK_HACK /* hack - rewind had byte count of 1, so triggered this error when it is not */ @@ -771,23 +857,36 @@ void chan_end(uint16 chsa, uint16 flags) { chp->ccw_flags = 0; /* no flags */ } #else - if (((chp->ccw_cmd & 0xF) == 0x02) || ((chp->ccw_cmd & 0xf) == 0x01)) { /* see if this is a read/write cmd */ + /* see if this is a read/write cmd */ + if (((chp->ccw_cmd & 0x7) == 0x02) || ((chp->ccw_cmd & 0x7) == 0x01)) { /* test for incorrect transfer length */ if (chp->ccw_count != 0 && ((chp->ccw_flags & FLAG_SLI) == 0)) { chp->chan_status |= STATUS_LENGTH; /* show incorrect length status */ + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end setting SLI chsa %04x count %04x ccw_flags %04x status %04x\n", + chsa, chp->ccw_count, chp->ccw_flags, chp->chan_status); chp->ccw_flags = 0; /* no flags */ } } #endif - sim_debug(DEBUG_EXP, &cpu_dev, "chan_end SLI test chsa %04x ccw_flags %04x status %04x\n", - chsa, chp->ccw_flags, chp->chan_status); + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end SLI2 test chsa %04x ccw_flags %04x status %04x\n", + chsa, chp->ccw_flags, chp->chan_status); chp->ccw_cmd = 0; /* reset the completed channel command */ + + /* Diags dos not want SLI if we have no device end status */ + if ((chp->chan_status & FLAG_SLI) && ((chp->chan_status & STATUS_DEND) == 0)) + chp->chan_status &= ~FLAG_SLI; + /* no flags for attention status */ if (flags & (SNS_ATTN|SNS_UNITCHK|SNS_UNITEXP)) { chp->ccw_flags = 0; /* no flags */ } - sim_debug(DEBUG_EXP, &cpu_dev, "chan_end test end chsa %04x, flags %04x\n", chsa, flags); + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end test end chsa %04x ccw_flags %04x status %04x\n", + chsa, chp->ccw_flags, chp->chan_status); + /* test for device or controller end */ if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { chp->chan_byte = BUFF_NEWCMD; /* clear byte flag */ @@ -914,7 +1013,7 @@ t_stat checkxio(uint16 lchsa, uint32 *status) { return SCPE_OK; /* just busy or something, CC3|CC4 */ } } - *status = CC1BIT; /* CCs = 1, CMD accepted & queued, will not echo status */ + *status = CC1BIT; /* CCs = 1, CMD accepted & queued, no echo status */ sim_debug(DEBUG_XIO, &cpu_dev, "checkxio done CC1 status %08x\n", *status); return SCPE_OK; /* No CC's all OK */ } @@ -964,17 +1063,20 @@ t_stat startxio(uint16 lchsa, uint32 *status) { chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ + sim_debug(DEBUG_XIO, &cpu_dev, "startxio test chsa %04x cmd %02x iocla %08x flags %04x IOCD1 %08x IOCD2 %08x\n", chsa, chp->ccw_cmd, iocla, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); sim_debug(DEBUG_CMD, &cpu_dev, "$$$ SIO %04x %04x cmd %02x flags %04x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); + /* check for a Command or data chain operation in progresss */ if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { - sim_debug(DEBUG_XIO, &cpu_dev, "startxio busy return CC4 chsa %04x chan %04x\n", chsa, chan); - *status = CC4BIT; /* busy, so CC4 */ - return SCPE_OK; /* just busy CC4 */ + sim_debug(DEBUG_XIO, &cpu_dev, + "startxio busy return CC3&CC4 chsa %04x chan %04x\n", chsa, chan); + *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ + return SCPE_OK; /* just busy CC3&CC4 */ } /* determine if channel DIB has a pre startio command processor */ @@ -990,7 +1092,7 @@ t_stat startxio(uint16 lchsa, uint32 *status) { return SCPE_OK; /* just busy or something, CC3|CC4 */ } sim_debug(DEBUG_XIO, &cpu_dev, - "startxio pre_io call return not busy chan %04x cstat %08x\n", + "startxio pre_io call return not busy ctan %04x cstat %08x\n", chan, tempa); } @@ -1001,16 +1103,26 @@ t_stat startxio(uint16 lchsa, uint32 *status) { /* set status words in memory to first IOCD information */ tempa = chp->chan_inch_addr; /* get inch status buffer address */ - sim_debug(DEBUG_XIO, &cpu_dev, "@ startxio 4 chsa %04x iocla %08x tempa %08x\n", + sim_debug(DEBUG_XIO, &cpu_dev, + "$$ SIO start IOCL processing chsa %04x iocla %08x incha %08x\n", chsa, iocla, tempa); - sim_debug(DEBUG_XIO, &cpu_dev, "$$ SIO starting IOCL processing chsa %04x iocla %08x\n", chsa, iocla); - /* start processing the IOCL */ if (load_ccw(chp, 0) || (chp->chan_status & STATUS_PCI)) { /* we have an error or user requested interrupt, return status */ sim_debug(DEBUG_EXP, &cpu_dev, "startxio store csw CC2 chan %04x status %08x\n", chan, chp->chan_status); + /* DIAG's want CC1 with memory access error */ + if (chp->chan_status & STATUS_PCHK) { + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ + chp->chan_status &= ~STATUS_LENGTH; /* clear incorrect length */ + store_csw(chp); /* store the status in the inch status dw */ + dev_status[chsa] = 0; /* no device status */ +//DIAG *status = CC2BIT; /* status stored, so CC2 */ + *status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */ + irq_pend = 1; /* still pending int */ + return SCPE_OK; /* CC2 (0x20) status stored */ + } store_csw(chp); /* store the status in the inch status dw */ chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ dev_status[chsa] = 0; /* no device status */ @@ -1019,14 +1131,14 @@ t_stat startxio(uint16 lchsa, uint32 *status) { return SCPE_OK; /* CC2 (0x20) status stored */ } - *status = CC1BIT; /* CCs = 1, SIO accepted & queued, will not echo status */ + *status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */ sim_debug(DEBUG_CMD, &cpu_dev, "$$$ SIO done chsa %04x status %08x iocla %08x\n", chsa, chp->chan_status, iocla); return SCPE_OK; /* No CC's all OK */ } /* TIO - I/O status */ -t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */ +t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */ // uint32 chan = get_chan(lchsa); int lchan = get_chan(lchsa); /* get the logical channel number */ DIB *dibp; @@ -1036,7 +1148,7 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */ uint32 tempa, inta, spadent, chan; uint16 chsa; /* chan/subaddr */ CHANP *chp, *pchp; /* Channel prog pointers */ - uint32 sw1, sw2; /* status word 1 & 2 */ + uint32 sw1=0, sw2=0; /* status word 1 & 2 */ /* get the device entry for the logical channel in SPAD */ spadent = SPAD[lchan]; /* get spad device entry for logical channel */ @@ -1080,7 +1192,8 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */ /* check for a Command or data chain operation in progresss */ if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { - sim_debug(DEBUG_CMD, &cpu_dev, "testxio busy return CC4 chsa %04x chan %04x\n", chsa, chan); + sim_debug(DEBUG_CMD, &cpu_dev, + "testxio busy return CC4 chsa %04x chan %04x\n", chsa, chan); *status = CC4BIT; /* busy, so CC4 */ goto tioret; /* just busy CC4 */ } @@ -1088,12 +1201,13 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */ if ((FIFO_Get(chsa, &sw1) == 0) && (FIFO_Get(chsa, &sw2) == 0)) { uint32 chan_icb = find_int_icb(chsa); /* get icb address */ - sim_debug(DEBUG_IRQ, &cpu_dev, "testxio FIFO status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2); + sim_debug(DEBUG_IRQ, &cpu_dev, + "testxio FIFO status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2); /* we have status to return, do it now */ tempa = pchp->chan_inch_addr; /* get inch status buffer address */ M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ /* save the status to memory */ - M[(tempa+4) >> 2] = sw2; /* save status and residual count in status WD 2 loc */ + M[(tempa+4) >> 2] = 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 */ M[(chan_icb + 20) >> 2] = tempa | BIT1; /* post sw addr in ICB+5w & set CC2 in INCH addr */ *status = CC2BIT; /* status stored from SIO, so CC2 */ @@ -1141,7 +1255,7 @@ t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */ sim_debug(DEBUG_CMD, &cpu_dev, "stopxio dev spad %08x chsa %04x\n", spadent, chsa); /* the startio opcode processing software has already checked for F class */ - inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ + inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ inta = 127 - inta; /* get positive int level */ spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ sim_debug(DEBUG_CMD, &cpu_dev, "stopxio int spad %08x inta %08x chsa %04x\n", spadent, inta, chsa); @@ -1163,7 +1277,7 @@ t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */ /* reset the DC or CC bits to force completion after current IOCD */ chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */ - *status = CC4BIT; /* busy, so CC4 */ + *status = CC1BIT; /* request accepted, no status, so CC1 */ return SCPE_OK; /* just busy CC4 */ } /* the channel is not busy, so return OK */ @@ -1192,12 +1306,12 @@ t_stat rschnlxio(uint16 lchsa, uint32 *status) { /* reset channel XIO */ chp = find_chanp_ptr(chsa); /* find the chanp pointer */ uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ - sim_debug(DEBUG_CMD, &cpu_dev, "rschnlxio 1 chan %04x SPAD %08x\n", chsa, spadent); + sim_debug(DEBUG_XIO, &cpu_dev, "rschnlxio 1 chan %04x SPAD %08x\n", chsa, spadent); if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ *status = CC3BIT; /* not found, so CC3 */ return SCPE_OK; /* not found, CC3 */ } - sim_debug(DEBUG_CMD, &cpu_dev, "rschnlxio 2 chan %04x, spad %08x\r\n", chsa, spadent); + sim_debug(DEBUG_XIO, &cpu_dev, "rschnlxio 2 chan %04x, spad %08x\r\n", chsa, spadent); if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ *status = CC3BIT; /* not attached, so error CC3 */ return SCPE_OK; /* not found, CC3 */ @@ -1232,14 +1346,15 @@ t_stat rschnlxio(uint16 lchsa, uint32 *status) { /* reset channel XIO */ chp->ccw_count = 0; /* channel byte count 0 bytes*/ chp->ccw_flags = 0; /* clear flags */ chp->ccw_cmd = 0; /* read command */ + chp->chan_inch_addr = 0; /* clear inch addr */ } - sim_debug(DEBUG_CMD, &cpu_dev, "rschnlxio return CC1 chan %04x lev %04x\n", chan, lev); + sim_debug(DEBUG_XIO, &cpu_dev, "rschnlxio return CC1 chan %04x lev %04x\n", chan, lev); *status = CC1BIT; /* request accepted, no status, so CC1 TRY THIS */ return SCPE_OK; /* All OK */ } /* HIO - Halt I/O */ -t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ +t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ int chan = get_chan(lchsa); DIB *dibp; UNIT *uptr; @@ -1248,7 +1363,7 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ uint32 inta, spadent; uint16 chsa; CHANP *chp, *pchp; /* Channel prog pointers */ - uint32 sw1, sw2; /* status word 1 & 2 */ + uint32 sw1=0, sw2=0; /* status word 1 & 2 */ /* get the device entry for the logical channel in SPAD */ spadent = SPAD[chan]; /* get spad device entry for logical channel */ @@ -1257,7 +1372,7 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ dibp = dev_unit[chsa]; /* get the device information pointer */ chp = find_chanp_ptr(chsa); /* find the chanp pointer */ uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ - pchp = find_chanp_ptr(chsa & 0x7f00); /* find the channel chanp pointer */ + pchp = find_chanp_ptr(chsa & 0x7f00); /* find the parent channel pointer */ sim_debug(DEBUG_XIO, &cpu_dev, "haltxio 1 chsa %04x chan %04x\n", chsa, chan); if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ @@ -1283,16 +1398,39 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ sim_debug(DEBUG_XIO, &cpu_dev, - "haltxio busy test chsa %04x chan %04x cmd %02x flags %04x IOCD1 %8x IOCD2 %08x\n", + "haltxio busy test chsa %04x chan %04x cmd %02x flags %04x IOCD1 %08x IOCD2 %08x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); sim_debug(DEBUG_XIO, &cpu_dev, "$$$ HIO %04x %04x %02x %04x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); + if (chp->ccw_cmd == 0 && (chp->ccw_flags & (FLAG_DC|FLAG_CC)) == 0) { + /* the channel is not busy, so return OK */ +#ifdef DIAGTUE + *status = CC1BIT; /* request accepted, no status, so CC1 */ + sim_debug(DEBUG_CMD, &cpu_dev, + "$$$ HIO END chsa %04x chan %04x cmd %02x flags %04x status %04x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + return SCPE_OK; /* No CC's all OK */ +#else + /* diag wants an interrupt for a non busy HIO ??? */ + dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ + store_csw(chp); /* store the status in the inch status dw */ + dev_status[chsa] = 0; /* no device status */ + irq_pend = 1; /* still pending int */ +// *status = CC2BIT; /* sub channel status posted, CC2BIT */ + *status = CC1BIT; /* request accepted, no status, so CC1 */ + goto hioret; /* CC2 and OK */ +#endif + } + + chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ /* see if we have a haltio device entry */ if (dibp->halt_io != NULL) { /* NULL if no haltio function */ /* call the device controller to get halt_io status */ uint32 tempa = dibp->halt_io(uptr); /* get status from device */ +#ifdef BAD_TUE if (tempa == SNS_BSY) { *status = CC3BIT|CC4BIT; /* sub channel busy, CC3BIT & CC4BIT */ irq_pend = 1; /* still pending int */ @@ -1300,40 +1438,59 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ "haltxio halt_io return busy chan %04x CC3|CC4\n", chan); goto hioret; /* just return */ } +#endif /* test for SCPE_IOERR */ if (tempa != 0) { /* sub channel has status ready */ /* The device I/O has been terminated and status stored. */ sim_debug(DEBUG_CMD, &cpu_dev, - "haltxio halt_io call return busy chan %04x cstat %08x\n", - chan, tempa); - chp->ccw_count = 0; /* force zero count */ - chp->chan_status &= ~STATUS_LENGTH; /* remove PCI status bit */ - store_csw(chp); /* store the status in the inch status dw */ + "haltxio halt_io call return ERROR chan %04x retstat %08x cstat %08x\n", + chan, tempa, chp->chan_status); +/*TUE*/ chp->chan_status &= ~STATUS_LENGTH; /* remove SLI status bit */ chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ +//TUE dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */ + /* chan_end called in hio device service routine */ + store_csw(chp); /* store the status in the inch status dw */ + chp->ccw_count = 0; /* force zero count */ dev_status[chsa] = 0; /* no device status */ - /* the channel is not busy, see if any status to post */ - if ((FIFO_Get(chsa, &sw1) == 0) && (FIFO_Get(chsa, &sw2) == 0)) { - uint32 chan_icb = find_int_icb(chsa); /* get icb address */ + if (CPU_MODEL >= MODEL_V6) { + /* UTX wants the status posted now, MPX wants interrupt */ + /* the channel is not busy, see if any status to post */ + if ((FIFO_Get(chsa, &sw1) == 0) && (FIFO_Get(chsa, &sw2) == 0)) { + uint32 chan_icb = find_int_icb(chsa); /* get icb address */ + + sim_debug(DEBUG_IRQ, &cpu_dev, + "haltxio 0 FIFO status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2); + /* we have status to return, do it now */ + tempa = pchp->chan_inch_addr; /* get inch status buffer address */ + M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ + /* save the status to memory */ + M[(tempa+4) >> 2] = sw2; /* save status and count in status WD 2 loc */ + /* now store the status dw address into word 5 of the ICB for the channel */ + /* post sw addr in ICB+5w & set CC2 in INCH addr */ + M[(chan_icb + 20) >> 2] = tempa | BIT2; + sim_debug(DEBUG_IRQ, &cpu_dev, + "haltxio 1 FIFO status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2); + irq_pend = 1; /* still pending int */ + // UTX likes this return and does not panic */ + // The diag's want an interrupt generated, so want + *status = CC2BIT; /* status stored from SIO, so CC2 */ + goto hioret; /* CC2 and OK */ + } + /* nothing going on, so say all OK */ + *status = CC1BIT; /* request accepted, no status, so CC1 */ + goto hioret; /* CC2 and OK */ + } else { sim_debug(DEBUG_IRQ, &cpu_dev, - "haltxio FIFO status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2); - /* we have status to return, do it now */ - tempa = pchp->chan_inch_addr; /* get inch status buffer address */ - M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ - /* save the status to memory */ - M[(tempa+4) >> 2] = sw2; /* save status and residual count in status WD 2 loc */ - /* now store the status dw address into word 5 of the ICB for the channel */ - M[(chan_icb + 20) >> 2] = tempa | BIT2; /* post sw addr in ICB+5w & set CC2 in INCH addr */ + "haltxio FIFO 2 status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2); irq_pend = 1; /* still pending int */ - *status = CC2BIT; /* status stored from SIO, so CC2 */ +//TUE *status = 0; /* request accepted, no status, so CC1 */ +/*TUE*/ *status = CC1BIT; /* request accepted, no status, so CC1 */ goto hioret; /* CC2 and OK */ } - /* nothing going on, so say all OK */ - *status = CC1BIT; /* request accepted, no status, so CC1 */ - } - else { - /* we have completed the i/o without error */ + } else { + /* we have completed the I/O without error */ /* the channel is not busy, so return OK */ *status = 0; /* CCs = 0, accepted */ sim_debug(DEBUG_CMD, &cpu_dev, @@ -1462,7 +1619,7 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */ t_stat chan_boot(uint16 chsa, DEVICE *dptr) { int chan = get_chan(chsa); DIB *dibp = dev_unit[chsa]; - CHANP *chp = dibp->chan_prg; + CHANP *chp = 0; sim_debug(DEBUG_EXP, &cpu_dev, "Channel Boot chan/device addr %04x\n", chsa); if (dibp == 0) /* if no channel or device, error */ @@ -1508,14 +1665,12 @@ uint32 scan_chan(int *ilev) { uint32 chan; /* channel num 0-7f */ uint32 tempa; /* icb address */ uint32 chan_ivl; /* int level table address */ -// int lev; /* interrupt level */ uint32 chan_icba; /* int level context block address */ CHANP *chp; /* channel prog pointer */ DIB *dibp; /* DIB pointer */ if (irq_pend == 1) { /* pending int? */ /* see if we have a channel completed */ -// irq_pend = 0; /* not pending anymore */ /* loop through all the channels/units for channel with pending I/O completion */ for (i = 0; sim_devices[i] != NULL; i++) { DEVICE *dptr = sim_devices[i]; /* get pointer to configured device */ @@ -1574,7 +1729,6 @@ uint32 scan_chan(int *ilev) { irq_pend = 1; /* still pending int */ //WAS goto trythis; return 0; /* just return */ -// keep looking return 0; /* just return */ } } uptr++; /* next UNIT pointer */ @@ -1611,17 +1765,18 @@ uint32 scan_chan(int *ilev) { chp = find_chanp_ptr(chan); /* find the chanp pointer for channel */ /* get the address of the interrupt IVL table in main memory */ chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_icba = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ + chan_icba = M[chan_ivl >> 2]; /* get the interrupt context blk addr in memory */ tempa = chp->chan_inch_addr; /* get inch status buffer address */ M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ /* save the status to memory */ - M[(tempa+4) >> 2] = sw2; /* save status and residual count in status WD 2 loc */ + M[(tempa+4) >> 2] = sw2; /* save status and count in status WD 2 loc */ /* now store the status dw address into word 5 of the ICB for the channel */ - M[(chan_icba + 20) >> 2] = tempa | BIT1; /* post sw addr in ICB+5w & set CC2 in SW */ + /* post sw addr in ICB+5w & set CC2 in SW */ + M[(chan_icba + 20) >> 2] = tempa | BIT1; INTS[i] |= INTS_REQ; /* turn on channel interrupt request */ - sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan %04x FIFO read, set irq %04x inch %06x chan_icba %06x sw1 %08x sw2 %08x\n", - chan, i, tempa, chan_icba, sw1, sw2); + sim_debug(DEBUG_IRQ, &cpu_dev, + "scan_chan %04x FIFO read, set irq %04x inch %06x chan_icba %06x sw1 %08x sw2 %08x\n", + chan, i, tempa, chan_icba, sw1, sw2); } } } @@ -1634,13 +1789,14 @@ uint32 scan_chan(int *ilev) { INTS[i] |= INTS_ACT; /* turn on active */ SPAD[i+0x80] |= SINT_ACT; /* show active in SPAD too */ /* make sure both enabled too */ - /* should already be enabled */ + /* should already be enabled */ // INTS[i] |= INTS_ENAB; /* turn on enable */ // SPAD[i+0x80] |= SINT_ENAB; /* show enabled in SPAD too */ /* get the address of the interrupt IVL table in main memory */ chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */ chan_icba = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ - sim_debug(DEBUG_IRQ, &cpu_dev, "scan_chan INTS REQ irq %04x found chan_icba %08x INTS %08x\n", + sim_debug(DEBUG_IRQ, &cpu_dev, + "scan_chan INTS REQ irq %04x found chan_icba %08x INTS %08x\n", i, chan_icba, INTS[i]); *ilev = i; /* return interrupt level */ irq_pend = 0; /* not pending anymore */ @@ -1648,10 +1804,6 @@ uint32 scan_chan(int *ilev) { } } } -// if (irq_pend == 0) /* pending int? */ -// return 0; /* no, so just return */ -// irq_pend = 0; /* not pending anymore */ - return 0; /* done */ } @@ -1661,7 +1813,7 @@ uint32 scan_chan(int *ilev) { */ DEVICE *get_dev(UNIT *uptr) { - DEVICE *dptr; + DEVICE *dptr = NULL; uint32 i, j; if (uptr == NULL) /* must be valid unit */ @@ -1768,11 +1920,7 @@ t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { chan = get_uint(cptr, 16, 0xffff, &r); /* get new device address */ if (r != SCPE_OK) /* need good number */ return r; /* number error, return error */ -//printf("finding chan %s (%x) with unit address %04x dptr %x\n", -// cptr, chan, GET_UADDR(uptr->u3), uptr->dptr); -// if ((chan == 0) || ((chan & 0x7f00) != chan)) /* is chan 1-7f */ -// return SCPE_ARG; /* no, bad channel # */ chan &= 0x7f00; /* clean channel address */ dibp->chan_addr = chan; /* set new parent channel addr */ diff --git a/SEL32/sel32_clk.c b/SEL32/sel32_clk.c index 3a52817..91c0f12 100644 --- a/SEL32/sel32_clk.c +++ b/SEL32/sel32_clk.c @@ -1,6 +1,6 @@ /* sel32_clk.c: SEL 32 Class F IOP processor RTOM functions. - Copyright (c) 2018, James C. Bevier + Copyright (c) 2018-2020, James C. Bevier Portions provided by Richard Cornwell and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a diff --git a/SEL32/sel32_com.c b/SEL32/sel32_com.c index 5003366..d129c0f 100644 --- a/SEL32/sel32_com.c +++ b/SEL32/sel32_com.c @@ -1,6 +1,6 @@ /* sel32_com.c: SEL 32 8-Line IOP communications controller - Copyright (c) 2018, James C. Bevier + Copyright (c) 2018-2020, James C. Bevier Portions provided by Richard Cornwell and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a diff --git a/SEL32/sel32_con.c b/SEL32/sel32_con.c index b93c387..14be731 100644 --- a/SEL32/sel32_con.c +++ b/SEL32/sel32_con.c @@ -1,6 +1,6 @@ /* sel32_con.c: SEL 32 Class F IOP processor console. - Copyright (c) 2018, James C. Bevier + Copyright (c) 2018-2020, James C. Bevier Portions provided by Richard Cornwell and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a @@ -49,6 +49,8 @@ extern void post_extirq(void); extern uint32 attention_trap; /* set when trap is requested */ extern void set_devwake(uint16 addr, uint8 flags); extern DEVICE *get_dev(UNIT *uptr); +extern t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */ +extern CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */ #define CMD u3 /* Held in u3 is the device command and status */ @@ -123,8 +125,8 @@ MTAB con_mod[] = { }; UNIT con_unit[] = { - {UDATA(con_srvi, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7EFC)}, /* Input */ - {UDATA(con_srvo, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7EFD)}, /* Output */ + {UDATA(&con_srvi, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7EFC)}, /* Input */ + {UDATA(&con_srvo, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7EFD)}, /* Output */ }; //DIB con_dib = {NULL, con_startcmd, NULL, NULL, NULL, con_ini, con_unit, con_chp, NUM_UNITS_CON, 0xf, 0x7e00, 0, 0, 0}; @@ -157,12 +159,13 @@ DEVICE con_dev = { */ /* initialize the console chan/unit */ void con_ini(UNIT *uptr, t_bool f) { -// int unit = (uptr - con_unit); /* unit 0 */ + int unit = (uptr - con_unit); /* unit 0 */ // DEVICE *dptr = get_dev(uptr); -// con_data[unit].incnt = 0; /* no input data */ - con_data[0].incnt = 0; /* no input data */ - con_data[1].incnt = 0; /* no output data */ + uptr->u4 = 0; /* no input cpunt */ + con_data[unit].incnt = 0; /* no input data */ +// con_data[0].incnt = 0; /* no input data */ +// con_data[1].incnt = 0; /* no output data */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ sim_activate(uptr, 1000); /* time increment */ } @@ -206,10 +209,6 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { case CON_RWD: /* 0x37 */ /* TOF and write line */ case CON_WR: /* 0x01 */ /* Write command */ /* if input requested for output device, give error */ - if (unit == 0) { - uptr->SNS |= SNS_CMDREJ; /* command rejected */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ - } uptr->CMD &= LMASK; /* leave only chsa */ uptr->CMD |= (cmd & CON_MSK); /* save command */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ @@ -221,10 +220,6 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { case CON_RD: /* 0x02 */ /* Read command */ case CON_ECHO: /* 0x0a */ /* Read command w/ECHO */ /* if output requested for input device, give error */ - if (unit == 1) { - uptr->SNS |= SNS_CMDREJ; /* command rejected */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ - } uptr->CMD &= LMASK; /* leave only chsa */ uptr->CMD |= (cmd & CON_MSK); /* save command */ if (cmd == CON_ECHO) /* echo command? */ @@ -242,15 +237,16 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ uptr->CMD &= LMASK; /* leave only chsa */ uptr->CMD |= (cmd & CON_MSK); /* save command */ +// uptr->u4 = 0; /* no I/O yet */ +// con_data[unit].incnt = 0; /* clear any input data */ sim_activate(uptr, 10); /* start us off */ -//TRIED sim_activate(uptr, 2); /* start us off */ return 0; /* no status change */ break; -#ifdef JUNK - case 0x0c: /* 0x0C */ /* Unknown command */ +#ifndef JUNK + case 0x0C: /* 0x0C */ /* Unknown command */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ - uptr->CND &= LMASK; /* leave only chsa */ + uptr->CMD &= LMASK; /* leave only chsa */ uptr->CMD |= (cmd & CON_MSK); /* save command */ sim_activate(uptr, 10); /* start us off */ return 0; /* no status change */ @@ -269,9 +265,6 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { return SNS_CHNEND|SNS_DEVEND; /* good return */ break; -#ifdef JUNK - case 0x0c: /* 0x0C */ /* Unknown command */ -#endif case CON_SNS: /* 0x04 */ /* Sense */ sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %04x: Cmd Sense %02x\n", chan, uptr->SNS); @@ -284,6 +277,8 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { default: /* invalid command */ uptr->SNS |= SNS_CMDREJ; /* command rejected */ +// uptr->u4 = 0; /* no I/O yet */ +// con_data[unit].incnt = 0; /* clear any input data */ sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %04x: Invalid command %02x Sense %02x\n", chan, cmd, uptr->SNS); @@ -299,35 +294,59 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { /* Handle output transfers for console */ t_stat con_srvo(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->CMD); - int unit = (uptr - con_unit); /* unit 0 is read, unit 1 is write */ + int unit = (uptr - con_unit); /* unit 0 is read, unit 1 is write */ int cmd = uptr->CMD & CON_MSK; + CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ uint8 ch, cp; sim_debug(DEBUG_DETAIL, &con_dev, "con_srvo enter chsa %04x cmd = %02x\n", chsa, cmd); - if (cmd == 0x0C) { /* unknown has to do nothing */ - sim_debug(DEBUG_CMD, &con_dev, "con_srvo Unknown (0x0C) chsa %04x cmd = %02x\n", chsa, cmd); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ - return SCPE_OK; + + /* if input tried from output device, error */ + if ((cmd == CON_RD) || (cmd == CON_ECHO) || (cmd == 0xC0)) { /* check for output */ + /* CON_RD: 0x02 */ /* Read command */ + /* CON_ECHO: 0x0a */ /* Read command w/ECHO */ + /* if input requested for output device, give error */ + if (unit == 1) { + uptr->SNS |= SNS_CMDREJ; /* command rejected */ + uptr->CMD &= LMASK; /* nothing left, command complete */ +//DIAG_TUE chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* unit check */ + chan_end(chsa, SNS_CHNEND|SNS_UNITCHK); /* unit check */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvo Read to output device chsa %04x cmd = %02x\n", chsa, cmd); + return SCPE_OK; + } } if ((cmd == CON_NOP) || (cmd == CON_INCH2)) { /* NOP has to do nothing */ - uptr->CMD &= LMASK; /* nothing left, command complete */ - if (cmd == CON_INCH2) { /* Channel end only for INCH */ - sim_debug(DEBUG_CMD, &con_dev, "con_srvo INCH chsa %04x cmd = %02x\n", chsa, cmd); - chan_end(chsa, SNS_CHNEND); /* done */ + uptr->CMD &= LMASK; /* nothing left, command complete */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvo INCH/NOP unit %02x: cmd %02x incnt %02x u4 %02x\n", + unit, cmd, con_data[unit].incnt, uptr->u4); + if (cmd == CON_INCH2) { /* Channel end only for INCH */ + int len = chp->ccw_count; /* INCH command count */ + uint32 mema = chp->ccw_addr; /* get inch or buffer addr */ +// int i = set_inch(uptr, mema); /* new address */ + set_inch(uptr, mema); /* new address */ + + sim_debug(DEBUG_CMD, &con_dev, + "con_srvo INCH chsa %04x len %02x inch %06x\n", chsa, len, mema); + chan_end(chsa, SNS_CHNEND); /* INCH done */ } else { - sim_debug(DEBUG_CMD, &con_dev, "con_srvo NOP chsa %04x cmd = %02x\n", chsa, cmd); + sim_debug(DEBUG_CMD, &con_dev, + "con_srvo NOP chsa %04x cmd = %02x\n", chsa, cmd); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ } return SCPE_OK; } -// static uint32 lastch = 0; if ((cmd == CON_WR) || (cmd == CON_RWD)) { /* Write to device */ if (chan_read_byte(chsa, &ch)) { /* get byte from memory */ uptr->CMD &= LMASK; /* nothing left, command complete */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvo write %02x chsa %04x cmd %02x complete\n", + ch, chsa, cmd); } else { /* HACK HACK HACK */ ch &= 0x7f; /* make 7 bit w/o parity */ @@ -339,15 +358,11 @@ t_stat con_srvo(UNIT *uptr) { cp = ch; else cp = '^'; - sim_debug(DEBUG_CMD, &con_dev, "con_srvo write %01x: putch 0x%02x %c\n", unit, ch, cp); -#ifdef DO_DYNAMIC_DEBUG - lastch = (lastch << 8) | cp; - if ((lastch & 0xffff) == 0x6e29) /* check for ion) */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif + sim_debug(DEBUG_CMD, &con_dev, + "con_srvo write %01x: putch 0x%02x %c\n", unit, ch, cp); //WAS sim_putchar(ch); /* output next char to device */ sim_putchar(cp); /* output next char to device */ - sim_activate(uptr, 20); /* start us off */ + sim_activate(uptr, 20); /* keep going */ } } return SCPE_OK; @@ -358,11 +373,27 @@ t_stat con_srvi(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->CMD); int unit = (uptr - con_unit); /* unit 0 is read, unit 1 is write */ int cmd = uptr->CMD & CON_MSK; + CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ uint8 ch; t_stat r; sim_debug(DEBUG_DETAIL, &con_dev, "con_srvi enter chsa %04x cmd = %02x\n", chsa, cmd); + /* if output tried to input device, error */ + if ((cmd == CON_RWD) || (cmd == CON_WR) || (cmd == 0x0C)) { /* check for output */ + /* CON_RWD: 0x37 */ /* TOF and write line */ + /* CON_WR: 0x01 */ /* Write command */ + /* if input requested for output device, give error */ + if (unit == 0) { + uptr->SNS |= SNS_CMDREJ; /* command rejected */ + uptr->CMD &= LMASK; /* nothing left, command complete */ +//DIAGTUE chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* unit check */ + chan_end(chsa, SNS_CHNEND|SNS_UNITCHK); /* unit check */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi Write to input device chsa %04x cmd = %02x\n", chsa, cmd); +//fall thru return SCPE_OK; + } + } #ifdef JUNK if (cmd == 0x0C) { /* unknown has to do nothing */ sim_debug(DEBUG_CMD, &con_dev, "con_srvi Unknown (0x0C) chsa %04x cmd = %02x\n", chsa, cmd); @@ -373,14 +404,23 @@ t_stat con_srvi(UNIT *uptr) { if ((cmd == CON_NOP) || (cmd == CON_INCH2)) { /* NOP is do nothing */ uptr->CMD &= LMASK; /* nothing left, command complete */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi INCH/NOP unit %02x: cmd %02x incnt %02x u4 %02x\n", + unit, cmd, con_data[unit].incnt, uptr->u4); if (cmd == CON_INCH2) { /* Channel end only for INCH */ - sim_debug(DEBUG_CMD, &con_dev, "con_srvi INCH chsa %04x cmd = %02x\n", chsa, cmd); - chan_end(chsa, SNS_CHNEND); /* done */ + int len = chp->ccw_count; /* INCH command count */ + uint32 mema = chp->ccw_addr; /* get inch or buffer addr */ +// int i = set_inch(uptr, mema); /* new address */ + set_inch(uptr, mema); /* new address */ + + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi INCH chsa %04x len %02x inch %06x\n", chsa, len, mema); + chan_end(chsa, SNS_CHNEND); /* INCH done */ // chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ } else { - sim_debug(DEBUG_CMD, &con_dev, "con_srvi NOP chsa %04x cmd = %02x\n", chsa, cmd); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ -// chan_end(chsa, SNS_CHNEND); /* done */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi NOP chsa %04x cmd = %02x\n", chsa, cmd); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* NOP done */ } /* drop through to poll input */ } @@ -390,25 +430,31 @@ t_stat con_srvi(UNIT *uptr) { case CON_RD: /* 0x02 */ /* read from device */ case CON_ECHO: /* 0x0a */ /* read from device w/ECHO */ if (uptr->CMD & CON_INPUT) { /* input waiting? */ + int len = chp->ccw_count; /* get command count */ ch = con_data[unit].ibuff[uptr->u4++]; /* get char from read buffer */ -#ifdef DO_DYNAMIC_DEBUG - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif - sim_debug(DEBUG_CMD, &con_dev, "con_srvi unit %02x: read %02x\n", unit, ch); + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi unit %02x: read %02x incnt %02x u4 %02x len %02x\n", + unit, ch, con_data[unit].incnt, uptr->u4, len); + if (chan_write_byte(chsa, &ch)) { /* write byte to memory */ con_data[unit].incnt = 0; /* buffer empty */ cmd = 0; /* no cmd either */ +// uptr->u4 = 0; /* no I/O yet */ uptr->CMD &= LMASK; /* nothing left, command complete */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ } else { +// len = chp->ccw_count; /* INCH command count */ +// if ((len==0) && uptr->u4 == con_data[unit].incnt) { /* read completed */ if (uptr->u4 == con_data[unit].incnt) { /* read completed */ con_data[unit].incnt = 0; /* buffer is empty */ cmd = 0; /* no cmd either */ +// uptr->u4 = 0; /* no I/O yet */ uptr->CMD &= LMASK; /* nothing left, command complete */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ } } } +// default: break; } @@ -471,7 +517,8 @@ t_stat con_srvi(UNIT *uptr) { atbuf = 0; /* reset attention buffer */ sim_putchar('\r'); /* return char */ sim_putchar('\n'); /* line feed char */ - sim_debug(DEBUG_CMD, &con_dev, "con_srvi unit %02x: read @@A Console Trap\n", unit); + sim_debug(DEBUG_CMD, &con_dev, + "con_srvi unit %02x: read @@A Console Trap\n", unit); } } else { if (ch == '?') { @@ -484,8 +531,10 @@ t_stat con_srvi(UNIT *uptr) { } if ((r & SCPE_KFLAG) && /* got something and */ ((cmd == CON_RD) || (cmd == CON_ECHO))) /* looking for input */ - return sim_activate (uptr, 20); - return tmxr_clock_coschedule_tmr (uptr, TMR_RTC, 1); /* come back soon */ +//WAS return sim_activate (uptr, 20); + return sim_activate (uptr, 100); + return sim_activate (uptr, 500); +//WAS return tmxr_clock_coschedule_tmr (uptr, TMR_RTC, 1); /* come back soon */ } t_stat con_reset(DEVICE *dptr) { @@ -497,22 +546,46 @@ t_stat con_reset(DEVICE *dptr) { uint8 con_haltio(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->CMD); int cmd = uptr->CMD & CON_MSK; -// int unit = (uptr - con_unit); /* unit # */ + int unit = (uptr - con_unit); /* unit # 0 is read, 1 is write */ + uint8 ch; sim_debug(DEBUG_EXP, &con_dev, "con_haltio enter chsa %04x cmd = %02x\n", chsa, cmd); -// if ((unit == 0) && ((uptr->CMD & 0xff00) != 0)) { /* just return if busy */ -// return SNS_BSY; -// } +#ifdef DO_DYNAMIC_DEBUG + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); + con_dev.dctrl |= (DEBUG_CMD | DEBUG_EXP | DEBUG_DETAIL); +#endif /* terminate any input command */ if ((uptr->CMD & CON_MSK) != 0) { /* is unit busy */ + sim_debug(DEBUG_CMD, &con_dev, + "con_haltio HIO chsa %04x cmd = %02x\n", chsa, cmd); + if (unit == 0) { + if (chan_write_byte(chsa, &ch)) { /* write byte to memory */ + con_data[unit].incnt = 0; /* buffer empty */ + uptr->CMD &= LMASK; /* nothing left, command complete */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ + sim_debug(DEBUG_CMD, &con_dev, + "con_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd); +// return SCPE_OK; /* not busy anymore */ + return SCPE_IOERR; + } + } else { + if (chan_read_byte(chsa, &ch)) { /* get byte from memory */ + uptr->CMD &= LMASK; /* nothing left, command complete */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ + sim_debug(DEBUG_CMD, &con_dev, + "con_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd); + // return SCPE_OK; /* not busy anymore */ + return SCPE_IOERR; + } + } uptr->CMD &= LMASK; /* make non-busy */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ - sim_debug(DEBUG_CMD, &con_dev, "con_haltio HIO chsa %04x cmd = %02x\n", chsa, cmd); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ -// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* done bit 14 */ /* bad status */ + return SCPE_OK; /* not busy */ +//no work chan_end(chsa, SNS_CHNEND|SNS_UNITCHK); /* write terminated */ +// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* write terminated */ // chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* done bit 15 */ /* bad status */ - return SCPE_IOERR; +// return SCPE_IOERR; } return SCPE_OK; /* not busy */ } diff --git a/SEL32/sel32_cpu.c b/SEL32/sel32_cpu.c index 808ddb7..460142a 100644 --- a/SEL32/sel32_cpu.c +++ b/SEL32/sel32_cpu.c @@ -1,6 +1,6 @@ /* sel32_cpu.c: Sel 32 CPU simulator - Copyright (c) 2018, James C. Bevier + Copyright (c) 2018-2020, James C. Bevier Portions provided by Richard Cornwell and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a @@ -316,7 +316,7 @@ UNIT cpu_unit = REG cpu_reg[] = { {HRDATAD(PC, PC, 24, "Program Counter"), REG_FIT}, - {BRDATAD(PSD, PSD, 16, 32, 2, "Progtam Status Doubleword"), REG_FIT}, + {BRDATAD(PSD, PSD, 16, 32, 2, "Program Status Doubleword"), REG_FIT}, {BRDATAD(GPR, GPR, 16, 32, 8, "Index registers"), REG_FIT}, {BRDATAD(BR, BR, 16, 32, 8, "Base registers"), REG_FIT}, {BRDATAD(BOOTR, BOOTR, 16, 32, 8, "Boot registers"), REG_FIT}, @@ -1458,6 +1458,9 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) else *prot = offset; /* return memory write protection status */ +// if (addr != word) +//sim_debug(DEBUG_EXP, &cpu_dev, +//"At RealAddr Hit convert %06x to addr %08x\n", addr, word); sim_debug(DEBUG_DETAIL, &cpu_dev, "RealAddrX address %06x, TLB %06x MAPC[%03x] %08x wprot %02x prot %02x\n", word, TLB[index], index/2, MAPC[index/2], (word>>11)&3, *prot); @@ -1554,7 +1557,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) sim_debug(DEBUG_TRAP, &cpu_dev, "AddrMa %06x RealAddr %06x Map0 HIT %04x, TLB[%3x] %08x MAPC[%03x] %08x\n", addr, word, map, nix, TLB[nix], nix/2, MAPC[nix/2]); - /* do a demand page request for the reqired page */ + /* do a demand page request for the required page */ pfault = nix; /* save page number */ sim_debug(DEBUG_TRAP, &cpu_dev, "Mem_write Daddr2 %06x page %04x demand page bits set TLB %08x map %04x\n", @@ -1592,6 +1595,9 @@ cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_XIO); #endif *realaddr = word; /* return the real address */ raddr = TLB[nix]; /* get the base address & bits */ +// if (addr != word) +//sim_debug(DEBUG_EXP, &cpu_dev, +//"At RealAddr Miss convert %06x to addr %08x\n", addr, word); if ((CPU_MODEL == MODEL_67) || (CPU_MODEL == MODEL_97)) { /* get protection status of map */ @@ -1708,6 +1714,9 @@ t_stat Mem_read(uint32 addr, uint32 *data) uint32 status, realaddr, prot, page, map, mix, nix, msdl, mpl, nmap; status = RealAddr(addr, &realaddr, &prot, MEM_RD); /* convert address to real physical address */ +// if (addr != realaddr) +//sim_debug(DEBUG_EXP, &cpu_dev, +//"At Mem_read convert %06x to addr %08x\n", addr, realaddr); if (status == ALLOK) { // *data = M[realaddr >> 2]; /* valid address, get physical address contents */ @@ -2044,9 +2053,17 @@ redo: SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ sim_debug(DEBUG_IRQ, &cpu_dev, - "Interrupt %04x OPSD1 %08x OPSD2 %08x NPSD1 %08x NPSD2 %08x ICBA %08x\n", - il, RMW(int_icb), RMW(int_icb+4), PSD1, PSD2, int_icb); -// il, M[int_icb>>2], M[(int_icb>>2)+1], PSD1, PSD2, int_icb); + "Inter %03x OPSD1 %08x OPSD2 %08x NPSD1 %08x NPSD2 %08x\n", + il, RMW(int_icb), RMW(int_icb+4), PSD1, PSD2); + bc = RMW(int_icb+20) & 0xffffff; + if (RMW(int_icb+16) == 0) + sim_debug(DEBUG_IRQ, &cpu_dev, + "Inter2 %03x ICBA %06x IOCLA %06x\n", + il, int_icb, RMW(int_icb+16)); + else + sim_debug(DEBUG_IRQ, &cpu_dev, + "Inter2 %03x ICBA %06x IOCLA %06x STAT %08x SW1 %08x SW2 %08x\n", + il, int_icb, RMW(int_icb+16), RMW(int_icb+20), RMW(bc), RMW(bc+4)); wait4int = 0; /* wait is over for int */ irq_pend = 1; /* scan for interrupts again */ skipinstr = 1; /* skip next inter test after this instr */ @@ -2091,14 +2108,6 @@ redo: /* Check for external interrupt here */ /* see if we have an attention request from console */ if (!skipinstr && attention_trap) { -#ifdef DO_DYNAMIC_DEBUG - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_EXP | DEBUG_IRQ | DEBUG_XIO); - sim_debug(DEBUG_EXP, &cpu_dev, "Attention TRAP %04x skip %01x wait4int %01x irq_pend %01x\n", - TRAPME, skipinstr, wait4int, irq_pend); - sim_debug(DEBUG_EXP, &cpu_dev, "Attention TRAPME %04x PSD %08x %08x\n", - TRAPME, PSD1, PSD2); -#endif TRAPME = attention_trap; /* get trap number */ attention_trap = 0; /* clear flag */ sim_debug(DEBUG_XIO, &cpu_dev, "Attention TRAP %04x\n", TRAPME); @@ -2110,17 +2119,9 @@ skipi: i_flags = 0; /* do not update pc if MF or NPM */ skipinstr = 0; /* skip only once */ TRAPSTATUS = CPUSTATUS & 0x57; /* clear all trap status except cpu type */ -//WAS if (sim_brk_summ && sim_brk_test(PC, SWMASK('E'))) { -//WAS reason = STOP_IBKPT; -//WAS break; -//WAS } /* fill IR from logical memory address */ if ((TRAPME = read_instruction(PSD, &IR))) { -#ifdef DO_DYNAMIC_DEBUG - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif sim_debug(DEBUG_TRAP, &cpu_dev, "read_instr TRAPME %04x PSD %08x %08x i_flags %04x drop_nop %01x\n", TRAPME, PSD1, PSD2, i_flags, drop_nop); @@ -2698,8 +2699,8 @@ exec: break; case 0x9: /* RDSTS */ GPR[reg] = CPUSTATUS; /* get CPU status word */ - sim_debug(DEBUG_CMD, &cpu_dev, - "RDSTS CPUSTATUS %08x SPAD[0xf9] %08x\n", CPUSTATUS, SPAD[0xf9]); +//sim_debug(DEBUG_CMD, &cpu_dev, +//"RDSTS CPUSTATUS %08x SPAD[0xf9] %08x\n", CPUSTATUS, SPAD[0xf9]); #ifdef DO_DYNAMIC_DEBUG /* start debugging */ cpu_dev.dctrl |= (DEBUG_INST | DEBUG_TRAP | DEBUG_EXP | DEBUG_IRQ); @@ -3689,8 +3690,8 @@ tbr: /* handle basemode TBR too * t = (GPR[reg] >> 16) & 0xff; /* get SPAD address from Rd (6-8) */ temp2 = SPAD[t]; /* get old SPAD data */ SPAD[t] = GPR[sreg]; /* store Rs into SPAD */ - sim_debug(DEBUG_CMD, &cpu_dev, - "At TRSC with spad[%02x] %08x old %08x\n", t, SPAD[t], temp2); +//sim_debug(DEBUG_CMD, &cpu_dev, +//"At TRSC with spad[%02x] %08x old %08x\n", t, SPAD[t], temp2); break; case 0xF: /* TSCR */ /* Transfer scratchpad to register */ @@ -3704,8 +3705,8 @@ tbr: /* handle basemode TBR too * } t = (GPR[sreg] >> 16) & 0xff; /* get SPAD address from Rs (9-11) */ temp = SPAD[t]; /* get SPAD data into Rd (6-8) */ - sim_debug(DEBUG_CMD, &cpu_dev, - "At TSCR with spad[%02x] %08x\n", t, SPAD[t]); +//sim_debug(DEBUG_CMD, &cpu_dev, +//"At TSCR with spad[%02x] %08x\n", t, SPAD[t]); break; } GPR[reg] = temp; /* save the temp value to Rd reg */ @@ -4013,6 +4014,8 @@ skipit: break; } td = (t_int64)dest % (t_int64)source; /* remainder */ +// dbl = !(td >= 0); /* double reg is neg remainder */ +// dbl = ((t_int64)td < 0); /* double reg is neg remainder */ dbl = (td < 0); /* double reg is neg remainder */ if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */ td = NEGATE32(td); /* dividend and remainder must be same sign */ @@ -4641,6 +4644,8 @@ doovr3: case 0x80>>2: /* 0x80 SD|ADR - SD|ADR */ /* LEAR */ /* convert address to real physical address */ TRAPME = RealAddr(addr, &temp, &t, MEM_RD); +//sim_debug(DEBUG_EXP, &cpu_dev, +//"At LEAR convert %06x to addr %08x\n", addr, temp); // diag allows any addr if mapped if (TRAPME != ALLOK) { sim_debug(DEBUG_TRAP, &cpu_dev, @@ -4687,7 +4692,7 @@ doovr3: WMR((nix<<1), map); /* store the map reg contents into cache */ TLB[nix] |= 0x0c000000; /* set the accessed & hit bits in TLB too */ WMH(msdl+(mix<<1), mmap); /* save modified memory map with access bit set */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_EXP, &cpu_dev, "LEAR Laddr %06x page %04x set access bit TLB %08x map %04x nmap %04x\n", addr, nix, TLB[nix], map, mmap); } @@ -4697,6 +4702,8 @@ doovr3: /* DIAGS needs it, so put it back */ if (FC & 4) /* see if F bit was set */ temp |= 0x01000000; /* set bit 7 of address */ +//sim_debug(DEBUG_EXP, &cpu_dev, +//"At LEAR convert %06x to addr %08x\n", addr, temp); dest = temp; /* put in dest to go out */ break; @@ -5022,6 +5029,11 @@ meoa: /* merge point for eor, and, or */ "\n\tR0=%.8x R1=%.8x R2=%.8x R3=%.8x", GPR[0], GPR[1], GPR[2], GPR[3]); sim_debug(DEBUG_INST, &cpu_dev, " R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]); +#ifdef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, + "EXM skipinstr %x irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + skipinstr, irq_pend, PSD1, PSD2, CPUSTATUS); +#endif /*DIAG*/ skipinstr = 0; /* only test this once */ goto exec; /* go execute the instruction */ break; @@ -5320,7 +5332,7 @@ doovr2: TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ goto newpsd; /* program error */ } - temp2 = ((IR>>12) & 0x0f) << 2; /* get SVC index from IR */ + temp2 = ((IR>>12) & 0x0f) << 2; /* get SVC index from IR */ t = M[(temp+temp2)>>2]; /* get secondary trap vector address ICB address */ if (t == 0 || t == 0xffffffff) { /* see if ICB set up */ TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ @@ -5403,6 +5415,11 @@ doovr2: "\n\tR0=%.8x R1=%.8x R2=%.8x R3=%.8x", GPR[0], GPR[1], GPR[2], GPR[3]); sim_debug(DEBUG_INST, &cpu_dev, " R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]); +#ifdef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, + "EXR skipinstr %x irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + skipinstr, irq_pend, PSD1, PSD2, CPUSTATUS); +#endif /*DIAG*/ skipinstr = 0; /* only test this once */ goto exec; /* go execute the instruction */ break; @@ -6347,9 +6364,6 @@ mcheck: sim_debug(DEBUG_XIO, &cpu_dev, "XIO SIO ret chan %04x chsa %04x status %08x\n", chan, (chan<<8)|suba, status); - sim_debug(DEBUG_IRQ, &cpu_dev, - "SIO skipinstr %x irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - skipinstr, irq_pend, PSD1, PSD2, CPUSTATUS); break; case 0x03: /* Test I/O TIO */ @@ -6364,6 +6378,10 @@ mcheck: sim_debug(DEBUG_XIO, &cpu_dev, "XIO TIO ret chan %04x sa %04x status %08x spad %08x INTS[%02x] %08x\n", chan, suba, status, t, ix, INTS[ix]); +#ifdef DO_DYNAMIC_DEBUG + /* start debugging */ + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); +#endif break; case 0x04: /* Stop I/O STPIO */ diff --git a/SEL32/sel32_defs.h b/SEL32/sel32_defs.h index 32ddbc3..4fe6ab9 100644 --- a/SEL32/sel32_defs.h +++ b/SEL32/sel32_defs.h @@ -1,6 +1,6 @@ /* sel32_defs.h: SEL-32 Concept/32 simulator definitions - Copyright (c) 2018-2019, James C. Bevier + Copyright (c) 2018-2020, James C. Bevier Portions provided by Richard Cornwell and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a @@ -417,6 +417,8 @@ extern DEBTAB dev_debug[]; #define WMW(a,d) (M[(a)>>2]=d) /* write memory addressed word */ /* write halfword to memory address */ #define WMH(a,d) ((a)&2?(M[(a)>>2]=(M[(a)>>2]&LMASK)|((d)&RMASK)):(M[(a)>>2]=(M[(a)>>2]&RMASK)|((d)<<16))) +/* write byte to memory */ +#define WMB(a,d) (M[(a)>>2]=(M[(a)>>2]&(~(0xff<<(8*(7-(a&3)))))|((d&0xff)<<(8*(7-(a&3)))))) /* map register access macros */ /* The RMR and WMR macros are used to read/write the MAPC cache registers */ diff --git a/SEL32/sel32_disk.c b/SEL32/sel32_disk.c index 8efb646..018763c 100644 --- a/SEL32/sel32_disk.c +++ b/SEL32/sel32_disk.c @@ -32,6 +32,8 @@ extern void set_devattn(uint16 addr, uint8 flags); extern t_stat chan_boot(uint16 addr, DEVICE *dptr); extern int test_write_byte_end(uint16 chsa); extern DEVICE *get_dev(UNIT *uptr); +extern t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */ +extern CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */ extern uint32 M[]; /* our memory */ extern uint32 SPAD[]; /* cpu SPAD memory */ @@ -230,10 +232,13 @@ 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 ATTR u6 +#define CHS u6 /* u6 */ -/* u6 holds drive attribute entry */ -/* provided by inch command for controller */ +/* u6 holds the current cyl, hd, sec for the drive */ + +/* this attribute information is provided by the INCH command */ +/* for each device and is not used. It is reconstructed from */ +/* the disk_t structure data for the assigned disk */ /* bits 0-7 - Flags bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option @@ -249,16 +254,13 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option mini-module) */ -#define DDATA up7 -/* Pointer held in up7 */ -/* sects/cylinder = sects/track * numhds */ -/* allocated during attach command for each unit defined */ -struct ddata_t -{ - uint16 cyl; /* Cylinder head at */ - uint16 tpos; /* Track position */ - uint16 spos; /* Sector position */ -}; +/* Not Used up7 */ + +#ifdef NOUSED +/* registers */ +uint32 star[NUM_UNITS_DISK]; +uint32 attr[NUM_UNITS_DISK]; +#endif /* disk definition structure */ struct disk_t @@ -273,7 +275,6 @@ struct disk_t /* bit 1 mhd */ /* bits 6/7 = 0 768 byte blk */ /* not used on UDP/DPII */ /* = 1 1024 byte blk */ /* not used on UDP/DPII */ -// uint32 geom; /* disk star geometry cyl(16) hsd(8) sec(8) */ } disk_type[] = @@ -286,7 +287,7 @@ disk_type[] = {"MH300", 19, 192, 20, 800, 823, 0x40}, /* 3 823 300M 8127 */ {"MH600", 40, 192, 20, 800, 843, 0x40}, /* 4 843 600M 8155 */ /* For UTX */ - {"9342", 5, 256, 16, 819, 823, 0x40}, /* 5 823 80M */ + {"9342", 5, 256, 16, 819, 823, 0x40}, /* 5 823 80M XXXX */ {"8148", 10, 256, 16, 819, 823, 0x40}, /* 6 823 160M 8148 */ {"9346", 19, 256, 16, 819, 823, 0x40}, /* 7 823 300M */ {"8858", 24, 256, 16, 707, 711, 0x40}, /* 8 711 340M */ @@ -333,6 +334,14 @@ UNIT dda_unit[] = { {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x807)}, /* 7 */ }; +#ifdef NOUSED +REG dda_reg = { + (BRDATAD(STAR, astar, 16, 32, NUM_UNITS_DISK, "Current STAR position"), REG_FIT, + (BRDATAD(ATTR, aattr, 16, 32, NUM_UNITS_DISK, "Disk Attributes"), RET_FIT, + {NULL} +}; +#endif + DIB dda_dib = { disk_preio, /* Pre start I/O */ disk_startcmd, /* Start a command */ @@ -351,7 +360,7 @@ DIB dda_dib = { }; DEVICE dda_dev = { - "DMA", dda_unit, NULL, disk_mod, + "DMA", dda_unit, NULL/*dda_reg*/, disk_mod, NUM_UNITS_DISK, 16, 24, 4, 16, 32, NULL, NULL, &disk_reset, &disk_boot, &disk_attach, &disk_detach, &dda_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, @@ -375,6 +384,13 @@ UNIT ddb_unit[] = { {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC07)}, /* 7 */ }; +#ifdef NOUSED +REG ddb_reg = { + (BRDATAD(STAR, bstar, 16, 32, NUM_UNITS_DISK, "Current STAR position"), REG_FIT, + (BRDATAD(ATTR, battr, 16, 32, NUM_UNITS_DISK, "Disk Attributes"), RET_FIT, + {NULL} +}; +#endif DIB ddb_dib = { disk_preio, /* Pre Start I/O */ @@ -394,7 +410,7 @@ DIB ddb_dib = { }; DEVICE ddb_dev = { - "DMB", ddb_unit, NULL, disk_mod, + "DMB", ddb_unit, NULL, /*ddb_reg*/, disk_mod, NUM_UNITS_DISK, 16, 24, 4, 16, 32, NULL, NULL, &disk_reset, &disk_boot, &disk_attach, &disk_detach, &ddb_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, @@ -418,7 +434,7 @@ uint32 disksec2star(uint32 daddr, int type) uint8 disk_preio(UNIT *uptr, uint16 chan) { DEVICE *dptr = get_dev(uptr); - uint16 addr = GET_UADDR(uptr->CMD); + uint16 chsa = GET_UADDR(uptr->CMD); int unit = (uptr - dptr->units); sim_debug(DEBUG_CMD, dptr, "disk_preio CMD %08x unit %02x\n", uptr->CMD, unit); @@ -426,20 +442,20 @@ uint8 disk_preio(UNIT *uptr, uint16 chan) return SNS_BSY; } - sim_debug(DEBUG_CMD, dptr, "disk_preio unit %02x chsa %04x OK\n", unit, addr); + sim_debug(DEBUG_CMD, dptr, "disk_preio unit %02x chsa %04x OK\n", unit, chsa); return 0; /* good to go */ } uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { - uint16 addr = GET_UADDR(uptr->CMD); + uint16 chsa = GET_UADDR(uptr->CMD); DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); - uint8 ch; + CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ sim_debug(DEBUG_CMD, dptr, - "disk_startcmd addr %04x unit %02x cmd %02x CMD %08x\n", - addr, unit, cmd, uptr->CMD); + "disk_startcmd chsa %04x unit %02x cmd %02x CMD %08x\n", + chsa, unit, cmd, uptr->CMD); 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 */ @@ -455,128 +471,29 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) } sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD continue unit=%02x cmd %02x\n", unit, cmd); - if ((uptr->flags & UNIT_ATT) == 0) { /* see if unit is attached */ - if (cmd == DSK_SNS) { /* not attached, is cmd Sense 0x04 */ - sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD sense\n"); - /* bytes 0,1 - Cyl entry from STAR reg in STAR */ - ch = (uptr->STAR >> 24) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b0 unit=%02x 1 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - ch = (uptr->STAR >> 16) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b1 unit=%02x 1 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - /* byte 2 - Track entry from STAR reg in STAR */ - ch = (uptr->STAR >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b2 unit=%02x 1 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - /* byte 3 - Sector entry from STAR reg in STAR */ - ch = (uptr->STAR) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b3 unit=%02x 1 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - /* bytes 4 - mode reg, byte 0 of SNS */ - ch = (uptr->SNS >> 24) & 0xff; /* return the sense data for device */ - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%02x 1 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - /* bytes 5-7 - status bytes, bytes 1-3 of SNS */ - ch = (uptr->SNS >> 16) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%02x %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - ch = (uptr->SNS >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%02x 3 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - ch = (uptr->SNS) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%02x 4 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - /* bytes 8-11 - drive attribute register (DATR) entries from uptr->ATTR - * via INCH cmd */ - ch = (uptr->ATTR >> 24) & 0xff; - chan_write_byte(addr, &ch) ; - ch = (uptr->ATTR >> 16) & 0xff; - chan_write_byte(addr, &ch) ; - ch = (uptr->ATTR >> 8 ) & 0xff; - chan_write_byte(addr, &ch) ; - ch = (uptr->ATTR >> 0) & 0xff; - chan_write_byte(addr, &ch) ; - /* bytes 12 & 13 contain drive related status */ - ch = 0; /* zero for now */ - chan_write_byte(addr, &ch) ; - chan_write_byte(addr, &ch) ; - - uptr->SNS &= 0xff000000; /* clear status bytes, but leave mode data */ - return SNS_CHNEND|SNS_DEVEND; - } - if (cmd == 0x0) /* INCH cmd gives unit check */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - - uptr->SNS |= (SNS_INTVENT|SNS_CMDREJ); /* set new error status */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* we done */ - } - /* Unit is online, so process a command */ switch (cmd) { - case DSK_INCH: /* INCH 0x0 */ - { - uint32 mema; /* memory address */ - uint32 i; - UNIT *up = dptr->units; /* first unit for this device */ + case DSK_INCH: /* INCH cmd 0x0 */ sim_debug(DEBUG_CMD, dptr, - "disk_startcmd starting INCH cmd, addr %04x MemBuf %06x\n", - addr, uptr->u4); - /* STAR (u4) has IOCD word 1 contents. For the disk processor it contains */ - /* a pointer to the INCH buffer followed by 8 drive attribute words that */ - /* contains the flags, sector count, MHD head count, and FHD count */ - /* us9 has the byte count from IOCD wd2 and should be 0x24 (36) */ - /* the INCH buffer address must be returned in u4 and us9 left non-zero */ - /* just return OK and channel software will use u4 as status buffer addr */ - mema = (uint32)uptr->u4; /* get memory address of buffer */ - uptr->u4 = M[mema>>2]; /* get status buffer address for XIO return status */ - sim_debug(DEBUG_CMD, dptr, - "disk_startcmd starting INCH cmd addr %04x StatAdr %06x mema %06x units %02x\n", - addr, uptr->u4, mema, dptr->numunits); - /* the next 8 words have drive data for each unit */ - /* WARNING 8 drives must be defined for this controller */ - /* so we will not have a map fault */ - for (i=0; inumunits && i<8; i++) { /* process all drives */ - int type = GET_TYPE(up->flags); /* get disk type */ - up->ATTR = M[(mema>>2)+i+1]; /* save each unit's drive data */ - /* see if sec/trk and num hds are set, if not set them */ - if ((up->ATTR & 0x00ff0000) == 0) - up->ATTR = (up->ATTR & 0xff00ffff) | ((disk_type[type].spt & 0xff) << 16); - if ((up->ATTR & 0x0000ff00) == 0) - up->ATTR = (up->ATTR & 0xffff00ff) | ((disk_type[type].nhds & 0xff) << 8); - sim_debug(DEBUG_CMD, dptr, - "disk_startcmd ATTR data %08x unit %02x flags %02x sec %02x MHD %02x FHD %02x\n", - up->ATTR, i, (up->ATTR >> 24)&0xff, (up->ATTR >> 16)&0xff, - (up->ATTR >> 8)&0xff, (up->ATTR&0xff)); - up++; /* next unit for this device */ - } - sim_debug(DEBUG_CMD, dptr, "disk_startcmd done INCH cmd addr %04x\n", addr); + "disk_startcmd starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n", + uptr->u4, chsa, chp->ccw_addr, chp->ccw_count); + uptr->CMD |= DSK_INCH2; /* use 0xf0 for inch, just need int */ sim_activate(uptr, 20); /* start things off */ return 0; break; - } case DSK_SCK: /* Seek command 0x07 */ case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ -// uptr->CMD &= ~(DSK_STAR); /* show we do not have seek STAR in STAR */ case DSK_WD: /* Write command 0x01 */ case DSK_RD: /* Read command 0x02 */ case DSK_LMR: /* read mode register */ uptr->CMD |= cmd; /* save cmd */ sim_debug(DEBUG_CMD, dptr, - "disk_startcmd starting disk seek r/w cmd %02x addr %04x\n", - cmd, addr); + "disk_startcmd starting disk seek r/w cmd %02x chsa %04x\n", + cmd, chsa); sim_activate(uptr, 20); /* start things off */ return 0; break; @@ -618,8 +535,8 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) } sim_debug(DEBUG_CMD, dptr, - "disk_startcmd done with disk_startcmd %02x addr %04x SNS %08x\n", - cmd, addr, uptr->SNS); + "disk_startcmd done with disk_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 */ @@ -631,27 +548,24 @@ t_stat disk_srv(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->CMD); DEVICE *dptr = get_dev(uptr); - DIB *dibp = (DIB *)dptr->ctxt; - /* get pointer to Dev Info Blk for this device */ - CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */ - struct ddata_t *data = (struct ddata_t *)(uptr->DDATA); + DIB *dibp = (DIB *)dptr->ctxt; /* get DIB address */ + CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */ int cmd = uptr->CMD & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); -// uint32 trk, cyl, sec; - uint32 trk, cyl; + uint32 trk, cyl, sec; int unit = (uptr - dptr->units); int len; int i; uint8 ch; uint16 ssize = disk_type[type].ssiz * 4; /* disk sector size in bytes */ - uint32 tsize = disk_type[type].spt * ssize; /* get track size in bytes */ uint32 tstart; uint8 buf2[1024]; uint8 buf[1024]; sim_debug(DEBUG_CMD, dptr, "disk_srv entry unit %02x CMD %08x chsa %04x count %04x %x/%x/%x \n", - unit, uptr->CMD, chsa, chp->ccw_count, data->cyl, data->tpos, data->spos); + 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 */ @@ -660,21 +574,93 @@ t_stat disk_srv(UNIT *uptr) } sim_debug(DEBUG_CMD, dptr, - "disk_srv cmd=%02x chsa %04x count %04x\n", - cmd, chsa, chp->ccw_count); + "disk_srv cmd=%02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); + switch (cmd) { case 0: /* No command, stop disk */ break; - case DSK_INCH2: /* use 0xff for inch, just need int */ + case DSK_INCH2: /* used 0xff for inch, just need int */ + { + uint32 mema; /* memory address */ +// uint32 daws[8]; /* drive attribute registers */ +// uint32 i, j; + uint32 i; + + 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); + + /* mema has IOCD word 1 contents. For the disk processor it contains */ + /* a pointer to the INCH buffer followed by 8 drive attribute words that */ + /* contains the flags, sector count, MHD head count, and FHD count */ + /* len has the byte count from IOCD wd2 and should be 0x24 (36) */ + /* the INCH buffer address must be set for the parrent channel as well */ + /* 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; + } + + /* read all 36 bytes, stopping every 4 bytes to make words */ + /* the first word has the inch buffer address */ + /* the next 8 words have drive data for each unit */ + /* WARNING 8 drives must be defined for this controller */ + /* so we will not have a map fault */ +// for (i=0, j=0; i < 36; i++) { + for (i=0; i < 36; i++) { + if (chan_read_byte(chsa, &buf[i])) { + /* we have error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (((i+1)%4) == 0) { /* see if we have a word yet */ + if (i == 3) + /* inch buffer address */ + mema = (buf[0]<<24) | (buf[1]<<16) | + (buf[2]<<8) | (buf[3]); + else + /* drive attribute registers */ + // daws[j++] = (buf[i-3]<<24) | (buf[i-2]<<16) + // | (buf[i-1]<<8) | (buf[i]); + /* may want to use this later */ + /* clear warning errors */ + tstart = (buf[i-3]<<24) | (buf[i-2]<<16) + | (buf[i-1]<<8) | (buf[i]); + } + } + /* now call set_inch() function to write and test inch bybber addresses */ + 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; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } +#endif uptr->CMD &= ~(0xffff); /* remove old cmd */ - sim_debug(DEBUG_CMD, dptr, "disk_srv cmd INCH chsa %04x count %04x completed\n", - chsa, chp->ccw_count); + sim_debug(DEBUG_CMD, dptr, + "disk_srv cmd INCH chsa %04x addr %06x count %04x completed\n", + chsa, mema, chp->ccw_count); #ifdef FIX4MPX chan_end(chsa, SNS_CHNEND); /* return just channel end OK */ #else chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ #endif + } break; case DSK_WSL: /* WSL 0x31 make into NOP */ @@ -682,10 +668,10 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "disk_srv cmd WSL chsa %04x count %04x completed\n", chsa, chp->ccw_count); + sim_debug(DEBUG_DETAIL, dptr, "Sector 1 label"); /* now read sector label data */ len = chp->ccw_count; -// for (i = 0; i < 30; i++) { for (i = 0; i < len; i++) { if (chan_read_byte(chsa, &buf[i])) { /* we have write error, bail out */ @@ -693,7 +679,6 @@ t_stat disk_srv(UNIT *uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } -// if (i == 16) if ((i%16) == 0) sim_debug(DEBUG_DETAIL, dptr, "\nSector 1 label"); sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); @@ -736,51 +721,30 @@ t_stat disk_srv(UNIT *uptr) break; case DSK_SNS: /* 0x4 */ -#ifdef OLD_WAY - ch = uptr->SNS & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%02x 1 %02x\n", unit, ch); - chan_write_byte(chsa, &ch) ; - ch = (uptr->SNS >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%02x 2 %02x\n", unit, ch); - chan_write_byte(chsa, &ch) ; - ch = 0; - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%02x 3 %02x\n", unit, ch); - chan_write_byte(chsa, &ch) ; - ch = unit; - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%02x 4 %02x\n", unit, ch); - chan_write_byte(chsa, &ch) ; - ch = 4; - uptr->CMD &= ~(0xff00); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - break; -#else sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD sense\n"); - /* bytes 0,1 - Cyl entry from STAR reg in STAR */ -// ch = (uptr->STAR >> 24) & 0xff; - ch = (data->cyl >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_srv sense STAR b0 unit=%02x 1 %02x\n", + /* 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", unit, ch); chan_write_byte(chsa, &ch); -// ch = (uptr->STAR >> 16) & 0xff; - ch = (data->cyl) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_srv sense STAR b1 unit=%02x 2 %02x\n", + ch = (uptr->CHS >> 16) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "disk_srv sense CHS b1 unit=%02x 2 %02x\n", unit, ch); chan_write_byte(chsa, &ch); - /* byte 2 - Track entry from STAR reg in STAR */ -// ch = (uptr->STAR >> 8) & 0xff; - ch = (data->tpos) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_srv sense STAR b2 unit=%02x 3 %02x\n", + /* byte 2 - Track entry from CHS reg */ + ch = (uptr->CHS >> 8) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "disk_srv sense CHS b2 unit=%02x 3 %02x\n", unit, ch); chan_write_byte(chsa, &ch); - /* byte 3 - Sector entry from STAR reg in STAR */ -// ch = (uptr->STAR) & 0xff; - ch = (data->spos) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_srv sense STAR b3 unit=%02x 4 %02x\n", + /* byte 3 - Sector entry from CHS reg */ + ch = (uptr->CHS) & 0xff; + 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 */ - ch = (uptr->SNS >> 24) & 0xff; /* return the sense data for device */ + ch = (uptr->SNS >> 24) & 0xff; /* return the sense data */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv sense unit=%02x 1 %02x\n", unit, ch); chan_write_byte(chsa, &ch); @@ -797,24 +761,25 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_DETAIL, dptr, "disk_srv sense unit=%02x 4 %02x\n", unit, ch); chan_write_byte(chsa, &ch); - /* bytes 8-11 - drive attribute register (DATR) entries from uptr->ATTR via - * INCH cmd */ - ch = (uptr->ATTR >> 24) & 0xff; + + /* bytes 8-11 - drive mode register entries from assigned disk */ + ch = disk_type[type].type & 0xff; /* type byte */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv datr unit=%02x 1 %02x\n", unit, ch); chan_write_byte(chsa, &ch); - ch = (uptr->ATTR >> 16) & 0xff; + ch = disk_type[type].spt & 0xff; /* get sectors per track */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv datr unit=%02x 2 %02x\n", unit, ch); chan_write_byte(chsa, &ch); - ch = (uptr->ATTR >> 8 ) & 0xff; + ch = disk_type[type].nhds & 0xff; /* get # MHD heads */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv datr unit=%02x 3 %02x\n", unit, ch); chan_write_byte(chsa, &ch); - ch = (uptr->ATTR >> 0) & 0xff; + ch = 0; /* no FHD heads */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv datr unit=%02x 4 %02x\n", unit, ch); chan_write_byte(chsa, &ch); + /* bytes 12 & 13 are optional, so check if read done */ /* TODO add drive status bits here */ if ((test_write_byte_end(chsa)) == 0) { @@ -829,93 +794,45 @@ t_stat disk_srv(UNIT *uptr) unit, ch); chan_write_byte(chsa, &ch); } -//NEW uptr->SNS &= 0xff000000; /* clear status bytes, but leave mode data */ -//TRY uptr->CMD &= ~(0xff00); /* clear busy status */ uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; -#endif - 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 ((int32)(uptr->STAR >> 16) == (int32)data->cyl) { + if (STAR2CYL(uptr->STAR) == STAR2CYL(uptr->CHS)) { /* we are on cylinder, seek is done */ - sim_debug(DEBUG_CMD, dptr, "dsk_srv seek on cylinder unit=%02x %02x %04x\n", - unit, uptr->STAR >> 16, data->cyl); + sim_debug(DEBUG_CMD, dptr, "disk_srv seek on cylinder unit=%02x %04x %04x\n", + unit, uptr->STAR >> 16, uptr->CHS >> 16); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ -// set_devattn(chsa, SNS_DEVEND); /* start the operation */ - sim_debug(DEBUG_CMD, dptr, "dsk_srv seek end unit=%02x %02x %04x\n", - unit, uptr->STAR >> 16, data->cyl); + /* we have already seeked to the required sector */ + /* we do not need to seek again, so move on */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); sim_activate(uptr, 20); break; } else { -#ifndef TRYTHIS - data->cyl = ((uptr->STAR >> 16)&0xffff); + /* we have wasted enough time, we there */ + uptr->CHS = uptr->STAR; /* we are there */ sim_activate(uptr, 10); break; -#else - /* Compute delay based of difference. */ - /* Set next state = index */ - i = (int32)((uptr->STAR >> 16)&0xffff) - (int32)data->cyl; - sim_debug(DEBUG_CMD, dptr, "dsk_srv seek unit=%02x %02x %04x\n", - unit, uptr->STAR >> 16, i); - if (i > 0 ) { - if (i > 50) { - data->cyl += 50; /* seek 50 cyl */ - sim_activate(uptr, 800); - } else - if (i > 20) { - data->cyl += 20; /* seek 20 cyl */ - sim_activate(uptr, 400); - } else { - data->cyl++; /* Seek 1 cyl */ - sim_activate(uptr, 200); - } - if (data->cyl >= (int)disk_type[type].cyl) /* test for over max */ - data->cyl = disk_type[type].cyl-1; /* make max */ - } else { - if (i < -50) { - data->cyl -= 50; /* seek 50 cyl */ - sim_activate(uptr, 800); - } else - if (i < -20) { - data->cyl -= 20; /* seek 20 cyl */ - sim_activate(uptr, 400); - } else { - data->cyl--; /* seek 1 cyl */ - sim_activate(uptr, 200); - } - if ((int32)data->cyl < 0) /* test for less than zero */ - data->cyl = 0; /* make zero */ - } -#endif - sim_debug(DEBUG_DETAIL, dptr, - "dsk_srv seek next unit=%02x %02x %04x\n", - unit, uptr->STAR >> 16, data->cyl); -#ifdef OLD_WAY - sim_activate(uptr, 2); -#else -/*BAD?*/ sim_activate(uptr, 10); -#endif - break; } } /* not seeking, so start a new seek */ /* set buf data to current STAR values */ - buf[0] = (data->cyl >> 8) & 0xff; - buf[1] = (data->cyl) & 0xff; - buf[2] = (data->tpos) & 0xff; - buf[3] = (data->spos) & 0xff; - sim_debug(DEBUG_CMD, dptr, "disk_srv STAR unit=%02x star %02x %02x %02x %02x\n", + 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 */ + + sim_debug(DEBUG_CMD, dptr, + "disk_srv current STAR unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); - /* Read in 4 character seek code */ + /* Read in 1-4 character seek code */ for (i = 0; i < 4; i++) { if (chan_read_byte(chsa, &buf[i])) { if (i == 0) { @@ -938,25 +855,32 @@ t_stat disk_srv(UNIT *uptr) buf[0] = buf[1] = buf[2] = buf[3] = 0; } /* else the cyl, trk, and sect 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]); rezero: sim_debug(DEBUG_DETAIL, dptr, "disk_srv seek unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); + /* save STAR (target sector) data in STAR */ uptr->STAR = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]); - cyl = (uptr->STAR >> 16) & 0xffff; /* get the cylinder */ + cyl = STAR2CYL(uptr->STAR); /* get the cylinder */ trk = buf[2]; /* get the track */ + sim_debug(DEBUG_DETAIL, dptr, - "disk_srv SEEK cyl %04x trk %02x sec %02x unit=%02x\n", + "disk_srv NEW SEEK cyl %04x trk %02x sec %02x unit=%02x\n", cyl&0xffff, trk, buf[3], unit); /* Check if seek valid */ if (cyl >= disk_type[type].cyl || trk >= disk_type[type].nhds || - buf[3] >= disk_type[type].spt) { + buf[3] >= disk_type[type].spt) { + sim_debug(DEBUG_CMD, dptr, "disk_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 */ @@ -965,36 +889,37 @@ rezero: break; } -// uptr->CMD |= DSK_STAR; /* show we have seek STAR in STAR */ - /* calc the sector address of data */ + /* calc the new sector address of data */ /* calculate file position in bytes of requested sector */ -//LAST tstart = (((cyl * disk_type[type].nhds * tsize) + (trk * tsize) + buf[3]) * ssize); - tstart = (cyl * disk_type[type].nhds * tsize) + (trk * tsize) + (buf[3] * ssize); - data->tpos = trk; /* save the track/head number */ - data->spos = buf[3]; /* save the sector number */ + /* file offseet 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]); + sim_debug(DEBUG_DETAIL, dptr, "disk_srv seek start %04x cyl %04x trk %02x sec %02x\n", tstart, cyl, trk, buf[3]); + /* 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_DETAIL, dptr, "dsk_srv Error on seek to %04x\n", tstart); + sim_debug(DEBUG_DETAIL, dptr, "disk_srv Error on seek to %04x\n", tstart); } /* Check if already on correct cylinder */ - if (cyl != data->cyl) { - /* Do seek */ + /* if not, do a delay to slow things down */ + if (STAR2CYL(uptr->STAR) != STAR2CYL(uptr->CHS)) { + /* Do a fake seek to kill time */ uptr->CMD |= DSK_SEEKING; /* show we are seeking */ sim_debug(DEBUG_DETAIL, dptr, - "dsk_srv seek unit=%02x cyl %04x trk %02x cyl %02x\n", + "disk_srv seeking unit=%02x to cyl %04x trk %02x sec %02x\n", unit, cyl, trk, buf[3]); sim_activate(uptr, 20); /* start us off */ -//WHAT? chan_end(chsa, SNS_CHNEND); } else { + /* we are on cylinder/track/sector, so go on */ sim_debug(DEBUG_DETAIL, dptr, - "dsk_srv calc sect addr seek start %04x cyl %04x trk %02x sec %02x\n", + "disk_srv done seeking to %04x cyl %04x trk %02x sec %02x\n", tstart, cyl, trk, buf[3]); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ -// sim_activate(uptr, 20); chan_end(chsa, SNS_DEVEND|SNS_CHNEND); } return SCPE_OK; @@ -1004,6 +929,7 @@ rezero: 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 |= DSK_SCK; /* show as seek command */ tstart = 0; /* byte offset is 0 */ @@ -1042,15 +968,23 @@ rezero: if ((uptr->CMD & DSK_READING) == 0) { /* see if we are reading data */ uptr->CMD |= DSK_READING; /* read from disk starting */ sim_debug(DEBUG_CMD, dptr, - "DISK READ starting unit=%02x CMD %08x\n", unit, uptr->CMD); + "DISK READ starting CMD %08x chsa %04x buffer %06x count %04x\n", + uptr->CMD, chsa, chp->ccw_addr, chp->ccw_count); } if (uptr->CMD & DSK_READING) { /* see if we are reading data */ + cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ + sec = uptr->CHS & 0xff; /* get sec */ + /* get sector offset */ +// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)); + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* 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, data->cyl, data->tpos, data->spos); + len, ssize, cyl, trk, sec); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -1059,13 +993,14 @@ rezero: sim_debug(DEBUG_CMD, dptr, "disk_srv after READ chsa %04x buffer %06x count %04x\n", chsa, chp->ccw_addr, chp->ccw_count); + /* process the next sector of data */ for (i=0; iccw_count, data->cyl, data->tpos, data->spos); + "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; @@ -1073,43 +1008,41 @@ rezero: } sim_debug(DEBUG_CMD, dptr, - "DISK READ %04x bytes leaving %4x to be read from diskfile /%04x/%02x/%02x\n", - ssize, chp->ccw_count, data->cyl, data->tpos, data->spos); - data->spos++; - /* set sector to read next one */ - if (data->spos >= (disk_type[type].spt)) { - data->spos = 0; /* number of sectors per track */ - data->tpos++; /* track position */ - if (data->tpos >= (disk_type[type].nhds)) { - data->tpos = 0; /* number of tracks per cylinder */ - data->cyl++; /* cylinder position */ - if (data->cyl >= (int)(disk_type[type].cyl)) { - /* EOM reached, abort */ - sim_debug(DEBUG_CMD, dptr, - "DISK Read reached EOM for read from disk @ /%04x/%02x/%02x\n", - data->cyl, data->tpos, data->spos); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - data->cyl = 0; /* reset cylinder position */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - } - } + "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); + /* 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", - data->cyl, data->tpos, data->spos); + 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; - } else { - sim_debug(DEBUG_DATA, dptr, - "DISK sector read complete, %x bytes to go from diskfile /%04x/%02x/%02x\n", - chp->ccw_count, data->cyl, data->tpos, data->spos); - sim_activate(uptr, 10); /* wait to read next sector */ + } + + /* tstart has file offset in sectors */ + tstart++; /* bump to next sector */ + /* convert sect back to chs value */ + uptr->CHS = disksec2star(tstart, type); + /* see of over end of disk */ +// if (tstart >= CAPB(type)) { + if (tstart >= CAP(type)) { + /* EOM reached, abort */ + sim_debug(DEBUG_CMD, dptr, + "DISK Read reached EOM for read from disk @ /%04x/%02x/%02x\n", + STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CHS = 0; /* reset cylinder position */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); 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)); + sim_activate(uptr, 10); /* wait to read next sector */ + break; rddone: uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ } @@ -1122,6 +1055,13 @@ rddone: "DISK WRITE starting unit=%02x CMD %02x\n", unit, uptr->CMD); } if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */ + cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ + sec = uptr->CHS & 0xff; /* get sec */ + /* get sector offset */ +// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)); + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* process the next sector of data */ len = 0; /* used here as a flag for short read */ for (i=0; iCMD &= ~(0xffff); /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "DISK Wrote %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", - ssize, data->cyl, data->tpos, data->spos); + ssize, cyl, trk, sec); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); goto wrdone; } @@ -1140,11 +1080,12 @@ rddone: } buf2[i] = ch; /* save the char */ } + /* 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, data->cyl, data->tpos, data->spos); + i, ssize, cyl, trk, sec); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -1152,31 +1093,30 @@ rddone: if (len != 0) { /* see if done with write command */ sim_debug(DEBUG_DATA, dptr, "DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", - ssize, data->cyl, data->tpos, data->spos); + ssize, cyl, trk, sec); uptr->CMD &= ~(0xffff); /* 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 %0x4x bytes end %04x to diskfile cyl %04x hds %02x sec %02x\n", - len, ssize, data->cyl, data->tpos, data->spos); - data->spos++; - if (data->spos >= (disk_type[type].spt)) { - data->spos = 0; /* number of sectors per track */ - data->tpos++; /* track position */ - if (data->tpos >= (disk_type[type].nhds)) { - data->tpos = 0; /* number of tracks per cylinder */ - data->cyl++; /* cylinder position */ - if (data->cyl >= (int)(disk_type[type].cyl)) { - /* EOM reached, abort */ - sim_debug(DEBUG_DETAIL, dptr, - "Error %08x on write %04x to diskfile cyl %04x hds %02x sec %02x\n", - i, ssize, data->cyl, data->tpos, data->spos); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - } + "DISK WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x\n", + len, ssize, cyl, trk, sec); + + /* 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 >= CAPB(type)) { + if (tstart >= 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->CMD &= ~(0xffff); /* 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; @@ -1203,62 +1143,36 @@ wrdone: /* 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 = (uptr->STAR >> 16) & 0xffff; /* get the cylinder */ -// trk = (uptr->STAR >> 8) & 0xff; /* get the track */ -// sec = (uptr->STAR) & 0xff; /* get the sector */ - sim_debug(DEBUG_CMD, dptr, "disk_startcmd RSL STAR %08x disk geom %08x\n", - uptr->STAR, GEOM(type)); + uptr->CHS, GEOM(type)); -#ifdef OLD_WAY - buf[0] = (data->cyl >> 8) & 0xff; /* lcyl cyl upper 8 bits */ - buf[1] = data->cyl & 0xff; /* lcyl cyl lower 8 bits */ - buf[2] = data->tpos & 0xff; /* ltkn trk */ - buf[3] = data->spos & 0xff; /* lid sector ID */ + /* 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 */ 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]); - cyl = disk_type[type].cyl-1; /* last cyl */ - trk = disk_type[type].nhds-1; /* last head number */ - sec = disk_type[type].spt-1; /* last sector number */ - -// daddr = (cap-1) - (3 * csize) - ((nhds - 2) * tsize); - tstart = (((cyl * disk_type[type].nhds) * disk_type[type].spt) + - (trk * disk_type[type].spt) + sec); /* last sector address */ - tstart = tstart - (3 * disk_type[type].nhds * disk_type[type].spt); - tstart = tstart - (2 * disk_type[type].spt) + 1; - /* UTX dmap at daddr - 32 sec (2 tracks) */ - tstart = tstart - (2 * disk_type[type].spt); -#else /* get sector address of UTX media descriptor */ + /* 819/7/0 is right for 8887, 819/16/0 for 9346 */ tstart = ((CYL(type)-4) * SPC(type)) + ((HDS(type)-2) * SPT(type)) - SPT(type); -#endif 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]); -#ifdef OLD_WAY - cyl = disk_type[type].cyl-3; /* cyl */ - trk = disk_type[type].nhds-2; /* head */ - sec = 0; /* last sector number */ -// daddr = (cap-1) - (3 * csize) - ((nhds - 2) * tsize); - sim_debug(DEBUG_CMD, dptr, - "disk_srv RSL sector %d %x star %02x %02x %02x %02x\n", - tstart, tstart, cyl>>8, cyl&0xff, trk, sec); -#endif - /* on HSDP DMAP is in wd 3 on label 0 */ /* on HSDP UMAP is in wd 4 on label 1 */ /* on UDP & DPII DMAP is in wd 3 on label 0 */ /* on UDP & DPII UMAP is in wd 4 on label 0 */ -// tstart = 0x440aa; /* 819/0/7 logical 278698 */ - tstart = (tstart * (SPT(type) - 1))/SPT(type); /* make logical */ +// tstart = 0x3cd90; /* 819/16/0 physical 249232 */ + /* the address must be physical for UDP */ /* store into sec 1 label */ buf[16] = (tstart >> 24) & 0xff; /* UMAP pointer */ buf[17] = (tstart >> 16) & 0xff; @@ -1309,19 +1223,26 @@ wrdone: for (i = 0; i < 30; i++) buf[i] = 0; - /* set buf data to current STAR values */ -// cyl = (uptr->STAR >> 16) & 0xffff; /* get the cylinder */ -// trk = (uptr->STAR >> 8) & 0xff; /* get the track */ -// sec = (uptr->STAR) & 0xff; /* get the sector */ + /* set buf data to current CHS values */ + if (uptr->CHS == 0) { /* write last address on trk 0 */ + cyl = CYL(type)-1; /* lcyl cyl upper 8 bits */ + trk = HDS(type)-1; /* ltkn trk */ + sec = SPT(type)-1; /* lid sector ID */ + } else { + /* write current address on other tracks */ + cyl = (uptr->CHS >> 16) & 0xffff; /* get the cylinder */ + trk = (uptr->CHS >> 8) & 0xff; /* get the track */ + sec = (uptr->CHS) & 0xff; /* get the sector */ + } sim_debug(DEBUG_CMD, dptr, "disk_startcmd RTL STAR %08x disk geom %08x\n", - uptr->STAR, GEOM(type)); + uptr->CHS, GEOM(type)); /* set buf data to current STAR values */ - buf[0] = (data->cyl >> 8) & 0xff; /* lcyl cyl upper 8 bits */ - buf[1] = data->cyl & 0xff; /* lcyl cyl lower 8 bits */ - buf[2] = data->tpos & 0xff; /* ltkn trk */ - buf[3] = data->spos & 0xff; /* lid sector ID */ + buf[0] = (cyl >> 8) & 0xff; /* lcyl cyl upper 8 bits */ + buf[1] = cyl & 0xff; /* lcyl cyl lower 8 bits */ + buf[2] = trk & 0xff; /* ltkn trk */ + buf[3] = sec & 0xff; /* lid sector ID */ buf[4] = 0x80; /* show good sector */ sim_debug(DEBUG_DETAIL, dptr, @@ -1336,35 +1257,16 @@ wrdone: /* previous track, so MDT = VDT-SPT is CYL-4/HDS-2/0 */ /* The UTX flaw map is at FMAP = MDT-SPT CYL-4/HDS-3/0 */ /* UTX media map is 1 track lower at UTXMM=FMAP-SPT CYL-4/HDS-4/0 */ - /* The UTX med map is pointed to by sector label 1 */ + /* The UTX media map is pointed to by sector label 1 */ /* simulate pointers here, set wd[3] in label to VDT */ -#ifdef OLD_WAY - /* the dmap pointer is placed by the vendor of diag into track 0 */ - /* simulate pointer here */ -// i = 250191; /* 0x3d14f 337/13/0F */ /* dmap sector address */ - cyl = disk_type[type].cyl-1; /* last cyl */ - trk = disk_type[type].nhds-1; /* last head number */ - sec = disk_type[type].spt-1; /* last sector number */ -// daddr = (cap) - (3 * csize) - (2 * tsize); - tstart = (((cyl * disk_type[type].nhds) * disk_type[type].spt) + - (trk * disk_type[type].spt) + sec); /* last sector address */ - tstart = tstart - (3 * disk_type[type].nhds * disk_type[type].spt); - tstart = tstart - (2 * disk_type[type].spt) + 1; -// tstart = 249248; - /* vaddr is (cap) - 3 cyl - 8 sec */ -//BAD tstart = ((cyl-3) * (trk+1) * (sec+1)) - 8; /* 249256 0x3cda8 */ -// tstart = ((cyl-3) * (trk+1) * (sec+1)) - -// (2 * (trk+1) * (sec+1)); /* 249248 0x3cda0 */ -#else - /* get sector address of vendor defect table */ - /* 249264 (819/17/0) for 9346 - 823/19/16 */ + /* get sector address of media defect table */ + /* 249264 (819/17/0) 0x3cda0 for 9346 - 823/19/16 */ tstart = (CYL(type)-4) * SPC(type) + (HDS(type)-2) * SPT(type); cyl = disk_type[type].cyl-1; /* last cyl */ trk = disk_type[type].nhds-1; /* last head number */ // sec = disk_type[type].spt-1; /* last sector number */ -#endif sim_debug(DEBUG_CMD, dptr, "disk_srv RTL STAR %04x/%02x/%02x Dmap pointer 0x%08x %d\n", @@ -1373,7 +1275,7 @@ wrdone: "disk_srv TRK0 RTL sector %d %x star %02x %02x %02x %02x\n", tstart, tstart, buf[0], buf[1], buf[2], buf[3]); - if (uptr->STAR == 0) { /* only write dmap address in trk 0 */ + if (uptr->CHS == 0) { /* only write dmap address in trk 0 */ /* output last sector address of disk */ buf[12] = (tstart >> 24) & 0xff; /* DMAP pointer */ buf[13] = (tstart >> 16) & 0xff; @@ -1381,6 +1283,19 @@ wrdone: buf[15] = (tstart) & 0xff; } +#ifndef NOTNOW + /* get sector address of umap table */ + /* 249232 (819/16/0) 0x3cd90 for 9346 - 823/19/16 */ + tstart -= SPT(type); /* calc utxfmap address */ + /* the address must be physical for UDP */ + if (uptr->CHS == 0) { /* only write dmap address on trk 0 */ + buf[16] = (tstart >> 24) & 0xff; /* ldeallp UMAP */ + buf[17] = (tstart >> 16) & 0xff; + buf[18] = (tstart >> 8) & 0xff; + buf[19] = (tstart) & 0xff; + } +#endif + /* the tech doc shows the cyl/trk/sec data is in the first 4 bytes */ /* of the track label, BUT it is really in the configuration data */ /* area too. That is where UTX looks. Byte 27 is sectors/track */ @@ -1420,8 +1335,8 @@ wrdone: chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } - sim_debug(DEBUG_DETAIL, dptr, "disk_srv done cmd=%02x chsa %04x count %04x\n", - cmd, chsa, chp->ccw_count); + sim_debug(DEBUG_DETAIL, dptr, + "disk_srv done cmd=%02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); return SCPE_OK; } @@ -1448,8 +1363,6 @@ t_stat disk_reset(DEVICE *dptr) /* create the disk file for the specified device */ int disk_format(UNIT *uptr) { -// struct ddata_t *data = (struct ddata_t *)uptr->up7; -// uint16 addr = GET_UADDR(uptr->CMD); int type = GET_TYPE(uptr->flags); DEVICE *dptr = get_dev(uptr); uint32 ssize = disk_type[type].ssiz * 4; /* disk sector size in bytes */ @@ -1463,11 +1376,11 @@ int disk_format(UNIT *uptr) { /* last sector address of disk (cyl * hds * spt) - 1 */ uint32 laddr = CAP(type) - 1; /* last sector of disk */ /* get sector address of vendor defect table */ - /* put data = 0xf0000004 0xf4000000 */ + /* put data = 0xf0000000 0xf4000004 */ int32 vaddr = (CYL(type)-4) * SPC(type) + (HDS(type)-1) * SPT(type); /* get sector address of utx diag map track 0 pointer */ /* put data = 0xf0000000 + (cyl-1), 0x8a000000 + daddr, */ - /* 0x9a000000 + (cyl-1), 0xf4000000 */ + /* 0x9a000000 + (cyl-1), 0xf4000008 */ int32 daddr = vaddr - SPT(type); /* get sector address of utx flaw map sec 1 pointer */ /* use this address for sec 1 label pointer */ @@ -1491,6 +1404,7 @@ int disk_format(UNIT *uptr) { }; #else { + /* try to makeup a utx dmap */ // 0xf003d14f,0x8a03cda0,0x9a03cdbf,0x8903cdc0, // 0x9903d01f,0x8c03d020,0x9c03d14f,0xf4000000, 0xf0000000 | (cap-1), 0x8a000000 | daddr, @@ -1507,7 +1421,8 @@ int disk_format(UNIT *uptr) { /* vendor flaw map */ uint32 vmap[2] = {0xf0000004, 0xf4000000}; uint32 dmap[4] = {0xf0000000 | (cap-1), 0x8a000000 | daddr, - 0x9a000000 | (cap-1), 0xf4000000}; + 0x9a000000 | (cap-1), 0xf4000008}; +//TRY 0x9a000000 | (cap-1), 0xf4000000}; /* see if user wants to initialize the disk */ if (!get_yn("Initialize disk? [Y] ", TRUE)) { @@ -1565,8 +1480,7 @@ int disk_format(UNIT *uptr) { fputc('\n', stderr); /* byte swap the buffers for dmap and umap */ -// for (i=0; i<256; i++) { - for (i=0; i<8; i++) { + for (i=0; i<256; i++) { umap[i] = (((umap[i] & 0xff) << 24) | ((umap[i] & 0xff00) << 8) | ((umap[i] & 0xff0000) >> 8) | ((umap[i] >> 24) & 0xff)); } @@ -1612,9 +1526,9 @@ int disk_format(UNIT *uptr) { "Error on dmap write to diskfile sect %06x\n", daddr * ssize); } -#ifdef MAYBE +#ifndef MAYBE sim_fseek(uptr->fileref, (uaddr)*ssize, SEEK_SET); /* seek UMAP */ - if ((sim_fwrite((char *)&umap, sizeof(uint32), 4, uptr->fileref)) != 4) { + if ((sim_fwrite((char *)&umap, sizeof(uint32), 256, uptr->fileref)) != 256) { sim_debug(DEBUG_CMD, dptr, "Error on umap write to diskfile sect %06x\n", uaddr * ssize); } @@ -1631,19 +1545,17 @@ int disk_format(UNIT *uptr) { /* seek home again */ sim_fseek(uptr->fileref, 0, SEEK_SET); /* seek home */ free(buff); /* free cylinder buffer */ -// set_devattn(addr, SNS_DEVEND); /* start us up */ return 0; } /* attach the selected file to the disk */ t_stat disk_attach(UNIT *uptr, CONST char *file) { - uint16 addr = GET_UADDR(uptr->CMD); + uint16 chsa = GET_UADDR(uptr->CMD); int type = GET_TYPE(uptr->flags); DEVICE *dptr = get_dev(uptr); t_stat r; uint32 ssize; /* sector size in bytes */ - struct ddata_t *data; uint8 buff[1024]; /* see if valid disk entry */ @@ -1656,14 +1568,6 @@ t_stat disk_attach(UNIT *uptr, CONST char *file) if ((r = attach_unit(uptr, file)) != SCPE_OK) return r; - /* get a buffer to hold disk_t structure */ - /* extended data structure per unit */ - if ((data = (struct ddata_t *)calloc(1, sizeof(struct ddata_t))) == 0) { - detach_unit(uptr); - return SCPE_FMT; - } - - uptr->DDATA = (void *)data; /* save pointer to structure in DDATA */ uptr->capac = CAP(type); /* disk capacity in sectors */ ssize = SSB(type); /* get sector size in bytes */ @@ -1701,9 +1605,7 @@ fmt: } /* start out at sector 0 */ - data->cyl = 0; /* current cylinder position */ - data->tpos = 0; /* current track position */ - data->spos = 0; /* current sector position */ + uptr->CHS = 0; /* set CHS to cyl/hd/sec = 0 */ sim_debug(DEBUG_CMD, dptr, "Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\n", @@ -1713,18 +1615,13 @@ fmt: sim_debug(DEBUG_CMD, dptr, "File %s attached to %s\r\n", file, disk_type[type].name); - set_devattn(addr, SNS_DEVEND); + set_devattn(chsa, SNS_DEVEND); return SCPE_OK; } /* detach a disk device */ t_stat disk_detach(UNIT *uptr) { - struct ddata_t *data = (struct ddata_t *)uptr->DDATA; - - if (data != 0) { - free(data); /* free disk data structure */ - } - uptr->DDATA = 0; /* no pointer to disk data */ + uptr->SNS = 0; /* clear sense data */ uptr->CMD &= ~0xffff; /* no cmd and flags */ return detach_unit(uptr); /* tell simh we are done with disk */ } @@ -1754,6 +1651,7 @@ t_stat disk_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) return SCPE_IERR; /* no, error */ if (uptr->flags & UNIT_ATT) /* is unit attached? */ return SCPE_ALATT; /* no, error */ + /* now loop through the units and find named disk */ for (i = 0; disk_type[i].name != 0; i++) { if (strcmp(disk_type[i].name, cptr) == 0) { @@ -1791,8 +1689,6 @@ t_stat disk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cp } fprintf (st, ".\nEach drive has the following storage capacity:\r\n"); for (i = 0; disk_type[i].name != 0; i++) { -// int32 capac = CAP(i); /* disk capacity in sectors */ -// int32 ssize = SSB(i); /* disk sector size in bytes */ int32 size = CAPB(i); /* disk capacity in bytes */ size /= 1024; /* make KB */ size = (10 * size) / 1024; /* size in MB * 10 */ diff --git a/SEL32/sel32_fltpt.c b/SEL32/sel32_fltpt.c index 9aebc2b..00de400 100644 --- a/SEL32/sel32_fltpt.c +++ b/SEL32/sel32_fltpt.c @@ -1,6 +1,6 @@ /* sel32_fltpt.c: SEL 32 floating point instructions processing. - Copyright (c) 2018, James C. Bevier + Copyright (c) 2018-2020, James C. Bevier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/SEL32/sel32_hsdp.c b/SEL32/sel32_hsdp.c index 0324b67..3b2f00a 100644 --- a/SEL32/sel32_hsdp.c +++ b/SEL32/sel32_hsdp.c @@ -32,6 +32,8 @@ extern void set_devattn(uint16 addr, uint8 flags); extern t_stat chan_boot(uint16 addr, DEVICE *dptr); extern int test_write_byte_end(uint16 chsa); extern DEVICE *get_dev(UNIT *uptr); +extern t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */ +extern CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */ extern uint32 M[]; /* our memory */ extern uint32 SPAD[]; /* cpu SPAD memory */ @@ -291,9 +293,12 @@ Byte 1 bits 7-15 #define SNS_RTAE 0x02 /* Reserve track access error */ #define SNS_UESS 0x01 /* Uncorrectable ECC error */ -#define ATTR u6 -/* u6 holds drive attribute entry */ -/* provided by inch command for controller */ +#define CHS u6 +/* u6 holds the current cyl, hd, sec for the drive */ + +/* this attribute information is provided by the INCH command */ +/* for each device and is not used. It is reconstructed from */ +/* the disk_t structure data for the assigned disk */ /* bits 0-7 - Flags bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option @@ -309,16 +314,7 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option mini-module) */ -#define DDATA up7 -/* Pointer held in up7 */ -/* sects/cylinder = sects/track * numhds */ -/* allocated during attach command for each unit defined */ -struct ddata_t -{ - uint16 cyl; /* Cylinder head at */ - uint16 tpos; /* Track position */ - uint16 spos; /* Sector position */ -}; +/* Not Used up7 */ /* disk definition structure */ struct hsdp_t @@ -333,7 +329,6 @@ struct hsdp_t /* bit 1 mhd */ /* bits 6/7 = 0 768 byte blk */ /* not used on UDP/DPII */ /* = 1 1024 byte blk */ /* not used on UDP/DPII */ -// uint32 geom; /* disk star geometry cyl(16) hsd(8) sec(8) */ } hsdp_type[] = @@ -347,8 +342,8 @@ hsdp_type[] = {"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 */ - {"8146", 10, 256, 16, 819, 823, 0x41}, /* 6 823 160M 8146 MH160 */ - {"9344", 19, 256, 16, 800, 823, 0x41}, /* 7 823 300M 9344 MH300 */ + {"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 */ {"8155", 40, 256, 16, 839, 843, 0x41}, /* 10 843 600M 8155 MH600 */ @@ -494,7 +489,7 @@ uint8 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uint16 addr = GET_UADDR(uptr->CMD); DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); - uint8 ch; + CHANP *chp = find_chanp_ptr(addr); /* find the chanp pointer */ sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd addr %04x unit %02x cmd %02x CMD %08x\n", @@ -517,121 +512,21 @@ uint8 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) } sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd CMD continue unit=%02x cmd %02x\n", unit, cmd); - if ((uptr->flags & UNIT_ATT) == 0) { /* see if unit is attached */ - if (cmd == DSK_SNS) { /* not attached, is cmd Sense 0x04 */ - sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd CMD sense\n"); - /* bytes 0,1 - Cyl entry from STAR reg in STAR */ - ch = (uptr->STAR >> 24) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense STAR b0 unit=%02x 1 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - ch = (uptr->STAR >> 16) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense STAR b1 unit=%02x 1 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - /* byte 2 - Track entry from STAR reg in STAR */ - ch = (uptr->STAR >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense STAR b2 unit=%02x 1 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - /* byte 3 - Sector entry from STAR reg in STAR */ - ch = (uptr->STAR) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense STAR b3 unit=%02x 1 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - /* bytes 4 - mode reg, byte 0 of SNS */ - ch = (uptr->SNS >> 24) & 0xff; /* return the sense data for device */ - sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense unit=%02x 1 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - /* bytes 5-7 - status bytes, bytes 1-3 of SNS */ - ch = (uptr->SNS >> 16) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense unit=%02x %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - ch = (uptr->SNS >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense unit=%02x 3 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - ch = (uptr->SNS) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense unit=%02x 4 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - /* bytes 8-11 - drive attribute register (DATR) entries from uptr->ATTR - * via INCH cmd */ - ch = (uptr->ATTR >> 24) & 0xff; - chan_write_byte(addr, &ch) ; - ch = (uptr->ATTR >> 16) & 0xff; - chan_write_byte(addr, &ch) ; - ch = (uptr->ATTR >> 8 ) & 0xff; - chan_write_byte(addr, &ch) ; - ch = (uptr->ATTR >> 0) & 0xff; - chan_write_byte(addr, &ch) ; - /* bytes 12 & 13 contain drive related status */ - ch = 0; /* zero for now */ - /* TODO set drive status bits here */ - chan_write_byte(addr, &ch) ; - chan_write_byte(addr, &ch) ; - - uptr->SNS &= 0xff000000; /* clear status bytes, but leave mode data */ - return SNS_CHNEND|SNS_DEVEND; - } - if (cmd == 0x0) /* INCH cmd gives unit check here */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - - uptr->SNS |= (SNS_INTVENT|SNS_CMDREJ); /* set new error status */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* we done */ - } - /* Unit is online, so process a command */ switch (cmd) { - case DSK_INCH: /* INCH 0x0 */ - { - uint32 mema; /* memory address */ - uint32 i; - UNIT *up = dptr->units; /* first unit for this device */ + case DSK_INCH: /* INCH 0x0 */ sim_debug(DEBUG_CMD, dptr, - "hsdp_startcmd starting inch cmd addr %04x MemBuf %08x\n", - addr, uptr->u4); - /* STAR (u4) has IOCD word 1 contents. For the disk processor it contains */ - /* a pointer to the INCH buffer followed by 8 drive attribute words that */ - /* contains the flags, sector count, MHD head count, and FHD count */ - /* us9 has the byte count from IOCD wd2 and should be 0x24 (36) */ - /* the INCH buffer address must be returned in u4 and us9 left non-zero */ - /* just return OK and channel software will use up8 as status buffer */ - mema = (uint32)uptr->u4; /* get memory address of buffer */ - uptr->u4 = M[mema>>2]; /* get status buffer address for XIO return status */ - sim_debug(DEBUG_CMD, dptr, - "hsdp_startcmd starting inch cmd addr %04x StatAdr %06x mema %06x units %02x\n", - addr, uptr->u4, mema, dptr->numunits); - /* the next 8 words have drive data for each unit */ - /* WARNING 8 drives must be defined for this controller */ - /* so we will not have a map fault */ - for (i=0; inumunits && i<8; i++) { /* process all drives */ - int type = GET_TYPE(up->flags); /* get disk type */ - up->ATTR = M[(mema>>2)+i+1]; /* save each unit's drive data */ - /* see if sec/trk and num hds are set, if not set them */ - if ((up->ATTR & 0x00ff0000) == 0) - up->ATTR = (up->ATTR & 0xff00ffff) | ((hsdp_type[type].spt & 0xff) << 16); - if ((up->ATTR & 0x0000ff00) == 0) - up->ATTR = (up->ATTR & 0xffff00ff) | ((hsdp_type[type].nhds & 0xff) << 8); - sim_debug(DEBUG_CMD, dptr, - "hsdp_startcmd ATTR data %08x unit %02x flags %02x sec %02x MHD %02x FHD %02x\n", - up->ATTR, i, (up->ATTR >> 24)&0xff, (up->ATTR >> 16)&0xff, - (up->ATTR >> 8)&0xff, (up->ATTR&0xff)); - up++; /* next unit for this device */ - } - sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd done inch cmd addr %04x\n", addr); + "hsdp_startcmd starting INCH %06x cmd, chsa %04x MemBuf %08x cnt %04x\n", + uptr->u4, addr, chp->ccw_addr, chp->ccw_count); + uptr->CMD |= DSK_FINC; /* use 0xc0 for inch, just need int */ sim_activate(uptr, 20); /* start things off */ return 0; break; - } case DSK_SCK: /* Seek command 0x07 */ case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ -// uptr->CMD &= ~(DSK_STAR); /* show we do not have seek STAR in STAR */ case DSK_WD: /* Write command 0x01 */ case DSK_RD: /* Read command 0x02 */ case DSK_LMR: /* read mode register */ @@ -679,6 +574,7 @@ uint8 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) return 0; break; } + sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd done with hsdp_startcmd %02x addr %04x SNS %08x\n", cmd, addr, uptr->SNS); @@ -693,27 +589,29 @@ t_stat hsdp_srv(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->CMD); DEVICE *dptr = get_dev(uptr); - DIB *dibp = (DIB *)dptr->ctxt; - /* get pointer to Dev Info Blk for this device */ - CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */ + DIB *dibp = (DIB *)dptr->ctxt; /* get DIB address */ + CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */ +#ifdef OLDWAY struct ddata_t *data = (struct ddata_t *)(uptr->DDATA); +#endif int cmd = uptr->CMD & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); -// uint32 trk, cyl, sec; - uint32 trk, cyl; + uint32 trk, cyl, sec; +// uint32 trk, cyl; int unit = (uptr - dptr->units); int len; int i; uint8 ch; uint16 ssize = hsdp_type[type].ssiz * 4; /* disk sector size in bytes */ - uint32 tsize = hsdp_type[type].spt * ssize; /* get track size in bytes */ uint32 tstart; uint8 buf2[1024]; uint8 buf[1024]; sim_debug(DEBUG_CMD, dptr, "hsdp_srv entry unit %02x CMD %08x chsa %04x count %04x %x/%x/%x \n", - unit, uptr->CMD, chsa, chp->ccw_count, data->cyl, data->tpos, data->spos); +// unit, uptr->CMD, chsa, chp->ccw_count, data->cyl, data->tpos, data->spos); + 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 */ @@ -722,21 +620,93 @@ t_stat hsdp_srv(UNIT *uptr) } sim_debug(DEBUG_CMD, dptr, - "hsdp_srv cmd=%02x chsa %04x count %04x\n", - cmd, chsa, chp->ccw_count); + "hsdp_srv cmd=%02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); + switch (cmd) { case 0: /* No command, stop disk */ break; - case DSK_FINC: /* use 0xc0 for inch, just need int */ + case DSK_FINC: /* use 0xc0 for inch, just need int */ + { + uint32 mema; /* memory address */ +// uint32 daws[8]; /* drive attribute registers */ +// uint32 i, j; + uint32 i; + + len = chp->ccw_count; /* INCH command count */ + mema = chp->ccw_addr; /* get inch or buffer addr */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv starting INCH cmd, chsa %04x MemBuf %06x cnt %04x\n", + chsa, chp->ccw_addr, chp->ccw_count); + + /* mema has IOCD word 1 contents. For the disk processor it contains */ + /* a pointer to the INCH buffer followed by 8 drive attribute words that */ + /* contains the flags, sector count, MHD head count, and FHD count */ + /* len has the byte count from IOCD wd2 and should be 0x24 (36) */ + /* the INCH buffer address must be set for the parrent channel as well */ + /* 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; + } + + /* read all 36 bytes, stopping every 4 bytes to make words */ + /* the first word has the inch buffer address */ + /* the next 8 words have drive data for each unit */ + /* WARNING 8 drives must be defined for this controller */ + /* so we will not have a map fault */ +// for (i=0, j=0; i < 36; i++) { + for (i=0; i < 36; i++) { + if (chan_read_byte(chsa, &buf[i])) { + /* we have error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (((i+1)%4) == 0) { /* see if we have a word yet */ + if (i == 3) + /* inch buffer address */ + mema = (buf[0]<<24) | (buf[1]<<16) | + (buf[2]<<8) | (buf[3]); + else + /* drive attribute registers */ +// daws[j++] = (buf[i-3]<<24) | (buf[i-2]<<16) +// | (buf[i-1]<<8) | (buf[i]); + /* may want to use this later */ + /* clear warning errors */ + tstart = (buf[i-3]<<24) | (buf[i-2]<<16) + | (buf[i-1]<<8) | (buf[i]); + } + } + /* now call set_inch() function to write and test inch bybber addresses */ + 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; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } +#endif uptr->CMD &= ~(0xffff); /* remove old cmd */ - sim_debug(DEBUG_CMD, dptr, "disk_srv cmd INCH chsa %04x count %04x completed\n", - chsa, chp->ccw_count); + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv cmd INCH chsa %04x addr %06x count %04x completed\n", + chsa, mema, chp->ccw_count); #ifdef FIX4MPX chan_end(chsa, SNS_CHNEND); /* return just channel end OK */ #else chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ #endif + } break; case DSK_WSL: /* WSL 0x31 make into NOP */ @@ -748,7 +718,6 @@ t_stat hsdp_srv(UNIT *uptr) sim_debug(DEBUG_DETAIL, dptr, "Sector 1 label"); /* now read sector label data */ len = chp->ccw_count; -// for (i = 0; i < 30; i++) { for (i = 0; i < len; i++) { if (chan_read_byte(chsa, &buf[i])) { /* we have write error, bail out */ @@ -756,7 +725,6 @@ t_stat hsdp_srv(UNIT *uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } -// if (i == 16) if ((i%16) == 0) sim_debug(DEBUG_DETAIL, dptr, "\nSector 1 label"); sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); @@ -801,31 +769,28 @@ t_stat hsdp_srv(UNIT *uptr) case DSK_SNS: /* 0x4 */ sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd CMD sense\n"); - /* bytes 0,1 - Cyl entry from STAR reg in STAR */ -// ch = (uptr->STAR >> 24) & 0xff; - ch = (data->cyl >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv sense STAR b0 unit=%02x 1 %02x\n", + /* 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", unit, ch); chan_write_byte(chsa, &ch); -// ch = (uptr->STAR >> 16) & 0xff; - ch = (data->cyl) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv sense STAR b1 unit=%02x 2 %02x\n", + ch = (uptr->CHS >> 16) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv sense CHS b1 unit=%02x 2 %02x\n", unit, ch); chan_write_byte(chsa, &ch); - /* byte 2 - Track entry from STAR reg in STAR */ -// ch = (uptr->STAR >> 8) & 0xff; - ch = (data->tpos) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv sense STAR b2 unit=%02x 3 %02x\n", + /* byte 2 - Track entry from CHS reg */ + ch = (uptr->CHS >> 8) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv sense CHS b2 unit=%02x 3 %02x\n", unit, ch); chan_write_byte(chsa, &ch); - /* byte 3 - Sector entry from STAR reg in STAR */ -// ch = (uptr->STAR) & 0xff; - ch = (data->spos) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv sense STAR b3 unit=%02x 4 %02x\n", + /* byte 3 - Sector entry from CHS reg */ + ch = (uptr->CHS) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv sense CHS b3 unit=%02x 4 %02x\n", unit, ch); chan_write_byte(chsa, &ch); + /* bytes 4 - mode reg, byte 0 of SNS */ - ch = (uptr->SNS >> 24) & 0xff; /* return the sense data for device */ + ch = (uptr->SNS >> 24) & 0xff; /* return the sense data */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv sense unit=%02x 1 %02x\n", unit, ch); chan_write_byte(chsa, &ch); @@ -842,24 +807,25 @@ t_stat hsdp_srv(UNIT *uptr) sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv sense unit=%02x 4 %02x\n", unit, ch); chan_write_byte(chsa, &ch); - /* bytes 8-11 - drive attribute register (DATR) entries from uptr->ATTR via - * INCH cmd */ - ch = (uptr->ATTR >> 24) & 0xff; + + /* bytes 8-11 - drive mode register entries from assigned hsdp */ + ch = hsdp_type[type].type & 0xff; /* type byte */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv datr unit=%02x 1 %02x\n", unit, ch); chan_write_byte(chsa, &ch); - ch = (uptr->ATTR >> 16) & 0xff; + ch = hsdp_type[type].spt & 0xff; /* get sectors per track */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv datr unit=%02x 2 %02x\n", unit, ch); chan_write_byte(chsa, &ch); - ch = (uptr->ATTR >> 8 ) & 0xff; + ch = hsdp_type[type].nhds & 0xff; /* get # MHD heads */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv datr unit=%02x 3 %02x\n", unit, ch); chan_write_byte(chsa, &ch); - ch = (uptr->ATTR >> 0) & 0xff; + ch = 0; /* no FHD heads */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv datr unit=%02x 4 %02x\n", unit, ch); chan_write_byte(chsa, &ch); + /* bytes 12 & 13 are optional, so check if read done */ /* TODO add drive status bits here */ if ((test_write_byte_end(chsa)) == 0) { @@ -869,13 +835,11 @@ t_stat hsdp_srv(UNIT *uptr) unit, ch); chan_write_byte(chsa, &ch); - ch = 030; /* drive on cyl and ready for now */ + ch = 0x30; /* 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); } -//NEW uptr->SNS &= 0xff000000; /* clear status bytes, but leave mode data */ -//TRY uptr->CMD &= ~(0xff00); /* clear busy status */ uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; @@ -885,87 +849,37 @@ t_stat hsdp_srv(UNIT *uptr) /* If we are waiting on seek to finish, check if there yet. */ if (uptr->CMD & DSK_SEEKING) { /* see if on cylinder yet */ - if ((int32)(uptr->STAR >> 16) == (int32)data->cyl) { + 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 %02x %04x\n", - unit, uptr->STAR >> 16, data->cyl); + sim_debug(DEBUG_CMD, dptr, "hsdp_srv seek on cylinder unit=%02x %04x %04x\n", + unit, uptr->STAR >> 16, uptr->CHS >> 16); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ -// set_devattn(chsa, SNS_DEVEND); /* start the operation */ - sim_debug(DEBUG_CMD, dptr, "hsdp_srv seek end unit=%02x %02x %04x\n", - unit, uptr->STAR >> 16, data->cyl); + /* we have already seeked to the required sector */ + /* we do not need to seek again, so move on */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); sim_activate(uptr, 20); break; } else { -#ifndef TRYTHIS - data->cyl = ((uptr->STAR >> 16)&0xffff); + /* we have wasted enough time, we there */ + uptr->CHS = uptr->STAR; /* we are there */ sim_activate(uptr, 10); break; -#else - /* Compute delay based of difference. */ - /* Set next state = index */ - i = (int32)((uptr->STAR >> 16)&0xffff) - (int32)data->cyl; - sim_debug(DEBUG_CMD, dptr, "hsdp_srv seek unit=%02x %02x %04x\n", - unit, uptr->STAR >> 16, i); - if (i > 0 ) { - if (i > 500) { - data->cyl += 500; /* seek 500 cyl */ - sim_activate(uptr, 800); - } else - if (i > 200) { - data->cyl += 200; /* seek 200 cyl */ - sim_activate(uptr, 400); - } else - if (i > 50) { - data->cyl += 50; /* seek 50 cyl */ - sim_activate(uptr, 200); - } else { - data->cyl = uptr->STAR >> 16; /* Seek the rest i cyl */ - sim_activate(uptr, 20); - } - if (data->cyl >= (int)hsdp_type[type].cyl) /* test for over max */ - data->cyl = hsdp_type[type].cyl-1; /* make max */ - } else { - if (i < -500) { - data->cyl -= 500; /* seek 500 cyl */ - sim_activate(uptr, 800); - } else - if (i < -200) { - data->cyl -= 200; /* seek 200 cyl */ - sim_activate(uptr, 400); - } else - if (i < -50) { - data->cyl -= 50; /* seek 50 cyl */ - sim_activate(uptr, 200); - } else { - data->cyl = uptr->STAR >> 16; /* Seek the rest i cyl */ - sim_activate(uptr, 20); - } - if ((int32)data->cyl < 0) /* test for less than zero */ - data->cyl = 0; /* make zero */ - } -#endif - sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv seek next unit=%02x %02x %04x\n", - unit, uptr->STAR >> 16, data->cyl); -#ifdef OLD_WAY - sim_activate(uptr, 2); -#else -/*BAD?*/ sim_activate(uptr, 10); -#endif - break; } } /* not seeking, so start a new seek */ /* set buf data to current STAR values */ - buf[0] = (data->cyl >> 8) & 0xff; - buf[1] = (data->cyl) & 0xff; - buf[2] = (data->tpos) & 0xff; - buf[3] = (data->spos) & 0xff; - sim_debug(DEBUG_CMD, dptr, "hsdp_srv STAR unit=%02x star %02x %02x %02x %02x\n", + 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 */ + + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv current STAR unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); - /* Read in up to 4 character seek code */ + /* Read in 1-4 character seek code */ for (i = 0; i < 4; i++) { if (chan_read_byte(chsa, &buf[i])) { if (i == 0) { @@ -988,25 +902,32 @@ t_stat hsdp_srv(UNIT *uptr) buf[0] = buf[1] = buf[2] = buf[3] = 0; } /* 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", + unit, buf[0], buf[1], buf[2], buf[3]); rezero: sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv seek unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); + /* save STAR (target sector) data in STAR */ uptr->STAR = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]); - cyl = (uptr->STAR >> 16) & 0xffff; /* get the cylinder */ + cyl = STAR2CYL(uptr->STAR); /* get the cylinder */ trk = buf[2]; /* get the track */ + sim_debug(DEBUG_DETAIL, dptr, - "hsdp_srv SEEK cyl %04x trk %02x sec %02x unit=%02x\n", + "hsdp_srv NEW SEEK cyl %04x trk %02x sec %02x unit=%02x\n", cyl&0xffff, trk, buf[3], unit); /* Check if seek valid */ if (cyl >= hsdp_type[type].cyl || trk >= hsdp_type[type].nhds || buf[3] >= hsdp_type[type].spt) { + sim_debug(DEBUG_CMD, dptr, "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 */ @@ -1015,35 +936,36 @@ rezero: break; } -// uptr->CMD |= DSK_STAR; /* show we have seek STAR in STAR */ - /* calc the sector address of data */ + /* calc the new sector address of data */ /* calculate file position in bytes of requested sector */ - tstart = (cyl * hsdp_type[type].nhds * tsize) + (trk * tsize) + (buf[3] * ssize); - data->tpos = trk; /* save the track/head number */ - data->spos = buf[3]; /* save the sector number */ + 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]); + sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv seek start %04x cyl %04x trk %02x sec %02x\n", tstart, cyl, trk, buf[3]); + + /* just seek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* seek home */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv Error on seek to %08x\n", tstart); } /* Check if already on correct cylinder */ - if (cyl != data->cyl) { - /* Do seek */ + /* if not, do a delay to slow things down */ + if (STAR2CYL(uptr->STAR) != STAR2CYL(uptr->CHS)) { + /* 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 */ -//WHAT? chan_end(chsa, SNS_CHNEND); } else { - /* Yes, we done */ + /* we are on cylinder/track/sector, so go on */ sim_debug(DEBUG_DETAIL, dptr, - "hsdp_srv calc sect addr seek end %04x cyl %04x trk %02x sec %02x\n", + "hsdp_srv done seeking to %04x cyl %04x trk %02x sec %02x\n", tstart, cyl, trk, buf[3]); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ -// sim_activate(uptr, 20); chan_end(chsa, SNS_DEVEND|SNS_CHNEND); } return SCPE_OK; @@ -1053,6 +975,7 @@ rezero: 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 |= DSK_SCK; /* show as seek command */ tstart = 0; /* byte offset is 0 */ @@ -1091,15 +1014,23 @@ rezero: if ((uptr->CMD & DSK_READING) == 0) { /* see if we are reading data */ uptr->CMD |= DSK_READING; /* read from disk starting */ sim_debug(DEBUG_CMD, dptr, - "DISK READ starting unit=%02x CMD %02x\n", unit, uptr->CMD); + "DISK READ starting CMD %08x chsa %04x buffer %06x count %04x\n", + uptr->CMD, chsa, chp->ccw_addr, chp->ccw_count); } if (uptr->CMD & DSK_READING) { /* see if we are reading data */ + cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ + sec = uptr->CHS & 0xff; /* get sec */ + /* get sector offset */ +// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)); + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* 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, data->cyl, data->tpos, data->spos); + len, ssize, cyl, trk, sec); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -1108,13 +1039,35 @@ rezero: sim_debug(DEBUG_CMD, dptr, "hsdp_srv after READ chsa %04x buffer %06x count %04x\n", chsa, chp->ccw_addr, chp->ccw_count); + +#ifdef LOOK + /* check for 0x280 or 0x308 read count */ + sec = chp->ccw_count; + if (sec == 0x308 || sec == 0x280) { + for (i = 0; i < sec; i++) { + if ((i%16) == 0) + sim_debug(DEBUG_CMD, dptr, "\nREAD: %06x", chp->ccw_addr + i); + sim_debug(DEBUG_CMD, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_CMD, dptr, "\n\n"); + } + if (sec == 0x308 || sec == 0x280) { + for (i = sec; i < ssize; i++) { + if (((i-sec)%16) == 0) + sim_debug(DEBUG_CMD, dptr, "\nREAD: %06x", chp->ccw_addr + i - sec); + sim_debug(DEBUG_CMD, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_CMD, dptr, "\n"); + } +#endif + /* process the next sector of data */ for (i=0; iccw_count, data->cyl, data->tpos, data->spos); + i, chp->ccw_count, cyl, trk, sec); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); goto rddone; @@ -1122,43 +1075,41 @@ rezero: } sim_debug(DEBUG_CMD, dptr, - "DISK READ %04x bytes leaving %4x to be read from diskfile /%04x/%02x/%02x\n", - ssize, chp->ccw_count, data->cyl, data->tpos, data->spos); - data->spos++; - /* set sector to read next one */ - if (data->spos >= (hsdp_type[type].spt)) { - data->spos = 0; /* number of sectors per track */ - data->tpos++; /* track position */ - if (data->tpos >= (hsdp_type[type].nhds)) { - data->tpos = 0; /* number of tracks per cylinder */ - data->cyl++; /* cylinder position */ - if (data->cyl >= (int)(hsdp_type[type].cyl)) { - /* EOM reached, abort */ - sim_debug(DEBUG_CMD, dptr, - "DISK Read reached EOM for read from disk @ /%04x/%02x/%02x\n", - data->cyl, data->tpos, data->spos); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - data->cyl = 0; /* reset cylinder position */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - } - } + "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); + /* 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", - data->cyl, data->tpos, data->spos); + 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; - } else { - sim_debug(DEBUG_DATA, dptr, - "DISK sector read complete, %x bytes to go from diskfile /%04x/%02x/%02x\n", - chp->ccw_count, data->cyl, data->tpos, data->spos); - sim_activate(uptr, 10); /* wait to read next sector */ + } + + /* 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 >= CAPB(type)) { + if (tstart >= CAP(type)) { + /* EOM reached, abort */ + sim_debug(DEBUG_CMD, dptr, + "DISK Read reached EOM for read from disk @ /%04x/%02x/%02x\n", + STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CHS = 0; /* reset cylinder position */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); 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)); + sim_activate(uptr, 10); /* wait to read next sector */ + break; rddone: uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ } @@ -1171,6 +1122,19 @@ rddone: "DISK WRITE starting unit=%02x CMD %02x\n", unit, uptr->CMD); } if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */ + cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ + sec = uptr->CHS & 0xff; /* get sec */ + /* get sector offset */ +// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)); + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + +#ifdef LOOK + /* check for 0x280 or 0x308 read count */ + sec = chp->ccw_count; + tstart = chp->ccw_addr; +#endif + /* process the next sector of data */ len = 0; /* used here as a flag for short read */ for (i=0; iCMD &= ~(0xffff); /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "DISK Wrote %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", - ssize, data->cyl, data->tpos, data->spos); + ssize, cyl, trk, sec); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); goto wrdone; } @@ -1188,12 +1152,38 @@ rddone: len++; /* show we have no more data to write */ } buf2[i] = ch; /* save the char */ +#ifdef LOOK + trk = chp->ccw_addr; +#endif } + +#ifdef LOOK + /* check for 0x280 or 0x308 read count */ +// sec = chp->ccw_count; + if (sec == 0x308 || sec == 0x280) { + for (i = 0; i < sec; i++) { + if ((i%16) == 0) + sim_debug(DEBUG_CMD, dptr, "\nWRIT: %06x", tstart + i); + sim_debug(DEBUG_CMD, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_CMD, dptr, "\n\n"); + } + if (sec == 0x308 || sec == 0x280) { + tstart = trk - (ssize-sec); + for (i = sec; i < ssize; i++) { + if (((i-sec)%16) == 0) + sim_debug(DEBUG_CMD, dptr, "\nWRIT: %06x", tstart + i - sec); + sim_debug(DEBUG_CMD, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_CMD, dptr, "\n"); + } +#endif + /* 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, data->cyl, data->tpos, data->spos); + i, ssize, cyl, trk, sec); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -1201,31 +1191,39 @@ rddone: if (len != 0) { /* see if done with write command */ sim_debug(DEBUG_DATA, dptr, "DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", - ssize, data->cyl, data->tpos, data->spos); + ssize, cyl, trk, sec); uptr->CMD &= ~(0xffff); /* 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 %0x4x bytes end %04x to diskfile cyl %04x hds %02x sec %02x\n", - len, ssize, data->cyl, data->tpos, data->spos); - data->spos++; - if (data->spos >= (hsdp_type[type].spt)) { - data->spos = 0; /* number of sectors per track */ - data->tpos++; /* track position */ - if (data->tpos >= (hsdp_type[type].nhds)) { - data->tpos = 0; /* number of tracks per cylinder */ - data->cyl++; /* cylinder position */ - if (data->cyl >= (int)(hsdp_type[type].cyl)) { - /* EOM reached, abort */ - sim_debug(DEBUG_DETAIL, dptr, - "Error %08x on write %04x to diskfile cyl %04x hds %02x sec %02x\n", - i, ssize, data->cyl, data->tpos, data->spos); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - } + "DISK WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x\n", + len, ssize, cyl, trk, sec); +#ifdef LOOK + sec = 0; + for (i = 0; i < ssize; i++) { + if ((i%16) == 0) + sim_debug(DEBUG_CMD, dptr, "\nWRIT %3x:", i); + sim_debug(DEBUG_CMD, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_CMD, dptr, "\n\n"); +#endif + + /* 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 >= CAPB(type)) { + if (tstart >= 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->CMD &= ~(0xffff); /* 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; @@ -1235,9 +1233,6 @@ wrdone: break; case DSK_RSL: /* RSL 0x32 */ -#ifdef DO_DYNAMIC_DEBUG - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif /* Read sector label zero to get disk geometry */ /* write 30 bytes, b0-b1=cyl, b1=trk, b2=sec */ /* zero the Track Label Buffer */ @@ -1255,62 +1250,36 @@ wrdone: /* 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 = (uptr->STAR >> 16) & 0xffff; /* get the cylinder */ -// trk = (uptr->STAR >> 8) & 0xff; /* get the track */ -// sec = (uptr->STAR) & 0xff; /* get the sector */ - sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd RSL STAR %08x disk geom %08x\n", - uptr->STAR, GEOM(type)); + uptr->CHS, GEOM(type)); -#ifdef OLD_WAY /* set buf data to current STAR values */ - buf[0] = (data->cyl >> 8) & 0xff; /* lcyl cyl upper 8 bits */ - buf[1] = data->cyl & 0xff; /* lcyl cyl lower 8 bits */ - buf[2] = data->tpos & 0xff; /* ltkn trk */ - buf[3] = data->spos & 0xff; /* lid sector ID */ + 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 */ 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]); - cyl = hsdp_type[type].cyl-1; /* last cyl */ - trk = hsdp_type[type].nhds-1; /* last head number */ - sec = hsdp_type[type].spt-1; /* last sector number */ - -// daddr = (cap-1) - (3 * csize) - ((nhds - 2) * tsize); - tstart = (((cyl * hsdp_type[type].nhds) * hsdp_type[type].spt) + - (trk * hsdp_type[type].spt) + sec); /* last sector address */ - tstart = tstart - (3 * hsdp_type[type].nhds * hsdp_type[type].spt); - tstart = tstart - (2 * hsdp_type[type].spt) + 1; - /* UTX dmap at daddr - 32 sec (2 tracks) */ - tstart = tstart - (2 * hsdp_type[type].spt); -#else /* get sector address of UTX media descriptor */ + /* 819/7/0 is right for 8887, 819/16/0 for 9346 */ tstart = ((CYL(type)-4) * SPC(type)) + ((HDS(type)-2) * SPT(type)) - SPT(type); -#endif 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]); -#ifdef OLD_WAY - cyl = hsdp_type[type].cyl-3; /* cyl */ - trk = hsdp_type[type].nhds-2; /* head */ - sec = 0; /* last sector number */ -// daddr = (cap-1) - (3 * csize) - ((nhds - 2) * tsize); - sim_debug(DEBUG_CMD, dptr, - "hsdp_srv RSL sector %d %x star %02x %02x %02x %02x\n", - tstart, tstart, cyl>>8, cyl&0xff, trk, sec); -#endif - /* on HSDP DMAP is in wd 3 on label 0 */ - /* on HSDP UMAP is in wd 3 on label 1 */ + /* on HSDP UMAP is in wd 4 on label 1 */ /* on UDP & DPII DMAP is in wd 3 on label 0 */ /* on UDP & DPII UMAP is in wd 4 on label 0 */ -// tstart = 0x440aa; /* 819/0/7 logical 278698 */ +// tstart = 0x440aa; /* 819/7/0 logical 278698 */ + /* the address must be logical */ tstart = (tstart * (SPT(type) - 1))/SPT(type); /* make logical */ /* store into sec 1 label */ buf[12] = (tstart >> 24) & 0xff; /* UMAP pointer */ @@ -1318,6 +1287,12 @@ wrdone: buf[14] = (tstart >> 8) & 0xff; buf[15] = (tstart) & 0xff; +#ifndef NOTNOW + buf[16] = (tstart >> 24) & 0xff; /* UMAP pointer too */ + buf[17] = (tstart >> 16) & 0xff; + buf[18] = (tstart >> 8) & 0xff; + buf[19] = (tstart) & 0xff; +#endif /* 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 */ @@ -1358,26 +1333,30 @@ wrdone: /* Read track zero to get disk geometry */ /* write 30 bytes, b0-b1=cyl, b1=trk, b2=sec */ -#ifdef DO_DYNAMIC_DEBUG - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_XIO); -#endif /* zero the Track Label Buffer */ for (i = 0; i < 30; i++) buf[i] = 0; - /* set buf data to current STAR values */ -// cyl = (uptr->STAR >> 16) & 0xffff; /* get the cylinder */ -// trk = (uptr->STAR >> 8) & 0xff; /* get the track */ -// sec = (uptr->STAR) & 0xff; /* get the sector */ + /* set buf data to current CHS values */ + if (uptr->CHS == 0) { /* write last address on trk 0 */ + cyl = CYL(type)-1; /* lcyl cyl upper 8 bits */ + trk = HDS(type)-1; /* ltkn trk */ + sec = SPT(type)-1; /* lid sector ID */ + } else { + /* write current address on other tracks */ + cyl = (uptr->CHS >> 16) & 0xffff; /* get the cylinder */ + trk = (uptr->CHS >> 8) & 0xff; /* get the track */ + sec = (uptr->CHS) & 0xff; /* get the sector */ + } sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd RTL STAR %08x disk geom %08x\n", - uptr->STAR, GEOM(type)); + uptr->CHS, GEOM(type)); /* set buf data to current STAR values */ - buf[0] = (data->cyl >> 8) & 0xff; /* lcyl cyl upper 8 bits */ - buf[1] = data->cyl & 0xff; /* lcyl cyl lower 8 bits */ - buf[2] = data->tpos & 0xff; /* ltkn trk */ - buf[3] = data->spos & 0xff; /* lid sector ID */ + buf[0] = (cyl >> 8) & 0xff; /* lcyl cyl upper 8 bits */ + buf[1] = cyl & 0xff; /* lcyl cyl lower 8 bits */ + buf[2] = trk & 0xff; /* ltkn trk */ + buf[3] = sec & 0xff; /* lid sector ID */ buf[4] = 0x80; /* set lflg1 */ sim_debug(DEBUG_DETAIL, dptr, @@ -1392,34 +1371,16 @@ wrdone: /* previous track, so MDT = VDT-SPT is CYL-4/HDS-2/0 */ /* The UTX flaw map is at FMAP = MDT-SPT CYL-4/HDS-3/0 */ /* UTX media map is 1 track lower at UTXMM=FMAP-SPT CYL-4/HDS-4/0 */ - /* The UTX med map is pointed to by sector label 1 */ + /* The UTX media map is pointed to by sector label 1 */ /* simulate pointers here, set wd[3] in label to VDT */ -#ifdef OLD_WAY - /* the dmap pointer is placed by the vendor of diag into track 0 */ - /* simulate pointer here */ -// i = 250191; /* 0x3d14f 337/13/0F */ /* dmap sector address */ - cyl = hsdp_type[type].cyl-1; /* last cyl */ - trk = hsdp_type[type].nhds-1; /* last head number */ - sec = hsdp_type[type].spt-1; /* last sector number */ -// daddr = (cap) - (3 * csize) - (2 * tsize); - tstart = (((cyl * hsdp_type[type].nhds) * hsdp_type[type].spt) + - (trk * hsdp_type[type].spt) + sec); /* last sector address */ - tstart = tstart - (3 * hsdp_type[type].nhds * hsdp_type[type].spt); - tstart = tstart - (2 * hsdp_type[type].spt) + 1; -// tstart = 249248; - /* vaddr is (cap) - 3 cyl - 8 sec */ -//BAD tstart = ((cyl-3) * (trk+1) * (sec+1)) - 8; /* 249256 0x3cda8 */ -// tstart = ((cyl-3) * (trk+1) * (sec+1)) - -// (2 * (trk+1) * (sec+1)); /* 249248 0x3cda0 */ -#else - /* get sector address of vendor defect table */ - /* 249264 (819/17/0) for 9346 - 823/19/16 */ + + /* get sector address of media defect table */ + /* 286930 (819/8/0) 0x460d2 for 8887 - 823/10/36 */ tstart = (CYL(type)-4) * SPC(type) + (HDS(type)-2) * SPT(type); cyl = hsdp_type[type].cyl-1; /* last cyl */ trk = hsdp_type[type].nhds-1; /* last head number */ // sec = hsdp_type[type].spt-1; /* last sector number */ -#endif sim_debug(DEBUG_CMD, dptr, "hsdp_srv RTL STAR %04x/%02x/%02x Dmap pointer 0x%08x %d\n", @@ -1428,7 +1389,7 @@ wrdone: "hsdp_srv TRK0 RTL sector %d %x star %02x %02x %02x %02x\n", tstart, tstart, buf[0], buf[1], buf[2], buf[3]); - if (uptr->STAR == 0) { /* only write dmap address in trk 0 */ + if (uptr->CHS == 0) { /* only write dmap address in trk 0 */ /* output last sector address of disk */ buf[12] = (tstart >> 24) & 0xff; /* ldeallp DMAP pointer */ buf[13] = (tstart >> 16) & 0xff; @@ -1436,9 +1397,14 @@ wrdone: buf[15] = (tstart) & 0xff; } -#ifdef NOTNOW +#ifndef NOTNOW + /* get sector address of umap table */ + /* 286895 (819/7/0) 0x460af for 8887 - 823/10/36 */ tstart -= SPT(type); /* calc utxfmap address */ - if (uptr->STAR == 0) { /* only write dmap address on trk 0 */ + /* the address must be logical */ + tstart = (tstart * (SPT(type) - 1))/SPT(type); /* make logical */ + /* 278698 (819/7/0) 0x440aa for 8887 - 823/10/35 */ + if (uptr->CHS == 0) { /* only write dmap address on trk 0 */ buf[16] = (tstart >> 24) & 0xff; /* ldeallp UMAP */ buf[17] = (tstart >> 16) & 0xff; buf[18] = (tstart >> 8) & 0xff; @@ -1512,7 +1478,6 @@ t_stat hsdp_reset(DEVICE *dptr) /* create the disk file for the specified device */ int hsdp_format(UNIT *uptr) { -// struct ddata_t *data = (struct ddata_t *)uptr->up7; // uint16 addr = GET_UADDR(uptr->CMD); int type = GET_TYPE(uptr->flags); DEVICE *dptr = get_dev(uptr); @@ -1520,18 +1485,17 @@ int hsdp_format(UNIT *uptr) { uint32 tsize = hsdp_type[type].spt; /* get track size in sectors */ uint32 csize = hsdp_type[type].nhds * tsize; /* get cylinder size in sectors */ uint32 cyl = hsdp_type[type].cyl; /* get # cylinders */ - uint16 spc = hsdp_type[type].nhds * hsdp_type[type].spt; /* sectors/cyl */ uint32 cap = hsdp_type[type].cyl * csize; /* disk capacity in sectors */ uint32 cylv = cyl; /* number of cylinders */ uint8 *buff; /* last sector address of disk (cyl * hds * spt) - 1 */ uint32 laddr = CAP(type) - 1; /* last sector of disk */ /* get sector address of vendor defect table */ - /* put data = 0xf0000004 0xf4000000 */ + /* put data = 0xf0000000 0xf4000004 */ int32 vaddr = (CYL(type)-4) * SPC(type) + (HDS(type)-1) * SPT(type); /* get sector address of utx diag map track 0 pointer */ - /* put data = 0xf0000000 + cyl-1, 0x8a000000 + daddr, */ - /* 0x9a000000 + cyl-1, 0xf4000000 */ + /* put data = 0xf0000000 + (cyl-1), 0x8a000000 + daddr, */ + /* 0x9a000000 + (cyl-1), 0xf4000008 */ int32 daddr = vaddr - SPT(type); /* get sector address of utx flaw map sec 1 pointer */ /* use this address for sec 1 label pointer */ @@ -1542,19 +1506,37 @@ int hsdp_format(UNIT *uptr) { int32 faddr = uaddr - SPT(type); #endif uint32 umap[256] = -#ifdef OLDWAY -// {0x4e554d50,0x4450b,0x43fbb,0,0,0,0xffffffff,0xe10, - {0x4e554d50,0x3d14f,0x00000,0,0,0,0xffffffff,0xe10, +#ifndef NOTFORMPX +#ifndef NOERRORS + /* try having no error, 7 in 3rd line */ + {0x4e554d50,0x4450b,0x43fbb,0,0,0,0,0xe10, +// {0x4e554d50,0x3d14f,0x00000,0,0,0,0xffffffff,0xe10, // 7,0x5258,0,0x4e5c,0x3e,0x43fbc,0,0xd32c, - 7,0x5258,0,0x4e5c,0x3e,0x43fbc,0,0xd32c, + 0,0x5258,0,0x4e5c,0x3e,0x43fbc,0,0xd32c, 0x79,0x187cc,0x118,0x14410,0x23f,0,0,0, - 0,0x3821a2d6,0x4608c,0x1102000,0,0,0x4608c,0, + 0,0x3821a2d6,0,0x1102000,0xf4,0,0,0, +// 0,0x3821a2d6,0x4608c,0x1102000,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + }; +#else + /* use original copy of geert's left disk */ + {0x4e554d50,0x4450b,0x43fbb,0,0,0,0,0xe10, +// {0x4e554d50,0x3d14f,0x00000,0,0,0,0xffffffff,0xe10, + 7,0x5258,0,0x4e5c,0x3e,0x43fbc,0,0xd32c, +// 0,0x5258,0,0x4e5c,0x3e,0x43fbc,0,0xd32c, + 0x79,0x187cc,0x118,0x14410,0x23f,0,0,0, + 0,0x3821a2d6,0x4608c,0x1102000,0xf4,0,0x4608c,0, +// 0,0x3821a2d6,0,0x1102000,0,0,0x4608c,0, 0,0x46069,0,0,0x46046,0,0,0x46023, 0,0,0x46000,0,0,0x45fdd,0,0, 0x45fba,0,0,0,0,0,0,0, }; +#endif #else { + /* some values created by j.vfmt */ // 0xf003d14f,0x8a03cda0,0x9a03cdbf,0x8903cdc0, // 0x9903d01f,0x8c03d020,0x9c03d14f,0xf4000000, 0xf0000000 | (cap-1), 0x8a000000 | daddr, @@ -1568,10 +1550,12 @@ int hsdp_format(UNIT *uptr) { /* 250191 249248 250191 0 */ // uint32 dmap[4] = {0xf003d14f, 0x8a03cda0, 0x9a03d14f, 0xf4000000}; int i; - /* vendor flaw map */ + /* NULL vendor flaw map */ uint32 vmap[2] = {0xf0000004, 0xf4000000}; + /* diag flaw map */ uint32 dmap[4] = {0xf0000000 | (cap-1), 0x8a000000 | daddr, - 0x9a000000 | (cap-1), 0xf4000000}; + 0x9a000000 | (cap-1), 0xf4000008}; +//WAS 0x9a000000 | (cap-1), 0xf4000000}; /* see if user wants to initialize the disk */ if (!get_yn("Initialize disk? [Y] ", TRUE)) { @@ -1630,8 +1614,7 @@ int hsdp_format(UNIT *uptr) { fputc('\n', stderr); /* byte swap the buffers for dmap and umap */ -// for (i=0; i<256; i++) { - for (i=0; i<8; i++) { + for (i=0; i<256; i++) { umap[i] = (((umap[i] & 0xff) << 24) | ((umap[i] & 0xff00) << 8) | ((umap[i] & 0xff0000) >> 8) | ((umap[i] >> 24) & 0xff)); } @@ -1672,16 +1655,17 @@ int hsdp_format(UNIT *uptr) { /* vaddr is daddr - spt */ sim_fseek(uptr->fileref, (daddr)*ssize, SEEK_SET); /* seek DMAP */ +// if ((sim_fwrite((char *)&vmap, sizeof(uint32), 2, uptr->fileref)) != 2) { if ((sim_fwrite((char *)&dmap, sizeof(uint32), 4, uptr->fileref)) != 4) { sim_debug(DEBUG_CMD, dptr, "Error on dmap write to diskfile sect %06x\n", daddr * ssize); } -#ifdef MAYBE +#ifndef MAYBE sim_fseek(uptr->fileref, (uaddr)*ssize, SEEK_SET); /* seek UMAP */ - if ((sim_fwrite((char *)&umap, sizeof(uint32), 4, uptr->fileref)) != 4) { + if ((sim_fwrite((char *)&umap, sizeof(uint32), 256, uptr->fileref)) != 256) { sim_debug(DEBUG_CMD, dptr, - "Error on umap write to diskfile sect %06x\n", uaddr * ssize); + "Error on umap write to diskfile sect %06x\n", uaddr * ssize); } #endif @@ -1696,7 +1680,6 @@ int hsdp_format(UNIT *uptr) { /* seek home again */ sim_fseek(uptr->fileref, 0, SEEK_SET); /* seek home */ free(buff); /* free cylinder buffer */ -// set_devattn(addr, SNS_DEVEND); /* start us up */ return 0; } @@ -1708,7 +1691,6 @@ t_stat hsdp_attach(UNIT *uptr, CONST char *file) DEVICE *dptr = get_dev(uptr); t_stat r; uint32 ssize; /* sector size in bytes */ - struct ddata_t *data; uint8 buff[1024]; /* see if valid disk entry */ @@ -1721,14 +1703,6 @@ t_stat hsdp_attach(UNIT *uptr, CONST char *file) if ((r = attach_unit(uptr, file)) != SCPE_OK) return r; - /* get a buffer to hold hsdp_t structure */ - /* extended data structure per unit */ - if ((data = (struct ddata_t *)calloc(1, sizeof(struct ddata_t))) == 0) { - detach_unit(uptr); - return SCPE_FMT; - } - - uptr->DDATA = (void *)data; /* save pointer to structure in DDATA */ uptr->capac = CAP(type); /* size in sectors */ ssize = SSB(type); /* disk sector size in bytes */ @@ -1766,9 +1740,7 @@ fmt: } /* start out at sector 0 */ - data->cyl = 0; /* current cylinder position */ - data->tpos = 0; /* current track position */ - data->spos = 0; /* current sector position */ + uptr->CHS = 0; /* set CHS to cyl/hd/sec = 0 */ sim_debug(DEBUG_CMD, dptr, "Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\n", @@ -1784,12 +1756,7 @@ fmt: /* detach a disk device */ t_stat hsdp_detach(UNIT *uptr) { - struct ddata_t *data = (struct ddata_t *)uptr->DDATA; - - if (data != 0) { - free(data); /* free disk data structure */ - } - uptr->DDATA = 0; /* no pointer to disk data */ + uptr->SNS = 0; /* clear sense data */ uptr->CMD &= ~0xffff; /* no cmd and flags */ return detach_unit(uptr); /* tell simh we are done with disk */ } @@ -1803,6 +1770,7 @@ t_stat hsdp_boot(int32 unit_num, DEVICE * dptr) { SPAD[0xf8] = 0xF000; /* show as F class device */ if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ + /* now boot the disk */ return chan_boot(GET_UADDR(uptr->CMD), dptr); /* boot the ch/sa */ } @@ -1818,6 +1786,8 @@ t_stat hsdp_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) return SCPE_IERR; /* no, error */ if (uptr->flags & UNIT_ATT) /* is unit attached? */ return SCPE_ALATT; /* no, error */ + + /* now loop through the units and find named disk */ for (i = 0; hsdp_type[i].name != 0; i++) { if (strcmp(hsdp_type[i].name, cptr) == 0) { uptr->flags &= ~UNIT_TYPE; /* clear old type */ @@ -1833,7 +1803,7 @@ t_stat hsdp_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) t_stat hsdp_get_type(FILE *st, UNIT * uptr, int32 v, CONST void *desc) { if (uptr == NULL) - return SCPE_IERR; + return SCPE_IERR; fputs("TYPE=", st); fputs(hsdp_type[GET_TYPE(uptr->flags)].name, st); return SCPE_OK; @@ -1854,8 +1824,6 @@ t_stat hsdp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cp } fprintf (st, ".\nEach drive has the following storage capacity:\r\n"); for (i = 0; hsdp_type[i].name != 0; i++) { -// int32 capac = CAP(i); /* disk capacity in sectors */ -// int32 ssize = SSB(i); /* disk sector size in bytes */ int32 size = CAPB(i); /* disk capacity in bytes */ size /= 1024; /* make KB */ size = (10 * size) / 1024; /* size in MB * 10 */ diff --git a/SEL32/sel32_iop.c b/SEL32/sel32_iop.c index 1dfbbce..b36b0a5 100644 --- a/SEL32/sel32_iop.c +++ b/SEL32/sel32_iop.c @@ -1,6 +1,6 @@ /* sel32_iop.c: SEL-32 Model 8000/8001/8002 IOP processor controller - Copyright (c) 2018-2019, James C. Bevier + Copyright (c) 2018-2020, James C. Bevier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -44,6 +44,8 @@ extern void set_devattn(uint16 addr, uint8 flags); extern void post_extirq(void); extern uint32 attention_trap; /* set when trap is requested */ extern void set_devwake(uint16 addr, uint8 flags); +extern t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */ +extern CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */ /* forward definitions */ uint8 iop_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); @@ -68,7 +70,7 @@ const char *iop_desc(DEVICE *dptr); #define CON_OUTPUT 0x1000 /* Output ready for unit */ #define CON_READ 0x2000 /* Read mode selected */ -/* Input buffer pointer held in u4 */ +/* not used u4 */ /* in u5 packs sense byte 0,1 and 3 */ /* Sense byte 0 */ @@ -91,18 +93,19 @@ struct _iop_data uint8 ibuff[145]; /* Input line buffer */ uint8 incnt; /* char count */ } -iop_data[NUM_UNITS_CON]; +iop_data[NUM_UNITS_IOP]; /* channel program information */ -CHANP iop_chp[NUM_UNITS_MT] = {0}; +CHANP iop_chp[NUM_UNITS_IOP] = {0}; MTAB iop_mod[] = { - {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, &show_dev_addr, NULL}, + {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", + &set_dev_addr, &show_dev_addr, NULL, "Device address"}, {0} }; UNIT iop_unit[] = { - {UDATA(iop_srv, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7E00)}, /* Channel controlller */ + {UDATA(&iop_srv, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7E00)}, /* Channel controller */ }; //DIB iop_dib = {NULL, iop_startcmd, NULL, NULL, NULL, iop_ini, iop_unit, iop_chp, NUM_UNITS_IOP, 0xff, 0x7e00,0,0,0}; @@ -115,7 +118,7 @@ DIB iop_dib = { iop_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ iop_unit, /* UNIT* units */ /* Pointer to units structure */ iop_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ - NUM_UNITS_IOP, /* uint8 numunits */ /* number of units defined */ + NUM_UNITS_IOP, /* uint8 numunits */ /* number of units defined */ 0xff, /* uint8 mask */ /* 16 devices - device mask */ 0x7e00, /* uint16 chan_addr */ /* parent channel address */ 0, /* uint32 chan_fifo_in */ /* fifo input index */ @@ -129,8 +132,8 @@ DEVICE iop_dev = { NULL, NULL, &iop_reset, /* examine, deposit, reset */ NULL, NULL, NULL, /* boot, attach, detach */ &iop_dib, DEV_UADDR|DEV_DISABLE|DEV_DEBUG, 0, dev_debug, /* dib, dev flags, debug flags, debug */ - NULL, NULL, &iop_help, /* ?, ?, help */ - NULL, NULL, &iop_desc /* ?, ?, description */ +// NULL, NULL, &iop_help, /* ?, ?, help */ +// NULL, NULL, &iop_desc /* ?, ?, description */ }; /* IOP controller routines */ @@ -140,7 +143,9 @@ void iop_ini(UNIT *uptr, t_bool f) int unit = (uptr - iop_unit); /* unit 0 */ DEVICE *dptr = &iop_dev; /* one and only dummy device */ - sim_debug(DEBUG_CMD, &iop_dev, "IOP init device %s controller/device %04x\n", dptr->name, GET_UADDR(uptr->u3)); + sim_debug(DEBUG_CMD, &iop_dev, + "IOP init device %s controller/device %04x\n", + dptr->name, GET_UADDR(uptr->u3)); iop_data[unit].incnt = 0; /* no input data */ uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ } @@ -148,6 +153,9 @@ void iop_ini(UNIT *uptr, t_bool f) /* start an I/O operation */ uint8 iop_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { + sim_debug(DEBUG_CMD, &iop_dev, + "IOP startcmd %02x controller/device %04x\n", + cmd, GET_UADDR(uptr->u3)); if ((uptr->u3 & IOP_MSK) != 0) /* is unit busy */ return SNS_BSY; /* yes, return busy */ @@ -158,9 +166,16 @@ uint8 iop_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) case IOP_INCH: /* INCH command */ uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ uptr->u3 &= LMASK; /* leave only chsa */ - sim_debug(DEBUG_CMD, &iop_dev, "iop_startcmd %04x: Cmd INCH\n", chan); + sim_debug(DEBUG_CMD, &iop_dev, + "iop_startcmd %04x: Cmd INCH iptr %06x INCHa %06x\n", + chan, iop_chp[0].ccw_addr, /* set inch buffer addr */ + iop_chp[0].chan_inch_addr); /* set inch buffer addr */ + + iop_chp[0].chan_inch_addr = iop_chp[0].ccw_addr; /* set inch buffer addr */ +// set_inch(uptr, iop_chp[0].ccw_addr); /* new address */ + uptr->u3 |= IOP_INCH2; /* save INCH command as 0xf0 */ - sim_activate(uptr, 20); /* TRY 07-13-19 */ + sim_activate(uptr, 20); /* go on */ return 0; /* no status change */ break; @@ -190,44 +205,48 @@ uint8 iop_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) /* Handle transfers for other sub-channels on IOP */ t_stat iop_srv(UNIT *uptr) { - uint16 chsa = GET_UADDR(uptr->u3); - int cmd = uptr->u3 & IOP_MSK; + uint16 chsa = GET_UADDR(uptr->u3); + int cmd = uptr->u3 & IOP_MSK; +// CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + CHANP *chp = &iop_chp[0]; /* find the chanp pointer */ +// int i; +// int len = chp->ccw_count; /* INCH command count */ + uint32 mema = chp->ccw_addr; /* get inch or buffer addr */ /* test for NOP or INCH cmds */ - if ((cmd == IOP_NOP) || (cmd == IOP_INCH2)) { /* NOP has do nothing */ - uptr->u3 &= LMASK; /* nothing left, command complete */ - sim_debug(DEBUG_CMD, &iop_dev, "iop_srv INCH/NOP chan %02x: chnend|devend\n", chsa); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ - } else - if (cmd) { + if ((cmd != IOP_NOP) && (cmd != IOP_INCH2)) { /* NOP or INCH */ uptr->u3 &= LMASK; /* nothing left, command complete */ sim_debug(DEBUG_CMD, &iop_dev, "iop_srv Unknown cmd %02x chan %02x: chnend|devend|unitexp\n", cmd, chsa); chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* done */ + return SCPE_OK; + } else + + if (cmd == IOP_NOP) { /* NOP do nothing */ + uptr->u3 &= LMASK; /* nothing left, command complete */ + sim_debug(DEBUG_CMD, &iop_dev, "iop_srv INCH/NOP chan %02x: chnend|devend\n", chsa); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ + return SCPE_OK; + } else + + /* test for INCH cmd */ + if (cmd == IOP_INCH2) { /* INCH */ + sim_debug(DEBUG_CMD, &iop_dev, + "iop_srv starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n", + mema, chsa, chp->ccw_addr, chp->ccw_count); + + /* the chp->ccw_addr location contains the inch address */ + /* call set_inch() to setup inch buffer */ +// i = set_inch(uptr, mema); /* new address */ + set_inch(uptr, mema); /* new address */ +// chp->chan_inch_addr = mema; /* set inch buffer addr */ + uptr->u3 &= LMASK; /* clear the cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ +// chan_end(chsa, SNS_CHNEND); /* we are done dev|chan end */ } return SCPE_OK; } -/* Handle output transfers for console */ -t_stat iop_srvo(UNIT *uptr) -{ - uint16 chsa = GET_UADDR(uptr->u3); - int cmd = uptr->u3 & IOP_MSK; - - sim_debug(DEBUG_CMD, &iop_dev, "iop_srvo start %04x: cmd %02x \n", chsa, cmd); - return SCPE_OK; -} - -/* Handle input transfers for console */ -t_stat iop_srvi(UNIT *uptr) -{ - uint16 chsa = GET_UADDR(uptr->u3); - int cmd = uptr->u3 & IOP_MSK; - - sim_debug(DEBUG_CMD, &iop_dev, "iop_srv start %04x: cmd %02x \n", chsa, cmd); - return SCPE_OK; -} - t_stat iop_reset(DEVICE *dptr) { /* add reset code here */ diff --git a/SEL32/sel32_lpr.c b/SEL32/sel32_lpr.c index 138717b..fb73beb 100644 --- a/SEL32/sel32_lpr.c +++ b/SEL32/sel32_lpr.c @@ -1,6 +1,6 @@ /* sel32_lpr.c: SEL 32 Line Printer - Copyright (c) 2018, James C. Bevier + Copyright (c) 2018-2020, James C. Bevier Portions provided by Richard Cornwell and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a @@ -161,9 +161,9 @@ MTAB lpr_mod[] = { }; UNIT lpr_unit[] = { - {UDATA(lpr_srv, UNIT_LPR, 66), 300, UNIT_ADDR(0x7EF8)}, /* A */ + {UDATA(&lpr_srv, UNIT_LPR, 66), 300, UNIT_ADDR(0x7EF8)}, /* A */ #if NUM_DEVS_LPR > 1 - {UDATA(lpr_srv, UNIT_LPR, 66), 300, UNIT_ADDR(0x7EF9)}, /* B */ + {UDATA(&lpr_srv, UNIT_LPR, 66), 300, UNIT_ADDR(0x7EF9)}, /* B */ #endif }; @@ -217,6 +217,7 @@ uint8 lpr_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) /* process the command */ switch (cmd & LPR_CMDMSK) { case 0x00: /* INCH command */ + /* the IOP should already have the inch buffer set, so ignore */ sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd %04x: Cmd INCH\n", chan); //fprintf(stderr, "lpr_startcmd %04x: Cmd INCH\n", chan); return SNS_CHNEND|SNS_DEVEND; /* all is well */ diff --git a/SEL32/sel32_mt.c b/SEL32/sel32_mt.c index 153ac54..d3b02b5 100644 --- a/SEL32/sel32_mt.c +++ b/SEL32/sel32_mt.c @@ -1,6 +1,6 @@ /* sel32_mt.c: SEL-32 8051 Buffered Tape Processor - Copyright (c) 2018, James C. Bevier + Copyright (c) 2018-2020, James C. Bevier Portions provided by Richard Cornwell and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a @@ -47,8 +47,11 @@ extern int chan_write_byte(uint16 chan, uint8 *data); extern void set_devattn(uint16 addr, uint8 flags); extern t_stat chan_boot(uint16 addr, DEVICE *dptr); extern DEVICE *get_dev(UNIT *uptr); +extern t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */ +extern CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */ -extern uint32 SPAD[]; /* cpu SPAD */ +extern uint32 M[]; /* our memory */ +extern uint32 SPAD[]; /* cpu SPAD */ #ifdef NUM_DEVS_MT #define BUFFSIZE (64 * 1024) @@ -56,70 +59,6 @@ extern uint32 SPAD[]; /* cpu SPAD */ #define DEV_BUF_NUM(x) (((x) & 07) << DEV_V_UF) #define GET_DEV_BUF(x) (((x) >> DEV_V_UF) & 07) -#if 0 -CMNDCODE EQU $-1B -/* IOCD cmd bits 0-7 OP */ - DATAB X'23' 1 REW - DATAB X'02' 2 READ - DATAB X'01' 3 WRITE - DATAB X'93' 4 WEOF - DATAB X'FF' 5 XCHANP - DATAB X'43' 6 ADVR - DATAB X'63' 7 ADVF - DATAB X'53' 8 BKSR - DATAB X'73' 9 BKXF - DATAB X'01' A UPSPACE (REALLY A WRITE) - DATAB X'A3' B ERASE - SPACE 3 -* TIMER TABLE VALUES -* -* ENTRIES CORRESPOND ONE-FOR-ONE WITH ENTRIES IN OTAB -* AND REPRESENT THE MAXIMUM NUMBER OF SECONDS WHICH THE -* CORRESPONDING FUNCTION WOULD REQUIRE TO COMPLETE ON A 25 IPS -* TAPE DRIVE ON WHICH WAS MOUNTED A 2400 ft REEL OF TAPE. - BOUND 1W -TIMETBL DATAH 0 OPEN - DATAH 2 REWIND - DATAH 128 READ ASSUME TRANSFER OF 128K - DATAH 128 WRITE ASSUME TRANSFER OF 128K - DATAH 2 WRITE END-OF-FILE - DATAH 0 EXECUTE CHANNEL PROGRAM - DATAH 2 ADVANCE RECORD - DATAH 1152 SPACE FORWARD TO END-OF-FILE - DATAH 2 BACKSPACE RECORD - DATAH 1152 SPACE BACKWARD TO END-OF-FILE - DATAH 2 UPSPACE - DATAH 2 ERASE - DATAH 0 EJECT - DATAH 0 CLOSE - DATAH 0 TERM - DATAH 0 TEST -TOENTS EQU $-TIMETBL/2 NUMBER OF ENTRIES IN TABLE - SPACE 2 -* -* HANDLER OP CODE VECTOR TABLE -* - BOUND 1W -OTAB EQU $ - ACH OPEN 0 OPEN - ACH RWND 1 RWND - ACH READ 2 READ - ACH WRITE 3 WRITE - ACH WEOF 4 WEOF - ACH XCHANP 5 EXECUTE CHANNEL PROGRAM - ACH ADVR 6 ADVR - ACH ADVF 7 ADVF - ACH BKSR 8 BKSR - ACH BKSF 9 BKSF - ACH UPSP A UPSP - ACH ERASE B ERASE - ACH EJCT C EJCT - ACH CLOSE D CLOSE - ACH TERM E TERM - ACH TEST F TEST - SPACE 3 -#endif - #define CMD u3 /* BTP tape commands */ #define MT_INCH 0x00 /* Initialize channel command */ @@ -436,8 +375,10 @@ DEVICE mtb_dev = { /* start an I/O operation */ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { + 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_EXP, &mta_dev, "mt_startcmd entry chan %04x cmd %02x\n", chan, cmd); if (mt_busy[GET_DEV_BUF(dptr->flags)] != 0 || (uptr->CMD & MT_CMDMSK) != 0) { @@ -450,10 +391,12 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) switch (cmd & 0xFF) { case 0x00: /* INCH command */ - /* POS has INCH buffer address and us9 the count */ - /* just return OK and channel software will use POS as status buffer */ - sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd INCH done unit %04x cmd %02x\n", - unit, cmd); + sim_debug(DEBUG_CMD, dptr, "start INCH command\n"); + + sim_debug(DEBUG_CMD, dptr, + "mt_startcmd starting INCH %06x cmd, chsa %04x MemBuf %08x cnt %04x\n", + uptr->u4, chsa, chp->ccw_addr, chp->ccw_count); + /* UTX_needs_interrupt */ cmd = MT_CMDMSK; /* insert INCH cmd as 0xff */ /* fall through */ @@ -477,7 +420,6 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->SNS = (uptr->SNS & 0x0000ff00); /* clear all but byte 2 */ uptr->SNS |= (SNS_RDY|SNS_ONLN); /* set ready status */ /* Fall through */ -// case 0x4: /* Sense */ if (sim_tape_wrp(uptr)) uptr->SNS |= (SNS_WRP); /* write protected */ if (sim_tape_bot(uptr)) @@ -572,28 +514,71 @@ t_stat mt_srv(UNIT *uptr) int unit = (uptr - dptr->units); int cmd = uptr->CMD & MT_CMDMSK; int bufnum = GET_DEV_BUF(dptr->flags); + CHANP *chp = find_chanp_ptr(addr); /* find the chanp pointer */ t_mtrlnt reclen; - t_stat r = SCPE_ARG; /* Force error if not set */ + t_stat r = SCPE_ARG; /* Force error if not set */ + int i; + uint32 mema; + uint16 len; uint8 ch; uint8 zc = 0; + uint8 buf[1024]; sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv unit %04x cmd %02x\n", unit, cmd); - if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ - uptr->SNS |= SNS_INTVENT; /* unit intervention required */ - mt_busy[bufnum] &= ~1; /* make our buffer not busy */ - if (cmd != MT_SENSE) { /* we are completed with unit check status */ + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + uptr->SNS |= SNS_INTVENT; /* unit intervention required */ + mt_busy[bufnum] &= ~1; /* make our buffer not busy */ + if (cmd != MT_SENSE) { /* we are completed with unit check status */ chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SCPE_OK; } } switch (cmd) { - case MT_CMDMSK: /* 0x0ff for inch 0x00 */ /* INCH is for channel, nothing for us */ + case MT_CMDMSK: /* 0x0ff for inch 0x00 */ /* INCH is for channel, nothing for us */ + len = chp->ccw_count; /* INCH command count */ + mema = chp->ccw_addr; /* get inch or buffer addr */ + sim_debug(DEBUG_CMD, dptr, + "mt_srv starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n", + mema, addr, chp->ccw_addr, chp->ccw_count); + + if (len == 0) { + /* we have invalid count, error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + for (i=0; i < len; i++) { + if (chan_read_byte(addr, &buf[i])) { + /* we have error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + /* just dump data */ + } /* uptr->POS has INCH buffer address, just leave it */ - sim_debug(DEBUG_CMD, &mta_dev, "mt_srv cmd 0 INCH unit=%04x\n", unit); - uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ - mt_busy[bufnum] &= ~1; /* make our buffer not busy */ - chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ + /* the chp->ccw_addr location contains the inch address */ + /* call set_inch() to setup inch buffer */ + 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; + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } +#endif + sim_debug(DEBUG_CMD, dptr, + "mt_srv cmd INCH chsa %04x addr %06x count %04x completed\n", + addr, mema, chp->ccw_count); + uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ + mt_busy[bufnum] &= ~1; /* make our buffer not busy */ + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ break; #ifndef FIX_DIAG @@ -976,7 +961,7 @@ t_stat mt_srv(UNIT *uptr) uptr->CMD &= ~(MT_CMDMSK); mt_busy[bufnum] &= ~1; sim_debug(DEBUG_CMD, &mta_dev, "Skip record at EOT\n"); -//BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); +//BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK); chan_end(addr, SNS_DEVEND|SNS_UNITEXP); break; } @@ -1019,7 +1004,7 @@ t_stat mt_srv(UNIT *uptr) uptr->SNS &= ~SNS_LOAD; /* reset BOT */ mt_busy[bufnum] &= ~1; sim_debug(DEBUG_CMD, &mta_dev, "Skip file got EOT sense %08x unit %02x\n", uptr->SNS, unit); -//BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); +//BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK); chan_end(addr, SNS_DEVEND|SNS_UNITEXP); break; } @@ -1032,7 +1017,8 @@ t_stat mt_srv(UNIT *uptr) uptr->SNS |= SNS_CMDREJ; uptr->CMD &= ~MT_CMDMSK; mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_DEVEND|SNS_UNITCHK); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); +//BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK); + chan_end(addr, SNS_DEVEND|SNS_UNITEXP); } else { uptr->POS ++; sim_activate(uptr, 500); @@ -1048,7 +1034,7 @@ t_stat mt_srv(UNIT *uptr) uptr->CMD &= ~(MT_CMDMSK); mt_busy[bufnum] &= ~1; /* we are done dev|chan end */ - chan_end(addr, SNS_DEVEND); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND); + chan_end(addr, SNS_DEVEND); break; } break; @@ -1118,6 +1104,9 @@ t_stat mt_attach(UNIT *uptr, CONST char *file) return r; /* report any error */ } sim_debug(DEBUG_EXP, &mta_dev, "mt_attach complete filename %s\n", file); + uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ + uptr->POS = 0; /* clear position data */ + uptr->SNS = 0; /* clear sense data */ set_devattn(addr, SNS_DEVEND); /* ready int???? */ return SCPE_OK; /* return good status */ } @@ -1127,6 +1116,8 @@ t_stat mt_detach(UNIT *uptr) { sim_debug(DEBUG_EXP, &mta_dev, "mt_detach\n"); uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ + uptr->POS = 0; /* clear position data */ + uptr->SNS = 0; /* clear sense data */ return sim_tape_detach(uptr); } diff --git a/SEL32/sel32_scfi.c b/SEL32/sel32_scfi.c index f9ebcd7..93bdff4 100644 --- a/SEL32/sel32_scfi.c +++ b/SEL32/sel32_scfi.c @@ -32,6 +32,8 @@ extern void set_devattn(uint16 addr, uint8 flags); extern t_stat chan_boot(uint16 addr, DEVICE *dptr); extern int test_write_byte_end(uint16 chsa); extern DEVICE *get_dev(UNIT *uptr); +extern t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */ +extern CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */ extern uint32 M[]; /* our memory */ extern uint32 SPAD[]; /* cpu SPAD memory */ @@ -40,6 +42,34 @@ extern uint32 SPAD[]; /* cpu SPAD memory */ #define UNIT_SCFI UNIT_ATTABLE | UNIT_IDLE | UNIT_DISABLE +/* useful conversions */ +/* Fill STAR value from cyl, trk, sec data */ +#define CHS2STAR(c,h,s) (((c<<16) & 0xffff0000)|((h<<8) & 0xff00)|(s & 0xff)) +/* convert STAR value to number of sectors */ +#define STAR2SEC(star,spt,spc) ((star&0xff)+(((star>>8)&0xff)*spt)+((star>>16)*spc)) +/* convert STAR value to number of heads or tracks */ +#define STAR2TRK(star,tpc) ((star >> 16) * tpc + ((star >> 8) & 0x0ff)) +/* convert STAR value to number of cylinders */ +#define STAR2CYL(star) ((star >> 16) & 0xffff) +/* convert byte value to number of sectors mod sector size */ +#define BYTES2SEC(bytes,ssize) (((bytes) + (ssize-1)) >> 10) +/* get sectors per track for specified type */ +#define SPT(type) (scfi_type[type].spt) +/* get sectors per cylinderfor specified type */ +#define SPC(type) (scfi_type[type].spt*scfi_type[type].nhds) +/* get number of cylinders for specified type */ +#define CYL(type) (scfi_type[type].cyl) +/* get number of heads for specified type */ +#define HDS(type) (scfi_type[type].nhds) +/* get disk capacity in sectors for specified type */ +#define CAP(type) (CYL(type)*HDS(type)*SPT(type)) +/* get number of bytes per sector for specified type */ +#define SSB(type) (scfi_type[type].ssiz*4) +/* get disk capacity in bytes for specified type */ +#define CAPB(type) (CAP(type)*SSB(type)) +/* get disk geometry as STAR value for specified type */ +#define GEOM(type) (CHS2STAR(CYL(type),HDS(type),SPT(type))) + /* INCH command information */ /* WD 0 - Data address @@ -165,10 +195,12 @@ 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 ATTR u6 -/* u6 */ -/* u6 holds drive attribute entry */ -/* provided by inch command for controller */ +#define CHS u6 +/* u6 holds the current cyl, hd, sec for the drive */ + +/* this attribute information is provided by the INCH command */ +/* for each device and is not used. It is reconstructed from */ +/* the disk_t structure data for the assigned disk */ /* bits 0-7 - Flags bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option @@ -176,24 +208,15 @@ bits 0-7 - Flags bit 3 - 0=Reserved bit 4 - 1=Drive not present bit 5 - 1=Dual Port - bit 6 - 0=Reserved - bit 7 - 0=Reserved + bit 6 - 0=Reserved 00 768 byte sec + bit 7 - 0=Reserved 01 1024 byte sec bits 8-15 - sector count (sectors per track)(F16=16, F20=20) bits 16-23 - MHD Head count (number of heads on MHD) bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option of mini-module) */ -#define DDATA up7 -/* Pointer held in up7 */ -/* sects/cylinder = sects/track * numhds */ -/* allocated during attach command for each unit defined */ -struct ddata_t -{ - uint16 cyl; /* Cylinder head at */ - uint16 tpos; /* Track position */ - uint16 spos; /* Sector position */ -}; +/* Not Used up7 */ /* disk definition structure */ struct scfi_t @@ -205,7 +228,9 @@ struct scfi_t uint16 ucyl; /* Number of cylinders used */ uint16 cyl; /* Number of cylinders on disk */ uint8 type; /* Device type code */ - uint32 geom; /* disk star geometry cyl(16) hsd(8) sec(8) */ + /* bit 1 mhd */ + /* bits 6/7 = 0 768 byte blk */ /* not used on UDP/DPII */ + /* = 1 1024 byte blk */ /* not used on UDP/DPII */ } scfi_type[] = @@ -219,49 +244,6 @@ scfi_type[] = {NULL, 0} }; -#if 0 -***************************************************************** -* DEVICE ID TABLE -***************************************************************** - SPACE - BOUND 1W -DID.TBL EQU $ -* -*DEVICE ID NAME.................................................. -*TOTAL ALLOC. UNITS..................................... : -*BIT MAP SIZE .............................. : : -*NO. OF HEADS ........................ : : : -*SECTOR SIZE ................... : : : : -*SECTORS/TRACK .............. : : : : : -*SECTORS/ALOC. UNIT.......... : : : : : : -*SECTORS/BLOCK ....... : : : : : : : -*OLD DEVICE ID NAME.... : : : : : : : : -* : : : : : : : : : -* ......:..:..:...:....:....:.....:......:........: -DID FORM 32, 8, 8, 8, 8, 16, 16, 32, 64 - SPACE -* CLASS 'F' EXTENDED I/O DISC DEVICES - DID C'DF01', 3, 3, 26, 64, 2, , 1334, C'FL001' - DID C'DF02', 1, 2, 20, 192, 5, 625, 20000, C'MH040' - DID C'DF03', 1, 2, 20, 192, 5, 1250, 40000, C'MH080' - DID C'DF04', 1, 4, 20, 192, 19, 2375, 76000, C'MH300' - DID C'DF0E', 1,16, 20, 192, 1, 2732, 87400, C'MH1GB' - DID C'DF05', 1, 1, 20, 192, 4, 184, 5120, C'FH005' - DID C'DF06', 1, 2, 20, 192, 1, 250, 8000, C'CD032' - DID C'DF07', 1, 2, 20, 192, 3, 750, 24000, C'CD064' - DID C'DF08', 1, 2, 20, 192, 1, 250, 8000, C'CD096' - DID C'DF08', 1, 2, 20, 192, 5, 1250, 40000, C'CD096' - DID C'DF09', 1, 8, 20, 192, 40, 2500, 80000, C'MH600' - DID C'DF0A', 1, 8, 20, 192, 40, 2500, 80000, C'FM600' - DID C'DF0B', 1, 8, 20, 192, 1, 1711, 5472, C'SG038' - DID C'DF0C', 1, 8, 20, 192, 1, 5464,174848, C'SG120' - DID C'DF0D', 1, 8, 20, 192, 1, 3491,116808, C'SG076' - DID C'DF0B', 1, 8, 20, 192, 1, 1711, 54752, C'SG038' - DID C'DF0C', 1, 8, 20, 192, 1, 5464,174848, C'SG120' - DID C'DF0D', 1, 8, 20, 192, 1, 3491,116808, C'SG076' -* -#endif - uint8 scfi_preio(UNIT *uptr, uint16 chan); uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); uint8 scfi_haltio(uint16 addr); @@ -370,17 +352,30 @@ DEVICE sdb_dev = { }; #endif +/* convert sector disk address to star values (c,h,s) */ +uint32 scfisec2star(uint32 daddr, int type) +{ + int32 sec = daddr % scfi_type[type].spt; /* get sector value */ + int32 spc = scfi_type[type].nhds * scfi_type[type].spt; /* sec per cyl */ + int32 cyl = daddr / spc; /* cylinders */ + int32 hds = (daddr % spc) / scfi_type[type].spt; /* heads */ + + /* now return the star value */ + return (CHS2STAR(cyl,hds,sec)); /* return STAR */ +} + /* start a disk operation */ uint8 scfi_preio(UNIT *uptr, uint16 chan) { - DEVICE *dptr = get_dev(uptr); - int unit = (uptr - dptr->units); + DEVICE *dptr = get_dev(uptr); + uint16 chsa = GET_UADDR(uptr->CMD); + int unit = (uptr - dptr->units); sim_debug(DEBUG_CMD, dptr, "scfi_preio CMD %08x unit=%02x\n", uptr->CMD, unit); if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */ return SNS_BSY; } - sim_debug(DEBUG_CMD, dptr, "scfi_preio unit=%02x\n", unit); + sim_debug(DEBUG_CMD, dptr, "scfi_preio unit %02x chsa %04x OK\n", unit, chsa); return 0; /* good to go */ } @@ -389,9 +384,11 @@ uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uint16 addr = GET_UADDR(uptr->CMD); DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); - uint8 ch; + CHANP *chp = find_chanp_ptr(addr); /* find the chanp pointer */ - sim_debug(DEBUG_CMD, dptr, "scfi_startcmd unit %02x cmd %04x CMD %08x\n", unit, cmd, uptr->CMD); + sim_debug(DEBUG_CMD, dptr, + "scfi_startcmd unit %02x cmd %04x CMD %08x\n", + unit, cmd, uptr->CMD); 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 */ @@ -407,114 +404,21 @@ uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) } sim_debug(DEBUG_CMD, dptr, "scfi_startcmd CMD 2 unit=%02x cmd %02x\n", unit, cmd); - if ((uptr->flags & UNIT_ATT) == 0) { /* see if unit is attached */ - if (cmd == DSK_SNS) { /* not attached, is cmd Sense 0x04 */ - sim_debug(DEBUG_CMD, dptr, "scfi_startcmd CMD sense\n"); - /* bytes 0,1 - Cyl entry from STAR reg in STAR */ - ch = (uptr->STAR >> 24) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b0 unit=%02x 1 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - ch = (uptr->STAR >> 16) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b1 unit=%02x 1 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - /* byte 2 - Track entry from STAR reg in STAR */ - ch = (uptr->STAR >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b2 unit=%02x 1 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - /* byte 3 - Sector entry from STAR reg in STAR */ - ch = (uptr->STAR) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b3 unit=%02x 1 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - /* bytes 4 - mode reg, byte 0 of SNS */ - ch = (uptr->SNS >> 24) & 0xff; /* return the sense data for device */ - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%02x 1 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - /* bytes 5-7 - status bytes, bytes 1-3 of SNS */ - ch = (uptr->SNS >> 16) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%02x 2 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - ch = (uptr->SNS >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%02x 3 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - ch = (uptr->SNS) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%02x 4 %02x\n", - unit, ch); - chan_write_byte(addr, &ch) ; - /* bytes 8-11 - drive attribute register (DATR) entries from uptr->ATTR - * via INCH cmd */ - ch = (uptr->ATTR >> 24) & 0xff; - chan_write_byte(addr, &ch) ; - ch = (uptr->ATTR >> 16) & 0xff; - chan_write_byte(addr, &ch) ; - ch = (uptr->ATTR >> 8 ) & 0xff; - chan_write_byte(addr, &ch) ; - ch = (uptr->ATTR >> 0) & 0xff; - chan_write_byte(addr, &ch) ; - /* bytes 12 & 13 contain drive related status */ - ch = 0; /* zero for now */ - chan_write_byte(addr, &ch) ; - chan_write_byte(addr, &ch) ; - - uptr->SNS &= 0xff000000; /* clear status bytes, but leave mode data */ - return SNS_CHNEND|SNS_DEVEND; - } - if (cmd == 0x0) /* INCH cmd gives unit check */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - - uptr->SNS |= (SNS_INTVENT|SNS_CMDREJ); /* set new error status */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* we done */ - } - /* Unit is online, so process a command */ switch (cmd) { - case DSK_INCH: /* INCH 0x00 */ - { - uint32 mema; /* memory address */ - uint32 i; - UNIT *up = dptr->units; /* first unit for this device */ + case DSK_INCH: /* INCH 0x00 */ sim_debug(DEBUG_CMD, dptr, - "scfi_startcmd starting inch cmd addr %04x STAR %08x\n", - addr, uptr->STAR); - /* STAR (u4) has IOCD word 1 contents. For the disk processor it contains */ - /* a pointer to the INCH buffer followed by 8 drive attribute words that */ - /* contains the flags, sector count, MHD head count, and FHD count */ - /* us9 has the byte count from IOCD wd2 and should be 0x24 (36) */ - /* the INCH buffer address must be returned in STAR and us9 left non-zero */ - /* just return OK and channel software will use up8 as status buffer */ - mema = (uint32)uptr->STAR; /* get memory address of buffer */ - uptr->STAR = M[mema>>2]; /* get status buffer address for XIO return status */ - sim_debug(DEBUG_CMD, dptr, - "scfi_startcmd starting inch cmd addr %04x STAR %08x mema %08x units %02x\n", - addr, uptr->STAR, mema, dptr->numunits); - /* the next 8 words have drive data for each unit */ - /* WARNING 8 drives must be defined for this controller */ - /* so we will not have a map fault */ - for (i=0; inumunits && i<8; i++) { /* process all drives */ - up->ATTR = M[(mema>>2)+i+1]; /* save each unit's drive data */ - sim_debug(DEBUG_CMD, dptr, - "scfi_startcmd ATTR data %08x unit %02x flags %02x sec %02x MHD %02x FHD %02x\n", - up->ATTR, i, (up->ATTR >> 24)&0xff, (up->ATTR >> 16)&0xff, - (up->ATTR >> 8)&0xff, (up->ATTR&0xff)); - up++; /* next unit for this device */ - } - sim_debug(DEBUG_CMD, dptr, "scfi_startcmd done INCH cmd addr %04x\n", addr); + "scfi_startcmd starting INCH %06x cmd, chsa %04x MemBuf %08x cnt %04x\n", + uptr->u4, addr, chp->ccw_addr, chp->ccw_count); + uptr->CMD |= DSK_INCH2; /* use 0xf0 for inch, just need int */ sim_activate(uptr, 20); /* start things off */ return 0; break; - } case DSK_SCK: /* Seek command 0x07 */ case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ - uptr->CMD &= ~(DSK_STAR); /* show we do not have seek STAR in STAR */ case DSK_WD: /* Write command 0x01 */ case DSK_RD: /* Read command 0x02 */ case DSK_LMR: /* read mode register */ @@ -554,25 +458,23 @@ t_stat scfi_srv(UNIT *uptr) DEVICE *dptr = get_dev(uptr); /* get pointer to Dev Info Blk for this device */ DIB *dibp = (DIB *)dptr->ctxt; - CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */ - struct ddata_t *data = (struct ddata_t *)(uptr->up7); + CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */ int cmd = uptr->CMD & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); - uint32 trk, cyl; + uint32 trk, cyl, sec; int unit = (uptr - dptr->units); - int len; - int dlen = 0; /* total bytes processed */ + int len=0; int i; uint8 ch; - uint16 ssize = scfi_type[type].ssiz*4; /* Size of one sector in bytes */ - int tsize = scfi_type[type].spt * ssize; /* get track size in bytes */ - int32 tstart = 0; /* Location of start of cyl/track/sect in data */ + uint16 ssize = scfi_type[type].ssiz*4; /* Size of one sector in bytes */ + int32 tstart = 0; /* Location of start of cyl/track/sect in data */ uint8 buf2[1024]; uint8 buf[1024]; sim_debug(DEBUG_DETAIL, &sda_dev, - "scfi_srv entry unit %02x cmd %02x chsa %04x chan %04x count %04x\n", - unit, cmd, chsa, chsa>>8, chp->ccw_count); + "scfi_srv entry unit %02x CMD %08x chsa %04x count %04x %x/%x/%x \n", + unit, uptr->CMD, chsa, chp->ccw_count, + STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ uptr->SNS |= SNS_INTVENT; /* unit intervention required */ @@ -581,17 +483,92 @@ t_stat scfi_srv(UNIT *uptr) } sim_debug(DEBUG_CMD, dptr, - "scfi_srv cmd=%02x chsa %04x count %04x\n", - cmd, chsa, chp->ccw_count); + "scfi_srv cmd=%02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); switch (cmd) { case 0: /* No command, stop disk */ break; case DSK_INCH2: /* use 0xff for inch, just need int */ + { + uint32 mema; /* memory address */ +// uint32 daws[8]; /* drive attribute registers */ +// uint32 i, j; + uint32 i; + + len = chp->ccw_count; /* INCH command count */ + mema = chp->ccw_addr; /* get inch or buffer addr */ + sim_debug(DEBUG_CMD, dptr, + "scfi_srv starting INCH cmd, chsa %04x MemBuf %06x cnt %04x\n", + chsa, chp->ccw_addr, chp->ccw_count); + + /* mema has IOCD word 1 contents. For the disk processor it contains */ + /* a pointer to the INCH buffer followed by 8 drive attribute words that */ + /* contains the flags, sector count, MHD head count, and FHD count */ + /* len has the byte count from IOCD wd2 and should be 0x24 (36) */ + /* the INCH buffer address must be set for the parrent channel as well */ + /* 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; + } + + /* read all 36 bytes, stopping every 4 bytes to make words */ + /* the first word has the inch buffer address */ + /* the next 8 words have drive data for each unit */ + /* WARNING 8 drives must be defined for this controller */ + /* so we will not have a map fault */ +// for (i=0, j=0; i < 36; i++) { + for (i=0; i < 36; i++) { + if (chan_read_byte(chsa, &buf[i])) { + /* we have error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (((i+1)%4) == 0) { /* see if we have a word yet */ + if (i == 3) + /* inch buffer address */ + mema = (buf[0]<<24) | (buf[1]<<16) | + (buf[2]<<8) | (buf[3]); + else + /* drive attribute registers */ +// daws[j++] = (buf[i-3]<<24) | (buf[i-2]<<16) +// | (buf[i-1]<<8) | (buf[i]); + /* may want to use this later */ + /* clear warning errors */ + tstart = (buf[i-3]<<24) | (buf[i-2]<<16) + | (buf[i-1]<<8) | (buf[i]); + } + } + /* now call set_inch() function to write and test inch bybber addresses */ + 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; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } +#endif uptr->CMD &= ~(0xffff); /* remove old cmd */ sim_debug(DEBUG_CMD, dptr, - "scfi_srv cmd INCH chsa %04x count %04x completed\n", chsa, chp->ccw_count); - chan_end(chsa, SNS_CHNEND); /* return just channel end */ + "scfi_srv cmd INCH chsa %04x addr %06x count %04x completed\n", + chsa, mema, chp->ccw_count); +#ifdef FIX4MPX + chan_end(chsa, SNS_CHNEND); /* return just channel end OK */ +#else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ +#endif + } break; case DSK_NOP: /* NOP 0x03 */ @@ -623,58 +600,23 @@ t_stat scfi_srv(UNIT *uptr) 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 ((uptr->STAR >> 16) == data->cyl) { + if (STAR2CYL(uptr->STAR) == STAR2CYL(uptr->CHS)) { /* we are on cylinder, seek is done */ sim_debug(DEBUG_CMD, dptr, "scfi_srv seek on cylinder unit=%02x %04x %04x\n", - unit, uptr->STAR >> 16, data->cyl); + unit, uptr->STAR >> 16, uptr->CHS >> 16); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - set_devattn(chsa, SNS_DEVEND); /* start the operation */ - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek end unit=%02x %04x %04x\n", - unit, uptr->STAR >> 16, data->cyl); + /* we have already seeked to the required sector */ + /* we do not need to seek again, so move on */ + chan_end(chsa, SNS_DEVEND|SNS_CHNEND); sim_activate(uptr, 20); break; } else { - /* Compute delay based of difference. */ - /* Set next state = index */ - i = (uptr->STAR >> 16) - data->cyl; - sim_debug(DEBUG_CMD, dptr, "scfi_srv seek unit=%02x %04x %04x\n", - unit, uptr->STAR >> 16, i); - if (i > 0 ) { - if (i > 50) { - data->cyl += 50; /* seek 50 cyl */ - sim_activate(uptr, 800); - } else - if (i > 20) { - data->cyl += 20; /* seek 20 cyl */ - sim_activate(uptr, 400); - } else { - data->cyl++; /* Seek 1 cyl */ - sim_activate(uptr, 200); - } - if (data->cyl >= scfi_type[type].cyl) /* test for over max */ - data->cyl = scfi_type[type].cyl-1; /* make max */ - } else { - if (i < -50) { - data->cyl -= 50; /* seek 50 cyl */ - sim_activate(uptr, 800); - } else - if (i < -20) { - data->cyl -= 20; /* seek 20 cyl */ - sim_activate(uptr, 400); - } else { - data->cyl--; /* seek 1 cyl */ - sim_activate(uptr, 200); - } - if ((int32)data->cyl < 0) /* test for less than zero */ - data->cyl = 0; /* make zero */ - } - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek next unit=%02x %04x %04x\n", - unit, uptr->STAR >> 16, data->cyl); - sim_activate(uptr, 2); + /* we have wasted enough time, we there */ + uptr->CHS = uptr->STAR; /* we are there */ + sim_activate(uptr, 10); break; } } @@ -690,26 +632,35 @@ t_stat scfi_srv(UNIT *uptr) break; } } -rezero: - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek unit=%02x star %02x %02x %02x %02x\n", + /* the value is really a sector offset for the disk */ + /* but will treat as c/h/s for processing */ + /* the cyl, trk, and sect are ready to update */ + sim_debug(DEBUG_CMD, dptr, + "scfi_srv STAR unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); +rezero: + sim_debug(DEBUG_DETAIL, dptr, + "scfi_srv seek unit=%02x star %02x %02x %02x %02x\n", + unit, buf[0], buf[1], buf[2], buf[3]); + /* save STAR (target sector) data in STAR */ uptr->STAR = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]); - cyl = uptr->STAR >> 16; /* get the cylinder */ + cyl = STAR2CYL(uptr->STAR); /* get the cylinder */ trk = buf[2]; /* get the track */ - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv SEEK %08x cyl %04x trk %02x sec %02x unit=%02x\n", - uptr->CMD, cyl&0xffff, trk, buf[3], unit); - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv Disk %s cyl %04x hds %02x sec/trk %02x unit=%02x\n", - scfi_type[type].name, scfi_type[type].cyl, scfi_type[type].nhds, scfi_type[type].spt, unit); - /* FIXME do something with FHD here */ + sim_debug(DEBUG_DETAIL, dptr, + "scfi_srv SEEK %08x cyl %04x trk %02x sec %02x unit=%02x\n", + uptr->CMD, cyl&0xffff, trk, buf[3], unit); + /* Check if seek valid */ if (cyl >= scfi_type[type].cyl || trk >= scfi_type[type].nhds || buf[3] >= scfi_type[type].spt) { + sim_debug(DEBUG_CMD, dptr, "dsk_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 */ @@ -718,35 +669,36 @@ rezero: break; } - uptr->CMD |= DSK_STAR; /* show we have seek STAR in CMD */ - /* calc the sector address of data */ + /* calc the new sector address of data */ /* calculate file position in bytes of requested sector */ /* file offset in bytes */ - tstart = (((cyl * scfi_type[type].nhds * tsize) + (trk * tsize) + buf[3]) * ssize); - data->tpos = trk; /* save the track/head number */ - data->spos = buf[3]; /* save the sector number */ + tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type); + uptr->CHS = CHS2STAR(STAR2CYL(uptr->CHS), trk, buf[3]); + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek start %08x trk %04x sec %02x\n", tstart, trk, buf[3]); + + /* just seek to the location where we will r/w data */ if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* seek home */ sim_debug(DEBUG_DETAIL, dptr, "scfi_srv Error on seek to %08x\n", tstart); } /* Check if already on correct cylinder */ - if (cyl != data->cyl) { - /* No, Do seek */ + /* if not, do a delay to slow things down */ + if (STAR2CYL(uptr->STAR) != STAR2CYL(uptr->CHS)) { + /* Do a fake seek to kill time */ uptr->CMD |= DSK_SEEKING; /* show we are seeking */ sim_debug(DEBUG_DETAIL, dptr, - "scfi_srv seek unit=%02x cyl %04x trk %04x sec %04x\n", + "scfi_srv seeking unit=%02x to cyl %04x trk %04x sec %04x\n", unit, cyl, trk, buf[3]); sim_activate(uptr, 20); -// chan_end(chsa, SNS_CHNEND); } else { + /* we are on cylinder/track/sector, so go on */ sim_debug(DEBUG_DETAIL, dptr, "scfi_srv calc sect addr seek start %08x cyl %04x trk %04x sec %02x\n", tstart, cyl, trk, buf[3]); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ -// sim_activate(uptr, 20); chan_end(chsa, SNS_DEVEND|SNS_CHNEND); } return SCPE_OK; @@ -756,10 +708,10 @@ rezero: 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 |= DSK_SCK; /* show as seek command */ tstart = 0; /* byte offset is 0 */ - dlen = 0; /* no data written yet */ /* Read in 1 dummy character for length to inhibit SLI posting */ if (chan_read_byte(chsa, &buf[0])) { /* we have error, bail out */ @@ -770,7 +722,7 @@ rezero: } /* zero stuff */ buf[0] = buf[1] = buf[2] = buf[3] = 0; - goto rezero; /* murge with seek code */ + goto rezero; /* merge with seek code */ break; case DSK_LMR: @@ -783,6 +735,8 @@ rezero: chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } + sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x old %x new %x\n", + unit, (uptr->SNS)&0xff, buf[0]); uptr->CMD &= ~(0xffff); /* remove old cmd */ uptr->SNS &= 0x00ffffff; /* clear old mode data */ uptr->SNS |= (buf[0] << 24); /* save mode value */ @@ -793,17 +747,24 @@ rezero: /* tstart has start of sector address in bytes */ if ((uptr->CMD & DSK_READING) == 0) { /* see if we are reading data */ uptr->CMD |= DSK_READING; /* read from disk starting */ - dlen = 0; /* no data read yet */ - sim_debug(DEBUG_CMD, dptr, "DISK READ starting unit=%02x CMD %08x count %04x\n", + sim_debug(DEBUG_CMD, dptr, + "DISK READ starting unit=%02x CMD %08x count %04x\n", unit, uptr->CMD, 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)); + /* 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, data->cyl, data->tpos, data->spos); + len, ssize, cyl, trk, sec); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -811,33 +772,53 @@ rezero: sim_debug(DEBUG_CMD, dptr, "scfi_srv after READ chsa %04x count %04x\n", chsa, chp->ccw_count); + /* process the next sector of data */ for (i=0; icyl, data->tpos, data->spos, tstart); + "DISK Read %04x bytes from diskfile /%04x/%02x/%02x tstart %08x\n", + len, cyl, trk, sec, tstart); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); goto rddone; } } - dlen += len; /* add byte read to total count */ sim_debug(DEBUG_CMD, dptr, - "DISK READ from sec end %04x bytes end %04x from diskfile cyl %04x hds %02x sec %02x tstart %08x\n", - dlen, ssize, data->cyl, data->tpos, data->spos, tstart); - data->spos++; + "DISK READ from sec end %04x bytes end %04x from diskfile /%04x/%02x/%02x tstart %08x\n", + len, ssize, cyl, trk, sec, tstart); + + /* tstart has file offset in sectors */ + tstart++; /* bump to next sector */ + /* convert sect back to chs value */ + uptr->CHS = scfisec2star(tstart, type); + /* see of over end of disk */ +// if (tstart >= CAPB(type)) { + if (tstart >= CAP(type)) { + /* EOM reached, abort */ + sim_debug(DEBUG_CMD, dptr, + "DISK Read reached EOM for read from disk @ /%04x/%02x/%02x\n", + STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->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 Read %04x bytes from diskfile cyl %04x hds %02x sec %02x tstart %08x\n", - dlen, data->cyl, data->tpos, data->spos, tstart); + "DISK Read complete Read %04x bytes from diskfile /%04x/%02x/%02x tstart %08x\n", + ssize, cyl, trk, sec, tstart); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; } else { + sim_debug(DEBUG_DATA, dptr, + "DISK sector read complete, %x bytes to go from diskfile /%04x/%02x/%02x\n", + chp->ccw_count, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); sim_activate(uptr, 10); /* wait to read next sector */ break; } @@ -848,14 +829,21 @@ rddone: case DSK_WD: /* Write Data */ /* tstart has start of sector address in bytes */ + if ((uptr->CMD & DSK_WRITING) == 0) { /* see if we are writing data */ uptr->CMD |= DSK_WRITING; /* write to disk starting */ - dlen = 0; /* no data written yet */ sim_debug(DEBUG_CMD, dptr, "DISK WRITE starting unit=%02x CMD %08x bytes %04x\n", - unit, uptr->CMD, dlen); + unit, uptr->CMD, len); } - if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */ + if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */ + cyl = STAR2CYL(uptr->CHS); /* get current cyl */ + trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ + sec = uptr->CHS & 0xff; /* get sec */ + /* get sector offset */ +// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)); + tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); + /* process the next sector of data */ len = 0; /* used here as a flag for short read */ for (i=0; iCMD &= ~(0xffff); /* remove old status bits & cmd */ sim_debug(DEBUG_DATA, dptr, "DISK Wrote %04x bytes to diskfile cyl %04x hds %02x sec %02x tstart %08x\n", - ssize, data->cyl, data->tpos, data->spos, tstart); + ssize, cyl, trk, sec, tstart); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); goto wrdone; } @@ -874,12 +862,12 @@ rddone: } buf2[i] = ch; /* save the char */ } - dlen += ssize; /* add 1 sector of bytes */ + /* write the sector to disk */ if ((i=sim_fwrite(buf2, 1, ssize, uptr->fileref)) != ssize) { sim_debug(DEBUG_CMD, dptr, "Error %08x on write %04x to diskfile cyl %04x hds %02x sec %02x\n", - i, ssize, data->cyl, data->tpos, data->spos); + i, ssize, cyl, trk, sec); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -887,16 +875,32 @@ rddone: if (len != 0) { /* see if done with write command */ sim_debug(DEBUG_DATA, dptr, "DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x tstart %08x\n", - ssize, data->cyl, data->tpos, data->spos, tstart); + ssize, cyl, trk, sec, tstart); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; } sim_debug(DEBUG_CMD, dptr, "DISK WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x tstart %08x\n", - dlen, ssize, data->cyl, data->tpos, data->spos, tstart); - data->spos++; - sim_activate(uptr, 10); + len, ssize, cyl, trk, sec, tstart); + + /* tstart has file offset in sectors */ + tstart++; /* bump to next sector */ + /* convert sect back to chs value */ + uptr->CHS = scfisec2star(tstart, type); + /* see of over end of disk */ +// if (tstart >= CAPB(type)) { + if (tstart >= 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->CMD &= ~(0xffff); /* 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 */ @@ -904,7 +908,7 @@ wrdone: break; default: - sim_debug(DEBUG_DETAIL, dptr, "invalid command %02x unit %02x\n", cmd, unit); + 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 */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); @@ -919,16 +923,12 @@ wrdone: void scfi_ini(UNIT *uptr, t_bool f) { DEVICE *dptr = get_dev(uptr); - uint32 i = GET_TYPE(uptr->flags); -// uint32 ssize = scfi_type[i].ssiz * 4; /* disk sector size in bytes */ - uint32 tsize = scfi_type[i].spt; /* get track size in sectors */ - uint32 csize = scfi_type[i].nhds * tsize; /* get cylinder size in sectors */ - /* capacity is total cylinders time sectors per cylinder */ - uint32 tdisk = scfi_type[i].cyl * csize; /* get total disk size in sectors */ + int i = GET_TYPE(uptr->flags); uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ + uptr->SNS = ((uptr->SNS & 0x00ffffff) | (scfi_type[i].type << 24)); /* save mode value */ /* total sectors on disk */ - uptr->capac = tdisk; /* disk size in sectors */ + uptr->capac = CAP(i); /* disk size in sectors */ sim_debug(DEBUG_EXP, &sda_dev, "SDA init device %s on unit SDA%.1x cap %x\n", dptr->name, GET_UADDR(uptr->CMD), uptr->CMD); @@ -976,7 +976,7 @@ int scfi_format(UNIT *uptr) { buff[2] = 'R'; buff[3] = 'O'; sim_debug(DEBUG_CMD, dptr, - "Creating disk file of trk size %04x capacity %d\n", + "Creating disk file of trk size %04x bytes, capacity %d\n", tsize*ssize, cap*ssize); /* write zeros to each track of the disk */ for (cyl = 0; cyl < cylv; cyl++) { @@ -991,7 +991,7 @@ int scfi_format(UNIT *uptr) { buff[3] = 0; } } - if ((cyl % 400) == 0) + if ((cyl % 100) == 0) fputc('.', stderr); fputc('\r', stderr); fputc('\n', stderr); @@ -1006,41 +1006,27 @@ int scfi_format(UNIT *uptr) { t_stat scfi_attach(UNIT *uptr, CONST char *file) { uint16 addr = GET_UADDR(uptr->CMD); int type = GET_TYPE(uptr->flags); -// DEVICE *dptr = get_dev(uptr); + DEVICE *dptr = get_dev(uptr); t_stat r; - uint32 tsize; /* track size in bytes */ uint32 ssize; /* sector size in bytes */ - uint32 csize, tdisk; - struct ddata_t *data; uint8 buff[1024]; - /* have simulator attach the file to the unit */ - if ((r = attach_unit(uptr, file)) != SCPE_OK) - return r; - if (scfi_type[type].name == 0) { /* does the assigned disk have a name */ detach_unit(uptr); /* no, reject */ return SCPE_FMT; /* error */ } - /* get a buffer to hold scfi_t structure */ - /* extended data structure per unit */ - if ((data = (struct ddata_t *)calloc(1, sizeof(struct ddata_t))) == 0) { - detach_unit(uptr); - return SCPE_FMT; - } + /* have simulator attach the file to the unit */ + if ((r = attach_unit(uptr, file)) != SCPE_OK) + return r; - uptr->up7 = (void *)data; /* save pointer to structure in up7 */ - /* track size in bytes is sectors/track times words/sector time 4 bytse/word */ - ssize = scfi_type[type].ssiz * 4; /* disk sector size in bytes */ - tsize = scfi_type[type].spt; /* get track size in sectors */ - csize = scfi_type[type].nhds * tsize; /* get cylinder size in sectors */ - /* capacity is total cylinders time sectors per cylinder */ - tdisk = scfi_type[type].cyl * csize; /* get total disk size in sectors */ - uptr->capac = tdisk; /* disk capacity in sectors */ + uptr->capac = CAP(type); /* disk capacity in sectors */ + ssize = SSB(type); /* get sector size in bytes */ + + sim_debug(DEBUG_CMD, dptr, "Disk %s cyl %d hds %d sec %d ssiz %d capacity %d\n", + scfi_type[type].name, scfi_type[type].cyl, scfi_type[type].nhds, + scfi_type[type].spt, ssize, uptr->capac); /* disk capacity */ - sim_debug(DEBUG_CMD, &sda_dev, "Disk cyl %d spt %d ssiz %d capacity %d\n", - csize, tsize, ssize, uptr->capac*ssize); /* disk capacity */ if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ detach_unit(uptr); /* if no space, error */ @@ -1070,18 +1056,12 @@ fmt: return SCPE_FMT; /* error */ } - /* set the max configuration geometry */ - scfi_type[type].geom = (scfi_type[type].cyl << 16) | - (scfi_type[type].nhds << 8) | (scfi_type[type].spt); - data->cyl = 0; /* current cylinder position */ - data->tpos = 0; /* current track position */ - data->spos = 0; /* current sector position */ + uptr->CHS = 0; /* set CHS to cyl/hd/sec = 0 */ sim_debug(DEBUG_CMD, &sda_dev, - "Attach %8s hds %d spt %d spc %d cyl %d capacity %d\n", - scfi_type[type].name, scfi_type[type].nhds, scfi_type[type].spt, - scfi_type[type].nhds * scfi_type[type].spt, - scfi_type[type].cyl, uptr->capac); + "Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\n", + scfi_type[type].name, CYL(type), HDS(type), SPT(type), SPC(type), + CAP(type), CAPB(type)); sim_debug(DEBUG_CMD, &sda_dev, "File %s attached to %s\r\n", file, scfi_type[type].name); @@ -1092,12 +1072,7 @@ fmt: /* detach a disk device */ t_stat scfi_detach(UNIT *uptr) { - struct ddata_t *data = (struct ddata_t *)uptr->up7; - - if (data != 0) { - free(data); /* free disk data structure */ - } - uptr->up7 = 0; /* no pointer to disk data */ + uptr->SNS = 0; /* clear sense data */ uptr->CMD &= ~0xffff; /* no cmd and flags */ return detach_unit(uptr); /* tell simh we are done with disk */ } @@ -1125,14 +1100,14 @@ t_stat scfi_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) return SCPE_IERR; /* no, error */ if (uptr->flags & UNIT_ATT) /* is unit attached? */ return SCPE_ALATT; /* no, error */ + /* now loop through the units and find named disk */ for (i = 0; scfi_type[i].name != 0; i++) { if (strcmp(scfi_type[i].name, cptr) == 0) { uptr->flags &= ~UNIT_TYPE; /* clear the old UNIT type */ uptr->flags |= SET_TYPE(i); /* set the new type */ /* set capacity of disk in sectors */ - uptr->capac = scfi_type[i].cyl * scfi_type[i].nhds * - scfi_type[i].spt; + uptr->capac = CAP(i); return SCPE_OK; } } @@ -1164,13 +1139,11 @@ t_stat scfi_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, } fprintf (st, ".\nEach drive has the following storage capacity:\r\n"); for (i = 0; scfi_type[i].name != 0; i++) { - /* disk capacity in sectors */ - int32 capac = scfi_type[i].cyl * scfi_type[i].nhds * scfi_type[i].spt; - int32 ssize = scfi_type[i].ssiz * 4; /* disk sector size in bytes */ - int32 size = capac * ssize; /* disk capacity in bytes */ + int32 size = CAPB(i); /* disk capacity in bytes */ size /= 1024; /* make KB */ size = (10 * size) / 1024; /* size in MB * 10 */ - fprintf(st, " %-8s %4d.%1d MB\r\n", scfi_type[i].name, size/10, size%10); + fprintf(st, " %-8s %4d.%1d MB cyl %3d hds %3d sec %3d blk %3d\r\n", + scfi_type[i].name, size/10, size%10, CYL(i), HDS(i), SPT(i), SSB(i)); } fprint_set_help(st, dptr); fprint_show_help(st, dptr); diff --git a/SEL32/sel32_sys.c b/SEL32/sel32_sys.c index 79172e1..830a4d5 100644 --- a/SEL32/sel32_sys.c +++ b/SEL32/sel32_sys.c @@ -1,6 +1,6 @@ /* sel32_sys.c: SEL-32 Gould Concept/32 (orignal SEL-32) Simulator system interface. - Copyright (c) 2018, James C. Bevier + Copyright (c) 2018-2020, James C. Bevier Portions provided by Richard Cornwell and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a