1
0
mirror of https://github.com/simh/simh.git synced 2026-04-25 11:41:25 +00:00

Notes For V3.5-0

The source set has been extensively overhauled.  For correct
viewing, set Visual C++ or Emacs to have tab stops every 4
characters.

1. New Features in 3.4-1

1.1 All Ethernet devices

- Added Windows user-defined adapter names (from Timothe Litt)

1.2 Interdata, SDS, HP, PDP-8, PDP-18b terminal multiplexors

- Added support for SET <unit>n DISCONNECT

1.3 VAX

- Added latent QDSS support
- Revised autoconfigure to handle QDSS

1.4 PDP-11

- Revised autoconfigure to handle more casees

2. Bugs Fixed in 3.4-1

2.1 SCP and libraries

- Trim trailing spaces on all input (for example, attach file names)
- Fixed sim_sock spurious SIGPIPE error in Unix/Linux
- Fixed sim_tape misallocation of TPC map array for 64b simulators

2.2 1401

- Fixed bug, CPU reset was clearing SSB through SSG

2.3 PDP-11

- Fixed bug in VH vector display routine
- Fixed XU runt packet processing (found by Tim Chapman)

2.4 Interdata

- Fixed bug in SHOW PAS CONN/STATS
- Fixed potential integer overflow exception in divide

2.5 SDS

- Fixed bug in SHOW MUX CONN/STATS

2.6 HP

- Fixed bug in SHOW MUX CONN/STATS

2.7 PDP-8

- Fixed bug in SHOW TTIX CONN/STATS
- Fixed bug in SET/SHOW TTOXn LOG

2.8 PDP-18b

- Fixed bug in SHOW TTIX CONN/STATS
- Fixed bug in SET/SHOW TTOXn LOG

2.9 Nova, Eclipse

- Fixed potential integer overflow exception in divide
This commit is contained in:
Bob Supnik
2005-09-09 18:09:00 -07:00
committed by Mark Pizzolato
parent ec60bbf329
commit b7c1eae41f
257 changed files with 107140 additions and 97195 deletions

View File

