diff --git a/SEL32/sel32_chan.c b/SEL32/sel32_chan.c index 27e89d8..4cfb0fb 100644 --- a/SEL32/sel32_chan.c +++ b/SEL32/sel32_chan.c @@ -412,7 +412,8 @@ loop: /* Check if not chaining data */ if ((chp->ccw_flags & FLAG_DC) == 0) { chp->ccw_cmd = (word >> 24) & 0xff; /* not DC, so set command from IOCD wd 1 */ - sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw No DC, flags %04x cmd %02x\n", chp->ccw_flags, chp->ccw_cmd); + sim_debug(DEBUG_EXP, &cpu_dev, + "load_ccw No DC, flags %04x cmd %02x\n", chp->ccw_flags, chp->ccw_cmd); docmd = 1; /* show we have a command */ } /* Set up for this command */ @@ -449,6 +450,15 @@ loop: if (uptr == 0) return 1; /* if none, error */ +#ifdef DO_DYNAMIC_DEBUG + if ((chp->chan_dev == 0x1000) && ((chp->ccw_cmd & 0xff) == 0x80)) { + uint32 addr = chp->ccw_addr; /* set the data address */ + /* start debugging */ + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP); + sim_debug(DEBUG_CMD, &cpu_dev, "cmd 80 MT wds @ addr %08x %08x %08x %08x %08x\n", + addr, M[addr>>2], M[(addr+4)>>2], M[(addr+8)>>2], M[(addr+12)>>2]); + } +#endif #ifndef CON_BUG #ifdef DO_DYNAMIC_DEBUG if ((chp->chan_dev == 0x7efc) && ((chp->ccw_cmd & 0xff) == 0x03) && (chp->ccw_count == 0)) @@ -969,13 +979,13 @@ t_stat startxio(uint16 lchsa, uint32 *status) { /* start processing the IOCL */ if (load_ccw(chp, 0) || (chp->chan_status & STATUS_PCI)) { /* we have an error or user requested interrupt, return status */ - store_csw(chp); /* store the status in the inch status dw */ - sim_debug(DEBUG_CMD, &cpu_dev, "startxio store csw CC1 chan %04x status %08x\n", + sim_debug(DEBUG_CMD, &cpu_dev, "startxio store csw CC2 chan %04x status %08x\n", chan, chp->chan_status); + store_csw(chp); /* store the status in the inch status dw */ chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ dev_status[chsa] = 0; /* no device status */ - *status = CC1BIT; /* status stored, so CC1 */ - return SCPE_OK; /* CC1 (0x40) status stored */ + *status = CC2BIT; /* status stored, so CC2 */ + return SCPE_OK; /* CC2 (0x20) status stored */ } *status = CC1BIT; /* CCs = 1, SIO accepted & queued, will not echo status */ diff --git a/SEL32/sel32_cpu.c b/SEL32/sel32_cpu.c index ff22f96..69c5439 100644 --- a/SEL32/sel32_cpu.c +++ b/SEL32/sel32_cpu.c @@ -5824,7 +5824,7 @@ newpsd: } /* do not update pc for page fault */ case DEMANDPG_TRAP: /* 0xC4 Demand Page Fault Trap (V6&V9 Only) */ -#ifndef DO_DYNAMIC_DEBUG +#ifdef DO_DYNAMIC_DEBUG /* start debugging */ if (TRAPME == DEMANDPG_TRAP) cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); diff --git a/SEL32/sel32_defs.h b/SEL32/sel32_defs.h index bd45426..9c356a6 100644 --- a/SEL32/sel32_defs.h +++ b/SEL32/sel32_defs.h @@ -111,10 +111,12 @@ #define NUM_UNITS_MT 4 /* 4 of 8 devices */ #define NUM_DEVS_DISK 1 /* 1 DP02 disk drive controller */ #define NUM_UNITS_DISK 4 /* 4 disk drive devices */ -//#define NUM_DEVS_SCFI 1 /* 1 scfi (SCSI) disk drive units */ -//#define NUM_UNITS_SCFI 1 /* 1 of 4 disk drive devices */ -#define NUM_DEVS_SCFI 2 /* 2 scfi (SCSI) disk drive units */ -#define NUM_UNITS_SCFI 2 /* 2 of 4 disk drive devices */ +#define NUM_DEVS_HSDP 1 /* 1 HSPD disk drive controller */ +#define NUM_UNITS_HSDP 2 /* 2 disk drive devices */ +#define NUM_DEVS_SCFI 1 /* 1 scfi (SCSI) disk drive units */ +#define NUM_UNITS_SCFI 1 /* 1 of 4 disk drive devices */ +//#define NUM_DEVS_SCFI 2 /* 2 scfi (SCSI) disk drive units */ +//#define NUM_UNITS_SCFI 2 /* 2 of 4 disk drive devices */ #define NUM_DEVS_RTOM 1 /* 1 IOP RTOM channel */ #define NUM_UNITS_RTOM 1 /* 1 IOP RTOM device (clock & interval timer) */ #define NUM_DEVS_LPR 1 /* 1 IOP Line printer */ @@ -144,6 +146,12 @@ extern DEVICE dda_dev; #if NUM_DEVS_DISK > 1 extern DEVICE ddb_dev; #endif +#ifdef NUM_DEVS_HSDP +extern DEVICE dpa_dev; +#endif +#if NUM_DEVS_HSDP > 1 +extern DEVICE dpb_dev; +#endif #ifdef NUM_DEVS_SCFI extern DEVICE sda_dev; #endif diff --git a/SEL32/sel32_disk.c b/SEL32/sel32_disk.c index 782326c..9c0a83a 100644 --- a/SEL32/sel32_disk.c +++ b/SEL32/sel32_disk.c @@ -1,6 +1,6 @@ -/* sel32_disk.c: SEL-32 2311/2314 Disk controller +/* sel32_disk.c: SEL-32 2311/2314 Disk Processor II - Copyright (c) 2018, James C. Bevier + Copyright (c) 2018-2019, James C. Bevier Portions provided by Richard Cornwell and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a @@ -32,15 +32,15 @@ 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 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 SET_TYPE(x) (UNIT_TYPE & ((x) << UNIT_V_TYPE)) #define UNIT_DISK UNIT_ATTABLE | UNIT_IDLE /* INCH command information */ @@ -83,89 +83,89 @@ 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 /* Flag to send a CUE */ /* 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_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_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 holds drive attribute entry */ @@ -191,24 +191,24 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option /* allocated during attach command for each unit defined */ struct ddata_t { - int16 cyl; /* Cylinder head at */ - uint16 tpos; /* Track position */ - uint16 spos; /* Sector position */ + uint16 cyl; /* Cylinder head at */ + uint16 tpos; /* Track position */ + uint16 spos; /* Sector position */ }; /* disk definition structure */ 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 */ - uint8 type; /* Device type code */ + 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 */ + uint8 type; /* Device type code */ } disk_type[] = { @@ -222,8 +222,8 @@ disk_type[] = /* Class F Disc Devices */ {"FL001", 1334, 0, 2, 64, 26, 3, 3, 26, 0x40}, /* 1 M */ - {"MH040", 20000, 625, 5, 192, 20, 2, 1, 40, 0x40}, /* 40 M */ - {"MH080", 40000, 1250, 5, 192, 20, 2, 1, 80, 0x40}, /* 80 M */ + {"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 */ {"FH005", 5120, 184, 4, 192, 20, 1, 1, 64, 0x80}, /* 5 M */ {"CD032", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /* 32 M */ @@ -232,8 +232,8 @@ disk_type[] = {"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, 80, 0x40}, /* 600 M */ - {"FM600", 80000, 2500, 40, 192, 20, 8, 1, 80, 0x40}, /* 600 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} }; @@ -322,20 +322,20 @@ UNIT dda_unit[] = { }; DIB dda_dib = { - disk_preio, /* Pre start I/O */ - disk_startcmd, /* Start a command */ - NULL, /* Stop I/O */ - NULL, /* Test I/O */ - NULL, /* Post I/O */ - disk_ini, /* init function */ - 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 */ - 0x0800, /* parent channel address */ - 0, /* fifo input index */ - 0, /* fifo output index */ - 0, /* interrupt status fifo for channel */ + disk_preio, /* Pre start I/O */ + disk_startcmd, /* Start a command */ + NULL, /* Stop I/O */ + NULL, /* Test I/O */ + NULL, /* Post I/O */ + disk_ini, /* init function */ + 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 */ + 0x0800, /* parent channel address */ + 0, /* fifo input index */ + 0, /* fifo output index */ + 0, /* interrupt status fifo for channel */ }; DEVICE dda_dev = { @@ -364,20 +364,20 @@ UNIT ddb_unit[] = { DIB ddb_dib = { - disk_preio, /* Pre Start I/O */ - disk_startcmd, /* Start a command SIO */ - NULL, /* Stop I/O HIO */ - NULL, /* Test I/O TIO */ - NULL, /* Post I/O */ - disk_ini, /* init function */ - 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 */ - 0x0C00, /* parent channel address */ - 0, /* fifo input index */ - 0, /* fifo output index */ - 0, /* interrupt status fifo for channel */ + disk_preio, /* Pre Start I/O */ + disk_startcmd, /* Start a command SIO */ + NULL, /* Stop I/O HIO */ + NULL, /* Test I/O TIO */ + NULL, /* Post I/O */ + disk_ini, /* init function */ + 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 */ + 0x0C00, /* parent channel address */ + 0, /* fifo input index */ + 0, /* fifo output index */ + 0, /* interrupt status fifo for channel */ }; DEVICE ddb_dev = { @@ -395,12 +395,12 @@ uint8 disk_preio(UNIT *uptr, uint16 chan) DEVICE *dptr = find_dev_from_unit(uptr); int unit = (uptr - dptr->units); - if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */ + if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */ return SNS_BSY; } - sim_debug(DEBUG_CMD, dptr, "dsk_preio unit=%d OK\n", unit); - return 0; /* good to go */ + sim_debug(DEBUG_CMD, dptr, "dsk_preio unit=%02x OK\n", unit); + return 0; /* good to go */ } uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) @@ -410,60 +410,60 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) int unit = (uptr - dptr->units); uint8 ch; - sim_debug(DEBUG_CMD, dptr, "disk_startcmd unit %d cmd %x CMD %x\n", unit, cmd, uptr->CMD); - if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ - uptr->SNS |= SNS_INTVENT; /* unit intervention required */ - if (cmd != DSK_SNS) /* we are completed with unit check status */ + sim_debug(DEBUG_CMD, dptr, "disk_startcmd unit %02x cmd %02x CMD %08x\n", unit, cmd, uptr->CMD); + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + uptr->SNS |= SNS_INTVENT; /* unit intervention required */ + if (cmd != DSK_SNS) /* we are completed with unit check status */ 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, "disk_startcmd CMD continue unit=%d cmd %02x\n", unit, cmd); + sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD continue unit=%02x cmd %02x\n", unit, cmd); - if ((uptr->flags & UNIT_ATT) == 0) { /* see if unit is attached */ - if (cmd == DSK_SNS) { /* not attached, is cmd Sense 0x04 */ + if ((uptr->flags & UNIT_ATT) == 0) { /* see if unit is attached */ + if (cmd == DSK_SNS) { /* not attached, is cmd Sense 0x04 */ sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD sense\n"); /* bytes 0,1 - Cyl entry from STAR reg in STAR */ ch = (uptr->STAR >> 24) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b0 unit=%d 1 %x\n", + sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b0 unit=%02x 1 %02x\n", unit, ch); chan_write_byte(addr, &ch) ; ch = (uptr->STAR >> 16) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b1 unit=%d 1 %x\n", + sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b1 unit=%02x 1 %02x\n", unit, ch); chan_write_byte(addr, &ch) ; /* byte 2 - Track entry from STAR reg in STAR */ ch = (uptr->STAR >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b2 unit=%d 1 %x\n", + sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b2 unit=%02x 1 %02x\n", unit, ch); chan_write_byte(addr, &ch) ; /* byte 3 - Sector entry from STAR reg in STAR */ ch = (uptr->STAR) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b3 unit=%d 1 %x\n", + sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b3 unit=%02x 1 %02x\n", unit, ch); chan_write_byte(addr, &ch) ; /* bytes 4 - mode reg, byte 0 of SNS */ - ch = (uptr->SNS >> 24) & 0xff; /* return the sense data for device */ - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%d 1 %x\n", + ch = (uptr->SNS >> 24) & 0xff; /* return the sense data for device */ + sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%02x 1 %02x\n", unit, ch); chan_write_byte(addr, &ch) ; /* bytes 5-7 - status bytes, bytes 1-3 of SNS */ ch = (uptr->SNS >> 16) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%d 2 %x\n", + sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%02x %02x\n", unit, ch); chan_write_byte(addr, &ch) ; ch = (uptr->SNS >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%d 3 %x\n", + sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%02x 3 %02x\n", unit, ch); chan_write_byte(addr, &ch) ; ch = (uptr->SNS) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%d 4 %x\n", + 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 @@ -477,17 +477,17 @@ uint8 disk_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 == 0x0) /* INCH cmd gives unit check here */ + if (cmd == 0x0) /* INCH cmd gives unit check here */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - uptr->SNS |= (SNS_INTVENT|SNS_CMDREJ); /* set new error status */ + uptr->SNS |= (SNS_INTVENT|SNS_CMDREJ); /* set new error status */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* we done */ } @@ -496,10 +496,10 @@ uint8 disk_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, "disk_startcmd starting inch cmd addr %x STAR %x\n", + 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); /* 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 */ @@ -507,55 +507,56 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) /* 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 */ + 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, - "disk_startcmd starting inch cmd addr %x STAR %x mema %x units %d\n", + "disk_startcmd starting inch cmd addr %04x STAR %08x mema %08x units %02x\n", addr, uptr->STAR, mema, dptr->numunits); /* the next 8 words have drive data for each unit */ /* WARNING 8 drives must be defined for this controller */ /* so we will not have a map fault */ - for (i=0; inumunits && i<8; i++) { /* process all drives */ - up->ATTR = M[(mema>>2)+i+1]; /* save each unit's drive data */ - sim_debug(DEBUG_CMD, dptr, "disk_startcmd ATTR data %x unit %x flags %x sec %x MHD %x FHD %x\n", + for (i=0; inumunits && i<8; i++) { /* process all drives */ + up->ATTR = M[(mema>>2)+i+1]; /* save each unit's drive data */ + sim_debug(DEBUG_CMD, dptr, + "disk_startcmd ATTR data %08x unit %02x flags %02x sec %02x MHD %02x FHD %02x\n", up->ATTR, i, (up->ATTR >> 24)&0xff, (up->ATTR >> 16)&0xff, (up->ATTR >> 8)&0xff, (up->ATTR&0xff)); - up++; /* next unit for this device */ + up++; /* next unit for this device */ } - sim_debug(DEBUG_CMD, dptr, "disk_startcmd done inch cmd addr %x\n", addr); - uptr->CMD |= DSK_CMDMSK; /* use 0xff for inch, just need int */ - sim_activate(uptr, 20); /* start things off */ + sim_debug(DEBUG_CMD, dptr, "disk_startcmd done inch cmd addr %04x\n", addr); + uptr->CMD |= DSK_CMDMSK; /* use 0xff for inch, just need int */ + sim_activate(uptr, 20); /* start things off */ return 0; } - case DSK_SCK: /* Seek command 0x07 */ - case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ - uptr->CMD &= ~(DSK_STAR); /* show we do not have seek STAR in STAR */ - case DSK_WD: /* Write command 0x01 */ - case DSK_RD: /* Read command 0x02 */ - case DSK_LMR: /* read mode register */ + case DSK_SCK: /* Seek command 0x07 */ + case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ + uptr->CMD &= ~(DSK_STAR); /* show we do not have seek STAR in STAR */ + case DSK_WD: /* Write command 0x01 */ + case DSK_RD: /* Read command 0x02 */ + case DSK_LMR: /* read mode register */ - uptr->CMD |= cmd; /* save cmd */ + uptr->CMD |= cmd; /* save cmd */ sim_debug(DEBUG_CMD, dptr, - "disk_startcmd starting disk seek r/w cmd %x addr %x\n", cmd, addr); - sim_activate(uptr, 20); /* start things off */ + "disk_startcmd starting disk seek r/w cmd %02x addr %04x\n", cmd, addr); + sim_activate(uptr, 20); /* start things off */ return 0; - case DSK_NOP: /* NOP 0x03 */ - uptr->CMD |= cmd; /* save cmd */ - sim_activate(uptr, 20); /* start things off */ + case DSK_NOP: /* NOP 0x03 */ + uptr->CMD |= cmd; /* save cmd */ + sim_activate(uptr, 20); /* start things off */ return 0; - case DSK_SNS: /* Sense 0x04 */ - uptr->CMD |= cmd; /* save cmd */ - sim_activate(uptr, 20); /* start things off */ + case DSK_SNS: /* Sense 0x04 */ + uptr->CMD |= cmd; /* save cmd */ + sim_activate(uptr, 20); /* start things off */ break; } sim_debug(DEBUG_CMD, dptr, - "disk_startcmd done with disk_startcmd %x addr %x SNS %x\n", + "disk_startcmd done with disk_startcmd %02x addr %04x SNS %08x\n", cmd, addr, uptr->SNS); - if (uptr->SNS & 0xff) /* any other cmd is error */ + if (uptr->SNS & 0xff) /* any other cmd is error */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 20); /* start things off */ return SNS_CHNEND|SNS_DEVEND; } @@ -565,7 +566,7 @@ t_stat disk_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 */ + /* 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; @@ -576,57 +577,57 @@ t_stat disk_srv(UNIT * uptr) 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 ssize = disk_type[type].ssiz * 4; /* disk sector size in bytes */ int tstart; uint8 buf2[768]; uint8 buf[768]; sim_debug(DEBUG_DETAIL, &dda_dev, - "disk_srv entry unit %d cmd %x chsa %x chan %x count %x\n", + "disk_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 */ - uptr->SNS |= SNS_INTVENT; /* unit intervention required */ - if (cmd != DSK_SNS) /* we are completed with unit check status */ + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + uptr->SNS |= SNS_INTVENT; /* unit intervention required */ + if (cmd != DSK_SNS) /* we are completed with unit check status */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; } - sim_debug(DEBUG_CMD, dptr, "disk_srv cmd=%x chsa %04x count %x\n", + 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_CMDMSK: /* use 0xff for inch, just need int */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ - sim_debug(DEBUG_CMD, dptr, "disk_srv cmd=%x chsa %04x count %x completed\n", + uptr->CMD &= ~(0xffff); /* remove old cmd */ + sim_debug(DEBUG_CMD, dptr, "disk_srv cmd=%02x chsa %04x count %04x completed\n", cmd, chsa, chp->ccw_count); #ifdef FIX4MPX - chan_end(chsa, SNS_CHNEND); /* return just channel end OK */ + chan_end(chsa, SNS_CHNEND); /* return just channel end OK */ #else chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ #endif break; case DSK_NOP: /* NOP 0x03 */ - uptr->CMD &= ~(0xffff); /* remove old cmd */ - sim_debug(DEBUG_CMD, dptr, "disk_srv cmd=%x chsa %04x count %x completed\n", - cmd, chsa, chp->ccw_count); + 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 */ ch = uptr->SNS & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%d 1 %x\n", unit, ch); + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%02x 1 %02x\n", unit, ch); chan_write_byte(chsa, &ch) ; ch = (uptr->SNS >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%d 2 %x\n", unit, ch); + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%02x 2 %02x\n", unit, ch); chan_write_byte(chsa, &ch) ; ch = 0; - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%d 3 %x\n", unit, ch); + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%02x 3 %02x\n", unit, ch); chan_write_byte(chsa, &ch) ; ch = unit; - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%d 4 %x\n", unit, ch); + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%02x 4 %02x\n", unit, ch); chan_write_byte(chsa, &ch) ; ch = 4; uptr->CMD &= ~(0xff00); @@ -640,11 +641,11 @@ t_stat disk_srv(UNIT * uptr) /* see if on cylinder yet */ if ((uptr->STAR >> 16) == data->cyl) { /* we are on cylinder, seek is done */ - sim_debug(DEBUG_CMD, dptr, "dsk_srv seek on cylinder unit=%d %d %d\n", + 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=%d %x %x\n", + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek end unit=%02x %02x %04x\n", unit, uptr->STAR >> 16, data->cyl); sim_activate(uptr, 20); break; @@ -652,7 +653,7 @@ t_stat disk_srv(UNIT * uptr) /* Compute delay based of difference. */ /* Set next state = index */ i = (uptr->STAR >> 16) - data->cyl; - sim_debug(DEBUG_CMD, dptr, "dsk_srv seek unit=%d %x %x\n", unit, + sim_debug(DEBUG_CMD, dptr, "dsk_srv seek unit=%02x %02x %04x\n", unit, uptr->STAR >> 16, i); if (i > 0 ) { if (i > 50) { @@ -683,7 +684,7 @@ t_stat disk_srv(UNIT * uptr) if (data->cyl < 0) /* test for less than zero */ data->cyl = 0; /* make zero */ } - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek next unit=%d %d %d\n", + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek next unit=%02x %02x %04x\n", unit, uptr->STAR >> 16, data->cyl); sim_activate(uptr, 2); break; @@ -695,21 +696,21 @@ t_stat disk_srv(UNIT * uptr) 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->CMD &= ~(0xffff); /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } } rezero: - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek unit=%d star %02d%02d %02d %02d\n", + sim_debug(DEBUG_DETAIL, dptr, "dsk_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 */ - trk = buf[2]; /* get the track */ + cyl = uptr->STAR >> 16; /* get the cylinder */ + trk = buf[2]; /* get the track */ sim_debug(DEBUG_DETAIL, dptr, - "dsk_srv SEEK cyl %d trk %d sec %d unit=%d\n", cyl&0xffff, trk, buf[3], unit); + "dsk_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 */ @@ -717,9 +718,9 @@ rezero: trk >= disk_type[type].nhds || buf[3] > disk_type[type].spt) { sim_debug(DEBUG_CMD, dptr, - "dsk_srv seek ERROR cyl %x trk %x sec %x unit=%d\n", + "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->CMD &= ~(0xffff); /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; /* set error status */ /* we have an error, tell user */ @@ -727,31 +728,31 @@ 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 */ tstart = (cyl * disk_type[type].nhds * tsize) + (trk * tsize) + (buf[3] * 0x300); - 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 %x trk %x sec %x\n", + 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, "dsk_srv Error on seek to %x\n", tstart); + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv Error on seek to %04x\n", tstart); } /* Check if already on correct cylinder */ if (trk != data->cyl) { /* Do seek */ - uptr->CMD |= DSK_SEEKING; /* show we are seeking */ - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek unit=%d trk %x cyl %x\n", + 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); } else { sim_debug(DEBUG_DETAIL, dptr, - "dsk_srv calc sect addr seek start %x trk %x sec %x\n", + "dsk_srv calc sect addr seek start %04x trk %02x sec %02x\n", tstart, trk, buf[3]); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ sim_activate(uptr, 20); chan_end(chsa, SNS_DEVEND|SNS_CHNEND); } @@ -759,88 +760,88 @@ rezero: case DSK_XEZ: /* Rezero & Read IPL record */ - sim_debug(DEBUG_CMD, dptr, "RD REZERO IPL unit=%d seek 0\n", unit); + 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_SCK; /* show as seek command */ - tstart = 0; /* byte offset is 0 */ + 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 */ /* 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; } /* zero stuff */ buf[0] = buf[1] = buf[2] = buf[3] = 0; - goto rezero; /* murge with seek code */ + goto rezero; /* murge with seek code */ break; case DSK_LMR: - sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%d\n", unit); + sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x\n", unit); /* Read in 1 character of mode data */ if (chan_read_byte(chsa, &buf[0])) { /* 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 */ - 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 */ sim_debug(DEBUG_CMD, dptr, - "DISK READ starting unit=%d CMD %x\n", unit, uptr->CMD); + "DISK READ starting unit=%02x CMD %02x\n", unit, uptr->CMD); } - 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 %d on read %d of diskfile cyl %d hds %d sec %d\n", - len, ssize, data->cyl, data->tpos, data->spos); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + "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 */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } sim_debug(DEBUG_CMD, dptr, - "disk_srv after READ chsa %04x count %x\n", chsa, chp->ccw_count); + "disk_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); - 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; } } sim_debug(DEBUG_CMD, dptr, -"DISK READ from sec end bytes end %d from diskfile cyl %d hds %d sec %d\n", - ssize, data->cyl, data->tpos, data->spos); + "DISK READ from sec end bytes end %04x from diskfile cyl %04x hds %02x sec %02\n", + ssize, data->cyl, data->tpos, data->spos); data->spos++; /* set sector to read next one */ if (data->spos >= (disk_type[type].spt)) { - data->spos = 0; /* number of sectors per track */ - data->tpos++; /* track position */ + data->spos = 0; /* number of sectors per track */ + data->tpos++; /* track position */ if (data->tpos >= (disk_type[type].nhds)) { - data->tpos = 0; /* number of tracks per cylinder */ - data->cyl++; /* cylinder position */ + data->tpos = 0; /* number of tracks per cylinder */ + data->cyl++; /* cylinder position */ if (data->cyl >= (int)(disk_type[type].cyl)) { /* EOM reached, abort */ - 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; } @@ -849,73 +850,73 @@ rezero: /* see if we are done reading data */ if (test_write_byte_end(chsa)) { sim_debug(DEBUG_DATAIO, dptr, - "DISK Read complete Read bytes from diskfile cyl %d hds %d sec %d\n", - data->cyl, data->tpos, data->spos); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + "DISK Read complete Read bytes from diskfile cyl %04x hds %02x sec %02x\n", + data->cyl, data->tpos, data->spos); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); } rddone: - sim_activate(uptr, 10); /* wait to read next sector */ + sim_activate(uptr, 10); /* wait to read next sector */ break; } break; case DSK_WD: /* Write Data */ - if ((uptr->CMD & DSK_WRITING) == 0) { /* see if we are writing data */ - uptr->CMD |= DSK_WRITING; /* write to disk starting */ + if ((uptr->CMD & DSK_WRITING) == 0) { /* see if we are writing data */ + uptr->CMD |= DSK_WRITING; /* write to disk starting */ sim_debug(DEBUG_CMD, dptr, - "DISK WRITE starting unit=%d CMD %x\n", unit, uptr->CMD); + "DISK WRITE starting unit=%02x CMD %02x\n", unit, uptr->CMD); } - if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */ + if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */ /* process the next sector of data */ - len = 0; /* used here as a flag for short read */ + len = 0; /* used here as a flag for short read */ for (i=0; iCMD &= ~(0xffff); /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, - "DISK Wrote bytes to diskfile cyl %d hds %d sec %d\n", - data->cyl, data->tpos, data->spos); + "DISK Wrote %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", + ssize, data->cyl, data->tpos, data->spos); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); goto wrdone; } - ch = 0; /* finish out the sector with zero */ - len++; /* show we have no more data to write */ + ch = 0; /* finish out the sector with zero */ + len++; /* show we have no more data to write */ } - buf2[i] = ch; /* save the char */ + buf2[i] = ch; /* save the char */ } /* write the sector to disk */ if ((i=sim_fwrite(buf2, 1, ssize, uptr->fileref)) != ssize) { sim_debug(DEBUG_CMD, dptr, - "Error %d on write %d to diskfile cyl %d hds %d sec %d\n", + "Error %08x on write %04x bytes 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; } - if (len != 0) { /* see if done with write command */ + if (len != 0) { /* see if done with write command */ sim_debug(DEBUG_DATAIO, dptr, - "DISK WroteB bytes to diskfile cyl %d hds %d sec %d\n", - data->cyl, data->tpos, data->spos); - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + "DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", + 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; } sim_debug(DEBUG_CMD, dptr, - "DISK WR to sec end bytes end %d to diskfile cyl %d hds %d sec %d\n", - ssize, data->cyl, data->tpos, data->spos); + "DISK WR to sec end %0x4x bytes end %04x to diskfile cyl %04x hds %02x sec %02x\n", + len, ssize, data->cyl, data->tpos, data->spos); data->spos++; if (data->spos >= (disk_type[type].spt)) { - data->spos = 0; /* number of sectors per track */ - data->tpos++; /* track position */ + data->spos = 0; /* number of sectors per track */ + data->tpos++; /* track position */ if (data->tpos >= (disk_type[type].nhds)) { - data->tpos = 0; /* number of tracks per cylinder */ - data->cyl++; /* cylinder position */ + data->tpos = 0; /* number of tracks per cylinder */ + data->cyl++; /* cylinder position */ if (data->cyl >= (int)(disk_type[type].cyl)) { /* EOM reached, abort */ sim_debug(DEBUG_DETAIL, dptr, - "Error %d on write %d to diskfile cyl %d hds %d sec %d\n", + "Error %08x on write %04x to diskfile cyl %04x hds %02x sec %02x\n", i, ssize, data->cyl, data->tpos, data->spos); uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); @@ -930,14 +931,14 @@ wrdone: break; default: - sim_debug(DEBUG_DETAIL, dptr, "invalid command=%d %x\n", unit, cmd); + 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; } - sim_debug(DEBUG_DETAIL, dptr, "disk_srv done cmd=%x chsa %04x count %x\n", - cmd, chsa, chp->ccw_count); + sim_debug(DEBUG_DETAIL, dptr, "disk_srv done cmd=%02x chsa %04x count %04x\n", + cmd, chsa, chp->ccw_count); return SCPE_OK; } @@ -947,7 +948,7 @@ void disk_ini(UNIT *uptr, t_bool f) DEVICE *dptr = find_dev_from_unit(uptr); int i = GET_TYPE(uptr->flags); - uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ + uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ /* capacity is total allocation units time sectors per allocation unit */ /* total sectors on disk */ uptr->capac = disk_type[i].taus * disk_type[i].spau; @@ -969,8 +970,8 @@ t_stat disk_attach(UNIT *uptr, CONST char *file) int type = GET_TYPE(uptr->flags); DEVICE *dptr = find_dev_from_unit(uptr); t_stat r; - uint16 tsize; /* track size in bytes */ - uint16 ssize; /* sector size in bytes */ + uint16 tsize; /* track size in bytes */ + uint16 ssize; /* sector size in bytes */ struct ddata_t *data; // uint8 buff[1024]; @@ -978,9 +979,9 @@ t_stat disk_attach(UNIT *uptr, CONST char *file) if ((r = attach_unit(uptr, file)) != SCPE_OK) return r; - if (disk_type[type].name == 0) { /* does the assigned disk have a name */ - detach_unit(uptr); /* no, reject */ - return SCPE_FMT; /* error */ + if (disk_type[type].name == 0) { /* does the assigned disk have a name */ + detach_unit(uptr); /* no, reject */ + return SCPE_FMT; /* error */ } /* get a buffer to hold disk_t structure */ @@ -990,25 +991,25 @@ t_stat disk_attach(UNIT *uptr, CONST char *file) return SCPE_FMT; } - uptr->DDATA = (void *)data; /* save pointer to structure in DDATA */ + 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 */ + /* disk capacity in sectors */ + ssize = disk_type[type].ssiz * 4; /* disk sector size in bytes */ + uptr->capac *= ssize; /* disk capacity 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 */ + 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 */ + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ } - data->tpos = 0; /* current track position */ - data->spos = 0; /* current sector position */ + data->tpos = 0; /* current track position */ + data->spos = 0; /* current sector position */ set_devattn(addr, SNS_DEVEND); return SCPE_OK; @@ -1019,22 +1020,22 @@ t_stat disk_detach(UNIT * uptr) { struct ddata_t *data = (struct ddata_t *)uptr->DDATA; if (data != 0) { - free(data); /* free disk data structure */ + free(data); /* free disk data structure */ } - uptr->DDATA = 0; /* no pointer to disk data */ - uptr->CMD &= ~0xffff; /* no cmd and flags */ - return detach_unit(uptr); /* tell simh we are done with disk */ + uptr->DDATA = 0; /* no pointer to disk data */ + uptr->CMD &= ~0xffff; /* no cmd and flags */ + return detach_unit(uptr); /* tell simh we are done with disk */ } /* boot from the specified disk unit */ t_stat disk_boot(int32 unit_num, DEVICE * dptr) { - UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */ + 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)); - SPAD[0xf4] = GET_UADDR(uptr->CMD); /* put boot device chan/sa into spad */ - SPAD[0xf8] = 0xF000; /* show as F class device */ + 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? */ + return SCPE_UNATT; /* attached? */ return chan_boot(GET_UADDR(uptr->CMD), dptr); /* boot the ch/sa */ } @@ -1074,7 +1075,7 @@ t_stat disk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { int i; - fprintf (st, "SEL 2314 Disk Processor\r\n"); + fprintf (st, "SEL 2314 Disk Processor II\r\n"); fprintf (st, "Use:\r\n"); fprintf (st, " sim> SET %sn TYPE=type\r\n", dptr->name); fprintf (st, "Type can be: "); @@ -1100,7 +1101,7 @@ t_stat disk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *disk_description (DEVICE *dptr) { - return "SEL 2314 Disk Processor"; + return "SEL 2314 Disk Processor II"; } #endif diff --git a/SEL32/sel32_hsdp.c b/SEL32/sel32_hsdp.c new file mode 100644 index 0000000..cea4671 --- /dev/null +++ b/SEL32/sel32_hsdp.c @@ -0,0 +1,1128 @@ +/* sel32_hsdp.c: SEL-32 8064 High Speed Disk Processor + + Copyright (c) 2018-2019, James C. Bevier + Portions provided by Richard Cornwell and other SIMH contributers + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + JAMES C. BEVIER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#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 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 + +/* 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 + +Memory attribute register layout +bits 0-7 - Flags + bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option + bit 2 - 1=Cartridge module drive + bit 3 - 0=Reserved + bit 4 - 1=Drive not present + bit 5 - 1=Dual Port + bit 6 - 0=Reserved + 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) +*/ + + +/* 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 +/* 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 */ +/* 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_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 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 */ + +/* 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 */ + +/* 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 */ + +/* 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 ATTR u6 +/* u6 holds drive attribute entry */ +/* provided by inch command for controller */ +/* +bits 0-7 - Flags + bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option + bit 2 - 1=Cartridge module drive + bit 3 - 0=Reserved + bit 4 - 1=Drive not present + bit 5 - 1=Dual Port + bit 6 - 0=Reserved + 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) +*/ + +#define DDATA up7 +/* Pointer held in up7 */ +/* sects/cylinder = sects/track * numhds */ +/* allocated during attach command for each unit defined */ +struct ddata_t +{ + uint16 cyl; /* Cylinder head at */ + uint16 tpos; /* Track position */ + uint16 spos; /* Sector position */ +}; + +/* disk definition structure */ +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 */ + uint8 type; /* Device type code */ +} +hsdp_type[] = +{ + /* Class F Disc Devices */ /*XX CYL SIZE */ + {"MH040", 20000, 625, 5, 256, 16, 2, 1, 400, 0x40}, /*0 411 40 M */ + {"MH080", 40000, 1250, 5, 256, 16, 2, 1, 800, 0x40}, /*1 823 80 M */ + {"MH160", 80000, 1250, 10, 256, 16, 4, 1, 1600, 0x40}, /*2 823 160 M */ + {"MH300", 76000, 2375, 19, 256, 16, 4, 1, 800, 0x40}, /*3 823 300 M */ + {"MH340", 76000, 2375, 24, 256, 16, 4, 1, 800, 0x40}, /*4 711 340 M */ + {"FH005", 5120, 184, 4, 256, 16, 1, 1, 64, 0x80}, /*5 64 5 M */ + {"CD032", 8000, 250, 1, 256, 16, 2, 1, 800, 0x60}, /*6 823 32 M */ + {"CD032", 8000, 250, 1, 256, 16, 2, 1, 800, 0x60}, /*7 823 32 M */ + {"CD064", 8000, 250, 1, 256, 16, 2, 1, 800, 0x60}, /*8 823 64 M */ + {"CD064", 24000, 750, 3, 256, 16, 2, 1, 800, 0x60}, /*9 823 64 M */ + {"CD096", 8000, 250, 1, 256, 16, 2, 1, 800, 0x60}, /*10 823 96 M */ + {"CD096", 40000, 1250, 5, 256, 16, 2, 1, 800, 0x60}, /*11 823 96 M */ + {"MH600", 80000, 2500, 40, 256, 16, 8, 1, 800, 0x40}, /*12 843 600 M */ + {"FM600", 80000, 2500, 40, 256, 16, 8, 1, 800, 0x40}, /*13 843 600 M */ + {"FM600", 1600, 50, 40, 256, 16, 1, 1, 2, 0x80}, /*14 10 600 M */ + {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); +t_stat hsdp_srv(UNIT *); +t_stat hsdp_boot(int32, DEVICE *); +void hsdp_ini(UNIT *, t_bool); +t_stat hsdp_reset(DEVICE *); +t_stat hsdp_attach(UNIT *, CONST char *); +t_stat hsdp_detach(UNIT *); +t_stat hsdp_set_type(UNIT * uptr, int32 val, CONST char *cptr, void *desc); +t_stat hsdp_get_type(FILE * st, UNIT * uptr, int32 v, CONST void *desc); +t_stat hsdp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +const char *hsdp_description (DEVICE *dptr); + +/* channel program information */ +CHANP dpa_chp[NUM_UNITS_HSDP] = {0}; + +MTAB hsdp_mod[] = { + {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "TYPE", "TYPE", + &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} +}; + +UNIT dpa_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 */ +}; + +DIB dpa_dib = { + hsdp_preio, /* Pre start I/O */ + hsdp_startcmd, /* Start a command */ + NULL, /* Stop I/O */ + NULL, /* Test I/O */ + NULL, /* Post I/O */ + hsdp_ini, /* init function */ + dpa_unit, /* Pointer to units structure */ + dpa_chp, /* Pointer to chan_prg structure */ + NUM_UNITS_HSDP, /* number of units defined */ + 0x0F, /* 16 devices - device mask */ + 0x0C00, /* parent channel address */ + 0, /* fifo input index */ + 0, /* fifo output index */ + 0, /* interrupt status fifo for channel */ +}; + +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, + NULL, NULL, &hsdp_help, NULL, NULL, &hsdp_description +}; + +#if NUM_DEVS_HSDP > 1 +/* channel program information */ +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(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 */ +}; + + +DIB dpb_dib = { + hsdp_preio, /* Pre Start I/O */ + hsdp_startcmd, /* Start a command SIO */ + NULL, /* Stop I/O HIO */ + NULL, /* Test I/O TIO */ + NULL, /* Post I/O */ + hsdp_ini, /* init function */ + dpb_unit, /* Pointer to units structure */ + dpb_chp, /* Pointer to chan_prg structure */ + NUM_UNITS_HSDP, /* number of units defined */ + 0x0F, /* 8 devices - device mask */ + 0x0800, /* parent channel address */ + 0, /* fifo input index */ + 0, /* fifo output index */ + 0, /* interrupt status fifo for channel */ +}; + +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, + NULL, NULL, &hsdp_help, NULL, NULL, &hsdp_description +}; +#endif + +/* start a disk operation */ +uint8 hsdp_preio(UNIT *uptr, uint16 chan) +{ + DEVICE *dptr = find_dev_from_unit(uptr); + int unit = (uptr - dptr->units); + + if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */ + return SNS_BSY; + } + + sim_debug(DEBUG_CMD, dptr, "hsdp_preio unit=%02x OK\n", unit); + 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); + int unit = (uptr - dptr->units); + uint8 ch; + + sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd unit %02x cmd %02x CMD %08x\n", unit, cmd, uptr->CMD); + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + uptr->SNS |= SNS_INTVENT; /* unit intervention required */ + if (cmd != DSK_SNS) /* we are completed with unit check status */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + } + + if ((uptr->CMD & DSK_CMDMSK) != 0) { + uptr->CMD |= DSK_BUSY; /* Flag we we are busy */ + return SNS_BSY; + } + if ((uptr->CMD & 0xff00) != 0) { /* if any status info, we are busy */ + return SNS_BSY; + } + sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd CMD continue unit=%02x cmd %02x\n", unit, cmd); + + if ((uptr->flags & UNIT_ATT) == 0) { /* see if unit is attached */ + if (cmd == DSK_SNS) { /* not attached, is cmd Sense 0x04 */ + sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd CMD sense\n"); + /* bytes 0,1 - Cyl entry from STAR reg in STAR */ + ch = (uptr->STAR >> 24) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense STAR b0 unit=%02x 1 %02x\n", + unit, ch); + chan_write_byte(addr, &ch) ; + ch = (uptr->STAR >> 16) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense STAR b1 unit=%02x 1 %02x\n", + unit, ch); + chan_write_byte(addr, &ch) ; + /* byte 2 - Track entry from STAR reg in STAR */ + ch = (uptr->STAR >> 8) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense STAR b2 unit=%02x 1 %02x\n", + unit, ch); + chan_write_byte(addr, &ch) ; + /* byte 3 - Sector entry from STAR reg in STAR */ + ch = (uptr->STAR) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense STAR b3 unit=%02x 1 %02x\n", + unit, ch); + chan_write_byte(addr, &ch) ; + /* bytes 4 - mode reg, byte 0 of SNS */ + ch = (uptr->SNS >> 24) & 0xff; /* return the sense data for device */ + sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense unit=%02x 1 %02x\n", + unit, ch); + chan_write_byte(addr, &ch) ; + /* bytes 5-7 - status bytes, bytes 1-3 of SNS */ + ch = (uptr->SNS >> 16) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense unit=%02x %02x\n", + unit, ch); + chan_write_byte(addr, &ch) ; + ch = (uptr->SNS >> 8) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense unit=%02x 3 %02x\n", + unit, ch); + chan_write_byte(addr, &ch) ; + ch = (uptr->SNS) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "hsdp_startcmd sense unit=%02x 4 %02x\n", + unit, ch); + chan_write_byte(addr, &ch) ; + /* bytes 8-11 - drive attribute register (DATR) entries from uptr->ATTR via + * INCH cmd */ + ch = (uptr->ATTR >> 24) & 0xff; + chan_write_byte(addr, &ch) ; + ch = (uptr->ATTR >> 16) & 0xff; + chan_write_byte(addr, &ch) ; + ch = (uptr->ATTR >> 8 ) & 0xff; + chan_write_byte(addr, &ch) ; + ch = (uptr->ATTR >> 0) & 0xff; + chan_write_byte(addr, &ch) ; + /* bytes 12 & 13 contain drive related status */ + ch = 0; /* zero for now */ + chan_write_byte(addr, &ch) ; + chan_write_byte(addr, &ch) ; + + uptr->SNS &= 0xff000000; /* clear status bytes, but leave mode data */ + return SNS_CHNEND|SNS_DEVEND; + } + if (cmd == 0x0) /* INCH cmd gives unit check here */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + + uptr->SNS |= (SNS_INTVENT|SNS_CMDREJ); /* set new error status */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* we done */ + } + + /* Unit is online, so process a command */ + switch (cmd) { + + case DSK_INCH: /* INCH 0x00 */ + { + 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); + /* STAR (u4) has IOCD word 1 contents. For the disk processor it contains */ + /* a pointer to the INCH buffer followed by 8 drive attribute words that */ + /* contains the flags, sector count, MHD head count, and FHD count */ + /* us9 has the byte count from IOCD wd2 and should be 0x24 (36) */ + /* the INCH buffer address must be returned in STAR and us9 left non-zero */ + /* just return OK and channel software will use up8 as status buffer */ + mema = (uint32)uptr->STAR; /* get memory address of buffer */ + uptr->STAR = M[mema>>2]; /* get status buffer address for XIO return status */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_startcmd starting inch cmd addr %04x STAR %08x mema %08x units %02x\n", + addr, uptr->STAR, mema, dptr->numunits); + /* the next 8 words have drive data for each unit */ + /* WARNING 8 drives must be defined for this controller */ + /* so we will not have a map fault */ + for (i=0; inumunits && i<8; i++) { /* process all drives */ + up->ATTR = M[(mema>>2)+i+1]; /* save each unit's drive data */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_startcmd ATTR data %08x unit %02x flags %02x sec %02x MHD %02x FHD %02x\n", + up->ATTR, i, (up->ATTR >> 24)&0xff, (up->ATTR >> 16)&0xff, (up->ATTR >> 8)&0xff, (up->ATTR&0xff)); + up++; /* next unit for this device */ + } + sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd done inch cmd addr %04x\n", addr); + uptr->CMD |= DSK_CMDMSK; /* use 0xff for inch, just need int */ + sim_activate(uptr, 20); /* start things off */ + return 0; + } + + case DSK_SCK: /* Seek command 0x07 */ + case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ + uptr->CMD &= ~(DSK_STAR); /* show we do not have seek STAR in STAR */ + case DSK_WD: /* Write command 0x01 */ + case DSK_RD: /* Read command 0x02 */ + case DSK_LMR: /* read mode register */ + + uptr->CMD |= cmd; /* save cmd */ + sim_debug(DEBUG_CMD, dptr, + "hsdp_startcmd starting disk seek r/w cmd %02x addr %04x\n", cmd, addr); + sim_activate(uptr, 20); /* start things off */ + return 0; + + case DSK_NOP: /* NOP 0x03 */ + uptr->CMD |= cmd; /* save cmd */ + sim_activate(uptr, 20); /* start things off */ + return 0; + + case DSK_SNS: /* Sense 0x04 */ + uptr->CMD |= cmd; /* save cmd */ + sim_activate(uptr, 20); /* start things off */ + break; + } + sim_debug(DEBUG_CMD, dptr, + "hsdp_startcmd done with hsdp_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; +} + +/* Handle processing of disk requests. */ +t_stat hsdp_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 */ + 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; + 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; + uint8 buf2[1024]; + uint8 buf[1024]; + + sim_debug(DEBUG_DETAIL, &dda_dev, + "hsdp_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 */ + 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, "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 */ + 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); +#ifdef FIX4MPX + chan_end(chsa, SNS_CHNEND); /* return just channel end OK */ +#else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ +#endif + break; + + case DSK_NOP: /* NOP 0x03 */ + 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; + + case DSK_SNS: /* 0x4 */ + ch = uptr->SNS & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%02x 1 %02x\n", unit, ch); + chan_write_byte(chsa, &ch) ; + ch = (uptr->SNS >> 8) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%02x 2 %02x\n", unit, ch); + chan_write_byte(chsa, &ch) ; + ch = 0; + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%02x 3 %02x\n", unit, ch); + chan_write_byte(chsa, &ch) ; + ch = unit; + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv sense unit=%02x 4 %02x\n", unit, ch); + chan_write_byte(chsa, &ch) ; + ch = 4; + uptr->CMD &= ~(0xff00); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; + + 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) { + /* 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", + unit, uptr->STAR >> 16, data->cyl); + sim_activate(uptr, 20); + break; + } else { + /* Compute delay based of difference. */ + /* Set next state = index */ + i = (uptr->STAR >> 16) - data->cyl; + sim_debug(DEBUG_CMD, dptr, "dsk_srv seek unit=%02x %02x %04x\n", unit, + uptr->STAR >> 16, i); + if (i > 0 ) { + if (i > 50) { + data->cyl += 50; /* seek 50 cyl */ + sim_activate(uptr, 800); + } else + if (i > 20) { + data->cyl += 20; /* seek 20 cyl */ + sim_activate(uptr, 400); + } else { + data->cyl++; /* Seek 1 cyl */ + sim_activate(uptr, 200); + } + if (data->cyl >= (int)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 */ + sim_activate(uptr, 800); + } else + if (i < -20) { + data->cyl -= 20; /* seek 20 cyl */ + sim_activate(uptr, 400); + } else { + data->cyl--; /* seek 1 cyl */ + sim_activate(uptr, 200); + } + if (data->cyl < 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); + sim_activate(uptr, 2); + break; + } + } + + /* not seeking, so start a new seek */ + /* 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; + } + } +rezero: + sim_debug(DEBUG_DETAIL, dptr, "dsk_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 */ + 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); + + /* FIXME do something with FHD here */ + /* Check if seek valid */ + if (cyl > hsdp_type[type].cyl || + trk >= hsdp_type[type].nhds || + buf[3] > hsdp_type[type].spt) { + sim_debug(DEBUG_CMD, dptr, + "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 STAR */ + /* calc the sector address of data */ + /* calculate file position in bytes of requested sector */ + tstart = (cyl * hsdp_type[type].nhds * tsize) + (trk * tsize) + (buf[3] * 1024); + 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, "dsk_srv Error on seek to %04x\n", tstart); + } + + /* Check if already on correct cylinder */ + if (trk != 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); + } else { + sim_debug(DEBUG_DETAIL, dptr, + "dsk_srv calc sect addr seek start %04x trk %02x sec %02x\n", + tstart, trk, buf[3]); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + sim_activate(uptr, 20); + chan_end(chsa, SNS_DEVEND|SNS_CHNEND); + } + return SCPE_OK; + + 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_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])) { + /* 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; + } + /* zero stuff */ + buf[0] = buf[1] = buf[2] = buf[3] = 0; + goto rezero; /* murge with seek code */ + break; + + case DSK_LMR: + sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x\n", unit); + /* Read in 1 character of mode data */ + if (chan_read_byte(chsa, &buf[0])) { + /* 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; + } + 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 */ + 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); + } + + 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 */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + + sim_debug(DEBUG_CMD, dptr, + "hsdp_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); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + goto rddone; + } + } + + sim_debug(DEBUG_CMD, dptr, + "DISK READ from sec end bytes end %04x from diskfile cyl %04x hds %02x sec %02\n", + ssize, data->cyl, data->tpos, data->spos); + data->spos++; + /* set sector to read next one */ + if (data->spos >= (hsdp_type[type].spt)) { + data->spos = 0; /* number of sectors per track */ + data->tpos++; /* track position */ + if (data->tpos >= (hsdp_type[type].nhds)) { + data->tpos = 0; /* number of tracks per cylinder */ + data->cyl++; /* cylinder position */ + if (data->cyl >= (int)(hsdp_type[type].cyl)) { + /* EOM reached, abort */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + } + } + /* see if we are done reading data */ + if (test_write_byte_end(chsa)) { + sim_debug(DEBUG_DATAIO, dptr, + "DISK Read complete Read bytes from diskfile cyl %04x hds %02x sec %02x\n", + data->cyl, data->tpos, data->spos); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + } +rddone: + sim_activate(uptr, 10); /* wait to read next sector */ + break; + } + break; + + case DSK_WD: /* Write Data */ + if ((uptr->CMD & DSK_WRITING) == 0) { /* see if we are writing data */ + uptr->CMD |= DSK_WRITING; /* write to disk starting */ + sim_debug(DEBUG_CMD, dptr, + "DISK WRITE starting unit=%02x CMD %02x\n", unit, uptr->CMD); + } + if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */ + /* process the next sector of data */ + len = 0; /* used here as a flag for short read */ + for (i=0; iCMD &= ~(0xffff); /* remove old status bits & cmd */ + sim_debug(DEBUG_CMD, dptr, + "DISK Wrote %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", + ssize, data->cyl, data->tpos, data->spos); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + goto wrdone; + } + ch = 0; /* finish out the sector with zero */ + len++; /* show we have no more data to write */ + } + buf2[i] = ch; /* save the char */ + } + /* write the sector to disk */ + if ((i=sim_fwrite(buf2, 1, ssize, uptr->fileref)) != ssize) { + sim_debug(DEBUG_CMD, dptr, + "Error %08x on write %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", + i, ssize, data->cyl, data->tpos, data->spos); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (len != 0) { /* see if done with write command */ + sim_debug(DEBUG_DATAIO, dptr, + "DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x\n", + 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; + } + sim_debug(DEBUG_CMD, dptr, + "DISK WR to sec end %0x4x bytes end %04x to diskfile cyl %04x hds %02x sec %02x\n", + len, ssize, data->cyl, data->tpos, data->spos); + data->spos++; + if (data->spos >= (hsdp_type[type].spt)) { + data->spos = 0; /* number of sectors per track */ + data->tpos++; /* track position */ + if (data->tpos >= (hsdp_type[type].nhds)) { + data->tpos = 0; /* number of tracks per cylinder */ + data->cyl++; /* cylinder position */ + if (data->cyl >= (int)(hsdp_type[type].cyl)) { + /* EOM reached, abort */ + sim_debug(DEBUG_DETAIL, dptr, + "Error %08x on write %04x to diskfile cyl %04x hds %02x sec %02x\n", + i, ssize, data->cyl, data->tpos, data->spos); + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + } + } +wrdone: + sim_activate(uptr, 10); + break; + } + 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 */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv done cmd=%02x chsa %04x count %04x\n", + cmd, chsa, chp->ccw_count); + return SCPE_OK; +} + +/* initialize the disk */ +void hsdp_ini(UNIT *uptr, t_bool f) +{ + DEVICE *dptr = find_dev_from_unit(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 */ + /* total sectors on disk */ + uptr->capac = hsdp_type[i].taus * hsdp_type[i].spau; + + sim_debug(DEBUG_EXP, &dda_dev, "DPA init device %s on unit DPA%.1x cap %x\n", + dptr->name, GET_UADDR(uptr->CMD), uptr->capac); +} + +t_stat hsdp_reset(DEVICE * dptr) +{ + /* add reset code here */ + return SCPE_OK; +} + +/* 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); + t_stat r; + uint16 tsize; /* track size in bytes */ + uint16 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; + + if (hsdp_type[type].name == 0) { /* does the assigned disk have a name */ + detach_unit(uptr); /* no, reject */ + return SCPE_FMT; /* error */ + } + + /* get a buffer to hold hsdp_t structure */ + /* extended data structure per unit */ + if ((data = (struct ddata_t *)calloc(1, sizeof(struct ddata_t))) == 0) { + detach_unit(uptr); + return SCPE_FMT; + } + + uptr->DDATA = (void *)data; /* save pointer to structure in DDATA */ + /* 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 */ + + 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 */ + + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ + } + + data->tpos = 0; /* current track position */ + data->spos = 0; /* current sector position */ + + set_devattn(addr, SNS_DEVEND); + return SCPE_OK; +} + +/* detach a disk device */ +t_stat hsdp_detach(UNIT * uptr) { + struct ddata_t *data = (struct ddata_t *)uptr->DDATA; + + if (data != 0) { + free(data); /* free disk data structure */ + } + uptr->DDATA = 0; /* no pointer to disk data */ + uptr->CMD &= ~0xffff; /* no cmd and flags */ + return detach_unit(uptr); /* tell simh we are done with disk */ +} + +/* boot from the specified disk unit */ +t_stat hsdp_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)); + 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? */ + return chan_boot(GET_UADDR(uptr->CMD), dptr); /* boot the ch/sa */ +} + +/* Disk option setting commands */ +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; + for (i = 0; hsdp_type[i].name != 0; i++) { + if (strcmp(hsdp_type[i].name, cptr) == 0) { + uptr->flags &= ~UNIT_TYPE; + uptr->flags |= SET_TYPE(i); + uptr->capac = hsdp_type[i].taus * hsdp_type[i].spau; + return SCPE_OK; + } + } + return SCPE_ARG; +} + +t_stat hsdp_get_type(FILE * st, UNIT * uptr, int32 v, CONST void *desc) +{ + if (uptr == NULL) + return SCPE_IERR; + fputs("TYPE=", st); + fputs(hsdp_type[GET_TYPE(uptr->flags)].name, st); + return SCPE_OK; +} + +/* help information for disk */ +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"); + fprintf (st, "Use:\r\n"); + fprintf (st, " sim> SET %sn TYPE=type\r\n", dptr->name); + fprintf (st, "Type can be: "); + for (i = 0; hsdp_type[i].name != 0; i++) { + fprintf(st, "%s", hsdp_type[i].name); + if (hsdp_type[i+1].name != 0) + fprintf(st, ", "); + } + 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); + } + fprint_set_help(st, dptr); + fprint_show_help(st, dptr); + return SCPE_OK; +} + +const char *hsdp_description (DEVICE *dptr) +{ + return "SEL 8064 High Speed Disk Processor"; +} + +#endif diff --git a/SEL32/sel32_mt.c b/SEL32/sel32_mt.c index 38c4d2a..102709c 100644 --- a/SEL32/sel32_mt.c +++ b/SEL32/sel32_mt.c @@ -139,12 +139,12 @@ OTAB EQU $ #define MT_MODEMSK 0xFF /* Mode Mask */ /* set mode bits for BTP (MT_SETM) */ -#define MT_MODE_AUTO 0x80 /* =0 Perform auto error recodery on read */ +#define MT_MODE_AUTO 0x80 /* =0 Perform auto error recovery on read */ #define MT_MODE_FORCE 0x80 /* =1 Read regardless if error recovery fails */ #define MT_MDEN_800 0x40 /* =0 select 800 BPI NRZI mode 9 track only */ #define MT_MDEN_1600 0x40 /* =1 select 1600 BPI PE mode 9 track only */ -#define MT_MDEN_6250 0x20 /* =0 Use mode from bit one for NRZI/PE */ -#define MT_MDEN_6250 0x20 /* =1 6250 BPI GCR mode 9 track only */ +#define MT_MDEN_6250 0x02 /* =0 Use mode from bit one for NRZI/PE */ +#define MT_MDEN_6250 0x02 /* =1 6250 BPI GCR mode 9 track only */ #define MT_MDEN_SCATGR 0x01 /* =1 HSTP scatter/gather mode */ #define MT_MDEN_MSK 0xc0 /* Density mask */ @@ -445,24 +445,36 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd processing unit %04x cmd %02x\n", unit, cmd); - switch (cmd & 0xF) { - case 0x0: /* INCH command */ + switch (cmd & 0xFF) { + case 0x00: /* INCH command */ /* POS has INCH buffer address and us9 the count */ /* just return OK and channel software will use POS as status buffer */ - sim_debug(DEBUG_DETAIL, &mta_dev, "mt_startcmd INCH done unit %04x cmd %02x\n", + sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd INCH done unit %04x cmd %02x\n", unit, cmd); /* UTX_needs_interrupt */ cmd = MT_CMDMSK; /* insert INCH cmd as 0xff */ /* fall through */ - case 0x3: /* Tape motion commands */ - /* UTX_needs_interrupt */ + case 0x03: /* Tape motion commands or NOP */ + case 0x13: /* Read and compare command */ + case 0x23: /* Rewind command */ + case 0x33: /* Rewind and unload */ + case 0x43: /* Advance record */ + case 0x53: /* Backspace record */ + case 0x63: /* Advance filemark */ + case 0x73: /* Backspace filemark */ + case 0x83: /* Set Mode command */ + case 0x93: /* Write Tape filemark */ + case 0xA3: /* Erase 3.5 of tape */ + /* UTX_needs_interrupt on NOP or INCH */ /* fall through */ - case 0x1: /* Write command */ - case 0x2: /* Read command */ - case 0xc: /* Read backward */ + case 0x01: /* Write command */ + case 0x02: /* Read command */ + case 0x0C: /* Read backward */ if (cmd != 0x03) /* if this is a nop do not zero status */ uptr->SNS = (uptr->SNS & 0x0000ff00); /* clear all but byte 2 */ uptr->SNS |= (SNS_RDY|SNS_ONLN); /* set ready status */ + /* Fall through */ +// case 0x4: /* Sense */ if (sim_tape_wrp(uptr)) uptr->SNS |= (SNS_WRP); /* write protected */ if (sim_tape_bot(uptr)) @@ -472,27 +484,31 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) /* Fall through */ case 0x4: /* Sense */ +#ifndef FIX_DIAG + case 0x80: /* Unknown diag cmd with byte cnt of 0x0c */ +#endif uptr->CMD &= ~(MT_CMDMSK); /* clear out last cmd */ uptr->CMD |= cmd & MT_CMDMSK; /* insert new cmd */ CLR_BUF(uptr); /* buffer is empty */ - /* INCH cmd has iNCH buffer address in POS, so leave it */ + /* INCH cmd has INCH buffer address in POS, so leave it */ if (cmd != MT_CMDMSK) uptr->POS = 0; /* reset buffer position pointer */ sim_activate(uptr, 100); /* Start unit off */ mt_busy[GET_DEV_BUF(dptr->flags)] = 1; /* show we are busy */ - sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd sense return 0 chan %04x cmd %02x\n", - chan, cmd); + sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd sense %08x return 0 chan %04x cmd %02x\n", + uptr->SNS, chan, cmd); return 0; default: /* invalid command */ - sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd CMDREJ return chan %04x cmd %02x\n", chan, cmd); + sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd CMDREJ return chan %04x cmd %02x\n", + chan, cmd); uptr->SNS |= SNS_CMDREJ; break; } if (uptr->SNS & 0xff000000) /* errors? */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; sim_debug(DEBUG_EXP, &mta_dev, - "mt_startcmd ret CHNEND|DEVEND chan %04x unit %04x cmd %02x\n", chan, unit, cmd); + "mt_startcmd ret CHNEND|DEVEND chan %04x unit %04x cmd %02x\n", chan, unit, cmd); return SNS_CHNEND|SNS_DEVEND; } @@ -556,8 +572,9 @@ t_stat mt_srv(UNIT *uptr) t_mtrlnt reclen; t_stat r = SCPE_ARG; /* Force error if not set */ uint8 ch; + uint8 zc = 0; - sim_debug(DEBUG_DATA, &mta_dev, "mt_srv unit %04x cmd %02x\n", unit, cmd); + sim_debug(DEBUG_CMD, &mta_dev, "mt_srv unit %04x cmd %02x\n", unit, cmd); if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ uptr->SNS |= SNS_INTVENT; /* unit intervention required */ mt_busy[bufnum] &= ~1; /* make our buffer not busy */ @@ -576,6 +593,33 @@ t_stat mt_srv(UNIT *uptr) chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ break; +#ifndef FIX_DIAG + case 0x80: /* other? */ /* default to NOP */ + sim_debug(DEBUG_CMD, &mta_dev, "mt_srv cmd 80 DIAG unit=%04x SNS %08x\n", unit, uptr->SNS); + ch = (uptr->SNS >> 24) & 0xff; /* get sense byte 0 status */ + sim_debug(DEBUG_DETAIL, &mta_dev, "sense unit %02x byte 0 %02x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 0 */ + ch = (uptr->SNS >> 16) & 0xff; /* get sense byte 1 status */ + sim_debug(DEBUG_DETAIL, &mta_dev, "sense unit %02x byte 1 %02x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 1 */ + ch = (uptr->SNS >> 8) & 0xff; /* get sense byte 2 status */ + sim_debug(DEBUG_DETAIL, &mta_dev, "sense unit %02x byte 2 %02x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 2 */ + ch = (uptr->SNS >> 0) & 0xff; /* get sense byte 3 status */ + sim_debug(DEBUG_DETAIL, &mta_dev, "sense unit %02x byte 3 %02x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 3 */ + for (ch=4; ch < 0xc; ch++) { +// chan_write_byte(addr, &ch); /* write byte */ + chan_write_byte(addr, &zc); /* write zero byte */ + } + uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ + mt_busy[bufnum] &= ~1; /* make our buffer not busy */ + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ + sim_debug(DEBUG_CMD, &mta_dev, "mt_srv DIAG SNS %08x char complete unit=%02x\n", + uptr->SNS, unit); + break; + +#endif case MT_NOP: /* 0x03 */ /* NOP motion command */ uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ mt_busy[bufnum] &= ~1; /* make our buffer not busy */ @@ -583,7 +627,7 @@ t_stat mt_srv(UNIT *uptr) break; case MT_SENSE: /* 0x04 */ /* get sense data */ - sim_debug(DEBUG_CMD, &mta_dev, "mt_srv cmd 4 SENSE unit=%04x\n", unit); + sim_debug(DEBUG_CMD, &mta_dev, "mt_srv cmd 4 SENSE %08x unit=%04x\n", uptr->SNS, unit); ch = (uptr->SNS >> 24) & 0xff; /* get sense byte 0 status */ sim_debug(DEBUG_DETAIL, &mta_dev, "sense unit %02x byte 0 %02x\n", unit, ch); chan_write_byte(addr, &ch); /* write byte 0 */ @@ -601,7 +645,7 @@ t_stat mt_srv(UNIT *uptr) mt_busy[bufnum] &= ~1; /* make our buffer not busy */ chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ sim_debug(DEBUG_CMD, &mta_dev, "mt_srv SENSE %08x char complete unit=%02x\n", - uptr->POS, unit); + uptr->SNS, unit); break; case MT_READ: /* 0x02 */ /* read a record from the device */ @@ -616,8 +660,8 @@ t_stat mt_srv(UNIT *uptr) mt_busy[bufnum] &= ~1; /* not busy anymore */ chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* set chan end, dev end status */ sim_debug(DEBUG_CMD, &mta_dev, - "mt_srv READ %04x char complete unit=%02x sense %08x\n", - uptr->POS, unit, uptr->SNS); + "mt_srv READ %04x char complete unit=%02x sense %08x\n", + uptr->POS, unit, uptr->SNS); break; } /* read is not completed, get an input char */ @@ -703,90 +747,90 @@ t_stat mt_srv(UNIT *uptr) break; case MT_WRITE: /* 0x01 */ /* write record */ - /* Check if write protected */ - if (sim_tape_wrp(uptr)) { - uptr->SNS |= SNS_CMDREJ; - uptr->CMD &= ~MT_CMDMSK; - mt_busy[bufnum] &= ~1; - sim_debug(DEBUG_DETAIL, &mta_dev, "Write write protected unit=%02x\n", unit); - chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } + /* Check if write protected */ + if (sim_tape_wrp(uptr)) { + uptr->SNS |= SNS_CMDREJ; + uptr->CMD &= ~MT_CMDMSK; + mt_busy[bufnum] &= ~1; + sim_debug(DEBUG_CMD, &mta_dev, "Write write protected unit=%02x\n", unit); + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } - /* Grab data until channel has no more */ - if (chan_read_byte(addr, &ch)) { - if (uptr->POS > 0) { /* Only if data in record */ - reclen = uptr->hwmark; - sim_debug(DEBUG_DETAIL, &mta_dev, "Write unit=%02x Block %04x chars\n", - unit, reclen); - r = sim_tape_wrrecf(uptr, &mt_buffer[bufnum][0], reclen); - uptr->POS = 0; - uptr->CMD &= ~MT_CMDMSK; - mt_error(uptr, addr, r, dptr); /* Record errors */ - } - } else { + /* Grab data until channel has no more */ + if (chan_read_byte(addr, &ch)) { + if (uptr->POS > 0) { /* Only if data in record */ + reclen = uptr->hwmark; + sim_debug(DEBUG_CMD, &mta_dev, "Write unit=%02x Block %04x chars\n", + unit, reclen); + r = sim_tape_wrrecf(uptr, &mt_buffer[bufnum][0], reclen); + uptr->POS = 0; + uptr->CMD &= ~MT_CMDMSK; + mt_error(uptr, addr, r, dptr); /* Record errors */ + } + } else { mt_buffer[bufnum][uptr->POS++] = ch; sim_debug(DEBUG_DATA, &mta_dev, "Write data unit=%02x %04x %02x\n", - unit, uptr->POS, ch); + unit, uptr->POS, ch); uptr->hwmark = uptr->POS; - } - sim_activate(uptr, 20); - break; + } + sim_activate(uptr, 20); + break; case MT_RDBK: /* 0x0C */ /* Read Backwards */ - if (uptr->CMD & MT_READDONE) { + if (uptr->CMD & MT_READDONE) { uptr->CMD &= ~(MT_CMDMSK|MT_READDONE); mt_busy[bufnum] &= ~1; chan_end(addr, SNS_CHNEND|SNS_DEVEND); return SCPE_OK; - } + } - /* If at end of record, fill buffer */ - if (BUF_EMPTY(uptr)) { + /* If at end of record, fill buffer */ + if (BUF_EMPTY(uptr)) { if (sim_tape_bot(uptr)) { uptr->CMD &= ~MT_CMDMSK; mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1; chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SCPE_OK; } - sim_debug(DEBUG_DETAIL, &mta_dev, "Read backward unit=%02x\n", unit); + sim_debug(DEBUG_CMD, &mta_dev, "Read backward unit=%02x\n", unit); if ((r = sim_tape_rdrecr(uptr, &mt_buffer[bufnum][0], &reclen, BUFFSIZE)) != MTSE_OK) { uptr->CMD &= ~(MT_CMDMSK|MT_READDONE); return mt_error(uptr, addr, r, dptr); } uptr->POS = reclen; uptr->hwmark = reclen; - sim_debug(DEBUG_DETAIL, &mta_dev, "Binary Block %04x chars\n", reclen); - } + sim_debug(DEBUG_CMD, &mta_dev, "Binary Block %04x chars\n", reclen); + } - ch = mt_buffer[bufnum][--uptr->POS]; + ch = mt_buffer[bufnum][--uptr->POS]; - if (chan_write_byte(addr, &ch)) { - sim_debug(DEBUG_DATA, &mta_dev, "Read unit=%02x EOR cnt %04x\n", - unit, uptr->POS); - /* If not read whole record, skip till end */ - if (uptr->POS >= 0) { - sim_activate(uptr, (uptr->POS) * 20); - uptr->CMD |= MT_READDONE; - return SCPE_OK; - } - uptr->CMD &= ~MT_CMDMSK; - mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_CHNEND|SNS_DEVEND); - } else { - sim_debug(DEBUG_DATA, &mta_dev, "Read data unit=%02x %04x %02x\n", - unit, uptr->POS, ch); - if (uptr->POS == 0) { /* In IRG */ - uptr->CMD &= ~MT_CMDMSK; - mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_CHNEND|SNS_DEVEND); - } else - sim_activate(uptr, 20); - } - break; + if (chan_write_byte(addr, &ch)) { + sim_debug(DEBUG_CMD, &mta_dev, "Read unit=%02x EOR cnt %04x\n", + unit, uptr->POS); + /* If not read whole record, skip till end */ + if (uptr->POS >= 0) { + sim_activate(uptr, (uptr->POS) * 20); + uptr->CMD |= MT_READDONE; + return SCPE_OK; + } + uptr->CMD &= ~MT_CMDMSK; + mt_busy[bufnum] &= ~1; + chan_end(addr, SNS_CHNEND|SNS_DEVEND); + } else { + sim_debug(DEBUG_DATA, &mta_dev, "Read data unit=%02x %04x %02x\n", + unit, uptr->POS, ch); + if (uptr->POS == 0) { /* In IRG */ + uptr->CMD &= ~MT_CMDMSK; + mt_busy[bufnum] &= ~1; + chan_end(addr, SNS_CHNEND|SNS_DEVEND); + } else + sim_activate(uptr, 20); + } + break; case MT_WTM: /* 0x93 */ /* Write tape filemark */ - if (uptr->POS == 0) { + if (uptr->POS == 0) { if (sim_tape_wrp(uptr)) { uptr->SNS |= SNS_CMDREJ; uptr->CMD &= ~MT_CMDMSK; @@ -796,211 +840,223 @@ t_stat mt_srv(UNIT *uptr) } uptr->POS ++; sim_activate(uptr, 500); - } else { - sim_debug(DEBUG_DETAIL, &mta_dev, "Write Mark unit=%02x\n", unit); + } else { + sim_debug(DEBUG_CMD, &mta_dev, "Write Mark unit=%02x\n", unit); uptr->CMD &= ~(MT_CMDMSK); r = sim_tape_wrtmk(uptr); - chan_end(addr, SNS_DEVEND); + chan_end(addr, SNS_DEVEND); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND); mt_busy[bufnum] &= ~1; - } - break; + } + break; case MT_BSR: /* 0x53 */ /* Backspace record */ - sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv cmd 0x53 BSR unit %02x POS %04x\n", - unit, uptr->POS); - switch (uptr->POS ) { - case 0: - if (sim_tape_bot(uptr)) { - uptr->CMD &= ~MT_CMDMSK; - mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1; - chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; - } - uptr->POS++; - sim_activate(uptr, 50); - break; - case 1: - uptr->POS++; - sim_debug(DEBUG_DETAIL, &mta_dev, "Backspace rec unit %02x POS %04x\n", - unit, uptr->POS); - r = sim_tape_sprecr(uptr, &reclen); - /* We don't set EOF on BSR */ - if (r == MTSE_TMK) { - uptr->POS++; - sim_debug(DEBUG_DETAIL, &mta_dev, "MARK\n"); - sim_activate(uptr, 50); - } else { - sim_debug(DEBUG_DETAIL, &mta_dev, "Backspace reclen %04x\n", reclen); - sim_activate(uptr, 50); - } - break; - case 2: - uptr->CMD &= ~(MT_CMDMSK); - mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_CHNEND|SNS_DEVEND); - break; - case 3: - uptr->CMD &= ~(MT_CMDMSK); - mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_DEVEND|SNS_UNITEXP); - break; - } - break; - - case MT_BSF: /* 0x73 */ /* Backspace file */ - sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv cmd 0x73 BSF unit %02x\n", unit); - switch(uptr->POS) { - case 0: - if (sim_tape_bot(uptr)) { - uptr->CMD &= ~MT_CMDMSK; - mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - uptr->POS++; - sim_activate(uptr, 500); - break; - case 1: - sim_debug(DEBUG_DETAIL, &mta_dev, "Backspace file unit=%02x\n", unit); - r = sim_tape_sprecr(uptr, &reclen); - if (r == MTSE_TMK) { - uptr->POS++; - sim_debug(DEBUG_DETAIL, &mta_dev, "MARK\n"); - sim_activate(uptr, 50); - } else if (r == MTSE_BOT) { - uptr->POS+= 2; - sim_activate(uptr, 50); - } else { - sim_activate(uptr, 20); - } - break; - case 2: /* File Mark */ - uptr->CMD &= ~(MT_CMDMSK); - mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_DEVEND); - break; - case 3: /* BOT */ - uptr->CMD &= ~(MT_CMDMSK); - mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_DEVEND); - break; - } - break; - - case MT_FSR: /* 0x43 */ /* Advance record */ - switch(uptr->POS) { - case 0: - sim_debug(DEBUG_DETAIL, &mta_dev, "Skip rec entry unit=%02x ", unit); - uptr->POS++; - sim_activate(uptr, 50); - break; - case 1: - uptr->POS++; - sim_debug(DEBUG_DETAIL, &mta_dev, "Skip rec unit=%02x ", unit); - r = sim_tape_sprecf(uptr, &reclen); - if (r == MTSE_TMK) { - uptr->POS = 3; - sim_debug(DEBUG_DETAIL, &mta_dev, "FSR MARK\n"); - sim_activate(uptr, 50); - } else if (r == MTSE_EOM) { - uptr->POS = 4; - sim_activate(uptr, 50); - } else { - sim_debug(DEBUG_DETAIL, &mta_dev, "FSR skipped %04x byte record\n", - reclen); - sim_activate(uptr, 10 + (10 * reclen)); - } - break; - case 2: - uptr->CMD &= ~(MT_CMDMSK); - mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_DEVEND); - break; - case 3: - uptr->CMD &= ~(MT_CMDMSK); - mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_DEVEND|SNS_UNITEXP); - sim_debug(DEBUG_DETAIL, &mta_dev, "Skip record Completed\n"); - break; - case 4: - uptr->CMD &= ~(MT_CMDMSK); - mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_DEVEND|SNS_UNITCHK); - break; - } - break; - - case MT_FSF: /* 0x63 */ /* advance filemark */ - switch(uptr->POS) { + sim_debug(DEBUG_CMD, &mta_dev, "mt_srv cmd 0x53 BSR unit %02x POS %04x\n", + unit, uptr->POS); + switch (uptr->POS ) { case 0: - sim_debug(DEBUG_DETAIL, &mta_dev, "Skip file entry unit=%02x\n", unit); + if (sim_tape_bot(uptr)) { + uptr->CMD &= ~MT_CMDMSK; + mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1; + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + } uptr->POS++; sim_activate(uptr, 50); break; case 1: - sim_debug(DEBUG_DETAIL, &mta_dev, "Skip file unit=%02x\n", unit); - r = sim_tape_sprecf(uptr, &reclen); + uptr->POS++; + sim_debug(DEBUG_CMD, &mta_dev, "Backspace rec unit %02x POS %04x\n", + unit, uptr->POS); + r = sim_tape_sprecr(uptr, &reclen); + /* We don't set EOF on BSR */ if (r == MTSE_TMK) { uptr->POS++; - uptr->SNS |= SNS_FMRKDT; /* file mark detected */ - sim_debug(DEBUG_DETAIL, &mta_dev, "FSF MARK\n"); - sim_activate(uptr, 50); - } else if (r == MTSE_EOM) { - uptr->SNS |= SNS_EOT; /* set EOT status */ - uptr->POS+= 2; + sim_debug(DEBUG_CMD, &mta_dev, "MARK\n"); sim_activate(uptr, 50); } else { - sim_debug(DEBUG_DETAIL, &mta_dev, "FSF skipped %04x byte record\n", reclen); + sim_debug(DEBUG_CMD, &mta_dev, "Backspace reclen %04x\n", reclen); sim_activate(uptr, 50); } break; case 2: uptr->CMD &= ~(MT_CMDMSK); mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ - sim_debug(DEBUG_DETAIL, &mta_dev, "Skip file done unit=%02x\n", unit); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); break; case 3: uptr->CMD &= ~(MT_CMDMSK); mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_DEVEND|SNS_UNITCHK|SNS_UNITCHK); + chan_end(addr, SNS_DEVEND|SNS_UNITEXP); + break; + } + break; + + case MT_BSF: /* 0x73 */ /* Backspace file */ + sim_debug(DEBUG_CMD, &mta_dev, "mt_srv cmd 0x73 BSF unit %02x\n", unit); + switch(uptr->POS) { + case 0: + if (sim_tape_bot(uptr)) { + uptr->CMD &= ~MT_CMDMSK; + mt_busy[bufnum] &= ~1; + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + uptr->POS++; + sim_activate(uptr, 500); + break; + case 1: + sim_debug(DEBUG_CMD, &mta_dev, "Backspace file unit=%02x\n", unit); + r = sim_tape_sprecr(uptr, &reclen); + if (r == MTSE_TMK) { + uptr->POS++; + sim_debug(DEBUG_DETAIL, &mta_dev, "MARK\n"); + sim_activate(uptr, 50); + } else if (r == MTSE_BOT) { + uptr->POS+= 2; + sim_activate(uptr, 50); + } else { + sim_activate(uptr, 20); + } + break; + case 2: /* File Mark */ + uptr->CMD &= ~(MT_CMDMSK); + mt_busy[bufnum] &= ~1; + chan_end(addr, SNS_DEVEND); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND); + break; + case 3: /* BOT */ + uptr->CMD &= ~(MT_CMDMSK); + mt_busy[bufnum] &= ~1; + chan_end(addr, SNS_DEVEND); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND); + break; + } + break; + + case MT_FSR: /* 0x43 */ /* Advance record */ + switch(uptr->POS) { + case 0: + sim_debug(DEBUG_CMD, &mta_dev, "Skip rec entry unit=%02x ", unit); + uptr->POS++; + sim_activate(uptr, 50); + break; + case 1: + uptr->POS++; + sim_debug(DEBUG_CMD, &mta_dev, "Skip rec unit=%02x ", unit); + r = sim_tape_sprecf(uptr, &reclen); + if (r == MTSE_TMK) { + uptr->POS = 3; + uptr->SNS |= SNS_FMRKDT; /* file mark detected */ + sim_debug(DEBUG_CMD, &mta_dev, "FSR MARK\n"); + sim_activate(uptr, 50); + } else if (r == MTSE_EOM) { + uptr->POS = 4; + uptr->SNS |= SNS_EOT; /* set EOT status */ + sim_activate(uptr, 50); + } else { + sim_debug(DEBUG_CMD, &mta_dev, "FSR skipped %04x byte record\n", + reclen); + sim_activate(uptr, 10 + (10 * reclen)); + } + break; + case 2: + uptr->CMD &= ~(MT_CMDMSK); + mt_busy[bufnum] &= ~1; + sim_debug(DEBUG_CMD, &mta_dev, "Skip record Completed\n"); + chan_end(addr, SNS_DEVEND); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND); + break; + case 3: + uptr->CMD &= ~(MT_CMDMSK); + mt_busy[bufnum] &= ~1; + chan_end(addr, SNS_DEVEND|SNS_UNITEXP); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); + sim_debug(DEBUG_CMD, &mta_dev, "Skip record at EOF\n"); + break; + case 4: + uptr->CMD &= ~(MT_CMDMSK); + mt_busy[bufnum] &= ~1; + sim_debug(DEBUG_CMD, &mta_dev, "Skip record at EOT\n"); +//BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + chan_end(addr, SNS_DEVEND|SNS_UNITEXP); + break; + } + break; + + case MT_FSF: /* 0x63 */ /* advance filemark */ + switch(uptr->POS) { + case 0: + sim_debug(DEBUG_CMD, &mta_dev, "Skip file entry sense %08x unit %02x\n", uptr->SNS, unit); + uptr->POS++; + sim_activate(uptr, 50); + break; + case 1: + sim_debug(DEBUG_CMD, &mta_dev, "Skip file unit=%02x\n", unit); + r = sim_tape_sprecf(uptr, &reclen); + if (r == MTSE_TMK) { + uptr->POS++; + uptr->SNS |= SNS_FMRKDT; /* file mark detected */ + sim_debug(DEBUG_CMD, &mta_dev, "FSF EOF MARK sense %08x\n", uptr->SNS); + sim_activate(uptr, 50); + } else if (r == MTSE_EOM) { + uptr->SNS |= SNS_EOT; /* set EOT status */ + sim_debug(DEBUG_CMD, &mta_dev, "FSF EOT sense %08x\n", uptr->SNS); + uptr->POS+= 2; + sim_activate(uptr, 50); + } else { + sim_debug(DEBUG_CMD, &mta_dev, "FSF skipped %04x byte record\n", reclen); + sim_activate(uptr, 50); + } + break; + case 2: + uptr->CMD &= ~(MT_CMDMSK); + mt_busy[bufnum] &= ~1; + uptr->SNS &= ~SNS_LOAD; /* reset BOT */ + sim_debug(DEBUG_CMD, &mta_dev, "Skip file done sense %08x unit %02x\n", uptr->SNS, unit); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ + break; + case 3: + uptr->CMD &= ~(MT_CMDMSK); + uptr->SNS &= ~SNS_LOAD; /* reset BOT */ + mt_busy[bufnum] &= ~1; + sim_debug(DEBUG_CMD, &mta_dev, "Skip file got EOT sense %08x unit %02x\n", uptr->SNS, unit); +//BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + chan_end(addr, SNS_DEVEND|SNS_UNITEXP); break; } break; case MT_ERG: /* 0xA3 */ /* Erace 3.5 in tape */ - switch (uptr->POS) { - case 0: - if (sim_tape_wrp(uptr)) { - uptr->SNS |= SNS_CMDREJ; - uptr->CMD &= ~MT_CMDMSK; - mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_DEVEND|SNS_UNITCHK); - } else { - uptr->POS ++; - sim_activate(uptr, 500); - } - break; - case 1: - sim_debug(DEBUG_DETAIL, &mta_dev, "Erase unit=%02x\n", unit); - r = sim_tape_wrgap(uptr, 35); - sim_activate(uptr, 5000); - uptr->POS++; - break; - case 2: - uptr->CMD &= ~(MT_CMDMSK); - mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_DEVEND); - } - break; + switch (uptr->POS) { + case 0: + if (sim_tape_wrp(uptr)) { + uptr->SNS |= SNS_CMDREJ; + uptr->CMD &= ~MT_CMDMSK; + mt_busy[bufnum] &= ~1; + chan_end(addr, SNS_DEVEND|SNS_UNITCHK); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + } else { + uptr->POS ++; + sim_activate(uptr, 500); + } + break; + case 1: + sim_debug(DEBUG_CMD, &mta_dev, "Erase unit=%02x\n", unit); + r = sim_tape_wrgap(uptr, 35); + sim_activate(uptr, 5000); + uptr->POS++; + break; + case 2: + uptr->CMD &= ~(MT_CMDMSK); + mt_busy[bufnum] &= ~1; + /* we are done dev|chan end */ + chan_end(addr, SNS_DEVEND); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND); + break; + } + break; case MT_REW: /* 0x23 */ /* rewind tape */ if (uptr->POS == 0) { uptr->POS++; - sim_debug(DEBUG_DETAIL, &mta_dev, "Start rewind unit %02x\n", unit); + sim_debug(DEBUG_CMD, &mta_dev, "Start rewind unit %02x\n", unit); sim_activate(uptr, 1500); } else { - sim_debug(DEBUG_DETAIL, &mta_dev, "Rewind complete unit %02x\n", unit); + sim_debug(DEBUG_CMD, &mta_dev, "Rewind complete unit %02x\n", unit); uptr->CMD &= ~(MT_CMDMSK); r = sim_tape_rewind(uptr); uptr->SNS |= SNS_LOAD; /* set BOT */ @@ -1015,7 +1071,7 @@ t_stat mt_srv(UNIT *uptr) mt_busy[bufnum] &= ~1; sim_activate(uptr, 30000); } else { - sim_debug(DEBUG_DETAIL, &mta_dev, "Unload unit=%02x\n", unit); + sim_debug(DEBUG_CMD, &mta_dev, "Unload unit=%02x\n", unit); uptr->CMD &= ~(MT_CMDMSK); r = sim_tape_detach(uptr); } diff --git a/SEL32/sel32_scfi.c b/SEL32/sel32_scfi.c index c1d7fd2..b9e6100 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, James C. Bevier + Copyright (c) 2018-2019, James C. Bevier Portions provided by Richard Cornwell and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a @@ -32,16 +32,15 @@ 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 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_DISABLE | UNIT_ROABLE | UNIT_FIX | UNIT_IDLE +#define SET_TYPE(x) (UNIT_TYPE & ((x) << UNIT_V_TYPE)) #define UNIT_SCFI UNIT_ATTABLE | UNIT_IDLE /* INCH command information */ @@ -83,89 +82,89 @@ 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 /* Flag to send a CUE */ /* 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_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_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 */ @@ -191,66 +190,47 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option /* allocated during attach command for each unit defined */ struct ddata_t { - uint8 rbuf[1024]; /* read buffer, Sector buffer 768 or 1024 */ - uint8 wbuf[1024]; /* write buffer, Sector buffer 768 or 1024 */ - uint32 cpos; /* Position of head of cylinder in file */ - uint32 tstart; /* Location of start of cyl/track/sect in data */ - uint32 spare; /* drive register spare */ - uint16 tsize; /* Size of one track in byte */ - uint16 ssize; /* Size of one sector in bytes */ - uint16 ccyl; /* Current Cylinder number */ - uint16 cyl; /* Cylinder head at */ - uint16 tpos; /* Track position */ - uint16 spos; /* Sector position */ - uint16 dlen; /* remaining in data */ - uint16 rec; /* Current record number */ - uint16 count; /* Remaining in current operation */ + uint16 cyl; /* Cylinder head at */ + uint16 tpos; /* Track position */ + uint16 spos; /* Sector position */ }; /* disk definition structure */ 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 */ - uint8 type; /* Device type code */ + 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 */ + uint8 type; /* Device type code */ } scfi_type[] = { - /* Class E Disc Devices */ - {"FE004", 5888, 184, 256, 192, 23, 1, 1, 1, 0x80}, /*0 4 M */ - {"CE010", 12800, 200, 2, 96, 16, 1, 2, 400, 0x60}, /*1 10 M */ - {"ME040", 23000, 719, 5, 192, 23, 2, 1, 400, 0x40}, /*2 40 M */ - {"ME080", 46000, 1438, 5, 192, 23, 2, 1, 800, 0x40}, /*3 80 M */ - {"ME300", 87400, 2732, 19, 192, 23, 4, 1, 800, 0x40}, /*4 300 M */ - {"FE005", 5888, 184, 4, 192, 23, 1, 1, 64, 0x80}, /*5 5 M */ - /* Class F Disc Devices */ - {"FL001", 1334, 0, 2, 64, 26, 3, 3, 26, 0x40}, /*6 1 M */ - {"MH040", 20000, 625, 5, 192, 20, 2, 1, 40, 0x40}, /*7 40 M */ - {"MH080", 40000, 1250, 5, 192, 20, 2, 1, 80, 0x40}, /*8 80 M */ - {"MH300", 76000, 2375, 19, 192, 20, 4, 1, 800, 0x40}, /*9 300 M */ - {"MH1GB", 87400, 2732, 1, 192, 20,16, 1,69920, 0x40}, /*10 1000 M */ - {"SG038", 54752, 1711, 1, 192, 20, 8, 1,21900, 0x40}, /*11 38 M */ - {"SG120", 174848, 5464, 1, 192, 20, 8, 1,69939, 0x40}, /*12 120 M */ - {"SG076", 116808, 3491, 1, 192, 20, 8, 1,46723, 0x40}, /*13 76 M */ - {"FH005", 5120, 184, 4, 192, 20, 1, 1, 64, 0x80}, /*14 5 M */ - {"CD032", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*15 32 M */ - {"CD032", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*16 32 M */ - {"CD064", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*17 64 M */ - {"CD064", 24000, 750, 3, 192, 20, 2, 1, 800, 0x60}, /*18 64 M */ - {"CD096", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*19 96 M */ - {"CD096", 40000, 1250, 5, 192, 20, 2, 1, 800, 0x60}, /*20 96 M */ - {"MH600", 80000, 2500, 40, 192, 20, 8, 1, 80, 0x40}, /*21 600 M */ - {"FM600", 80000, 2500, 40, 192, 20, 8, 1, 80, 0x40}, /*22 600 M */ - {"FM600", 1600, 50, 40, 192, 20, 1, 1, 2, 0x80}, /*23 600 M */ + {"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 */ {NULL, 0} }; @@ -275,13 +255,6 @@ DID.TBL EQU $ * ......:..:..:...:....:....:.....:......:........: 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' @@ -330,15 +303,15 @@ MTAB scfi_mod[] = { }; UNIT sda_unit[] = { -/* SET_TYPE(12) SG120 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(12), 0), 0, UNIT_ADDR(0x400)}, /* 0 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(12), 0), 0, UNIT_ADDR(0x410)}, /* 1 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(12), 0), 0, UNIT_ADDR(0x420)}, /* 2 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(12), 0), 0, UNIT_ADDR(0x430)}, /* 3 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(12), 0), 0, UNIT_ADDR(0x440)}, /* 4 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(12), 0), 0, UNIT_ADDR(0x450)}, /* 5 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(12), 0), 0, UNIT_ADDR(0x460)}, /* 6 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(12), 0), 0, UNIT_ADDR(0x470)}, /* 7 */ +/* 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 */ }; //DIB sda_dib = {scfi_preio, scfi_startcmd, NULL, NULL, NULL, scfi_ini, sda_unit, sda_chp, NUM_UNITS_SCFI, 0x0f, 0x0400, 0, 0, 0}; @@ -373,15 +346,15 @@ DEVICE sda_dev = { CHANP sdb_chp[NUM_UNITS_SCFI] = {0}; UNIT sdb_unit[] = { -/* SET_TYPE(10) DM1GB */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(10), 0), 0, UNIT_ADDR(0xC00)}, /* 0 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(10), 0), 0, UNIT_ADDR(0xC10)}, /* 1 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(10), 0), 0, UNIT_ADDR(0xC20)}, /* 2 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(10), 0), 0, UNIT_ADDR(0xC30)}, /* 3 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(10), 0), 0, UNIT_ADDR(0xC40)}, /* 4 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(10), 0), 0, UNIT_ADDR(0xC50)}, /* 5 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(10), 0), 0, UNIT_ADDR(0xC60)}, /* 6 */ - {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(10), 0), 0, UNIT_ADDR(0xC70)}, /* 7 */ +/* 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 */ }; //DIB sdb_dib = {scfi_preio, scfi_startcmd, NULL, NULL, NULL, scfi_ini, sdb_unit, sdb_chp, NUM_UNITS_SCFI, 0x0f, 0x0c00, 0, 0, 0}; @@ -419,11 +392,11 @@ uint8 scfi_preio(UNIT *uptr, uint16 chan) int unit = (uptr - dptr->units); sim_debug(DEBUG_CMD, dptr, "scfi_preio u3 %08x unit=%02x\n", uptr->u3, unit); - if ((uptr->u3 & 0xff00) != 0) { /* just return if busy */ + if ((uptr->u3 & 0xff00) != 0) { /* just return if busy */ return SNS_BSY; } sim_debug(DEBUG_CMD, dptr, "scfi_preio unit=%02x\n", unit); - return 0; /* good to go */ + return 0; /* good to go */ } uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { @@ -433,23 +406,23 @@ uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uint8 ch; sim_debug(DEBUG_CMD, dptr, "scfi_startcmd unit %02x cmd %04x u3 %08x\n", unit, cmd, uptr->u3); - if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ - uptr->u5 |= SNS_INTVENT; /* unit intervention required */ - if (cmd != DSK_SNS) /* we are completed with unit check status */ + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + uptr->u5 |= 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->u3 & DSK_CMDMSK) != 0) { - uptr->u3 |= DSK_BUSY; /* Flag we we are busy */ + uptr->u3 |= DSK_BUSY; /* Flag we we are busy */ return SNS_BSY; } - if ((uptr->u3 & 0xff00) != 0) { /* if any status info, we are busy */ + if ((uptr->u3 & 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); - if ((uptr->flags & UNIT_ATT) == 0) { /* see if unit is attached */ - if (cmd == DSK_SNS) { /* not attached, is cmd Sense 0x04 */ + 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 u4 */ ch = (uptr->u4 >> 24) & 0xff; @@ -494,13 +467,13 @@ uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { chan_write_byte(addr, &ch) ; chan_write_byte(addr, &ch) ; - uptr->u5 &= 0xff000000; /* clear status bytes, but leave mode data */ + uptr->u5 &= 0xff000000; /* clear status bytes, but leave mode data */ return SNS_CHNEND|SNS_DEVEND; } - if (cmd == 0x0) /* INCH cmd gives unit check */ + if (cmd == 0x0) /* INCH cmd gives unit check */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - uptr->u5 |= (SNS_INTVENT|SNS_CMDREJ); /* set new error status */ + uptr->u5 |= (SNS_INTVENT|SNS_CMDREJ); /* set new error status */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* we done */ } @@ -509,9 +482,9 @@ 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 */ + UNIT *up = dptr->units; /* first unit for this device */ sim_debug(DEBUG_CMD, dptr, "scfi_startcmd starting inch cmd addr %04x u4 %08x\n", addr, uptr->u4); /* u4 has IOCD word 1 contents. For the disk processor it contains */ @@ -520,57 +493,56 @@ uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { /* us9 has the byte count from IOCD wd2 and should be 0x24 (36) */ /* the INCH buffer address must be returned in u4 and us9 left non-zero */ /* just return OK and channel software will use up8 as status buffer */ - mema = (uint32)uptr->u4; /* get memory address of buffer */ - uptr->u4 = M[mema>>2]; /* get status buffer address for XIO return status */ + 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, "scfi_startcmd starting inch cmd addr %04x u4 %08x mema %08x 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 */ - up->u6 = M[(mema>>2)+i+1]; /* save each unit's drive data */ + for (i=0; inumunits && i<8; i++) { /* process all drives */ + up->u6 = M[(mema>>2)+i+1]; /* save each unit's drive data */ sim_debug(DEBUG_CMD, dptr, "scfi_startcmd ATTR data %08x unit %02x flags %02x sec %02x MHD %02x FHD %02x\n", up->ATTR, i, (up->ATTR >> 24)&0xff, (up->ATTR >> 16)&0xff, (up->ATTR >> 8)&0xff, (up->ATTR&0xff)); - up++; /* next unit for this device */ + 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->u3 |= DSK_CMDMSK; /* use 0xff for inch, just need int */ - sim_activate(uptr, 20); /* start things off */ + uptr->u3 |= DSK_CMDMSK; /* use 0xff 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->u3 &= ~(DSK_STAR); /* show we do not have seek STAR in u4 */ - case DSK_WD: /* Write command 0x01 */ - case DSK_RD: /* Read command 0x02 */ - case DSK_LMR: /* read mode register */ + case DSK_SCK: /* Seek command 0x07 */ + case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ + uptr->u3 &= ~(DSK_STAR); /* show we do not have seek STAR in u4 */ + case DSK_WD: /* Write command 0x01 */ + case DSK_RD: /* Read command 0x02 */ + case DSK_LMR: /* read mode register */ - uptr->u3 |= cmd; /* save cmd */ + uptr->u3 |= cmd; /* save cmd */ sim_debug(DEBUG_CMD, dptr, "scfi_startcmd done with disk seek r/w cmd %02x addr %04x\n", cmd, addr); - sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 20); /* start things off */ return 0; break; case DSK_NOP: /* NOP 0x03 */ -// return SNS_CHNEND|SNS_DEVEND; /* return OK */ - uptr->u3 |= cmd; /* save cmd */ - sim_activate(uptr, 20); /* start things off */ +// return SNS_CHNEND|SNS_DEVEND; /* return OK */ + uptr->u3 |= cmd; /* save cmd */ + sim_activate(uptr, 20); /* start things off */ return 0; break; - case DSK_SNS: /* Sense 0x04 */ - uptr->u3 |= cmd; /* save cmd */ - sim_activate(uptr, 20); /* start things off */ + case DSK_SNS: /* Sense 0x04 */ + uptr->u3 |= cmd; /* save cmd */ + sim_activate(uptr, 20); /* start things off */ return 0; -// goto dosns; /* use code above */ break; } sim_debug(DEBUG_CMD, dptr, @@ -578,7 +550,7 @@ uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { cmd, addr, uptr->u5); if (uptr->u5 & 0xff) return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - sim_activate(uptr, 20); /* start things off */ + sim_activate(uptr, 20); /* start things off */ return SNS_CHNEND|SNS_DEVEND; } @@ -587,23 +559,27 @@ t_stat scfi_srv(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->u3); DEVICE *dptr = find_dev_from_unit(uptr); - DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to Dev Info Blk for this device */ + 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->up7); int cmd = uptr->u3 & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); - int count = data->count; int32 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 */ + int32 tstart; /* Location of start of cyl/track/sect in data */ uint8 buf2[768]; uint8 buf[768]; 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 */ +// if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ // return SCPE_OK; // } if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ @@ -620,14 +596,14 @@ t_stat scfi_srv(UNIT *uptr) case DSK_CMDMSK: /* use 0xff for inch, just need int */ uptr->u3 &= ~(0xffff); /* remove old cmd */ sim_debug(DEBUG_CMD, dptr, - "disk_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->u3 &= ~(0xffff); /* remove old cmd */ sim_debug(DEBUG_CMD, dptr, - "disk_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; @@ -712,7 +688,7 @@ t_stat scfi_srv(UNIT *uptr) for (i = 0; i < 4; i++) { if (chan_read_byte(chsa, &buf[i])) { /* we have error, bail out */ - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -723,38 +699,36 @@ rezero: unit, buf[0], buf[1], buf[2], buf[3]); /* save STAR (target sector) data in u4 */ uptr->u4 = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]); - cyl = uptr->u4 >> 16; /* get the cylinder */ - trk = buf[2]; /* get the track */ + cyl = uptr->u4 >> 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->u4, 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); - uptr->u3 |= DSK_STAR; /* show we have seek STAR in u4 */ + uptr->u3 |= DSK_STAR; /* show we have seek STAR in u4 */ /* calc the sector address of data */ /* calculate file position in bytes of requested sector */ - data->tstart = uptr->u4 * (scfi_type[type].spb * scfi_type[type].ssiz * 4); /* file offset in bytes */ - data->tpos = trk; /* save the track/head number */ - data->spos = buf[3]; /* save the sector number */ - data->count = 0; /* no data seen yet */ - data->rec = 0; /* number of bytes in this sector */ - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek start %08x trk %04x sec %02x\n", data->tstart, trk, buf[3]); - if ((sim_fseek(uptr->fileref, data->tstart, SEEK_SET)) != 0) { /* seek home */ - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv Error on seek to %08x\n", data->tstart); + tstart = uptr->u4 * (scfi_type[type].spb * scfi_type[type].ssiz * 4); /* file offset in bytes */ + 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]); + if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* seek home */ + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv Error on seek to %08x\n", tstart); } /* Check if already on correct cylinder */ if (trk != data->cyl) { /* Do seek */ - uptr->u3 |= DSK_SEEKING; /* show we are seeking */ + uptr->u3 |= DSK_SEEKING; /* show we are seeking */ sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek unit=%02x trk %04x cyl %04x\n", - unit, trk, data->cyl); + unit, trk, data->cyl); sim_activate(uptr, 20); chan_end(chsa, SNS_CHNEND); } else { sim_debug(DEBUG_DETAIL, dptr, "scfi_srv calc sect addr seek start %08x trk %04x sec %02x\n", - data->tstart, trk, buf[3]); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + tstart, trk, buf[3]); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ sim_activate(uptr, 20); chan_end(chsa, SNS_DEVEND|SNS_CHNEND); } @@ -764,22 +738,22 @@ rezero: sim_debug(DEBUG_CMD, dptr, "RD REZERO IPL unit=%02x seek 0\n", unit); /* Do a seek to 0 */ - uptr->u4 = 0; /* set STAR to 0, 0, 0 */ - uptr->u3 &= ~(0xffff); /* remove old cmd */ - uptr->u3 |= DSK_SCK; /* show as seek command */ - data->tstart = 0; /* byte offset is 0 */ - data->dlen = 0; /* no data written yet */ + uptr->u4 = 0; /* set STAR to 0, 0, 0 */ + uptr->u3 &= ~(0xffff); /* remove old cmd */ + uptr->u3 |= 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->u3 &= ~(0xffff); /* remove old status bits & cmd */ + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } /* zero stuff */ buf[0] = buf[1] = buf[2] = buf[3] = 0; - goto rezero; /* murge with seek code */ + goto rezero; /* murge with seek code */ break; case DSK_LMR: @@ -787,125 +761,120 @@ rezero: /* Read in 1 character of mode data */ if (chan_read_byte(chsa, &buf[0])) { /* we have error, bail out */ - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } - uptr->u3 &= ~(0xffff); /* remove old cmd */ - uptr->u5 &= 0x00ffffff; /* clear old mode data */ - uptr->u5 |= (buf[0] << 24); /* save mode value */ + uptr->u3 &= ~(0xffff); /* remove old cmd */ + uptr->u5 &= 0x00ffffff; /* clear old mode data */ + uptr->u5 |= (buf[0] << 24); /* save mode value */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; case DSK_RD: /* Read Data */ - /* data->tstart has start of sector address in bytes */ + /* tstart has start of sector address in bytes */ if ((uptr->u3 & DSK_READING) == 0) { /* see if we are reading data */ - uptr->u3 |= DSK_READING; /* read from disk starting */ - data->dlen = 0; /* no data read yet */ - sim_debug(DEBUG_CMD, dptr, "DISK READ starting unit=%02x u3 %08x count %04x rec %04x\n", - unit, uptr->u3, count, data->rec); + uptr->u3 |= DSK_READING; /* read from disk starting */ + dlen = 0; /* no data read yet */ + sim_debug(DEBUG_CMD, dptr, "DISK READ starting unit=%02x u3 %08x count %04x\n", + unit, uptr->u3, chp->ccw_count); } - if (uptr->u3 & DSK_READING) { /* see if we are reading data */ + if (uptr->u3 & DSK_READING) { /* see if we are reading data */ /* read in a sector of data from disk */ - if ((count=sim_fread(buf, 1, data->ssize, uptr->fileref)) != data->ssize) { - sim_debug(DEBUG_CMD, dptr, "Error %08x on read %04x of diskfile cyl %04x hds %02x sec %02x\n", - count, data->ssize, data->cyl, data->tpos, data->spos); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ -// sim_activate(uptr, 20); + 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->u3 &= ~(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); /* process the next sector of data */ - data->rec = count; /* no bytes in sector yet */ - count = 0; /* used here as a flag for short write */ - for (i=0; i<(data->rec); i++) { - ch = buf[i]; /* get a char from buffer */ + for (i=0; idlen+i, data->cyl, data->tpos, data->spos, data->tstart); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + dlen+i, data->cyl, data->tpos, data->spos, tstart); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); goto rddone; } } - data->dlen += data->rec; /* add byte read to total count */ + dlen += len; /* add byte read to total count */ sim_debug(DEBUG_CMD, dptr, "DISK READ from sec end %04x bytes end %04x from diskfile cyl %04x hds %02x sec %02x tstart %08x\n", - data->dlen, data->ssize, data->cyl, data->tpos, data->spos, data->tstart); + dlen, ssize, data->cyl, data->tpos, data->spos, tstart); data->spos++; /* see if we are done reading data */ if (test_write_byte_end(chsa)) { sim_debug(DEBUG_DATAIO, dptr, "DISK Read complete Read %04x bytes from diskfile cyl %04x hds %02x sec %02x tstart %08x\n", - data->dlen, data->cyl, data->tpos, data->spos, data->tstart); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + dlen, data->cyl, data->tpos, data->spos, tstart); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); } rddone: -// sim_activate(uptr, 20); - sim_activate(uptr, 10); /* wait to read next sector */ + sim_activate(uptr, 10); /* wait to read next sector */ break; } break; case DSK_WD: /* Write Data */ - /* data->tstart has start of sector address in bytes */ - if ((uptr->u3 & DSK_WRITING) == 0) { /* see if we are writing data */ - uptr->u3 |= DSK_WRITING; /* write to disk starting */ - data->dlen = 0; /* no data written yet */ - sim_debug(DEBUG_CMD, dptr, "DISK WRITE starting unit=%02x u3 %08x bytes %04x rec %04x\n", - unit, uptr->u3, data->dlen, data->rec); + /* tstart has start of sector address in bytes */ + if ((uptr->u3 & DSK_WRITING) == 0) { /* see if we are writing data */ + uptr->u3 |= DSK_WRITING; /* write to disk starting */ + dlen = 0; /* no data written yet */ + sim_debug(DEBUG_CMD, dptr, "DISK WRITE starting unit=%02x u3 %08x bytes %04x\n", + unit, uptr->u3, dlen); } - if (uptr->u3 & DSK_WRITING) { /* see if we are writing data */ + if (uptr->u3 & DSK_WRITING) { /* see if we are writing data */ /* process the next sector of data */ - data->rec = 0; /* no bytes in sector yet */ - count = 0; /* used here as a flag for short read */ - for (i=0; i<(data->ssize); i++) { + len = 0; /* used here as a flag for short read */ + for (i=0; iu3 &= ~(0xffff); /* remove old status bits & cmd */ sim_debug(DEBUG_DATAIO, dptr, "DISK Wrote %04x bytes to diskfile cyl %04x hds %02x sec %02x tstart %08x\n", - data->dlen, data->cyl, data->tpos, data->spos, data->tstart); + ssize, data->cyl, data->tpos, data->spos, tstart); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); goto wrdone; } - ch = 0; /* finish out the sector with zero */ - count++; /* show we have no more data to write */ + ch = 0; /* finish out the sector with zero */ + len++; /* show we have no more data to write */ } - buf2[i] = ch; /* save the char */ + buf2[i] = ch; /* save the char */ } - data->dlen += data->ssize; /* add 1 sector of bytes */ + dlen += ssize; /* add 1 sector of bytes */ /* write the sector to disk */ - if ((i=sim_fwrite(buf2, 1, data->ssize, uptr->fileref)) != data->ssize) { + if ((i=sim_fwrite(buf2, 1, ssize, uptr->fileref)) != ssize) { sim_debug(DEBUG_CMD, dptr, "Error %08x on write %04x to diskfile cyl %04x hds %02x sec %02x\n", - i, data->ssize, data->cyl, data->tpos, data->spos); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + i, ssize, data->cyl, data->tpos, data->spos); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } - if (count != 0) { /* see if done with write command */ + if (len != 0) { /* see if done with write command */ sim_debug(DEBUG_DATAIO, dptr, "DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x tstart %08x\n", - data->dlen, data->cyl, data->tpos, data->spos, data->tstart); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + ssize, data->cyl, data->tpos, data->spos, tstart); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; } sim_debug(DEBUG_CMD, dptr, "DISK WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x tstart %08x\n", - data->dlen, data->ssize, data->cyl, data->tpos, data->spos, data->tstart); + dlen, ssize, data->cyl, data->tpos, data->spos, tstart); data->spos++; wrdone: -// sim_activate(uptr, 20); sim_activate(uptr, 10); break; } @@ -914,11 +883,12 @@ wrdone: default: sim_debug(DEBUG_DETAIL, dptr, "invalid command %02x unit %02x\n", cmd, unit); uptr->u5 |= SNS_CMDREJ; - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } - sim_debug(DEBUG_CMD, dptr, "scfi_srv done cmd %02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); + sim_debug(DEBUG_CMD, dptr, + "scfi_srv done cmd %02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); return SCPE_OK; } @@ -928,7 +898,7 @@ void scfi_ini(UNIT *uptr, t_bool f) DEVICE *dptr = find_dev_from_unit(uptr); int i = GET_TYPE(uptr->flags); - uptr->u3 &= ~0xffff; /* clear out the flags but leave ch/sa */ + uptr->u3 &= ~0xffff; /* clear out the flags but leave ch/sa */ /* capacity is total allocation units times sectors per allocation unit */ /* total sectors on disk */ uptr->capac = scfi_type[i].taus * scfi_type[i].spau; @@ -949,11 +919,12 @@ int scfi_format(UNIT *uptr) { uint16 addr = GET_UADDR(uptr->u3); int type = GET_TYPE(uptr->flags); DEVICE *dptr = find_dev_from_unit(uptr); - uint16 tsize = data->tsize; /* get track size in bytes */ + 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 */ + uint32 cylv = cap / spc; /* calc number of cylinders */ uint8 *buff; /* see if user wants to initialize the disk */ @@ -976,10 +947,10 @@ 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 * data->ssize); + sim_debug(DEBUG_CMD, dptr, "Creating disk file of trk size %04x capacity %d\n", tsize, cap*ssize); /* write zeros to each track of the disk */ for (cyl = 0; cyl < cylv; cyl++) { - if ((sim_fwrite(buff, 1, data->tsize, uptr->fileref)) != data->tsize) { + if ((sim_fwrite(buff, 1, tsize, uptr->fileref)) != tsize) { sim_debug(DEBUG_CMD, dptr, "Error on write to diskfile cyl %04x\n", cyl); } if (cyl == 0) { @@ -994,12 +965,9 @@ int scfi_format(UNIT *uptr) { fputc('\r', stderr); fputc('\n', stderr); /* seek home again */ - sim_fseek(uptr->fileref, 0, SEEK_SET); /* seek home */ - free(buff); /* free cylinder buffer */ - data->cpos = 0; - data->ccyl = 0; - set_devattn(addr, SNS_DEVEND); /* start us up */ -// sim_activate(uptr, 100); + sim_fseek(uptr->fileref, 0, SEEK_SET); /* seek home */ + free(buff); /* free cylinder buffer */ + set_devattn(addr, SNS_DEVEND); /* start us up */ return 0; } @@ -1009,8 +977,8 @@ t_stat scfi_attach(UNIT *uptr, CONST char *file) { int type = GET_TYPE(uptr->flags); DEVICE *dptr = find_dev_from_unit(uptr); t_stat r; - uint16 tsize; /* track size in bytes */ - uint16 ssize; /* sector size in bytes */ + uint16 tsize; /* track size in bytes */ + uint16 ssize; /* sector size in bytes */ struct ddata_t *data; uint8 buff[1024]; @@ -1018,9 +986,9 @@ t_stat scfi_attach(UNIT *uptr, CONST char *file) { if ((r = attach_unit(uptr, file)) != SCPE_OK) return r; - if (scfi_type[type].name == 0) { /* does the assigned disk have a name */ - detach_unit(uptr); /* no, reject */ - return SCPE_FMT; /* error */ + if (scfi_type[type].name == 0) { /* does the assigned disk have a name */ + detach_unit(uptr); /* no, reject */ + return SCPE_FMT; /* error */ } /* get a buffer to hold scfi_t structure */ @@ -1030,21 +998,19 @@ t_stat scfi_attach(UNIT *uptr, CONST char *file) { return SCPE_FMT; } - uptr->up7 = (void *)data; /* save pointer to structure in up7 */ + 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 */ - data->tsize = tsize; /* save size of track 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 */ - data->ssize = ssize; /* save sector size bytes */ + ssize = scfi_type[type].ssiz * 4; /* disk sector size in bytes */ + uptr->capac *= ssize; /* disk capacity in bytes */ 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 */ if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ - detach_unit(uptr); /* if no space, error */ - return SCPE_FMT; /* error */ + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ } /* read in the 1st sector of the 'disk' */ @@ -1060,24 +1026,18 @@ t_stat scfi_attach(UNIT *uptr, CONST char *file) { fmt: /* format the drive */ if (scfi_format(uptr)) { - detach_unit(uptr); /* if no space, error */ - return SCPE_FMT; /* error */ + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ } } if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ - detach_unit(uptr); /* if no space, error */ - return SCPE_FMT; /* error */ + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ } - data->ssize = ssize; /* save sector size in bytes */ - data->tsize = tsize; /* save track size in bytes */ - data->cpos = 0; /* current read/write position in cylinder*/ - data->ccyl = 0; /* current cylinder number */ - data->tpos = 0; /* current track position */ - data->spos = 0; /* current sector position */ - data->rec = 0; /* record length */ - data->count = 0; /* clear count value */ + 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", scfi_type[type].name, scfi_type[type].nhds, scfi_type[type].spt, @@ -1094,22 +1054,22 @@ t_stat scfi_detach(UNIT *uptr) { struct ddata_t *data = (struct ddata_t *)uptr->up7; if (data != 0) { - free(data); /* free disk data structure */ + free(data); /* free disk data structure */ } - uptr->up7 = 0; /* no pointer to disk data */ - uptr->u3 &= ~0xffff; /* no cmd and flags */ - return detach_unit(uptr); /* tell simh we are done with disk */ + uptr->up7 = 0; /* no pointer to disk data */ + uptr->u3 &= ~0xffff; /* no cmd and flags */ + return detach_unit(uptr); /* tell simh we are done with disk */ } /* boot from the specified disk unit */ t_stat scfi_boot(int32 unit_num, DEVICE *dptr) { - UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */ + 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->u3)); - SPAD[0xf4] = GET_UADDR(uptr->u3); /* put boot device chan/sa into spad */ - SPAD[0xf8] = 0xF000; /* show as F class device */ + SPAD[0xf4] = GET_UADDR(uptr->u3); /* 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? */ + return SCPE_UNATT; /* attached? */ return chan_boot(GET_UADDR(uptr->u3), dptr); /* boot the ch/sa */ } diff --git a/SEL32/sel32_sys.c b/SEL32/sel32_sys.c index bca51ae..3a2f1a7 100644 --- a/SEL32/sel32_sys.c +++ b/SEL32/sel32_sys.c @@ -32,30 +32,29 @@ extern uint32 PSD[]; /* SCP data structures and interface routines - The interface between the simulator control package (SCP) and the - simulator consists of the following routines and data structures +The interface between the simulator control package (SCP) and the +simulator consists of the following routines and data structures - sim_name simulator name string - sim_devices[] array of pointers to simulated devices - sim_PC pointer to saved PC register descriptor - sim_interval simulator interval to next event (in sel32_cpu.c) - sim_stop_messages[] array of pointers to stop messages - sim_instr() instruction execution routine (in sel32_cpu.c) - sim_load() binary loader routine - sim_emax maximum number of words for examine +sim_name simulator name string +sim_devices[] array of pointers to simulated devices +sim_PC pointer to saved PC register descriptor +sim_interval simulator interval to next event (in sel32_cpu.c) +sim_stop_messages[] array of pointers to stop messages +sim_instr() instruction execution routine (in sel32_cpu.c) +sim_load() binary loader routine +sim_emax maximum number of words for examine - In addition, the simulator must supply routines to print and parse - architecture specific formats +In addition, the simulator must supply routines to print and parse +architecture specific formats - fprint_sym print symbolic output - fparse_sym parse symbolic input +fprint_sym print symbolic output +fparse_sym parse symbolic input */ -char sim_name[] = "SEL 32"; /* our simulator name */ +char sim_name[] = "SEL-32"; /* our simulator name */ REG *sim_PC = &cpu_reg[0]; -//old int32 sim_emax = 1; /* maximum number of instructions/words to examine */ int32 sim_emax = 4; /* maximum number of instructions/words to examine */ DEVICE *sim_devices[] = { @@ -97,6 +96,12 @@ DEVICE *sim_devices[] = { &sdb_dev, #endif #endif +#ifdef NUM_DEVS_HSDP + &dpa_dev, +#if NUM_DEVS_HSDP > 1 + &dpb_dev, +#endif +#endif #ifdef NUM_DEVS_COM &coml_dev, &com_dev, @@ -142,10 +147,8 @@ int get_word(FILE *fileref, uint32 *word) if (sim_fread(cbuf, 1, 4, fileref) != 4) return 1; /* read error or eof */ /* byte swap while reading data */ - *word = ((cbuf[0]) << 24) | - ((cbuf[1]) << 16) | - ((cbuf[2]) << 8) | - ((cbuf[3])); + *word = ((cbuf[0]) << 24) | ((cbuf[1]) << 16) | + ((cbuf[2]) << 8) | ((cbuf[3])); return 0; /* all OK */ }