Fix bug in interrupt handling in KI when EPT not at 0. Fix bug with handling of CCW_COMP flag on DF10 devices.
996 lines
36 KiB
C
996 lines
36 KiB
C
/* kx10_dp.c: Dec Data Products Disk Drive.
|
||
|
||
Copyright (c) 2013-2020, Richard Cornwell
|
||
|
||
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
|
||
RICHARD CORNWELL 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 "kx10_defs.h"
|
||
#include "kx10_disk.h"
|
||
|
||
#ifndef NUM_DEVS_DP
|
||
#define NUM_DEVS_DP 0
|
||
#endif
|
||
|
||
#if (NUM_DEVS_DP > 0)
|
||
|
||
#if KL
|
||
#define DP_DIS DEV_DIS
|
||
#endif
|
||
|
||
#ifndef DP_DIS
|
||
#define DP_DIS 0
|
||
#endif
|
||
|
||
#define BUF_EMPTY(u) (u->hwmark == 0xFFFFFFFF)
|
||
#define CLR_BUF(u) u->hwmark = 0xFFFFFFFF
|
||
|
||
#define RP_NUMWD 128 /* 36bit words/sec */
|
||
#define DP_DEVNUM 0250 /* First device number */
|
||
#define NUM_UNITS_DP 8
|
||
|
||
/* Flags in the unit flags word */
|
||
|
||
#define DEV_WHDR (1 << DEV_V_UF) /* Enable write headers */
|
||
#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */
|
||
#define UNIT_M_DTYPE 3
|
||
#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE)
|
||
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
|
||
|
||
/* Parameters in the unit descriptor */
|
||
|
||
#define CUR_CYL u3 /* current cylinder */
|
||
#define DATAPTR u4 /* data pointer */
|
||
#define UFLAGS u5 /* Function */
|
||
#define STATUS u6 /* Drive status */
|
||
#define SECT_CNT up7 /* Sector counter */
|
||
#define CONTROL 007
|
||
#define CMD_MASK 070
|
||
#define SEEK_DONE 0100 /* Seek finished */
|
||
#define SEEK_STATE 0200 /* Seek in progress */
|
||
#define DONE 0400 /* Done bit */
|
||
|
||
|
||
/* CONI/CONO Flags */
|
||
#define CCW_COMP 0000000000040LL
|
||
#define SUF_ERR 0000000000100LL
|
||
#define SEC_ERR 0000000000200LL
|
||
#define ILL_CMD 0000000000400LL
|
||
#define ILL_WR 0000000001000LL
|
||
#define NOT_RDY 0000000002000LL /* Clear CXR */
|
||
#define PRT_ERR 0000000004000LL /* 14-17 Clear CCPE, DSPE, DISK WDPE, CDPE */
|
||
#define NXM_ERR 0000000010000LL
|
||
#define SLW_CHN 0000000020000LL
|
||
#define SRC_ERR 0000000040000LL
|
||
#define PWR_FAIL_10 0000000100000LL
|
||
#define END_CYL 0000000200000LL /* No effect */
|
||
#define SRC_DONE 0000000400000LL /* No effect */
|
||
#define DSK_PRTY 0000001000000LL /* No effect */
|
||
#define CHN_PRTY 0000002000000LL /* No effect */
|
||
#define SEC_PRTY 0000004000000LL /* No effect */
|
||
#define CCW_PRTY 0000010000000LL /* No effect */
|
||
#define B22_FLAG 0000020000000LL
|
||
|
||
#define CLRMSK 0000000177710LL
|
||
#define CLRMSK2 0000176000000LL
|
||
|
||
/* DATAO */
|
||
#define DWPE_STOP 0000000001000LL
|
||
#define SPARE 0000000002000LL
|
||
#define DSPE_STOP 0000000004000LL
|
||
#define SECTOR 0000000170000LL
|
||
#define CYL256 0000000200000LL
|
||
#define SURFACE 0000017400000LL
|
||
#define CYL 0007760000000LL
|
||
#define DRIVE 0070000000000LL
|
||
#define OP 0700000000000LL
|
||
|
||
#define RD 0
|
||
#define WR 1
|
||
#define RV 2
|
||
#define WH 3
|
||
#define SK 4
|
||
#define CL 5
|
||
#define NO 6
|
||
#define RC 7
|
||
|
||
/* DATAI Flags */
|
||
#define ATTN 0000000000776LL
|
||
#define DEFECT 0000000001000LL
|
||
#define SEL_RP03 0000000002000LL
|
||
#define SEL_CYL256 0000000004000LL
|
||
#define SEL_SPARE 0000000010000LL
|
||
#define SEL_SEC 0000000760000LL
|
||
#define WR_HD_LK 0000001000000LL
|
||
#define RD_ONLY 0000002000000LL
|
||
#define NO_DRIVE 0000004000000LL
|
||
#define FILE_UNSAFE 0000010000000LL
|
||
#define DRV_ONLINE 0000020000000LL
|
||
#define ON_CYL 0000040000000LL
|
||
#define SEEK_INC 0000100000000LL
|
||
#define SEL_CYL 0077600000000LL
|
||
#define SEL_DRIVE 0700000000000LL
|
||
|
||
#define RP01_DTYPE 0
|
||
#define RP01_SECT 5
|
||
#define RP01_SURF 10
|
||
#define RP01_CYL 203
|
||
#define RP01_DEV 0
|
||
#define RP01_SIZE (RP01_SECT * RP01_SURF * RP01_CYL * RP_NUMWD)
|
||
|
||
#define RP02_DTYPE 1
|
||
#define RP02_SECT 10
|
||
#define RP02_SURF 20
|
||
#define RP02_CYL 203
|
||
#define RP02_DEV 0
|
||
#define RP02_SIZE (RP02_SECT * RP02_SURF * RP02_CYL * RP_NUMWD)
|
||
|
||
#define RP03_DTYPE 2
|
||
#define RP03_SECT 10
|
||
#define RP03_SURF 20
|
||
#define RP03_CYL 406
|
||
#define RP03_DEV 1
|
||
#define RP03_SIZE (RP03_SECT * RP03_SURF * RP03_CYL * RP_NUMWD)
|
||
|
||
struct drvtyp {
|
||
int32 sect; /* sectors */
|
||
int32 surf; /* surfaces */
|
||
int32 cyl; /* cylinders */
|
||
int32 size; /* #blocks */
|
||
int32 devtype; /* device type */
|
||
};
|
||
|
||
struct drvtyp dp_drv_tab[] = {
|
||
{ RP01_SECT, RP01_SURF, RP01_CYL, RP01_SIZE, RP01_DTYPE},
|
||
{ RP02_SECT, RP02_SURF, RP02_CYL, RP02_SIZE, RP02_DTYPE},
|
||
{ RP03_SECT, RP03_SURF, RP03_CYL, RP03_SIZE, RP03_DTYPE},
|
||
{ 0 }
|
||
};
|
||
|
||
|
||
struct df10 dp_df10[NUM_DEVS_DP];
|
||
uint32 dp_cur_unit[NUM_DEVS_DP];
|
||
uint64 dp_buf[NUM_DEVS_DP][RP_NUMWD];
|
||
int readin_flag = 0;
|
||
|
||
t_stat dp_devio(uint32 dev, uint64 *data);
|
||
t_stat dp_svc(UNIT *);
|
||
t_stat dp_boot(int32, DEVICE *);
|
||
void dp_ini(UNIT *, t_bool);
|
||
t_stat dp_reset(DEVICE *);
|
||
t_stat dp_attach(UNIT *, CONST char *);
|
||
t_stat dp_detach(UNIT *);
|
||
t_stat dp_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||
t_stat dp_set_hdr(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||
t_stat dp_show_hdr(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||
t_stat dp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
|
||
const char *cptr);
|
||
const char *dp_description (DEVICE *dptr);
|
||
|
||
UNIT dp_unit[] = {
|
||
/* Controller 1 */
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
|
||
#if (NUM_DEVS_DP > 1)
|
||
/* Controller 2 */
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
#if (NUM_DEVS_DP > 2)
|
||
/* Controller 3 */
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
#if (NUM_DEVS_DP > 3)
|
||
/* Controller 4 */
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||
UNIT_ROABLE+(RP03_DTYPE << UNIT_V_DTYPE), RP03_SIZE) },
|
||
#endif
|
||
#endif
|
||
#endif
|
||
};
|
||
|
||
DIB dp_dib[] = {
|
||
{DP_DEVNUM+000, 1, &dp_devio, NULL},
|
||
{DP_DEVNUM+004, 1, &dp_devio, NULL},
|
||
{DP_DEVNUM+010, 1, &dp_devio, NULL},
|
||
{DP_DEVNUM+014, 1, &dp_devio, NULL}};
|
||
|
||
|
||
MTAB dp_mod[] = {
|
||
{ MTAB_XTD|MTAB_VUN, 0, "write enabled", "WRITEENABLED",
|
||
&set_writelock, &show_writelock, NULL, "Write enable drive" },
|
||
{ MTAB_XTD|MTAB_VUN, 1, NULL, "LOCKED",
|
||
&set_writelock, NULL, NULL, "Write lock drive" },
|
||
{MTAB_XTD|MTAB_VDV, 0, NULL, "NOHEADERS",
|
||
&dp_set_hdr, &dp_show_hdr, NULL, "Disable header writing"},
|
||
{MTAB_XTD|MTAB_VDV, DEV_WHDR, "write header", "HEADERS",
|
||
&dp_set_hdr, &dp_show_hdr, NULL, "Enable header writing"},
|
||
{UNIT_DTYPE, (RP03_DTYPE << UNIT_V_DTYPE), "RP03", "RP03", &dp_set_type },
|
||
{UNIT_DTYPE, (RP02_DTYPE << UNIT_V_DTYPE), "RP02", "RP02", &dp_set_type },
|
||
{UNIT_DTYPE, (RP01_DTYPE << UNIT_V_DTYPE), "RP01", "RP01", &dp_set_type },
|
||
{MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", NULL, &disk_show_fmt },
|
||
{0},
|
||
};
|
||
|
||
REG dpa_reg[] = {
|
||
{BRDATA(BUFF, dp_buf[0], 16, 64, RP_NUMWD), REG_HRO},
|
||
{HRDATA(UNIT, dp_cur_unit[0], 32), REG_HRO},
|
||
{FLDATA(READIN, readin_flag, 0), REG_HRO},
|
||
{ORDATA(STATUS, dp_df10[0].status, 18), REG_RO},
|
||
{ORDATA(CIA, dp_df10[0].cia, 18)},
|
||
{ORDATA(CCW, dp_df10[0].ccw, 18)},
|
||
{ORDATA(WCR, dp_df10[0].wcr, 18)},
|
||
{ORDATA(CDA, dp_df10[0].cda, 18)},
|
||
{ORDATA(DEVNUM, dp_df10[0].devnum, 9), REG_HRO},
|
||
{ORDATA(BUF, dp_df10[0].buf, 36), REG_HRO},
|
||
{ORDATA(NXM, dp_df10[0].nxmerr, 8), REG_HRO},
|
||
{0}
|
||
};
|
||
|
||
DEVICE dpa_dev = {
|
||
"DPA", dp_unit, dpa_reg, dp_mod,
|
||
NUM_UNITS_DP, 8, 18, 1, 8, 36,
|
||
NULL, NULL, &dp_reset, &dp_boot, &dp_attach, &dp_detach,
|
||
&dp_dib[0], DEV_DISABLE | DEV_DEBUG | DP_DIS, 0, dev_debug,
|
||
NULL, NULL, &dp_help, NULL, NULL, &dp_description
|
||
};
|
||
|
||
#if (NUM_DEVS_DP > 1)
|
||
REG dpb_reg[] = {
|
||
{BRDATA(BUFF, dp_buf[1], 16, 64, RP_NUMWD), REG_HRO},
|
||
{HRDATA(DF10, dp_cur_unit[1], 32), REG_HRO},
|
||
{ORDATA(STATUS, dp_df10[1].status, 18), REG_RO},
|
||
{ORDATA(CIA, dp_df10[1].cia, 18)},
|
||
{ORDATA(CCW, dp_df10[1].ccw, 18)},
|
||
{ORDATA(WCR, dp_df10[1].wcr, 18)},
|
||
{ORDATA(CDA, dp_df10[1].cda, 18)},
|
||
{ORDATA(DEVNUM, dp_df10[1].devnum, 9), REG_HRO},
|
||
{ORDATA(BUF, dp_df10[1].buf, 36), REG_HRO},
|
||
{ORDATA(NXM, dp_df10[1].nxmerr, 8), REG_HRO},
|
||
{0}
|
||
};
|
||
|
||
DEVICE dpb_dev = {
|
||
"DPB", &dp_unit[010], dpb_reg, dp_mod,
|
||
NUM_UNITS_DP, 8, 18, 1, 8, 36,
|
||
NULL, NULL, &dp_reset, &dp_boot, &dp_attach, &dp_detach,
|
||
&dp_dib[1], DEV_DISABLE | DEV_DEBUG | DP_DIS, 0, dev_debug,
|
||
NULL, NULL, &dp_help, NULL, NULL, &dp_description
|
||
};
|
||
|
||
#if (NUM_DEVS_DP > 2)
|
||
REG dpc_reg[] = {
|
||
{BRDATA(BUFF, dp_buf[2], 16, 64, RP_NUMWD), REG_HRO},
|
||
{HRDATA(DF10, dp_cur_unit[2], 32), REG_HRO},
|
||
{ORDATA(STATUS, dp_df10[2].status, 18), REG_RO},
|
||
{ORDATA(CIA, dp_df10[2].cia, 18)},
|
||
{ORDATA(CCW, dp_df10[2].ccw, 18)},
|
||
{ORDATA(WCR, dp_df10[2].wcr, 18)},
|
||
{ORDATA(CDA, dp_df10[2].cda, 18)},
|
||
{ORDATA(DEVNUM, dp_df10[2].devnum, 9), REG_HRO},
|
||
{ORDATA(BUF, dp_df10[2].buf, 36), REG_HRO},
|
||
{ORDATA(NXM, dp_df10[2].nxmerr, 8), REG_HRO},
|
||
{0}
|
||
};
|
||
|
||
DEVICE dpc_dev = {
|
||
"DPC", &dp_unit[020], dpc_reg, dp_mod,
|
||
NUM_UNITS_DP, 8, 18, 1, 8, 36,
|
||
NULL, NULL, &dp_reset, &dp_boot, &dp_attach, &dp_detach,
|
||
&dp_dib[2], DEV_DISABLE | DEV_DEBUG | DP_DIS, 0, dev_debug,
|
||
NULL, NULL, &dp_help, NULL, NULL, &dp_description
|
||
};
|
||
|
||
#if (NUM_DEVS_DP > 3)
|
||
REG dpd_reg[] = {
|
||
{BRDATA(BUFF, &dp_buf[3][0], 16, 64, RP_NUMWD), REG_HRO},
|
||
{BRDATA(DF10, dp_cur_unit[3], 32), REG_HRO},
|
||
{ORDATA(STATUS, dp_df10[3].status, 18), REG_RO},
|
||
{ORDATA(CIA, dp_df10[3].cia, 18)},
|
||
{ORDATA(CCW, dp_df10[3].ccw, 18)},
|
||
{ORDATA(WCR, dp_df10[3].wcr, 18)},
|
||
{ORDATA(CDA, dp_df10[3].cda, 18)},
|
||
{ORDATA(DEVNUM, dp_df10[3].devnum, 9), REG_HRO},
|
||
{ORDATA(BUF, dp_df10[3].buf, 36), REG_HRO},
|
||
{ORDATA(NXM, dp_df10[3].nxmerr, 8), REG_HRO},
|
||
{0}
|
||
};
|
||
|
||
DEVICE dpd_dev = {
|
||
"DPD", &dp_unit[030], dpd_reg, dp_mod,
|
||
NUM_UNITS_DP, 8, 18, 1, 8, 36,
|
||
NULL, NULL, &dp_reset, &dp_boot, &dp_attach, &dp_detach,
|
||
&dp_dib[3], DEV_DISABLE | DEV_DEBUG | DP_DIS, 0, dev_debug,
|
||
NULL, NULL, &dp_help, NULL, NULL, &dp_description
|
||
};
|
||
|
||
#endif
|
||
#endif
|
||
#endif
|
||
|
||
DEVICE *dp_devs[] = {
|
||
&dpa_dev,
|
||
#if (NUM_DEVS_DP > 1)
|
||
&dpb_dev,
|
||
#if (NUM_DEVS_DP > 2)
|
||
&dpc_dev,
|
||
#if (NUM_DEVS_DP > 3)
|
||
&dpd_dev,
|
||
#endif
|
||
#endif
|
||
#endif
|
||
};
|
||
|
||
|
||
t_stat dp_devio(uint32 dev, uint64 *data) {
|
||
uint64 res;
|
||
int ctlr = (dev - DP_DEVNUM) >> 2;
|
||
struct df10 *df10;
|
||
DEVICE *dptr;
|
||
UNIT *uptr;
|
||
int unit;
|
||
int cyl;
|
||
int tmp;
|
||
static int sect_count;
|
||
|
||
if (ctlr < 0 || ctlr >= NUM_DEVS_DP)
|
||
return SCPE_OK;
|
||
|
||
df10 = &dp_df10[ctlr];
|
||
dptr = dp_devs[ctlr];
|
||
unit = dp_cur_unit[ctlr];
|
||
uptr = &dp_unit[(ctlr * NUM_UNITS_DP) + unit];
|
||
switch(dev & 3) {
|
||
case CONI:
|
||
*data = (uint64)(df10->status | uptr->STATUS);
|
||
#if KI_22BIT
|
||
if (cpu_unit[0].flags & UNIT_DF10C) {
|
||
*data |= B22_FLAG;
|
||
}
|
||
#endif
|
||
sim_debug(DEBUG_CONI, dptr, "DP %03o CONI %012llo %d PC=%o\n", dev,
|
||
*data, ctlr, PC);
|
||
break;
|
||
|
||
case CONO:
|
||
clr_interrupt(dev);
|
||
df10->status &= ~07LL;
|
||
df10->status |= *data & 07LL;
|
||
if (*data & BUSY) {
|
||
/* Stop controller */
|
||
sim_cancel(uptr);
|
||
df10_finish_op(df10, 0);
|
||
uptr->STATUS &= ~(BUSY);
|
||
}
|
||
/* Clear flags */
|
||
uptr->STATUS &= ~(*data & CLRMSK);
|
||
if (*data & PRT_ERR)
|
||
uptr->STATUS &= ~(CLRMSK2);
|
||
if (*data & CCW_COMP) {
|
||
df10_writecw(df10);
|
||
df10->status |= CCW_COMP;
|
||
}
|
||
if (*data & PI_ENABLE) {
|
||
uptr->UFLAGS &= ~DONE;
|
||
/* Check if any drives still reporting seek done */
|
||
tmp = 1;
|
||
uptr = &dp_unit[ctlr * NUM_UNITS_DP];
|
||
for(unit = 0; unit < NUM_UNITS_DP; unit++) {
|
||
if (uptr->UFLAGS & SEEK_DONE) {
|
||
tmp = 0;
|
||
break;
|
||
}
|
||
uptr++;
|
||
}
|
||
if (tmp)
|
||
df10->status &= ~PI_ENABLE;
|
||
else
|
||
df10_setirq(df10);
|
||
}
|
||
sim_debug(DEBUG_CONO, dptr, "DP %03o CONO %06o %d PC=%o %06o\n", dev,
|
||
(uint32)*data, ctlr, PC, df10->status);
|
||
break;
|
||
|
||
case DATAI:
|
||
res = (uint64)(unit) << 33;
|
||
if ((dptr->flags & DEV_WHDR) == 0)
|
||
res |= WR_HD_LK; /* Can't write headers. */
|
||
if (dp_drv_tab[GET_DTYPE(uptr->flags)].devtype == RP03_DTYPE)
|
||
res |= SEL_RP03;
|
||
if (uptr->flags & UNIT_DIS) {
|
||
res |= NO_DRIVE;
|
||
} else if (uptr->flags & UNIT_ATT) {
|
||
res |= DRV_ONLINE;
|
||
cyl = uptr->CUR_CYL;
|
||
res |= ((uint64)(cyl & 0377)) << 25;
|
||
if (cyl & 0400)
|
||
res |= SEL_CYL256;
|
||
if (sect_count > 20)
|
||
sect_count = 0;
|
||
res |= SEL_SEC & (uint64)(sect_count << 13);
|
||
sect_count++;
|
||
if ((uptr->UFLAGS & SEEK_STATE) == 0)
|
||
res |= ON_CYL;
|
||
if (uptr->flags & UNIT_WPRT)
|
||
res |= RD_ONLY|WR_HD_LK;
|
||
}
|
||
uptr = &dp_unit[ctlr * NUM_UNITS_DP];
|
||
for(unit = 0; unit < NUM_UNITS_DP; unit++) {
|
||
if (uptr->UFLAGS & SEEK_DONE)
|
||
res |= 0400>>unit;
|
||
uptr++;
|
||
}
|
||
sim_debug(DEBUG_DATAIO, dptr, "DP %03o DATI %012llo %d PC=%o F=%o %o\n",
|
||
dev, res, ctlr, PC, uptr->UFLAGS, sect_count);
|
||
*data = res;
|
||
break;
|
||
|
||
case DATAO:
|
||
sim_debug(DEBUG_DATAIO, dptr, "DP %03o DATO %012llo, %d PC=%o\n",
|
||
dev, *data, ctlr, PC);
|
||
if (df10->status & BUSY) {
|
||
uptr->STATUS |= ILL_CMD;
|
||
return SCPE_OK;
|
||
}
|
||
clr_interrupt(dev);
|
||
df10->status &= ~(PI_ENABLE|CCW_COMP);
|
||
unit = (*data >> 30) & 07;
|
||
dp_cur_unit[ctlr] = unit;
|
||
uptr = &dp_unit[(ctlr * NUM_UNITS_DP) + unit];
|
||
if ((uptr->STATUS & NOT_RDY) == 0) {
|
||
uptr->STATUS &= ~(SUF_ERR|SEC_ERR|SRC_ERR|NXM_ERR|ILL_WR|
|
||
NO_DRIVE|NOT_RDY|ILL_CMD|END_CYL|SRC_DONE);
|
||
}
|
||
cyl = ((*data >> 22) & 0377);
|
||
if (*data & CYL256)
|
||
cyl += 0400;
|
||
tmp = (*data >> 33) & 07;
|
||
switch(tmp) {
|
||
case WH:
|
||
if ((dptr->flags & DEV_WHDR) == 0) {
|
||
uptr->UFLAGS |= DONE;
|
||
uptr->STATUS |= ILL_WR;
|
||
df10_setirq(df10);
|
||
return SCPE_OK;
|
||
}
|
||
*data &= ~SECTOR; /* Clear sector */
|
||
/* Fall through */
|
||
|
||
case WR:
|
||
if (uptr->flags & UNIT_WPRT) {
|
||
uptr->UFLAGS |= DONE;
|
||
uptr->STATUS |= ILL_WR;
|
||
df10_setirq(df10);
|
||
return SCPE_OK;
|
||
}
|
||
/* Fall through */
|
||
|
||
case RD:
|
||
case RV:
|
||
if (uptr->flags & UNIT_DIS) {
|
||
uptr->UFLAGS |= DONE;
|
||
uptr->STATUS |= NO_DRIVE;
|
||
df10_setirq(df10);
|
||
return SCPE_OK;
|
||
}
|
||
if ((uptr->flags & UNIT_ATT) == 0) {
|
||
uptr->UFLAGS |= DONE;
|
||
uptr->STATUS |= NOT_RDY;
|
||
df10_setirq(df10);
|
||
return SCPE_OK;
|
||
}
|
||
uptr->UFLAGS = ((*data & (SURFACE|SECTOR)) >> 3) | (cyl << 20)
|
||
| (tmp << 3) | ctlr;
|
||
uptr->DATAPTR = 0; /* Set no data */
|
||
CLR_BUF(uptr);
|
||
df10_setup(df10, (uint32)*data);
|
||
uptr->STATUS |= BUSY;
|
||
break;
|
||
|
||
case RC:
|
||
cyl = 0;
|
||
/* Fall through */
|
||
|
||
case SK:
|
||
uptr->STATUS |= NOT_RDY;
|
||
if ((uptr->flags & UNIT_ATT) == 0)
|
||
return SCPE_OK;
|
||
uptr->UFLAGS = (cyl << 20) | (tmp<<3) | ctlr | SEEK_STATE;
|
||
break;
|
||
|
||
case CL:
|
||
uptr->UFLAGS &= ~DONE;
|
||
uptr = &dp_unit[ctlr * NUM_UNITS_DP];
|
||
for(unit = 0; unit < NUM_UNITS_DP; unit++) {
|
||
if (*data & (0400 >> unit))
|
||
uptr->UFLAGS &= ~(SEEK_DONE);
|
||
uptr++;
|
||
}
|
||
/* Fall through */
|
||
|
||
case NO:
|
||
tmp = 0;
|
||
uptr = &dp_unit[ctlr * NUM_UNITS_DP];
|
||
for(unit = 0; unit < NUM_UNITS_DP; unit++) {
|
||
if (uptr->UFLAGS & SEEK_DONE) {
|
||
tmp = 1;
|
||
break;
|
||
}
|
||
uptr++;
|
||
}
|
||
if (tmp) {
|
||
df10_setirq(df10);
|
||
}
|
||
return SCPE_OK;
|
||
}
|
||
sim_activate(uptr, 150);
|
||
}
|
||
return SCPE_OK;
|
||
}
|
||
|
||
|
||
t_stat dp_svc (UNIT *uptr)
|
||
{
|
||
int dtype = GET_DTYPE(uptr->flags);
|
||
int ctlr = uptr->UFLAGS & 03;
|
||
int cmd = (uptr->UFLAGS & 070) >> 3;
|
||
int sect = (uptr->UFLAGS >> 9);
|
||
int surf = (sect >> 5) & 037;
|
||
int cyl = (uptr->UFLAGS >> 20) & 0777;
|
||
DEVICE *dptr = dp_devs[ctlr];
|
||
struct df10 *df10 = &dp_df10[ctlr];
|
||
int diff, diffs;
|
||
int r;
|
||
sect &= 017;
|
||
|
||
switch(cmd) {
|
||
case WR:
|
||
case RV:
|
||
case RD:
|
||
/* Cylinder, Surface, Sector all ok */
|
||
if (BUF_EMPTY(uptr)) {
|
||
sim_debug(DEBUG_DETAIL, dptr,
|
||
"DP %d cmd=%o cyl=%d (%o) sect=%d surf=%d %d\n",
|
||
ctlr, uptr->UFLAGS, cyl, cyl, sect, surf,uptr->CUR_CYL);
|
||
uptr->STATUS |= SRC_DONE;
|
||
if (uptr->STATUS & END_CYL) {
|
||
if (cmd == WR) {
|
||
if(df10_read(df10))
|
||
df10_read(df10);
|
||
}
|
||
uptr->UFLAGS |= DONE;
|
||
uptr->STATUS &= ~BUSY;
|
||
df10_finish_op(df10, 0);
|
||
return SCPE_OK;
|
||
}
|
||
if (sect >= dp_drv_tab[dtype].sect) {
|
||
uptr->STATUS &= ~BUSY;
|
||
uptr->STATUS |= SEC_ERR;
|
||
}
|
||
if (surf >= dp_drv_tab[dtype].surf) {
|
||
uptr->STATUS &= ~BUSY;
|
||
uptr->STATUS |= SUF_ERR;
|
||
}
|
||
if (cyl != uptr->CUR_CYL) {
|
||
uptr->STATUS &= ~BUSY;
|
||
uptr->STATUS |= SRC_ERR;
|
||
}
|
||
if ((uptr->STATUS & BUSY) == 0) {
|
||
uptr->UFLAGS |= DONE;
|
||
df10_finish_op(df10, 0);
|
||
return SCPE_OK;
|
||
}
|
||
if (cmd != WR) {
|
||
/* Read the block */
|
||
int da = ((cyl * dp_drv_tab[dtype].surf + surf)
|
||
* dp_drv_tab[dtype].sect + sect);
|
||
(void)disk_read(uptr, &dp_buf[ctlr][0], da, RP_NUMWD);
|
||
uptr->hwmark = RP_NUMWD;
|
||
uptr->DATAPTR = 0;
|
||
sect = sect + 1;
|
||
if (sect >= dp_drv_tab[dtype].sect) {
|
||
sect = 0;
|
||
surf = surf + 1;
|
||
if (surf >= dp_drv_tab[dtype].surf) {
|
||
uptr->STATUS |= END_CYL;
|
||
} else {
|
||
uptr->UFLAGS &= ~(01757000);
|
||
uptr->UFLAGS |= (surf << 14);
|
||
}
|
||
} else {
|
||
uptr->UFLAGS &= ~(017000);
|
||
uptr->UFLAGS |= (sect << 9);
|
||
}
|
||
} else {
|
||
uptr->DATAPTR = 0;
|
||
uptr->hwmark = 0;
|
||
}
|
||
sim_activate(uptr, 50);
|
||
return SCPE_OK;
|
||
}
|
||
switch(cmd) {
|
||
case WR:
|
||
r = df10_read(df10);
|
||
if (r)
|
||
uptr->hwmark = uptr->DATAPTR;
|
||
dp_buf[ctlr][uptr->DATAPTR] = df10->buf;
|
||
break;
|
||
case RV:
|
||
case RD:
|
||
df10->buf = dp_buf[ctlr][uptr->DATAPTR];
|
||
r = df10_write(df10);
|
||
break;
|
||
}
|
||
sim_debug(DEBUG_DATA, dptr, "Xfer %d %08o %012llo %08o\n",
|
||
uptr->DATAPTR, df10->cda, df10->buf, df10->wcr);
|
||
uptr->DATAPTR++;
|
||
if (uptr->DATAPTR >= RP_NUMWD || r == 0 ) {
|
||
if (cmd == WR) {
|
||
int da = ((cyl * dp_drv_tab[dtype].surf + surf)
|
||
* dp_drv_tab[dtype].sect + sect);
|
||
/* write block the block */
|
||
for (; uptr->DATAPTR < RP_NUMWD; uptr->DATAPTR++)
|
||
dp_buf[ctlr][uptr->DATAPTR] = 0;
|
||
(void)disk_write(uptr, &dp_buf[ctlr][0], da, RP_NUMWD);
|
||
uptr->STATUS |= SRC_DONE;
|
||
sect = sect + 1;
|
||
if (sect >= dp_drv_tab[dtype].sect) {
|
||
sect = 0;
|
||
surf = surf + 1;
|
||
if (surf >= dp_drv_tab[dtype].surf) {
|
||
uptr->STATUS |= END_CYL;
|
||
} else {
|
||
uptr->UFLAGS &= ~(01757 << 9);
|
||
uptr->UFLAGS |= (surf << 14);
|
||
}
|
||
} else {
|
||
uptr->UFLAGS &= ~(017 << 9);
|
||
uptr->UFLAGS |= (sect << 9);
|
||
}
|
||
}
|
||
uptr->DATAPTR = 0;
|
||
CLR_BUF(uptr);
|
||
}
|
||
if (r)
|
||
sim_activate(uptr, 25);
|
||
else {
|
||
uptr->STATUS &= ~(SRC_DONE|END_CYL|BUSY);
|
||
uptr->UFLAGS |= DONE;
|
||
return SCPE_OK;
|
||
}
|
||
break;
|
||
case WH:
|
||
/* Cylinder, Surface, Sector all ok */
|
||
if (BUF_EMPTY(uptr)) {
|
||
if (uptr->DATAPTR == 0)
|
||
sim_debug(DEBUG_DETAIL, dptr,
|
||
"DP %d cmd=%o cyl=%d (%o) sect=%d surf=%d %d\n",
|
||
ctlr, uptr->UFLAGS, cyl, cyl, sect, surf,uptr->CUR_CYL);
|
||
uptr->STATUS |= SRC_DONE;
|
||
if (uptr->STATUS & END_CYL) {
|
||
if(df10_read(df10))
|
||
df10_read(df10);
|
||
uptr->UFLAGS |= DONE;
|
||
uptr->STATUS &= ~BUSY;
|
||
df10_finish_op(df10, 0);
|
||
return SCPE_OK;
|
||
}
|
||
if (sect >= dp_drv_tab[dtype].sect) {
|
||
uptr->STATUS &= ~BUSY;
|
||
uptr->STATUS |= SEC_ERR;
|
||
}
|
||
if (surf >= dp_drv_tab[dtype].surf) {
|
||
uptr->STATUS &= ~BUSY;
|
||
uptr->STATUS |= SUF_ERR;
|
||
}
|
||
if (cyl != uptr->CUR_CYL) {
|
||
uptr->STATUS &= ~BUSY;
|
||
uptr->STATUS |= SRC_ERR;
|
||
}
|
||
if ((uptr->STATUS & BUSY) == 0) {
|
||
uptr->UFLAGS |= DONE;
|
||
df10_finish_op(df10, 0);
|
||
return SCPE_OK;
|
||
}
|
||
r = df10_read(df10);
|
||
uptr->DATAPTR++;
|
||
sim_debug(DEBUG_DATA, dptr, "Xfer h%d %012llo\n",
|
||
uptr->DATAPTR, df10->buf);
|
||
if (uptr->DATAPTR == 36) {
|
||
uptr->DATAPTR = 0;
|
||
uptr->hwmark = 0;
|
||
}
|
||
} else {
|
||
r = df10_read(df10);
|
||
if (r)
|
||
uptr->hwmark = uptr->DATAPTR;
|
||
dp_buf[ctlr][uptr->DATAPTR] = (df10->buf << 1) & FMASK;
|
||
sim_debug(DEBUG_DATA, dptr, "Xfer %d %012llo\n",
|
||
uptr->DATAPTR, df10->buf);
|
||
uptr->DATAPTR++;
|
||
if (uptr->DATAPTR >= RP_NUMWD || r == 0 ) {
|
||
int da = ((cyl * dp_drv_tab[dtype].surf + surf)
|
||
* dp_drv_tab[dtype].sect + sect);
|
||
/* write block the block */
|
||
for (; uptr->DATAPTR < RP_NUMWD; uptr->DATAPTR++)
|
||
dp_buf[ctlr][uptr->DATAPTR] = 0;
|
||
(void)disk_write(uptr, &dp_buf[ctlr][0], da, RP_NUMWD);
|
||
uptr->STATUS |= SRC_DONE;
|
||
sect = sect + 1;
|
||
if (sect >= dp_drv_tab[dtype].sect) {
|
||
uptr->STATUS |= END_CYL;
|
||
} else {
|
||
uptr->UFLAGS &= ~(017 << 9);
|
||
uptr->UFLAGS |= (sect << 9);
|
||
}
|
||
uptr->DATAPTR = 0;
|
||
CLR_BUF(uptr);
|
||
}
|
||
}
|
||
if (r)
|
||
sim_activate(uptr, 25);
|
||
else {
|
||
uptr->STATUS &= ~(SRC_DONE|END_CYL|BUSY);
|
||
uptr->UFLAGS |= DONE;
|
||
return SCPE_OK;
|
||
}
|
||
break;
|
||
|
||
case CL:
|
||
case NO:
|
||
return SCPE_OK;
|
||
case RC:
|
||
case SK:
|
||
if(uptr->UFLAGS & SEEK_STATE) {
|
||
diff = cyl - uptr->CUR_CYL;
|
||
diffs = (diff < 0) ? -1 : 1;
|
||
sim_debug(DEBUG_DETAIL, dptr, "DP Seek %d %d %d %d\n",
|
||
ctlr, cyl, uptr->CUR_CYL, diff);
|
||
if (diff == 0) {
|
||
uptr->UFLAGS |= SEEK_DONE;
|
||
uptr->UFLAGS &= ~SEEK_STATE;
|
||
uptr->STATUS &= ~(NOT_RDY);
|
||
if ((df10->status & BUSY) == 0)
|
||
df10_setirq(df10);
|
||
} else if (diff < 10 && diff > -10) {
|
||
uptr->CUR_CYL += diffs;
|
||
if (uptr->CUR_CYL < 0) {
|
||
uptr->UFLAGS |= SEEK_DONE;
|
||
uptr->UFLAGS &= ~SEEK_STATE;
|
||
uptr->STATUS &= ~(NOT_RDY);
|
||
uptr->CUR_CYL = 0;
|
||
if ((df10->status & BUSY) == 0)
|
||
df10_setirq(df10);
|
||
} else if (uptr->CUR_CYL > dp_drv_tab[dtype].cyl) {
|
||
uptr->UFLAGS |= SEEK_DONE;
|
||
uptr->UFLAGS &= ~SEEK_STATE;
|
||
uptr->STATUS &= ~(NOT_RDY);
|
||
uptr->CUR_CYL = dp_drv_tab[dtype].cyl;
|
||
if ((df10->status & BUSY) == 0)
|
||
df10_setirq(df10);
|
||
} else
|
||
sim_activate(uptr, 500);
|
||
} else if (diff > 100 || diff < -100) {
|
||
uptr->CUR_CYL += diffs * 100;
|
||
sim_activate(uptr, 4000);
|
||
} else {
|
||
uptr->CUR_CYL += diffs * 10;
|
||
sim_activate(uptr, 1000);
|
||
}
|
||
}
|
||
}
|
||
return SCPE_OK;
|
||
}
|
||
|
||
|
||
t_stat
|
||
dp_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||
{
|
||
int i;
|
||
if (uptr == NULL) return SCPE_IERR;
|
||
for (i = 0; dp_drv_tab[i].sect != 0; i++) {
|
||
if (GET_DTYPE(val) == dp_drv_tab[i].devtype) {
|
||
uptr->flags &= ~(UNIT_DTYPE);
|
||
uptr->flags |= val;
|
||
uptr->capac = dp_drv_tab[i].size;
|
||
return SCPE_OK;
|
||
}
|
||
}
|
||
return SCPE_IERR;
|
||
}
|
||
|
||
t_stat
|
||
dp_set_hdr(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||
{
|
||
DEVICE *dptr;
|
||
dptr = find_dev_from_unit (uptr);
|
||
if (dptr == NULL)
|
||
return SCPE_IERR;
|
||
dptr->flags &= ~DEV_WHDR;
|
||
dptr->flags |= val;
|
||
return SCPE_OK;
|
||
}
|
||
|
||
t_stat dp_show_hdr (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||
{
|
||
DEVICE *dptr;
|
||
|
||
if (uptr == NULL)
|
||
return SCPE_IERR;
|
||
|
||
dptr = find_dev_from_unit(uptr);
|
||
if (dptr == NULL)
|
||
return SCPE_IERR;
|
||
fprintf (st, "%s", (dptr->flags & DEV_WHDR) ? "HEADERS" : "NOHEADERS");
|
||
return SCPE_OK;
|
||
}
|
||
|
||
|
||
t_stat
|
||
dp_reset(DEVICE * dptr)
|
||
{
|
||
int unit;
|
||
int ctlr;
|
||
UNIT *uptr = dptr->units;
|
||
for(unit = 0; unit < NUM_UNITS_DP; unit++) {
|
||
uptr->UFLAGS = 0;
|
||
uptr->STATUS = 0;
|
||
uptr->CUR_CYL = 0;
|
||
uptr++;
|
||
}
|
||
for (ctlr = 0; ctlr < NUM_DEVS_DP; ctlr++) {
|
||
df10_init(&dp_df10[ctlr], dp_dib[ctlr].dev_num, 12);
|
||
}
|
||
return SCPE_OK;
|
||
}
|
||
|
||
/* Boot from given device */
|
||
t_stat
|
||
dp_boot(int32 unit_num, DEVICE * dptr)
|
||
{
|
||
UNIT *uptr = &dptr->units[unit_num];
|
||
uint32 addr;
|
||
uint32 ptr;
|
||
int sect;
|
||
int wc;
|
||
|
||
addr = (MEMSIZE - 512) & RMASK;
|
||
for (sect = 4; sect <= 7; sect++) {
|
||
(void)disk_read(uptr, &dp_buf[0][0], sect, RP_NUMWD);
|
||
ptr = 0;
|
||
for(wc = RP_NUMWD; wc > 0; wc--)
|
||
M[addr++] = dp_buf[0][ptr++];
|
||
}
|
||
PC = (MEMSIZE - 512) & RMASK;
|
||
return SCPE_OK;
|
||
}
|
||
|
||
/* Device attach */
|
||
|
||
t_stat dp_attach (UNIT *uptr, CONST char *cptr)
|
||
{
|
||
t_stat r;
|
||
DEVICE *dptr;
|
||
DIB *dib;
|
||
int ctlr;
|
||
|
||
r = disk_attach (uptr, cptr);
|
||
if (r != SCPE_OK || (sim_switches & SIM_SW_REST) != 0)
|
||
return r;
|
||
uptr->capac = dp_drv_tab[GET_DTYPE (uptr->flags)].size;
|
||
dptr = find_dev_from_unit(uptr);
|
||
if (dptr == 0)
|
||
return SCPE_OK;
|
||
dib = (DIB *) dptr->ctxt;
|
||
ctlr = dib->dev_num & 014;
|
||
uptr->CUR_CYL = 0;
|
||
uptr->UFLAGS = (NO << 3) | SEEK_DONE | (ctlr >> 2);
|
||
dp_df10[ctlr].status |= PI_ENABLE;
|
||
set_interrupt(DP_DEVNUM + (ctlr), dp_df10[ctlr].status);
|
||
return SCPE_OK;
|
||
}
|
||
|
||
/* Device detach */
|
||
|
||
t_stat dp_detach (UNIT *uptr)
|
||
{
|
||
if (!(uptr->flags & UNIT_ATT)) /* attached? */
|
||
return SCPE_OK;
|
||
if (sim_is_active (uptr)) /* unit active? */
|
||
sim_cancel (uptr); /* cancel operation */
|
||
return disk_detach (uptr);
|
||
}
|
||
|
||
t_stat dp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||
{
|
||
fprintf (st, "RP10 RP01/2/3 Disk Pack Drives (DP)\n\n");
|
||
fprintf (st, "The DP controller implements the RP10 disk drives. RP\n");
|
||
fprintf (st, "options include the ability to set units write enabled or write locked, to\n");
|
||
fprintf (st, "set the drive type to one of three disk types.\n");
|
||
disk_attach_help(st, dptr, uptr, flag, cptr);
|
||
fprint_set_help (st, dptr);
|
||
fprint_show_help (st, dptr);
|
||
fprintf (st, "\nThe type options can be used only when a unit is not attached to a file.\n");
|
||
fprintf (st, "The RP device supports the BOOT command.\n");
|
||
fprint_reg_help (st, dptr);
|
||
return SCPE_OK;
|
||
}
|
||
|
||
const char *dp_description (DEVICE *dptr)
|
||
{
|
||
return "RP10 disk controller";
|
||
}
|
||
|
||
#endif
|