From 18215f0e73509ad5910078da48c5bb31240bc713 Mon Sep 17 00:00:00 2001 From: AZBevier Date: Tue, 4 Feb 2020 18:16:35 -0700 Subject: [PATCH] SEL32: Allow channel address reconfiguration. SEL32: Add disk definitions for UTX and MPX. SEL32: Add disk initialization for UTX and MPX HSDP & DISK controllers. SEL32: Add read/write track/sector label simulation for UTX & MPX. SEL32: Create revised initialization test files for SIMH. --- SEL32/sel32_chan.c | 215 ++++--- SEL32/sel32_com.c | 5 +- SEL32/sel32_con.c | 9 +- SEL32/sel32_cpu.c | 29 +- SEL32/sel32_defs.h | 71 ++- SEL32/sel32_disk.c | 1390 +++++++++++++++++++++++++++++++----------- SEL32/sel32_hsdp.c | 1189 +++++++++++++++++++++++++----------- SEL32/sel32_mt.c | 35 +- SEL32/sel32_scfi.c | 632 ++++++++++--------- SEL32/tests/diag.ini | 163 ++++- 10 files changed, 2544 insertions(+), 1194 deletions(-) diff --git a/SEL32/sel32_chan.c b/SEL32/sel32_chan.c index 6464805..6753980 100644 --- a/SEL32/sel32_chan.c +++ b/SEL32/sel32_chan.c @@ -123,6 +123,7 @@ 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); t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc); +DEVICE *get_dev(UNIT *uptr); /* FIFO support */ /* These are FIFO queues which return an error when full. @@ -303,7 +304,7 @@ int readfull(CHANP *chp, uint32 maddr, uint32 *word) } maddr >>= 2; /* get 32 bit word index */ *word = M[maddr]; /* get the contents */ - sim_debug(DEBUG_EXP, &cpu_dev, "readfull read %08x from addr %08x\n", *word, maddr<<2); + sim_debug(DEBUG_EXP, &cpu_dev, "READFULL read %08x from addr %08x\n", *word, maddr<<2); return 0; /* return OK */ } @@ -327,7 +328,7 @@ int readbuff(CHANP *chp) addr >>= 2; /* byte to word address */ chp->chan_buf = M[addr]; /* get 4 bytes */ - sim_debug(DEBUG_DETAIL, &cpu_dev, "readbuff read memory bytes into buffer %02x %06x %08x %08x [", + 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) { char ch = (chp->chan_buf >> k) & 0xFF; @@ -349,13 +350,17 @@ int writebuff(CHANP *chp) 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", addr, MEMSIZE, chp->chan_status); + sim_debug(DEBUG_DETAIL, &cpu_dev, + "writebuff PCHK addr %08x to big mem %08x status %04x\n", + addr, MEMSIZE, chp->chan_status); chp->chan_byte = BUFF_CHNEND; irq_pend = 1; return 1; } addr &= MASK24; - sim_debug(DEBUG_DETAIL, &cpu_dev, "writebuff WRITE addr %08x MEMSIZE %08x status %04x\n", addr, MEMSIZE, chp->chan_status); + sim_debug(DEBUG_DETAIL, &cpu_dev, + "writebuff WRITE addr %06x DATA %08x status %04x\n", + addr, chp->chan_buf, chp->chan_status); M[addr>>2] = chp->chan_buf; return 0; } @@ -372,10 +377,12 @@ int load_ccw(CHANP *chp, int tic_ok) CHANP *pchp; loop: - sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw entry chan_status[%04x] %04x\n", chan, chp->chan_status); + sim_debug(DEBUG_XIO, &cpu_dev, + "load_ccw entry chan_status[%04x] %04x\n", chan, chp->chan_status); /* Abort if we have any errors */ - if (chp->chan_status & 0x3f03) { /* check channel status */ - sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); + if (chp->chan_status & 0x3f03) { /* check channel status */ + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); return 1; } @@ -388,13 +395,16 @@ loop: /* Read in first or next CCW */ 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 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); return 1; /* error return */ } - sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw read ccw chan %02x caw %06x IOCD wd 1 %08x\n", + 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", + 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 @@ -641,8 +651,8 @@ int chan_write_byte(uint16 chsa, uint8 *data) return 1; /* return error */ } if (chp->ccw_count == 0) { - sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte ccw_count is zero ccw_count[%04x] %04x\n", - chan, chp->ccw_count); + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_byte ccw_count is zero ccw_count[%04x] %04x\n", + chan, chp->ccw_count); if (chp->chan_byte & BUFF_DIRTY) { sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte 2 BUF DIRTY ret\n"); if (writebuff(chp)) /* write it */ @@ -660,7 +670,8 @@ int chan_write_byte(uint16 chsa, uint8 *data) return 1; /* return error */ } } - sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte non zero ccw_count[%04x]=%04x\n", chan, chp->ccw_count); + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_byte non zero ccw_count[%04x]=%04x\n", + chan, chp->ccw_count); if (chp->ccw_flags & FLAG_SKIP) { chp->ccw_count--; chp->chan_byte = BUFF_EMPTY; @@ -735,8 +746,9 @@ void chan_end(uint16 chsa, uint16 flags) { uint32 chan_icb = find_int_icb(chsa); /* get icb address */ 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); + 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); if (chp->chan_byte & BUFF_DIRTY) { if (writebuff(chp)) /* write remaining data */ return; /* error */ @@ -746,8 +758,9 @@ 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", - chsa, chp->ccw_flags, chp->ccw_count, chp->chan_status); + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_end SLI test 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 */ /* remove until I figure out what is required */ @@ -876,13 +889,15 @@ t_stat checkxio(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 */ + tempa = M[(chan_ivl+20)>>2]; /* status is in wd 5 of ICB */ sim_debug(DEBUG_CMD, &cpu_dev, - "checkxio busy 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]); + "checkxio busy ck chsa %04x cmd %02x iocla %08x flags %04x IOCD1 %08x IOCD2 %08x status %08x\n", + chsa, chp->ccw_cmd, iocla, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2], tempa); /* 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, "checkxio busy return CC4 chsa %04x chan %04x\n", chsa, chan); + sim_debug(DEBUG_XIO, &cpu_dev, + "checkxio busy return CC4 chsa %04x chan %04x\n", chsa, chan); *status = CC4BIT; /* busy, so CC4 */ return SCPE_OK; /* just busy CC4 */ } @@ -1640,6 +1655,32 @@ uint32 scan_chan(int *ilev) { return 0; /* done */ } +/* Find_dev pointer for a unit + Input: uptr = pointer to unit + Output: dptr = pointer to device +*/ +DEVICE *get_dev(UNIT *uptr) +{ + DEVICE *dptr; + uint32 i, j; + + if (uptr == NULL) /* must be valid unit */ + return NULL; + if (uptr->dptr) /* get device pointer from unit */ + return uptr->dptr; /* return valid pointer */ + /* the device pointer in the unit is not set up, do it now */ + /* This should never happed as the pointer is setup in first reset call */ + for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* do all devices */ + for (j = 0; j < dptr->numunits; j++) { /* do all units for device */ + if (uptr == (dptr->units + j)) { /* match found? */ + uptr->dptr = dptr; /* set the pointer in unit */ + return dptr; /* return valid pointer */ + } + } + } + return NULL; +} + /* set up the devices configured into the simulator */ /* only devices with a DIB will be processed */ t_stat chan_set_devs() { @@ -1652,20 +1693,29 @@ t_stat chan_set_devs() { for (i = 0; sim_devices[i] != NULL; i++) { DEVICE *dptr = sim_devices[i]; /* get pointer to next configured device */ UNIT *uptr = dptr->units; /* get pointer to units defined for this device */ - DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to Device Information Block for this device */ + DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to DIB for this device */ CHANP *chp; /* channel program pointer */ int chsa; /* addr of device chan & subaddress */ + /* set the device back pointer in the unit structure */ + for (j = 0; j < dptr->numunits; j++) { /* loop through unit entries */ + uptr->dptr = dptr; /* set the device pointer in unit structure */ + uptr++; /* next UNIT pointer */ + } + uptr = dptr->units; /* get pointer to units again */ + if (dibp == NULL) /* If no DIB, not channel device */ continue; - if (dptr->flags & DEV_DIS) { /* Skip disabled devices */ + if (dptr->flags & DEV_DIS) /* Skip disabled devices */ continue; - } + if ((chp = (CHANP *)dibp->chan_prg) == NULL)/* must have channel information for each device */ continue; /* Check if address is in unit or dev entry */ for (j = 0; j < dptr->numunits; j++) { /* loop through unit entries */ chsa = GET_UADDR(uptr->u3); /* ch/sa value */ +//printf("Setup device %s%d chsa %04x type %03d dptr %x\n", +// dptr->name, j, chsa, GET_TYPE(uptr->flags), uptr->dptr); /* zero some channel data loc's for device */ dev_status[chsa] = 0; /* zero device status flags */ dev_status[chsa&0x7f00] = 0; /* clear the channel status location */ @@ -1678,8 +1728,11 @@ t_stat chan_set_devs() { chp->ccw_flags = 0; /* Command chain and supress incorrect length */ chp->ccw_cmd = 0; /* read command */ chp->chan_inch_addr = 0; /* clear address of stat dw in memory */ - if ((uptr->flags & UNIT_DIS) == 0) /* is unit marked disabled? */ + if ((uptr->flags & UNIT_DIS) == 0) { /* is unit marked disabled? */ + if (dev_unit[chsa] != 0) + printf("Channel/SubAddress %04x multiple defined\n", chsa); dev_unit[chsa] = dibp; /* no, save the dib address */ + } if (dibp->dev_ini != NULL) /* if there is an init routine, call it now */ dibp->dev_ini(uptr, 1); /* init the channel */ uptr++; /* next UNIT pointer */ @@ -1691,91 +1744,67 @@ t_stat chan_set_devs() { /* Validate and set the device onto a given channel */ t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { - DEVICE *dptr; - DIB *dibp; - t_value newdev; - t_stat r; - int i; - int devaddr; + DEVICE *dptr; /* device pointer */ + DIB *dibp; /* dib pointer */ + UNIT *tuptr; /* temp unit pointer */ + t_value chan; /* new channel addr */ + t_stat r; /* return status */ + int i; /* temp */ + int chsa; /* dev addr */ +// dptr = uptr->dptr /* get device pointer from unit */ if (cptr == NULL) /* is there a UNIT name specified */ return SCPE_ARG; /* no, arg error */ if (uptr == NULL) /* is there a UNIT pointer */ return SCPE_IERR; /* no, arg error */ - dptr = find_dev_from_unit(uptr); /* find the device from unit pointer */ + dptr = get_dev(uptr); /* find the device from unit pointer */ if (dptr == NULL) /* device not found, so error */ return SCPE_IERR; /* error */ - dibp = (DIB *)dptr->ctxt; - if (dibp == NULL) - return SCPE_IERR; + dibp = (DIB *)dptr->ctxt; /* get dib pointer from device struct */ + if (dibp == NULL) /* we need a DIB */ + return SCPE_IERR; /* no DIB, so error */ - newdev = get_uint(cptr, 16, 0xffff, &r); + 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 (r != SCPE_OK) - return r; +// 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 */ - 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; - } else { - devaddr &= (dibp->mask | 0x7f00); - for (i = 0; i < dibp->numunits; i++) - dev_unit[devaddr + i] = NULL; + /* change all the unit addresses with the new channel, but keep sub address */ + /* Clear out existing entries for all units on this device */ + tuptr = dptr->units; /* get pointer to units defined for this device */ + /* loop through all units for this device */ + for (i = 0; i < dibp->numunits; i++) { + chsa = GET_UADDR(tuptr->u3); /* get old chsa for this unit */ + dev_unit[chsa] = NULL; /* clear sa dib pointer */ + dev_unit[chsa&0x7f00] = NULL; /* clear the channel dib address */ + chsa = chan | (chsa & 0xff); /* merge new channel with new sa */ + tuptr->u3 &= ~UNIT_ADDR_MASK; /* clear old chsa for this unit */ + tuptr->u3 |= UNIT_ADDR(chsa); /* clear old chsa for this unit */ + dev_unit[chan&0x7f00] = dibp; /* set the channel dib address */ + dev_unit[chsa] = dibp; /* save the dib address for new chsa */ + fprintf(stderr, "Set dev %04x to %04x\r\n", GET_UADDR(tuptr->u3), chsa); + tuptr++; /* next unit pointer */ } - - /* Check if device already at newdev */ - if (dptr->flags & DEV_UADDR) { - if (dev_unit[newdev] != NULL) - r = SCPE_ARG; - } else { - newdev &= (dibp->mask | 0x7f00); - for (i = 0; i < dibp->numunits; i++) { - if (dev_unit[newdev + i] != NULL) - r = SCPE_ARG; - } - } - - /* If not, point to new dev, else restore old */ - if (r == SCPE_OK) - devaddr = newdev; - - /* Update device entry */ - if (dptr->flags & DEV_UADDR) { - dev_unit[devaddr] = dibp; - uptr->u3 &= ~UNIT_ADDR(0x7fff); - uptr->u3 |= UNIT_ADDR(devaddr); - fprintf(stderr, "Set dev %04x\r\n", GET_UADDR(uptr->u3)); - } else { - for (i = 0; i < dibp->numunits; i++) { - dev_unit[devaddr + i] = dibp; - uptr = &((dibp->units)[i]); - uptr->u3 &= ~UNIT_ADDR(0x7fff); - uptr->u3 |= UNIT_ADDR(devaddr + i); - fprintf(stderr, "Set dev %04x\r\n", GET_UADDR(uptr->u3)); - } - } - return r; + return SCPE_OK; } t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc) { DEVICE *dptr; int chsa; - if (uptr == NULL) - return SCPE_IERR; - dptr = find_dev_from_unit(uptr); - if (dptr == NULL) - return SCPE_IERR; - chsa = GET_UADDR(uptr->u3); - fprintf(st, "CHAN/SA %04x", chsa); - return SCPE_OK; + if (uptr == NULL) /* valid unit? */ + return SCPE_IERR; /* no, error return */ + dptr = get_dev(uptr); /* get the device pointer from unit */ + if (dptr == NULL) /* valid pointer? */ + return SCPE_IERR; /* retunr error */ + chsa = GET_UADDR(uptr->u3); /* get the unit address */ + fprintf(st, "CHAN/SA %04x", chsa); /* display channel/subaddress */ + return SCPE_OK; /* we done */ } diff --git a/SEL32/sel32_com.c b/SEL32/sel32_com.c index 695b2d0..5003366 100644 --- a/SEL32/sel32_com.c +++ b/SEL32/sel32_com.c @@ -35,6 +35,7 @@ extern void chan_end(uint16 chan, uint8 flags); extern int chan_read_byte(uint16 chan, uint8 *data); extern int chan_write_byte(uint16 chan, uint8 *data); extern void set_devwake(uint16 addr, uint8 flags); +extern DEVICE *get_dev(UNIT *uptr); /* Constants */ #define COM_LINES 8 /* max lines */ @@ -377,7 +378,7 @@ void coml_ini(UNIT *uptr, t_bool f) /* 8-line serial routines */ void com_ini(UNIT *uptr, t_bool f) { - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = get_dev(uptr); sim_debug(DEBUG_CMD, &com_dev, "COM init device %s controller 0x7e00\n", dptr->name); sim_activate(uptr, 1000); /* time increment */ @@ -386,7 +387,7 @@ void com_ini(UNIT *uptr, t_bool f) /* called from sel32_chan to start an I/O operation */ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); uint8 ch; diff --git a/SEL32/sel32_con.c b/SEL32/sel32_con.c index 83fbef0..b93c387 100644 --- a/SEL32/sel32_con.c +++ b/SEL32/sel32_con.c @@ -48,6 +48,7 @@ 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 DEVICE *get_dev(UNIT *uptr); #define CMD u3 /* Held in u3 is the device command and status */ @@ -157,7 +158,7 @@ DEVICE con_dev = { /* initialize the console chan/unit */ void con_ini(UNIT *uptr, t_bool f) { // int unit = (uptr - con_unit); /* unit 0 */ -// DEVICE *dptr = find_dev_from_unit(uptr); +// DEVICE *dptr = get_dev(uptr); // con_data[unit].incnt = 0; /* no input data */ con_data[0].incnt = 0; /* no input data */ @@ -169,7 +170,7 @@ void con_ini(UNIT *uptr, t_bool f) { /* start a console operation */ uint8 con_preio(UNIT *uptr, uint16 chan) { - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */ @@ -301,7 +302,6 @@ t_stat con_srvo(UNIT *uptr) { int unit = (uptr - con_unit); /* unit 0 is read, unit 1 is write */ int cmd = uptr->CMD & CON_MSK; uint8 ch, cp; - static uint32 lastch = 0; sim_debug(DEBUG_DETAIL, &con_dev, "con_srvo enter chsa %04x cmd = %02x\n", chsa, cmd); if (cmd == 0x0C) { /* unknown has to do nothing */ @@ -322,6 +322,7 @@ t_stat con_srvo(UNIT *uptr) { 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 */ @@ -339,8 +340,8 @@ t_stat con_srvo(UNIT *uptr) { else cp = '^'; sim_debug(DEBUG_CMD, &con_dev, "con_srvo write %01x: putch 0x%02x %c\n", unit, ch, cp); - lastch = (lastch << 8) | 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 diff --git a/SEL32/sel32_cpu.c b/SEL32/sel32_cpu.c index 2b4f99c..808ddb7 100644 --- a/SEL32/sel32_cpu.c +++ b/SEL32/sel32_cpu.c @@ -1983,9 +1983,11 @@ wait_loop: } redo: if (skipinstr) { /* need to skip interrupt test? */ +#ifdef NOTNOW sim_debug(DEBUG_TRAP, &cpu_dev, "Skipinstr set to zero PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", PSD1, PSD2, CPUSTATUS); +#endif skipinstr = 0; /* skip only once */ goto skipi; /* skip int test */ } @@ -2662,9 +2664,11 @@ exec: PSD2 |= 0x00004000; /* set bit 49 only */ SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ +#ifdef NOTNOW sim_debug(DEBUG_IRQ, &cpu_dev, "BEI skipinstr %x irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", skipinstr, irq_pend, PSD1, PSD2, CPUSTATUS); +#endif break; case 0x7: /* UEI */ if ((modes & PRIVBIT) == 0) { /* must be privileged to UEI */ @@ -2681,9 +2685,11 @@ exec: PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ +#ifdef NOTNOW sim_debug(DEBUG_IRQ, &cpu_dev, "UEI skipinstr %x irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", skipinstr, irq_pend, PSD1, PSD2, CPUSTATUS); +#endif break; case 0x8: /* EAE */ PSD1 |= AEXPBIT; /* set the enable AEXP flag in PSD */ @@ -5950,16 +5956,16 @@ doovr2: if (PSD2 & MAPBIT) { /* set mapped mode in cpu status */ CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "B4 LPSDCM temp %06x TPSD %08x %08x PSD %08x %08x\n", temp, TPSD[0], TPSD[1], PSD1, PSD2); - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "B4 LPSDCM BPIX %04x CPIX %04x CPIXPL %04x\n", BPIX, CPIX, CPIXPL); - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "B4 LPSDCM OS MAPC[0-5] %08x %08x %08x %08x %08x %08x\n", MAPC[0], MAPC[1], MAPC[2], MAPC[3], MAPC[4], MAPC[5]); - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "B4 LPSDCM US MAPC[%x-%x] %08x %08x %08x %08x %08x %08x\n", BPIX, BPIX+5, MAPC[BPIX], MAPC[BPIX+1], MAPC[BPIX+2], MAPC[BPIX+3], MAPC[BPIX+4], MAPC[BPIX+5]); @@ -5974,23 +5980,18 @@ doovr2: } #endif if ((PSD2 & RETMBIT) == 0) { /* don't load maps if retain bit set */ -#ifdef DO_DYNAMIC_DEBUG - /* start debugging */ - if ((PSD1&0xffffff) == 0x11314) - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif /* we need to load the new maps */ TRAPME = load_maps(PSD, 0); /* load maps for new PSD */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "AF LPSDCM TPSD %08x %08x PSD %08x %08x TRAPME %02x\n", TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "AF LPSDCM BPIX %04x CPIX %04x CPIXPL %04x\n", BPIX, CPIX, CPIXPL); - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "AF LPSDCM OS MAPC[0-5] %08x %08x %08x %08x %08x %08x\n", MAPC[0], MAPC[1], MAPC[2], MAPC[3], MAPC[4], MAPC[5]); - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "AF LPSDCM US MAPC[%x-%x] %08x %08x %08x %08x %08x %08x\n", BPIX, BPIX+5, MAPC[BPIX], MAPC[BPIX+1], MAPC[BPIX+2], MAPC[BPIX+3], MAPC[BPIX+4], MAPC[BPIX+5]); @@ -5998,7 +5999,7 @@ doovr2: PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_CMD, &cpu_dev, "LPSDCM MAPS LOADED TRAPME = %02x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", TRAPME, PSD1, PSD2, CPUSTATUS); } diff --git a/SEL32/sel32_defs.h b/SEL32/sel32_defs.h index 56cb9cb..32ddbc3 100644 --- a/SEL32/sel32_defs.h +++ b/SEL32/sel32_defs.h @@ -108,11 +108,11 @@ #define NUM_UNITS_CON 2 /* 2 console input & output */ #define NUM_DEVS_MT 1 /* 1 mag tape controllers */ #define NUM_UNITS_MT 4 /* 4 of 8 devices */ -//#define FOR_UTX +#define FOR_UTX #ifdef FOR_UTX #define NUM_DEVS_HSDP 1 /* 1 HSPD disk drive controller */ #define NUM_UNITS_HSDP 2 /* 2 disk drive devices */ -#else +//#else #define NUM_DEVS_DISK 1 /* 1 DP02 disk drive controller */ #define NUM_UNITS_DISK 2 /* 2 disk drive devices */ //#define NUM_UNITS_DISK 4 /* 4 disk drive devices */ @@ -181,12 +181,12 @@ typedef struct chp { uint32 chan_inch_addr; /* Channel status dw in memory */ uint32 chan_caw; /* Channel command address word */ uint32 ccw_addr; /* Channel address */ + uint32 chan_buf; /* Channel data buffer */ uint16 ccw_count; /* Channel count */ - uint8 ccw_cmd; /* Channel command and flags */ uint16 ccw_flags; /* Channel flags */ uint16 chan_status; /* Channel status */ uint16 chan_dev; /* Device on channel */ - uint32 chan_buf; /* Channel data buffer */ + uint8 ccw_cmd; /* Channel command and flags */ uint8 chan_byte; /* Current byte, dirty/full */ } CHANP; @@ -224,6 +224,13 @@ typedef struct dib { #define GET_DADDR(x) (0x7f & ((x) >> DEV_V_ADDR)) #define DEV_ADDR(x) ((x) << DEV_V_ADDR) +/* allow 255 type disks */ +#define UNIT_V_TYPE (UNIT_V_UF + 0) +#define UNIT_TYPE (0xff << UNIT_V_TYPE) +/* get & set disk types */ +#define GET_TYPE(x) ((UNIT_TYPE & (x)) >> UNIT_V_TYPE) +#define SET_TYPE(x) (UNIT_TYPE & ((x) << UNIT_V_TYPE)) + #define UNIT_V_ADDR 16 #define UNIT_ADDR_MASK (0x7fff << UNIT_V_ADDR) #define GET_UADDR(x) ((UNIT_ADDR_MASK & x) >> UNIT_V_ADDR) @@ -344,34 +351,34 @@ extern DEBTAB dev_debug[]; #define BIT1 0x40000000 /* general use for bit 1 testing */ #define BIT2 0x20000000 /* general use for bit 2 testing */ #define BIT3 0x10000000 /* general use for bit 3 testing */ -#define BIT4 0x80000000 /* general use for bit 4 testing */ -#define BIT5 0x40000000 /* general use for bit 5 testing */ -#define BIT6 0x20000000 /* general use for bit 6 testing */ -#define BIT7 0x10000000 /* general use for bit 7 testing */ -#define BIT8 0x80000000 /* general use for bit 8 testing */ -#define BIT9 0x40000000 /* general use for bit 9 testing */ -#define BIT10 0x20000000 /* general use for bit 10 testing */ -#define BIT11 0x10000000 /* general use for bit 11 testing */ -#define BIT12 0x80000000 /* general use for bit 12 testing */ -#define BIT13 0x40000000 /* general use for bit 13 testing */ -#define BIT14 0x20000000 /* general use for bit 14 testing */ -#define BIT15 0x10000000 /* general use for bit 15 testing */ -#define BIT16 0x80000000 /* general use for bit 16 testing */ -#define BIT17 0x40000000 /* general use for bit 17 testing */ -#define BIT18 0x20000000 /* general use for bit 18 testing */ -#define BIT19 0x10000000 /* general use for bit 19 testing */ -#define BIT20 0x80000000 /* general use for bit 20 testing */ -#define BIT21 0x40000000 /* general use for bit 21 testing */ -#define BIT22 0x20000000 /* general use for bit 22 testing */ -#define BIT23 0x10000000 /* general use for bit 23 testing */ -#define BIT24 0x80000000 /* general use for bit 24 testing */ -#define BIT25 0x40000000 /* general use for bit 25 testing */ -#define BIT26 0x20000000 /* general use for bit 26 testing */ -#define BIT27 0x10000000 /* general use for bit 27 testing */ -#define BIT28 0x80000000 /* general use for bit 28 testing */ -#define BIT29 0x40000000 /* general use for bit 29 testing */ -#define BIT30 0x20000000 /* general use for bit 30 testing */ -#define BIT31 0x10000000 /* general use for bit 31 testing */ +#define BIT4 0x08000000 /* general use for bit 4 testing */ +#define BIT5 0x04000000 /* general use for bit 5 testing */ +#define BIT6 0x02000000 /* general use for bit 6 testing */ +#define BIT7 0x01000000 /* general use for bit 7 testing */ +#define BIT8 0x00800000 /* general use for bit 8 testing */ +#define BIT9 0x00400000 /* general use for bit 9 testing */ +#define BIT10 0x00200000 /* general use for bit 10 testing */ +#define BIT11 0x00100000 /* general use for bit 11 testing */ +#define BIT12 0x00080000 /* general use for bit 12 testing */ +#define BIT13 0x00040000 /* general use for bit 13 testing */ +#define BIT14 0x00020000 /* general use for bit 14 testing */ +#define BIT15 0x00010000 /* general use for bit 15 testing */ +#define BIT16 0x00008000 /* general use for bit 16 testing */ +#define BIT17 0x00004000 /* general use for bit 17 testing */ +#define BIT18 0x00002000 /* general use for bit 18 testing */ +#define BIT19 0x00001000 /* general use for bit 19 testing */ +#define BIT20 0x00000800 /* general use for bit 20 testing */ +#define BIT21 0x00000400 /* general use for bit 21 testing */ +#define BIT22 0x00000200 /* general use for bit 22 testing */ +#define BIT23 0x00000100 /* general use for bit 23 testing */ +#define BIT24 0x00000080 /* general use for bit 24 testing */ +#define BIT25 0x00000040 /* general use for bit 25 testing */ +#define BIT26 0x00000020 /* general use for bit 26 testing */ +#define BIT27 0x00000010 /* general use for bit 27 testing */ +#define BIT28 0x00000008 /* general use for bit 28 testing */ +#define BIT29 0x00000004 /* general use for bit 29 testing */ +#define BIT30 0x00000002 /* general use for bit 30 testing */ +#define BIT31 0x00000001 /* general use for bit 31 testing */ #define MASK16 0x0000FFFF /* 16 bit address mask */ #define MASK19 0x0007FFFF /* 19 bit address mask */ #define MASK20 0x000FFFFF /* 20 bit address mask */ diff --git a/SEL32/sel32_disk.c b/SEL32/sel32_disk.c index 24295ec..8efb646 100644 --- a/SEL32/sel32_disk.c +++ b/SEL32/sel32_disk.c @@ -1,6 +1,6 @@ /* sel32_disk.c: SEL-32 2311/2314 Disk Processor II - 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 @@ -23,32 +23,57 @@ #include "sel32_defs.h" -extern t_stat set_dev_addr(UNIT * uptr, int32 val, CONST char *cptr, void *desc); -extern t_stat show_dev_addr(FILE * st, UNIT * uptr, int32 v, CONST void *desc); -extern void chan_end(uint16 chan, uint8 flags); -extern int chan_read_byte(uint16 chsa, uint8 *data); -extern int chan_write_byte(uint16 chsa, uint8 *data); -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 t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +extern t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc); +extern void chan_end(uint16 chan, uint8 flags); +extern int chan_read_byte(uint16 chsa, uint8 *data); +extern int chan_write_byte(uint16 chsa, uint8 *data); +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 uint32 M[]; /* our memory */ -extern uint32 SPAD[]; /* cpu SPAD memory */ +extern uint32 M[]; /* our memory */ +extern uint32 SPAD[]; /* cpu SPAD memory */ #ifdef NUM_DEVS_DISK -#define UNIT_V_TYPE (UNIT_V_UF + 0) -#define UNIT_TYPE (0xf << UNIT_V_TYPE) -#define GET_TYPE(x) ((UNIT_TYPE & (x)) >> UNIT_V_TYPE) -#define SET_TYPE(x) (UNIT_TYPE & ((x) << UNIT_V_TYPE)) -#define UNIT_DISK UNIT_ATTABLE | UNIT_IDLE +#define UNIT_DISK 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) (disk_type[type].spt) +/* get sectors per cylinderfor specified type */ +#define SPC(type) (disk_type[type].spt*disk_type[type].nhds) +/* get number of cylinders for specified type */ +#define CYL(type) (disk_type[type].cyl) +/* get number of heads for specified type */ +#define HDS(type) (disk_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) (disk_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 WD 1 - Flags - 0 -36 byte count -Data - 224 word INCH buffer address +Data - 224 word INCH buffer address (SST) WD 1 Drive 0 Attribute register WD 2 Drive 1 Attribute register WD 3 Drive 2 Attribute register @@ -65,110 +90,148 @@ 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=Blk size 00=768 byte blk + bit 7 - 0=Blk size 01=1024 byte blk 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) + mini-module) */ - /* 224 word INCH Buffer layout */ /* 128 word subchannel status storage (SST) */ /* 66 words of program status queue (PSQ) */ /* 26 words of scratchpad */ /* 4 words of label buffer registers */ -#define CMD u3 +/* track label / sector label definations */ +/* + short lcyl; cylinder + char ltkn; track + char lid; sector id + char lflg1; track/sector status flags + bit 0 good + 1 alternate + 2 spare + 3 reserved + 4 flaw + 5 last track + 6 start of alternate + char lflg2; + short lspar1; + short lspar2; + short ldef1; + int ldeallp; DMAP block number trk0 + int lumapp; UMAP block number sec1 + short ladef3; + short laltcyl; + char lalttk; sectors per track + char ldscnt; number of heads + char ldatrflg; device attributes + bit 0 n/u + 1 disk is mhd + 2 n/u + 3 n/u + 4 n/u + 5 dual ported + 6/7 00 768 bytes/blk + 01 1024 bytes/blk + 10 2048 bytes/blk + char ldatrscnt; sectors per track (again) + char ldatrmhdc; MHD head count + char ldatrfhdc; FHD head count + */ + +#define CMD u3 /* u3 */ /* in u3 is device command code and status */ -#define DSK_CMDMSK 0x00ff /* Command being run */ -#define DSK_STAR 0x0100 /* STAR value in u4 */ -#define DSK_NU2 0x0200 /* */ -#define DSK_READDONE 0x0400 /* Read finished, end channel */ -#define DSK_ENDDSK 0x0800 /* Sensed end of disk */ -#define DSK_SEEKING 0x1000 /* Disk is currently seeking */ -#define DSK_READING 0x2000 /* Disk is reading data */ -#define DSK_WRITING 0x4000 /* Disk is writing data */ -#define DSK_BUSY 0x8000 /* Flag to send a CUE */ +#define DSK_CMDMSK 0x00ff /* Command being run */ +#define DSK_STAR 0x0100 /* STAR value in u4 */ +#define DSK_NU2 0x0200 /* */ +#define DSK_READDONE 0x0400 /* Read finished, end channel */ +#define DSK_ENDDSK 0x0800 /* Sensed end of disk */ +#define DSK_SEEKING 0x1000 /* Disk is currently seeking */ +#define DSK_READING 0x2000 /* Disk is reading data */ +#define DSK_WRITING 0x4000 /* Disk is writing data */ +#define DSK_BUSY 0x8000 /* Disk is busy */ /* commands */ -#define DSK_INCH 0x00 /* Initialize channel */ -#define DSK_INCH2 0xf0 /* Initialize channel for processing */ -#define DSK_WD 0x01 /* Write data */ -#define DSK_RD 0x02 /* Read data */ -#define DSK_NOP 0x03 /* No operation */ -#define DSK_SNS 0x04 /* Sense */ -#define DSK_SCK 0x07 /* Seek cylinder, track, sector */ -#define DSK_TIC 0x08 /* Transfer in channel */ -#define DSK_FNSK 0x0B /* Format for no skip */ -#define DSK_LPL 0x13 /* Lock protected label */ -#define DSK_LMR 0x1F /* Load mode register */ -#define DSK_RES 0x23 /* Reserve */ -#define DSK_WSL 0x31 /* Write sector label */ -#define DSK_RSL 0x32 /* Read sector label */ -#define DSK_REL 0x33 /* Release */ -#define DSK_XEZ 0x37 /* Rezero */ -#define DSK_POR 0x43 /* Priority Override */ -#define DSK_IHA 0x47 /* Increment head address */ -#define DSK_SRM 0x4F /* Set reserve track mode */ -#define DSK_WTL 0x51 /* Write track label */ -#define DSK_RTL 0x52 /* Read track label */ -#define DSK_XRM 0x5F /* Reset reserve track mode */ -#define DSK_RAP 0xA2 /* Read angular positions */ -#define DSK_TESS 0xAB /* Test STAR (subchannel target address register) */ -#define DSK_ICH 0xFF /* Initialize Controller */ +#define DSK_INCH 0x00 /* Initialize channel */ +#define DSK_INCH2 0xf0 /* Initialize channel for processing */ +#define DSK_WD 0x01 /* Write data */ +#define DSK_RD 0x02 /* Read data */ +#define DSK_NOP 0x03 /* No operation */ +#define DSK_SNS 0x04 /* Sense */ +#define DSK_SCK 0x07 /* Seek cylinder, track, sector */ +#define DSK_TIC 0x08 /* Transfer in channel */ +#define DSK_FNSK 0x0B /* Format for no skip */ +#define DSK_LPL 0x13 /* Lock protected label */ +#define DSK_LMR 0x1F /* Load mode register */ +#define DSK_RES 0x23 /* Reserve */ +#define DSK_WSL 0x31 /* Write sector label */ +#define DSK_RSL 0x32 /* Read sector label */ +#define DSK_REL 0x33 /* Release */ +#define DSK_XEZ 0x37 /* Rezero */ +#define DSK_POR 0x43 /* Priority Override */ +#define DSK_IHA 0x47 /* Increment head address */ +#define DSK_SRM 0x4F /* Set reserve track mode */ +#define DSK_WTL 0x51 /* Write track label */ +#define DSK_RTL 0x52 /* Read track label */ +#define DSK_XRM 0x5F /* Reset reserve track mode */ +#define DSK_RAP 0xA2 /* Read angular positions */ +#define DSK_TESS 0xAB /* Test STAR (subchannel target address register) */ +#define DSK_ICH 0xFF /* Initialize Controller */ -#define STAR u4 +#define STAR u4 /* u4 - sector target address register (STAR) */ /* Holds the current cylinder, head(track), sector */ -#define DISK_CYL 0xFFFF0000 /* cylinder mask */ -#define DISK_TRACK 0x0000FF00 /* track mask */ -#define DISK_SECTOR 0x000000ff /* sector mask */ +#define DISK_CYL 0xFFFF0000 /* cylinder mask */ +#define DISK_TRACK 0x0000FF00 /* track mask */ +#define DISK_SECTOR 0x000000ff /* sector mask */ -#define SNS u5 +#define SNS u5 /* u5 */ /* Sense byte 0 - mode register */ -#define SNS_DROFF 0x80000000 /* Drive Carriage will be offset */ -#define SNS_TRKOFF 0x40000000 /* Track offset: 0=positive, 1=negative */ -#define SNS_RDTMOFF 0x20000000 /* Read timing offset = 1 */ -#define SNS_RDSTRBT 0x10000000 /* Read strobe timing: 1=positive, 0=negative */ -#define SNS_DIAGMOD 0x08000000 /* Diagnostic Mode ECC Code generation and checking */ -#define SNS_RSVTRK 0x04000000 /* Reserve Track mode: 1=OK to write, 0=read only */ -#define SNS_FHDOPT 0x02000000 /* FHD or FHD option = 1 */ -#define SNS_RESERV 0x01000000 /* Reserved */ +#define SNS_DROFF 0x80000000 /* Drive Carriage will be offset */ +#define SNS_TRKOFF 0x40000000 /* Track offset: 0=positive, 1=negative */ +#define SNS_RDTMOFF 0x20000000 /* Read timing offset = 1 */ +#define SNS_RDSTRBT 0x10000000 /* Read strobe timing: 1=positive, 0=negative */ +#define SNS_DIAGMOD 0x08000000 /* Diagnostic Mode ECC Code generation and checking */ +#define SNS_RSVTRK 0x04000000 /* Reserve Track mode: 1=OK to write, 0=read only */ +#define SNS_FHDOPT 0x02000000 /* FHD or FHD option = 1 */ +#define SNS_RESERV 0x01000000 /* Reserved */ /* Sense byte 1 */ -#define SNS_CMDREJ 0x800000 /* Command reject */ -#define SNS_INTVENT 0x400000 /* Unit intervention required */ -#define SNS_SPARE1 0x200000 /* Spare */ -#define SNS_EQUCHK 0x100000 /* Equipment check */ -#define SNS_DATCHK 0x080000 /* Data Check */ -#define SNS_OVRRUN 0x040000 /* Data overrun/underrun */ -#define SNS_DSKFERR 0x020000 /* Disk format error */ -#define SNS_DEFTRK 0x010000 /* Defective track encountered */ +#define SNS_CMDREJ 0x800000 /* Command reject */ +#define SNS_INTVENT 0x400000 /* Unit intervention required */ +#define SNS_SPARE1 0x200000 /* Spare */ +#define SNS_EQUCHK 0x100000 /* Equipment check */ +#define SNS_DATCHK 0x080000 /* Data Check */ +#define SNS_OVRRUN 0x040000 /* Data overrun/underrun */ +#define SNS_DSKFERR 0x020000 /* Disk format error */ +#define SNS_DEFTRK 0x010000 /* Defective track encountered */ /* Sense byte 2 */ -#define SNS_LAST 0x8000 /* Last track flag encountered */ -#define SNS_AATT 0x4000 /* At Alternate track */ -#define SNS_WPER 0x2000 /* Write protection error */ -#define SNS_WRL 0x1000 /* Write lock error */ -#define SNS_MOCK 0x0800 /* Mode check */ -#define SNS_INAD 0x0400 /* Invalid memory address */ -#define SNS_RELF 0x0200 /* Release fault */ -#define SNS_CHER 0x0100 /* Chaining error */ +#define SNS_LAST 0x8000 /* Last track flag encountered */ +#define SNS_AATT 0x4000 /* At Alternate track */ +#define SNS_WPER 0x2000 /* Write protection error */ +#define SNS_WRL 0x1000 /* Write lock error */ +#define SNS_MOCK 0x0800 /* Mode check */ +#define SNS_INAD 0x0400 /* Invalid memory address */ +#define SNS_RELF 0x0200 /* Release fault */ +#define SNS_CHER 0x0100 /* Chaining error */ /* Sense byte 3 */ -#define SNS_REVL 0x80 /* Revolution lost */ -#define SNS_DADE 0x40 /* Disc addressing or seek error */ -#define SNS_BUCK 0x20 /* Buffer check */ -#define SNS_ECCS 0x10 /* ECC error in sector label */ -#define SNS_ECCD 0x08 /* ECC error iin data */ -#define SNS_ECCT 0x04 /* ECC error in track label */ -#define SNS_RTAE 0x02 /* Reserve track access error */ -#define SNS_UESS 0x01 /* Uncorrectable ECC error */ +#define SNS_REVL 0x80 /* Revolution lost */ +#define SNS_DADE 0x40 /* Disc addressing or seek error */ +#define SNS_BUCK 0x20 /* Buffer check */ +#define SNS_ECCS 0x10 /* ECC error in sector label */ +#define SNS_ECCD 0x08 /* ECC error iin data */ +#define SNS_ECCT 0x04 /* ECC error in track label */ +#define SNS_RTAE 0x02 /* Reserve track access error */ +#define SNS_UESS 0x01 /* Uncorrectable ECC error */ -#define ATTR u6 +#define ATTR u6 +/* u6 */ /* u6 holds drive attribute entry */ /* provided by inch command for controller */ /* @@ -178,15 +241,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) + mini-module) */ -#define DDATA up7 +#define DDATA up7 /* Pointer held in up7 */ /* sects/cylinder = sects/track * numhds */ /* allocated during attach command for each unit defined */ @@ -201,107 +264,37 @@ struct ddata_t struct disk_t { const char *name; /* Device ID Name */ - uint32 taus; /* total allocation units */ - uint16 bms; /* bit map size */ uint16 nhds; /* Number of heads */ uint16 ssiz; /* sector size in words */ - uint16 spt; /* # sectors per track(cylinder) */ - uint8 spau; /* # sectors per allocation unit */ - uint8 spb; /* # sectors per block (192 WDS)*/ - uint32 cyl; /* Number of cylinders */ + uint16 spt; /* # sectors per track(head) */ + uint16 ucyl; /* Number of cylinders used */ + uint16 cyl; /* Number of cylinders on disk */ uint8 type; /* Device type code */ + /* 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[] = { -#ifdef NOTUSED_FOR_NOW - /* Class E Disc Devices */ - {"FE004", 5888, 184, 256, 192, 23, 1, 1, 1, 0x80}, /* 4 M */ - {"CE010", 12800, 200, 2, 96, 16, 1, 2, 400, 0x60}, /* 10 M */ - {"ME040", 23000, 719, 5, 192, 23, 2, 1, 400, 0x40}, /* 40 M */ - {"ME080", 46000, 1438, 5, 192, 23, 2, 1, 800, 0x40}, /* 80 M */ - {"ME300", 87400, 2732, 19, 192, 23, 4, 1, 800, 0x40}, /* 300 M */ - {"FE005", 5888, 184, 4, 192, 23, 1, 1, 64, 0x80}, /* 5 M */ - /* Class F Disc Devices */ - {"FL001", 1334, 0, 2, 64, 26, 3, 3, 26, 0x40}, /* 1 M */ - {"MH040", 20000, 625, 5, 192, 20, 2, 1, 400, 0x40}, /* 40 M */ -#ifdef FOR_UTX - {"9342", 40000, 1250, 5, 256, 16, 2, 1, 800, 0x40}, /*823 80 M */ - {"9344", 76000, 2375, 19, 256, 16, 4, 1, 800, 0x40}, /*823 300 M */ -#else - {"MH080", 40000, 1250, 5, 192, 20, 2, 1, 800, 0x40}, /* 80 M */ - {"MH300", 76000, 2375, 19, 192, 20, 4, 1, 800, 0x40}, /* 300 M */ -#endif - {"FH005", 5120, 184, 4, 192, 20, 1, 1, 64, 0x80}, /* 5 M */ - {"CD032", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /* 32 M */ - {"CD032", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /* 32 M */ - {"CD064", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /* 64 M */ - {"CD064", 24000, 750, 3, 192, 20, 2, 1, 800, 0x60}, /* 64 M */ - {"CD096", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /* 96 M */ - {"CD096", 40000, 1250, 5, 192, 20, 2, 1, 800, 0x60}, /* 96 M */ - {"MH600", 80000, 2500, 40, 192, 20, 8, 1, 800, 0x40}, /* 600 M */ - {"FM600", 80000, 2500, 40, 192, 20, 8, 1, 800, 0x40}, /* 600 M */ - {"FM600", 1600, 50, 40, 192, 20, 1, 1, 2, 0x80}, /* 600 M */ - {NULL, 0} -#else - /* Class F Disc Devices */ - {"MH040", 20000, 625, 5, 192, 20, 2, 1, 400, 0x40}, /* 40 M */ - {"MH080", 40000, 1250, 5, 192, 20, 2, 1, 800, 0x40}, /* 80 M */ - {"MH300", 76000, 2375, 19, 192, 20, 4, 1, 800, 0x40}, /* 300 M */ - {"MH600", 80000, 2500, 40, 192, 20, 8, 1, 800, 0x40}, /* 600 M */ + /* For MPX */ + {"MH040", 5, 192, 20, 400, 411, 0x40}, /* 0 411 40M XXXX */ + {"MH080", 5, 192, 20, 800, 823, 0x40}, /* 1 823 80M 8138 */ + {"MH160", 10, 192, 20, 800, 823, 0x40}, /* 2 823 160M 8148 */ + {"MH300", 19, 192, 20, 800, 823, 0x40}, /* 3 823 300M 8127 */ + {"MH600", 40, 192, 20, 800, 843, 0x40}, /* 4 843 600M 8155 */ /* For UTX */ - {"9342", 40000, 1250, 5, 256, 16, 2, 1, 800, 0x40}, /*823 80 M */ - {"9344", 76000, 2375, 19, 256, 16, 4, 1, 800, 0x40}, /*823 300 M */ - {"8887", 76000, 2375, 10, 256, 34, 4, 1, 819, 0x40}, /*823 300 M */ -#endif + {"9342", 5, 256, 16, 819, 823, 0x40}, /* 5 823 80M */ + {"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 */ + {"8887", 10, 256, 35, 819, 823, 0x40}, /* 9 823 340M */ + {"8155", 40, 256, 16, 839, 843, 0x40}, /* 10 843 675M */ + {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 'E' DISC DEVICES - DID C'DE01', 1, 1, 23, 192, 256, 184, 5888, C'FE004' - DID C'DE02', 2, 1, 16, 96, 2, 200, 12800, C'CE010' - DID C'DE04', 1, 2, 23, 192, 5, 719, 23000, C'ME040' - DID C'DE05', 1, 2, 23, 192, 5, 1438, 46000, C'ME080' - DID C'DE06', 1, 4, 23, 192, 19, 2732, 87400, C'ME300' - DID C'DE07', 1, 1, 23, 192, 4, 184, 5888, C'FE005' -* 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'DF05', 1, 1, 20, 192, 4, 184, 5120, C'FH005' - DID C'DF06', 1, 2, 20, 192, 1, 250, 8000, C'CD032' - DID C'DF06', 1, 2, 20, 192, 1, 250, 8000, C'CD032' - DID C'DF07', 1, 2, 20, 192, 1, 250, 8000, C'CD064' - 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'DF0A', 1, 1, 20, 192, 40, 50, 1600, C'FM600' -* -#endif - uint8 disk_preio(UNIT *uptr, uint16 chan) ; uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; uint8 disk_haltio(uint16 addr); @@ -311,10 +304,10 @@ void disk_ini(UNIT *, t_bool); t_stat disk_reset(DEVICE *); t_stat disk_attach(UNIT *, CONST char *); t_stat disk_detach(UNIT *); -t_stat disk_set_type(UNIT * uptr, int32 val, CONST char *cptr, void *desc); -t_stat disk_get_type(FILE * st, UNIT * uptr, int32 v, CONST void *desc); +t_stat disk_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat disk_get_type(FILE *st, UNIT *uptr, int32 v, CONST void *desc); t_stat disk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); -const char *disk_description (DEVICE *dptr); +const char *disk_description (DEVICE *dptr); /* channel program information */ CHANP dda_chp[NUM_UNITS_DISK] = {0}; @@ -324,20 +317,20 @@ MTAB disk_mod[] = { &disk_set_type, &disk_get_type, NULL, "Type of disk"}, {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, &show_dev_addr, NULL, "Device channel address"}, - {0} + {0}, }; UNIT dda_unit[] = { /* SET_TYPE(9) DM300 old */ -/* SET_TYPE(2) DM300 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0x800)}, /* 0 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0x801)}, /* 1 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0x802)}, /* 2 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0x803)}, /* 3 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0x804)}, /* 4 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0x805)}, /* 5 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0x806)}, /* 6 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0x807)}, /* 7 */ +/* SET_TYPE(3) DM300 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x800)}, /* 0 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x801)}, /* 1 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x802)}, /* 2 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x803)}, /* 3 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x804)}, /* 4 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x805)}, /* 5 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x806)}, /* 6 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0x807)}, /* 7 */ }; DIB dda_dib = { @@ -350,18 +343,18 @@ DIB dda_dib = { dda_unit, /* Pointer to units structure */ dda_chp, /* Pointer to chan_prg structure */ NUM_UNITS_DISK, /* number of units defined */ - 0x0f, /* 16 devices - device mask */ + 0x07, /* 8 devices - device mask */ 0x0800, /* parent channel address */ 0, /* fifo input index */ 0, /* fifo output index */ - {0} /* interrupt status fifo for channel */ + {0}, /* interrupt status fifo for channel */ }; DEVICE dda_dev = { "DMA", dda_unit, NULL, 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, 0, dev_debug, + &dda_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, NULL, NULL, &disk_help, NULL, NULL, &disk_description }; @@ -371,15 +364,15 @@ CHANP ddb_chp[NUM_UNITS_DISK] = {0}; UNIT ddb_unit[] = { /* SET_TYPE(9) DM300 old */ -/* SET_TYPE(2) DM300 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0xC00)}, /* 0 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0xC01)}, /* 1 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0xC02)}, /* 2 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0xC03)}, /* 3 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0xC04)}, /* 4 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0xC05)}, /* 5 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0xC06)}, /* 6 */ - {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(2), 0), 0, UNIT_ADDR(0xC07)}, /* 7 */ +/* SET_TYPE(3) DM300 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC00)}, /* 0 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC01)}, /* 1 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC02)}, /* 2 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC03)}, /* 3 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC04)}, /* 4 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC05)}, /* 5 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC06)}, /* 6 */ + {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC07)}, /* 7 */ }; @@ -393,44 +386,60 @@ DIB ddb_dib = { ddb_unit, /* Pointer to units structure */ ddb_chp, /* Pointer to chan_prg structure */ NUM_UNITS_DISK, /* number of units defined */ - 0x0f, /* 16 devices - device mask */ + 0x07, /* 8 devices - device mask */ 0x0C00, /* parent channel address */ 0, /* fifo input index */ 0, /* fifo output index */ - 0, /* interrupt status fifo for channel */ + {0}, /* interrupt status fifo for channel */ }; DEVICE ddb_dev = { "DMB", ddb_unit, NULL, 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, 0, dev_debug, + &ddb_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, NULL, NULL, &disk_help, NULL, NULL, &disk_description }; #endif +/* convert sector disk address to star values (c,h,s) */ +uint32 disksec2star(uint32 daddr, int type) +{ + int32 sec = daddr % disk_type[type].spt; /* get sector value */ + int32 spc = disk_type[type].nhds * disk_type[type].spt; /* sec per cyl */ + int32 cyl = daddr / spc; /* cylinders */ + int32 hds = (daddr % spc) / disk_type[type].spt; /* heads */ + + /* now return the star value */ + return (CHS2STAR(cyl,hds,sec)); /* return STAR */ +} + /* start a disk operation */ uint8 disk_preio(UNIT *uptr, uint16 chan) { - DEVICE *dptr = find_dev_from_unit(uptr); - int unit = (uptr - dptr->units); + DEVICE *dptr = get_dev(uptr); + uint16 addr = GET_UADDR(uptr->CMD); + int unit = (uptr - dptr->units); + sim_debug(DEBUG_CMD, dptr, "disk_preio CMD %08x unit %02x\n", uptr->CMD, unit); if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */ return SNS_BSY; } - sim_debug(DEBUG_CMD, dptr, "dsk_preio unit=%02x OK\n", unit); + sim_debug(DEBUG_CMD, dptr, "disk_preio unit %02x chsa %04x OK\n", unit, addr); return 0; /* good to go */ } uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uint16 addr = GET_UADDR(uptr->CMD); - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); uint8 ch; - sim_debug(DEBUG_CMD, dptr, "disk_startcmd unit %02x cmd %02x CMD %08x\n", unit, cmd, uptr->CMD); + sim_debug(DEBUG_CMD, dptr, + "disk_startcmd addr %04x unit %02x cmd %02x CMD %08x\n", + addr, 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 */ @@ -438,7 +447,7 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) } if ((uptr->CMD & DSK_CMDMSK) != 0) { - uptr->CMD |= DSK_BUSY; /* Flag we we are busy */ + uptr->CMD |= DSK_BUSY; /* Flag we are busy */ return SNS_BSY; } if ((uptr->CMD & 0xff00) != 0) { /* if any status info, we are busy */ @@ -486,8 +495,8 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) 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 */ + /* 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; @@ -504,7 +513,7 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->SNS &= 0xff000000; /* clear status bytes, but leave mode data */ return SNS_CHNEND|SNS_DEVEND; } - if (cmd == 0x00) /* INCH cmd gives unit check here */ + 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 */ @@ -514,66 +523,103 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) /* Unit is online, so process a command */ switch (cmd) { - case DSK_INCH: /* INCH 0x00 */ + case DSK_INCH: /* INCH 0x0 */ { uint32 mema; /* memory address */ uint32 i; UNIT *up = dptr->units; /* first unit for this device */ - sim_debug(DEBUG_CMD, dptr, "disk_startcmd starting inch cmd addr %04x STAR %08x\n", - addr, uptr->STAR); + 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 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 */ + /* 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 STAR %08x mema %08x units %02x\n", - addr, uptr->STAR, mema, dptr->numunits); + "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->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); + sim_debug(DEBUG_CMD, dptr, "disk_startcmd done INCH cmd addr %04x\n", addr); 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 */ +// 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 addr %04x\n", + cmd, addr); sim_activate(uptr, 20); /* start things off */ return 0; + break; case DSK_NOP: /* NOP 0x03 */ uptr->CMD |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ return 0; + break; case DSK_SNS: /* Sense 0x04 */ uptr->CMD |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ break; + + case DSK_WSL: /* WSL 0x31 */ + uptr->CMD |= cmd; /* save cmd */ + sim_activate(uptr, 20); /* start things off */ + return 0; + break; + + case DSK_RSL: /* RSL 0x32 */ + uptr->CMD |= cmd; /* save cmd */ + sim_activate(uptr, 20); /* start things off */ + return 0; + break; + + case DSK_WTL: /* WTL 0x51 */ + uptr->CMD |= cmd; /* save cmd */ + sim_activate(uptr, 20); /* start things off */ + return 0; + break; + + case DSK_RTL: /* RTL 0x52 */ + uptr->CMD |= cmd; /* save cmd */ + sim_activate(uptr, 20); /* start things off */ + return 0; + break; } + sim_debug(DEBUG_CMD, dptr, "disk_startcmd done with disk_startcmd %02x addr %04x SNS %08x\n", - cmd, addr, uptr->SNS); + cmd, addr, 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 */ @@ -581,30 +627,31 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) } /* Handle processing of disk requests. */ -t_stat disk_srv(UNIT * uptr) +t_stat disk_srv(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->CMD); - DEVICE *dptr = find_dev_from_unit(uptr); + 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); int cmd = uptr->CMD & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); +// uint32 trk, cyl, sec; uint32 trk, cyl; int unit = (uptr - dptr->units); int len; int i; uint8 ch; - int tsize = disk_type[type].spt * disk_type[type].ssiz * 4; /* get track size in bytes */ - int ssize = disk_type[type].ssiz * 4; /* disk sector size in bytes */ - int tstart; + 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_DETAIL, &dda_dev, - "disk_srv entry unit %02x cmd %02x chsa %04x chan %04x count %04x\n", - unit, cmd, chsa, chsa>>8, chp->ccw_count); + 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); if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ uptr->SNS |= SNS_INTVENT; /* unit intervention required */ @@ -612,16 +659,17 @@ t_stat disk_srv(UNIT * uptr) return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; } - sim_debug(DEBUG_CMD, dptr, "disk_srv cmd=%02x chsa %04x count %04x\n", - cmd, chsa, chp->ccw_count); + sim_debug(DEBUG_CMD, dptr, + "disk_srv cmd=%02x chsa %04x count %04x\n", + cmd, chsa, chp->ccw_count); switch (cmd) { - case 0: /* No command, stop disk */ + case 0: /* No command, stop disk */ break; - case DSK_INCH2: /* use 0xff for inch, just need int */ + case DSK_INCH2: /* use 0xff for inch, just need int */ 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); + chsa, chp->ccw_count); #ifdef FIX4MPX chan_end(chsa, SNS_CHNEND); /* return just channel end OK */ #else @@ -629,14 +677,66 @@ t_stat disk_srv(UNIT * uptr) #endif break; - case DSK_NOP: /* NOP 0x03 */ + case DSK_WSL: /* WSL 0x31 make into NOP */ uptr->CMD &= ~(0xffff); /* remove old cmd */ - sim_debug(DEBUG_CMD, dptr, "disk_srv cmd NOP chsa %04x count %04x completed\n", + 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 */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + 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]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case DSK_WTL: /* WTL 0x51 make into NOP */ + uptr->CMD &= ~(0xffff); /* remove old cmd */ + sim_debug(DEBUG_CMD, dptr, + "disk_srv cmd WTL chsa %04x count %04x completed\n", + chsa, chp->ccw_count); + + sim_debug(DEBUG_DETAIL, dptr, "Track 0 label"); + /* now read track label data */ + for (i = 0; i < 30; i++) { + if (chan_read_byte(chsa, &buf[i])) { + /* we have read error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (i == 16) + sim_debug(DEBUG_DETAIL, dptr, "\nTrack 0 label"); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case DSK_NOP: /* NOP 0x03 */ + uptr->CMD &= ~(0xffff); /* remove old cmd */ + sim_debug(DEBUG_CMD, dptr, + "disk_srv cmd NOP chsa %04x count %04x completed\n", chsa, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; case DSK_SNS: /* 0x4 */ +#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) ; @@ -653,28 +753,117 @@ t_stat disk_srv(UNIT * uptr) uptr->CMD &= ~(0xff00); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; +#else + sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD sense\n"); - case DSK_SCK: /* Seek cylinder, track, sector 0x07 */ + /* 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", + 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", + 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", + 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", + 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 */ + sim_debug(DEBUG_DETAIL, dptr, "disk_srv sense unit=%02x 1 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + /* bytes 5-7 - status bytes, bytes 1-3 of SNS */ + ch = (uptr->SNS >> 16) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "disk_srv sense unit=%02x 2 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + ch = (uptr->SNS >> 8) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "disk_srv sense unit=%02x 3 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + ch = (uptr->SNS) & 0xff; + 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; + 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; + 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; + 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; + 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) { + /* bytes 12 & 13 contain drive related status */ + ch = 0; /* zero for now */ + sim_debug(DEBUG_DETAIL, dptr, "disk_srv dsr unit=%02x 1 %02x\n", + unit, ch); + chan_write_byte(chsa, &ch); + + ch = 0x30; /* drive on cylinder and ready for now */ + sim_debug(DEBUG_DETAIL, dptr, "disk_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; + +#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 ((uptr->STAR >> 16) == data->cyl) { + if ((int32)(uptr->STAR >> 16) == (int32)data->cyl) { /* 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); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - set_devattn(chsa, SNS_DEVEND); /* start the operation */ - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek end unit=%02x %02x %04x\n", +// 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); + chan_end(chsa, SNS_DEVEND|SNS_CHNEND); sim_activate(uptr, 20); break; } else { +#ifndef TRYTHIS + data->cyl = ((uptr->STAR >> 16)&0xffff); + sim_activate(uptr, 10); + break; +#else /* Compute delay based of difference. */ /* Set next state = index */ - i = (uptr->STAR >> 16) - data->cyl; - sim_debug(DEBUG_CMD, dptr, "dsk_srv seek unit=%02x %02x %04x\n", unit, - uptr->STAR >> 16, i); + 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 */ @@ -704,60 +893,90 @@ t_stat disk_srv(UNIT * uptr) if ((int32)data->cyl < 0) /* test for less than zero */ data->cyl = 0; /* make zero */ } - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek next unit=%02x %02x %04x\n", - unit, uptr->STAR >> 16, data->cyl); +#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", + unit, buf[0], buf[1], buf[2], buf[3]); + /* Read in 4 character seek code */ for (i = 0; i < 4; 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 == 0) { + sim_debug(DEBUG_DETAIL, dptr, + "disk_srv seek error unit=%02x star %02x %02x %02x %02x\n", + unit, buf[0], buf[1], buf[2], buf[3]); + /* we have error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + break; + } + /* just read the next byte */ } } + /* done reading, see how many we read */ + if (i == 1) { + /* UTX wants to set seek STAR to zero */ + buf[0] = buf[1] = buf[2] = buf[3] = 0; + } + /* else the cyl, trk, and sect are ready to update */ rezero: - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek unit=%02x star %02x %02x %02x %02x\n", + 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; /* get the cylinder */ + cyl = (uptr->STAR >> 16) & 0xffff; /* get the cylinder */ trk = buf[2]; /* get the track */ sim_debug(DEBUG_DETAIL, dptr, - "dsk_srv SEEK cyl %04x trk %02x sec %02x unit=%02x\n", cyl&0xffff, trk, buf[3], unit); + "disk_srv SEEK cyl %04x trk %02x sec %02x unit=%02x\n", + cyl&0xffff, trk, buf[3], unit); - /* FIXME do something with FHD here */ /* Check if seek valid */ - if (cyl > disk_type[type].cyl || + 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, - "dsk_srv seek ERROR cyl %04x trk %02x sec %02x unit=%02x\n", - cyl, trk, buf[3], unit); + "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 */ + uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; /* set error status */ /* we have an error, tell user */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* end command */ break; } - uptr->CMD |= DSK_STAR; /* show we have seek STAR in STAR */ +// uptr->CMD |= DSK_STAR; /* show we have seek STAR in STAR */ /* calc the sector address of data */ /* calculate file position in bytes of requested sector */ - // FIXME for variable sector size +//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 */ - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek start %04x trk %02x sec %02x\n", - tstart, trk, buf[3]); - if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* seek home */ + sim_debug(DEBUG_DETAIL, dptr, + "disk_srv seek start %04x cyl %04x trk %02x sec %02x\n", + tstart, cyl, trk, buf[3]); + + 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); } @@ -765,21 +984,22 @@ rezero: if (cyl != data->cyl) { /* Do seek */ uptr->CMD |= DSK_SEEKING; /* show we are seeking */ - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek unit=%02x trk %02x cyl %02x\n", - unit, trk, data->cyl); - sim_activate(uptr, 20); - chan_end(chsa, SNS_CHNEND); + sim_debug(DEBUG_DETAIL, dptr, + "dsk_srv seek unit=%02x cyl %04x trk %02x cyl %02x\n", + unit, cyl, trk, buf[3]); + sim_activate(uptr, 20); /* start us off */ +//WHAT? chan_end(chsa, SNS_CHNEND); } else { sim_debug(DEBUG_DETAIL, dptr, - "dsk_srv calc sect addr seek start %04x trk %02x sec %02x\n", - tstart, trk, buf[3]); + "dsk_srv calc sect addr seek start %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); +// sim_activate(uptr, 20); chan_end(chsa, SNS_DEVEND|SNS_CHNEND); } return SCPE_OK; - case DSK_XEZ: /* Rezero & Read IPL record */ + case DSK_XEZ: /* Rezero & Read IPL record */ sim_debug(DEBUG_CMD, dptr, "RD REZERO IPL unit=%02x seek 0\n", unit); /* Do a seek to 0 */ @@ -797,7 +1017,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: @@ -810,17 +1030,19 @@ 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 */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case DSK_RD: /* Read Data */ + case DSK_RD: /* Read Data */ 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 unit=%02x CMD %08x\n", unit, uptr->CMD); } if (uptr->CMD & DSK_READING) { /* see if we are reading data */ @@ -835,14 +1057,15 @@ rezero: } sim_debug(DEBUG_CMD, dptr, - "disk_srv after READ chsa %04x count %04x\n", chsa, chp->ccw_count); + "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; icyl, data->tpos, data->spos); + "DISK Read %04x bytes leaving %04x from diskfile /%04x/%02x/%02x\n", + i, chp->ccw_count, data->cyl, data->tpos, data->spos); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); goto rddone; @@ -850,8 +1073,8 @@ rezero: } sim_debug(DEBUG_CMD, dptr, - "DISK READ from sec end bytes end %04x from diskfile cyl %04x hds %02x sec %02x\n", - ssize, data->cyl, data->tpos, data->spos); + "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)) { @@ -862,7 +1085,11 @@ rezero: 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; } @@ -871,14 +1098,20 @@ rezero: /* see if we are done reading data */ if (test_write_byte_end(chsa)) { sim_debug(DEBUG_DATA, dptr, - "DISK Read complete Read bytes from diskfile cyl %04x hds %02x sec %02x\n", + "DISK Read complete for read from diskfile /%04x/%02x/%02x\n", data->cyl, data->tpos, data->spos); 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 */ + break; } rddone: - sim_activate(uptr, 10); /* wait to read next sector */ - break; + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ } break; @@ -919,7 +1152,7 @@ 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, data->cyl, data->tpos, data->spos); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; @@ -939,20 +1172,249 @@ rddone: 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 */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } } } -wrdone: - sim_activate(uptr, 10); + sim_activate(uptr, 10); /* keep writing */ break; +wrdone: + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ } break; + case DSK_RSL: /* RSL 0x32 */ + /* Read sector label zero to get disk geometry */ + /* write 30 bytes, b0-b1=cyl, b1=trk, b2=sec */ + /* zero the Track Label Buffer */ + for (i = 0; i < 30; i++) + buf[i] = 0; + + /* the dmap pointer is placed by the vendor or diag into the */ + /* track zero label in word 3 of the 30 byte label. */ + /* The disk address is the last track of the user area. The vendor */ + /* reserves the last cylinder, SEL diags reserve the next two, so the */ + /* addr is CYL-4/HDS-1/0 and is VDT. The UTX/MPX media table is on */ + /* previous track, so MDT = VDT-SPT is CYL-4/HDS-2/0 */ + /* The UTX flaw map is at 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 */ + /* 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)); + +#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 */ + 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 */ + 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 */ + /* store into sec 1 label */ + buf[16] = (tstart >> 24) & 0xff; /* UMAP pointer */ + buf[17] = (tstart >> 16) & 0xff; + buf[18] = (tstart >> 8) & 0xff; + buf[19] = (tstart) & 0xff; + + /* the tech doc shows the cyl/trk/sec data is in the first 4 bytes */ + /* of the track label, BUT it is really in the configuration data */ + /* area are too. That is where UTX looks. Byte 27 is sectors/track */ + /* and byte 28 is number of heads. Byte 25 is copy of byte 27. */ + buf[25] = disk_type[type].spt & 0xff; /* sect per track 35 */ + + /* UTX looks at bit 6 & 7 to determine if UDP or HSDP controller */ + /* The UDP/DPII controllers do not use these bits, so UTX keys */ + /* on these bits to determine type of controller. Bit 31 is set */ + /* for a HSDP and not set for the UDP/DPII */ + buf[26] = disk_type[type].type & 0xfc; /* sector size bits not used in UDP/DPII */ + buf[27] = disk_type[type].spt & 0xff; /* sec per track 35 */ + buf[28] = disk_type[type].nhds & 0xff; /* num heads 10 */ + + sim_debug(DEBUG_DETAIL, dptr, "Sector 1 label"); + /* now write sector label data */ + for (i = 0; i < 30; i++) { + if (chan_write_byte(chsa, &buf[i])) { + /* we have write error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (i == 16) + sim_debug(DEBUG_DETAIL, dptr, "\nSector 1 label"); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + /* command done */ + uptr->CMD &= ~(0xffff); /* remove old cmd */ + sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd RSL done chsa %04x count %04x completed\n", + chsa, chp->ccw_count); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case DSK_RTL: /* RTL 0x52 */ + /* Read track zero to get disk geometry */ + /* write 30 bytes, b0-b1=cyl, b1=trk, b2=sec */ + + /* 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 */ + + sim_debug(DEBUG_CMD, dptr, "disk_startcmd RTL STAR %08x disk geom %08x\n", + uptr->STAR, 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[4] = 0x80; /* show good sector */ + + sim_debug(DEBUG_DETAIL, dptr, + "disk_srv RTL unit=%02x star %02x %02x %02x %02x\n", + unit, buf[0], buf[1], buf[2], buf[3]); + + /* the dmap pointer is placed by the vendor or diag into the */ + /* track zero label in word 3 of the 30 byte label. */ + /* The disk address is the last track of the user area. The vendor */ + /* reserves the last cylinder, SEL diags reserve the next two, so the */ + /* addr is CYL-4/HDS-1/0 and is VDT. The UTX/MPX media table is on */ + /* previous track, so MDT = VDT-SPT is CYL-4/HDS-2/0 */ + /* The UTX flaw map is at 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 */ + /* 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 */ + 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", + cyl-3, trk-1, 0, tstart, tstart); + sim_debug(DEBUG_CMD, dptr, + "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 */ + /* output last sector address of disk */ + buf[12] = (tstart >> 24) & 0xff; /* DMAP pointer */ + buf[13] = (tstart >> 16) & 0xff; + buf[14] = (tstart >> 8) & 0xff; + buf[15] = (tstart) & 0xff; + } + + /* 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 */ + /* and byte 28 is number of heads. Byte 26 is mode. */ + /* Byte 25 is copy of byte 27. */ + buf[25] = disk_type[type].spt & 0xff; + buf[26] = disk_type[type].type; /* mode data in UDP/DPII */ + buf[27] = disk_type[type].spt & 0xff; + buf[28] = disk_type[type].nhds & 0xff; + + sim_debug(DEBUG_DETAIL, dptr, "Track 0 label"); + /* now write track label data */ + for (i = 0; i < 30; i++) { + if (chan_write_byte(chsa, &buf[i])) { + /* we have write error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (i == 16) + sim_debug(DEBUG_DETAIL, dptr, "\nTrack 0 label"); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + /* command done */ + uptr->CMD &= ~(0xffff); /* remove old cmd */ + sim_debug(DEBUG_CMD, dptr, "disk_srv cmd RTL done chsa %04x count %04x completed\n", + chsa, chp->ccw_count); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + 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); @@ -966,45 +1428,234 @@ wrdone: /* initialize the disk */ void disk_ini(UNIT *uptr, t_bool f) { - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = get_dev(uptr); int i = GET_TYPE(uptr->flags); uptr->CMD &= ~0x7fff; /* clear out the flags but leave ch/sa */ - /* capacity is total allocation units time sectors per allocation unit */ + uptr->SNS = ((uptr->SNS & 0x00ffffff) | (disk_type[i].type << 24)); /* save mode value */ /* total sectors on disk */ - uptr->capac = disk_type[i].taus * disk_type[i].spau; + uptr->capac = CAP(i); /* size in sectors */ - sim_debug(DEBUG_EXP, &dda_dev, "DMA init device %s on unit DMA%.1x cap %x\n", - dptr->name, GET_UADDR(uptr->CMD), uptr->capac); + sim_debug(DEBUG_EXP, &dda_dev, "DMA init device %s on unit DMA%.1x cap %x %d\n", + dptr->name, GET_UADDR(uptr->CMD), uptr->capac, uptr->capac); } -t_stat disk_reset(DEVICE * dptr) +t_stat disk_reset(DEVICE *dptr) { /* add reset code here */ return SCPE_OK; } +/* 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 */ + uint32 tsize = disk_type[type].spt; /* get track size in sectors */ + uint32 csize = disk_type[type].nhds * tsize; /* get cylinder size in sectors */ + uint32 cyl = disk_type[type].cyl; /* get # cylinders */ + uint32 spc = disk_type[type].nhds * disk_type[type].spt; /* sectors/cyl */ + uint32 cap = disk_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 */ + 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 */ + int32 daddr = vaddr - SPT(type); + /* get sector address of utx flaw map sec 1 pointer */ + /* use this address for sec 1 label pointer */ + int32 uaddr = daddr - SPT(type); +#ifdef MAYBE + /* get sector address of utx flaw data (1 track long) */ + /* set trace data to zero */ + 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, +// 7,0x5258,0,0x4e5c,0x3e,0x43fbc,0,0xd32c, + 7,0x5258,0,0x4e5c,0x3e,0x43fbc,0,0xd32c, + 0x79,0x187cc,0x118,0x14410,0x23f,0,0,0, + 0,0x3821a2d6,0x4608c,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, + }; +#else + { +// 0xf003d14f,0x8a03cda0,0x9a03cdbf,0x8903cdc0, +// 0x9903d01f,0x8c03d020,0x9c03d14f,0xf4000000, + 0xf0000000 | (cap-1), 0x8a000000 | daddr, + 0x9a000000 | (daddr + ((2 * tsize) - 1)), + 0x89000000 | (daddr + (2 * tsize)), + 0x99000000 | ((cap-1)-spc), + 0x8c000000 | (cap-spc), + 0x9c000000 | (cap-1), 0xf4000000, + }; +#endif + /* 250191 249248 250191 0 */ +// uint32 dmap[4] = {0xf003d14f, 0x8a03cda0, 0x9a03d14f, 0xf4000000}; + int i; + /* vendor flaw map */ + uint32 vmap[2] = {0xf0000004, 0xf4000000}; + uint32 dmap[4] = {0xf0000000 | (cap-1), 0x8a000000 | daddr, + 0x9a000000 | (cap-1), 0xf4000000}; + + /* see if user wants to initialize the disk */ + if (!get_yn("Initialize disk? [Y] ", TRUE)) { + return 1; + } +#ifdef OLD_WAY + /* dmap data */ + /* the diag map (dmap) is in last sec of disk */ + /* (cyl * trk * sec) - 1 = cap - 1*/ + /* 0xf0046531 - 288049 - 822/9/34 */ + /* 0x8a0460d2 - 286930 - 819/8/0 */ + /* 0x9a046531 - 288049 - 822/9/34 */ + /* 0xf4000000 */ + dmap[0] = 0xf0000000 | (cap-1); /* 0xf003d14f */ + dmap[1] = 0x8a000000 | daddr; /* 0x8a03ccaf */ + dmap[2] = 0x9a000000 | (cap-1); /* 0x9a03d14f */ + dmap[3] = 0xf4000000; +#endif + + /* seek to sector 0 */ + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + fprintf (stderr, "Error on seek to 0\r\n"); + } + + /* get buffer for track data in bytes */ + if ((buff = (uint8 *)calloc(csize*ssize, sizeof(uint8))) == 0) { + detach_unit(uptr); + return SCPE_ARG; + } + /* put dummy data in first word of disk */ + buff[0] = 'Z'; + buff[1] = 'E'; + buff[2] = 'R'; + buff[3] = 'O'; + sim_debug(DEBUG_CMD, dptr, + "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++) { + if ((sim_fwrite(buff, 1, csize*ssize, uptr->fileref)) != csize*ssize) { + sim_debug(DEBUG_CMD, dptr, + "Error on write to diskfile cyl %04x\n", cyl); + } + if (cyl == 0) { + buff[0] = 0; + buff[1] = 0; + buff[2] = 0; + buff[3] = 0; + } + if ((cyl % 100) == 0) + fputc('.', stderr); + } + fputc('\r', stderr); + fputc('\n', stderr); + + /* byte swap the buffers for dmap and umap */ +// for (i=0; i<256; i++) { + for (i=0; i<8; i++) { + umap[i] = (((umap[i] & 0xff) << 24) | ((umap[i] & 0xff00) << 8) | + ((umap[i] & 0xff0000) >> 8) | ((umap[i] >> 24) & 0xff)); + } + for (i=0; i<4; i++) { + dmap[i] = (((dmap[i] & 0xff) << 24) | ((dmap[i] & 0xff00) << 8) | + ((dmap[i] & 0xff0000) >> 8) | ((dmap[i] >> 24) & 0xff)); + } + for (i=0; i<2; i++) { + vmap[i] = (((vmap[i] & 0xff) << 24) | ((vmap[i] & 0xff00) << 8) | + ((vmap[i] & 0xff0000) >> 8) | ((vmap[i] >> 24) & 0xff)); + } + + /* now seek to end of disk and write the dmap data */ + /* setup dmap pointed to by track label 0 wd[3] = (cyl-4) * spt + (spt - 1) */ + + /* write dmap data to last sector on disk */ + sim_fseek(uptr->fileref, laddr*ssize, SEEK_SET); /* seek last sector */ + if ((sim_fwrite((char *)&dmap, sizeof(uint32), 4, uptr->fileref)) != 4) { + sim_debug(DEBUG_CMD, dptr, + "Error on vendor map write to diskfile sect %06x\n", (cap-1) * ssize); + } + + /* 1 cylinder is saved for disk manufacture */ + /* 2 cylinders are saved for diagnostics */ + /* write vmap to vaddr that is the address in trk 0 label + 1 track */ + /* daddr is (cap) - 3 cyl - 2 tracks */ + /* vaddr is (cap) - 3 cyl - 1 track */ + + /* seek to vendor label area */ + sim_fseek(uptr->fileref, (vaddr)*ssize, SEEK_SET); /* seek UMAP */ + if ((sim_fwrite((char *)&vmap, sizeof(uint32), 2, uptr->fileref)) != 2) { + sim_debug(DEBUG_CMD, dptr, + "Error on vendor map write to diskfile sect %06x\n", vaddr * ssize); + } + + /* write dmap to daddr that is the address in trk 0 label */ + /* daddr is (cap) - 3 cyl - 2 tracks */ + /* vaddr is daddr - spt */ + + sim_fseek(uptr->fileref, (daddr)*ssize, SEEK_SET); /* seek DMAP */ + 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 + sim_fseek(uptr->fileref, (uaddr)*ssize, SEEK_SET); /* seek UMAP */ + if ((sim_fwrite((char *)&umap, sizeof(uint32), 4, uptr->fileref)) != 4) { + sim_debug(DEBUG_CMD, dptr, + "Error on umap write to diskfile sect %06x\n", uaddr * ssize); + } +#endif + + printf("writing to vmap sec %x bytes %x\n", + vaddr, (vaddr)*ssize); + printf("writing zeros to umap sec %x bytes %x\n", + uaddr, (uaddr)*ssize); + printf("writing dmap to %x %d %x %d dmap to %x %d %x %d\n", + cap-1, cap-1, (cap-1)*ssize, (cap-1)*ssize, + daddr, daddr, daddr*ssize, daddr*ssize); + + /* 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); int type = GET_TYPE(uptr->flags); - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = get_dev(uptr); t_stat r; -// uint16 tsize; /* track size in bytes */ - uint16 ssize; /* sector size in bytes */ + uint32 ssize; /* sector size in bytes */ 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; + uint8 buff[1024]; + /* see if valid disk entry */ if (disk_type[type].name == 0) { /* does the assigned disk have a name */ detach_unit(uptr); /* no, reject */ return SCPE_FMT; /* error */ } + /* have simulator attach the file to the unit */ + 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) { @@ -1013,31 +1664,61 @@ t_stat disk_attach(UNIT *uptr, CONST char *file) } uptr->DDATA = (void *)data; /* save pointer to structure in DDATA */ - /* track size in bytes is sectors/track times words/sector time 4 bytse/word */ -// tsize = disk_type[type].spt * disk_type[type].ssiz * 4; /* get track size in bytes */ - uptr->capac = disk_type[type].taus * disk_type[type].spau; - /* disk capacity in sectors */ - ssize = disk_type[type].ssiz * 4; /* disk sector size in bytes */ - uptr->capac *= ssize; /* disk capacity in bytes */ + uptr->capac = CAP(type); /* disk capacity in sectors */ + ssize = SSB(type); /* get sector size in bytes */ - sim_debug(DEBUG_CMD, dptr, "Disk taus %d spau %d ssiz %d cap %d\n", - disk_type[type].taus, disk_type[type].spau, disk_type[type].ssiz * 4, - uptr->capac); /* disk capacity */ + sim_debug(DEBUG_CMD, dptr, "Disk %s cyl %d hds %d sec %d ssiz %d capacity %d\n", + disk_type[type].name, disk_type[type].cyl, disk_type[type].nhds, + disk_type[type].spt, ssize, uptr->capac); /* disk capacity */ if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ detach_unit(uptr); /* if no space, error */ return SCPE_FMT; /* error */ } + /* see if there is any data on sector zero of disk, if not format it */ + if ((r = sim_fread(buff, sizeof(uint8), ssize, uptr->fileref) != ssize)) { + sim_debug(DEBUG_CMD, dptr, "Disk format fread ret = %04x\n", r); + goto fmt; + } + + if ((buff[0] | buff[1] | buff[2] | buff[3]) == 0) { + sim_debug(DEBUG_CMD, dptr, + "Disk format buf0 %02x buf1 %02x buf2 %02x buf3 %02x\n", + buff[0], buff[1], buff[2], buff[3]); +fmt: + /* format the drive */ + if (disk_format(uptr)) { + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ + } + } + + /* there is data on sector 0, so already formatted */ + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + detach_unit(uptr); /* detach if error */ + return SCPE_FMT; /* error */ + } + + /* start out at sector 0 */ + data->cyl = 0; /* current cylinder position */ data->tpos = 0; /* current track position */ data->spos = 0; /* current sector position */ + sim_debug(DEBUG_CMD, dptr, + "Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\n", + disk_type[type].name, CYL(type), HDS(type), SPT(type), SPC(type), + CAP(type), CAPB(type)); + + sim_debug(DEBUG_CMD, dptr, "File %s attached to %s\r\n", + file, disk_type[type].name); + set_devattn(addr, SNS_DEVEND); return SCPE_OK; } /* detach a disk device */ -t_stat disk_detach(UNIT * uptr) { +t_stat disk_detach(UNIT *uptr) { struct ddata_t *data = (struct ddata_t *)uptr->DDATA; if (data != 0) { @@ -1049,40 +1730,44 @@ t_stat disk_detach(UNIT * uptr) { } /* boot from the specified disk unit */ -t_stat disk_boot(int32 unit_num, DEVICE * dptr) { +t_stat disk_boot(int32 unit_num, DEVICE *dptr) { UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */ - sim_debug(DEBUG_CMD, &dda_dev, "Disk Boot dev/unit %x\n", GET_UADDR(uptr->CMD)); + sim_debug(DEBUG_CMD, dptr, "Disk Boot dev/unit %x\n", GET_UADDR(uptr->CMD)); SPAD[0xf4] = GET_UADDR(uptr->CMD); /* put boot device chan/sa into spad */ 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 */ } /* Disk option setting commands */ -t_stat disk_set_type(UNIT * uptr, int32 val, CONST char *cptr, void *desc) +/* set the disk type attached to unit */ +t_stat disk_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { int i; - if (cptr == NULL) - return SCPE_ARG; - if (uptr == NULL) - return SCPE_IERR; - if (uptr->flags & UNIT_ATT) - return SCPE_ALATT; + if (cptr == NULL) /* any disk name input? */ + return SCPE_ARG; /* arg error */ + if (uptr == NULL) /* valid unit? */ + 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) { - uptr->flags &= ~UNIT_TYPE; - uptr->flags |= SET_TYPE(i); - uptr->capac = disk_type[i].taus * disk_type[i].spau; + 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 = CAP(i); return SCPE_OK; } } return SCPE_ARG; } -t_stat disk_get_type(FILE * st, UNIT * uptr, int32 v, CONST void *desc) +t_stat disk_get_type(FILE *st, UNIT *uptr, int32 v, CONST void *desc) { if (uptr == NULL) return SCPE_IERR; @@ -1092,8 +1777,7 @@ t_stat disk_get_type(FILE * st, UNIT * uptr, int32 v, CONST void *desc) } /* help information for disk */ -t_stat disk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, - const char *cptr) +t_stat disk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { int i; fprintf (st, "SEL 2314 Disk Processor II\r\n"); @@ -1107,13 +1791,13 @@ t_stat disk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, } fprintf (st, ".\nEach drive has the following storage capacity:\r\n"); for (i = 0; disk_type[i].name != 0; i++) { - /* disk capacity in sectors */ - int32 capac = disk_type[i].taus * disk_type[i].spau; - int32 ssize = disk_type[i].ssiz * 4; /* disk sector size in bytes */ - int32 size = capac * ssize; /* disk capacity in bytes */ - size /= 1024; /* make KB */ - size = (10 * size) / 1024; /* size in MB * 10 */ - fprintf(st, " %-8s %4d.%1d MB\r\n", disk_type[i].name, size/10, size%10); +// 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 */ + fprintf(st, " %-8s %4d.%1d MB cyl %3d hds %3d sec %3d blk %3d\r\n", + disk_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_hsdp.c b/SEL32/sel32_hsdp.c index 1d2da32..0324b67 100644 --- a/SEL32/sel32_hsdp.c +++ b/SEL32/sel32_hsdp.c @@ -1,6 +1,6 @@ /* sel32_hsdp.c: SEL-32 8064 High Speed Disk Processor - 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 @@ -23,25 +23,50 @@ #include "sel32_defs.h" -extern t_stat set_dev_addr(UNIT * uptr, int32 val, CONST char *cptr, void *desc); -extern t_stat show_dev_addr(FILE * st, UNIT * uptr, int32 v, CONST void *desc); -extern void chan_end(uint16 chan, uint8 flags); -extern int chan_read_byte(uint16 chsa, uint8 *data); -extern int chan_write_byte(uint16 chsa, uint8 *data); -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 t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +extern t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc); +extern void chan_end(uint16 chan, uint8 flags); +extern int chan_read_byte(uint16 chsa, uint8 *data); +extern int chan_write_byte(uint16 chsa, uint8 *data); +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 uint32 M[]; /* our memory */ -extern uint32 SPAD[]; /* cpu SPAD memory */ +extern uint32 M[]; /* our memory */ +extern uint32 SPAD[]; /* cpu SPAD memory */ #ifdef NUM_DEVS_HSDP -#define UNIT_V_TYPE (UNIT_V_UF + 0) -#define UNIT_TYPE (0xf << UNIT_V_TYPE) -#define GET_TYPE(x) ((UNIT_TYPE & (x)) >> UNIT_V_TYPE) -#define SET_TYPE(x) (UNIT_TYPE & ((x) << UNIT_V_TYPE)) -#define UNIT_HSDP UNIT_ATTABLE | UNIT_IDLE +#define UNIT_HSDP 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) (hsdp_type[type].spt) +/* get sectors per cylinderfor specified type */ +#define SPC(type) (hsdp_type[type].spt*hsdp_type[type].nhds) +/* get number of cylinders for specified type */ +#define CYL(type) (hsdp_type[type].cyl) +/* get number of heads for specified type */ +#define HDS(type) (hsdp_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) (hsdp_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 */ /* @@ -173,58 +198,58 @@ Byte 1 bits 7-15 /* 8 words of retry counters (1/channel) */ /* 22 words reserved */ -#define CMD u3 +#define CMD u3 /* u3 */ /* in u3 is device command code and status */ -#define DSK_CMDMSK 0x00ff /* Command being run */ -#define DSK_STAR 0x0100 /* STAR value in u4 */ -#define DSK_NU2 0x0200 /* */ -#define DSK_READDONE 0x0400 /* Read finished, end channel */ -#define DSK_ENDDSK 0x0800 /* Sensed end of disk */ -#define DSK_SEEKING 0x1000 /* Disk is currently seeking */ -#define DSK_READING 0x2000 /* Disk is reading data */ -#define DSK_WRITING 0x4000 /* Disk is writing data */ -#define DSK_BUSY 0x8000 /* Disk is busy */ +#define DSK_CMDMSK 0x00ff /* Command being run */ +#define DSK_STAR 0x0100 /* STAR value in u4 */ +#define DSK_NU2 0x0200 /* */ +#define DSK_READDONE 0x0400 /* Read finished, end channel */ +#define DSK_ENDDSK 0x0800 /* Sensed end of disk */ +#define DSK_SEEKING 0x1000 /* Disk is currently seeking */ +#define DSK_READING 0x2000 /* Disk is reading data */ +#define DSK_WRITING 0x4000 /* Disk is writing data */ +#define DSK_BUSY 0x8000 /* Disk is busy */ /* commands */ -#define DSK_INCH 0x00 /* Initialize channel */ -#define DSK_WD 0x01 /* Write data */ -#define DSK_RD 0x02 /* Read data */ -#define DSK_NOP 0x03 /* No operation */ -#define DSK_SNS 0x04 /* Sense */ -#define DSK_SKC 0x07 /* Seek cylinder, track, sector */ -#define DSK_TIC 0x08 /* Transfer in channel */ -#define DSK_FMT 0x0B /* Format track */ -#define DSK_RE 0x12 /* Read express bus with ECC */ -//#define DSK_LPL 0x13 /* Lock protected label */ -#define DSK_LMR 0x1F /* Load mode register */ -#define DSK_RENO 0x22 /* Read express bus with no ECC */ -#define DSK_RES 0x23 /* Reserve */ -#define DSK_WSL 0x31 /* Write sector label */ -#define DSK_RSL 0x32 /* Read sector label */ -#define DSK_REL 0x33 /* Release */ -#define DSK_XEZ 0x37 /* Rezero */ -#define DSK_WTF 0x41 /* Write track format */ -#define DSK_RVL 0x42 /* Read vendor label */ -#define DSK_POR 0x43 /* Priority Override */ -#define DSK_IHA 0x47 /* Increment head address */ -//#define DSK_SRM 0x4F /* Set reserve track mode */ -#define DSK_WTL 0x51 /* Write track label */ -#define DSK_RTL 0x52 /* Read track label */ -//#define DSK_XRM 0x5F /* Reset reserve track mode */ -#define DSK_RAP 0xA2 /* Read angular position */ -//#define DSK_TESS 0xAB /* Test STAR (subchannel target address register) */ -#define DSK_REC 0xB2 /* Read ECC */ -#define DSK_FINC 0xC0 /* Fake while in srv Initialize channel */ -#define DSK_INC 0xFF /* Initialize Controller */ +#define DSK_INCH 0x00 /* Initialize channel */ +#define DSK_WD 0x01 /* Write data */ +#define DSK_RD 0x02 /* Read data */ +#define DSK_NOP 0x03 /* No operation */ +#define DSK_SNS 0x04 /* Sense */ +#define DSK_SCK 0x07 /* Seek cylinder, track, sector */ +#define DSK_TIC 0x08 /* Transfer in channel */ +#define DSK_FMT 0x0B /* Format track */ +#define DSK_RE 0x12 /* Read express bus with ECC */ +//#define DSK_LPL 0x13 /* Lock protected label */ +#define DSK_LMR 0x1F /* Load mode register */ +#define DSK_RENO 0x22 /* Read express bus with no ECC */ +#define DSK_RES 0x23 /* Reserve */ +#define DSK_WSL 0x31 /* Write sector label */ +#define DSK_RSL 0x32 /* Read sector label */ +#define DSK_REL 0x33 /* Release */ +#define DSK_XEZ 0x37 /* Rezero */ +#define DSK_WTF 0x41 /* Write track format */ +#define DSK_RVL 0x42 /* Read vendor label */ +#define DSK_POR 0x43 /* Priority Override */ +#define DSK_IHA 0x47 /* Increment head address */ +//#define DSK_SRM 0x4F /* Set reserve track mode */ +#define DSK_WTL 0x51 /* Write track label */ +#define DSK_RTL 0x52 /* Read track label */ +//#define DSK_XRM 0x5F /* Reset reserve track mode */ +#define DSK_RAP 0xA2 /* Read angular position */ +//#define DSK_TESS 0xAB /* Test STAR (subchannel target address register) */ +#define DSK_REC 0xB2 /* Read ECC */ +#define DSK_FINC 0xC0 /* Fake while in srv Initialize channel */ +#define DSK_INC 0xFF /* Initialize Controller */ -#define STAR u4 +#define STAR u4 /* u4 - sector target address register (STAR) */ /* Holds the current cylinder, head(track), sector */ -#define DISK_CYL 0xFFFF0000 /* cylinder mask */ -#define DISK_TRACK 0x0000FF00 /* track mask */ -#define DISK_SECTOR 0x000000ff /* sector mask */ +#define DISK_CYL 0xFFFF0000 /* cylinder mask */ +#define DISK_TRACK 0x0000FF00 /* track mask */ +#define DISK_SECTOR 0x000000ff /* sector mask */ -#define SNS u5 +#define SNS u5 /* u5 */ /* Sense byte 0 - mode register */ #define SNS_DROFF 0x80000000 /* Drive Carriage will be offset */ @@ -266,7 +291,7 @@ Byte 1 bits 7-15 #define SNS_RTAE 0x02 /* Reserve track access error */ #define SNS_UESS 0x01 /* Uncorrectable ECC error */ -#define ATTR u6 +#define ATTR u6 /* u6 holds drive attribute entry */ /* provided by inch command for controller */ /* @@ -276,15 +301,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) + mini-module) */ -#define DDATA up7 +#define DDATA up7 /* Pointer held in up7 */ /* sects/cylinder = sects/track * numhds */ /* allocated during attach command for each unit defined */ @@ -299,117 +324,37 @@ struct ddata_t struct hsdp_t { const char *name; /* Device ID Name */ - uint32 taus; /* total allocation units */ - uint16 bms; /* bit map size */ uint16 nhds; /* Number of heads */ uint16 ssiz; /* sector size in words */ - uint16 spt; /* # sectors per track(cylinder) */ - uint8 spau; /* # sectors per allocation unit */ - uint8 spb; /* # sectors per block (256 WDS)*/ - uint32 cyl; /* Number of cylinders */ - uint32 geom; /* disk star geometry cyl(16) hsd(8) sec(8) */ + uint16 spt; /* # sectors per track(head) */ + uint16 ucyl; /* Number of cylinders used */ + uint16 cyl; /* Number of cylinders on disk */ uint8 type; /* Device type code */ + /* 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[] = { - /* Class F Disc Devices */ /*XX CYL SIZE */ - {"MH040", 20000, 625, 5, 256, 16, 2, 1, 400, 0, 0x40}, /*0 411 40 M */ - {"MH080", 40000, 1250, 5, 256, 16, 2, 1, 800, 0, 0x40}, /*1 823 80 M 9342 */ - {"MH160", 80000, 1250, 10, 256, 16, 4, 1, 1600, 0, 0x40}, /*2 823 160 M 8148 */ -// {"MH300", 76000, 2375, 19, 256, 16, 4, 1, 800, 0, 0x40}, /*3 823 300 M 9346 */ -// {"MH300", 80000, 2500, 10, 256, 35, 4, 1, 800, 0, 0x40}, /*3 823 300 M 8887 */ -// {"MH300", 80000, 2500, 10, 256, 34, 4, 1, 820, 0, 0x40}, /*3 823 300 M 8887 */ - {"8887", 80000, 2500, 10, 256, 34, 4, 1, 844, 0, 0x40}, /*3 823 300 M 8887 */ - {"MH300", 80000, 2500, 10, 256, 34, 4, 1, 844, 0, 0x40}, /*3 823 300 M 8887 */ - {"MH340", 76000, 2375, 24, 256, 16, 4, 1, 800, 0, 0x40}, /*4 711 340 M 8858 */ - {"FH005", 5120, 184, 4, 256, 16, 1, 1, 64, 0, 0x80}, /*5 64 5 M */ - {"CD032", 8000, 250, 1, 256, 16, 2, 1, 800, 0, 0x60}, /*6 823 32 M */ - {"CD032", 8000, 250, 1, 256, 16, 2, 1, 800, 0, 0x60}, /*7 823 32 M */ - {"CD064", 8000, 250, 1, 256, 16, 2, 1, 800, 0, 0x60}, /*8 823 64 M */ - {"CD064", 24000, 750, 3, 256, 16, 2, 1, 800, 0, 0x60}, /*9 823 64 M */ - {"CD096", 8000, 250, 1, 256, 16, 2, 1, 800, 0, 0x60}, /*10 823 96 M */ - {"CD096", 40000, 1250, 5, 256, 16, 2, 1, 800, 0, 0x60}, /*11 823 96 M */ - {"MH600", 80000, 2500, 40, 256, 16, 8, 1, 800, 0, 0x40}, /*12 843 600 M */ - {"FM600", 80000, 2500, 40, 256, 16, 8, 1, 800, 0, 0x40}, /*13 843 600 M */ - {"FM600", 1600, 50, 40, 256, 16, 1, 1, 2, 0, 0x80}, /*14 10 600 M */ + /* Class F Disc Devices */ + /* For MPX */ + {"MH040", 5, 192, 20, 400, 411, 0x40}, /* 0 411 40M XXXX */ + {"MH080", 5, 192, 20, 800, 823, 0x40}, /* 1 823 80M 8138 */ + {"MH160", 10, 192, 20, 800, 823, 0x40}, /* 2 823 160M 8148 */ + {"MH300", 19, 192, 20, 800, 823, 0x40}, /* 3 823 300M 9346 */ + {"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 */ + {"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 */ {NULL, 0} }; -#if 0 -***************************************************************** -* DEVICE ID TABLE -***************************************************************** - SPACE - BOUND 1W -DID.TBL EQU $ MPX1.X -* -*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 (MPX 1.X) - 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'DF05', 1, 1, 20, 192, 4, 184, 5120, C'FH005' - DID C'DF06', 1, 2, 20, 192, 1, 250, 8000, C'CD032' - DID C'DF06', 1, 2, 20, 192, 1, 250, 8000, C'CD032' - DID C'DF07', 1, 2, 20, 192, 1, 250, 8000, C'CD064' - 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'DF0A', 1, 1, 20, 192, 40, 50, 1600, C'FM600' -* - BOUND 1W -DID.TBL EQU $ MPX3.X -* -*DEVICE ID NAME.................................................. -*TOTAL SECTORS ......................................... : -*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 MPX3.X - DID C'DF01', 3, 1, 26, 64, 2, , 4004, C'FL001 ' - DID C'DF02', 1, 2, 20, 192, 5, 642, 41100, C'MH040 ' - DID C'DF03', 1, 2, 20, 192, 5, 1286, 82300, C'MH080 ' - DID C'DF04', 1, 4, 20, 192, 19, 2444,312740, C'MH300 ' - DID C'DF05', 1, 1, 20, 192, 4, 160, 5120, C'FH005 ' - DID C'DF06', 1, 2, 20, 192, 1, 258, 16460, C'CD032 ' - DID C'DF06', 1, 2, 20, 192, 1, 258, 16460, C'CD032 ' - DID C'DF07', 1, 2, 20, 192, 1, 258, 16460, C'CD064 ' - DID C'DF07', 1, 2, 20, 192, 3, 772, 49380, C'CD064 ' - DID C'DF08', 1, 2, 20, 192, 1, 258, 16460, C'CD096 ' - DID C'DF08', 1, 2, 20, 192, 5, 1286, 82300, C'CD096 ' - DID C'DF09', 1,10, 20, 192, 40, 2635,674400, C'MH600 ' - DID C'DF0A', 1,10, 20, 192, 40, 2635,674400, C'FM600 ' - DID C'DF0A', 1, 1, 20, 192, 96, 60, 1920, C'FM600 ' - DID C'DF0B', 1, 4, 20, 192, 10, 1286,164600, C'MH160 ' - DID C'DF0C', 1, 2, 20, 192, 5, 1286, 00, C'ANY ' - DID C'DF0D', 1, 4, 20, 192, 24, 2670,341280, C'MH340 ' -* -#endif - uint8 hsdp_preio(UNIT *uptr, uint16 chan) ; uint8 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; uint8 hsdp_haltio(uint16 addr); @@ -432,20 +377,20 @@ MTAB hsdp_mod[] = { &hsdp_set_type, &hsdp_get_type, NULL, "Type of disk"}, {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, &show_dev_addr, NULL, "Device channel address"}, - {0} + {0}, }; UNIT dpa_unit[] = { /* SET_TYPE(3) DM300 */ -/* SET_TYPE(4) 8887 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0x800)}, /* 0 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0x802)}, /* 1 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0x804)}, /* 2 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0x806)}, /* 3 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0x808)}, /* 4 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0x80A)}, /* 5 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0x80C)}, /* 6 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0x80E)}, /* 7 */ +/* SET_TYPE(8) 8887 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(8), 0), 0, UNIT_ADDR(0x800)}, /* 0 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(8), 0), 0, UNIT_ADDR(0x802)}, /* 1 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(8), 0), 0, UNIT_ADDR(0x804)}, /* 2 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(8), 0), 0, UNIT_ADDR(0x806)}, /* 3 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(8), 0), 0, UNIT_ADDR(0x808)}, /* 4 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(8), 0), 0, UNIT_ADDR(0x80A)}, /* 5 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(8), 0), 0, UNIT_ADDR(0x80C)}, /* 6 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(8), 0), 0, UNIT_ADDR(0x80E)}, /* 7 */ }; DIB dpa_dib = { @@ -458,7 +403,7 @@ DIB dpa_dib = { dpa_unit, /* Pointer to units structure */ dpa_chp, /* Pointer to chan_prg structure */ NUM_UNITS_HSDP, /* number of units defined */ - 0x0E, /* 16 devices - device mask */ + 0x0E, /* 8 devices - device mask */ 0x0800, /* parent channel address */ 0, /* fifo input index */ 0, /* fifo output index */ @@ -469,7 +414,7 @@ DEVICE dpa_dev = { "DPA", dpa_unit, NULL, hsdp_mod, NUM_UNITS_HSDP, 16, 24, 4, 16, 32, NULL, NULL, &hsdp_reset, &hsdp_boot, &hsdp_attach, &hsdp_detach, - &dpa_dib, DEV_DISABLE|DEV_DEBUG, 0, dev_debug, + &dpa_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, NULL, NULL, &hsdp_help, NULL, NULL, &hsdp_description }; @@ -479,14 +424,14 @@ CHANP dpb_chp[NUM_UNITS_HSDP] = {0}; UNIT dpb_unit[] = { /* SET_TYPE(3) DM300 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC00)}, /* 0 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC02)}, /* 1 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC04)}, /* 2 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC06)}, /* 3 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC08)}, /* 4 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC0A)}, /* 5 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC0C)}, /* 6 */ - {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC0E)}, /* 7 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC00)}, /* 0 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC02)}, /* 1 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC04)}, /* 2 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC06)}, /* 3 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC08)}, /* 4 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC0A)}, /* 5 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC0C)}, /* 6 */ + {UDATA(&hsdp_srv, UNIT_HSDP|SET_TYPE(3), 0), 0, UNIT_ADDR(0xC0E)}, /* 7 */ }; @@ -511,35 +456,48 @@ DEVICE dpb_dev = { "DPB", dpb_unit, NULL, hsdp_mod, NUM_UNITS_HSDP, 16, 24, 4, 16, 32, NULL, NULL, &hsdp_reset, &hsdp_boot, &hsdp_attach, &hsdp_detach, - &dpb_dib, DEV_DISABLE|DEV_DEBUG, 0, dev_debug, + &dpb_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, NULL, NULL, &hsdp_help, NULL, NULL, &hsdp_description }; #endif +/* convert sector disk address to star values (c,h,s) */ +uint32 hsdpsec2star(uint32 daddr, int type) +{ + int32 sec = daddr % hsdp_type[type].spt; /* get sector value */ + int32 spc = hsdp_type[type].nhds * hsdp_type[type].spt; /* sec per cyl */ + int32 cyl = daddr / spc; /* cylinders */ + int32 hds = (daddr % spc) / hsdp_type[type].spt; /* heads */ + + /* now return the star value */ + return (CHS2STAR(cyl,hds,sec)); /* return STAR */ +} + /* start a disk operation */ uint8 hsdp_preio(UNIT *uptr, uint16 chan) { - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = get_dev(uptr); uint16 addr = GET_UADDR(uptr->CMD); int unit = (uptr - dptr->units); -//TRY if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */ - if (uptr->CMD & DSK_BUSY) { /* just return if busy */ + sim_debug(DEBUG_CMD, dptr, "hsdp_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, "hsdp_preio unit=%02x chsa=%04x OK\n", unit, addr); + sim_debug(DEBUG_CMD, dptr, "hsdp_preio unit %02x chsa %04x OK\n", unit, addr); return 0; /* good to go */ } uint8 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uint16 addr = GET_UADDR(uptr->CMD); - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); uint8 ch; - sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd addr %04x unit %02x cmd %02x CMD %08x\n", + sim_debug(DEBUG_CMD, dptr, + "hsdp_startcmd addr %04x unit %02x cmd %02x CMD %08x\n", addr, unit, cmd, uptr->CMD); if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd unit %02x not attached\n", unit); @@ -550,7 +508,7 @@ uint8 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) if ((uptr->CMD & DSK_CMDMSK) != 0) { sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd unit %02x busy\n", unit); - uptr->CMD |= DSK_BUSY; /* Flag we we are busy */ + uptr->CMD |= DSK_BUSY; /* Flag we are busy */ return SNS_BSY; } if ((uptr->CMD & 0xff00) != 0) { /* if any status info, we are busy */ @@ -599,8 +557,8 @@ uint8 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) 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 */ + /* 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; @@ -628,24 +586,25 @@ uint8 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) /* Unit is online, so process a command */ switch (cmd) { - case DSK_INCH: /* INCH 0x00 */ + case DSK_INCH: /* INCH 0x0 */ { uint32 mema; /* memory address */ uint32 i; UNIT *up = dptr->units; /* first unit for this device */ - sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd starting inch cmd addr %04x STAR %08x\n", - addr, uptr->STAR); + 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 STAR and us9 left non-zero */ + /* 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->STAR; /* get memory address of buffer */ - uptr->STAR = M[mema>>2]; /* get status buffer address for XIO return status */ + 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 stat buf addr %08x mema %08x units %02x\n", - addr, uptr->STAR, mema, dptr->numunits); + "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 */ @@ -659,47 +618,70 @@ uint8 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) 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->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); -// uptr->CMD |= DSK_CMDMSK; /* use 0xff for inch, just need int */ uptr->CMD |= DSK_FINC; /* use 0xc0 for inch, just need int */ sim_activate(uptr, 20); /* start things off */ return 0; + break; } - case DSK_SKC: /* Seek command 0x07 */ + 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 */ +// 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, - "hsdp_startcmd starting disk seek r/w cmd %02x addr %04x\n", cmd, addr); + "hsdp_startcmd starting disk seek r/w cmd %02x addr %04x\n", + cmd, addr); sim_activate(uptr, 20); /* start things off */ return 0; + break; case DSK_NOP: /* NOP 0x03 */ uptr->CMD |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ return 0; + break; case DSK_SNS: /* Sense 0x04 */ uptr->CMD |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ break; + case DSK_WSL: /* WSL 0x31 */ + uptr->CMD |= cmd; /* save cmd */ + sim_activate(uptr, 20); /* start things off */ + return 0; + break; + + case DSK_RSL: /* RSL 0x32 */ + uptr->CMD |= cmd; /* save cmd */ + sim_activate(uptr, 20); /* start things off */ + return 0; + break; + + case DSK_WTL: /* WTL 0x51 */ + uptr->CMD |= cmd; /* save cmd */ + sim_activate(uptr, 20); /* start things off */ + return 0; + break; + case DSK_RTL: /* RTL 0x52 */ uptr->CMD |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ return 0; + break; } sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd done with hsdp_startcmd %02x addr %04x SNS %08x\n", - cmd, addr, uptr->SNS); + cmd, addr, 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 */ @@ -707,30 +689,31 @@ uint8 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) } /* Handle processing of disk requests. */ -t_stat hsdp_srv(UNIT * uptr) +t_stat hsdp_srv(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->CMD); - DEVICE *dptr = find_dev_from_unit(uptr); + 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); int cmd = uptr->CMD & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); +// uint32 trk, cyl, sec; uint32 trk, cyl; int unit = (uptr - dptr->units); int len; int i; uint8 ch; - int tsize = hsdp_type[type].spt * hsdp_type[type].ssiz * 4; /* get track size in bytes */ - int ssize = hsdp_type[type].ssiz * 4; /* disk sector size in bytes */ - int tstart; + 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_DETAIL, dptr, - "hsdp_srv entry unit %02x cmd %02x chsa %04x chan %04x count %04x\n", - unit, cmd, chsa, chsa>>8, chp->ccw_count); + 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); if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ uptr->SNS |= SNS_INTVENT; /* unit intervention required */ @@ -738,28 +721,79 @@ t_stat hsdp_srv(UNIT * uptr) return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; } - sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd=%02x chsa %04x count %04x\n", - cmd, chsa, chp->ccw_count); + sim_debug(DEBUG_CMD, dptr, + "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_CMDMSK: /* use 0xff for inch, just need int */ case DSK_FINC: /* use 0xc0 for inch, just need int */ uptr->CMD &= ~(0xffff); /* remove old cmd */ - sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd=%02x chsa %04x count %04x completed\n", - cmd, chsa, chp->ccw_count); + sim_debug(DEBUG_CMD, dptr, "disk_srv cmd INCH chsa %04x count %04x completed\n", + chsa, chp->ccw_count); #ifdef FIX4MPX chan_end(chsa, SNS_CHNEND); /* return just channel end OK */ #else -//TRY chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ - chan_end(chsa, SNS_CHNEND); /* return OK for UTX */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ #endif break; - case DSK_NOP: /* NOP 0x03 */ + case DSK_WSL: /* WSL 0x31 make into NOP */ uptr->CMD &= ~(0xffff); /* remove old cmd */ - sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd NOP chsa %04x count %04x completed\n", + sim_debug(DEBUG_CMD, dptr, + "hsdp_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 */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + 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]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case DSK_WTL: /* WTL 0x51 make into NOP */ + uptr->CMD &= ~(0xffff); /* remove old cmd */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv cmd WTL chsa %04x count %04x completed\n", + chsa, chp->ccw_count); + + sim_debug(DEBUG_DETAIL, dptr, "Track 0 label"); + /* now read track label data */ + for (i = 0; i < 30; i++) { + if (chan_read_byte(chsa, &buf[i])) { + /* we have read error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (i == 16) + sim_debug(DEBUG_DETAIL, dptr, "\nTrack 0 label"); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case DSK_NOP: /* NOP 0x03 */ + uptr->CMD &= ~(0xffff); /* remove old cmd */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_srv cmd NOP chsa %04x count %04x completed\n", chsa, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; @@ -830,73 +864,94 @@ t_stat hsdp_srv(UNIT * uptr) /* TODO add drive status bits here */ if ((test_write_byte_end(chsa)) == 0) { /* bytes 12 & 13 contain drive related status */ - ch = 0; /* zero for now */ + ch = 0; /* zero for now */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv dsr unit=%02x 1 %02x\n", unit, ch); chan_write_byte(chsa, &ch); + + ch = 030; /* drive on cyl and ready for now */ sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv dsr unit=%02x 2 %02x\n", unit, ch); chan_write_byte(chsa, &ch); } - uptr->SNS &= 0xff000000; /* clear status bytes, but leave mode data */ +//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 */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case DSK_SKC: /* Seek cylinder, track, sector 0x07 */ + 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 ((int32)(uptr->STAR >> 16) == (int32)data->cyl) { /* 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); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ - set_devattn(chsa, SNS_DEVEND); /* start the operation */ - sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv seek end unit=%02x %02x %04x\n", +// 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); + chan_end(chsa, SNS_DEVEND|SNS_CHNEND); sim_activate(uptr, 20); break; } else { +#ifndef TRYTHIS + data->cyl = ((uptr->STAR >> 16)&0xffff); + sim_activate(uptr, 10); + break; +#else /* Compute delay based of difference. */ /* Set next state = index */ - i = (uptr->STAR >> 16) - data->cyl; - sim_debug(DEBUG_CMD, dptr, "hsdp_srv seek unit=%02x %02x %04x\n", unit, - uptr->STAR >> 16, i); + 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 > 50) { - data->cyl += 50; /* seek 50 cyl */ + if (i > 500) { + data->cyl += 500; /* seek 500 cyl */ sim_activate(uptr, 800); } else - if (i > 20) { - data->cyl += 20; /* seek 20 cyl */ + if (i > 200) { + data->cyl += 200; /* seek 200 cyl */ sim_activate(uptr, 400); - } else { - data->cyl++; /* Seek 1 cyl */ + } 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 < -50) { - data->cyl -= 50; /* seek 50 cyl */ + if (i < -500) { + data->cyl -= 500; /* seek 500 cyl */ sim_activate(uptr, 800); } else - if (i < -20) { - data->cyl -= 20; /* seek 20 cyl */ + if (i < -200) { + data->cyl -= 200; /* seek 200 cyl */ sim_activate(uptr, 400); - } else { - data->cyl--; /* seek 1 cyl */ + } 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); + unit, uptr->STAR >> 16, data->cyl); +#ifdef OLD_WAY sim_activate(uptr, 2); +#else +/*BAD?*/ sim_activate(uptr, 10); +#endif break; } } @@ -907,16 +962,21 @@ t_stat hsdp_srv(UNIT * uptr) buf[1] = (data->cyl) & 0xff; buf[2] = (data->tpos) & 0xff; buf[3] = (data->spos) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv STAR unit=%02x star %02x %02x %02x %02x\n", + 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]); + /* Read in up to 4 character seek code */ for (i = 0; i < 4; i++) { if (chan_read_byte(chsa, &buf[i])) { if (i == 0) { + sim_debug(DEBUG_DETAIL, dptr, + "hsdp_srv seek error unit=%02x star %02x %02x %02x %02x\n", + unit, buf[0], buf[1], buf[2], buf[3]); /* we have error, bail out */ uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; break; } /* just read the next byte */ @@ -929,22 +989,24 @@ t_stat hsdp_srv(UNIT * uptr) } /* else the cyl, trk, and sect are ready to update */ rezero: - sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv seek unit=%02x star %02x %02x %02x %02x\n", + 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 */ trk = buf[2]; /* get the track */ sim_debug(DEBUG_DETAIL, dptr, - "hsdp_srv SEEK cyl %04x trk %02x sec %02x unit=%02x\n", cyl&0xffff, trk, buf[3], unit); + "hsdp_srv 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 || + if (cyl >= hsdp_type[type].cyl || trk >= hsdp_type[type].nhds || - buf[3] > hsdp_type[type].spt) { + 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); + "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 */ @@ -953,14 +1015,14 @@ rezero: break; } - uptr->CMD |= DSK_STAR; /* show we have seek STAR in STAR */ +// uptr->CMD |= DSK_STAR; /* show we have seek STAR in STAR */ /* calc the sector address of data */ /* calculate file position in bytes of requested sector */ - // FIXME for variable sector size - tstart = (cyl * hsdp_type[type].nhds * tsize) + (trk * tsize) + (buf[3] * 1024); + 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 */ - sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv seek start %04x cyl %04x trk %02x sec %02x\n", + sim_debug(DEBUG_DETAIL, dptr, + "hsdp_srv seek start %04x cyl %04x trk %02x sec %02x\n", tstart, cyl, trk, buf[3]); 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); @@ -968,30 +1030,31 @@ rezero: /* Check if already on correct cylinder */ if (cyl != data->cyl) { - /* No, Do seek */ + /* Do seek */ 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", + 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 up off */ - chan_end(chsa, SNS_CHNEND); + sim_activate(uptr, 20); /* start us off */ +//WHAT? chan_end(chsa, SNS_CHNEND); } else { /* Yes, we done */ sim_debug(DEBUG_DETAIL, dptr, - "hsdp_srv calc sect addr seek start %04x cyl %04x trk %02x sec %02x\n", + "hsdp_srv calc sect addr seek end %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); +// sim_activate(uptr, 20); chan_end(chsa, SNS_DEVEND|SNS_CHNEND); } return SCPE_OK; - case DSK_XEZ: /* Rezero & Read IPL record */ + case DSK_XEZ: /* Rezero & Read IPL record */ sim_debug(DEBUG_CMD, dptr, "RD REZERO IPL unit=%02x seek 0\n", unit); /* Do a seek to 0 */ uptr->STAR = 0; /* set STAR to 0, 0, 0 */ uptr->CMD &= ~(0xffff); /* remove old cmd */ - uptr->CMD |= DSK_SKC; /* show as seek command */ + uptr->CMD |= DSK_SCK; /* show as seek command */ tstart = 0; /* byte offset is 0 */ /* Read in 1 dummy character for length to inhibit SLI posting */ if (chan_read_byte(chsa, &buf[0])) { @@ -1003,7 +1066,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: @@ -1016,13 +1079,15 @@ 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 */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case DSK_RD: /* Read Data */ + case DSK_RD: /* Read Data */ 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, @@ -1041,14 +1106,15 @@ rezero: } sim_debug(DEBUG_CMD, dptr, - "hsdp_srv after READ chsa %04x count %04x\n", chsa, chp->ccw_count); + "hsdp_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; icyl, data->tpos, data->spos); + "DISK Read %04x bytes leaving %04x from diskfile /%04x/%02x/%02x\n", + i, chp->ccw_count, data->cyl, data->tpos, data->spos); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); goto rddone; @@ -1056,8 +1122,8 @@ rezero: } sim_debug(DEBUG_CMD, dptr, - "DISK READ at sector end, read %04x bytes from disk @ cyl %04x hds %02x sec %02x\n", - ssize, data->cyl, data->tpos, data->spos); + "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)) { @@ -1068,8 +1134,8 @@ rezero: data->cyl++; /* cylinder position */ if (data->cyl >= (int)(hsdp_type[type].cyl)) { /* EOM reached, abort */ - sim_debug(DEBUG_DATA, dptr, - "DISK Read reached EOM for read from disk @ cyl %04x hds %02x sec %02x\n", + 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 */ @@ -1081,14 +1147,20 @@ rezero: /* 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 @ cyl %04x hds %02x sec %02x\n", + "DISK Read complete for read from disk @ /%04x/%02x/%02x\n", data->cyl, data->tpos, data->spos); 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 */ + break; } rddone: - sim_activate(uptr, 10); /* wait to read next sector */ - break; + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ } break; @@ -1129,7 +1201,7 @@ 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, data->cyl, data->tpos, data->spos); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; @@ -1155,45 +1227,235 @@ rddone: } } } -wrdone: - sim_activate(uptr, 10); + sim_activate(uptr, 10); /* keep writing */ break; +wrdone: + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ } break; - case DSK_RTL: /* RTL 0x52 */ - /* Read track zero to get disk geometry */ + 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 */ for (i = 0; i < 30; i++) buf[i] = 0; - i = 286895; /* umap sector address */ - sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd RTL STAR %08x Umap pointer %08x\n", - hsdp_type[type].geom, i); + + /* the dmap pointer is placed by the vendor or diag into the */ + /* track zero label in word 3 of the 30 byte label. */ + /* The disk address is the last track of the user area. The vendor */ + /* reserves the last cylinder, SEL diags reserve the next two, so the */ + /* addr is CYL-4/HDS-1/0 and is VDT. The UTX/MPX media table is on */ + /* previous track, so MDT = VDT-SPT is CYL-4/HDS-2/0 */ + /* The UTX flaw map is at 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 */ + /* simulate pointers here, set wd[3] in label to VDT */ + /* set buf data to current STAR values */ - buf[0] = (hsdp_type[type].cyl >> 8) & 0xff; - buf[1] = (hsdp_type[type].cyl) & 0xff; - buf[2] = hsdp_type[type].nhds & 0xff; - buf[3] = hsdp_type[type].spt & 0xff; - sim_debug(DEBUG_DETAIL, dptr, - "hsdp_srv RTL unit=%02x star %02x %02x %02x %02x\n", +// 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)); + +#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 */ + 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]); - /* the umap pointer is placed by prep program */ - /* simulate pointer here */ - i = 286895; /* umap sector address */ - buf[16] = (i >> 24) & 0xff; - buf[17] = (i >> 16) & 0xff; - buf[18] = (i >> 8) & 0xff; - buf[19] = (i) & 0xff; + 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 */ + 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 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 */ + /* store into sec 1 label */ + buf[12] = (tstart >> 24) & 0xff; /* UMAP pointer */ + buf[13] = (tstart >> 16) & 0xff; + buf[14] = (tstart >> 8) & 0xff; + buf[15] = (tstart) & 0xff; + /* the tech doc shows the cyl/trk/sec data is in the first 4 bytes */ /* of the track label, BUT it is really in the configuration data */ /* area are too. That is where UTX looks. Byte 27 is sectors/track */ /* and byte 28 is number of heads. Byte 25 is copy of byte 27. */ - buf[25] = hsdp_type[type].spt & 0xff; - buf[27] = hsdp_type[type].spt & 0xff; - buf[28] = hsdp_type[type].nhds & 0xff; + buf[25] = hsdp_type[type].spt & 0xff; /* sect per track 35 */ + /* UTX looks at bit 6 & 7 to determine if UDP or HSDP controller */ + /* The UDP/DPII controllers do not use these bits, so UTX keys */ + /* on these bits to determine type of controller. Bit 31 is set */ + /* for a HSDP and not set for the UDP/DPII. MPX has this bit cleared. */ + buf[26] = hsdp_type[type].type | 1; /* mode data is 0x41 */ + buf[27] = hsdp_type[type].spt & 0xff; /* sec per track 35 */ + buf[28] = hsdp_type[type].nhds & 0xff; /* num heads 10 */ + + sim_debug(DEBUG_DETAIL, dptr, "Sector 1 label"); + /* now write sector label data */ + for (i = 0; i < 30; i++) { + if (chan_write_byte(chsa, &buf[i])) { + /* we have write error, bail out */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (i == 16) + sim_debug(DEBUG_DETAIL, dptr, "\nSector 1 label"); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); + } + sim_debug(DEBUG_DETAIL, dptr, "\n"); + + /* command done */ + uptr->CMD &= ~(0xffff); /* remove old cmd */ + sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd RSL done chsa %04x count %04x completed\n", + chsa, chp->ccw_count); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ + break; + + case DSK_RTL: /* RTL 0x52 */ + /* 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 */ + + sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd RTL STAR %08x disk geom %08x\n", + uptr->STAR, 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[4] = 0x80; /* set lflg1 */ + + sim_debug(DEBUG_DETAIL, dptr, + "hsdp_srv RTL unit=%02x star %02x %02x %02x %02x\n", + unit, buf[0], buf[1], buf[2], buf[3]); + + /* the dmap pointer is placed by the vendor or diag into the */ + /* track zero label in word 3 of the 30 byte label. */ + /* The disk address is the last track of the user area. The vendor */ + /* reserves the last cylinder, SEL diags reserve the next two, so the */ + /* addr is CYL-4/HDS-1/0 and is VDT. The UTX/MPX media table is on */ + /* previous track, so MDT = VDT-SPT is CYL-4/HDS-2/0 */ + /* The UTX flaw map is at 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 */ + /* 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 */ + 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", + cyl-3, trk-1, 0, tstart, tstart); + sim_debug(DEBUG_CMD, dptr, + "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 */ + /* output last sector address of disk */ + buf[12] = (tstart >> 24) & 0xff; /* ldeallp DMAP pointer */ + buf[13] = (tstart >> 16) & 0xff; + buf[14] = (tstart >> 8) & 0xff; + buf[15] = (tstart) & 0xff; + } + +#ifdef NOTNOW + tstart -= SPT(type); /* calc utxfmap address */ + if (uptr->STAR == 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 */ + /* and byte 28 is number of heads. Byte 25 is copy of byte 27. */ + buf[25] = hsdp_type[type].spt & 0xff; /* sect per track 35 */ + buf[26] = hsdp_type[type].type | 1; /* sense data set for 1024 byte blk */ + buf[27] = hsdp_type[type].spt & 0xff; /* sec per track 35 */ + buf[28] = hsdp_type[type].nhds & 0xff; /* num heads 10 */ + + sim_debug(DEBUG_DETAIL, dptr, "Track 0 label"); /* now write track label data */ for (i = 0; i < 30; i++) { if (chan_write_byte(chsa, &buf[i])) { @@ -1202,7 +1464,11 @@ wrdone: chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } + if (i == 16) + sim_debug(DEBUG_DETAIL, dptr, "\nTrack 0 label"); + sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]); } + sim_debug(DEBUG_DETAIL, dptr, "\n"); /* command done */ uptr->CMD &= ~(0xffff); /* remove old cmd */ @@ -1212,7 +1478,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); @@ -1226,45 +1492,235 @@ wrdone: /* initialize the disk */ void hsdp_ini(UNIT *uptr, t_bool f) { - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = get_dev(uptr); int i = GET_TYPE(uptr->flags); - uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ - /* capacity is total allocation units time sectors per allocation unit */ + uptr->CMD &= ~0x7fff; /* clear out the flags but leave ch/sa */ + uptr->SNS = ((uptr->SNS & 0x00ffffff) | (hsdp_type[i].type << 24)); /* save mode value */ /* total sectors on disk */ - uptr->capac = hsdp_type[i].taus * hsdp_type[i].spau; + uptr->capac = CAP(i); /* size in sectors */ - sim_debug(DEBUG_EXP, dptr, "DPA init device %s on unit DPA%.1x cap %x\n", - dptr->name, GET_UADDR(uptr->CMD), uptr->capac); + sim_debug(DEBUG_EXP, &dda_dev, "DMA init device %s on unit DMA%.1x cap %x %d\n", + dptr->name, GET_UADDR(uptr->CMD), uptr->capac, uptr->capac); } -t_stat hsdp_reset(DEVICE * dptr) +t_stat hsdp_reset(DEVICE *dptr) { /* add reset code here */ return SCPE_OK; } +/* 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); + uint32 ssize = hsdp_type[type].ssiz * 4; /* disk sector size in bytes */ + 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 */ + 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 */ + int32 daddr = vaddr - SPT(type); + /* get sector address of utx flaw map sec 1 pointer */ + /* use this address for sec 1 label pointer */ + int32 uaddr = daddr - SPT(type); +#ifdef MAYBE + /* get sector address of utx flaw data (1 track long) */ + /* set trace data to zero */ + 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, +// 7,0x5258,0,0x4e5c,0x3e,0x43fbc,0,0xd32c, + 7,0x5258,0,0x4e5c,0x3e,0x43fbc,0,0xd32c, + 0x79,0x187cc,0x118,0x14410,0x23f,0,0,0, + 0,0x3821a2d6,0x4608c,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, + }; +#else + { +// 0xf003d14f,0x8a03cda0,0x9a03cdbf,0x8903cdc0, +// 0x9903d01f,0x8c03d020,0x9c03d14f,0xf4000000, + 0xf0000000 | (cap-1), 0x8a000000 | daddr, + 0x9a000000 | (daddr + ((2 * tsize) - 1)), + 0x89000000 | (daddr + (2 * tsize)), + 0x99000000 | ((cap-1)-spc), + 0x8c000000 | (cap-spc), + 0x9c000000 | (cap-1), 0xf4000000, + }; +#endif + /* 250191 249248 250191 0 */ +// uint32 dmap[4] = {0xf003d14f, 0x8a03cda0, 0x9a03d14f, 0xf4000000}; + int i; + /* vendor flaw map */ + uint32 vmap[2] = {0xf0000004, 0xf4000000}; + uint32 dmap[4] = {0xf0000000 | (cap-1), 0x8a000000 | daddr, + 0x9a000000 | (cap-1), 0xf4000000}; + + /* see if user wants to initialize the disk */ + if (!get_yn("Initialize disk? [Y] ", TRUE)) { + return 1; + } + +#ifdef OLD_WAY + /* dmap data */ + /* the diag map (dmap) is in last sec of disk */ + /* (cyl * trk * sec) - 1 = cap - 1*/ + /* 0xf0046531 - 288049 - 822/9/34 */ + /* 0x8a0460d2 - 286930 - 819/8/0 */ + /* 0x9a046531 - 288049 - 822/9/34 */ + /* 0xf4000000 */ + dmap[0] = 0xf0000000 | (cap-1); /* 0xf003d14f */ + dmap[1] = 0x8a000000 | daddr; /* 0x8a03ccaf */ + dmap[2] = 0x9a000000 | (cap-1); /* 0x9a03d14f */ + dmap[3] = 0xf4000000; +#endif + + /* seek to sector 0 */ + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + fprintf (stderr, "Error on seek to 0\r\n"); + } + + /* get buffer for track data in bytes */ + if ((buff = (uint8 *)calloc(csize*ssize, sizeof(uint8))) == 0) { + detach_unit(uptr); + return SCPE_ARG; + } + /* put dummy data in first word of disk */ + buff[0] = 'Z'; + buff[1] = 'E'; + buff[2] = 'R'; + buff[3] = 'O'; + sim_debug(DEBUG_CMD, dptr, + "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++) { + if ((sim_fwrite(buff, 1, csize*ssize, uptr->fileref)) != csize*ssize) { + sim_debug(DEBUG_CMD, dptr, + "Error on write to diskfile cyl %04x\n", cyl); + } + if (cyl == 0) { + buff[0] = 0; + buff[1] = 0; + buff[2] = 0; + buff[3] = 0; + } + if ((cyl % 100) == 0) + fputc('.', stderr); + } + fputc('\r', stderr); + fputc('\n', stderr); + + /* byte swap the buffers for dmap and umap */ +// for (i=0; i<256; i++) { + for (i=0; i<8; i++) { + umap[i] = (((umap[i] & 0xff) << 24) | ((umap[i] & 0xff00) << 8) | + ((umap[i] & 0xff0000) >> 8) | ((umap[i] >> 24) & 0xff)); + } + for (i=0; i<4; i++) { + dmap[i] = (((dmap[i] & 0xff) << 24) | ((dmap[i] & 0xff00) << 8) | + ((dmap[i] & 0xff0000) >> 8) | ((dmap[i] >> 24) & 0xff)); + } + for (i=0; i<2; i++) { + vmap[i] = (((vmap[i] & 0xff) << 24) | ((vmap[i] & 0xff00) << 8) | + ((vmap[i] & 0xff0000) >> 8) | ((vmap[i] >> 24) & 0xff)); + } + + /* now seek to end of disk and write the dmap data */ + /* setup dmap pointed to by track label 0 wd[3] = (cyl-4) * spt + (spt - 1) */ + + /* write dmap data to last sector on disk */ + sim_fseek(uptr->fileref, laddr*ssize, SEEK_SET); /* seek last sector */ + if ((sim_fwrite((char *)&dmap, sizeof(uint32), 4, uptr->fileref)) != 4) { + sim_debug(DEBUG_CMD, dptr, + "Error on vendor map write to diskfile sect %06x\n", (cap-1) * ssize); + } + + /* 1 cylinder is saved for disk manufacture */ + /* 2 cylinders are saved for diagnostics */ + /* write vmap to vaddr that is the address in trk 0 label + 1 track */ + /* daddr is (cap) - 3 cyl - 2 tracks */ + /* vaddr is (cap) - 3 cyl - 1 track */ + + /* seek to vendor label area */ + sim_fseek(uptr->fileref, (vaddr)*ssize, SEEK_SET); /* seek UMAP */ + if ((sim_fwrite((char *)&vmap, sizeof(uint32), 2, uptr->fileref)) != 2) { + sim_debug(DEBUG_CMD, dptr, + "Error on vendor map write to diskfile sect %06x\n", vaddr * ssize); + } + + /* write dmap to daddr that is the address in trk 0 label */ + /* daddr is (cap) - 3 cyl - 2 tracks */ + /* vaddr is daddr - spt */ + + sim_fseek(uptr->fileref, (daddr)*ssize, SEEK_SET); /* seek DMAP */ + 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 + sim_fseek(uptr->fileref, (uaddr)*ssize, SEEK_SET); /* seek UMAP */ + if ((sim_fwrite((char *)&umap, sizeof(uint32), 4, uptr->fileref)) != 4) { + sim_debug(DEBUG_CMD, dptr, + "Error on umap write to diskfile sect %06x\n", uaddr * ssize); + } +#endif + + printf("writing to vmap sec %x bytes %x\n", + vaddr, (vaddr)*ssize); + printf("writing zeros to umap sec %x bytes %x\n", + uaddr, (uaddr)*ssize); + printf("writing dmap to %x %d %x %d dmap to %x %d %x %d\n", + cap-1, cap-1, (cap-1)*ssize, (cap-1)*ssize, + daddr, daddr, daddr*ssize, daddr*ssize); + + /* 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 hsdp_attach(UNIT *uptr, CONST char *file) { uint16 addr = GET_UADDR(uptr->CMD); int type = GET_TYPE(uptr->flags); - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = get_dev(uptr); t_stat r; -// uint16 tsize; /* track size in bytes */ - uint16 ssize; /* sector size in bytes */ + uint32 ssize; /* sector size in bytes */ 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; + uint8 buff[1024]; + /* see if valid disk entry */ if (hsdp_type[type].name == 0) { /* does the assigned disk have a name */ detach_unit(uptr); /* no, reject */ return SCPE_FMT; /* error */ } + /* have simulator attach the file to the unit */ + 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) { @@ -1273,35 +1729,61 @@ t_stat hsdp_attach(UNIT *uptr, CONST char *file) } uptr->DDATA = (void *)data; /* save pointer to structure in DDATA */ - /* track size in bytes is sectors/track times words/sector time 4 bytse/word */ -// tsize = hsdp_type[type].spt * hsdp_type[type].ssiz * 4; /* get track size in bytes */ - uptr->capac = hsdp_type[type].taus * hsdp_type[type].spau; - /* disk capacity in sectors */ - ssize = hsdp_type[type].ssiz * 4; /* disk sector size in bytes */ - uptr->capac *= ssize; /* disk capacity in bytes */ + uptr->capac = CAP(type); /* size in sectors */ + ssize = SSB(type); /* disk sector size in bytes */ - sim_debug(DEBUG_CMD, dptr, "Disk taus %d spau %d ssiz %d cap %d\n", - hsdp_type[type].taus, hsdp_type[type].spau, hsdp_type[type].ssiz * 4, - uptr->capac); /* disk capacity */ + sim_debug(DEBUG_CMD, dptr, "Disk %s cyl %d hds %d sec %d ssiz %d capacity %d\n", + hsdp_type[type].name, hsdp_type[type].cyl, hsdp_type[type].nhds, + hsdp_type[type].spt, ssize, uptr->capac); /* hsdp capacity */ if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ detach_unit(uptr); /* if no space, error */ return SCPE_FMT; /* error */ } - /* set the max configuration geometry */ - hsdp_type[type].geom = (hsdp_type[type].cyl << 16) | - (hsdp_type[type].nhds << 8) | (hsdp_type[type].spt); + /* see if there is any data on sector zero of disk, if not format it */ + if ((r = sim_fread(buff, sizeof(uint8), ssize, uptr->fileref) != ssize)) { + sim_debug(DEBUG_CMD, dptr, "Disk format fread ret = %04x\n", r); + goto fmt; + } + + if ((buff[0] | buff[1] | buff[2] | buff[3]) == 0) { + sim_debug(DEBUG_CMD, dptr, + "Disk format buf0 %02x buf1 %02x buf2 %02x buf3 %02x\n", + buff[0], buff[1], buff[2], buff[3]); +fmt: + /* format the drive */ + if (hsdp_format(uptr)) { + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ + } + } + + /* there is data on sector 0, so already formatted */ + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ + } + + /* start out at sector 0 */ data->cyl = 0; /* current cylinder position */ data->tpos = 0; /* current track position */ data->spos = 0; /* current sector position */ + sim_debug(DEBUG_CMD, dptr, + "Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\n", + hsdp_type[type].name, CYL(type), HDS(type), SPT(type), SPC(type), + CAP(type), CAPB(type)); + + sim_debug(DEBUG_CMD, dptr, "File %s attached to %s\r\n", + file, hsdp_type[type].name); + set_devattn(addr, SNS_DEVEND); return SCPE_OK; } /* detach a disk device */ -t_stat hsdp_detach(UNIT * uptr) { +t_stat hsdp_detach(UNIT *uptr) { struct ddata_t *data = (struct ddata_t *)uptr->DDATA; if (data != 0) { @@ -1325,28 +1807,30 @@ t_stat hsdp_boot(int32 unit_num, DEVICE * dptr) { } /* Disk option setting commands */ -t_stat hsdp_set_type(UNIT * uptr, int32 val, CONST char *cptr, void *desc) +/* set the disk type attached to unit */ +t_stat hsdp_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { int i; - if (cptr == NULL) - return SCPE_ARG; - if (uptr == NULL) - return SCPE_IERR; - if (uptr->flags & UNIT_ATT) - return SCPE_ALATT; + if (cptr == NULL) /* any disk name input? */ + return SCPE_ARG; /* arg error */ + if (uptr == NULL) /* valid unit? */ + return SCPE_IERR; /* no, error */ + if (uptr->flags & UNIT_ATT) /* is unit attached? */ + return SCPE_ALATT; /* no, error */ for (i = 0; hsdp_type[i].name != 0; i++) { if (strcmp(hsdp_type[i].name, cptr) == 0) { uptr->flags &= ~UNIT_TYPE; /* clear old type */ uptr->flags |= SET_TYPE(i); /* set new type */ - uptr->capac = hsdp_type[i].taus * hsdp_type[i].spau; + /* set capacity of disk in sectors */ + uptr->capac = CAP(i); return SCPE_OK; } } return SCPE_ARG; } -t_stat hsdp_get_type(FILE * st, UNIT * uptr, int32 v, CONST void *desc) +t_stat hsdp_get_type(FILE *st, UNIT * uptr, int32 v, CONST void *desc) { if (uptr == NULL) return SCPE_IERR; @@ -1356,8 +1840,7 @@ t_stat hsdp_get_type(FILE * st, UNIT * uptr, int32 v, CONST void *desc) } /* help information for disk */ -t_stat hsdp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, - const char *cptr) +t_stat hsdp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { int i; fprintf (st, "SEL 8064 High Speed Disk Processor\r\n"); @@ -1371,13 +1854,13 @@ t_stat hsdp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, } fprintf (st, ".\nEach drive has the following storage capacity:\r\n"); for (i = 0; hsdp_type[i].name != 0; i++) { - /* disk capacity in sectors */ - int32 capac = hsdp_type[i].taus * hsdp_type[i].spau; - int32 ssize = hsdp_type[i].ssiz * 4; /* disk sector size in bytes */ - int32 size = capac * ssize; /* disk capacity in bytes */ - size /= 1024; /* make KB */ - size = (10 * size) / 1024; /* size in MB * 10 */ - fprintf(st, " %-8s %4d.%1d MB\r\n", hsdp_type[i].name, size/10, size%10); +// 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 */ + fprintf(st, " %-8s %4d.%1d MB cyl %3d hds %3d sec %3d blk %3d\r\n", + hsdp_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_mt.c b/SEL32/sel32_mt.c index 8d59525..153ac54 100644 --- a/SEL32/sel32_mt.c +++ b/SEL32/sel32_mt.c @@ -39,14 +39,16 @@ #include "sel32_defs.h" #include "sim_tape.h" -extern t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); -extern t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc); -extern void chan_end(uint16 chan, uint8 flags); -extern int chan_read_byte(uint16 chan, uint8 *data); -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 uint32 SPAD[]; /* cpu SPAD */ +extern t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +extern t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc); +extern void chan_end(uint16 chan, uint8 flags); +extern int chan_read_byte(uint16 chan, uint8 *data); +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 uint32 SPAD[]; /* cpu SPAD */ #ifdef NUM_DEVS_MT #define BUFFSIZE (64 * 1024) @@ -383,6 +385,7 @@ DEVICE mta_dev = { "MTA", mta_unit, NULL, mt_mod, NUM_UNITS_MT, 16, 24, 4, 16, 32, NULL, NULL, &mt_reset, &mt_boot, &mt_attach, &mt_detach, + /* ctxt is the DIB pointer */ &mta_dib, DEV_BUF_NUM(0) | DEV_DISABLE | DEV_DEBUG | DEV_TAPE, 0, dev_debug, NULL, NULL, &mt_help, NULL, NULL, &mt_description @@ -433,7 +436,7 @@ DEVICE mtb_dev = { /* start an I/O operation */ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd entry chan %04x cmd %02x\n", chan, cmd); @@ -565,7 +568,7 @@ t_stat mt_error(UNIT *uptr, uint16 addr, t_stat r, DEVICE *dptr) t_stat mt_srv(UNIT *uptr) { uint16 addr = GET_UADDR(uptr->CMD); - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); int cmd = uptr->CMD & MT_CMDMSK; int bufnum = GET_DEV_BUF(dptr->flags); @@ -1083,7 +1086,7 @@ t_stat mt_srv(UNIT *uptr) /* initialize the tape chan/unit */ void mt_ini(UNIT *uptr, t_bool f) { - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = get_dev(uptr); if (MT_DENS(uptr->dynflags) == 0) uptr->dynflags |= MT_DENS_6250 << UNIT_S_DF_TAPE; @@ -1091,8 +1094,8 @@ void mt_ini(UNIT *uptr, t_bool f) uptr->SNS = 0; /* clear sense data */ uptr->SNS |= (SNS_RDY|SNS_ONLN|SNS_LOAD); /* set initial status */ mt_busy[GET_DEV_BUF(dptr->flags)] = 0; /* set not busy */ - sim_debug(DEBUG_EXP, dptr, "MT init device %s unit %02x\n", dptr->name, - GET_UADDR(uptr->CMD)); + sim_debug(DEBUG_EXP, dptr, "MT init device %s unit %02x\n", + dptr->name, GET_UADDR(uptr->CMD)); } /* reset the mag tape */ @@ -1106,8 +1109,8 @@ t_stat mt_reset(DEVICE *dptr) /* attach the specified file to the tape device */ t_stat mt_attach(UNIT *uptr, CONST char *file) { - uint16 addr = GET_UADDR(uptr->CMD); /* get address of mt device */ - t_stat r; + uint16 addr = GET_UADDR(uptr->CMD); /* get address of mt device */ + t_stat r; /* mount the specified file to the MT */ if ((r = sim_tape_attach(uptr, file)) != SCPE_OK) { @@ -1123,7 +1126,7 @@ t_stat mt_attach(UNIT *uptr, CONST char *file) t_stat mt_detach(UNIT *uptr) { sim_debug(DEBUG_EXP, &mta_dev, "mt_detach\n"); - uptr->CMD = 0; + uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ return sim_tape_detach(uptr); } diff --git a/SEL32/sel32_scfi.c b/SEL32/sel32_scfi.c index 22dca97..f9ebcd7 100644 --- a/SEL32/sel32_scfi.c +++ b/SEL32/sel32_scfi.c @@ -1,6 +1,6 @@ /* sel32_scfi.c: SEL-32 SCFI SCSI Disk controller - 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 @@ -23,40 +23,37 @@ #include "sel32_defs.h" -extern t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); -extern t_stat show_dev_addr(FILE * st, UNIT *uptr, int32 v, CONST void *desc); -extern void chan_end(uint16 chan, uint8 flags); -extern int chan_read_byte(uint16 chsa, uint8 *data); -extern int chan_write_byte(uint16 chsa, uint8 *data); -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 t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +extern t_stat show_dev_addr(FILE * st, UNIT *uptr, int32 v, CONST void *desc); +extern void chan_end(uint16 chan, uint8 flags); +extern int chan_read_byte(uint16 chsa, uint8 *data); +extern int chan_write_byte(uint16 chsa, uint8 *data); +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 uint32 M[]; /* our memory */ -extern uint32 SPAD[]; /* cpu SPAD memory */ +extern uint32 M[]; /* our memory */ +extern uint32 SPAD[]; /* cpu SPAD memory */ #ifdef NUM_DEVS_SCFI -#define UNIT_V_TYPE (UNIT_V_UF + 0) -#define UNIT_TYPE (0xf << UNIT_V_TYPE) -#define GET_TYPE(x) ((UNIT_TYPE & (x)) >> UNIT_V_TYPE) -#define SET_TYPE(x) (UNIT_TYPE & ((x) << UNIT_V_TYPE)) -#define UNIT_SCFI UNIT_ATTABLE | UNIT_IDLE +#define UNIT_SCFI UNIT_ATTABLE | UNIT_IDLE | UNIT_DISABLE /* INCH command information */ /* WD 0 - Data address WD 1 - Flags - 0 -36 byte count -Data - 224 word INCH buffer address -WD 1 Drive 0 Attribute register -WD 2 Drive 1 Attribute register -WD 3 Drive 2 Attribute register -WD 4 Drive 3 Attribute register -WD 5 Drive 4 Attribute register -WD 6 Drive 5 Attribute register -WD 7 Drive 6 Attribute register -WD 8 Drive 7 Attribute register +Data - 224 word INCH buffer address (SST) +WD 1 Drive 0 Attribute register +WD 2 Drive 1 Attribute register +WD 3 Drive 2 Attribute register +WD 4 Drive 3 Attribute register +WD 5 Drive 4 Attribute register +WD 6 Drive 5 Attribute register +WD 7 Drive 6 Attribute register +WD 8 Drive 7 Attribute register Memory attribute register layout bits 0-7 - Flags @@ -69,7 +66,8 @@ bits 0-7 - Flags bit 7 - 0=Reserved 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) +bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option of + mini-module) */ @@ -82,90 +80,90 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option #define CMD u3 /* u3 */ /* in u3 is device command code and status */ -#define DSK_CMDMSK 0x00ff /* Command being run */ -#define DSK_STAR 0x0100 /* STAR value in u4 */ -#define DSK_NU2 0x0200 /* */ -#define DSK_READDONE 0x0400 /* Read finished, end channel */ -#define DSK_ENDDSK 0x0800 /* Sensed end of disk */ -#define DSK_SEEKING 0x1000 /* Disk is currently seeking */ -#define DSK_READING 0x2000 /* Disk is reading data */ -#define DSK_WRITING 0x4000 /* Disk is writing data */ -#define DSK_BUSY 0x8000 /* Flag to send a CUE */ +#define DSK_CMDMSK 0x00ff /* Command being run */ +#define DSK_STAR 0x0100 /* STAR value in u4 */ +#define DSK_NU2 0x0200 /* */ +#define DSK_READDONE 0x0400 /* Read finished, end channel */ +#define DSK_ENDDSK 0x0800 /* Sensed end of disk */ +#define DSK_SEEKING 0x1000 /* Disk is currently seeking */ +#define DSK_READING 0x2000 /* Disk is reading data */ +#define DSK_WRITING 0x4000 /* Disk is writing data */ +#define DSK_BUSY 0x8000 /* Disk is busy */ /* commands */ -#define DSK_INCH 0x00 /* Initialize channel */ -#define DSK_INCH2 0xf0 /* Initialize channel for processing */ -#define DSK_WD 0x01 /* Write data */ -#define DSK_RD 0x02 /* Read data */ -#define DSK_NOP 0x03 /* No operation */ -#define DSK_SNS 0x04 /* Sense */ -#define DSK_SCK 0x07 /* Seek cylinder, track, sector */ -#define DSK_TIC 0x08 /* Transfer in channel */ -#define DSK_FNSK 0x0B /* Format for no skip */ -#define DSK_LPL 0x13 /* Lock protected label */ -#define DSK_LMR 0x1F /* Load mode register */ -#define DSK_RES 0x23 /* Reserve */ -#define DSK_WSL 0x31 /* Write sector label */ -#define DSK_RSL 0x32 /* Read sector label */ -#define DSK_REL 0x33 /* Release */ -#define DSK_XEZ 0x37 /* Rezero */ -#define DSK_POR 0x43 /* Priority Override */ -#define DSK_IHA 0x47 /* Increment head address */ -#define DSK_SRM 0x4F /* Set reserve track mode */ -#define DSK_WTL 0x51 /* Write track label */ -#define DSK_RTL 0x52 /* Read track label */ -#define DSK_XRM 0x5F /* Reset reserve track mode */ -#define DSK_RAP 0xA2 /* Read angular positions */ -#define DSK_TESS 0xAB /* Test STAR (subchannel target address register) */ -#define DSK_ICH 0xFF /* Initialize Controller */ +#define DSK_INCH 0x00 /* Initialize channel */ +#define DSK_INCH2 0xf0 /* Initialize channel for processing */ +#define DSK_WD 0x01 /* Write data */ +#define DSK_RD 0x02 /* Read data */ +#define DSK_NOP 0x03 /* No operation */ +#define DSK_SNS 0x04 /* Sense */ +#define DSK_SCK 0x07 /* Seek cylinder, track, sector */ +#define DSK_TIC 0x08 /* Transfer in channel */ +#define DSK_FNSK 0x0B /* Format for no skip */ +#define DSK_LPL 0x13 /* Lock protected label */ +#define DSK_LMR 0x1F /* Load mode register */ +#define DSK_RES 0x23 /* Reserve */ +#define DSK_WSL 0x31 /* Write sector label */ +#define DSK_RSL 0x32 /* Read sector label */ +#define DSK_REL 0x33 /* Release */ +#define DSK_XEZ 0x37 /* Rezero */ +#define DSK_POR 0x43 /* Priority Override */ +#define DSK_IHA 0x47 /* Increment head address */ +#define DSK_SRM 0x4F /* Set reserve track mode */ +#define DSK_WTL 0x51 /* Write track label */ +#define DSK_RTL 0x52 /* Read track label */ +#define DSK_XRM 0x5F /* Reset reserve track mode */ +#define DSK_RAP 0xA2 /* Read angular positions */ +#define DSK_TESS 0xAB /* Test STAR (subchannel target address register) */ +#define DSK_ICH 0xFF /* Initialize Controller */ #define STAR u4 /* u4 - sector target address register (STAR) */ /* Holds the current cylinder, head(track), sector */ -#define DISK_CYL 0xFFFF0000 /* cylinder mask */ -#define DISK_TRACK 0x0000FF00 /* track mask */ -#define DISK_SECTOR 0x000000ff /* sector mask */ +#define DISK_CYL 0xFFFF0000 /* cylinder mask */ +#define DISK_TRACK 0x0000FF00 /* track mask */ +#define DISK_SECTOR 0x000000ff /* sector mask */ #define SNS u5 /* u5 */ /* Sense byte 0 - mode register */ -#define SNS_DROFF 0x80000000 /* Drive Carriage will be offset */ -#define SNS_TRKOFF 0x40000000 /* Track offset: 0=positive, 1=negative */ -#define SNS_RDTMOFF 0x20000000 /* Read timing offset = 1 */ -#define SNS_RDSTRBT 0x10000000 /* Read strobe timing: 1=positive, 0=negative */ -#define SNS_DIAGMOD 0x08000000 /* Diagnostic Mode ECC Code generation and checking */ -#define SNS_RSVTRK 0x04000000 /* Reserve Track mode: 1=OK to write, 0=read only */ -#define SNS_FHDOPT 0x02000000 /* FHD or FHD option = 1 */ -#define SNS_RESERV 0x01000000 /* Reserved */ +#define SNS_DROFF 0x80000000 /* Drive Carriage will be offset */ +#define SNS_TRKOFF 0x40000000 /* Track offset: 0=positive, 1=negative */ +#define SNS_RDTMOFF 0x20000000 /* Read timing offset = 1 */ +#define SNS_RDSTRBT 0x10000000 /* Read strobe timing: 1=positive, 0=negative */ +#define SNS_DIAGMOD 0x08000000 /* Diagnostic Mode ECC Code generation and checking */ +#define SNS_RSVTRK 0x04000000 /* Reserve Track mode: 1=OK to write, 0=read only */ +#define SNS_FHDOPT 0x02000000 /* FHD or FHD option = 1 */ +#define SNS_RESERV 0x01000000 /* Reserved */ /* Sense byte 1 */ -#define SNS_CMDREJ 0x800000 /* Command reject */ -#define SNS_INTVENT 0x400000 /* Unit intervention required */ -#define SNS_SPARE1 0x200000 /* Spare */ -#define SNS_EQUCHK 0x100000 /* Equipment check */ -#define SNS_DATCHK 0x080000 /* Data Check */ -#define SNS_OVRRUN 0x040000 /* Data overrun/underrun */ -#define SNS_DSKFERR 0x020000 /* Disk format error */ -#define SNS_DEFTRK 0x010000 /* Defective track encountered */ +#define SNS_CMDREJ 0x800000 /* Command reject */ +#define SNS_INTVENT 0x400000 /* Unit intervention required */ +#define SNS_SPARE1 0x200000 /* Spare */ +#define SNS_EQUCHK 0x100000 /* Equipment check */ +#define SNS_DATCHK 0x080000 /* Data Check */ +#define SNS_OVRRUN 0x040000 /* Data overrun/underrun */ +#define SNS_DSKFERR 0x020000 /* Disk format error */ +#define SNS_DEFTRK 0x010000 /* Defective track encountered */ /* Sense byte 2 */ -#define SNS_LAST 0x8000 /* Last track flag encountered */ -#define SNS_AATT 0x4000 /* At Alternate track */ -#define SNS_WPER 0x2000 /* Write protection error */ -#define SNS_WRL 0x1000 /* Write lock error */ -#define SNS_MOCK 0x0800 /* Mode check */ -#define SNS_INAD 0x0400 /* Invalid memory address */ -#define SNS_RELF 0x0200 /* Release fault */ -#define SNS_CHER 0x0100 /* Chaining error */ +#define SNS_LAST 0x8000 /* Last track flag encountered */ +#define SNS_AATT 0x4000 /* At Alternate track */ +#define SNS_WPER 0x2000 /* Write protection error */ +#define SNS_WRL 0x1000 /* Write lock error */ +#define SNS_MOCK 0x0800 /* Mode check */ +#define SNS_INAD 0x0400 /* Invalid memory address */ +#define SNS_RELF 0x0200 /* Release fault */ +#define SNS_CHER 0x0100 /* Chaining error */ /* Sense byte 3 */ -#define SNS_REVL 0x80 /* Revolution lost */ -#define SNS_DADE 0x40 /* Disc addressing or seek error */ -#define SNS_BUCK 0x20 /* Buffer check */ -#define SNS_ECCS 0x10 /* ECC error in sector label */ -#define SNS_ECCD 0x08 /* ECC error iin data */ -#define SNS_ECCT 0x04 /* ECC error in track label */ -#define SNS_RTAE 0x02 /* Reserve track access error */ -#define SNS_UESS 0x01 /* Uncorrectable ECC error */ +#define SNS_REVL 0x80 /* Revolution lost */ +#define SNS_DADE 0x40 /* Disc addressing or seek error */ +#define SNS_BUCK 0x20 /* Buffer check */ +#define SNS_ECCS 0x10 /* ECC error in sector label */ +#define SNS_ECCD 0x08 /* ECC error iin data */ +#define SNS_ECCT 0x04 /* ECC error in track label */ +#define SNS_RTAE 0x02 /* Reserve track access error */ +#define SNS_UESS 0x01 /* Uncorrectable ECC error */ #define ATTR u6 /* u6 */ @@ -182,7 +180,8 @@ bits 0-7 - Flags bit 7 - 0=Reserved 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) +bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option of + mini-module) */ #define DDATA up7 @@ -200,44 +199,29 @@ struct ddata_t struct scfi_t { const char *name; /* Device ID Name */ - uint32 taus; /* total allocation units */ - uint16 bms; /* bit map size */ uint16 nhds; /* Number of heads */ uint16 ssiz; /* sector size in words */ uint16 spt; /* # sectors per track(cylinder) */ - uint8 spau; /* # sectors per allocation unit */ - uint8 spb; /* # sectors per block (192 WDS)*/ - uint32 cyl; /* Number of cylinders */ + 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) */ } scfi_type[] = { /* Class F Disc Devices */ - {"MH040", 20000, 625, 5, 192, 20, 2, 1, 400, 0x40}, /*0 411 40 M */ - {"MH080", 40000, 1250, 5, 192, 20, 2, 1, 800, 0x40}, /*1 823 80 M */ - {"MH160", 80000, 1250, 10, 192, 20, 4, 1, 1600, 0x40}, /*2 823 160 M */ - {"MH300", 76000, 2375, 19, 192, 20, 4, 1, 800, 0x40}, /*3 823 300 M */ - {"MH1GB", 87400, 2732, 1, 192, 20,16, 1,69920, 0x40}, /*4 69920 1000 M */ - {"SG038", 54752, 1711, 1, 192, 20, 8, 1,21900, 0x40}, /*5 21900 38 M */ - {"SG120", 174848, 5464, 1, 192, 20, 8, 1,69939, 0x40}, /*6 69939 120 M */ - {"SG076", 116808, 3491, 1, 192, 20, 8, 1,46723, 0x40}, /*7 46723 76 M */ - {"FH005", 5120, 184, 4, 192, 20, 1, 1, 64, 0x80}, /*8 64 5 M */ - {"CD032", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*9 823 32 M */ - {"CD032", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*10 823 32 M */ - {"CD064", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*11 823 64 M */ - {"CD064", 24000, 750, 3, 192, 20, 2, 1, 800, 0x60}, /*12 823 64 M */ - {"CD096", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*13 823 96 M */ - {"CD096", 40000, 1250, 5, 192, 20, 2, 1, 800, 0x60}, /*14 823 96 M */ - {"MH600", 80000, 2500, 40, 192, 20, 8, 1, 800, 0x40}, /*15 843 600 M */ - {"FM600", 80000, 2500, 40, 192, 20, 8, 1, 800, 0x40}, /*16 843 600 M */ - {"FM600", 1600, 50, 40, 192, 20, 1, 1, 2, 0x80}, /*17 10 600 M */ + /* MPX SCSI disks for SCFI controller */ + {"MH1GB", 1, 192, 40, 34960, 34960, 0x40}, /*0 69920 1000M */ + {"SG038", 1, 192, 20, 2190, 2190, 0x40}, /*1 21900 38M */ + {"SG120", 1, 192, 40, 34970, 34970, 0x40}, /*2 69940 1200M */ + {"SG076", 1, 192, 20, 46725, 46725, 0x40}, /*3 46725 760M */ {NULL, 0} }; #if 0 ***************************************************************** -* DEVICE ID TABLE +* DEVICE ID TABLE ***************************************************************** SPACE BOUND 1W @@ -290,7 +274,7 @@ t_stat scfi_detach(UNIT *); t_stat scfi_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat scfi_get_type(FILE * st, UNIT *uptr, int32 v, CONST void *desc); t_stat scfi_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); -const char *scfi_description (DEVICE *dptr); +const char *scfi_description (DEVICE *dptr); /* channel program information */ CHANP sda_chp[NUM_UNITS_SCFI] = {0}; @@ -304,15 +288,15 @@ MTAB scfi_mod[] = { }; UNIT sda_unit[] = { -/* SET_TYPE(6) SG120 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(6), 0), 0, UNIT_ADDR(0x400)}, /* 0 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(6), 0), 0, UNIT_ADDR(0x410)}, /* 1 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(6), 0), 0, UNIT_ADDR(0x420)}, /* 2 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(6), 0), 0, UNIT_ADDR(0x430)}, /* 3 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(6), 0), 0, UNIT_ADDR(0x440)}, /* 4 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(6), 0), 0, UNIT_ADDR(0x450)}, /* 5 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(6), 0), 0, UNIT_ADDR(0x460)}, /* 6 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(6), 0), 0, UNIT_ADDR(0x470)}, /* 7 */ +/* SET_TYPE(2) SG120 */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x400)}, /* 0 */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x410)}, /* 1 */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x420)}, /* 2 */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x430)}, /* 3 */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x440)}, /* 4 */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x450)}, /* 5 */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x460)}, /* 6 */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(2), 0), 0, UNIT_ADDR(0x470)}, /* 7 */ }; //DIB sda_dib = {scfi_preio, scfi_startcmd, NULL, NULL, NULL, scfi_ini, sda_unit, sda_chp, NUM_UNITS_SCFI, 0x0f, 0x0400, 0, 0, 0}; @@ -338,7 +322,7 @@ DEVICE sda_dev = { "SDA", sda_unit, NULL, scfi_mod, NUM_UNITS_SCFI, 16, 24, 4, 16, 32, NULL, NULL, &scfi_reset, &scfi_boot, &scfi_attach, &scfi_detach, - &sda_dib, DEV_DISABLE|DEV_DEBUG, 0, dev_debug, + &sda_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, NULL, NULL, &scfi_help, NULL, NULL, &scfi_description }; @@ -347,15 +331,15 @@ DEVICE sda_dev = { CHANP sdb_chp[NUM_UNITS_SCFI] = {0}; UNIT sdb_unit[] = { -/* SET_TYPE(4) DM1GB */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(4), 0), 0, UNIT_ADDR(0xC00)}, /* 0 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(4), 0), 0, UNIT_ADDR(0xC10)}, /* 1 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(4), 0), 0, UNIT_ADDR(0xC20)}, /* 2 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(4), 0), 0, UNIT_ADDR(0xC30)}, /* 3 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(4), 0), 0, UNIT_ADDR(0xC40)}, /* 4 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(4), 0), 0, UNIT_ADDR(0xC50)}, /* 5 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(4), 0), 0, UNIT_ADDR(0xC60)}, /* 6 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(4), 0), 0, UNIT_ADDR(0xC70)}, /* 7 */ +/* SET_TYPE(0) DM1GB */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC00)}, /* 0 */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC10)}, /* 1 */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC20)}, /* 2 */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC30)}, /* 3 */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC40)}, /* 4 */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC50)}, /* 5 */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC60)}, /* 6 */ + {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(0), 0), 0, UNIT_ADDR(0xC70)}, /* 7 */ }; //DIB sdb_dib = {scfi_preio, scfi_startcmd, NULL, NULL, NULL, scfi_ini, sdb_unit, sdb_chp, NUM_UNITS_SCFI, 0x0f, 0x0c00, 0, 0, 0}; @@ -381,7 +365,7 @@ DEVICE sdb_dev = { "SDB", sdb_unit, NULL, scfi_mod, NUM_UNITS_SCFI, 16, 24, 4, 16, 32, NULL, NULL, &scfi_reset, &scfi_boot, &scfi_attach, &scfi_detach, - &sdb_dib, DEV_DISABLE|DEV_DEBUG, 0, dev_debug, + &sdb_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug, NULL, NULL, &scfi_help, NULL, NULL, &scfi_description }; #endif @@ -389,7 +373,7 @@ DEVICE sdb_dev = { /* start a disk operation */ uint8 scfi_preio(UNIT *uptr, uint16 chan) { - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); sim_debug(DEBUG_CMD, dptr, "scfi_preio CMD %08x unit=%02x\n", uptr->CMD, unit); @@ -400,24 +384,25 @@ uint8 scfi_preio(UNIT *uptr, uint16 chan) return 0; /* good to go */ } -uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { +uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) +{ uint16 addr = GET_UADDR(uptr->CMD); - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); uint8 ch; 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 */ + uptr->SNS |= SNS_INTVENT; /* unit intervention required */ if (cmd != DSK_SNS) /* we are completed with unit check status */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; } if ((uptr->CMD & DSK_CMDMSK) != 0) { - uptr->CMD |= DSK_BUSY; /* Flag we we are busy */ + uptr->CMD |= DSK_BUSY; /* Flag we we are busy */ return SNS_BSY; } - if ((uptr->CMD & 0xff00) != 0) { /* if any status info, we are busy */ + if ((uptr->CMD & 0xff00) != 0) { /* if any status info, we are busy */ return SNS_BSY; } sim_debug(DEBUG_CMD, dptr, "scfi_startcmd CMD 2 unit=%02x cmd %02x\n", unit, cmd); @@ -425,36 +410,45 @@ uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 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 CMD */ - ch = (uptr->CMD >> 24) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b0 unit=%02x 1 %02x\n", unit, ch); + /* 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->CMD >> 16) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b1 unit=%02x 1 %02x\n", unit, 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 CMD */ - ch = (uptr->CMD >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b2 unit=%02x 1 %02x\n", unit, 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 CMD */ - ch = (uptr->CMD) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b3 unit=%02x 1 %02x\n", unit, 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); + 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); + 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); + 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); + 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 */ + /* 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; @@ -464,17 +458,17 @@ uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { ch = (uptr->ATTR >> 0) & 0xff; chan_write_byte(addr, &ch) ; /* bytes 12 & 13 contain drive related status */ - ch = 0; /* zero for now */ + 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 */ + uptr->SNS &= 0xff000000; /* clear status bytes, but leave mode data */ return SNS_CHNEND|SNS_DEVEND; } - if (cmd == 0x00) /* INCH cmd gives unit check */ + 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 */ + + uptr->SNS |= (SNS_INTVENT|SNS_CMDREJ); /* set new error status */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* we done */ } @@ -483,27 +477,28 @@ uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { case DSK_INCH: /* INCH 0x00 */ { - uint32 mema; /* memory address */ + uint32 mema; /* memory address */ uint32 i; UNIT *up = dptr->units; /* first unit for this device */ sim_debug(DEBUG_CMD, dptr, - "scfi_startcmd starting inch cmd addr %04x CMD %08x\n", addr, uptr->CMD); - /* CMD has IOCD word 1 contents. For the disk processor it contains */ + "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 CMD and us9 left non-zero */ + /* 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->CMD; /* get memory address of buffer */ - uptr->CMD = M[mema>>2]; /* get status buffer address for XIO return status */ + 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 CMD %08x mema %08x units %02x\n", - addr, uptr->CMD, mema, dptr->numunits); + "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 */ + 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, @@ -511,45 +506,42 @@ uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { up++; /* next unit for this device */ } sim_debug(DEBUG_CMD, dptr, "scfi_startcmd done INCH cmd addr %04x\n", addr); -// return SNS_CHNEND|SNS_DEVEND; -// break; uptr->CMD |= DSK_INCH2; /* use 0xf0 for inch, just need int */ sim_activate(uptr, 20); /* start things off */ - return (0); + 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 CMD */ + 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 */ + uptr->CMD |= cmd; /* save cmd */ sim_debug(DEBUG_CMD, dptr, - "scfi_startcmd done with disk seek r/w cmd %02x addr %04x\n", cmd, addr); + "scfi_startcmd starting disk seek r/w cmd %02x addr %04x\n", cmd, addr); sim_activate(uptr, 20); /* start things off */ return 0; break; - case DSK_NOP: /* NOP 0x03 */ -// return SNS_CHNEND|SNS_DEVEND; /* return OK */ - uptr->CMD |= cmd; /* save cmd */ + case DSK_NOP: /* NOP 0x03 */ + uptr->CMD |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ return 0; break; case DSK_SNS: /* Sense 0x04 */ - uptr->CMD |= cmd; /* save cmd */ + uptr->CMD |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ return 0; break; } sim_debug(DEBUG_CMD, dptr, - "scfi_startcmd done with scfi_startcmd %02x addr %04x SNS %08x\n", - cmd, addr, uptr->SNS); - if (uptr->SNS & 0xff) + "scfi_startcmd done with scfi_startcmd %02x addr %04x SNS %08x\n", + cmd, addr, uptr->SNS); + if (uptr->SNS & 0xff) /* any other cmd is error */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; sim_activate(uptr, 20); /* start things off */ return SNS_CHNEND|SNS_DEVEND; @@ -559,52 +551,54 @@ uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { t_stat scfi_srv(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->CMD); - DEVICE *dptr = find_dev_from_unit(uptr); - DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to Dev Info Blk for this device */ + 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); int cmd = uptr->CMD & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); - int32 trk, cyl; + uint32 trk, cyl; int unit = (uptr - dptr->units); int len; int dlen = 0; /* total bytes processed */ int i; uint8 ch; -// int tsize = scfi_type[type].spt * scfi_type[type].ssiz*4; /* get track size in bytes */ 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 */ 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", + 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); -// if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ -// return SCPE_OK; -// } if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ - uptr->SNS |= SNS_INTVENT; /* unit intervention required */ + uptr->SNS |= SNS_INTVENT; /* unit intervention required */ if (cmd != DSK_SNS) /* we are completed with unit check status */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; } - sim_debug(DEBUG_CMD, dptr, "scfi_srv cmd=%02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); + sim_debug(DEBUG_CMD, dptr, + "scfi_srv cmd=%02x chsa %04x count %04x\n", + cmd, chsa, chp->ccw_count); switch (cmd) { case 0: /* No command, stop disk */ - break; + break; case DSK_INCH2: /* use 0xff for inch, just need int */ 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); + "scfi_srv cmd INCH chsa %04x count %04x completed\n", chsa, chp->ccw_count); chan_end(chsa, SNS_CHNEND); /* return just channel end */ break; case DSK_NOP: /* NOP 0x03 */ uptr->CMD &= ~(0xffff); /* remove old cmd */ sim_debug(DEBUG_CMD, dptr, - "scfi_srv cmd NOP chsa %04x count %04x completed\n", chsa, chp->ccw_count); + "scfi_srv cmd NOP chsa %04x count %04x completed\n", + chsa, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; @@ -623,31 +617,32 @@ t_stat scfi_srv(UNIT *uptr) chan_write_byte(chsa, &ch) ; ch = 4; sim_debug(DEBUG_CMD, dptr, "DISK SENSE %02x chars complete %08x, unit %02x\n", - ch, uptr->SNS, unit); + ch, uptr->SNS, unit); uptr->CMD &= ~(0xff00); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case DSK_SCK: /* Seek cylinder, track, sector 0x07 */ + 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->CMD >> 16) == data->cyl) { + if ((uptr->STAR >> 16) == data->cyl) { /* we are on cylinder, seek is done */ sim_debug(DEBUG_CMD, dptr, "scfi_srv seek on cylinder unit=%02x %04x %04x\n", - unit, uptr->CMD >> 16, data->cyl); + unit, uptr->STAR >> 16, data->cyl); 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->CMD >> 16, data->cyl); + unit, uptr->STAR >> 16, data->cyl); sim_activate(uptr, 20); break; } else { /* Compute delay based of difference. */ /* Set next state = index */ - i = (uptr->CMD >> 16) - data->cyl; - sim_debug(DEBUG_CMD, dptr, "scfi_srv seek unit=%02x %04x %04x\n", unit, uptr->CMD >> 16, i); + 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 */ @@ -678,7 +673,7 @@ t_stat scfi_srv(UNIT *uptr) data->cyl = 0; /* make zero */ } sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek next unit=%02x %04x %04x\n", - unit, uptr->CMD >> 16, data->cyl); + unit, uptr->STAR >> 16, data->cyl); sim_activate(uptr, 2); break; } @@ -698,23 +693,41 @@ t_stat scfi_srv(UNIT *uptr) 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 CMD */ - uptr->CMD = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]); - cyl = uptr->CMD >> 16; /* get the cylinder */ + /* 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 */ 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 */ + /* 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 */ + + /* we have an error, tell user */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* end command */ + break; + } + uptr->CMD |= DSK_STAR; /* show we have seek STAR in CMD */ /* calc the sector address of data */ /* calculate file position in bytes of requested sector */ /* file offset in bytes */ - tstart = uptr->CMD * (scfi_type[type].spb * scfi_type[type].ssiz * 4); + 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 */ - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek start %08x trk %04x sec %02x\n", tstart, trk, buf[3]); + sim_debug(DEBUG_DETAIL, dptr, + "scfi_srv seek start %08x trk %04x sec %02x\n", + tstart, trk, buf[3]); 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); } @@ -722,33 +735,35 @@ rezero: /* Check if already on correct cylinder */ if (cyl != data->cyl) { /* No, Do seek */ - 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", + 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", unit, cyl, trk, buf[3]); sim_activate(uptr, 20); - chan_end(chsa, SNS_CHNEND); +// chan_end(chsa, SNS_CHNEND); } else { - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv calc sect addr seek start %08x cyl %04x trk %04x sec %02x\n", + 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); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ +// sim_activate(uptr, 20); chan_end(chsa, SNS_DEVEND|SNS_CHNEND); } return SCPE_OK; - case DSK_XEZ: /* Rezero & Read IPL record */ + case DSK_XEZ: /* Rezero & Read IPL record */ sim_debug(DEBUG_CMD, dptr, "RD REZERO IPL unit=%02x seek 0\n", unit); /* Do a seek to 0 */ - uptr->CMD = 0; /* set STAR to 0, 0, 0 */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ - uptr->CMD |= DSK_SCK; /* show as seek command */ + uptr->STAR = 0; /* set STAR 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 */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -763,38 +778,39 @@ rezero: /* Read in 1 character of mode data */ if (chan_read_byte(chsa, &buf[0])) { /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } - uptr->CMD &= ~(0xffff); /* remove old cmd */ - uptr->SNS &= 0x00ffffff; /* clear old mode data */ - uptr->SNS |= (buf[0] << 24); /* save mode value */ + uptr->CMD &= ~(0xffff); /* remove old cmd */ + uptr->SNS &= 0x00ffffff; /* clear old mode data */ + uptr->SNS |= (buf[0] << 24); /* save mode value */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case DSK_RD: /* Read Data */ + case DSK_RD: /* Read Data */ /* 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 */ + 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", unit, uptr->CMD, chp->ccw_count); } - if (uptr->CMD & DSK_READING) { /* see if we are reading data */ + if (uptr->CMD & DSK_READING) { /* see if we are reading data */ /* 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); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } - sim_debug(DEBUG_CMD, dptr, "scfi_srv after READ chsa %04x count %04x\n", chsa, chp->ccw_count); + 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); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); goto rddone; } @@ -818,21 +834,25 @@ rezero: 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); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; + } else { + sim_activate(uptr, 10); /* wait to read next sector */ + break; } rddone: - sim_activate(uptr, 10); /* wait to read next sector */ - break; + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ } break; 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 */ + 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", + sim_debug(DEBUG_CMD, dptr, + "DISK WRITE starting unit=%02x CMD %08x bytes %04x\n", unit, uptr->CMD, dlen); } if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */ @@ -860,7 +880,7 @@ rddone: 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); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -868,7 +888,7 @@ rddone: 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); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; } @@ -876,16 +896,17 @@ rddone: "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++; -wrdone: sim_activate(uptr, 10); break; +wrdone: + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ } break; default: sim_debug(DEBUG_DETAIL, dptr, "invalid command %02x unit %02x\n", cmd, unit); uptr->SNS |= SNS_CMDREJ; - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } @@ -897,16 +918,20 @@ wrdone: /* initialize the disk */ void scfi_ini(UNIT *uptr, t_bool f) { - DEVICE *dptr = find_dev_from_unit(uptr); - int i = GET_TYPE(uptr->flags); + 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 */ - uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ - /* capacity is total allocation units times sectors per allocation unit */ + uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ /* total sectors on disk */ - uptr->capac = scfi_type[i].taus * scfi_type[i].spau; + uptr->capac = tdisk; /* 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); + dptr->name, GET_UADDR(uptr->CMD), uptr->CMD); } t_stat scfi_reset(DEVICE * dptr) @@ -918,16 +943,17 @@ t_stat scfi_reset(DEVICE * dptr) /* create the disk file for the specified device */ int scfi_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 = find_dev_from_unit(uptr); - uint16 tsize = scfi_type[type].spt * scfi_type[type].ssiz*4; /* get track size in bytes */ - int32 ssize = scfi_type[type].ssiz * 4; /* disk sector size in bytes */ - uint32 cyl; - uint16 spc = scfi_type[type].nhds * scfi_type[type].spt; /* sectors/cyl */ - uint32 cap = scfi_type[type].taus * scfi_type[type].spau; /* disk capacity in sectors */ - uint32 cylv = cap / spc; /* calc number of cylinders */ - uint8 *buff; + uint16 addr = GET_UADDR(uptr->CMD); + int type = GET_TYPE(uptr->flags); + DEVICE *dptr = get_dev(uptr); + int32 ssize = scfi_type[type].ssiz * 4; /* disk sector size in bytes */ + uint32 tsize = scfi_type[type].spt; /* get track size in sectors */ + uint32 csize = scfi_type[type].nhds * tsize; /* get cylinder size in sectors */ + uint32 cyl = scfi_type[type].cyl; /* get # cyl */ +// uint16 spc = scfi_type[type].nhds * scfi_type[type].spt; /* sectors/cyl */ + uint32 cap = scfi_type[type].cyl * csize; /* disk capacity in sectors */ + uint32 cylv = cyl; /* number of cylinders */ + uint8 *buff; /* see if user wants to initialize the disk */ if (!get_yn("Initialize disk? [Y] ", TRUE)) { @@ -940,7 +966,7 @@ int scfi_format(UNIT *uptr) { } /* get buffer for track data */ - if ((buff = (uint8 *)calloc(tsize, sizeof(uint8))) == 0) { + if ((buff = (uint8 *)calloc(tsize*ssize, sizeof(uint8))) == 0) { detach_unit(uptr); return SCPE_ARG; } @@ -949,11 +975,14 @@ int scfi_format(UNIT *uptr) { buff[1] = 'E'; buff[2] = 'R'; buff[3] = 'O'; - sim_debug(DEBUG_CMD, dptr, "Creating disk file of trk size %04x capacity %d\n", tsize, cap*ssize); + sim_debug(DEBUG_CMD, dptr, + "Creating disk file of trk size %04x capacity %d\n", + tsize*ssize, cap*ssize); /* write zeros to each track of the disk */ for (cyl = 0; cyl < cylv; cyl++) { - if ((sim_fwrite(buff, 1, tsize, uptr->fileref)) != tsize) { - sim_debug(DEBUG_CMD, dptr, "Error on write to diskfile cyl %04x\n", cyl); + if ((sim_fwrite(buff, 1, tsize*ssize, uptr->fileref)) != tsize*ssize) { + sim_debug(DEBUG_CMD, dptr, + "Error on write to diskfile cyl %04x\n", cyl); } if (cyl == 0) { buff[0] = 0; @@ -977,10 +1006,11 @@ 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 = find_dev_from_unit(uptr); +// DEVICE *dptr = get_dev(uptr); t_stat r; -// uint16 tsize; /* track size in bytes */ - uint16 ssize; /* sector size in bytes */ + uint32 tsize; /* track size in bytes */ + uint32 ssize; /* sector size in bytes */ + uint32 csize, tdisk; struct ddata_t *data; uint8 buff[1024]; @@ -1002,14 +1032,15 @@ t_stat scfi_attach(UNIT *uptr, CONST char *file) { uptr->up7 = (void *)data; /* save pointer to structure in up7 */ /* track size in bytes is sectors/track times words/sector time 4 bytse/word */ -// tsize = scfi_type[type].spt * scfi_type[type].ssiz * 4; /* get track size in bytes */ - uptr->capac = scfi_type[type].taus * scfi_type[type].spau; /* disk capacity in sectors */ ssize = scfi_type[type].ssiz * 4; /* disk sector size in bytes */ - uptr->capac *= ssize; /* disk capacity 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 */ - sim_debug(DEBUG_CMD, dptr, "Disk taus %d spau %d ssiz %d cap %d\n", - scfi_type[type].taus, scfi_type[type].spau, scfi_type[type].ssiz * 4, - 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 */ @@ -1039,15 +1070,21 @@ 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 */ - sim_debug(DEBUG_CMD, &sda_dev, "Attach %8s hds %d spt %d spc %d cyl %d capacity %d\n", + 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); - sim_debug(DEBUG_CMD, &sda_dev, "File %s attached to %s\r\n", file, scfi_type[type].name); + + sim_debug(DEBUG_CMD, &sda_dev, "File %s attached to %s\r\n", + file, scfi_type[type].name); set_devattn(addr, SNS_DEVEND); return SCPE_OK; @@ -1061,7 +1098,7 @@ t_stat scfi_detach(UNIT *uptr) { free(data); /* free disk data structure */ } uptr->up7 = 0; /* no pointer to disk data */ - uptr->CMD &= ~0xffff; /* no cmd and flags */ + uptr->CMD &= ~0xffff; /* no cmd and flags */ return detach_unit(uptr); /* tell simh we are done with disk */ } @@ -1070,7 +1107,7 @@ t_stat scfi_boot(int32 unit_num, DEVICE *dptr) { UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */ sim_debug(DEBUG_CMD, &sda_dev, "SCFI Disk Boot dev/unit %04x\n", GET_UADDR(uptr->CMD)); - SPAD[0xf4] = GET_UADDR(uptr->CMD); /* put boot device chan/sa into spad */ + SPAD[0xf4] = GET_UADDR(uptr->CMD); /* put boot device chan/sa into spad */ SPAD[0xf8] = 0xF000; /* show as F class device */ if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ @@ -1082,17 +1119,20 @@ t_stat scfi_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { int i; - if (cptr == NULL) - return SCPE_ARG; - if (uptr == NULL) - return SCPE_IERR; - if (uptr->flags & UNIT_ATT) - return SCPE_ALATT; + if (cptr == NULL) /* any disk name input? */ + return SCPE_ARG; /* arg error */ + if (uptr == NULL) /* valid unit? */ + 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; - uptr->flags |= SET_TYPE(i); - uptr->capac = scfi_type[i].taus * scfi_type[i].spau; + 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; return SCPE_OK; } } @@ -1125,11 +1165,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].taus * scfi_type[i].spau; - int32 ssize = scfi_type[i].ssiz * 4; /* disk sector size in bytes */ - int32 size = capac * ssize; /* disk capacity in bytes */ - size /= 1024; /* make KB */ - size = (10 * size) / 1024; /* size in MB * 10 */ + 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 */ + 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); } fprint_set_help(st, dptr); diff --git a/SEL32/tests/diag.ini b/SEL32/tests/diag.ini index b056539..26b445b 100644 --- a/SEL32/tests/diag.ini +++ b/SEL32/tests/diag.ini @@ -1,33 +1,45 @@ +; Set debug output set debug -n sel.log -;set RTC 50 -set RTC 60 -;set RTC debug=cmd -;set ITM debug=cmd +;set debug stderr +; +; CPU type and memory +; Bad on UTX +;set CPU 32/27 2M ;set CPU 32/27 4M ;set CPU 32/87 4M ;set CPU 32/67 4M +;End of Bad ;set CPU 32/97 4M set CPU V6 4M +;set CPU V6 8M ;set CPU V9 4M -;set debug stderr -;set mta debug=cmd;detail;exp;data -;set mta debug=inst;cmd;detail;exp -;set inq debug=cmd;detail -;set cpu debug=cmd;exp -;set cpu debug=exp;irq -;set cpu debug=irq -;set cpu debug=inst;cmd;exp;irq -;set cpu debug=cmd;exp;inst;detail;data -;set cpu debug=cmd;exp;inst;detail -;set cpu debug=cmd;exp;irq -;set con debug=exp -;set con debug=cmd;exp -;set con debug=cmd;exp;data -;set mta debug=cmd;exp;inst;data;detail -;set mta debug=cmd;exp -;set dma debug=cmd;exp;detail;data -;set dma debug=cmd;exp;detail;data +;set CPU V9 8M ; +; CPU debug options +;set cpu debug=cmd;exp;inst;detail;trap;xio;irq +; Set instruction trace history size +;set cpu history=10000 +; useful options +;set cpu debug=cmd;exp +;set cpu debug=cmd;exp;irq;trap;xio +;set cpu debug=cmd;irq;trap;exp +;set cpu debug=irq;trap;exp;xio +;set cpu debug=irq;xio +; +; RTC realtime clock +set RTC 50 +;set RTC 60 +; RTC debug options +;set RTC debug=cmd +; +; ITM interval timer +;set ITM debug=cmd +; +; IOP +;set iop debug=cmd +; +; COM 8-Line +;set com debug=cmd; ;set coml0 enable ;set coml1 enable ;set coml2 enable @@ -37,30 +49,119 @@ set CPU V6 4M ;set coml6 enable ;set coml7 enable ; +; Enable telnet sessions on port 4747 ;set comc enable ;at comc 4747 ; -;set con debug=CMD +; LPR +;set lpr debug=cmd;detail +set lpr enable +; LPR output file +at lpr lprout ; -;set lpr enable -;at lpr lprout +; CON Console +;set con debug=cmd;exp;detail +; useful options +;set con debug=cmd;exp; ; -;at mta0 mpxsdt4.tap -;at mta0 mpxsdt5.tap -;at sda0 diskfile4 -;at sda1 diskfile5 +; MTA Buffered tape processor +;set mta debug=cmd;exp;detail;data +; useful options +;set mta debug=cmd;detail;exp ; +; enable MTA to change channel +set mta enable +; set mta channel +set mta0 dev=1000 + +; Attach in/out tape files +;at mta0 mpxsdt.tap +;at mta0 nbctape.tap +;at mta0 utx21a1.tap ;at mta0 sim32sdt.tap at mta0 diag.tap ;at mta1 temptape.tap ;at mta2 output.tap +; +; DMA disk processor II/UDP +; enable DMA to change channel +;set dma enable +; set disk chan to 0800 +;set dma0 dev=800 +; set disk type to MPX MH300 +;set dma0 type=MH300 +; set disk type to UTX 9346 +;set dma0 type=9346 +;set dma0 type=8155 +;set dma0 type=8887 +;set dma0 type=8148 +; +; Attach diskfile +;at dma0 utx0disk +;at dma0 utx1disk +;at dma0 sim32disk +;at dma debug=cmd;exp;detail;data ;at dma0 diagdisk -;bo dma0 -;set history=10000 +; useful options +;set dma debug=cmd;exp +;set dma debug=exp;cmd;detail +; +; SDA SCFI disk processor +;set sda debug=cmd;exp;data;detail +; Attach diskfiles +;at sda0 diskfile4 +;at sda1 diskfile5 +; +; DPA high speed disk processor +; enable the HSDP to change channel +;set dpa enable +; set channel addr +;set dpa dev=800 +; set disk type to UTX 8887 +;set dpa0 type=8887 +; +; Attach diskfiles +;at utxdsk.dsk +;at dpa0 utx0hsdp +;at dpa1 utx1hsdp +; +;set dpa debug=cmd;detail;exp +; useful options +;set dpa debug=cmd;exp +; +; set console switches deposit CSW 0 +; +;UTX boot tape options +;set GPR 7 to 0x00 to boot in multi-user mode +;set GPR 7 to 0x01 to prompt for unix filename +;set GPR 7 to 0x02 to boot in single user mode +;set GPR 7 to 0x10 to disable swapping and paging +;set GPR 7 to 0x20 to boot from device specified in GPR6 +;set GPR 7 to 0x40 to allow progress messages on boot +;deposit BOOTR[7] 40 +;deposit BOOTR[7] 52 +;deposit BOOTR[7] 42 +;deposit BOOTR[7] 2 +;deposit BOOTR[6] 800 +;deposit BOOTR[0] ffffffff + +; Set register content at boot for SEL diagnostics ; uncomment next line to get diag loader prompt ;deposit bootr[0] ffffffff deposit bootr[1] 0 deposit bootr[2] 0 +; +; allow cpu idle +set cpu idle +; Set expect script for auto time entry on MPX at OPCOM prompt +;expect haltafter=20000 +; wait for expected output from simulator, then enter this text +;expect "??" send " %DATE_MM%/%DATE_DD%/%DATE_YY%,%TIME_HH%:%TIME_MM%:%TIME_SS%\r"; GO +; +; Boot from disk +;bo dpa0 +;bo dma0 +; ; Boot from mag tape bo mta0