diff --git a/IBM360/ibm360_chan.c b/IBM360/ibm360_chan.c index fb6aca9..5b6a74c 100644 --- a/IBM360/ibm360_chan.c +++ b/IBM360/ibm360_chan.c @@ -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); diff --git a/IBM360/ibm360_con.c b/IBM360/ibm360_con.c index 3dc586b..93a1acf 100644 --- a/IBM360/ibm360_con.c +++ b/IBM360/ibm360_con.c @@ -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; diff --git a/IBM360/ibm360_cpu.c b/IBM360/ibm360_cpu.c index 0a467eb..98859e3 100644 --- a/IBM360/ibm360_cpu.c +++ b/IBM360/ibm360_cpu.c @@ -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; diff --git a/IBM360/ibm360_dasd.c b/IBM360/ibm360_dasd.c index 83ac5d9..37b2b5e 100644 --- a/IBM360/ibm360_dasd.c +++ b/IBM360/ibm360_dasd.c @@ -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} }; diff --git a/IBM360/ibm360_defs.h b/IBM360/ibm360_defs.h index efb8de7..308af96 100644 --- a/IBM360/ibm360_defs.h +++ b/IBM360/ibm360_defs.h @@ -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 *); diff --git a/IBM360/ibm360_scon.c b/IBM360/ibm360_scon.c index 96475b8..aa54fcb 100644 --- a/IBM360/ibm360_scon.c +++ b/IBM360/ibm360_scon.c @@ -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; diff --git a/IBM360/ibm360_sys.c b/IBM360/ibm360_sys.c index 14e1c88..2f3c6bd 100644 --- a/IBM360/ibm360_sys.c +++ b/IBM360/ibm360_sys.c @@ -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 },