diff --git a/IBM360/STATUS.txt b/IBM360/STATUS.txt index d25dbdc..0808ad7 100644 --- a/IBM360/STATUS.txt +++ b/IBM360/STATUS.txt @@ -1,18 +1,21 @@ Current status: Operating Systems: -TOS/360: Will IPL, and read IPL deck. Will not run any test jobs. +TOS/360: Will IPL, and read IPL deck. Will run some jobs. -DOS/360: Will IPL disk init job. +DOS/360: Will initialize disk. + Will not restore disk. + Will run 2314 distribution. -OS/360: Will IPL disk init job. +OS/360: Will initialize disk. + Will not restore disk. + Will start to IPL OS/360 ibm360_cpu.c: Need to complete floating point and decimal instructions. ibm360_chan.c - Need to move fprintf's to sim_debug functions. - Add number of Channels and subchannels as option. + More debugging required. ibm360_cdp.c: Add support for binary mode. @@ -27,13 +30,13 @@ ibm360_con.c: Appears to be working. ibm360_dasd.c: - Need to complete. + Possibly working. ibm360_lpr.c: Need to add in support for line skip and skip control. ibm360_mt.c: - Appears to be working. + Possibly working. ibm360_sys.c: Need to add in deposit function. diff --git a/IBM360/ibm360_chan.c b/IBM360/ibm360_chan.c index 4081e25..7490ecc 100644 --- a/IBM360/ibm360_chan.c +++ b/IBM360/ibm360_chan.c @@ -77,9 +77,9 @@ #define PMASK 0xf0000000 /* Storage protection mask */ extern uint32 *M; extern uint8 key[MAXMEMSIZE / 2048]; -extern UNIT cpu_unit; #define MAX_DEV (MAX_CHAN * 256) +int channels = MAX_CHAN; int subchannels = SUB_CHANS; /* Number of subchannels */ int irq_pend = 0; uint32 caw[256]; /* Channel command address word */ @@ -132,7 +132,7 @@ find_subchan(uint16 device) { return -1; if (device > 0xff) { chan = (device >> 8) & 0x7; - if (chan > MAX_CHAN) + if (chan > channels) return -1; return subchannels + chan; } @@ -178,24 +178,15 @@ int writefull(int chan, uint32 addr, uint32 *word) { chan_status[chan] |= STATUS_PROT; return 1; } - k = key[(addr & 0xfffc00) >> 10]; + k = key[(addr & 0xfffc00) >> 10]; if ((k & 0x8) != 0 && (k & 0xf0) != sk) { chan_status[chan] |= STATUS_PROT; return 1; } } -fprintf(stderr, "Channel write %02x %06x %08x %08x '", chan, addr, *word, ccw_count[chan]); addr &= AMASK; addr >>= 2; M[addr] = *word; - for(k = 24; k >= 0; k -= 8) { - char ch = ebcdic_to_ascii[(*word >> k) & 0xFF]; - if (ch < 0x20 || ch == 0xff) - ch = '.'; - fprintf(stderr, "%c", ch); - } - - fprintf(stderr, "'\n\r"); return 0; } @@ -206,18 +197,25 @@ load_ccw(uint16 chan, int tic_ok) { UNIT *uptr; loop: + /* Abort if channel not on double boundry */ if ((caw[chan] & 0x7) != 0) { chan_status[chan] |= STATUS_PCHK; return 1; } + /* Abort if we have any errors */ + if (chan_status[chan] & 0x7f) + return 1; /* Check if we have status modifier set */ if (chan_status[chan] & STATUS_MOD) { caw[chan]+=8; caw[chan] &= PMASK|AMASK; /* Mask overflow bits */ chan_status[chan] &= ~STATUS_MOD; } + /* Read in next CCW */ readfull(chan, caw[chan], &word); -fprintf(stderr, "Channel read ccw %02x %06x %08x\n\r", chan, caw[chan], word); + sim_debug(DEBUG_CMD, &cpu_dev, "Channel read ccw %02x %06x %08x\n", + chan, caw[chan], word); + /* TIC can't follow TIC nor be first in chain */ if (((word >> 24) & 0xf) == CMD_TIC) { if (tic_ok) { caw[chan] = (caw[chan] & PMASK) | (word & AMASK); @@ -230,15 +228,17 @@ fprintf(stderr, "Channel read ccw %02x %06x %08x\n\r", chan, caw[chan], word); } caw[chan] += 4; caw[chan] &= PMASK|AMASK; /* Mask overflow bits */ - /* Check if fetch ok */ + /* Check if not chaining data */ if ((ccw_flags[chan] & FLAG_CD) == 0) { ccw_cmd[chan] = (word >> 24) & 0xff; cmd = 1; } + /* Set up for this command */ ccw_addr[chan] = word & AMASK; ccw_addr[chan] |= caw[chan] & PMASK; /* Copy key */ readfull(chan, caw[chan], &word); -fprintf(stderr, "Channel read ccw2 %02x %06x %08x\n\r", chan, caw[chan], word); + sim_debug(DEBUG_CMD, &cpu_dev, "Channel read ccw2 %02x %06x %08x\n", + chan, caw[chan], word); caw[chan]+=4; caw[chan] &= PMASK|AMASK; /* Mask overflow bits */ ccw_count[chan] = word & 0xffff; @@ -292,26 +292,41 @@ chan_read_byte(uint16 addr, uint8 *data) { int byte; int k; + /* Abort if we have any errors */ + if (chan_status[chan] & 0x7f) + return 1; if ((ccw_cmd[chan] & 0x1) == 0) { return 1; } if (chan_byte[chan] == BUFF_CHNEND) return 1; + if (ccw_count[chan] == 0) { + if ((ccw_flags[chan] & FLAG_CD) == 0) { + chan_status[chan] |= STATUS_CEND; + chan_byte[chan] = BUFF_CHNEND; + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_read_end\n"); + return 1; + } else { + if (load_ccw(chan, 1)) + return 1; + } + } if (chan_byte[chan] == BUFF_EMPTY) { if (readfull(chan, ccw_addr[chan], &chan_buf[chan])) { chan_byte[chan] = BUFF_CHNEND; irq_pend = 1; return 1; } -fprintf(stderr, "Channel read %02x %06x %08x %08x '", chan, ccw_addr[chan], chan_buf[chan], ccw_count[chan]); + sim_debug(DEBUG_DATA, &cpu_dev, "Channel write %02x %06x %08x %08x '", + chan, ccw_addr[chan], chan_buf[chan], ccw_count[chan]); for(k = 24; k >= 0; k -= 8) { char ch = ebcdic_to_ascii[(chan_buf[chan] >> k) & 0xFF]; if (ch < 0x20 || ch == 0xff) ch = '.'; - fprintf(stderr, "%c", ch); + sim_debug(DEBUG_DATA, &cpu_dev, "%c", ch); } - fprintf(stderr, "'\n\r"); + sim_debug(DEBUG_DATA, & cpu_dev, "'\n"); chan_byte[chan] = ccw_addr[chan] & 0x3; ccw_addr[chan] += 4 - chan_byte[chan]; } @@ -319,16 +334,6 @@ fprintf(stderr, "Channel read %02x %06x %08x %08x '", chan, ccw_addr[chan], chan byte = (chan_buf[chan] >> (8 * (3 - (chan_byte[chan] & 0x3)))) & 0xff; chan_byte[chan]++; *data = byte; - if (ccw_count[chan] == 0) { - if (ccw_flags[chan] & FLAG_CD) - return load_ccw(chan, 1); - else { - chan_status[chan] |= STATUS_CEND; - chan_byte[chan] = BUFF_CHNEND; - } -fprintf(stderr, "chan_read_end\n\r"); - return 1; - } return 0; } @@ -338,11 +343,34 @@ chan_write_byte(uint16 addr, uint8 *data) { int chan = find_subchan(addr); int byte; int offset; + int k; uint32 mask; + /* Abort if we have any errors */ + if (chan_status[chan] & 0x7f) + return 1; if ((ccw_cmd[chan] & 0x1) != 0) { return 1; } + if (ccw_count[chan] == 0) { + if (chan_byte[chan] != BUFF_CHNEND) { + if (writefull(chan, ccw_addr[chan], &chan_buf[chan])) { + chan_byte[chan] = BUFF_CHNEND; + return 1; + } + } + if ((ccw_flags[chan] & FLAG_CD) == 0) { + chan_byte[chan] = BUFF_CHNEND; + if ((ccw_flags[chan] & FLAG_SLI) == 0) { + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_ length\n"); + chan_status[chan] |= STATUS_LENGTH; + } + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_end\n"); + return 1; + } + if (load_ccw(chan, 1)) + return 1; + } if (chan_byte[chan] == BUFF_CHNEND) { if ((ccw_flags[chan] & FLAG_SLI) == 0) { chan_status[chan] |= STATUS_LENGTH; @@ -355,13 +383,13 @@ chan_write_byte(uint16 addr, uint8 *data) { ccw_addr[chan]--; else ccw_addr[chan]++; - if (ccw_count[chan] == 0) { - if (ccw_flags[chan] & FLAG_CD) - return load_ccw(chan, 1); - else - chan_byte[chan] = BUFF_CHNEND; - return 1; - } +// if (ccw_count[chan] == 0) { + // if (ccw_flags[chan] & FLAG_CD) + // return load_ccw(chan, 1); + // else + // chan_byte[chan] = BUFF_CHNEND; + // return 1; + // } return 0; } if (chan_byte[chan] == (BUFF_EMPTY|BUFF_DIRTY)) { @@ -370,6 +398,15 @@ chan_write_byte(uint16 addr, uint8 *data) { irq_pend = 1; return 1; } + sim_debug(DEBUG_DATA, &cpu_dev, "Channel read %02x %06x %08x %08x '", + chan, ccw_addr[chan], chan_buf[chan], ccw_count[chan]); + for(k = 24; k >= 0; k -= 8) { + char ch = ebcdic_to_ascii[(chan_buf[chan] >> k) & 0xFF]; + if (ch < 0x20 || ch == 0xff) + ch = '.'; + sim_debug(DEBUG_DATA, &cpu_dev, "%c", ch); + } + sim_debug(DEBUG_DATA, &cpu_dev, "'\n"); if ((ccw_cmd[chan] & 0xf) == CMD_RDBWD) ccw_addr[chan] -= 1 + (ccw_addr[chan] & 0x3); else @@ -397,17 +434,6 @@ chan_write_byte(uint16 addr, uint8 *data) { } else chan_byte[chan]++; chan_byte[chan] |= BUFF_DIRTY; - if (ccw_count[chan] == 0) { - if (writefull(chan, ccw_addr[chan], &chan_buf[chan])) { - chan_byte[chan] = BUFF_CHNEND; - return 1; - } - if (ccw_flags[chan] & FLAG_CD) - return load_ccw(chan, 1); - chan_byte[chan] = BUFF_CHNEND; -fprintf(stderr, "chan_write_end\n\r"); - return 1; - } return 0; } @@ -420,7 +446,8 @@ set_devattn(uint16 addr, uint8 flags) { chan_status[chan] |= ((uint16)flags) << 8; } else dev_status[addr] = flags; -fprintf(stderr, "set_devattn(%x, %x) %x\n\r", addr, flags, chan_dev[chan]); + sim_debug(DEBUG_EXP, &cpu_dev, "set_devattn(%x, %x) %x\n", + addr, flags, chan_dev[chan]); irq_pend = 1; } @@ -428,15 +455,26 @@ void chan_end(uint16 addr, uint8 flags) { int chan = find_subchan(addr); -fprintf(stderr, "chan_end(%x, %x)\n\r", addr, flags); if (chan_byte[chan] & BUFF_DIRTY) { + int k; writefull(chan, ccw_addr[chan], &chan_buf[chan]); chan_byte[chan] = BUFF_EMPTY; + sim_debug(DEBUG_DATA, &cpu_dev, "Channel read %02x %06x %08x %08x '", + chan, ccw_addr[chan], chan_buf[chan], ccw_count[chan]); + for(k = 24; k >= 0; k -= 8) { + char ch = ebcdic_to_ascii[(chan_buf[chan] >> k) & 0xFF]; + if (ch < 0x20 || ch == 0xff) + ch = '.'; + sim_debug(DEBUG_DATA, &cpu_dev, "%c", ch); + } + sim_debug(DEBUG_DATA, &cpu_dev, "'\n"); } + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end(%x, %x) %x\n", addr, flags, ccw_count[chan]); chan_status[chan] |= STATUS_CEND; chan_status[chan] |= ((uint16)flags) << 8; ccw_cmd[chan] = 0; if (ccw_count[chan] != 0 && (ccw_flags[chan] & FLAG_SLI) == 0) { + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end length\n"); chan_status[chan] |= STATUS_LENGTH; ccw_flags[chan] = 0; } @@ -455,7 +493,10 @@ int store_csw(uint16 chan) { M[0x40 >> 2] = caw[chan]; M[0x44 >> 2] = (((uint32)ccw_count[chan])) | ((uint32)chan_status[chan]<<16); -fprintf(stderr, "Channel store csw %02x %06x %08x\n\r", chan, M[0x40>>2], M[0x44 >> 2]); + chan_status[chan] = 0; + chan_dev[chan] = 0; + sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %02x %06x %08x\n", + chan, M[0x40>>2], M[0x44 >> 2]); return chan_dev[chan]; } @@ -466,12 +507,15 @@ int startio(uint16 addr) { UNIT *uptr; uint8 status; -fprintf(stderr, "SIO %x %x %x %x\n\r", addr, chan, ccw_cmd[chan], ccw_flags[chan]); + sim_debug(DEBUG_CMD, &cpu_dev, "SIO %x %x %x %x\n", addr, chan, + ccw_cmd[chan], ccw_flags[chan]); if (chan < 0 || dibp == 0) return 3; uptr = find_chan_dev(addr); if (uptr == 0) return 3; + if ((uptr->flags & UNIT_ATT) == 0) + return 3; if (ccw_cmd[chan] != 0 || (ccw_flags[chan] & (FLAG_CD|FLAG_CC)) != 0) return 2; chan_status[chan] = 0; @@ -482,18 +526,31 @@ fprintf(stderr, "SIO %x %x %x %x\n\r", addr, chan, ccw_cmd[chan], ccw_flags[chan chan_status[chan] = dibp->start_io(uptr, chan) << 8; if (chan_status[chan] != 0) { M[0x44 >> 2] = ((uint32)chan_status[chan]<<16) | M[0x44 >> 2] & 0xffff; - fprintf(stderr, "Channel store csw %02x %08x\n\r", chan, M[0x44 >> 2]); + sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %02x %08x\n", + chan, M[0x44 >> 2]); chan_status[chan] = 0; return 1; } } if (load_ccw(chan, 0) || (chan_status[chan] & (STATUS_PCI))) { M[0x44 >> 2] = ((uint32)chan_status[chan]<<16) | M[0x44 >> 2] & 0xffff; - fprintf(stderr, "Channel store csw %02x %08x\n\r", chan, M[0x44 >> 2]); + sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %02x %08x\n", + chan, M[0x44 >> 2]); chan_status[chan] &= ~STATUS_PCI; dev_status[addr] = 0; return 1; } + if (chan_status[chan] & STATUS_BUSY) { + M[0x40 >> 2] = 0; + M[0x44 >> 2] = ((uint32)chan_status[chan]<<16);// | M[0x44 >> 2] & 0xffff; + sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %02x %08x\n", + chan, M[0x44 >> 2]); + chan_status[chan] = 0; + dev_status[addr] = 0; + chan_dev[chan] = 0; + ccw_cmd[chan] = 0; + return 1; + } return 0; } @@ -508,23 +565,23 @@ int testio(uint16 addr) { uptr = find_chan_dev(addr); if (uptr == 0) return 3; - if (ccw_cmd[chan] != 0 || (ccw_flags[chan] & (FLAG_CD|FLAG_CC)) != 0) + if ((uptr->flags & UNIT_ATT) == 0) + return 3; + if (ccw_cmd[chan] != 0 || (ccw_flags[chan] & (FLAG_CD|FLAG_CC)) != 0) return 2; - if (chan_dev[chan] != addr) + if (chan_dev[chan] != 0 && chan_dev[chan] != addr) return 2; if (ccw_cmd[chan] == 0 && chan_status[chan] != 0) { store_csw(chan); - chan_status[chan] = 0; dev_status[addr] = 0; return 1; } - if (dev_status[addr] & (SNS_ATTN|SNS_UNITCHK|SNS_UNITEXP)) { + if (dev_status[addr] != 0) { M[0x40 >> 2] = 0; M[0x44 >> 2] = ((uint32)dev_status[addr]) << 24; dev_status[addr] = 0; return 1; } -fprintf(stderr, "Testio %x %x\n\r", addr, chan_status[chan]); chan_status[chan] = dibp->start_cmd(uptr, chan, 0) << 8; if (chan_status[chan] & (STATUS_ATTN|STATUS_CHECK|STATUS_EXPT)) { M[0x44 >> 2] = ((uint32)chan_status[chan]<<16) | M[0x44 >> 2] & 0xffff; @@ -565,6 +622,8 @@ int testchan(uint16 channel) { channel >>= 8; if (channel = 0) return 0; + if (channel > channels) + return 3; st = chan_status[subchannels + channel]; if (st & STATUS_BUSY) return 2; @@ -598,6 +657,7 @@ t_stat chan_boot(uint16 addr, DEVICE *dptyr) { chan_dev[chan] = addr; ccw_count[chan] = 24; ccw_flags[chan] = FLAG_CC|FLAG_SLI; + ccw_addr[chan] = 0; chan_byte[chan] = BUFF_EMPTY; ccw_cmd[chan] = 0x2; chan_status[chan] &= 0xff; @@ -621,20 +681,20 @@ uint16 scan_chan(uint8 mask) { if (irq_pend == 0) return 0; irq_pend = 0; - for (i = 0; i < subchannels + MAX_CHAN; i++) { + for (i = 0; i < subchannels + channels; i++) { if (i >= subchannels) imask = imask / 2; /* If channel end, check if we should continue */ if (chan_status[i] & STATUS_CEND) { if (ccw_flags[i] & FLAG_CC) { -//fprintf(stderr, "Scan(%x %x) CC\n\r", i, chan_status[i]); if (chan_status[i] & STATUS_DEND) (void)load_ccw(i, 1); else irq_pend = 1; } else { -fprintf(stderr, "Scan(%x %x %x %x) end\n\r", i, chan_status[i], imask, mask); + sim_debug(DEBUG_EXP, &cpu_dev, "Scan(%x %x %x %x) end\n", i, + chan_status[i], imask, mask); if ((imask & mask) != 0 || loading != 0) { pend = chan_dev[i]; break; @@ -645,10 +705,9 @@ fprintf(stderr, "Scan(%x %x %x %x) end\n\r", i, chan_status[i], imask, mask); if (pend) { irq_pend = 1; i = find_subchan(pend); -fprintf(stderr, "Scan end (%x %x)\n\r", chan_dev[i], pend); + sim_debug(DEBUG_EXP, &cpu_dev, "Scan end (%x %x)\n", chan_dev[i], + pend); store_csw(i); - chan_status[i] = 0; - chan_dev[i] = 0; dev_status[pend] = 0; } else { for (i = 0; i < MAX_DEV; i++) { @@ -656,10 +715,11 @@ fprintf(stderr, "Scan end (%x %x)\n\r", chan_dev[i], pend); pend = find_subchan(i); if (ccw_cmd[pend] == 0 && mask & (0x80 >> (i >> 8))) { irq_pend = 1; -fprintf(stderr, "Set atten %03x %02x\n\r", i, dev_status[i]); -// M[0x40 >> 2] = 0; - M[0x44 >> 2] = (((uint32)dev_status[i]) << 24) | - (M[0x44>>2] & 0xffff); + M[0x44 >> 2] = (((uint32)dev_status[i]) << 24); + M[0x40>>2] = 0; + sim_debug(DEBUG_EXP, &cpu_dev, + "Set atten %03x %02x [%08x] %08x\n", + i, dev_status[i], M[0x40 >> 2], M[0x44 >> 2]); dev_status[i] = 0; return i; } @@ -667,6 +727,9 @@ fprintf(stderr, "Set atten %03x %02x\n\r", i, dev_status[i]); } pend = 0; } + /* Only return loading unit on loading */ + if (loading != 0 && loading != pend) + return 0; return pend; } @@ -737,10 +800,14 @@ set_dev_addr(UNIT * uptr, int32 val, CONST char *cptr, void *desc) if (r != SCPE_OK) return r; - devaddr = GET_UADDR(uptr->u3); + if ((newdev >> 8) > channels) + return SCPE_ARG; + if (newdev > MAX_DEV) return SCPE_ARG; + devaddr = GET_UADDR(uptr->u3); + /* Clear out existing entry */ if (dptr->flags & DEV_UADDR) { dev_unit[devaddr] = NULL; @@ -769,11 +836,16 @@ set_dev_addr(UNIT * uptr, int32 val, CONST char *cptr, void *desc) /* Update device entry */ if (dptr->flags & DEV_UADDR) { dev_unit[devaddr] = dibp; - fprintf(stderr, "Set dev %x\n\r", devaddr); + uptr->u3 &= ~UNIT_ADDR(0x7ff); + uptr->u3 |= UNIT_ADDR(devaddr); + fprintf(stderr, "Set dev %x\n\r", GET_UADDR(uptr->u3)); } else { for (i = 0; i < dibp->numunits; i++) { dev_unit[devaddr + i] = dibp; - fprintf(stderr, "Set dev %x\n\r", devaddr + i); + uptr = &((dibp->units)[i]); + uptr->u3 &= ~UNIT_ADDR(0x7ff); + uptr->u3 |= UNIT_ADDR(devaddr + i); + fprintf(stderr, "Set dev %x\n\r", GET_UADDR(uptr->u3)); } } return r; diff --git a/IBM360/ibm360_con.c b/IBM360/ibm360_con.c index fcb473b..812c07e 100644 --- a/IBM360/ibm360_con.c +++ b/IBM360/ibm360_con.c @@ -85,13 +85,19 @@ t_stat con_detach(UNIT *); UNIT con_unit[] = { - {UDATA(con_srv, 0, 0), 0, UNIT_ADDR(0x1F)}, /* A */ + {UDATA(con_srv, UNIT_ATT, 0), 0, UNIT_ADDR(0x1F)}, /* A */ +}; + +MTAB con_mod[] = { + {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, + &show_dev_addr, NULL}, + {0} }; struct dib con_dib = { 0xFF, 1, NULL, con_startcmd, NULL, con_unit, con_ini}; DEVICE con_dev = { - "INQ", con_unit, NULL, NULL, + "INQ", con_unit, NULL, con_mod, NUM_DEVS_CON, 8, 15, 1, 8, 8, NULL, NULL, NULL, NULL, NULL, NULL, &con_dib, DEV_UADDR | DEV_DISABLE | DEV_DEBUG, 0, dev_debug @@ -258,7 +264,7 @@ con_srv(UNIT *uptr) { switch (ch) { case '\r': case '\n': - sim_debug(DEBUG_CMD, &con_dev, "%d: ent\n", u); + sim_debug(DEBUG_DATA, &con_dev, "%d: ent\n", u); // if (con_data[u].inptr != 0) uptr->u3 |= CON_INPUT; uptr->u3 |= CON_CR; @@ -295,7 +301,7 @@ con_srv(UNIT *uptr) { break; default: - sim_debug(DEBUG_CMD, &con_dev, "%d: key '%c'\n", u, ch); + sim_debug(DEBUG_DATA, &con_dev, "%d: key '%c'\n", u, ch); if (con_data[u].inptr < sizeof(con_data[u].ibuff)) { ch = ascii_to_ebcdic[ch]; if (ch == 0xff) { diff --git a/IBM360/ibm360_cpu.c b/IBM360/ibm360_cpu.c index fcc7601..390d3a1 100644 --- a/IBM360/ibm360_cpu.c +++ b/IBM360/ibm360_cpu.c @@ -36,7 +36,9 @@ #define UNIT_MSIZE (0xff << UNIT_V_MSIZE) #define MEMAMOUNT(x) (x << UNIT_V_MSIZE) -#define HIST_MAX 50000 +#define TMR_RTC 0 + +#define HIST_MAX 5000000 #define HIST_MIN 64 #define HIST_PC 0x1000000 #define HIST_SPW 0x2000000 @@ -56,6 +58,8 @@ uint16 irqcode; /* Interupt code */ uint8 flags; /* Misc flags */ uint16 irqaddr; /* Address of IRQ vector */ uint16 loading; /* Doing IPL */ +uint8 interval_irq = 0; /* Interval timer IRQ */ + #define ASCII 0x08 /* ASCII/EBCDIC mode */ #define MCHECK 0x04 /* Machine check flag */ @@ -143,6 +147,12 @@ const char *cpu_description (DEVICE *dptr); t_bool build_dev_tab (void); +/* Interval timer option */ +t_stat rtc_srv(UNIT * uptr); +t_stat rtc_reset(DEVICE * dptr); +int32 rtc_tps = 120; + + /* CPU data structures cpu_dev CPU device descriptor @@ -151,7 +161,7 @@ t_bool build_dev_tab (void); cpu_mod CPU modifier list */ -UNIT cpu_unit = { UDATA (/*&rtc_srv*/NULL, UNIT_BINK, MAXMEMSIZE) }; +UNIT cpu_unit = { UDATA (&rtc_srv, UNIT_BINK, MAXMEMSIZE) }; REG cpu_reg[] = { { HRDATA (PC, PC, 24) }, @@ -206,9 +216,9 @@ MTAB cpu_mod[] = { DEVICE cpu_dev = { "CPU", &cpu_unit, cpu_reg, cpu_mod, 1, 16, 24, 1, 16, 8, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL, NULL, 0, 0, NULL, - NULL, NULL, &cpu_help, NULL, NULL, &cpu_description + &cpu_ex, &cpu_dep, &cpu_reset, NULL, NULL, NULL, + NULL, DEV_DEBUG, 0, dev_debug, +// NULL, NULL, &cpu_help, NULL, NULL, &cpu_description }; #if 0 /* 370 Operators */ @@ -337,9 +347,10 @@ int WriteFull(uint32 addr, uint32 data) { storepsw(OPPSW, IRC_ADDR); return 1; } -// if ((addr& 0xffff00) == 0x1800) { -// fprintf(stderr, "Write %x %x\n\r", addr, data); -// } + + if ((addr & 0xfffff0) == 0xc90 && data == 0x40404040) { + fprintf(stderr, "Error word\n\r"); + } offset = addr & 0x3; addr >>= 2; @@ -406,9 +417,9 @@ int WriteByte(uint32 addr, uint32 data) { storepsw(OPPSW, IRC_ADDR); return 1; } -// if ((addr& 0xffff00) == 0x1800) { -// fprintf(stderr, "Write Byte %x %x\n\r", addr, data); -// } + if ((addr & 0xfffff0) == 0xc90 && data == 0x40) { + fprintf(stderr, "Error byte\n\r"); + } offset = 8 * (3 - (addr & 0x3)); addr >>= 2; @@ -447,10 +458,10 @@ int WriteHalf(uint32 addr, uint32 data) { storepsw(OPPSW, IRC_ADDR); return 1; } -// if ((addr& 0xffff00) == 0x1800) { -// fprintf(stderr, "Write Half %x %x\n\r", addr, data); -// } + if ((addr & 0xfffff0) == 0xc90 && data == 0x4040) { + fprintf(stderr, "Error half\n\r"); + } offset = addr & 0x3; addr >>= 2; @@ -523,6 +534,12 @@ sim_instr(void) t_uint64 t64a; reason = SCPE_OK; + /* Enable timer if option set */ + if (cpu_unit.flags & FEAT_TIMER) { + sim_activate(&cpu_unit, 10000); + } + interval_irq = 0; + while (reason == SCPE_OK) { wait_loop: @@ -549,8 +566,16 @@ wait_loop: goto supress; } + if (interval_irq && (sysmsk & 01)) { + interval_irq = 0; + storepsw(OEPSW, 0x40); + goto supress; + } + if (loading || flags & WAIT) { /* CPU IDLE */ + if (flags & WAIT && sysmsk == 0) + return STOP_HALT; sim_interval = -1; goto wait_loop; } @@ -780,9 +805,19 @@ opr: } else if ((addr1 & 0x7) != 0) { storepsw(OPPSW, IRC_SPEC); } else { - irqaddr = addr1; - irqcode = 0; - goto supress; + if (ReadFull(addr1, &src1)) + goto supress; + if (ReadFull(addr1+4, &src2)) + goto supress; + if (hst_lnt) { + hst_p = hst_p + 1; + if (hst_p >= hst_lnt) + hst_p = 0; + hst[hst_p].pc = irqaddr | HIST_LPW; + hst[hst_p].src1 = src1; + hst[hst_p].src2 = src2; + } + goto lpsw; } break; @@ -798,6 +833,8 @@ opr: storepsw(OPPSW, IRC_PRIV); else cc = testio(addr1); +// if (cc != 0 && hst_lnt && hst_p > 2) + // hst_p -= 2; break; case OP_HIO: @@ -879,10 +916,8 @@ set_cc: set_cc3: regs[reg1] = dest; cc = 3; - if (pmsk & FIXOVR) { + if (pmsk & FIXOVR) storepsw(OPPSW, IRC_FIXOVR); - reason =1; - } } goto set_cc; @@ -895,9 +930,9 @@ set_cc3: case OP_ALR: dest = src1 + src2; cc = 0; - if ((uint32)src1 > (uint32)src2) + if ((uint32)dest < (uint32)src1) cc |= 2; - if (dest == 0) + if (dest != 0) cc |= 1; regs[reg1] = dest; break; @@ -1035,10 +1070,9 @@ fprintf(stderr, " %d %08x %08x\n\r", src1, dest, src1); src1 = -src1; if (fill & 2) src2 = -src2; - regs[reg1|1] = src2; - regs[reg1] = src1; + regs[reg1] = src2; + regs[reg1|1] = src1; fprintf(stderr, " %08x %08x\n\r", src1, src2); -// reason =1; break; case OP_NR: @@ -1147,23 +1181,31 @@ char_save: case OP_SRL: dest = regs[reg1]; + if (hst_lnt) + hst[hst_p].src1 = dest; dest = ((uint32)dest) >> (addr1 & 0x3f); regs[reg1] = dest; break; case OP_SLL: dest = regs[reg1]; + if (hst_lnt) + hst[hst_p].src1 = dest; dest = ((uint32)dest) << (addr1 & 0x3f); regs[reg1] = dest; break; case OP_SRA: dest = regs[reg1]; + if (hst_lnt) + hst[hst_p].src1 = dest; dest = (int32)dest >> (addr1 & 0x3f); goto set_cc; case OP_SLA: dest = regs[reg1]; + if (hst_lnt) + hst[hst_p].src1 = dest; src2 = dest & MSIGN; addr1 &= 0x3f; cc = 0; @@ -1752,12 +1794,12 @@ save_dbl: /* Floating Store register */ case OP_STD: - if (WriteFull(addr2 + 4, src1h)) + if (WriteFull(addr1 + 4, src1h)) break; /* Fall through */ case OP_STE: - WriteFull(addr2, src1); + WriteFull(addr1, src1); break; /* Floating Compare */ @@ -1913,8 +1955,8 @@ save_dbl: /* Compute sign of result */ case OP_MP: case OP_DP: -// storepsw(OPPSW, IRC_OPR); - // goto supress; + storepsw(OPPSW, IRC_OPR); + goto supress; break; /* Extended precision load round */ @@ -1926,7 +1968,7 @@ save_dbl: case OP_MXDR: case OP_MXD: default: - reason=1; + // reason=1; storepsw(OPPSW, IRC_OPR); goto supress; } @@ -1951,6 +1993,7 @@ supress: if (hst_lnt) { hst[hst_p].src2 = src2; } +lpsw: sysmsk = (src1 >> 24) & 0xff; st_key = (src1 >> 16) & 0xf0; flags = (src1 >> 16) & 0xf; @@ -1980,6 +2023,26 @@ t_stat cpu_reset (DEVICE *dptr) return SCPE_OK; } + +/* Interval timer routines */ +t_stat +rtc_srv(UNIT * uptr) +{ + if (cpu_unit.flags & FEAT_TIMER) { + int32 t; + t = sim_rtcn_calb (rtc_tps, TMR_RTC); + sim_activate_after(uptr, 1000000/rtc_tps); + t = M[0x50>>2]; + M[0x50>>2]--; + if (((t ^ M[0x50>>2]) & MSIGN) != 0 && (t & MSIGN) == 0) { + fprintf(stderr, "Timer %08x\n\r", M[0x50>>2]); + interval_irq = 1; + } + } + return SCPE_OK; +} + + /* Memory examine */ t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) diff --git a/IBM360/ibm360_dasd.c b/IBM360/ibm360_dasd.c index 0a07287..d4cb672 100644 --- a/IBM360/ibm360_dasd.c +++ b/IBM360/ibm360_dasd.c @@ -101,10 +101,10 @@ #define DK_ERASE 0x11 /* Erase to end of track */ #define DK_MT 0x80 /* Multi track flag */ -#define DK_INDEX 0x100 /* Index seen in command */ -#define DK_NOEQ 0x200 /* Not equal compare */ -#define DK_HIGH 0x400 /* High compare */ -#define DK_PARAM 0x800 /* Parameter in u4 */ +#define DK_INDEX 0x0100 /* Index seen in command */ +#define DK_NOEQ 0x0200 /* Not equal compare */ +#define DK_HIGH 0x0400 /* High compare */ +#define DK_PARAM 0x0800 /* Parameter in u4 */ #define DK_MSET 0x1000 /* Mode set command already */ #define DK_SHORTSRC 0x2000 /* Last search was short */ #define DK_SRCOK 0x4000 /* Last search good */ @@ -129,29 +129,27 @@ #define DK_M_TRACK 0x3ff00 /* Max 1024 cylinders */ #define DK_V_HEAD 0 #define DK_M_HEAD 0xff /* Max 256 heads */ -#define DK_V_FILEMSK 18 -#define DK_M_FILEMSK 0xFF /* File mask */ /* u5 */ /* Sense byte 0 */ -#define SNS_CMDREJ 0x01 /* Command reject */ -#define SNS_INTVENT 0x02 /* Unit intervention required */ -#define SNS_BUSCHK 0x04 /* Parity error on bus */ -#define SNS_EQUCHK 0x08 /* Equipment check */ -#define SNS_DATCHK 0x10 /* Data Check */ -#define SNS_OVRRUN 0x20 /* Data overrun */ -#define SNS_TRKCND 0x40 /* Track Condition */ -#define SNS_SEEKCK 0x80 /* Seek Check */ +#define SNS_CMDREJ 0x80 /* Command reject */ +#define SNS_INTVENT 0x40 /* Unit intervention required */ +#define SNS_BUSCHK 0x20 /* Parity error on bus */ +#define SNS_EQUCHK 0x10 /* Equipment check */ +#define SNS_DATCHK 0x08 /* Data Check */ +#define SNS_OVRRUN 0x04 /* Data overrun */ +#define SNS_TRKCND 0x02 /* Track Condition */ +#define SNS_SEEKCK 0x01 /* Seek Check */ /* Sense byte 1 */ -#define SNS_DCCNT 0x01 /* Data Check Count */ -#define SNS_TRKOVR 0x02 /* Track Overrun */ -#define SNS_ENDCYL 0x04 /* End of Cylinder */ -#define SNS_INVSEQ 0x08 /* Invalid Sequence */ -#define SNS_NOREC 0x10 /* No record found */ -#define SNS_WRP 0x20 /* Write Protect */ -#define SNS_ADDR 0x40 /* Missing Address Mark */ -#define SNS_OVRINC 0x80 /* Overflow Incomplete */ +#define SNS_DCCNT 0x80 /* Data Check Count */ +#define SNS_TRKOVR 0x40 /* Track Overrun */ +#define SNS_ENDCYL 0x20 /* End of Cylinder */ +#define SNS_INVSEQ 0x10 /* Invalid Sequence */ +#define SNS_NOREC 0x08 /* No record found */ +#define SNS_WRP 0x04 /* Write Protect */ +#define SNS_ADDR 0x02 /* Missing Address Mark */ +#define SNS_OVRINC 0x01 /* Overflow Incomplete */ /* Sense byte 2 */ #define SNS_BYTE2 0x00 /* Diags Use */ @@ -160,14 +158,14 @@ /* saved in state field of data */ /* Record position, high 4 bits, low internal short count */ -#define DK_POS_INDEX 0x00 /* At Index Mark */ -#define DK_POS_HA 0x10 /* In home address (c) */ -#define DK_POS_CNT 0x20 /* In count (c) */ -#define DK_POS_KEY 0x30 /* In Key area */ -#define DK_POS_DATA 0x40 /* In Data area */ -#define DK_POS_AM 0x50 /* Address mark before record */ -#define DK_POS_END 0x80 /* Past end of data */ -#define DK_POS_SEEK 0xF0 /* In seek */ +#define DK_POS_INDEX 0x0 /* At Index Mark */ +#define DK_POS_HA 0x1 /* In home address (c) */ +#define DK_POS_CNT 0x2 /* In count (c) */ +#define DK_POS_KEY 0x3 /* In Key area */ +#define DK_POS_DATA 0x4 /* In Data area */ +#define DK_POS_AM 0x5 /* Address mark before record */ +#define DK_POS_END 0x8 /* Past end of data */ +#define DK_POS_SEEK 0xF /* In seek */ /* u6 holds last command */ /* Held in ccyl entry */ @@ -201,14 +199,14 @@ struct disk_t } disk_type[] = { - {"2301", 1, 200, 20483, 0x01}, /* 4.1 M */ - {"2302", 250, 46, 4984, 0x02}, /* 57.32 M 50ms, 120ms/10, 180ms> 10 */ - {"2303", 80, 10, 4984, 0x03}, /* 4.00 M */ - {"2305", 48, 8, 14568, 0x05}, /* 5.43 M */ - {"2305-2",96, 8, 14858, 0x05}, /* 11.26 M */ - {"2311", 202, 10, 3625, 0x11}, /* 7.32 M 156k/s 30 ms 145 full */ - {"2314", 203, 20, 7294, 0x14}, /* 29.17 M */ - {"3330", 411, 19, 13165, 0x30}, /* 100.00 M */ + {"2301", 1, 200, 20483, 0x01}, /* 4.1 M */ + {"2302", 250, 46, 4984, 0x02}, /* 57.32 M 50ms, 120ms/10, 180ms> 10 */ + {"2303", 80, 10, 4984, 0x03}, /* 4.00 M */ + {"2305", 48, 8, 14568, 0x05}, /* 5.43 M */ + {"2305-2",96, 8, 14858, 0x05}, /* 11.26 M */ + {"2311", 202, 10, 3717, 0x11}, /* 7.32 M 156k/s 30 ms 145 full */ + {"2314", 203, 20, 7294, 0x14}, /* 29.17 M */ + {"3330", 411, 19, 13165, 0x30}, /* 100.00 M */ {"3330-2",815, 19, 13165, 0x30}, #if 0 {"3340", 349, 12, 8535}, /* 34.94 M */ @@ -222,13 +220,13 @@ disk_type[] = /* Header block */ struct dasd_header { - uint8 devid[8]; /* device header. */ - uint32 heads; /* number of heads per cylinder */ - uint32 tracksize; /* size of track */ - uint8 devtype; /* Hex code of last two digits of device type. */ - uint8 fileseq; /* always 0. */ - uint16 highcyl; /* highest cylinder. */ - uint8 resv[492]; /* pad to 512 byte block */ + uint8 devid[8]; /* device header. */ + uint32 heads; /* number of heads per cylinder */ + uint32 tracksize; /* size of track */ + uint8 devtype; /* Hex code of last two digits of device type. */ + uint8 fileseq; /* always 0. */ + uint16 highcyl; /* highest cylinder. */ + uint8 resv[492]; /* pad to 512 byte block */ }; uint8 dasd_startio(UNIT *uptr, uint16 chan) ; @@ -268,7 +266,8 @@ UNIT dda_unit[] = { {UDATA(&dasd_srv, UNIT_DASD, 0), 0, UNIT_ADDR(0x137)}, /* 7 */ }; -struct dib dda_dib = { 0xF8, NUM_UNITS_MT, NULL, dasd_startcmd, NULL, dda_unit, dasd_ini}; +struct dib dda_dib = { 0xF8, NUM_UNITS_MT, dasd_startio, dasd_startcmd, NULL, + dda_unit, dasd_ini}; DEVICE dda_dev = { "DA", dda_unit, NULL, dasd_mod, @@ -290,7 +289,8 @@ UNIT ddb_unit[] = { {UDATA(&dasd_srv, UNIT_DASD, 0), 0, UNIT_ADDR(0x237)}, /* 7 */ }; -struct dib ddb_dib = { 0xF8, NUM_UNITS_MT, NULL, dasd_startcmd, NULL, ddb_unit, dasd_ini}; +struct dib ddb_dib = { 0xF8, NUM_UNITS_MT, dasd_startio, dasd_startcmd, NULL, + ddb_unit, dasd_ini}; DEVICE ddb_dev = { "DB", ddb_unit, NULL, dasd_mod, @@ -310,7 +310,10 @@ uint8 dasd_startio(UNIT *uptr, uint16 chan) { return SNS_BSY; } uptr->u3 &= ~(DK_INDEX|DK_NOEQ|DK_HIGH|DK_PARAM|DK_MSET); - uptr->u4 &= ~(DK_M_FILEMSK << DK_V_FILEMSK); + if ((uptr->flags & UNIT_ATT) != 0) { + struct dasd_t *data = (struct dasd_t *)(uptr->up7); + data->filemsk = 0; + } sim_debug(DEBUG_CMD, dptr, "start io unit=%d\n", unit); return 0; } @@ -318,6 +321,7 @@ uint8 dasd_startio(UNIT *uptr, uint16 chan) { uint8 dasd_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uint16 addr = GET_UADDR(uptr->u3); DEVICE *dptr = find_dev_from_unit(uptr); + struct dasd_t *data = (struct dasd_t *)(uptr->up7); int unit = (uptr - dptr->units); uint8 ch; @@ -326,6 +330,33 @@ uint8 dasd_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { } sim_debug(DEBUG_CMD, dptr, "CMD unit=%d %02x\n", unit, cmd); + if ((uptr->flags & UNIT_ATT) == 0) { + if (cmd == 0x4) { /* Sense */ + sim_debug(DEBUG_CMD, dptr, "CMD sense\n"); + ch = uptr->u5 & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "sense unit=%d 1 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + ch = (uptr->u5 >> 8) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "sense unit=%d 2 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + ch = 0; + sim_debug(DEBUG_DETAIL, dptr, "sense unit=%d 3 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + ch = unit; + sim_debug(DEBUG_DETAIL, dptr, "sense unit=%d 4 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + ch = 0; + chan_write_byte(addr, &ch) ; + chan_write_byte(addr, &ch) ; + uptr->u5 = 0; + return SNS_CHNEND|SNS_DEVEND; + } + if (cmd == 0x0) + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + + uptr->u5 = 0x48; //SNS_INTVENT|SNS_CMDREJ; + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + } switch (cmd & 0x3) { case 0x3: /* Control */ @@ -333,6 +364,7 @@ uint8 dasd_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { return SNS_CHNEND|SNS_DEVEND; case 0x1: /* Write command */ case 0x2: /* Read command */ + uptr->u3 &= ~(DK_PARAM); uptr->u3 |= cmd; return 0; @@ -358,10 +390,12 @@ t_stat dasd_srv(UNIT * uptr) int cmd = uptr->u3 & 0xff; int type = GET_TYPE(uptr->flags); int state = data->state; + int count = data->count; int trk; int i; int rd = ((cmd & 0x3) == 0x1) | ((cmd & 0x3) == 0x2); uint8 *rec; + uint8 *da; uint8 ch; uint8 buf[8]; @@ -374,20 +408,30 @@ t_stat dasd_srv(UNIT * uptr) uptr->u3 &= ~DK_CYL_DIRTY; } data->ccyl = data->cyl; + sim_debug(DEBUG_DETAIL, dptr, "Load unit=%d cyl=%d\n", unit, data->cyl); data->cpos = sizeof(struct dasd_header) + (data->ccyl * tsize); sim_fseek(uptr->fileref, data->cpos, SEEK_SET); sim_fread(data->cbuf, 1, tsize, uptr->fileref); } +// sim_debug(DEBUG_EXP, dptr, "state unit=%d %02x %d\n", unit, state, data->tpos); - switch(state & 0xF0) { + rec = &data->cbuf[data->rpos + data->tstart]; + da = &data->cbuf[data->tpos + data->tstart]; + if (data->tpos >= data->tsize) { + sim_debug(DEBUG_EXP, dptr, "state end unit=%d\n", unit); + data->state = DK_POS_INDEX; + sim_activate(uptr, 50); + } + switch(state) { case DK_POS_INDEX: /* At Index Mark */ /* Read and multi-track advance to next head */ - if ((cmd & 0x83) == 0x81) { - data->tstart += data->tsize; + if ((cmd & 0x83) == 0x82) { + sim_debug(DEBUG_DETAIL, dptr, "adv head unit=%d %02x %d\n", unit, state, data->tpos); uptr->u4 ++; uptr->u3 &= ~DK_INDEX; } - if (data->tstart > (data->tsize * disk_type[type].heads)) { + if ((uptr->u4 & 0xff) > disk_type[type].heads) { + sim_debug(DEBUG_DETAIL, dptr, "end cyl unit=%d %02x %d\n", unit, state, data->tpos); uptr->u5 |= (SNS_ENDCYL << 8); data->tstart = 0; uptr->u4 &= ~0xff; @@ -395,113 +439,131 @@ t_stat dasd_srv(UNIT * uptr) chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); } /* If INDEX set signal no record if read */ - if (rd && uptr->u3 & DK_INDEX) { - uptr->u5 |= (SNS_NOREC << 8); + if ((cmd & 0x83) == 0x01 && uptr->u3 & DK_INDEX) { + sim_debug(DEBUG_DETAIL, dptr, "index unit=%d %02x %d\n", unit, state, data->tpos); + /* No seeks allowed, error out */ + if ((data->filemsk & DK_MSK_SK) == DK_MSK_SKNONE) + uptr->u5 |= (SNS_WRP << 8); + else + uptr->u5 |= (SNS_NOREC << 8); uptr->u3 &= ~0xff; chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; } uptr->u3 |= DK_INDEX; + data->tstart = data->tsize * (uptr->u4 & 0xff); data->tpos = data->rpos = 0; data->state = DK_POS_HA; data->rec = 0; - sim_activate(uptr, 100); + sim_activate(uptr, 50); break; case DK_POS_HA: /* In home address (c) */ - data->tpos = data->count; - if (data->count == 5) { - data->rpos = 5; + data->tpos++; + if (data->count == 4) { +// sim_debug(DEBUG_DATA, dptr, "HA:unit=%d :", unit); + // for(i = 0; i < 40; i++) + // sim_debug(DEBUG_DATA, dptr, "%d:%02x ", i, rec[i]); + // sim_debug(DEBUG_DATA, dptr, "\n"); + data->tpos = data->rpos = 5; data->state = DK_POS_CNT; - rec = &data->cbuf[data->rpos]; + sim_debug(DEBUG_EXP, dptr, "state HA unit=%d %d %d\n", unit, data->count, data->tpos); + rec = &data->cbuf[data->rpos + data->tstart]; /* Check for end of track */ if ((rec[0] & rec[1] & rec[2] & rec[3]) == 0xff) data->state = DK_POS_END; - sim_activate(uptr, 100); + sim_activate(uptr, 50); } else - sim_activate(uptr, 20); + sim_activate(uptr, 2); break; case DK_POS_CNT: /* In count (c) */ data->tpos++; - if (data->count == 8) { - rec = &data->cbuf[data->rpos]; + if (data->count == 7) { /* Check for end of track */ if ((rec[0] & rec[1] & rec[2] & rec[3]) == 0xff) { state = DK_POS_END; data->state = DK_POS_END; + } else { + data->klen = rec[5]; + data->dlen = (rec[6] << 8) | rec[7]; + data->state = DK_POS_KEY; + if (data->klen == 0) + data->state = DK_POS_DATA; } - data->klen = rec[5]; - data->dlen = (rec[6] << 8) | rec[7]; - data->state = DK_POS_KEY; - if (data->klen == 0) - data->state = DK_POS_DATA; - sim_activate(uptr, 100); + sim_debug(DEBUG_EXP, dptr, "state count unit=%d %d %02x %02x %02x %02x %02x %02x %02x %02x k=%d d=%d %d\n", unit, data->rec, rec[0], rec[1], rec[2], rec[3], + rec[4], rec[5], rec[6], rec[7], data->klen, data->dlen, data->tpos); + sim_activate(uptr, 50); } else { - sim_activate(uptr, 20); + sim_activate(uptr, 2); } break; case DK_POS_KEY: /* In Key area */ - if (data->count == data->klen) { - data->state = DK_POS_DATA; - sim_activate(uptr, 100); - } else { - sim_activate(uptr, 20); data->tpos++; + if (data->count == data->klen) { + sim_debug(DEBUG_EXP, dptr, "state key unit=%d %d %d\n", unit, data->rec, data->count); + data->state = DK_POS_DATA; + data->count = 0; + count = 0; + state = DK_POS_DATA; + sim_activate(uptr, 50); + } else { + sim_activate(uptr, 2); } break; case DK_POS_DATA: /* In Data area */ - if (data->count == data->dlen) { - data->state = DK_POS_AM; - sim_activate(uptr, 100); - } else { data->tpos++; - sim_activate(uptr, 20); + if (data->count == data->dlen) { + sim_debug(DEBUG_EXP, dptr, "state data unit=%d %d %d\n", unit, data->rec, data->count); + data->state = DK_POS_AM; + sim_activate(uptr, 50); + } else { + sim_activate(uptr, 2); } break; case DK_POS_AM: /* Beginning of record */ data->rpos += data->dlen + data->klen + 8; + data->tpos = data->rpos; data->rec++; + sim_debug(DEBUG_EXP, dptr, "state am unit=%d %d %d\n", unit, data->rec, data->count); data->state = DK_POS_CNT; - rec = &data->cbuf[data->rpos]; + data->count = 0; + rec = &data->cbuf[data->rpos + data->tstart]; /* Check for end of track */ if ((rec[0] & rec[1] & rec[2] & rec[3]) == 0xff) data->state = DK_POS_END; - sim_activate(uptr, 100); + sim_activate(uptr, 75); break; case DK_POS_END: /* Past end of data */ - data->tpos++; + data->tpos+=10; data->count = 0; data->klen = 0; data->dlen = 0; - if (data->tpos >= data->tsize) { - data->state = DK_POS_INDEX; - sim_activate(uptr, 100); - } else - sim_activate(uptr, 20); + sim_activate(uptr, 50); break; case DK_POS_SEEK: /* In seek */ /* Compute delay based of difference. */ /* Set next state = index */ i = (uptr->u4 >> 8) - data->cyl; if (i == 0) { + uptr->u3 &= ~DK_INDEX; data->state = DK_POS_INDEX; - set_devattn(addr, SNS_DEVEND); - sim_activate(uptr, 100); + if (cmd != DK_RD_IPL) + set_devattn(addr, SNS_DEVEND); + sim_activate(uptr, 200); } else if (i > 0 ) { - if (i > 10) { - data->cyl += 10; - sim_activate(uptr, 4000); + if (i > 20) { + data->cyl += 20; + sim_activate(uptr, 1000); } else { data->cyl ++; - sim_activate(uptr, 500); + sim_activate(uptr, 200); } } else { - if (i < 10) { - data->cyl -= 10; - sim_activate(uptr, 4000); + if (i < -20) { + data->cyl -= 20; + sim_activate(uptr, 1000); } else { data->cyl --; - sim_activate(uptr, 500); + sim_activate(uptr, 200); } } break; @@ -509,7 +571,6 @@ t_stat dasd_srv(UNIT * uptr) switch (cmd & 0x7f) { case 0: /* No command, stop tape */ - sim_debug(DEBUG_DETAIL, dptr, "Idle unit=%d\n", unit); break; case 0x4: @@ -527,23 +588,18 @@ t_stat dasd_srv(UNIT * uptr) chan_write_byte(addr, &ch) ; ch = 0; chan_write_byte(addr, &ch) ; - uptr->u3 &= ~0xff; + chan_write_byte(addr, &ch) ; + uptr->u3 &= ~(0xff|DK_INDEX); chan_end(addr, SNS_CHNEND|SNS_DEVEND); break; case DK_SEEK: /* Seek */ case DK_SEEKCYL: /* Seek Cylinder */ case DK_SEEKHD: /* Seek Head */ - if ((uptr->u3 & DK_PARAM) != 0) { - uptr->u6 = uptr->u3 & 0xff; - uptr->u3 &= ~(0xff); - chan_end(addr, SNS_DEVEND); - break; - } - /* Check if seek valid */ i = data->filemsk & DK_MSK_SK; if (i == DK_MSK_SKNONE) { /* No seeks allowed, error out */ + sim_debug(DEBUG_DETAIL, dptr, "seek unit=%d not allow\n", unit); uptr->u6 = uptr->u3 & 0xff; uptr->u3 &= ~(0xff); uptr->u5 |= SNS_CMDREJ; @@ -553,6 +609,7 @@ t_stat dasd_srv(UNIT * uptr) if (i != DK_MSK_SKALLSKR) { /* Some restrictions */ if ((cmd == DK_SEEKHD && i != DK_MSK_SKALLHD) || (cmd == DK_SEEK)) { + sim_debug(DEBUG_DETAIL, dptr, "seek unit=%d not allow\n", unit); uptr->u6 = uptr->u3 & 0xff; uptr->u3 &= ~(0xff); uptr->u5 |= SNS_CMDREJ; @@ -571,11 +628,16 @@ t_stat dasd_srv(UNIT * uptr) break; } } + sim_debug(DEBUG_DETAIL, dptr, + "seek unit=%d %02x %02x %02x %02x %02x %02x\n", unit, + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); trk = (buf[2] << 8) | buf[3]; + sim_debug(DEBUG_DETAIL, dptr, "seek unit=%d %d %d\n", + unit, trk, buf[5]); /* Check if seek valid */ - if ((buf[0] | buf[1] | buf[4]) != 0 || trk == 0 || - trk > disk_type[type].cyl || buf[5] > disk_type[type].heads) { + if ((buf[0] | buf[1] | buf[4]) != 0 || trk > disk_type[type].cyl + || buf[5] > disk_type[type].heads) { uptr->u6 = uptr->u3 & 0xff; uptr->u3 &= ~(0xff); uptr->u5 |= SNS_CMDREJ|SNS_SEEKCK; @@ -591,61 +653,69 @@ t_stat dasd_srv(UNIT * uptr) break; } - chan_end(addr, SNS_CHNEND); - uptr->u3 |= DK_PARAM; data->tstart = buf[5] * data->tsize; /* Point to start of record */ uptr->u4 = (trk << 8) | buf[5]; + uptr->u6 = uptr->u3 & 0xff; + uptr->u3 &= ~(0xff); /* Check if on correct cylinder */ if (trk != data->cyl) { /* Do seek */ data->state = DK_POS_SEEK; + chan_end(addr, SNS_CHNEND); + } else { + chan_end(addr, SNS_DEVEND|SNS_CHNEND); } return SCPE_OK; case DK_RESTORE: /* Restore */ - if ((uptr->u3 & DK_PARAM) != 0) { - uptr->u6 = uptr->u3 & 0xff; - uptr->u3 &= ~(0xff); - chan_end(addr, SNS_DEVEND); - break; - } + + sim_debug(DEBUG_DETAIL, dptr, "restore unit=%d\n", unit); if ((data->filemsk & DK_MSK_SK) != DK_MSK_SKALLSKR) { uptr->u5 |= SNS_CMDREJ; uptr->u6 = 0; uptr->u3 &= ~(0xff|DK_PARAM); chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); } - uptr->u3 |= DK_PARAM; uptr->u4 = 0; data->tstart = 0; - chan_end(addr, SNS_CHNEND); - if (data->cyl != 0) { - /* Do a seek */ + uptr->u6 = uptr->u3 & 0xff; + uptr->u3 &= ~(0xff); + /* Check if on correct cylinder */ + if (trk != data->cyl) { + /* Do seek */ data->state = DK_POS_SEEK; + chan_end(addr, SNS_CHNEND); + } else { + chan_end(addr, SNS_DEVEND|SNS_CHNEND); } return SCPE_OK; case DK_SETMSK: /* Set file mask */ /* If mask already set, error */ + sim_debug(DEBUG_DETAIL, dptr, "setmsk unit=%d\n", unit); uptr->u6 = uptr->u3 & 0xff; uptr->u3 &= ~(0xff|DK_PARAM); if (uptr->u3 & DK_MSET) { + sim_debug(DEBUG_DETAIL, dptr, "setmsk dup\n"); uptr->u6 = 0; uptr->u5 |= SNS_CMDREJ | (SNS_INVSEQ << 8); chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); } /* Grab mask */ if (chan_read_byte(addr, &ch)) { + sim_debug(DEBUG_DETAIL, dptr, "setmsk rdr\n"); uptr->u6 = 0; uptr->u5 |= SNS_CMDREJ; chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); } /* Save */ if ((ch & ~(DK_MSK_SK|DK_MSK_WRT)) != 0) { + sim_debug(DEBUG_DETAIL, dptr, "setmsk inv\n"); uptr->u6 = 0; uptr->u5 |= SNS_CMDREJ; chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); } + sim_debug(DEBUG_DETAIL, dptr, "setmsk unit=%d %x\n", unit, ch); data->filemsk = ch; uptr->u3 |= DK_MSET; chan_end(addr, SNS_CHNEND|SNS_DEVEND); @@ -654,21 +724,23 @@ t_stat dasd_srv(UNIT * uptr) case DK_SPACE: /* Space record */ break; case DK_SRCH_HAEQ: /* Search HA equal */ - if (state == DK_POS_INDEX) { + if (state == DK_POS_HA && count == 0) { + sim_debug(DEBUG_DETAIL, dptr, "search HA unit=%d %x %d %x\n", unit, state, count, uptr->u4); uptr->u3 &= ~DK_SRCOK; uptr->u3 |= DK_PARAM; break; } - if (uptr->u3 & DK_PARAM && state == DK_POS_HA) { - uptr->u3 &= ~DK_INDEX; + if (uptr->u3 & DK_PARAM) { if (chan_read_byte(addr, &ch)) { - if (data->count != 0x5) + if (count < 4) uptr->u3 |= DK_SHORTSRC; - } else if (ch != data->cbuf[data->tpos]) { + } else if (ch != *da) { uptr->u3 |= DK_NOEQ; } - if (data->count == 5 || uptr->u3 & DK_SHORTSRC) { + sim_debug(DEBUG_DETAIL, dptr, "search HA unit=%d %d %x %02x=%02x %d\n", unit, + count, state, ch, *da, data->tpos); + if (count == 4 || uptr->u3 & DK_SHORTSRC) { uptr->u6 = uptr->u3 & 0xff; uptr->u3 &= ~(0xff|DK_PARAM); if (uptr->u3 & DK_NOEQ) @@ -682,14 +754,19 @@ t_stat dasd_srv(UNIT * uptr) break; case DK_RD_CNT: /* Read count */ - if (state == DK_POS_AM) { + if (state == DK_POS_AM) uptr->u3 |= DK_PARAM; - } + if (state == DK_POS_END || state == DK_POS_INDEX || state == DK_POS_HA) + uptr->u3 &= ~DK_PARAM; + + if (uptr->u3 & DK_PARAM && state == DK_POS_CNT) { - uptr->u3 &= ~DK_INDEX; - ch = data->cbuf[data->tpos]; - if (chan_write_byte(addr, &ch) || data->count == 8) { +// uptr->u3 &= ~DK_INDEX; + ch = *da; + sim_debug(DEBUG_DETAIL, dptr, "readcnt ID unit=%d %d %x %02x %x %d %x\n", unit, + count, state, ch, uptr->u4, data->tpos, uptr->u4); + if (chan_write_byte(addr, &ch) || count == 7) { uptr->u6 = uptr->u3 & 0xff; uptr->u3 &= ~(0xff); chan_end(addr, SNS_CHNEND|SNS_DEVEND); @@ -700,33 +777,40 @@ t_stat dasd_srv(UNIT * uptr) case DK_SRCH_IDEQ: /* Search ID equal */ case DK_SRCH_IDGT: /* Search ID greater */ case DK_SRCH_IDGE: /* Search ID greater or equal */ - if (state == DK_POS_CNT) { - uptr->u3 &= ~(DK_SRCOK|DK_SHORTSRC); + if (state == DK_POS_CNT && count == 0) { + sim_debug(DEBUG_DETAIL, dptr, "search ID unit=%d %x %d %x %d\n", + unit, state, count, uptr->u4, data->rec); + uptr->u3 &= ~(DK_SRCOK|DK_SHORTSRC|DK_NOEQ|DK_HIGH); uptr->u3 |= DK_PARAM; } if (uptr->u3 & DK_PARAM) { - uptr->u3 &= ~DK_INDEX; - /* Wait for start of record */ + /* Wait for start of record */ if (chan_read_byte(addr, &ch)) { uptr->u3 |= DK_SHORTSRC; - } else if (ch != data->cbuf[data->tpos]) { + } else if (ch != *da) { if ((uptr->u3 & DK_NOEQ) == 0) { uptr->u3 |= DK_NOEQ; - if (ch > *rec) + if (ch < *da) uptr->u3 |= DK_HIGH; } } - if (data->count == 5 || uptr->u3 & DK_SHORTSRC) { + sim_debug(DEBUG_DETAIL, dptr, + "search ID unit=%d %d %x %02x=%02x %d %c %c\n", unit, count, + state, ch, *da, data->tpos, + ((uptr->u3 & DK_NOEQ) ? '!' : '='), + ((uptr->u3 & DK_HIGH) ? 'h' : 'l')); + if (count == 4 || uptr->u3 & DK_SHORTSRC) { uptr->u6 = uptr->u3 & 0xff; uptr->u3 &= ~(0xff); i = 0; - if ((cmd & 0x2) && (uptr->u3 & DK_NOEQ) == 0) + if ((cmd & 0x20) && (uptr->u3 & DK_NOEQ) == 0) i = SNS_SMS; - if ((cmd & 0x4) && (uptr->u3 & DK_HIGH)) + if ((cmd & 0x40) && (uptr->u3 & DK_HIGH)) i = SNS_SMS; - if (i) + if (i) { uptr->u3 |= DK_SRCOK; + } chan_end(addr, SNS_CHNEND|SNS_DEVEND|i); } } @@ -735,35 +819,71 @@ t_stat dasd_srv(UNIT * uptr) case DK_SRCH_KYEQ: /* Search Key equal */ case DK_SRCH_KYGT: /* Search Key greater */ case DK_SRCH_KYGE: /* Search Key greater or equal */ - if (state == DK_POS_AM) - uptr->u3 &= ~DK_SRCOK; - if (state == DK_POS_KEY && data->count == 0) { - if (data->rec == 0 && (uptr->u3 & DK_SRCOK) == 0) + /* Check if at beginning of key */ + if (state == DK_POS_KEY && count == 0) { + /* Check proper sequence */ + if (uptr->u6 == DK_RD_CNT || uptr->u6 == 0x100 + || ((uptr->u6 & 0x1F) == 0x11 && /* Search ID */ + (uptr->u3 & (DK_SRCOK|DK_SHORTSRC)) == DK_SRCOK )) { + uptr->u3 &= ~(DK_SRCOK|DK_SHORTSRC|DK_NOEQ|DK_HIGH); + uptr->u3 |= DK_PARAM; + sim_debug(DEBUG_DETAIL, dptr, "search Key cn unit=%d %x %d %x %d\n", + unit, state, count, uptr->u4, data->rec); + } + } + /* Check if previous record had zero length key */ + if (state == DK_POS_DATA && count == 0 && data->klen == 0) { + if (uptr->u6 == DK_RD_CNT || ((uptr->u6 & 0x1F) == 0x11 && + (uptr->u3 & (DK_SRCOK|DK_SHORTSRC)) == DK_SRCOK )) { + sim_debug(DEBUG_DETAIL, dptr, "search Key da unit=%d %x %d %x %d\n", + unit, state, count, uptr->u4, data->rec); + uptr->u6 = uptr->u3 & 0xff; + uptr->u3 &= ~(0xff); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); break; - uptr->u3 &= ~(DK_SRCOK|DK_SHORTSRC); - uptr->u3 |= DK_PARAM; + } + } + /* If we hit address mark, see if over */ + if (state == DK_POS_AM) { + if (uptr->u6 == DK_RD_CNT || ((uptr->u6 & 0x1F) == 0x11 && + (uptr->u3 & (DK_SRCOK|DK_SHORTSRC)) == DK_SRCOK )) { + sim_debug(DEBUG_DETAIL, dptr, "search Key am unit=%d %x %d %x %d\n", + unit, state, count, uptr->u4, data->rec); + uptr->u6 = uptr->u3 & 0xff; + uptr->u3 &= ~(0xff); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); + break; + } else { + uptr->u6 = 0x100; + } } if (uptr->u3 & DK_PARAM) { /* Wait for key */ if (chan_read_byte(addr, &ch)) { uptr->u3 |= DK_SHORTSRC; - } else if (ch != data->cbuf[data->tpos]) { + } else if (ch != *da) { if ((uptr->u3 & DK_NOEQ) == 0) { uptr->u3 |= DK_NOEQ; - if (ch > *rec) + if (ch < *da) uptr->u3 |= DK_HIGH; } } - if (data->count == data->klen || uptr->u3 & DK_SHORTSRC) { + sim_debug(DEBUG_DETAIL, dptr, + "search Key unit=%d %d %x %02x=%02x %d %c %c\n", unit, count, + state, ch, *da, data->tpos, + ((uptr->u3 & DK_NOEQ) ? '!' : '='), + ((uptr->u3 & DK_HIGH) ? 'h' : 'l')); + if (count == data->klen-1 || uptr->u3 & DK_SHORTSRC) { uptr->u6 = uptr->u3 & 0xff; uptr->u3 &= ~(0xff); i = 0; - if ((cmd & 0x2) && (uptr->u3 & DK_NOEQ) == 0) + if ((cmd & 0x20) && (uptr->u3 & DK_NOEQ) == 0) i = SNS_SMS; - if ((cmd & 0x4) && (uptr->u3 & DK_HIGH)) + if ((cmd & 0x40) && (uptr->u3 & DK_HIGH)) i = SNS_SMS; - if (i) + if (i) { uptr->u3 |= DK_SRCOK; + } chan_end(addr, SNS_CHNEND|SNS_DEVEND|i); } } @@ -774,10 +894,10 @@ t_stat dasd_srv(UNIT * uptr) uptr->u3 |= DK_PARAM; } - if (uptr->u3 & DK_PARAM && (state & 0xF0) == DK_POS_HA) { - uptr->u3 &= ~DK_INDEX; - ch = data->cbuf[data->tpos]; - if (chan_write_byte(addr, &ch) || (state & 0xF) == 5) { + if (uptr->u3 & DK_PARAM && state == DK_POS_HA) { +// uptr->u3 &= ~DK_INDEX; + ch = *da; + if (chan_write_byte(addr, &ch) || count == 4) { uptr->u6 = uptr->u3 & 0xff; uptr->u3 &= ~(0xff); chan_end(addr, SNS_CHNEND|SNS_DEVEND); @@ -786,55 +906,82 @@ t_stat dasd_srv(UNIT * uptr) break; case DK_RD_IPL: /* Read IPL record */ - if (data->count == 0 && state == DK_POS_CNT && data->rec == 1) { - uptr->u3 &= ~DK_INDEX; - uptr->u3 |= DK_PARAM; + if (uptr->u4 != 0) { + /* Do a seek */ + uptr->u4 = 0; + data->tstart = 0; + data->state = DK_POS_SEEK; + sim_debug(DEBUG_DETAIL, dptr, "RD IPL unit=%d seek\n", unit); + break; } + if (count == 0 && state == DK_POS_DATA && data->rec == 1) { + uptr->u3 |= DK_PARAM; + uptr->u3 &= ~DK_INDEX; + sim_debug(DEBUG_DETAIL, dptr, "RD IPL unit=%d %d k=%d d=%d %02x %04x\n", unit, data->rec, data->klen, data->dlen, data->state, 8 + data->klen + data->dlen); + } + goto rd; case DK_RD_R0: /* Read R0 */ - if (data->count == 0 && state == DK_POS_CNT && data->rec == 0) { + if (count == 0 && state == DK_POS_CNT && data->rec == 0) { uptr->u3 |= DK_PARAM; uptr->u3 &= ~DK_INDEX; + sim_debug(DEBUG_DETAIL, dptr, "RD R0 unit=%d %d k=%d d=%d %02x %04x\n", unit, data->rec, data->klen, data->dlen, data->state, 8 + data->klen + data->dlen); } goto rd; case DK_RD_CKD: /* Read count, key and data */ - if (data->count == 0 && state == DK_POS_CNT) { + if (count == 0 && state == DK_POS_CNT) { uptr->u3 |= DK_PARAM; uptr->u3 &= ~DK_INDEX; + sim_debug(DEBUG_DETAIL, dptr, "RD CKD unit=%d %d k=%d d=%d %02x %04x\n", unit, data->rec, data->klen, data->dlen, data->state, 8 + data->klen + data->dlen); } + goto rd; case DK_RD_KD: /* Read key and data */ - if (data->count == 0 && state == DK_POS_KEY) { + if (count == 0 && state == DK_POS_KEY) { uptr->u3 |= DK_PARAM; uptr->u3 &= ~DK_INDEX; + sim_debug(DEBUG_DETAIL, dptr, "RD KD unit=%d %d k=%d d=%d %02x %04x\n", unit, data->rec, data->klen, data->dlen, data->state, 8 + data->klen + data->dlen); } + goto rd; case DK_RD_D: /* Read Data */ - if (data->count == 0 && state == DK_POS_DATA) { + if (count == 0 && state == DK_POS_DATA) { uptr->u3 |= DK_PARAM; uptr->u3 &= ~DK_INDEX; + sim_debug(DEBUG_DETAIL, dptr, "RD D unit=%d %d k=%d d=%d %02x %04x %d\n", unit, data->rec, data->klen, data->dlen, data->state, 8 + data->klen + data->dlen, count); } rd: if (uptr->u3 & DK_PARAM) { +extern uint16 ccw_count[]; /* Check for end of file */ - if (state == DK_POS_DATA && data->count == 0 && data->dlen == 0) { - uptr->u6 = uptr->u3 & 0xff; + if (state == DK_POS_DATA && count == 0 && data->dlen == 0) { + sim_debug(DEBUG_DETAIL, dptr, "RD EOF unit=%d %x %d %d\n", unit, state, count, data->rec); +// uptr->u6 = uptr->u3 & 0xff; uptr->u3 &= ~(0xff|DK_PARAM); chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); break; } - ch = data->cbuf[data->tpos]; - if (chan_write_byte(addr, &ch)) { - uptr->u6 = uptr->u3 & 0xff; - uptr->u3 &= ~(0xff|DK_PARAM); - chan_end(addr, SNS_CHNEND|SNS_DEVEND); + if (state == DK_POS_DATA && count == data->dlen) { + // uptr->u6 = uptr->u3 & 0xff; + uptr->u3 &= ~(0xff|DK_PARAM); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); + break; } - if (state == DK_POS_DATA && data->count == data->dlen) { - uptr->u6 = uptr->u3 & 0xff; - uptr->u3 &= ~(0xff|DK_PARAM); - chan_end(addr, SNS_CHNEND|SNS_DEVEND); + if (state == DK_POS_INDEX) { + uptr->u5 = SNS_TRKOVR << 8; + uptr->u3 &= ~(0xff|DK_PARAM); + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + ch = *da; +sim_debug(DEBUG_DATA, dptr, "RD Char %02x, %04x %02x %d %d\n", ch, ccw_count[0x81], state, count, data->tpos); + if (chan_write_byte(addr, &ch)) { +// uptr->u6 = uptr->u3 & 0xff; + uptr->u3 &= ~(0xff|DK_PARAM); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); + break; } } break; @@ -856,25 +1003,26 @@ rd: if (uptr->u3 & DK_PARAM) { uptr->u3 &= ~DK_INDEX; + sim_debug(DEBUG_DETAIL, dptr, "Wr HA unit=%d %x %d %d\n", unit, state, count, data->rec); if (chan_read_byte(addr, &ch)) { ch = 0; } - data->cbuf[data->tpos] = ch; - if (data->count == 5) { + *da = ch; + uptr->u3 |= DK_CYL_DIRTY; + if (count == 4) { uptr->u6 = uptr->u3 & 0xff; uptr->u3 &= ~(0xff|DK_PARAM); chan_end(addr, SNS_CHNEND|SNS_DEVEND); - for(i = 0; i < 4; i++) - data->cbuf[data->tpos+i] = 0xff; - for(; i < 8; i++) - data->cbuf[data->tpos+i] = 0; + for(i = 0; i < 8; i++) + da[i] = 0xff; } } break; case DK_WR_R0: /* Write R0 */ if ((state == DK_POS_CNT || state == DK_POS_END) - && data->rec == 0 && data->count == 0) { + && data->rec == 0 && count == 0) { + sim_debug(DEBUG_DETAIL, dptr, "Wr R0 unit=%d %x %d\n", unit, state, count); /* Check if command ok based on mask */ if ((data->filemsk & DK_MSK_WRT) != DK_MSK_ALLWRT) { uptr->u5 |= SNS_CMDREJ; @@ -886,6 +1034,11 @@ rd: if (uptr->u6 == DK_WR_HA || (uptr->u6 == DK_SRCH_HAEQ && (uptr->u3 & (DK_SHORTSRC|DK_SRCOK)) == DK_SRCOK)) { +// if (state == DK_POS_END) { + data->tpos = data->rpos; + da = &data->cbuf[data->tpos + data->tstart]; + data->tpos++; + // } state = data->state = DK_POS_CNT; uptr->u3 |= DK_PARAM; } else { @@ -897,13 +1050,18 @@ rd: } goto wrckd; - case DK_WR_SCKD: /* Write special count, key and data */ case DK_WR_CKD: /* Write count, key and data */ if ((state == DK_POS_CNT || state == DK_POS_END) - && data->rec != 0 && data->count == 0) { + && data->rec != 0 && count == 0) { + sim_debug(DEBUG_DETAIL, dptr, "Wr CKD unit=%d %x %d\n", unit, state, count); +// sim_debug(DEBUG_DATA, dptr, "WCKD:unit=%d :", unit); + // for(i = 0; i < (16+data->klen+data->dlen); i++) + // sim_debug(DEBUG_DATA, dptr, "%02x ", rec[i]); + // sim_debug(DEBUG_DATA, dptr, "\n"); /* Check if command ok based on mask */ i = data->filemsk & DK_MSK_WRT; - if (i != DK_MSK_ALLWRT || i != DK_MSK_INHWR0) { + if (i == DK_MSK_INHWRT || i == DK_MSK_ALLWRU) { + sim_debug(DEBUG_DETAIL, dptr, "Wr CKD unit=%d mask\n", unit); uptr->u5 |= SNS_CMDREJ; uptr->u6 = 0; uptr->u3 &= ~(0xff); @@ -911,46 +1069,28 @@ rd: break; } if (uptr->u6 == DK_WR_R0 || uptr->u6 == DK_WR_CKD || - ((uptr->u6 & 0x3) == 1 && (uptr->u6 & 0xE0) != 0 && + ((uptr->u6 & 0x7) == 1 && (uptr->u6 & 0x60) != 0 && (uptr->u3 & (DK_SHORTSRC|DK_SRCOK)) == DK_SRCOK)) { + sim_debug(DEBUG_DETAIL, dptr, "Wr CKD unit=%d ok\n", unit); + // if (state == DK_POS_END) { + data->tpos = data->rpos; + da = &data->cbuf[data->tpos + data->tstart]; + data->tpos++; + // } state = data->state = DK_POS_CNT; uptr->u3 |= DK_PARAM; } else { + sim_debug(DEBUG_DETAIL, dptr, "Wr CKD unit=%d seq\n", unit); uptr->u5 |= SNS_CMDREJ | (SNS_INVSEQ << 8); uptr->u6 = 0; uptr->u3 &= ~(0xff); chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); } } - -wrckd: - if (uptr->u3 & DK_PARAM) { - uptr->u3 &= ~DK_INDEX; - if (chan_read_byte(addr, &ch)) { - ch = 0; - } - data->cbuf[data->tpos] = ch; - if (state == DK_POS_CNT && data->count == 8) { - rec = &data->cbuf[data->rpos]; - data->klen = rec[5]; - data->dlen = (rec[6] << 8) | rec[7]; - data->state = DK_POS_KEY; - if (data->klen == 0) - data->state = DK_POS_DATA; - } else if (state == DK_POS_DATA && data->count == data->dlen) { - uptr->u6 = uptr->u3 & 0xff; - uptr->u3 &= ~(0xff|DK_PARAM); - chan_end(addr, SNS_CHNEND|SNS_DEVEND); - for(i = 0; i < 4; i++) - data->cbuf[data->tpos+i] = 0xff; - for(; i < 8; i++) - data->cbuf[data->tpos+i] = 0; - } - } - break; + goto wrckd; case DK_WR_KD: /* Write key and data */ - if ((state == DK_POS_KEY) && data->rec != 0 && data->count == 0) { + if ((state == DK_POS_KEY) && count == 0) { /* Check if command ok based on mask */ if ((data->filemsk & DK_MSK_WRT) == DK_MSK_INHWRT) { uptr->u5 |= SNS_CMDREJ; @@ -969,10 +1109,10 @@ wrckd: chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); } } - goto wr; + goto wrckd; case DK_WR_D: /* Write Data */ - if ((state == DK_POS_DATA) && data->rec != 0 && data->count == 0) { + if ((state == DK_POS_DATA) && count == 0) { /* Check if command ok based on mask */ if ((data->filemsk & DK_MSK_WRT) == DK_MSK_INHWRT) { uptr->u5 |= SNS_CMDREJ; @@ -992,25 +1132,46 @@ wrckd: } } -wr: +wrckd: if (uptr->u3 & DK_PARAM) { +extern uint16 ccw_count[]; uptr->u3 &= ~DK_INDEX; - /* Check for end of file */ - if (state == DK_POS_DATA && data->count == 0 && data->dlen == 0) { - uptr->u6 = uptr->u3 & 0xff; - uptr->u3 &= ~(0xff|DK_PARAM); - chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); - break; + if (state == DK_INDEX) { + uptr->u5 = SNS_TRKOVR << 8; + uptr->u3 &= ~(0xff|DK_PARAM); + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } else if (state == DK_POS_DATA && count == data->dlen) { + // data->state = DK_POS_AM; + uptr->u6 = uptr->u3 & 0xff; + uptr->u3 &= ~(0xff|DK_PARAM); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); + if ((cmd & 0x10) != 0) { + for(i = 0; i < 8; i++) + da[i] = 0xff; + } + sim_debug(DEBUG_DETAIL, dptr, "WCKD end unit=%d %d %d %04x\n", unit, data->tpos+8, count, data->tpos - data->rpos); +// sim_debug(DEBUG_DATA, dptr, "WCKD:unit=%d :", unit); + // for(i = 0; i < (16+data->klen+data->dlen); i++) + // sim_debug(DEBUG_DATA, dptr, "%02x ", rec[i]); + // sim_debug(DEBUG_DATA, dptr, "\n"); + + break; } if (chan_read_byte(addr, &ch)) { ch = 0; } - data->cbuf[data->tpos] = ch; - if (state == DK_POS_DATA && data->count == data->dlen) { - uptr->u6 = uptr->u3 & 0xff; - uptr->u3 &= ~(0xff|DK_PARAM); - chan_end(addr, SNS_CHNEND|SNS_DEVEND); - } +sim_debug(DEBUG_DATA, dptr, "Char %02x, %04x %02x %d %d\n", ch, ccw_count[0x81], state, count, data->tpos); + *da = ch; + uptr->u3 |= DK_CYL_DIRTY; + if (state == DK_POS_CNT && count == 7) { + data->klen = rec[5]; + data->dlen = (rec[6] << 8) | rec[7]; + sim_debug(DEBUG_DETAIL, dptr, "WCKD count unit=%d %d k=%d d=%d %02x %04x\n", unit, data->rec, data->klen, data->dlen, data->state, 8 + data->klen + data->dlen); + data->state = DK_POS_KEY; + if (data->klen == 0) + data->state = DK_POS_DATA; + } } break; @@ -1018,7 +1179,7 @@ wr: if (state == DK_POS_AM || state == DK_POS_END) { /* Check if command ok based on mask */ i = data->filemsk & DK_MSK_WRT; - if (i != DK_MSK_ALLWRT || i != DK_MSK_INHWR0) { + if (i == DK_MSK_INHWRT || i == DK_MSK_ALLWRU) { uptr->u5 |= SNS_CMDREJ; uptr->u6 = 0; uptr->u3 &= ~(0xff); @@ -1039,17 +1200,23 @@ wr: } if (uptr->u3 & DK_PARAM) { - uptr->u3 &= ~DK_INDEX; uptr->u6 = uptr->u3 & 0xff; - uptr->u3 &= ~(0xff|DK_PARAM); + uptr->u3 &= ~(0xff|DK_PARAM|DK_INDEX); + uptr->u3 |= DK_CYL_DIRTY; chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* Write end mark */ - for(i = 0; i < 4; i++) - data->cbuf[data->rpos+i] = 0xff; - for(; i < 8; i++) - data->cbuf[data->rpos+i] = 0; + for(i = 0; i < 8; i++) + rec[i] = 0xff; } break; + case DK_WR_SCKD: /* Write special count, key and data */ + default: + sim_debug(DEBUG_DETAIL, dptr, "invalid command=%d %x\n", unit, cmd); + uptr->u5 |= SNS_CMDREJ; + uptr->u6 = 0; + uptr->u3 &= ~(0xff); + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; } if (state == data->state) data->count++; @@ -1064,6 +1231,8 @@ dasd_ini(UNIT * uptr, t_bool f) DEVICE *dptr = find_dev_from_unit(uptr); int i = GET_TYPE(uptr->flags); uptr->capac = disk_type[i].bpt * disk_type[i].heads * disk_type[i].cyl; + if ((uptr->flags & UNIT_ATT) != 0) + sim_activate(uptr, 100); } t_stat @@ -1076,13 +1245,14 @@ int dasd_format(UNIT * uptr) { struct dasd_header hdr; struct dasd_t *data; + uint16 addr = GET_UADDR(uptr->u3); int type = GET_TYPE(uptr->flags); int tsize; int cyl; int hd; int pos; - if (!get_yn("Initialize dasd? [Y]", TRUE)) { + if (!get_yn("Initialize dasd? [Y] ", TRUE)) { return 1; } memset(&hdr, 0, sizeof(struct dasd_header)); @@ -1099,19 +1269,29 @@ dasd_format(UNIT * uptr) { data->tsize = hdr.tracksize; if ((data->cbuf = (uint8 *)calloc(tsize, sizeof(uint8))) == 0) return 1; - for (cyl = 0; cyl < disk_type[type].cyl; cyl++) { + for (cyl = 0; cyl <= disk_type[type].cyl; cyl++) { pos = 0; for (hd = 0; hd < disk_type[type].heads; hd++) { - data->cbuf[pos++] = 0; + int cpos = pos; + data->cbuf[pos++] = 0; /* HA */ data->cbuf[pos++] = (cyl >> 8); data->cbuf[pos++] = (cyl & 0xff); data->cbuf[pos++] = (hd >> 8); data->cbuf[pos++] = (hd & 0xff); + data->cbuf[pos++] = (cyl >> 8); /* R0 */ + data->cbuf[pos++] = (cyl & 0xff); + data->cbuf[pos++] = (hd >> 8); + data->cbuf[pos++] = (hd & 0xff); + data->cbuf[pos++] = 0; /* Rec */ + data->cbuf[pos++] = 0; /* keylen */ + data->cbuf[pos++] = 0; /* dlen */ + data->cbuf[pos++] = 8; /* */ + pos += 8; + data->cbuf[pos++] = 0xff; /* End record */ data->cbuf[pos++] = 0xff; data->cbuf[pos++] = 0xff; data->cbuf[pos++] = 0xff; - data->cbuf[pos++] = 0xff; - pos += data->tsize - 9; + pos = cpos + data->tsize; } sim_fwrite(data->cbuf, 1, tsize, uptr->fileref); if ((cyl % 10) == 0) @@ -1122,8 +1302,9 @@ dasd_format(UNIT * uptr) { data->cpos = sizeof(struct dasd_header); data->ccyl = 0; data->ccyl = 0; - data->cyl = 2000; - data->state = DK_POS_SEEK; +// data->cyl = 2000; +// data->state = DK_POS_SEEK; + set_devattn(addr, SNS_DEVEND); sim_activate(uptr, 100); fputc('\n', stderr); fputc('\r', stderr); @@ -1161,7 +1342,7 @@ dasd_attach(UNIT * uptr, CONST char *file) if (GET_TYPE(uptr->flags) != i) { /* Ask if we should change */ fprintf(stderr, "Wrong type %s\n\r", disk_type[i].name); - if (!get_yn("Update dasd type? [N]", FALSE)) { + if (!get_yn("Update dasd type? [N] ", FALSE)) { detach_unit(uptr); return SCPE_FMT; } @@ -1189,8 +1370,9 @@ dasd_attach(UNIT * uptr, CONST char *file) sim_fread(data->cbuf, 1, tsize, uptr->fileref); data->cpos = sizeof(struct dasd_header); data->ccyl = 0; - data->cyl = 2000; - data->state = DK_POS_SEEK; +// data->cyl = 2000; +// data->state = DK_POS_SEEK; + set_devattn(addr, SNS_DEVEND); sim_activate(uptr, 100); return SCPE_OK; } @@ -1211,7 +1393,7 @@ dasd_detach(UNIT * uptr) free(data); } uptr->up7 = 0; - uptr->u3 = 0; + uptr->u3 &= ~0xffff; return detach_unit(uptr); } diff --git a/IBM360/ibm360_defs.h b/IBM360/ibm360_defs.h index 1a4f8b0..060e81a 100644 --- a/IBM360/ibm360_defs.h +++ b/IBM360/ibm360_defs.h @@ -347,6 +347,7 @@ const char ebcdic_to_ascii[256]; extern DEBTAB dev_debug[]; extern DEBTAB crd_debug[]; +extern DEVICE cpu_dev; extern DEVICE cdp_dev; extern DEVICE cdr_dev; extern DEVICE lpr_dev; @@ -356,6 +357,7 @@ extern DEVICE mtb_dev; extern DEVICE dda_dev; extern DEVICE ddb_dev; extern DEVICE com_dev; +extern UNIT cpu_unit; #define NUM_DEVS_CDP 1 #define NUM_DEVS_CDR 1 @@ -368,5 +370,4 @@ extern DEVICE com_dev; #define NUM_DEVS_COM 1 #define NUM_UNITS_COM 16 -extern DEVICE cpu_dev; extern void fprint_inst(FILE *, uint16 *); diff --git a/IBM360/ibm360_lpr.c b/IBM360/ibm360_lpr.c index 56205ac..04a23f8 100644 --- a/IBM360/ibm360_lpr.c +++ b/IBM360/ibm360_lpr.c @@ -175,7 +175,7 @@ print_line(UNIT * uptr) /* Print out buffer */ sim_fwrite(&out, 1, i, uptr->fileref); -fprintf(stderr, "%s", out); + sim_debug(DEBUG_DETAIL, &lpr_dev, "%s", out); uptr->u4++; if (uptr->u4 > uptr->capac) { uptr->u4 = 1; @@ -190,14 +190,15 @@ uint8 lpr_startcmd(UNIT * uptr, uint16 chan, uint8 cmd) uint8 ch; if ((uptr->u3 & LPR_CMDMSK) != 0) { - if ((uptr->flags & UNIT_ATT) != 0) + if ((uptr->flags & UNIT_ATT) != 0) return SNS_BSY; return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; } + sim_debug(DEBUG_CMD, &lpr_dev, "Cmd %02x\n", cmd); + switch (cmd & 0x7) { case 1: /* Write command */ - case 3: uptr->u3 &= ~(LPR_CMDMSK); uptr->u3 |= (cmd & LPR_CMDMSK); sim_activate(uptr, 10); /* Start unit off */ @@ -205,6 +206,14 @@ uint8 lpr_startcmd(UNIT * uptr, uint16 chan, uint8 cmd) uptr->u6 = 0; return 0; + case 3: /* Carrage control */ + uptr->u3 &= ~(LPR_CMDMSK); + uptr->u3 |= (cmd & LPR_CMDMSK); + sim_activate(uptr, 10); /* Start unit off */ + uptr->u5 = 0; + uptr->u6 = 0; + return SNS_CHNEND; + case 0: /* Status */ break; @@ -228,33 +237,37 @@ t_stat lpr_srv(UNIT *uptr) { int addr = GET_UADDR(uptr->u3); int u = (uptr - lpr_unit); + int cmd = (uptr->u3 & 0x7); - if ((uptr->u3 & 0xFF) == 4) { + if (cmd == 4) { uint8 ch = uptr->u5; + uptr->u3 &= ~(LPR_CMDMSK); chan_write_byte(GET_UADDR(uptr->u3), &ch); chan_end(addr, SNS_DEVEND|SNS_CHNEND); return SCPE_OK; } - if ((uptr->u3 & LPR_FULL) || (uptr->u3 & 0x7) == 0x3) { + if ((uptr->u3 & LPR_FULL) || cmd == 0x3) { print_line(uptr); uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK); uptr->u6 = 0; - chan_end(addr, SNS_CHNEND|SNS_DEVEND); -// set_devattn(addr, SNS_DEVEND); +// chan_end(addr, SNS_CHNEND|SNS_DEVEND); + set_devattn(addr, SNS_DEVEND); + return SCPE_OK; } /* Copy next column over */ - if ((uptr->u3 & 0x7) == 1 && uptr->u6 < 144) { - if(chan_read_byte(addr, &lpr_data[u].lbuff[uptr->u6++])) { + if (cmd == 1 && (uptr->u3 & LPR_FULL) == 0) { + if(chan_read_byte(addr, &lpr_data[u].lbuff[uptr->u6])) { uptr->u3 |= LPR_FULL; } else { - sim_activate(uptr, 10); + sim_activate(uptr, 20); + uptr->u6++; } - if (uptr->u3 & LPR_FULL || uptr->u6 >= 144) { + if (uptr->u3 & LPR_FULL || uptr->u6 >= 132) { uptr->u3 |= LPR_FULL; -// chan_end(addr, SNS_CHNEND); - sim_activate(uptr, 1000); + chan_end(addr, SNS_CHNEND); + sim_activate(uptr, 3000); } } return SCPE_OK; diff --git a/IBM360/ibm360_mt.c b/IBM360/ibm360_mt.c index b95dae9..0e328a2 100644 --- a/IBM360/ibm360_mt.c +++ b/IBM360/ibm360_mt.c @@ -85,8 +85,6 @@ #define MT_TRANS 0x2000 /* Translation turned on ignored 9 track */ #define MT_CONV 0x4000 /* Data converter on ignored 9 track */ #define MT_BUSY 0x8000 /* Flag to send a CUE */ -#define MT_CHAN_MSK 0xff0000 /* Channel mask */ -#define MT_CHAN_V 16 /* Channel shift */ /* in u4 is current buffer position */ @@ -171,7 +169,7 @@ UNIT mta_unit[] = { {UDATA(&mt_srv, UNIT_MT, 0), 0, UNIT_ADDR(0x187)}, /* 7 */ }; -struct dib mta_dib = { 0xF8, NUM_UNITS_MT, NULL, mt_startcmd, NULL, mta_unit, NULL}; +struct dib mta_dib = { 0xF8, NUM_UNITS_MT, NULL, mt_startcmd, NULL, mta_unit, mt_ini}; DEVICE mta_dev = { "MTA", mta_unit, NULL, mt_mod, @@ -192,7 +190,7 @@ UNIT mtb_unit[] = { {UDATA(&mt_srv, UNIT_MT, 0), 0, UNIT_ADDR(0x287)}, /* 7 */ }; -struct dib mtb_dib = { 0xF8, NUM_UNITS_MT, NULL, mt_startcmd, NULL, mtb_unit, NULL}; +struct dib mtb_dib = { 0xF8, NUM_UNITS_MT, NULL, mt_startcmd, NULL, mtb_unit, mt_ini}; DEVICE mtb_dev = { "MTB", mtb_unit, NULL, mt_mod, @@ -264,36 +262,52 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uptr->u4 = 0; uptr->u6 = 0; mt_busy[GET_DEV_BUF(dptr->flags)] = 1; - if ((cmd & 0x7) == 0x7) /* Quick end channel on control */ + if ((cmd & 0x7) == 0x7) { /* Quick end channel on control */ +// if ((cmd & 0x30) == 0) { + // mt_busy[GET_DEV_BUF(dptr->flags)] = 0; + // } return SNS_CHNEND; + } return 0; case 0x3: /* Control */ case 0xb: /* Control */ if ((uptr->flags & MTUF_9TR) == 0) { uptr->u5 |= (SNS_7TRACK << 8); - if ((cmd & 0x30) == 0) - return SNS_DEVEND; - if ((cmd & 0x38) == 0x18) - return SNS_DEVEND; - if ((cmd & 0xc0) != 0xc0) { + if ((cmd & 0xc0) == 0xc0) { uptr->u5 |= SNS_CMDREJ; - } else { - uptr->u3 &= ~MT_MDEN_MSK; - uptr->u3 |= (cmd & MT_MDEN_MSK); + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + } + switch((cmd >> 3) & 07) { + case 0: /* NOP */ + case 1: /* Diagnostics */ + case 3: + return SNS_CHNEND|SNS_DEVEND ; + case 2: /* Reset condition */ + uptr->u3 &= ~(MT_ODD|MT_TRANS|MT_CONV|MT_MDEN_MSK); + uptr->u3 |= (cmd & MT_MDEN_MSK) | MT_ODD | MT_CONV; + break; + case 4: + uptr->u3 &= ~(MT_ODD|MT_TRANS|MT_CONV|MT_MDEN_MSK); + uptr->u3 |= (cmd & MT_MDEN_MSK); + break; + case 5: + uptr->u3 &= ~(MT_ODD|MT_TRANS|MT_CONV|MT_MDEN_MSK); + uptr->u3 |= (cmd & MT_MDEN_MSK) | MT_TRANS; + break; + case 6: + uptr->u3 &= ~(MT_ODD|MT_TRANS|MT_CONV|MT_MDEN_MSK); + uptr->u3 |= (cmd & MT_MDEN_MSK) | MT_ODD; + break; + case 7: + uptr->u3 &= ~(MT_ODD|MT_TRANS|MT_CONV|MT_MDEN_MSK); + uptr->u3 |= (cmd & MT_MDEN_MSK) | MT_ODD | MT_TRANS; + break; } - uptr->u3 &= ~(MT_ODD|MT_TRANS); - uptr->u3 |= MT_CONV; - if (cmd & 0x10) - uptr->u3 |= MT_ODD; - if (cmd & 0x20) - uptr->u3 &= ~MT_CONV; - if (cmd & 0x08) - uptr->u3 |= MT_TRANS; } else { - if ((cmd & 0xf0) != 0xc0) { - uptr->u5 |= SNS_CMDREJ; - } +// if ((cmd & 0xf0) != 0xc0) { + // uptr->u5 |= SNS_CMDREJ; + // } uptr->u3 &= ~MT_MDEN_MSK; if (cmd & 0x8) uptr->u3 |= MT_MDEN_800; @@ -420,7 +434,7 @@ t_stat mt_srv(UNIT * uptr) ch = mt_buffer[bufnum][uptr->u4++]; /* if we are a 7track tape, handle conversion */ if ((uptr->flags & MTUF_9TR) == 0) { - mode = (uptr->u3 & MT_ODD) ? 0100 : 0; + mode = (uptr->u3 & MT_ODD) ? 0 : 0100; if ((parity_table[ch & 077] ^ (ch & 0100) ^ mode) == 0) { sim_debug(DEBUG_DETAIL, dptr, "Parity error unit=%d %d %03o\n", unit, uptr->u4-1, ch); @@ -504,7 +518,7 @@ t_stat mt_srv(UNIT * uptr) } } else { if ((uptr->flags & MTUF_9TR) == 0) { - mode = (uptr->u3 & MT_ODD) ? 0100 : 0; + mode = (uptr->u3 & MT_ODD) ? 0 : 0100; if (uptr->u3 & MT_TRANS) ch = (ch & 0xf) | ((ch & 0x30) ^ 0x30); if (uptr->u3 & MT_CONV) { @@ -564,7 +578,7 @@ t_stat mt_srv(UNIT * uptr) ch = mt_buffer[bufnum][--uptr->u4]; if ((uptr->flags & MTUF_9TR) == 0) { - mode = (uptr->u3 & MT_ODD) ? 0100 : 0; + mode = (uptr->u3 & MT_ODD) ? 0 : 0100; ch &= 077; if ((parity_table[ch & 077] ^ (ch & 0100) ^ mode) == 0) { uptr->u5 |= (SNS_VRC << 16) | SNS_DATCHK; @@ -621,10 +635,12 @@ t_stat mt_srv(UNIT * uptr) uptr->u3 &= ~MT_CMDMSK; mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1; set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); +// chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SCPE_OK; } uptr->u4 ++; sim_activate(uptr, 500); + // chan_end(addr, SNS_CHNEND); } else { sim_debug(DEBUG_DETAIL, dptr, "Write Mark unit=%d\n", unit); uptr->u3 &= ~(MT_CMDMSK); @@ -641,10 +657,12 @@ t_stat mt_srv(UNIT * uptr) uptr->u3 &= ~MT_CMDMSK; mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1; set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); +// chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SCPE_OK; } uptr->u4 ++; sim_activate(uptr, 500); +// chan_end(addr, SNS_CHNEND); break; case 1: uptr->u4++; @@ -680,8 +698,10 @@ t_stat mt_srv(UNIT * uptr) uptr->u3 &= ~MT_CMDMSK; mt_busy[bufnum] &= ~1; set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); +// chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } +// chan_end(addr, SNS_CHNEND); uptr->u4 ++; sim_activate(uptr, 500); break; @@ -717,6 +737,7 @@ t_stat mt_srv(UNIT * uptr) case 0: uptr->u4 ++; sim_activate(uptr, 500); + // chan_end(addr, SNS_CHNEND); break; case 1: uptr->u4++; @@ -757,6 +778,7 @@ t_stat mt_srv(UNIT * uptr) case 0: uptr->u4 ++; sim_activate(uptr, 500); +// chan_end(addr, SNS_CHNEND); break; case 1: sim_debug(DEBUG_DETAIL, dptr, "Skip rec unit=%d ", unit); @@ -795,10 +817,12 @@ t_stat mt_srv(UNIT * uptr) uptr->u5 |= SNS_CMDREJ; uptr->u3 &= ~MT_CMDMSK; mt_busy[bufnum] &= ~1; +// chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); } else { uptr->u4 ++; sim_activate(uptr, 500); +// chan_end(addr, SNS_CHNEND); } break; case 1: @@ -818,24 +842,26 @@ t_stat mt_srv(UNIT * uptr) if (uptr->u4 == 0) { uptr->u4 ++; sim_activate(uptr, 30000); +// chan_end(addr, SNS_CHNEND); + mt_busy[bufnum] &= ~1; } else { sim_debug(DEBUG_DETAIL, dptr, "Rewind unit=%d\n", unit); uptr->u3 &= ~(MT_CMDMSK); r = sim_tape_rewind(uptr); set_devattn(addr, SNS_DEVEND); - mt_busy[bufnum] &= ~1; } break; case MT_RUN: if (uptr->u4 == 0) { uptr->u4 ++; + mt_busy[bufnum] &= ~1; sim_activate(uptr, 30000); +// chan_end(addr, SNS_CHNEND); } else { sim_debug(DEBUG_DETAIL, dptr, "Unload unit=%d\n", unit); uptr->u3 &= ~(MT_CMDMSK); r = sim_tape_detach(uptr); - mt_busy[bufnum] &= ~1; } break; } @@ -847,7 +873,9 @@ mt_ini(UNIT * uptr, t_bool f) { DEVICE *dptr = find_dev_from_unit(uptr); - uptr->u3 = MT_ODD|MT_DENS_800; + uptr->u3 &= ~0xffff; + if ((uptr->flags & MTUF_9TR) == 0) + uptr->u3 |= MT_ODD|MT_CONV|MT_MDEN_800; mt_busy[GET_DEV_BUF(dptr->flags)] = 0; } @@ -884,7 +912,10 @@ mt_boot(int32 unit_num, DEVICE * dptr) if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ - uptr->u3 |= MT_CONV; + if ((uptr->flags & MTUF_9TR) == 0) { + uptr->u3 &= ~0xffff; + uptr->u3 |= MT_ODD|MT_CONV|MT_MDEN_800; + } return chan_boot(GET_UADDR(uptr->u3), dptr); }