mirror of
https://github.com/rcornwell/sims.git
synced 2026-01-26 04:01:16 +00:00
IBM360: Fixes to better handle storage modification bits.
This commit is contained in:
@@ -84,13 +84,7 @@
|
||||
extern uint32 *M;
|
||||
extern uint8 key[MAXMEMSIZE / 2048];
|
||||
|
||||
#define UNIT_V_TYPE (UNIT_V_UF + 0)
|
||||
#define UNIT_SEL (1 << UNIT_V_TYPE) /* Selector channel */
|
||||
#define UNIT_MUX (0 << UNIT_V_TYPE) /* Multiplexer channel */
|
||||
#define UNIT_BMUX (2 << UNIT_V_TYPE) /* Multiplexer channel */
|
||||
#define UNIT_M_TYPE (3 << UNIT_V_TYPE)
|
||||
|
||||
#define UNIT_V_SUBCHAN (UNIT_V_UF + 2)
|
||||
#define UNIT_V_SUBCHAN (UNIT_V_CTYPE + 2)
|
||||
#define UNIT_M_SUBCHAN 0xff
|
||||
#define UNIT_G_SCHAN(x) ((((x) >> UNIT_V_SUBCHAN) & UNIT_M_SUBCHAN) + 1)
|
||||
#define UNIT_SCHAN(x) (((x - 1) & UNIT_M_SUBCHAN) << UNIT_V_SUBCHAN)
|
||||
@@ -103,9 +97,9 @@ t_stat chan_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char
|
||||
const char *chan_description (DEVICE *dptr);
|
||||
|
||||
MTAB chan_mod[] = {
|
||||
{ UNIT_M_TYPE, UNIT_MUX, NULL, "MUX", NULL, NULL, NULL, "Multiplexer channel"},
|
||||
{ UNIT_M_TYPE, UNIT_SEL, NULL, "SEL", NULL, NULL, NULL, "Selector channel"},
|
||||
{ UNIT_M_TYPE, UNIT_BMUX, NULL, "BMUX", NULL, NULL, NULL, "Block Multiplexer channel"},
|
||||
{ UNIT_M_CTYPE, UNIT_MUX, NULL, "MUX", NULL, NULL, NULL, "Multiplexer channel"},
|
||||
{ UNIT_M_CTYPE, UNIT_SEL, NULL, "SEL", NULL, NULL, NULL, "Selector channel"},
|
||||
{ UNIT_M_CTYPE, UNIT_BMUX, NULL, "BMUX", NULL, NULL, NULL, "Block Multiplexer channel"},
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "SUB", "SUB", set_subchan, show_subchan, NULL,
|
||||
"Number of subchannels"},
|
||||
{0}
|
||||
@@ -231,11 +225,11 @@ find_subchan(uint16 device) {
|
||||
uptr = &chan_unit[chan];
|
||||
if ((uptr->flags & UNIT_DIS) != 0)
|
||||
return NULL;
|
||||
if ((uptr->flags & UNIT_M_TYPE) == UNIT_SEL) {
|
||||
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_SEL) {
|
||||
return &(chan_ctl[0]);
|
||||
}
|
||||
device &= 0xff;
|
||||
if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX) {
|
||||
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX) {
|
||||
extern uint32 cregs[16];
|
||||
if ((cpu_unit[0].flags & FEAT_370) != 0 &&
|
||||
(cregs[0] & 0x80000000) != 0) {
|
||||
@@ -1150,13 +1144,13 @@ int testchan(uint16 channel) {
|
||||
}
|
||||
|
||||
/* Multiplexer channels return channel is available */
|
||||
if ((uptr->flags & UNIT_M_TYPE) == UNIT_MUX) {
|
||||
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_MUX) {
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "TCH CC %x cc=0, mux\n", channel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Block Multiplexer channels operating in select mode */
|
||||
if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX) {
|
||||
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX) {
|
||||
extern uint32 cregs[16];
|
||||
if ((cpu_unit[0].flags & FEAT_370) != 0 &&
|
||||
(cregs[0] & 0x80000000) != 0) {
|
||||
@@ -1267,13 +1261,13 @@ scan_chan(uint16 mask, int irq_en) {
|
||||
if ((uptr->flags & UNIT_DIS) != 0)
|
||||
continue;
|
||||
nchan = 1;
|
||||
if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX) {
|
||||
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX) {
|
||||
extern uint32 cregs[16];
|
||||
if ((cpu_unit[0].flags & FEAT_370) != 0 &&
|
||||
(cregs[0] & 0x80000000) != 0) {
|
||||
nchan = 32;
|
||||
}
|
||||
} else if ((uptr->flags & UNIT_M_TYPE) == UNIT_MUX) {
|
||||
} else if ((uptr->flags & UNIT_M_CTYPE) == UNIT_MUX) {
|
||||
nchan = UNIT_G_SCHAN(uptr->flags);
|
||||
}
|
||||
/* Scan all subchannels on this channel */
|
||||
@@ -1386,9 +1380,9 @@ chan_reset(DEVICE * dptr)
|
||||
if (uptr->flags & UNIT_DIS)
|
||||
continue;
|
||||
n = 1;
|
||||
if ((uptr->flags & UNIT_M_TYPE) == UNIT_MUX)
|
||||
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_MUX)
|
||||
n = UNIT_G_SCHAN(uptr->flags)+1;
|
||||
if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX)
|
||||
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX)
|
||||
n = 32;
|
||||
uptr->schans = n;
|
||||
uptr->up7 = calloc(n, sizeof(struct _chanctl));
|
||||
@@ -1425,9 +1419,9 @@ chan_set_devs()
|
||||
continue;
|
||||
}
|
||||
n = 1;
|
||||
if ((uptr->flags & UNIT_M_TYPE) == UNIT_MUX)
|
||||
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_MUX)
|
||||
n = UNIT_G_SCHAN(uptr->flags)+1;
|
||||
if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX)
|
||||
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX)
|
||||
n = 32;
|
||||
/* If no device array, create one */
|
||||
if (uptr->up8 == NULL)
|
||||
@@ -1516,9 +1510,9 @@ show_subchan(FILE * st, UNIT * uptr, int32 v, CONST void *desc)
|
||||
|
||||
if (uptr == NULL)
|
||||
return SCPE_IERR;
|
||||
if ((uptr->flags & UNIT_M_TYPE) == UNIT_SEL) {
|
||||
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_SEL) {
|
||||
fprintf(st, "SEL");
|
||||
} else if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX) {
|
||||
} else if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX) {
|
||||
fprintf(st, "BMUX");
|
||||
} else {
|
||||
n = UNIT_G_SCHAN(uptr->flags);
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#define CON_WR 0x01 /* Write console */
|
||||
#define CON_ACR 0x09 /* Auto carrage return */
|
||||
#define CON_RD 0x0a /* Read console */
|
||||
#define CON_ALR 0x0b /* Control Alarm */
|
||||
#define CON_NOP 0x03 /* No op command */
|
||||
#define CON_MSK 0x0f /* Command mask */
|
||||
|
||||
@@ -174,6 +175,9 @@ uint8 con_startcmd(UNIT *uptr, uint8 cmd) {
|
||||
return 0;
|
||||
|
||||
case 3: /* Control */
|
||||
if (cmd == 0xb) {
|
||||
sim_putchar('\a');
|
||||
}
|
||||
sim_debug(DEBUG_CMD, &con_dev, "%d: Cmd NOP\n", u);
|
||||
if (uptr->CMD & CON_REQ) {
|
||||
uptr->CMD &= ~CON_REQ;
|
||||
|
||||
@@ -609,8 +609,7 @@ TransAddr(uint32 va, uint32 *pa)
|
||||
}
|
||||
|
||||
/* Now we need to fetch the actual entry */
|
||||
addr = (entry & PTE_ADR) + (page << 1);
|
||||
addr &= AMASK;
|
||||
addr = ((entry & PTE_ADR) + (page << 1)) & AMASK;
|
||||
if (addr >= MEMSIZE) {
|
||||
storepsw(OPPSW, IRC_ADDR);
|
||||
return 1;
|
||||
@@ -650,7 +649,7 @@ TransAddr(uint32 va, uint32 *pa)
|
||||
page = (va >> page_shift);
|
||||
entry |= ((page & 0x1f00) << 4) | TLB_VALID;
|
||||
tlb[page & 0xff] = entry;
|
||||
*pa = (va & page_mask) | ((entry & TLB_PHY) << page_shift);
|
||||
*pa = ((va & page_mask) | ((entry & TLB_PHY) << page_shift)) & AMASK;
|
||||
if (*pa >= MEMSIZE) {
|
||||
storepsw(OPPSW, IRC_ADDR);
|
||||
return 1;
|
||||
@@ -688,9 +687,6 @@ ReadFull(uint32 addr, uint32 *data)
|
||||
}
|
||||
}
|
||||
|
||||
/* Update access flag */
|
||||
key[pa >> 11] |= 0x4;
|
||||
|
||||
offset = pa & 0x3;
|
||||
|
||||
/* If not on word boundry and store feature not set */
|
||||
@@ -730,6 +726,10 @@ ReadFull(uint32 addr, uint32 *data)
|
||||
temp >>= 8 * (4 - offset);
|
||||
*data |= temp;
|
||||
}
|
||||
|
||||
/* Update access flag */
|
||||
key[pa >> 11] |= 0x4;
|
||||
|
||||
/* sim_debug(DEBUG_DATA, &cpu_dev, "RD A=%08x %08x\n", addr, *data); */
|
||||
return 0;
|
||||
}
|
||||
@@ -840,7 +840,6 @@ WriteFull(uint32 addr, uint32 data)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
key[pa >> 11] |= 0x6;
|
||||
|
||||
pa2 = pa + 4;
|
||||
/* Check if we handle unaligned access */
|
||||
@@ -874,6 +873,9 @@ WriteFull(uint32 addr, uint32 data)
|
||||
}
|
||||
key[pa2 >> 11] |= 0x6;
|
||||
}
|
||||
|
||||
key[pa >> 11] |= 0x6;
|
||||
|
||||
pa >>= 2;
|
||||
pa2 >>= 2;
|
||||
|
||||
@@ -1017,9 +1019,6 @@ WriteHalf(uint32 addr, uint32 data)
|
||||
}
|
||||
}
|
||||
|
||||
/* Flag as modified */
|
||||
key[pa >> 11] |= 0x6;
|
||||
|
||||
if (offset == 3) {
|
||||
addr += 4;
|
||||
/* Check if in storage area */
|
||||
@@ -1051,8 +1050,10 @@ WriteHalf(uint32 addr, uint32 data)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
key[pa2 >> 11] |= 0x6;
|
||||
}
|
||||
|
||||
key[pa >> 11] |= 0x6;
|
||||
key[pa2 >> 11] |= 0x6;
|
||||
pa >>= 2;
|
||||
pa2 >>= 2;
|
||||
M[pa] &= 0xffffff00;
|
||||
@@ -1061,6 +1062,10 @@ WriteHalf(uint32 addr, uint32 data)
|
||||
M[pa2] |= 0xff000000 & (data << 24);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Flag as modified */
|
||||
key[pa >> 11] |= 0x6;
|
||||
|
||||
pa >>= 2;
|
||||
|
||||
mask = 0xffff;
|
||||
@@ -2346,8 +2351,7 @@ save_dbl:
|
||||
}
|
||||
|
||||
/* Now we need to fetch the actual entry */
|
||||
addr2 = (entry & PTE_ADR) + (page << 1);
|
||||
addr2 &= AMASK;
|
||||
addr2 = ((entry & PTE_ADR) + (page << 1)) & AMASK;
|
||||
if (addr2 >= MEMSIZE) {
|
||||
storepsw(OPPSW, IRC_ADDR);
|
||||
goto supress;
|
||||
@@ -2369,7 +2373,7 @@ save_dbl:
|
||||
|
||||
/* Convert to address */
|
||||
entry >>= pte_shift;
|
||||
addr2 = (addr1 & page_mask) | ((entry & TLB_PHY) << page_shift);
|
||||
addr2 = ((addr1 & page_mask) | ((entry & TLB_PHY) << page_shift)) & AMASK;
|
||||
cc = 0;
|
||||
regs[reg1] = addr2;
|
||||
per_mod |= 1 << reg1;
|
||||
@@ -2963,7 +2967,7 @@ save_dbl:
|
||||
|
||||
case OP_370:
|
||||
if (Q370) {
|
||||
if (reg < 2 || reg > 0x13) {
|
||||
if (reg > 0x13) {
|
||||
storepsw(OPPSW, IRC_OPR);
|
||||
goto supress;
|
||||
}
|
||||
@@ -2975,6 +2979,13 @@ save_dbl:
|
||||
goto supress;
|
||||
}
|
||||
switch(reg) {
|
||||
case 0x0: /* CONCS */
|
||||
/* Connect channel set */
|
||||
case 0x1: /* DISCS */
|
||||
/* Disconnect channel set */
|
||||
cc = 3;
|
||||
break;
|
||||
|
||||
case 0x2: /* STIDP */
|
||||
/* Store CPUID in double word */
|
||||
dest = 100;
|
||||
@@ -2987,15 +2998,18 @@ save_dbl:
|
||||
|
||||
case 0x3: /* STIDC */
|
||||
/* Store channel id */
|
||||
dest = (addr1 >> 8) & 0xff;
|
||||
if (dest > MAX_CHAN) {
|
||||
src1 = (addr1 >> 8) & 0xff;
|
||||
if (src1 > MAX_CHAN) {
|
||||
cc = 3;
|
||||
break;
|
||||
}
|
||||
if (dest == 0 || dest == 4)
|
||||
dest = 0;
|
||||
if ((chan_unit[src1].flags & UNIT_M_CTYPE) == UNIT_MUX) {
|
||||
dest = 0x10000000;
|
||||
else
|
||||
dest = 0;
|
||||
}
|
||||
if ((chan_unit[src1].flags & UNIT_M_CTYPE) == UNIT_BMUX) {
|
||||
dest = 0x20000000;
|
||||
}
|
||||
addr1 = 0xA8;
|
||||
if (WriteFull(addr1, dest))
|
||||
goto supress;
|
||||
@@ -3102,9 +3116,7 @@ save_dbl:
|
||||
storepsw(OPPSW, IRC_OPR);
|
||||
goto supress;
|
||||
}
|
||||
for (addr2 = 0;
|
||||
addr2 < sizeof(tlb)/sizeof(uint32);
|
||||
addr2++)
|
||||
for (addr2 = 0; addr2 < sizeof(tlb)/sizeof(uint32); addr2++)
|
||||
tlb[addr2] = 0;
|
||||
break;
|
||||
case 0x10: /* SPX */
|
||||
@@ -3118,6 +3130,7 @@ save_dbl:
|
||||
goto supress;
|
||||
case 0x13: /* RRB */
|
||||
/* Set storage block reference bit to zero */
|
||||
addr1 &= AMASK;
|
||||
addr1 >>= 11;
|
||||
dest = key[addr1];
|
||||
key[addr1] &= 0xfb; /* Clear reference bit */
|
||||
@@ -3266,6 +3279,7 @@ save_dbl:
|
||||
break;
|
||||
|
||||
case OP_LCTL:
|
||||
temp = 0;
|
||||
if (Q360) {
|
||||
storepsw(OPPSW, IRC_OPR);
|
||||
} else if (flags & PROBLEM) {
|
||||
@@ -3326,12 +3340,10 @@ save_dbl:
|
||||
~page_mask) & AMASK) >> page_shift;
|
||||
intval_en = ((dest & 0x400) != 0);
|
||||
tod_en = ((dest & 0x800) != 0);
|
||||
// temp = 1;
|
||||
break;
|
||||
case 0x1: /* Segment table address and length */
|
||||
for (addr2 = 0;
|
||||
addr2 < sizeof(tlb)/sizeof(uint32);
|
||||
addr2++)
|
||||
tlb[addr2] = 0;
|
||||
temp = 1;
|
||||
seg_addr = dest & AMASK;
|
||||
seg_len = (((dest >> 24) & 0xff) + 1) << 4;
|
||||
break;
|
||||
@@ -3363,6 +3375,11 @@ save_dbl:
|
||||
reg1 &= 0xf;
|
||||
addr1 += 4;
|
||||
};
|
||||
/* Purge TLB if segment pointer updated */
|
||||
if (temp) {
|
||||
for (addr2 = 0; addr2 < sizeof(tlb)/sizeof(uint32); addr2++)
|
||||
tlb[addr2] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -212,19 +212,20 @@ struct disk_t
|
||||
}
|
||||
disk_type[] =
|
||||
{
|
||||
{"2301", 1, 200, 20483, 6, 0x01}, /* 4.1 M */
|
||||
{"2302", 250, 46, 4984, 6, 0x02}, /* 57.32 M 50ms, 120ms/10, 180ms> 10 */
|
||||
{"2303", 80, 10, 4984, 6, 0x03}, /* 4.00 M */
|
||||
{"2305", 48, 8, 14568, 6, 0x05}, /* 5.43 M */
|
||||
{"2305-2",96, 8, 14858, 6, 0x05}, /* 11.26 M */
|
||||
{"2311", 203, 10, 3717, 6, 0x11}, /* 7.32 M 156k/s 30 ms 145 full */
|
||||
{"2314", 202, 20, 7294, 6, 0x14}, /* 29.17 M */
|
||||
{"3330", 410, 19, 13165, 24, 0x30}, /* 100.00 M */
|
||||
{"3330-2",815, 19, 13165, 24, 0x30},
|
||||
{"3340", 349, 12, 8535, 24, 0x40}, /* 34.94 M */
|
||||
{"3340-2",698, 12, 8535, 24, 0x40}, /* 69.89 M */
|
||||
{"3350", 559, 30, 19254, 24, 0x50}, /* 304.80 M */
|
||||
{"5625", 403, 20, 7294, 6, 0x14}, /* 56.00 M */
|
||||
{"2301", 1, 200, 20483, 6, 0x01}, /* 4.1 M */
|
||||
{"2302", 250, 46, 4984, 6, 0x02}, /* 57.32 M 50ms, 120ms/10, 180ms> 10 */
|
||||
{"2303", 80, 10, 4984, 6, 0x03}, /* 4.00 M */
|
||||
{"2305", 48, 8, 14568, 6, 0x05}, /* 5.43 M */
|
||||
{"2305-2" ,96, 8, 14858, 6, 0x05}, /* 11.26 M */
|
||||
{"2311", 203, 10, 3717, 6, 0x11}, /* 7.32 M 156k/s 30 ms 145 full */
|
||||
{"2314", 202, 20, 7294, 6, 0x14}, /* 29.17 M */
|
||||
{"3330", 410, 19, 13165, 24, 0x30}, /* 100.00 M */
|
||||
{"3330-2" ,815, 19, 13165, 24, 0x30}, /* 194.00 M */
|
||||
{"3340", 349, 12, 8535, 24, 0x40}, /* 34.94 M */
|
||||
{"3340-2" ,698, 12, 8535, 24, 0x40}, /* 69.89 M */
|
||||
{"3350", 559, 30, 19254, 24, 0x50}, /* 304.80 M */
|
||||
{"3375", 962, 12, 36000, 24, 0x75}, /* 369.30 M */
|
||||
{"5625", 403, 20, 7294, 6, 0x14}, /* 56.00 M */
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
@@ -299,6 +299,13 @@ typedef struct dib {
|
||||
#define OP_MP 0xFC
|
||||
#define OP_DP 0xFD
|
||||
|
||||
/* Channel type selection */
|
||||
#define UNIT_V_CTYPE (UNIT_V_UF + 0)
|
||||
#define UNIT_SEL (0 << UNIT_V_CTYPE) /* Selector channel */
|
||||
#define UNIT_MUX (1 << UNIT_V_CTYPE) /* Multiplexer channel */
|
||||
#define UNIT_BMUX (2 << UNIT_V_CTYPE) /* Multiplexer channel */
|
||||
#define UNIT_M_CTYPE (3 << UNIT_V_CTYPE)
|
||||
|
||||
/* Channel sense bytes */
|
||||
#define SNS_ATTN 0x80 /* Unit attention */
|
||||
#define SNS_SMS 0x40 /* Status modifier */
|
||||
@@ -393,6 +400,7 @@ extern DEVICE coml_dev;
|
||||
extern DEVICE com_dev;
|
||||
extern DEVICE scoml_dev;
|
||||
extern DEVICE scom_dev;
|
||||
extern UNIT cpu_unit[];
|
||||
extern UNIT cpu_unit[];
|
||||
extern UNIT chan_unit[];
|
||||
|
||||
extern void fprint_inst(FILE *, uint16 *);
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#define CON_WR 0x01 /* Write console */
|
||||
#define CON_ACR 0x09 /* Auto carrage return */
|
||||
#define CON_RD 0x0a /* Read console */
|
||||
#define CON_ALR 0x0b /* Control Alarm */
|
||||
#define CON_NOP 0x03 /* No op command */
|
||||
#define CON_MSK 0x0f /* Command mask */
|
||||
|
||||
@@ -185,6 +186,9 @@ uint8 scon_startcmd(UNIT *uptr, uint8 cmd) {
|
||||
return 0;
|
||||
|
||||
case 3: /* Control */
|
||||
if (cmd == CON_ALR) {
|
||||
tmxr_putc_ln(&scon_ldsc[u], '\a');
|
||||
}
|
||||
sim_debug(DEBUG_CMD, &scon_dev, "%d: Cmd NOP\n", u);
|
||||
if (uptr->CMD & CON_REQ) {
|
||||
uptr->CMD &= ~CON_REQ;
|
||||
|
||||
@@ -407,6 +407,8 @@ t_opcode optab[] = {
|
||||
};
|
||||
|
||||
t_opcode soptab[] = {
|
||||
{ 0x00, "CONCS", RS },
|
||||
{ 0x01, "DISCS", RS },
|
||||
{ 0x02, "STIDP", RS },
|
||||
{ 0x03, "STIDC", RS },
|
||||
{ 0x04, "SCK", RS },
|
||||
|
||||
Reference in New Issue
Block a user