From e7a7f7355496495e516fe3aefcbb04bb74c3de06 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 22 Oct 2020 17:17:00 -0400 Subject: [PATCH] IBM360: Redid channel I/O to support changing channel type. --- IBM360/ibm360_cdp.c | 4 +- IBM360/ibm360_cdr.c | 4 +- IBM360/ibm360_chan.c | 1398 +++++++++++++++++++++++++----------------- IBM360/ibm360_com.c | 10 +- IBM360/ibm360_con.c | 4 +- IBM360/ibm360_cpu.c | 3 +- IBM360/ibm360_dasd.c | 18 +- IBM360/ibm360_defs.h | 19 +- IBM360/ibm360_lpr.c | 31 +- IBM360/ibm360_mt.c | 30 +- IBM360/ibm360_scom.c | 4 +- IBM360/ibm360_sys.c | 29 +- doc/ibm360.doc | Bin 114176 -> 120320 bytes 13 files changed, 940 insertions(+), 614 deletions(-) diff --git a/IBM360/ibm360_cdp.c b/IBM360/ibm360_cdp.c index 8fa02ca..ff6eec5 100644 --- a/IBM360/ibm360_cdp.c +++ b/IBM360/ibm360_cdp.c @@ -77,7 +77,7 @@ cdp_mod Card Punch modifiers list */ -uint8 cdp_startcmd(UNIT *, uint16, uint8); +uint8 cdp_startcmd(UNIT *, uint8); void cdp_ini(UNIT *, t_bool); t_stat cdp_srv(UNIT *); t_stat cdp_reset(DEVICE *); @@ -125,7 +125,7 @@ DEVICE cdp_dev = { * Start the card punch to punch one card. */ -uint8 cdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { +uint8 cdp_startcmd(UNIT *uptr, uint8 cmd) { DEVICE *dptr = find_dev_from_unit(uptr); int unit = (uptr - dptr->units); diff --git a/IBM360/ibm360_cdr.c b/IBM360/ibm360_cdr.c index a31de82..42fdda1 100644 --- a/IBM360/ibm360_cdr.c +++ b/IBM360/ibm360_cdr.c @@ -77,7 +77,7 @@ */ -uint8 cdr_startcmd(UNIT *, uint16, uint8); +uint8 cdr_startcmd(UNIT *, uint8); t_stat cdr_boot(int32, DEVICE *); t_stat cdr_srv(UNIT *); t_stat cdr_reset(DEVICE *); @@ -121,7 +121,7 @@ DEVICE cdr_dev = { /* * Start card reader to read in one card. */ -uint8 cdr_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { +uint8 cdr_startcmd(UNIT *uptr, uint8 cmd) { DEVICE *dptr = find_dev_from_unit(uptr); int unit = (uptr - dptr->units); diff --git a/IBM360/ibm360_chan.c b/IBM360/ibm360_chan.c index 08060d3..057aba3 100644 --- a/IBM360/ibm360_chan.c +++ b/IBM360/ibm360_chan.c @@ -63,6 +63,10 @@ #define STATUS_INTER 0x0002 /* Channel interface check */ #define STATUS_CHAIN 0x0001 /* Channel chain check */ +#define ERROR_STATUS (STATUS_ATTN|STATUS_PCI|STATUS_EXPT|STATUS_CHECK| \ + STATUS_PROT|STATUS_CDATA|STATUS_CCNTL|STATUS_INTER| \ + STATUS_CHAIN) + #define FLAG_CD 0x8000 /* Chain data */ #define FLAG_CC 0x4000 /* Chain command */ #define FLAG_SLI 0x2000 /* Suppress length indicator */ @@ -76,58 +80,130 @@ #define AMASK 0x00ffffff #define PMASK 0xf0000000 /* Storage protection mask */ + extern uint32 *M; extern uint8 key[MAXMEMSIZE / 2048]; -#define MAX_DEV (MAX_CHAN * 256) +#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_V_SUBCHAN (UNIT_V_UF + 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) -#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[CHAN_SZ]; /* Channel command address word */ -uint32 ccw_addr[CHAN_SZ]; /* Channel address */ -uint32 ccw_iaddr[CHAN_SZ]; /* Channel indirect address */ -uint16 ccw_count[CHAN_SZ]; /* Channel count */ -uint8 ccw_cmd[CHAN_SZ]; /* Channel command and flags */ -uint8 ccw_key[CHAN_SZ]; /* Channel key */ -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 */ -uint8 chan_pend[CHAN_SZ]; /* Pending status on this channel */ -DIB *dev_unit[MAX_DEV]; /* Pointer to Device info block */ -uint8 dev_status[MAX_DEV]; /* last device status flags */ +t_stat chan_reset(DEVICE *); +t_stat set_subchan(UNIT * uptr, int32 val, CONST char *cptr, void *desc); +t_stat show_subchan(FILE * st, UNIT * uptr, int32 v, CONST void *desc); + +MTAB chan_mod[] = { + { UNIT_SEL, 0, NULL, "MUX", NULL, NULL, NULL, "Multiplexer channel"}, + { UNIT_SEL, UNIT_SEL, NULL, "SEL", NULL, NULL, NULL, "Selector channel"}, + { MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "SUB", "SUB", set_subchan, show_subchan, NULL, + "Number of subchannels"}, + {0} +}; + +#define SEL_CHAN UNIT_SEL | UNIT_SCHAN(SUB_CHANS) | UNIT_DISABLE +#define MUX_CHAN UNIT_MUX | UNIT_SCHAN(SUB_CHANS) | UNIT_DISABLE + +UNIT chan_unit[] = { + {UDATA(NULL, MUX_CHAN, 0), 0, 0, }, /* 0 */ + {UDATA(NULL, SEL_CHAN, 0), 0, 0, }, /* 1 */ + {UDATA(NULL, SEL_CHAN, 0), 0, 0, }, /* 2 */ + {UDATA(NULL, SEL_CHAN, 0), 0, 0, }, /* 3 */ +#if MAX_CHAN > 3 + {UDATA(NULL, MUX_CHAN|UNIT_DIS, 0), 0, 0, }, /* 4 */ +#endif +#if MAX_CHAN > 4 + {UDATA(NULL, SEL_CHAN|UNIT_DIS, 0), 0, 0, }, /* 5 */ +#endif +#if MAX_CHAN > 5 + {UDATA(NULL, SEL_CHAN|UNIT_DIS, 0), 0, 0, }, /* 6 */ +#endif +#if MAX_CHAN > 6 + {UDATA(NULL, SEL_CHAN|UNIT_DIS, 0), 0, 0, }, /* 7 */ +#endif +#if MAX_CHAN > 7 + {UDATA(NULL, MUX_CHAN|UNIT_DIS, 0), 0, 0, }, /* 8 */ +#endif +#if MAX_CHAN > 8 + {UDATA(NULL, SEL_CHAN|UNIT_DIS, 0), 0, 0, }, /* 9 */ +#endif +#if MAX_CHAN > 9 + {UDATA(NULL, MUX_CHAN|UNIT_DIS, 0), 0, 0, }, /* a */ +#endif +#if MAX_CHAN > 10 + {UDATA(NULL, SEL_CHAN|UNIT_DIS, 0), 0, 0, }, /* b */ +#endif +#if MAX_CHAN > 11 + {UDATA(NULL, SEL_CHAN|UNIT_DIS, 0), 0, 0, }, /* c */ +#endif +#if MAX_CHAN > 12 + {UDATA(NULL, SEL_CHAN|UNIT_DIS, 0), 0, 0, }, /* d */ +#endif +#if MAX_CHAN > 13 + {UDATA(NULL, SEL_CHAN|UNIT_DIS, 0), 0, 0, }, /* e */ +#endif +#if MAX_CHAN > 14 + {UDATA(NULL, SEL_CHAN|UNIT_DIS, 0), 0, 0, }, /* f */ +#endif +}; + +DEVICE chan_dev = { + "CH", chan_unit, NULL, chan_mod, + MAX_CHAN, 8, 15, 1, 8, 8, + NULL, NULL, &chan_reset, NULL, NULL, NULL, + NULL, DEV_DEBUG, 0, dev_debug, +// NULL, NULL, &chan_help, NULL, NULL, &chan_description +}; + +struct _dev { + DIB *dibp; /* Pointer to channel DIB entry */ + UNIT *unit; /* Pointer to the Unit structure */ + uint16 dev_addr; /* Address of device */ +}; + +struct _chanctl { + struct _dev *dev; /* Pointer to dev structure for current dev */ + uint32 caw; /* Channel command address word */ + uint32 ccw_addr; /* Channel address */ + uint32 ccw_iaddr; /* Channel indirect address */ + uint16 ccw_count; /* Channel count */ + uint8 ccw_cmd; /* Channel command and flags */ + uint8 ccw_key; /* Channel key */ + uint32 chan_buf; /* Channel data buffer */ + uint16 ccw_flags; /* Channel flags */ + uint16 chan_status; /* Channel status */ + uint16 daddr; /* Device on channel */ + uint8 chan_byte; /* Current byte, dirty/full */ +}; + +uint8 dev_status[MAX_CHAN * 256]; /* Device status array */ +uint8 chan_pend[MAX_CHAN]; /* Status pending on channel */ + +#define chan_ctl ((struct _chanctl *)(uptr->up7)) +#define dev_tab ((struct _dev *)(uptr->up8)) +#define schans u3 /* Number of subchannels */ /* Find unit pointer for given device */ -UNIT * -find_chan_dev(uint16 addr) { - struct dib *dibp; +struct _dev * +find_device(uint16 addr) { UNIT *uptr; - DEVICE *dptr; - int i; + int chan; - if (addr >= MAX_DEV) + chan = (addr >> 8) & 0xf; + if (chan > MAX_CHAN) return NULL; - dibp = dev_unit[addr]; - if (dibp == 0) + uptr = &chan_unit[chan]; + if ((uptr->flags & UNIT_DIS) != 0) return NULL; - uptr = dibp->units; - dptr = find_dev_from_unit(uptr); - if (dptr == NULL) + + if (uptr->up8 == NULL) return NULL; - if (dptr->flags & DEV_UADDR) { - for (i = 0; i < dibp->numunits; i++) { - if (addr == GET_UADDR(uptr->u3)) - return uptr; - uptr++; - } - } else { - return uptr + (addr & ~dibp->mask & 0xff); - } - return NULL; + return &(dev_tab[addr & 0xff]); } /* channel: @@ -138,48 +214,26 @@ find_chan_dev(uint16 addr) { */ /* look up device to find subchannel device is on */ -int +struct _chanctl * find_subchan(uint16 device) { - int chan; - int base = 0; - if (device >= MAX_DEV) - return -1; + int chan; + UNIT *uptr; + chan = (device >> 8) & 0xf; + if (chan > MAX_CHAN) + return NULL; + uptr = &chan_unit[chan]; + if ((uptr->flags & UNIT_DIS) != 0) + return NULL; + if ((uptr->flags & UNIT_SEL) != 0) + return &(chan_ctl[0]); device &= 0xff; - if (chan > channels) - return -1; - switch(chan) { - case 4: - base += subchannels; - /* Fall through */ - - case 0: /* Multiplexer channel */ - if (device >= subchannels) - device = ((device - subchannels) >> 4) & 0x7; - return base + device; - case 1: /* Selector channel */ - case 2: - case 3: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - return SEL_BASE + chan; + if (device >= uptr->schans) { + if (device >= 128) /* All shared devices over subchannels */ + return NULL; + device = (device >> 4) & 0x7; } - return -1; -} - -/* find a channel for a given index */ -int -find_chan(int chan) { - return (chan_dev[chan] >> 8) & 0xf; + return &(chan_ctl[device]); } /* Read a full word into memory. @@ -187,25 +241,25 @@ find_chan(int chan) { * Return 0 if success. */ int -readfull(int chan, uint32 addr, uint32 *word) { +readfull(struct _chanctl *chan, uint32 addr, uint32 *word) { if ((addr & AMASK) > MEMSIZE) { - chan_status[chan] |= STATUS_PCHK; + chan->chan_status |= STATUS_PCHK; *word = 0; irq_pend = 1; return 1; } addr >>= 2; - if (ccw_key[chan] != 0) { + if (chan->ccw_key != 0) { int k; if ((cpu_unit[0].flags & FEAT_PROT) == 0) { - chan_status[chan] |= STATUS_PROT; + chan->chan_status |= STATUS_PROT; *word = 0; irq_pend = 1; return 1; } k = key[addr >> 9]; - if ((k & 0x8) != 0 && (k & 0xf0) != ccw_key[chan]) { - chan_status[chan] |= STATUS_PROT; + if ((k & 0x8) != 0 && (k & 0xf0) != chan->ccw_key) { + chan->chan_status |= STATUS_PROT; *word = 0; irq_pend = 1; return 1; @@ -221,22 +275,22 @@ readfull(int chan, uint32 addr, uint32 *word) { * Return 0 if success. */ int -readbuff(int chan) { +readbuff(struct _chanctl *chan) { int k; uint32 addr; - if (ccw_flags[chan] & FLAG_IDA && cpu_unit[0].flags & FEAT_370) - addr = ccw_iaddr[chan]; + if (chan->ccw_flags & FLAG_IDA && cpu_unit[0].flags & FEAT_370) + addr = chan->ccw_iaddr; else - addr = ccw_addr[chan]; - if (readfull(chan, addr, &chan_buf[chan])) { - chan_byte[chan] = BUFF_CHNEND; + addr = chan->ccw_addr; + if (readfull(chan, addr, &chan->chan_buf)) { + chan->chan_byte = BUFF_CHNEND; return 1; } - if ((ccw_cmd[chan] & 1) == 1) { - sim_debug(DEBUG_CDATA, &cpu_dev, "Channel write %02x %06x %08x %08x '", - chan, addr, chan_buf[chan], ccw_count[chan]); + if ((chan->ccw_cmd & 1) == 1) { + sim_debug(DEBUG_CDATA, &cpu_dev, "Channel write %03x %03x %08x %08x '", + chan->daddr, addr, chan->chan_buf, chan->ccw_count); for(k = 24; k >= 0; k -= 8) { - unsigned char ch = ebcdic_to_ascii[(chan_buf[chan] >> k) & 0xFF]; + unsigned char ch = ebcdic_to_ascii[(chan->chan_buf >> k) & 0xFF]; if (ch < 0x20 || ch == 0xff) ch = '.'; sim_debug(DEBUG_CDATA, &cpu_dev, "%c", ch); @@ -252,41 +306,41 @@ readbuff(int chan) { * Return 0 if success. */ int -writebuff(int chan) { +writebuff(struct _chanctl *chan) { uint32 addr; int k; - if (ccw_flags[chan] & FLAG_IDA && cpu_unit[0].flags & FEAT_370) - addr = ccw_iaddr[chan]; + if (chan->ccw_flags & FLAG_IDA && cpu_unit[0].flags & FEAT_370) + addr = chan->ccw_iaddr; else - addr = ccw_addr[chan]; + addr = chan->ccw_addr; if ((addr & AMASK) > MEMSIZE) { - chan_status[chan] |= STATUS_PCHK; - chan_byte[chan] = BUFF_CHNEND; + chan->chan_status |= STATUS_PCHK; + chan->chan_byte = BUFF_CHNEND; irq_pend = 1; return 1; } addr >>= 2; - if (ccw_key[chan] != 0) { + if (chan->ccw_key != 0) { if ((cpu_unit[0].flags & FEAT_PROT) == 0) { - chan_status[chan] |= STATUS_PROT; - chan_byte[chan] = BUFF_CHNEND; + chan->chan_status |= STATUS_PROT; + chan->chan_byte = BUFF_CHNEND; irq_pend = 1; return 1; } k = key[addr >> 9]; - if ((k & 0xf0) != ccw_key[chan]) { - chan_status[chan] |= STATUS_PROT; - chan_byte[chan] = BUFF_CHNEND; + if ((k & 0xf0) != chan->ccw_key) { + chan->chan_status |= STATUS_PROT; + chan->chan_byte = BUFF_CHNEND; irq_pend = 1; return 1; } } key[addr >> 9] |= 0x6; - M[addr] = chan_buf[chan]; - sim_debug(DEBUG_CDATA, &cpu_dev, "Channel readf %02x %06x %08x %08x '", - chan, addr << 2, chan_buf[chan], ccw_count[chan]); + M[addr] = chan->chan_buf; + sim_debug(DEBUG_CDATA, &cpu_dev, "Channel readf %03x %06x %08x %08x '", + chan->daddr, addr << 2, chan->chan_buf, chan->ccw_count); for(k = 24; k >= 0; k -= 8) { - unsigned char ch = ebcdic_to_ascii[(chan_buf[chan] >> k) & 0xFF]; + unsigned char ch = ebcdic_to_ascii[(chan->chan_buf >> k) & 0xFF]; if (ch < 0x20 || ch == 0xff) ch = '.'; sim_debug(DEBUG_CDATA, &cpu_dev, "%c", ch); @@ -299,110 +353,129 @@ writebuff(int chan) { * Load in the next CCW, return 1 if failure, 0 if success. */ int -load_ccw(uint16 chan, int tic_ok) { +load_ccw(struct _chanctl *chan, int tic_ok) { uint32 word; int cmd = 0; - UNIT *uptr; loop: /* Abort if channel not on double boundry */ - if ((caw[chan] & 0x7) != 0) { - chan_status[chan] |= STATUS_PCHK; + if ((chan->caw & 0x7) != 0) { + chan->chan_status |= STATUS_PCHK; return 1; } /* Abort if we have any errors */ - if (chan_status[chan] & 0x7f) + if (chan->chan_status & 0x7f) return 1; /* Check if we have status modifier set */ - if (chan_status[chan] & STATUS_MOD) { - caw[chan]+=8; - caw[chan] &= PMASK|AMASK; /* Mask overflow bits */ - chan_status[chan] &= ~STATUS_MOD; + if (chan->chan_status & STATUS_MOD) { + chan->caw+=8; + chan->caw &= PMASK|AMASK; /* Mask overflow bits */ + chan->chan_status &= ~STATUS_MOD; } /* Read in next CCW */ - readfull(chan, caw[chan], &word); - sim_debug(DEBUG_CMD, &cpu_dev, "Channel read ccw %02x %06x %08x\n", - chan, caw[chan], word); + readfull(chan, chan->caw, &word); + sim_debug(DEBUG_CMD, &cpu_dev, "Channel read ccw %03x %06x %08x\n", + chan->daddr, chan->caw, word); /* TIC can't follow TIC nor be first in chain */ if (((word >> 24) & 0xf) == CMD_TIC) { if (tic_ok) { - caw[chan] = (caw[chan] & PMASK) | (word & AMASK); + chan->caw = (chan->caw & PMASK) | (word & AMASK); tic_ok = 0; goto loop; } - chan_status[chan] |= STATUS_PCHK; + chan->chan_status |= STATUS_PCHK; irq_pend = 1; return 1; } - caw[chan] += 4; - caw[chan] &= AMASK; /* Mask overflow bits */ + chan->caw += 4; + chan->caw &= AMASK; /* Mask overflow bits */ /* Check if not chaining data */ - if ((ccw_flags[chan] & FLAG_CD) == 0) { - ccw_cmd[chan] = (word >> 24) & 0xff; + if ((chan->ccw_flags & FLAG_CD) == 0) { + chan->ccw_cmd = (word >> 24) & 0xff; cmd = 1; } /* Set up for this command */ - ccw_addr[chan] = word & AMASK; - readfull(chan, caw[chan], &word); - sim_debug(DEBUG_CMD, &cpu_dev, "Channel read ccw2 %02x %06x %08x\n", - chan, caw[chan], word); - caw[chan]+=4; - caw[chan] &= AMASK; /* Mask overflow bits */ - ccw_count[chan] = word & 0xffff; + chan->ccw_addr = word & AMASK; + readfull(chan, chan->caw, &word); + sim_debug(DEBUG_CMD, &cpu_dev, "Channel read ccw2 %03x %06x %08x\n", + chan->daddr, chan->caw, word); + chan->caw+=4; + chan->caw &= AMASK; /* Mask overflow bits */ + chan->ccw_count = word & 0xffff; /* Copy SLI indicator on CD command */ - if ((ccw_flags[chan] & (FLAG_CD|FLAG_SLI)) == (FLAG_CD|FLAG_SLI)) + if ((chan->ccw_flags & (FLAG_CD|FLAG_SLI)) == (FLAG_CD|FLAG_SLI)) word |= (FLAG_SLI<<16); - ccw_flags[chan] = (word >> 16) & 0xff00; - chan_byte[chan] = BUFF_EMPTY; + chan->ccw_flags = (word >> 16) & 0xff00; + chan->chan_byte = BUFF_EMPTY; /* Check invalid count */ - if (ccw_count[chan] == 0) { - chan_status[chan] |= STATUS_PCHK; - ccw_cmd[chan] = 0; + if (chan->ccw_count == 0) { + chan->chan_status |= STATUS_PCHK; + chan->ccw_cmd = 0; irq_pend = 1; return 1; } - if (ccw_flags[chan] & FLAG_IDA && cpu_unit[0].flags & FEAT_370) { - readfull(chan, ccw_addr[chan], &word); - ccw_iaddr[chan] = word & AMASK; - sim_debug(DEBUG_DETAIL, &cpu_dev, "Channel fetch idaw %02x %08x\n", - chan, ccw_iaddr[chan]); + if (chan->ccw_flags & FLAG_IDA && cpu_unit[0].flags & FEAT_370) { + readfull(chan, chan->ccw_addr, &word); + chan->ccw_iaddr = word & AMASK; + sim_debug(DEBUG_DETAIL, &cpu_dev, "Channel fetch idaw %03x %08x\n", + chan->daddr, chan->ccw_iaddr); } if (cmd) { - DIB *dibp = dev_unit[chan_dev[chan]]; + struct _dev *dev = chan->dev; + DIB *dibp; + UNIT *uptr; + /* Check if invalid command */ - if ((ccw_cmd[chan] & 0xF) == 0) { - chan_status[chan] |= STATUS_PCHK; - ccw_cmd[chan] = 0; + if ((chan->ccw_cmd & 0xF) == 0) { + chan->chan_status |= STATUS_PCHK; + chan->ccw_cmd = 0; irq_pend = 1; return 1; } - uptr = find_chan_dev(chan_dev[chan]); - if (uptr == 0) + if (dev == NULL) return 1; - chan_status[chan] &= 0xff; - chan_status[chan] |= dibp->start_cmd(uptr, chan, ccw_cmd[chan]) << 8; - if (chan_status[chan] & (STATUS_ATTN|STATUS_CHECK|STATUS_EXPT)) { + uptr = dev->unit; + dibp = dev->dibp; + if (uptr == NULL || dibp == NULL) + return 1; + chan->chan_status &= 0xff; + chan->chan_status |= dibp->start_cmd(uptr, chan->ccw_cmd) << 8; + if (chan->chan_status & STATUS_BUSY) { + sim_debug(DEBUG_DETAIL, &cpu_dev, "Channel %03x busy\n", + chan->daddr); + } + + if (chan->chan_status & (STATUS_ATTN|STATUS_CHECK|STATUS_EXPT)) { sim_debug(DEBUG_DETAIL, &cpu_dev, "Channel %03x abort %04x\n", - chan, chan_status[chan]); - chan_status[chan] |= STATUS_CEND; - ccw_flags[chan] = 0; - ccw_cmd[chan] = 0; + chan->daddr, chan->chan_status); + chan->chan_status |= STATUS_CEND; + chan->ccw_flags = 0; + chan->ccw_cmd = 0; irq_pend = 1; return 1; } - if (chan_status[chan] & (STATUS_DEND|STATUS_CEND)) { - chan_status[chan] |= STATUS_CEND; - ccw_cmd[chan] = 0; + /* Check if immediate channel end */ + if (chan->chan_status & STATUS_CEND) { + chan->ccw_cmd = 0; + if ((chan->chan_status & SNS_DEVEND) != 0) + chan->ccw_flags &= ~(FLAG_CD|FLAG_SLI); + + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end(%x load) %x %04x end\n", + chan->daddr, chan->chan_status, chan->ccw_flags); + } + if (chan->chan_status & (STATUS_DEND|STATUS_CEND)) { + chan->chan_status |= STATUS_CEND; + chan->ccw_cmd = 0; irq_pend = 1; - if ((ccw_flags[chan] & (FLAG_CD|FLAG_CC)) == 0) + if ((chan->ccw_flags & (FLAG_CD|FLAG_CC)) == 0) return 1; /* No chain? Give imm. SIO response. */ } } - if (ccw_flags[chan] & FLAG_PCI) { - chan_status[chan] |= STATUS_PCI; - ccw_flags[chan] &= ~FLAG_PCI; + if (chan->ccw_flags & FLAG_PCI) { + chan->chan_status |= STATUS_PCI; + chan->ccw_flags &= ~FLAG_PCI; irq_pend = 1; - sim_debug(DEBUG_CMD, &cpu_dev, "Set PCI %02x load\n", chan); + sim_debug(DEBUG_CMD, &cpu_dev, "Set PCI %03x load\n", chan->daddr); } return 0; } @@ -411,28 +484,28 @@ loop: /* read byte from memory */ int chan_read_byte(uint16 addr, uint8 *data) { - int chan = find_subchan(addr); - int byte; + struct _chanctl *chan = find_subchan(addr); + int byte; /* Abort if we have any errors */ - if (chan < 0) + if (chan == NULL) return 1; - if (chan_status[chan] & 0x7f) + if (chan->chan_status & 0x7f) return 1; - if ((ccw_cmd[chan] & 0x1) == 0) { + if ((chan->ccw_cmd & 0x1) == 0) { return 1; } /* Check if finished transfer */ - if (chan_byte[chan] == BUFF_CHNEND) + if (chan->chan_byte == BUFF_CHNEND) return 1; /* Check if count is zero */ - if (ccw_count[chan] == 0) { + if (chan->ccw_count == 0) { /* If not data channing, let device know there will be no * more data to come */ - if ((ccw_flags[chan] & FLAG_CD) == 0) { - chan_status[chan] |= STATUS_CEND; - chan_byte[chan] = BUFF_CHNEND; + if ((chan->ccw_flags & FLAG_CD) == 0) { + chan->chan_status |= STATUS_CEND; + chan->chan_byte = BUFF_CHNEND; sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_read_end\n"); return 1; } else { @@ -442,33 +515,33 @@ chan_read_byte(uint16 addr, uint8 *data) { } } /* Read in next work if buffer is in empty status */ - if (chan_byte[chan] == BUFF_EMPTY) { + if (chan->chan_byte == BUFF_EMPTY) { if (readbuff(chan)) return 1; - if (ccw_flags[chan] & FLAG_IDA && cpu_unit[0].flags & FEAT_370) { - chan_byte[chan] = ccw_iaddr[chan] & 0x3; - ccw_iaddr[chan] += 4 - chan_byte[chan]; - if ((ccw_iaddr[chan] & 0x7ff) == 0) { + if (chan->ccw_flags & FLAG_IDA && cpu_unit[0].flags & FEAT_370) { + chan->chan_byte = chan->ccw_iaddr & 0x3; + chan->ccw_iaddr += 4 - chan->chan_byte; + if ((chan->ccw_iaddr & 0x7ff) == 0) { uint32 temp; - ccw_addr[chan] += 4; - readfull(chan, ccw_addr[chan], &temp); - ccw_iaddr[chan] = temp & AMASK; - sim_debug(DEBUG_DETAIL, &cpu_dev, "Channel fetch idaw %02x %08x\n", - chan, ccw_iaddr[chan]); + chan->ccw_addr += 4; + readfull(chan, chan->ccw_addr, &temp); + chan->ccw_iaddr = temp & AMASK; + sim_debug(DEBUG_DETAIL, &cpu_dev, "Channel fetch idaw %03x %08x\n", + chan->daddr, chan->ccw_iaddr); } } else { - chan_byte[chan] = ccw_addr[chan] & 0x3; - ccw_addr[chan] += 4 - chan_byte[chan]; + chan->chan_byte = chan->ccw_addr & 0x3; + chan->ccw_addr += 4 - chan->chan_byte; } } /* Return current byte */ - ccw_count[chan]--; - byte = (chan_buf[chan] >> (8 * (3 - (chan_byte[chan] & 0x3)))) & 0xff; - chan_byte[chan]++; + chan->ccw_count--; + byte = (chan->chan_buf >> (8 * (3 - (chan->chan_byte & 0x3)))) & 0xff; + chan->chan_byte++; *data = byte; /* If count is zero and chainging load in new CCW */ - if (ccw_count[chan] == 0 && (ccw_flags[chan] & FLAG_CD) != 0) { - chan_byte[chan] = BUFF_EMPTY; + if (chan->ccw_count == 0 && (chan->ccw_flags & FLAG_CD) != 0) { + chan->chan_byte = BUFF_EMPTY; /* Try and grab next CCW */ if (load_ccw(chan, 1)) return 1; @@ -479,40 +552,40 @@ chan_read_byte(uint16 addr, uint8 *data) { /* write byte to memory */ int chan_write_byte(uint16 addr, uint8 *data) { - int chan = find_subchan(addr); - int offset; - uint32 mask; + struct _chanctl *chan = find_subchan(addr); + int offset; + uint32 mask; /* Abort if we have any errors */ - if (chan < 0) + if (chan == NULL) return 1; - if (chan_status[chan] & 0x7f) + if (chan->chan_status & 0x7f) return 1; - if ((ccw_cmd[chan] & 0x1) != 0) { + if ((chan->ccw_cmd & 0x1) != 0) { return 1; } /* Check if at end of transfer */ - if (chan_byte[chan] == BUFF_CHNEND) { - if ((ccw_flags[chan] & FLAG_SLI) == 0) { - chan_status[chan] |= STATUS_LENGTH; + if (chan->chan_byte == BUFF_CHNEND) { + if ((chan->ccw_flags & FLAG_SLI) == 0) { + chan->chan_status |= STATUS_LENGTH; } return 1; } /* Check if count is zero */ - if (ccw_count[chan] == 0) { + if (chan->ccw_count == 0) { /* Flush the buffer if we got anything back. */ - if (chan_byte[chan] & BUFF_DIRTY) { + if (chan->chan_byte & BUFF_DIRTY) { if (writebuff(chan)) return 1; } /* If not data channing, let device know there will be no * more data to come */ - if ((ccw_flags[chan] & FLAG_CD) == 0) { - chan_byte[chan] = BUFF_CHNEND; - if ((ccw_flags[chan] & FLAG_SLI) == 0) { + if ((chan->ccw_flags & FLAG_CD) == 0) { + chan->chan_byte = BUFF_CHNEND; + if ((chan->ccw_flags & FLAG_SLI) == 0) { sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_ length\n"); - chan_status[chan] |= STATUS_LENGTH; + chan->chan_status |= STATUS_LENGTH; } sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_end\n"); return 1; @@ -522,101 +595,101 @@ chan_write_byte(uint16 addr, uint8 *data) { return 1; } /* If we are skipping, just adjust count */ - if (ccw_flags[chan] & FLAG_SKIP) { - ccw_count[chan]--; - chan_byte[chan] = BUFF_EMPTY; - if (ccw_flags[chan] & FLAG_IDA && cpu_unit[0].flags & FEAT_370) { - if ((ccw_cmd[chan] & 0xf) == CMD_RDBWD) { - ccw_iaddr[chan]--; - if ((ccw_iaddr[chan] & 0x7ff) == 0x7ff) { + if (chan->ccw_flags & FLAG_SKIP) { + chan->ccw_count--; + chan->chan_byte = BUFF_EMPTY; + if (chan->ccw_flags & FLAG_IDA && cpu_unit[0].flags & FEAT_370) { + if ((chan->ccw_cmd & 0xf) == CMD_RDBWD) { + chan->ccw_iaddr--; + if ((chan->ccw_iaddr & 0x7ff) == 0x7ff) { uint32 temp; - ccw_addr[chan] += 4; - readfull(chan, ccw_addr[chan], &temp); - ccw_iaddr[chan] = temp & AMASK; - sim_debug(DEBUG_DETAIL, &cpu_dev, "Channel fetch idaw %02x %08x\n", - chan, ccw_iaddr[chan]); + chan->ccw_addr += 4; + readfull(chan, chan->ccw_addr, &temp); + chan->ccw_iaddr = temp & AMASK; + sim_debug(DEBUG_DETAIL, &cpu_dev, "Channel fetch idaw %03x %08x\n", + chan->daddr, chan->ccw_iaddr); } } else { - ccw_iaddr[chan]++; - if ((ccw_iaddr[chan] & 0x7ff) == 0) { + chan->ccw_iaddr++; + if ((chan->ccw_iaddr & 0x7ff) == 0) { uint32 temp; - ccw_addr[chan] += 4; - readfull(chan, ccw_addr[chan], &temp); - ccw_iaddr[chan] = temp & AMASK; - sim_debug(DEBUG_DETAIL, &cpu_dev, "Channel fetch idaw %02x %08x\n", - chan, ccw_iaddr[chan]); + chan->ccw_addr += 4; + readfull(chan, chan->ccw_addr, &temp); + chan->ccw_iaddr = temp & AMASK; + sim_debug(DEBUG_DETAIL, &cpu_dev, "Channel fetch idaw %03x %08x\n", + chan->daddr, chan->ccw_iaddr); } } } else { - if ((ccw_cmd[chan] & 0xf) == CMD_RDBWD) - ccw_addr[chan]--; + if ((chan->ccw_cmd & 0xf) == CMD_RDBWD) + chan->ccw_addr--; else - ccw_addr[chan]++; + chan->ccw_addr++; } return 0; } /* Check if we need to save what we have */ - if (chan_byte[chan] == (BUFF_EMPTY|BUFF_DIRTY)) { + if (chan->chan_byte == (BUFF_EMPTY|BUFF_DIRTY)) { if (writebuff(chan)) return 1; - if (ccw_flags[chan] & FLAG_IDA && cpu_unit[0].flags & FEAT_370) { - if ((ccw_cmd[chan] & 0xf) == CMD_RDBWD) { - ccw_iaddr[chan] -= 1 + (ccw_iaddr[chan] & 0x3); - if ((ccw_iaddr[chan] & 0x7ff) == 0x7fc) { + if (chan->ccw_flags & FLAG_IDA && cpu_unit[0].flags & FEAT_370) { + if ((chan->ccw_cmd & 0xf) == CMD_RDBWD) { + chan->ccw_iaddr -= 1 + (chan->ccw_iaddr & 0x3); + if ((chan->ccw_iaddr & 0x7ff) == 0x7fc) { uint32 temp; - ccw_addr[chan] += 4; - readfull(chan, ccw_addr[chan], &temp); - ccw_iaddr[chan] = temp & AMASK; - sim_debug(DEBUG_DETAIL, &cpu_dev, "Channel fetch idaw %02x %08x\n", - chan, ccw_iaddr[chan]); + chan->ccw_addr += 4; + readfull(chan, chan->ccw_addr, &temp); + chan->ccw_iaddr = temp & AMASK; + sim_debug(DEBUG_DETAIL, &cpu_dev, "Channel fetch idaw %03x %08x\n", + chan->daddr, chan->ccw_iaddr); } } else { - ccw_iaddr[chan] += 4 - (ccw_iaddr[chan] & 0x3); - if ((ccw_iaddr[chan] & 0x7ff) == 0) { + chan->ccw_iaddr += 4 - (chan->ccw_iaddr & 0x3); + if ((chan->ccw_iaddr & 0x7ff) == 0) { uint32 temp; - ccw_addr[chan] += 4; - readfull(chan, ccw_addr[chan], &temp); - ccw_iaddr[chan] = temp & AMASK; - sim_debug(DEBUG_DETAIL, &cpu_dev, "Channel fetch idaw %02x %08x\n", - chan, ccw_iaddr[chan]); + chan->ccw_addr += 4; + readfull(chan, chan->ccw_addr, &temp); + chan->ccw_iaddr = temp & AMASK; + sim_debug(DEBUG_DETAIL, &cpu_dev, "Channel fetch idaw %03x %08x\n", + chan->daddr, chan->ccw_iaddr); } } } else { - if ((ccw_cmd[chan] & 0xf) == CMD_RDBWD) - ccw_addr[chan] -= 1 + (ccw_addr[chan] & 0x3); + if ((chan->ccw_cmd & 0xf) == CMD_RDBWD) + chan->ccw_addr -= 1 + (chan->ccw_addr & 0x3); else - ccw_addr[chan] += 4 - (ccw_addr[chan] & 0x3); + chan->ccw_addr += 4 - (chan->ccw_addr & 0x3); } - chan_byte[chan] = BUFF_EMPTY; + chan->chan_byte = BUFF_EMPTY; } - if (chan_byte[chan] == BUFF_EMPTY) { + if (chan->chan_byte == BUFF_EMPTY) { if (readbuff(chan)) return 1; - if (ccw_flags[chan] & FLAG_IDA && cpu_unit[0].flags & FEAT_370) - chan_byte[chan] = ccw_iaddr[chan] & 0x3; + if (chan->ccw_flags & FLAG_IDA && cpu_unit[0].flags & FEAT_370) + chan->chan_byte = chan->ccw_iaddr & 0x3; else - chan_byte[chan] = ccw_addr[chan] & 0x3; + chan->chan_byte = chan->ccw_addr & 0x3; } /* Store it in buffer and adjust pointer */ - ccw_count[chan]--; - offset = 8 * (chan_byte[chan] & 0x3); + chan->ccw_count--; + offset = 8 * (chan->chan_byte & 0x3); mask = 0xff000000 >> offset; - chan_buf[chan] &= ~mask; - chan_buf[chan] |= ((uint32)(*data)) << (24 - offset); - if ((ccw_cmd[chan] & 0xf) == CMD_RDBWD) { - if (chan_byte[chan] & 0x3) - chan_byte[chan]--; + chan->chan_buf &= ~mask; + chan->chan_buf |= ((uint32)(*data)) << (24 - offset); + if ((chan->ccw_cmd & 0xf) == CMD_RDBWD) { + if (chan->chan_byte & 0x3) + chan->chan_byte--; else - chan_byte[chan] = BUFF_EMPTY; + chan->chan_byte = BUFF_EMPTY; } else - chan_byte[chan]++; - chan_byte[chan] |= BUFF_DIRTY; + chan->chan_byte++; + chan->chan_byte |= BUFF_DIRTY; /* If count is zero and chainging load in new CCW */ - if (ccw_count[chan] == 0 && (ccw_flags[chan] & FLAG_CD) != 0) { + if (chan->ccw_count == 0 && (chan->ccw_flags & FLAG_CD) != 0) { /* Flush buffer */ if (writebuff(chan)) return 1; - chan_byte[chan] = BUFF_EMPTY; + chan->chan_byte = BUFF_EMPTY; /* Try and grab next CCW */ if (load_ccw(chan, 1)) return 1; @@ -629,19 +702,20 @@ chan_write_byte(uint16 addr, uint8 *data) { */ void set_devattn(uint16 addr, uint8 flags) { - int chan = find_subchan(addr); + struct _chanctl *chan = find_subchan(addr); - if (chan < 0) + if (chan == NULL) return; - if (chan_dev[chan] == addr && (chan_status[chan] & STATUS_CEND) != 0 && + /* Check if device is current on channel */ + if (chan->daddr == addr && (chan->chan_status & STATUS_CEND) != 0 && (flags & SNS_DEVEND) != 0) { - chan_status[chan] |= ((uint16)flags) << 8; + chan->chan_status |= ((uint16)flags) << 8; } else { dev_status[addr] = flags; - chan_pend[chan] = 1; + chan_pend[(addr >> 8) & 0xf]= 1; } sim_debug(DEBUG_EXP, &cpu_dev, "set_devattn(%x, %x) %x\n", - addr, flags, chan_dev[chan]); + addr, flags, chan->daddr); irq_pend = 1; } @@ -650,61 +724,62 @@ set_devattn(uint16 addr, uint8 flags) { */ void chan_end(uint16 addr, uint8 flags) { - int chan = find_subchan(addr); + struct _chanctl *chan = find_subchan(addr); - if (chan < 0) + if (chan == NULL) return; sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end(%x, %x) %x %04x %04x\n", addr, flags, - ccw_count[chan], ccw_flags[chan], chan_status[chan]); + chan->ccw_count, chan->ccw_flags, chan->chan_status); /* Flush buffer if there was any change */ - if (chan_byte[chan] & BUFF_DIRTY) { + if (chan->chan_byte & BUFF_DIRTY) { (void)(writebuff(chan)); - chan_byte[chan] = BUFF_EMPTY; + chan->chan_byte = BUFF_EMPTY; } - chan_status[chan] |= STATUS_CEND; - chan_status[chan] |= ((uint16)flags) << 8; - ccw_cmd[chan] = 0; + chan->chan_status |= STATUS_CEND; + chan->chan_status |= ((uint16)flags) << 8; + chan->ccw_cmd = 0; /* If count not zero and not suppressing length, report error */ - if (ccw_count[chan] != 0 && (ccw_flags[chan] & FLAG_SLI) == 0) { + if (chan->ccw_count != 0 && (chan->ccw_flags & FLAG_SLI) == 0) { sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end length\n"); - chan_status[chan] |= STATUS_LENGTH; - ccw_flags[chan] = 0; + chan->chan_status |= STATUS_LENGTH; + chan->ccw_flags = 0; } - if (ccw_count[chan] != 0 && (ccw_flags[chan] & (FLAG_CD|FLAG_SLI)) == (FLAG_CD|FLAG_SLI)) { + if (chan->ccw_count != 0 && (chan->ccw_flags & (FLAG_CD|FLAG_SLI)) == (FLAG_CD|FLAG_SLI)) { sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end length 2\n"); - chan_status[chan] |= STATUS_LENGTH; + chan->chan_status |= STATUS_LENGTH; } if (flags & (SNS_ATTN|SNS_UNITCHK|SNS_UNITEXP)) - ccw_flags[chan] = 0; + chan->ccw_flags = 0; if ((flags & SNS_DEVEND) != 0) - ccw_flags[chan] &= ~(FLAG_CD|FLAG_SLI); + chan->ccw_flags &= ~(FLAG_CD|FLAG_SLI); +// dev_status[addr] = 0; irq_pend = 1; sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end(%x, %x) %x %04x end\n", addr, flags, - chan_status[chan], ccw_flags[chan]); + chan->chan_status, chan->ccw_flags); } /* * Save full csw. */ void -store_csw(uint16 chan) { - M[0x40 >> 2] = caw[chan]; - M[0x44 >> 2] = (((uint32)ccw_count[chan])) | ((uint32)chan_status[chan]<<16); +store_csw(struct _chanctl *chan) { + M[0x40 >> 2] = chan->caw; + M[0x44 >> 2] = (((uint32)chan->ccw_count)) | ((uint32)chan->chan_status<<16); key[0] |= 0x6; - if (chan_status[chan] & STATUS_PCI) { - chan_status[chan] &= ~STATUS_PCI; - sim_debug(DEBUG_CMD, &cpu_dev, "Clr PCI %02x store\n", chan); + if (chan->chan_status & STATUS_PCI) { + chan->chan_status &= ~STATUS_PCI; + sim_debug(DEBUG_CMD, &cpu_dev, "Clr PCI %02x store\n", chan->daddr); } else { - chan_status[chan] = 0; + chan->chan_status = 0; } - ccw_flags[chan] &= ~FLAG_PCI; - sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %02x %06x %08x\n", - chan, M[0x40>>2], M[0x44 >> 2]); + chan->ccw_flags &= ~FLAG_PCI; + sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %03x %06x %08x\n", + chan->daddr, M[0x40>>2], M[0x44 >> 2]); } /* @@ -712,98 +787,104 @@ store_csw(uint16 chan) { */ int startio(uint16 addr) { - int chan = find_subchan(addr); - DIB *dibp = NULL; - UNIT *uptr; + struct _dev *dev = find_device(addr); + struct _chanctl *chan = find_subchan(addr); + DIB *dibp = NULL; + UNIT *uptr; + uint16 status; - if (addr < MAX_DEV) - dibp = dev_unit[addr]; + if (dev == NULL || chan == NULL) { + sim_debug(DEBUG_CMD, &cpu_dev, "SIO %x cc=3\n", addr); + return 3; + } + + dibp = dev->dibp; + uptr = dev->unit; /* Find channel this device is on, if no none return cc=3 */ - if (chan < 0 || dibp == NULL) { - sim_debug(DEBUG_CMD, &cpu_dev, "SIO %x %x cc=3\n", addr, chan); - return 3; - } - uptr = find_chan_dev(addr); - if (uptr == 0) { - sim_debug(DEBUG_CMD, &cpu_dev, "SIO u %x %x cc=3\n", addr, chan); + if (dibp == NULL || uptr == NULL) { + sim_debug(DEBUG_CMD, &cpu_dev, "SIO %x cc=3\n", addr); return 3; } - sim_debug(DEBUG_CMD, &cpu_dev, "SIO %x %x %x %x %x\n", addr, chan, - ccw_cmd[chan], ccw_flags[chan], chan_status[chan]); + sim_debug(DEBUG_CMD, &cpu_dev, "SIO %03x %03x %02x %x %x\n", addr, chan->daddr, + chan->ccw_cmd, chan->ccw_flags, chan->chan_status); /* If pending status is for us, return it with status code */ - if (chan_dev[chan] == addr && chan_status[chan] != 0) { + if (chan->daddr == addr && chan->chan_status != 0) { store_csw(chan); return 1; } /* If channel is active return cc=2 */ - if (ccw_cmd[chan] != 0 || - (ccw_flags[chan] & (FLAG_CD|FLAG_CC)) != 0 || - chan_status[chan] != 0) { - sim_debug(DEBUG_CMD, &cpu_dev, "SIO %x %x %08x cc=2\n", addr, chan, - chan_status[chan]); + if (chan->ccw_cmd != 0 || + (chan->ccw_flags & (FLAG_CD|FLAG_CC)) != 0 || + chan->chan_status != 0) { + sim_debug(DEBUG_CMD, &cpu_dev, "SIO %03x %08x cc=2\n", addr, chan->chan_status); return 2; } - + /* Check for any pending status for this device */ if (dev_status[addr] != 0) { M[0x44 >> 2] = (((uint32)dev_status[addr]) << 24); M[0x40 >> 2] = 0; key[0] |= 0x6; sim_debug(DEBUG_EXP, &cpu_dev, - "SIO Set atten %03x %x %02x [%08x] %08x\n", - addr, chan, dev_status[addr], M[0x40 >> 2], M[0x44 >> 2]); + "SIO Set atten %03x %02x [%08x] %08x\n", + addr, dev_status[addr], M[0x40 >> 2], M[0x44 >> 2]); dev_status[addr] = 0; return 1; } - /* All ok, get caw address */ - chan_status[chan] = 0; - dev_status[addr] = 0; - caw[chan] = M[0x48>>2]; - ccw_key[chan] = (caw[chan] & PMASK) >> 24; - caw[chan] &= AMASK; - key[0] |= 0x4; - chan_dev[chan] = addr; - /* If device has start_io function run it */ if (dibp->start_io != NULL) { - chan_status[chan] = dibp->start_io(uptr, chan) << 8; - if (chan_status[chan] != 0) { - M[0x44 >> 2] = ((uint32)chan_status[chan]<<16) | (M[0x44 >> 2] & 0xffff); - sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %02x %08x\n", - chan, M[0x44 >> 2]); - chan_status[chan] = 0; + status = dibp->start_io(uptr) << 8; + if (status & STATUS_BUSY) + return 2; + if (status != 0) { + M[0x44 >> 2] = ((uint32)status<<16) | (M[0x44 >> 2] & 0xffff); + sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %03x %08x\n", + chan->daddr, M[0x44 >> 2]); return 1; } } + /* All ok, get caw address */ + chan->chan_status = 0; + chan->caw = M[0x48>>2]; + chan->ccw_key = (chan->caw & PMASK) >> 24; + chan->caw &= AMASK; + key[0] |= 0x4; + dev_status[addr] = 0; + chan->daddr = addr; + chan->dev = dev; + /* Try to load first command */ if (load_ccw(chan, 0)) { - M[0x44 >> 2] = ((uint32)chan_status[chan]<<16) | (M[0x44 >> 2] & 0xffff); + M[0x44 >> 2] = ((uint32)chan->chan_status<<16) | (M[0x44 >> 2] & 0xffff); key[0] |= 0x6; - sim_debug(DEBUG_CMD, &cpu_dev, "SIO %x %x %x %x cc=2\n", addr, chan, - ccw_cmd[chan], ccw_flags[chan]); - chan_status[chan] = 0; + sim_debug(DEBUG_CMD, &cpu_dev, "SIO %03x %02x %x cc=2\n", addr, + chan->ccw_cmd, chan->ccw_flags); + chan->chan_status = 0; + chan->ccw_cmd = 0; dev_status[addr] = 0; - ccw_cmd[chan] = 0; + chan->daddr = NO_DEV; + chan->dev = NULL; return 1; } /* If channel returned busy save CSW and return cc=1 */ - if (chan_status[chan] & STATUS_BUSY) { + if (chan->chan_status & STATUS_BUSY) { M[0x40 >> 2] = 0; - M[0x44 >> 2] = ((uint32)chan_status[chan]<<16); + M[0x44 >> 2] = ((uint32)chan->chan_status<<16); key[0] |= 0x6; - sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %02x %08x\n", - chan, M[0x44 >> 2]); - chan_status[chan] = 0; + chan->chan_status = 0; + chan->ccw_cmd = 0; dev_status[addr] = 0; - chan_dev[chan] = 0; - ccw_cmd[chan] = 0; + chan->daddr = NO_DEV; + chan->dev = NULL; + sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %03x %08x\n", + addr, M[0x44 >> 2]); return 1; } @@ -814,74 +895,76 @@ startio(uint16 addr) { * Handle TIO instruction. */ int testio(uint16 addr) { - int chan = find_subchan(addr); + struct _dev *dev = find_device(addr); + struct _chanctl *chan = find_subchan(addr); DIB *dibp = NULL; UNIT *uptr; uint16 status; + int ch; - if (addr < MAX_DEV) - dibp = dev_unit[addr]; - - /* Find channel this device is on, if no none return cc=3 */ - if (chan < 0 || dibp == NULL) { - sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x cc=3\n", addr, chan); + if (dev == NULL || chan == NULL) { + sim_debug(DEBUG_CMD, &cpu_dev, "TIO %03x cc=3\n", addr); return 3; } - uptr = find_chan_dev(addr); - if (uptr == 0) { - sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x uptr cc=3\n", addr, chan); + + dibp = dev->dibp; + uptr = dev->unit; + + /* Find channel this device is on, if no none return cc=3 */ + if (dibp == NULL || uptr == NULL) { + sim_debug(DEBUG_CMD, &cpu_dev, "TIO %03x cc=3\n", addr); return 3; } /* If any error pending save csw and return cc=1 */ - if (chan_status[chan] & (STATUS_PCI|STATUS_ATTN|STATUS_CHECK|\ - STATUS_PROT|STATUS_PCHK|STATUS_EXPT)) { - sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x %x %x cc=1\n", addr, chan, - ccw_cmd[chan], ccw_flags[chan]); + if (chan->chan_status & ERROR_STATUS) { + sim_debug(DEBUG_CMD, &cpu_dev, "TIO %03x %03x %02x %x cc=1\n", addr, + chan->daddr, chan->ccw_cmd, chan->ccw_flags); store_csw(chan); return 1; } /* If channel active, return cc=2 */ - if (ccw_cmd[chan] != 0 || (ccw_flags[chan] & (FLAG_CD|FLAG_CC)) != 0) { - sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x %x %x cc=2\n", addr, chan, - ccw_cmd[chan], ccw_flags[chan]); + if (chan->ccw_cmd != 0 || (chan->ccw_flags & (FLAG_CD|FLAG_CC)) != 0) { + sim_debug(DEBUG_CMD, &cpu_dev, "TIO %03x %03x %02x %x cc=2\n", addr, + chan->daddr, chan->ccw_cmd, chan->ccw_flags); return 2; } /* Device finished and channel status pending return it and cc=1 */ - if (ccw_cmd[chan] == 0 && chan_status[chan] != 0) { - sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x %x %x cc=1a\n", addr, chan, - ccw_cmd[chan], ccw_flags[chan]); + if (chan->ccw_cmd == 0 && chan->chan_status != 0) { + sim_debug(DEBUG_CMD, &cpu_dev, "TIO %03x %03x %02x %x cc=1a\n", addr, + chan->daddr, chan->ccw_cmd, chan->ccw_flags); store_csw(chan); - chan_dev[chan] = 0; +// dev_status[addr] = 0; + chan->daddr = NO_DEV; + chan->dev = NULL; return 1; } /* Device has returned a status, store the csw and return cc=1 */ if (dev_status[addr] != 0) { - sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x %x %x cc=1b\n", addr, chan, - ccw_cmd[chan], ccw_flags[chan]); + sim_debug(DEBUG_CMD, &cpu_dev, "TIO %03x %03x %02x %x cc=1b\n", addr, + chan->daddr, chan->ccw_cmd, chan->ccw_flags); M[0x40 >> 2] = 0; M[0x44 >> 2] = ((uint32)dev_status[addr]) << 24; key[0] |= 0x6; dev_status[addr] = 0; - chan_pend[chan] = 0; return 1; } - /* If error pending for another device, return cc=2 */ - if (chan_pend[chan] != 0) { - int pend, ch; - chan_pend[chan] = 0; + ch = (addr >> 8) & 0xf; + /* If error pending for another device on subchannel, return cc=2 */ + if (chan_pend[ch]) { + int dev; /* Check if might be false */ - for (pend = 0; pend < MAX_DEV; pend++) { - if (dev_status[pend] != 0) { - ch = find_subchan(pend); - if (ch == chan) { - chan_pend[ch] = 1; - sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x %x %x %x cc=2a\n", addr, chan, - ccw_cmd[chan], ccw_flags[chan], pend); + for (dev = (addr & 0xf00); dev < (addr | 0xfff); dev++) { + if (dev_status[dev] != 0) { + /* Check if same subchannel */ + if (find_subchan(dev) == chan) { + irq_pend = 1; + sim_debug(DEBUG_CMD, &cpu_dev, "TIO %03x %03x %x %x %x cc=2a\n", + addr, chan->daddr, chan->ccw_cmd, chan->ccw_flags, dev); return 2; } } @@ -889,27 +972,27 @@ int testio(uint16 addr) { } /* Nothing pending, send a 0 command to device to get status */ - status = dibp->start_cmd(uptr, chan, 0) << 8; + status = dibp->start_cmd(uptr, 0) << 8; /* If no status and unattached device return cc=3 */ if (status == 0 && (uptr->flags & UNIT_ATT) == 0) { - sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x %x %x cc=1c\n", addr, chan, - ccw_cmd[chan], ccw_flags[chan]); + sim_debug(DEBUG_CMD, &cpu_dev, "TIO %03x %03x %02x %x cc=1c\n", addr, + chan->daddr, chan->ccw_cmd, chan->ccw_flags); return 3; } /* If we get a error, save csw and return cc=1 */ - if (status & (STATUS_ATTN|STATUS_CHECK|STATUS_EXPT)) { + if (status & ERROR_STATUS) { M[0x44 >> 2] = ((uint32)status<<24) | (M[0x44 >> 2] & 0xffff); key[0] |= 0x6; - sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x %x %x cc=1d\n", addr, chan, - ccw_cmd[chan], ccw_flags[chan]); + sim_debug(DEBUG_CMD, &cpu_dev, "TIO %03x %03x %02x %x cc=1d\n", addr, + chan->daddr, chan->ccw_cmd, chan->ccw_flags); return 1; } /* Everything ok, return cc=0 */ - sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x %x %x cc=0\n", addr, chan, - ccw_cmd[chan], ccw_flags[chan]); + sim_debug(DEBUG_CMD, &cpu_dev, "TIO %03x %03x %02x %x cc=0\n", addr, + chan->daddr, chan->ccw_cmd, chan->ccw_flags); return 0; } @@ -917,64 +1000,65 @@ int testio(uint16 addr) { * Handle HIO instruction. */ int haltio(uint16 addr) { - int chan = find_subchan(addr); - DIB *dibp = NULL; - UNIT *uptr; - int cc; + struct _dev *dev = find_device(addr); + struct _chanctl *chan = find_subchan(addr); + DIB *dibp = NULL; + UNIT *uptr; + int cc; - if (addr < MAX_DEV) - dibp = dev_unit[addr]; + if (dev == NULL || chan == NULL) { + sim_debug(DEBUG_CMD, &cpu_dev, "HIO %03x cc=3\n", addr); + return 3; + } + + dibp = dev->dibp; + uptr = dev->unit; /* Find channel this device is on, if no none return cc=3 */ - if (chan < 0 || dibp == NULL) { - sim_debug(DEBUG_CMD, &cpu_dev, "HIO %x %x\n", addr, chan); + if (dibp == NULL || uptr == NULL) { + sim_debug(DEBUG_CMD, &cpu_dev, "HIO %03x cc=3\n", addr); return 3; } - uptr = find_chan_dev(addr); - if (uptr == 0) { - sim_debug(DEBUG_CMD, &cpu_dev, "HIOu %x %x\n", addr, chan); - return 3; - } - sim_debug(DEBUG_CMD, &cpu_dev, "HIO %x %x %x %x\n", addr, chan, - ccw_cmd[chan], ccw_flags[chan]); + + sim_debug(DEBUG_CMD, &cpu_dev, "HIO %03x %03x %x %x\n", addr, chan->daddr, + chan->ccw_cmd, chan->ccw_flags); /* Generic halt I/O, tell device to stop and */ /* If any error pending save csw and return cc=1 */ - if (chan_status[chan] & (STATUS_PCI|STATUS_ATTN|STATUS_CHECK|\ - STATUS_PROT|STATUS_PCHK|STATUS_EXPT)) { - sim_debug(DEBUG_CMD, &cpu_dev, "HIO %x %x %x cc=0\n", addr, chan, - chan_status[chan]); + if ((chan->chan_status & ERROR_STATUS) != 0) { + sim_debug(DEBUG_CMD, &cpu_dev, "HIO %03x %03x %x cc=0\n", addr, chan->daddr, + chan->chan_status); return 0; } /* If channel active, tell it to terminate */ - if (ccw_cmd[chan]) { - chan_byte[chan] = BUFF_CHNEND; - ccw_flags[chan] &= ~(FLAG_CD|FLAG_CC); + if (chan->ccw_cmd != 0) { + chan->chan_byte = BUFF_CHNEND; + chan->ccw_flags &= ~(FLAG_CD|FLAG_CC); } /* Not executing a command, issue halt if available */ if (dibp->halt_io != NULL) { /* Let device do it's thing */ cc = dibp->halt_io(uptr); - sim_debug(DEBUG_CMD, &cpu_dev, "HIOd %x %x cc=%d\n", addr, chan, cc); + sim_debug(DEBUG_CMD, &cpu_dev, "HIOd %03x %03x cc=%d\n", addr, + chan->daddr, cc); if (cc == 1) { - M[0x44 >> 2] = (((uint32)chan_status[chan]) << 16) | + M[0x44 >> 2] = (((uint32)chan->chan_status) << 16) | (M[0x44 >> 2] & 0xffff); key[0] |= 0x6; - sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %02x %08x\n", - chan, M[0x44 >> 2]); + sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %03x %08x\n", + chan->daddr, M[0x44 >> 2]); } return cc; } - /* Store CSW and return 1. */ - sim_debug(DEBUG_CMD, &cpu_dev, "HIOx %x %x cc=1\n", addr, chan); - M[0x44 >> 2] = (((uint32)chan_status[chan]) << 16) | - (M[0x44 >> 2] & 0xffff); + sim_debug(DEBUG_CMD, &cpu_dev, "HIOx %03x %03x cc=1\n", addr, chan->daddr); + M[0x44 >> 2] = (((uint32)chan->chan_status) << 16) | (M[0x44 >> 2] & 0xffff); key[0] |= 0x6; - sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %02x %08x\n", chan, M[0x44 >> 2]); + sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %03x %08x\n", chan->daddr, + M[0x44 >> 2]); return 1; } @@ -982,8 +1066,9 @@ int haltio(uint16 addr) { * Handle TCH instruction. */ int testchan(uint16 channel) { - uint16 st = 0; - uint8 cc = 0; + UNIT *uptr; + struct _chanctl *chan; + uint8 cc = 0; /* 360 Principles of Operation says, "Bit positions 21-23 of the sum formed by the addition of the content of register B1 and the @@ -1009,21 +1094,38 @@ int testchan(uint16 channel) { cc = (channel >> 11) & 0x03; channel = (channel >> 8) & 0x0f; - if (cc > 1 || channel > channels) { + if (cc > 1 || channel > chan_dev.numunits) { sim_debug(DEBUG_CMD, &cpu_dev, "TCH CC %x %x cc=3\n", cc, channel); return 3; } - if (channel == 0 || channel == 4 || channel == 8 || channel == 12) - return 0; - if (channel > channels) + + uptr = &(chan_dev.units[channel]); + + /* Return 3 if no channel */ + if ((uptr->flags & UNIT_DIS) != 0) { + sim_debug(DEBUG_CMD, &cpu_dev, "TCH CC %x cc=3\n", channel); return 3; - st = chan_status[SEL_BASE + channel]; - if (st & STATUS_BUSY) + } + + /* Multiplexer channels return channel is available */ + if ((uptr->flags & UNIT_SEL) == 0) { + sim_debug(DEBUG_CMD, &cpu_dev, "TCH CC %x cc=0, mux\n", channel); + return 0; + } + + chan = &(chan_ctl[0]); + + /* If channel is processing a command, return 2 */ + if (chan->ccw_cmd != 0) { + sim_debug(DEBUG_CMD, &cpu_dev, "TCH CC %x cc=2, sel busy\n", channel); return 2; - if (st & (STATUS_ATTN|STATUS_PCI|STATUS_EXPT|STATUS_CHECK| - STATUS_PROT|STATUS_CDATA|STATUS_CCNTL|STATUS_INTER| - STATUS_CHAIN)) + } + + if (chan->chan_status != 0) { + sim_debug(DEBUG_CMD, &cpu_dev, "TCH CC %x cc=1, error\n", channel); return 1; + } + sim_debug(DEBUG_CMD, &cpu_dev, "TCH CC %x cc=0, ok\n", channel); return 0; } @@ -1032,38 +1134,51 @@ int testchan(uint16 channel) { * length warning, and chain command. */ t_stat chan_boot(uint16 addr, DEVICE *dptyr) { - int chan = find_subchan(addr); - DIB *dibp = NULL; - UNIT *uptr; - int i; + struct _dev *dev; + struct _chanctl *chan; + DIB *dibp = NULL; + UNIT *uptr; + int status; + int i; - if (addr < MAX_DEV) - dibp = dev_unit[addr]; - - if (chan < 0 || dibp == NULL) - return SCPE_IOERR; - for (i = 0; i < MAX_DEV; i++) { + for (i = 0; i < (MAX_CHAN * 256); i++) dev_status[i] = 0; + chan_set_devs(); + dev = find_device(addr); + chan = find_subchan(addr); + if (dev == NULL || chan == NULL) { + return SCPE_IOERR; } - for (i = 0; i < 256; i++) { - ccw_cmd[i] = 0; - ccw_flags[i] = 0; + + dibp = dev->dibp; + uptr = dev->unit; + + /* Find channel this device is on, if no none return cc=3 */ + if (dibp == NULL || uptr == NULL) { + return SCPE_IOERR; } - uptr = find_chan_dev(addr); - chan_status[chan] = 0; + + /* If device has start_io function run it */ + if (dibp->start_io != NULL) { + status = dibp->start_io(uptr) << 8; + if (status != 0) { + return SCPE_IOERR; + } + } + chan->chan_status = 0; dev_status[addr] = 0; - caw[chan] = 0x8; - chan_dev[chan] = addr; - ccw_count[chan] = 24; - ccw_flags[chan] = FLAG_CC|FLAG_SLI; - ccw_addr[chan] = 0; - ccw_key[chan] = 0; - chan_byte[chan] = BUFF_EMPTY; - ccw_cmd[chan] = 0x2; - chan_status[chan] &= 0xff; - chan_status[chan] |= dibp->start_cmd(uptr, chan, ccw_cmd[chan]) << 8; - if (chan_status[chan] & (STATUS_ATTN|STATUS_CHECK|STATUS_EXPT)) { - ccw_flags[chan] = 0; + chan->dev = dev; + chan->caw = 0x8; + chan->daddr = addr; + chan->ccw_count = 24; + chan->ccw_flags = FLAG_CC|FLAG_SLI; + chan->ccw_addr = 0; + chan->ccw_key = 0; + chan->chan_byte = BUFF_EMPTY; + chan->ccw_cmd = 0x2; /* IPL command */ + chan->chan_status = dibp->start_cmd(uptr, chan->ccw_cmd) << 8; + if (chan->chan_status & (STATUS_ATTN|STATUS_CHECK|STATUS_EXPT)) { + chan->ccw_flags = 0; return SCPE_IOERR; } loading = addr; @@ -1076,108 +1191,198 @@ t_stat chan_boot(uint16 addr, DEVICE *dptyr) { */ uint16 scan_chan(uint16 mask, int irq_en) { - int i; - int ch; - int pend = 0; /* No device */ - int imask = 0x8000; + unsigned int i; + int j; + int pend; /* I/O done on device */ + int imask; + UNIT *uptr; + int nchan; + struct _chanctl *chan; /* Quick exit if no pending IRQ's */ if (irq_pend == 0) - return 0; - irq_pend = 0; + return NO_DEV; + irq_pend = 0; /* Clear pending flag */ + pend = NO_DEV; /* Start with channel 0 and work through all channels */ - for (i = 0; i < CHAN_SZ; i++) { - /* Check if PCI pending */ - if (irq_en && (chan_status[i] & STATUS_PCI) != 0) { - 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]; - break; - } - } - - /* If channel end, check if we should continue */ - if (chan_status[i] & STATUS_CEND) { - if (ccw_flags[i] & FLAG_CC) { - if (chan_status[i] & STATUS_DEND) - (void)load_ccw(i, 1); - else - irq_pend = 1; - } else if (irq_en || loading) { - 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 ((chan_status[i] & STATUS_DEND) != 0 && - ((imask & mask) != 0 || loading != 0)) { - pend = chan_dev[i]; + for (i = 0; i < chan_dev.numunits && pend == NO_DEV; i++) { + imask = 0x8000 >> i; /* Mask for this channel */ + uptr = &((chan_dev.units)[i]); + /* If channel disabled, just skip */ + if ((uptr->flags & UNIT_DIS) != 0) + continue; + nchan = 1; + if ((uptr->flags & UNIT_SEL) == 0) + nchan = UNIT_G_SCHAN(uptr->flags); + /* Scan all subchannels on this channel */ + for (j = 0; j < nchan; j++) { + chan = &(chan_ctl[j]); + if (chan->daddr == NO_DEV) + continue; + /* Check if PCI pending */ + if (irq_en && (chan->chan_status & STATUS_PCI) != 0) { + sim_debug(DEBUG_EXP, &cpu_dev, "Scan PCI(%x %x %x %x %x) end\n", i, + chan->daddr, chan->chan_status, imask, mask); + if ((imask & mask) != 0) { + pend = chan->daddr; break; - } + } + } + + /* If channel end, check if we should continue */ + if (chan->chan_status & STATUS_CEND) { + sim_debug(DEBUG_EXP, &cpu_dev, "Scan(%x %x %x %x) Cend\n", i, + chan->daddr, chan->chan_status, chan->ccw_flags); + /* Grab another command if command chainging in effect */ + if (chan->ccw_flags & FLAG_CC) { + if (chan->chan_status & STATUS_DEND) + (void)load_ccw(chan, 1); + else + irq_pend = 1; + } else if (irq_en || loading) { + /* Disconnect from device */ + sim_debug(DEBUG_EXP, &cpu_dev, "Scan(%x %x %x %x %x) end\n", i, + chan->daddr, chan->chan_status, imask, mask); + if (//(chan->chan_status & STATUS_CEND) != 0 && + ((imask & mask) != 0 || loading != 0)) { + pend = chan->daddr; + break; + } + } } } } /* Only return loading unit on loading */ if (loading != 0 && loading != pend) - return 0; + return NO_DEV; /* See if we can post an IRQ */ - if (pend) { - irq_pend = 1; - ch = find_subchan(pend); - if (ch < 0) - return 0; + if (pend != NO_DEV) { + irq_pend = 1; /* Set to scan next time */ if (loading && loading == pend) { - chan_status[ch] = 0; + chan->chan_status = 0; return pend; } - if (ch >= 0 && loading == 0) { - sim_debug(DEBUG_EXP, &cpu_dev, "Scan end (%x %x)\n", chan_dev[ch], pend); - store_csw(ch); + if (loading == 0) { + sim_debug(DEBUG_EXP, &cpu_dev, "Scan end (%x %x)\n", chan->daddr, pend); + store_csw(chan); dev_status[pend] = 0; return pend; } - } else { - if (!irq_en) - return 0; - for (pend = 0; pend < MAX_DEV; pend++) { - if (dev_status[pend] != 0) { - ch = find_subchan(pend); - if (ch >= 0 && ccw_cmd[ch] == 0 && - (mask & (0x8000 >> (pend >> 8))) != 0) { - irq_pend = 1; - M[0x44 >> 2] = (((uint32)dev_status[pend]) << 24); - M[0x40>>2] = 0; - key[0] |= 0x6; - sim_debug(DEBUG_EXP, &cpu_dev, - "Set atten %03x %02x [%08x] %08x\n", - ch, dev_status[pend], M[0x40 >> 2], M[0x44 >> 2]); - dev_status[pend] = 0; - return pend; - } - } - } + } else if (irq_en) { + /* If interrupts are wanted, check for pending device status */ + + /* Scan channel for pending device status change */ + for (j = 0; j < MAX_CHAN; j++) { + /* Nothing pending, or not enabled, just skip */ + if (chan_pend[j] == 0 || ((0x8000 >> j) & mask) == 0) + continue; + nchan = j << 8; + chan_pend[j] = 0; + for (i = 0; i < 256; i++) { + if (dev_status[nchan|i] != 0) { + chan_pend[j] = 1; + irq_pend = 1; + M[0x44 >> 2] = (((uint32)dev_status[nchan|i]) << 24); + M[0x40>>2] = 0; + key[0] |= 0x6; + sim_debug(DEBUG_EXP, &cpu_dev, + "Set atten %03x %02x [%08x] %08x\n", nchan|i, + dev_status[nchan|i], M[0x40 >> 2], M[0x44 >> 2]); + dev_status[nchan|i] = 0; + return nchan|i; + } + } + } } - return 0; + return NO_DEV; } +t_stat +chan_reset(DEVICE * dptr) +{ + unsigned int i, j; + + for (i = 0; i < dptr->numunits; i++) { + UNIT *uptr = &dptr->units[i]; + int n; + + if (uptr->up7 != NULL) + free(uptr->up7); + if (uptr->up8 != NULL) + free(uptr->up8); + uptr->up7 = NULL; + uptr->up8 = NULL; + if (uptr->flags & UNIT_DIS) + continue; + n = 1; + if ((uptr->flags & UNIT_SEL) == 0) + n = UNIT_G_SCHAN(uptr->flags)+1; + uptr->schans = n; + uptr->up7 = calloc(n, sizeof(struct _chanctl)); + uptr->up8 = calloc(256, sizeof(struct _dev)); + for (j = 0; j < n; j++) { + struct _chanctl *chan = &(chan_ctl[j]); + chan->daddr = NO_DEV; + } + } + return SCPE_OK; +} + /* * Scan all devices and create the device mapping. */ t_stat chan_set_devs() { - uint32 i, j; + unsigned i, j; - for(i = 0; i < MAX_DEV; i++) { - dev_unit[i] = NULL; /* Device pointer */ + /* Readjust subchannels if there was a change */ + for (i = 0; i < chan_dev.numunits; i++) { + UNIT *uptr = &chan_unit[i]; + int n; + + /* If channel disconnected free the buffers */ + if (uptr->flags & UNIT_DIS) { + if (uptr->up7 != NULL) + free(uptr->up7); + if (uptr->up8 != NULL) + free(uptr->up8); + uptr->up7 = NULL; + uptr->up8 = NULL; + continue; + } + n = 1; + if ((uptr->flags & UNIT_SEL) == 0) + n = UNIT_G_SCHAN(uptr->flags) + 1; + /* If no device array, create one */ + if (uptr->up8 == NULL) + uptr->up8 = calloc(256, sizeof(struct _dev)); + if (uptr->up7 == NULL || uptr->schans != n) { + if (uptr->up7 != NULL) + free(uptr->up7); + uptr->up7 = calloc(n, sizeof(struct _chanctl)); + for (j = 0; j < n; j++) { + struct _chanctl *chan = &(chan_ctl[j]); + chan->daddr = NO_DEV; + } + } + uptr->schans = n; + for (j = 0; j < 256; j++) { + struct _dev *dev = &(dev_tab[j]); + dev->dibp = NULL; + dev->unit = NULL; + dev->dev_addr = NO_DEV; + } } + /* Build channel array */ for (i = 0; sim_devices[i] != NULL; i++) { - DEVICE *dptr = sim_devices[i]; - UNIT *uptr = dptr->units; - DIB *dibp = (DIB *) dptr->ctxt; - int addr; + DEVICE *dptr = sim_devices[i]; + UNIT *uptr = dptr->units; + DIB *dibp = (DIB *) dptr->ctxt; + int addr; + struct _dev *dev; /* If no DIB, not channel device */ if (dibp == NULL) @@ -1187,11 +1392,15 @@ chan_set_devs() continue; /* Check if address is in unit or dev entry */ for (j = 0; j < dptr->numunits; j++) { - addr = GET_UADDR(uptr->u3); - if ((uptr->flags & UNIT_DIS) == 0) - dev_unit[addr] = dibp; - if (dibp->dev_ini != NULL) - dibp->dev_ini(uptr, 1); + addr = GET_UADDR(uptr->u3); + dev = find_device(addr); + if (dev != NULL && (uptr->flags & UNIT_DIS) == 0) { + dev->unit = uptr; + dev->dibp = dibp; + dev->dev_addr = addr; + if (dibp->dev_ini != NULL) + dibp->dev_ini(uptr, 1); + } uptr++; } @@ -1199,15 +1408,61 @@ chan_set_devs() return SCPE_OK; } +/* Sets the number of subchannels for a channel */ +t_stat +set_subchan(UNIT * uptr, int32 val, CONST char *cptr, void *desc) +{ + t_value nschans; + t_stat r; + + if (cptr == NULL) + return SCPE_ARG; + if (uptr == NULL) + return SCPE_IERR; + + nschans = get_uint (cptr, 10, 256, &r); + + if (r != SCPE_OK) + return r; + + if (nschans < 32 || (nschans & 0xf) != 0) + return SCPE_ARG; + + uptr->flags &= ~UNIT_SCHAN(0xff); + uptr->flags |= UNIT_SCHAN(nschans); + + return r; +} + +/* Display the address of the device */ +t_stat +show_subchan(FILE * st, UNIT * uptr, int32 v, CONST void *desc) +{ + int n; + + if (uptr == NULL) + return SCPE_IERR; + if ((uptr->flags & UNIT_SEL) != 0) { + fprintf(st, "SEL"); + } else { + n = UNIT_G_SCHAN(uptr->flags); + fprintf(st, "MUX SUB=%d", n); + } + return SCPE_OK; +} + + /* Sets the device onto a given channel */ t_stat set_dev_addr(UNIT * uptr, int32 val, CONST char *cptr, void *desc) { DEVICE *dptr; + struct _dev *dev; DIB *dibp; t_value newdev; + struct _dev *ndev; t_stat r; - int i; + unsigned int i; int devaddr; if (cptr == NULL) @@ -1227,32 +1482,52 @@ set_dev_addr(UNIT * uptr, int32 val, CONST char *cptr, void *desc) if (r != SCPE_OK) return r; - if ((newdev >> 8) > (t_value)channels) + if ((newdev >> 8) > (t_value)dptr->numunits) return SCPE_ARG; - if (newdev >= MAX_DEV) + if ((newdev >> 8) >= MAX_CHAN) return SCPE_ARG; devaddr = GET_UADDR(uptr->u3); + dev = find_device(devaddr); + + if (dev == NULL) + return SCPE_ARG; /* Clear out existing entry */ if (dptr->flags & DEV_UADDR) { - dev_unit[devaddr] = NULL; + dev->dibp = NULL; + dev->unit = NULL; } else { devaddr &= dibp->mask | 0xf00; - for (i = 0; i < dibp->numunits; i++) - dev_unit[devaddr + i] = NULL; + for (i = 0; i < dibp->numunits; i++) { + dev = find_device(devaddr + i); + if (dev != NULL) { + dev->dibp = NULL; + dev->unit = NULL; + } else { + r = SCPE_ARG; + } + } } - /* Check if device already at newdev */ - if (dptr->flags & DEV_UADDR) { - if (dev_unit[newdev] != NULL) - r = SCPE_ARG; + ndev = find_device(newdev); + + if (ndev == NULL) { + r = SCPE_ARG; } else { - newdev &= dibp->mask | 0xf00; - for (i = 0; i < dibp->numunits; i++) { - if (dev_unit[newdev + i] != NULL) + /* Check if device already at newdev */ + if (dptr->flags & DEV_UADDR) { + if (dev->unit != NULL) r = SCPE_ARG; + } else { + newdev &= dibp->mask | 0xf00; + for (i = 0; i < dibp->numunits; i++) { + ndev = find_device(newdev + i); + if (dev == NULL || dev->unit != NULL) { + r = SCPE_ARG; + } + } } } @@ -1260,17 +1535,25 @@ set_dev_addr(UNIT * uptr, int32 val, CONST char *cptr, void *desc) if (r == SCPE_OK) devaddr = newdev; + dev = find_device(devaddr); /* Update device entry */ if (dptr->flags & DEV_UADDR) { - dev_unit[devaddr] = dibp; + dev->dibp = dibp; + dev->unit = uptr; + dev->dev_addr = devaddr; uptr->u3 &= ~UNIT_ADDR(0xfff); uptr->u3 |= UNIT_ADDR(devaddr); - fprintf(stderr, "Set dev %s %x\n\r", dptr->name, GET_UADDR(uptr->u3)); + sim_printf("Set dev %s %x\n\r", dptr->name, GET_UADDR(uptr->u3)); } else { - fprintf(stderr, "Set dev %s0 %x\n\r", dptr->name, devaddr); + sim_printf("Set dev %s0 %x\n\r", dptr->name, devaddr); for (i = 0; i < dibp->numunits; i++) { - dev_unit[devaddr + i] = dibp; + dev = find_device(devaddr + i); uptr = &((dibp->units)[i]); + if (dev != NULL) { + dev->dibp = dibp; + dev->unit = uptr; + dev->dev_addr = devaddr + i; + } uptr->u3 &= ~UNIT_ADDR(0xfff); uptr->u3 |= UNIT_ADDR(devaddr + i); } @@ -1282,15 +1565,10 @@ set_dev_addr(UNIT * uptr, int32 val, CONST char *cptr, void *desc) t_stat show_dev_addr(FILE * st, UNIT * uptr, int32 v, CONST void *desc) { - DEVICE *dptr; int addr; - if (uptr == NULL) return SCPE_IERR; - dptr = find_dev_from_unit(uptr); - if (dptr == NULL) - return SCPE_IERR; addr = GET_UADDR(uptr->u3); fprintf(st, "DEV=%03x", addr); return SCPE_OK; diff --git a/IBM360/ibm360_com.c b/IBM360/ibm360_com.c index 79da78b..e211b61 100644 --- a/IBM360/ibm360_com.c +++ b/IBM360/ibm360_com.c @@ -81,7 +81,7 @@ #define SNS u5 #define BPTR u6 -uint8 coml_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; +uint8 coml_startcmd(UNIT *uptr, uint8 cmd) ; uint8 coml_haltio(UNIT *uptr); t_stat coml_srv(UNIT *uptr); t_stat com_reset(DEVICE *dptr); @@ -164,7 +164,7 @@ static const uint8 com_2741_in[128] = { /*CAN EM SUB ESC FS GS RS US */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* sp ! " # $ % & ' */ - 0x81, 0xD7, 0x00, 0x16, 0x57, 0x8B, 0x61, 0x8D, /* 40 - 77 */ + 0x81, 0xD7, 0x96, 0x16, 0x57, 0x8B, 0x61, 0x8D, /* 40 - 77 */ /* ( ) * + , - . / */ 0x93, 0x95, 0x90, 0xE1, 0x37, 0xC0, 0x76, 0x23, /* 0 1 2 3 4 5 6 7 */ @@ -259,7 +259,7 @@ static const uint8 com_2741_out[256] = { /* * Issue a command to the 2701 controller. */ -uint8 coml_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { +uint8 coml_startcmd(UNIT *uptr, uint8 cmd) { DEVICE *dptr = find_dev_from_unit(uptr); int unit = (uptr - dptr->units); @@ -397,7 +397,7 @@ t_stat coml_srv(UNIT * uptr) uptr->SNS = SNS_INTVENT; uptr->BPTR = 0; uptr->IPTR = 0; - chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK|SNS_UNITEXP); return SCPE_OK; } else if (uptr->CMD & INPUT) { if (uptr->BPTR == uptr->IPTR) { @@ -407,8 +407,6 @@ t_stat coml_srv(UNIT * uptr) chan_end(addr, SNS_CHNEND|SNS_DEVEND); return SCPE_OK; } -// if (ch == 0x1f) -// uptr->CMD |= ADDR; ch = com_buf[unit][uptr->IPTR++]; if (chan_write_byte( addr, &ch)) { uptr->CMD &= ~(0xff|INPUT|RECV); diff --git a/IBM360/ibm360_con.c b/IBM360/ibm360_con.c index c95ac3d..4a2c8f2 100644 --- a/IBM360/ibm360_con.c +++ b/IBM360/ibm360_con.c @@ -78,7 +78,7 @@ struct _con_data } con_data[NUM_DEVS_CON]; -uint8 con_startcmd(UNIT *, uint16, uint8); +uint8 con_startcmd(UNIT *, uint8); uint8 con_haltio(UNIT *); void con_ini(UNIT *, t_bool); t_stat con_srv(UNIT *); @@ -122,7 +122,7 @@ con_ini(UNIT *uptr, t_bool f) { sim_activate(uptr, 1000); } -uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { +uint8 con_startcmd(UNIT *uptr, uint8 cmd) { int u = (uptr - con_unit); if ((uptr->CMD & CON_MSK) != 0) diff --git a/IBM360/ibm360_cpu.c b/IBM360/ibm360_cpu.c index 9fa5e17..a6b4056 100644 --- a/IBM360/ibm360_cpu.c +++ b/IBM360/ibm360_cpu.c @@ -1135,7 +1135,7 @@ wait_loop: /* Check if we should see if an IRQ is pending */ irq = scan_chan(sysmsk, irq_en); - if (irq != 0) { + if (irq != NO_DEV) { ilc = 0; sim_debug(DEBUG_DETAIL, &cpu_dev, "IRQ=%04x %08x\n", irq, PC); if (loading) { @@ -5796,6 +5796,7 @@ t_stat cpu_reset (DEVICE *dptr) } /* Set up channels */ chan_set_devs(); + sysmsk = irqcode = irqaddr = loading = 0; st_key = cc = pmsk = ec_mode = interval_irq = flags = 0; dat_en = irq_en = ext_en = per_en = 0; diff --git a/IBM360/ibm360_dasd.c b/IBM360/ibm360_dasd.c index b2e5da0..7813a43 100644 --- a/IBM360/ibm360_dasd.c +++ b/IBM360/ibm360_dasd.c @@ -240,8 +240,8 @@ struct dasd_header uint8 resv[492]; /* pad to 512 byte block */ }; -uint8 dasd_startio(UNIT *uptr, uint16 chan) ; -uint8 dasd_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; +uint8 dasd_startio(UNIT *uptr) ; +uint8 dasd_startcmd(UNIT *uptr, uint8 cmd) ; uint8 dasd_haltio(uint16 addr); t_stat dasd_srv(UNIT *); t_stat dasd_boot(int32, DEVICE *); @@ -365,13 +365,19 @@ DEVICE ddd_dev = { #endif #endif -uint8 dasd_startio(UNIT *uptr, uint16 chan) { +uint8 dasd_startio(UNIT *uptr) { DEVICE *dptr = find_dev_from_unit(uptr); int unit = (uptr - dptr->units); + unsigned int i; - if ((uptr->CMD & 0xff) != 0) { - return SNS_BSY; +#if 0 + /* Check if controller is free */ + for (i = 0; i < dptr->numunits; i++) { + int cmd = (dptr->units[i].CMD) & 0xff; + if (cmd != 0 && cmd != DK_SEEK) + return SNS_BSY; } +#endif uptr->CMD &= ~(DK_INDEX|DK_NOEQ|DK_HIGH|DK_PARAM|DK_MSET|DK_DONE|DK_INDEX2); if ((uptr->flags & UNIT_ATT) != 0) { struct dasd_t *data = (struct dasd_t *)(uptr->up7); @@ -381,7 +387,7 @@ uint8 dasd_startio(UNIT *uptr, uint16 chan) { return 0; } -uint8 dasd_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { +uint8 dasd_startcmd(UNIT *uptr, uint8 cmd) { uint16 addr = GET_UADDR(uptr->CMD); DEVICE *dptr = find_dev_from_unit(uptr); int unit = (uptr - dptr->units); diff --git a/IBM360/ibm360_defs.h b/IBM360/ibm360_defs.h index 54b0359..aa515d5 100644 --- a/IBM360/ibm360_defs.h +++ b/IBM360/ibm360_defs.h @@ -55,9 +55,8 @@ Channels 1-n run on channels virtual channels above subchannels. */ -#define MAX_CHAN 6 -#define SUB_CHANS 192 -#define MAX_MUX 2 +#define MAX_CHAN 12 +#define SUB_CHANS 128 /* Define number of supported units for each device type */ #define NUM_DEVS_CDP 4 @@ -78,9 +77,9 @@ typedef struct dib { uint8 mask; /* Device mask */ uint8 numunits; /* Number of units */ /* Start I/O */ - uint8 (*start_io)(UNIT *uptr, uint16 chan); + uint8 (*start_io)(UNIT *uptr); /* Start a command */ - uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd); + uint8 (*start_cmd)(UNIT *uptr, uint8 cmd); /* Stop I/O */ uint8 (*halt_io)(UNIT *uptr); UNIT *units; /* Pointer to units structure */ @@ -334,14 +333,15 @@ typedef struct dib { #define STATUS_INTER 0x0002 /* Channel interface check */ #define STATUS_CHAIN 0x0001 /* Channel chain check */ +#define NO_DEV 0xffff /* Code for no device */ + void post_extirq(); /* look up device to find subchannel device is on */ -int find_subchan(uint16 device); -int chan_read_byte(uint16 chan, uint8 *data); -int chan_write_byte(uint16 chan, uint8 *data); +int chan_read_byte(uint16 addr, uint8 *data); +int chan_write_byte(uint16 addr, uint8 *data); void set_devattn(uint16 addr, uint8 flags); -void chan_end(uint16 chan, uint8 flags); +void chan_end(uint16 addr, uint8 flags); int startio(uint16 addr) ; int testio(uint16 addr); int haltio(uint16 addr); @@ -371,6 +371,7 @@ extern DEBTAB dev_debug[]; extern DEBTAB crd_debug[]; extern DEVICE cpu_dev; +extern DEVICE chan_dev; extern DEVICE cdp_dev; extern DEVICE cdr_dev; extern DEVICE lpr_dev; diff --git a/IBM360/ibm360_lpr.c b/IBM360/ibm360_lpr.c index aa9a819..c1fd5ac 100644 --- a/IBM360/ibm360_lpr.c +++ b/IBM360/ibm360_lpr.c @@ -88,7 +88,8 @@ struct _lpr_data } lpr_data[NUM_DEVS_LPR]; -uint8 lpr_startcmd(UNIT *, uint16, uint8); +uint8 lpr_startio(UNIT *uptr); +uint8 lpr_startcmd(UNIT *, uint8); void lpr_ini(UNIT *, t_bool); t_stat lpr_srv(UNIT *); t_stat lpr_reset(DEVICE *); @@ -120,7 +121,7 @@ MTAB lpr_mod[] = { {0} }; -struct dib lpr_dib = { 0xFF, 1, NULL, lpr_startcmd, NULL, lpr_unit, lpr_ini}; +struct dib lpr_dib = { 0xFF, 1, lpr_startio, lpr_startcmd, NULL, lpr_unit, lpr_ini}; DEVICE lpr_dev = { "LPR", lpr_unit, NULL, lpr_mod, @@ -291,7 +292,19 @@ print_line(UNIT * uptr) } -uint8 lpr_startcmd(UNIT * uptr, uint16 chan, uint8 cmd) +uint8 lpr_startio(UNIT *uptr) { + + if ((uptr->CMD & LPR_CMDMSK) != 0) { + if ((uptr->flags & UNIT_ATT) != 0) + return SNS_BSY; + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + } + sim_debug(DEBUG_CMD, &lpr_dev, "start io unit\n"); + return 0; +} + + +uint8 lpr_startcmd(UNIT * uptr, uint8 cmd) { if ((uptr->CMD & LPR_CMDMSK) != 0) { if ((uptr->flags & UNIT_ATT) != 0) @@ -316,6 +329,9 @@ uint8 lpr_startcmd(UNIT * uptr, uint16 chan, uint8 cmd) sim_activate(uptr, 10); /* Start unit off */ uptr->SNS = 0; uptr->POS = 0; + /* Motion and not load UCS */ + if ((cmd & 0x77) != 0x73 && (cmd & 07) == 3) + return SNS_CHNEND; return 0; case 0: /* Status */ @@ -390,7 +406,10 @@ lpr_srv(UNIT *uptr) { uptr->SNS = SNS_CMDREJ; uptr->CMD &= ~(LPR_CMDMSK); sim_debug(DEBUG_DETAIL, &lpr_dev, "%d Invalid skip %x %d", u, l, l); - chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + if (cmd == 3) + set_devattn(addr, SNS_DEVEND|SNS_UNITCHK); + else + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SCPE_OK; } @@ -400,10 +419,10 @@ lpr_srv(UNIT *uptr) { uptr->CMD &= ~(LPR_FULL|LPR_CMDMSK); uptr->POS = 0; if (uptr->SNS & SNS_CHN12) { - chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); + set_devattn(addr, SNS_DEVEND|SNS_UNITEXP); uptr->SNS &= 0xff; } else { - chan_end(addr, SNS_CHNEND|SNS_DEVEND); + set_devattn(addr, SNS_DEVEND); } return SCPE_OK; } diff --git a/IBM360/ibm360_mt.c b/IBM360/ibm360_mt.c index 9bb09b4..9e552de 100644 --- a/IBM360/ibm360_mt.c +++ b/IBM360/ibm360_mt.c @@ -140,7 +140,8 @@ #define SNS u5 #define CPOS u6 -uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; +uint8 mt_startio(UNIT *uptr); +uint8 mt_startcmd(UNIT *uptr, uint8 cmd); t_stat mt_srv(UNIT *); t_stat mt_boot(int32, DEVICE *); void mt_ini(UNIT *, t_bool); @@ -178,7 +179,7 @@ UNIT mta_unit[] = { {UDATA(&mt_srv, UNIT_MT(0), 0), 0, UNIT_ADDR(0x187)}, /* 7 */ }; -struct dib mta_dib = { 0xF8, NUM_UNITS_MT, NULL, mt_startcmd, NULL, mta_unit, mt_ini}; +struct dib mta_dib = { 0xF8, NUM_UNITS_MT, mt_startio, mt_startcmd, NULL, mta_unit, mt_ini}; DEVICE mta_dev = { "MTA", mta_unit, NULL, mt_mod, @@ -200,7 +201,7 @@ UNIT mtb_unit[] = { {UDATA(&mt_srv, UNIT_MT(1), 0), 0, UNIT_ADDR(0x287)}, /* 7 */ }; -struct dib mtb_dib = { 0xF8, NUM_UNITS_MT, NULL, mt_startcmd, NULL, mtb_unit, mt_ini}; +struct dib mtb_dib = { 0xF8, NUM_UNITS_MT, mt_startio, mt_startcmd, NULL, mtb_unit, mt_ini}; DEVICE mtb_dev = { "MTB", mtb_unit, NULL, mt_mod, @@ -233,8 +234,29 @@ uint8 bcd_to_ebcdic[64] = { 0x50, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xc0, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f}; +uint8 mt_startio(UNIT *uptr) { + DEVICE *dptr = find_dev_from_unit(uptr); + unsigned int i; -uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { +#if 0 + if (mt_busy[GET_DEV_BUF(dptr->flags)] != 0) { + sim_debug(DEBUG_CMD, dptr, "busy\n"); + uptr->flags |= MT_BUSY; /* Flag we need to send CUE */ + return SNS_BSY; + } + /* Check if controller is free */ + for (i = 0; i < dptr->numunits; i++) { + if ((dptr->units[i].CMD & MT_CMDMSK) != 0) { + uptr->flags |= MT_BUSY; /* Flag we need to send CUE */ + return SNS_BSY; + } + } + sim_debug(DEBUG_CMD, dptr, "start io\n"); +#endif + return 0; +} + +uint8 mt_startcmd(UNIT *uptr, uint8 cmd) { DEVICE *dptr = find_dev_from_unit(uptr); int unit = (uptr - dptr->units); diff --git a/IBM360/ibm360_scom.c b/IBM360/ibm360_scom.c index 873dfc1..46e0e06 100644 --- a/IBM360/ibm360_scom.c +++ b/IBM360/ibm360_scom.c @@ -116,7 +116,7 @@ struct _line { extern int32 tmxr_poll; -uint8 scoml_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; +uint8 scoml_startcmd(UNIT *uptr, uint8 cmd) ; uint8 scoml_haltio(UNIT *uptr); t_stat scoml_srv(UNIT *uptr); t_stat scom_reset(DEVICE *dptr); @@ -188,7 +188,7 @@ DEVICE scoml_dev = { /* * Issue a scommand to the 2701 controller. */ -uint8 scoml_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { +uint8 scoml_startcmd(UNIT *uptr, uint8 cmd) { DEVICE *dptr = find_dev_from_unit(uptr); int unit = (uptr - dptr->units); diff --git a/IBM360/ibm360_sys.c b/IBM360/ibm360_sys.c index 3d6d7bf..c871444 100644 --- a/IBM360/ibm360_sys.c +++ b/IBM360/ibm360_sys.c @@ -47,43 +47,44 @@ int32 sim_emax = 16; DEVICE *sim_devices[] = { &cpu_dev, + &chan_dev, #ifdef NUM_DEVS_CON - &con_dev, + &con_dev, #endif #ifdef NUM_DEVS_CDR - &cdr_dev, + &cdr_dev, #endif #ifdef NUM_DEVS_CDP - &cdp_dev, + &cdp_dev, #endif #ifdef NUM_DEVS_LPR - &lpr_dev, + &lpr_dev, #endif #ifdef NUM_DEVS_MT - &mta_dev, + &mta_dev, #if NUM_DEVS_MT > 1 - &mtb_dev, + &mtb_dev, #endif #endif #ifdef NUM_DEVS_DASD - &dda_dev, + &dda_dev, #if NUM_DEVS_DASD > 1 - &ddb_dev, + &ddb_dev, #if NUM_DEVS_DASD > 2 - &ddc_dev, + &ddc_dev, #if NUM_DEVS_DASD > 3 - &ddd_dev, + &ddd_dev, #endif #endif #endif #endif #ifdef NUM_DEVS_COM - &coml_dev, - &com_dev, + &coml_dev, + &com_dev, #endif #ifdef NUM_DEVS_SCOM - &scoml_dev, - &scom_dev, + &scoml_dev, + &scom_dev, #endif NULL }; diff --git a/doc/ibm360.doc b/doc/ibm360.doc index 5b3d271f97b3850f28150ab81153a2d3991bca9f..8acab189f5aa8420fb79a037c896d23b304be1f4 100644 GIT binary patch delta 12325 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 Zqsu*Jas@3dGfRJ~OTEIF=4x~O{SQhZqsagO