1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-03-27 10:20:52 +00:00

KA10: Merged in support for KL10A/B

This commit is contained in:
Richard Cornwell
2020-02-17 15:21:46 -05:00
25 changed files with 11268 additions and 1991 deletions

View File

@@ -246,7 +246,7 @@ static int transaction (unsigned char *request, unsigned char *response)
return 0;
}
int auxcpu_read (int addr, t_uint64 *data)
int auxcpu_read (t_addr addr, t_uint64 *data)
{
unsigned char request[12];
unsigned char response[12];
@@ -292,7 +292,7 @@ int auxcpu_read (int addr, t_uint64 *data)
return 0;
}
int auxcpu_write (int addr, t_uint64 data)
int auxcpu_write (t_addr addr, t_uint64 data)
{
unsigned char request[12];
unsigned char response[12];

View File

@@ -335,8 +335,6 @@ void ch10_command (uint32 data)
t_stat ch10_devio(uint32 dev, uint64 *data)
{
DEVICE *dptr = &imx_dev;
switch(dev & 07) {
case CONO:
sim_debug (DBG_REG, &ch10_dev, "CONO %012llo %012llo \n", *data, ch10_status);

623
PDP10/ka10_iii.c Normal file
View File

@@ -0,0 +1,623 @@
/* ka10_iii.c: Triple III display processor.
Copyright (c) 2013-2019, 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.
Except as contained in this notice, the name of Richard Cornwell shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Richard Cornwell
*/
#include "kx10_defs.h"
#ifndef NUM_DEVS_III
#define NUM_DEVS_III 0
#endif
#if NUM_DEVS_III > 0
#include "display/display.h"
#define III_DEVNUM 0430
#define STATUS u3
#define MAR u4
#define PIA u5
#define POS u6
/* CONO Bits */
#define SET_PIA 000000010 /* Set if this bit is zero */
#define STOP 000000020 /* Stop processor after instruction */
#define CONT 000000040 /* Start execution at address */
#define F 000000100 /* Clear flags */
#define SET_MSK 000360000 /* Set mask */
#define RST_MSK 007400000 /* Reset mask */
/* CONI Bits */
#define PIA_MSK 000000007
#define INST_HLT 000000010 /* Halt instruction */
#define WRAP_ENB 000000020 /* Wrap around mask */
#define EDGE_ENB 000000040 /* Edge interrupt mask */
#define LIGH_ENB 000000100 /* Light pen enable mask */
#define CLK_STOP 000000200 /* Clock stop */
#define CLK_BIT 000001000 /* Clock */
#define NXM_BIT 000002000 /* Non-existent memory */
#define IRQ_BIT 000004000 /* Interrupt pending */
#define DATAO_LK 000010000 /* PDP10 gave DATAO when running */
#define LIGHT_FLG 000020000 /* Light pen flag */
#define WRAP_FLG 000040000 /* Wrap around flag */
#define EDGE_FLG 000100000 /* Edge overflow */
#define HLT_FLG 000200000 /* Not running */
#define WRAP_MSK 00001
#define EDGE_MSK 00002
#define LIGH_MSK 00004
#define HLT_MSK 00010
#define WRP_FBIT 00020
#define EDG_FBIT 00040
#define LIT_FBIT 00100
#define CTL_FBIT 00200
#define HLT_FBIT 00400
#define NXM_FLG 01000
#define DATA_FLG 02000
#define RUN_FLG 04000
#define TSS_INST 012 /* Test */
#define LVW_INST 006 /* Long Vector */
#define SVW_INST 002 /* Short vector */
#define JMP_INST 000 /* Jump or Halt */
#define JSR_INST 004 /* JSR(1) or JMS(0), SAVE(3) */
#define RES_INST 014 /* Restore */
#define SEL_INST 010 /* Select instruction */
#define CSIZE 00000000007 /* Current char size */
#define CBRT 00000000070 /* Current brightness */
#define POS_Y 00000377700
#define POS_X 01777400000
#define CSIZE_V 0
#define CBRT_V 3
#define POS_X_V 6
#define POS_Y_V 16
/*
* Character map.
* M(x,y) moves pointer to x,y.
* V(x,y) draws a vector between current pointer and x,y.
* All characters start at 0,6 and end at 8,6.
* In the map there are up to 18 points per character. For a character a M(0,0) indicates
* that drawing is done and a move to 8,6 should be done.
*/
#define M(x,y) (x << 4)|y|0000
#define V(x,y) (x << 4)|y|0200
uint8 map[128][18] = {
{ 0 },
{ M(0,9), V(3,6), V(3,14), M(3,6), V(6,9) },
{ M(6,6), V(3,9), V(1,9), V(0,8), V(0,7), V(1,6), V(3,6), V(6,9) },
{ V(2,8), V(2,13), V(3,14), V(5,14), V(6,13), V(6,12), V(5,11), V(2,11), M(5,11),
V(6,10), V(6,9), V(5,8), V(3,8), V(2,9) },
{ M(0,8), V(3,11), V(6,8) },
{ M(0,10), V(6,10), V(6,7) },
{ M(3,9), V(2,10), V(1,10), V(0,9), V(0,7), V(1,6), V(2,6), V(3,7), M(2,8), V(0,8) },
{ M(0,10), V(6,10), M(4,10), V(4,6), M(2,6), V(2,10) },
{ V(3,9), M(0,11), V(1,11), V(6,6) },
{ M(0,11), V(1,12), V(2,12), V(5,9), V(5,7), V(4,6), V(3,6), V(2,7), V(2,8), V(6,12) },
{ M(2,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7), V(4,9), V(3,10), V(2,10),
V(2,12), V(4,12) },
{ M(0,7), V(1,6), V(2,6), V(3,7), V(3,12), V(4,13), V(5,13), V(6,12) },
{ M(0,9), V(4,9), M(2,11), V(2,7), M(0,7), V(4,7) },
{ M(0,8), V(0,7), V(1,6), V(3,6), V(4,7), V(4,9), V(3,10), V(1,10), V(0,9), V(0,8),
V(4,8), M(2,10), V(2,6) },
{ M(0,10), V(1,9), V(2,9), V(4,11), V(5,11), V(6,10), V(5,9), V(4,9), V(2,11), V(1,11),
V(0,10) },
{ M(4,8), V(3,9), V(1,9), V(0,8), V(0,7), V(1,6), V(3,6), V(4,7), V(4,10), V(2,12),
V(1,12) },
{ M(3,11), V(1,11), V(0,10), V(0,8), V(1,7), V(3,7) },
{ M(0,11), V(2,11), V(3,10), V(3,8), V(2,7), V(0,7) },
{ M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7) },
{ M(0,10), V(0,8), V(1,7), V(3,7), V(4,8), V(4,10) },
{ M(0,13), V(0,8), V(2,6), V(4,6), V(6,8), V(6,13), M(0,10), V(6,10) },
{ V(6,6), V(6,14), V(0,14), M(2,10), V(6,10) },
{ V(4,10), M(0,10), V(4,6), M(3,6), V(1,6), V(0,7), V(0,9), V(1,10), V(3,10), V(4,9),
V(4,7), V(3,6) },
{ M(2,8), V(0,10), V(2,12), M(0,10), V(6,10), M(4,12), V(6,10), V(4,8) },
{ M(0,5), V(6,5) },
{ M(0,10), V(6,10), M(3,13), V(6,10), V(3,7) },
{ M(0,12), V(2,14), V(4,12), V(6,14) },
{ V(6,12), M(0,10), V(6,10), M(0,8), V(6,8) },
{ V(3,6), M(3,7), V(0,10), V(3,13) },
{ V(3,6), M(0,7), V(3,10), V(0,13) },
{ M(0,7), V(6,7), M(6,9), V(0,9), M(0,11), V(6,11) },
{ M(0,11), V(3,8), V(6,11) },
{ 0, },
{ M(2,6), V(2,7), M(2,8), V(2,13) },
{ M(2,12), V(2,14), M(4,14), V(4,12) },
{ M(2,7), V(2,13), M(4,13), V(4,7), M(6,9), V(0,9), M(0,11), V(6,11) },
{ M(0,8), V(2,6), V(4,6), V(6,8), V(4,10), V(2,10), V(0,12), V(2,14), V(4,14), V(6,12),
M(4,14), V(4,6), M(2,6), V(2,14) },
{ V(6,12), V(1,12), V(0,11), V(0,10), V(1,9), V(2,9), V(3,10), V(3,11), V(2,12), M(4,9),
V(3,8), V(3,7), V(4,6), V(5,6), V(6,7), V(6,8), V(5,9), V(4,9) },
{ M(6,6), V(1,11), V(1,13), V(2,14), V(3,14), V(4,13), V(0,9), V(0,7), V(1,6), V(3,6),
V(5,8) },
{ M(2,12), V(4,14) },
{ M(2,6), V(0,8), V(0,12), V(2,14) },
{ V(2,8), V(2,12), V(0,14) },
{ M(1,8), V(5,12), M(3,13), V(3,7), M(5,8), V(1,12), M(0,10), V(6,10) },
{ M(2,7), V(2,11), M(0,9), V(4,9) },
{ M(0,7), V(1,6), V(1,5), V(0,4) },
{ M(0,9), V(4,9) },
{ M(2,6), V(3,6), V(3,7), V(2,7), V(2,6) },
{ V(6,12) },
{ M(0,7), V(6,13), M(6,12), V(4,14), V(2,14), V(0,12), V(0,8), V(2,6), V(4,6), V(6,8),
V(6,12) },
{ M(1,12), V(3,14), V(3,6) },
{ M(0,13), V(1,14), V(4,14), V(6,12), V(6,11), V(5,10), V(2,10), V(0,8), V(0,6), V(6,6) },
{ M(0,14), V(6,14), V(6,12), V(4,10), V(5,10), V(6,9), V(6,7), V(5,6), V(0,6) },
{ M(5,6), V(5,14), V(0,9), V(6,9) },
{ M(0,7), V(1,6), V(4,6), V(6,8), V(6,9), V(5,10), V(1,10), V(0,9), V(0,14), V(6,14) },
{ M(0,9), V(1,10), V(5,10), V(6,9), V(6,7), V(5,6), V(1,6), V(0,7), V(0,10), V(4,14) },
{ V(6,12), V(6,14), V(0,14) },
{ M(1,10), V(0,9), V(0,7), V(1,6), V(5,6), V(6,7), V(6,9), V(5,10), V(6,11), V(6,13),
V(5,14), V(1,14), V(0,13), V(0,11), V(1,10), V(5,10) },
{ M(2,6), V(6,10), V(6,13), V(5,14), V(1,14), V(0,13), V(0,11), V(1,10), V(5,10),
V(6,11) },
{ M(2,6), V(3,6), V(3,7), V(2,7), V(2,6), M(2,10), V(3,10), V(3,11), V(2,11), V(2,10) },
{ M(2,7), V(3,6), V(3,5), V(2,4), M(2,10), V(3,10), V(3,11), V(2,11), V(2,10) },
{ M(3,7), V(0,10), V(3,13) },
{ M(0,8), V(6,8), M(6,10), V(0,10) },
{ M(0,7), V(3,10), V(0,13) },
{ M(0,13), V(1,14), V(2,13), V(2,12), V(1,11), V(1,8), M(1,7), V(1,6) },
{ M(1,6), V(0,7), V(0,11), V(1,12), V(5,12), V(6,11), V(6,8), V(5,7), V(4,8), V(4,11),
M(4,10), V(3,11), V(2,11), V(1,10), V(1,9), V(2,8), V(3,8), V(4,9) },
{ V(0,12), V(2,14), V(4,14), V(6,12), V(6,9), V(0,9), V(6,9), V(6,6) },
{ V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10), V(5,10), V(6,9), V(6,7), V(5,6),
V(0,6) },
{ M(6,13), V(5,14), V(2,14), V(0,12), V(0,8), V(2,6), V(5,6), V(6,7) },
{ V(0,14), V(4,14), V(6,12), V(6,8), V(4,6), V(0,6) },
{ M(6,6), V(0,6), V(0,10), V(4,10), V(0,10), V(0,14), V(6,14) },
{ V(0,10), V(4,10), V(0,10), V(0,14), V(6,14) },
{ M(6,13), V(5,14), V(2,14), V(0,12), V(0,8), V(2,6), V(4,6), V(6,8), V(6,10), V(4,10) },
{ V(0,14), V(0,10), V(6,10), V(6,14), V(6,6) },
{ M(1,6), V(5,6), V(3,6), V(3,14), V(1,14), V(5,14) },
{ M(1,9), V(1,7), V(2,6), V(3,6), V(4,7), V(4,14), V(2,14), V(6,14) },
{ V(0,14), V(0,8), V(6,14), V(2,10), V(6,6) },
{ M(0,14), V(0,6), V(6,6) },
{ V(0,14), V(3,11), V(6,14), V(6,6) },
{ V(0,14), V(0,13), V(6,7), V(6,6), V(6,14) },
{ M(0,8), V(0,12), V(2,14), V(4,14), V(6,12), V(6,8), V(4,6), V(2,6), V(0,8) },
{ V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10) },
{ M(0,8), V(0,12), V(2,14), V(4,14), V(6,12), V(6,8), V(4,6), V(2,6), V(0,8), M(3,9),
V(6,6) },
{ V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10), V(2,10), V(6,6) },
{ M(0,8), V(2,6), V(4,6), V(6,8), V(4,10), V(2,10), V(0,12), V(2,14), V(4,14), V(6,12) },
{ M(3,6), V(3,14), V(0,14), V(6,14) },
{ M(0,14), V(0,7), V(1,6), V(5,6), V(6,7), V(6,14) },
{ M(0,14), V(0,9), V(3,6), V(6,9), V(6,14) },
{ M(0,14), V(0,6), V(3,9), V(6,6), V(6,14) },
{ V(0,7), V(6,13), V(6,14), M(0,14), V(0,13), V(6,7), V(6,6) },
{ M(0,14), V(3,11), V(6,14), V(3,11), V(3,6) },
{ M(0,14), V(6,14), V(6,13), V(0,7), V(0,6), V(6,6) },
{ M(3,5), V(0,5), V(0,15), V(3,15) },
{ M(0,12), V(6,6) },
{ M(0,5), V(3,5), V(3,15), V(0,15) },
{ M(0,11), V(3,14), V(6,11), M(3,14), V(3,6) },
{ M(3,7), V(0,10), V(3,13), M(0,10), V(6,10) },
{ M(2,14), V(4,12) },
{ M(0,9), V(1,10), V(3,10), V(4,9), V(4,6), M(4,8), V(3,9), V(1,9), V(0,8), V(0,7),
V(1,6), V(3,6), V(4,7) },
{ V(0,13), M(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7) },
{ M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7) },
{ M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7), M(4,6),
V(4,13) },
{ M(4,7), V(3,6), V(1,6), V(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,8), V(0,8) },
{ M(2,6), V(2,12), V(3,13), V(4,13), V(5,12), M(0,11), V(4,11) },
{ M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7), M(4,10), V(4,5),
V(3,4), V(1,4), V(0,5) },
{ V(0,13), M(0,9), V(1,10), V(3,10), V(4,9), V(4,6) },
{ M(3,12), V(3,11), M(3,10), V(3,7), V(4,6), V(5,6) },
{ M(3,12), V(3,11), M(3,10), V(3,5), V(2,4), V(1,3) },
{ V(0,13), M(0,8), V(2,10), M(0,8), V(2,6) },
{ M(2,6), V(2,13) },
{ V(0,10), M(0,9), V(1,10), V(2,10), V(3,9), V(3,6), M(3,9), V(4,10), V(5,10), V(6,9),
V(6,6) },
{ V(0,10), M(0,9), V(1,10), V(2,10), V(3,9), V(3,6) },
{ M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7) },
{ M(0,4), V(0,10), M(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7) },
{ M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7), M(4,10), V(4,4) },
{ V(0,10), M(0,9), V(1,10), V(3,10), V(4,9) },
{ M(0,7), V(1,6), V(3,6), V(4,7), V(3,8), V(1,8), V(0,9), V(1,10), V(3,10), V(4,9) },
{ M(2,13), V(2,7), V(3,6), V(4,6), V(5,7), M(1,11), V(3,11) },
{ M(0,10), V(0,7), V(1,6), V(3,6), V(4,7), V(4,10), V(4,6) },
{ M(0,9), V(3,6), V(6,9) },
{ M(0,10), V(0,6), V(2,8), V(4,6), V(4,10) },
{ V(4,10), M(0,10), V(4,6) },
{ M(0,9), V(3,6), M(6,9), V(1,4), V(0,4) },
{ M(0,10), V(4,10), V(0,6), V(4,6) },
{ M(3,15), V(2,14), V(2,12), V(0,10), V(2,8), V(2,6), V(3,5) },
{ M(2,4), V(2,14) },
{ M(3,6), V(0,9), V(3,12), V(6,9), V(3,6) },
{ M(0,15), V(1,14), V(1,12), V(3,10), V(1,8), V(1,6), V(0,5) },
{ M(0,12), V(6,6) },
};
uint64 iii_instr; /* Currently executing instruction */
int iii_sel; /* Select mask */
t_stat iii_devio(uint32 dev, uint64 *data);
t_stat iii_svc(UNIT *uptr);
static void draw_point(int x, int y, int b);
static void draw_line(int x1, int y1, int x2, int y2, int b);
t_stat iii_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
const char *iii_description (DEVICE *dptr);
DIB iii_dib = { III_DEVNUM, 1, iii_devio, NULL};
UNIT iii_unit[] = {
{UDATA (&iii_svc, UNIT_IDLE, 0) },
{ 0 }
};
MTAB iii_mod[] = {
{ 0 }
};
DEVICE iii_dev = {
"III", iii_unit, NULL, iii_mod,
2, 10, 31, 1, 8, 8,
NULL, NULL, NULL,
NULL, NULL, NULL, &iii_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS, 0, dev_debug,
NULL, NULL, &iii_help, NULL, NULL, &iii_description
};
int status;
t_stat iii_devio(uint32 dev, uint64 *data) {
UNIT *uptr = &iii_unit[0];
switch(dev & 3) {
case CONI:
*data = (((uint64)iii_sel) << 18) | (uint64)(uptr->PIA);
if ((iii_instr & 037) == 0)
*data |= INST_HLT;
*data |= (uptr->STATUS & 07) << 4;
if (uptr->STATUS & NXM_FLG)
*data |= NXM_BIT;
if (uptr->STATUS & DATA_FLG)
*data |= DATAO_LK;
if ((uptr->STATUS & RUN_FLG) == 0)
*data |= HLT_FLG;
if (uptr->STATUS & WRP_FBIT)
*data |= WRAP_FLG;
if (uptr->STATUS & EDG_FBIT)
*data |= EDGE_FLG;
if (uptr->STATUS & LIT_FBIT)
*data |= LIGHT_FLG;
sim_debug(DEBUG_CONI, &iii_dev, "III %03o CONI %06o\n", dev, (uint32)*data);
break;
case CONO:
if (*data & SET_PIA)
uptr->PIA = (int)(*data&PIA_MSK);
if (*data & F)
uptr->STATUS &= ~(WRP_FBIT|EDG_FBIT|LIT_FBIT|DATA_FLG|NXM_FLG);
uptr->STATUS &= ~(017 & ((*data >> 14) ^ (*data >> 10)));
uptr->STATUS ^= (017 & (*data >> 10));
if (*data & STOP)
uptr->STATUS |= RUN_FLG;
if (*data & CONT) {
uptr->STATUS &= ~RUN_FLG;
iii_instr = M[uptr->MAR];
sim_activate(uptr, 10);
}
sim_debug(DEBUG_CONO, &iii_dev, "III %03o CONO %06o\n", dev, (uint32)*data);
break;
case DATAI:
sim_debug(DEBUG_DATAIO, &iii_dev, "III %03o DATAI %06o\n", dev, (uint32)*data);
break;
case DATAO:
if (uptr->STATUS & RUN_FLG)
uptr->STATUS |= DATA_FLG;
else {
iii_instr = *data;
sim_activate(uptr, 10);
}
sim_debug(DEBUG_DATAIO, &iii_dev, "III %03o DATAO %06o\n", dev, (uint32)*data);
break;
}
return SCPE_OK;
}
t_stat
iii_svc (UNIT *uptr)
{
uint64 temp;
int A;
int ox, oy, nx, ny, br, sz;
int i, j, ch;
switch(iii_instr & 017) {
case 000: /* JMP and HLT */
if (iii_instr & 020) {
uptr->MAR = (iii_instr >> 18) & RMASK;
} else {
uptr->STATUS &= ~RUN_FLG;
}
break;
case 001:
case 003:
case 005:
case 007:
case 011:
case 013:
case 015:
case 017: /* Draw 4 characters */
/* Extract X,Y,Bright and Size */
sz = (uptr->POS & CSIZE) >> CSIZE_V;
br = (uptr->POS & CBRT) >> CBRT_V;
ox = (uptr->POS & POS_X) >> POS_X_V;
oy = (uptr->POS & POS_Y) >> POS_Y_V;
for (i = 29; i >= 1; i -= 7) {
/* Extract character and compute initial point */
int cx, cy;
uint8 v;
ch = (iii_instr >> i) & 0177;
cx = ox;
cy = oy + (6 * sz);
/* Scan map and draw lines as needed */
for(j = 0; j < 18; j++) {
v = map[i][j];
if (v == 0)
break;
nx = cx + (((v >> 4) & 07) * sz);
ny = cy + ((v & 017) * sz);
if (v & 0200)
draw_line(cx, cy, nx, ny, br);
cx = nx;
cy = ny;
}
ox += 8 * sz;
}
/* Repack to new position. */
uptr->POS = (POS_X & (nx << POS_X_V)) |
(POS_Y & (ny << POS_Y_V)) |
(uptr->POS & (CBRT|CSIZE));
break;
case 002: /* Short Vector */
/* Extract X,Y,Bright and Size */
sz = (uptr->POS & CSIZE) >> CSIZE_V;
br = (uptr->POS & CBRT) >> CBRT_V;
ox = (uptr->POS & POS_X) >> POS_X_V;
oy = (uptr->POS & POS_Y) >> POS_Y_V;
/* Do first point */
nx = (iii_instr >> 29) & 077;
ny = (iii_instr >> 22) & 077;
/* Sign extend */
if (nx & 0100)
nx |= 03700;
if (ny & 0100)
ny |= 03700;
/* Compute relative position. */
nx += ox;
ny += oy;
if ((iii_instr & 010000000LL) == 0) { /* Check if visible */
if ((iii_instr & 004000000LL) == 0) { /* Draw a line */
draw_line(ox, oy, nx, ny, br);
} else {
draw_point(nx, ny, br);
}
}
/* Do second point */
nx = (iii_instr >> 13) & 0177;
ny = (iii_instr >> 6) & 0177;
/* Sign extend */
if (nx & 0100)
nx |= 03700;
if (ny & 0100)
ny |= 03700;
/* Compute relative position. */
nx += ox;
ny += oy;
if ((iii_instr & 040) == 0) { /* Check if visible */
if ((iii_instr & 020) == 0) { /* Draw a line */
draw_line(ox, oy, nx, ny, br);
} else {
draw_point(nx, ny, br);
}
}
/* Repack to new position. */
uptr->POS = (POS_X & (nx << POS_X_V)) |
(POS_Y & (ny << POS_Y_V)) |
(uptr->POS & (CBRT|CSIZE));
break;
case 004: /* JSR, JMS, SAVE */
temp = (((uint64)uptr->MAR) << 18) | 020 /* | CPC */;
A = (iii_instr >> 18) & RMASK;
if ((iii_instr & 030) != 030) {
M[A] = temp;
A++;
}
if ((iii_instr & 020) != 020) {
temp = uptr->STATUS & 0377;
temp |= ((uint64)uptr->POS) << 8;
M[A] = temp;
A++;
}
if ((iii_instr & 030) != 030) {
uptr->MAR = A;
}
break;
case 006: /* Long Vector */
/* Extract X,Y,Bright and Size */
sz = (uptr->POS & CSIZE) >> CSIZE_V;
br = (uptr->POS & CBRT) >> CBRT_V;
ox = (uptr->POS & POS_X) >> POS_X_V;
oy = (uptr->POS & POS_Y) >> POS_Y_V;
/* Update sizes if needed */
if (((iii_instr >> 9) & CSIZE) != 0)
sz = (iii_instr >> 9) & CSIZE;
if (((iii_instr >> 12) & 7) != 0)
br = (iii_instr > 12) & 7;
nx = (iii_instr >> 25) & 03777;
ny = (iii_instr >> 15) & 03777;
if ((iii_instr & 0100) == 0) { /* Relative mode */
nx += ox;
ny += oy;
}
if ((iii_instr & 040) == 0) { /* Check if visible */
if ((iii_instr & 020) == 0) /* Draw a line */
draw_line(ox, oy, nx, ny, br);
else
draw_point(nx, ny, br);
}
/* Repack to new position. */
uptr->POS = (POS_X & (nx << POS_X_V)) |
(POS_Y & (ny << POS_Y_V)) |
(CBRT & (br << CBRT_V)) |
(CSIZE & (sz << CSIZE_V));
break;
case 010: /* Select instruction */
break;
case 012: /* Test instruction */
A = (uptr->STATUS & (int32)(iii_instr >> 12) & 0377) != 0;
uptr->STATUS &= ~(0377 & ((iii_instr >> 28) ^ (iii_instr >> 20)));
uptr->STATUS ^= (0377 & (iii_instr >> 20));
if (A ^ ((iii_instr & 020) != 0))
uptr->MAR++;
break;
case 014: /* Restore */
A = (iii_instr >> 18) & RMASK;
temp = M[A];
if ((iii_instr & 020) != 0) {
uptr->STATUS &= ~0377;
uptr->STATUS |= temp & 0377;
}
if ((iii_instr & 040) != 0) {
uptr->POS = (temp >> 8) & (POS_X|POS_Y|CBRT|CSIZE);
}
break;
case 016: /* Nop */
break;
}
if (uptr->STATUS & RUN_FLG) {
iii_instr = M[uptr->MAR];
uptr->MAR++;
uptr->MAR &= RMASK;
sim_activate(uptr, 10);
}
return SCPE_OK;
}
/* Draw a point at x,y with intensity b. */
/* X and Y runs from -512 to 512. */
static void
draw_point(int x, int y, int b)
{
display_point(x, y, b, 0);
}
/* Draw a line between two points */
static void
draw_line(int x1, int y1, int x2, int y2, int b)
{
int dx, px;
int dy, py;
int i, p;
int minx, miny;
int maxx, maxy;
dx = x1 - x2;
dy = y1 - y2;
if (x1 < 0) {
dx = -1;
px = -x1;
} else if (x1 > 0) {
dx = 1;
px = x1;
} else {
dx = 0;
px = 0;
}
if (y1 < 0) {
dy = -1;
py = -y1;
} else if (y1 > 0) {
dy = 1;
py = y1;
} else {
dy = 0;
py = 0;
}
if (dx == 0) {
/* Vertical line */
for (i = 1; i < py; i++) {
dy += dy;
draw_point(dx, dy, b);
}
} else if (dy == 0) {
/* Horizontal line */
for (i = 1; i < px; i++) {
dx += dx;
draw_point(dx, dy, b);
}
} else if (py > px) {
/* More horizontal */
p = 2 * px - py;
for (i = 1; i < py; i++) {
if (p > 0) {
dx += dx;
p += (2 * px) - (2 * py);
} else {
p += 2 * px;
}
dy += dy;
draw_point(dx, dy, b);
}
} else {
/* More vertical */
p = 2 * py - px;
for (i = 1; i < px; i++) {
if (p > 0) {
dy += dy;
p += (2 * py) - (2 * px);
} else {
p += 2 * py;
}
dx += dx;
draw_point(dx, dy, b);
}
}
}
t_stat iii_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
{
return SCPE_OK;
}
const char *iii_description (DEVICE *dptr)
{
return "Triple III Display";
}
#endif

