1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-03-04 18:34:53 +00:00

IBM360: Initial commit of IBM370 support.

This commit is contained in:
Richard Cornwell
2020-01-30 23:52:14 -05:00
parent 6e654bde53
commit 38211f6315
6 changed files with 1155 additions and 190 deletions

View File

@@ -79,18 +79,21 @@ extern uint32 *M;
extern uint8 key[MAXMEMSIZE / 2048];
#define MAX_DEV (MAX_CHAN * 256)
#define SEL_BASE (SUB_CHANS * MAX_MUX)
#define CHAN_SZ (SEL_BASE + MAX_CHAN)
int channels = MAX_CHAN;
int subchannels = SUB_CHANS; /* Number of subchannels */
int irq_pend = 0;
uint32 caw[256]; /* Channel command address word */
uint32 ccw_addr[256]; /* Channel address */
uint16 ccw_count[256]; /* Channel count */
uint8 ccw_cmd[256]; /* Channel command and flags */
uint16 ccw_flags[256]; /* Channel flags */
uint16 chan_status[256]; /* Channel status */
uint16 chan_dev[256]; /* Device on channel */
uint32 chan_buf[256]; /* Channel data buffer */
uint8 chan_byte[256]; /* Current byte, dirty/full */
uint32 caw[CHAN_SZ]; /* Channel command address word */
uint32 ccw_addr[CHAN_SZ]; /* Channel address */
uint16 ccw_count[CHAN_SZ]; /* Channel count */
uint8 ccw_cmd[CHAN_SZ]; /* Channel command and flags */
uint16 ccw_flags[CHAN_SZ]; /* Channel flags */
uint16 chan_status[CHAN_SZ]; /* Channel status */
uint16 chan_dev[CHAN_SZ]; /* Device on channel */
uint32 chan_buf[CHAN_SZ]; /* Channel data buffer */
uint8 chan_byte[CHAN_SZ]; /* Current byte, dirty/full */
DIB *dev_unit[MAX_DEV]; /* Pointer to Device info block */
uint8 dev_status[MAX_DEV]; /* last device status flags */
@@ -128,17 +131,40 @@ find_chan_dev(uint16 addr) {
int
find_subchan(uint16 device) {
int chan;
int base = 0;
if (device > MAX_DEV)
return -1;
if (device > 0xff) {
chan = (device >> 8) & 0x7;
if (chan > channels)
return -1;
return subchannels + chan;
chan = (device >> 8) & 0xf;
device &= 0xff;
if (chan > channels)
return -1;
switch(chan) {
case 4:
base += subchannels;
case 0: /* Multiplexer channel */
if (device >= subchannels)
device = ((device - subchannels) >> 4) & 0xf;
return base + device;
case 1: /* Selector channel */
case 2:
case 3:
case 5:
case 6:
case 7:
return SEL_BASE + chan;
}
if (device < subchannels)
return device;
return ((device - subchannels)>>4) & 0xf;
return -1;
}
/* find a channel for a given index */
int
find_chan(int index) {
int chan = 0;
if (index > SEL_BASE)
return index - SEL_BASE;
if (index > subchannels)
return 4;
return 0;
}
/* Read a full word into memory.
@@ -692,11 +718,15 @@ int testio(uint16 addr) {
uint16 status;
/* Find channel this device is on, if no none return cc=3 */
if (chan < 0 || dibp == 0)
if (chan < 0 || dibp == 0) {
sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x cc=3\n", addr, chan);
return 3;
}
uptr = find_chan_dev(addr);
if (uptr == 0)
if (uptr == 0) {
sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x uptr cc=3\n", addr, chan);
return 3;
}
/* If any error pending save csw and return cc=1 */
if (chan_status[chan] & (STATUS_PCI|STATUS_ATTN|STATUS_CHECK|\
@@ -804,7 +834,7 @@ int testchan(uint16 channel) {
return 0;
if (channel > channels)
return 3;
st = chan_status[subchannels + channel];
st = chan_status[SEL_BASE + channel];
if (st & STATUS_BUSY)
return 2;
if (st & (STATUS_ATTN|STATUS_PCI|STATUS_EXPT|STATUS_CHECK|
@@ -870,14 +900,11 @@ scan_chan(uint16 mask) {
return 0;
irq_pend = 0;
/* Start with channel 0 and work through all channels */
for (i = 0; i < subchannels + channels; i++) {
/* If onto channel 1 or above shift mask */
if (i >= subchannels)
imask = imask / 2;
for (i = 0; i < CHAN_SZ; i++) {
/* Check if PCI pending */
if (chan_status[i] & STATUS_PCI) {
sim_debug(DEBUG_EXP, &cpu_dev, "Scan PCI(%x %x %x %x) end\n", i,
imask = 0x8000 >> find_chan(i);
sim_debug(DEBUG_EXP, &cpu_dev, "Scan PCI(%x %x %x %x) end\n", i,
chan_status[i], imask, mask);
if ((imask & mask) != 0) {
pend = chan_dev[i];
@@ -893,9 +920,11 @@ scan_chan(uint16 mask) {
else
irq_pend = 1;
} else {
imask = 0x8000 >> find_chan(i);
sim_debug(DEBUG_EXP, &cpu_dev, "Scan(%x %x %x %x) end\n", i,
chan_status[i], imask, mask);
if ((imask & mask) != 0 || loading != 0) {
if ((chan_status[i] & STATUS_DEND) != 0 &&
(imask & mask) != 0 || loading != 0) {
pend = chan_dev[i];
break;
}
@@ -1048,7 +1077,7 @@ set_dev_addr(UNIT * uptr, int32 val, CONST char *cptr, void *desc)
uptr->u3 |= UNIT_ADDR(devaddr);
fprintf(stderr, "Set dev %s %x\n\r", dptr->name, GET_UADDR(uptr->u3));
} else {
fprintf(stderr, "Set dev %s0 %x\n\r", dptr->name, GET_UADDR(uptr->u3));
fprintf(stderr, "Set dev %s0 %x\n\r", dptr->name, GET_UADDR(uptr->u3));
for (i = 0; i < dibp->numunits; i++) {
dev_unit[devaddr + i] = dibp;
uptr = &((dibp->units)[i]);

File diff suppressed because it is too large Load Diff

View File

@@ -33,6 +33,44 @@
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define MEM_ADDR_OK(x) (((x)) < MEMSIZE)
/* channel:
Channels 0 and 4 are multiplexer channels.
subchannels = 128
0 - 7 0x80-0xff
8 - 127 0x00-0x7f
256 - +6 0x1xx - 0x6xx
subchannels = 192
0 - 3 0xd0-0xff
4 - 192 0x00-0xcf
384 - +6 0x1xx - 0x6xx
Channels 1,2,3,5,6 are selector channels.
Devices on channel 0 below number of subchannels have there own
virtual channel.
Devices on channel 0 above the number of subchannels are mapped in
groups of 16 into channels 0 to n.
Channels 1-n run on channels virtual channels above subchannels.
*/
#define MAX_CHAN 6
#define SUB_CHANS 192
#define MAX_MUX 2
/* Define number of supported units for each device type */
#define NUM_DEVS_CDP 1
#define NUM_DEVS_CDR 1
#define NUM_DEVS_CON 1
#define NUM_DEVS_LPR 1
#define NUM_DEVS_MT 1
#define NUM_UNITS_MT 8
#define NUM_DEVS_DASD 4
#define NUM_UNITS_DASD 8
#define NUM_DEVS_COM 1
#define NUM_UNITS_COM 16
/* Device information block */
typedef struct dib {
uint8 mask; /* Device mask */
@@ -60,15 +98,17 @@ typedef struct dib {
#define GET_UADDR(x) ((UNIT_ADDR_MASK & x) >> UNIT_V_ADDR)
#define UNIT_ADDR(x) ((x) << UNIT_V_ADDR)
/* CPU options, needed by channel */
#define FEAT_PROT (1 << (UNIT_V_UF + 8)) /* Storage protection feature */
#define FEAT_DEC (1 << (UNIT_V_UF + 9)) /* Decimal instruction set */
#define FEAT_FLOAT (1 << (UNIT_V_UF + 10)) /* Floating point instruction set */
#define FEAT_UNIV (3 << (UNIT_V_UF + 9)) /* All instructions */
#define FEAT_STOR (1 << (UNIT_V_UF + 11)) /* No alignment restrictions */
#define FEAT_TIMER (1 << (UNIT_V_UF + 12)) /* Interval timer */
#define FEAT_DAT (1 << (UNIT_V_UF + 13)) /* Dynamic address translation */
#define EXT_IRQ (1 << (UNIT_V_UF_31)) /* External interrupt */
/* CPU options */
#define FEAT_PROT (1 << (UNIT_V_UF + 0)) /* Storage protection feature */
#define FEAT_DEC (1 << (UNIT_V_UF + 1)) /* Decimal instruction set */
#define FEAT_FLOAT (1 << (UNIT_V_UF + 2)) /* Floating point instruction set */
#define FEAT_UNIV (3 << (UNIT_V_UF + 1)) /* All instructions */
#define FEAT_STOR (1 << (UNIT_V_UF + 3)) /* No alignment restrictions */
#define FEAT_TIMER (1 << (UNIT_V_UF + 4)) /* Interval timer */
#define FEAT_DAT (1 << (UNIT_V_UF + 5)) /* Dynamic address translation */
#define FEAT_EFP (1 << (UNIT_V_UF + 6)) /* Extended floating point */
#define FEAT_370 (1 << (UNIT_V_UF + 7)) /* Is a 370 */
#define EXT_IRQ (1 << (UNIT_V_UF + 8)) /* External interrupt */
/* low addresses */
#define IPSW 0x00 /* IPSW */
@@ -98,6 +138,8 @@ typedef struct dib {
#define OP_ISK 0x09
#define OP_SVC 0x0A
#define OP_BASR 0x0D
#define OP_MVCL 0x0E /* 370 Move long */
#define OP_CLCL 0x0F /* 370 Compare logical long */
#define OP_LPR 0x10
#define OP_LNR 0x11
#define OP_LTR 0x12
@@ -220,9 +262,21 @@ typedef struct dib {
#define OP_TIO 0x9D
#define OP_HIO 0x9E
#define OP_TCH 0x9F
#define OP_STMC 0xB0
#define OP_STNSM 0xAC /* 370 Store then and system mask */
#define OP_STOSM 0xAD /* 370 Store then or system mask */
#define OP_SIGP 0xAE /* 370 Signal processor */
#define OP_MC 0xAF /* 370 Monitor call */
#define OP_STMC 0xB0 /* 360/67 Store control */
#define OP_LRA 0xB1
#define OP_LMC 0xB8
#define OP_370 0xB2 /* Misc 370 system instructions */
#define OP_STCTL 0xB6 /* 370 Store control */
#define OP_LCTL 0xB7 /* 370 Load control */
#define OP_LMC 0xB8 /* 360/67 Load Control */
#define OP_CS 0xBA /* 370 Compare and swap */
#define OP_CDS 0xBB /* 370 Compare double and swap */
#define OP_CLM 0xBD /* 370 Compare character under mask */
#define OP_STCM 0xBE /* 370 Store character under mask */
#define OP_ICM 0xBF /* 370 Insert character under mask */
#define OP_MVN 0xD1
#define OP_MVC 0xD2
#define OP_MVZ 0xD3
@@ -234,6 +288,7 @@ typedef struct dib {
#define OP_TRT 0xDD
#define OP_ED 0xDE
#define OP_EDMK 0xDF
#define OP_SRP 0xF0 /* 370 Shift and round decimal */
#define OP_MVO 0xF1
#define OP_PACK 0xF2
#define OP_UNPK 0xF3
@@ -281,23 +336,6 @@ typedef struct dib {
#define STATUS_INTER 0x0002 /* Channel interface check */
#define STATUS_CHAIN 0x0001 /* Channel chain check */
/* channel:
subchannels = 128
0 - 7 0x80-0xff
8 - 127 0x00-0x7f
128 - +6 0x1xx - 0x6xx
Devices on channel 0 below number of subchannels have there own
virtual channel.
Devices on channel 0 above the number of subchannels are mapped in
groups of 16 into channels 0 to n.
Channels 1-n run on channels virtual channels above subchannels.
*/
#define MAX_CHAN 3
#define SUB_CHANS 192
void post_extirq();
/* look up device to find subchannel device is on */
@@ -349,15 +387,4 @@ extern DEVICE coml_dev;
extern DEVICE com_dev;
extern UNIT cpu_unit;
#define NUM_DEVS_CDP 1
#define NUM_DEVS_CDR 1
#define NUM_DEVS_CON 1
#define NUM_DEVS_LPR 1
#define NUM_DEVS_MT 1
#define NUM_UNITS_MT 8
#define NUM_DEVS_DASD 4
#define NUM_UNITS_DASD 8
#define NUM_DEVS_COM 1
#define NUM_UNITS_COM 16
extern void fprint_inst(FILE *, uint16 *);

View File

@@ -247,10 +247,19 @@ lpr_srv(UNIT *uptr) {
return SCPE_OK;
}
if (cmd == 7) {
uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK);
uptr->u6 = 0;
chan_end(addr, SNS_DEVEND|SNS_CHNEND);
return SCPE_OK;
}
if ((uptr->u3 & LPR_FULL) || cmd == 0x3) {
print_line(uptr);
uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK);
uptr->u6 = 0;
if (cmd == 0x3)
chan_end(addr, SNS_CHNEND);
set_devattn(addr, SNS_DEVEND);
return SCPE_OK;
}

View File

@@ -855,6 +855,7 @@ t_stat mt_srv(UNIT * uptr)
sim_debug(DEBUG_DETAIL, dptr, "Unload unit=%d\n", unit);
uptr->u3 &= ~(MT_CMDMSK);
r = sim_tape_detach(uptr);
set_devattn(addr, SNS_DEVEND);
}
break;
}

View File

@@ -205,6 +205,7 @@ typedef struct _opcode {
#define RS 03
#define SI 04
#define SS 05
#define XX 06
#define LNMSK 07
#define ONEOP 010
#define IMDOP 020
@@ -366,11 +367,24 @@ t_opcode optab[] = {
{ OP_SP, "SP", SS|TWOOP },
{ OP_MP, "MP", SS|TWOOP },
{ OP_DP, "DP", SS|TWOOP },
{ OP_MVCL, "MVCL", RR },
{ OP_CLCL, "CLCL", RR },
{ OP_STNSM, "STNSM", SI },
{ OP_STOSM, "STOSM", SI },
{ OP_SIGP, "SIGP", RS },
{ OP_MC, "MC", SI },
{ OP_370, "I370", XX },
{ OP_STCTL, "STCTL", RS },
{ OP_LCTL, "LCTL", RS },
{ OP_CS, "CS", RS },
{ OP_CDS, "CDS", RS },
{ OP_CLM, "CLM", RS },
{ OP_STCM, "STCM", RS },
{ OP_ICM, "ICM", RS },
{ OP_SRP, "SRP", SS|TWOOP },
{ 0, NULL, 0 }
};
void fprint_inst(FILE *of, uint16 *val) {
uint8 inst = (val[0] >> 8) & 0xff;
int i;