@@ -1,6 +1,6 @@
/* nova_dsk.c: 4019 fixed head disk simulator
Copyright (c) 1993-2004, Robert M. Supnik
Copyright (c) 1993-2005, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -19,23 +19,23 @@
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.
Except as contained in this notice, the name of Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
dsk fixed head disk
dsk fixed head disk
04-Jan-04 RMS Changed sim_fsize calling sequence
26-Jul-03 RMS Fixed bug in set size routine
14-Mar-03 RMS Fixed variable capacity interaction with save/restore
03-Mar-03 RMS Fixed variable capacity and autosizing
03-Oct-02 RMS Added DIB
06-Jan-02 RMS Revised enable/disable support
23-Aug-01 RMS Fixed bug in write watermarking
26-Apr-01 RMS Added device enable/disable support
10-Dec-00 RMS Added Eclipse support
15-Oct-00 RMS Editorial changes
14-Apr-99 RMS Changed t_addr to unsigned
04-Jan-04 RMS Changed sim_fsize calling sequence
26-Jul-03 RMS Fixed bug in set size routine
14-Mar-03 RMS Fixed variable capacity interaction with save/restore
03-Mar-03 RMS Fixed variable capacity and autosizing
03-Oct-02 RMS Added DIB
06-Jan-02 RMS Revised enable/disable support
23-Aug-01 RMS Fixed bug in write watermarking
26-Apr-01 RMS Added device enable/disable support
10-Dec-00 RMS Added Eclipse support
15-Oct-00 RMS Editorial changes
14-Apr-99 RMS Changed t_addr to unsigned
The 4019 is a head-per-track disk. To minimize overhead, the entire disk
is buffered in memory.
@@ -44,61 +44,62 @@
#include "nova_defs.h"
#include <math.h>
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
#define UNIT_M_PLAT 07
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
#define UNIT_AUTO (1 << UNIT_V_AUTO)
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
#define UNIT_M_PLAT 07
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
#define UNIT_AUTO (1 << UNIT_V_AUTO)
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
/* Constants */
#define DSK_NUMWD 256 /* words/sector */
#define DSK_NUMSC 8 /* sectors/track */
#define DSK_NUMTR 128 /* tracks/disk */
#define DSK_DKSIZE (DSK_NUMTR*DSK_NUMSC*DSK_NUMWD) /* words/disk */
#define DSK_AMASK ((DSK_NUMDK*DSK_NUMTR*DSK_NUMSC) - 1) /* address mask */
#define DSK_NUMDK 8 /* disks/controller */
#define GET_DISK(x) (((x) / (DSK_NUMSC * DSK_NUMTR)) & (DSK_NUMDK - 1))
#define DSK_NUMWD 256 /* words/sector */
#define DSK_NUMSC 8 /* sectors/track */
#define DSK_NUMTR 128 /* tracks/disk */
#define DSK_DKSIZE (DSK_NUMTR*DSK_NUMSC*DSK_NUMWD) /* words/disk */
#define DSK_AMASK ((DSK_NUMDK*DSK_NUMTR*DSK_NUMSC) - 1) /* address mask */
#define DSK_NUMDK 8 /* disks/controller */
#define GET_DISK(x) (((x) / (DSK_NUMSC * DSK_NUMTR)) & (DSK_NUMDK - 1))
/* Parameters in the unit descriptor */
#define FUNC u4 /* function */
#define FUNC u4 /* function */
/* Status register */
#define DSKS_WLS 020 /* write lock status */
#define DSKS_DLT 010 /* data late error */
#define DSKS_NSD 004 /* non-existent disk */
#define DSKS_CRC 002 /* parity error */
#define DSKS_ERR 001 /* error summary */
#define DSKS_ALLERR (DSKS_WLS | DSKS_DLT | DSKS_NSD | DSKS_CRC | DSKS_ERR)
#define DSKS_WLS 020 /* write lock status */
#define DSKS_DLT 010 /* data late error */
#define DSKS_NSD 004 /* non-existent disk */
#define DSKS_CRC 002 /* parity error */
#define DSKS_ERR 001 /* error summary */
#define DSKS_ALLERR (DSKS_WLS | DSKS_DLT | DSKS_NSD | DSKS_CRC | DSKS_ERR)
/* Map logical sector numbers to physical sector numbers
(indexed by track<2:0>'sector)
*/
static const int32 sector_map[] = {
0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 2, 4, 6, 0,
2, 4, 6, 0, 3, 5, 7, 1, 3, 5, 7, 1, 4, 6, 0, 2,
4, 6, 0, 2, 5, 7, 1, 3, 5, 7, 1, 3, 6, 0, 2, 4,
6, 0, 2, 4, 7, 1, 3, 5, 7, 1, 3, 5, 0, 2, 4, 6 };
0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 2, 4, 6, 0,
2, 4, 6, 0, 3, 5, 7, 1, 3, 5, 7, 1, 4, 6, 0, 2,
4, 6, 0, 2, 5, 7, 1, 3, 5, 7, 1, 3, 6, 0, 2, 4,
6, 0, 2, 4, 7, 1, 3, 5, 7, 1, 3, 5, 0, 2, 4, 6
};
#define DSK_MMASK 077
#define GET_SECTOR(x) ((int) fmod (sim_gtime() / ((double) (x)), \
((double) DSK_NUMSC)))
#define DSK_MMASK 077
#define GET_SECTOR(x) ((int) fmod (sim_gtime() / ((double) (x)), \
((double) DSK_NUMSC)))
extern uint16 M[];
extern UNIT cpu_unit;
extern int32 int_req, dev_busy, dev_done, dev_disable;
int32 dsk_stat = 0; /* status register */
int32 dsk_da = 0; /* disk address */
int32 dsk_ma = 0; /* memory address */
int32 dsk_wlk = 0; /* wrt lock switches */
int32 dsk_stopioe = 1; /* stop on error */
int32 dsk_time = 100; /* time per sector */
int32 dsk_stat = 0; /* status register */
int32 dsk_da = 0; /* disk address */
int32 dsk_ma = 0; /* memory address */
int32 dsk_wlk = 0; /* wrt lock switches */
int32 dsk_stopioe = 1; /* stop on error */
int32 dsk_time = 100; /* time per sector */
DEVICE dsk_dev;
int32 dsk (int32 pulse, int32 code, int32 AC);
@@ -110,49 +111,53 @@ t_stat dsk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
/* DSK data structures
dsk_dev device descriptor
dsk_unit unit descriptor
dsk_reg register list
dsk_dev device descriptor
dsk_unit unit descriptor
dsk_reg register list
*/
DIB dsk_dib = { DEV_DSK, INT_DSK, PI_DSK, &dsk };
UNIT dsk_unit =
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
DSK_DKSIZE) };
UNIT dsk_unit = {
UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
DSK_DKSIZE)
};
REG dsk_reg[] = {
{ ORDATA (STAT, dsk_stat, 16) },
{ ORDATA (DA, dsk_da, 16) },
{ ORDATA (MA, dsk_ma, 16) },
{ FLDATA (BUSY, dev_busy, INT_V_DSK) },
{ FLDATA (DONE, dev_done, INT_V_DSK) },
{ FLDATA (DISABLE, dev_disable, INT_V_DSK) },
{ FLDATA (INT, int_req, INT_V_DSK) },
{ ORDATA (WLK, dsk_wlk, 8) },
{ DRDATA (TIME, dsk_time, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, dsk_stopioe, 0) },
{ NULL } };
{ ORDATA (STAT, dsk_stat, 16) },
{ ORDATA (DA, dsk_da, 16) },
{ ORDATA (MA, dsk_ma, 16) },
{ FLDATA (BUSY, dev_busy, INT_V_DSK) },
{ FLDATA (DONE, dev_done, INT_V_DSK) },
{ FLDATA (DISABLE, dev_disable, INT_V_DSK) },
{ FLDATA (INT, int_req, INT_V_DSK) },
{ ORDATA (WLK, dsk_wlk, 8) },
{ DRDATA (TIME, dsk_time, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, dsk_stopioe, 0) },
{ NULL }
};
MTAB dsk_mod[] = {
{ UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &dsk_set_size },
{ UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &dsk_set_size },
{ UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &dsk_set_size },
{ UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &dsk_set_size },
{ UNIT_PLAT, (4 << UNIT_V_PLAT), NULL, "5P", &dsk_set_size },
{ UNIT_PLAT, (5 << UNIT_V_PLAT), NULL, "6P", &dsk_set_size },
{ UNIT_PLAT, (6 << UNIT_V_PLAT), NULL, "7P", &dsk_set_size },
{ UNIT_PLAT, (7 << UNIT_V_PLAT), NULL, "8P", &dsk_set_size },
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
{ 0 } };
{ UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &dsk_set_size },
{ UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &dsk_set_size },
{ UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &dsk_set_size },
{ UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &dsk_set_size },
{ UNIT_PLAT, (4 << UNIT_V_PLAT), NULL, "5P", &dsk_set_size },
{ UNIT_PLAT, (5 << UNIT_V_PLAT), NULL, "6P", &dsk_set_size },
{ UNIT_PLAT, (6 << UNIT_V_PLAT), NULL, "7P", &dsk_set_size },
{ UNIT_PLAT, (7 << UNIT_V_PLAT), NULL, "8P", &dsk_set_size },
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
{ 0 }
};
DEVICE dsk_dev = {
"DK", &dsk_unit, dsk_reg, dsk_mod,
1, 8, 21, 1, 8, 16,
NULL, NULL, &dsk_reset,
&dsk_boot, &dsk_attach, NULL,
&dsk_dib, DEV_DISABLE };
"DK", &dsk_unit, dsk_reg, dsk_mod,
1, 8, 21, 1, 8, 16,
NULL, NULL, &dsk_reset,
&dsk_boot, &dsk_attach, NULL,
&dsk_dib, DEV_DISABLE
};
/* IOT routine */
int32 dsk (int32 pulse, int32 code, int32 AC)
@@ -160,47 +165,56 @@ int32 dsk (int32 pulse, int32 code, int32 AC)
int32 t, rval;
rval = 0;
switch (code) { /* decode IR<5:7> */
case ioDIA: /* DIA */
rval = dsk_stat & DSKS_ALLERR; /* read status */
break;
case ioDOA: /* DOA */
dsk_da = AC & DSK_AMASK; /* save disk addr */
break;
case ioDIB: /* DIB */
rval = dsk_ma & AMASK; /* read mem addr */
break;
case ioDOB: /* DOB */
dsk_ma = AC & AMASK; /* save mem addr */
break; } /* end switch code */
switch (code) { /* decode IR<5:7> */
if (pulse) { /* any pulse? */
dev_busy = dev_busy & ~INT_DSK; /* clear busy */
dev_done = dev_done & ~INT_DSK; /* clear done */
int_req = int_req & ~INT_DSK; /* clear int */
dsk_stat = 0; /* clear status */
sim_cancel (&dsk_unit); } /* stop I/O */
case ioDIA: /* DIA */
rval = dsk_stat & DSKS_ALLERR; /* read status */
break;
if ((pulse == iopP) && ((dsk_wlk >> GET_DISK (dsk_da)) & 1)) { /* wrt lock? */
dev_done = dev_done | INT_DSK; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
dsk_stat = DSKS_ERR + DSKS_WLS; /* set status */
return rval; }
case ioDOA: /* DOA */
dsk_da = AC & DSK_AMASK; /* save disk addr */
break;
if (pulse & 1) { /* read or write? */
if (((uint32) (dsk_da * DSK_NUMWD)) >= dsk_unit.capac) { /* inv sev? */
dev_done = dev_done | INT_DSK; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
dsk_stat = DSKS_ERR + DSKS_NSD; /* set status */
return rval; } /* done */
dsk_unit.FUNC = pulse; /* save command */
dev_busy = dev_busy | INT_DSK; /* set busy */
t = sector_map[dsk_da & DSK_MMASK] - GET_SECTOR (dsk_time);
if (t < 0) t = t + DSK_NUMSC;
sim_activate (&dsk_unit, t * dsk_time); } /* activate */
case ioDIB: /* DIB */
rval = dsk_ma & AMASK; /* read mem addr */
break;
case ioDOB: /* DOB */
dsk_ma = AC & AMASK; /* save mem addr */
break;
} /* end switch code */
if (pulse) { /* any pulse? */
dev_busy = dev_busy & ~INT_DSK; /* clear busy */
dev_done = dev_done & ~INT_DSK; /* clear done */
int_req = int_req & ~INT_DSK; /* clear int */
dsk_stat = 0; /* clear status */
sim_cancel (&dsk_unit); /* stop I/O */
}
if ((pulse == iopP) && ((dsk_wlk >> GET_DISK (dsk_da)) & 1)) { /* wrt lock? */
dev_done = dev_done | INT_DSK; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
dsk_stat = DSKS_ERR + DSKS_WLS; /* set status */
return rval;
}
if (pulse & 1) { /* read or write? */
if (((uint32) (dsk_da * DSK_NUMWD)) >= dsk_unit.capac) { /* inv sev? */
dev_done = dev_done | INT_DSK; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
dsk_stat = DSKS_ERR + DSKS_NSD; /* set status */
return rval; /* done */
}
dsk_unit.FUNC = pulse; /* save command */
dev_busy = dev_busy | INT_DSK; /* set busy */
t = sector_map[dsk_da & DSK_MMASK] - GET_SECTOR (dsk_time);
if (t < 0) t = t + DSK_NUMSC;
sim_activate (&dsk_unit, t * dsk_time); /* activate */
}
return rval;
}
/* Unit service */
t_stat dsk_svc (UNIT *uptr)
@@ -208,58 +222,63 @@ t_stat dsk_svc (UNIT *uptr)
int32 i, da, pa;
int16 *fbuf = uptr->filebuf;
dev_busy = dev_busy & ~INT_DSK; /* clear busy */
dev_done = dev_done | INT_DSK; /* set done */
dev_busy = dev_busy & ~INT_DSK; /* clear busy */
dev_done = dev_done | INT_DSK; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
dsk_stat = DSKS_ERR + DSKS_NSD; /* set status */
return IORETURN (dsk_stopioe, SCPE_UNATT); }
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
dsk_stat = DSKS_ERR + DSKS_NSD; /* set status */
return IORETURN (dsk_stopioe, SCPE_UNATT);
}
da = dsk_da * DSK_NUMWD; /* calc disk addr */
if (uptr->FUNC == iopS) { /* read? */
for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */
pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */
if (MEM_ADDR_OK (pa)) M[pa] = fbuf[da + i]; }
dsk_ma = (dsk_ma + DSK_NUMWD) & AMASK; }
if (uptr->FUNC == iopP) { /* write? */
for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */
pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */
fbuf[da + i] = M[pa]; }
if (((uint32) (da + i)) >= uptr->hwmark) /* past end? */
uptr->hwmark = da + i + 1; /* upd hwmark */
dsk_ma = (dsk_ma + DSK_NUMWD + 3) & AMASK; }
da = dsk_da * DSK_NUMWD; /* calc disk addr */
if (uptr->FUNC == iopS) { /* read? */
for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */
pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */
if (MEM_ADDR_OK (pa)) M[pa] = fbuf[da + i];
}
dsk_ma = (dsk_ma + DSK_NUMWD) & AMASK;
}
if (uptr->FUNC == iopP) { /* write? */
for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */
pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */
fbuf[da + i] = M[pa];
}
if (((uint32) (da + i)) >= uptr->hwmark) /* past end? */
uptr->hwmark = da + i + 1; /* upd hwmark */
dsk_ma = (dsk_ma + DSK_NUMWD + 3) & AMASK;
}
dsk_stat = 0; /* set status */
dsk_stat = 0; /* set status */
return SCPE_OK;
}
/* Reset routine */
t_stat dsk_reset (DEVICE *dptr)
{
dsk_stat = dsk_da = dsk_ma = 0;
dev_busy = dev_busy & ~INT_DSK; /* clear busy */
dev_done = dev_done & ~INT_DSK; /* clear done */
int_req = int_req & ~INT_DSK; /* clear int */
dev_busy = dev_busy & ~INT_DSK; /* clear busy */
dev_done = dev_done & ~INT_DSK; /* clear done */
int_req = int_req & ~INT_DSK; /* clear int */
sim_cancel (&dsk_unit);
return SCPE_OK;
}
/* Bootstrap routine */
#define BOOT_START 2000
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
#define BOOT_START 2000
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
static const int32 boot_rom[] = {
060220, /* NIOC DSK ; clear disk */
0102400, /* SUB 0,0 ; addr = 0 */
061020, /* DOA 0,DSK ; set disk addr */
062120, /* DOBS 0,DSK ; set mem addr, rd */
063620, /* SKPDN DSK ; done? */
000776, /* JMP .-2 */
000377, /* JMP 377 */
};
060220, /* NIOC DSK ; clear disk */
0102400, /* SUB 0,0 ; addr = 0 */
061020, /* DOA 0,DSK ; set disk addr */
062120, /* DOBS 0,DSK ; set mem addr, rd */
063620, /* SKPDN DSK ; done? */
000776, /* JMP .-2 */
000377, /* JMP 377 */
};
t_stat dsk_boot (int32 unitno, DEVICE *dptr)
{
@@ -282,11 +301,11 @@ t_stat r;
r = attach_unit (uptr, cptr);
if (r != SCPE_OK) return r;
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) {
p = (sz + ds_bytes - 1) / ds_bytes;
if (p >= DSK_NUMDK) p = DSK_NUMDK - 1;
uptr->flags = (uptr->flags & ~UNIT_PLAT) |
(p << UNIT_V_PLAT); }
uptr->capac = UNIT_GETP (uptr->flags) * DSK_DKSIZE; /* set capacity */
p = (sz + ds_bytes - 1) / ds_bytes;
if (p >= DSK_NUMDK) p = DSK_NUMDK - 1;
uptr->flags = (uptr->flags & ~UNIT_PLAT) | (p << UNIT_V_PLAT);
}
uptr->capac = UNIT_GETP (uptr->flags) * DSK_DKSIZE; /* set capacity */
return SCPE_OK;
}