View File

@@ -142,7 +142,7 @@
#define DK_MSK_SKNONE 0x18 /* Allow no seeks */
#define DK_MSK_SK 0x18 /* Seek mask */
#define POS u4
#define POS u4
/* u4 */
/* Holds the current track and head */
#define DK_V_TRACK 8
@@ -348,9 +348,9 @@ uint64 pmp_status; /* CONI status for device 500 */
int pmp_statusb;
uint32 pmp_cmd_hold; /* Command hold register */
uint32 pmp_wc_hold; /* Word count hold */
uint32 pmp_addr_hold; /* Address register hold */
t_addr pmp_addr_hold; /* Address register hold */
uint32 pmp_wc; /* Current word count register */
uint32 pmp_addr; /* Current address register */
t_addr pmp_addr; /* Current address register */
uint64 pmp_data; /* Data assembly register */
int pmp_cnt; /* Character count in asm register */
int pmp_cmd; /* Current command */
@@ -382,7 +382,7 @@ t_stat pmp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
const char *cptr);
const char *pmp_description (DEVICE *dptr);
DIB pmp_dib[] = {
DIB pmp_dib[] = {
{PMP_DEV, 2, &pmp_devio, NULL}};
@@ -433,13 +433,13 @@ pmp_devio(uint32 dev, uint64 *data) {
if ((pmp_statusb & (WCMA_LD|CMD_LD)) != (WCMA_LD|CMD_LD))
*data |= HOLD_EMPTY;
if (pmp_cur_unit != NULL)
*data |= ((uint64)GET_UADDR(pmp_cur_unit->flags)) << 24;
*data |= ((uint64)GET_UADDR(pmp_cur_unit->flags)) << 24;
if ((pmp_status & (NXM_ERR|CHA_ERR|SEL_ERR)) != 0)
*data |= UNU_END;
sim_debug(DEBUG_CONI, &pmp_dev, "PMP %03o CONI %012llo PC=%o\n",
dev, *data, PC);
break;
case CONO:
sim_debug(DEBUG_CONO, &pmp_dev, "PMP %03o CONO %012llo PC=%06o\n",
dev, *data, PC);
@@ -597,9 +597,8 @@ chan_read_byte(uint8 *data) {
pmp_statusb |= TRANS_CH; /* Tranfer in progress */
/* Read in next work if buffer is in empty status */
if (pmp_cnt & BUFF_EMPTY) {
if (pmp_addr >= (int)MEMSIZE)
if (Mem_read_word(pmp_addr, &pmp_data, 0))
return pmp_posterror(NXM_ERR);
pmp_data = M[pmp_addr];
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_read %06o %012llo\n", pmp_addr, pmp_data);
pmp_addr++;
pmp_cnt = 0;
@@ -616,10 +615,9 @@ chan_read_byte(uint8 *data) {
if ((pmp_cnt & 0xf) > 0x3) {
if ((pmp_cnt & 0xf) == 0x4) { /* Split byte */
byte = (pmp_data << 4) & 0xf0;
if (pmp_addr >= (int)MEMSIZE)
if (Mem_read_word(pmp_addr, &pmp_data, 0))
return pmp_posterror(NXM_ERR);
pmp_data = M[pmp_addr];
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_read %06o %012llo\n", pmp_addr, pmp_data);
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_read %06o %012llo\n", pmp_addr, pmp_data);
pmp_addr++;
xfer = 1; /* Read in a word */
byte |= pmp_data & 0xf;
@@ -639,7 +637,7 @@ chan_read_byte(uint8 *data) {
} else if (xfer) {
pmp_wc ++;
}
if (pmp_wc & 07000000)
if (pmp_wc & 07000000)
pmp_cnt |= BUFF_CHNEND;
return 0;
#if 0
@@ -693,11 +691,10 @@ chan_write_byte(uint8 *data) {
pmp_cnt |= BUFF_DIRTY;
if ((pmp_cnt & 03) == 0) {
pmp_cnt &= ~(BUFF_DIRTY|7);
if (pmp_addr >= (int)MEMSIZE)
if (Mem_write_word(pmp_addr, &pmp_data, 0))
return pmp_posterror(NXM_ERR);
M[pmp_addr] = pmp_data;
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo\n", pmp_addr, pmp_data);
pmp_addr++;
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo\n", pmp_addr, pmp_data);
pmp_addr++;
xfer = 1;
}
} else {
@@ -705,9 +702,8 @@ chan_write_byte(uint8 *data) {
if ((pmp_cnt & 0xf) == 0x4) { /* Split byte */
pmp_data &= ~0xf;
pmp_data |= (uint64)((*data >> 4) & 0xf);
if (pmp_addr >= (int)MEMSIZE)
if (Mem_write_word(pmp_addr, &pmp_data, 0))
return pmp_posterror(NXM_ERR);
M[pmp_addr] = pmp_data;
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo %2x\n", pmp_addr, pmp_data, pmp_cnt);
pmp_addr++;
xfer = 1; /* Read in a word */
@@ -726,9 +722,8 @@ chan_write_byte(uint8 *data) {
pmp_cnt++;
if ((pmp_cnt & 0xf) == 9) {
pmp_cnt = BUFF_EMPTY;
if (pmp_addr >= (int)MEMSIZE)
if (Mem_write_word(pmp_addr, &pmp_data, 0))
return pmp_posterror(NXM_ERR);
M[pmp_addr] = pmp_data;
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo %2x\n", pmp_addr, pmp_data, pmp_cnt);
pmp_addr++;
xfer = 1; /* Read in a word */
@@ -774,16 +769,15 @@ chan_end(uint8 flags) {
/* Flush buffer if there was any change */
if (pmp_cnt & BUFF_DIRTY) {
pmp_cnt = BUFF_EMPTY;
if (pmp_addr >= (int)MEMSIZE) {
if (Mem_write_word(pmp_addr, &pmp_data, 0)) {
(void) pmp_posterror(NXM_ERR);
return;
}
M[pmp_addr] = pmp_data;
sim_debug(DEBUG_DATA, &pmp_dev, "chan_write %012llo\n", pmp_data);
pmp_addr++;
}
pmp_statusb &= ~TRANS_CH; /* Clear transfer in progress */
pmp_statusb |= IDLE_CH;
pmp_statusb |= IDLE_CH;
pmp_status |= NEW_STS | CHN_END | ((uint64)flags) << 5;
if (pmp_status & (BSY|UNIT_CHK))
@@ -798,7 +792,7 @@ chan_end(uint8 flags) {
if (pmp_cmd & DATCH_ON) {
(void) pmp_posterror(CHA_ERR);
return;
}
}
if (pmp_cmd & CMDCH_ON) {
pmp_startcmd();

View File

@@ -239,7 +239,7 @@ static int transaction (unsigned char *request, unsigned char *response)
return 0;
}
static int read_word (int addr, int *data)
static int read_word (t_addr addr, int *data)
{
unsigned char request[8];
unsigned char response[8];
@@ -285,7 +285,7 @@ static int read_word (int addr, int *data)
return 0;
}
int ten11_read (int addr, uint64 *data)
int ten11_read (t_addr addr, uint64 *data)
{
int offset = addr & 01777;
int word1, word2;
@@ -328,7 +328,7 @@ int ten11_read (int addr, uint64 *data)
return 0;
}
static int write_word (int addr, uint16 data)
static int write_word (t_addr addr, uint16 data)
{
unsigned char request[8];
unsigned char response[8];
@@ -366,7 +366,7 @@ static int write_word (int addr, uint16 data)
return 0;
}
int ten11_write (int addr, uint64 data)
int ten11_write (t_addr addr, uint64 data)
{
int offset = addr & 01777;

2463
PDP10/kl10_fe.c Normal file

File diff suppressed because it is too large Load Diff

1672
PDP10/kl10_nia.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -46,16 +46,12 @@
#define KI 0
#endif
#ifndef KLA
#define KLA 0
#ifndef KL
#define KL 0
#endif
#ifndef KLB
#define KLB 0
#endif
#ifndef KL /* Either KL10A or KL10B */
#define KL (KLA+KLB)
#if KL
#define EPT440 0 /* Force KL10 to use as 440 section address */
#endif
#if (PDP6 + KA + KI + KL) != 1
@@ -81,6 +77,11 @@
#define WAITS KA
#endif
/* Support for ITS on KL */
#ifndef KL_ITS
#define KL_ITS KL
#endif
#ifndef PDP6_DEV /* Include PDP6 devices */
#define PDP6_DEV PDP6|WAITS
#endif
@@ -161,12 +162,19 @@ extern DEBTAB crd_debug[];
#define XMASK 03777777777777LL
#define EMASK 00777000000000LL
#define MMASK 00000777777777LL
#define SECTM 00007777000000LL
#define BIT1 00200000000000LL
#define BIT2 00100000000000LL
#define BIT3 00040000000000LL
#define BIT4 00020000000000LL
#define BIT5 00010000000000LL
#define BIT6 00004000000000LL
#define BIT7 00002000000000LL
#define BIT8 00001000000000LL
#define BIT9 00000400000000LL
#define BIT10 00000200000000LL
#define BIT10_35 00000377777777LL
#define BIT12 00000040000000LL
#define BIT17 00000001000000LL
#define MANT 00000777777777LL
#define EXPO 00377000000000LL
@@ -181,6 +189,7 @@ extern DEBTAB crd_debug[];
#define FPRBIT1 00000000000200000000000LL
#define CM(x) (FMASK ^ (x))
#define CCM(x) ((CMASK ^ (x)) & CMASK)
#define INST_V_OP 27 /* opcode */
#define INST_M_OP 0777
@@ -205,6 +214,8 @@ extern DEBTAB crd_debug[];
#define LRZ(x) (((x) >> 18) & RMASK)
#define JRST1 (((uint64)OP_JRST << 27) + 1)
#define OP_PORTAL(x) (((x) & 00777740000000LL) == 0254040000000LL)
#if PDP6
#define NODIV 000000
#define FLTUND 000000
@@ -275,6 +286,12 @@ extern DEBTAB crd_debug[];
#define AMASK 00000017777777LL
#define WMASK 0037777LL
#define CSHIFT 22
#if KL
#define RH20_WMASK 003777LL
#define RH20_XFER SMASK
#define RH20_HALT BIT1
#define RH20_REV BIT2
#endif
#else
#define AMASK RMASK
#define WMASK RMASK
@@ -285,11 +302,19 @@ extern DEBTAB crd_debug[];
#define PI_ENABLE 0000000010 /* Clear DONE */
#define BUSY 0000000020 /* STOP */
#define CCW_COMP 0000000040 /* Write Final CCW */
/* RH10 / RH20 interrupt */
#define IADR_ATTN 0000000000040LL /* Interrupt on attention */
#define IARD_RAE 0000000000100LL /* Interrupt on register access error */
#define CCW_COMP_1 0000000040000LL /* Control word written. */
#if KI
#define DEF_SERIAL 514 /* Default DEC test machine */
#endif
#if KL
#define DEF_SERIAL 1025 /* Default DEC test machine */
#endif
#if BBN
#define BBN_PAGE 0000017777777LL
#define BBN_TRPPG 0000017000000LL
@@ -306,13 +331,36 @@ extern DEBTAB crd_debug[];
#define BBN_MERGE 0161740000000LL
#endif
#if KL
/* KL10 TLB paging bits */
#define KL_PAG_A 0400000 /* Access */
#define KL_PAG_P 0200000 /* Public */
#define KL_PAG_W 0100000 /* Writable (M Tops 20) */
#define KL_PAG_S 0040000 /* Software (W Writable Tops 20) */
#define KL_PAG_C 0020000 /* Cacheable */
#endif
#if KI
/* KI10 TLB paging bits */
#define KI_PAG_A 0400000 /* Access */
#define KI_PAG_P 0200000 /* Public */
#define KI_PAG_W 0100000 /* Writable */
#define KI_PAG_S 0040000 /* Software */
#define KI_PAG_X 0020000 /* Reserved */
#endif
/* Flags for CPU unit */
#define UNIT_V_MSIZE (UNIT_V_UF + 0)
#define UNIT_MSIZE (0177 << UNIT_V_MSIZE)
#define UNIT_V_MAOFF (UNIT_V_MSIZE + 8)
#define UNIT_V_PAGE (UNIT_V_MAOFF + 1)
#define UNIT_MAOFF (1 << UNIT_V_MAOFF)
#if KL
#define UNIT_KL10B (1 << UNIT_V_PAGE)
#define UNIT_TWOSEG (0)
#else
#define UNIT_TWOSEG (1 << UNIT_V_PAGE)
#endif
#define UNIT_ITSPAGE (2 << UNIT_V_PAGE)
#define UNIT_BBNPAGE (4 << UNIT_V_PAGE)
#define UNIT_M_PAGE (007 << UNIT_V_PAGE)
@@ -322,7 +370,29 @@ extern DEBTAB crd_debug[];
#define UNIT_V_MPX (UNIT_V_WAITS + 1)
#define UNIT_M_MPX (1 << UNIT_V_MPX)
#define UNIT_MPX (UNIT_M_MPX) /* MPX Device for ITS */
#define CNTRL_V_RH (UNIT_V_UF + 4)
#define CNTRL_M_RH 7
#define GET_CNTRL_RH(x) (((x) >> CNTRL_V_RH) & CNTRL_M_RH)
#define CNTRL_RH(x) (((x) & CNTRL_M_RH) << CNTRL_V_RH)
#define DEV_V_RH (DEV_V_UF + 1) /* Type RH20 */
#define DEV_M_RH (1 << DEV_V_RH)
#define TYPE_RH10 (0 << DEV_V_RH)
#define TYPE_RH20 (1 << DEV_V_RH)
#if KL
/* DTE memory access functions, n = DTE# */
extern int Mem_examine_word(int n, int wrd, uint64 *data);
extern int Mem_deposit_word(int n, int wrd, uint64 *data);
extern int Mem_read_byte(int n, uint16 *data, int byte);
extern int Mem_write_byte(int n, uint16 *data);
#endif
/*
* Access main memory. Returns 0 if access ok, 1 if out of memory range.
* On KI10 and KL10, optional EPT flag indicates address relative to ept.
*/
extern int Mem_read_word(t_addr addr, uint64 *data, int ept);
extern int Mem_write_word(t_addr addr, uint64 *data, int ept);
#if MPX_DEV
extern void set_interrupt_mpx(int dev, int lvl, int mpx);
@@ -338,8 +408,15 @@ extern void set_pi_hold();
extern UNIT cpu_unit[];
extern UNIT ten11_unit[];
extern UNIT auxcpu_unit[];
extern DEVICE cpu_dev;
#if KL
extern DEVICE dte_dev;
extern DEVICE lp20_dev;
extern DEVICE tty_dev;
extern DEVICE nia_dev;
#else
extern DEVICE cty_dev;
#endif
extern DEVICE cpu_dev;
extern DEVICE mt_dev;
extern DEVICE dpa_dev;
extern DEVICE dpb_dev;
@@ -365,6 +442,7 @@ extern DEVICE pmp_dev;
extern DEVICE dk_dev;
extern DEVICE pd_dev;
extern DEVICE dpy_dev;
extern DEVICE iii_dev;
extern DEVICE imx_dev;
extern DEVICE imp_dev;
extern DEVICE ch10_dev;
@@ -387,41 +465,67 @@ extern t_stat (*dev_tab[128])(uint32 dev, t_uint64 *data);
#define VEC_DEVMAX 8 /* max device vec */
/* DF10 Interface */
struct df10 {
uint32 status; /* DF10 status word */
uint32 cia; /* Initial transfer address */
uint32 ccw; /* Next control word address */
uint32 wcr; /* CUrrent word count */
uint32 cda; /* Current transfer address */
uint32 devnum; /* Device number */
t_uint64 buf; /* Data buffer */
uint8 nxmerr; /* Bit to set for NXM */
uint8 ccw_comp; /* Have we written out CCW */
} ;
/* RH10/RH20 Interface */
struct rh_if {
void (*dev_write)(DEVICE *dptr, struct rh_if *rh, int reg, uint32 data);
uint32 (*dev_read)(DEVICE *dptr, struct rh_if *rh, int reg);
void (*dev_reset)(DEVICE *dptr);
t_uint64 buf; /* Data buffer */
uint32 status; /* DF10 status word */
uint32 cia; /* Initial transfer address */
uint32 ccw; /* Current word count */
uint32 wcr;
uint32 cda; /* Current transfer address */
uint32 devnum; /* Device number */
int ivect; /* Interrupt vector */
uint8 imode; /* Mode of vector */
int cop; /* RH20 Channel operator */
uint32 sbar; /* RH20 Starting address */
uint32 stcr; /* RH20 Count */
uint32 pbar;
uint32 ptcr;
int reg; /* Last register selected */
int drive; /* Last drive selected */
int rae; /* Access register error */
int attn; /* Attention bits */
int xfer_drive; /* Current transfering drive */
};
/* Device context block */
struct pdp_dib {
uint32 dev_num; /* device address */
uint32 num_devs; /* length */
t_stat (*io)(uint32 dev, t_uint64 *data);
int (*irq)(uint32 dev, int addr);
t_addr (*irq)(uint32 dev, t_addr addr);
struct rh_if *rh;
};
#define RH10_DEV 01000
#define RH20_DEV 02000
struct rh_dev {
uint32 dev_num;
DEVICE *dev;
struct rh_if *rh;
};
typedef struct pdp_dib DIB;
/* DF10 Interface */
struct df10 {
uint32 status;
uint32 cia;
uint32 ccw;
uint32 wcr;
uint32 cda;
uint32 devnum;
t_uint64 buf;
uint8 nxmerr;
uint8 ccw_comp;
} ;
void df10_setirq(struct df10 *df) ;
void df10_writecw(struct df10 *df) ;
void df10_finish_op(struct df10 *df, int flags) ;
void df10_setirq(struct df10 *df);
void df10_writecw(struct df10 *df);
void df10_finish_op(struct df10 *df, int flags);
void df10_setup(struct df10 *df, uint32 addr);
int df10_fetch(struct df10 *df);
int df10_read(struct df10 *df);
@@ -432,8 +536,27 @@ int dct_write(int u, t_uint64 *data, int c);
int dct_is_connect(int u);
#endif
int ten11_read (int addr, t_uint64 *data);
int ten11_write (int addr, t_uint64 data);
/* Define RH10/RH20 functions */
t_stat rh_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat rh_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat rh_devio(uint32 dev, t_uint64 *data);
t_addr rh_devirq(uint32 dev, t_addr addr);
#if KL
void rh20_setup(struct rh_if *rhc);
#endif
void rh_setup(struct rh_if *rh, uint32 addr);
void rh_setattn(struct rh_if *rh, int unit);
void rh_error(struct rh_if *rh);
int rh_blkend(struct rh_if *rh);
void rh_setirq(struct rh_if *rh);
void rh_writecw(struct rh_if *rh, int nxm);
void rh_finish_op(struct rh_if *rh, int flags);
int rh_read(struct rh_if *rh);
int rh_write(struct rh_if *rh);
int ten11_read (t_addr addr, t_uint64 *data);
int ten11_write (t_addr addr, t_uint64 data);
/* Console lights. */
extern void ka10_lights_init (void);
@@ -441,14 +564,20 @@ extern void ka10_lights_main (t_uint64);
extern void ka10_lights_set_aux (int);
extern void ka10_lights_clear_aux (int);
int auxcpu_read (int addr, t_uint64 *);
int auxcpu_write (int addr, t_uint64);
int auxcpu_read (t_addr addr, t_uint64 *);
int auxcpu_write (t_addr addr, t_uint64);
/* I/O system parameters */
#define NUM_DEVS_LP 1
#if KL
#define NUM_DEVS_PT 0
#define NUM_DEVS_CR 0
#define NUM_DEVS_CP 0
#else
#define NUM_DEVS_PT 1
#define NUM_DEVS_CR 1
#define NUM_DEVS_CP 1
#endif
#define NUM_DEVS_DPY USE_DISPLAY
#define NUM_DEVS_WCNSLS USE_DISPLAY
#if PDP6_DEV
@@ -461,16 +590,31 @@ int auxcpu_write (int addr, t_uint64);
#if !PDP6
#define NUM_DEVS_DC 1
#define NUM_DEVS_MT 1
#if KL
#define NUM_DEVS_RC 0
#define NUM_DEVS_DT 0
#define NUM_DEVS_DK 0
#define NUM_DEVS_DP 0
#define NUM_DEVS_LP20 1
#define NUM_DEVS_TTY 1
#define NUM_LINES_TTY 40
#define NUM_DEVS_NIA 1
#else
#define NUM_DEVS_RC 1
#define NUM_DEVS_DT 1
#define NUM_DEVS_DK 1
#define NUM_DEVS_DP 2
#define NUM_DEVS_LP20 0
#define NUM_DEVS_TTY 0
#define NUM_DEVS_NIA 0
#endif
#define NUM_DEVS_RP 4
#define NUM_DEVS_RS 1
#define NUM_DEVS_TU 1
#define NUM_DEVS_PMP WAITS
#define NUM_DEVS_DKB WAITS
#define NUM_DEVS_PD ITS
#define NUM_DEVS_III 0 /* (WAITS * USE_DISPLAY) *//* Disabled until working */
#define NUM_DEVS_PD ITS | KL_ITS
#define NUM_DEVS_IMX ITS
#define NUM_DEVS_STK ITS
#define NUM_DEVS_TK10 ITS
@@ -478,7 +622,7 @@ int auxcpu_write (int addr, t_uint64);
#define NUM_DEVS_TEN11 ITS
#define NUM_DEVS_AUXCPU ITS
#define NUM_DEVS_IMP 1
#define NUM_DEVS_CH10 ITS
#define NUM_DEVS_CH10 ITS | KL_ITS
#define NUM_DEVS_DPK ITS
#define NUM_DEVS_AI ITS
#endif

View File

@@ -1,6 +1,6 @@
/* ka10_df.c: DF10 common routines.
/* kx10_df.c: DF10 common routines.
Copyright (c) 2015-2017, Richard Cornwell
Copyright (c) 2015-2019, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -23,18 +23,24 @@
#include "kx10_defs.h"
/* Set an IRQ for a DF10 device */
void df10_setirq(struct df10 *df) {
df->status |= PI_ENABLE;
set_interrupt(df->devnum, df->status);
}
/* Generate the DF10 complete word */
void df10_writecw(struct df10 *df) {
uint64 wrd;
df->status |= 1 << df->ccw_comp;
if (df->wcr != 0)
df->cda++;
M[df->cia|1] = ((uint64)(df->ccw & WMASK) << CSHIFT) | ((uint64)(df->cda) & AMASK);
wrd = ((uint64)(df->ccw & WMASK) << CSHIFT) | ((uint64)(df->cda) & AMASK);
(void)Mem_write_word(df->cia|1, &wrd, 0);
}
/* Finish off a DF10 transfer */
void df10_finish_op(struct df10 *df, int flags) {
df->status &= ~BUSY;
df->status |= flags;
@@ -42,6 +48,7 @@ void df10_finish_op(struct df10 *df, int flags) {
df10_setirq(df);
}
/* Setup for a DF10 transfer */
void df10_setup(struct df10 *df, uint32 addr) {
df->cia = addr & ICWA;
df->ccw = df->cia;
@@ -50,24 +57,23 @@ void df10_setup(struct df10 *df, uint32 addr) {
df->status &= ~(1 << df->ccw_comp);
}
/* Fetch the next IO control word */
int df10_fetch(struct df10 *df) {
uint64 data;
if (df->ccw > MEMSIZE) {
if (Mem_read_word(df->ccw, &data, 0)) {
df10_finish_op(df, df->nxmerr);
return 0;
}
data = M[df->ccw];
while((data & (WMASK << CSHIFT)) == 0) {
if ((data & AMASK) == 0 || (uint32)(data & AMASK) == df->ccw) {
df10_finish_op(df,0);
return 0;
}
df->ccw = (uint32)(data & AMASK);
if (df->ccw > MEMSIZE) {
if (Mem_read_word(df->ccw, &data, 0)) {
df10_finish_op(df, 1<<df->nxmerr);
return 0;
}
data = M[df->ccw];
}
#if KA & ITS
if (cpu_unit[0].flags & UNIT_ITSPAGE) {
@@ -84,6 +90,7 @@ int df10_fetch(struct df10 *df) {
return 1;
}
/* Read next word */
int df10_read(struct df10 *df) {
uint64 data;
if (df->wcr == 0) {
@@ -102,7 +109,10 @@ int df10_read(struct df10 *df) {
else
#endif
df->cda = (uint32)((df->cda + 1) & AMASK);
data = M[df->cda];
if (Mem_read_word(df->cda, &data, 0)) {
df10_finish_op(df, 1<<df->nxmerr);
return 0;
}
} else {
data = 0;
}
@@ -113,6 +123,7 @@ int df10_read(struct df10 *df) {
return 1;
}
/* Write next word */
int df10_write(struct df10 *df) {
if (df->wcr == 0) {
if (!df10_fetch(df))
@@ -130,7 +141,10 @@ int df10_write(struct df10 *df) {
else
#endif
df->cda = (uint32)((df->cda + 1) & AMASK);
M[df->cda] = df->buf;
if (Mem_write_word(df->cda, &df->buf, 0)) {
df10_finish_op(df, 1<<df->nxmerr);
return 0;
}
}
if (df->wcr == 0) {
return df10_fetch(df);

View File

@@ -423,7 +423,6 @@ t_stat dp_devio(uint32 dev, uint64 *data) {
if (*data & BUSY) {
/* Stop controller */
sim_cancel(uptr);
uptr->STATUS &= ~BUSY;
df10_finish_op(df10, 0);
}
/* Clear flags */
@@ -722,7 +721,7 @@ t_stat dp_svc (UNIT *uptr)
CLR_BUF(uptr);
}
if (r)
sim_activate(uptr, 25);
sim_activate(uptr, 40);
else {
uptr->STATUS &= ~(SRC_DONE|END_CYL|BUSY);
uptr->UFLAGS |= DONE;

View File

@@ -1061,6 +1061,7 @@ dt_boot(int32 unit_num, DEVICE * dptr)
addr = (addr + 1) & RMASK;
word = ((uint64)fbuf[off++]) << 18;
word |= (uint64)fbuf[off++];
fprintf(stderr, "%06o %012llo %06o\n\r", addr, word, wc);
if (addr < 020)
FM[addr] = word;
else
@@ -1073,6 +1074,7 @@ dt_boot(int32 unit_num, DEVICE * dptr)
uptr->DSTATE = (1 << DTC_V_BLK) | DTC_BLOCK | DTC_MOT;
sim_activate(uptr,30000);
PC = word & RMASK;
fprintf(stderr, "%06o\n\r", PC);
return SCPE_OK;
}

View File

@@ -451,6 +451,7 @@ static CONST ETH_MAC broadcast_ethaddr = {0xff,0xff,0xff,0xff,0xff,0xff};
static CONST in_addr_T broadcast_ipaddr = {0xffffffff};
t_stat imp_devio(uint32 dev, uint64 *data);
t_addr imp_devirq(uint32 dev, t_addr addr);
t_stat imp_srv(UNIT *);
t_stat imp_eth_srv(UNIT *);
t_stat imp_tim_srv(UNIT *);
@@ -503,7 +504,13 @@ UNIT imp_unit[] = {
{UDATA(imp_eth_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */
{UDATA(imp_tim_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */
};
DIB imp_dib = {IMP_DEVNUM, 1, &imp_devio, NULL};
DIB imp_dib = {IMP_DEVNUM, 1, &imp_devio,
#if KL
&imp_devirq,
#else
NULL
#endif
};
MTAB imp_mod[] = {
{ MTAB_XTD|MTAB_VDV|MTAB_VALR|MTAB_NC, 0, "MAC", "MAC=xx:xx:xx:xx:xx:xx",
@@ -562,10 +569,13 @@ DEBTAB imp_debug[] = {
{0, 0}
};
REG imp_reg[] = {
{BRDATA(DATA, &imp_data, 16, 8, sizeof(struct imp_device)), REG_HRO},
{0}
};
DEVICE imp_dev = {
"IMP", imp_unit, NULL, imp_mod,
"IMP", imp_unit, imp_reg, imp_mod,
3, 8, 0, 1, 8, 36,
NULL, NULL, &imp_reset, NULL, &imp_attach, &imp_detach,
&imp_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, imp_debug,
@@ -635,6 +645,7 @@ t_stat imp_devio(uint32 dev, uint64 *data)
uptr->STATUS |= IMPIHE;
if (*data & IMPLHW) /* Last host word. */
uptr->STATUS |= IMPLHW;
check_interrupts(uptr);
break;
case TYPE_BBN:
break;
@@ -731,6 +742,20 @@ t_stat imp_devio(uint32 dev, uint64 *data)
return SCPE_OK;
}
#if KL
/* Handle KL style interrupt vectors for ITS */
t_addr
imp_devirq(uint32 dev, t_addr addr) {
if ((cpu_unit[0].flags & UNIT_ITSPAGE) != 0 && (imp_data.pia & 7) == 1) {
if (imp_unit[0].STATUS & IMPID && (imp_unit[0].STATUS & IMPLW) == 0)
return 070|RSIGN;
if (imp_unit[0].STATUS & IMPOD)
return 072|RSIGN;
}
return addr;
}
#endif
t_stat imp_srv(UNIT * uptr)
{
DEVICE *dptr = find_dev_from_unit(uptr);

801
PDP10/kx10_rh.c Normal file
View File

@@ -0,0 +1,801 @@
/* kx10_rh.c: RH10/RH20 interace routines.
Copyright (c) 2015-2019, 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"
/* CONI Flags */
#define IADR_ATTN 0000000000040LL /* Interrupt on attention */
#define IARD_RAE 0000000000100LL /* Interrupt on register access error */
#define DIB_CBOV 0000000000200LL /* Control bus overrun */
#define CXR_PS_FAIL 0000000002000LL /* Power supply fail (not implemented) */
#define CXR_ILC 0000000004000LL /* Illegal function code */
#define CR_DRE 0000000010000LL /* Or Data and Control Timeout */
#define DTC_OVER 0000000020000LL /* DF10 did not supply word on time (not implemented) */
#define CCW_COMP_1 0000000040000LL /* Control word written. */
#define CXR_CHAN_ER 0000000100000LL /* Channel Error */
#define CXR_EXC 0000000200000LL /* Error in drive transfer */
#define CXR_DBPE 0000000400000LL /* Device Parity error (not implemented) */
#define CXR_NXM 0000001000000LL /* Channel non-existent memory (not implemented) */
#define CXR_CWPE 0000002000000LL /* Channel Control word parity error (not implemented) */
#define CXR_CDPE 0000004000000LL /* Channel Data Parity Error (not implemented) */
#define CXR_SD_RAE 0000200000000LL /* Register access error */
#define CXR_ILFC 0000400000000LL /* Illegal CXR function code */
#define B22_FLAG 0004000000000LL /* 22 bit channel */
#define CC_CHAN_PLS 0010000000000LL /* Channel transfer pulse (not implemented) */
#define CC_CHAN_ACT 0020000000000LL /* Channel in use */
#define CC_INH 0040000000000LL /* Disconnect channel */
#define CB_FULL 0200000000000LL /* Set when channel buffer is full (not implemented) */
#define AR_FULL 0400000000000LL /* Set when AR is full (not implemented) */
/* RH20 CONI Flags */
#define RH20_PCR_FULL 0000000000020LL /* Primary command file full */
#define RH20_ATTN_ENA 0000000000040LL /* Attention enable */
#define RH20_SCR_FULL 0000000000100LL /* Secondary command full */
#define RH20_ATTN 0000000000200LL /* Attention */
#define RH20_MASS_ENA 0000000000400LL /* Mass bus enable */
#define RH20_DATA_OVR 0000000001000LL /* Data overrun */
#define RH20_CHAN_RDY 0000000002000LL /* Channel ready to start */
#define RH20_RAE 0000000004000LL /* Register access error */
#define RH20_DR_RESP 0000000010000LL /* Drive no response */
#define RH20_CHAN_ERR 0000000020000LL /* Channel error */
#define RH20_SHRT_WC 0000000040000LL /* Short word count */
#define RH20_LONG_WC 0000000100000LL /* Long word count */
#define RH20_DR_EXC 0000000200000LL /* Exception */
#define RH20_DATA_PRI 0000000400000LL /* Data parity error */
#define RH20_SBAR 0000001000000LL /* SBAR set */
#define RH20_XEND 0000002000000LL /* Transfer ended */
/* CONO Flags */
#define ATTN_EN 0000000000040LL /* enable attention interrupt. */
#define REA_EN 0000000000100LL /* enable register error interrupt */
#define CBOV_CLR 0000000000200LL /* Clear CBOV */
#define CONT_RESET 0000000002000LL /* Clear All error bits */
#define ILC_CLR 0000000004000LL /* Clear ILC and SD RAE */
#define DRE_CLR 0000000010000LL /* Clear CR_CBTO and CR_DBTO */
#define OVER_CLR 0000000020000LL /* Clear DTC overrun */
#define WRT_CW 0000000040000LL /* Write control word */
#define CHN_CLR 0000000100000LL /* Clear Channel Error */
#define DR_EXC_CLR 0000000200000LL /* Clear DR_EXC */
#define DBPE_CLR 0000000400000LL /* Clear CXR_DBPE */
/* RH20 CONO Flags */
#define RH20_DELETE_SCR 0000000000100LL /* Clear SCR */
#define RH20_RCLP 0000000000200LL /* Reset command list */
#define RH20_MASS_EN 0000000000400LL /* Mass bus enable */
#define RH20_XFER_CLR 0000000001000LL /* Clear XFER error */
#define RH20_CLR_MBC 0000000002000LL /* Clear MBC */
#define RH20_CLR_RAE 0000000004000LL /* Clear RAE error */
/* DATAO/DATAI */
#define CR_REG 0770000000000LL /* Register number */
#define LOAD_REG 0004000000000LL /* Load register */
#define CR_MAINT_MODE 0000100000000LL /* Maint mode... not implemented */
#define CR_DRIVE 0000007000000LL
#define CR_GEN_EVD 0000000400000LL /* Enable Parity */
#define CR_DXES 0000000200000LL /* Disable DXES errors */
#define CR_INAD 0000000077600LL
#define CR_WTEVM 0000000000100LL /* Verify Parity */
#define CR_FUNC 0000000000076LL
#define CR_GO 0000000000001LL
#define IRQ_VECT 0000000000777LL /* Interupt vector */
#define IRQ_KI10 0000002000000LL
#define IRQ_KA10 0000001000000LL
#define FNC_XFER 024 /* >=? data xfr */
/* Status register settings */
#define DS_OFF 0000001 /* offset mode */
#define DS_VV 0000100 /* volume valid */
#define DS_DRY 0000200 /* drive ready */
#define DS_DPR 0000400 /* drive present */
#define DS_PGM 0001000 /* programable NI */
#define DS_LST 0002000 /* last sector */
#define DS_WRL 0004000 /* write locked */
#define DS_MOL 0010000 /* medium online */
#define DS_PIP 0020000 /* pos in progress */
#define DS_ERR 0040000 /* error */
#define DS_ATA 0100000 /* attention active */
/* RH20 channel status flags */
#define RH20_MEM_PAR 00200000000000LL /* Memory parity error */
#define RH20_NADR_PAR 00100000000000LL /* Address parity error */
#define RH20_NOT_WC0 00040000000000LL /* Word count not zero */
#define RH20_NXM_ERR 00020000000000LL /* Non existent memory */
#define RH20_LAST_ERR 00000400000000LL /* Last transfer error */
#define RH20_ERROR 00000200000000LL /* RH20 error */
#define RH20_LONG_STS 00000100000000LL /* Did not reach wc */
#define RH20_SHRT_STS 00000040000000LL /* WC reached zero */
#define RH20_OVER 00000020000000LL /* Overrun error */
/* 0-37 mass bus register.
70 SBAR, block address.
71 STCR, neg block count, func
72 PBAR
73 PTCR
74 IVIR Interrupt vector address.
75 Diags read.
76 Diags write.
77 Status (tra,cb test, bar test, ev par, r/w, exc,ebl, 0, attn, sclk
*/
/*
* CCW 000..... New channel comand list pointer HALT.
010..... Next CCW Address JUMP
1xycount-address. x=halt last xfer, y=reverse
*/
extern uint32 eb_ptr;
t_stat
rh_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
DEVICE *dptr;
DIB *dibp;
dptr = find_dev_from_unit (uptr);
if (dptr == NULL)
return SCPE_IERR;
dibp = (DIB *) dptr->ctxt;
dptr->flags &= ~DEV_M_RH;
dptr->flags |= val;
dibp->dev_num &= ~(RH10_DEV|RH20_DEV);
dibp->dev_num |= (val) ? RH20_DEV: RH10_DEV;
return SCPE_OK;
}
t_stat rh_show_type (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 & TYPE_RH20) ? "RH20" : "RH10");
return SCPE_OK;
}
t_stat rh_devio(uint32 dev, uint64 *data) {
DEVICE *dptr = NULL;
struct rh_if *rhc = NULL;
int drive;
for (drive = 0; rh[drive].dev_num != 0; drive++) {
if (rh[drive].dev_num == (dev & 0774)) {
rhc = rh[drive].rh;
dptr = rh[drive].dev;
break;
}
}
if (rhc == NULL)
return SCPE_OK;
#if KL
if (dptr->flags & TYPE_RH20) {
switch(dev & 3) {
case CONI:
*data = rhc->status & RMASK;
if (rhc->attn != 0)
*data |= RH20_ATTN;
if (rhc->rae != 0)
*data |= RH20_RAE;
sim_debug(DEBUG_CONI, dptr, "%s %03o CONI %06o PC=%o %o\n",
dptr->name, dev, (uint32)*data, PC, rhc->attn);
return SCPE_OK;
case CONO:
clr_interrupt(dev);
/* Clear flags */
if (*data & RH20_CLR_MBC) {
if (rhc->dev_reset != NULL)
rhc->dev_reset(dptr);
rhc->attn = 0;
rhc->imode = 2;
}
rhc->status &= ~(07LL|IADR_ATTN|RH20_MASS_EN);
rhc->status |= *data & (07LL|IADR_ATTN|RH20_MASS_EN);
if (*data & RH20_DELETE_SCR)
rhc->status &= ~(RH20_SBAR|RH20_SCR_FULL);
if (*data & (RH20_RCLP|RH20_CLR_MBC))
rhc->cia = eb_ptr | (rhc->devnum - 0540);
if (*data & (RH20_CLR_RAE|RH20_CLR_MBC))
rhc->rae = 0;
if (*data & PI_ENABLE)
rhc->status &= ~PI_ENABLE;
if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0)
|| (rhc->status & PI_ENABLE))
set_interrupt(rhc->devnum, rhc->status);
sim_debug(DEBUG_CONO, dptr, "%s %03o CONO %06o PC=%06o %06o\n",
dptr->name, dev, (uint32)*data, PC, rhc->status);
return SCPE_OK;
case DATAI:
*data = 0;
if (rhc->status & BUSY && rhc->reg != 04) {
rhc->status |= CC_CHAN_ACT;
return SCPE_OK;
}
if (rhc->reg < 040) {
int parity;
*data = (uint64)(rhc->dev_read(dptr, rhc, rhc->reg) & 0177777);
parity = (int)((*data >> 8) ^ *data);
parity = (parity >> 4) ^ parity;
parity = (parity >> 2) ^ parity;
parity = ((parity >> 1) ^ parity) & 1;
*data |= ((uint64)(!parity)) << 16;
*data |= ((uint64)(rhc->drive)) << 18;
*data |= BIT10;
} else if ((rhc->reg & 070) != 070) {
rhc->rae = 1;
break;
} else {
switch(rhc->reg & 07) {
case 0: *data = rhc->sbar; break;
case 1: *data = rhc->stcr; break;
case 2: *data = rhc->pbar; break;
case 3: *data = rhc->ptcr; break;
case 4: *data = rhc->ivect; break;
case 5:
case 6: break;
case 7: *data = 0; break;
}
}
*data |= ((uint64)(rhc->reg)) << 30;
sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATI %012llo %d PC=%06o\n",
dptr->name, dev, *data, rhc->drive, PC);
return SCPE_OK;
case DATAO:
sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATO %012llo PC=%06o %06o\n",
dptr->name, dev, *data, PC, rhc->status);
rhc->reg = ((int)(*data >> 30)) & 077;
rhc->imode |= 2;
if (rhc->reg < 040)
rhc->drive = (int)(*data >> 18) & 07;
if (*data & LOAD_REG) {
if (rhc->reg < 040) {
clr_interrupt(dev);
/* Check if access error */
if (rhc->rae & (1 << rhc->drive) && (*data & BIT9) == 0) {
set_interrupt(rhc->devnum, rhc->status);
return SCPE_OK;
}
rhc->dev_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777));
if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0)
|| (rhc->status & PI_ENABLE))
set_interrupt(rhc->devnum, rhc->status);
/* Check if access error */
if (rhc->rae & (1 << rhc->drive) && (*data & BIT9) == 0)
set_interrupt(rhc->devnum, rhc->status);
else
rhc->rae &= ~(1 << rhc->drive);
} else if ((rhc->reg & 070) != 070) {
if ((*data & BIT9) == 0) {
rhc->rae = (1 << rhc->drive);
set_interrupt(rhc->devnum, rhc->status);
}
} else {
switch(rhc->reg & 07) {
case 0:
rhc->sbar = (*data) & (CR_DRIVE|RMASK);
rhc->status |= RH20_SBAR;
break;
case 1:
rhc->stcr = (*data) & (BIT10|BIT7|CR_DRIVE|RMASK);
rhc->status |= RH20_SCR_FULL;
break;
case 4:
rhc->ivect = (*data & IRQ_VECT);
break;
case 2:
case 3:
case 5:
case 6:
case 7:
break;
}
}
}
}
if ((rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL))
rh20_setup(rhc);
return SCPE_OK;
}
#endif
switch(dev & 3) {
case CONI:
*data = rhc->status & ~(IADR_ATTN|IARD_RAE);
if (rhc->attn != 0 && (rhc->status & IADR_ATTN))
*data |= IADR_ATTN;
if (rhc->rae != 0 && (rhc->status & IARD_RAE))
*data |= IARD_RAE;
#if KI_22BIT
*data |= B22_FLAG;
#endif
sim_debug(DEBUG_CONI, dptr, "%s %03o CONI %06o PC=%o %o\n",
dptr->name, dev, (uint32)*data, PC, rhc->attn);
return SCPE_OK;
case CONO:
clr_interrupt(dev);
rhc->status &= ~(07LL|IADR_ATTN|IARD_RAE);
rhc->status |= *data & (07LL|IADR_ATTN|IARD_RAE);
/* Clear flags */
if (*data & CONT_RESET && rhc->dev_reset != NULL)
rhc->dev_reset(dptr);
if (*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR))
rhc->status &= ~(*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR));
if (*data & OVER_CLR)
rhc->status &= ~(DTC_OVER);
if (*data & CBOV_CLR)
rhc->status &= ~(DIB_CBOV);
if (*data & CXR_ILC)
rhc->status &= ~(CXR_ILFC|CXR_SD_RAE);
if (*data & WRT_CW)
rh_writecw(rhc, 0);
if (*data & PI_ENABLE)
rhc->status &= ~PI_ENABLE;
if (rhc->status & PI_ENABLE)
set_interrupt(dev, rhc->status);
if ((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0)
set_interrupt(dev, rhc->status);
sim_debug(DEBUG_CONO, dptr, "%s %03o CONO %06o PC=%06o %06o\n",
dptr->name, dev, (uint32)*data, PC, rhc->status);
return SCPE_OK;
case DATAI:
*data = 0;
if (rhc->status & BUSY && rhc->reg != 04) {
rhc->status |= CC_CHAN_ACT;
return SCPE_OK;
}
if (rhc->reg == 040) {
*data = (uint64)(rhc->dev_read(dptr, rhc, 0) & 077);
*data |= ((uint64)(rhc->cia)) << 6;
*data |= ((uint64)(rhc->xfer_drive)) << 18;
} else if (rhc->reg == 044) {
*data = (uint64)rhc->ivect;
if (rhc->imode)
*data |= IRQ_KI10;
else
*data |= IRQ_KA10;
} else if (rhc->reg == 054) {
*data = (uint64)(rhc->rae);
} else if ((rhc->reg & 040) == 0) {
int parity;
*data = (uint64)(rhc->dev_read(dptr, rhc, rhc->reg) & 0177777);
parity = (int)((*data >> 8) ^ *data);
parity = (parity >> 4) ^ parity;
parity = (parity >> 2) ^ parity;
parity = ((parity >> 1) ^ parity) & 1;
*data |= ((uint64)(parity ^ 1)) << 17;
*data |= ((uint64)(rhc->drive)) << 18;
}
*data |= ((uint64)(rhc->reg)) << 30;
sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATI %012llo %d PC=%06o\n",
dptr->name, dev, *data, rhc->drive, PC);
return SCPE_OK;
case DATAO:
sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATO %012llo PC=%06o %06o\n",
dptr->name, dev, *data, PC, rhc->status);
rhc->reg = ((int)(*data >> 30)) & 077;
rhc->imode &= ~2;
if (rhc->reg < 040 && rhc->reg != 04) {
rhc->drive = (int)(*data >> 18) & 07;
}
if (*data & LOAD_REG) {
if (rhc->reg == 040) {
if ((*data & 1) == 0) {
return SCPE_OK;
}
if (rhc->status & BUSY) {
rhc->status |= CC_CHAN_ACT;
return SCPE_OK;
}
rhc->status &= ~(CCW_COMP_1|PI_ENABLE);
if (((*data >> 1) & 037) < FNC_XFER) {
rhc->status |= CXR_ILC;
rh_setirq(rhc);
sim_debug(DEBUG_DATAIO, dptr,
"%s %03o command abort %012llo, %d PC=%06o %06o\n",
dptr->name, dev, *data, rhc->drive, PC, rhc->status);
return SCPE_OK;
}
/* Check if access error */
if (rhc->rae & (1 << rhc->drive))
return SCPE_OK;
/* Start command */
rh_setup(rhc, (uint32)(*data >> 6));
rhc->xfer_drive = (int)(*data >> 18) & 07;
rhc->dev_write(dptr, rhc, 0, (uint32)(*data & 077));
sim_debug(DEBUG_DATAIO, dptr,
"%s %03o command %012llo, %d PC=%06o %06o\n",
dptr->name, dev, *data, rhc->drive, PC, rhc->status);
} else if (rhc->reg == 044) {
/* Set KI10 Irq vector */
rhc->ivect = (int)(*data & IRQ_VECT);
rhc->imode = (*data & IRQ_KI10) != 0;
} else if (rhc->reg == 050) {
; /* Diagnostic access to mass bus. */
} else if (rhc->reg == 054) {
/* clear flags */
rhc->rae &= ~(*data & 0377);
if (rhc->rae == 0)
clr_interrupt(dev);
} else if ((rhc->reg & 040) == 0) {
rhc->drive = (int)(*data >> 18) & 07;
/* Check if access error */
if (rhc->rae & (1 << rhc->drive)) {
return SCPE_OK;
}
rhc->dev_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777));
}
}
clr_interrupt(dev);
if (((rhc->status & (IADR_ATTN|BUSY)) == IADR_ATTN && rhc->attn != 0)
|| (rhc->status & PI_ENABLE))
set_interrupt(rhc->devnum, rhc->status);
return SCPE_OK;
}
return SCPE_OK; /* Unreached */
}
/* Handle KI and KL style interrupt vectors */
t_addr
rh_devirq(uint32 dev, t_addr addr) {
DEVICE *dptr = NULL;
struct rh_if *rhc = NULL;
int drive;
for (drive = 0; rh[drive].dev_num != 0; drive++) {
if (rh[drive].dev_num == (dev & 0774)) {
rhc = rh[drive].rh;
break;
}
}
if (rhc != NULL) {
if (rhc->imode == 1) /* KI10 Style */
addr = RSIGN | rhc->ivect;
else if (rhc->imode == 2) /* RH20 style */
addr = rhc->ivect;
}
return addr;
}
/* Set the attention flag for a unit */
void rh_setattn(struct rh_if *rhc, int unit)
{
rhc->attn |= 1<<unit;
if ((rhc->status & BUSY) == 0 && (rhc->status & IADR_ATTN) != 0)
set_interrupt(rhc->devnum, rhc->status);
}
void rh_error(struct rh_if *rhc)
{
if (rhc->imode == 2)
rhc->status |= RH20_DR_EXC;
}
/* Decrement block count for RH20, nop for RH10 */
int rh_blkend(struct rh_if *rhc)
{
#if KL
if (rhc->imode == 2) {
//fprintf(stderr, "RH blkend %o\n\r", rhc->cia);
rhc->cia = (rhc->cia + 1) & 01777;
if (rhc->cia == 0) {
rhc->status |= RH20_XEND;
return 1;
}
}
#endif
return 0;
}
/* Set an IRQ for a DF10 device */
void rh_setirq(struct rh_if *rhc) {
rhc->status |= PI_ENABLE;
set_interrupt(rhc->devnum, rhc->status);
}
/* Generate the DF10 complete word */
void rh_writecw(struct rh_if *rhc, int nxm) {
uint64 wrd1;
#if KL
if (rhc->imode == 2) {
uint32 chan = (rhc->devnum - 0540);
int wc = ((rhc->wcr ^ RH20_WMASK) + 1) & RH20_WMASK;
rhc->status |= RH20_CHAN_RDY;
rhc->status &= ~(RH20_PCR_FULL);
if (wc != 0 || (rhc->status & RH20_XEND) == 0 ||
(rhc->ptcr & BIT10) != 0 || nxm) {
uint64 wrd2;
wrd1 = SMASK|(uint64)(rhc->ccw);
if ((rhc->ptcr & BIT10) == 0 || (rhc->status & RH20_DR_EXC) != 0)
return;
if (nxm) {
wrd1 |= RH20_NXM_ERR;
rhc->status |= RH20_CHAN_ERR;
}
if (wc != 0) {
wrd1 |= RH20_NOT_WC0;
if (rhc->status & RH20_XEND) {
wrd1 |= RH20_LONG_STS;
if ((rhc->ptcr & 070) == 060) { /* Write command */
rhc->status |= RH20_LONG_WC|RH20_CHAN_ERR;
}
}
} else if ((rhc->status & RH20_XEND) == 0) {
wrd1 |= RH20_SHRT_STS;
if ((rhc->ptcr & 070) == 060) { /* Write command */
rhc->status |= RH20_SHRT_WC|RH20_CHAN_ERR;
}
}
/* No error and not storing */
if ((rhc->status & RH20_CHAN_ERR) == 0 && (rhc->ptcr & BIT10) == 0)
return;
wrd1 |= RH20_NADR_PAR;
wrd2 = ((uint64)rhc->cop << 33) | (((uint64)wc) << CSHIFT) |
((uint64)(rhc->cda) & AMASK);
(void)Mem_write_word(chan+1, &wrd1, 1);
(void)Mem_write_word(chan+2, &wrd2, 1);
//fprintf(stderr, "RH20 final %012llo %012llo %06o\n\r", wrd1, wrd2, wc);
}
return;
}
#endif
if (nxm)
rhc->status |= CXR_NXM;
rhc->status |= CCW_COMP_1;
if (rhc->wcr != 0)
rhc->cda++;
wrd1 = ((uint64)(rhc->ccw & WMASK) << CSHIFT) | ((uint64)(rhc->cda) & AMASK);
(void)Mem_write_word(rhc->cia|1, &wrd1, 0);
}
/* Finish off a DF10 transfer */
void rh_finish_op(struct rh_if *rhc, int nxm) {
#if KL
if (rhc->imode != 2)
#endif
rhc->status &= ~BUSY;
rh_writecw(rhc, nxm);
rh_setirq(rhc);
#if KL
if (rhc->imode == 2 &&
(rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL) &&
(rhc->status & (RH20_DR_EXC|RH20_CHAN_ERR)) == 0)
rh20_setup(rhc);
#endif
}
#if KL
/* Set up for a RH20 transfer */
void rh20_setup(struct rh_if *rhc)
{
DEVICE *dptr = NULL;
int reg;
for (reg = 0; rh[reg].dev_num != 0; reg++) {
if (rh[reg].rh == rhc) {
dptr = rh[reg].dev;
break;
}
}
if (dptr == 0)
return;
rhc->pbar = rhc->sbar;
rhc->ptcr = rhc->stcr;
/* Read drive status */
rhc->drive = (rhc->ptcr >> 18) & 07;
rhc->status &= ~(RH20_DATA_OVR|RH20_CHAN_RDY|RH20_DR_RESP|RH20_CHAN_ERR|RH20_SHRT_WC|\
RH20_LONG_WC|RH20_DR_EXC|RH20_SCR_FULL|PI_ENABLE|RH20_XEND);
rhc->status |= RH20_PCR_FULL;
if (rhc->status & RH20_SBAR) {
rhc->drive = (rhc->pbar >> 18) & 07;
if (rhc->dev_write != NULL)
rhc->dev_write(dptr, rhc, 5, (rhc->pbar & 0177777));
rhc->status &= ~RH20_SBAR;
}
if (rhc->ptcr & BIT7) { /* If RCPL reset I/O pointers */
rhc->ccw = eb_ptr + (rhc->devnum - 0540);
rhc->wcr = 0;
}
/* Hold block count in cia */
rhc->drive = (rhc->ptcr >> 18) & 07;
rhc->cia = (rhc->ptcr >> 6) & 01777;
if (rhc->dev_write != NULL)
rhc->dev_write(dptr, rhc, 0, (rhc->ptcr & 077));
rhc->cop = 0;
rhc->wcr = 0;
rhc->status &= ~RH20_CHAN_RDY;
//fprintf(stderr, "RH setup %06o %06o %o\n\r", rhc->ptcr, rhc->ccw, rhc->cia);
}
#endif
/* Setup for a DF10 transfer */
void rh_setup(struct rh_if *rhc, uint32 addr)
{
rhc->cia = addr & ICWA;
rhc->ccw = rhc->cia;
rhc->wcr = 0;
rhc->status |= BUSY;
}
/* Fetch the next IO control word */
int rh_fetch(struct rh_if *rhc) {
uint64 data;
int reg;
DEVICE *dptr = NULL;
for (reg = 0; rh[reg].dev_num != 0; reg++) {
if (rh[reg].rh == rhc) {
dptr = rh[reg].dev;
break;
}
}
#if KL
if (rhc->imode == 2 && (rhc->cop & 2) != 0) {
return 0;
}
#endif
if (Mem_read_word(rhc->ccw, &data, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
sim_debug(DEBUG_EXP, dptr, "%s fetch %06o %012llo\n\r", dptr->name, rhc->ccw, data);
#if KL
if (rhc->imode == 2) {
while((data & RH20_XFER) == 0) {
rhc->ccw = (uint32)(data & AMASK);
if ((data & (BIT1|BIT2)) == 0) {
return 0;
}
if (Mem_read_word(rhc->ccw, &data, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
sim_debug(DEBUG_EXP, dptr, "%s fetch2 %06o %012llo\n\r", dptr->name, rhc->ccw, data);
//fprintf(stderr, "RH20 fetch2 %06o %012llo\n\r", rhc->ccw, data);
}
rhc->wcr = (((data >> CSHIFT) & RH20_WMASK) ^ WMASK) + 1;
rhc->cda = (data & AMASK);
rhc->cop = (data >> 33) & 07;
rhc->ccw = (uint32)((rhc->ccw + 1) & AMASK);
return 1;
}
#endif
while((data & (WMASK << CSHIFT)) == 0) {
if ((data & AMASK) == 0 || (uint32)(data & AMASK) == rhc->ccw) {
rh_finish_op(rhc, 0);
return 0;
}
rhc->ccw = (uint32)(data & AMASK);
if (Mem_read_word(rhc->ccw, &data, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
sim_debug(DEBUG_EXP, dptr, "%s fetch2 %06o %012llo\n\r", dptr->name, rhc->ccw, data);
}
rhc->wcr = (uint32)((data >> CSHIFT) & WMASK);
rhc->cda = (uint32)(data & AMASK);
rhc->ccw = (uint32)((rhc->ccw + 1) & AMASK);
return 1;
}
/* Read next word */
int rh_read(struct rh_if *rhc) {
uint64 data;
if (rhc->wcr == 0) {
if (!rh_fetch(rhc))
return 0;
}
rhc->wcr = (uint32)((rhc->wcr + 1) & WMASK);
if (rhc->cda != 0) {
if (rhc->cda > MEMSIZE) {
rh_finish_op(rhc, 1);
return 0;
}
#if KL
if (rhc->imode == 2) {
if (Mem_read_word(rhc->cda, &data, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
if (rhc->cop & 01)
rhc->cda = (uint32)((rhc->cda - 1) & AMASK);
else
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
} else {
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
if (Mem_read_word(rhc->cda, &data, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
}
#else
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
if (Mem_read_word(rhc->cda, &data, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
#endif
} else {
data = 0;
}
rhc->buf = data;
if (rhc->wcr == 0) {
return rh_fetch(rhc);
}
return 1;
}
/* Write next word */
int rh_write(struct rh_if *rhc) {
if (rhc->wcr == 0) {
if (!rh_fetch(rhc))
return 0;
}
rhc->wcr = (uint32)((rhc->wcr + 1) & WMASK);
if (rhc->cda != 0) {
if (rhc->cda > MEMSIZE) {
rh_finish_op(rhc, 1);
return 0;
}
#if KL
if (rhc->imode == 2) {
if (Mem_write_word(rhc->cda, &rhc->buf, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
if (rhc->cop & 01)
rhc->cda = (uint32)((rhc->cda - 1) & AMASK);
else
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
} else {
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
if (Mem_write_word(rhc->cda, &rhc->buf, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
}
#else
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
if (Mem_write_word(rhc->cda, &rhc->buf, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
#endif
}
if (rhc->wcr == 0) {
return rh_fetch(rhc);
}
return 1;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* ka10_rs.c: Dec RH10 RS04
Copyright (c) 2017, Richard Cornwell
Copyright (c) 2017-2019, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -28,6 +28,8 @@
#endif
#if (NUM_DEVS_RS > 0)
#define BUF_EMPTY(u) (u->hwmark == 0xFFFFFFFF)
#define CLR_BUF(u) u->hwmark = 0xFFFFFFFF
#define RS_NUMWD 128 /* 36bit words/sec */
#define NUM_UNITS_RS 8
@@ -42,72 +44,14 @@
#define DTYPE(x) (((x) & UNIT_M_DTYPE) << UNIT_V_DTYPE)
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
#define CNTRL_V_CTYPE (UNIT_V_UF + 4)
#define CNTRL_M_CTYPE 7
#define GET_CNTRL(x) (((x) >> CNTRL_V_CTYPE) & CNTRL_M_CTYPE)
#define CNTRL(x) (((x) & CNTRL_M_CTYPE) << CNTRL_V_CTYPE)
/* Parameters in the unit descriptor */
/* CONI Flags */
#define IADR_ATTN 0000000000040LL /* Interrupt on attention */
#define IARD_RAE 0000000000100LL /* Interrupt on register access error */
#define DIB_CBOV 0000000000200LL /* Control bus overrun */
#define CXR_PS_FAIL 0000000002000LL /* Power supply fail (not implemented) */
#define CXR_ILC 0000000004000LL /* Illegal function code */
#define CR_DRE 0000000010000LL /* Or Data and Control Timeout */
#define DTC_OVER 0000000020000LL /* DF10 did not supply word on time (not implemented) */
#define CCW_COMP_1 0000000040000LL /* Control word written. */
#define CXR_CHAN_ER 0000000100000LL /* Channel Error */
#define CXR_EXC 0000000200000LL /* Error in drive transfer */
#define CXR_DBPE 0000000400000LL /* Device Parity error (not implemented) */
#define CXR_NXM 0000001000000LL /* Channel non-existent memory (not implemented) */
#define CXR_CWPE 0000002000000LL /* Channel Control word parity error (not implemented) */
#define CXR_CDPE 0000004000000LL /* Channel Data Parity Error (not implemented) */
#define CXR_SD_RAE 0000200000000LL /* Register access error */
#define CXR_ILFC 0000400000000LL /* Illegal CXR function code */
#define B22_FLAG 0004000000000LL /* 22 bit channel */
#define CC_CHAN_PLS 0010000000000LL /* Channel transfer pulse (not implemented) */
#define CC_CHAN_ACT 0020000000000LL /* Channel in use */
#define CC_INH 0040000000000LL /* Disconnect channel */
#define CB_FULL 0200000000000LL /* Set when channel buffer is full (not implemented) */
#define AR_FULL 0400000000000LL /* Set when AR is full (not implemented) */
/* CONO Flags */
#define ATTN_EN 0000000000040LL /* enable attention interrupt. */
#define REA_EN 0000000000100LL /* enable register error interrupt */
#define CBOV_CLR 0000000000200LL /* Clear CBOV */
#define CONT_RESET 0000000002000LL /* Clear All error bits */
#define ILC_CLR 0000000004000LL /* Clear ILC and SD RAE */
#define DRE_CLR 0000000010000LL /* Clear CR_CBTO and CR_DBTO */
#define OVER_CLR 0000000020000LL /* Clear DTC overrun */
#define WRT_CW 0000000040000LL /* Write control word */
#define CHN_CLR 0000000100000LL /* Clear Channel Error */
#define DR_EXC_CLR 0000000200000LL /* Clear DR_EXC */
#define DBPE_CLR 0000000400000LL /* Clear CXR_DBPE */
/* DATAO/DATAI */
#define CR_REG 0770000000000LL /* Register number */
#define LOAD_REG 0004000000000LL /* Load register */
#define CR_MAINT_MODE 0000100000000LL /* Maint mode... not implemented */
#define CR_DRIVE 0000007000000LL
#define CR_GEN_EVD 0000000400000LL /* Enable Parity */
#define CR_DXES 0000000200000LL /* Disable DXES errors */
#define CR_INAD 0000000077600LL
#define CR_WTEVM 0000000000100LL /* Verify Parity */
#define CR_FUNC 0000000000076LL
#define CR_GO 0000000000001LL
#define IRQ_VECT 0000000000177LL /* Interupt vector */
#define IRQ_KI10 0000002000000LL
#define IRQ_KA10 0000001000000LL
#define CMD u3
/* u3 low */
/* RSC - 00 - control */
#define CS1_GO CR_GO /* go */
#define CS1_GO 1 /* go */
#define CS1_V_FNC 1 /* function pos */
#define CS1_M_FNC 037 /* function mask */
#define CS1_FNC (CS1_M_FNC << CS1_V_FNC)
@@ -228,21 +172,10 @@ struct drvtyp rs_drv_tab[] = {
};
struct df10 rs_df10[NUM_DEVS_RS];
uint32 rs_xfer_drive[NUM_DEVS_RS];
uint64 rs_buf[NUM_DEVS_RS][RS_NUMWD];
int rs_reg[NUM_DEVS_RS];
int rs_ivect[NUM_DEVS_RS];
int rs_imode[NUM_DEVS_RS];
int rs_drive[NUM_DEVS_RS];
int rs_rae[NUM_DEVS_RS];
int rs_attn[NUM_DEVS_RS];
extern int readin_flag;
t_stat rs_devio(uint32 dev, uint64 *data);
int rs_devirq(uint32 dev, int addr);
void rs_write(int ctlr, int unit, int reg, uint32 data);
uint32 rs_read(int ctlr, int unit, int reg);
void rs_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data);
uint32 rs_read(DEVICE *dptr, struct rh_if *rhc, int reg);
void rs_rst(DEVICE *dptr);
t_stat rs_svc(UNIT *);
t_stat rs_boot(int32, DEVICE *);
void rs_ini(UNIT *, t_bool);
@@ -258,28 +191,38 @@ const char *rs_description (DEVICE *dptr);
UNIT rs_unit[] = {
/* Controller 1 */
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
};
struct rh_if rs_rh[] = {
{ &rs_write, &rs_read, &rs_rst},
};
DIB rs_dib[] = {
{RH10_DEV, 1, &rs_devio, &rs_devirq}
{RH10_DEV, 1, &rh_devio, &rh_devirq, &rs_rh[0]}
};
MTAB rs_mod[] = {
#if KL
{MTAB_XTD|MTAB_VDV, TYPE_RH10, NULL, "RH10", &rh_set_type, NULL,
NULL, "Sets controller to RH10" },
{MTAB_XTD|MTAB_VDV, TYPE_RH20, "RH20", "RH20", &rh_set_type, &rh_show_type,
NULL, "Sets controller to RH20"},
#endif
{UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL},
{UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL},
{UNIT_DTYPE, (RS03_DTYPE << UNIT_V_DTYPE), "RS03", "RS03", &rs_set_type },
@@ -288,23 +231,20 @@ MTAB rs_mod[] = {
};
REG rsa_reg[] = {
{ORDATA(IVECT, rs_ivect[0], 18)},
{FLDATA(IMODE, rs_imode[0], 0)},
{ORDATA(XFER, rs_xfer_drive[0], 3), REG_HRO},
{ORDATA(DRIVE, rs_drive[0], 3), REG_HRO},
{ORDATA(REG, rs_reg[0], 6), REG_RO},
{ORDATA(RAE, rs_rae[0], 8), REG_RO},
{ORDATA(ATTN, rs_attn[0], 8), REG_RO},
{FLDATA(READIN, readin_flag, 0), REG_HRO},
{ORDATA(STATUS, rs_df10[0].status, 18), REG_RO},
{ORDATA(CIA, rs_df10[0].cia, 18)},
{ORDATA(CCW, rs_df10[0].ccw, 18)},
{ORDATA(WCR, rs_df10[0].wcr, 18)},
{ORDATA(CDA, rs_df10[0].cda, 18)},
{ORDATA(DEVNUM, rs_df10[0].devnum, 9), REG_HRO},
{ORDATA(BUF, rs_df10[0].buf, 36), REG_HRO},
{ORDATA(NXM, rs_df10[0].nxmerr, 8), REG_HRO},
{ORDATA(COMP, rs_df10[0].ccw_comp, 8), REG_HRO},
{ORDATA(IVECT, rs_rh[0].ivect, 18)},
{FLDATA(IMODE, rs_rh[0].imode, 0)},
{ORDATA(XFER, rs_rh[0].xfer_drive, 3), REG_HRO},
{ORDATA(DRIVE, rs_rh[0].drive, 3), REG_HRO},
{ORDATA(REG, rs_rh[0].reg, 6), REG_RO},
{ORDATA(RAE, rs_rh[0].rae, 8), REG_RO},
{ORDATA(ATTN, rs_rh[0].attn, 8), REG_RO},
{ORDATA(STATUS, rs_rh[0].status, 18), REG_RO},
{ORDATA(CIA, rs_rh[0].cia, 18)},
{ORDATA(CCW, rs_rh[0].ccw, 18)},
{ORDATA(WCR, rs_rh[0].wcr, 18)},
{ORDATA(CDA, rs_rh[0].cda, 18)},
{ORDATA(DEVNUM, rs_rh[0].devnum, 9), REG_HRO},
{ORDATA(BUF, rs_rh[0].buf, 36), REG_HRO},
{BRDATA(BUFF, &rs_buf[0][0], 16, 64, RS_NUMWD), REG_HRO},
{0}
};
@@ -322,213 +262,44 @@ DEVICE *rs_devs[] = {
};
t_stat rs_devio(uint32 dev, uint64 *data) {
int ctlr = -1;
DEVICE *dptr = NULL;
struct df10 *df10;
int drive;
for (drive = 0; rh[drive].dev_num != 0; drive++) {
if (rh[drive].dev_num == (dev & 0774)) {
dptr = rh[drive].dev;
break;
}
}
if (dptr == NULL)
return SCPE_OK;
ctlr = GET_CNTRL(dptr->units[0].flags);
df10 = &rs_df10[ctlr];
df10->devnum = dev;
switch(dev & 3) {
case CONI:
*data = df10->status & ~(IADR_ATTN|IARD_RAE);
if (rs_attn[ctlr] != 0 && (df10->status & IADR_ATTN))
*data |= IADR_ATTN;
if (rs_rae[ctlr] != 0 && (df10->status & IARD_RAE))
*data |= IARD_RAE;
#if KI_22BIT
*data |= B22_FLAG;
#endif
sim_debug(DEBUG_CONI, dptr, "RS %03o CONI %06o PC=%o %o\n",
dev, (uint32)*data, PC, rs_attn[ctlr]);
return SCPE_OK;
case CONO:
clr_interrupt(dev);
df10->status &= ~(07LL|IADR_ATTN|IARD_RAE);
df10->status |= *data & (07LL|IADR_ATTN|IARD_RAE);
/* Clear flags */
if (*data & CONT_RESET) {
UNIT *uptr=dptr->units;
for(drive = 0; drive < NUM_UNITS_RS; drive++, uptr++) {
uptr->CMD &= DS_MOL|DS_WRL|DS_DPR|DS_DRY|DS_VV|076;
uptr->DA &= 003400177777;
}
}
if (*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR))
df10->status &= ~(*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR));
if (*data & OVER_CLR)
df10->status &= ~(DTC_OVER);
if (*data & CBOV_CLR)
df10->status &= ~(DIB_CBOV);
if (*data & CXR_ILC)
df10->status &= ~(CXR_ILFC|CXR_SD_RAE);
if (*data & WRT_CW)
df10_writecw(df10);
if (*data & PI_ENABLE)
df10->status &= ~PI_ENABLE;
if (df10->status & PI_ENABLE)
set_interrupt(dev, df10->status);
if ((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0)
set_interrupt(dev, df10->status);
sim_debug(DEBUG_CONO, dptr, "RS %03o CONO %06o %d PC=%06o %06o\n",
dev, (uint32)*data, ctlr, PC, df10->status);
return SCPE_OK;
case DATAI:
*data = 0;
if (df10->status & BUSY && rs_reg[ctlr] != 04) {
df10->status |= CC_CHAN_ACT;
return SCPE_OK;
}
if (rs_reg[ctlr] == 040) {
*data = (uint64)(rs_read(ctlr, rs_drive[ctlr], 0) & 077);
*data |= ((uint64)(df10->cia)) << 6;
*data |= ((uint64)(rs_xfer_drive[ctlr])) << 18;
} else if (rs_reg[ctlr] == 044) {
*data = (uint64)rs_ivect[ctlr];
if (rs_imode[ctlr])
*data |= IRQ_KI10;
else
*data |= IRQ_KA10;
} else if (rs_reg[ctlr] == 054) {
*data = (uint64)(rs_rae[ctlr]);
} else if ((rs_reg[ctlr] & 040) == 0) {
int parity;
*data = (uint64)(rs_read(ctlr, rs_drive[ctlr], rs_reg[ctlr]) & 0177777);
parity = (int)((*data >> 8) ^ *data);
parity = (parity >> 4) ^ parity;
parity = (parity >> 2) ^ parity;
parity = ((parity >> 1) ^ parity) & 1;
*data |= ((uint64)(parity ^ 1)) << 17;
*data |= ((uint64)(rs_drive[ctlr])) << 18;
}
*data |= ((uint64)(rs_reg[ctlr])) << 30;
sim_debug(DEBUG_DATAIO, dptr, "RS %03o DATI %012llo, %d %d PC=%06o\n",
dev, *data, ctlr, rs_drive[ctlr], PC);
return SCPE_OK;
case DATAO:
sim_debug(DEBUG_DATAIO, dptr, "RS %03o DATO %012llo, %d PC=%06o %06o\n",
dev, *data, ctlr, PC, df10->status);
rs_reg[ctlr] = ((int)(*data >> 30)) & 077;
if (rs_reg[ctlr] < 040 && rs_reg[ctlr] != 04) {
rs_drive[ctlr] = (int)(*data >> 18) & 07;
}
if (*data & LOAD_REG) {
if (rs_reg[ctlr] == 040) {
if ((*data & 1) == 0) {
return SCPE_OK;
}
if (df10->status & BUSY) {
df10->status |= CC_CHAN_ACT;
return SCPE_OK;
}
df10->status &= ~(1 << df10->ccw_comp);
df10->status &= ~PI_ENABLE;
if (((*data >> 1) & 077) < FNC_XFER) {
df10->status |= CXR_ILC;
df10_setirq(df10);
sim_debug(DEBUG_DATAIO, dptr,
"RS %03o command abort %012llo, %d[%d] PC=%06o %06o\n",
dev, *data, ctlr, rs_drive[ctlr], PC, df10->status);
return SCPE_OK;
}
/* Start command */
df10_setup(df10, (uint32)(*data >> 6));
rs_xfer_drive[ctlr] = (int)(*data >> 18) & 07;
rs_write(ctlr, rs_drive[ctlr], 0, (uint32)(*data & 077));
sim_debug(DEBUG_DATAIO, dptr,
"RS %03o command %012llo, %d[%d] PC=%06o %06o\n",
dev, *data, ctlr, rs_drive[ctlr], PC, df10->status);
} else if (rs_reg[ctlr] == 044) {
/* Set KI10 Irq vector */
rs_ivect[ctlr] = (int)(*data & IRQ_VECT);
rs_imode[ctlr] = (*data & IRQ_KI10) != 0;
} else if (rs_reg[ctlr] == 050) {
; /* Diagnostic access to mass bus. */
} else if (rs_reg[ctlr] == 054) {
/* clear flags */
rs_rae[ctlr] &= ~(*data & 0377);
if (rs_rae[ctlr] == 0)
clr_interrupt(dev);
} else if ((rs_reg[ctlr] & 040) == 0) {
rs_drive[ctlr] = (int)(*data >> 18) & 07;
/* Check if access error */
if (rs_rae[ctlr] & (1 << rs_drive[ctlr])) {
return SCPE_OK;
}
rs_drive[ctlr] = (int)(*data >> 18) & 07;
rs_write(ctlr, rs_drive[ctlr], rs_reg[ctlr] & 037,
(int)(*data & 0777777));
}
}
return SCPE_OK;
}
return SCPE_OK; /* Unreached */
}
/* Handle KI and KL style interrupt vectors */
int
rs_devirq(uint32 dev, int addr) {
DEVICE *dptr = NULL;
int drive;
for (drive = 0; rh[drive].dev_num != 0; drive++) {
if (rh[drive].dev_num == (dev & 0774)) {
dptr = rh[drive].dev;
break;
}
}
if (dptr != NULL) {
drive = GET_CNTRL(dptr->units[0].flags);
return (rs_imode[drive] ? rs_ivect[drive] : addr);
}
return addr;
void
rs_rst(DEVICE *dptr)
{
UNIT *uptr=dptr->units;
int drive;
for(drive = 0; drive < NUM_UNITS_RS; drive++, uptr++) {
uptr->CMD &= DS_MOL|DS_WRL|DS_DPR|DS_DRY|DS_VV|076;
uptr->DA &= 003400177777;
}
}
void
rs_write(int ctlr, int unit, int reg, uint32 data) {
rs_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) {
int i;
DEVICE *dptr = rs_devs[ctlr];
struct df10 *df10 = &rs_df10[ctlr];
int unit = rhc->drive;
UNIT *uptr = &dptr->units[unit];
if ((uptr->CMD & CR_GO) && reg != 04) {
if ((uptr->CMD & CS1_GO) && reg != 04) {
uptr->CMD |= (ER1_RMR << 16)|DS_ERR;
return;
}
switch(reg) {
case 000: /* control */
sim_debug(DEBUG_DETAIL, dptr, "RSA%o %d Status=%06o\n", unit, ctlr, uptr->CMD);
sim_debug(DEBUG_DETAIL, dptr, "%s%o Status=%06o\n", dptr->name, unit, uptr->CMD);
/* Set if drive not writable */
if (uptr->flags & UNIT_WLK)
uptr->CMD |= DS_WRL;
/* If drive not ready don't do anything */
if ((uptr->CMD & DS_DRY) == 0) {
uptr->CMD |= (ER1_RMR << 16)|DS_ERR;
sim_debug(DEBUG_DETAIL, dptr, "RSA%o %d busy\n", unit, ctlr);
sim_debug(DEBUG_DETAIL, dptr, "%s%o busy\n", dptr->name, unit);
return;
}
/* Check if GO bit set */
if ((data & 1) == 0) {
uptr->CMD &= ~076;
uptr->CMD |= data & 076;
sim_debug(DEBUG_DETAIL, dptr, "RSA%o %d no go\n", unit, ctlr);
sim_debug(DEBUG_DETAIL, dptr, "%s%o no go\n", dptr->name, unit);
return; /* No, nop */
}
uptr->CMD &= DS_ATA|DS_VV|DS_DPR|DS_MOL|DS_WRL;
@@ -542,7 +313,8 @@ rs_write(int ctlr, int unit, int reg, uint32 data) {
case FNC_WCHK: /* write check */
case FNC_WRITE: /* write */
case FNC_READ: /* read */
uptr->CMD |= DS_PIP|CR_GO;
uptr->CMD |= DS_PIP|CS1_GO;
CLR_BUF(uptr);
uptr->DATAPTR = 0;
break;
@@ -551,30 +323,26 @@ rs_write(int ctlr, int unit, int reg, uint32 data) {
if ((uptr->flags & UNIT_ATT) != 0)
uptr->CMD |= DS_VV;
uptr->CMD |= DS_DRY;
df10_setirq(df10);
rh_setirq(rhc);
break;
case FNC_DCLR: /* drive clear */
uptr->CMD |= DS_DRY;
uptr->CMD &= ~(DS_ATA|CR_GO);
rs_attn[ctlr] = 0;
clr_interrupt(df10->devnum);
uptr->CMD &= ~(DS_ATA|CS1_GO);
rhc->attn = 0;
clr_interrupt(rhc->devnum);
for (i = 0; i < 8; i++) {
if (rs_unit[(ctlr * 8) + i].CMD & DS_ATA)
rs_attn[ctlr] = 1;
if (dptr->units[i].CMD & DS_ATA)
rhc->attn |= 1 << i;
}
if ((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0)
df10_setirq(df10);
break;
default:
uptr->CMD |= DS_DRY|DS_ERR|DS_ATA;
uptr->CMD |= (ER1_ILF << 16);
if ((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0)
df10_setirq(df10);
}
if (uptr->CMD & CR_GO)
if (uptr->CMD & CS1_GO)
sim_activate(uptr, 100);
sim_debug(DEBUG_DETAIL, dptr, "RSA%o AStatus=%06o\n", unit, uptr->CMD);
sim_debug(DEBUG_DETAIL, dptr, "%s%o AStatus=%06o\n", dptr->name, unit, uptr->CMD);
return;
case 001: /* status */
break;
@@ -587,17 +355,13 @@ rs_write(int ctlr, int unit, int reg, uint32 data) {
case 003: /* maintenance */
break;
case 004: /* atten summary */
rs_attn[ctlr] = 0;
rhc->attn = 0;
for (i = 0; i < 8; i++) {
if (data & (1<<i))
rs_unit[(ctlr * 8) + i].CMD &= ~DS_ATA;
if (rs_unit[(ctlr * 8) + i].CMD & DS_ATA)
rs_attn[ctlr] = 1;
dptr->units[i].CMD &= ~DS_ATA;
if (dptr->units[i].CMD & DS_ATA)
rhc->attn |= 1 << i;
}
clr_interrupt(df10->devnum);
if (((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0) ||
(df10->status & PI_ENABLE))
df10_setirq(df10);
break;
case 005: /* sector/track */
uptr->DA = data & 0177777;
@@ -607,14 +371,13 @@ rs_write(int ctlr, int unit, int reg, uint32 data) {
break;
default:
uptr->CMD |= (ER1_ILR<<16)|DS_ERR;
rs_rae[ctlr] &= ~(1<<unit);
rhc->rae |= 1 << unit;
}
}
uint32
rs_read(int ctlr, int unit, int reg) {
DEVICE *dptr = rs_devs[ctlr];
struct df10 *df10 = &rs_df10[ctlr];
rs_read(DEVICE *dptr, struct rh_if *rhc, int reg) {
int unit = rhc->drive;
UNIT *uptr = &dptr->units[unit];
uint32 temp = 0;
int i;
@@ -628,7 +391,7 @@ rs_read(int ctlr, int unit, int reg) {
temp = uptr->CMD & 077;
if (uptr->flags & UNIT_ATT)
temp |= CS1_DVA;
if ((df10->status & BUSY) == 0 && (uptr->CMD & CR_GO) == 0)
if ((uptr->CMD & CS1_GO) == 0)
temp |= CS1_GO;
break;
case 001: /* status */
@@ -639,7 +402,7 @@ rs_read(int ctlr, int unit, int reg) {
break;
case 004: /* atten summary */
for (i = 0; i < 8; i++) {
if (rs_unit[(ctlr * 8) + i].CMD & DS_ATA) {
if (dptr->units[i].CMD & DS_ATA) {
temp |= 1 << i;
}
}
@@ -655,7 +418,7 @@ rs_read(int ctlr, int unit, int reg) {
break;
default:
uptr->CMD |= (ER1_ILR<<16);
rs_rae[ctlr] &= ~(1<<unit);
rhc->rae |= 1 << unit;
}
return temp;
}
@@ -663,22 +426,21 @@ rs_read(int ctlr, int unit, int reg) {
t_stat rs_svc (UNIT *uptr)
{
int dtype = GET_DTYPE(uptr->flags);
int ctlr = GET_CNTRL(uptr->flags);
int unit;
DEVICE *dptr;
struct df10 *df;
int da;
t_stat r;
int dtype = GET_DTYPE(uptr->flags);
int ctlr = GET_CNTRL_RH(uptr->flags);
int unit;
DEVICE *dptr;
struct rh_if *rhc;
int da;
int sts;
/* Find dptr, and df10 */
dptr = rs_devs[ctlr];
rhc = &rs_rh[ctlr];
unit = uptr - dptr->units;
df = &rs_df10[ctlr];
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
uptr->CMD |= (ER1_UNS << 16) | DS_ATA|DS_ERR; /* set drive error */
df->status &= ~BUSY;
df10_setirq(df);
rh_setirq(rhc);
return (SCPE_OK);
}
@@ -693,42 +455,35 @@ t_stat rs_svc (UNIT *uptr)
case FNC_DCLR: /* drive clear */
break;
case FNC_PRESET: /* read-in preset */
rs_attn[ctlr] = 1;
uptr->CMD |= DS_DRY|DS_ATA;
uptr->CMD &= ~CR_GO;
df->status &= ~BUSY;
if (df->status & IADR_ATTN)
df10_setirq(df);
sim_debug(DEBUG_DETAIL, dptr, "RSA%o seekdone\n", unit);
uptr->CMD &= ~CS1_GO;
rh_setattn(rhc, unit);
sim_debug(DEBUG_DETAIL, dptr, "%s%o seekdone\n", dptr->name, unit);
break;
case FNC_SEARCH: /* search */
if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect ||
GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf)
uptr->CMD |= (ER1_IAE << 16)|DS_ERR;
rs_attn[ctlr] = 1;
uptr->CMD |= DS_DRY|DS_ATA;
uptr->CMD &= ~CR_GO;
df->status &= ~BUSY;
if ((df->status & (IADR_ATTN|BUSY)) == IADR_ATTN)
df10_setirq(df);
sim_debug(DEBUG_DETAIL, dptr, "RSA%o searchdone\n", unit);
uptr->CMD &= ~CS1_GO;
rh_setattn(rhc, unit);
sim_debug(DEBUG_DETAIL, dptr, "%s%o searchdone\n", dptr->name, unit);
break;
case FNC_READ: /* read */
case FNC_WCHK: /* write check */
if (uptr->DATAPTR == 0) {
if (BUF_EMPTY(uptr)) {
int wc;
if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect ||
GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) {
uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA;
df->status &= ~BUSY;
uptr->CMD &= ~CR_GO;
sim_debug(DEBUG_DETAIL, dptr, "RSA%o readx done\n", unit);
df10_finish_op(df, 0);
uptr->CMD &= ~CS1_GO;
sim_debug(DEBUG_DETAIL, dptr, "%s%o readx done\n", dptr->name, unit);
rh_finish_op(rhc, 0);
return SCPE_OK;
}
sim_debug(DEBUG_DETAIL, dptr, "RSA%o read (%d,%d)\n", unit,
sim_debug(DEBUG_DETAIL, dptr, "%s%o read (%d,%d)\n", dptr->name, unit,
GET_SC(uptr->DA), GET_SF(uptr->DA));
da = GET_DA(uptr->DA, dtype) * RS_NUMWD;
(void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET);
@@ -737,15 +492,17 @@ t_stat rs_svc (UNIT *uptr)
while (wc < RS_NUMWD)
rs_buf[ctlr][wc++] = 0;
uptr->hwmark = RS_NUMWD;
uptr->DATAPTR = 0;
}
df->buf = rs_buf[ctlr][uptr->DATAPTR++];
sim_debug(DEBUG_DATA, dptr, "RSA%o read word %d %012llo %09o %06o\n",
unit, uptr->DATAPTR, df->buf, df->cda, df->wcr);
if (df10_write(df)) {
if (uptr->DATAPTR == uptr->hwmark) {
rhc->buf = rs_buf[ctlr][uptr->DATAPTR++];
sim_debug(DEBUG_DATA, dptr, "%s%o read word %d %012llo %09o %06o\n",
dptr->name, unit, uptr->DATAPTR, rhc->buf, rhc->cda, rhc->wcr);
if (rh_write(rhc)) {
if (uptr->DATAPTR == RS_NUMWD) {
/* Increment to next sector. Set Last Sector */
uptr->DATAPTR = 0;
CLR_BUF(uptr);
uptr->DA += 1 << DA_V_SC;
if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect) {
uptr->DA &= (DA_M_SF << DA_V_SF);
@@ -753,43 +510,53 @@ t_stat rs_svc (UNIT *uptr)
if (GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf)
uptr->CMD |= DS_LST;
}
if (rh_blkend(rhc))
goto rd_end;
}
sim_activate(uptr, 20);
sim_activate(uptr, 10);
} else {
sim_debug(DEBUG_DETAIL, dptr, "RSA%o read done\n", unit);
rd_end:
sim_debug(DEBUG_DETAIL, dptr, "%s%o read done\n", dptr->name, unit);
uptr->CMD |= DS_DRY;
uptr->CMD &= ~CR_GO;
df10_finish_op(df, 0);
uptr->CMD &= ~CS1_GO;
if (uptr->DATAPTR == RS_NUMWD)
(void)rh_blkend(rhc);
rh_finish_op(rhc, 0);
return SCPE_OK;
}
break;
case FNC_WRITE: /* write */
if (uptr->DATAPTR == 0) {
if (BUF_EMPTY(uptr)) {
if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect ||
GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) {
uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA;
uptr->CMD &= ~CR_GO;
sim_debug(DEBUG_DETAIL, dptr, "RSA%o writex done\n", unit);
df10_finish_op(df, 0);
uptr->CMD &= ~CS1_GO;
sim_debug(DEBUG_DETAIL, dptr, "%s%o writex done\n", dptr->name, unit);
rh_finish_op(rhc, 0);
return SCPE_OK;
}
uptr->DATAPTR = 0;
uptr->hwmark = 0;
}
r = df10_read(df);
rs_buf[ctlr][uptr->DATAPTR++] = df->buf;
sim_debug(DEBUG_DATA, dptr, "RSA%o write word %d %012llo %09o %06o\n",
unit, uptr->DATAPTR, df->buf, df->cda, df->wcr);
if (r == 0 || uptr->DATAPTR == RS_NUMWD) {
sts = rh_read(rhc);
rs_buf[ctlr][uptr->DATAPTR++] = rhc->buf;
sim_debug(DEBUG_DATA, dptr, "%s%o write word %d %012llo %09o %06o\n",
dptr->name, unit, uptr->DATAPTR, rhc->buf, rhc->cda, rhc->wcr);
if (sts == 0) {
while (uptr->DATAPTR < RS_NUMWD)
rs_buf[ctlr][uptr->DATAPTR++] = 0;
sim_debug(DEBUG_DETAIL, dptr, "RSA%o write (%d,%d)\n", unit,
}
if (uptr->DATAPTR == RS_NUMWD) {
sim_debug(DEBUG_DETAIL, dptr, "%s%o write (%d,%d)\n", dptr->name, unit,
GET_SC(uptr->DA), GET_SF(uptr->DA));
da = GET_DA(uptr->DA, dtype) * RS_NUMWD;
(void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET);
(void)sim_fwrite (&rs_buf[ctlr][0], sizeof(uint64), RS_NUMWD,
uptr->fileref);
uptr->DATAPTR = 0;
if (r) {
CLR_BUF(uptr);
if (sts) {
uptr->DA += 1 << DA_V_SC;
if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect) {
uptr->DA &= (DA_M_SF << DA_V_SF);
@@ -798,14 +565,17 @@ t_stat rs_svc (UNIT *uptr)
uptr->CMD |= DS_LST;
}
}
if (rh_blkend(rhc))
goto wr_end;
}
if (r) {
sim_activate(uptr, 20);
if (sts) {
sim_activate(uptr, 10);
} else {
sim_debug(DEBUG_DETAIL, dptr, "RSA%o write done\n", unit);
wr_end:
sim_debug(DEBUG_DETAIL, dptr, "%s%o write done\n", dptr->name, unit);
uptr->CMD |= DS_DRY;
uptr->CMD &= ~CR_GO;
df10_finish_op(df, 0);
uptr->CMD &= ~CS1_GO;
rh_finish_op(rhc, 0);
return SCPE_OK;
}
break;
@@ -833,12 +603,9 @@ rs_reset(DEVICE * rstr)
{
int ctlr;
for (ctlr = 0; ctlr < NUM_DEVS_RS; ctlr++) {
rs_df10[ctlr].devnum = rs_dib[ctlr].dev_num;
rs_df10[ctlr].nxmerr = 19;
rs_df10[ctlr].ccw_comp = 14;
rs_df10[ctlr].status = 0;
rs_attn[ctlr] = 0;
rs_rae[ctlr] = 0;
rs_rh[ctlr].status = 0;
rs_rh[ctlr].attn = 0;
rs_rh[ctlr].rae = 0;
}
return SCPE_OK;
}
@@ -848,16 +615,16 @@ t_stat
rs_boot(int32 unit_num, DEVICE * rptr)
{
UNIT *uptr = &rptr->units[unit_num];
int ctlr = GET_CNTRL(uptr->flags);
int ctlr = GET_CNTRL_RH(uptr->flags);
struct rh_if *rhc;
DEVICE *dptr;
struct df10 *df;
uint32 addr;
uint32 ptr = 0;
uint64 word;
int wc;
df = &rs_df10[ctlr];
dptr = rs_devs[ctlr];
rhc = &rs_rh[ctlr];
(void)sim_fseek(uptr->fileref, 0, SEEK_SET);
(void)sim_fread (&rs_buf[0][0], sizeof(uint64), RS_NUMWD, uptr->fileref);
uptr->CMD |= DS_VV;
@@ -875,9 +642,9 @@ rs_boot(int32 unit_num, DEVICE * rptr)
addr = rs_buf[0][ptr] & RMASK;
wc = (rs_buf[0][ptr++] >> 18) & RMASK;
word = rs_buf[0][ptr++];
rs_reg[ctlr] = 040;
rs_drive[ctlr] = uptr - dptr->units;
df->status |= CCW_COMP_1|PI_ENABLE;
rhc->reg = 040;
rhc->drive = uptr - dptr->units;
rhc->status |= CCW_COMP_1|PI_ENABLE;
PC = word & RMASK;
return SCPE_OK;
@@ -901,14 +668,17 @@ t_stat rs_attach (UNIT *uptr, CONST char *cptr)
if (rstr == 0)
return SCPE_OK;
dib = (DIB *) rstr->ctxt;
ctlr = dib->dev_num & 014;
for (ctlr = 0; rh[ctlr].dev_num != 0; ctlr++) {
if (rh[ctlr].dev == rstr)
break;
}
uptr->DA = 0;
uptr->CMD &= ~DS_VV;
uptr->CMD |= DS_DPR|DS_MOL|DS_DRY;
if (uptr->flags & UNIT_WLK)
uptr->CMD |= DS_WRL;
rs_df10[ctlr].status |= PI_ENABLE;
set_interrupt(dib->dev_num, rs_df10[ctlr].status);
rs_rh[ctlr].status |= PI_ENABLE;
set_interrupt(dib->dev_num, rs_rh[ctlr].status);
return SCPE_OK;
}

View File

@@ -3,7 +3,7 @@
Copyright (c) 2005-2009, Robert M Supnik
Copyright (c) 2011-2018, Richard Cornwell
Copyright (c) 2011-2019, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -42,11 +42,8 @@
sim_load binary loader
*/
#if KLB
char sim_name[] = "KL-10B";
#endif
#if KLA
char sim_name[] = "KL-10A";
#if KL
char sim_name[] = "KL-10";
#endif
#if KI
char sim_name[] = "KI-10";
@@ -68,6 +65,9 @@ DEVICE *sim_devices[] = {
#if PDP6 | KA | KI
&cty_dev,
#endif
#if KL
&dte_dev,
#endif
#if (NUM_DEVS_PT > 0)
&ptp_dev,
&ptr_dev,
@@ -75,6 +75,9 @@ DEVICE *sim_devices[] = {
#if (NUM_DEVS_LP > 0)
&lpt_dev,
#endif
#if (NUM_DEVS_LP20 > 0)
&lp20_dev,
#endif
#if (NUM_DEVS_CR > 0)
&cr_dev,
#endif
@@ -141,6 +144,9 @@ DEVICE *sim_devices[] = {
#if (NUM_DEVS_DC > 0)
&dc_dev,
#endif
#if (NUM_DEVS_TTY > 0)
&tty_dev,
#endif
#if (NUM_DEVS_DCS > 0)
&dcs_dev,
#endif
@@ -156,9 +162,15 @@ DEVICE *sim_devices[] = {
&wcnsls_dev,
#endif
#endif
#if (NUM_DEVS_III > 0)
&iii_dev,
#endif
#if NUM_DEVS_IMP > 0
&imp_dev,
#endif
#if NUM_DEVS_NIA > 0
&nia_dev,
#endif
#if NUM_DEVS_CH10 > 0
&ch10_dev,
#endif
@@ -197,7 +209,8 @@ DEVICE *sim_devices[] = {
const char *sim_stop_messages[] = {
"Unknown error",
"HALT instruction",
"Breakpoint"
"Breakpoint",
"Invalid access"
};
/* Simulator debug controls */
@@ -232,6 +245,7 @@ DEBTAB crd_debug[] = {
#define FMT_E 3 /* EXE */
#define FMT_D 4 /* WAITS DMP */
#define FMT_I 5 /* ITS SBLK */
#define FMT_B 6 /* EXB format */
#define EXE_DIR 01776 /* EXE directory */
#define EXE_VEC 01775 /* EXE entry vec */
@@ -510,19 +524,28 @@ return SCPE_OK;
}
int get_word(FILE *fileref, uint64 *word)
int get_word(FILE *fileref, uint64 *word, int ftype)
{
char cbuf[5];
char cbuf[5];
if (sim_fread(cbuf, 1, 5, fileref) != 5)
if (sim_fread(cbuf, 1, 5, fileref) != 5)
return 1;
*word = ((uint64)(cbuf[0]) << 29) |
((uint64)(cbuf[1]) << 22) |
((uint64)(cbuf[2]) << 15) |
((uint64)(cbuf[3]) << 8) |
((uint64)(cbuf[4] & 0177) << 1) |
((uint64)(cbuf[4] & 0200) >> 7);
return 0;
if (ftype) {
*word = ((uint64)(cbuf[0] & 0177) << 29) |
((uint64)(cbuf[1] & 0177) << 22) |
((uint64)(cbuf[2] & 0177) << 15) |
((uint64)(cbuf[3] & 0177) << 8) |
((uint64)(cbuf[4] & 0177) << 1);
if (cbuf[4] & 0200)
*word |= 1;
} else {
*word = ((uint64)(cbuf[0] & 0377) << 28) |
((uint64)(cbuf[1] & 0377) << 20) |
((uint64)(cbuf[2] & 0377) << 12) |
((uint64)(cbuf[3] & 0377) << 4) |
(uint64)(cbuf[4] & 017);
}
return 0;
}
/* SAV file loader
@@ -538,14 +561,14 @@ int get_word(FILE *fileref, uint64 *word)
JRST start
*/
t_stat load_sav (FILE *fileref)
t_stat load_sav (FILE *fileref, int ftype)
{
uint64 data;
uint32 pa;
int32 wc;
for ( ;; ) { /* loop */
if (get_word(fileref, &data))
if (get_word(fileref, &data, ftype))
return SCPE_OK;
wc = (int32)(data >> 18);
pa = (uint32) (data & RMASK);
@@ -559,7 +582,7 @@ t_stat load_sav (FILE *fileref)
pa &= RMASK;
wc++;
wc &= RMASK;
if (get_word(fileref, &data))
if (get_word(fileref, &data, ftype))
return SCPE_FMT;
M[pa] = data;
} /* end if count*/
@@ -594,7 +617,7 @@ t_stat load_sav (FILE *fileref)
#define PAG_V_PN 9
#define DIRSIZ (2 * PAG_SIZE)
t_stat load_exe (FILE *fileref)
t_stat load_exe (FILE *fileref, int ftype)
{
uint64 data, dirbuf[DIRSIZ], pagbuf[PAG_SIZE], entbuf[2];
int32 ndir, entvec, i, j, k, cont, bsz, bty, rpt, wc;
@@ -604,8 +627,9 @@ uint32 ma;
ndir = entvec = 0; /* no dir, entvec */
cont = 1;
do {
wc = sim_fread (&data, sizeof (uint64), 1, fileref);/* read blk hdr */
if (wc == 0) /* error? */
wc = get_word(fileref, &data, ftype);
if (wc != 0) /* error? */
return SCPE_FMT;
bsz = (int32) ((data & RMASK) - 1); /* get count */
if (bsz < 0) /* zero? */
@@ -616,9 +640,11 @@ do {
case EXE_DIR: /* directory */
if (ndir != 0) /* got one */
return SCPE_FMT;
ndir = sim_fread (dirbuf, sizeof (uint64), bsz, fileref);
if (ndir < bsz) /* error */
return SCPE_FMT;
for (i = 0; i < bsz; i++) {
if (get_word(fileref, &dirbuf[i], ftype))
return SCPE_FMT;
}
ndir = bsz;
break;
case EXE_PDV: /* optional */
@@ -628,9 +654,11 @@ do {
case EXE_VEC: /* entry vec */
if (bsz != 2) /* must be 2 wds */
return SCPE_FMT;
entvec = sim_fread (entbuf, sizeof (uint64), bsz, fileref);
if (entvec < 2) /* error? */
return SCPE_FMT;
for (i = 0; i < bsz; i++) {
if (get_word(fileref, &entbuf[i], ftype))
return SCPE_FMT;
}
entvec = bsz;
cont = 0; /* stop */
break;
@@ -651,10 +679,11 @@ for (i = 0; i < ndir; i = i + 2) { /* loop thru dir */
rpt = ((int32) ((dirbuf[i + 1] >> 27) + 1)) & 0777; /* repeat count */
for (j = 0; j < rpt; j++, mpage++) { /* loop thru rpts */
if (fpage) { /* file pages? */
(void)sim_fseek (fileref, (fpage << PAG_V_PN) * sizeof (uint64), SEEK_SET);
wc = sim_fread (pagbuf, sizeof (uint64), PAG_SIZE, fileref);
if (wc < PAG_SIZE)
return SCPE_FMT;
(void)sim_fseek (fileref, (fpage << PAG_V_PN) * 5, SEEK_SET);
for (k = 0; k < PAG_SIZE; k++) {
if (get_word(fileref, &pagbuf[k], ftype))
break;
}
fpage++;
}
ma = mpage << PAG_V_PN; /* mem addr */
@@ -667,18 +696,103 @@ for (i = 0; i < ndir; i = i + 2) { /* loop thru dir */
} /* end directory */
if (entvec && entbuf[1])
PC = (int32) (entbuf[1] & RMASK); /* start addr */
else if (entvec == 0)
PC = (int32) (M[0120] & RMASK);
return SCPE_OK;
}
static int exb_pos = -1;
int get_exb_byte (FILE *fileref, int *byt, int ftype)
{
static uint64 word;
exb_pos++;
switch(exb_pos & 3) {
case 0: if (get_word(fileref, &word, ftype))
return 1;
*byt = ((word >> 18) & 0377);
break;
case 1: *byt = ((word >> 26) & 0377);
break;
case 2: *byt = ((word >> 0) & 0377);
break;
case 3: *byt = ((word >> 8) & 0377);
break;
}
return 0;
}
t_stat load_exb (FILE *fileref, int ftype)
{
int odd = 0;
int pos = 0;
int wc;
int byt;
uint64 word;
t_addr addr;
exb_pos = -1;
for ( ;; ) {
/* All records start on even byte */
if (odd && get_exb_byte (fileref, &byt, ftype))
return SCPE_FMT;
if (get_exb_byte(fileref, &byt, ftype))
return SCPE_FMT;
wc = byt;
if (get_exb_byte(fileref, &byt, ftype))
return SCPE_FMT;
wc |= byt << 8;
wc -= 4;
odd = wc & 1;
if (get_exb_byte(fileref, &byt, ftype))
return SCPE_FMT;
addr = byt;
if (get_exb_byte(fileref, &byt, ftype))
return SCPE_FMT;
addr |= byt << 8;
if (get_exb_byte(fileref, &byt, ftype))
return SCPE_FMT;
addr |= byt << 16;
if (get_exb_byte(fileref, &byt, ftype))
return SCPE_FMT;
addr |= byt << 24;
/* Empty record gives start address */
if (wc == 0) {
PC = addr;
return SCPE_OK;
}
pos = 0;
for (; wc > 0; wc--, pos++) {
if (get_exb_byte(fileref, &byt, ftype))
return SCPE_FMT;
switch(pos) {
case 0: word = ((uint64)byt); break;
case 1: word |= ((uint64)byt) << 8; break;
case 2: word |= ((uint64)byt) << 16; break;
case 3: word |= ((uint64)byt) << 24; break;
case 4: word |= ((uint64)(byt & 017)) << 32;
M[addr++] = word;
pos = -1;
break;
}
}
}
return SCPE_FMT;
}
/* Master loader */
t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag)
{
uint64 data;
int32 wc, fmt;
int ftype;
extern int32 sim_switches;
fmt = 0; /* no fmt */
ftype = 0;
if (sim_switches & SWMASK ('C')) /* -c? core dump */
ftype = 1;
if (sim_switches & SWMASK ('R')) /* -r? */
fmt = FMT_R;
else if (sim_switches & SWMASK ('S')) /* -s? */
@@ -689,12 +803,16 @@ else if (sim_switches & SWMASK ('D')) /* -d? */
fmt = FMT_D;
else if (sim_switches & SWMASK ('I')) /* -i? */
fmt = FMT_I;
else if (sim_switches & SWMASK ('B')) /* -b? */
fmt = FMT_B;
else if (match_ext (fnam, "RIM")) /* .RIM? */
fmt = FMT_R;
else if (match_ext (fnam, "SAV")) /* .SAV? */
fmt = FMT_S;
else if (match_ext (fnam, "EXE")) /* .EXE? */
fmt = FMT_E;
else if (match_ext (fnam, "EXB")) /* .EXB? */
fmt = FMT_B;
else if (match_ext (fnam, "DMP")) /* .DMP? */
fmt = FMT_D;
else if (match_ext (fnam, "BIN")) /* .BIN? */
@@ -716,16 +834,19 @@ switch (fmt) { /* case fmt */
return load_rim (fileref);
case FMT_S: /* SAV */
return load_sav (fileref);
return load_sav (fileref, ftype);
case FMT_E: /* EXE */
return load_exe (fileref);
return load_exe (fileref, ftype);
case FMT_D: /* DMP */
return load_dmp (fileref);
case FMT_I: /* SBLK */
return load_sblk (fileref);
case FMT_B: /* EXB */
return load_exb (fileref, ftype);
}
printf ("Can't determine load file format\n");
@@ -759,13 +880,22 @@ static const char *opcode[] = {
"LUUO10", "LUUO11", "LUUO12", "LUUO13", "LUUO14", "LUUO15", "LUUO16", "LUUO17",
"LUUO20", "LUUO21", "LUUO22", "LUUO23", "LUUO24", "LUUO25", "LUUO26", "LUUO27",
"LUUO30", "LUUO31", "LUUO32", "LUUO33", "LUUO34", "LUUO35", "LUUO36", "LUUO37",
"MUUO40", "MUUO41", "MUUO42", "MUUO43", "MUUO44", "MUUO45", "MUUO46", "MUUO47",
"MUUO50", "MUUO51", "MUUO52", "MUUO53", "MUUO54", "MUUO55", "MUUO56", "MUUO57",
"MUUO60", "MUUO61", "MUUO62", "MUUO63", "MUUO64", "MUUO65", "MUUO66", "MUUO67",
"MUUO70", "MUUO71", "MUUO72", "MUUO73", "MUUO74", "MUUO75", "MUUO76", "MUUO77",
"CALL", "INITI", "MUUO42", "MUUO43", "MUUO44", "MUUO45", "MUUO46", "CALLI",
#if KL
"OPEN", "TTCALL", "PMOVE", "PMOVEM", "MUUO54", "RENAME", "IN", "OUT",
#else
"OPEN", "TTCALL", "MUUO52", "MUUO53", "MUUO54", "RENAME", "IN", "OUT",
#endif
"SETSTS", "STATO", "STATUS", "GETSTS", "INBUF", "OUTBUF", "INPUT", "OUTPUT",
"CLOSE", "RELEAS", "MTAPE", "UGETF", "USETI", "USETO", "LOOKUP", "ENTER",
"UJEN", "MUUO101", "MUUO102", "JSYS", "MUUO104", "MUUO105", "MUUO106",
#if KL
"UJEN", "GFAD", "GFSB", "JSYS", "ADJSP", "GFMP", "GFDV ",
"DFAD", "DFSB", "DFMP", "DFDV", "DADD", "DSUB", "DMUL", "DDIV",
#else
"UJEN", "MUUO101", "MUUO102", "JSYS", "MUUO104", "MUUO105", "MUUO106",
"DFAD", "DFSB", "DFMP", "DFDV", "MUUO114", "MUUO115", "MUUO116", "MUUO117",
#endif
"DMOVE", "DMOVN", "FIX", "EXTEND", "DMOVEM", "DMOVNM", "FIXR", "FLTR",
"UFA", "DFN", "FSC", "ADJBP", "ILDB", "LDB", "IDPB", "DPB",
"FAD", "FADL", "FADM", "FADB", "FADR", "FADRL", "FADRM", "FADRB",

File diff suppressed because it is too large Load Diff

101
README.md
View File

@@ -1,8 +1,8 @@
[![Coverity Scan Build Status](https://scan.coverity.com/projects/12020/badge.svg)](https://scan.coverity.com/projects/rcornwell-sims)
This is a working copy of my Burroughs B5500, Dec PDP6, KA10, KI10, SEL32, IBM 360 and IBM7000
series simulators for SimH.
This is a working copy of my Burroughs B5500, Dec PDP6, KA10, KI10, KL10, SEL32, IBM 360
and IBM7000 series simulators for SimH.
# Stable released simulators.
@@ -64,7 +64,14 @@ Latest status for I7000 Cpus:
Emulates a dual CPU B5500 with up to 32K of memory. I can support either DFX disks or
dual disks up to 20 units. Up to 16 magnetic tapes drives is support. 2 Card readers
a card punch and a pair of line printers.
a card punch and a pair of line printers. Will run MCP XIII and XV.
* Up to either 10 disks with DFX support or 20 disks without.
* Up to 16 magnetic tape drives.
* Dual card reader.
* Dual Line printer.
* Single card punch.
* Up to 32 terminal lines.
# Dec PDP6
@@ -88,76 +95,60 @@ The PDP6 runs TOPS 10 4.5 off Dectape.
Type 340 graphics display.
# Dec KA10 & KI10
# Dec KA10 & KI10 & KL10
These are nearing release. Please report any issues that you find in them.
The KA10 sim has successfully run Tops 10 4.5, 5.03 and Tops 10 6.03.
The KI10 sim has successfully run Tops 10 6.03 with VMSER
The KA10 sim has successfully run ITS.
The KA10 sim has successfully run WAITS (with and without BBN pager).
The KA10 sim has successfully run Tops 10 4.5, 5.03 and 6.03, ITS and WAITS.
The KI10 sim has successfully run Tops 10 6.03 with VMSER.
The KL10 sim has successfully run Tops 10 6.03-7.03, ITS and Tops 20 V2-V7.
Disk
* RC10 RD10/RM10
* RP10 RP01/RP02/RP03
* RH10 RP04/RP06/RP07 (RP07 not supported under 6.03).
* RH10 RS04
* RH10/RH20 RP04/RP06/RP07 (RP07 not supported under 6.03).
* RH10/RH20 RS04
* PMP (P. PETIT'S IBM CHANNEL)
* System Concepts DC-10 IBM 2314
Tape
* TM10A or B
* RH10 TM03/TU16
* RH10/RH20 TM03/TU16
* TD10 Dectape
Paper Tape
* Punch
* Reader
DC10E terminal mux.
Morton tty Mux for ITS.
Knight Kludge mux for ITS.
* DC10E terminal mux.
* Morton tty Mux for ITS.
* Knight Kludge mux for ITS.
* Terminals on KL10 Front End.
IMP networking support for ITS and TENEX.
CH10 networking support for ITS.
* LP10 Line printer.
* LP20 Line printer on KL10 Front End.
340 Display Station support.
* IMP networking support for ITS and TENEX.
* NIA20 networking support for KL10.
* CH10 networking support for ITS.
Optional support for PDP6 devices (standard if WAITS included).
* 340 Display Station support.
* III Display support for WAITS (in progress).
* Optional support for PDP6 devices (standard if WAITS included).
The RP10 supports boot (actual hardware did not), by reading in Blocks 4-7
and transfering to the loaded value. RC10, RH10, TM10 support readin mode.
Support for KL10A will be started in the summer.
# Development Simulators.
# Dec KL10
Still in initial coding stages.
Disk
* RH10 RP04/RP06/RP07
* RH10 RS04
* RH20 RP04/RP06/RP07
* RH20 RS04
Tape
* TM10A or B
* RH10 TM03/TU16
* RH20 TM03/TU16
DC10E terminal mux.
Terminals attached to front end processor
IMP networking support for ITS and TENEX.
# ICL 1900 simulator.
This is a new simulator. Will pass 1904E/1905E CPU diagnostics (FLIT). Will boot paper
tape executive E4BM and tape executive E6RM. Still need to add more devices and test
with Goerge 2 and 3.
The CPU can be configured for model A, B or C type system. Or models 1901 throgh 1909.
Paging is currently not supported. Both standard interface and older non-standard interface
are supported on most device.
# IBM 360 simulator.
Currently will run IPL TOS/360, DOS/360, OS/360. TSO support still in progress.
@@ -186,18 +177,14 @@ The current test version is for the SEL 32/27, 32/67, 32/87, 32/97 computers.
Support for 32/55, 32/75, V6, and V9 computers may be added in the future.
This simulator is co-authors with James C. Bevier. I did the initial parts
of the simulator, James took it to a working simulator, I am assisting him
in maintaining and enhancing the simulator.
# SEL Concept/32
This simulator is running a test version of MPX-32 1.5F. It is capable of
creating a disk image of the O/S from a SDT tape. The disk image can be
booted, initialized, and run many of the MPX utilities; including OPCOM & TSM.
Eight terminals can be used to access TSM via Telnet port 4747. Initial
support has been added for excess 64 floating point arithmetic. More testing
is still required. The sim32disk.gz can be uncompressed and booted with the
sel32.27.sim32.disk.ini initialization file. The sim32sdt.tap.gz file can
also be uncompressed and started with the sel32.27.sim32.tape.ini initialization
file to install from tape.
in maintaining and enhancing the simulator. This simulator is running a test
version of MPX-32 1.5F. It is capable of creating a disk image of the O/S
from a SDT tape. The disk image can be booted, initialized, and run many of
the MPX utilities; including OPCOM & TSM. Eight terminals can be used to
access TSM via Telnet port 4747. Initial support has been added for excess
64 floating point arithmetic. More testing is still required. The sim32disk.gz
can be uncompressed and booted with the sel32.27.sim32.disk.ini initialization file.
The sim32sdt.tap.gz file can also be uncompressed and started with the
sel32.27.sim32.tape.ini initialization file to install from tape.

View File

@@ -975,6 +975,18 @@ display_init(enum display_type type, int sf, void *dptr)
fprintf(stderr, "Display initialization failed\r\n");
return 0;
}
void
display_close(void *dptr)
{
if (!initialized)
return;
free (points);
ws_shutdown();
initialized = 0;
}
void
display_reset(void)

View File

@@ -65,6 +65,11 @@ enum display_type {
*/
extern int display_init(enum display_type, int scale, void *dptr);
/*
* close display
*/
extern void display_close(void *dptr);
/* return size of virtual display */
extern int display_xpoints(void);
extern int display_ypoints(void);

Binary file not shown.

Binary file not shown.

BIN
doc/kl10_doc.doc Normal file

Binary file not shown.

View File

@@ -109,8 +109,8 @@ endif
ifneq (,$(or $(findstring pdp6,${MAKECMDGOALS}),$(findstring pdp10-ka,${MAKECMDGOALS}),$(findstring pdp10-ki,${MAKECMDGOALS})))
VIDEO_USEFUL = true
endif
# building the KA10 or KI10 networking can be used.
ifneq (,$(or $(findstring pdp10-ka,${MAKECMDGOALS}),$(findstring pdp10-ki,${MAKECMDGOALS})))
# building the KA10, KI10 or KL10 networking can be used.
ifneq (,$(or $(findstring pdp10-ka,${MAKECMDGOALS}),$(findstring pdp10-ki,${MAKECMDGOALS},$(findstring pdp10-kl,${MAKECMDGOALS}))))
NETWORK_USEFUL = true
endif
# building the PDP-7 needs video support
@@ -2023,13 +2023,13 @@ KA10 = ${KA10D}/kx10_cpu.c ${KA10D}/kx10_sys.c ${KA10D}/kx10_df.c \
${KA10D}/kx10_rp.c ${KA10D}/kx10_rc.c ${KA10D}/kx10_dt.c \
${KA10D}/kx10_dk.c ${KA10D}/kx10_cr.c ${KA10D}/kx10_cp.c \
${KA10D}/kx10_tu.c ${KA10D}/kx10_rs.c ${KA10D}/ka10_pd.c \
${KA10D}/kx10_imp.c ${KA10D}/ka10_tk10.c \
${KA10D}/kx10_rh.c ${KA10D}/kx10_imp.c ${KA10D}/ka10_tk10.c \
${KA10D}/ka10_mty.c ${KA10D}/ka10_imx.c ${KA10D}/ka10_ch10.c \
${KA10D}/ka10_stk.c ${KA10D}/ka10_ten11.c ${KA10D}/ka10_auxcpu.c \
$(KA10D)/ka10_pmp.c ${KA10D}/ka10_dkb.c ${KA10D}/pdp6_dct.c \
${KA10D}/pdp6_dtc.c ${KA10D}/pdp6_mtc.c ${KA10D}/pdp6_dsk.c \
${KA10D}/pdp6_dcs.c ${KA10D}/ka10_dpk.c ${KA10D}/kx10_dpy.c \
${PDP10D}/ka10_ai.c ${DISPLAYL} ${DISPLAY340}
${PDP10D}/ka10_ai.c ${KA10D}/ka10_iii.c ${DISPLAYL} ${DISPLAY340}
KA10_OPT = -DKA=1 -DUSE_INT64 -I ${KA10D} -DUSE_SIM_CARD ${NETWORK_OPT} ${DISPLAY_OPT} ${KA10_DISPLAY_OPT}
ifneq (${PANDA_LIGHTS},)
# ONLY for Panda display.
@@ -2045,7 +2045,7 @@ endif
KI10 = ${KI10D}/kx10_cpu.c ${KI10D}/kx10_sys.c ${KI10D}/kx10_df.c \
${KI10D}/kx10_dp.c ${KI10D}/kx10_mt.c ${KI10D}/kx10_cty.c \
${KI10D}/kx10_lp.c ${KI10D}/kx10_pt.c ${KI10D}/kx10_dc.c \
${KI10D}/kx10_rp.c ${KI10D}/kx10_rc.c \
${KI10D}/kx10_rh.c ${KI10D}/kx10_rp.c ${KI10D}/kx10_rc.c \
${KI10D}/kx10_dt.c ${KI10D}/kx10_dk.c ${KI10D}/kx10_cr.c \
${KI10D}/kx10_cp.c ${KI10D}/kx10_tu.c ${KI10D}/kx10_rs.c \
${KI10D}/kx10_imp.c ${KI10D}/kx10_dpy.c ${DISPLAYL} ${DISPLAY340}
@@ -2057,6 +2057,14 @@ KI10 += ${KA10D}/ka10_lights.c
KI10_LDFLAGS = -lusb-1.0
endif
KL10D = ${SIMHD}/PDP10
KL10 = ${KL10D}/kx10_cpu.c ${KL10D}/kx10_sys.c ${KL10D}/kx10_df.c \
${KL10D}/kx10_mt.c ${KL10D}/kx10_dc.c ${KL10D}/kx10_rh.c \
${KL10D}/kx10_rp.c ${KL10D}/kx10_tu.c ${KL10D}/kx10_rs.c \
${KL10D}/kx10_imp.c ${KL10D}/kl10_fe.c ${KL10D}/ka10_pd.c \
${KL10D}/ka10_ch10.c ${KL10D}/kx10_lp.c ${KL10D}/kl10_nia.c
KL10_OPT = -DKL=1 -DUSE_INT64 -I $(KL10D) -DUSE_SIM_CARD ${NETWORK_OPT}
ATT3B2D = ${SIMHD}/3B2
ATT3B2 = ${ATT3B2D}/3b2_cpu.c ${ATT3B2D}/3b2_mmu.c \
${ATT3B2D}/3b2_iu.c ${ATT3B2D}/3b2_if.c \
@@ -2131,7 +2139,7 @@ ALL = pdp1 pdp4 pdp7 pdp8 pdp9 pdp15 pdp11 pdp10 \
scelbi 3b2 i701 i704 i7010 i7070 i7080 i7090 \
sigma uc15 pdp10-ka pdp10-ki pdp6
ALL = b5500 i701 i704 i7010 i7070 i7080 i7090 pdp10-ka pdp10-ki ibm360 ibm360_32 icl1900 pdp6 sel32
ALL = b5500 i701 i704 i7010 i7070 i7080 i7090 pdp10-ka pdp10-ki pdp10-kl ibm360 ibm360_32 icl1900 pdp6 sel32
all : ${ALL}
@@ -2965,6 +2973,15 @@ ifneq (,$(call find_test,${PDP10D},ki10))
$@ $(call find_test,${PDP10D},ki10) ${TEST_ARG}
endif
pdp10-kl : ${BIN}pdp10-kl${EXE}
${BIN}pdp10-kl${EXE} : ${KL10} ${SIM}
${MKDIRBIN}
${CC} ${KL10} ${SIM} ${KL10_OPT} ${CC_OUTSPEC} ${LDFLAGS}
ifneq (,$(call find_test,${PDP10D},kl10))
$@ $(call find_test,${PDP10D},kl10) ${TEST_ARG}
endif
# Front Panel API Demo/Test program
frontpaneltest : ${BIN}frontpaneltest${EXE}