diff --git a/SEL32/sel32_chan.c b/SEL32/sel32_chan.c index 0d29db2..24413f4 100644 --- a/SEL32/sel32_chan.c +++ b/SEL32/sel32_chan.c @@ -41,9 +41,9 @@ /* Bits 13-15 - Aug code = 5 - TD */ /* Bits 16-18 - TD Level 2000, 4000, 8000 */ -/* 01 - TD 2000 Level Status Testing */ -/* 02 - TD 4000 Level Status Testing */ -/* 04 - TD 8000 Level Status Testing */ +/* 01 - TD 2000 Level Status Testing */ +/* 02 - TD 4000 Level Status Testing */ +/* 04 - TD 8000 Level Status Testing */ /* CC1 CC2 CC3 CC4 */ /* TD8000 Undefined I/O Activ I/O Error Dev Stat Present */ /* TD4000 Invd Mem Acc Mem Parity Prog Viol Data Ovr/Undr */ @@ -58,81 +58,81 @@ /* Bits 00-06 - Op code 0xFC */ /* Bits 09-12 - I/O type */ -/* 00 - Unassigned */ -/* 01 - Unassigned */ -/* 02 - Start I/O (SIO) */ -/* 03 - Test I/O (TIO) */ -/* 04 - Stop I/O (STPIO */ -/* 05 - Reset channel (RSCHNL) */ -/* 06 - Halt I/O (HIO) */ -/* 07 - Grab controller (GRIO) Not supported */ -/* 08 - Reset channel (RSCTL) */ -/* 09 - Enable write channel WCS (ECWCS) Not supported */ -/* 0A - Unassigned */ -/* 0B - Write channel WCS (WCWCS) Not supported */ -/* 0C - Enable channel interrupt (ECI) */ -/* 0D - Disable channel interrupt (DCI) */ -/* 0E - Activate channel interrupt (ACI) */ -/* 0F - Deactivate channel interrupt (DACI) */ +/* 00 - Unassigned */ +/* 01 - Unassigned */ +/* 02 - Start I/O (SIO) */ +/* 03 - Test I/O (TIO) */ +/* 04 - Stop I/O (STPIO */ +/* 05 - Reset channel (RSCHNL) */ +/* 06 - Halt I/O (HIO) */ +/* 07 - Grab controller (GRIO) Not supported */ +/* 08 - Reset channel (RSCTL) */ +/* 09 - Enable write channel WCS (ECWCS) Not supported */ +/* 0A - Unassigned */ +/* 0B - Write channel WCS (WCWCS) Not supported */ +/* 0C - Enable channel interrupt (ECI) */ +/* 0D - Disable channel interrupt (DCI) */ +/* 0E - Activate channel interrupt (ACI) */ +/* 0F - Deactivate channel interrupt (DACI) */ /* Bits 13-15 - Aug Code */ /* Bit 16 - unused - must be zero */ /* Bits 16-23 - Channel address (0-127) */ /* Bits 24-31 - Device Sub address (0-255) */ -int channels = MAX_CHAN; /* maximum number of channels */ -int subchannels = SUB_CHANS; /* maximum number of subchannel devices */ -int irq_pend = 0; /* pending interrupt flag */ +int channels = MAX_CHAN; /* maximum number of channels */ +int subchannels = SUB_CHANS; /* maximum number of subchannel devices */ +int irq_pend = 0; /* pending interrupt flag */ -#define AMASK 0x00ffffff /* 24 bit mask */ +#define AMASK 0x00ffffff /* 24 bit mask */ -extern uint32 M[]; /* our memory */ -extern uint32 SPAD[]; /* CPU scratchpad memory */ -extern uint32 CPUSTATUS; /* CPU status word */ -extern uint32 INTS[]; /* Interrupt status flags */ +extern uint32 M[]; /* our memory */ +extern uint32 SPAD[]; /* CPU scratchpad memory */ +extern uint32 CPUSTATUS; /* CPU status word */ +extern uint32 INTS[]; /* Interrupt status flags */ extern uint16 ccw_count[]; extern int traceme, trstart; #if 0 #define FIFO_SIZE 256 /* FIFO structure */ -uint32 chan_fifo[MAX_CHAN][FIFO_SIZE]; /* interrupt status fifo each channel */ -uint32 chan_fifo_in[MAX_CHAN]; /* fifo input index */ -uint32 chan_fifo_out[MAX_CHAN]; /* fifo output index */ +uint32 chan_fifo[MAX_CHAN][FIFO_SIZE]; /* interrupt status fifo each channel */ +uint32 chan_fifo_in[MAX_CHAN]; /* fifo input index */ +uint32 chan_fifo_out[MAX_CHAN]; /* fifo output index */ /* channel values defined in CHANP structure */ -uint32 chan_inch_addr[MAX_CHAN]; /* Channel status dw in memory */ -uint32 chan_caw[MAX_CHAN]; /* Channel command address word */ -uint32 ccw_addr[MAX_CHAN]; /* Channel address */ -uint16 ccw_count[MAX_CHAN]; /* Channel count */ -uint8 ccw_cmd[MAX_CHAN]; /* Channel command and flags */ -uint16 ccw_flags[MAX_CHAN]; /* Channel flags */ -uint16 chan_status[MAX_CHAN]; /* Channel status */ -uint16 chan_dev[MAX_CHAN]; /* Device on channel */ -uint32 chan_buf[MAX_CHAN]; /* Channel data buffer */ -uint8 chan_byte[MAX_CHAN]; /* Current byte, dirty/full */ +uint32 chan_inch_addr[MAX_CHAN]; /* Channel status dw in memory */ +uint32 chan_caw[MAX_CHAN]; /* Channel command address word */ +uint32 ccw_addr[MAX_CHAN]; /* Channel address */ +uint16 ccw_count[MAX_CHAN]; /* Channel count */ +uint8 ccw_cmd[MAX_CHAN]; /* Channel command and flags */ +uint16 ccw_flags[MAX_CHAN]; /* Channel flags */ +uint16 chan_status[MAX_CHAN]; /* Channel status */ +uint16 chan_dev[MAX_CHAN]; /* Device on channel */ +uint32 chan_buf[MAX_CHAN]; /* Channel data buffer */ +uint8 chan_byte[MAX_CHAN]; /* Current byte, dirty/full */ #endif /* device status */ -DIB *dev_unit[MAX_DEV]; /* Pointer to Device info block */ -uint16 dev_status[MAX_DEV]; /* last device status flags */ -uint16 loading; /* set when booting */ +DIB *dev_unit[MAX_DEV]; /* Pointer to Device info block */ +uint16 dev_status[MAX_DEV]; /* last device status flags */ +uint16 loading; /* set when booting */ -#define get_chan(chsa) ((chsa>>8)&0x7f) /* get channel number from ch/sa */ +#define get_chan(chsa) ((chsa>>8)&0x7f) /* get channel number from ch/sa */ /* forward definitions */ -CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */ -UNIT *find_unit_ptr(uint16 chsa); /* find unit pointer */ +CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */ +UNIT *find_unit_ptr(uint16 chsa); /* find unit pointer */ int chan_read_byte(uint16 chan, uint8 *data); int chan_write_byte(uint16 chan, uint8 *data); void set_devattn(uint16 chsa, uint16 flags); -void set_devwake(uint16 chsa, uint16 flags); /* wakeup O/S for async line */ +void set_devwake(uint16 chsa, uint16 flags); /* wakeup O/S for async line */ void chan_end(uint16 chan, uint16 flags); int test_write_byte_end(uint16 chsa); -t_stat startxio(uint16 chsa, uint32 *status); /* start XIO */ -t_stat testxio(uint16 chsa, uint32 *status); /* test XIO */ -t_stat stoptxio(uint16 chsa, uint32 *status); /* stop XIO */ -t_stat rschnlxio(uint16 chsa, uint32 *status); /* reset channel XIO */ -t_stat haltxio(uint16 chsa, uint32 *status); /* halt XIO */ -t_stat grabxio(uint16 chsa, uint32 *status); /* grab XIO n/u */ -t_stat rsctlxio(uint16 chsa, uint32 *status); /* reset controller XIO */ +t_stat startxio(uint16 chsa, uint32 *status); /* start XIO */ +t_stat testxio(uint16 chsa, uint32 *status); /* test XIO */ +t_stat stoptxio(uint16 chsa, uint32 *status); /* stop XIO */ +t_stat rschnlxio(uint16 chsa, uint32 *status); /* reset channel XIO */ +t_stat haltxio(uint16 chsa, uint32 *status); /* halt XIO */ +t_stat grabxio(uint16 chsa, uint32 *status); /* grab XIO n/u */ +t_stat rsctlxio(uint16 chsa, uint32 *status); /* reset controller XIO */ uint32 find_int_icb(uint16 chsa); uint32 find_int_lev(uint16 chsa); uint32 scan_chan(void); @@ -159,154 +159,154 @@ t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc); /* add an entry to the FIFO */ int32 FIFO_Put(uint16 chsa, uint32 entry) { - DIB *dibp = dev_unit[chsa & 0x7f00]; /* get DIB pointer for channel */ - if (dibp->chan_fifo_in == ((dibp->chan_fifo_out-1+FIFO_SIZE) % FIFO_SIZE)) { - return -1; /* FIFO Full */ - } -// fprintf(stderr, "FIFO PUT chsa %x entry %x index %x\r\n", chsa, entry, dibp->chan_fifo_in); - dibp->chan_fifo[dibp->chan_fifo_in] = entry; /* add new entry */ - dibp->chan_fifo_in += 1; /* next entry */ - dibp->chan_fifo_in %= FIFO_SIZE; /* modulo FIFO size */ - return 0; /* all OK */ + DIB *dibp = dev_unit[chsa & 0x7f00]; /* get DIB pointer for channel */ + if (dibp->chan_fifo_in == ((dibp->chan_fifo_out-1+FIFO_SIZE) % FIFO_SIZE)) { + return -1; /* FIFO Full */ + } +// fprintf(stderr, "FIFO PUT chsa %x entry %x index %x\r\n", chsa, entry, dibp->chan_fifo_in); + dibp->chan_fifo[dibp->chan_fifo_in] = entry; /* add new entry */ + dibp->chan_fifo_in += 1; /* next entry */ + dibp->chan_fifo_in %= FIFO_SIZE; /* modulo FIFO size */ + return 0; /* all OK */ } /* get the next entry from the FIFO */ int FIFO_Get(uint16 chsa, uint32 *old) { - DIB *dibp = dev_unit[chsa & 0x7f00]; /* get DIB pointer for channel */ - /* see if the FIFO is empty */ - if (dibp->chan_fifo_in == dibp->chan_fifo_out) { - return -1; /* FIFO is empty, tell caller */ - } - *old = dibp->chan_fifo[dibp->chan_fifo_out]; /* get the next entry */ -// fprintf(stderr, "FIFO GET chsa %x entry %x index %x\r\n", chsa, *old, dibp->chan_fifo_out); - dibp->chan_fifo_out += 1; /* next entry */ - dibp->chan_fifo_out %= FIFO_SIZE; /* modulo FIFO size */ - return 0; /* all OK */ + DIB *dibp = dev_unit[chsa & 0x7f00]; /* get DIB pointer for channel */ + /* see if the FIFO is empty */ + if (dibp->chan_fifo_in == dibp->chan_fifo_out) { + return -1; /* FIFO is empty, tell caller */ + } + *old = dibp->chan_fifo[dibp->chan_fifo_out]; /* get the next entry */ +// fprintf(stderr, "FIFO GET chsa %x entry %x index %x\r\n", chsa, *old, dibp->chan_fifo_out); + dibp->chan_fifo_out += 1; /* next entry */ + dibp->chan_fifo_out %= FIFO_SIZE; /* modulo FIFO size */ + return 0; /* all OK */ } /* Find interrupt level for the given device (ch/sa) */ /* return 0 if not found, otherwise leve number */ uint32 find_int_lev(uint16 chsa) { - uint32 chan, level, val; - int i; + uint32 chan, level, val; + int i; - chan = (chsa >> 8) & 0x7f; /* get channel number */ - /* scan the channel entries for our chan */ - for (i=0; i<128; i++) { - val = SPAD[i]; /* get spad entry */ - if ((val == 0) || (val == 0xffffffff)) - continue; /* not valid entry */ - /* look for class F devices */ - if ((val & 0x0f000000) == 0x0f000000) { - /* F class only uses chan entry */ - if (((val >> 8 ) & 0x7f) == chan) { - /* channel matches, now get interrupt level number */ - level = ((val >> 16) & 0x7f); /* 1's comp of int level */ - level = 127 - level; /* get positive number level */ - sim_debug(DEBUG_EXP, &cpu_dev, - "find_int_lev F SPAD %x chan %x chsa %x level %x\n", val, chan, chsa, level); - return(level); /* return the level*/ - } - } - /* look for E class or class 3 device */ - if (((val & 0x0f000000) == 0x0e000000) || /* E class */ - ((val & 0x0f800000) == 0x03800000)) { /* class 3 (interval timer) */ - /* E class uses chan and device address */ - if ((val & 0x7f00) == (chsa & 0x7f00)) { /* check chan/subaddress */ - /* channel/subaddress matches, now get interrupt level number */ - level = ((val >> 16) & 0x7f); /* 1's comp of int level */ - level = 127 - level; /* get positive number level */ - sim_debug(DEBUG_EXP, &cpu_dev, - "find_int_lev E SPAD %x chan %x chsa %x level %x\n", val, chan, chsa, level); - return(level); /* return the level*/ - } - } - } - /* not a real device, so check interrupt entries for match */ - /* scan the entries for our channel/subaddress */ - for (i=0; i<112; i++) { - val = SPAD[i+0x80]; /* get spade entry */ - if (val == 0 || val == 0xffffffff) - continue; /* not valid entry */ - /* look for class 3 device or non device entries */ - if (((val & 0x0f800000) == 0x00800000) || /* clock or external interrupt */ - ((val & 0x0f800000) == 0x03800000)) { /* class 3 (interval timer) */ - /* E class or non I/O uses chan and device address */ - if ((val & 0x7f00) == (chsa & 0x7f00)) { /* check chan/sub address */ - /* channel/subaddress matches, now get interrupt level number */ - level = ((val >> 16) & 0x7f); /* 1's comp of int level */ - level = 127 - level; /* get positive number level */ - return(level); /* return the level*/ - } - } - } - return 0; /* not found */ + chan = (chsa >> 8) & 0x7f; /* get channel number */ + /* scan the channel entries for our chan */ + for (i=0; i<128; i++) { + val = SPAD[i]; /* get spad entry */ + if ((val == 0) || (val == 0xffffffff)) + continue; /* not valid entry */ + /* look for class F devices */ + if ((val & 0x0f000000) == 0x0f000000) { + /* F class only uses chan entry */ + if (((val >> 8 ) & 0x7f) == chan) { + /* channel matches, now get interrupt level number */ + level = ((val >> 16) & 0x7f); /* 1's comp of int level */ + level = 127 - level; /* get positive number level */ + sim_debug(DEBUG_EXP, &cpu_dev, + "find_int_lev F SPAD %x chan %x chsa %x level %x\n", val, chan, chsa, level); + return(level); /* return the level*/ + } + } + /* look for E class or class 3 device */ + if (((val & 0x0f000000) == 0x0e000000) || /* E class */ + ((val & 0x0f800000) == 0x03800000)) { /* class 3 (interval timer) */ + /* E class uses chan and device address */ + if ((val & 0x7f00) == (chsa & 0x7f00)) { /* check chan/subaddress */ + /* channel/subaddress matches, now get interrupt level number */ + level = ((val >> 16) & 0x7f); /* 1's comp of int level */ + level = 127 - level; /* get positive number level */ + sim_debug(DEBUG_EXP, &cpu_dev, + "find_int_lev E SPAD %x chan %x chsa %x level %x\n", val, chan, chsa, level); + return(level); /* return the level*/ + } + } + } + /* not a real device, so check interrupt entries for match */ + /* scan the entries for our channel/subaddress */ + for (i=0; i<112; i++) { + val = SPAD[i+0x80]; /* get spade entry */ + if (val == 0 || val == 0xffffffff) + continue; /* not valid entry */ + /* look for class 3 device or non device entries */ + if (((val & 0x0f800000) == 0x00800000) || /* clock or external interrupt */ + ((val & 0x0f800000) == 0x03800000)) { /* class 3 (interval timer) */ + /* E class or non I/O uses chan and device address */ + if ((val & 0x7f00) == (chsa & 0x7f00)) { /* check chan/sub address */ + /* channel/subaddress matches, now get interrupt level number */ + level = ((val >> 16) & 0x7f); /* 1's comp of int level */ + level = 127 - level; /* get positive number level */ + return(level); /* return the level*/ + } + } + } + return 0; /* not found */ } /* Find interrupt context block address for given device (ch/sa) */ /* return 0 if not found, otherwise ICB memory address */ uint32 find_int_icb(uint16 chsa) { - uint32 level, icba; + uint32 level, icba; - level = find_int_lev(chsa); /* find the int level */ - if (level == 0) - return 0; /* not found */ - icba = SPAD[0xf1] + (level<<2); /* interrupt vector address in memory */ - icba = M[icba>>2]; /* get address of ICB from memory */ - return(icba); /* return the address */ + level = find_int_lev(chsa); /* find the int level */ + if (level == 0) + return 0; /* not found */ + icba = SPAD[0xf1] + (level<<2); /* interrupt vector address in memory */ + icba = M[icba>>2]; /* get address of ICB from memory */ + return(icba); /* return the address */ } /* Find unit pointer for given device (ch/sa) */ UNIT *find_unit_ptr(uint16 chsa) { - struct dib *dibp; /* DIB pointer */ - UNIT *uptr; /* UNIT pointer */ - int i; + struct dib *dibp; /* DIB pointer */ + UNIT *uptr; /* UNIT pointer */ + int i; - dibp = dev_unit[chsa]; /* get DIB pointer from device pointers */ - if (dibp == 0) { /* if zero, not defined on system */ + dibp = dev_unit[chsa]; /* get DIB pointer from device pointers */ + if (dibp == 0) { /* if zero, not defined on system */ //fprintf(stderr, "find_unit_ptr NULL DIB PTR chsa %0x\r\n", chsa); - return NULL; /* tell caller */ - } + return NULL; /* tell caller */ + } - uptr = dibp->units; /* get the pointer to the units on this channel */ - for (i = 0; i < dibp->numunits; i++) { /* search through units to get a match */ - if (chsa == GET_UADDR(uptr->u3)) { /* does ch/sa match? */ - return uptr; /* return the pointer */ - } - uptr++; /* next unit */ - } - return NULL; /* device not found on system */ + uptr = dibp->units; /* get the pointer to the units on this channel */ + for (i = 0; i < dibp->numunits; i++) { /* search through units to get a match */ + if (chsa == GET_UADDR(uptr->u3)) { /* does ch/sa match? */ + return uptr; /* return the pointer */ + } + uptr++; /* next unit */ + } + return NULL; /* device not found on system */ } /* Find chanp pointer for given device (ch/sa) */ CHANP *find_chanp_ptr(uint16 chsa) { - struct dib *dibp; /* DIB pointer */ - UNIT *uptr; /* UNIT pointer */ - CHANP *chp; /* CHANP pointer */ - int i; + struct dib *dibp; /* DIB pointer */ + UNIT *uptr; /* UNIT pointer */ + CHANP *chp; /* CHANP pointer */ + int i; - dibp = dev_unit[chsa]; /* get DIB pointer from device pointers */ - if (dibp == 0) /* if zero, not defined on system */ - return NULL; /* tell caller */ - if ((chp = (CHANP *)dibp->chan_prg) == NULL) { /* must have channel information for each device */ + dibp = dev_unit[chsa]; /* get DIB pointer from device pointers */ + if (dibp == 0) /* if zero, not defined on system */ + return NULL; /* tell caller */ + if ((chp = (CHANP *)dibp->chan_prg) == NULL) { /* must have channel information for each device */ //fprintf(stderr, "find_chanp_ptr NULL DIB PTR chsa %0x\r\n", chsa); - return NULL; /* tell caller */ - } + return NULL; /* tell caller */ + } - uptr = dibp->units; /* get the pointer to the units on this channel */ - for (i = 0; i < dibp->numunits; i++) { /* search through units to get a match */ - if (chsa == GET_UADDR(uptr->u3)) { /* does ch/sa match? */ - return chp; /* return the pointer */ - } - uptr++; /* next UNIT */ - chp++; /* next CHANP */ - } - return NULL; /* device not found on system */ + uptr = dibp->units; /* get the pointer to the units on this channel */ + for (i = 0; i < dibp->numunits; i++) { /* search through units to get a match */ + if (chsa == GET_UADDR(uptr->u3)) { /* does ch/sa match? */ + return chp; /* return the pointer */ + } + uptr++; /* next UNIT */ + chp++; /* next CHANP */ + } + return NULL; /* device not found on system */ } /* Read a full word into memory. @@ -315,15 +315,15 @@ CHANP *find_chanp_ptr(uint16 chsa) */ int readfull(CHANP *chp, uint32 maddr, uint32 *word) { - maddr &= AMASK; /* mask addr to 24 bits */ - if (maddr > MEMSIZE) { /* see if mem addr > MEMSIZE */ - chp->chan_status |= STATUS_PCHK; /* program check error */ - return 1; /* show we have error */ - } - maddr >>= 2; /* get 32 bit word index */ - *word = M[maddr]; /* get the contents */ - sim_debug(DEBUG_EXP, &cpu_dev, "readfull read %x from addr %x\n", *word, maddr<<2); - return 0; /* return OK */ + maddr &= AMASK; /* mask addr to 24 bits */ + if (maddr > MEMSIZE) { /* see if mem addr > MEMSIZE */ + chp->chan_status |= STATUS_PCHK; /* program check error */ + return 1; /* show we have error */ + } + maddr >>= 2; /* get 32 bit word index */ + *word = M[maddr]; /* get the contents */ + sim_debug(DEBUG_EXP, &cpu_dev, "readfull read %x from addr %x\n", *word, maddr<<2); + return 0; /* return OK */ } /* Read a word into the channel buffer. @@ -333,28 +333,28 @@ int readfull(CHANP *chp, uint32 maddr, uint32 *word) int readbuff(CHANP *chp) { int k; - uint32 addr = chp->ccw_addr; /* channel buffer address */ - uint16 chan = get_chan(chp->chan_dev); /* our channel */ + uint32 addr = chp->ccw_addr; /* channel buffer address */ + uint16 chan = get_chan(chp->chan_dev); /* our channel */ - if ((addr & AMASK) > MEMSIZE) { /* see if memory address invalid */ - chp->chan_status |= STATUS_PCHK; /* bad, program check */ - chp->chan_byte = BUFF_CHNEND; /* force channel end */ - irq_pend = 1; /* and we have an interrupt */ - return 1; /* done, with error */ + if ((addr & AMASK) > MEMSIZE) { /* see if memory address invalid */ + chp->chan_status |= STATUS_PCHK; /* bad, program check */ + chp->chan_byte = BUFF_CHNEND; /* force channel end */ + irq_pend = 1; /* and we have an interrupt */ + return 1; /* done, with error */ } - addr &= AMASK; /* address only */ - addr >>= 2; /* byte to word address */ - chp->chan_buf = M[addr]; /* get 4 bytes */ + addr &= AMASK; /* address only */ + addr >>= 2; /* byte to word address */ + chp->chan_buf = M[addr]; /* get 4 bytes */ - sim_debug(DEBUG_DATA, &cpu_dev, "readbuff read memory bytes into buffer %02x %06x %08x %08x [", + sim_debug(DEBUG_DATA, &cpu_dev, "readbuff read memory bytes into buffer %02x %06x %08x %08x [", chan, chp->ccw_addr & 0xFFFFFC, chp->chan_buf, chp->ccw_count); for(k = 24; k >= 0; k -= 8) { char ch = (chp->chan_buf >> k) & 0xFF; if (ch < 0x20 || ch == 0xff) ch = '.'; - sim_debug(DEBUG_DATA, &cpu_dev, "%c", ch); + sim_debug(DEBUG_DATA, &cpu_dev, "%c", ch); } - sim_debug(DEBUG_DATA, &cpu_dev, "]\n"); + sim_debug(DEBUG_DATA, &cpu_dev, "]\n"); return 0; } @@ -382,259 +382,259 @@ int writebuff(CHANP *chp) /* return = 1 error, chan_status will have reason */ int load_ccw(CHANP *chp, int tic_ok) { - uint32 word; - int docmd = 0; - UNIT *uptr; - uint16 chan = get_chan(chp->chan_dev); /* our channel */ + uint32 word; + int docmd = 0; + UNIT *uptr; + uint16 chan = get_chan(chp->chan_dev); /* our channel */ loop: - /* Abort if we have any errors */ - if (chp->chan_status & 0x3f03) { /* check channel status */ - sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw ERROR chan_status[%x] %x\n", chan, chp->chan_status); -// fprintf(stderr, "load_ccw ERROR chan_status[%x] %x\r\n", chan, chp->chan_status); - return 1; - } + /* Abort if we have any errors */ + if (chp->chan_status & 0x3f03) { /* check channel status */ + sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw ERROR chan_status[%x] %x\n", chan, chp->chan_status); +// fprintf(stderr, "load_ccw ERROR chan_status[%x] %x\r\n", chan, chp->chan_status); + return 1; + } - /* Check if we have status modifier set */ - if (chp->chan_status & STATUS_MOD) { - chp->chan_caw += 8; /* move to next IOCD */ - chp->chan_status &= ~STATUS_MOD; /* turn off status modifier flag */ - } + /* Check if we have status modifier set */ + if (chp->chan_status & STATUS_MOD) { + chp->chan_caw += 8; /* move to next IOCD */ + chp->chan_status &= ~STATUS_MOD; /* turn off status modifier flag */ + } - /* Read in first or next CCW */ - if (readfull(chp, chp->chan_caw, &word) != 0) { /* read word from memory */ - chp->chan_status |= STATUS_PCHK; /* memory read error, program check */ - sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw ERROR chan_status[%x] %x\n", chan, chp->chan_status); -// fprintf(stderr, "load_ccw ERROR chan_status[%x] %x\r\n", chan, chp->chan_status); - return 1; /* error return */ - } + /* Read in first or next CCW */ + if (readfull(chp, chp->chan_caw, &word) != 0) { /* read word from memory */ + chp->chan_status |= STATUS_PCHK; /* memory read error, program check */ + sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw ERROR chan_status[%x] %x\n", chan, chp->chan_status); +// fprintf(stderr, "load_ccw ERROR chan_status[%x] %x\r\n", chan, chp->chan_status); + return 1; /* error return */ + } - sim_debug(DEBUG_CMD, &cpu_dev, "load_ccw read ccw chan %02x caw %06x IOCD wd 1 %08x\n", - chan, chp->chan_caw, word); -// fprintf(stderr, "load_ccw read ccw chan %02x caw %06x IOCD wd 1 %08x\r\n", -// chan, chp->chan_caw, word); - /* TIC can't follow TIC or be first in command chain */ - if (((word >> 24) & 0xf) == CMD_TIC) { - if (tic_ok) { - chp->chan_caw = word & AMASK; /* get new IOCD address */ - tic_ok = 0; /* another tic not allowed */ - goto loop; /* restart the IOCD processing */ - } - chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ - sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw ERROR chan_status[%x] %x\n", chan, chp->chan_status); -// fprintf(stderr, "load_ccw ERROR chan_status[%x] %x\r\n", chan, chp->chan_status); - irq_pend = 1; /* status pending */ - return 1; /* error return */ - } - chp->chan_caw += 4; /* point to 2nd word of the IOCD */ + sim_debug(DEBUG_CMD, &cpu_dev, "load_ccw read ccw chan %02x caw %06x IOCD wd 1 %08x\n", + chan, chp->chan_caw, word); +// fprintf(stderr, "load_ccw read ccw chan %02x caw %06x IOCD wd 1 %08x\r\n", +// chan, chp->chan_caw, word); + /* TIC can't follow TIC or be first in command chain */ + if (((word >> 24) & 0xf) == CMD_TIC) { + if (tic_ok) { + chp->chan_caw = word & AMASK; /* get new IOCD address */ + tic_ok = 0; /* another tic not allowed */ + goto loop; /* restart the IOCD processing */ + } + chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ + sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw ERROR chan_status[%x] %x\n", chan, chp->chan_status); +// fprintf(stderr, "load_ccw ERROR chan_status[%x] %x\r\n", chan, chp->chan_status); + irq_pend = 1; /* status pending */ + return 1; /* error return */ + } + chp->chan_caw += 4; /* point to 2nd word of the IOCD */ - /* Check if not chaining data */ - if ((chp->ccw_flags & FLAG_DC) == 0) { - chp->ccw_cmd = (word >> 24) & 0xff; /* not DC, so set command from IOCD wd 1 */ - sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw No DC, flags %x cmd %x\n", - chp->ccw_flags, chp->ccw_cmd); -// fprintf(stderr, "load_ccw No DC, flags %x cmd %x\r\n", -// chp->ccw_flags, chp->ccw_cmd); - docmd = 1; /* show we have a command */ - } - /* Set up for this command */ - chp->ccw_addr = word & AMASK; /* set the data address */ - readfull(chp, chp->chan_caw, &word); /* get IOCD WD 2 */ + /* Check if not chaining data */ + if ((chp->ccw_flags & FLAG_DC) == 0) { + chp->ccw_cmd = (word >> 24) & 0xff; /* not DC, so set command from IOCD wd 1 */ + sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw No DC, flags %x cmd %x\n", + chp->ccw_flags, chp->ccw_cmd); +// fprintf(stderr, "load_ccw No DC, flags %x cmd %x\r\n", +// chp->ccw_flags, chp->ccw_cmd); + docmd = 1; /* show we have a command */ + } + /* Set up for this command */ + chp->ccw_addr = word & AMASK; /* set the data address */ + readfull(chp, chp->chan_caw, &word); /* get IOCD WD 2 */ - sim_debug(DEBUG_CMD, &cpu_dev, "load_ccw read ccw chan %02x caw %06x IOCD wd 2 %08x\n", - chan, chp->chan_caw, word); -// fprintf(stderr, "load_ccw read ccw chan %02x caw %06x IOCD wd 2 %08x\r\n", chan, chp->chan_caw, word); - chp->chan_caw += 4; /* next IOCD address */ - chp->ccw_count = word & 0xffff; /* get 16 bit byte count from IOCD WD 2*/ - chp->ccw_flags = (word >> 16) & 0xffff; /* get flags from bits 0-7 of WD 2 of IOCD */ - chp->chan_byte = BUFF_EMPTY; /* no bytes transferred yet */ - if (chp->ccw_flags & FLAG_PCI) { /* do we have prog controlled int? */ - chp->chan_status |= STATUS_PCI; /* set PCI flag in status */ - irq_pend = 1; /* interrupt pending */ - } + sim_debug(DEBUG_CMD, &cpu_dev, "load_ccw read ccw chan %02x caw %06x IOCD wd 2 %08x\n", + chan, chp->chan_caw, word); +// fprintf(stderr, "load_ccw read ccw chan %02x caw %06x IOCD wd 2 %08x\r\n", chan, chp->chan_caw, word); + chp->chan_caw += 4; /* next IOCD address */ + chp->ccw_count = word & 0xffff; /* get 16 bit byte count from IOCD WD 2*/ + chp->ccw_flags = (word >> 16) & 0xffff; /* get flags from bits 0-7 of WD 2 of IOCD */ + chp->chan_byte = BUFF_EMPTY; /* no bytes transferred yet */ + if (chp->ccw_flags & FLAG_PCI) { /* do we have prog controlled int? */ + chp->chan_status |= STATUS_PCI; /* set PCI flag in status */ + irq_pend = 1; /* interrupt pending */ + } - sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw read docmd %x irq_flag %x count %x chan %x\n", - docmd, irq_pend, chp->ccw_count, chan); -// fprintf(stderr, "load_ccw read docmd %x irq_flag %x count %x chan %x\r\n", -// docmd, irq_pend, chp->ccw_count, chan); - /* Check invalid count */ - /* HACK HACK - LPR sends CC cmd only without data addr/count */ - if ((chp->ccw_count == 0) && (chp->ccw_addr != 0)) { /* see if byte count is zero */ - chp->chan_status |= STATUS_PCHK; /* program check if it is */ - irq_pend = 1; /* status pending int */ - return 1; /* error return */ - } - if (docmd) { /* see if we need to process command */ - DIB *dibp = dev_unit[chp->chan_dev]; /* get the device pointer */ - uptr = find_unit_ptr(chp->chan_dev); /* find the unit pointer */ - if (uptr == 0) - return 1; /* if none, error */ + sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw read docmd %x irq_flag %x count %x chan %x\n", + docmd, irq_pend, chp->ccw_count, chan); +// fprintf(stderr, "load_ccw read docmd %x irq_flag %x count %x chan %x\r\n", +// docmd, irq_pend, chp->ccw_count, chan); + /* Check invalid count */ + /* HACK HACK - LPR sends CC cmd only without data addr/count */ + if ((chp->ccw_count == 0) && (chp->ccw_addr != 0)) { /* see if byte count is zero */ + chp->chan_status |= STATUS_PCHK; /* program check if it is */ + irq_pend = 1; /* status pending int */ + return 1; /* error return */ + } + if (docmd) { /* see if we need to process command */ + DIB *dibp = dev_unit[chp->chan_dev]; /* get the device pointer */ + uptr = find_unit_ptr(chp->chan_dev); /* find the unit pointer */ + if (uptr == 0) + return 1; /* if none, error */ - /* Check if this is INCH command */ - if ((chp->ccw_cmd & 0xFF) == 0) { /* see if this is an initialize channel cmd */ - uptr->u4 = (uint32)chp->ccw_addr; /* save the memory address in wd 1 of iocd */ - uptr->us9 = chp->ccw_count & 0xffff; /* get count from IOCD wd 2 */ - /* just drop through and call the device startcmd function */ - /* the INCH buffer will be returned in uptr->u4 and uptr->us9 will be non-zero */ - /* it should just return SNS_CHNEND and SNS_DEVEND status */ - } + /* Check if this is INCH command */ + if ((chp->ccw_cmd & 0xFF) == 0) { /* see if this is an initialize channel cmd */ + uptr->u4 = (uint32)chp->ccw_addr; /* save the memory address in wd 1 of iocd */ + uptr->us9 = chp->ccw_count & 0xffff; /* get count from IOCD wd 2 */ + /* just drop through and call the device startcmd function */ + /* the INCH buffer will be returned in uptr->u4 and uptr->us9 will be non-zero */ + /* it should just return SNS_CHNEND and SNS_DEVEND status */ + } - sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw before start_cmd chan %0x status %.8x count %x\n", - chan, chp->chan_status, chp->ccw_count); + sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw before start_cmd chan %0x status %.8x count %x\n", + chan, chp->chan_status, chp->ccw_count); - /* call the device startcmd function to process command */ - chp->chan_status = dibp->start_cmd(uptr, chan, chp->ccw_cmd); + /* call the device startcmd function to process command */ + chp->chan_status = dibp->start_cmd(uptr, chan, chp->ccw_cmd); - sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw after start_cmd chan %0x status %.8x count %x\n", - chan, chp->chan_status, chp->ccw_count); + sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw after start_cmd chan %0x status %.8x count %x\n", + chan, chp->chan_status, chp->ccw_count); - /* see if bad status */ - if (chp->chan_status & (STATUS_ATTN|STATUS_CHECK|STATUS_EXPT)) { - chp->chan_status |= STATUS_CEND; /* channel end status */ - chp->ccw_flags = 0; /* no flags */ - chp->ccw_cmd = 0; /* stop IOCD processing */ - irq_pend = 1; /* int coming */ - sim_debug(DEBUG_CMD, &cpu_dev, "load_ccw bad status chan %0x status %.8x\n", - chan, chp->chan_status); - return 1; /* error return */ - } + /* see if bad status */ + if (chp->chan_status & (STATUS_ATTN|STATUS_CHECK|STATUS_EXPT)) { + chp->chan_status |= STATUS_CEND; /* channel end status */ + chp->ccw_flags = 0; /* no flags */ + chp->ccw_cmd = 0; /* stop IOCD processing */ + irq_pend = 1; /* int coming */ + sim_debug(DEBUG_CMD, &cpu_dev, "load_ccw bad status chan %0x status %.8x\n", + chan, chp->chan_status); + return 1; /* error return */ + } - /* see if command completed */ - if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { - /* INCH cmd will return here too, get INCH buffer addr from uptr->u4 */ - /* see if this is an initialize channel cmd */ - if ((chp->ccw_cmd & 0xFF) == 0 && (uptr->us9 != 0)) { - chp->chan_inch_addr = uptr->u4; /* save INCH buffer address */ -// fprintf(stderr, "load_ccw INCH %x saved for chan %0x\r\n", -// chp->chan_inch_addr, chan); - sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw INCH %x saved chan %0x\n", - chp->chan_inch_addr, chan); - } - chp->chan_status |= STATUS_CEND; /* set channel end status */ - chp->chan_byte = BUFF_NEWCMD; /* ready for new cmd */ - chp->ccw_cmd = 0; /* stop IOCD processing */ - irq_pend = 1; /* int coming */ - sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw cmd complete chan %0x status %.8x count %x\n", - chan, chp->chan_status, chp->ccw_count); -// fprintf(stderr, "load_ccw cmd complete chan %0x status %.8x count %x\r\n", -// chan, chp->chan_status, chp->ccw_count); - } - } -// fprintf(stderr, "load_ccw return, chan %0x status %.8x count %x\r\n", -// chan, chp->chan_status, chp->ccw_count); -// sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw return, chan %0x status %.8x count %x\n", -// chan, chp->chan_status, chp->ccw_count); - return 0; /* good return */ + /* see if command completed */ + if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { + /* INCH cmd will return here too, get INCH buffer addr from uptr->u4 */ + /* see if this is an initialize channel cmd */ + if ((chp->ccw_cmd & 0xFF) == 0 && (uptr->us9 != 0)) { + chp->chan_inch_addr = uptr->u4; /* save INCH buffer address */ +// fprintf(stderr, "load_ccw INCH %x saved for chan %0x\r\n", +// chp->chan_inch_addr, chan); + sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw INCH %x saved chan %0x\n", + chp->chan_inch_addr, chan); + } + chp->chan_status |= STATUS_CEND; /* set channel end status */ + chp->chan_byte = BUFF_NEWCMD; /* ready for new cmd */ + chp->ccw_cmd = 0; /* stop IOCD processing */ + irq_pend = 1; /* int coming */ + sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw cmd complete chan %0x status %.8x count %x\n", + chan, chp->chan_status, chp->ccw_count); +// fprintf(stderr, "load_ccw cmd complete chan %0x status %.8x count %x\r\n", +// chan, chp->chan_status, chp->ccw_count); + } + } +// fprintf(stderr, "load_ccw return, chan %0x status %.8x count %x\r\n", +// chan, chp->chan_status, chp->ccw_count); +// sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw return, chan %0x status %.8x count %x\n", +// chan, chp->chan_status, chp->ccw_count); + return 0; /* good return */ } /* read byte from memory */ /* write to device */ int chan_read_byte(uint16 chsa, uint8 *data) { - int chan = get_chan(chsa); /* get the channel number */ - CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ - int byte; + int chan = get_chan(chsa); /* get the channel number */ + CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ + int byte; /* Abort if we have any errors */ - if (chp->chan_status & 0x3f03) /* check channel status */ - return 1; /* return error */ + if (chp->chan_status & 0x3f03) /* check channel status */ + return 1; /* return error */ if (chp->chan_byte == BUFF_CHNEND) - return 1; /* return error */ - if (chp->ccw_count == 0) { /* see if more data required */ - if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if Data Chain */ - chp->chan_status |= STATUS_CEND; /* no, end of data */ - chp->chan_byte = BUFF_CHNEND; /* buffer end too */ - sim_debug(DEBUG_DATA, &cpu_dev, "chan_read_byte end status %x\n", chp->chan_status); - return 1; /* return error */ + return 1; /* return error */ + if (chp->ccw_count == 0) { /* see if more data required */ + if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if Data Chain */ + chp->chan_status |= STATUS_CEND; /* no, end of data */ + chp->chan_byte = BUFF_CHNEND; /* buffer end too */ + sim_debug(DEBUG_DATA, &cpu_dev, "chan_read_byte end status %x\n", chp->chan_status); + return 1; /* return error */ } else { - /* we have data chaining, process iocl */ - sim_debug(DEBUG_DATA, &cpu_dev, "chan_read_byte calling load_ccw chan %x\n", chan); - if (load_ccw(chp, 1)) /* process data chaining */ - return 1; /* return error */ + /* we have data chaining, process iocl */ + sim_debug(DEBUG_DATA, &cpu_dev, "chan_read_byte calling load_ccw chan %x\n", chan); + if (load_ccw(chp, 1)) /* process data chaining */ + return 1; /* return error */ } } - if (chp->chan_byte == BUFF_EMPTY) { /* is buffer empty? */ - if (readbuff(chp)) /* read next 4 chars */ - return 1; /* return error */ - chp->chan_byte = chp->ccw_addr & 0x3; /* get byte number from address */ - chp->ccw_addr += 4 - chp->chan_byte; /* next byte address */ + if (chp->chan_byte == BUFF_EMPTY) { /* is buffer empty? */ + if (readbuff(chp)) /* read next 4 chars */ + return 1; /* return error */ + chp->chan_byte = chp->ccw_addr & 0x3; /* get byte number from address */ + chp->ccw_addr += 4 - chp->chan_byte; /* next byte address */ } - chp->ccw_count--; /* one char less to process */ - /* get the byte of data */ + chp->ccw_count--; /* one char less to process */ + /* get the byte of data */ byte = (chp->chan_buf >> (8 * (3 - (chp->chan_byte & 0x3)))) & 0xff; - chp->chan_byte++; /* next byte offset in word */ - *data = byte; /* return the data */ - sim_debug(DEBUG_DATA, &cpu_dev, "chan_read_byte transferred %x\n", byte); - return 0; /* good return */ + chp->chan_byte++; /* next byte offset in word */ + *data = byte; /* return the data */ + sim_debug(DEBUG_DATA, &cpu_dev, "chan_read_byte transferred %x\n", byte); + return 0; /* good return */ } /* test end of write byte I/O (device read) */ int test_write_byte_end(uint16 chsa) { - int chan = get_chan(chsa); /* get the channel number */ - CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ + int chan = get_chan(chsa); /* get the channel number */ + CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ - /* see if at end of buffer */ + /* see if at end of buffer */ if (chp->chan_byte == BUFF_CHNEND) - return 1; /* return done */ + return 1; /* return done */ if (chp->ccw_count == 0) { if (chp->chan_byte & BUFF_DIRTY) { - writebuff(chp); /* write it */ - } - if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if we have data chaining */ - chp->chan_status |= STATUS_CEND; /* no, end of data */ - chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ - return 1; /* return done */ - } - } - return 0; /* not done yet */ + writebuff(chp); /* write it */ + } + if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if we have data chaining */ + chp->chan_status |= STATUS_CEND; /* no, end of data */ + chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ + return 1; /* return done */ + } + } + return 0; /* not done yet */ } /* write byte to memory */ /* read from device */ int chan_write_byte(uint16 chsa, uint8 *data) { - int chan = get_chan(chsa); /* get the channel number */ - CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ - int offset; - uint32 mask; + int chan = get_chan(chsa); /* get the channel number */ + CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ + int offset; + uint32 mask; /* Abort if we have any errors */ - if (chp->chan_status & 0x3f03) /* check channel status */ - return 1; /* return error */ + if (chp->chan_status & 0x3f03) /* check channel status */ + return 1; /* return error */ - /* see if at end of buffer */ + /* see if at end of buffer */ if (chp->chan_byte == BUFF_CHNEND) { - sim_debug(DEBUG_CMD, &cpu_dev, "chan_write_byte BUFF_CHNEND\n"); - /* if SLI not set, we have incorrect length */ + sim_debug(DEBUG_CMD, &cpu_dev, "chan_write_byte BUFF_CHNEND\n"); + /* if SLI not set, we have incorrect length */ if ((chp->ccw_flags & FLAG_SLI) == 0) { - sim_debug(DEBUG_CMD, &cpu_dev, "chan_write_byte 4 setting SLI ret\n"); - chp->chan_status |= STATUS_LENGTH; /* set SLI */ + sim_debug(DEBUG_CMD, &cpu_dev, "chan_write_byte 4 setting SLI ret\n"); + chp->chan_status |= STATUS_LENGTH; /* set SLI */ } - return 1; /* return error */ + return 1; /* return error */ } if (chp->ccw_count == 0) { - sim_debug(DEBUG_CMD, &cpu_dev, "chan_write_byte cccw_count is zero ccw_count[%x] %x\n", - chan, chp->ccw_count); + sim_debug(DEBUG_CMD, &cpu_dev, "chan_write_byte cccw_count is zero ccw_count[%x] %x\n", + chan, chp->ccw_count); if (chp->chan_byte & BUFF_DIRTY) { - sim_debug(DEBUG_CMD, &cpu_dev, "chan_write_byte 2 BUF DIRTY ret\n"); - if (writebuff(chp)) /* write it */ - return 1; /* return error */ + sim_debug(DEBUG_CMD, &cpu_dev, "chan_write_byte 2 BUF DIRTY ret\n"); + if (writebuff(chp)) /* write it */ + return 1; /* return error */ } - if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if we have data chaining */ - sim_debug(DEBUG_CMD, &cpu_dev, "chan_write_byte no DC\n"); - chp->chan_status |= STATUS_CEND; /* no, end of data */ - chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ - return 1; /* return error */ - } else { - /* we have data chaining, process iocl */ - sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte calling load_ccw chan %x\n", chan); - if (load_ccw(chp, 1)) /* process data chaining */ - return 1; /* return error */ + if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if we have data chaining */ + sim_debug(DEBUG_CMD, &cpu_dev, "chan_write_byte no DC\n"); + chp->chan_status |= STATUS_CEND; /* no, end of data */ + chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ + return 1; /* return error */ + } else { + /* we have data chaining, process iocl */ + sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte calling load_ccw chan %x\n", chan); + if (load_ccw(chp, 1)) /* process data chaining */ + return 1; /* return error */ } } - sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte non zero ccw_count[%x] %x\n", chan, chp->ccw_count); + sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte non zero ccw_count[%x] %x\n", chan, chp->ccw_count); if (chp->ccw_flags & FLAG_SKIP) { chp->ccw_count--; chp->chan_byte = BUFF_EMPTY; @@ -642,26 +642,26 @@ int chan_write_byte(uint16 chsa, uint8 *data) chp->ccw_addr--; else chp->ccw_addr++; - sim_debug(DEBUG_CMD, &cpu_dev, "chan_write_byte SKIP ret\n"); + sim_debug(DEBUG_CMD, &cpu_dev, "chan_write_byte SKIP ret\n"); return 0; } - if (chp->chan_byte == (BUFF_EMPTY|BUFF_DIRTY)) { - if (writebuff(chp)) - return 1; - sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte BUF EMPTY|DIRTY ret\n"); - if ((chp->ccw_cmd & 0xff) == CMD_RDBWD) - chp->ccw_addr -= (1 + (chp->ccw_addr & 0x3)); - else - chp->ccw_addr += (4 - (chp->ccw_addr & 0x3)); - chp->chan_byte = BUFF_EMPTY; - } + if (chp->chan_byte == (BUFF_EMPTY|BUFF_DIRTY)) { + if (writebuff(chp)) + return 1; + sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte BUF EMPTY|DIRTY ret\n"); + if ((chp->ccw_cmd & 0xff) == CMD_RDBWD) + chp->ccw_addr -= (1 + (chp->ccw_addr & 0x3)); + else + chp->ccw_addr += (4 - (chp->ccw_addr & 0x3)); + chp->chan_byte = BUFF_EMPTY; + } if (chp->chan_byte == BUFF_EMPTY) chp->chan_byte = chp->ccw_addr & 0x3; chp->ccw_count--; - offset = 8 * (chp->chan_byte & 0x3); /* calc byte offset in word */ - mask = 0xff000000 >> offset; /* build char mask */ - chp->chan_buf &= ~mask; /* zero out the old byte */ - chp->chan_buf |= ((uint32)(*data)) << (24 - offset); /* or in the new one */ + offset = 8 * (chp->chan_byte & 0x3); /* calc byte offset in word */ + mask = 0xff000000 >> offset; /* build char mask */ + chp->chan_buf &= ~mask; /* zero out the old byte */ + chp->chan_buf |= ((uint32)(*data)) << (24 - offset); /* or in the new one */ if ((chp->ccw_cmd & 0xff) == CMD_RDBWD) { if (chp->chan_byte & 0x3) @@ -669,86 +669,86 @@ int chan_write_byte(uint16 chsa, uint8 *data) else chp->chan_byte = BUFF_EMPTY; } else - chp->chan_byte++; /* next byte */ - chp->chan_byte |= BUFF_DIRTY; /* we are used */ + chp->chan_byte++; /* next byte */ + chp->chan_byte |= BUFF_DIRTY; /* we are used */ return 0; } /* post wakeup interrupt for specified async line */ void set_devwake(uint16 chsa, uint16 flags) { - uint32 stwd1, stwd2; /* words 1&2 of stored status */ - /* put sub address in byte 0 */ - stwd1 = (chsa & 0xff) << 24; /* subaddress and IOCD address to SW 1 */ - /* save 16 bit channel status and residual byte count in SW 2 */ - stwd2 = (uint32)flags << 16; - if ((FIFO_Put(chsa, stwd1) == -1) || (FIFO_Put(chsa, stwd2) == -1)) { - fprintf(stderr, "FIFO Overflow ERROR on chsa %x\r\n", chsa); - } - irq_pend = 1; /* wakeup controller */ + uint32 stwd1, stwd2; /* words 1&2 of stored status */ + /* put sub address in byte 0 */ + stwd1 = (chsa & 0xff) << 24; /* subaddress and IOCD address to SW 1 */ + /* save 16 bit channel status and residual byte count in SW 2 */ + stwd2 = (uint32)flags << 16; + if ((FIFO_Put(chsa, stwd1) == -1) || (FIFO_Put(chsa, stwd2) == -1)) { + fprintf(stderr, "FIFO Overflow ERROR on chsa %x\r\n", chsa); + } + irq_pend = 1; /* wakeup controller */ } /* post interrupt for specified channel */ void set_devattn(uint16 chsa, uint16 flags) { - int chan = get_chan(chsa); /* get the channel number */ - CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ + int chan = get_chan(chsa); /* get the channel number */ + CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ - sim_debug(DEBUG_EXP, &cpu_dev, "set_devattn chsa %x, flags %x\n", chsa, flags); -// fprintf(stderr, "set_devattn chsa %x, flags %x\r\n", chsa, flags); + sim_debug(DEBUG_EXP, &cpu_dev, "set_devattn chsa %x, flags %x\n", chsa, flags); +// fprintf(stderr, "set_devattn chsa %x, flags %x\r\n", chsa, flags); - if (chp->chan_dev == chsa && (chp->chan_status & STATUS_CEND) != 0 && (flags & SNS_DEVEND) != 0) { - chp->chan_status |= ((uint16)flags); - } else - dev_status[chsa] = flags; /* save device status flags */ - sim_debug(DEBUG_CMD, &cpu_dev, "set_devattn(%x, %x) %x\n", chsa, flags, chp->chan_dev); -// fprintf(stderr, "set_devattn2(%x, %x) %x\r\n", chsa, flags, chp->chan_dev); - irq_pend = 1; + if (chp->chan_dev == chsa && (chp->chan_status & STATUS_CEND) != 0 && (flags & SNS_DEVEND) != 0) { + chp->chan_status |= ((uint16)flags); + } else + dev_status[chsa] = flags; /* save device status flags */ + sim_debug(DEBUG_CMD, &cpu_dev, "set_devattn(%x, %x) %x\n", chsa, flags, chp->chan_dev); +// fprintf(stderr, "set_devattn2(%x, %x) %x\r\n", chsa, flags, chp->chan_dev); + irq_pend = 1; } /* channel operation completed */ void chan_end(uint16 chsa, uint16 flags) { - int chan = get_chan(chsa); /* get the channel number */ - uint32 chan_icb = find_int_icb(chsa); /* get icb address */ - CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ + int chan = get_chan(chsa); /* get the channel number */ + uint32 chan_icb = find_int_icb(chsa); /* get icb address */ + CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ //fprintf(stderr, "chan_end addr %0x flags %x\r\n", chsa, flags); - if (chp->chan_byte & BUFF_DIRTY) { - if (writebuff(chp)) /* write remaining data */ - return; /* error */ - chp->chan_byte = BUFF_EMPTY; /* we are empty now */ - } - chp->chan_status |= STATUS_CEND; /* set channel end */ - chp->chan_status |= ((uint16)flags); /* add in the callers flags */ - chp->ccw_cmd = 0; /* reset the completed channel command */ + if (chp->chan_byte & BUFF_DIRTY) { + if (writebuff(chp)) /* write remaining data */ + return; /* error */ + chp->chan_byte = BUFF_EMPTY; /* we are empty now */ + } + chp->chan_status |= STATUS_CEND; /* set channel end */ + chp->chan_status |= ((uint16)flags); /* add in the callers flags */ + chp->ccw_cmd = 0; /* reset the completed channel command */ - /* test for incorrect transfer length */ - if (chp->ccw_count != 0 && ((chp->ccw_flags & FLAG_SLI) == 0)) { - chp->chan_status |= STATUS_LENGTH; /* show incorrect length status */ - chp->ccw_flags = 0; /* no flags */ - } - /* no flags for attention status */ - if (flags & (SNS_ATTN|SNS_UNITCHK|SNS_UNITEXP)) { -// fprintf(stderr, "chan_end attention status chsa %x status flags %x\r\n", chsa, flags); - chp->ccw_flags = 0; /* no flags */ - } + /* test for incorrect transfer length */ + if (chp->ccw_count != 0 && ((chp->ccw_flags & FLAG_SLI) == 0)) { + chp->chan_status |= STATUS_LENGTH; /* show incorrect length status */ + chp->ccw_flags = 0; /* no flags */ + } + /* no flags for attention status */ + if (flags & (SNS_ATTN|SNS_UNITCHK|SNS_UNITEXP)) { +// fprintf(stderr, "chan_end attention status chsa %x status flags %x\r\n", chsa, flags); + chp->ccw_flags = 0; /* no flags */ + } - /* test for device or controller end */ - if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { - chp->chan_byte = BUFF_NEWCMD; /* clear byte flag */ -// fprintf(stderr, "chan_end chsa %x status DEND|CEND\n", chsa); - while ((chp->ccw_flags & FLAG_DC)) { /* handle data chaining */ -// fprintf(stderr, "chan_end test for ccw flags %x chsa %x\n", chp->ccw_flags, chsa); - if (load_ccw(chp, 1)) /* continue channel program */ - break; /* error */ - if ((chp->ccw_flags & FLAG_SLI) == 0) { /* suppress incorrect length? */ - chp->chan_status |= STATUS_LENGTH; /* no, show incorrect length */ - chp->ccw_flags = 0; /* no flags */ - } - } - } - irq_pend = 1; /* flag to test for int condition */ -// fprintf(stderr, "chan_end END chsa %x status %x\r\n", chsa, chp->chan_status); + /* test for device or controller end */ + if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { + chp->chan_byte = BUFF_NEWCMD; /* clear byte flag */ +// fprintf(stderr, "chan_end chsa %x status DEND|CEND\n", chsa); + while ((chp->ccw_flags & FLAG_DC)) { /* handle data chaining */ +// fprintf(stderr, "chan_end test for ccw flags %x chsa %x\n", chp->ccw_flags, chsa); + if (load_ccw(chp, 1)) /* continue channel program */ + break; /* error */ + if ((chp->ccw_flags & FLAG_SLI) == 0) { /* suppress incorrect length? */ + chp->chan_status |= STATUS_LENGTH; /* no, show incorrect length */ + chp->ccw_flags = 0; /* no flags */ + } + } + } + irq_pend = 1; /* flag to test for int condition */ +// fprintf(stderr, "chan_end END chsa %x status %x\r\n", chsa, chp->chan_status); } /* store the device status into the status DW in memory */ @@ -756,19 +756,19 @@ void chan_end(uint16 chsa, uint16 flags) { /* return the icb address */ void store_csw(CHANP *chp) { - uint32 stwd1, stwd2; /* words 1&2 of stored status */ - uint32 chsa = chp->chan_dev; /* get ch/sa information */ + uint32 stwd1, stwd2; /* words 1&2 of stored status */ + uint32 chsa = chp->chan_dev; /* get ch/sa information */ - /* put sub address in byte 0 */ - stwd1 = ((chsa & 0xff) << 24) | chp->chan_caw; /* subaddress and IOCD address to SW 1 */ - /* save 16 bit channel status and residual byte count in SW 2 */ - stwd2 = ((uint32)chp->chan_status << 16) | ((uint32)chp->ccw_count); - if ((FIFO_Put(chsa, stwd1) == -1) || (FIFO_Put(chsa, stwd2) == -1)) { - fprintf(stderr, "FIFO Overflow ERROR on chsa %x\r\n", chsa); - } + /* put sub address in byte 0 */ + stwd1 = ((chsa & 0xff) << 24) | chp->chan_caw; /* subaddress and IOCD address to SW 1 */ + /* save 16 bit channel status and residual byte count in SW 2 */ + stwd2 = ((uint32)chp->chan_status << 16) | ((uint32)chp->ccw_count); + if ((FIFO_Put(chsa, stwd1) == -1) || (FIFO_Put(chsa, stwd2) == -1)) { + fprintf(stderr, "FIFO Overflow ERROR on chsa %x\r\n", chsa); + } - chp->chan_status = 0; /* no status anymore */ - irq_pend = 1; /* wakeup controller */ + chp->chan_status = 0; /* no status anymore */ + irq_pend = 1; /* wakeup controller */ } /* SIO CC status returned to caller */ @@ -796,515 +796,515 @@ void store_csw(CHANP *chp) /* Condition codes to return 0-f as specified above */ t_stat startxio(uint16 lchsa, uint32 *status) { - int lchan = get_chan(lchsa); /* get the logical channel number */ - DIB *dibp; /* device information pointer */ - UNIT *uptr; /* pointer to unit in channel */ - uint32 chan_ivl; /* Interrupt Level ICB address for channel */ - uint32 iocla; /* I/O channel IOCL address int ICB */ - uint32 tempa, inta, spadent, chan; - uint16 chsa; - CHANP *chp; + int lchan = get_chan(lchsa); /* get the logical channel number */ + DIB *dibp; /* device information pointer */ + UNIT *uptr; /* pointer to unit in channel */ + uint32 chan_ivl; /* Interrupt Level ICB address for channel */ + uint32 iocla; /* I/O channel IOCL address int ICB */ + uint32 tempa, inta, spadent, chan; + uint16 chsa; + CHANP *chp; - /* get the device entry for the logical channel in SPAD */ - spadent = SPAD[lchan]; /* get spad device entry for logical channel */ - chan = (spadent & 0xff00) >> 8; /* get real channel */ - chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ - dibp = dev_unit[chsa]; /* get the device information pointer */ - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ + /* get the device entry for the logical channel in SPAD */ + spadent = SPAD[lchan]; /* get spad device entry for logical channel */ + chan = (spadent & 0xff00) >> 8; /* get real channel */ + chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ + dibp = dev_unit[chsa]; /* get the device information pointer */ + chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ -// fprintf(stderr, "SIO chan startxio 1 spad[%x] %x lchsa %x chsa %0x chan %x\r\n", -// lchan, spadent, lchsa, chsa, chan); - sim_debug(DEBUG_CMD, &cpu_dev, "startxio 1 chsa %x chan %x\n", chsa, chan); - if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ - *status = CC3BIT; /* not found, so CC3 */ - return SCPE_OK; /* not found, CC3 */ - } -// fprintf(stderr, "SIO chan startxio 2 spad[%x] %x lchsa %x chsa %0x chan %x\r\n", -// lchan, spadent, lchsa, chsa, chan); - sim_debug(DEBUG_CMD, &cpu_dev, "startxio 2 chsa %x chan %x\n", chsa, chan); - if ((uptr->flags & UNIT_ATT) == 0) { /* is unit attached? */ - fprintf(stderr, "startxio chsa %x is not attached, error return\r\n", chsa); - *status = CC3BIT; /* not attached, so error CC3 */ - return SCPE_OK; /* not found, CC3 */ - } - /* see if interrupt is setup in SPAD and determine IVL for channel */ -// fprintf(stderr, "startxio dev spad %.8x chsa %x chan %x\r\n", spadent, chsa, chan); - sim_debug(DEBUG_CMD, &cpu_dev, "startxio dev spad %.8x chsa %x chan %x\n", spadent, chsa, chan); +// fprintf(stderr, "SIO chan startxio 1 spad[%x] %x lchsa %x chsa %0x chan %x\r\n", +// lchan, spadent, lchsa, chsa, chan); + sim_debug(DEBUG_CMD, &cpu_dev, "startxio 1 chsa %x chan %x\n", chsa, chan); + if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ + *status = CC3BIT; /* not found, so CC3 */ + return SCPE_OK; /* not found, CC3 */ + } +// fprintf(stderr, "SIO chan startxio 2 spad[%x] %x lchsa %x chsa %0x chan %x\r\n", +// lchan, spadent, lchsa, chsa, chan); + sim_debug(DEBUG_CMD, &cpu_dev, "startxio 2 chsa %x chan %x\n", chsa, chan); + if ((uptr->flags & UNIT_ATT) == 0) { /* is unit attached? */ + fprintf(stderr, "startxio chsa %x is not attached, error return\r\n", chsa); + *status = CC3BIT; /* not attached, so error CC3 */ + return SCPE_OK; /* not found, CC3 */ + } + /* see if interrupt is setup in SPAD and determine IVL for channel */ +// fprintf(stderr, "startxio dev spad %.8x chsa %x chan %x\r\n", spadent, chsa, chan); + sim_debug(DEBUG_CMD, &cpu_dev, "startxio dev spad %.8x chsa %x chan %x\n", spadent, chsa, chan); - inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ - inta = 127 - inta; /* get positive int level */ - spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ - sim_debug(DEBUG_CMD, &cpu_dev, "startxio int spad %.8x inta %x chan %x\n", spadent, inta, chan); + inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ + inta = 127 - inta; /* get positive int level */ + spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ + sim_debug(DEBUG_CMD, &cpu_dev, "startxio int spad %.8x inta %x chan %x\n", spadent, inta, chan); - /* get the address of the interrupt IVL in main memory */ - chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ - iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ - sim_debug(DEBUG_CMD, &cpu_dev, "startxio busy test chsa %0x chan %x cmd %x flags %x IOCD1 %x IOCD2 %x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); -// fprintf(stderr, "startxio busy test chsa %0x chan %x cmd %x flags %x iocla %x IOCD1 %x IOCD2 %x\r\n", -// chsa, chan, chp->ccw_cmd, chp->ccw_flags, iocla, M[iocla>>2], M[(iocla+4)>>2]); + /* get the address of the interrupt IVL in main memory */ + chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ + chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ + iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ + sim_debug(DEBUG_CMD, &cpu_dev, "startxio busy test chsa %0x chan %x cmd %x flags %x IOCD1 %x IOCD2 %x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); +// fprintf(stderr, "startxio busy test chsa %0x chan %x cmd %x flags %x iocla %x IOCD1 %x IOCD2 %x\r\n", +// chsa, chan, chp->ccw_cmd, chp->ccw_flags, iocla, M[iocla>>2], M[(iocla+4)>>2]); - sim_debug(DEBUG_CMD, &cpu_dev, "$$$ SIO %x %x cmd %x flags %x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags); -// fprintf(stderr, "$$$ SIO %x %x cmd %x flags %x iocla %x\r\n", -// chsa, chan, chp->ccw_cmd, chp->ccw_flags, iocla); - /* check for a Command or data chain operation in progresss */ - if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { -// fprintf(stderr, "startxio busy return CC4 cmd %x flags %x\r\n", chp->ccw_cmd, chp->ccw_flags); - sim_debug(DEBUG_CMD, &cpu_dev, "startxio busy return CC4 chsa %x chan %x\n", chsa, chan); - *status = CC4BIT; /* busy, so CC4 */ - return SCPE_OK; /* just busy CC4 */ - } + sim_debug(DEBUG_CMD, &cpu_dev, "$$$ SIO %x %x cmd %x flags %x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags); +// fprintf(stderr, "$$$ SIO %x %x cmd %x flags %x iocla %x\r\n", +// chsa, chan, chp->ccw_cmd, chp->ccw_flags, iocla); + /* check for a Command or data chain operation in progresss */ + if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { +// fprintf(stderr, "startxio busy return CC4 cmd %x flags %x\r\n", chp->ccw_cmd, chp->ccw_flags); + sim_debug(DEBUG_CMD, &cpu_dev, "startxio busy return CC4 chsa %x chan %x\n", chsa, chan); + *status = CC4BIT; /* busy, so CC4 */ + return SCPE_OK; /* just busy CC4 */ + } - /* determine if channel DIB has a pre startio command processor */ - if (dibp->pre_io != NULL) { /* NULL if no startio function */ - /* call the device controller to get prestart_io status */ - tempa = dibp->pre_io(uptr, chan); /* get status from device */ - if (tempa != 0) { /* see if sub channel status is ready */ - /* The device must be busy or something, but it is not ready. Return busy */ - sim_debug(DEBUG_CMD, &cpu_dev, "startxio start_io call return busy chan %x cstat %08x\n", - chan, tempa); - chp->chan_status = 0; /* no status anymore */ - *status = CC3BIT|CC4BIT; /* sub channel busy, so CC3|CC4 */ - return SCPE_OK; /* just busy or something, CC3|CC4 */ - } - } + /* determine if channel DIB has a pre startio command processor */ + if (dibp->pre_io != NULL) { /* NULL if no startio function */ + /* call the device controller to get prestart_io status */ + tempa = dibp->pre_io(uptr, chan); /* get status from device */ + if (tempa != 0) { /* see if sub channel status is ready */ + /* The device must be busy or something, but it is not ready. Return busy */ + sim_debug(DEBUG_CMD, &cpu_dev, "startxio start_io call return busy chan %x cstat %08x\n", + chan, tempa); + chp->chan_status = 0; /* no status anymore */ + *status = CC3BIT|CC4BIT; /* sub channel busy, so CC3|CC4 */ + return SCPE_OK; /* just busy or something, CC3|CC4 */ + } + } - /* channel not busy and ready to go, so start a new command */ - chp->chan_status = 0; /* no channel status yet */ - dev_status[chsa] = 0; /* no unit status either */ - chp->chan_caw = iocla; /* get iocla address in memory */ - /* set status words in memory to first IOCD information */ - tempa = chp->chan_inch_addr; /* get inch status buffer address */ - if (tempa != 0) { - M[tempa >> 2] = (chsa & 0xff) << 24 | iocla; /* suba & IOCD address to status */ - M[(tempa+4) >> 2] = 0; /* null status and residual byte count */ - } + /* channel not busy and ready to go, so start a new command */ + chp->chan_status = 0; /* no channel status yet */ + dev_status[chsa] = 0; /* no unit status either */ + chp->chan_caw = iocla; /* get iocla address in memory */ + /* set status words in memory to first IOCD information */ + tempa = chp->chan_inch_addr; /* get inch status buffer address */ + if (tempa != 0) { + M[tempa >> 2] = (chsa & 0xff) << 24 | iocla; /* suba & IOCD address to status */ + M[(tempa+4) >> 2] = 0; /* null status and residual byte count */ + } - sim_debug(DEBUG_CMD, &cpu_dev, "$$ SIO starting IOCL processing chsa %02x\n", chsa); -// fprintf(stderr, "$$ SIO starting IOCL processsing chsa %0x\r\n", chsa); + sim_debug(DEBUG_CMD, &cpu_dev, "$$ SIO starting IOCL processing chsa %02x\n", chsa); +// fprintf(stderr, "$$ SIO starting IOCL processsing chsa %0x\r\n", chsa); - /* start processing the IOCL */ - if (load_ccw(chp, 0) || (chp->chan_status & STATUS_PCI)) { - /* we have an error or user requested interrupt, return status */ -// fprintf(stderr, "chan startxio after load_ccw chsa %0x status %x\r\n", chsa, chp->chan_status); - store_csw(chp); /* store the status in the inch status dw */ - sim_debug(DEBUG_CMD, &cpu_dev, "startxio store csw CC1 chan %02x status %08x\n", chan, chp->chan_status); -// fprintf(stderr, "startxio store csw CC1 chan %02x status %08x\n", chan, chp->chan_status); - chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ - dev_status[chsa] = 0; /* no device status */ - *status = CC1BIT; /* status stored, so CC1 */ - return SCPE_OK; /* CC1 (0x40) status stored */ - } + /* start processing the IOCL */ + if (load_ccw(chp, 0) || (chp->chan_status & STATUS_PCI)) { + /* we have an error or user requested interrupt, return status */ +// fprintf(stderr, "chan startxio after load_ccw chsa %0x status %x\r\n", chsa, chp->chan_status); + store_csw(chp); /* store the status in the inch status dw */ + sim_debug(DEBUG_CMD, &cpu_dev, "startxio store csw CC1 chan %02x status %08x\n", chan, chp->chan_status); +// fprintf(stderr, "startxio store csw CC1 chan %02x status %08x\n", chan, chp->chan_status); + chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ + dev_status[chsa] = 0; /* no device status */ + *status = CC1BIT; /* status stored, so CC1 */ + return SCPE_OK; /* CC1 (0x40) status stored */ + } #if NOT_NEEDED - if (chp->chan_status & STATUS_BUSY) { - fprintf(stderr, "chan startxio busy chan %0x status %x\r\n", chsa, chp->chan_status); - sim_debug(DEBUG_CMD, &cpu_dev, "startxio store busy chan %x status %08x\n", chan, chp->chan_status); - store_csw(chp); /* store the status in the inch status dw */ - M[tempa >> 2] = 0; /* zero sa & IOCD address in status WD 1 */ - chp->chan_status = 0; /* no channel status */ - dev_status[chsa] = 0; /* no unit status */ - chp->ccw_cmd = 0; /* no cmd either */ - *status = CC4BIT; /* channel busy, so CC4 */ - return SCPE_OK; /* CC4 (0x01) channel busy */ - } + if (chp->chan_status & STATUS_BUSY) { + fprintf(stderr, "chan startxio busy chan %0x status %x\r\n", chsa, chp->chan_status); + sim_debug(DEBUG_CMD, &cpu_dev, "startxio store busy chan %x status %08x\n", chan, chp->chan_status); + store_csw(chp); /* store the status in the inch status dw */ + M[tempa >> 2] = 0; /* zero sa & IOCD address in status WD 1 */ + chp->chan_status = 0; /* no channel status */ + dev_status[chsa] = 0; /* no unit status */ + chp->ccw_cmd = 0; /* no cmd either */ + *status = CC4BIT; /* channel busy, so CC4 */ + return SCPE_OK; /* CC4 (0x01) channel busy */ + } #endif - if ((chp->ccw_cmd & 0xFF) == 0) /* see if this is an initialize channel cmd */ - *status = CC1BIT; /* request accepted, no status, so CC1 TRY THIS */ - else - *status = 0; /* CCs = 0, SIO accepted, will echo status */ -// fprintf(stderr, "$$$ SIO done chsa %0x status %x\r\n", chsa, chp->chan_status); - sim_debug(DEBUG_CMD, &cpu_dev, "$$$ SIO done chsa %x status %08x\n", chsa, chp->chan_status); - return SCPE_OK; /* No CC's all OK */ + if ((chp->ccw_cmd & 0xFF) == 0) /* see if this is an initialize channel cmd */ + *status = CC1BIT; /* request accepted, no status, so CC1 TRY THIS */ + else + *status = 0; /* CCs = 0, SIO accepted, will echo status */ +// fprintf(stderr, "$$$ SIO done chsa %0x status %x\r\n", chsa, chp->chan_status); + sim_debug(DEBUG_CMD, &cpu_dev, "$$$ SIO done chsa %x status %08x\n", chsa, chp->chan_status); + return SCPE_OK; /* No CC's all OK */ } /* TIO - I/O status */ -t_stat testxio(uint16 lchsa, uint32 *status) /* test XIO */ +t_stat testxio(uint16 lchsa, uint32 *status) /* test XIO */ { - uint32 chan = get_chan(lchsa); - DIB *dibp; - UNIT *uptr; - uint32 chan_ivl; /* Interrupt Level ICB address for channel */ - uint32 iocla; /* I/O channel IOCL address int ICB */ - uint32 stata; /* I/O channel status location in ICB */ - uint32 tempa, inta, spadent; - uint16 chsa; /* chan/subaddr */ - CHANP *chp, *pchp; /* Channel prog pointers */ - uint32 sw1, sw2; /* status word 1 & 2 */ + uint32 chan = get_chan(lchsa); + DIB *dibp; + UNIT *uptr; + uint32 chan_ivl; /* Interrupt Level ICB address for channel */ + uint32 iocla; /* I/O channel IOCL address int ICB */ + uint32 stata; /* I/O channel status location in ICB */ + uint32 tempa, inta, spadent; + uint16 chsa; /* chan/subaddr */ + CHANP *chp, *pchp; /* Channel prog pointers */ + uint32 sw1, sw2; /* status word 1 & 2 */ - /* get the device entry for the logical channel in SPAD */ - spadent = SPAD[chan]; /* get spad device entry for logical channel */ - chan = (spadent & 0xff00) >> 8; /* get real channel */ - chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ - dibp = dev_unit[chsa]; /* get the device information pointer */ - chp = find_chanp_ptr(chsa); /* find the device chanp pointer */ - uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ - pchp = find_chanp_ptr(chsa & 0x7f00); /* find the channel chanp pointer */ + /* get the device entry for the logical channel in SPAD */ + spadent = SPAD[chan]; /* get spad device entry for logical channel */ + chan = (spadent & 0xff00) >> 8; /* get real channel */ + chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ + dibp = dev_unit[chsa]; /* get the device information pointer */ + chp = find_chanp_ptr(chsa); /* find the device chanp pointer */ + uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ + pchp = find_chanp_ptr(chsa & 0x7f00); /* find the channel chanp pointer */ -// fprintf(stderr, "TIO chan testxio 1 spad[%x] %x lchsa %x chsa %0x chan %x\r\n", -// lchsa, spadent, lchsa, chsa, chan); - sim_debug(DEBUG_CMD, &cpu_dev, "testxio 1 chsa %x chan %x\n", chsa, chan); - if ((dibp == 0) || (uptr == 0)) { /* if non found, CC3 on return */ - *status = CC3BIT; /* not found, so CC3 */ - goto tioret; /* not found, CC3 */ - } - sim_debug(DEBUG_CMD, &cpu_dev, "testxio 2 chsa %x chan %x\n", chsa, chan); - if ((uptr->flags & UNIT_ATT) == 0) { /* is unit already attached? */ - *status = CC3BIT; /* not attached, so error CC3 */ - goto tioret; /* not found, CC3 */ - } - /* see if interrupt is setup in SPAD and determine IVL for channel */ - sim_debug(DEBUG_CMD, &cpu_dev, "testxio dev spad %.8x chsa %x chan %x\n", spadent, chsa, chan); +// fprintf(stderr, "TIO chan testxio 1 spad[%x] %x lchsa %x chsa %0x chan %x\r\n", +// lchsa, spadent, lchsa, chsa, chan); + sim_debug(DEBUG_CMD, &cpu_dev, "testxio 1 chsa %x chan %x\n", chsa, chan); + if ((dibp == 0) || (uptr == 0)) { /* if non found, CC3 on return */ + *status = CC3BIT; /* not found, so CC3 */ + goto tioret; /* not found, CC3 */ + } + sim_debug(DEBUG_CMD, &cpu_dev, "testxio 2 chsa %x chan %x\n", chsa, chan); + if ((uptr->flags & UNIT_ATT) == 0) { /* is unit already attached? */ + *status = CC3BIT; /* not attached, so error CC3 */ + goto tioret; /* not found, CC3 */ + } + /* see if interrupt is setup in SPAD and determine IVL for channel */ + sim_debug(DEBUG_CMD, &cpu_dev, "testxio dev spad %.8x chsa %x chan %x\n", spadent, chsa, chan); - /* the startio opcode processing software has already checked for F class */ - inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ - inta = 127 - inta; /* get positive int level */ - spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ - sim_debug(DEBUG_CMD, &cpu_dev, "testxio int spad %.8x inta %x chan %x\n", spadent, inta, chan); + /* the startio opcode processing software has already checked for F class */ + inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ + inta = 127 - inta; /* get positive int level */ + spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ + sim_debug(DEBUG_CMD, &cpu_dev, "testxio int spad %.8x inta %x chan %x\n", spadent, inta, chan); - /* get the address of the interrupt IVL in main memory */ - chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ - iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ + /* get the address of the interrupt IVL in main memory */ + chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ + chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ + iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ - sim_debug(DEBUG_CMD, &cpu_dev, "testxio busy test chsa %0x chan %x cmd %x flags %x IOCD1 %x IOCD2 %x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); -// fprintf(stderr, "testxio busy test chsa %0x chan %x cmd %x flags %x IOCD1 %x IOCD2 %x\r\n", -// chsa, chan, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); + sim_debug(DEBUG_CMD, &cpu_dev, "testxio busy test chsa %0x chan %x cmd %x flags %x IOCD1 %x IOCD2 %x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); +// fprintf(stderr, "testxio busy test chsa %0x chan %x cmd %x flags %x IOCD1 %x IOCD2 %x\r\n", +// chsa, chan, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); - sim_debug(DEBUG_CMD, &cpu_dev, "$$$ TIO %x %x %x %x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); -// fprintf(stderr, "$$$ TIO chsa %x chan %x cmd %x flags %x\r\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); + sim_debug(DEBUG_CMD, &cpu_dev, "$$$ TIO %x %x %x %x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); +// fprintf(stderr, "$$$ TIO chsa %x chan %x cmd %x flags %x\r\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); - /* check for a Command or data chain operation in progresss */ - if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { - sim_debug(DEBUG_CMD, &cpu_dev, "testxio busy return CC4 chsa %x chan %x\n", chsa, chan); - *status = CC4BIT; /* busy, so CC4 */ - goto tioret; /* just busy CC4 */ - } - /* the channel is not busy, see if any status to post */ - if ((FIFO_Get(chsa, &sw1) == 0) && (FIFO_Get(chsa, &sw2) == 0)) { - uint32 chan_icb = find_int_icb(chsa); /* get icb address */ + /* check for a Command or data chain operation in progresss */ + if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { + sim_debug(DEBUG_CMD, &cpu_dev, "testxio busy return CC4 chsa %x chan %x\n", chsa, chan); + *status = CC4BIT; /* busy, so CC4 */ + goto tioret; /* just busy CC4 */ + } + /* the channel is not busy, see if any status to post */ + if ((FIFO_Get(chsa, &sw1) == 0) && (FIFO_Get(chsa, &sw2) == 0)) { + uint32 chan_icb = find_int_icb(chsa); /* get icb address */ - sim_debug(DEBUG_CMD, &cpu_dev, "testxio status stored OK, sw1 %x sw2 %x\n", sw1, sw2); -// fprintf(stderr, "testxio status stored OK, sw1 %x sw2 %x\r\n", sw1, sw2); - /* we have status to return, do it now */ - tempa = pchp->chan_inch_addr; /* get inch status buffer address */ - M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ - /* save the status to memory */ - M[(tempa+4) >> 2] = sw2; /* save status and residual count in status WD 2 loc */ - /* now store the status dw address into word 5 of the ICB for the channel */ - M[(chan_icb + 20) >> 2] = tempa | BIT1; /* post sw addr in ICB+5w & set CC2 in INCH addr */ - *status = CC2BIT; /* status stored from SIO, so CC2 */ - goto tioret; /* CC2 and OK */ - } - /* nothing going on, so say all OK */ - *status = CC1BIT; /* request accepted, no status, so CC1 TRY THIS */ + sim_debug(DEBUG_CMD, &cpu_dev, "testxio status stored OK, sw1 %x sw2 %x\n", sw1, sw2); +// fprintf(stderr, "testxio status stored OK, sw1 %x sw2 %x\r\n", sw1, sw2); + /* we have status to return, do it now */ + tempa = pchp->chan_inch_addr; /* get inch status buffer address */ + M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ + /* save the status to memory */ + M[(tempa+4) >> 2] = sw2; /* save status and residual count in status WD 2 loc */ + /* now store the status dw address into word 5 of the ICB for the channel */ + M[(chan_icb + 20) >> 2] = tempa | BIT1; /* post sw addr in ICB+5w & set CC2 in INCH addr */ + *status = CC2BIT; /* status stored from SIO, so CC2 */ + goto tioret; /* CC2 and OK */ + } + /* nothing going on, so say all OK */ + *status = CC1BIT; /* request accepted, no status, so CC1 TRY THIS */ tioret: -// fprintf(stderr, "$$$ TIO END chsa %x chan %x cmd %x flags %x chan_stat %x CCs %x\r\n", -// chsa, chan, chp->ccw_cmd, chp->ccw_flags, chp->chan_status, *status); - return SCPE_OK; /* No CC's all OK */ +// fprintf(stderr, "$$$ TIO END chsa %x chan %x cmd %x flags %x chan_stat %x CCs %x\r\n", +// chsa, chan, chp->ccw_cmd, chp->ccw_flags, chp->chan_status, *status); + return SCPE_OK; /* No CC's all OK */ } /* Stop XIO */ -t_stat stopxio(uint16 lchsa, uint32 *status) /* stop XIO */ +t_stat stopxio(uint16 lchsa, uint32 *status) /* stop XIO */ { - int chan = get_chan(lchsa); - DIB *dibp; - UNIT *uptr; - uint32 chan_ivl; /* Interrupt Level ICB address for channel */ - uint32 iocla; /* I/O channel IOCL address int ICB */ - uint32 inta, spadent; - uint16 chsa; - CHANP *chp; + int chan = get_chan(lchsa); + DIB *dibp; + UNIT *uptr; + uint32 chan_ivl; /* Interrupt Level ICB address for channel */ + uint32 iocla; /* I/O channel IOCL address int ICB */ + uint32 inta, spadent; + uint16 chsa; + CHANP *chp; - /* get the device entry for the logical channel in SPAD */ - spadent = SPAD[chan]; /* get spad device entry for logical channel */ - chan = (spadent & 0xff00) >> 8; /* get real channel */ - chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ - dibp = dev_unit[chsa]; /* get the device information pointer */ - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ + /* get the device entry for the logical channel in SPAD */ + spadent = SPAD[chan]; /* get spad device entry for logical channel */ + chan = (spadent & 0xff00) >> 8; /* get real channel */ + chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ + dibp = dev_unit[chsa]; /* get the device information pointer */ + chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ - sim_debug(DEBUG_CMD, &cpu_dev, "stopxio 1 chsa %x chan %x\n", chsa, chan); - if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ - *status = CC3BIT; /* not found, so CC3 */ - return SCPE_OK; /* not found, CC3 */ - } - sim_debug(DEBUG_CMD, &cpu_dev, "stopxio 2 chsa %x chan %x\n", chsa, chan); - if ((uptr->flags & UNIT_ATT) == 0) { /* is unit already attached? */ - *status = CC3BIT; /* not attached, so error CC3 */ - return SCPE_OK; /* not found, CC3 */ - } - /* see if interrupt is setup in SPAD and determine IVL for channel */ - sim_debug(DEBUG_CMD, &cpu_dev, "stopxio dev spad %.8x chsa %x chan %x\n", spadent, chsa, chan); + sim_debug(DEBUG_CMD, &cpu_dev, "stopxio 1 chsa %x chan %x\n", chsa, chan); + if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ + *status = CC3BIT; /* not found, so CC3 */ + return SCPE_OK; /* not found, CC3 */ + } + sim_debug(DEBUG_CMD, &cpu_dev, "stopxio 2 chsa %x chan %x\n", chsa, chan); + if ((uptr->flags & UNIT_ATT) == 0) { /* is unit already attached? */ + *status = CC3BIT; /* not attached, so error CC3 */ + return SCPE_OK; /* not found, CC3 */ + } + /* see if interrupt is setup in SPAD and determine IVL for channel */ + sim_debug(DEBUG_CMD, &cpu_dev, "stopxio dev spad %.8x chsa %x chan %x\n", spadent, chsa, chan); - /* the startio opcode processing software has already checked for F class */ - inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ - inta = 127 - inta; /* get positive int level */ - spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ - sim_debug(DEBUG_CMD, &cpu_dev, "stopxio int spad %.8x inta %x chan %x\n", spadent, inta, chan); + /* the startio opcode processing software has already checked for F class */ + inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ + inta = 127 - inta; /* get positive int level */ + spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ + sim_debug(DEBUG_CMD, &cpu_dev, "stopxio int spad %.8x inta %x chan %x\n", spadent, inta, chan); - /* get the address of the interrupt IVL in main memory */ - chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ - iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ - sim_debug(DEBUG_CMD, &cpu_dev, "stopxio busy test chsa %0x chan %x cmd %x flags %x IOCD1 %x IOCD2 %x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); + /* get the address of the interrupt IVL in main memory */ + chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ + chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ + iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ + sim_debug(DEBUG_CMD, &cpu_dev, "stopxio busy test chsa %0x chan %x cmd %x flags %x IOCD1 %x IOCD2 %x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); -// sim_debug(DEBUG_CMD, &cpu_dev, "$$$ STOPIO %x %x %x %x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); -// fprintf(stderr, "$$$ STOPIO %x %x %x %x\r\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); +// sim_debug(DEBUG_CMD, &cpu_dev, "$$$ STOPIO %x %x %x %x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); +// fprintf(stderr, "$$$ STOPIO %x %x %x %x\r\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); - /* check for a Command or data chain operation in progresss */ - if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { - sim_debug(DEBUG_CMD, &cpu_dev, "stopxio busy return CC4 chsa %x chan %x\n", chsa, chan); -// fprintf(stderr, "stopxio busy return CC4 chsa %x chan %x\r\n", chsa, chan); - /* reset the DC or CC bits to force completion after current IOCD */ - chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ - dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */ - *status = CC4BIT; /* busy, so CC4 */ - return SCPE_OK; /* just busy CC4 */ - } - /* the channel is not busy, so return OK */ - *status = 0; /* CCs = 0, accepted */ -// fprintf(stderr, "$$$ STOPIO good return chsa %x chan %x cmd %x flags %x status %x\r\n", -// chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); - return SCPE_OK; /* No CC's all OK */ + /* check for a Command or data chain operation in progresss */ + if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { + sim_debug(DEBUG_CMD, &cpu_dev, "stopxio busy return CC4 chsa %x chan %x\n", chsa, chan); +// fprintf(stderr, "stopxio busy return CC4 chsa %x chan %x\r\n", chsa, chan); + /* reset the DC or CC bits to force completion after current IOCD */ + chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ + dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */ + *status = CC4BIT; /* busy, so CC4 */ + return SCPE_OK; /* just busy CC4 */ + } + /* the channel is not busy, so return OK */ + *status = 0; /* CCs = 0, accepted */ +// fprintf(stderr, "$$$ STOPIO good return chsa %x chan %x cmd %x flags %x status %x\r\n", +// chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + return SCPE_OK; /* No CC's all OK */ } /* Reset Channel XIO */ -t_stat rschnlxio(uint16 lchsa, uint32 *status) /* reset channel XIO */ +t_stat rschnlxio(uint16 lchsa, uint32 *status) /* reset channel XIO */ { - DIB *dibp; - UNIT *uptr; - uint32 spadent; - uint16 chsa; - CHANP *chp; - int lev, i; - uint32 chan = get_chan(lchsa); + DIB *dibp; + UNIT *uptr; + uint32 spadent; + uint16 chsa; + CHANP *chp; + int lev, i; + uint32 chan = get_chan(lchsa); - /* get the device entry for the logical channel in SPAD */ - spadent = SPAD[chan]; /* get spad device entry for logical channel */ - chan = spadent & 0x7f00; /* get real channel */ - chsa = chan; /* use just channel */ - dibp = dev_unit[chsa]; /* get the device information pointer */ - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ + /* get the device entry for the logical channel in SPAD */ + spadent = SPAD[chan]; /* get spad device entry for logical channel */ + chan = spadent & 0x7f00; /* get real channel */ + chsa = chan; /* use just channel */ + dibp = dev_unit[chsa]; /* get the device information pointer */ + chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ - sim_debug(DEBUG_CMD, &cpu_dev, "rschnlxio 1 chan %x SPAD %x\n", chsa, spadent); -// fprintf(stderr, "rschnlxio 1 chan %x spad %x\r\n", chsa, spadent); - if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ - *status = CC3BIT; /* not found, so CC3 */ - return SCPE_OK; /* not found, CC3 */ - } - sim_debug(DEBUG_CMD, &cpu_dev, "rschnlxio 2 chan %x, spad %x\r\n", chsa, spadent); -// fprintf(stderr, "rschnlxio 2 chan %x, spad %x\n", chsa, spadent); - if ((uptr->flags & UNIT_ATT) == 0) { /* is unit already attached? */ - *status = CC3BIT; /* not attached, so error CC3 */ - return SCPE_OK; /* not found, CC3 */ - } - /* reset the FIFO pointers */ - dibp->chan_fifo_in = 0; - dibp->chan_fifo_out = 0; - dev_status[chan] = 0; /* clear the channel status location */ - chp->chan_inch_addr = 0; /* remove inch status buffer address */ - lev = find_int_lev(chan); /* get our int level */ - INTS[lev] &= ~INTS_ACT; /* clear level active */ - INTS[lev] &= ~INTS_REQ; /* clear level request */ - SPAD[lev+0x80] &= ~SINT_ACT; /* clear spad too */ + sim_debug(DEBUG_CMD, &cpu_dev, "rschnlxio 1 chan %x SPAD %x\n", chsa, spadent); +// fprintf(stderr, "rschnlxio 1 chan %x spad %x\r\n", chsa, spadent); + if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ + *status = CC3BIT; /* not found, so CC3 */ + return SCPE_OK; /* not found, CC3 */ + } + sim_debug(DEBUG_CMD, &cpu_dev, "rschnlxio 2 chan %x, spad %x\r\n", chsa, spadent); +// fprintf(stderr, "rschnlxio 2 chan %x, spad %x\n", chsa, spadent); + if ((uptr->flags & UNIT_ATT) == 0) { /* is unit already attached? */ + *status = CC3BIT; /* not attached, so error CC3 */ + return SCPE_OK; /* not found, CC3 */ + } + /* reset the FIFO pointers */ + dibp->chan_fifo_in = 0; + dibp->chan_fifo_out = 0; + dev_status[chan] = 0; /* clear the channel status location */ + chp->chan_inch_addr = 0; /* remove inch status buffer address */ + lev = find_int_lev(chan); /* get our int level */ + INTS[lev] &= ~INTS_ACT; /* clear level active */ + INTS[lev] &= ~INTS_REQ; /* clear level request */ + SPAD[lev+0x80] &= ~SINT_ACT; /* clear spad too */ - /* now go through all the sa for the channel and stop any IOCLs */ - for (i=0; i<256; i++) { - chsa = chan | i; /* merge sa to real channel */ - dibp = dev_unit[chsa]; /* get the device information pointer */ - if (dibp == 0) - { - continue; /* not used */ - } - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - if (chp == 0) { -// fprintf(stderr, "rschnl found dib without valid chp for chsa %x, ignoring\r\n", chsa); - continue; /* not used */ - } -// fprintf(stderr, "rschnl found dib and chp for chsa %x, resetting\r\n", chsa); - dev_status[chsa] = 0; /* clear device status */ - chp->chan_status = 0; /* clear the channel status */ - chp->chan_byte = BUFF_EMPTY; /* no data yet */ - chp->ccw_addr = 0; /* clear buffer address */ - chp->chan_caw = 0x0; /* clear IOCD address */ - chp->ccw_count = 0; /* channel byte count 0 bytes*/ - chp->ccw_flags = 0; /* clear flags */ - chp->ccw_cmd = 0; /* read command */ - } - sim_debug(DEBUG_CMD, &cpu_dev, "rschnlxio return CC1 chan %x lev %x\n", chan, lev); -// fprintf(stderr, "RSCHNL rschnlxio return CC1 chan %x lev %x\r\n", chan, lev); - *status = CC1BIT; /* request accepted, no status, so CC1 TRY THIS */ - return SCPE_OK; /* All OK */ + /* now go through all the sa for the channel and stop any IOCLs */ + for (i=0; i<256; i++) { + chsa = chan | i; /* merge sa to real channel */ + dibp = dev_unit[chsa]; /* get the device information pointer */ + if (dibp == 0) + { + continue; /* not used */ + } + chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + if (chp == 0) { +// fprintf(stderr, "rschnl found dib without valid chp for chsa %x, ignoring\r\n", chsa); + continue; /* not used */ + } +// fprintf(stderr, "rschnl found dib and chp for chsa %x, resetting\r\n", chsa); + dev_status[chsa] = 0; /* clear device status */ + chp->chan_status = 0; /* clear the channel status */ + chp->chan_byte = BUFF_EMPTY; /* no data yet */ + chp->ccw_addr = 0; /* clear buffer address */ + chp->chan_caw = 0x0; /* clear IOCD address */ + chp->ccw_count = 0; /* channel byte count 0 bytes*/ + chp->ccw_flags = 0; /* clear flags */ + chp->ccw_cmd = 0; /* read command */ + } + sim_debug(DEBUG_CMD, &cpu_dev, "rschnlxio return CC1 chan %x lev %x\n", chan, lev); +// fprintf(stderr, "RSCHNL rschnlxio return CC1 chan %x lev %x\r\n", chan, lev); + *status = CC1BIT; /* request accepted, no status, so CC1 TRY THIS */ + return SCPE_OK; /* All OK */ } /* HIO - Halt I/O */ -t_stat haltxio(uint16 lchsa, uint32 *status) /* halt XIO */ +t_stat haltxio(uint16 lchsa, uint32 *status) /* halt XIO */ { - int chan = get_chan(lchsa); - DIB *dibp; - UNIT *uptr; - uint32 chan_ivl; /* Interrupt Level ICB address for channel */ - uint32 iocla; /* I/O channel IOCL address int ICB */ - uint32 inta, spadent; - uint16 chsa; - CHANP *chp; + int chan = get_chan(lchsa); + DIB *dibp; + UNIT *uptr; + uint32 chan_ivl; /* Interrupt Level ICB address for channel */ + uint32 iocla; /* I/O channel IOCL address int ICB */ + uint32 inta, spadent; + uint16 chsa; + CHANP *chp; - /* get the device entry for the logical channel in SPAD */ - spadent = SPAD[chan]; /* get spad device entry for logical channel */ - chan = (spadent & 0xff00) >> 8; /* get real channel */ - chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ - dibp = dev_unit[chsa]; /* get the device information pointer */ - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ + /* get the device entry for the logical channel in SPAD */ + spadent = SPAD[chan]; /* get spad device entry for logical channel */ + chan = (spadent & 0xff00) >> 8; /* get real channel */ + chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ + dibp = dev_unit[chsa]; /* get the device information pointer */ + chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ - sim_debug(DEBUG_CMD, &cpu_dev, "haltxio 1 chsa %x chan %x\n", chsa, chan); - if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ - *status = CC3BIT; /* not found, so CC3 */ - return SCPE_OK; /* not found, CC3 */ - } - sim_debug(DEBUG_CMD, &cpu_dev, "haltxio 2 chsa %x chan %x\n", chsa, chan); - if ((uptr->flags & UNIT_ATT) == 0) { /* is unit already attached? */ - *status = CC3BIT; /* not attached, so error CC3 */ - return SCPE_OK; /* not found, CC3 */ - } - /* see if interrupt is setup in SPAD and determine IVL for channel */ - sim_debug(DEBUG_CMD, &cpu_dev, "haltxio dev spad %.8x chsa %x chan %x\n", spadent, chsa, chan); + sim_debug(DEBUG_CMD, &cpu_dev, "haltxio 1 chsa %x chan %x\n", chsa, chan); + if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ + *status = CC3BIT; /* not found, so CC3 */ + return SCPE_OK; /* not found, CC3 */ + } + sim_debug(DEBUG_CMD, &cpu_dev, "haltxio 2 chsa %x chan %x\n", chsa, chan); + if ((uptr->flags & UNIT_ATT) == 0) { /* is unit already attached? */ + *status = CC3BIT; /* not attached, so error CC3 */ + return SCPE_OK; /* not found, CC3 */ + } + /* see if interrupt is setup in SPAD and determine IVL for channel */ + sim_debug(DEBUG_CMD, &cpu_dev, "haltxio dev spad %.8x chsa %x chan %x\n", spadent, chsa, chan); - /* the startio opcode processing software has already checked for F class */ - inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ - inta = 127 - inta; /* get positive int level */ - spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ - sim_debug(DEBUG_CMD, &cpu_dev, "haltxio int spad %.8x inta %x chan %x\n", spadent, inta, chan); + /* the startio opcode processing software has already checked for F class */ + inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ + inta = 127 - inta; /* get positive int level */ + spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ + sim_debug(DEBUG_CMD, &cpu_dev, "haltxio int spad %.8x inta %x chan %x\n", spadent, inta, chan); - /* get the address of the interrupt IVL in main memory */ - chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ - iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ - sim_debug(DEBUG_CMD, &cpu_dev, "haltxio busy test chsa %0x chan %x cmd %x flags %x IOCD1 %x IOCD2 %x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); + /* get the address of the interrupt IVL in main memory */ + chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */ + chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ + iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */ + sim_debug(DEBUG_CMD, &cpu_dev, "haltxio busy test chsa %0x chan %x cmd %x flags %x IOCD1 %x IOCD2 %x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); - sim_debug(DEBUG_CMD, &cpu_dev, "$$$ HIO %x %x %x %x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); -// fprintf(stderr, "$$$ HIO %x %x %x %x\r\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); + sim_debug(DEBUG_CMD, &cpu_dev, "$$$ HIO %x %x %x %x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); +// fprintf(stderr, "$$$ HIO %x %x %x %x\r\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); - /* check for a Command or data chain operation in progresss */ - if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { - sim_debug(DEBUG_CMD, &cpu_dev, "haltxio busy return CC4 chsa %x chan %x\n", chsa, chan); - fprintf(stderr, "HIO haltxio busy return CC4 chsa %x chan %x\r\n", chsa, chan); - /* reset the DC or CC bits to force completion after current IOCD */ - chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ - dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */ - *status = 0; /* not busy, no CC */ - goto hioret; /* just busy CC4 */ - } - /* the channel is not busy, so return OK */ - *status = CC2BIT; /* INCH status stored, so CC2 TRY */ + /* check for a Command or data chain operation in progresss */ + if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { + sim_debug(DEBUG_CMD, &cpu_dev, "haltxio busy return CC4 chsa %x chan %x\n", chsa, chan); + fprintf(stderr, "HIO haltxio busy return CC4 chsa %x chan %x\r\n", chsa, chan); + /* reset the DC or CC bits to force completion after current IOCD */ + chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ + dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */ + *status = 0; /* not busy, no CC */ + goto hioret; /* just busy CC4 */ + } + /* the channel is not busy, so return OK */ + *status = CC2BIT; /* INCH status stored, so CC2 TRY */ hioret: -// fprintf(stderr, "$$$ HIO END chsa %x chan %x cmd %x flags %x status %x\r\n", -// chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); - return SCPE_OK; /* No CC's all OK */ +// fprintf(stderr, "$$$ HIO END chsa %x chan %x cmd %x flags %x status %x\r\n", +// chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); + return SCPE_OK; /* No CC's all OK */ } /* grab controller n/u */ /* TODO return unimplemented function error, not busy */ -t_stat grabxio(uint16 lchsa, uint32 *status) /* grab controller XIO n/u */ +t_stat grabxio(uint16 lchsa, uint32 *status) /* grab controller XIO n/u */ { - int chan = get_chan(lchsa); - uint32 spadent; - uint16 chsa; - CHANP *chp; + int chan = get_chan(lchsa); + uint32 spadent; + uint16 chsa; + CHANP *chp; - /* get the device entry for the logical channel in SPAD */ - spadent = SPAD[chan]; /* get spad device entry for logical channel */ - chan = (spadent & 0xff00) >> 8; /* get real channel */ - chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + /* get the device entry for the logical channel in SPAD */ + spadent = SPAD[chan]; /* get spad device entry for logical channel */ + chan = (spadent & 0xff00) >> 8; /* get real channel */ + chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ + chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - /* check for a Command or data chain operation in progresss */ - if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { - sim_debug(DEBUG_CMD, &cpu_dev, "grabxio busy return CC4 chsa %x chan %x\n", chsa, chan); - *status = CC4BIT; /* busy, so CC4 */ - return SCPE_OK; /* CC4 all OK */ - } - *status = 0; /* not busy, no CC */ -// fprintf(stderr, "chan grabxio chsa %0x chan %x\r\n", chsa, chan); - sim_debug(DEBUG_CMD, &cpu_dev, "grabxio chsa %x chan %08x\n", chsa, chan); - return 0; + /* check for a Command or data chain operation in progresss */ + if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { + sim_debug(DEBUG_CMD, &cpu_dev, "grabxio busy return CC4 chsa %x chan %x\n", chsa, chan); + *status = CC4BIT; /* busy, so CC4 */ + return SCPE_OK; /* CC4 all OK */ + } + *status = 0; /* not busy, no CC */ +// fprintf(stderr, "chan grabxio chsa %0x chan %x\r\n", chsa, chan); + sim_debug(DEBUG_CMD, &cpu_dev, "grabxio chsa %x chan %08x\n", chsa, chan); + return 0; } /* reset controller XIO */ -t_stat rsctlxio(uint16 lchsa, uint32 *status) /* reset controller XIO */ +t_stat rsctlxio(uint16 lchsa, uint32 *status) /* reset controller XIO */ { - int chan = get_chan(lchsa); - uint32 spadent; - uint16 chsa; - CHANP *chp; + int chan = get_chan(lchsa); + uint32 spadent; + uint16 chsa; + CHANP *chp; - /* get the device entry for the logical channel in SPAD */ - spadent = SPAD[chan]; /* get spad device entry for logical channel */ - chan = (spadent & 0xff00) >> 8; /* get real channel */ - chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + /* get the device entry for the logical channel in SPAD */ + spadent = SPAD[chan]; /* get spad device entry for logical channel */ + chan = (spadent & 0xff00) >> 8; /* get real channel */ + chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ + chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - *status = 0; /* not busy, no CC */ -// fprintf(stderr, "chan rsctlxio chsa %0x chan %x\r\n", chsa, chan); - sim_debug(DEBUG_CMD, &cpu_dev, "rsctlxio chsa %x chan %08x\n", chsa, chan); - return 0; + *status = 0; /* not busy, no CC */ +// fprintf(stderr, "chan rsctlxio chsa %0x chan %x\r\n", chsa, chan); + sim_debug(DEBUG_CMD, &cpu_dev, "rsctlxio chsa %x chan %08x\n", chsa, chan); + return 0; } /* boot from the device (ch/sa) the caller specified */ /* on CPU reset, the cpu has set the IOCD data at location 0-4 */ t_stat chan_boot(uint16 chsa, DEVICE *dptr) { - int chan = get_chan(chsa); - DIB *dibp = dev_unit[chsa]; - CHANP *chp = dibp->chan_prg; - int i,j; + int chan = get_chan(chsa); + DIB *dibp = dev_unit[chsa]; + CHANP *chp = dibp->chan_prg; + int i,j; - sim_debug(DEBUG_EXP, &cpu_dev, "Channel Boot chan/device addr %x\n", chsa); -// fprintf(stderr, "chan_boot chsa %0x\r\n", chsa); - if (dibp == 0) /* if no channel or device, error */ - return SCPE_IOERR; /* error */ - if (dibp->chan_prg == NULL) /* must have channel information for each device */ - return SCPE_IOERR; /* error */ - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + sim_debug(DEBUG_EXP, &cpu_dev, "Channel Boot chan/device addr %x\n", chsa); +// fprintf(stderr, "chan_boot chsa %0x\r\n", chsa); + if (dibp == 0) /* if no channel or device, error */ + return SCPE_IOERR; /* error */ + if (dibp->chan_prg == NULL) /* must have channel information for each device */ + return SCPE_IOERR; /* error */ + chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - dev_status[chsa&0x7f00] = 0; /* clear the channel status location */ - dev_status[chsa] = 0; /* device status too */ - chp->chan_status = 0; /* clear the channel status */ - chp->chan_dev = chsa; /* save our address (ch/sa) */ - chp->chan_byte = BUFF_EMPTY; /* no data yet */ - chp->ccw_addr = 0; /* start loading at loc 0 */ - chp->chan_caw = 0x0; /* set IOCD address to memory location 0 */ - chp->ccw_count = 0; /* channel byte count 0 bytes*/ - chp->ccw_flags = 0; /* Command chain and supress incorrect length */ - chp->ccw_cmd = 0; /* read command */ + dev_status[chsa&0x7f00] = 0; /* clear the channel status location */ + dev_status[chsa] = 0; /* device status too */ + chp->chan_status = 0; /* clear the channel status */ + chp->chan_dev = chsa; /* save our address (ch/sa) */ + chp->chan_byte = BUFF_EMPTY; /* no data yet */ + chp->ccw_addr = 0; /* start loading at loc 0 */ + chp->chan_caw = 0x0; /* set IOCD address to memory location 0 */ + chp->ccw_count = 0; /* channel byte count 0 bytes*/ + chp->ccw_flags = 0; /* Command chain and supress incorrect length */ + chp->ccw_cmd = 0; /* read command */ - sim_debug(DEBUG_CMD, &cpu_dev, "Channel Boot calling load_ccw chan %02x status %08x\n", - chan, chp->chan_status); -// fprintf(stderr, "Channel Boot calling load_ccw chan %02x status %08x\r\n", -// chan, chp->chan_status); + sim_debug(DEBUG_CMD, &cpu_dev, "Channel Boot calling load_ccw chan %02x status %08x\n", + chan, chp->chan_status); +// fprintf(stderr, "Channel Boot calling load_ccw chan %02x status %08x\r\n", +// chan, chp->chan_status); - /* start processing the boot IOCL at loc 0 */ - if (load_ccw(chp, 0)) { /* load IOCL starting from location 0 */ - sim_debug(DEBUG_CMD, &cpu_dev, "Channel Boot Error return from load_ccw chan %02x status %08x\n", - chan, chp->chan_status); -// fprintf(stderr, "Channel Boot Error return from load_ccw chan %02x status %08x\r\n", -// chan, chp->chan_status); - dev_status[chsa] = 0; /* no device status */ - chp->ccw_flags = 0; /* clear the command flags */ - return SCPE_IOERR; /* return error */ - } -// fprintf(stderr, "Channel Boot OK return from load_ccw chsa %02x status %08x\r\n", -// chsa, chp->chan_status); - loading = chsa; /* show we are loading from the boot device */ - return SCPE_OK; /* all OK */ + /* start processing the boot IOCL at loc 0 */ + if (load_ccw(chp, 0)) { /* load IOCL starting from location 0 */ + sim_debug(DEBUG_CMD, &cpu_dev, "Channel Boot Error return from load_ccw chan %02x status %08x\n", + chan, chp->chan_status); +// fprintf(stderr, "Channel Boot Error return from load_ccw chan %02x status %08x\r\n", +// chan, chp->chan_status); + dev_status[chsa] = 0; /* no device status */ + chp->ccw_flags = 0; /* clear the command flags */ + return SCPE_IOERR; /* return error */ + } +// fprintf(stderr, "Channel Boot OK return from load_ccw chsa %02x status %08x\r\n", +// chsa, chp->chan_status); + loading = chsa; /* show we are loading from the boot device */ + return SCPE_OK; /* all OK */ } /* Scan all channels and see if one is ready to start or has @@ -1312,220 +1312,220 @@ t_stat chan_boot(uint16 chsa, DEVICE *dptr) */ uint32 scan_chan(void) { - int i,j; - uint32 chsa = 0; /* No device */ - uint32 chan; /* channel num 0-7f */ - uint32 tempa; /* icb address */ - uint32 chan_ivl; /* int level table address */ - int lev; /* interrupt level */ - uint32 chan_icba; /* int level context block address */ - CHANP *chp; /* channel prog pointer */ - DIB *dibp; /* DIB pointer */ + int i,j; + uint32 chsa = 0; /* No device */ + uint32 chan; /* channel num 0-7f */ + uint32 tempa; /* icb address */ + uint32 chan_ivl; /* int level table address */ + int lev; /* interrupt level */ + uint32 chan_icba; /* int level context block address */ + CHANP *chp; /* channel prog pointer */ + DIB *dibp; /* DIB pointer */ - /* see if we are able to look for ints */ - if ((CPUSTATUS & 0x80) == 0) { /* are interrupts blocked */ - /* ints not blocked, so look for highest requesting interrupt */ - for (i=0; i<112; i++) { - if (INTS[i]&INTS_ACT) /* look for level active */ - break; /* this level active, so stop looking */ - if (SPAD[i+0x80] == 0) /* not initialize? */ - continue; /* skip this one */ - if (SPAD[i+0x80] == 0xffffffff) /* not initialize? */ - continue; /* skip this one */ - /* see if there is pending status for this channel */ - /* if there is and the level is not requesting, do it */ - if ((INTS[i] & INTS_ENAB) && !(INTS[i] & INTS_REQ)) { - /* get the device entry for the logical channel in SPAD */ - chan = (SPAD[i+0x80] & 0xff00); /* get real channel and zero sa */ - dibp = dev_unit[chan]; /* get the device information pointer */ - if (dibp == 0) - continue; /* skip unconfigured channel */ - /* see if the FIFO is empty */ - if (dibp->chan_fifo_in != dibp->chan_fifo_out) { - uint32 sw1, sw2; - /* fifo is not empty, so post status and request an interrupt */ - if ((FIFO_Get(chan, &sw1) == 0) && (FIFO_Get(chan, &sw2) == 0)) { - /* we have status to return, do it now */ - chp = find_chanp_ptr(chan); /* find the chanp pointer for channel */ - /* get the address of the interrupt IVL table in main memory */ - chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_icba = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ - tempa = chp->chan_inch_addr; /* get inch status buffer address */ -// fprintf(stderr, "FOUND INT %x SPAD %x chan %x icb %x inch %x\r\n", i, SPAD[i+0x80], chan, chan_icba, tempa); - M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ - /* save the status to memory */ - M[(tempa+4) >> 2] = sw2; /* save status and residual count in status WD 2 loc */ - //FIXME - TEST for IOP device here - /* now store the status dw address into word 5 of the ICB for the channel */ - M[(chan_icba + 20) >> 2] = tempa | BIT1; /* post sw addr in ICB+5w & set CC2 in SW */ - INTS[i] |= INTS_REQ; /* turn on channel interrupt request */ - } - } - } - /* look for the highest requesting interrupt */ - /* that is enabled */ - if (((INTS[i] & INTS_ENAB) && (INTS[i] & INTS_REQ)) || - ((SPAD[i+0x80] & INTS_ENAB) && (INTS[i] & INTS_REQ))) { - /* requesting, make active and turn off request flag */ - INTS[i] &= ~INTS_REQ; /* turn off request */ - INTS[i] |= INTS_ACT; /* turn on active */ - SPAD[i+0x80] |= SINT_ACT; /* show active in SPAD too */ - /* make sure both enabled too */ - INTS[i] |= INTS_ENAB; /* turn on enable */ - SPAD[i+0x80] |= SINT_ENAB; /* show enabled in SPAD too */ - /* get the address of the interrupt IVL table in main memory */ - chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_icba = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ - sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan INTS REQ irq %x found chan_icba %x INTS %x\n", - i, chan_icba, INTS[i]); - return(chan_icba); /* return ICB address */ - } - } - } - if (irq_pend == 0) /* pending int? */ - return 0; /* no, so just return */ - irq_pend = 0; /* not pending anymore */ + /* see if we are able to look for ints */ + if ((CPUSTATUS & 0x80) == 0) { /* are interrupts blocked */ + /* ints not blocked, so look for highest requesting interrupt */ + for (i=0; i<112; i++) { + if (INTS[i]&INTS_ACT) /* look for level active */ + break; /* this level active, so stop looking */ + if (SPAD[i+0x80] == 0) /* not initialize? */ + continue; /* skip this one */ + if (SPAD[i+0x80] == 0xffffffff) /* not initialize? */ + continue; /* skip this one */ + /* see if there is pending status for this channel */ + /* if there is and the level is not requesting, do it */ + if ((INTS[i] & INTS_ENAB) && !(INTS[i] & INTS_REQ)) { + /* get the device entry for the logical channel in SPAD */ + chan = (SPAD[i+0x80] & 0xff00); /* get real channel and zero sa */ + dibp = dev_unit[chan]; /* get the device information pointer */ + if (dibp == 0) + continue; /* skip unconfigured channel */ + /* see if the FIFO is empty */ + if (dibp->chan_fifo_in != dibp->chan_fifo_out) { + uint32 sw1, sw2; + /* fifo is not empty, so post status and request an interrupt */ + if ((FIFO_Get(chan, &sw1) == 0) && (FIFO_Get(chan, &sw2) == 0)) { + /* we have status to return, do it now */ + chp = find_chanp_ptr(chan); /* find the chanp pointer for channel */ + /* get the address of the interrupt IVL table in main memory */ + chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */ + chan_icba = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ + tempa = chp->chan_inch_addr; /* get inch status buffer address */ +// fprintf(stderr, "FOUND INT %x SPAD %x chan %x icb %x inch %x\r\n", i, SPAD[i+0x80], chan, chan_icba, tempa); + M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ + /* save the status to memory */ + M[(tempa+4) >> 2] = sw2; /* save status and residual count in status WD 2 loc */ + //FIXME - TEST for IOP device here + /* now store the status dw address into word 5 of the ICB for the channel */ + M[(chan_icba + 20) >> 2] = tempa | BIT1; /* post sw addr in ICB+5w & set CC2 in SW */ + INTS[i] |= INTS_REQ; /* turn on channel interrupt request */ + } + } + } + /* look for the highest requesting interrupt */ + /* that is enabled */ + if (((INTS[i] & INTS_ENAB) && (INTS[i] & INTS_REQ)) || + ((SPAD[i+0x80] & INTS_ENAB) && (INTS[i] & INTS_REQ))) { + /* requesting, make active and turn off request flag */ + INTS[i] &= ~INTS_REQ; /* turn off request */ + INTS[i] |= INTS_ACT; /* turn on active */ + SPAD[i+0x80] |= SINT_ACT; /* show active in SPAD too */ + /* make sure both enabled too */ + INTS[i] |= INTS_ENAB; /* turn on enable */ + SPAD[i+0x80] |= SINT_ENAB; /* show enabled in SPAD too */ + /* get the address of the interrupt IVL table in main memory */ + chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */ + chan_icba = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */ + sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan INTS REQ irq %x found chan_icba %x INTS %x\n", + i, chan_icba, INTS[i]); + return(chan_icba); /* return ICB address */ + } + } + } + if (irq_pend == 0) /* pending int? */ + return 0; /* no, so just return */ + irq_pend = 0; /* not pending anymore */ - /* loop through all the channels/units for channel with pending I/O completion */ + /* loop through all the channels/units for channel with pending I/O completion */ for (i = 0; sim_devices[i] != NULL; i++) { - DEVICE *dptr = sim_devices[i]; /* get pointer to configured device */ - DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to Device Information Block for this device */ - UNIT *uptr = dptr->units; /* get pointer to units defined for this device */ + DEVICE *dptr = sim_devices[i]; /* get pointer to configured device */ + DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to Device Information Block for this device */ + UNIT *uptr = dptr->units; /* get pointer to units defined for this device */ - if (dibp == NULL) /* If no DIB, not channel device */ - continue; - if (dptr->flags & DEV_DIS) { /* Skip disabled devices */ - continue; - } - if ((chp = (CHANP *)dibp->chan_prg) == NULL)/* must have channel information for each device */ - continue; - /* Check if address is in unit or dev entry */ - for (j = 0; j < dibp->numunits; j++) { /* loop through unit entries */ - chsa = GET_UADDR(uptr->u3); /* ch/sa value */ + if (dibp == NULL) /* If no DIB, not channel device */ + continue; + if (dptr->flags & DEV_DIS) { /* Skip disabled devices */ + continue; + } + if ((chp = (CHANP *)dibp->chan_prg) == NULL)/* must have channel information for each device */ + continue; + /* Check if address is in unit or dev entry */ + for (j = 0; j < dibp->numunits; j++) { /* loop through unit entries */ + chsa = GET_UADDR(uptr->u3); /* ch/sa value */ - /* If channel end, check if we should continue */ - if (chp->chan_status & STATUS_CEND) { /* do we have channel end */ - if (chp->ccw_flags & FLAG_CC) { /* command chain flag */ - /* we have channel end and CC flag, continue channel prog */ - if (chp->chan_status & STATUS_DEND) { /* device end? */ -// fprintf(stderr, "scan_chan found channel end w/CC @ chsa %x flags %x do load_ccw\r\n", -// chp->chan_dev, chp->ccw_flags); - (void)load_ccw(chp, 1); /* go load the next IOCB */ - } else - irq_pend = 1; /* still pending int */ - } else { - /* we have channel end and no CC flag, end command */ - chsa = chp->chan_dev; /* get the chan/sa */ -// fprintf(stderr, "scan_chan found channel end wo/CC @ chsa %x do load_ccw loading %x\r\n", -// chp->chan_dev, loading); - dev_status[chsa] = 0; /* no device status anymore */ - /* handle case where we are loading the O/S on boot */ - if (loading) { - if (chp->chan_status & 0x3f03) { /* check if any channel errors */ - return 0; /* yes, just return */ - } - irq_pend = 0; /* no pending int */ - chp->chan_status = 0; /* no channel status */ - return chsa; /* if loading, just channel number */ - } - /* we are not loading, but have completed channel program */ - store_csw(chp); /* store the status */ - lev = find_int_lev(chsa); /* get interrupt level */ - if (lev == 0) { - irq_pend = 1; /* still pending int */ - return 0; /* just return */ - } - irq_pend = 1; /* still pending int */ - return 0; /* just return */ - } - } - uptr++; /* next UNIT pointer */ - chp++; /* next CHANP pointer */ - } - } + /* If channel end, check if we should continue */ + if (chp->chan_status & STATUS_CEND) { /* do we have channel end */ + if (chp->ccw_flags & FLAG_CC) { /* command chain flag */ + /* we have channel end and CC flag, continue channel prog */ + if (chp->chan_status & STATUS_DEND) { /* device end? */ +// fprintf(stderr, "scan_chan found channel end w/CC @ chsa %x flags %x do load_ccw\r\n", +// chp->chan_dev, chp->ccw_flags); + (void)load_ccw(chp, 1); /* go load the next IOCB */ + } else + irq_pend = 1; /* still pending int */ + } else { + /* we have channel end and no CC flag, end command */ + chsa = chp->chan_dev; /* get the chan/sa */ +// fprintf(stderr, "scan_chan found channel end wo/CC @ chsa %x do load_ccw loading %x\r\n", +// chp->chan_dev, loading); + dev_status[chsa] = 0; /* no device status anymore */ + /* handle case where we are loading the O/S on boot */ + if (loading) { + if (chp->chan_status & 0x3f03) { /* check if any channel errors */ + return 0; /* yes, just return */ + } + irq_pend = 0; /* no pending int */ + chp->chan_status = 0; /* no channel status */ + return chsa; /* if loading, just channel number */ + } + /* we are not loading, but have completed channel program */ + store_csw(chp); /* store the status */ + lev = find_int_lev(chsa); /* get interrupt level */ + if (lev == 0) { + irq_pend = 1; /* still pending int */ + return 0; /* just return */ + } + irq_pend = 1; /* still pending int */ + return 0; /* just return */ + } + } + uptr++; /* next UNIT pointer */ + chp++; /* next CHANP pointer */ + } + } #if NOT_SURE_NEEDED - /* process any pending channel */ - for (chsa = 0; chsa < MAX_DEV; chsa++) { /* loop through all the channels/units */ - if (dev_status[chsa] != 0) { /* any pending status */ - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ -// chan = get_chan(chsa); /* get channel from device number */ - if (chp->ccw_cmd == 0) { - CHANP *pchp = find_chanp_ptr(chsa&0x7f00); /* find the chanp pointer for channel */ - fprintf(stderr, "scan_chan Found dev_status %x for chsa %x\r\n", dev_status[chsa], chsa); - if (pchp->chan_inch_addr != 0) { - tempa = pchp->chan_inch_addr; /* get inch status buffer address */ - M[tempa >> 2] = 0; /* zero sa & IOCD address in status WD 1 */ - /* save the status to memory */ - M[(tempa+4) >> 2] = (((uint32)dev_status[chsa]) << 24); - } - irq_pend = 1; /* int still pending */ - dev_status[chsa] = 0; /* no status anymore */ - lev = find_int_lev(chsa); /* get interrupt level */ - if (lev == 0) { - fprintf(stderr, "scan_chan SCAN END ERROR LEV=0 chsa %x place 2\r\n", chsa); - return 0; /* just return */ - } - chan_icba = find_int_icb(chsa); /* get icb address */ - INTS[lev] |= INTS_REQ; /* turn on channel interrupt request */ - return 0; /* just return */ - } - } - } + /* process any pending channel */ + for (chsa = 0; chsa < MAX_DEV; chsa++) { /* loop through all the channels/units */ + if (dev_status[chsa] != 0) { /* any pending status */ + chp = find_chanp_ptr(chsa); /* find the chanp pointer */ +// chan = get_chan(chsa); /* get channel from device number */ + if (chp->ccw_cmd == 0) { + CHANP *pchp = find_chanp_ptr(chsa&0x7f00); /* find the chanp pointer for channel */ + fprintf(stderr, "scan_chan Found dev_status %x for chsa %x\r\n", dev_status[chsa], chsa); + if (pchp->chan_inch_addr != 0) { + tempa = pchp->chan_inch_addr; /* get inch status buffer address */ + M[tempa >> 2] = 0; /* zero sa & IOCD address in status WD 1 */ + /* save the status to memory */ + M[(tempa+4) >> 2] = (((uint32)dev_status[chsa]) << 24); + } + irq_pend = 1; /* int still pending */ + dev_status[chsa] = 0; /* no status anymore */ + lev = find_int_lev(chsa); /* get interrupt level */ + if (lev == 0) { + fprintf(stderr, "scan_chan SCAN END ERROR LEV=0 chsa %x place 2\r\n", chsa); + return 0; /* just return */ + } + chan_icba = find_int_icb(chsa); /* get icb address */ + INTS[lev] |= INTS_REQ; /* turn on channel interrupt request */ + return 0; /* just return */ + } + } + } #endif - return 0; + return 0; } /* set up the devices configured into the simulator */ /* only devices with a DIB will be processed */ t_stat chan_set_devs() { - int i, j; + int i, j; - for(i = 0; i < MAX_DEV; i++) { - dev_unit[i] = NULL; /* clear Device pointer array */ - } - /* Build channel array */ - for (i = 0; sim_devices[i] != NULL; i++) { - DEVICE *dptr = sim_devices[i]; /* get pointer to next configured device */ - UNIT *uptr = dptr->units; /* get pointer to units defined for this device */ - DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to Device Information Block for this device */ - CHANP *chp; /* channel program pointer */ - int chsa; /* addr of device chan & subaddress */ + for(i = 0; i < MAX_DEV; i++) { + dev_unit[i] = NULL; /* clear Device pointer array */ + } + /* Build channel array */ + for (i = 0; sim_devices[i] != NULL; i++) { + DEVICE *dptr = sim_devices[i]; /* get pointer to next configured device */ + UNIT *uptr = dptr->units; /* get pointer to units defined for this device */ + DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to Device Information Block for this device */ + CHANP *chp; /* channel program pointer */ + int chsa; /* addr of device chan & subaddress */ - if (dibp == NULL) /* If no DIB, not channel device */ - continue; - if (dptr->flags & DEV_DIS) { /* Skip disabled devices */ -// fprintf(stderr, "chan_set_devs DISABLED check %s u3 %x\r\n", dptr->name, GET_UADDR(uptr->u3)); - continue; - } - if ((chp = (CHANP *)dibp->chan_prg) == NULL)/* must have channel information for each device */ - continue; - /* Check if address is in unit or dev entry */ - for (j = 0; j < dptr->numunits; j++) { /* loop through unit entries */ - chsa = GET_UADDR(uptr->u3); /* ch/sa value */ - /* zero some channel data loc's for device */ - dev_status[chsa] = 0; /* zero device status flags */ - dev_status[chsa&0x7f00] = 0; /* clear the channel status location */ - dev_status[chsa] = 0; /* device status too */ - chp->chan_status = 0; /* clear the channel status */ - chp->chan_dev = chsa; /* save our address (ch/sa) */ - chp->chan_byte = BUFF_EMPTY; /* no data yet */ - chp->ccw_addr = 0; /* start loading at loc 0 */ - chp->chan_caw = 0; /* set IOCD address to memory location 0 */ - chp->ccw_count = 0; /* channel byte count 0 bytes*/ - chp->ccw_flags = 0; /* Command chain and supress incorrect length */ - chp->ccw_cmd = 0; /* read command */ - chp->chan_inch_addr = 0; /* clear address of stat dw in memory */ - if ((uptr->flags & UNIT_DIS) == 0) /* is unit marked disabled? */ - dev_unit[chsa] = dibp; /* no, save the dib address */ - if (dibp->dev_ini != NULL) /* if there is an init routine, call it now */ - dibp->dev_ini(uptr, 1); /* init the channel */ - uptr++; /* next UNIT pointer */ - chp++; /* next CHANP pointer */ - } - } - return SCPE_OK; /* all is OK */ + if (dibp == NULL) /* If no DIB, not channel device */ + continue; + if (dptr->flags & DEV_DIS) { /* Skip disabled devices */ +// fprintf(stderr, "chan_set_devs DISABLED check %s u3 %x\r\n", dptr->name, GET_UADDR(uptr->u3)); + continue; + } + if ((chp = (CHANP *)dibp->chan_prg) == NULL)/* must have channel information for each device */ + continue; + /* Check if address is in unit or dev entry */ + for (j = 0; j < dptr->numunits; j++) { /* loop through unit entries */ + chsa = GET_UADDR(uptr->u3); /* ch/sa value */ + /* zero some channel data loc's for device */ + dev_status[chsa] = 0; /* zero device status flags */ + dev_status[chsa&0x7f00] = 0; /* clear the channel status location */ + dev_status[chsa] = 0; /* device status too */ + chp->chan_status = 0; /* clear the channel status */ + chp->chan_dev = chsa; /* save our address (ch/sa) */ + chp->chan_byte = BUFF_EMPTY; /* no data yet */ + chp->ccw_addr = 0; /* start loading at loc 0 */ + chp->chan_caw = 0; /* set IOCD address to memory location 0 */ + chp->ccw_count = 0; /* channel byte count 0 bytes*/ + chp->ccw_flags = 0; /* Command chain and supress incorrect length */ + chp->ccw_cmd = 0; /* read command */ + chp->chan_inch_addr = 0; /* clear address of stat dw in memory */ + if ((uptr->flags & UNIT_DIS) == 0) /* is unit marked disabled? */ + dev_unit[chsa] = dibp; /* no, save the dib address */ + if (dibp->dev_ini != NULL) /* if there is an init routine, call it now */ + dibp->dev_ini(uptr, 1); /* init the channel */ + uptr++; /* next UNIT pointer */ + chp++; /* next CHANP pointer */ + } + } + return SCPE_OK; /* all is OK */ } /* Validate and set the device onto a given channel */ @@ -1539,13 +1539,13 @@ t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc) int devaddr; fprintf(stderr, "set_dev_addr val %x cptr %s desc %s\r\n", val, cptr, (char *)desc); - if (cptr == NULL) /* is there a UNIT name specified */ - return SCPE_ARG; /* no, arg error */ - if (uptr == NULL) /* is there a UNIT pointer */ - return SCPE_IERR; /* no, arg error */ - dptr = find_dev_from_unit(uptr); /* find the device from unit pointer */ - if (dptr == NULL) /* device not found, so error */ - return SCPE_IERR; /* error */ + if (cptr == NULL) /* is there a UNIT name specified */ + return SCPE_ARG; /* no, arg error */ + if (uptr == NULL) /* is there a UNIT pointer */ + return SCPE_IERR; /* no, arg error */ + dptr = find_dev_from_unit(uptr); /* find the device from unit pointer */ + if (dptr == NULL) /* device not found, so error */ + return SCPE_IERR; /* error */ dibp = (DIB *)dptr->ctxt; if (dibp == NULL) @@ -1609,17 +1609,17 @@ fprintf(stderr, "set_dev_addr val %x cptr %s desc %s\r\n", val, cptr, (char *)de t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc) { - DEVICE *dptr; - int chsa; + DEVICE *dptr; + int chsa; -// fprintf(stderr, "show_dev_addr val %x desc %s\r\n", v, (char *)desc); - if (uptr == NULL) - return SCPE_IERR; - dptr = find_dev_from_unit(uptr); - if (dptr == NULL) - return SCPE_IERR; - chsa = GET_UADDR(uptr->u3); - fprintf(st, "%04x", chsa); - return SCPE_OK; +// fprintf(stderr, "show_dev_addr val %x desc %s\r\n", v, (char *)desc); + if (uptr == NULL) + return SCPE_IERR; + dptr = find_dev_from_unit(uptr); + if (dptr == NULL) + return SCPE_IERR; + chsa = GET_UADDR(uptr->u3); + fprintf(st, "%04x", chsa); + return SCPE_OK; } diff --git a/SEL32/sel32_clk.c b/SEL32/sel32_clk.c index a9c850b..84a27bf 100644 --- a/SEL32/sel32_clk.c +++ b/SEL32/sel32_clk.c @@ -50,14 +50,14 @@ t_stat rtc_reset (DEVICE *dptr); t_stat rtc_set_freq (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat rtc_show_freq (FILE *st, UNIT *uptr, int32 val, CONST void *desc); -extern int irq_pend; /* go scan for pending int or I/O */ -extern uint32 INTS[]; /* interrupt control flags */ -extern uint32 SPAD[]; /* computer SPAD */ -extern uint32 M[]; /* system memory */ +extern int irq_pend; /* go scan for pending int or I/O */ +extern uint32 INTS[]; /* interrupt control flags */ +extern uint32 SPAD[]; /* computer SPAD */ +extern uint32 M[]; /* system memory */ -int32 rtc_pie = 0; /* rtc pulse ie */ -int32 rtc_tps = 60; /* rtc ticks/sec */ -int32 rtc_lvl = 0x18; /* rtc interrupt level */ +int32 rtc_pie = 0; /* rtc pulse ie */ +int32 rtc_tps = 60; /* rtc ticks/sec */ +int32 rtc_lvl = 0x18; /* rtc interrupt level */ /* Clock data structures @@ -106,14 +106,14 @@ DEVICE rtc_dev = { /* service clock signal from simulator */ t_stat rtc_srv (UNIT *uptr) { - if (rtc_pie) { /* set pulse intr */ - INTS[rtc_lvl] |= INTS_REQ; /* request the interrupt */ - irq_pend = 1; /* make sure we scan for int */ - } -// rtc_unit.wait = sim_rtcn_calb (rtc_tps, TMR_RTC); /* calibrate */ -// sim_activate (&rtc_unit, rtc_unit.wait); /* reactivate */ - sim_activate (&rtc_unit, 16667); /* reactivate */ - return SCPE_OK; + if (rtc_pie) { /* set pulse intr */ + INTS[rtc_lvl] |= INTS_REQ; /* request the interrupt */ + irq_pend = 1; /* make sure we scan for int */ + } +// rtc_unit.wait = sim_rtcn_calb (rtc_tps, TMR_RTC); /* calibrate */ +// sim_activate (&rtc_unit, rtc_unit.wait); /* reactivate */ + sim_activate (&rtc_unit, 16667); /* reactivate */ + return SCPE_OK; } /* Clock interrupt start/stop */ @@ -122,64 +122,64 @@ t_stat rtc_srv (UNIT *uptr) /* level = interrupt level */ void rtc_setup(uint ss, uint32 level) { - uint32 val = SPAD[level+0x80]; /* get SPAD value for interrupt vector */ - rtc_lvl = level; /* save the interrupt level */ - uint32 addr = SPAD[0xf1] + (level<<2); /* vector address in SPAD */ - addr = M[addr>>2]; /* get the interrupt context block addr */ + uint32 val = SPAD[level+0x80]; /* get SPAD value for interrupt vector */ + rtc_lvl = level; /* save the interrupt level */ + uint32 addr = SPAD[0xf1] + (level<<2); /* vector address in SPAD */ + addr = M[addr>>2]; /* get the interrupt context block addr */ //fprintf(stderr, "rtc_setup called ss %x level %x SPAD %x icba %x\r\n", ss, level, val, addr); - if (ss == 1) { /* starting? */ - INTS[level] |= INTS_ENAB; /* make sure enabled */ - SPAD[level+0x80] |= SINT_ENAB; /* in spad too */ - INTS[level] |= INTS_REQ; /* request the interrupt */ - sim_activate(&rtc_unit, 20); /* start us off */ - } else { - INTS[level] &= ~INTS_ENAB; /* make sure disabled */ - SPAD[level+0x80] &= ~SINT_ENAB; /* in spad too */ - } - rtc_pie = ss; /* set new state */ + if (ss == 1) { /* starting? */ + INTS[level] |= INTS_ENAB; /* make sure enabled */ + SPAD[level+0x80] |= SINT_ENAB; /* in spad too */ + INTS[level] |= INTS_REQ; /* request the interrupt */ + sim_activate(&rtc_unit, 20); /* start us off */ + } else { + INTS[level] &= ~INTS_ENAB; /* make sure disabled */ + SPAD[level+0x80] &= ~SINT_ENAB; /* in spad too */ + } + rtc_pie = ss; /* set new state */ } /* Clock reset */ t_stat rtc_reset(DEVICE *dptr) { - rtc_pie = 0; /* disable pulse */ - rtc_unit.wait = sim_rtcn_init (rtc_unit.wait, TMR_RTC); /* initialize clock calibration */ - sim_activate (&rtc_unit, rtc_unit.wait); /* activate unit */ - return SCPE_OK; + rtc_pie = 0; /* disable pulse */ + rtc_unit.wait = sim_rtcn_init (rtc_unit.wait, TMR_RTC); /* initialize clock calibration */ + sim_activate (&rtc_unit, rtc_unit.wait); /* activate unit */ + return SCPE_OK; } /* Set frequency */ t_stat rtc_set_freq(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { - if (cptr) /* if chars, bad */ - return SCPE_ARG; /* ARG error */ - if ((val != 50) && (val != 60) && (val != 100) && (val != 120)) - return SCPE_IERR; /* scope error */ - rtc_tps = val; /* set the new frequency */ - return SCPE_OK; /* we done */ + if (cptr) /* if chars, bad */ + return SCPE_ARG; /* ARG error */ + if ((val != 50) && (val != 60) && (val != 100) && (val != 120)) + return SCPE_IERR; /* scope error */ + rtc_tps = val; /* set the new frequency */ + return SCPE_OK; /* we done */ } /* Show frequency */ t_stat rtc_show_freq (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { - /* print the cirrent frequency setting */ - if (rtc_tps < 100) - fprintf (st, (rtc_tps == 50)? "50Hz": "60Hz"); - else - fprintf (st, (rtc_tps == 100)? "100Hz": "120Hz"); - return SCPE_OK; + /* print the cirrent frequency setting */ + if (rtc_tps < 100) + fprintf (st, (rtc_tps == 50)? "50Hz": "60Hz"); + else + fprintf (st, (rtc_tps == 100)? "100Hz": "120Hz"); + return SCPE_OK; } /************************************************************************/ /* Interval Timer support */ -int32 itm_pie = 0; /* itm pulse enable */ -//int32 itm_tps = 38; /* itm 26041 ticks/sec = 38.4 us per tic */ -///int32 itm_tps = 48; /* itm 26041 ticks/sec = 38.4 us per tic */ -int32 itm_tps = 64; /* itm 26041 ticks/sec = 38.4 us per tic */ -int32 itm_lvl = 0x5f; /* itm interrupt level */ -int32 itm_cnt = 26041; /* value that we are downcounting */ -int32 itm_run = 0; /* set when timer running */ +int32 itm_pie = 0; /* itm pulse enable */ +//int32 itm_tps = 38; /* itm 26041 ticks/sec = 38.4 us per tic */ +///int32 itm_tps = 48; /* itm 26041 ticks/sec = 38.4 us per tic */ +int32 itm_tps = 64; /* itm 26041 ticks/sec = 38.4 us per tic */ +int32 itm_lvl = 0x5f; /* itm interrupt level */ +int32 itm_cnt = 26041; /* value that we are downcounting */ +int32 itm_run = 0; /* set when timer running */ t_stat itm_srv (UNIT *uptr); t_stat itm_set_freq (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat itm_reset (DEVICE *dptr); @@ -236,33 +236,33 @@ DEVICE itm_dev = { /* downcount the loaded value until zero and then cause interrupt */ t_stat itm_srv (UNIT *uptr) { -// uint32 val = SPAD[itm_lvl+0x80]; /* get SPAD value for interrupt vector */ -// uint32 addr = SPAD[0xf1] + (itm_lvl<<2); /* vector address in SPAD */ -// addr = M[addr>>2]; /* get the interrupt context block addr */ +// uint32 val = SPAD[itm_lvl+0x80]; /* get SPAD value for interrupt vector */ +// uint32 addr = SPAD[0xf1] + (itm_lvl<<2); /* vector address in SPAD */ +// addr = M[addr>>2]; /* get the interrupt context block addr */ //fprintf(stderr, "itm_srv level %x itm_pie %x wait %x spad %x icba %x\r\n", -// itm_lvl, itm_pie, itm_unit.wait, val, addr); +// itm_lvl, itm_pie, itm_unit.wait, val, addr); - /* count down about 48 instructions per tick ~38.4 us */ - /* we will be called once for each instructon */ - itm_unit.wait -= 1; /* subtract 1 from wait count */ - if (itm_unit.wait > 0) - return SCPE_OK; /* not time yet */ - itm_unit.wait = itm_tps; /* reset wait count */ + /* count down about 48 instructions per tick ~38.4 us */ + /* we will be called once for each instructon */ + itm_unit.wait -= 1; /* subtract 1 from wait count */ + if (itm_unit.wait > 0) + return SCPE_OK; /* not time yet */ + itm_unit.wait = itm_tps; /* reset wait count */ - if (itm_run) { /* see if timer running */ - itm_cnt--; /* down count by one */ - if ((itm_cnt == 0) && itm_pie) { /* see if reached 0 yet */ -// if (itm_cnt == 0) { /* see if reached 0 yet */ + if (itm_run) { /* see if timer running */ + itm_cnt--; /* down count by one */ + if ((itm_cnt == 0) && itm_pie) { /* see if reached 0 yet */ +// if (itm_cnt == 0) { /* see if reached 0 yet */ //fprintf(stderr, "itm_srv REQ itm_pie %x wait %x itm_cnt %x\r\n", itm_pie, itm_unit.wait, itm_cnt); - INTS[itm_lvl] |= INTS_REQ; /* request the interrupt on zero value */ - irq_pend = 1; /* make sure we scan for int */ - } - } + INTS[itm_lvl] |= INTS_REQ; /* request the interrupt on zero value */ + irq_pend = 1; /* make sure we scan for int */ + } + } #if 0 - itm_unit.wait = sim_rtcn_calb (itm_tps, TMR_ITM); /* calibrate */ - sim_activate (&itm_unit, itm_unit.wait); /* reactivate */ + itm_unit.wait = sim_rtcn_calb (itm_tps, TMR_ITM); /* calibrate */ + sim_activate (&itm_unit, itm_unit.wait); /* reactivate */ #endif - return SCPE_OK; + return SCPE_OK; } /* ITM read/load function called from CD command processing */ @@ -275,37 +275,37 @@ t_stat itm_srv (UNIT *uptr) /* ret = return value read from timer */ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) { - uint32 temp; -// uint32 val = SPAD[level+0x80]; /* get SPAD value for interrupt vector */ + uint32 temp; +// uint32 val = SPAD[level+0x80]; /* get SPAD value for interrupt vector */ -// itm_lvl = level; /* save the interrupt level */ -// uint32 addr = SPAD[0xf1] + (level<<2); /* vector address in SPAD */ -// addr = M[addr>>2]; /* get the interrupt context block addr */ +// itm_lvl = level; /* save the interrupt level */ +// uint32 addr = SPAD[0xf1] + (level<<2); /* vector address in SPAD */ +// addr = M[addr>>2]; /* get the interrupt context block addr */ //fprintf(stderr, "itm_rdwr called ss %x level %x SPAD %x icba %x\r\n", ss, level, val, addr); //fprintf(stderr, "itm_rdwr called cmd %x count %x (%d) level %x return cnt %x (%d)\r\n", -// cmd, cnt, cnt, level, itm_cnt, itm_cnt); - switch (cmd) { - case 0x39: /* load timer with new value and start*/ - if (cnt < 0) - cnt = 26042; /* TRY ??*/ - itm_cnt = cnt; /* load timer with value from user to down count */ - itm_run = 1; /* start timer */ - return 0; /* does not matter, no value returned */ - case 0x60: /* read and stop timer */ - temp = itm_cnt; /* get timer value and stop timer */ - itm_run = 0; /* stop timer */ -// itm_cnt = 0; /* reset with timer value from user to down count */ - return temp; /* return current count value */ - case 0x79: /* read the current timer value */ - temp = itm_cnt; /* get timer value, load new value and start timer */ - itm_cnt = cnt; /* load timer with value from user to down count */ - itm_run = 1; /* start timer */ - return temp; /* return current count value */ - case 0x40: /* read the current timer value */ - return itm_cnt; /* return current count value */ - break; - } - return 0; /* does not matter, no value returned */ +// cmd, cnt, cnt, level, itm_cnt, itm_cnt); + switch (cmd) { + case 0x39: /* load timer with new value and start*/ + if (cnt < 0) + cnt = 26042; /* TRY ??*/ + itm_cnt = cnt; /* load timer with value from user to down count */ + itm_run = 1; /* start timer */ + return 0; /* does not matter, no value returned */ + case 0x60: /* read and stop timer */ + temp = itm_cnt; /* get timer value and stop timer */ + itm_run = 0; /* stop timer */ +// itm_cnt = 0; /* reset with timer value from user to down count */ + return temp; /* return current count value */ + case 0x79: /* read the current timer value */ + temp = itm_cnt; /* get timer value, load new value and start timer */ + itm_cnt = cnt; /* load timer with value from user to down count */ + itm_run = 1; /* start timer */ + return temp; /* return current count value */ + case 0x40: /* read the current timer value */ + return itm_cnt; /* return current count value */ + break; + } + return 0; /* does not matter, no value returned */ } /* Clock interrupt start/stop */ @@ -314,54 +314,54 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) /* level = interrupt level */ void itm_setup(uint ss, uint32 level) { - itm_lvl = level; /* save the interrupt level */ + itm_lvl = level; /* save the interrupt level */ // fprintf(stderr, "itm_setup called ss %x level %x\r\n", ss, level); - if (ss == 1) { /* starting? */ - INTS[level] |= INTS_ENAB; /* make sure enabled */ - SPAD[level+0x80] |= SINT_ENAB; /* in spad too */ - INTS[level] |= INTS_REQ; /* request the interrupt */ - itm_cnt = 26042; /* start with 1 sec */ - itm_run = 0; /* not running yet */ -/// sim_activate(&itm_unit, 48); /* start us off */ - } else { - INTS[level] &= ~INTS_ENAB; /* make sure disabled */ - SPAD[level+0x80] &= ~SINT_ENAB; /* in spad too */ - } - itm_pie = ss; /* set new state */ + if (ss == 1) { /* starting? */ + INTS[level] |= INTS_ENAB; /* make sure enabled */ + SPAD[level+0x80] |= SINT_ENAB; /* in spad too */ + INTS[level] |= INTS_REQ; /* request the interrupt */ + itm_cnt = 26042; /* start with 1 sec */ + itm_run = 0; /* not running yet */ +/// sim_activate(&itm_unit, 48); /* start us off */ + } else { + INTS[level] &= ~INTS_ENAB; /* make sure disabled */ + SPAD[level+0x80] &= ~SINT_ENAB; /* in spad too */ + } + itm_pie = ss; /* set new state */ } /* Clock reset */ t_stat itm_reset (DEVICE *dptr) { -// int intlev = 0x5f; /* interrupt level for itm */ +// int intlev = 0x5f; /* interrupt level for itm */ //fprintf(stderr, "itm_reset called\r\n"); - itm_pie = 0; /* disable pulse */ - itm_cnt = 26042; /* start with 1 sec */ - itm_run = 0; /* not running yet */ + itm_pie = 0; /* disable pulse */ + itm_cnt = 26042; /* start with 1 sec */ + itm_run = 0; /* not running yet */ #if 0 - rtc_unit.wait = sim_rtcn_init (itm_unit.wait, TMR_ITM); /* initialize clock calibration */ - sim_activate (&itm_unit, itm_unit.wait); /* activate unit */ + rtc_unit.wait = sim_rtcn_init (itm_unit.wait, TMR_ITM); /* initialize clock calibration */ + sim_activate (&itm_unit, itm_unit.wait); /* activate unit */ #endif - return SCPE_OK; + return SCPE_OK; } /* Set frequency */ t_stat itm_set_freq (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { - if (cptr) /* if chars, bad */ - return SCPE_ARG; /* ARG error */ - if ((val != 384) && (val != 768)) - return SCPE_IERR; /* scope error */ - itm_tps = val/10; /* set the new frequency */ - return SCPE_OK; /* we done */ + if (cptr) /* if chars, bad */ + return SCPE_ARG; /* ARG error */ + if ((val != 384) && (val != 768)) + return SCPE_IERR; /* scope error */ + itm_tps = val/10; /* set the new frequency */ + return SCPE_OK; /* we done */ } /* Show frequency */ t_stat itm_show_freq (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { - /* print the cirrent frequency setting */ - fprintf (st, (itm_tps == 38)? "38.4us": "76.8us"); - return SCPE_OK; + /* print the cirrent frequency setting */ + fprintf (st, (itm_tps == 38)? "38.4us": "76.8us"); + return SCPE_OK; } #endif diff --git a/SEL32/sel32_com.c b/SEL32/sel32_com.c index 4952223..71148d9 100644 --- a/SEL32/sel32_com.c +++ b/SEL32/sel32_com.c @@ -29,22 +29,22 @@ #ifdef NUM_DEVS_COM -extern t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); -extern t_stat show_dev_addr(FILE *st, UNIT * uptr, int32 v, CONST void *desc); -extern void chan_end(uint16 chan, uint8 flags); -extern int chan_read_byte(uint16 chan, uint8 *data); -extern int chan_write_byte(uint16 chan, uint8 *data); -extern void set_devwake(uint16 addr, uint8 flags); -extern int traceme, trstart; +extern t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +extern t_stat show_dev_addr(FILE *st, UNIT * uptr, int32 v, CONST void *desc); +extern void chan_end(uint16 chan, uint8 flags); +extern int chan_read_byte(uint16 chan, uint8 *data); +extern int chan_write_byte(uint16 chan, uint8 *data); +extern void set_devwake(uint16 addr, uint8 flags); +extern int traceme, trstart; /* Constants */ -#define COM_LINES 8 /* max lines */ -//#define COM_LINES 16 /* max lines */ -#define COM_LINES_DFLT 8 /* default lines */ -#define COM_INIT_POLL 8000 -#define COML_WAIT 500 -#define COM_WAIT 500 -#define COM_NUMLIN com_desc.lines /* curr # lines */ +#define COM_LINES 8 /* max lines */ +//#define COM_LINES 16 /* max lines */ +#define COM_LINES_DFLT 8 /* default lines */ +#define COM_INIT_POLL 8000 +#define COML_WAIT 500 +#define COM_WAIT 500 +#define COM_NUMLIN com_desc.lines /* curr # lines */ #define COMC 0 /* channel thread */ #define COMI 1 /* input thread */ @@ -74,157 +74,157 @@ TMLN com_ldsc[COM_LINES] = { 0 }; /* line descrs */ TMXR com_desc = { COM_LINES_DFLT, 0, 0, com_ldsc }; /* com descr */ /* Held in u3 is the device command and status */ -#define COM_INCH 0x00 /* Initialize channel command */ -#define COM_WR 0x01 /* Write terminal */ -#define COM_RD 0x02 /* Read terminal */ -#define COM_NOP 0x03 /* No op command */ -#define COM_SNS 0x04 /* Sense command */ -#define COM_WRSCM 0x05 /* Write w/Sub chan monitor */ -#define COM_RDECHO 0x06 /* Read with Echo */ -#define COM_RDFC 0x0A /* Read w/flow control */ -#define COM_DEFSC 0x0B /* Define special char */ -#define COM_WRHFC 0x0D /* Write hardware flow control */ -#define COM_RDTR 0x13 /* Reset DTR (ADVR) */ -#define COM_SDTR 0x17 /* Set DTR (ADVF) */ -#define COM_RRTS 0x1B /* Reset RTS */ -#define COM_SRTS 0x1F /* Set RTS */ -#define COM_RBRK 0x33 /* Reset BREAK */ -#define COM_SBRK 0x37 /* Set BREAK */ -#define COM_RDHFC 0x8E /* Read w/hardware flow control only */ -#define COM_SACE 0xFF /* Set ACE parameters */ +#define COM_INCH 0x00 /* Initialize channel command */ +#define COM_WR 0x01 /* Write terminal */ +#define COM_RD 0x02 /* Read terminal */ +#define COM_NOP 0x03 /* No op command */ +#define COM_SNS 0x04 /* Sense command */ +#define COM_WRSCM 0x05 /* Write w/Sub chan monitor */ +#define COM_RDECHO 0x06 /* Read with Echo */ +#define COM_RDFC 0x0A /* Read w/flow control */ +#define COM_DEFSC 0x0B /* Define special char */ +#define COM_WRHFC 0x0D /* Write hardware flow control */ +#define COM_RDTR 0x13 /* Reset DTR (ADVR) */ +#define COM_SDTR 0x17 /* Set DTR (ADVF) */ +#define COM_RRTS 0x1B /* Reset RTS */ +#define COM_SRTS 0x1F /* Set RTS */ +#define COM_RBRK 0x33 /* Reset BREAK */ +#define COM_SBRK 0x37 /* Set BREAK */ +#define COM_RDHFC 0x8E /* Read w/hardware flow control only */ +#define COM_SACE 0xFF /* Set ACE parameters */ -#define COM_MSK 0xFF /* Command mask */ +#define COM_MSK 0xFF /* Command mask */ /* Status held in u3 */ /* controller/unit address in upper 16 bits */ -#define COM_INPUT 0x100 /* Input ready for unit */ -#define COM_CR 0x200 /* Output at beginning of line */ -#define COM_REQ 0x400 /* Request key pressed */ -#define COM_EKO 0x800 /* Echo input character */ -#define COM_OUTPUT 0x1000 /* Output ready for unit */ -#define COM_READ 0x2000 /* Read mode selected */ +#define COM_INPUT 0x100 /* Input ready for unit */ +#define COM_CR 0x200 /* Output at beginning of line */ +#define COM_REQ 0x400 /* Request key pressed */ +#define COM_EKO 0x800 /* Echo input character */ +#define COM_OUTPUT 0x1000 /* Output ready for unit */ +#define COM_READ 0x2000 /* Read mode selected */ /* ACE data kept in u4 */ /* in u5 packs sense byte 0, 1, 2 and 3 */ /* Sense byte 0 */ -#define SNS_CMDREJ 0x80000000 /* Command reject */ -#define SNS_INTVENT 0x40000000 /* Unit intervention required (N/U) */ -#define SNS_BOCHK 0x20000000 /* Bus out check (IOP parity error */ -#define SNS_EQUIPCK 0x10000000 /* Equipment check (device error) */ -#define SNS_DATACK 0x08000000 /* Data check */ -#define SNS_OVERRN 0x04000000 /* Overrun (N/U) */ -#define SNS_NUB01 0x02000000 /* Zero (N/U) */ -#define SNS_NUB02 0x01000000 /* Zero (N/U) */ +#define SNS_CMDREJ 0x80000000 /* Command reject */ +#define SNS_INTVENT 0x40000000 /* Unit intervention required (N/U) */ +#define SNS_BOCHK 0x20000000 /* Bus out check (IOP parity error */ +#define SNS_EQUIPCK 0x10000000 /* Equipment check (device error) */ +#define SNS_DATACK 0x08000000 /* Data check */ +#define SNS_OVERRN 0x04000000 /* Overrun (N/U) */ +#define SNS_NUB01 0x02000000 /* Zero (N/U) */ +#define SNS_NUB02 0x01000000 /* Zero (N/U) */ /* Sense byte 1 */ -#define SNS_ASCIICD 0x00800000 /* ASCII control char detected interrupt */ -#define SNS_SPCLCD 0x00400000 /* Special char detected interrupt */ -#define SNS_ETX 0x00200000 /* ETX interrupt */ -#define SNS_BREAK 0x00100000 /* BREAK interrupt */ -#define SNS_ACEFE 0x00080000 /* ACE framing error interrupt */ -#define SNS_ACEPEI 0x00040000 /* ACE parity error interrupt */ -#define SNS_ACEOVR 0x00020000 /* ACE overrun error interrupt */ -#define SNS_RING 0x00010000 /* Ring character interrupt */ +#define SNS_ASCIICD 0x00800000 /* ASCII control char detected interrupt */ +#define SNS_SPCLCD 0x00400000 /* Special char detected interrupt */ +#define SNS_ETX 0x00200000 /* ETX interrupt */ +#define SNS_BREAK 0x00100000 /* BREAK interrupt */ +#define SNS_ACEFE 0x00080000 /* ACE framing error interrupt */ +#define SNS_ACEPEI 0x00040000 /* ACE parity error interrupt */ +#define SNS_ACEOVR 0x00020000 /* ACE overrun error interrupt */ +#define SNS_RING 0x00010000 /* Ring character interrupt */ /* Sense byte 2 Modem status */ -#define SNS_RLSDS 0x00008000 /* Received line signal detect status */ -#define SNS_RINGST 0x00004000 /* Ring indicator line status */ -#define SNS_DSRS 0x00002000 /* DSR Data set ready line status */ -#define SNS_CTSS 0x00001000 /* CTS Clear to send line status */ -#define SNS_DELTA 0x00000800 /* Delta receive line signal detect failure interrupt */ -#define SNS_MRING 0x00000400 /* RI Modem ring interrupt */ -#define SNS_DELDSR 0x00000200 /* Delta data set ready interrupt */ -#define SNS_DELCLR 0x00000100 /* Ring character interrupt */ +#define SNS_RLSDS 0x00008000 /* Received line signal detect status */ +#define SNS_RINGST 0x00004000 /* Ring indicator line status */ +#define SNS_DSRS 0x00002000 /* DSR Data set ready line status */ +#define SNS_CTSS 0x00001000 /* CTS Clear to send line status */ +#define SNS_DELTA 0x00000800 /* Delta receive line signal detect failure interrupt */ +#define SNS_MRING 0x00000400 /* RI Modem ring interrupt */ +#define SNS_DELDSR 0x00000200 /* Delta data set ready interrupt */ +#define SNS_DELCLR 0x00000100 /* Ring character interrupt */ /* Sense byte 3 Modem Control/Operation status */ -#define SNS_HALFD 0x00000080 /* Half-duplix operation set */ -#define SNS_MRINGE 0x00000040 /* Modem ring enabled (1) */ -#define SNS_ACEDEF 0x00000020 /* ACE parameters defined */ -#define SNS_DIAGM 0x00000010 /* Diagnostic mode set */ -#define SNS_AUXOL2 0x00000008 /* Auxiliary output level 2 */ -#define SNS_AUXOL1 0x00000004 /* Auxiliary output level 1 */ -#define SNS_RTS 0x00000002 /* RTS Request to send set */ -#define SNS_DTR 0x00000001 /* DTR Data terminal ready set */ +#define SNS_HALFD 0x00000080 /* Half-duplix operation set */ +#define SNS_MRINGE 0x00000040 /* Modem ring enabled (1) */ +#define SNS_ACEDEF 0x00000020 /* ACE parameters defined */ +#define SNS_DIAGM 0x00000010 /* Diagnostic mode set */ +#define SNS_AUXOL2 0x00000008 /* Auxiliary output level 2 */ +#define SNS_AUXOL1 0x00000004 /* Auxiliary output level 1 */ +#define SNS_RTS 0x00000002 /* RTS Request to send set */ +#define SNS_DTR 0x00000001 /* DTR Data terminal ready set */ /* Sense byte 4 ACE Parameters status */ -#define SNS_ACEDLE 0x80000000 /* Divisor latch enable 0=dis, 1=enb */ -#define SNS_ACEBS 0x40000000 /* Break set 0=reset, 1=set */ -#define SNS_ACEFP 0x20000000 /* Forced parity 0=odd, 1=even */ -#define SNS_ACEP 0x10000000 /* Parity 0=odd, 1=even */ -#define SNS_ACEPE 0x08000000 /* Parity enable 0=dis, 1=enb */ -#define SNS_ACESTOP 0x04000000 /* Stop bit 0=1, 1=1.5 or 2 */ -#define SNS_ACECLEN 0x02000000 /* Character length 00=5, 01=6, 11=7, 11=8 */ -#define SNS_ACECL2 0x01000000 /* 2nd bit for above */ +#define SNS_ACEDLE 0x80000000 /* Divisor latch enable 0=dis, 1=enb */ +#define SNS_ACEBS 0x40000000 /* Break set 0=reset, 1=set */ +#define SNS_ACEFP 0x20000000 /* Forced parity 0=odd, 1=even */ +#define SNS_ACEP 0x10000000 /* Parity 0=odd, 1=even */ +#define SNS_ACEPE 0x08000000 /* Parity enable 0=dis, 1=enb */ +#define SNS_ACESTOP 0x04000000 /* Stop bit 0=1, 1=1.5 or 2 */ +#define SNS_ACECLEN 0x02000000 /* Character length 00=5, 01=6, 11=7, 11=8 */ +#define SNS_ACECL2 0x01000000 /* 2nd bit for above */ /* Sense byte 5 Baud rate */ -#define SNS_NUB50 0x00800000 /* Zero N/U */ -#define SNS_NUB51 0x00400000 /* Zero N/U */ -#define SNS_RINGCR 0x00200000 /* Ring or wakeup character recognition 0=enb, 1=dis */ -#define SNS_DIAGL 0x00100000 /* Set diagnostic loopback */ -#define SNS_BAUD 0x000F0000 /* Baud rate bits 4-7 */ -#define BAUD50 0x00000000 /* 50 baud */ -#define BAUD75 0x00010000 /* 75 baud */ -#define BAUD110 0x00020000 /* 110 baud */ -#define BAUD114 0x00030000 /* 134 baud */ -#define BAUD150 0x00040000 /* 150 baud */ -#define BAUD300 0x00050000 /* 300 baud */ -#define BAUD600 0x00060000 /* 600 baud */ -#define BAUD1200 0x00070000 /* 1200 baud */ -#define BAUD1800 0x00080000 /* 1800 baud */ -#define BAUD2000 0x00090000 /* 2000 baud */ -#define BAUD2400 0x000A0000 /* 2400 baud */ -#define BAUD3600 0x000B0000 /* 3600 baud */ -#define BAUD4800 0x000C0000 /* 4800 baud */ -#define BAUD7200 0x000D0000 /* 7200 baud */ -#define BAUD9600 0x000E0000 /* 9600 baud */ -#define BAUD19200 0x000F0000 /* 19200 baud */ +#define SNS_NUB50 0x00800000 /* Zero N/U */ +#define SNS_NUB51 0x00400000 /* Zero N/U */ +#define SNS_RINGCR 0x00200000 /* Ring or wakeup character recognition 0=enb, 1=dis */ +#define SNS_DIAGL 0x00100000 /* Set diagnostic loopback */ +#define SNS_BAUD 0x000F0000 /* Baud rate bits 4-7 */ +#define BAUD50 0x00000000 /* 50 baud */ +#define BAUD75 0x00010000 /* 75 baud */ +#define BAUD110 0x00020000 /* 110 baud */ +#define BAUD114 0x00030000 /* 134 baud */ +#define BAUD150 0x00040000 /* 150 baud */ +#define BAUD300 0x00050000 /* 300 baud */ +#define BAUD600 0x00060000 /* 600 baud */ +#define BAUD1200 0x00070000 /* 1200 baud */ +#define BAUD1800 0x00080000 /* 1800 baud */ +#define BAUD2000 0x00090000 /* 2000 baud */ +#define BAUD2400 0x000A0000 /* 2400 baud */ +#define BAUD3600 0x000B0000 /* 3600 baud */ +#define BAUD4800 0x000C0000 /* 4800 baud */ +#define BAUD7200 0x000D0000 /* 7200 baud */ +#define BAUD9600 0x000E0000 /* 9600 baud */ +#define BAUD19200 0x000F0000 /* 19200 baud */ /* Sense byte 6 Firmware ID, Revision Level */ -#define SNS_FID 0x00006200 /* ID part 1 */ +#define SNS_FID 0x00006200 /* ID part 1 */ /* Sense byte 7 Firmware ID, Revision Level */ -#define SNS_REV 0x0000004f /* ID part 2 plus 4 bit rev # */ +#define SNS_REV 0x0000004f /* ID part 2 plus 4 bit rev # */ /* ACE information in u4 */ -#define ACE_WAKE 0x0000FF00 /* 8 bit wake-up character */ +#define ACE_WAKE 0x0000FF00 /* 8 bit wake-up character */ /* in u5 packs sense byte 0,1 and 3 */ /* Sense byte 0 */ -#define SNS_CMDREJ 0x80000000 /* Command reject */ -#define SNS_INTVENT 0x40000000 /* Unit intervention required */ +#define SNS_CMDREJ 0x80000000 /* Command reject */ +#define SNS_INTVENT 0x40000000 /* Unit intervention required */ /* sense byte 3 */ -#define SNS_RDY 0x80 /* device ready */ -#define SNS_ONLN 0x40 /* device online */ -#define SNS_DSR 0x04 /* data set ready */ +#define SNS_RDY 0x80 /* device ready */ +#define SNS_ONLN 0x40 /* device online */ +#define SNS_DSR 0x04 /* data set ready */ /* u6 */ -uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); -uint8 com_haltio(uint16 addr); -void com_ini(UNIT *, t_bool); -void coml_ini(UNIT *, t_bool); -t_stat com_reset(DEVICE *); -t_stat com_attach(UNIT *, CONST char *); -t_stat com_detach(UNIT *); -t_stat comc_srv(UNIT *uptr); -t_stat como_srv(UNIT *uptr); -t_stat comi_srv(UNIT *uptr); -t_stat com_reset(DEVICE *dptr); -t_stat com_attach(UNIT *uptr, CONST char *cptr); -t_stat com_detach(UNIT *uptr); -void com_reset_ln(int32 ln); -const char *com_description(DEVICE *dptr); /* device description */ +uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); +uint8 com_haltio(uint16 addr); +void com_ini(UNIT *, t_bool); +void coml_ini(UNIT *, t_bool); +t_stat com_reset(DEVICE *); +t_stat com_attach(UNIT *, CONST char *); +t_stat com_detach(UNIT *); +t_stat comc_srv(UNIT *uptr); +t_stat como_srv(UNIT *uptr); +t_stat comi_srv(UNIT *uptr); +t_stat com_reset(DEVICE *dptr); +t_stat com_attach(UNIT *uptr, CONST char *cptr); +t_stat com_detach(UNIT *uptr); +void com_reset_ln(int32 ln); +const char *com_description(DEVICE *dptr); /* device description */ /* COM data structures - com_chp COM channel program information - com_dev COM device descriptor - com_unit COM unit descriptor - com_reg COM register list - com_mod COM modifieers list + com_chp COM channel program information + com_dev COM device descriptor + com_unit COM unit descriptor + com_reg COM register list + com_mod COM modifieers list */ //#define COM_UNITS 2 #define COM_UNITS 1 /* channel program information */ -CHANP com_chp[COM_UNITS] = {0}; +CHANP com_chp[COM_UNITS] = {0}; /* dummy mux for 16 lines */ -MTAB com_mod[] = { +MTAB com_mod[] = { {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, &show_dev_addr, NULL}, {MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", &tmxr_dscln, NULL, &com_desc}, {UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &tmxr_show_summ, (void *) &com_desc}, @@ -245,30 +245,30 @@ MTAB com_mod[] = { { 0 } }; -UNIT com_unit[] = { - {UDATA(&comi_srv, UNIT_ATTABLE, 0), COM_WAIT, UNIT_ADDR(0x0000)}, /* 0 */ +UNIT com_unit[] = { + {UDATA(&comi_srv, UNIT_ATTABLE, 0), COM_WAIT, UNIT_ADDR(0x0000)}, /* 0 */ }; //DIB com_dib = {NULL, com_startcmd, NULL, NULL, com_ini, com_unit, com_chp, COM_UNITS, 0x0f, 0x7e00, 0, 0, 0}; -DIB com_dib = { - NULL, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ - com_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ - NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ - NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ - com_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ - com_unit, /* UNIT* units */ /* Pointer to units structure */ - com_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ - COM_UNITS, /* uint8 numunits */ /* number of units defined */ - 0x0f, /* uint8 mask */ /* 16 devices - device mask */ - 0x7E00, /* uint16 chan_addr */ /* parent channel address */ - 0, /* uint32 chan_fifo_in */ /* fifo input index */ - 0, /* uint32 chan_fifo_out */ /* fifo output index */ - 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ +DIB com_dib = { + NULL, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ + com_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ + NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ + NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ + com_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ + com_unit, /* UNIT* units */ /* Pointer to units structure */ + com_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + COM_UNITS, /* uint8 numunits */ /* number of units defined */ + 0x0f, /* uint8 mask */ /* 16 devices - device mask */ + 0x7E00, /* uint16 chan_addr */ /* parent channel address */ + 0, /* uint32 chan_fifo_in */ /* fifo input index */ + 0, /* uint32 chan_fifo_out */ /* fifo output index */ + 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ }; -REG com_reg[] = { +REG com_reg[] = { { BRDATAD (STA, com_sta, 16, 8, COM_LINES, "status buffers, lines 0 to 8") }, { BRDATAD (RBUF, com_rbuf, 16, 8, COM_LINES, "input buffer, lines 0 to 8") }, { BRDATAD (XBUF, com_xbuf, 16, 8, COM_LINES, "output buffer, lines 0 to 8") }, @@ -279,29 +279,29 @@ REG com_reg[] = { }; /* devices for channel 0x7ecx */ -DEVICE com_dev = { +DEVICE com_dev = { "COMC", com_unit, com_reg, com_mod, COM_UNITS, 8, 15, 1, 8, 8, &tmxr_ex, &tmxr_dep, &com_reset, NULL, &com_attach, &com_detach, &com_dib, DEV_NET | DEV_DISABLE | DEV_DEBUG, 0, dev_debug, - NULL, NULL, NULL, NULL, NULL, &com_description + NULL, NULL, NULL, NULL, NULL, &com_description }; /* COML data structures - coml_dev COM device descriptor - coml_unit COM unit descriptor - coml_reg COM register list - coml_mod COM modifieers list + coml_dev COM device descriptor + coml_unit COM unit descriptor + coml_reg COM register list + coml_mod COM modifieers list */ #define UNIT_COML UNIT_ATTABLE|UNIT_DISABLE|UNIT_ATT //#define UNIT_COML UNIT_ATTABLE|UNIT_DISABLE /* channel program information */ -CHANP coml_chp[COM_LINES*2] = {0}; +CHANP coml_chp[COM_LINES*2] = {0}; -UNIT coml_unit[] = { - /* 0-7 is input, 8-f is output */ +UNIT coml_unit[] = { + /* 0-7 is input, 8-f is output */ {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC0)}, /* 0 */ {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC1)}, /* 1 */ {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC2)}, /* 2 */ @@ -321,26 +321,26 @@ UNIT coml_unit[] = { }; //DIB coml_dib = { NULL, com_startcmd, NULL, NULL, NULL, coml_ini, coml_unit, coml_chp, COM_LINES*2, 0x0f, 0x7E00}; -DIB coml_dib = { - NULL, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ - com_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ - NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ - NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ - coml_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ - coml_unit, /* UNIT* units */ /* Pointer to units structure */ - coml_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ - COM_LINES*2, /* uint8 numunits */ /* number of units defined */ - 0x0f, /* uint8 mask */ /* 16 devices - device mask */ - 0x7E00, /* uint16 chan_addr */ /* parent channel address */ +DIB coml_dib = { + NULL, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ + com_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ + NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ + NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ + coml_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ + coml_unit, /* UNIT* units */ /* Pointer to units structure */ + coml_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + COM_LINES*2, /* uint8 numunits */ /* number of units defined */ + 0x0f, /* uint8 mask */ /* 16 devices - device mask */ + 0x7E00, /* uint16 chan_addr */ /* parent channel address */ }; -REG coml_reg[] = { - { URDATA (TIME, coml_unit[0].wait, 10, 24, 0, COM_LINES, REG_NZ + PV_LEFT) }, - { NULL } +REG coml_reg[] = { + { URDATA (TIME, coml_unit[0].wait, 10, 24, 0, COM_LINES, REG_NZ + PV_LEFT) }, + { NULL } }; -MTAB coml_mod[] = { +MTAB coml_mod[] = { { TT_MODE, TT_MODE_UC, "UC", "UC", NULL }, { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, @@ -354,271 +354,271 @@ MTAB coml_mod[] = { { 0 } }; -DEVICE coml_dev = { - "COML", coml_unit, coml_reg, coml_mod, - COM_LINES*2, 10, 31, 1, 8, 8, - NULL, NULL, &com_reset, - NULL, NULL, NULL, +DEVICE coml_dev = { + "COML", coml_unit, coml_reg, coml_mod, + COM_LINES*2, 10, 31, 1, 8, 8, + NULL, NULL, &com_reset, + NULL, NULL, NULL, &coml_dib, DEV_DISABLE | DEV_DEBUG, 0, dev_debug, - NULL, NULL, NULL, NULL, NULL, &com_description + NULL, NULL, NULL, NULL, NULL, &com_description }; /* 8-line serial routines */ void coml_ini(UNIT *uptr, t_bool f) { - int unit; - uint16 chsa; + int unit; + uint16 chsa; - unit = uptr - coml_unit; /* unit # */ - chsa = GET_UADDR(uptr->u3); /* get channel/sub-addr */ + unit = uptr - coml_unit; /* unit # */ + chsa = GET_UADDR(uptr->u3); /* get channel/sub-addr */ - /* maybe do someting here on master channel init */ - uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ + /* maybe do someting here on master channel init */ + uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ } /* 8-line serial routines */ void com_ini(UNIT *uptr, t_bool f) { - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = find_dev_from_unit(uptr); - sim_debug(DEBUG_CMD, &com_dev, "COM init device %s controller 0x7e00\n", dptr->name); - sim_activate(uptr, 1000); /* time increment */ + sim_debug(DEBUG_CMD, &com_dev, "COM init device %s controller 0x7e00\n", dptr->name); + sim_activate(uptr, 1000); /* time increment */ } /* called from sel32_chan to start an I/O operation */ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { - DEVICE *dptr = find_dev_from_unit(uptr); - int unit = (uptr - dptr->units); - uint8 ch; + DEVICE *dptr = find_dev_from_unit(uptr); + int unit = (uptr - dptr->units); + uint8 ch; - if ((uptr->u3 & COM_MSK) != 0) { /* is unit busy */ - return SNS_BSY; /* yes, return busy */ - } + if ((uptr->u3 & COM_MSK) != 0) { /* is unit busy */ + return SNS_BSY; /* yes, return busy */ + } sim_debug(DEBUG_CMD, dptr, "CMD unit %x chan %x cmd %x", unit, chan, cmd); - /* process the commands */ - switch (cmd & 0xFF) { - case COM_INCH: /* 00 */ /* INCH command */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: CMD INCH\n", chan); - return SNS_CHNEND|SNS_DEVEND; /* all is well */ - break; + /* process the commands */ + switch (cmd & 0xFF) { + case COM_INCH: /* 00 */ /* INCH command */ + sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: CMD INCH\n", chan); + return SNS_CHNEND|SNS_DEVEND; /* all is well */ + break; - /* write commands must use address 8-f */ - case COM_WR: /* 0x01 */ /* Write command */ - case COM_WRSCM: /* 0x05 */ /* Write w/sub channel monitor */ - case COM_WRHFC: /* 0x0D */ /* Write w/hardware flow control */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd WRITE %x\n", chan, cmd); + /* write commands must use address 8-f */ + case COM_WR: /* 0x01 */ /* Write command */ + case COM_WRSCM: /* 0x05 */ /* Write w/sub channel monitor */ + case COM_WRHFC: /* 0x0D */ /* Write w/hardware flow control */ + sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd WRITE %x\n", chan, cmd); - uptr->u3 &= LMASK; /* leave only chsa */ - uptr->u3 |= (cmd & COM_MSK); /* save command */ - uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ - sim_activate(uptr, 150); /* TRY 08-13-18 */ - return 0; /* no status change */ - break; + uptr->u3 &= LMASK; /* leave only chsa */ + uptr->u3 |= (cmd & COM_MSK); /* save command */ + uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ + sim_activate(uptr, 150); /* TRY 08-13-18 */ + return 0; /* no status change */ + break; - /* read commands must use address 0-7 */ - /* DSR must be set when a read command is issued, else it is unit check */ - /* bit 1-3 (ASP) of command has more definition */ - /* bit 1 A=1 ASCII control character detect (7-char mode only) */ - /* bit 2 S=1 Special character detect (7-char mode only) */ - /* bit 3 P=1 Purge input buffer */ - case COM_RD: /* 0x02 */ /* Read command */ - case COM_RDECHO: /* 0x06 */ /* Read command w/ECHO */ - case 0x46: /* 0x46 */ /* Read command w/ECHO & ASCII */ - case 0x56: /* 0x56 */ /* Read command w/ECHO & ASCII & Purge input */ - /* if bit 0 set for COM_RDFC, use DTR for flow, else use RTS for flow control */ - case COM_RDFC: /* 0x0A */ /* Read command w/flow control */ - case COM_RDHFC: /* 0x8E */ /* Read command w/hardware flow control only */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd read\n", chan); - uptr->u3 &= LMASK; /* leave only chsa */ - uptr->u3 |= (cmd & COM_MSK); /* save command */ - if ((cmd & 0x06) == COM_RDECHO) /* echo command? */ - uptr->u3 |= COM_EKO; /* save echo status */ - uptr->u3 |= COM_READ; /* show read mode */ - uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ - return 0; - break; + /* read commands must use address 0-7 */ + /* DSR must be set when a read command is issued, else it is unit check */ + /* bit 1-3 (ASP) of command has more definition */ + /* bit 1 A=1 ASCII control character detect (7-char mode only) */ + /* bit 2 S=1 Special character detect (7-char mode only) */ + /* bit 3 P=1 Purge input buffer */ + case COM_RD: /* 0x02 */ /* Read command */ + case COM_RDECHO: /* 0x06 */ /* Read command w/ECHO */ + case 0x46: /* 0x46 */ /* Read command w/ECHO & ASCII */ + case 0x56: /* 0x56 */ /* Read command w/ECHO & ASCII & Purge input */ + /* if bit 0 set for COM_RDFC, use DTR for flow, else use RTS for flow control */ + case COM_RDFC: /* 0x0A */ /* Read command w/flow control */ + case COM_RDHFC: /* 0x8E */ /* Read command w/hardware flow control only */ + sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd read\n", chan); + uptr->u3 &= LMASK; /* leave only chsa */ + uptr->u3 |= (cmd & COM_MSK); /* save command */ + if ((cmd & 0x06) == COM_RDECHO) /* echo command? */ + uptr->u3 |= COM_EKO; /* save echo status */ + uptr->u3 |= COM_READ; /* show read mode */ + uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ + return 0; + break; - case COM_NOP: /* 0x03 */ /* NOP has do nothing */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x NOP\n", chan, cmd); - uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ - return SNS_CHNEND|SNS_DEVEND; /* good return */ - break; + case COM_NOP: /* 0x03 */ /* NOP has do nothing */ + sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x NOP\n", chan, cmd); + uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ + return SNS_CHNEND|SNS_DEVEND; /* good return */ + break; - case COM_SNS: /* 0x04 */ /* Sense (8 bytes) */ - com_lstat[unit][0] = 0; /* Clear status wd 0 */ - com_lstat[unit][1] = 0; /* Clear status wd 1 */ - /* value 4 is Data Set Ready */ - /* value 5 is Data carrier detected n/u */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: unit %x Cmd Sense %02x\n", chan, unit, uptr->u5); + case COM_SNS: /* 0x04 */ /* Sense (8 bytes) */ + com_lstat[unit][0] = 0; /* Clear status wd 0 */ + com_lstat[unit][1] = 0; /* Clear status wd 1 */ + /* value 4 is Data Set Ready */ + /* value 5 is Data carrier detected n/u */ + sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: unit %x Cmd Sense %02x\n", chan, unit, uptr->u5); /* Sense byte 0 */ -//#define SNS_CMDREJ 0x80000000 /* Command reject */ -//#define SNS_INTVENT 0x40000000 /* Unit intervention required (N/U) */ -//#define SNS_BOCHK 0x20000000 /* Bus out check (IOP parity error */ -//#define SNS_EQUIPCK 0x10000000 /* Equipment check (device error) */ -//#define SNS_DATACK 0x08000000 /* Data check */ -//#define SNS_OVERRN 0x04000000 /* Overrun (N/U) */ -//#define SNS_NUB01 0x02000000 /* Zero (N/U) */ -//#define SNS_NUB02 0x01000000 /* Zero (N/U) */ -// com_lstat[unit][0] |= (SNS_ASCIICD | SNS_SPCLCD|SNS_RING); /* set char detect status */ -// com_lstat[unit][0] |= (SNS_ASCIICD | SNS_SPCLCD); /* set char detect status */ -// com_lstat[unit][0] |= (SNS_RING); /* set char detect status */ - ch = (com_lstat[unit][0] >> 24) & 0xff; - chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ +//#define SNS_CMDREJ 0x80000000 /* Command reject */ +//#define SNS_INTVENT 0x40000000 /* Unit intervention required (N/U) */ +//#define SNS_BOCHK 0x20000000 /* Bus out check (IOP parity error */ +//#define SNS_EQUIPCK 0x10000000 /* Equipment check (device error) */ +//#define SNS_DATACK 0x08000000 /* Data check */ +//#define SNS_OVERRN 0x04000000 /* Overrun (N/U) */ +//#define SNS_NUB01 0x02000000 /* Zero (N/U) */ +//#define SNS_NUB02 0x01000000 /* Zero (N/U) */ +// com_lstat[unit][0] |= (SNS_ASCIICD | SNS_SPCLCD|SNS_RING); /* set char detect status */ +// com_lstat[unit][0] |= (SNS_ASCIICD | SNS_SPCLCD); /* set char detect status */ +// com_lstat[unit][0] |= (SNS_RING); /* set char detect status */ + ch = (com_lstat[unit][0] >> 24) & 0xff; + chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ /* Sense byte 1 */ -//#define SNS_ASCIICD 0x00800000 /* ASCII control char detected interrupt */ -//#define SNS_SPCLCD 0x00400000 /* Special char detected interrupt */ -//#define SNS_ETX 0x00200000 /* ETX interrupt */ -//#define SNS_BREAK 0x00100000 /* X BREAK interrupt */ -//#define SNS_ACEFE 0x00080000 /* ACE framing error interrupt */ -//#define SNS_ACEPEI 0x00040000 /* ACE parity error interrupt */ -//#define SNS_ACEOVR 0x00020000 /* ACE overrun error interrupt */ -//#define SNS_RING 0x00010000 /* X Ring character interrupt */ - com_lstat[unit][0] |= (SNS_RING); /* set char detect status */ - com_lstat[unit][0] |= (SNS_ASCIICD); /* set char detect status */ - ch = (com_lstat[unit][0] >> 16) & 0xff; - chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ +//#define SNS_ASCIICD 0x00800000 /* ASCII control char detected interrupt */ +//#define SNS_SPCLCD 0x00400000 /* Special char detected interrupt */ +//#define SNS_ETX 0x00200000 /* ETX interrupt */ +//#define SNS_BREAK 0x00100000 /* X BREAK interrupt */ +//#define SNS_ACEFE 0x00080000 /* ACE framing error interrupt */ +//#define SNS_ACEPEI 0x00040000 /* ACE parity error interrupt */ +//#define SNS_ACEOVR 0x00020000 /* ACE overrun error interrupt */ +//#define SNS_RING 0x00010000 /* X Ring character interrupt */ + com_lstat[unit][0] |= (SNS_RING); /* set char detect status */ + com_lstat[unit][0] |= (SNS_ASCIICD); /* set char detect status */ + ch = (com_lstat[unit][0] >> 16) & 0xff; + chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ /* Sense byte 2 Modem status */ -//#define SNS_RLSDS 0x00008000 /* S Received line signal detect status */ -//#define SNS_RINGST 0x00004000 /* Ring indicator line status */ -//#define SNS_DSRS 0x00002000 /* C DSR Data set ready line status */ -//#define SNS_CTSS 0x00001000 /* C CTS Clear to send line status */ -//#define SNS_DELTA 0x00000800 /* BS Delta receive line signal detect failure interrupt */ -//#define SNS_MRING 0x00000400 /* X RI Modem ring interrupt */ -//#define SNS_DELDSR 0x00000200 /* BS Delta data set ready interrupt */ -//#define SNS_DELCLR 0x00000100 /* B Delta data set CTS failure interrupt */ - com_lstat[unit][0] |= (SNS_CTSS|SNS_DSRS); /* set CTS & DSR status */ - com_lstat[unit][0] |= (SNS_MRING); /* set char detect status */ - ch = (com_lstat[unit][0] >> 8) & 0xff; - chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ +//#define SNS_RLSDS 0x00008000 /* S Received line signal detect status */ +//#define SNS_RINGST 0x00004000 /* Ring indicator line status */ +//#define SNS_DSRS 0x00002000 /* C DSR Data set ready line status */ +//#define SNS_CTSS 0x00001000 /* C CTS Clear to send line status */ +//#define SNS_DELTA 0x00000800 /* BS Delta receive line signal detect failure interrupt */ +//#define SNS_MRING 0x00000400 /* X RI Modem ring interrupt */ +//#define SNS_DELDSR 0x00000200 /* BS Delta data set ready interrupt */ +//#define SNS_DELCLR 0x00000100 /* B Delta data set CTS failure interrupt */ + com_lstat[unit][0] |= (SNS_CTSS|SNS_DSRS); /* set CTS & DSR status */ + com_lstat[unit][0] |= (SNS_MRING); /* set char detect status */ + ch = (com_lstat[unit][0] >> 8) & 0xff; + chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ /* Sense byte 3 Modem Control/Operation status */ -//#define SNS_HALFD 0x00000080 /* Half-duplix operation set */ -//#define SNS_MRINGE 0x00000040 /* Modem ring enabled (1) */ -//#define SNS_ACEDEF 0x00000020 /* ACE parameters defined */ -//#define SNS_DIAGM 0x00000010 /* Diagnostic mode set */ -//#define SNS_AUXOL2 0x00000008 /* Auxiliary output level 2 */ -//#define SNS_AUXOL1 0x00000004 /* Auxiliary output level 1 */ -//#define SNS_RTS 0x00000002 /* RTS Request to send set */ -//#define SNS_DTR 0x00000001 /* DTR Data terminal ready set */ -// com_lstat[unit][0] |= (SNS_RTS|SNS_DTR); /* set RTS & DTR status */ - com_lstat[unit][0] |= (SNS_DTR); /* set DTR status */ - ch = (com_lstat[unit][0] >> 0) & 0xff; +//#define SNS_HALFD 0x00000080 /* Half-duplix operation set */ +//#define SNS_MRINGE 0x00000040 /* Modem ring enabled (1) */ +//#define SNS_ACEDEF 0x00000020 /* ACE parameters defined */ +//#define SNS_DIAGM 0x00000010 /* Diagnostic mode set */ +//#define SNS_AUXOL2 0x00000008 /* Auxiliary output level 2 */ +//#define SNS_AUXOL1 0x00000004 /* Auxiliary output level 1 */ +//#define SNS_RTS 0x00000002 /* RTS Request to send set */ +//#define SNS_DTR 0x00000001 /* DTR Data terminal ready set */ +// com_lstat[unit][0] |= (SNS_RTS|SNS_DTR); /* set RTS & DTR status */ + com_lstat[unit][0] |= (SNS_DTR); /* set DTR status */ + ch = (com_lstat[unit][0] >> 0) & 0xff; - chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ - ch = (com_lstat[unit][1] >> 24) & 0xff; - chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ - ch = (com_lstat[unit][1] >> 16) & 0xff; - chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ - ch = (com_lstat[unit][1] >> 8) & 0xff; - chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ - ch = (com_lstat[unit][1] >> 0) & 0xff; - chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ - sim_debug(DEBUG_CMD, &com_dev, - "com_startcmd Cmd SENSE return chan %x u5-status %x ls0 %x ls1 %x\n", - chan, uptr->u5, com_lstat[unit][0], com_lstat[unit][1]); - return SNS_CHNEND|SNS_DEVEND; /* good return */ - break; + chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ + ch = (com_lstat[unit][1] >> 24) & 0xff; + chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ + ch = (com_lstat[unit][1] >> 16) & 0xff; + chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ + ch = (com_lstat[unit][1] >> 8) & 0xff; + chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ + ch = (com_lstat[unit][1] >> 0) & 0xff; + chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ + sim_debug(DEBUG_CMD, &com_dev, + "com_startcmd Cmd SENSE return chan %x u5-status %x ls0 %x ls1 %x\n", + chan, uptr->u5, com_lstat[unit][0], com_lstat[unit][1]); + return SNS_CHNEND|SNS_DEVEND; /* good return */ + break; - case COM_DEFSC: /* 0x0B */ /* Define special char */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x DEFSC\n", chan, cmd); - chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char */ - uptr->u5 = ~SNS_RTS; /* Request to send not ready */ - return SNS_CHNEND|SNS_DEVEND; /* good return */ - break; + case COM_DEFSC: /* 0x0B */ /* Define special char */ + sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x DEFSC\n", chan, cmd); + chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char */ + uptr->u5 = ~SNS_RTS; /* Request to send not ready */ + return SNS_CHNEND|SNS_DEVEND; /* good return */ + break; - case COM_RRTS: /* 0x1B */ /* Reset RTS */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x RRTS\n", chan, cmd); - uptr->u5 &= ~SNS_RTS; /* Request to send not ready */ - return SNS_CHNEND|SNS_DEVEND; /* good return */ - break; + case COM_RRTS: /* 0x1B */ /* Reset RTS */ + sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x RRTS\n", chan, cmd); + uptr->u5 &= ~SNS_RTS; /* Request to send not ready */ + return SNS_CHNEND|SNS_DEVEND; /* good return */ + break; - case COM_SRTS: /* 0x1F */ /* Set RTS */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x SRTS\n", chan, cmd); - uptr->u5 |= SNS_RTS; /* Requestd to send ready */ - return SNS_CHNEND|SNS_DEVEND; /* good return */ - break; + case COM_SRTS: /* 0x1F */ /* Set RTS */ + sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x SRTS\n", chan, cmd); + uptr->u5 |= SNS_RTS; /* Requestd to send ready */ + return SNS_CHNEND|SNS_DEVEND; /* good return */ + break; - case COM_RBRK: /* 0x33 */ /* Reset BREAK */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x RBRK\n", chan, cmd); - uptr->u5 &= ~SNS_BREAK; /* Request to send not ready */ - return SNS_CHNEND|SNS_DEVEND; /* good return */ - break; + case COM_RBRK: /* 0x33 */ /* Reset BREAK */ + sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x RBRK\n", chan, cmd); + uptr->u5 &= ~SNS_BREAK; /* Request to send not ready */ + return SNS_CHNEND|SNS_DEVEND; /* good return */ + break; - case COM_SBRK: /* 0x37 */ /* Set BREAK */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x SBRK\n", chan, cmd); - uptr->u5 |= SNS_BREAK; /* Requestd to send ready */ - return SNS_CHNEND|SNS_DEVEND; /* good return */ - break; + case COM_SBRK: /* 0x37 */ /* Set BREAK */ + sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x SBRK\n", chan, cmd); + uptr->u5 |= SNS_BREAK; /* Requestd to send ready */ + return SNS_CHNEND|SNS_DEVEND; /* good return */ + break; - case COM_RDTR: /* 0x13 */ /* Reset DTR (ADVR) */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x DTR\n", chan, cmd); - uptr->u5 &= ~SNS_DTR; /* Data terminal not ready */ - return SNS_CHNEND|SNS_DEVEND; /* good return */ - break; + case COM_RDTR: /* 0x13 */ /* Reset DTR (ADVR) */ + sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x DTR\n", chan, cmd); + uptr->u5 &= ~SNS_DTR; /* Data terminal not ready */ + return SNS_CHNEND|SNS_DEVEND; /* good return */ + break; - case COM_SDTR: /* 0x17 */ /* Set DTR (ADVF) */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x NOP\n", chan, cmd); - uptr->u5 |= SNS_DTR; /* Data terminal ready */ - return SNS_CHNEND|SNS_DEVEND; /* good return */ - break; + case COM_SDTR: /* 0x17 */ /* Set DTR (ADVF) */ + sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x NOP\n", chan, cmd); + uptr->u5 |= SNS_DTR; /* Data terminal ready */ + return SNS_CHNEND|SNS_DEVEND; /* good return */ + break; #if 0 /* ACE byte 0 Modem Control/Operation status */ /* stored in u4 bytes 0-3 */ -#define SNS_HALFD 0x80000000 /* Half-duplix operation set */ -#define SNS_MRINGE 0x40000000 /* Modem ring enabled */ -#define SNS_ACEFP 0x20000000 /* Forced parity 0=odd, 1=even */ -#define SNS_ACEP 0x10000000 /* Parity 0=odd, 1=even */ -#define SNS_ACEPE 0x08000000 /* Parity enable 0=dis, 1=enb */ -#define SNS_ACESTOP 0x04000000 /* Stop bit 0=1, 1=1.5 or 2 */ -#define SNS_ACECLEN 0x02000000 /* Character length 00=5, 01=6, 11=7, 11=8 */ -#define SNS_ACECL2 0x01000000 /* 2nd bit for above */ +#define SNS_HALFD 0x80000000 /* Half-duplix operation set */ +#define SNS_MRINGE 0x40000000 /* Modem ring enabled */ +#define SNS_ACEFP 0x20000000 /* Forced parity 0=odd, 1=even */ +#define SNS_ACEP 0x10000000 /* Parity 0=odd, 1=even */ +#define SNS_ACEPE 0x08000000 /* Parity enable 0=dis, 1=enb */ +#define SNS_ACESTOP 0x04000000 /* Stop bit 0=1, 1=1.5 or 2 */ +#define SNS_ACECLEN 0x02000000 /* Character length 00=5, 01=6, 11=7, 11=8 */ +#define SNS_ACECL2 0x01000000 /* 2nd bit for above */ /* ACE byte 1 Baud rate */ -#define SNS_NUB50 0x00800000 /* Zero N/U */ -#define SNS_NUB51 0x00400000 /* Zero N/U */ -#define SNS_RINGCR 0x00200000 /* Ring or wakeup character recognition 0=enb, 1=dis */ -#define SNS_DIAGL 0x00100000 /* Set diagnostic loopback */ -#define SNS_BAUD 0x000F0000 /* Baud rate bits 4-7 */ -#define BAUD50 0x00000000 /* 50 baud */ -#define BAUD75 0x00010000 /* 75 baud */ -#define BAUD110 0x00020000 /* 110 baud */ -#define BAUD114 0x00030000 /* 134 baud */ -#define BAUD150 0x00040000 /* 150 baud */ -#define BAUD300 0x00050000 /* 300 baud */ -#define BAUD600 0x00060000 /* 600 baud */ -#define BAUD1200 0x00070000 /* 1200 baud */ -#define BAUD1800 0x00080000 /* 1800 baud */ -#define BAUD2000 0x00090000 /* 2000 baud */ -#define BAUD2400 0x000A0000 /* 2400 baud */ -#define BAUD3600 0x000B0000 /* 3600 baud */ -#define BAUD4800 0x000C0000 /* 4800 baud */ -#define BAUD7200 0x000D0000 /* 7200 baud */ -#define BAUD9600 0x000E0000 /* 9600 baud */ -#define BAUD19200 0x000F0000 /* 19200 baud */ +#define SNS_NUB50 0x00800000 /* Zero N/U */ +#define SNS_NUB51 0x00400000 /* Zero N/U */ +#define SNS_RINGCR 0x00200000 /* Ring or wakeup character recognition 0=enb, 1=dis */ +#define SNS_DIAGL 0x00100000 /* Set diagnostic loopback */ +#define SNS_BAUD 0x000F0000 /* Baud rate bits 4-7 */ +#define BAUD50 0x00000000 /* 50 baud */ +#define BAUD75 0x00010000 /* 75 baud */ +#define BAUD110 0x00020000 /* 110 baud */ +#define BAUD114 0x00030000 /* 134 baud */ +#define BAUD150 0x00040000 /* 150 baud */ +#define BAUD300 0x00050000 /* 300 baud */ +#define BAUD600 0x00060000 /* 600 baud */ +#define BAUD1200 0x00070000 /* 1200 baud */ +#define BAUD1800 0x00080000 /* 1800 baud */ +#define BAUD2000 0x00090000 /* 2000 baud */ +#define BAUD2400 0x000A0000 /* 2400 baud */ +#define BAUD3600 0x000B0000 /* 3600 baud */ +#define BAUD4800 0x000C0000 /* 4800 baud */ +#define BAUD7200 0x000D0000 /* 7200 baud */ +#define BAUD9600 0x000E0000 /* 9600 baud */ +#define BAUD19200 0x000F0000 /* 19200 baud */ /* ACE byte 2 Wake-up character */ -#define ACE_WAKE 0x0000FF00 /* 8 bit wake-up character */ +#define ACE_WAKE 0x0000FF00 /* 8 bit wake-up character */ #endif - case COM_SACE: /* 0xff */ /* Set ACE parameters (3 chars) */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x SACE\n", chan, cmd); - chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char 0 */ - uptr->u4 = ((uint32)ch)<<24; /* byte 0 of ACE data */ - chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char 1 */ - uptr->u4 |= ((uint32)ch)<<16; /* byte 1 of ACE data */ - chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char 2 */ - uptr->u4 |= ((uint32)ch)<<8; /* byte 2 of ACE data */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x SACE bytes %x\n", chan, cmd, uptr->u4); - return SNS_CHNEND|SNS_DEVEND; /* good return */ - break; + case COM_SACE: /* 0xff */ /* Set ACE parameters (3 chars) */ + sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x SACE\n", chan, cmd); + chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char 0 */ + uptr->u4 = ((uint32)ch)<<24; /* byte 0 of ACE data */ + chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char 1 */ + uptr->u4 |= ((uint32)ch)<<16; /* byte 1 of ACE data */ + chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char 2 */ + uptr->u4 |= ((uint32)ch)<<8; /* byte 2 of ACE data */ + sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd %x SACE bytes %x\n", chan, cmd, uptr->u4); + return SNS_CHNEND|SNS_DEVEND; /* good return */ + break; - default: /* invalid command */ - uptr->u5 |= SNS_CMDREJ; /* command rejected */ - sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd Invald %x status %02x\n", chan, cmd, uptr->u5); - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ - break; + default: /* invalid command */ + uptr->u5 |= SNS_CMDREJ; /* command rejected */ + sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %x: Cmd Invald %x status %02x\n", chan, cmd, uptr->u5); + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ + break; } if (uptr->u5 & 0xff) @@ -632,192 +632,192 @@ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) */ t_stat comi_srv(UNIT *uptr) { - uint8 ch; - int32 newln, ln, c; - uint16 chsa = GET_UADDR(uptr->u3); /* get channel/sub-addr */ - int cmd = uptr->u3 & 0xff; - uint32 cln = (uptr - coml_unit) & 0x7; /* use line # 0-7 for 8-15 */ - UNIT *comlp; + uint8 ch; + int32 newln, ln, c; + uint16 chsa = GET_UADDR(uptr->u3); /* get channel/sub-addr */ + int cmd = uptr->u3 & 0xff; + uint32 cln = (uptr - coml_unit) & 0x7; /* use line # 0-7 for 8-15 */ + UNIT *comlp; - ln = uptr - com_unit; /* line # */ - if ((com_unit[COMC].flags & UNIT_ATT) == 0){ /* attached? */ - return SCPE_OK; - } - newln = tmxr_poll_conn(&com_desc); /* look for connect */ - if (newln >= 0) { /* rcv enb pending? */ - uint16 chsa = GET_UADDR(coml_unit[newln].u3); /* get channel/sub-addr */ - int chan = ((chsa >> 8) & 0x7f); /* get the channel number */ - UNIT *comlp = coml_unit+ln; /* get uptr for coml line */ - int cmd = comlp->u3 & 0xff; /* get the active cmd */ -//fprintf(stderr, "comi_srv poll chsa %x new line %x\r\n", chsa, newln); - com_ldsc[newln].rcve = 1; /* enable rcv */ - com_ldsc[newln+8].xmte = 1; /* enable xmt for output line */ - com_sta[newln] &= ~COML_REP; /* clr pending */ - /* send attention to OS here for this channel */ - /* need to get chsa here for the channel */ -//fprintf(stderr, "comi_srv chsa %x chan %x\r\n", chsa, chan); - set_devwake(chsa, SNS_ATTN|SNS_DEVEND|SNS_CHNEND); /* tell user */ + ln = uptr - com_unit; /* line # */ + if ((com_unit[COMC].flags & UNIT_ATT) == 0){ /* attached? */ + return SCPE_OK; } - /* poll all devices for input */ - tmxr_poll_rx(&com_desc); /* poll for input */ - for (ln = 0; ln < COM_NUMLIN; ln++) { /* loop thru lines */ - UNIT *comlp = coml_unit+ln; /* get uptr for coml line */ - int cmd = comlp->u3 & 0xff; /* get the active cmd */ - uint16 chsa = GET_UADDR(comlp->u3); /* get channel/sub-addr */ - if (com_ldsc[ln].conn) { /* connected? */ - if ((c = tmxr_getc_ln(&com_ldsc[ln]))) { /* get char */ + newln = tmxr_poll_conn(&com_desc); /* look for connect */ + if (newln >= 0) { /* rcv enb pending? */ + uint16 chsa = GET_UADDR(coml_unit[newln].u3); /* get channel/sub-addr */ + int chan = ((chsa >> 8) & 0x7f); /* get the channel number */ + UNIT *comlp = coml_unit+ln; /* get uptr for coml line */ + int cmd = comlp->u3 & 0xff; /* get the active cmd */ +//fprintf(stderr, "comi_srv poll chsa %x new line %x\r\n", chsa, newln); + com_ldsc[newln].rcve = 1; /* enable rcv */ + com_ldsc[newln+8].xmte = 1; /* enable xmt for output line */ + com_sta[newln] &= ~COML_REP; /* clr pending */ + /* send attention to OS here for this channel */ + /* need to get chsa here for the channel */ +//fprintf(stderr, "comi_srv chsa %x chan %x\r\n", chsa, chan); + set_devwake(chsa, SNS_ATTN|SNS_DEVEND|SNS_CHNEND); /* tell user */ + } + /* poll all devices for input */ + tmxr_poll_rx(&com_desc); /* poll for input */ + for (ln = 0; ln < COM_NUMLIN; ln++) { /* loop thru lines */ + UNIT *comlp = coml_unit+ln; /* get uptr for coml line */ + int cmd = comlp->u3 & 0xff; /* get the active cmd */ + uint16 chsa = GET_UADDR(comlp->u3); /* get channel/sub-addr */ + if (com_ldsc[ln].conn) { /* connected? */ + if ((c = tmxr_getc_ln(&com_ldsc[ln]))) { /* get char */ //fprintf(stderr, "comi_srv chsa %x input %x cmd %x\r\n", chsa, c, cmd); - ch = c; /* just the char */ - /* echo the char out */ - tmxr_putc_ln(&com_ldsc[ln], ch); /* output char */ - tmxr_poll_tx(&com_desc); /* poll xmt */ - if (c & SCPE_BREAK) /* break? */ - com_sta[ln] |= COML_RBP; /* set rcv brk */ - else { /* normal char */ - com_sta[ln] &= ~COML_RBP; /* clr rcv brk */ - c = sim_tt_inpcvt(c, TT_GET_MODE(coml_unit[ln].flags)); - com_rbuf[ln] = c; /* save char */ - if ((cmd & COM_RD) == COM_RD) { /* read active? */ - ch = c; /* clean the char */ - if (ch == '\n') /* convert newline */ - ch = '\r'; /* to C/R */ - /* write byte to memory */ - if (chan_write_byte(chsa, &ch)) { - /* done, reading chars */ + ch = c; /* just the char */ + /* echo the char out */ + tmxr_putc_ln(&com_ldsc[ln], ch); /* output char */ + tmxr_poll_tx(&com_desc); /* poll xmt */ + if (c & SCPE_BREAK) /* break? */ + com_sta[ln] |= COML_RBP; /* set rcv brk */ + else { /* normal char */ + com_sta[ln] &= ~COML_RBP; /* clr rcv brk */ + c = sim_tt_inpcvt(c, TT_GET_MODE(coml_unit[ln].flags)); + com_rbuf[ln] = c; /* save char */ + if ((cmd & COM_RD) == COM_RD) { /* read active? */ + ch = c; /* clean the char */ + if (ch == '\n') /* convert newline */ + ch = '\r'; /* to C/R */ + /* write byte to memory */ + if (chan_write_byte(chsa, &ch)) { + /* done, reading chars */ //fprintf(stderr, "comi_srv chsa %x input %x complete cmd %x\r\n", chsa, c, cmd); - comlp->u3 &= LMASK; /* nothing left, clear cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ - } else { - /* more to go, continue */ + comlp->u3 &= LMASK; /* nothing left, clear cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ + } else { + /* more to go, continue */ //fprintf(stderr, "comi_srv chsa %x input %x cnt %x cmd %x\r\n", chsa, c, cmd); - if (ch == '\r') { /* see if done */ - comlp->u3 &= LMASK; /* nothing left, clear cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ - } - } - } - else { - /* see if user hit the wakeup key */ - if (((comlp->u4 & ACE_WAKE) >> 8) == ch) { - /* send attention to OS here for this channel */ - /* need to get chsa here for the channel */ -// fprintf(stderr, "comi_srv WAKEUP chsa %x ch %x wake %x\r\n", chsa, ch, (comlp->u4 & ACE_WAKE)>>8); - set_devwake(chsa, SNS_ATTN|SNS_DEVEND|SNS_CHNEND); /* tell user */ - } - } - } /* end else char */ - } /* end if char */ - } /* end if conn */ - else - com_sta[ln] &= ~COML_RBP; /* disconnected */ - } /* end for */ - return sim_clock_coschedule(uptr, 200); /* continue poll */ + if (ch == '\r') { /* see if done */ + comlp->u3 &= LMASK; /* nothing left, clear cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ + } + } + } + else { + /* see if user hit the wakeup key */ + if (((comlp->u4 & ACE_WAKE) >> 8) == ch) { + /* send attention to OS here for this channel */ + /* need to get chsa here for the channel */ +// fprintf(stderr, "comi_srv WAKEUP chsa %x ch %x wake %x\r\n", chsa, ch, (comlp->u4 & ACE_WAKE)>>8); + set_devwake(chsa, SNS_ATTN|SNS_DEVEND|SNS_CHNEND); /* tell user */ + } + } + } /* end else char */ + } /* end if char */ + } /* end if conn */ + else + com_sta[ln] &= ~COML_RBP; /* disconnected */ + } /* end for */ + return sim_clock_coschedule(uptr, 200); /* continue poll */ } /* Unit service - output transfers */ t_stat como_srv(UNIT *uptr) { - uint16 chsa = GET_UADDR(uptr->u3); /* get channel/sub-addr */ - uint32 ln = (uptr - coml_unit) & 0x7; /* use line # 0-7 for 8-15 */ - uint32 done; - int cmd = uptr->u3 & 0xff; /* get active cmd */ - uint8 ch; + uint16 chsa = GET_UADDR(uptr->u3); /* get channel/sub-addr */ + uint32 ln = (uptr - coml_unit) & 0x7; /* use line # 0-7 for 8-15 */ + uint32 done; + int cmd = uptr->u3 & 0xff; /* get active cmd */ + uint8 ch; //fprintf(stderr, "como_srv entry 1 chsa %x line %x cmd %x\r\n", chsa, ln, cmd); - if (cmd) { - /* get a user byte from memory */ - done = chan_read_byte(chsa, &ch); /* get byte from memory */ + if (cmd) { + /* get a user byte from memory */ + done = chan_read_byte(chsa, &ch); /* get byte from memory */ #if 0 - if (!done) - fprintf(stderr, "como_srv mem_read chsa %x line %x char %c %x\r\n", chsa, ln, ch, ch); - else - uptr->u3 &= LMASK; /* leave only chsa */ + if (!done) + fprintf(stderr, "como_srv mem_read chsa %x line %x char %c %x\r\n", chsa, ln, ch, ch); + else + uptr->u3 &= LMASK; /* leave only chsa */ #else - if (done) - uptr->u3 &= LMASK; /* leave only chsa */ + if (done) + uptr->u3 &= LMASK; /* leave only chsa */ #endif - } else - return SCPE_OK; + } else + return SCPE_OK; - if (com_dev.flags & DEV_DIS) { /* disabled */ + if (com_dev.flags & DEV_DIS) { /* disabled */ //fprintf(stderr, "como_srv chsa %x line %x DEV_DIS set\r\n", chsa, ln); - if (done) { + if (done) { //fprintf(stderr, "como_srv Write DONE %d status %x\r\n", ln, SNS_CHNEND|SNS_DEVEND); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ - } - return SCPE_OK; /* return */ - } + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ + } + return SCPE_OK; /* return */ + } //fprintf(stderr, "como_srv poll chsa %x line %x\r\n", chsa, ln); - if (com_ldsc[ln].conn) { /* connected? */ - if (com_ldsc[ln].xmte) { /* xmt enabled? */ - if (done) { /* are we done writing */ + if (com_ldsc[ln].conn) { /* connected? */ + if (com_ldsc[ln].xmte) { /* xmt enabled? */ + if (done) { /* are we done writing */ endit: - uptr->u3 &= LMASK; /* nothing left, command complete */ - sim_debug(DEBUG_CMD, &com_dev, "com_srvo write %d: chnend|devend\n", ln); + uptr->u3 &= LMASK; /* nothing left, command complete */ + sim_debug(DEBUG_CMD, &com_dev, "com_srvo write %d: chnend|devend\n", ln); //fprintf(stderr, "como_srv Write DONE %d status %x\r\n", ln, SNS_CHNEND|SNS_DEVEND); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ - return SCPE_OK; - } - /* send the next char out */ - tmxr_putc_ln(&com_ldsc[ln], ch); /* output char */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ + return SCPE_OK; + } + /* send the next char out */ + tmxr_putc_ln(&com_ldsc[ln], ch); /* output char */ //fprintf(stderr, "como_srv writing char %c to ln %d\r\n", ch, ln); - tmxr_poll_tx(&com_desc); /* poll xmt */ - sim_activate(uptr, uptr->wait); /* wait */ - return SCPE_OK; - } else { /* buf full */ - if (done) /* are we done writing */ - goto endit; /* done */ - /* just dump the char */ -// /* xmt disabled, just wait around */ + tmxr_poll_tx(&com_desc); /* poll xmt */ + sim_activate(uptr, uptr->wait); /* wait */ + return SCPE_OK; + } else { /* buf full */ + if (done) /* are we done writing */ + goto endit; /* done */ + /* just dump the char */ +// /* xmt disabled, just wait around */ //fprintf(stderr, "como_srv Write dumping %x on line %d\r\n", ch, ln); - tmxr_poll_tx(&com_desc); /* poll xmt */ -//?? sim_activate(uptr, coml_unit[ln].wait); /* wait */ - sim_activate(uptr, uptr->wait); /* wait */ - return SCPE_OK; - } - } else { - /* not connected, so dump char on ground */ - if (done) { + tmxr_poll_tx(&com_desc); /* poll xmt */ +//?? sim_activate(uptr, coml_unit[ln].wait); /* wait */ + sim_activate(uptr, uptr->wait); /* wait */ + return SCPE_OK; + } + } else { + /* not connected, so dump char on ground */ + if (done) { //fprintf(stderr, "como_srv Write dump DONE %d status %x\r\n", ln, SNS_CHNEND|SNS_DEVEND); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ - uptr->u3 &= LMASK; /* nothing left, command complete */ - } - sim_activate(uptr, uptr->wait); /* wait */ - return SCPE_OK; - } + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ + uptr->u3 &= LMASK; /* nothing left, command complete */ + } + sim_activate(uptr, uptr->wait); /* wait */ + return SCPE_OK; + } } /* Reset routine */ t_stat com_reset (DEVICE *dptr) { - int32 i; + int32 i; - if (com_dev.flags & DEV_DIS) /* master disabled? */ - com_dev.flags |= DEV_DIS; /* disable lines */ - else - com_dev.flags &= ~DEV_DIS; - if (com_unit[COMC].flags & UNIT_ATT) /* master att? */ - sim_clock_coschedule(&com_unit[0], 200); /* activate */ - for (i = 0; i < COM_LINES; i++) /* reset lines */ - com_reset_ln(i); - return SCPE_OK; + if (com_dev.flags & DEV_DIS) /* master disabled? */ + com_dev.flags |= DEV_DIS; /* disable lines */ + else + com_dev.flags &= ~DEV_DIS; + if (com_unit[COMC].flags & UNIT_ATT) /* master att? */ + sim_clock_coschedule(&com_unit[0], 200); /* activate */ + for (i = 0; i < COM_LINES; i++) /* reset lines */ + com_reset_ln(i); + return SCPE_OK; } /* attach master unit */ t_stat com_attach(UNIT *uptr, CONST char *cptr) { - uint16 chsa = GET_UADDR(com_unit[COMC].u3); /* get channel/subaddress */ - t_stat r; + uint16 chsa = GET_UADDR(com_unit[COMC].u3); /* get channel/subaddress */ + t_stat r; - chsa = GET_UADDR(com_unit[COMC].u3); /* get channel/subaddress */ + chsa = GET_UADDR(com_unit[COMC].u3); /* get channel/subaddress */ //fprintf(stderr, "com_attach chsa %x\r\n", chsa); - r = tmxr_attach(&com_desc, uptr, cptr); /* attach */ - if (r != SCPE_OK) /* error? */ - return r; /* return error */ - sim_activate(uptr, 0); /* start poll at once */ + r = tmxr_attach(&com_desc, uptr, cptr); /* attach */ + if (r != SCPE_OK) /* error? */ + return r; /* return error */ + sim_activate(uptr, 0); /* start poll at once */ //fprintf(stderr, "com_attach chsa %x\r\n", chsa); return SCPE_OK; } @@ -825,25 +825,25 @@ t_stat com_attach(UNIT *uptr, CONST char *cptr) /* detach master unit */ t_stat com_detach(UNIT *uptr) { - int32 i; - t_stat r; + int32 i; + t_stat r; - r = tmxr_detach(&com_desc, uptr); /* detach */ - for (i = 0; i < COM_LINES; i++) /* disable rcv */ - com_reset_ln(i); /* reset the line */ - sim_cancel(uptr); /* stop poll, cancel timer */ - return r; + r = tmxr_detach(&com_desc, uptr); /* detach */ + for (i = 0; i < COM_LINES; i++) /* disable rcv */ + com_reset_ln(i); /* reset the line */ + sim_cancel(uptr); /* stop poll, cancel timer */ + return r; } /* Reset an individual line */ void com_reset_ln (int32 ln) { - sim_cancel(&coml_unit[ln]); - com_sta[ln] = 0; - com_rbuf[ln] = 0; /* clear read buffer */ - com_xbuf[ln] = 0; /* clear write buffer */ - com_ldsc[ln].rcve = 0; - return; + sim_cancel(&coml_unit[ln]); + com_sta[ln] = 0; + com_rbuf[ln] = 0; /* clear read buffer */ + com_xbuf[ln] = 0; /* clear write buffer */ + com_ldsc[ln].rcve = 0; + return; } t_stat com_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) @@ -885,15 +885,15 @@ fprintf (st, " sim> SHOW COMC STATISTICS show statistics for active connec fprintf (st, " sim> SET COMLn DISCONNECT disconnects the specified line.\n"); fprintf (st, "\nThe additional terminals do not support save and restore. All open connections\n"); fprintf (st, "are lost when the simulator shuts down or DCI is detached.\n"); - fprint_set_help (st, dptr); - fprint_show_help (st, dptr); - return SCPE_OK; + fprint_set_help (st, dptr); + fprint_show_help (st, dptr); + return SCPE_OK; } /* description of controller */ const char *com_description (DEVICE *dptr) { - return "SEL 32 8-Line async communications controller"; + return "SEL 32 8-Line async communications controller"; } #endif diff --git a/SEL32/sel32_con.c b/SEL32/sel32_con.c index cf670c3..853888f 100644 --- a/SEL32/sel32_con.c +++ b/SEL32/sel32_con.c @@ -35,112 +35,112 @@ #ifdef NUM_DEVS_CON -extern t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); -extern t_stat show_dev_addr(FILE *st, UNIT * uptr, int32 v, CONST void *desc); -extern void chan_end(uint16 chan, uint8 flags); -extern int chan_read_byte(uint16 chan, uint8 *data); -extern int chan_write_byte(uint16 chan, uint8 *data); -extern void set_devattn(uint16 addr, uint8 flags); -extern void post_extirq(void); -extern uint32 attention_trap; /* set when trap is requested */ -extern void set_devwake(uint16 addr, uint8 flags); +extern t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +extern t_stat show_dev_addr(FILE *st, UNIT * uptr, int32 v, CONST void *desc); +extern void chan_end(uint16 chan, uint8 flags); +extern int chan_read_byte(uint16 chan, uint8 *data); +extern int chan_write_byte(uint16 chan, uint8 *data); +extern void set_devattn(uint16 addr, uint8 flags); +extern void post_extirq(void); +extern uint32 attention_trap; /* set when trap is requested */ +extern void set_devwake(uint16 addr, uint8 flags); /* Held in u3 is the device command and status */ -#define CON_INCH 0x00 /* Initialize channel command */ -#define CON_WR 0x01 /* Write console */ -#define CON_RD 0x02 /* Read console */ -#define CON_NOP 0x03 /* No op command */ -#define CON_SNS 0x04 /* Sense command */ -#define CON_ECHO 0x0a /* Read with Echo */ -#define CON_CON 0x1f /* connect line */ -#define CON_DIS 0x23 /* disconnect line */ -#define CON_RWD 0x37 /* TOF and write line */ +#define CON_INCH 0x00 /* Initialize channel command */ +#define CON_WR 0x01 /* Write console */ +#define CON_RD 0x02 /* Read console */ +#define CON_NOP 0x03 /* No op command */ +#define CON_SNS 0x04 /* Sense command */ +#define CON_ECHO 0x0a /* Read with Echo */ +#define CON_CON 0x1f /* connect line */ +#define CON_DIS 0x23 /* disconnect line */ +#define CON_RWD 0x37 /* TOF and write line */ -#define CON_MSK 0xff /* Command mask */ +#define CON_MSK 0xff /* Command mask */ /* Status held in u3 */ /* controller/unit address in upper 16 bits */ -#define CON_INPUT 0x100 /* Input ready for unit */ -#define CON_CR 0x200 /* Output at beginning of line */ -#define CON_REQ 0x400 /* Request key pressed */ -#define CON_EKO 0x800 /* Echo input character */ -#define CON_OUTPUT 0x1000 /* Output ready for unit */ -#define CON_READ 0x2000 /* Read mode selected */ +#define CON_INPUT 0x100 /* Input ready for unit */ +#define CON_CR 0x200 /* Output at beginning of line */ +#define CON_REQ 0x400 /* Request key pressed */ +#define CON_EKO 0x800 /* Echo input character */ +#define CON_OUTPUT 0x1000 /* Output ready for unit */ +#define CON_READ 0x2000 /* Read mode selected */ /* Input buffer pointer held in u4 */ /* in u5 packs sense byte 0,1 and 3 */ /* Sense byte 0 */ -#define SNS_CMDREJ 0x80000000 /* Command reject */ -#define SNS_INTVENT 0x40000000 /* Unit intervention required */ +#define SNS_CMDREJ 0x80000000 /* Command reject */ +#define SNS_INTVENT 0x40000000 /* Unit intervention required */ /* sense byte 3 */ -#define SNS_RDY 0x80 /* device ready */ -#define SNS_ONLN 0x40 /* device online */ -//#define SNS_DSR 0x04 /* data set ready */ -#define SNS_DSR 0x08 /* data set ready */ -#define SNS_DCD 0x04 /* data carrier detect */ +#define SNS_RDY 0x80 /* device ready */ +#define SNS_ONLN 0x40 /* device online */ +//#define SNS_DSR 0x04 /* data set ready */ +#define SNS_DSR 0x08 /* data set ready */ +#define SNS_DCD 0x04 /* data carrier detect */ /* std devices. data structures - con_dev Console device descriptor - con_unit Console unit descriptor - con_reg Console register list - con_mod Console modifiers list + con_dev Console device descriptor + con_unit Console unit descriptor + con_reg Console register list + con_mod Console modifiers list */ struct _con_data { - uint8 ibuff[145]; /* Input line buffer */ - uint8 incnt; /* char count */ + uint8 ibuff[145]; /* Input line buffer */ + uint8 incnt; /* char count */ } con_data[NUM_UNITS_CON]; -uint32 atbuf=0; /* attention buffer */ +uint32 atbuf=0; /* attention buffer */ /* forward definitions */ uint8 con_startcmd(UNIT *, uint16, uint8); -void con_ini(UNIT *, t_bool); -t_stat con_srvi(UNIT *); -t_stat con_srvo(UNIT *); -t_stat con_reset(DEVICE *); -t_stat con_attach(UNIT *, char *); -t_stat con_detach(UNIT *); +void con_ini(UNIT *, t_bool); +t_stat con_srvi(UNIT *); +t_stat con_srvo(UNIT *); +t_stat con_reset(DEVICE *); +t_stat con_attach(UNIT *, char *); +t_stat con_detach(UNIT *); /* channel program information */ -CHANP con_chp[NUM_UNITS_CON] = {0}; +CHANP con_chp[NUM_UNITS_CON] = {0}; -MTAB con_mod[] = { - {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, &show_dev_addr, NULL}, - {0} +MTAB con_mod[] = { + {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, &show_dev_addr, NULL}, + {0} }; -UNIT con_unit[] = { - {UDATA(con_srvi, UNIT_ATT, 0), 0, UNIT_ADDR(0x7EFC)}, /* Input */ - {UDATA(con_srvo, UNIT_ATT, 0), 0, UNIT_ADDR(0x7EFD)}, /* Output */ +UNIT con_unit[] = { + {UDATA(con_srvi, UNIT_ATT, 0), 0, UNIT_ADDR(0x7EFC)}, /* Input */ + {UDATA(con_srvo, UNIT_ATT, 0), 0, UNIT_ADDR(0x7EFD)}, /* Output */ }; -//DIB con_dib = {NULL, con_startcmd, NULL, NULL, NULL, con_ini, con_unit, con_chp, NUM_UNITS_CON, 0xf, 0x7e00, 0, 0, 0}; -DIB con_dib = { - NULL, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Start I/O */ - con_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ - NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ - NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ - con_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ - con_unit, /* UNIT* units */ /* Pointer to units structure */ - con_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ - NUM_UNITS_CON, /* uint8 numunits */ /* number of units defined */ - 0x0f, /* uint8 mask */ /* 2 devices - device mask */ - 0x7e00, /* uint16 chan_addr */ /* parent channel address */ - 0, /* uint32 chan_fifo_in */ /* fifo input index */ - 0, /* uint32 chan_fifo_out */ /* fifo output index */ - 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ +//DIB con_dib = {NULL, con_startcmd, NULL, NULL, NULL, con_ini, con_unit, con_chp, NUM_UNITS_CON, 0xf, 0x7e00, 0, 0, 0}; +DIB con_dib = { + NULL, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Start I/O */ + con_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ + NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ + NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ + con_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ + con_unit, /* UNIT* units */ /* Pointer to units structure */ + con_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NUM_UNITS_CON, /* uint8 numunits */ /* number of units defined */ + 0x0f, /* uint8 mask */ /* 2 devices - device mask */ + 0x7e00, /* uint16 chan_addr */ /* parent channel address */ + 0, /* uint32 chan_fifo_in */ /* fifo input index */ + 0, /* uint32 chan_fifo_out */ /* fifo output index */ + 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ }; -DEVICE con_dev = { - "CON", con_unit, NULL, con_mod, - NUM_UNITS_CON, 8, 15, 1, 8, 8, - NULL, NULL, NULL, NULL, NULL, NULL, - &con_dib, DEV_UADDR|DEV_DISABLE|DEV_DEBUG, 0, dev_debug +DEVICE con_dev = { + "CON", con_unit, NULL, con_mod, + NUM_UNITS_CON, 8, 15, 1, 8, 8, + NULL, NULL, NULL, NULL, NULL, NULL, + &con_dib, DEV_UADDR|DEV_DISABLE|DEV_DEBUG, 0, dev_debug }; /* @@ -148,91 +148,91 @@ DEVICE con_dev = { */ /* initialize the console chan/unit */ void con_ini(UNIT *uptr, t_bool f) { - int unit = (uptr - con_unit); /* unit 0 */ - DEVICE *dptr = find_dev_from_unit(uptr); + int unit = (uptr - con_unit); /* unit 0 */ + DEVICE *dptr = find_dev_from_unit(uptr); - con_data[unit].incnt = 0; /* no input data */ - uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ - sim_activate(uptr, 1000); /* time increment */ + con_data[unit].incnt = 0; /* no input data */ + uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ + sim_activate(uptr, 1000); /* time increment */ } /* start an I/O operation */ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { - int unit = (uptr - con_unit); /* unit 0,1 */ - uint8 ch; + int unit = (uptr - con_unit); /* unit 0,1 */ + uint8 ch; - if ((uptr->u3 & CON_MSK) != 0) /* is unit busy */ - return SNS_BSY; /* yes, return busy */ + if ((uptr->u3 & CON_MSK) != 0) /* is unit busy */ + return SNS_BSY; /* yes, return busy */ - /* process the commands */ - switch (cmd & 0xFF) { - case CON_INCH: /* 0x00 */ /* INCH command */ - sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %x: Cmd INCH\n", chan); - return SNS_CHNEND|SNS_DEVEND; /* all is well */ - break; + /* process the commands */ + switch (cmd & 0xFF) { + case CON_INCH: /* 0x00 */ /* INCH command */ + sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %x: Cmd INCH\n", chan); + return SNS_CHNEND|SNS_DEVEND; /* all is well */ + break; - case CON_RWD: /* 0x37 */ /* TOF and write line */ - case CON_WR: /* 0x01 */ /* Write command */ - /* if input requested for output device, give error */ - if (unit == 0) { - uptr->u5 |= SNS_CMDREJ; /* command rejected */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ - } - uptr->u3 &= LMASK; /* leave only chsa */ - uptr->u3 |= (cmd & CON_MSK); /* save command */ - uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ - sim_activate(uptr, 20); /* TRY 06-09-18 */ - return 0; /* no status change */ - break; + case CON_RWD: /* 0x37 */ /* TOF and write line */ + case CON_WR: /* 0x01 */ /* Write command */ + /* if input requested for output device, give error */ + if (unit == 0) { + uptr->u5 |= SNS_CMDREJ; /* command rejected */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ + } + uptr->u3 &= LMASK; /* leave only chsa */ + uptr->u3 |= (cmd & CON_MSK); /* save command */ + uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ + sim_activate(uptr, 20); /* TRY 06-09-18 */ + return 0; /* no status change */ + break; - case CON_RD: /* Read command */ - case CON_ECHO: /* Read command w/ECHO */ - /* if output requested for input device, give error */ - if (unit == 1) { - uptr->u5 |= SNS_CMDREJ; /* command rejected */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ - } - uptr->u3 &= LMASK; /* leave only chsa */ - uptr->u3 |= (cmd & CON_MSK); /* save command */ - if (cmd == CON_ECHO) /* echo command? */ - uptr->u3 |= CON_EKO; /* save echo status */ - uptr->u3 |= CON_READ; /* show read mode */ - atbuf = 0; /* reset attention buffer */ - uptr->u4 = 0; /* no I/O yet */ - uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ - return 0; - break; + case CON_RD: /* Read command */ + case CON_ECHO: /* Read command w/ECHO */ + /* if output requested for input device, give error */ + if (unit == 1) { + uptr->u5 |= SNS_CMDREJ; /* command rejected */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ + } + uptr->u3 &= LMASK; /* leave only chsa */ + uptr->u3 |= (cmd & CON_MSK); /* save command */ + if (cmd == CON_ECHO) /* echo command? */ + uptr->u3 |= CON_EKO; /* save echo status */ + uptr->u3 |= CON_READ; /* show read mode */ + atbuf = 0; /* reset attention buffer */ + uptr->u4 = 0; /* no I/O yet */ + uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ + return 0; + break; - case CON_NOP: /* NOP has do nothing */ - uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ - return SNS_CHNEND|SNS_DEVEND; /* good return */ - break; + case CON_NOP: /* NOP has do nothing */ + uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ + return SNS_CHNEND|SNS_DEVEND; /* good return */ + break; - case CON_CON: /* Connect, return Data Set ready */ - sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %x: Cmd %x NOP\n", chan, cmd); - uptr->u5 |= (SNS_DSR|SNS_DCD); /* Data set ready, Data Carrier detected */ - return SNS_CHNEND|SNS_DEVEND; /* good return */ - break; + case CON_CON: /* Connect, return Data Set ready */ + sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %x: Cmd %x NOP\n", chan, cmd); + uptr->u5 |= (SNS_DSR|SNS_DCD); /* Data set ready, Data Carrier detected */ + return SNS_CHNEND|SNS_DEVEND; /* good return */ + break; - case CON_DIS: /* NOP has do nothing */ - sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %x: Cmd %x NOP\n", chan, cmd); - uptr->u5 &= ~(SNS_DSR|SNS_DCD); /* Data set not ready */ - return SNS_CHNEND|SNS_DEVEND; /* good return */ - break; + case CON_DIS: /* NOP has do nothing */ + sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %x: Cmd %x NOP\n", chan, cmd); + uptr->u5 &= ~(SNS_DSR|SNS_DCD); /* Data set not ready */ + return SNS_CHNEND|SNS_DEVEND; /* good return */ + break; - case CON_SNS: /* Sense */ - sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %x: Cmd Sense %02x\n", chan, uptr->u5); - /* value 4 is Data Set Ready */ - /* value 5 is Data carrier detected n/u */ - ch = uptr->u5; /* status */ - chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ - return SNS_CHNEND|SNS_DEVEND; /* good return */ - break; + case CON_SNS: /* Sense */ + sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %x: Cmd Sense %02x\n", chan, uptr->u5); + /* value 4 is Data Set Ready */ + /* value 5 is Data carrier detected n/u */ + ch = uptr->u5; /* status */ + chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ + return SNS_CHNEND|SNS_DEVEND; /* good return */ + break; - default: /* invalid command */ - uptr->u5 |= SNS_CMDREJ; /* command rejected */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ - break; + default: /* invalid command */ + uptr->u5 |= SNS_CMDREJ; /* command rejected */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ + break; } if (uptr->u5 & (~(SNS_RDY|SNS_ONLN|SNS_DSR))) @@ -242,128 +242,128 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { /* Handle output transfers for console */ t_stat con_srvo(UNIT *uptr) { - uint16 chsa = GET_UADDR(uptr->u3); - int unit = (uptr - con_unit); /* unit 0 is read, unit 1 is write */ - int cmd = uptr->u3 & CON_MSK; - uint8 ch; + uint16 chsa = GET_UADDR(uptr->u3); + int unit = (uptr - con_unit); /* unit 0 is read, unit 1 is write */ + int cmd = uptr->u3 & CON_MSK; + uint8 ch; - if ((cmd == CON_WR) || (cmd == CON_RWD)) { - /* Write to device */ - if (chan_read_byte(chsa, &ch)) { /* get byte from memory */ - uptr->u3 &= LMASK; /* nothing left, command complete */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ - } else { - sim_debug(DEBUG_CMD, &con_dev, "con_srvo write %d: putch %0.2x %c\n", unit, ch, ch); - sim_putchar(ch); /* output next char to device */ - sim_activate(uptr, 20); /* TRY 07-18-18 */ - } - } + if ((cmd == CON_WR) || (cmd == CON_RWD)) { + /* Write to device */ + if (chan_read_byte(chsa, &ch)) { /* get byte from memory */ + uptr->u3 &= LMASK; /* nothing left, command complete */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ + } else { + sim_debug(DEBUG_CMD, &con_dev, "con_srvo write %d: putch %0.2x %c\n", unit, ch, ch); + sim_putchar(ch); /* output next char to device */ + sim_activate(uptr, 20); /* TRY 07-18-18 */ + } + } return SCPE_OK; } /* Handle input transfers for console */ t_stat con_srvi(UNIT *uptr) { - uint16 chsa = GET_UADDR(uptr->u3); - int unit = (uptr - con_unit); /* unit 0 is read, unit 1 is write */ - int cmd = uptr->u3 & CON_MSK; - t_stat r = SCPE_ARG; /* Force error if not set */ - uint8 ch; - int i; + uint16 chsa = GET_UADDR(uptr->u3); + int unit = (uptr - con_unit); /* unit 0 is read, unit 1 is write */ + int cmd = uptr->u3 & CON_MSK; + t_stat r = SCPE_ARG; /* Force error if not set */ + uint8 ch; + int i; - switch (cmd) { + switch (cmd) { - case CON_RD: /* read from device */ - case CON_ECHO: /* read from device w/ECHO */ - if (uptr->u3 & CON_INPUT) { /* input waiting? */ - ch = con_data[unit].ibuff[uptr->u4++]; /* get char from read buffer */ - sim_debug(DEBUG_CMD, &con_dev, "con_srvi %d: read %02x\n", unit, ch); - if (chan_write_byte(chsa, &ch)) { /* write byte to memory */ - con_data[unit].incnt = 0; /* buffer empty */ - cmd = 0; /* no cmd either */ - uptr->u3 &= LMASK; /* nothing left, command complete */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ - } else { - if (uptr->u4 == con_data[unit].incnt) { /* read completed */ - con_data[unit].incnt = 0; /* buffer is empty */ - cmd = 0; /* no cmd either */ - uptr->u3 &= LMASK; /* nothing left, command complete */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ - } - } - } - break; - } + case CON_RD: /* read from device */ + case CON_ECHO: /* read from device w/ECHO */ + if (uptr->u3 & CON_INPUT) { /* input waiting? */ + ch = con_data[unit].ibuff[uptr->u4++]; /* get char from read buffer */ + sim_debug(DEBUG_CMD, &con_dev, "con_srvi %d: read %02x\n", unit, ch); + if (chan_write_byte(chsa, &ch)) { /* write byte to memory */ + con_data[unit].incnt = 0; /* buffer empty */ + cmd = 0; /* no cmd either */ + uptr->u3 &= LMASK; /* nothing left, command complete */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ + } else { + if (uptr->u4 == con_data[unit].incnt) { /* read completed */ + con_data[unit].incnt = 0; /* buffer is empty */ + cmd = 0; /* no cmd either */ + uptr->u3 &= LMASK; /* nothing left, command complete */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ + } + } + } + break; + } - /* poll for next input if reading or @@A sequence */ - r = sim_poll_kbd(); /* poll for ready */ - if (r & SCPE_KFLAG) { /* got a char */ - ch = r & 0377; /* drop any extra bits */ - if ((cmd == CON_RD) || (cmd == CON_ECHO)) { /* looking for input */ - atbuf = 0; /* reset attention buffer */ - if (ch == '\n') /* convert newline */ - ch = '\r'; /* make newline into carriage return */ - /* Handle end of buffer */ - switch (ch) { + /* poll for next input if reading or @@A sequence */ + r = sim_poll_kbd(); /* poll for ready */ + if (r & SCPE_KFLAG) { /* got a char */ + ch = r & 0377; /* drop any extra bits */ + if ((cmd == CON_RD) || (cmd == CON_ECHO)) { /* looking for input */ + atbuf = 0; /* reset attention buffer */ + if (ch == '\n') /* convert newline */ + ch = '\r'; /* make newline into carriage return */ + /* Handle end of buffer */ + switch (ch) { - case 0x7f: /* Delete */ - case '\b': /* backspace */ - if (con_data[unit].incnt != 0) { - con_data[unit].incnt--; - sim_putchar('\b'); - sim_putchar(' '); - sim_putchar('\b'); - } - break; - case 03: /* ^C */ - case 025: /* ^U clear line */ - for (i = con_data[unit].incnt; i> 0; i--) { - sim_putchar('\b'); - sim_putchar(' '); - sim_putchar('\b'); - } - con_data[unit].incnt = 0; - break; + case 0x7f: /* Delete */ + case '\b': /* backspace */ + if (con_data[unit].incnt != 0) { + con_data[unit].incnt--; + sim_putchar('\b'); + sim_putchar(' '); + sim_putchar('\b'); + } + break; + case 03: /* ^C */ + case 025: /* ^U clear line */ + for (i = con_data[unit].incnt; i> 0; i--) { + sim_putchar('\b'); + sim_putchar(' '); + sim_putchar('\b'); + } + con_data[unit].incnt = 0; + break; - case '\r': /* return */ - case '\n': /* newline */ - uptr->u3 |= CON_CR; /* C/R received */ - /* fall through */ - default: - if (con_data[unit].incnt < sizeof(con_data[unit].ibuff)) { - if (uptr->u3 & CON_EKO) /* ECHO requested */ - sim_putchar(ch); /* ECHO the char */ - con_data[unit].ibuff[con_data[unit].incnt++] = ch; - uptr->u3 |= CON_INPUT; /* we have a char available */ - } - break; - } - } else { - /* look for attention sequence '@@A' */ - if (ch == '@' || ch == 'A' || ch == 'a') { - if (ch == 'a') - ch = 'A'; - atbuf = (atbuf|ch)<<8; - sim_putchar(ch); /* ECHO the char */ - if (atbuf == 0x40404100) { - attention_trap = CONSOLEATN_TRAP; /* console attn (0xb4) */ - atbuf = 0; /* reset attention buffer */ - sim_putchar('\r'); /* return char */ - sim_putchar('\n'); /* line feed char */ - } - } else { - if (ch == '?') { - int chan = ((chsa >> 8) & 0x7f); /* get the channel number */ - /* set ring bit? */ - set_devwake(chsa, SNS_ATTN|SNS_DEVEND|SNS_CHNEND); /* tell user */ - } - } - } - } - if ((cmd == CON_RD) || (cmd == CON_ECHO)) /* looking for input */ - sim_activate(uptr, 200); /* keep going */ - else - sim_activate(uptr, 400); /* keep going */ - return SCPE_OK; + case '\r': /* return */ + case '\n': /* newline */ + uptr->u3 |= CON_CR; /* C/R received */ + /* fall through */ + default: + if (con_data[unit].incnt < sizeof(con_data[unit].ibuff)) { + if (uptr->u3 & CON_EKO) /* ECHO requested */ + sim_putchar(ch); /* ECHO the char */ + con_data[unit].ibuff[con_data[unit].incnt++] = ch; + uptr->u3 |= CON_INPUT; /* we have a char available */ + } + break; + } + } else { + /* look for attention sequence '@@A' */ + if (ch == '@' || ch == 'A' || ch == 'a') { + if (ch == 'a') + ch = 'A'; + atbuf = (atbuf|ch)<<8; + sim_putchar(ch); /* ECHO the char */ + if (atbuf == 0x40404100) { + attention_trap = CONSOLEATN_TRAP; /* console attn (0xb4) */ + atbuf = 0; /* reset attention buffer */ + sim_putchar('\r'); /* return char */ + sim_putchar('\n'); /* line feed char */ + } + } else { + if (ch == '?') { + int chan = ((chsa >> 8) & 0x7f); /* get the channel number */ + /* set ring bit? */ + set_devwake(chsa, SNS_ATTN|SNS_DEVEND|SNS_CHNEND); /* tell user */ + } + } + } + } + if ((cmd == CON_RD) || (cmd == CON_ECHO)) /* looking for input */ + sim_activate(uptr, 200); /* keep going */ + else + sim_activate(uptr, 400); /* keep going */ + return SCPE_OK; } #endif diff --git a/SEL32/sel32_cpu.c b/SEL32/sel32_cpu.c index e8f42d8..c995b8d 100644 --- a/SEL32/sel32_cpu.c +++ b/SEL32/sel32_cpu.c @@ -1,4114 +1,4114 @@ -/* sel32_cpu.c: Sel 32 CPU simulator - - Copyright (c) 2018, James C. Bevier - Portions provided by Richard Cornwell and other SIMH contributers - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - JAMES C. BEVIER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -*/ - -#include "sel32_defs.h" - -/* 32/7x PSW/PSD Mode Trap/Interrupt Priorities */ -/* Relative Logical Int Vect TCW IOCD Description */ -/* Priority Priority Location Addr Addr */ -/* 0 0F4 Power Fail Safe Trap */ -/* 1 0FC System Override Trap (Not Used) */ -/* 2 0E8* Memory Parity Trap */ -/* 3 190 Nonpresent Memory Trap */ -/* 4 194 Undefined Instruction Trap */ -/* 5 198 Privilege Violation Trap */ -/* 6 180 Supervisor Call Trap (SVC) */ -/* 7 184 Machine Check Trap */ -/* 8 188 System Check Trap */ -/* 9 18C Map Fault Trap */ -/* A Not Used */ -/* B Not Used */ -/* C Not Used */ -/* D Not Used */ -/* E 0E4 Block Mode Timeout Trap */ -/* F 1A4* Arithmetic Exception Trap */ -/* 10 00 0F0 Power Fail Safe Interrupt */ -/* 11 01 0F8 System Override Interrupt */ -/* 12 12 0E8* Memory Parity Trap */ -/* 13 13 0EC Attention Interrupt */ -/* 14 14 140 100 700 I/O Channel 0 interrupt */ -/* 15 15 144 104 708 I/O Channel 1 interrupt */ -/* 16 16 148 108 710 I/O Channel 2 interrupt */ -/* 17 17 14C 10C 718 I/O Channel 3 interrupt */ -/* 18 18 150 110 720 I/O Channel 4 interrupt */ -/* 19 19 154 114 728 I/O Channel 5 interrupt */ -/* 1A 1A 158 118 730 I/O Channel 6 interrupt */ -/* 1B 1B 15C 11C 738 I/O Channel 7 interrupt */ -/* 1C 1C 160 120 740 I/O Channel 8 interrupt */ -/* 1D 1D 164 124 748 I/O Channel 9 interrupt */ -/* 1E 1E 168 128 750 I/O Channel A interrupt */ -/* 1F 1F 16C 12C 758 I/O Channel B interrupt */ -/* 20 20 170 130 760 I/O Channel C interrupt */ -/* 21 21 174 134 768 I/O Channel D interrupt */ -/* 22 22 178 138 770 I/O Channel E interrupt */ -/* 23 23 17C 13C 778 I/O Channel F interrupt */ -/* 24 24 190* Nonpresent Memory Trap */ -/* 25 25 194* Undefined Instruction Trap */ -/* 26 26 198* Privlege Violation Trap */ -/* 27 27 19C Call Monitor Interrupt */ -/* 28 28 1A0 Real-Time Clock Interrupt */ -/* 29 29 1A4* Arithmetic Exception Interrupt */ -/* 2A 2A 1A8 External/Software Interrupt */ -/* 2B 2B 1AC External/Software Interrupt */ -/* 2C 2C 1B0 External/Software Interrupt */ -/* 2D 2D 1B4 External/Software Interrupt */ -/* 2E 2E 1B8 External/Software Interrupt */ -/* 2F 2F 1BC External/Software Interrupt */ -/* 30 30 1C0 External/Software Interrupt */ -/* 31 31 1C4 External/Software Interrupt */ -/* THRU THRU THRU THRU */ -/* 77 77 2DC External/Software Interrupt */ -/* 78 2E0 End of IPU Processing Trap (CPU) */ -/* 79 2E4 Start IPU Processing Trap (IPU) */ -/* 7A 2E8 Supervisor Call Trap (IPU) */ -/* 7B 2EC Error Trap (IPU) */ -/* 7C 2F0 Call Monitor Trap (IPU) */ -/* 7D 7D 2F4 Stop IPU Processing Trap (IPU) */ -/* 7E 7E 2F8 External/Software Interrupt */ -/* 7F 7F 2FC External/Software Interrupt */ - -/* Concept 32 PSD Mode Trap/Interrupt Priorities */ -/* Relative|Logical |Int Vect|TCW |IOCD|Description */ -/* Priority|Priority|Location|Addr|Addr */ -/* - 080 Power Fail Safe Trap */ -/* - 084 Power On Trap */ -/* - 088 Memory Parity Trap */ -/* - 08C Nonpresent Memory Trap */ -/* - 090 Undefined Instruction Trap */ -/* - 094 Privilege Violation Trap */ -/* - 098 Supervisor Call Trap (SVC) */ -/* - 09C Machine Check Trap */ -/* - 0A0 System Check Trap */ -/* - 0A4 Map Fault Trap */ -/* - 0A8 Undefined IPU Instruction Trap */ -/* - 0AC Signal CPU or Signal IPU Trap */ -/* - 0B0 Address Specification Trap */ -/* - 0B4 Console Attention Trap */ -/* - 0B8 Privlege Mode Halt Trap */ -/* - 0BC Arithmetic Exception Trap */ -/* */ -/* 0 00 100 External/software Interrupt 0 */ -/* 1 01 104 External/software Interrupt 1 */ -/* 2 02 108 External/software Interrupt 2 */ -/* 3 03 10C External/software Interrupt 3 */ -/* 4 04 110 704 700 I/O Channel 0 interrupt */ -/* 5 05 114 70C 708 I/O Channel 1 interrupt */ -/* 6 06 118 714 710 I/O Channel 2 interrupt */ -/* 7 07 11C 71C 718 I/O Channel 3 interrupt */ -/* 8 08 120 724 720 I/O Channel 4 interrupt */ -/* 9 09 124 72C 728 I/O Channel 5 interrupt */ -/* A 0A 128 734 730 I/O Channel 6 interrupt */ -/* B 0B 12C 73C 738 I/O Channel 7 interrupt */ -/* C 0C 130 744 740 I/O Channel 8 interrupt */ -/* D 0D 134 74C 748 I/O Channel 9 interrupt */ -/* E 0E 138 754 750 I/O Channel A interrupt */ -/* F 0F 13C 75C 758 I/O Channel B interrupt */ -/* 10 10 140 764 760 I/O Channel C interrupt */ -/* 11 11 144 76C 768 I/O Channel D interrupt */ -/* 12 12 148 774 770 I/O Channel E interrupt */ -/* 13 13 14c 77C 778 I/O Channel F interrupt */ -/* 14 14 150 External/Software Interrupt */ -/* 15 15 154 External/Software Interrupt */ -/* 16 16 158 External/Software Interrupt */ -/* 17 17 15C External/Software Interrupt */ -/* 18 18 160 Real-Time Clock Interrupt */ -/* 19 19 164 External/Software Interrupt */ -/* 1A 1A 1A8 External/Software Interrupt */ -/* 1B 1B 1AC External/Software Interrupt */ -/* 1C 1C 1B0 External/Software Interrupt */ -/* THRU THRU THRU THRU */ -/* 6C 6C 2B0 External/Software Interrupt */ -/* 6D 6D 2B4 External/Software Interrupt */ -/* 6E 6E 2B8 External/Software Interrupt */ -/* 6F 6F 2BC Interval Timer Interrupt */ - -/* IVL ------------> ICB Trap/Interrupt Vector Location points to Interrupt Context Block */ -/* Wd 0 - Old PSD Word 1 points to return location */ -/* Wd 1 - Old PSD Word 2 */ -/* Wd 2 - New PSD Word 1 points to first instruction of service routine */ -/* Wd 3 - New PSD Word 2 */ -/* Wd 4 - CPU Status word at time of interrupt/trap */ -/* Wd 5 - N/U For Traps/Interrupts */ - -/* IVL ------------> ICB XIO Interrupt Vector Location */ -/* Wd 0 - Old PSD Word 1 points to return location */ -/* Wd 1 - Old PSD Word 2 */ -/* Wd 2 - New PSD Word 1 points to first instruction of service routine */ -/* Wd 3 - New PSD Word 2 */ -/* Wd 4 - Input/Output Command List Address (IOCL) for the Class F I/O CHannel */ -/* Wd 5 - 24 bit real address of the channel status word */ - -/* CPU registers, map cache, spad, and other variables */ -int traceme = 0; /* dynamic trace function */ -int trstart = 9981910; /* count of when to start tracing */ -//int trstart = 37; /* count of when to start tracing */ -int cpu_index; /* Current CPU running */ -uint32 PSD[2]; /* the PC for the instruction */ -#define PSD1 PSD[0] /* word 1 of PSD */ -#define PSD2 PSD[1] /* word 2 of PSD */ -uint32 M[MAXMEMSIZE] = { 0 }; /* Memory */ -uint32 GPR[8]; /* General Purpose Registers */ -uint32 BR[8]; /* Base registers */ -uint32 PC; /* Program counter */ -uint32 CC; /* Condition codes, bits 1-4 of PSD1 */ -uint32 SPAD[256]; /* Scratch pad memory */ -uint32 INTS[112]; /* Interrupt status flags */ -uint32 CPUSTATUS; /* cpu status word */ -uint32 TRAPSTATUS; /* trap status word */ -/* CPU mapping cache entries */ -/* 32/55 has none */ -/* 32/7x has 32 8KW maps per task */ -/* Concept/32 has 2048 2KW maps per task */ -uint32 MAPC[1024]; /* maps are 16bit entries on word bountries */ -uint32 HIWM = 0; /* max maps loaded so far */ - -uint32 modes; /* Operating modes, bits 0, 5, 6, 7 of PSD1 */ -uint8 wait4int = 0; /* waiting for interrupt if set */ - -/* define traps */ -uint32 TRAPME = 0; /* trap to be executed */ -uint32 attention_trap = 0; /* set when trap is requested */ - -struct InstHistory -{ - uint32 psd1; /* the PC for the instruction */ - uint32 psd2; /* the PC for the instruction */ - uint32 inst; /* the instruction itself */ - uint32 ea; /* computed effective address of data */ - uint32 reg; /* reg for operation */ - uint32 dest; /* destination value */ - uint32 src; /* source value */ - uint8 cc; /* cc's */ -}; - -/* forward definitions */ -t_stat cpu_ex(t_value * vptr, t_addr addr, UNIT * uptr, int32 sw); -t_stat cpu_dep(t_value val, t_addr addr, UNIT * uptr, int32 sw); -t_stat cpu_reset(DEVICE * dptr); -t_stat cpu_set_size(UNIT * uptr, int32 val, CONST char *cptr, void *desc); -t_stat cpu_show_hist(FILE * st, UNIT * uptr, int32 val, CONST void *desc); -t_stat cpu_set_hist(UNIT * uptr, int32 val, CONST char *cptr, void *desc); -uint32 cpu_cmd(UNIT * uptr, uint16 cmd, uint16 dev); -t_stat cpu_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); -const char *cpu_description (DEVICE *dptr); -t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot); -t_stat load_maps(uint32 thepsd[2]); -t_stat read_instruction(uint32 thepsd[2], uint32 *instr); -t_stat Mem_read(uint32 addr, uint32 *data); -t_stat Mem_write(uint32 addr, uint32 *data); - -/* external definitions */ -extern t_stat startxio(uint16 addr, uint32 *status); /* XIO start in chan.c */ -extern t_stat testxio(uint16 addr, uint32 *status); /* XIO test in chan.c */ -extern t_stat stopxio(uint16 addr, uint32 *status); /* XIO stop in chan.c */ -extern t_stat rschnlxio(uint16 addr, uint32 *status); /* reset channel XIO */ -extern t_stat haltxio(uint16 addr, uint32 *status); /* halt XIO */ -extern t_stat grabxio(uint16 addr, uint32 *status); /* grab XIO n/u */ -extern t_stat rsctlxio(uint16 addr, uint32 *status); /* reset controller XIO */ -extern t_stat chan_set_devs(); /* set up the defined devices on the simulator */ -extern uint32 scan_chan(void); /* go scan for I/O int pending */ -extern uint16 loading; /* set when doing IPL */ -extern int fprint_inst(FILE *of, uint32 val, int32 sw); /* instruction print function */ -extern int irq_pend; /* go scan for pending interrupt */ -extern void rtc_setup(int ss, uint32 level); /* tell rtc to start/stop */ -extern void itm_setup(int ss, uint32 level); /* tell itm to start/stop */ -extern int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level); /* read/write the interval timer */ -extern int32 itm_srv(UNIT *uptr); /* read/write the interval timer */ -extern UNIT itm_unit; /* fake interval timer */ - -/* History information */ -int32 hst_p = 0; /* History pointer */ -int32 hst_lnt = 0; /* History length */ -struct InstHistory *hst = NULL; /* History stack */ - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - pu_mod CPU modifiers list -*/ - -#ifdef DEFINED_IN_SIM_DEFS_H -/* Unit data structure from sim_defs.h - - Parts of the unit structure are device specific, that is, they are - not referenced by the simulator control package and can be freely - used by device simulators. Fields starting with 'buf', and flags - starting with 'UF', are device specific. The definitions given here - are for a typical sequential device. -*/ - -struct UNIT { - UNIT *next; /* next active */ - t_stat (*action)(UNIT *up); /* action routine */ - char *filename; /* open file name */ - FILE *fileref; /* file reference */ - void *filebuf; /* memory buffer */ - uint32 hwmark; /* high water mark */ - int32 time; /* time out */ - uint32 flags; /* flags */ - uint32 dynflags; /* dynamic flags */ - t_addr capac; /* capacity */ - t_addr pos; /* file position */ - void (*io_flush)(UNIT *up); /* io flush routine */ - uint32 iostarttime; /* I/O start time */ - int32 buf; /* buffer */ - int32 wait; /* wait */ - int32 u3; /* device specific */ - int32 u4; /* device specific */ - int32 u5; /* device specific */ - int32 u6; /* device specific */ - void *up7; /* device specific */ - void *up8; /* device specific */ - uint16 us9; /* device specific */ - uint16 us10; /* device specific */ - void *tmxr; /* TMXR linkage */ - t_bool (*cancel)(UNIT *); - double usecs_remaining; /* time balance for long delays */ - char *uname; /* Unit name */ -#ifdef SIM_ASYNCH_IO - void (*a_check_completion)(UNIT *); - t_bool (*a_is_active)(UNIT *); - UNIT *a_next; /* next asynch active */ - int32 a_event_time; - ACTIVATE_API a_activate_call; - /* Asynchronous Polling control */ - /* These fields should only be referenced when holding the sim_tmxr_poll_lock */ - t_bool a_polling_now; /* polling active flag */ - int32 a_poll_waiter_count; /* count of polling threads */ - /* waiting for this unit */ - /* Asynchronous Timer control */ - double a_due_time; /* due time for timer event */ - double a_due_gtime; /* due time (in instructions) for timer event */ - double a_usec_delay; /* time delay for timer event */ -#endif /* SIM_ASYNCH_IO */ - }; - -/* Unit flags */ - -#define UNIT_V_UF_31 12 /* dev spec, V3.1 */ -#define UNIT_V_UF 16 /* device specific */ -#define UNIT_V_RSV 31 /* reserved!! */ -#define FEAT_TIMER (1<<(UNIT_V_UF+12)) /* interval timer */ -#define TMR_RTC 0 - -#define UNIT_ATTABLE 0000001 /* attachable */ -#define UNIT_RO 0000002 /* read only */ -#define UNIT_FIX 0000004 /* fixed capacity */ -#define UNIT_SEQ 0000010 /* sequential */ -#define UNIT_ATT 0000020 /* attached */ -#define UNIT_BINK 0000040 /* K = power of 2 */ -#define UNIT_BUFABLE 0000100 /* bufferable */ -#define UNIT_MUSTBUF 0000200 /* must buffer */ -#define UNIT_BUF 0000400 /* buffered */ -#define UNIT_ROABLE 0001000 /* read only ok */ -#define UNIT_DISABLE 0002000 /* disable-able */ -#define UNIT_DIS 0004000 /* disabled */ -#define UNIT_IDLE 0040000 /* idle eligible */ -#endif /* DEFINED_IN_SIM_DEFS_H */ - -UNIT cpu_unit = - /* Unit data layout for CPU */ -/* { UDATA(rtc_srv, UNIT_BINK | MODEL(MODEL_27) | MEMAMOUNT(0), MAXMEMSIZE ), 120 }; */ - { - NULL, /* UNIT *next */ /* next active */ - NULL, /* t_stat (*action) */ /* action routine */ - NULL, /* char *filename */ /* open file name */ - NULL, /* FILE *fileref */ /* file reference */ - NULL, /* void *filebuf */ /* memory buffer */ - 0, /* uint32 hwmark */ /* high water mark */ - 0, /* int32 time */ /* time out */ - UNIT_BINK|MODEL(MODEL_27)|MEMAMOUNT(1), /* uint32 flags */ /* flags */ - 0, /* uint32 dynflags */ /* dynamic flags */ - MAXMEMSIZE, /* t_addr capac */ /* capacity */ - 0, /* t_addr pos */ /* file position */ - NULL, /* void (*io_flush) */ /* io flush routine */ - 0, /* uint32 iostarttime */ /* I/O start time */ - 0, /* int32 buf */ /* buffer */ - 80, /* int32 wait */ /* wait */ -}; - -/* Register data structure definition from sim_defs.h */ -#ifdef DEFINED_IN_SIM_DEFS_H -struct REG { - CONST char *name; /* name */ - void *loc; /* location */ - uint32 radix; /* radix */ - uint32 width; /* width */ - uint32 offset; /* starting bit */ - uint32 depth; /* save depth */ - const char *desc; /* description */ - BITFIELD *fields; /* bit fields */ - uint32 qptr; /* circ q ptr */ - size_t str_size; /* structure size */ - /* NOTE: Flags MUST always be last since it is initialized outside of macro definitions */ - uint32 flags; /* flags */ - }; - -/* Register flags from sim_defs.h */ -#define REG_FMT 00003 /* see PV_x */ -#define REG_RO 00004 /* read only */ -#define REG_HIDDEN 00010 /* hidden */ -#define REG_NZ 00020 /* must be non-zero */ -#define REG_UNIT 00040 /* in unit struct */ -#define REG_STRUCT 00100 /* in structure array */ -#define REG_CIRC 00200 /* circular array */ -#define REG_VMIO 00400 /* use VM data print/parse */ -#define REG_VMAD 01000 /* use VM addr print/parse */ -#define REG_FIT 02000 /* fit access to size */ -#define REG_HRO (REG_RO | REG_HIDDEN) /* hidden, read only */ - -#define REG_V_UF 16 /* device specific */ -#define REG_UFMASK (~((1u << REG_V_UF) - 1)) /* user flags mask */ -#define REG_VMFLAGS (REG_VMIO | REG_UFMASK) /* call VM routine if any of these are set */ -#endif /* DEFINED_IN_SIM_DEFS_H */ - -//UNIT cpu_unit = { UDATA (&rtc_srv, UNIT_BINK, MAXMEMSIZE) }; - -REG cpu_reg[] = { - {HRDATAD(PC, PC, 24, "Program Counter"), REG_FIT}, - {BRDATAD(PSD, PSD, 16, 32, 2, "Progtam Status Doubleword"), REG_FIT}, - {BRDATAD(GPR, GPR, 16, 32, 8, "Index registers"), REG_FIT}, - {BRDATAD(BR, BR, 16, 32, 8, "Base registers"), REG_FIT}, - {BRDATAD(SPAD, SPAD, 16, 32, 256, "CPU Scratchpad memory"), REG_FIT}, - {BRDATAD(MAPC, MAPC, 16, 32, 1024, "CPU mape cache"), REG_FIT}, - {HRDATAD(CPUSTATUS, CPUSTATUS, 32, "CPU Status Word"), REG_FIT}, - {HRDATAD(TRAPSTATUS, TRAPSTATUS, 32, "TRAP Status Word"), REG_FIT}, - {HRDATAD(CC, CC, 32, "Condition Codes"), REG_FIT}, - {BRDATAD(INTS, INTS, 16, 32, 112, "Interrupt Status"), REG_FIT}, -// {ORDATAD(BASE, baseaddr, 16, "Relocation base"), REG_FIT}, - {NULL} -}; - -/* Modifier table layout (MTAB) - only extended entries have disp, reg, or flags */ -MTAB cpu_mod[] = { - { - /* MTAB table layout for cpu type */ - /* {UNIT_MODEL, MODEL(MODEL_55), "32/55", "32/55", NULL, NULL, NULL, "Concept 32/55"}, */ - UNIT_MODEL, /* uint32 mask */ /* mask */ - MODEL(MODEL_55), /* uint32 match */ /* match */ - "32/55", /* cchar *pstring */ /* print string */ - "32/55", /* cchar *mstring */ /* match string */ - NULL, /* t_stat (*valid) */ /* validation routine */ - NULL, /* t_stat (*disp) */ /* display routine */ - NULL, /* void *desc */ /* value descriptor, REG* if MTAB_VAL, int* if not */ - "Concept 32/55", /* cchar *help */ /* help string */ - }, - {UNIT_MODEL, MODEL(MODEL_75), "32/75", "32/75", NULL, NULL, NULL, "Concept 32/75"}, - {UNIT_MODEL, MODEL(MODEL_27), "32/27", "32/27", NULL, NULL, NULL, "Concept 32/27"}, - {UNIT_MODEL, MODEL(MODEL_67), "32/67", "32/67", NULL, NULL, NULL, "Concept 32/67"}, - {UNIT_MODEL, MODEL(MODEL_87), "32/87", "32/87", NULL, NULL, NULL, "Concept 32/87"}, - {UNIT_MODEL, MODEL(MODEL_97), "32/97", "32/97", NULL, NULL, NULL, "Concept 32/97"}, - {UNIT_MODEL, MODEL(MODEL_V6), "V6", "V6", NULL, NULL, NULL, "Concept V6"}, - {UNIT_MODEL, MODEL(MODEL_V9), "V9", "V9", NULL, NULL, NULL, "Concept V9"}, - { - /* MTAB table layout for cpu memory size */ - /* {UNIT_MSIZE, MEMAMOUNT(0), "128K", "128K", &cpu_set_size}, */ - UNIT_MSIZE, /* uint32 mask */ /* mask */ - MEMAMOUNT(0), /* uint32 match */ /* match */ - "128K", /* cchar *pstring */ /* print string */ - "128K", /* cchar *mstring */ /* match string */ - &cpu_set_size, /* t_stat (*valid) */ /* validation routine */ - NULL, /* t_stat (*disp) */ /* display routine */ - NULL, /* void *desc */ /* value descriptor, REG* if MTAB_VAL, int* if not */ - NULL, /* cchar *help */ /* help string */ - }, - {UNIT_MSIZE, MEMAMOUNT(1), "256K", "256K", &cpu_set_size}, - {UNIT_MSIZE, MEMAMOUNT(2), "512K", "512K", &cpu_set_size}, - {UNIT_MSIZE, MEMAMOUNT(3), "1M", "1M", &cpu_set_size}, - {UNIT_MSIZE, MEMAMOUNT(4), "2M", "2M", &cpu_set_size}, - {UNIT_MSIZE, MEMAMOUNT(5), "3M", "3M", &cpu_set_size}, - {UNIT_MSIZE, MEMAMOUNT(6), "4M", "4M", &cpu_set_size}, - {UNIT_MSIZE, MEMAMOUNT(7), "8M", "8M", &cpu_set_size}, - {UNIT_MSIZE, MEMAMOUNT(8), "16M", "16M", &cpu_set_size}, - {MTAB_XTD | MTAB_VDV | MTAB_NMO | MTAB_SHP, 0, "HISTORY", "HISTORY", - &cpu_set_hist, &cpu_show_hist}, - {0} -}; - -/* CPU device descriptor */ -DEVICE cpu_dev = { - /* "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 24, 1, 8, 32, - &cpu_ex, &cpu_dep, &cpu_reset, NULL, NULL, NULL, - NULL, DEV_DEBUG, 0, dev_debug, - NULL, NULL, &cpu_help, NULL, NULL, &cpu_description */ - "CPU", /* cchar *name */ /* device name */ - &cpu_unit, /* UNIT *units */ /* unit array */ - cpu_reg, /* REG *registers */ /* register array */ - cpu_mod, /* MTAB *modifiers */ /* modifier array */ - 1, /* uint32 numunits */ /* number of units */ - 16, /* uint32 aradix */ /* address radix */ - 24, /* uint32 awidth */ /* address width */ - 2, /* uint32 aincr */ /* address increment */ - 16, /* uint32 dradix */ /* data radix */ - 32, /* uint32 dwidth */ /* data width */ - &cpu_ex, /* t_stat (*examine) */ /* examine routine */ - &cpu_dep, /* t_stat (*deposit) */ /* deposit routine */ - &cpu_reset, /* t_stat (*reset) */ /* reset routine */ - NULL, /* t_stat (*boot) */ /* boot routine */ - NULL, /* t_stat (*attach) */ /* attach routine */ - NULL, /* t_stat (*detach) */ /* detach routine */ - NULL, /* void *ctxt */ /* (context) device information block pointer */ - DEV_DEBUG, /* uint32 flags */ /* device flags */ - 0, /* uint32 dctrl */ /* debug control flags */ - dev_debug, /* DEBTAB *debflags */ /* debug flag name array */ - NULL, /* t_stat (*msize) */ /* memory size change routine */ - NULL, /* char *lname */ /* logical device name */ - &cpu_help, /* t_stat (*help) */ /* help function */ - NULL, /* t_stat (*attach_help) */ /* attach help function */ - NULL, /* void *help_ctx */ /* Context available to help routines */ - &cpu_description, /* cchar *(*description) */ /* Device description */ - NULL, /* BRKTYPTB *brk_types */ /* Breakpoint types */ -}; - -/* CPU Instruction decode flags */ -#define INV 0x0000 /* Instruction is invalid */ -#define HLF 0x0001 /* Half word instruction */ -#define ADR 0x0002 /* Normal addressing mode */ -#define IMM 0x0004 /* Immediate mode */ -#define WRD 0x0008 /* Word addressing, no index */ -#define SCC 0x0010 /* Sets CC */ -#define RR 0x0020 /* Read source register */ -#define R1 0x0040 /* Read destination register */ -#define RB 0x0080 /* Read base register into dest */ -#define SD 0x0100 /* Stores into destination register */ -#define SDD 0x0200 /* Stores double into destination */ -#define RM 0x0400 /* Reads memory */ -#define SM 0x0800 /* Stores memory */ -#define DBL 0x1000 /* Double word operation */ -#define SB 0x2000 /* Store Base register */ -#define BT 0x4000 /* Branch taken, no PC incr */ - -int nobase_mode[] = { - /* 00 04 08 0C */ - /* 00 ANR, ORR, EOR */ - HLF, SCC|R1|RR|SD|HLF, SCC|R1|RR|SD|HLF, SCC|R1|RR|SD|HLF, - /* 10 14 18 1C */ - /* CAR, CMR, SBR ZBR */ - HLF, HLF, HLF, HLF, - /* 20 24 28 2C */ - /* ABR TBR REG TRR */ - HLF, HLF, HLF, HLF, - /* 30 34 38 3C */ - /* CALM LA ADR SUR */ - HLF, SD|ADR, HLF, HLF, - /* 40 44 48 4C */ - /* MPR DVR */ - SD|HLF, HLF, INV, INV, - /* 50 54 58 5C */ - /* */ - INV, INV, INV, INV, - - /* 60 64 68 6C */ - /* NOR NORD SCZ SRA */ - SD|HLF, SDD|HLF, HLF, HLF, - - /* 70 74 78 7C */ - /* SRL SRC SRAD SRLD */ - SD|HLF, SD|HLF, HLF, HLF, - - /* 80 84 88 8C */ - /* LEAR ANM ORM EOM */ - SD|ADR, SCC|SD|RR|RM|ADR, SCC|SD|RR|RM|ADR, SCC|SD|RR|RM|ADR, - - /* 90 94 98 9C */ - /* CAM CMM SBM ZBM */ - SCC|RR|RM|ADR, RR|RM|ADR, ADR, ADR, - - /* A0 A4 A8 AC */ - /* ABM TBM EXM L */ - ADR, ADR, ADR, SCC|SD|RM|ADR, - - /* B0 B4 B8 BC */ - /* LM LN ADM SUM */ - SCC|SD|RM|ADR, SCC|SD|RM|ADR, SCC|SD|RR|RM|ADR, SCC|SD|RR|RM|ADR, - - /* C0 C4 C8 CC */ - /* MPM DVM IMM LF */ - SCC|SD|RM|ADR, RM|ADR, IMM, ADR, - - /* D0 D4 D8 DC */ - /* LEA ST STM STF */ - SD|ADR, RR|SM|ADR, RR|SM|ADR, ADR, - - /* E0 E4 E8 EC */ - /* ADF MPF ARM BCT */ - SCC|SD|RM|ADR, SCC|RM|ADR, SCC|SM|RR|RM|ADR, ADR, - - /* F0 F4 F8 FC */ - /* BCF BI MISC IO */ - ADR, RR|SD|WRD, ADR, IMM, -}; - -int base_mode[] = { - /* 00 04 08 0C */ - /* 00 AND, OR, EOR */ - HLF, SCC|RR|SD|HLF, SCC|RR|SD|HLF, SCC|RR|SD|HLF, - /* 10 14 18 1C */ - /* SACZ CMR xBR SRx */ - HLF, HLF, HLF, HLF, - /* 20 24 28 2C */ - /* SRxD SRC REG TRR */ - SD|HLF, SD|HLF, HLF, HLF, - /* 30 34 38 3C */ - /* LA FLRop SUR */ - INV, INV, SD|HLF, SD|HLF, - /* 40 44 48 4C */ - /* */ - INV, INV, INV, INV, - - /* 50 54 58 5C */ - /* LA BASE BASE CALLM */ - SD|ADR, SM,ADR, SB|RM|ADR, ADR, - - /* 60 64 68 6C */ - /* */ - INV, INV, INV, INV, - /* 70 74 78 7C */ - /* */ - INV, INV, INV, INV, - /* LEAR ANM ORM EOM */ - /* 80 84 88 8C */ - SD|ADR, SD|RM|ADR, SD|RM|ADR, SD|RM|ADR, - - /* CAM CMM SBM ZBM */ - /* 90 94 98 9C */ - RM|ADR, RM|ADR, ADR, ADR, - - /* A0 A4 A8 AC */ - /* ABM TBM EXM L */ - ADR, ADR, ADR, SD|RM|ADR, - - /* B0 B4 B8 BC */ - /* LM LN ADM SUM */ - SD|RM|ADR,SD|RM|ADR, SD|RM|ADR, SD|RM|ADR, - - /* C0 C4 C8 CC */ - /* MPM DVM IMM LF */ - SD|RM|ADR, RM|ADR, IMM, ADR, - - /* D0 D4 D8 DC */ - /* LEA ST STM STFBR */ - SD|ADR, SM|ADR, SM|ADR, ADR, - /* E0 E4 E8 EC */ - /* ADF MPF ARM BCT */ - SD|RM|ADR, RM|ADR, SM|RM|ADR, ADR, - /* F0 F4 F8 FC */ - /* BCF BI MISC IO */ - ADR, RR|SB|WRD, ADR, IMM, -}; - -/* set up the map registers for the current task in the cpu */ -/* the PSD bpix and cpix are used to setup the maps */ -/* return non-zero if mapping error */ -t_stat load_maps(uint32 thepsd[2]) -{ - uint32 num, sdc, spc; - uint32 mpl, cpixmsdl, bpixmsdl, msdl, midl; - uint32 cpix, bpix, i, j, map, osmidl; - - if (CPU_MODEL < MODEL_27) - { - /* 32/7x machine, 8KW maps */ - modes &= ~BASEBIT; /* no basemode on 7x */ - if ((thepsd[1] & 0xc0000000) == 0) { /* mapped mode? */ - return ALLOK; /* no, all OK, no mapping required */ - } - /* we are mapped, so load the maps for this task into the cpu map cache */ - cpix = (thepsd[1] >> 2) & 0xfff; /* get cpix 12 bit offset from psd wd 2 */ - bpix = (thepsd[1] >> 18) & 0xfff; /* get bpix 12 bit offset from psd wd 2 */ - num = 0; /* working map number */ - /* master process list is in 0x83 of spad for 7x */ - mpl = SPAD[0x83] >> 2; /* get mpl from spad address */ - cpixmsdl = M[mpl + cpix]; /* get msdl from mpl for given cpix */ - /* if bit zero of mpl entry is set, use bpix first to load maps */ - if (cpixmsdl & BIT0) - { - /* load bpix maps first */ - bpixmsdl = M[mpl + bpix]; /* get bpix msdl word address */ - sdc = (bpixmsdl >> 24) & 0x3f; /* get 6 bit segment description count */ - msdl = (bpixmsdl >> 2) & 0x3fffff; /* get 24 bit real address of msdl */ - for (i = 0; i < sdc; i++) /* loop through the msd's */ - { - spc = (M[msdl + i] >> 24) & 0xff; /* get segment page count from msdl */ - midl = (M[msdl + i] >> 2) && 0x3fffff; /* get 24 bit real word address of midl */ - for (j = 0; j < spc; j++) - { - /* load 16 bit map descriptors */ - map = (M[midl + (j / 2)]); /* get 2 16 bit map entries */ - if (j & 1) - map = (map & RMASK); /* use right half word map entry */ - else - map = ((map >> 16) & RMASK); /* use left half word map entry */ - /* the map register contents is now in right 16 bits */ - /* now load a 32 bit word with both maps from memory */ - /* and or in the new map entry data */ - if (num & 1) { - /* entry going to rt hw, clean it first */ - map = (MAPC[num/2] & LMASK) | map; /* map is in rt hw */ - } - else { - /* entry going to left hw, clean it first */ - map = (MAPC[num/2] & RMASK) | (map << 16); /* map is in left hw */ - } - MAPC[num++/2] = map; /* store the map reg contents into cache */ - if (num >= 32) - return MAPFLT; /* map loading overflow, map fault error */ - } - } - } - /* now load cpix maps */ - cpixmsdl = M[mpl + cpix]; /* get cpix msdl word address */ - sdc = (cpixmsdl >> 24) & 0x3f; /* get 6 bit segment description count */ - msdl = (cpixmsdl >> 2) & 0x3fffff; /* get 24 bit real address of msdl */ - for (i = 0; i < sdc; i++) - { - spc = (M[msdl + i] >> 24) & 0xff; /* get segment page count from msdl */ - midl = (M[msdl + i] >> 2) && 0x3fffff; /* get 24 bit real word address of midl */ - for (j = 0; j < spc; j++) - { - /* load 16 bit map descriptors */ - map = (M[midl + (j / 2)]); /* get 2 16 bit map entries */ - if (j & 1) - map = (map & RMASK); /* use right half word map entry */ - else - map = ((map >> 16) & RMASK); /* use left half word map entry */ - /* the map register contents is now in right 16 bits */ - /* now load a 32 bit word with both maps from memory */ - /* and or in the new map entry data */ - if (num & 1) { - /* entry going to rt hw, clean it first */ - map = (MAPC[num/2] & LMASK) | map; /* map is in rt hw */ - } - else { - /* entry going to left hw, clean it first */ - map = (MAPC[num/2] & RMASK) | (map << 16); /* map is in left hw */ - } - MAPC[num++/2] = map; /* store the map reg contents into cache */ - if (num >= 32) - return MAPFLT; /* map loading overflow, map fault error */ - } - } - /* if none loaded, map fault */ - if (num == 0) - return MAPFLT; /* map fault error */ - if (num & 1) { /* clear rest of maps */ - /* left hw of map is good, zero right */ - map = (MAPC[num/2] & LMASK); /* clean rt hw */ - MAPC[num++/2] = map; /* store the map reg contents into cache */ - } - /* num should be even at this point, so zero 32 bit word for remaining maps */ - if ((num/2) > HIWM) /* largerst number of maps loaded so far* */ - HIWM = num/2; /* yes, set new high watter mark */ -// for (i = num/2; i < 32/2; i++) /* zero any remaining entries */ - for (i = num/2; i < HIWM; i++) /* zero any remaining entries */ - MAPC[i] = 0; /* clear the map entry to make not valid */ - return ALLOK; /* all cache is loaded, return OK */ - } - else - { - char n[9]; - uint32 dqe; - /* 32/27, 32/67, 32/87, 32/97 2KW maps */ - /* Concept/32 machine, 2KW maps */ - if ((modes & MAPMODE) == 0) { /* mapped mode? */ -// fprintf(stderr, "not mapping PSD2 %x\r\n", PSD2); - return ALLOK; /* no, all OK, no mapping required */ - } - /* we are mapped, so calculate real address from map information */ - cpix = (thepsd[1] >> 2) & 0xfff; /* get word cpix 11 bit offset from psd wd 2 */ - num = 0; /* no maps loaded yet */ - /* master process list is in 0xf3 of spad for concept */ - mpl = SPAD[0xf3] >> 2; /* get mpl from spad address */ - midl = M[mpl+cpix]; /* get mpl entry wd 0 for given cpix */ - msdl = M[mpl+cpix+1]; /* get mpl entry wd 0 for given cpix */ - dqe = M[0x8e8>>2]; - for (j=0; j<8; j++) { - n[j] = (M[((dqe+0x18)>>2)+(j/4)] >> ((3-(j&7))*8)) & 0xff; - if (n[j] == 0) - n[j] = 0x20; - } - n[8] = 0; -// fprintf(stderr, "mapping SPAD PSD2 %.8x PSD2 %x mpl %x osmidl %x umidl %x C.CURR %x LMN %s\r\n", -// SPAD[0xf5], PSD2, mpl, M[mpl], midl, dqe, n); - /* if bit zero of mpl entry is set, use msd entry 0 first to load maps */ - if (midl & BIT0) - { -/* TODO do not load O/S if already loaded. Bit zero of O/S midl will be set by swapper */ - /* load msd 0 maps first (O/S) */ - osmidl = M[mpl]; /* get midl 0 word address */ - spc = osmidl & MASK16; /* get 16 bit segment description count */ - if (osmidl & BIT0) { /* see f O/S already loaded */ - num = spc; /* set the number of o/s maps loaded */ - goto skipos; /* skip load */ - } - midl = M[mpl+1] & MASK24; /* get 24 bit real address from mpl wd2 */ - midl = midl>>2; /* make word address */ - for (j = 0; j < spc; j++) - { - /* load 16 bit map descriptors */ - map = (M[midl + (j / 2)]); /* get 2 16 bit map entries */ - if (j & 1) - map = (map & RMASK); /* use right half word map entry */ - else - map = ((map >> 16) & RMASK); /* use left half word map entry */ - /* the map register contents is now in right 16 bits */ - /* now load a 32 bit word with both maps from memory */ - /* and or in the new map entry data */ - if (num & 1) { - /* entry going to rt hw, clean it first */ - map = (MAPC[num/2] & LMASK) | map; /* map is in rt hw */ -// fprintf(stderr, "mapping 0x%x O/S num 0x%x midl %x MAPC[%d] %x\r\n", -// spc, num-1, (midl+(j/2))<<2, num/2, map); - } - else { - /* entry going to left hw, clean it first */ - map = (MAPC[num/2] & RMASK) | (map << 16); /* map is in left hw */ - } - MAPC[num/2] = map; /* store the map reg contents into cache */ - if (++num >= 2048) - return MAPFLT; /* map loading overflow, map fault error */ - } -#if 0 - if (num & 1) - fprintf(stderr, "mapping 0x%x O/S num 0x%x midl %x MAPC[%d] %x\r\n", - spc, num-1, (midl+((spc-1)/2))<<2, num/2, map); -#endif - } -skipos: - /* now load cpix maps */ - midl = M[mpl+cpix]; /* get cpix midl word address */ - msdl = M[mpl+cpix+1]; /* get 24 bit real word address of midl */ - spc = midl & RMASK; /* get segment page count from msdl */ - midl = M[mpl+cpix+1] & MASK24; /* get 24 bit real word address of midl */ - midl = midl>>2; /* get word address of midl */ - for (j = 0; j < spc; j++) - { - /* load 16 bit map descriptors */ - map = M[midl + (j / 2)]; /* get 2 16 bit map entries */ - if (j & 1) - map = (map & RMASK); /* use right half word map entry */ - else - map = ((map >> 16) & RMASK); /* use left half word map entry */ - /* the map register contents is now in right 16 bits */ - /* now load a 32 bit word with both maps from memory */ - /* and or in the new map entry data */ - if (num & 1) { - /* entry going to rt hw, clean it first */ - map = (MAPC[num/2] & LMASK) | map; /* map is in rt hw */ -// fprintf(stderr, "mapping 0x%x USER num 0x%x midl %x MAPC[%d] %x\r\n", -// spc, num-1, (midl+(j/2))<<2, num/2, map); - } - else { - /* entry going to left hw, clean it first */ - map = (MAPC[num/2] & RMASK) | (map << 16); /* map is in left hw */ - } - MAPC[num/2] = map; /* store the map reg contents into cache */ - if (++num >= 2048) - return MAPFLT; /* map loading overflow, map fault error */ - } - /* if none loaded, map fault */ - /* we got here without map block found, return map fault error */ - if (num == 0) - return MAPFLT; /* map fault error */ - if (num & 1) { - /* left hw of map is good, zero right */ - map = (MAPC[num/2] & LMASK); /* clean rt hw */ -// if (spc != 0) -// fprintf(stderr, "mapping 0x%x USER num 0x%x midl %x MAPC[%d] %x\r\n", -// spc, num-1, (midl+((spc-1)/2))<<2, num/2, map); - MAPC[num++/2] = map; /* store the map reg contents into cache */ - } - /* num should be even at this point, so zero 32 bit words for remaining maps */ - if ((num/2) > HIWM) /* largerst number of maps loaded so far* */ - HIWM = num/2; /* yes, set new high watter mark */ -// for (i = num/2; i < 2048/2; i++) /* zero any remaining entries */ - for (i = num/2; i < HIWM; i++) /* zero any remaining entries */ - MAPC[i] = 0; /* clear the map entry to make not valid */ - return ALLOK; /* all cache is loaded, retun OK */ - } -} - -/* - * Return the real memory address from the logical address - * Also return the protection status, 1 if write protected address - */ -t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot) -{ - uint32 word, index, map, mask; - - *prot = 0; /* show unprotected memory as default */ - /* unmapped mode is unprotected */ - - /* see what machine we have */ - if (CPU_MODEL < MODEL_27) - { - /* 32/7x machine with 8KW maps */ - if (modes & EXTDBIT) - word = addr & 0xfffff; /* get 20 bit logical word address */ - else - word = addr & 0x7ffff; /* get 19 bit logical word address */ - if ((modes & MAPMODE) == 0) { - /* check if valid real address */ - if (word >= MEMSIZE) /* see if address is within our memory */ - return NPMEM; /* no, none present memory error */ - *realaddr = word; /* return the real address */ - return ALLOK; /* all OK, return instruction */ - } - /* we are mapped, so calculate real address from map information */ - /* 32/7x machine, 8KW maps */ - index = word >> 15; /* get 4 or 5 bit value */ - map = MAPC[index/2]; /* get two hw map entries */ - if (index & 1) - /* entry is in rt hw, clear left hw */ - map &= RMASK; /* map is in rt hw */ - else - /* entry is in left hw, move to rt hw */ - map >>= 16; /* map is in left hw */ - /* see if map is valid */ - if (map & 0x4000) { - /* required map is valid, get 9 bit address and merge with 15 bit page offset */ - word = ((map & 0x1ff) << 15) | (word & 0x7fff); - /* check if valid real address */ - if (word >= MEMSIZE) /* see if address is within our memory */ - return NPMEM; /* no, none present memory error */ - if ((modes & PRIVBIT) == 0) { /* see if we are in unprivileged mode */ - if (map & 0x2000) /* check if protect bit is set in map entry */ - *prot = 1; /* return memory write protection status */ - } - *realaddr = word; /* return the real address */ - return ALLOK; /* all OK, return instruction */ - } - /* map is invalid, so return map fault error */ - return MAPFLT; /* map fault error */ - } - else { - /* 32/27, 32/67, 32/87, 32/97 2KW maps */ - /* Concept 32 machine, 2KW maps */ - if (modes & (BASEBIT | EXTDBIT)) - word = addr & 0xffffff; /* get 24 bit address */ - else - word = addr & 0x7ffff; /* get 19 bit address */ - if ((modes & MAPMODE) == 0) { - /* check if valid real address */ - if (word >= MEMSIZE) /* see if address is within our memory */ - return NPMEM; /* no, none present memory error */ - *realaddr = word; /* return the real address */ -//fprintf(stderr, "Read Real unmapped addr %x\r\n", addr, index, map); - return ALLOK; /* all OK, return instruction */ - } - /* replace bits 8-18 with 11 bits from memory map register */ - /* we are mapped, so calculate real address from map information */ - index = (word >> 13) & 0x7ff; /* get 11 bit value */ - map = MAPC[index/2]; /* get two hw map entries */ -//fprintf(stderr, "read addr %x index %x map %x\r\n", addr, index, map); - if (index & 1) - /* entry is in rt hw, clear left hw */ - map &= RMASK; /* map is in rt hw */ - else - /* entry is in left hw, move to rt hw */ - map >>= 16; /* map is in left hw */ -//fprintf(stderr, "read 2 addr %x index %x map %x\r\n", word, index, map); - if (map & 0x8000) { /* see if map is valid */ - /* required map is valid, get 11 bit address and merge with 13 bit page offset */ - word = ((map & 0x7ff) << 13) | (word & 0x1fff); - /* check if valid real address */ - if (word >= MEMSIZE) /* see if address is within our memory */ - return NPMEM; /* no, none present memory error */ - if ((modes & PRIVBIT) == 0) { /* see if we are in unprivileged mode */ - mask = (word & 0x1800) >> 11; /* get offset of 2kb block for map being addressed */ - if (map & (0x4000 >> mask)) /* check if protect bit is set in map entry */ - *prot = 1; /* return memory write protection status */ - } -//fprintf(stderr, "Read Real addr %x index %x map %x reala %x PSD2 %x\r\n", addr, index, map, word, SPAD[0xf5]); - *realaddr = word; /* return the real address */ - return ALLOK; /* all OK, return instruction */ - } - /* map is invalid, so return map fault error */ -// fprintf(stderr, "RealAddr MAP FAIL %x MAPC %x word %x addr %x index %x\n", -// map, MAPC[index/2], word, addr, index); - sim_debug(DEBUG_CMD, &cpu_dev, "RealAddr MAP FAIL %x MAPC %x word %x addr %x index %x\n", - map, MAPC[index/2], word, addr, index); - return MAPFLT; /* map fault error */ - } -} - -/* fetch the current instruction from the PC address */ -t_stat read_instruction(uint32 thepsd[2], uint32 *instr) -{ - uint32 addr, status; - - if (CPU_MODEL < MODEL_27) - { - /* 32/7x machine with 8KW maps */ - /* instruction must be in first 512KB of address space */ - addr = thepsd[0] & 0x7fffc; /* get 19 bit logical word address */ - } - else - { - /* 32/27, 32/67, 32/87, 32/97 2KW maps */ - /* Concept 32 machine, 2KW maps */ - if (thepsd[0] & BASEBIT) { /* bit 6 is base mode? */ - addr = thepsd[0] & 0xfffffc; /* get 24 bit address */ - } - else - addr = thepsd[0] & 0x7fffc; /* get 19 bit address */ - } - status = Mem_read(addr, instr); /* get the instruction at the specified address */ - sim_debug(DEBUG_DETAIL, &cpu_dev, "read_instr status = %x\n", status); - return status; /* return ALLOK or ERROR */ -} - -/* - * Read a full word from memory - * Return error type if failure, ALLOK if - * success. Addr is logical address. - */ -t_stat Mem_read(uint32 addr, uint32 *data) -{ - uint32 status, realaddr, prot; - - status = RealAddr(addr, &realaddr, &prot); /* convert address to real physical address */ - sim_debug(DEBUG_DETAIL, &cpu_dev, "Mem_read status = %x\n", status); - if (status == ALLOK) { - *data = M[realaddr >> 2]; /* valid address, get physical address contents */ - status = ALLOK; /* good status return */ - sim_debug(DEBUG_DETAIL, &cpu_dev, "Mem_read addr %.8x realaddr %.8x data %.8x prot %d\n", - addr, realaddr, *data, prot); - } - return status; /* return ALLOK or ERROR */ -} - -/* - * Write a full word to memory, checking protection - * and alignment restrictions. Return 1 if failure, 0 if - * success. Addr is logical address, data is 32bit word - */ -t_stat Mem_write(uint32 addr, uint32 *data) -{ - uint32 status, realaddr, prot; - - status = RealAddr(addr, &realaddr, &prot); /* convert address to real physical address */ - sim_debug(DEBUG_DETAIL, &cpu_dev, "Mem_write addr %.8x realaddr %.8x data %.8x prot %d\n", - addr, realaddr, *data, prot); - if (status == ALLOK) { - if (prot) /* check for write protected memory */ - return MPVIOL; /* return memory protection violation */ - M[realaddr >> 2] = *data; /* valid address, put physical address contents */ - status = ALLOK; /* good status return */ - } - return status; /* return ALLOK or ERROR */ -} - -/* function to set the CCs in PSD1 */ -/* ovr is setting for CC1 */ -void set_CCs(uint32 value, int ovr) -{ - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - if (ovr) - CC = CC1BIT; /* CC1 value */ - else - CC = 0; /* CC1 off */ - if (value & FSIGN) - CC |= CC3BIT; /* CC3 for neg */ - else if (value == 0) - CC |= CC4BIT; /* CC4 for zero */ - else - CC |= CC2BIT; /* CC2 for greater than zero */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ -} - -/* Opcode definitions */ -/* called from simulator */ -t_stat -sim_instr(void) -{ - t_stat reason = 0; /* reason for stopping */ - t_uint64 dest; /* Holds destination/source register */ - t_uint64 source; /* Holds source or memory data */ - t_uint64 td; /* Temporary */ - uint32 addr; /* Holds address of last access */ - uint32 temp; /* General holding place for stuff */ - uint32 IR; /* Instruction register */ - uint32 i_flags; /* Instruction description flags from table */ - uint32 t; /* Temporary */ - uint32 temp2; /* Temporary */ - uint32 bc; /* Temporary bit count */ - uint16 opr; /* Top half of Instruction register */ - uint16 OP; /* Six bit instruction opcode */ - uint16 chan; /* I/O channel address */ - uint16 lchan; /* Logical I/O channel address */ - uint16 suba; /* I/O subaddress */ - uint8 FC; /* Current F&C bits */ - uint8 EXM_EXR=0; /* PC Increment for EXM/EXR instructions */ - int reg; /* GPR or Base register bits 6-8 */ - int sreg; /* Source reg in from bits 9-11 reg-reg instructions */ - int ix; /* index register */ - int dbl; /* Double word */ - int ovr; /* Overflow flag */ - int stopnext = 0; /* Stop on next instruction */ - int skipinstr = 0; /* Skip test for interrupt on this instruction */ - uint32 int_icb; /* interrupt context block address */ - uint32 OIR; /* Original Instruction register */ - uint32 OPSD1; /* Original PSD1 */ - uint32 OPC; /* Original PC */ - -wait_loop: - while (reason == 0) { /* loop until halted */ - - // wait_loop: - if (sim_interval <= 0) { /* event queue? */ - reason = sim_process_event(); /* process */ - if (reason != SCPE_OK) { - if (reason == SCPE_STEP) - stopnext = 1; - else - break; /* process */ - } - } - - if (sim_brk_summ && sim_brk_test(PC, SWMASK('E'))) { - reason = STOP_IBKPT; - break; - } - - /* call our fake interval timer to count down 64 instructions per count */ - itm_srv(&itm_unit); /* service interval timer */ - sim_interval--; /* count down */ - - if (skipinstr) { /* need to skip interrupt test? */ - skipinstr = 0; /* skip only once */ - goto skipi; /* skip int test */ - } - - /* process pending I/O interrupts */ - if (!loading && (wait4int || irq_pend)) { /* see if ints are pending */ - int_icb = scan_chan(); /* no, go scan for I/O int pending */ - if (int_icb != 0) { /* was ICB returned for an I/O or interrupt */ - int il; - /* find interrupt level for icb address */ - for (il=0; il<112; il++) { - /* get the address of the interrupt IVL table in main memory */ - uint32 civl = SPAD[0xf1] + (il<<2); /* contents of spad f1 points to chan ivl in mem */ - civl = M[civl >> 2]; /* get the interrupt context block addr in memory */ - if (civl == int_icb) - break; - } -//sim_debug(DEBUG_EXP, &cpu_dev, "Normal int scan return icb %x\n", int_icb); -//fprintf(stderr, "Normal Interrupt scan return icb %x irq_pend %x wait4int %x\r\n", int_icb, irq_pend, wait4int); - /* take interrupt, store the PSD, fetch new PSD */ - bc = PSD2 & 0x3ffc; /* get copy of cpix */ - M[int_icb>>2] = PSD1&0xfffffffe; /* store PSD 1 */ - M[(int_icb>>2)+1] = PSD2; /* store PSD 2 */ - PSD1 = M[(int_icb>>2)+2]; /* get new PSD 1 */ - PSD2 = (M[(int_icb>>2)+3] & ~0x3ffc) | bc; /* get new PSD 2 w/old cpix */ - /* I/O status DW address will be in WD 6 */ - /* set new map mode and interrupt blocking state in CPUSTATUS */ - modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ - if (PSD2 & MAPBIT) { - CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ - modes |= MAPMODE; /* set mapped mode */ - } else - CPUSTATUS &= 0xff7fffff; /* reset bit 8 of cpu status */ - if ((PSD2 & 0x8000) == 0) { /* is it retain blocking state */ - if (PSD2 & 0x4000) /* no, is it set blocking state */ - CPUSTATUS |= 0x80; /* yes, set blk state in cpu status bit 24 */ - else - CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ - } - PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ - if (CPUSTATUS & 0x80) /* see if old mode is blocked */ - PSD2 |= 0x00004000; /* set to blocked state */ - PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ - SPAD[0xf5] = PSD2; /* save the current PSD2 */ - sim_debug(DEBUG_INST, &cpu_dev, - "Interrupt %x OPSD1 %.8x OPSD2 %.8x NPSD1 %.8x NPSD2 %.8x ICBA %x\r\n", - il, M[int_icb>>2], M[(int_icb>>2)+1], PSD1, PSD2, int_icb); - wait4int = 0; /* wait is over for int */ - skipinstr = 1; /* skip next interrupt test only once */ - } - /* see if waiting at a wait instruction */ - if (wait4int || loading) { -// ???? sim_interval++; /* restore count */ - goto wait_loop; /* continue waiting */ - } - } else { - if (loading) { - uint32 chsa = scan_chan(); /* go scan for load complete pending */ - if (chsa != 0) { /* see if a boot channel/subaddress were returned */ - /* take interrupt, store the PSD, fetch new PSD */ - PSD1 = 0x80000000; /* get new PSD 1, priv and addr is 0 */ - PSD2 = 0x00004000; /* get new PSD 2, blocked */ - modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ - sim_debug(DEBUG_INST, &cpu_dev, "Boot Loading PSD1 %.8x PSD2 %.8x\n", PSD1, PSD2); - /* set interrupt blocking state in CPUSTATUS */ - CPUSTATUS |= 0x80; /* set blocked state in cpu status, bit 24 too */ - PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ - SPAD[0xf5] = PSD2; /* save the current PSD2 */ - loading = 0; /* we are done loading */ - skipinstr = 1; /* skip next interrupt test only once */ - } - goto wait_loop; /* continue waiting */ - } - /* see if in wait instruction */ - if (wait4int) /* TRY this */ - goto wait_loop; /* continue waiting */ - } - - /* Check for external interrupt here */ - /* see if we have an attention request from console */ - if (!skipinstr && attention_trap) { - TRAPME = attention_trap; /* get trap number */ - attention_trap = 0; /* do only once */ -// fprintf(stderr, "Attention TRAP %x\r\n", TRAPME); - skipinstr = 1; /* skip next interrupt test only once */ - goto newpsd; /* got process trap */ - } - -skipi: - if (sim_brk_summ && sim_brk_test(PC, SWMASK('E'))) { - reason = STOP_IBKPT; - break; - } - - /* fill IR from logical memory address */ - if ((TRAPME = read_instruction(PSD, &IR))) { - sim_debug(DEBUG_INST, &cpu_dev, "read_instr TRAPME = %x\n", TRAPME); - goto newpsd; /* got process trap */ - } - - /* If executing right half */ - if (PSD1 & 2) - IR <<= 16; -exec: -/*FIXME temp saves */ - OIR = IR; - OPSD1 = PSD1; - OPC = PSD1 & 0xfffffe; /* get 24 bit addr from PSD1 */ - - /* TODO Update history for this instruction */ - if (hst_lnt) - { - hst_p += 1; /* next history location */ - if (hst_p >= hst_lnt) /* check for wrap */ - hst_p = 0; /* start over at beginning */ - hst[hst_p].psd1 = PSD1; /* set execution address */ - hst[hst_p].psd2 = PSD2; /* set mapping/blocking status */ - } - - /* Split instruction into pieces */ - PC = PSD1 & 0xfffffe; /* get 24 bit addr from PSD1 */ - sim_debug(DEBUG_DATA, &cpu_dev, "-----Instr @ PC %x PSD1 %.8x PSD2 %.8x IR %.8x\n", PC, PSD1, PSD2, IR); - opr = (IR >> 16) & MASK16; /* use upper half of instruction */ - OP = (opr >> 8) & 0xFC; /* Get opcode (bits 0-5) left justified */ - FC = ((IR & F_BIT) ? 0x4 : 0) | (IR & 3); /* get F & C bits for addressing */ - reg = (opr >> 7) & 0x7; /* dest reg or xr on base mode */ - sreg = (opr >> 4) & 0x7; /* src reg for reg-reg instructions or BR instr */ - dbl = 0; /* no doubleword instruction */ - ovr = 0; /* no overflow or arithmetic exception either */ - dest = (t_uint64)IR; /* assume memory address specified */ - CC = PSD1 & 0x78000000; /* save CC's if any */ - - if (modes & BASEBIT) { - i_flags = base_mode[OP>>2]; /* set the instruction processing flags */ - addr = IR & RMASK; /* get address offset from instruction */ -// sim_debug(DEBUG_INST, &cpu_dev, "Base i_flags %x addr %.8x\n", i_flags, addr); - switch(i_flags & 0xf) { - case HLF: - source = GPR[sreg]; /* get the src reg from instruction */ - break; - case IMM: - if (PC & 02) { /* if pc is on HW boundry, bad address */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - break; - case ADR: - case WRD: - if (PC & 02) { /* if pc is on HW boundry, bad address */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - ix = (IR >> 20) & 7; /* get index reg from instruction */ - if (ix != 0) - addr += GPR[ix]; /* if not zero, add in reg contents */ - ix = (IR >> 16) & 7; /* get base reg from instruction */ - if (ix != 0) - addr += BR[ix]; /* if not zero, add to base reg contents */ - FC = ((IR & F_BIT) ? 4 : 0); /* get F bit from original instruction */ - FC |= addr & 3; /* set new C bits to address from orig or regs */ - break; - case INV: - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - goto newpsd; /* handle trap */ - break; - } - } else { - i_flags = nobase_mode[OP>>2]; /* set the instruction processing flags */ - addr = IR & 0x7ffff; /* get 19 bit address from instruction */ - -// sim_debug(DEBUG_INST, &cpu_dev, "Non Based i_flags %x addr %.8x\n", i_flags, addr); - /* non base mode instructions have bit 0 of the instruction set */ - /* for word length instructions and zero for halfword instructions */ - /* the LA (op=0x34) is the only exception. So test for PC on a halfword */ - /* address and trap if word opcode is in right hw */ - if (PC & 02) { /* if pc is on HW boundry, addr trap if bit zero set */ - if ((OP == 0x34) || (OP & 0x80)) { - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - } - switch(i_flags & 0xf) { - case HLF: /* halfword instruction */ - source = GPR[sreg]; /* get the src reg contents */ - break; - - case IMM: /* Immediate mode */ - if (PC & 02) { /* if pc is on HW boundry, bad address */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - break; - - case ADR: /* Normal addressing mode */ - ix = (IR >> 21) & 3; /* get the index reg if specified */ - if (ix != 0) { - addr += GPR[ix]; /* if not zero, add in reg contents */ - FC = ((IR & F_BIT) ? 4 : 0); /* get F bit from original instruction */ - FC |= addr & 3; /* set new C bits to address from orig or regs */ - } - - /* wart alert! */ - /* the lea instruction requires special handling for indirection. */ - /* Bit 0,1 are set to 1 of result addr if indirect bit is zero in */ - /* instruction. Bits 0 & 1 are set to the last word */ - /* or instruction in the chain bits 0 & 1 if indirect bit set */ - /* if IX == 00 => dest = IR */ - /* if IX == 0x => dest = IR + reg */ - /* if IX == Ix => dest = ind + reg */ - - /* fall through */ - - case WRD: /* Word addressing, no index */ - bc = 0xC0000000; /* set bits 0, 1 for instruction if not indirect */ - t = IR; /* get current IR */ - while (t & IND) { /* process indirection */ - if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - bc = temp & 0xC0000000; /* save new bits 0, 1 from indirect location */ - CC = (temp & 0x78000000); /* save CC's from the last indirect word */ - if (modes & EXTDBIT) { /* check if in extended mode */ - /* extended mode, so location has 24 bit addr, not X,I ADDR */ -// fprintf(stderr, "Indirect EXT before addr %x contents %x\n", addr, temp); - addr = temp & MASK24; /* get 24 bit addr */ - /* if no C bits set, use original, else new */ - if ((IR & F_BIT) || (addr & 3)) - FC = ((IR & F_BIT) ? 0x4 : 0) | (addr & 3); -// fprintf(stderr, "Indirect EXT after addr %x temp %x\n", addr, temp); - t &= ~IND; /* turn off IND bit to stop while loop */ - } else { - /* non-extended mode, process new X, I, ADDR fields */ -// fprintf(stderr, "Indirect NE before addr %x contents %x\n", addr, temp); - addr = temp & MASK19; /* get just the addr */ - ix = (temp >> 21) & 3; /* get the index reg from indirect word */ - if (ix != 0) - addr += (GPR[ix] & MASK19); /* add the register to the address */ - /* if no F or C bits set, use original, else new */ - if ((temp & F_BIT) || (addr & 3)) - FC = ((temp & F_BIT) ? 0x4 : 0) | (addr & 3); -// fprintf(stderr, "Indirect NE after addr %x temp %x\n", addr, temp); - t = temp; /* go process next indirect location */ - } - } - if (OP == 0xD0) /* test for LEA op */ - addr |= bc; /* insert bits 0,1 values into address */ - dest = (t_uint64)addr; /* make into 64 bit variable */ - break; - case INV: /* Invalid instruction */ - if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - goto newpsd; /* handle trap */ - break; - } - } - - /* Read memory operand */ - if (i_flags & RM) { - if ((TRAPME = Mem_read(addr, &temp))) { /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - } - source = (t_uint64)temp; /* make into 64 bit value */ - switch(FC) { - case 0: /* word address, extend sign */ - source |= (source & MSIGN) ? D32LMASK : 0; - break; - case 1: /* left hw */ - source >>= 16; /* move left hw to right hw*/ - /* Fall through */ - case 3: /* right hw or right shifted left hw */ - source &= 0xffff; /* use just the right hw */ - if (source & 0x8000) { /* check sign of 16 bit value */ - /* sign extend the value to leftmost 48 bits */ - source = 0xFFFF0000 | (source & 0xFFFF); /* extend low 32 bits */ - source |= (D32LMASK); /* extend hi bits */ - } - break; - case 2: /* double word address */ - if ((addr & 2) != 2) { /* must be double word adddress */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - if ((TRAPME = Mem_read(addr+4, &temp))) { /* get the 2nd word from memory */ - goto newpsd; /* memory read error or map fault */ - } - source = (source << 32) | (t_uint64)temp; /* merge in the low order 32 bits */ - dbl = 1; /* double word instruction */ - break; - case 4: /* byte mode, byte 0 */ - case 5: /* byte mode, byte 1 */ - case 6: /* byte mode, byte 2 */ - case 7: /* byte mode, byte 3 */ - source = (source >> (8*(7-FC))) & 0xff; /* right justify addressed byte */ - break; - } - } - - /* Read in if from register */ - if (i_flags & RR) { - if (FC == 2 && (i_flags & HLF) == 0) /* double dest? */ - dbl = 1; /* src must be dbl for dbl dest */ - dest = (t_uint64)GPR[reg]; /* get the register content */ - if (dbl) { /* is it double regs */ - if (reg & 1) { /* check for odd reg load */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - /* merge the regs into the 64bit value */ - dest = (((t_uint64)dest) << 32) | ((t_uint64)GPR[reg+1]); - } else { - /* sign extend the data value */ - dest |= (dest & MSIGN) ? D32LMASK : 0; - } - } - - /* For Base mode */ - if (i_flags & RB) { - dest = (t_uint64)BR[reg]; /* get base reg contents */ - } - - /* For register instructions */ - if (i_flags & R1) { - source = (t_uint64)GPR[sreg]; - if (dbl) { - if (sreg & 1) { - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - /* merge the regs into the 64bit value */ - source = (source << 32) | ((t_uint64)GPR[reg+1]); - } else { - /* sign extend the data value */ - source |= (source & MSIGN) ? ((t_uint64)MASK32) << 32: 0; - } - } - - /* TODO Update other history information for this instruction */ - if(hst_lnt) { - hst[hst_p].inst = IR; /* save the instruction */ - hst[hst_p].dest = dest; /* save the destination */ - hst[hst_p].src = source; /* save the source */ - hst[hst_p].reg = reg; /* save the src/dst reg */ - } - -// sim_debug(DEBUG_INST, &cpu_dev, "SW OP %x Non Based i_flags %x addr %.8x\n", OP, i_flags, addr); - switch (OP>>2) { -/* - * For op-codes=00,04,08,0c,10,14,28,2c,38,3c,40,44,60,64,68 - */ - /* Reg - Reg instruction Format (16 bit) */ - /* |--------------------------------------| */ - /* |0 1 2 3 4 5|6 7 8 |9 10 11|12 13 14 15| */ - /* | Op Code | DReg | SReg | Aug Code | */ - /* |--------------------------------------| */ - case 0x00>>2: /* HLF - HLF */ /* CPU General operations */ - switch(opr & 0xF) { /* switch on aug code */ - case 0x0: /* HALT */ - if ((modes & PRIVBIT) == 0) { /* must be privileged to halt */ - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - goto newpsd; /* Privlege violation trap */ - } - if (CPUSTATUS & 0x00000100) { /* Priv mode halt must be enabled */ - TRAPME = PRIVHALT_TRAP; /* set the trap to take */ - goto newpsd; /* Privlege mode halt trap */ - } -/*FIXME*/ reason = STOP_HALT; /* do halt for now */ - break; - case 0x1: /* WAIT */ - if (modes & PRIVBIT == 0) { /* must be privileged to wait */ - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - goto newpsd; /* Privlege violation trap */ - } - if (wait4int == 0) { - time_t result = time(NULL); -// fprintf(stderr, "Starting WAIT mode @%ju\r\n", (intmax_t)result); - sim_debug(DEBUG_CMD, &cpu_dev, "Starting WAIT mode %ju\n", (intmax_t)result); - } - wait4int = 1; /* show we are waiting for interrupt */ - i_flags |= BT; /* keep PC from being incremented while waiting */ - break; - case 0x2: /* NOP */ - break; - case 0x3: /* LCS */ - GPR[reg] = M[0x780 >> 2]; /* get console switches from memory loc 0x780 */ - set_CCs(GPR[reg], 0); /* set the CC's, CC1 = 0 */ - break; - case 0x4: /* ES */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - /* reg is reg to extend sign into from reg+1 */ - GPR[reg] = (GPR[reg+1] & FSIGN) ? FMASK : 0; - set_CCs(GPR[reg], 0); /* set CCs, CC2 & CC3 */ - break; - case 0x5: /* RND */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - temp = GPR[reg]; /* save the current contents of specified reg */ - if (GPR[reg+1] & FSIGN) { /* if sign of R+1 is set, incr R by 1 */ - temp++; /* incr temp R value */ - if (temp < GPR[reg]) /* if temp R less than R, we have overflow */ - ovr = 1; /* show we have overflow */ - GPR[reg] = temp; /* update the R value */ - } - set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - } - break; - case 0x6: /* BEI */ - if ((modes & PRIVBIT) == 0) { /* must be privileged to BEI */ - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - goto newpsd; /* Privlege violation trap */ - } - CPUSTATUS |= 0x80; /* into status word bit 24 too */ - PSD2 &= ~0x0000c000; /* clear bit 48 & 49 */ - PSD2 |= 0x00004000; /* set bit 49 only */ - SPAD[0xf5] = PSD2; /* save the current PSD2 */ - break; - case 0x7: /* UEI */ - if ((modes & PRIVBIT) == 0) { /* must be privileged to UEI */ - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - goto newpsd; /* Privlege violation trap */ - } - CPUSTATUS &= ~0x80; /* into status word bit 24 too */ - PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ - SPAD[0xf5] = PSD2; /* save the current PSD2 */ - irq_pend = 1; /* start scanning interrupts again */ - break; - case 0x8: /* EAE */ - PSD1 |= AEXPBIT; /* set the enable AEXP flag in PSD */ - CPUSTATUS |= AEXPBIT; /* into status word too */ - break; - case 0x9: /* RDSTS */ - GPR[reg] = CPUSTATUS; /* get CPU status word */ - break; - case 0xA: /* SIPU */ /* ignore for now */ - break; - case 0xB: /* INV */ /* RWCS ignore for now */ - case 0xC: /* INV */ /* WWCS ignore for now */ - break; - case 0xD: /* SEA */ - modes |= EXTDBIT; /* set new Extended flag in modes & PSD */ - PSD1 |= EXTDBIT; /* set the enable AEXP flag in PSD */ - CPUSTATUS |= EXTDBIT; /* into status word too */ - break; - case 0xE: /* DAE */ - modes &= AEXPBIT; /* set new extended flag in modes & PSD */ - PSD1 &= ~AEXPBIT; /* disable AEXP flag in PSD */ - CPUSTATUS &= ~AEXPBIT; /* into status word too */ - break; - - case 0xF: /* CEA */ - modes &= ~EXTDBIT; /* disable extended mode in modes and PSD */ - PSD1 &= ~EXTDBIT; /* disable extended mode flag in PSD */ - CPUSTATUS &= ~EXTDBIT; /* into status word too */ - break; - } - break; - case 0x04>>2: /* 0x04 SCC|RR|R1|SD|HLF - SD|HLF */ /* ANR, SMC, CMC, RPSWT */ - switch(opr & 0xF) { - case 0x0: /* ANR */ - dest &= source; /* just an and reg to reg */ - i_flags |= SCC; /* make sure we set CC's for dest value */ - break; - case 0xA: /* CMC */ /* Cache Memory Control - Diag use only */ - /* write reg to cache memory controller */ - break; - case 0x7: /* SMC */ /* Shared Memory Control Not Used */ - /* write reg to shared memory controller */ - break; - case 0xB: /* RPSWT */ /* Read Processor Status Word 2 (PSD2) */ - dest = PSD2; /* get PSD2 for user */ - break; - default: /* INV */ /* everything else is invalid instruction */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - goto newpsd; /* handle trap */ - break; - } - break; - - case 0x08>>2: /* 0x08 SCC|RR|R1|SD|HLF - */ /* ORR or ORRM */ - dest |= source; /* or the regs into dest reg */ - if (opr & 0x8) /* is this ORRM op? */ - dest &= GPR[4]; /* mask with reg 4 contents */ - break; - - case 0x0C>>2: /* 0x0c SCC|RR|R1|SD|HLF - SCC|SD|HLF */ /* EOR or EORM */ -//fprintf(stderr, "@EOR dest %.8x source %.8x\r\n", (uint32)dest, (uint32)source); - dest ^= source; /* exclusive or the regs into dest reg */ - if (opr & 0x8) /* is this EORM op? */ - dest &= GPR[4]; /* mask with reg 4 contents */ -//fprintf(stderr, "@EOR dest %.8x source %.8x\r\n", (uint32)dest, (uint32)source); - break; - - case 0x10>>2: /* 0x10 HLF - HLF */ /* CAR or (basemode SACZ ) */ - if (modes & BASEBIT) { /* handle basemode SACZ instruction */ -sacz: /* non basemode SCZ enters here */ - temp = GPR[reg]; /* get destination reg contents to shift */ - CC = 0; /* zero the CC's */ - t = 0; /* start with zero shift count */ - if (temp == 0) { - CC = CC4BIT; /* set CC4 showing dest is zero & cnt is zero too */ - } - else - if (temp & BIT0) { - CC = 0; /* clear CC4 & set count to zero */ - } - else - if (temp != 0) { /* shift non zero values */ - while ((temp & FSIGN) == 0) { /* shift the reg until bit 0 is set */ - temp <<= 1; /* shift left 1 bit */ - t++; /* increment shift count */ - } - temp <<= 1; /* shift the sign bit out */ - } - GPR[reg] = temp; /* save the shifted values */ - GPR[sreg] = t; /* set the shift cnt into the src reg */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - } else { - /* handle non basemode CAR instr */ - temp = GPR[reg] - GPR[sreg]; /* subtract src from destination value */ - set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ - } - break; - - case 0x14>>2: /* 0x14 HLF - HLF */ /* CMR compare masked with reg */ - //FIXME CMD needs both regs to be masked with R4 - temp = GPR[reg] ^ GPR[sreg]; /* exclusive or src and destination values */ - temp &= GPR[4]; /* and with mask reg (GPR 4) */ - CC = 0; /* set all CCs zero */ - if (temp == 0) /* if result is zero, set CC4 */ - CC = CC4BIT; /* set CC4 to show result 0 */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - break; - - case 0x18>>2: /* 0x18 SD|HLF - SD|HLF */ /* SBR, (basemode ZBR, ABR, TBR */ - if (modes & BASEBIT) { /* handle basemode ZBR, ABR, TBR */ - if ((opr & 0xC) == 0x0) /* SBR instruction */ - goto sbr; /* use nonbase SBR code */ - if ((opr & 0xC) == 0x4) /* ZBR instruction */ - goto zbr; /* use nonbase ZBR code */ - if ((opr & 0xC) == 0x8) /* ABR instruction */ - goto abr; /* use nonbase ABR code */ - if ((opr & 0xC) == 0xC) /* TBR instruction */ - goto tbr; /* use nonbase TBR code */ -inv: - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - goto newpsd; /* handle trap */ - - } else { /* handle non basemode SBR */ -sbr: /* handle basemode too */ - /* move the byte field bits 14-15 to bits 27-28 */ - /* or in the bit# from dest reg field bits 6-8 into bit 29-31 */ - bc = (((opr << 3) & 0x18) | reg); /* get # bits to shift right */ - bc = BIT0 >> bc; /* make a bit mask of bit number */ - t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ -//fprintf(stderr, "SBR1 bc %.8x PSD1 %.8x GPR[%d] %.8x\r\n", bc, PSD1, sreg, GPR[sreg]); - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - if (GPR[sreg] & bc) /* test the bit in src reg */ - t |= CC1BIT; /* set CC1 to the bit value */ - GPR[sreg] |= bc; /* set the bit in src reg */ - PSD1 |= t; /* update the CC's in the PSD */ -//fprintf(stderr, "SBR2 bc %.8x PSD1 %.8x GPR[%d] %.8x\r\n", bc, PSD1, sreg, GPR[sreg]); - } - break; - - case 0x1C>>2: /* 0x1C SD|HLF - SD|HLF */ /* ZBR (basemode SRA, SRL, SLA, SLL) */ - if (modes & BASEBIT) { /* handle basemode SRA, SRL, SLA, SLL */ - if ((opr & 0x60) == 0x00) /* SRA instruction */ - goto sra; /* use nonbase SRA code */ - if ((opr & 0x60) == 0x20) /* SRL instruction */ - goto srl; /* use nonbase SRL code */ - if ((opr & 0x60) == 0x40) /* SLA instruction */ - goto sla; /* use nonbase SLA code */ - if ((opr & 0x60) == 0x60) /* SLL instruction */ - goto sll; /* use nonbase SLL code */ - } else { /* handle nonbase ZBR */ -zbr: /* handle basemode too */ - /* move the byte field bits 14-15 to bits 27-28 */ - /* or in the bit# from dest reg field bits 6-8 into bit 29-31 */ - bc = (((opr << 3) & 0x18) | reg); /* get # bits to shift right */ - bc = BIT0 >> bc; /* make a bit mask of bit number */ - t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ -//fprintf(stderr, "ZBR1 bc %.8x PSD1 %.8x GPR[%d] %.8x\r\n", bc, PSD1, sreg, GPR[sreg]); - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - if (GPR[sreg] & bc) /* test the bit in src reg */ - t |= CC1BIT; /* set CC1 to the bit value */ - GPR[sreg] &= ~bc; /* reset the bit in src reg */ - PSD1 |= t; /* update the CC's in the PSD */ -//fprintf(stderr, "ZBR2 bc %.8x PSD1 %.8x GPR[%d] %.8x\r\n", bc, PSD1, sreg, GPR[sreg]); - } - break; - - case 0x20>>2: /* 0x20 HLF - HLF */ /* ABR (basemode SRAD, SRLD, SLAD, SLLD) */ - if (modes & BASEBIT) { /* handle basemode SRA, SRL, SLA, SLL */ - if ((opr & 0x60) == 0x00) /* SRAD instruction */ - goto sra; /* use nonbase SRAD code */ - if ((opr & 0x60) == 0x20) /* SRLD instruction */ - goto srl; /* use nonbase SRLD code */ - if ((opr & 0x60) == 0x40) /* SLAD instruction */ - goto sla; /* use nonbase SLAD code */ - if ((opr & 0x60) == 0x60) /* SLLD instruction */ - goto sll; /* use nonbase SLLD code */ - } else { /* handle nonbase mode ABR */ -abr: /* basemode ABR too */ - /* move the byte field bits 14-15 to bits 27-28 */ - /* or in the bit# from dest reg field bits 6-8 into bit 29-31 */ - bc = (((opr << 3) & 0x18) | reg); /* get # bits to shift right */ - bc = BIT0 >> bc; /* make a bit mask of bit number */ - temp = GPR[sreg]; /* get reg value to add bit to */ -//fprintf(stderr, "ABR bc %.8x addr %.8x PSD1 %.8x temp %.8x\r\n", bc, addr, PSD1, temp); - ovr = ((temp & FSIGN) != 0); /* set ovr to status of sign bit 0 */ - temp += bc; /* add the bit value to the reg */ - ovr ^= ((temp & FSIGN) != 0); /* set ovr if sign bit changed */ -//fprintf(stderr, "ABR bc %.8x addr %.8x PSD1 %.8x temp %.8x ovr %d\r\n", bc, addr, PSD1, temp, ovr); - GPR[sreg] = temp; /* save the new value */ - set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - } - } - break; - - case 0x24>>2: /* 0x24 HLF - SD|HLF */ /* TBR (basemode SRC) */ - if (modes & BASEBIT) { /* handle SRC basemode */ - if ((opr & 0x60) == 0x00) /* SRC instruction */ - goto src; /* use nonbase code */ - if ((opr & 0x60) == 0x40) /* SLC instruction */ - goto slc; /* use nonbase code */ - goto inv; /* else invalid */ - } else { /* handle TBR non basemode */ -tbr: /* handle basemode TBR too */ - /* move the byte field bits 14-15 to bits 27-28 */ - /* or in the bit# from dest reg field bits 6-8 into bit 29-31 */ - bc = (((opr << 3) & 0x18) | reg); /* get # bits to shift right */ - bc = BIT0 >> bc; /* make a bit mask of bit number */ - t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ -//fprintf(stderr, "TBR1 bc %.8x PSD1 %.8x GPR[%d] %.8x\r\n", bc, PSD1, sreg, GPR[sreg]); - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - if (GPR[sreg] & bc) /* test the bit in src reg */ - t |= CC1BIT; /* set CC1 to the bit value */ - PSD1 |= t; /* update the CC's in the PSD */ -//fprintf(stderr, "TBR2 bc %.8x PSD1 %.8x GPR[%d] %.8x\r\n", bc, PSD1, sreg, GPR[sreg]); - } - break; - - case 0x28>>2: /* 0x28 HLF - HLF */ /* Misc OP REG instructions */ - temp = GPR[reg]; /* get reg value */ - switch(opr & 0xF) { - - case 0x0: /* TRSW */ - if (modes & BASEBIT) - addr = temp & MASK24; /* 24 bits for based mode */ - else - addr = temp & 0x7FFFE; /* 19 bits for non based mode */ - /* we are returning to the addr in reg, set CC's from reg */ - /* update the PSD with new address */ - PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ - PSD1 = ((PSD1 & 0x87ffffff) | (temp & 0x78000000)); /* insert CCs from reg */ - i_flags |= BT; /* we branched, so no PC update */ - break; - - case 0x2: /* XCBR */ /* Exchange base registers */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - temp = BR[reg]; /* get dest reg value */ - BR[reg] = BR[sreg]; /* put source reg value int dest reg */ - BR[sreg] = temp; /* put dest reg value into src reg */ - break; - - case 0x4: /* TCCR */ /* Transfer condition codes to GPR */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - temp = CC >> 27; /* right justify CC's in reg */ - break; - - case 0x5: /* TRCC */ /* Transfer GPR to condition codes */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - PSD1 = ((PSD1 & 0x87fffffe) | (GPR[reg] << 27)); /* insert CCs from reg */ - break; - - case 0x8: /* BSUB */ /* Procedure call */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - /* if Rd field is 0 (reg is b6-8), this is a BSUB instruction */ - /* otherwise it is a CALL instruction (Rd != 0) */ - if (reg == 0) { - /* BSUB instruction */ - uint32 fp = BR[2]; /* get dword bounded frame pointer from BR2 */ - if ((BR[2] & 0x7) != 0) { - /* Fault, must be dw bounded address */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - M[fp>>2] = (PSD1 + 2) & 0x01fffffe; /* save AEXP bit and PC into frame */ - M[(fp>>2)+1] = 0x80000000; /* show frame created by BSUB instr */ - BR[3] = GPR[0]; /* GPR 0 to BR 3 (AP) */ - BR[0] = BR[2]; /* set frame pointer from BR 2 into BR 0 */ - BR[1] = BR[sreg]; /* Rs reg to BR 1 */ - PSD1 = (PSD1 & 0xff000000) | (BR[sreg] & 0xffffff); /* New PSD address */ - } else { - /* CALL instruction */ - /* get frame pointer from BR2 - 16 words & make it a dword addr */ - uint32 cfp = ((BR[2]-0x40) & 0xfffffff8); - M[cfp>>2] = (PSD1 + 2) & 0x01fffffe; /* save AEXP bit and PC from PSD1 in to frame */ - M[(cfp>>2)+1] = 0x00000000; /* show frame created by CALL instr */ - for (ix=0; ix<8; ix++) - M[(cfp>>2)+ix+2] = BR[ix]; /* save BRs 0-7 to call frame */ - for (ix=2; ix<8; ix++) - M[(cfp>>2)+ix+10] = GPR[ix]; /* save GPRs 2-7 to call frame */ - BR[3] = GPR[reg]; /* Rd to BR 3 (AP) */ - BR[0] = cfp; /* set current frame pointer into BR[0] */ - BR[2] = cfp; /* set current frame pointer into BR[2] */ - BR[1] = BR[sreg]; /* Rs reg to BR 1 */ - PSD1 = (PSD1 & 0xff000000) | (BR[sreg] & 0xffffff); /* New PSD address */ - } - break; - - case 0xC: /* TPCBR */ /* Transfer program Counter to Base Register */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - BR[reg] = PSD1 & 0xfffffe; /* save PC from PSD1 into BR */ - break; - - case 0x1: /* INV */ - case 0x3: /* INV */ - case 0x6: /* INV */ - case 0x7: /* INV */ - case 0x9: /* INV */ - case 0xA: /* INV */ - case 0xB: /* INV */ - case 0xD: /* INV */ - case 0xE: /* INV */ - case 0xF: /* INV */ - break; - } - break; - - case 0x2C>>2: /* 0x2C HLF - HLF */ /* Reg-Reg instructions */ - temp = GPR[reg]; /* reg contents specified by Rd */ - addr = GPR[sreg]; /* reg contents specified by Rs */ - bc = 0; -//fprintf(stderr, "@0x2c temp %.8x addr %.8x\r\n", temp, addr); - - switch(opr & 0xF) { - case 0x0: /* TRR */ /* SCC|SD|R1 */ - temp = addr; /* set value to go to GPR[reg] */ - bc = 1; /* set CC's at end */ - break; - - case 0x1: /* TRBR */ /* Transfer GPR to BR */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - BR[reg] = GPR[sreg]; /* copy GPR to BR */ - break; - - case 0x2: /* TBRR */ /* transfer BR to GPR */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - temp = BR[sreg]; /* set base reg value */ - bc = 1; /* set CC's at end */ - break; - - case 0x3: /* TRC */ /* Transfer register complement */ - temp = addr ^ FMASK; /* complement Rs */ - bc = 1; /* set CC's at end */ - break; - - case 0x4: /* TRN */ /* Transfer register negative */ - temp = -addr; /* negate Rs value */ - if (temp == addr) /* overflow if nothing changed */ - ovr = 1; /* set overflow flag */ - bc = 1; /* set the CC's */ - break; - - case 0x5: /* XCR */ /* exchange registers Rd & Rs */ - GPR[sreg] = temp; /* Rd to Rs */ - set_CCs(temp, ovr); /* set the CC's from original Rd */ - temp = addr; /* save the Rs value to Rd reg */ - break; - - case 0x6: /* INV */ - goto inv; - break; - - case 0x7: /* LMAP */ /* Load map reg - Diags only */ - goto inv; - break; - - case 0x8: /* TRRM */ /* SCC|SD|R1 */ - temp = addr & GPR[4]; /* transfer reg-reg masked */ - bc = 1; /* set CC's at end */ - break; - - /* CPUSTATUS bits */ - /* Bits 0-19 reserved */ - /* Bit 20 =0 Write to writable control store is disabled */ - /* =1 Write to writable control store is enabled */ - /* Bit 21 =0 Enable PROM mode */ - /* =1 Enable Alterable Control Store Mode */ - /* Bit 22 =0 Enable High Speed Floating Point Accelerator */ - /* =1 Disable High Speed Floating Point Accelerator */ - /* Bit 23 =0 Disable privileged mode halt trap */ - /* =1 Enable privileged mode halt trap */ - /* Bit 24 is reserved */ - /* bit 25 =0 Disable software trap handling (enable automatic trap handling) */ - /* =1 Enable software trap handling */ - /* Bits 26-31 reserved */ - case 0x9: /* SETCPU */ - CPUSTATUS &= 0xfffff0bf; /* zero bits that can change */ - CPUSTATUS |= (temp & 0x0f40); /* or in the new status bits */ - break; - - case 0xA: /* TMAPR */ /* Transfer map to Reg - Diags only */ - goto inv; /* not used */ - break; - - case 0xB: /* TRCM */ /* Transfer register complemented masked */ - temp = (addr ^ FMASK) & GPR[4]; /* compliment & mask */ - bc = 1; /* set the CC's */ - break; - - case 0xC: /* TRNM */ /* Transfer register negative masked */ - temp = -addr; /* complement GPR[reg] */ - if (temp == addr) /* check for overflow */ - ovr = 1; /* overflow */ - temp &= GPR[4]; /* and with negative reg */ - bc = 1; /* set the CC's */ - break; - - case 0xD: /* XCRM */ /* Exchange registers masked */ - addr &= GPR[4]; /* and Rs with mask reg */ - temp &= GPR[4]; /* and Rd with mask reg */ - GPR[sreg] = temp; /* Rs to get Rd masked value */ - set_CCs(temp, ovr); /* set the CC's from original Rd */ - temp = addr; /* save the Rs value to Rd reg */ - break; - - case 0xE: /* TRSC */ /* transfer reg to SPAD */ - t = (GPR[reg] >> 16) & 0xff; /* get SPAD address from Rd (6-8) */ - temp2 = SPAD[t]; /* get old SPAD data */ - SPAD[t] = GPR[sreg]; /* store Rs into SPAD */ -//fprintf(stderr, "TRSC SPAD[%x] old %.8x new %.8x INTS[%x] %.8x\r\n", t, temp2, SPAD[t], t, INTS[t]); - break; - - case 0xF: /* TSCR */ /* Transfer scratchpad to register */ - t = (GPR[sreg] >> 16) & 0xff; /* get SPAD address from Rs (9-11) */ - temp = SPAD[t]; /* get SPAD data into Rd (6-8) */ -//fprintf(stderr, "TSCR SPAD[%x] %.8x\r\n", t, temp); - break; - } - GPR[reg] = temp; /* save the temp value to Rd reg */ - if (bc) /* set cc's if bc set */ - set_CCs(temp, ovr); /* set the CC's */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - } - break; - -/*TODO*/ case 0x30>>2: /* 0x30 */ /* CALM */ - fprintf(stderr, "ERROR - CALM called\r\n"); - goto inv; /* TODO */ - break; - - case 0x34>>2: /* 0x34 SD|ADR - inv */ /* LA non-basemode */ - if (modes & BASEBIT) /* see if based */ - goto inv; /* invalid instruction in based mode */ - if (modes & EXTDBIT) { /* see if extended mode */ - dest = (t_uint64)addr; /* just pure 24 bit address */ - } else { /* use bits 13-31 */ - dest = (t_uint64)(addr | ((FC & 4) << 17)); /* F bit to bit 12 */ - } - break; - - case 0x38>>2: /* 0x38 SCC|SD|HLF - SD|HLF */ /* REG - REG floating point instructions */ - temp = GPR[reg]; /* reg contents specified by Rd */ - addr = GPR[sreg]; /* reg contents specified by Rs */ - switch(opr & 0xF) { - case 0x0: /* ADR */ - t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ - t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ - temp = temp + addr; /* add the values */ - if ((t == 3 && (temp & FSIGN) == 0) || - (t == 0 && (addr & FSIGN) != 0)) - ovr = 1; /* we have an overflow */ - break; - - case 0x1: /* ADRFW */ - goto inv; /* TODO */ - break; - case 0x2: /* MPRBR */ - goto inv; /* TODO */ - break; - case 0x3: /* SURFW */ - goto inv; /* TODO */ - break; - case 0x4: /* DVRFW */ - goto inv; /* TODO */ - break; - case 0x5: /* FIXW */ - goto inv; /* TODO */ - break; - case 0x6: /* MPRFW */ - goto inv; /* TODO */ - break; - case 0x7: /* FLTW */ - goto inv; /* TODO */ - break; - case 0x8: /* ADRM */ - t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ - t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ - temp = temp + addr; /* add the values */ - if ((t == 3 && (temp & FSIGN) == 0) || - (t == 0 && (temp & FSIGN) != 0)) - ovr = 1; /* we have an overflow */ - temp &= GPR[4]; /* mask the destination reg */ - break; - case 0x9: /* INV */ - goto inv; /* TODO */ - break; - case 0xA: /* DVRBR */ - goto inv; /* TODO */ - break; - case 0xB: /* SURFD */ - goto inv; /* TODO */ - break; - case 0xC: /* DVRFD */ - goto inv; /* TODO */ - break; - case 0xD: /* FIXD */ - goto inv; /* TODO */ - break; - case 0xE: /* MPRFD */ - goto inv; /* TODO */ - break; - case 0xF: /* FLTD */ - goto inv; /* TODO */ - break; - } - GPR[reg] = temp; /* temp has destination reg value */ - if ((opr & 0xF) < 6) { - set_CCs(temp, ovr); /* set the CC's */ - } - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - } - break; - - case 0x3C>>2: /* 0x3C HLF - HLF */ /* SUR and SURM */ - temp = GPR[reg]; /* get negative value to add */ - addr = -GPR[sreg]; /* reg contents specified by Rs */ - switch(opr & 0xF) { - case 0x0: /* SUR */ - t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ - t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ - temp = temp + addr; /* add the values */ - if ((t == 3 && (temp & FSIGN) == 0) || - (t == 0 && (addr & FSIGN) != 0)) - ovr = 1; /* we have an overflow */ - break; - case 0x8: /* SURM */ - t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ - t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ - temp = temp + addr; /* add the values */ - if ((t == 3 && (temp & FSIGN) == 0) || - (t == 0 && (temp & FSIGN) != 0)) - ovr = 1; /* we have an overflow */ - temp &= GPR[4]; /* mask the destination reg */ - break; - case 0x9: /* INV */ - goto inv; /* TODO */ - break; - case 0xA: /* DVRBR */ - goto inv; /* TODO */ - break; - case 0xB: /* SURFD */ - goto inv; /* TODO */ - break; - case 0xC: /* DVRFD */ - goto inv; /* TODO */ - break; - case 0xD: /* FIXD */ - goto inv; /* TODO */ - break; - case 0xE: /* MPRFD */ - goto inv; /* TODO */ - break; - case 0xF: /* FLTD */ - goto inv; /* TODO */ - break; - } - GPR[reg] = temp; /* save the result */ - if ((opr & 0xF) < 6) { - set_CCs(temp, ovr); /* set CCs for result */ - } - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - } - break; - - case 0x40>>2: /* 0x40 */ /* MPR */ - if (reg & 1) { - /* Spec fault */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - temp = GPR[reg+1]; /* get multiplicand */ - addr = GPR[sreg]; /* multiplier */ - - /* change immediate value into a 64 bit value */ - dest = ((t_uint64)(addr & FMASK)) | ((addr & FSIGN) ? D32LMASK : 0); -//fprintf(stderr, "MPR reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx\r\n", reg, GPR[reg], GPR[reg+1], dest); - source = ((t_uint64)(temp & FMASK)) | ((temp & FSIGN) ? D32LMASK : 0); -//fprintf(stderr, "MPR reg %d GPR[reg] %.8x GPR[reg+1] %.8x source %llx\r\n", reg, GPR[reg], GPR[reg+1], source); - dest = dest * source; /* do the multiply */ -//fprintf(stderr, "MPR dest result %llx\r\n", dest); - i_flags |= SD|SCC; /* save regs and set CC's */ - dbl = 1; /* double reg save */ - break; - - case 0x44>>2: /* 0x44 ADR - ADR */ /* DVR */ - /* sreg has Rs */ - if (reg & 1) { - /* Spec fault */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - /* get Rs divisor value */ - source = (t_uint64)(GPR[sreg]) | ((GPR[sreg] & FSIGN) ? D32LMASK : 0); -//fprintf(stderr, "DVR reg %d GPR[reg] %.8x GPR[reg+1] %.8x source %llx\r\n", reg, GPR[reg], GPR[reg+1], source); - /* merge the dividend regs into the 64bit value */ - dest = (((t_uint64)GPR[reg]) << 32) | ((t_uint64)GPR[reg+1]); -//fprintf(stderr, "DVR reg %d GPR[reg] %.8x GPR[reg+1] %.8x source %llx\r\n", reg, GPR[reg], GPR[reg+1], dest); - if (source == 0) { - goto doovr3; - break; - } - td = (t_int64)dest % (t_int64)source; /* remainder */ - dbl = (td < 0); /* double reg is neg remainder */ -//fprintf(stderr, "DVR remainder %llx dbl %x \r\n", td, dbl); - if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */ - td = -td; /* dividend and remainder must be same sign */ -//fprintf(stderr, "DVR fix sign %llx dbl %x source %llx dest %llx\r\n", td, dbl, source, dest); - dest = (t_int64)dest / (t_int64)source; /* now do the divide */ -//fprintf(stderr, "DVR dest %llx\r\n", dest); - if ((dest & D32LMASK) != 0 && (dest & D32LMASK) != D32LMASK) { /* test for overflow */ -doovr3: - ovr = 1; /* the quotient exceeds 31 bit, overflow */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - } - /* the original regs must be returned unchanged if aexp */ - set_CCs(temp, ovr); /* set the CC's */ -//fprintf(stderr, "DVR ovr %d reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx\r\n", ovr, reg, GPR[reg], GPR[reg+1], dest); - } else { - GPR[reg] = (uint32)(td & FMASK); /* reg gets remainder, reg+1 quotient */ - GPR[reg+1] = (uint32)(dest & FMASK); /* store quotient in reg+1 */ - set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ -//fprintf(stderr, "DVR good reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx rem %llx\r\n", reg, GPR[reg], GPR[reg+1], dest, td); - } - break; -//#endif /* SIMPLE_MODE*/ - - case 0x48>>2: /* 0x48 INV - INV */ /* unused opcodes */ - case 0x4C>>2: /* 0x4C INV - INV */ /* unused opcodes */ - default: -fprintf(stderr, "place @ UI op = %.8x\r\n", IR); - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - goto newpsd; /* handle trap */ - break; - - case 0x50>>2: /* 0x50 INV - SD|ADR */ /* LA basemode */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - if (modes & (BASEBIT|EXTDBIT)) { - dest = (t_uint64)addr; /* just pure 24 bit address */ - } else { - dest = (t_uint64)(addr | ((FC & 4) << 17)); /* F bit to bit 12 */ - } - break; - - case 0x54>>2: /* 0x54 SM|ADR - INV */ /* (basemode STWBR) */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - if (FC != 0) { /* word address only */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - dest = BR[reg]; /* save the BR to memory */ - break; - - case 0x58>>2: /* 0x58 SB|ADR - INV */ /* (basemode SUABR and LABR) */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - if ((FC & 4) != 0) { /* see if SUABR F=0 */ - dest = BR[reg] - addr; /* subtract addr from the BR and store back to BR */ - } else { /* LABR if F=1 */ - dest = addr; /* addr goes to specified BR */ - } - break; - case 0x5C>>2: /* 0x5C RM|SB|ADR - INV */ /* (basemode LWBR and BSUBM) */ - if ((modes & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - if (FC != 0) { /* word address only */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if ((FC & 0x4) != 0x4) { /* this is a LWBR instruction */ - BR[reg] = source; /* load memory location in BR */ - } else { /* this is a CALLM/BSUBM instruction */ - /* if Rd field is 0 (reg is b6-8), this is a BSUBM instruction */ - /* otherwise it is a CALLM instruction (Rd != 0) */ - if (reg == 0) { - /* BSUBM instruction */ - uint32 fp = BR[2]; /* get dword bounded frame pointer from BR2 */ - if ((BR[2] & 0x7) != 0) { - /* Fault, must be dw bounded address */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - M[fp>>2] = (PSD1+4) & 0x01fffffe; /* save AEXP bit and PC into frame */ - M[(fp>>2)+1] = 0x80000000; /* show frame created by BSUB instr */ - BR[3] = GPR[0]; /* GPR 0 to BR 3 (AP) */ - BR[0] = BR[2]; /* set frame pointer from BR 2 into BR 0 */ - BR[1] = (addr+0x80) & 0xfffffe; /* effective address to BR 1 */ - PSD1 = (PSD1 & 0xff000000) | BR[1]; /* New PSD address */ - } else { - /* CALM instruction */ - /* get frame pointer from BR2 - 16 words & make it a dword addr */ - uint32 cfp = ((BR[2]-0x40) & 0xfffffff8); - M[cfp>>2] = (PSD1+4) & 0x01fffffe; /* save AEXP bit and PC from PSD1 in to frame */ - M[(cfp>>2)+1] = 0x00000000; /* show frame created by CALL instr */ - for (ix=0; ix<8; ix++) - M[(cfp>>2)+ix+2] = BR[ix]; /* save BRs 0-7 to call frame */ - for (ix=2; ix<8; ix++) - M[(cfp>>2)+ix+10] = GPR[ix];/* save GPRs 2-7 to call frame */ - BR[3] = GPR[reg]; /* Rd to BR 3 (AP) */ - BR[0] = (uint32)cfp; /* set current frame pointer into BR[0] */ - BR[2] = (uint32)cfp; /* set current frame pointer into BR[2] */ - BR[1] = (addr + 0x80) & 0xfffffe; /* effective address to BR 1 */ - PSD1 = (PSD1 & 0xff000000) | BR[1]; /* New PSD address */ - } - } - break; - - case 0x60>>2: /* 0x60 SH|HLF - INV */ /* NOR Rd,Rs */ - if ((modes & BASEBIT)) { /* only for nonbased mode */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - goto newpsd; /* handle trap */ - } - temp = GPR[reg]; /* Rd */ - t = 0; /* no shifts yet */ - /* exponent must not be zero or all 1's */ - if (temp != 0 && temp != FMASK) { - /* non zero value or not all 1's, so normalize */ - uint32 m = temp & 0xF8000000; - /* shift left 4 bits at a time while left most 5 bits are not zero or all 1's */ - while ((m == 0) || (m == 0xF8000000)) { - temp <<= 4; /* move left 4 bits */ - t++; /* increment number times shifted */ - m = temp & 0xF8000000; /* get left most 5 bits again */ - } - /* temp value is now normalized with non zero nor all 1's value */ - GPR[reg] = temp; /* save the normalized value */ - GPR[(IR >> 20) & 7] = 0x40 - t; /* subtract shift count from 0x40 into Rs */ - } else { - GPR[(IR >> 20) & 7] = 0; /* set exponent to zero for zero value */ - } - break; - - case 0x64>>2: /* 0x64 SD|HLF - INV */ /* NORD */ - if ((modes & BASEBIT)) { /* only for nonbased mode */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - goto newpsd; /* handle trap */ - } - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - addr = GPR[reg]; /* high order 32 bits */ - temp = GPR[reg+1]; /* low order 32 bits */ - t = 0; /* zero shift count */ - if ((temp|addr) != 0 && (temp&addr) != FMASK) { - uint32 m = temp & 0xF8000000; /* upper 5 bit mask */ - /* shift until upper 5 bits are neither 0 or all 1's */ - while ((m == 0) || (m == 0xF8000000)) { - temp <<= 4; /* shift over 4 bits at a time */ - m = temp & 0xF8000000; /* upper 5 bits */ - temp |= (addr >> 28) & 0xf; /* copy in upper 4 bits from R+1 */ - addr <<= 4; /* shift 4 bits of zero int R+1 */ - t++; /* bump shift count */ - } - GPR[reg] = addr; /* save the new values */ - GPR[reg|1] = temp; - } - if (t != 0) - t = 0x40 - t; /* set the shift cnt */ - GPR[(IR >> 20) & 7] = t; /* put 0x40 - shift count or 0 into RS */ - break; - - case 0x68>>2: /* 0x68 SCC|SD|HLF - INV */ /* non basemode SCZ */ - if (modes & BASEBIT) - goto inv; /* invalid instruction */ - goto sacz; /* use basemode sacz instruction */ - - case 0x6C>>2: /* 0x6C SD|HLF - INV */ /* non basemode SRA & SLA */ - if (modes & BASEBIT) - goto inv; /* invalid instruction */ -sra: -sla: - bc = opr & 0x1f; /* get bit shift count */ - temp = GPR[reg]; /* get reg value to shift */ - t = temp & FSIGN; /* sign value */ - if (opr & 0x0040) { /* is this SLA */ - ovr = 0; /* set ovr off */ - for (ix=0; ix>= 1; /* shift bit 0 right one bit */ - temp |= t; /* restore original sign bit */ - } - GPR[reg] = temp; /* save the new value */ - } - break; - - case 0x70>>2: /* 0x70 SD|HLF - INV */ /* non-basemode SRL & SLL */ - if (modes & BASEBIT) - goto inv; /* invalid instruction in basemode */ -sll: -srl: - bc = opr & 0x1f; /* get bit shift count */ - temp = GPR[reg]; /* get reg value to shift */ -//fprintf(stderr, "before SLL/SRL dest %.8x cnt %d\r\n", temp, bc); - if (opr & 0x0040) /* is this SLL, bit 9 set */ - temp <<= bc; /* shift left #bits */ - else - temp >>= bc; /* shift right #bits */ - dest = temp; /* value to be output */ -//fprintf(stderr, "SLL/SRL dest %.8x cnt %d\r\n", (uint32)dest, bc); - break; - - case 0x74>>2: /* 0x74 SD|HLF - INV */ /* non-basemode SRC & SLC */ - if (modes & BASEBIT) - goto inv; /* invalid instruction in basemode */ -slc: -src: - bc = opr & 0x1f; /* get bit shift count */ - temp = GPR[reg]; /* get reg value to shift */ - if (opr & 0x0040) { /* is this SLC, bit 9 set */ - for (ix=0; ix>= 1; /* shift the bit out */ - if (t) - temp |= BIT0; /* put in new sign bit */ - } - } - dest = temp; /* shift result */ - break; - -/*TODO*/ - case 0x78>>2: /* 0x78 HLF - INV */ /* non-basemode SRAD & SLAD */ - if (modes & BASEBIT) /* Base mode? */ - goto inv; /* invalid instruction in basemode */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - bc = opr & 0x1f; /* get bit shift count */ - dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ - dest |= (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ - source = dest & DMSIGN; /* 64 bit sign value */ - if (opr & 0x0040) { /* is this SLAD */ - ovr = 0; /* set ovr off */ - for (ix=0; ix>32) & FMASK);/* save the hi order reg */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - if (ovr) - PSD1 |= BIT1; /* CC1 in PSD */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - } - } else { /* this is a SRAD */ - for (ix=0; ix>= 1; /* shift bit 0 right one bit */ - dest |= source; /* restore original sign bit */ - } - GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ - GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ - } - break; - - case 0x7C>>2: /* 0x7C SDD|HLF - INV */ /* non-basemode SRLD & SLLD */ - if (modes & BASEBIT) - goto inv; /* invalid instruction in basemode */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ - dest |= (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ - bc = opr & 0x1f; /* get bit shift count */ - if (opr & 0x0040) /* is this SLL, bit 9 set */ - dest <<= bc; /* shift left #bits */ - else - dest >>= bc; /* shift right #bits */ - GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ - GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ - break; - - case 0x80>>2: /* 0x80 SD|ADR - SD|ADR */ /* LEAR */ - /* convert address to real physical address */ - TRAPME = RealAddr(addr, &temp, &t); - if (TRAPME != ALLOK) - goto newpsd; /* memory read error or map fault */ - /* OS code says F bit is not transferred, so just ignore it */ -// if (FC & 4) /* see if F bit was set */ -// temp |= 0x01000000; /* set bit 7 of address */ - dest = temp; /* put in dest to go out */ -// fprintf(stderr, "LEAR Inst %.8x addr %.8x raddr %.8x PSD %.8x %.8x SPAD PSD@ %x\r\n", -// IR, addr, temp, PSD1, PSD2, SPAD[0xf5]); -// sim_debug(DEBUG_CMD, &cpu_dev, "LEAR Inst %.8x addr %.8x raddr %.8x PSD %.8x %.8x\n", -// IR, addr, temp, PSD1, PSD2); - break; - - case 0x84>>2: /* 0x84 SCC|SD|RR|RM|ADR - SD|RM|ADR */ /* ANMx */ - dest &= source; - break; - - case 0x88>>2: /* 0x88 SCC|SD|RR|RM|ADR - SD|RM|ADR */ /* ORMx */ - dest |= source; - break; - - case 0x8C>>2: /* 0x8C SCC|SD|RR|RM|ADR - SD|RM|ADR */ /* EOMx */ - dest ^= source; - break; - - case 0x90>>2: /* 0x90 SCC|RR|RM|ADR - RM|ADR */ /* CAMx */ -//fprintf(stderr, "CAMW src %llx dest %llx\r\n", source, dest); - dest -= source; - break; - - case 0x94>>2: /* 0x94 RR|RM|ADR - RM|ADR */ /* CMMx */ - //FIXME CMMD need both regs to be masked with R4 - if (dbl) { - /* we need to and both regs */ - t_uint64 nm = (((t_uint64)GPR[4]) << 32) | (((t_uint64)GPR[4]) & D32RMASK); - td = dest; /* save dest */ - dest ^= source; - dest &= nm; /* mask both regs with reg 4 contents */ -// fprintf(stderr, "CMMD PSD %x src %llx dst %llx GPR[4] %llx result %llx CC4 %x\r\n", -// PSD1, source, td, nm, dest, dest==0ll?1:0); - } else { - td = dest; /* save dest */ - dest ^= source; /* <= 32 bits, so just do lower 32 bits */ - dest &= (((t_uint64)GPR[4]) & D32RMASK); /* mask with reg 4 contents */ -// fprintf(stderr, "CMMW PSD %x src %llx dst %llx GPR[4] %llx result %llx CC4 %x\r\n", -// PSD1, source, td, ((t_uint64)GPR[4]), dest, dest==0ll?1:0); - } - CC = 0; - if (dest == 0ll) - CC |= CC4BIT; - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - PSD1 |= CC; /* update the CC's in the PSD */ - break; - - case 0x98>>2: /* 0x98 ADR - ADR */ /* SBM */ - if ((FC & 04) == 0) { - /* Fault, f-bit must be set for SBM instruction */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - - t = (CC & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ - /* use C bits and bits 6-8 (reg) to generate shift bit count */ - bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ - bc = BIT0 >> bc; /* make a bit mask of bit number */ -//fprintf(stderr, "SBM bc %.8x addr %.8x CC %0.2x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, PSD1, temp); - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - if (temp & bc) /* test the bit in memory */ - t |= CC1BIT; /* set CC1 to the bit value */ - PSD1 |= t; /* update the CC's in the PSD */ - temp |= bc; /* set the bit in temp */ -//fprintf(stderr, "SBM bc %.8x addr %.8x CC %0.2x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, PSD1, temp); - if ((TRAPME = Mem_write(addr, &temp))) /* put word back into memory */ - goto newpsd; /* memory write error or map fault */ - break; - - case 0x9C>>2: /* 0x9C ADR - ADR */ /* ZBM */ - if ((FC & 04) == 0) { - /* Fault, byte address not allowed */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - - t = (CC & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ - /* use C bits and bits 6-8 (reg) to generate shift bit count */ - bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ - bc = BIT0 >> bc; /* make a bit mask of bit number */ -//fprintf(stderr, "ZBM bc %.8x addr %.8x CC %0.2x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, PSD1, temp); - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - if (temp & bc) /* test the bit in memory */ - t |= CC1BIT; /* set CC1 to the bit value */ - PSD1 |= t; /* update the CC's in the PSD */ - temp &= ~bc; /* reset the bit in temp */ -//fprintf(stderr, "ZBM bc %.8x addr %.8x CC %0.2x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, PSD1, temp); - if ((TRAPME = Mem_write(addr, &temp))) /* put word into memory */ - goto newpsd; /* memory write error or map fault */ - break; - - case 0xA0>>2: /* 0xA0 ADR - ADR */ /* ABM */ - if ((FC & 04) == 0) { - /* Fault, byte address not allowed */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - - /* use C bits and bits 6-8 (reg) to generate shift bit count */ - bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ - bc = BIT0 >> bc; /* make a bit mask of bit number */ -//fprintf(stderr, "ABM B4 bc %.8x addr %.8x CC %0.2x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, PSD1, temp); - ovr = (temp & FSIGN) != 0; /* set ovr to status of sign bit 0 */ - temp += bc; /* add the bit value to the reg */ - ovr ^= (temp & FSIGN) != 0; /* set ovr if sign bit changed */ - set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ -//fprintf(stderr, "ABM AF bc %.8x addr %.8x CC %0.2x ovr %x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, ovr, PSD1, temp); - if ((TRAPME = Mem_write(addr, &temp))) /* put word into memory */ - goto newpsd; /* memory write error or map fault */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - break; - - case 0xA4>>2: /* 0xA4 ADR - ADR */ /* TBM */ - if ((FC & 04) == 0) { - /* Fault, byte address not allowed */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - - t = (CC & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ - /* use C bits and bits 6-8 (reg) to generate shift bit count */ - bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ - bc = BIT0 >> bc; /* make a bit mask of bit number */ -//fprintf(stderr, "TBM bc %.8x addr %.8x CC %0.2x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, PSD1, temp); - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - if (temp & bc) /* test the bit in memory */ - t |= CC1BIT; /* set CC1 to the bit value */ - PSD1 |= t; /* update the CC's in the PSD */ -//fprintf(stderr, "TBM bc %.8x addr %.8x CC %0.2x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, PSD1, temp); - break; - - case 0xA8>>2: /* 0xA8 RM|ADR - RM|ADR */ /* EXM */ - if ((FC & 04) != 0 || FC == 2) { /* can not be byte or doubleword */ - /* Fault */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - - IR = temp; /* get instruction from memory */ - if (FC == 2) /* see if right halfword specified */ - IR <<= 16; /* move over the HW instruction */ - if ((IR & 0xFC7F0000) == 0xC8070000 || - (IR & 0xFF800000) == 0xA8000000 || - (IR & 0xFC000000) == 0x80000000) { - /* Fault, attempt to execute another EXR, EXRR, EXM, or LEAR */ - goto inv; /* invalid instruction */ - } - EXM_EXR = 4; /* set PC increment for EXM */ - goto exec; /* go execute the instruction */ - - case 0xAC>>2: /* 0xAC SCC|SD|RM|ADR - SD|RM|ADR */ /* Lx */ - dest = source; /* set value to load into reg */ - break; - - case 0xB0>>2: /* 0xB0 SCC|SD|RM|ADR - SD|RM|ADR */ /* LMx */ - //FIXME LMD need both regs to be masked with R4 - if (dbl) { - /* we need to and both regs */ - t_uint64 nm = (((t_uint64)GPR[4]) << 32) | (((t_uint64)GPR[4]) & D32RMASK); - dest = source & nm; /* mask both regs with reg 4 contents */ -// fprintf(stderr, "LMD PSD %x src %llx GPR[4] %llx result %llx\r\n", PSD1, source, nm, dest); - } else { - dest = source; /* <= 32 bits, so just do lower 32 bits */ - dest &= (((t_uint64)GPR[4]) & D32RMASK); /* mask with reg 4 contents */ -// fprintf(stderr, "LMW PSD %x src %llx GPR[4] %llx result %llx\r\n", PSD1, source, ((t_uint64)GPR[4]), dest); - } - break; - - case 0xB4>>2: /* 0xB4 SCC|SD|RM|ADR - SD|RM|ADR */ /* LNx */ - dest = -source; /* set the value to load into reg */ - if (dest == source) - ovr = 1; /* set arithmetic exception status */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - } - break; - - case 0xBC>>2: /* 0xBC SCC|SD|RR|RM|ADR - SD|RM|ADR */ /* SUMx */ - source = -source; - /* Fall through */ - - case 0xE8>>2: /* 0xE8 SCC|SM|RR|RM|ADR - SM|RM|ADR */ /* ARMx */ - case 0xB8>>2: /* 0xB8 SCC|SD|RR|RM|ADR - SD|RM|ADR */ /* ADMx */ - t = (source & DMSIGN) != 0; - t |= ((dest & DMSIGN) != 0) ? 2 : 0; -//fprintf(stderr, "ARMW t %x src %llx dest %llx", t, source, dest); - dest = dest + source; - if ((t == 3) && ((dest & DMSIGN) == 0)) { - ovr = 1; -//fprintf(stderr, " @ovr0 %d", ovr); - } - if ((t == 0) && ((dest & DMSIGN) != 0)) { - ovr = 1; -//fprintf(stderr, " @ovr1 %d", ovr); - } - if ((dbl == 0) && ((dest & D32LMASK) != 0) && ((dest & D32LMASK) != D32LMASK)) { - ovr = 1; -//fprintf(stderr, " @ovr2 %d", ovr); - } - -//fprintf(stderr, " result %llx\r\n", dest); - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - } - break; - - case 0xC0>>2: /* 0xC0 SCC|SD|RM|ADR - SD|RM|ADR */ /* MPMx */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ -//fprintf(stderr, "MPM? before src %llx dest %llx\r\n", source, dest); - dest = (t_uint64)((t_int64)dest * (t_int64)source); -//fprintf(stderr, "MPM? after src %llx dest %llx\r\n", source, dest); - dbl = 1; - break; - - case 0xC4>>2: /* 0xC4 RM|ADR - RM|ADR */ /* DVMx */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } -//fprintf(stderr, "DVM reg %d GPR[reg] %.8x GPR[reg+1] %.8x source %llx\r\n", reg, GPR[reg], GPR[reg+1], source); - dest = (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ - dest |= (t_uint64)GPR[reg+1]; /* get low order reg value */ -//fprintf(stderr, "DVM reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx\r\n", reg, GPR[reg], GPR[reg+1], dest); - if (source == 0) { - goto doovr; /* we have div by zero */ - } - td = ((t_int64)dest % (t_int64)source); /* remainder */ - dbl = (td < 0); /* double reg if neg remainder */ -//fprintf(stderr, "DVM remainder %llx dbl %x \r\n", td, dbl); - if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */ - td = -td; /* dividend and remainder must be same sign */ -//fprintf(stderr, "DVM fix sign %llx dbl %x source %llx dest %llx\r\n", td, dbl, source, dest); - dest = (t_int64)dest / (t_int64)source; /* now do the divide */ -//fprintf(stderr, "DVM dest %llx\r\n", dest); - if ((dest & D32LMASK) != 0 && (dest & D32LMASK) != D32LMASK) { /* test for overflow */ -doovr: - ovr = 1; /* the quotient exceeds 31 bit, overflow */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (modes & AEXPBIT) - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - /* the original regs must be returned unchanged if aexp */ -// i_flags &= ~SD; /* remove the store to reg flag */ -// dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ -// dest |= (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ - set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ -//fprintf(stderr, "DVM ovr %d reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx\r\n", ovr, reg, GPR[reg], GPR[reg+1], dest); - } else { - GPR[reg] = (uint32)(td & FMASK); /* reg gets remainder, reg+1 quotient */ - GPR[reg+1] = (uint32)(dest & FMASK); /* store quotient in reg+1 */ - set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ -//fprintf(stderr, "DVM good reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx rem %llx\r\n", reg, GPR[reg], GPR[reg+1], dest, td); - } - break; - - case 0xC8>>2: /* 0xC8 IMM - IMM */ /* Immedate */ - temp = GPR[reg]; /* get reg contents */ - addr = IR & RMASK; /* sign extend 16 bit imm value from IR */ - if (addr & 0x8000) /* negative */ - addr |= LMASK; /* extend sign */ -//fprintf(stderr, "C8 IMM temp %.8x addr %.8x\r\n", temp, addr); - - switch(opr & 0xF) { /* switch on aug code */ - case 0x0: /* LI */ /* SCC | SD */ - GPR[reg] = addr; /* put immediate value into reg */ - set_CCs(addr, ovr); /* set the CC's, CC1 = ovr */ - break; - - case 0x2: /* SUI */ - addr = -addr; /* just make value a negative add */ - /* drop through */ - case 0x1: /* ADI */ - t = (temp & FSIGN) != 0; /* set flag for sign bit not set in reg value */ - t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the extended immediate value */ - temp = temp + addr; /* now add the numbers */ - if ((t == 3 && (temp & FSIGN) == 0) || - (t == 0 && (temp & FSIGN) != 0)) - ovr = 1; /* we have an overflow */ - GPR[reg] = temp; /* save the result */ - set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (modes & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - } - break; - - case 0x3: /* MPI */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - /* change immediate value into a 64 bit value */ - source = ((t_uint64)(addr & FMASK)) | ((addr & FSIGN) ? D32LMASK : 0); -//fprintf(stderr, "MPI reg %d GPR[reg] %.8x GPR[reg+1] %.8x source %llx\r\n", reg, GPR[reg], GPR[reg+1], source); - temp = GPR[reg+1]; /* get reg multiplier */ - dest = ((t_uint64)(temp & FMASK)) | ((temp & FSIGN) ? D32LMASK : 0); -//fprintf(stderr, "MPI reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx\r\n", reg, GPR[reg], GPR[reg+1], dest); - dest = dest * source; /* do the multiply */ -//fprintf(stderr, "MPI dest result %llx\r\n", dest); - i_flags |= SD|SCC; /* save regs and set CC's */ - dbl = 1; /* double reg save */ - break; - - case 0x4: /* DVI */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - /* change immediate value into a 64 bit value */ - source = ((t_uint64)(addr & FMASK)) | ((addr & FSIGN) ? D32LMASK : 0); -//fprintf(stderr, "DVI reg %d GPR[reg] %.8x GPR[reg+1] %.8x source %llx\r\n", reg, GPR[reg], GPR[reg+1], source); - if (source == 0) { - goto doovr2; - } - dest = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ - dest |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ -//fprintf(stderr, "DVI reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx\r\n", reg, GPR[reg], GPR[reg+1], dest); - td = ((t_int64)dest % (t_int64)source); /* remainder */ - dbl = (td < 0); /* double reg if neg remainder */ -//fprintf(stderr, "DVI remainder %llx dbl %x \r\n", td, dbl); - if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */ - td = -td; /* dividend and remainder must be same sign */ -//fprintf(stderr, "DVI fix sign %llx dbl %x source %llx dest %llx\r\n", td, dbl, source, dest); - dest = (t_int64)dest / (t_int64)source; /* now do the divide */ -//fprintf(stderr, "DVI dest %llx\r\n", dest); - if ((dest & D32LMASK) != 0 && (dest & D32LMASK) != D32LMASK) { /* test for overflow */ -doovr2: - ovr = 1; /* the quotient exceeds 31 bit, overflow */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (modes & AEXPBIT) - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - /* the original regs must be returned unchanged if aexp */ - /* put reg values back in dest for CC test */ -// dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ -// dest |= (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ - set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ -// i_flags |= SCC; /* set CC's */ -//fprintf(stderr, "DVI ovr %d reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx\r\n", ovr, reg, GPR[reg], GPR[reg+1], dest); - } else { - GPR[reg] = (uint32)(td & FMASK); /* reg gets remainder, reg+1 quotient */ - GPR[reg+1] = (uint32)(dest & FMASK); /* store quotient in reg+1 */ - set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ -//fprintf(stderr, "DVI good reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx rem %llx\r\n", reg, GPR[reg], GPR[reg+1], dest, td); - } - break; - - case 0x5: /* CI */ /* SCC */ - temp = ((int)temp - (int)addr); /* subtract imm value from reg value */ - set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ -//fprintf(stderr, "CI IMM temp %.8x addr %.8x PSD1 %.8x flags %.8x\r\n", temp, addr, PSD1, i_flags); - break; - -/* SVC instruction format C806 */ -/* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ -/* |00 01 02 03 04 05|06 07 08|09 10 11|12 13 14 15|16 17 18 19|20 21 22 23 24 25 26 27 28 29 30 31| */ -/* | Op Code | N/U | N/U | Aug | SVC Index | SVC Call Number | */ -/* | 1 1 0 0 1 0| 0 0 0| 0 0 0| 0 1 1 0| x x x x| x x x x x x x x x x x x| */ -/* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ -/* */ - case 0x6: /* SVC none - none */ /* Supervisor Call Trap */ - { -#if 0 - int j; - char n[9]; - uint32 dqe = M[0x8e8>>2]; - for (j=0; j<8; j++) { - n[j] = (M[((dqe+0x18)>>2)+(j/4)] >> ((3-(j&7))*8)) & 0xff; - if (n[j] == 0) - n[j] = 0x20; - } - n[8] = 0; -#endif - addr = SPAD[0xf0]; /* get trap table memory address from SPAD (def 80) */ -//fprintf(stderr, "SVC 1 IMM temp %.8x addr %.8x PSD1 %.8x flags %.8x\r\n", temp, addr, PSD1, i_flags); - if (addr == 0 || addr == 0xffffffff) { /* see if secondary vector table set up */ - TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ - goto newpsd; /* program error */ - } - addr = addr + (0x06 << 2); /* addr has mem addr of SVC trap vector (def 98) */ - temp = M[addr >> 2]; /* get the secondary trap table address from memory */ -//fprintf(stderr, "SVC 2 IMM temp %.8x addr %.8x PSD1 %.8x temp2 %.8x\r\n", temp, addr, PSD1, temp2); - if (temp == 0 || temp == 0xffffffff) { /* see if ICB set up */ - TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ - goto newpsd; /* program error */ - } - temp2 = ((IR>>12) & 0x0f) << 2; /* get SVC index from IR */ -//fprintf(stderr, "SVC 2a IMM temp %.8x addr %.8x PSD1 %.8x temp2 %.8x\r\n", temp, addr, PSD1, temp2>>2); - t = M[(temp+temp2)>>2]; /* get secondary trap vector address ICB address */ - if (t == 0 || t == 0xffffffff) { /* see if ICB set up */ - TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ - goto newpsd; /* program error */ - } -//fprintf(stderr, "SVC 3 IMM temp %.8x svca %.8x PSD1 %.8x temp2 %.8x\r\n", temp+temp2, t, PSD1, temp2); - bc = PSD2 & 0x3ffc; /* get copy of cpix */ - M[t>>2] = (PSD1+4) & 0xfffffffe; /* store PSD 1 + 1W to point to next instruction */ - M[(t>>2)+1] = PSD2; /* store PSD 2 */ - PSD1 = M[(t>>2)+2]; /* get new PSD 1 */ - PSD2 = (M[(t>>2)+3] & ~0x3ffc) | bc; /* get new PSD 2 w/old cpix */ - M[(t>>2)+4] = IR&0xFFF; /* store call number */ -#if 0 -fprintf(stderr, "SVC @ %.8x SVC %x,%x PSD1 %.8x PSD2 %.8x SPAD PSD@ %x C.CURR %x LMN %s\r\n", OPSD1, temp2>>2, IR&0xFFF, PSD1, PSD2, SPAD[0xf5], dqe, n); -fprintf(stderr, " R0=%x R1=%x R2=%x R3=%x", GPR[0], GPR[1], GPR[2], GPR[3]); -fprintf(stderr, " R4=%x R5=%x R6=%x R7=%x", GPR[4], GPR[5], GPR[6], GPR[7]); -fprintf(stderr, "\r\n"); - if (((temp2>>2) == 1) && ((IR&0xfff) == 0x75)) -fprintf(stderr, "SVC %x,%x GPR[6] %x GPR[6] %x\r\n", temp2>>2, IR&0xfff, GPR[6], GPR[7]); -#endif - /* set the mode bits and CCs from the new PSD */ - CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ - modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ - /* set new map mode and interrupt blocking state in CPUSTATUS */ - if (PSD2 & MAPBIT) { - CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ - modes |= MAPMODE; /* set mapped mode */ - } else - CPUSTATUS &= 0xff7fffff; /* reset bit 8 of cpu status */ - /* set interrupt blocking state */ - if ((PSD2 & 0x8000) == 0) { /* is it retain blocking state */ - if (PSD2 & 0x4000) /* no, is it set blocking state */ - CPUSTATUS |= 0x80; /* yes, set blk state in cpu status bit 24 */ - else { - CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ - irq_pend = 1; /* start scanning interrupts again */ - } - } - PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ - if (CPUSTATUS & 0x80) /* see if old mode is blocked */ - PSD2 |= 0x00004000; /* set to blocked state */ - - PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ - SPAD[0xf5] = PSD2; /* save the current PSD2 */ - goto newpsd; /* new psd loaded */ - } - break; - - case 0x7: /* EXR */ - IR = temp; /* get instruction to execute */ - if (addr & 2) /* if bit 30 set, instruction is in right hw, do EXRR */ - IR <<= 16; /* move instruction to left HW */ - if ((IR & 0xFC7F0000) == 0xC8070000 || - (IR & 0xFF800000) == 0xA8000000) { - /* Fault, attempt to execute another EXR, EXRR, or EXM */ - goto inv; /* invalid instruction */ - } - EXM_EXR = 4; /* set PC increment for EXR */ - goto exec; - break; - - /* these instruction were never used by MPX, only diags */ - case 0x8: /* SEM */ - case 0x9: /* LEM */ - case 0xA: /* CEMA */ - case 0xB: /* INV */ - case 0xC: /* INV */ - case 0xD: /* INV */ - case 0xE: /* INV */ - case 0xF: /* INV */ - goto inv; /* invalid instruction */ - break; - } - break; - - case 0xCC>>2: /* 0xCC ADR - ADR */ /* LF */ - /* For machines with Base mode 0xCC08 stores base registers */ - if ((FC & 3) != 0) { /* must be word address */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - bc = addr & 0x20; /* bit 26 initial value */ - while (reg < 8) { - if (bc != (addr & 0x20)) { /* test for crossing file boundry */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if (FC & 0x4) /* LFBR? */ - TRAPME = Mem_read(addr, &BR[reg]); /* read the base reg */ - else /* LF */ - TRAPME = Mem_read(addr, &GPR[reg]); /* read the GPR reg */ - if (TRAPME) /* TRAPME has error */ - goto newpsd; /* go execute the trap now */ - reg++; /* next reg to write */ - addr += 4; /* next addr */ - } - break; - - case 0xD0>>2: /* 0xD0 SD|ADR - INV */ /* LEA none basemode only */ -//fprintf(stderr, "Got LEA @ addr %x\\r\n", addr); - dest = (t_uint64)(addr); - break; - - case 0xD4>>2: /* 0xD4 SM|ADR - SM|ADR */ /* STx */ - break; - - case 0xD8>>2: /* 0xD8 SM|ADR - SM|ADR */ /* STMx */ - //FIXME STMD needs both regs to be masked with R4 - if (dbl) { - /* we need to and both regs */ - td = dest; - t_uint64 nm = (((t_uint64)GPR[4]) << 32) | (((t_uint64)GPR[4]) & D32RMASK); - dest &= nm; /* mask both regs with reg 4 contents */ -// fprintf(stderr, "STMD PSD %x src %llx GPR[4] %llx result %llx\r\n", -// PSD1, td, nm, dest); - } else { - td = dest; - dest &= (((t_uint64)GPR[4]) & D32RMASK); /* mask with reg 4 contents */ -// fprintf(stderr, "STMW PSD %x src %llx GPR[4] %llx result %llx\r\n", -// PSD1, td, ((t_uint64)GPR[4]), dest); - } - break; - - case 0xDC>>2: /* 0xDC INV - */ /* INV nonbasemode (STFx basemode) */ - /* DC00 STF */ /* DC08 STFBR */ - if ((FC & 0x4) && (CPU_MODEL <= MODEL_27)) { - /* basemode undefined for 32/7x & 32/27 */ /* TODO check this */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - goto newpsd; /* handle trap */ - } - /* For machines with Base mode 0xDC08 stores base registers */ - if ((FC & 3) != 0) { /* must be word address */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - bc = addr & 0x20; /* bit 26 initial value */ - while (reg < 8) { - if (bc != (addr & 0x20)) { /* test for crossing file boundry */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if (FC & 0x4) /* STFBR? */ - TRAPME = Mem_write(addr, &BR[reg]); /* store the base reg */ - else /* STF */ - TRAPME = Mem_write(addr, &GPR[reg]); /* store the GPR reg */ - if (TRAPME) /* TRAPME has error */ - goto newpsd; /* go execute the trap now */ - reg++; /* next reg to write */ - addr += 4; /* next addr */ - } - break; - - /* TODO */ - case 0xE0>>2: /* 0xE0 SCC|SD|RM|ADR - SD|RM|ADR */ /* ADFx, SUFx */ - if ((FC & 3) != 0) { /* must be word address */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if (opr & 0x0008) { /* Was it ADFx? */ - /* TODO ADF? call here */ - goto inv; - } else { - /* TODO SUF? call here */ - goto inv; - } /* it is SUFx */ - break; - - /* TODO */ - case 0xE4>>2: /* 0xE4 SCC|RM|ADR - RM|ADR */ /* MPFx, DVFx */ - if ((FC & 3) != 0) { /* must be word address */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if (opr & 0x0008) { /* Was it MPFx? */ - /* TODO MPF? call here */ - goto inv; - } else { - /* TODO DVF? call here */ - goto inv; - } /* it is DVFx */ - break; - - case 0xEC>>2: /* 0xEC ADR - ADR */ /* Branch unconditional or Branch True */ - /* GOOF alert, the assembler sets bit 31 to 1 so this test will fail*/ - /* so just test for F bit and go on */ - /* if ((FC & 5) != 0) { */ - if ((FC & 4) != 0) { - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - CC = PSD1 & 0x78000000; /* get CC's if any */ - switch(reg) { - case 0: t = 1; break; - case 1: t = (CC & CC1BIT) != 0; break; - case 2: t = (CC & CC2BIT) != 0; break; - case 3: t = (CC & CC3BIT) != 0; break; - case 4: t = (CC & CC4BIT) != 0; break; - case 5: t = (CC & (CC2BIT|CC4BIT)) != 0; break; - case 6: t = (CC & (CC3BIT|CC4BIT)) != 0; break; - case 7: t = (CC & (CC1BIT|CC2BIT|CC3BIT|CC4BIT)) != 0; break; - } -//fprintf(stderr, "BCT t %.8x addr %.8x CC %.8x PSD1 %.8x\r\n", t, addr, CC, PSD1); - if (t) { /* see if we are going to branch */ - /* we are taking the branch, set CC's if indirect, else leave'm */ - if (IR & IND) /* see if CCs from last indirect location are wanted */ - PSD1 = (PSD1 & 0x87fffffe) | CC; /* insert last CCs */ - /* update the PSD with new address */ - PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ - i_flags |= BT; /* we branched, so no PC update */ -//fprintf(stderr, "BR t %.8x addr %.8x PSD1 %.8x\r\n", t, addr, PSD1); - } - /* branch not taken, go do next instruction */ - break; - - case 0xF0>>2: /* 0xF0 ADR - ADR */ /* Branch False or Branch Function True */ - /* GOOF alert, the assembler sets bit 31 to 1 so this test will fail*/ - /* so just test for F bit and go on */ - /* if ((FC & 5) != 0) { */ - if ((FC & 4) != 0) { - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - CC = PSD1 & 0x78000000; /* get CC's if any */ - switch(reg) { - case 0: t = (GPR[4] & (0x8000 >> ((CC >> 27) & 0xf))) != 0; break; - case 1: t = (CC & CC1BIT) == 0; break; - case 2: t = (CC & CC2BIT) == 0; break; - case 3: t = (CC & CC3BIT) == 0; break; - case 4: t = (CC & CC4BIT) == 0; break; - case 5: t = (CC & (CC2BIT|CC4BIT)) == 0; break; - case 6: t = (CC & (CC3BIT|CC4BIT)) == 0; break; - case 7: t = (CC & (CC1BIT|CC2BIT|CC3BIT|CC4BIT)) == 0; break; - } -//fprintf(stderr, "BCF reg %d t %.8x addr %.8x CC %.8x PSD1 %.8x\r\n", reg, t, addr, CC, PSD1); - if (t) { /* see if we are going to branch */ - /* we are taking the branch, set CC's if indirect, else leave'm */ - /* update the PSD with new address */ - PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ - i_flags |= BT; /* we branched, so no PC update */ - if (IR & IND) /* see if CCs from last indirect location are wanted */ - PSD1 = (PSD1 & 0x87fffffe) | CC; /* insert last CCs */ -//fprintf(stderr, "BR t %.8x addr %.8x PSD1 %.8x\r\n", t, addr, PSD1); - } - break; - - case 0xF4>>2: /* 0xF4 RR|SD|ADR - RR|SB|WRD */ /* Branch increment */ - dest += 1 << ((IR >> 21) & 3); /* use bits 9 & 10 to incr reg */ - if (dest != 0) { /* if reg is not 0, take the branch */ - /* we are taking the branch, set CC's if indirect, else leave'm */ - /* update the PSD with new address */ -#if 1 -/* FIXME */ if (PC == (addr & 0x7FFFC)) { /* BIB to current PC, bump branch addr */ - addr += 4; -// fprintf(stderr, "BI? stopping BIB $ addr %x PC %x\r\n", addr, PC); - } -#endif - PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ - if (IR & IND) /* see if CCs from last indirect location are wanted */ - PSD1 = (PSD1 & 0x87fffffe) | CC; /* insert last CCs */ - i_flags |= BT; /* we branched, so no PC update */ - } - break; - - case 0xF8>>2: /* 0xF8 SM|ADR - SM|ADR */ /* ZMx, BL, BRI, LPSD, LPSDCM, TPR, TRP */ - switch((opr >> 7) & 0x7) { /* use bits 6-8 to determine instruction */ - case 0x0: /* ZMx F80x */ /* SM */ - dest = 0; /* destination value is zero */ - i_flags |= SM; /* SM not set so set it to store value */ - break; - case 0x1: /* BL F880 */ - /* copy CC's from instruction and PC incremented by 4 */ - GPR[0] = ((PSD1 & 0x78000000) | (PSD1 & 0x7fffe)) + 4; - if (IR & IND) /* see if CC from last indirect loacation are wanted */ - GPR[0] = (CC | (PSD1 & 0x7fffe)) + 4; /* set CC's and incremented PC */ - /* update the PSD with new address */ - PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); - i_flags |= BT; /* we branched, so no PC update */ - break; - - case 0x3: /* LPSD F980 */ - /* fall through */; - case 0x5: /* LPSDCM FA80 */ - { -#if 0 -int j; -char n[9]; -uint32 dqe = M[0x8e8>>2]; -for (j=0; j<8; j++) { - n[j] = (M[((dqe+0x18)>>2)+(j/4)] >> ((3-(j&7))*8)) & 0xff; - if (n[j] == 0) - n[j] = 0x20; -} -n[8] = 0; -#endif - CPUSTATUS |= 0x40; /* enable software traps */ - /* this will allow attn and */ - /* power fail traps */ - if ((TRAPME = Mem_read(addr, &PSD1))) { /* get PSD1 from memory */ - goto newpsd; /* memory read error or map fault */ - } - if ((TRAPME = Mem_read(addr+4, &PSD2))) { /* get PSD2 from memory */ - goto newpsd; /* memory read error or map fault */ - } - /* set the mode bits and CCs from the new PSD */ - CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ - modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ - /* set new map mode and interrupt blocking state in CPUSTATUS */ - if (PSD2 & MAPBIT) { - CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ - modes |= MAPMODE; /* set mapped mode */ - } else - CPUSTATUS &= 0xff7fffff; /* reset bit 8 of cpu status */ - /* set interrupt blocking state */ - if ((PSD2 & 0x8000) == 0) { /* is it retain blocking state */ - if (PSD2 & 0x4000) /* no, is it set blocking state */ - CPUSTATUS |= 0x80; /* yes, set blk state in cpu status bit 24 */ - else { - CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ - irq_pend = 1; /* start scanning interrupts again */ - } - } - PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ - if (CPUSTATUS & 0x80) /* see if old mode is blocked */ - PSD2 |= 0x00004000; /* set to blocked state */ - - /* TRY if cpix is zero, copy cpix from PSD2 in SPAD[0xf5] */ - if ((PSD2 & 0x3fff) == 0) - PSD2 |= (SPAD[0xf5] & 0x3fff); /* use new cpix */ - - if (opr & 0x0200) { /* Was it LPSDCM? */ - /* map bit must be on to load maps */ - if (PSD2 & MAPBIT) { -#if 0 - // FIXME DEBUG EDIT -// if (n[0] == 'E' && n[1] == 'D' && n[2] == 'I' && n[3] == 'T') -// traceme = trstart; /* start tracing */ -traceme++; /* start trace */ -//if (traceme >= trstart) { -fprintf(stderr, "LPSDCM #%d LOAD MAPS PSD1 %x PSD2 %x SPAD PSD2 %x CPUSTATUS %x C.CURR %x LMN %s\r\n", traceme, PSD1, PSD2, SPAD[0xf5], CPUSTATUS, dqe, n); -fprintf(stderr, " R0=%x R1=%x R2=%x R3=%x", GPR[0], GPR[1], GPR[2], GPR[3]); -fprintf(stderr, " R4=%x R5=%x R6=%x R7=%x", GPR[4], GPR[5], GPR[6], GPR[7]); -fprintf(stderr, "\r\n"); -//reason = STOP_HALT; /* do halt for now */ -//} -#endif - /* set mapped mode in cpu status */ - CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ - /* we need to load the new maps */ - TRAPME = load_maps(&PSD1); /* load maps for new PSD */ - PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ - SPAD[0xf5] = PSD2; /* save the current PSD2 */ - sim_debug(DEBUG_EXP, &cpu_dev, - "LPSDCM MAPS LOADED TRAPME = %x PSD1 %x PSD2 %x CPUSTATUS %x\n", - TRAPME, PSD1, PSD2, CPUSTATUS); - } - PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ - } else { - /* LPSD */ -//traceme++; /* start trace */ -#if 0 -sim_debug(DEBUG_EXP, &cpu_dev, "LPSD PSD1 %x PSD2 %x CPUSTATUS %x\n", PSD1, PSD2, CPUSTATUS); -fprintf(stderr, "LPSD PSD1 %x PSD2 %x SPAD PSD2 %x CPUSTATUS %x C.CURR %x LMN %s\r\n", - PSD1, PSD2, SPAD[0xf5], CPUSTATUS, dqe, n); -fprintf(stderr, " R0=%x R1=%x R2=%x R3=%x", GPR[0], GPR[1], GPR[2], GPR[3]); -fprintf(stderr, " R4=%x R5=%x R6=%x R7=%x", GPR[4], GPR[5], GPR[6], GPR[7]); -fprintf(stderr, "\r\n"); -#endif - } -} - /* TRAPME can be error from LPSDCM or OK here */ - skipinstr = 1; /* skip next interrupt test only once */ - goto newpsd; /* load the new psd */ - break; - - case 0x4: /* JWCS */ /* not used in simulator */ - case 0x2: /* BRI */ /* TODO - only for 32/55 or 32/7X in PSW mode */ - case 0x6: /* TRP */ - case 0x7: /* TPR */ - TRAPME = UNDEFINSTR_TRAP; /* trap condition */ - goto newpsd; /* undefined instruction trap */ - break; - } - break; - -/* F Class I/O device instruction format */ -/* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ -/* |00 01 02 03 04 05|06 07 08|09 10 11 12|13 14 15|16|17 18 19 20 21 22 23|24 25 26 27 28 29 30 31| */ -/* | Op Code | Reg | I/O type | Aug |0 | Channel Address | Device Sub-address | */ -/* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ -/* */ -/* E Class I/O device instruction format */ -/* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ -/* |00 01 02 03 04 05|06 07 08 09 10 11 12|13 14 15|16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31| */ -/* | Op Code | Device Number | Aug | Command Code | */ -/* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ -/* */ - case 0xFC>>2: /* 0xFC IMM - IMM */ /* XIO, CD, TD, Interrupt Control */ - if ((modes & PRIVBIT) == 0) { /* must be privileged to do I/O */ - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - TRAPSTATUS |= 0x1000; /* set Bit 19 of Trap Status word */ - goto newpsd; /* Privlege violation trap */ - } - if ((opr & 0x7) != 0x07) { /* aug is 111 for XIO instruction */ - /* Process Non-XIO instructions */ - uint32 status = 0; /* status returned from device */ - uint32 device = (opr >> 3) & 0x7f; /* get device code */ - uint32 prior = device; /* interrupt priority */ - t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - addr = SPAD[0xf1] + (prior<<2); /* vector address in SPAD */ - addr = M[addr>>2]; /* get the interrupt context block addr */ -//fprintf(stderr, "CD/TD etc device %x intr %x spad %.8x addr %x\r\n", device, prior, t, addr); - - switch(opr & 0x7) { /* use bits 13-15 to determine instruction */ - case 0x0: /* EI FC00 Enable Interrupt */ - prior = (opr >> 3) & 0x7f; /* get priority level */ - /* SPAD entries for interrupts begin at 0x80 */ - t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - if (t == 0 || t == 0xffffffff) /* if not set up, die */ - goto syscheck; /* system check */ - INTS[prior] |= INTS_ENAB; /* enable specified int level */ - SPAD[prior+0x80] |= SINT_ENAB; /* enable in SPAD too */ - irq_pend = 1; /* start scanning interrupts again */ -//fprintf(stderr, "EIO EI intr %.2x SPAD %.8x\r\n", prior, t); - if (prior == 0x18) /* is this the clock starting */ - rtc_setup(1, prior); /* tell clock to start */ - if (prior == 0x5f) /* is this the initerval timer starting */ - itm_setup(1, prior); /* tell timer to start */ - break; - - case 0x1: /* DI FC01 */ - prior = (opr >> 3) & 0x7f; /* get priority level */ - /* SPAD entries for interrupts begin at 0x80 */ - t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - if (t == 0 || t == 0xffffffff) /* if not set up, die */ - goto syscheck; /* system check */ - INTS[prior] &= ~INTS_ENAB; /* disable specified int level */ - INTS[prior] &= ~INTS_REQ; /* clears any requests also */ - SPAD[prior+0x80] &= ~SINT_ENAB; /* disable in SPAD too */ -//fprintf(stderr, "EIO DI intr %.2x SPAD %.8x\r\n", prior, t); - if (prior == 0x18) /* is this the clock stopping */ - rtc_setup(0, prior); /* tell clock to stop */ - if (prior == 0x5f) /* is this the initerval timer stopping */ - itm_setup(0, prior); /* tell timer to stop */ - break; - - case 0x2: /* RI FC02 */ - prior = (opr >> 3) & 0x7f; /* get priority level */ - /* SPAD entries for interrupts begin at 0x80 */ - t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - if (t == 0 || t == 0xffffffff) /* if not set up, die */ - goto syscheck; /* system check */ - INTS[prior] |= INTS_REQ; /* set the request flag for this level */ - irq_pend = 1; /* start scanning interrupts again */ -//fprintf(stderr, "EIO RI intr %.2x SPAD %.8x\r\n", prior, t); - break; - - case 0x3: /* AI FC03 */ - prior = (opr >> 3) & 0x7f; /* get priority level */ - /* SPAD entries for interrupts begin at 0x80 */ - t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - if (t == 0 || t == 0xffffffff) /* if not set up, die */ - goto syscheck; /* system check */ - INTS[prior] |= INTS_ACT; /* activate specified int level */ -//fprintf(stderr, "EIO AI intr %.2x SPAD %.8x\r\n", prior, t); - break; - - case 0x4: /* DAI FC04 */ - prior = (opr >> 3) & 0x7f; /* get priority level */ - /* SPAD entries for interrupts begin at 0x80 */ - t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - if (t == 0 || t == 0xffffffff) /* if not set up, die */ - goto syscheck; /* system check */ - INTS[prior] &= ~INTS_ACT; /* deactivate specified int level */ - SPAD[prior+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ -//fprintf(stderr, "EIO DAI intr %.2x SPAD %.8x INTS[%x] %x\r\n", prior, t, prior, INTS[prior]); - irq_pend = 1; /* start scanning interrupts again */ - skipinstr = 1; /* skip interrupt test */ - /* instruction following a DAI can not be interrupted */ - /* skip tests for interrupts if this is the case */ - break; - - case 0x5: /* TD FC05 */ /* bits 13-15 is test code type */ - case 0x6: /* CD FC06 */ - /* If CD or TD, make sure device is not F class device */ - /* the channel must be defined as a non class F I/O channel in SPAD */ - /* if class F, the system will generate a system check trap */ - t = SPAD[device]; /* get spad entry for channel */ - if (t == 0 || t == 0xffffffff) /* if not set up, die */ - goto syscheck; /* system check */ -//fprintf(stderr, "EIO TD/CD chan %.4x spad %.8x\r\n", device, t); - if ((t & 0x0f000000) == 0x0f000000) { /* class in bits 4-7 */ -syscheck: - TRAPME = SYSTEMCHK_TRAP; /* trap condition if F class */ - TRAPSTATUS &= ~BIT0; /* class E error bit */ - TRAPSTATUS &= ~BIT1; /* I/O processing error */ - goto newpsd; /* machine check trap */ - } - if (opr & 0x1) { /* see if CD or TD */ - /* process a TD */ -// if ((TRAPME = testEIO(device, testcode, &status))) -// goto newpsd; /* error returned, trap cpu */ - /* return status has new CC's in bits 1-4 of status word */ - PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status CCs */ -//fprintf(stderr, "EIO TD chan %.4x spad %.8x\r\n", device, t); - goto inv; /* invalid instruction until I fix it */ - } else { - /* process a CD */ -// if ((TRAPME = startEIO(device, &status))) -// goto newpsd; /* error returned, trap cpu */ -// t = SPAD[device]; /* get spad entry for channel */ - /* t has spad entry for device */ - /* get the 1's comp of interrupt address from bits 9-15 SPAD entry */ - ix = (t & 0x007f0000) >> 16; /* get the 1's comp of int level */ -//fprintf(stderr, "XIO1 chan %8x intr %8x spad %.8x\r\n", chan, ix, bc); - ix = 127 - ix; /* get positive number for interrupt */ -//fprintf(stderr, "XIO2 chan %x intr %x spad %.8x\r\n", chan, ix, bc); - temp = (IR & 0x7f); /* get cmd from instruction */ - if (device == 0x7f) { -//fprintf(stderr, "Interval Timer CD call cmd %x GPR[0] %x intr %x\r\n", temp, GPR[0], ix); - status = itm_rdwr(temp, GPR[0], ix); /* read/write the interval timer */ -//fprintf(stderr, "Interval Timer CD return status %x cmd %x GPR[0] %x intr %x\r\n", status, temp, GPR[0], ix); - if (temp != 0x39) /* this cmd does not return value */ - GPR[0] = status; /* return count in reg 0 */ - /* No CC's going out */ - } else { - goto inv; /* invalid instruction until I fix it */ - } - } - break; - case 0x7: /* XIO FC07*/ /* should never get here */ - break; - } - break; /* skip over XIO code */ - } - - /* Process XIO instructions */ - /* if reg is non-zero, add reg to 15 bits from instruction */ - if (reg) - temp2 = (IR & 0x7fff) + (GPR[reg] & 0x7fff); /* set new chan/suba into IR */ - else - temp2 = (IR & 0x7fff); /* set new chan/suba into IR */ - lchan = (temp2 & 0x7F00) >> 8; /* get 7 bit logical channel address */ - suba = temp2 & 0xFF; /* get 8 bit subaddress */ - /* the channel must be defined as a class F I/O channel in SPAD */ - /* if not class F, the system will generate a system check trap */ - t = SPAD[lchan]; /* get spad entry for channel */ - if (t == 0 || t == 0xffffffff) /* if not set up, die */ - goto syscheck; /* machine check */ -//fprintf(stderr, "XIO chan %x sa %x spad %.8x\r\n", chan, suba, t); -//sim_debug(DEBUG_EXP, &cpu_dev, "$$ XIO lchan %x sa %x spad %.8x\n", lchan, suba, t); - if ((t & 0x0f000000) != 0x0f000000) { /* class in bits 4-7 */ -mcheck: - TRAPME = MACHINECHK_TRAP; /* trap condition */ - TRAPSTATUS |= BIT0; /* class F error bit */ - TRAPSTATUS &= ~BIT1; /* I/O processing error */ - goto newpsd; /* machine check trap */ - } - /* get real channel from spad device entry */ - chan = (t & 0x7f00) >> 8; /* real channel */ - /* get the 1's comp of interrupt address from bits 9-15 SPAD entry */ - ix = (t & 0x007f0000) >> 16; /* get the 1's comp of int level */ -//fprintf(stderr, "XIO1 chan %8x intr %8x spad %.8x\r\n", chan, ix, bc); - ix = 127 - ix; /* get positive number for interrupt */ -//fprintf(stderr, "XIO2 chan %x intr %x spad %.8x\r\n", chan, ix, bc); - bc = SPAD[ix+0x80]; /* get interrupt entry for channel */ -//fprintf(stderr, "XIO chan %x intr %x spad %.8x\r\n", chan, ix, bc); - /* SPAD address F1 has interrupt table address */ - addr = SPAD[0xf1] + (ix<<2); /* vector address in SPAD */ -//fprintf(stderr, "XIOa spad %x intr %x spad %.8x addr %x\r\n", SPAD[0xf1], ix, bc, addr); - addr = M[addr>>2]; /* get the interrupt context block addr */ -//fprintf(stderr, "XIOb chan %x intr %x spad %.8x addr %x\r\n", chan, ix, bc, addr); - /* the context block contains the old PSD, */ - /* new PSD, IOCL address, and I/O status address */ - if (addr == 0) /* must be initialized address */ - goto mcheck; /* bad int icb address */ -//fprintf(stderr, "XIO chan %x intr %x addr %x iocla %x\r\n", chan, ix, addr, addr + 16); - if ((TRAPME = Mem_read(addr+16, &temp))) { /* get iocl address from icb wd 4 */ - goto mcheck; /* machine check if not there */ - } -//fprintf(stderr, "XIOx chan %x intr %x addr %x temp %x\r\n", chan, ix, addr, temp); - /* iocla must be valid addr if it is a SIO instruction */ - if (((temp & MASK24) == 0) && (((opr >> 2) & 0xf) == 2)) - goto mcheck; /* bad iocl address */ - -//fprintf(stderr, "XIO ready chan %x intr %x icb %x iocla %x iocd1 %.8x iocd2 %0.x8\r\n", -// chan, ix, addr, addr+16, M[temp>>2], M[(temp+4)>>2]); -//sim_debug(DEBUG_EXP, &cpu_dev, "XIO ready chan %x intr %x icb %x iocla %x iocd1 %.8x iocd2 %.8x\n", -// chan, ix, addr, addr+16, M[temp>>2], M[(temp+4)>>2]); - /* at this point, the channel has a valid SPAD channel entry */ - /* t is SPAD entry contents for chan device */ - /* temp2 has IR + reg contents if reg != 0 */ - /* lchan - logical channel address */ - /* chan - channel address */ - /* suba - channel device subaddress */ - /* ix - positive interrupt level */ - /* addr - ICB for specified interrupt level, points to 6 wd block */ - /* temp - First IOCD address */ -//fprintf(stderr, "XIO switch %x lchan %x chan %x intr %x chsa %x IOCDa %x\r\n", ((opr>>3)&0xf), lchan, chan, ix, (chan<<8)|suba, temp); -//sim_debug(DEBUG_EXP, &cpu_dev, "XIO switch chan %x intr %x chsa %x IOCDa %.8x\n", chan, ix, (chan<<8)|suba, temp); - switch((opr >> 3) & 0xf) { /* use bits 9-12 to determine I/O instruction */ - uint32 status; /* status returned by various functions */ - uint16 chsa; /* logical device address */ - - case 0x00: /* Unassigned */ - case 0x01: /* Unassigned */ - case 0x0A: /* Unassigned */ - TRAPME = UNDEFINSTR_TRAP; /* trap condition */ - goto newpsd; /* undefined instruction trap */ - break; - - case 0x09: /* Enable write channel ECWCS */ - case 0x0B: /* Write channel WCS WCWCS */ - /* for now or maybe forever, return unsupported transaction */ - PSD1 = ((PSD1 & 0x87fffffe) | (CC2BIT|CC4BIT)); /* insert status 5 */ - TRAPME = UNDEFINSTR_TRAP; /* trap condition */ - goto newpsd; /* undefined instruction trap */ - break; - - case 0x02: /* Start I/O SIO */ - chsa = temp2 & 0x7FFF; /* get logical device address */ - if ((TRAPME = startxio(chsa, &status))) - goto newpsd; /* error returned, trap cpu */ - PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ -//fprintf(stderr, "@@XIO SIO ret chan %x chsa %x status %x\r\n", chan, (chan<<8)|suba, status); -sim_debug(DEBUG_EXP, &cpu_dev, "XIO SIO ret chan %x chsa %x status %x\n", chan, (chan<<8)|suba, status); - break; - - case 0x03: /* Test I/O TIO */ - chsa = temp2 & 0x7FFF; /* get logical device address */ - if ((TRAPME = testxio(chsa, &status))) - goto newpsd; /* error returned, trap cpu */ - PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ -//fprintf(stderr, "@@XIO TIO ret chan %x chsa %x status %x\r\n", chan, (chan<<8)|suba, status); -sim_debug(DEBUG_EXP, &cpu_dev, "XIO TIO ret chan %x chsa %x status %x\n", chan, (chan<<8)|suba, status); - break; - - case 0x04: /* Stop I/O STPIO */ - chsa = temp2 & 0x7FFF; /* get logical device address */ - if ((TRAPME = stopxio(chsa, &status))) - goto newpsd; /* error returned, trap cpu */ - /* SPAD entries for interrupts begin at 0x80 */ -/* 07-16-18 chg */ INTS[ix] &= ~INTS_REQ; /* clears any requests also */ - INTS[ix] &= ~INTS_ACT; /* deactivate specified int level */ - SPAD[ix+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ - PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ -//fprintf(stderr, "@@XIO STPIO ret chan %x chsa %x status %x\r\n", chan, (chan<<8)|suba, status); -sim_debug(DEBUG_EXP, &cpu_dev, "XIO STPIO ret chan %x chsa %x status %x\n", chan, (chan<<8)|suba, status); - break; - - /* TODO Finish XIO */ - case 0x05: /* Reset channel RSCHNL */ - chsa = temp2 & 0x7FFF; /* get logical device address */ - /* SPAD entries for interrupts begin at 0x80 */ - INTS[ix] &= ~INTS_REQ; /* clears any requests */ - INTS[ix] &= ~INTS_ACT; /* deactivate specified int level */ - SPAD[ix+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ -//fprintf(stderr, "RSCHNL intr %.2x SPAD %.8x INTS[%x] %x\r\n", ix, bc, ix, INTS[ix]); - if ((TRAPME = rschnlxio(chsa, &status))) - goto newpsd; /* error returned, trap cpu */ - PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ -//fprintf(stderr, "XIO RSCHNL ret chan %x chsa %x status %x\r\n", chan, (chan<<8)|suba, status); -sim_debug(DEBUG_EXP, &cpu_dev, "XIO RSCHNL ret chan %x chsa %x status %x\n", chan, (chan<<8)|suba, status); - break; - - case 0x06: /* Halt I/O HIO */ - chsa = temp2 & 0x7FFF; /* get logical device address */ - if ((TRAPME = haltxio(chsa, &status))) - goto newpsd; /* error returned, trap cpu */ - PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ -//fprintf(stderr, "@@XIO HALTXIO ret chan %x chsa %x status %x\r\n", chan, (chan<<8)|suba, status); -sim_debug(DEBUG_EXP, &cpu_dev, "HIO HALTXIO ret chan %x chsa %x status %x\n", chan, (chan<<8)|suba, status); - break; - - case 0x07: /* Grab controller GRIO n/u */ - chsa = temp2 & 0x7FFF; /* get logical device address */ - if ((TRAPME = grabxio(chsa, &status))) - goto newpsd; /* error returned, trap cpu */ - PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ -//fprintf(stderr, "XIO GRIO ret chan %x chsa %x status %x\r\n", chan, (chan<<8)|suba, status); -sim_debug(DEBUG_EXP, &cpu_dev, "XIO GRIO ret chan %x chsa %x status %x\n", chan, (chan<<8)|suba, status); - break; - - case 0x08: /* Reset controller RSCTL */ - chsa = temp2 & 0x7FFF; /* get logical device address */ - if ((TRAPME = stopxio(chsa, &status))) - goto newpsd; /* error returned, trap cpu */ - PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ -//fprintf(stderr, "XIO STPIO ret chan %x chsa %x status %x\r\n", chan, (chan<<8)|suba, status); -sim_debug(DEBUG_EXP, &cpu_dev, "XIO RSCTL ret chan %x chsa %x status %x\n", chan, (chan<<8)|suba, status); - break; - - /* TODO Finish XIO interrupts */ - case 0x0C: /* Enable channel interrupt ECI */ - chsa = temp2 & 0x7FFF; /* get logical device address */ -//fprintf(stderr, "XIO ECI chan %x sa %x spad %.8x INTS %x SPAD %x\r\n", chan, suba, t, INTS[ix], SPAD[ix+0x80]); -sim_debug(DEBUG_EXP, &cpu_dev, "XIO ECI chan %x sa %x spad %.8x\n", chan, suba, t); - /* SPAD entries for interrupts begin at 0x80 */ - INTS[ix] |= INTS_ENAB; /* enable specified int level */ - SPAD[ix+0x80] |= SINT_ENAB; /* enable in SPAD too */ - INTS[ix] &= ~INTS_REQ; /* clears any requests also TRY 06-09-18 */ -//TRY 06-09-18 irq_pend = 1; /* start scanning interrupts again */ -//fprintf(stderr, "ECI intr %.2x SPAD %.8x INTS[%x] %x\r\n", ix, bc, ix, INTS[ix]); - break; - - case 0x0D: /* Disable channel interrupt DCI */ - chsa = temp2 & 0x7FFF; /* get logical device address */ -sim_debug(DEBUG_EXP, &cpu_dev, "XIO DCI chan %x sa %x spad %.8x\n", chan, suba, t); - /* SPAD entries for interrupts begin at 0x80 */ - INTS[ix] &= ~INTS_ENAB; /* disable specified int level */ - INTS[ix] &= ~INTS_REQ; /* clears any requests also */ - SPAD[ix+0x80] &= ~SINT_ENAB; /* disable in SPAD too */ -//fprintf(stderr, "DCI intr %.2x SPAD %.8x INTS[%x] %x\r\n", ix, bc, ix, INTS[ix]); - break; - - case 0x0E: /* Activate channel interrupt ACI */ - chsa = temp2 & 0x7FFF; /* get logical device address */ -sim_debug(DEBUG_EXP, &cpu_dev, "XIO ACI chan %x sa %x spad %.8x\n", chan, suba, t); - /* SPAD entries for interrupts begin at 0x80 */ - INTS[ix] |= INTS_ACT; /* activate specified int level */ -//fprintf(stderr, "ACI intr %.2x SPAD %.8x INTS[%x] %x\r\n", ix, bc, ix, INTS[ix]); - break; - - case 0x0F: /* Deactivate channel interrupt DACI */ - /* Note, instruction following DACI is not interruptable */ - chsa = temp2 & 0x7FFF; /* get logical device address */ -sim_debug(DEBUG_EXP, &cpu_dev, "XIO DACI chan %x sa %x spad %.8x\n", chan, suba, t); - /* SPAD entries for interrupts begin at 0x80 */ -/* 07-16-18 chg */ INTS[ix] &= ~INTS_REQ; /* clears any requests also */ - INTS[ix] &= ~INTS_ACT; /* deactivate specified int level */ - SPAD[ix+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ -//fprintf(stderr, "DACI intr %.2x SPAD %.8x INTS[%x] %x\r\n", ix, bc, ix, INTS[ix]); - irq_pend = 1; /* start scanning interrupts again */ - skipinstr = 1; /* skip interrupt test */ -//NOTE CC must be returned */ - break; - } /* end of XIO switch */ - break; - } /* End of Instruction Switch */ - - /* any instruction with an arithmetic exception will still end up here */ - /* after the instruction is done and before incrementing the PC, */ - /* we will trap the cpu if ovl is set nonzero by an instruction */ - - /* Store result to register */ - if (i_flags & SD) { - if (dbl) { /* if double reg, store 2nd reg */ - GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ - GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ - } else { - GPR[reg] = (uint32)(dest & FMASK); /* save the reg */ - } - } - - /* Store result to base register */ - if (i_flags & SB) { - if (dbl) { /* no dbl wd store to base regs */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - BR[reg] = (uint32)(dest & FMASK); /* save the base reg */ -//fprintf(stderr, "SB base reg %x dest(BR) %.8x\r\n", reg, BR[reg]); - } - - /* Store result to memory */ - if (i_flags & SM) { - /* Check if byte of half word */ - if (((FC & 04) || (FC & 5) == 1)) { /* hw or byte requires read first */ - if ((TRAPME = Mem_read(addr, &temp))) { /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - } - } - switch(FC) { - case 2: /* double word store */ - if ((addr & 2) != 2) { - TRAPME = ADDRSPEC_TRAP; /* address not on dbl wd boundry, error */ - goto newpsd; /* go execute the trap now */ - } - temp = (uint32)(dest & MASK32);/* get lo 32 bit */ - if ((TRAPME = Mem_write(addr + 4, &temp))) - goto newpsd; /* memory write error or map fault */ - temp = (uint32)(dest >> 32); /* move upper 32 bits to lo 32 bits */ - break; - - case 0: /* word store */ - temp = (uint32)(dest & FMASK); /* mask 32 bit of reg */ - if ((addr & 3) != 0) { - /* Address fault */ - TRAPME = ADDRSPEC_TRAP; /* address not on wd boundry, error */ - goto newpsd; /* go execute the trap now */ - } - break; - - case 1: /* left halfword write */ - temp &= RMASK; /* mask out 16 left most bits */ - temp |= (uint32)(dest & RMASK) << 16; /* put into left most 16 bits */ - if ((addr & 1) != 1) { - /* Address fault */ - TRAPME = ADDRSPEC_TRAP; /* address not on hw boundry, error */ - goto newpsd; /* go execute the trap now */ - } - break; - - case 3: /* right halfword write */ - temp &= LMASK; /* mask out 16 right most bits */ - temp |= (uint32)(dest & RMASK); /* put into right most 16 bits */ - if ((addr & 3) != 3) { - TRAPME = ADDRSPEC_TRAP; /* address not on hw boundry, error */ - goto newpsd; /* go execute the trap now */ - } - break; - - case 4: - case 5: - case 6: - case 7: /* byte store operation */ - temp &= ~(0xFF << (8 * (7 - FC))); /* clear the byte to store */ - temp |= (uint32)(dest & 0xFF) << (8 * (7 - FC)); /* insert new byte */ - break; - } - /* store back the modified memory location */ - if ((TRAPME = Mem_write(addr, &temp))) /* store back to memory */ - goto newpsd; /* memory write error or map fault */ - } - - /* Update condition code registers */ - if (i_flags & SCC) { - PSD1 &= 0x87FFFFFe; /* clear the old CC's */ - if (ovr) /* if overflow, set CC1 */ - CC |= CC1BIT; /* show we had AEXP */ - else - CC = 0; /* no CC's yet */ - if (dest & MSIGN) /* is it neg */ - CC |= CC3BIT; /* if neg, set CC3 */ - else if (dest == 0) - CC |= CC4BIT; /* if zero, set CC4 */ - else - CC |= CC2BIT; /* if gtr than zero, set CC2 */ - PSD1 |= CC & 0x78000000; /* update the CC's in the PSD */ - } - - /* Update instruction pointer to next instruction */ - if (EXM_EXR != 0) { /* special handling for EXM, EXR, EXRR */ - PSD1 = (PSD1 + 4) | (((PSD1 & 2) >> 1) & 1); - EXM_EXR = 0; /* reset PC increment for EXR */ - } else - if ((i_flags & BT) == 0) { /* see if PSD was replaced on a branch instruction */ -//fprintf(stderr, "@PCI1 temp %.8x addr %.8x PSD1 %.8x flags %.8x\r\n", temp, addr, PSD1, i_flags); - /* branch not taken, so update the PC */ - if (i_flags & HLF) { - PSD1 = (PSD1 + 2) | (((PSD1 & 2) >> 1) & 1); - } else { - PSD1 = (PSD1 + 4) | (((PSD1 & 2) >> 1) & 1); - } -//fprintf(stderr, "@PCI2 temp %.8x addr %.8x PSD1 %.8x flags %.8x\r\n", temp, addr, PSD1, i_flags); - } - - /* check if we had an arithmetic exception on the last instruction*/ - if (ovr && (modes & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* trap the system now */ - goto newpsd; /* process the trap */ - } -#if 0 - /* no trap, so continue with next instruction */ -//PC = PSD1 & 0xfffffe; /* get 24 bit addr from PSD1 */ -// Get CCs from PSD1 and PC from original instruction */ -//if (traceme >= 4) { -if (traceme >= trstart) { -OPSD1 &= 0x87FFFFFE; /* clear the old CC's */ -OPSD1 |= PSD1 & 0x78000000; /* update the CC's in the PSD */ -if (modes & MAPMODE) - fprintf(stderr, "M%.8x %.8x ", OPSD1, OIR); -else - fprintf(stderr, "U%.8x %.8x ", OPSD1, OIR); -fprint_inst(stderr, OIR, 0); /* display instruction */ -fprintf(stderr, " R0=%x R1=%x R2=%x R3=%x", GPR[0], GPR[1], GPR[2], GPR[3]); -fprintf(stderr, " R4=%x R5=%x R6=%x R7=%x", GPR[4], GPR[5], GPR[6], GPR[7]); -fprintf(stderr, "\r\n"); -} -#endif -sim_debug(DEBUG_DATA, &cpu_dev, "R0=%08x R1=%08x R2=%08x R3=%08x\n", GPR[0], GPR[1], GPR[2], GPR[3]); -sim_debug(DEBUG_DATA, &cpu_dev, "R4=%08x R5=%08x R6=%08x R7=%08x\n", GPR[4], GPR[5], GPR[6], GPR[7]); - continue; /* keep running */ -// break; /* quit for now after each instruction */ - -newpsd: -//fprintf(stderr, "place @ newpsd PSD1 %.8x PSD2 %.8x TRAPME %.4x\r\n", PSD1, PSD2, TRAPME); - /* we get here from a LPSD, LPSDCM, INTR, or TRAP */ - if (TRAPME) { - /* SPAD location 0xf0 has trap vector base address */ - uint32 tta = SPAD[0xf0]; /* get trap table address in memory */ - uint32 tvl; /* trap vector location */ - if (tta == 0 || tta == 0xffffffff) - tta = 0x80; /* if not set, assume 0x80 FIXME */ - /* Trap Table Address in memory is pointed to by SPAD 0xF0 */ - /* TODO update cpu status and trap status words with reason too */ - switch(TRAPME) { - case POWERFAIL_TRAP: /* 0x80 power fail trap */ - case POWERON_TRAP: /* 0x84 Power-On trap */ - case MEMPARITY_TRAP: /* 0x88 Memory Parity Error trap */ - case NONPRESMEM_TRAP: /* 0x8C Non Present Memory trap */ - case UNDEFINSTR_TRAP: /* 0x90 Undefined Instruction Trap */ - case PRIVVIOL_TRAP: /* 0x94 Privlege Violation Trap */ -//TODO case SVCCALL_TRAP: /* 0x98 Supervisor Call Trap */ - case MACHINECHK_TRAP: /* 0x9C Machine Check Trap */ - case SYSTEMCHK_TRAP: /* 0xA0 System Check Trap */ - case MAPFAULT_TRAP: /* 0xA4 Map Fault Trap */ - case IPUUNDEFI_TRAP: /* 0xA8 IPU Undefined Instruction Trap */ - case SIGNALIPU_TRAP: /* 0xAC Signal IPU/CPU Trap */ - case ADDRSPEC_TRAP: /* 0xB0 Address Specification Trap */ - case CONSOLEATN_TRAP: /* 0xB4 Console Attention Trap */ - case PRIVHALT_TRAP: /* 0xB8 Privlege Mode Halt Trap */ - case AEXPCEPT_TRAP: /* 0xBC Arithmetic Exception Trap */ - default: - tta = tta + (TRAPME - 0x80); /* tta has mem addr of trap vector */ - tvl = M[tta>>2] & 0x7FFFC; /* get trap vector address from trap vector loc */ -//fprintf(stderr, "tvl %.8x, tta %.8x status %.8x\r\n", tvl, tta, CPUSTATUS); - if (tvl == 0 || tvl == 0x7FFFC || (CPUSTATUS & 0x40) == 0) { - /* vector is zero or software has not enabled traps yet */ - /* execute a trap halt */ - /* set the PSD to trap vector location */ - PSD1 = 0x80000000 + TRAPME; /* just priv and PC to trap vector */ - PSD2 = 0x00004000; /* unmapped, blocked interrupts mode */ - M[0x680>>2] = PSD1; /* store PSD 1 */ - M[0x684>>2] = PSD2; /* store PSD 2 */ - M[0x688>>2] = TRAPSTATUS; /* store trap status */ - M[0x68C>>2] = 0; /* This will be device table entry later TODO */ -fprintf(stderr, "[][][][][][][][][][][] HALT TRAP [][][][][][][][][][][][]\r\n"); -fprintf(stderr, "PSD1 %.8x PSD2 %.8x TRAPME %.4x\r\n", PSD1, PSD2, TRAPME); - for (ix=0; ix<8; ix+=2) { - fprintf(stderr, "GPR[%d] %.8x GPR[%d] %.8x\r\n", ix, GPR[ix], ix+1, GPR[ix+1]); - } -fprintf(stderr, "[][][][][][][][][][][] HALT TRAP [][][][][][][][][][][][]\r\n"); - return STOP_HALT; /* exit to simh for halt */ - } else { - /* valid vector, so store the PSD, fetch new PSD */ - bc = PSD2 & 0x3ffc; /* get copy of cpix */ - M[tvl>>2] = PSD1 & 0xfffffffe; /* store PSD 1 */ - M[(tvl>>2)+1] = PSD2; /* store PSD 2 */ - PSD1 = M[(tvl>>2)+2]; /* get new PSD 1 */ - PSD2 = (M[(tvl>>2)+3] & ~0x3ffc) | bc; /* get new PSD 2 w/old cpix */ - M[(tvl>>2)+4] = TRAPSTATUS; /* store trap status */ - - /* set the mode bits and CCs from the new PSD */ - CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ - modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ - /* set new map mode and interrupt blocking state in CPUSTATUS */ - if (PSD2 & MAPBIT) { - CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ - modes |= MAPMODE; /* set mapped mode */ - } else - CPUSTATUS &= 0xff7fffff; /* reset bit 8 of cpu status */ - /* set interrupt blocking state */ - if ((PSD2 & 0x8000) == 0) { /* is it retain blocking state */ - if (PSD2 & 0x4000) /* no, is it set blocking state */ - CPUSTATUS |= 0x80; /* yes, set blk state in cpu status bit 24 */ - else - CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ - } - PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ - if (CPUSTATUS & 0x80) /* see if old mode is blocked */ - PSD2 |= 0x00004000; /* set to blocked state */ - - PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ - SPAD[0xf5] = PSD2; /* save the current PSD2 */ -#if 0 -if (TRAPME == UNDEFINSTR_TRAP) { -sim_debug(DEBUG_EXP, &cpu_dev, "TRAP PSD1 %x PSD2 %x CPUSTATUS %x\n", PSD1, PSD2, CPUSTATUS); -fprintf(stderr, "TRAPS %x LOAD MAPS PSD1 %x PSD2 %x CPUSTATUS %x\r\n", TRAPME, PSD1, PSD2, CPUSTATUS); -goto dumpi; -} -#endif - break; /* Go execute the trap */ - } - break; - } - } - skipinstr = 1; /* skip next instruction */ - /* we have a new PSD loaded via a LPSD or LPSDCM */ - /* TODO finish instruction history, then continue */ - /* update cpu status word too */ -#if 0 -if (traceme >= trstart) { -dumpi: -OPSD1 &= 0x87FFFFFE; /* clear the old CC's */ -OPSD1 |= PSD1 & 0x78000000; /* update the CC's in the PSD */ -if (modes & MAPMODE) - fprintf(stderr, "M%.8x %.8x ", OPSD1, OIR); -else - fprintf(stderr, "U%.8x %.8x ", OPSD1, OIR); -fprint_inst(stderr, OIR, 0); /* display instruction */ -fprintf(stderr, " R0=%x R1=%x R2=%x R3=%x", GPR[0], GPR[1], GPR[2], GPR[3]); -fprintf(stderr, " R4=%x R5=%x R6=%x R7=%x", GPR[4], GPR[5], GPR[6], GPR[7]); -fprintf(stderr, "\r\n"); -} -#endif -sim_debug(DEBUG_DATA, &cpu_dev, "R0=%08x R1=%08x R2=%08x R3=%08x\n", GPR[0], GPR[1], GPR[2], GPR[3]); -sim_debug(DEBUG_DATA, &cpu_dev, "R4=%08x R5=%08x R6=%08x R7=%08x\n", GPR[4], GPR[5], GPR[6], GPR[7]); - continue; /* single step cpu just for now */ -// break; /* quit for now after each instruction */ - } /* end while */ - - /* Simulation halted */ -//fprintf(stderr, "@end PSD1 %.8x PSD2 %.8x addr %.8x\r\n", PSD1, PSD2, addr); - return reason; -} - -/* these are the default ipl devices defined by the CPU jumpers */ -/* they can be overridden by specifying IPL device at ipl time */ -uint32 def_disk = 0x0800; /* disk channel 8, device 0 */ -uint32 def_tape = 0x1000; /* tape device 10, device 0 */ -uint32 def_floppy = 0x7ef0; /* IOP floppy disk channel 7e, device f0 */ -//int once = 0; /* one time inits */ - -/* Reset routine */ -/* do any one time initialization here for cpu */ -t_stat cpu_reset(DEVICE * dptr) -{ - int i; - - /* leave regs alone so values can be passed to boot code */ - PSD1 = 0x80000000; /* privileged, non mapped, non extended, address 0 */ - PSD2 = 0x00004000; /* blocked interrupts mode */ - modes = (PRIVBIT | BLKMODE); /* set modes to privileged and blocked interrupts */ - CC = 0; /* no CCs too */ - CPUSTATUS = CPU_MODEL; /* clear all cpu status except cpu type */ - CPUSTATUS |= 0x80000000; /* set privleged state bit 0 */ - CPUSTATUS |= 0x00000080; /* set blocked mode state bit 24 */ - TRAPSTATUS = CPU_MODEL; /* clear all trap status except cpu type */ - - chan_set_devs(); /* set up the defined devices on the simulator */ - - /* set default breaks to execution tracing */ - sim_brk_types = sim_brk_dflt = SWMASK('E'); - /* zero regs */ - for (i = 0; i < 8; i++) { - GPR[i] = 0; /* clear the registers */ - BR[i] = 0; /* clear the registers */ - } - /* zero interrupt status words */ - for (i = 0; i < 112; i++) - INTS[i] = 0; /* clear interrupt status flags */ - - /* add code here to initialize the SEL32 cpu scratchpad on initial start */ - /* see if spad setup by software, if yes, leave spad alone */ - /* otherwise set the default values into the spad */ - /* CPU key is 0xECDAB897, IPU key is 0x13254768 */ - /* Keys are loaded by the O/S software during the boot loading sequence */ - if (SPAD[0xf7] != 0xecdab897) - { - int ival = 0; /* init value for concept 32 */ - - if (CPU_MODEL < MODEL_27) - ival = 0xfffffff; /* init value for 32/7x int and dev entries */ - for (i = 0; i < 1024; i++) - MAPC[i] = 0; /* clear 2048 halfword map cache */ - for (i = 0; i < 224; i++) - SPAD[i] = ival; /* init 128 devices and 96 ints in the spad */ - for (i = 224; i < 256; i++) /* clear the last 32 extries */ - SPAD[i] = 0; /* clear the spad */ - SPAD[0xf0] = 0x80; /* default Trap Table Address (TTA) */ - SPAD[0xf1] = 0x100; /* Interrupt Table Address (ITA) */ - SPAD[0Xf2] = 0x700; /* IOCD Base Address */ - SPAD[0xf3] = 0x788; /* Master Process List (MPL) table address */ - SPAD[0xf4] = def_tape; /* Default IPL address from console IPL command or jumper */ - SPAD[0xf5] = 0x00004000; /* current PSD2 defaults to blocked */ - SPAD[0xf6] = 0; /* reserved (PSD1 ??) */ - SPAD[0xf7] = 0; /* make sure key is zero */ - SPAD[0xf8] = 0x0000f000; /* set DRT to class f (anything else is E) */ - SPAD[0xf9] = CPU_MODEL; /* set default cpu type in cpu status word */ - SPAD[0xff] = 0x00ffffff; /* interrupt level 7f 1's complament */ - } - M[0] = 0x02000000; /* 0x00 IOCD 1 read into address 0 */ - M[1] = 0x60000078; /* 0x04 IOCD 1 CMD Chain, Suppress incor length, 120 bytes */ - M[2] = 0x53000000; /* 0x08 IOCD 2 BKSR or RZR to re-read boot code */ - M[3] = 0x60000001; /* 0x0C IOCD 2 CMD chain,Supress incor length, 1 byte */ - M[4] = 0x02000000; /* 0x10 IOCD 3 Read into address 0 */ - M[5] = 0x000006EC; /* 0x14 IOCD 3 Read 0x6EC bytes */ - loading = 0; /* not loading yet */ - /* we are good to go */ - return SCPE_OK; -} - -/* Memory examine */ -/* examine a 32bit memory location */ -/* address is byte address with bits 30,31 = 0 */ -t_stat cpu_ex(t_value *vptr, t_addr baddr, UNIT *uptr, int32 sw) -{ - uint32 temp, t; - uint32 addr = (baddr & 0xfffffc) >> 2; /* make 24 bit byte address into word address */ - - /* MSIZE is in 32 bit words */ - if (addr >= MEMSIZE) /* see if address is within our memory */ - return SCPE_NXM; /* no, none existant memory error */ - if (vptr == NULL) /* any address specified by user */ - return SCPE_OK; /* no, just ignore the request */ - *vptr = M[addr]; /* return memory contents */ - return SCPE_OK; /* we are all ok */ -} - -/* Memory deposit */ -/* modify a 32bit memory location */ -/* address is byte address with bits 30,31 = 0 */ -t_stat cpu_dep(t_value val, t_addr baddr, UNIT *uptr, int32 sw) -{ - uint32 addr = (baddr & 0xfffffc) >> 2; /* make 24 bit byte address into word address */ - -//fprintf(stderr, "cpu_dep baddr %0x, sw %x\b\n", baddr, sw); - /* MSIZE is in 32 bit words */ - if (addr >= MEMSIZE) /* see if address is within our memory */ - return SCPE_NXM; /* no, none existant memory error */ - M[addr] = val; /* set the new data value */ - return SCPE_OK; /* all OK */ -} - -/* set the CPU memory size */ -t_stat cpu_set_size(UNIT *uptr, int32 val, CONST char *cptr, void *desc) -{ - t_uint64 mc = 0; - uint32 i; - -//fprintf(stderr, "WE are here 4 \b\n"); - cpu_unit.flags &= ~UNIT_MSIZE; - cpu_unit.flags |= val; /* set new memory size */ - val >>= UNIT_V_MSIZE; /* set size in 32bit words */ - val = (val + 1) * 128 * 1024; /* KW's */ - if ((val < 0) || (val > MAXMEMSIZE)) /* is size valid */ - return SCPE_ARG; /* nope, argument error */ - for (i = val; i < MEMSIZE; i++) /* see if memory contains anything */ - mc |= M[i]; /* or in any bits in memory */ - if ((mc != 0) && (!get_yn("Really truncate memory [N]?", FALSE))) - return SCPE_OK; /* return OK if user says no */ - MEMSIZE = val; /* set new size */ - for (i = MEMSIZE; i < MAXMEMSIZE; i++) - M[i] = 0; /* zero all of the new memory */ - return SCPE_OK; /* we done */ -} - -/* Handle execute history */ - -/* Set history */ -t_stat -cpu_set_hist(UNIT *uptr, int32 val, CONST char *cptr, void *desc) -{ - int32 i, lnt; - t_stat r; - - if (cptr == NULL) { /* check for any user options */ - for (i = 0; i < hst_lnt; i++) /* none, so just zero the history */ - hst[i].psd1 = 0; /* just psd1 for now */ - hst_p = 0; /* start at teh beginning */ - return SCPE_OK; /* all OK */ - } - /* the user has specified options, process them */ - lnt = (int32) get_uint(cptr, 10, HIST_MAX, &r); - if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) - return SCPE_ARG; /* arg error for bad input or too small a value */ - hst_p = 0; /* start at beginning */ - if (hst_lnt) { /* if a new length was input, resize history buffer */ - free(hst); /* out with the old */ - hst_lnt = 0; /* no length anymore */ - hst = NULL; /* and no pointer either */ - } - if (lnt) { /* see if new size specified, if so get new resized buffer */ - hst = (struct InstHistory *)calloc(sizeof(struct InstHistory), lnt); - if (hst == NULL) - return SCPE_MEM; /* allocation error, so tell user */ - hst_lnt = lnt; /* set new length */ - } - return SCPE_OK; /* we are good to go */ -} - -/* Show history */ -t_stat cpu_show_hist(FILE * st, UNIT * uptr, int32 val, CONST void *desc) -{ - int32 k, di, lnt; - char *cptr = (char *) desc; - t_stat r; - struct InstHistory *h; - - if (hst_lnt == 0) /* see if show history is enabled */ - return SCPE_NOFNC; /* no, so are out of here */ - if (cptr) { /* see if user provided a display count */ - lnt = (int32)get_uint(cptr, 10, hst_lnt, &r); /* get the count */ - if ((r != SCPE_OK) || (lnt == 0)) /* if error or 0 count */ - return SCPE_ARG; /* report argument error */ - } else - lnt = hst_lnt; /* dump all the entries */ - di = hst_p - lnt; /* work forward */ - if (di < 0) - di = di + hst_lnt; /* wrap */ - fprintf(st, "PSD1 PSD2 INST DEST SRC CC\n"); - for (k = 0; k < lnt; k++) { /* print specified entries */ - h = &hst[(++di) % hst_lnt]; /* entry pointer */ - /* display the instruction and results */ - fprintf(st, "%08x %08x %08x %08x %08x %1x", - h->psd1, h->psd2, h->inst, h->dest, h->src, h->cc); - fputc('\n', st); /* end line */ - } /* end for */ - return SCPE_OK; /* all is good */ -} - -/* return description for the specified device */ -const char *cpu_description (DEVICE *dptr) -{ - return "SEL 32 CPU"; /* return description */ -} - -t_stat -cpu_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) -{ - fprintf (st, "The CPU can be set to \n"); - fprintf (st, "The CPU can maintain a history of the most recently executed instructions.\n"); - fprintf (st, "This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:\n\n"); - fprintf (st, " sim> SET CPU HISTORY clear history buffer\n"); - fprintf (st, " sim> SET CPU HISTORY=0 disable history\n"); - fprintf (st, " sim> SET CPU HISTORY=n{:file} enable history, length = n\n"); - fprintf (st, " sim> SHOW CPU HISTORY print CPU history\n"); - return SCPE_OK; -} - +/* sel32_cpu.c: Sel 32 CPU simulator + + Copyright (c) 2018, James C. Bevier + Portions provided by Richard Cornwell and other SIMH contributers + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + JAMES C. BEVIER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +#include "sel32_defs.h" + +/* 32/7x PSW/PSD Mode Trap/Interrupt Priorities */ +/* Relative Logical Int Vect TCW IOCD Description */ +/* Priority Priority Location Addr Addr */ +/* 0 0F4 Power Fail Safe Trap */ +/* 1 0FC System Override Trap (Not Used) */ +/* 2 0E8* Memory Parity Trap */ +/* 3 190 Nonpresent Memory Trap */ +/* 4 194 Undefined Instruction Trap */ +/* 5 198 Privilege Violation Trap */ +/* 6 180 Supervisor Call Trap (SVC) */ +/* 7 184 Machine Check Trap */ +/* 8 188 System Check Trap */ +/* 9 18C Map Fault Trap */ +/* A Not Used */ +/* B Not Used */ +/* C Not Used */ +/* D Not Used */ +/* E 0E4 Block Mode Timeout Trap */ +/* F 1A4* Arithmetic Exception Trap */ +/* 10 00 0F0 Power Fail Safe Interrupt */ +/* 11 01 0F8 System Override Interrupt */ +/* 12 12 0E8* Memory Parity Trap */ +/* 13 13 0EC Attention Interrupt */ +/* 14 14 140 100 700 I/O Channel 0 interrupt */ +/* 15 15 144 104 708 I/O Channel 1 interrupt */ +/* 16 16 148 108 710 I/O Channel 2 interrupt */ +/* 17 17 14C 10C 718 I/O Channel 3 interrupt */ +/* 18 18 150 110 720 I/O Channel 4 interrupt */ +/* 19 19 154 114 728 I/O Channel 5 interrupt */ +/* 1A 1A 158 118 730 I/O Channel 6 interrupt */ +/* 1B 1B 15C 11C 738 I/O Channel 7 interrupt */ +/* 1C 1C 160 120 740 I/O Channel 8 interrupt */ +/* 1D 1D 164 124 748 I/O Channel 9 interrupt */ +/* 1E 1E 168 128 750 I/O Channel A interrupt */ +/* 1F 1F 16C 12C 758 I/O Channel B interrupt */ +/* 20 20 170 130 760 I/O Channel C interrupt */ +/* 21 21 174 134 768 I/O Channel D interrupt */ +/* 22 22 178 138 770 I/O Channel E interrupt */ +/* 23 23 17C 13C 778 I/O Channel F interrupt */ +/* 24 24 190* Nonpresent Memory Trap */ +/* 25 25 194* Undefined Instruction Trap */ +/* 26 26 198* Privlege Violation Trap */ +/* 27 27 19C Call Monitor Interrupt */ +/* 28 28 1A0 Real-Time Clock Interrupt */ +/* 29 29 1A4* Arithmetic Exception Interrupt */ +/* 2A 2A 1A8 External/Software Interrupt */ +/* 2B 2B 1AC External/Software Interrupt */ +/* 2C 2C 1B0 External/Software Interrupt */ +/* 2D 2D 1B4 External/Software Interrupt */ +/* 2E 2E 1B8 External/Software Interrupt */ +/* 2F 2F 1BC External/Software Interrupt */ +/* 30 30 1C0 External/Software Interrupt */ +/* 31 31 1C4 External/Software Interrupt */ +/* THRU THRU THRU THRU */ +/* 77 77 2DC External/Software Interrupt */ +/* 78 2E0 End of IPU Processing Trap (CPU) */ +/* 79 2E4 Start IPU Processing Trap (IPU) */ +/* 7A 2E8 Supervisor Call Trap (IPU) */ +/* 7B 2EC Error Trap (IPU) */ +/* 7C 2F0 Call Monitor Trap (IPU) */ +/* 7D 7D 2F4 Stop IPU Processing Trap (IPU) */ +/* 7E 7E 2F8 External/Software Interrupt */ +/* 7F 7F 2FC External/Software Interrupt */ + +/* Concept 32 PSD Mode Trap/Interrupt Priorities */ +/* Relative|Logical |Int Vect|TCW |IOCD|Description */ +/* Priority|Priority|Location|Addr|Addr */ +/* - 080 Power Fail Safe Trap */ +/* - 084 Power On Trap */ +/* - 088 Memory Parity Trap */ +/* - 08C Nonpresent Memory Trap */ +/* - 090 Undefined Instruction Trap */ +/* - 094 Privilege Violation Trap */ +/* - 098 Supervisor Call Trap (SVC) */ +/* - 09C Machine Check Trap */ +/* - 0A0 System Check Trap */ +/* - 0A4 Map Fault Trap */ +/* - 0A8 Undefined IPU Instruction Trap */ +/* - 0AC Signal CPU or Signal IPU Trap */ +/* - 0B0 Address Specification Trap */ +/* - 0B4 Console Attention Trap */ +/* - 0B8 Privlege Mode Halt Trap */ +/* - 0BC Arithmetic Exception Trap */ +/* */ +/* 0 00 100 External/software Interrupt 0 */ +/* 1 01 104 External/software Interrupt 1 */ +/* 2 02 108 External/software Interrupt 2 */ +/* 3 03 10C External/software Interrupt 3 */ +/* 4 04 110 704 700 I/O Channel 0 interrupt */ +/* 5 05 114 70C 708 I/O Channel 1 interrupt */ +/* 6 06 118 714 710 I/O Channel 2 interrupt */ +/* 7 07 11C 71C 718 I/O Channel 3 interrupt */ +/* 8 08 120 724 720 I/O Channel 4 interrupt */ +/* 9 09 124 72C 728 I/O Channel 5 interrupt */ +/* A 0A 128 734 730 I/O Channel 6 interrupt */ +/* B 0B 12C 73C 738 I/O Channel 7 interrupt */ +/* C 0C 130 744 740 I/O Channel 8 interrupt */ +/* D 0D 134 74C 748 I/O Channel 9 interrupt */ +/* E 0E 138 754 750 I/O Channel A interrupt */ +/* F 0F 13C 75C 758 I/O Channel B interrupt */ +/* 10 10 140 764 760 I/O Channel C interrupt */ +/* 11 11 144 76C 768 I/O Channel D interrupt */ +/* 12 12 148 774 770 I/O Channel E interrupt */ +/* 13 13 14c 77C 778 I/O Channel F interrupt */ +/* 14 14 150 External/Software Interrupt */ +/* 15 15 154 External/Software Interrupt */ +/* 16 16 158 External/Software Interrupt */ +/* 17 17 15C External/Software Interrupt */ +/* 18 18 160 Real-Time Clock Interrupt */ +/* 19 19 164 External/Software Interrupt */ +/* 1A 1A 1A8 External/Software Interrupt */ +/* 1B 1B 1AC External/Software Interrupt */ +/* 1C 1C 1B0 External/Software Interrupt */ +/* THRU THRU THRU THRU */ +/* 6C 6C 2B0 External/Software Interrupt */ +/* 6D 6D 2B4 External/Software Interrupt */ +/* 6E 6E 2B8 External/Software Interrupt */ +/* 6F 6F 2BC Interval Timer Interrupt */ + +/* IVL ------------> ICB Trap/Interrupt Vector Location points to Interrupt Context Block */ +/* Wd 0 - Old PSD Word 1 points to return location */ +/* Wd 1 - Old PSD Word 2 */ +/* Wd 2 - New PSD Word 1 points to first instruction of service routine */ +/* Wd 3 - New PSD Word 2 */ +/* Wd 4 - CPU Status word at time of interrupt/trap */ +/* Wd 5 - N/U For Traps/Interrupts */ + +/* IVL ------------> ICB XIO Interrupt Vector Location */ +/* Wd 0 - Old PSD Word 1 points to return location */ +/* Wd 1 - Old PSD Word 2 */ +/* Wd 2 - New PSD Word 1 points to first instruction of service routine */ +/* Wd 3 - New PSD Word 2 */ +/* Wd 4 - Input/Output Command List Address (IOCL) for the Class F I/O CHannel */ +/* Wd 5 - 24 bit real address of the channel status word */ + +/* CPU registers, map cache, spad, and other variables */ +int traceme = 0; /* dynamic trace function */ +int trstart = 9981910; /* count of when to start tracing */ +//int trstart = 37; /* count of when to start tracing */ +int cpu_index; /* Current CPU running */ +uint32 PSD[2]; /* the PC for the instruction */ +#define PSD1 PSD[0] /* word 1 of PSD */ +#define PSD2 PSD[1] /* word 2 of PSD */ +uint32 M[MAXMEMSIZE] = { 0 }; /* Memory */ +uint32 GPR[8]; /* General Purpose Registers */ +uint32 BR[8]; /* Base registers */ +uint32 PC; /* Program counter */ +uint32 CC; /* Condition codes, bits 1-4 of PSD1 */ +uint32 SPAD[256]; /* Scratch pad memory */ +uint32 INTS[112]; /* Interrupt status flags */ +uint32 CPUSTATUS; /* cpu status word */ +uint32 TRAPSTATUS; /* trap status word */ +/* CPU mapping cache entries */ +/* 32/55 has none */ +/* 32/7x has 32 8KW maps per task */ +/* Concept/32 has 2048 2KW maps per task */ +uint32 MAPC[1024]; /* maps are 16bit entries on word bountries */ +uint32 HIWM = 0; /* max maps loaded so far */ + +uint32 modes; /* Operating modes, bits 0, 5, 6, 7 of PSD1 */ +uint8 wait4int = 0; /* waiting for interrupt if set */ + +/* define traps */ +uint32 TRAPME = 0; /* trap to be executed */ +uint32 attention_trap = 0; /* set when trap is requested */ + +struct InstHistory +{ + uint32 psd1; /* the PC for the instruction */ + uint32 psd2; /* the PC for the instruction */ + uint32 inst; /* the instruction itself */ + uint32 ea; /* computed effective address of data */ + uint32 reg; /* reg for operation */ + uint32 dest; /* destination value */ + uint32 src; /* source value */ + uint8 cc; /* cc's */ +}; + +/* forward definitions */ +t_stat cpu_ex(t_value * vptr, t_addr addr, UNIT * uptr, int32 sw); +t_stat cpu_dep(t_value val, t_addr addr, UNIT * uptr, int32 sw); +t_stat cpu_reset(DEVICE * dptr); +t_stat cpu_set_size(UNIT * uptr, int32 val, CONST char *cptr, void *desc); +t_stat cpu_show_hist(FILE * st, UNIT * uptr, int32 val, CONST void *desc); +t_stat cpu_set_hist(UNIT * uptr, int32 val, CONST char *cptr, void *desc); +uint32 cpu_cmd(UNIT * uptr, uint16 cmd, uint16 dev); +t_stat cpu_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +const char *cpu_description (DEVICE *dptr); +t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot); +t_stat load_maps(uint32 thepsd[2]); +t_stat read_instruction(uint32 thepsd[2], uint32 *instr); +t_stat Mem_read(uint32 addr, uint32 *data); +t_stat Mem_write(uint32 addr, uint32 *data); + +/* external definitions */ +extern t_stat startxio(uint16 addr, uint32 *status); /* XIO start in chan.c */ +extern t_stat testxio(uint16 addr, uint32 *status); /* XIO test in chan.c */ +extern t_stat stopxio(uint16 addr, uint32 *status); /* XIO stop in chan.c */ +extern t_stat rschnlxio(uint16 addr, uint32 *status); /* reset channel XIO */ +extern t_stat haltxio(uint16 addr, uint32 *status); /* halt XIO */ +extern t_stat grabxio(uint16 addr, uint32 *status); /* grab XIO n/u */ +extern t_stat rsctlxio(uint16 addr, uint32 *status); /* reset controller XIO */ +extern t_stat chan_set_devs(); /* set up the defined devices on the simulator */ +extern uint32 scan_chan(void); /* go scan for I/O int pending */ +extern uint16 loading; /* set when doing IPL */ +extern int fprint_inst(FILE *of, uint32 val, int32 sw); /* instruction print function */ +extern int irq_pend; /* go scan for pending interrupt */ +extern void rtc_setup(int ss, uint32 level); /* tell rtc to start/stop */ +extern void itm_setup(int ss, uint32 level); /* tell itm to start/stop */ +extern int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level); /* read/write the interval timer */ +extern int32 itm_srv(UNIT *uptr); /* read/write the interval timer */ +extern UNIT itm_unit; /* fake interval timer */ + +/* History information */ +int32 hst_p = 0; /* History pointer */ +int32 hst_lnt = 0; /* History length */ +struct InstHistory *hst = NULL; /* History stack */ + +/* CPU data structures + + cpu_dev CPU device descriptor + cpu_unit CPU unit descriptor + cpu_reg CPU register list + pu_mod CPU modifiers list +*/ + +#ifdef DEFINED_IN_SIM_DEFS_H +/* Unit data structure from sim_defs.h + + Parts of the unit structure are device specific, that is, they are + not referenced by the simulator control package and can be freely + used by device simulators. Fields starting with 'buf', and flags + starting with 'UF', are device specific. The definitions given here + are for a typical sequential device. +*/ + +struct UNIT { + UNIT *next; /* next active */ + t_stat (*action)(UNIT *up); /* action routine */ + char *filename; /* open file name */ + FILE *fileref; /* file reference */ + void *filebuf; /* memory buffer */ + uint32 hwmark; /* high water mark */ + int32 time; /* time out */ + uint32 flags; /* flags */ + uint32 dynflags; /* dynamic flags */ + t_addr capac; /* capacity */ + t_addr pos; /* file position */ + void (*io_flush)(UNIT *up); /* io flush routine */ + uint32 iostarttime; /* I/O start time */ + int32 buf; /* buffer */ + int32 wait; /* wait */ + int32 u3; /* device specific */ + int32 u4; /* device specific */ + int32 u5; /* device specific */ + int32 u6; /* device specific */ + void *up7; /* device specific */ + void *up8; /* device specific */ + uint16 us9; /* device specific */ + uint16 us10; /* device specific */ + void *tmxr; /* TMXR linkage */ + t_bool (*cancel)(UNIT *); + double usecs_remaining; /* time balance for long delays */ + char *uname; /* Unit name */ +#ifdef SIM_ASYNCH_IO + void (*a_check_completion)(UNIT *); + t_bool (*a_is_active)(UNIT *); + UNIT *a_next; /* next asynch active */ + int32 a_event_time; + ACTIVATE_API a_activate_call; + /* Asynchronous Polling control */ + /* These fields should only be referenced when holding the sim_tmxr_poll_lock */ + t_bool a_polling_now; /* polling active flag */ + int32 a_poll_waiter_count; /* count of polling threads */ + /* waiting for this unit */ + /* Asynchronous Timer control */ + double a_due_time; /* due time for timer event */ + double a_due_gtime; /* due time (in instructions) for timer event */ + double a_usec_delay; /* time delay for timer event */ +#endif /* SIM_ASYNCH_IO */ + }; + +/* Unit flags */ + +#define UNIT_V_UF_31 12 /* dev spec, V3.1 */ +#define UNIT_V_UF 16 /* device specific */ +#define UNIT_V_RSV 31 /* reserved!! */ +#define FEAT_TIMER (1<<(UNIT_V_UF+12)) /* interval timer */ +#define TMR_RTC 0 + +#define UNIT_ATTABLE 0000001 /* attachable */ +#define UNIT_RO 0000002 /* read only */ +#define UNIT_FIX 0000004 /* fixed capacity */ +#define UNIT_SEQ 0000010 /* sequential */ +#define UNIT_ATT 0000020 /* attached */ +#define UNIT_BINK 0000040 /* K = power of 2 */ +#define UNIT_BUFABLE 0000100 /* bufferable */ +#define UNIT_MUSTBUF 0000200 /* must buffer */ +#define UNIT_BUF 0000400 /* buffered */ +#define UNIT_ROABLE 0001000 /* read only ok */ +#define UNIT_DISABLE 0002000 /* disable-able */ +#define UNIT_DIS 0004000 /* disabled */ +#define UNIT_IDLE 0040000 /* idle eligible */ +#endif /* DEFINED_IN_SIM_DEFS_H */ + +UNIT cpu_unit = + /* Unit data layout for CPU */ +/* { UDATA(rtc_srv, UNIT_BINK | MODEL(MODEL_27) | MEMAMOUNT(0), MAXMEMSIZE ), 120 }; */ + { + NULL, /* UNIT *next */ /* next active */ + NULL, /* t_stat (*action) */ /* action routine */ + NULL, /* char *filename */ /* open file name */ + NULL, /* FILE *fileref */ /* file reference */ + NULL, /* void *filebuf */ /* memory buffer */ + 0, /* uint32 hwmark */ /* high water mark */ + 0, /* int32 time */ /* time out */ + UNIT_BINK|MODEL(MODEL_27)|MEMAMOUNT(1), /* uint32 flags */ /* flags */ + 0, /* uint32 dynflags */ /* dynamic flags */ + MAXMEMSIZE, /* t_addr capac */ /* capacity */ + 0, /* t_addr pos */ /* file position */ + NULL, /* void (*io_flush) */ /* io flush routine */ + 0, /* uint32 iostarttime */ /* I/O start time */ + 0, /* int32 buf */ /* buffer */ + 80, /* int32 wait */ /* wait */ +}; + +/* Register data structure definition from sim_defs.h */ +#ifdef DEFINED_IN_SIM_DEFS_H +struct REG { + CONST char *name; /* name */ + void *loc; /* location */ + uint32 radix; /* radix */ + uint32 width; /* width */ + uint32 offset; /* starting bit */ + uint32 depth; /* save depth */ + const char *desc; /* description */ + BITFIELD *fields; /* bit fields */ + uint32 qptr; /* circ q ptr */ + size_t str_size; /* structure size */ + /* NOTE: Flags MUST always be last since it is initialized outside of macro definitions */ + uint32 flags; /* flags */ + }; + +/* Register flags from sim_defs.h */ +#define REG_FMT 00003 /* see PV_x */ +#define REG_RO 00004 /* read only */ +#define REG_HIDDEN 00010 /* hidden */ +#define REG_NZ 00020 /* must be non-zero */ +#define REG_UNIT 00040 /* in unit struct */ +#define REG_STRUCT 00100 /* in structure array */ +#define REG_CIRC 00200 /* circular array */ +#define REG_VMIO 00400 /* use VM data print/parse */ +#define REG_VMAD 01000 /* use VM addr print/parse */ +#define REG_FIT 02000 /* fit access to size */ +#define REG_HRO (REG_RO | REG_HIDDEN) /* hidden, read only */ + +#define REG_V_UF 16 /* device specific */ +#define REG_UFMASK (~((1u << REG_V_UF) - 1)) /* user flags mask */ +#define REG_VMFLAGS (REG_VMIO | REG_UFMASK) /* call VM routine if any of these are set */ +#endif /* DEFINED_IN_SIM_DEFS_H */ + +//UNIT cpu_unit = { UDATA (&rtc_srv, UNIT_BINK, MAXMEMSIZE) }; + +REG cpu_reg[] = { + {HRDATAD(PC, PC, 24, "Program Counter"), REG_FIT}, + {BRDATAD(PSD, PSD, 16, 32, 2, "Progtam Status Doubleword"), REG_FIT}, + {BRDATAD(GPR, GPR, 16, 32, 8, "Index registers"), REG_FIT}, + {BRDATAD(BR, BR, 16, 32, 8, "Base registers"), REG_FIT}, + {BRDATAD(SPAD, SPAD, 16, 32, 256, "CPU Scratchpad memory"), REG_FIT}, + {BRDATAD(MAPC, MAPC, 16, 32, 1024, "CPU mape cache"), REG_FIT}, + {HRDATAD(CPUSTATUS, CPUSTATUS, 32, "CPU Status Word"), REG_FIT}, + {HRDATAD(TRAPSTATUS, TRAPSTATUS, 32, "TRAP Status Word"), REG_FIT}, + {HRDATAD(CC, CC, 32, "Condition Codes"), REG_FIT}, + {BRDATAD(INTS, INTS, 16, 32, 112, "Interrupt Status"), REG_FIT}, +// {ORDATAD(BASE, baseaddr, 16, "Relocation base"), REG_FIT}, + {NULL} +}; + +/* Modifier table layout (MTAB) - only extended entries have disp, reg, or flags */ +MTAB cpu_mod[] = { + { + /* MTAB table layout for cpu type */ + /* {UNIT_MODEL, MODEL(MODEL_55), "32/55", "32/55", NULL, NULL, NULL, "Concept 32/55"}, */ + UNIT_MODEL, /* uint32 mask */ /* mask */ + MODEL(MODEL_55), /* uint32 match */ /* match */ + "32/55", /* cchar *pstring */ /* print string */ + "32/55", /* cchar *mstring */ /* match string */ + NULL, /* t_stat (*valid) */ /* validation routine */ + NULL, /* t_stat (*disp) */ /* display routine */ + NULL, /* void *desc */ /* value descriptor, REG* if MTAB_VAL, int* if not */ + "Concept 32/55", /* cchar *help */ /* help string */ + }, + {UNIT_MODEL, MODEL(MODEL_75), "32/75", "32/75", NULL, NULL, NULL, "Concept 32/75"}, + {UNIT_MODEL, MODEL(MODEL_27), "32/27", "32/27", NULL, NULL, NULL, "Concept 32/27"}, + {UNIT_MODEL, MODEL(MODEL_67), "32/67", "32/67", NULL, NULL, NULL, "Concept 32/67"}, + {UNIT_MODEL, MODEL(MODEL_87), "32/87", "32/87", NULL, NULL, NULL, "Concept 32/87"}, + {UNIT_MODEL, MODEL(MODEL_97), "32/97", "32/97", NULL, NULL, NULL, "Concept 32/97"}, + {UNIT_MODEL, MODEL(MODEL_V6), "V6", "V6", NULL, NULL, NULL, "Concept V6"}, + {UNIT_MODEL, MODEL(MODEL_V9), "V9", "V9", NULL, NULL, NULL, "Concept V9"}, + { + /* MTAB table layout for cpu memory size */ + /* {UNIT_MSIZE, MEMAMOUNT(0), "128K", "128K", &cpu_set_size}, */ + UNIT_MSIZE, /* uint32 mask */ /* mask */ + MEMAMOUNT(0), /* uint32 match */ /* match */ + "128K", /* cchar *pstring */ /* print string */ + "128K", /* cchar *mstring */ /* match string */ + &cpu_set_size, /* t_stat (*valid) */ /* validation routine */ + NULL, /* t_stat (*disp) */ /* display routine */ + NULL, /* void *desc */ /* value descriptor, REG* if MTAB_VAL, int* if not */ + NULL, /* cchar *help */ /* help string */ + }, + {UNIT_MSIZE, MEMAMOUNT(1), "256K", "256K", &cpu_set_size}, + {UNIT_MSIZE, MEMAMOUNT(2), "512K", "512K", &cpu_set_size}, + {UNIT_MSIZE, MEMAMOUNT(3), "1M", "1M", &cpu_set_size}, + {UNIT_MSIZE, MEMAMOUNT(4), "2M", "2M", &cpu_set_size}, + {UNIT_MSIZE, MEMAMOUNT(5), "3M", "3M", &cpu_set_size}, + {UNIT_MSIZE, MEMAMOUNT(6), "4M", "4M", &cpu_set_size}, + {UNIT_MSIZE, MEMAMOUNT(7), "8M", "8M", &cpu_set_size}, + {UNIT_MSIZE, MEMAMOUNT(8), "16M", "16M", &cpu_set_size}, + {MTAB_XTD | MTAB_VDV | MTAB_NMO | MTAB_SHP, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist}, + {0} +}; + +/* CPU device descriptor */ +DEVICE cpu_dev = { + /* "CPU", &cpu_unit, cpu_reg, cpu_mod, + 1, 8, 24, 1, 8, 32, + &cpu_ex, &cpu_dep, &cpu_reset, NULL, NULL, NULL, + NULL, DEV_DEBUG, 0, dev_debug, + NULL, NULL, &cpu_help, NULL, NULL, &cpu_description */ + "CPU", /* cchar *name */ /* device name */ + &cpu_unit, /* UNIT *units */ /* unit array */ + cpu_reg, /* REG *registers */ /* register array */ + cpu_mod, /* MTAB *modifiers */ /* modifier array */ + 1, /* uint32 numunits */ /* number of units */ + 16, /* uint32 aradix */ /* address radix */ + 24, /* uint32 awidth */ /* address width */ + 2, /* uint32 aincr */ /* address increment */ + 16, /* uint32 dradix */ /* data radix */ + 32, /* uint32 dwidth */ /* data width */ + &cpu_ex, /* t_stat (*examine) */ /* examine routine */ + &cpu_dep, /* t_stat (*deposit) */ /* deposit routine */ + &cpu_reset, /* t_stat (*reset) */ /* reset routine */ + NULL, /* t_stat (*boot) */ /* boot routine */ + NULL, /* t_stat (*attach) */ /* attach routine */ + NULL, /* t_stat (*detach) */ /* detach routine */ + NULL, /* void *ctxt */ /* (context) device information block pointer */ + DEV_DEBUG, /* uint32 flags */ /* device flags */ + 0, /* uint32 dctrl */ /* debug control flags */ + dev_debug, /* DEBTAB *debflags */ /* debug flag name array */ + NULL, /* t_stat (*msize) */ /* memory size change routine */ + NULL, /* char *lname */ /* logical device name */ + &cpu_help, /* t_stat (*help) */ /* help function */ + NULL, /* t_stat (*attach_help) */ /* attach help function */ + NULL, /* void *help_ctx */ /* Context available to help routines */ + &cpu_description, /* cchar *(*description) */ /* Device description */ + NULL, /* BRKTYPTB *brk_types */ /* Breakpoint types */ +}; + +/* CPU Instruction decode flags */ +#define INV 0x0000 /* Instruction is invalid */ +#define HLF 0x0001 /* Half word instruction */ +#define ADR 0x0002 /* Normal addressing mode */ +#define IMM 0x0004 /* Immediate mode */ +#define WRD 0x0008 /* Word addressing, no index */ +#define SCC 0x0010 /* Sets CC */ +#define RR 0x0020 /* Read source register */ +#define R1 0x0040 /* Read destination register */ +#define RB 0x0080 /* Read base register into dest */ +#define SD 0x0100 /* Stores into destination register */ +#define SDD 0x0200 /* Stores double into destination */ +#define RM 0x0400 /* Reads memory */ +#define SM 0x0800 /* Stores memory */ +#define DBL 0x1000 /* Double word operation */ +#define SB 0x2000 /* Store Base register */ +#define BT 0x4000 /* Branch taken, no PC incr */ + +int nobase_mode[] = { + /* 00 04 08 0C */ + /* 00 ANR, ORR, EOR */ + HLF, SCC|R1|RR|SD|HLF, SCC|R1|RR|SD|HLF, SCC|R1|RR|SD|HLF, + /* 10 14 18 1C */ + /* CAR, CMR, SBR ZBR */ + HLF, HLF, HLF, HLF, + /* 20 24 28 2C */ + /* ABR TBR REG TRR */ + HLF, HLF, HLF, HLF, + /* 30 34 38 3C */ + /* CALM LA ADR SUR */ + HLF, SD|ADR, HLF, HLF, + /* 40 44 48 4C */ + /* MPR DVR */ + SD|HLF, HLF, INV, INV, + /* 50 54 58 5C */ + /* */ + INV, INV, INV, INV, + + /* 60 64 68 6C */ + /* NOR NORD SCZ SRA */ + SD|HLF, SDD|HLF, HLF, HLF, + + /* 70 74 78 7C */ + /* SRL SRC SRAD SRLD */ + SD|HLF, SD|HLF, HLF, HLF, + + /* 80 84 88 8C */ + /* LEAR ANM ORM EOM */ + SD|ADR, SCC|SD|RR|RM|ADR, SCC|SD|RR|RM|ADR, SCC|SD|RR|RM|ADR, + + /* 90 94 98 9C */ + /* CAM CMM SBM ZBM */ + SCC|RR|RM|ADR, RR|RM|ADR, ADR, ADR, + + /* A0 A4 A8 AC */ + /* ABM TBM EXM L */ + ADR, ADR, ADR, SCC|SD|RM|ADR, + + /* B0 B4 B8 BC */ + /* LM LN ADM SUM */ + SCC|SD|RM|ADR, SCC|SD|RM|ADR, SCC|SD|RR|RM|ADR, SCC|SD|RR|RM|ADR, + + /* C0 C4 C8 CC */ + /* MPM DVM IMM LF */ + SCC|SD|RM|ADR, RM|ADR, IMM, ADR, + + /* D0 D4 D8 DC */ + /* LEA ST STM STF */ + SD|ADR, RR|SM|ADR, RR|SM|ADR, ADR, + + /* E0 E4 E8 EC */ + /* ADF MPF ARM BCT */ + SCC|SD|RM|ADR, SCC|RM|ADR, SCC|SM|RR|RM|ADR, ADR, + + /* F0 F4 F8 FC */ + /* BCF BI MISC IO */ + ADR, RR|SD|WRD, ADR, IMM, +}; + +int base_mode[] = { + /* 00 04 08 0C */ + /* 00 AND, OR, EOR */ + HLF, SCC|RR|SD|HLF, SCC|RR|SD|HLF, SCC|RR|SD|HLF, + /* 10 14 18 1C */ + /* SACZ CMR xBR SRx */ + HLF, HLF, HLF, HLF, + /* 20 24 28 2C */ + /* SRxD SRC REG TRR */ + SD|HLF, SD|HLF, HLF, HLF, + /* 30 34 38 3C */ + /* LA FLRop SUR */ + INV, INV, SD|HLF, SD|HLF, + /* 40 44 48 4C */ + /* */ + INV, INV, INV, INV, + + /* 50 54 58 5C */ + /* LA BASE BASE CALLM */ + SD|ADR, SM,ADR, SB|RM|ADR, ADR, + + /* 60 64 68 6C */ + /* */ + INV, INV, INV, INV, + /* 70 74 78 7C */ + /* */ + INV, INV, INV, INV, + /* LEAR ANM ORM EOM */ + /* 80 84 88 8C */ + SD|ADR, SD|RM|ADR, SD|RM|ADR, SD|RM|ADR, + + /* CAM CMM SBM ZBM */ + /* 90 94 98 9C */ + RM|ADR, RM|ADR, ADR, ADR, + + /* A0 A4 A8 AC */ + /* ABM TBM EXM L */ + ADR, ADR, ADR, SD|RM|ADR, + + /* B0 B4 B8 BC */ + /* LM LN ADM SUM */ + SD|RM|ADR,SD|RM|ADR, SD|RM|ADR, SD|RM|ADR, + + /* C0 C4 C8 CC */ + /* MPM DVM IMM LF */ + SD|RM|ADR, RM|ADR, IMM, ADR, + + /* D0 D4 D8 DC */ + /* LEA ST STM STFBR */ + SD|ADR, SM|ADR, SM|ADR, ADR, + /* E0 E4 E8 EC */ + /* ADF MPF ARM BCT */ + SD|RM|ADR, RM|ADR, SM|RM|ADR, ADR, + /* F0 F4 F8 FC */ + /* BCF BI MISC IO */ + ADR, RR|SB|WRD, ADR, IMM, +}; + +/* set up the map registers for the current task in the cpu */ +/* the PSD bpix and cpix are used to setup the maps */ +/* return non-zero if mapping error */ +t_stat load_maps(uint32 thepsd[2]) +{ + uint32 num, sdc, spc; + uint32 mpl, cpixmsdl, bpixmsdl, msdl, midl; + uint32 cpix, bpix, i, j, map, osmidl; + + if (CPU_MODEL < MODEL_27) + { + /* 32/7x machine, 8KW maps */ + modes &= ~BASEBIT; /* no basemode on 7x */ + if ((thepsd[1] & 0xc0000000) == 0) { /* mapped mode? */ + return ALLOK; /* no, all OK, no mapping required */ + } + /* we are mapped, so load the maps for this task into the cpu map cache */ + cpix = (thepsd[1] >> 2) & 0xfff; /* get cpix 12 bit offset from psd wd 2 */ + bpix = (thepsd[1] >> 18) & 0xfff; /* get bpix 12 bit offset from psd wd 2 */ + num = 0; /* working map number */ + /* master process list is in 0x83 of spad for 7x */ + mpl = SPAD[0x83] >> 2; /* get mpl from spad address */ + cpixmsdl = M[mpl + cpix]; /* get msdl from mpl for given cpix */ + /* if bit zero of mpl entry is set, use bpix first to load maps */ + if (cpixmsdl & BIT0) + { + /* load bpix maps first */ + bpixmsdl = M[mpl + bpix]; /* get bpix msdl word address */ + sdc = (bpixmsdl >> 24) & 0x3f; /* get 6 bit segment description count */ + msdl = (bpixmsdl >> 2) & 0x3fffff; /* get 24 bit real address of msdl */ + for (i = 0; i < sdc; i++) /* loop through the msd's */ + { + spc = (M[msdl + i] >> 24) & 0xff; /* get segment page count from msdl */ + midl = (M[msdl + i] >> 2) && 0x3fffff; /* get 24 bit real word address of midl */ + for (j = 0; j < spc; j++) + { + /* load 16 bit map descriptors */ + map = (M[midl + (j / 2)]); /* get 2 16 bit map entries */ + if (j & 1) + map = (map & RMASK); /* use right half word map entry */ + else + map = ((map >> 16) & RMASK); /* use left half word map entry */ + /* the map register contents is now in right 16 bits */ + /* now load a 32 bit word with both maps from memory */ + /* and or in the new map entry data */ + if (num & 1) { + /* entry going to rt hw, clean it first */ + map = (MAPC[num/2] & LMASK) | map; /* map is in rt hw */ + } + else { + /* entry going to left hw, clean it first */ + map = (MAPC[num/2] & RMASK) | (map << 16); /* map is in left hw */ + } + MAPC[num++/2] = map; /* store the map reg contents into cache */ + if (num >= 32) + return MAPFLT; /* map loading overflow, map fault error */ + } + } + } + /* now load cpix maps */ + cpixmsdl = M[mpl + cpix]; /* get cpix msdl word address */ + sdc = (cpixmsdl >> 24) & 0x3f; /* get 6 bit segment description count */ + msdl = (cpixmsdl >> 2) & 0x3fffff; /* get 24 bit real address of msdl */ + for (i = 0; i < sdc; i++) + { + spc = (M[msdl + i] >> 24) & 0xff; /* get segment page count from msdl */ + midl = (M[msdl + i] >> 2) && 0x3fffff; /* get 24 bit real word address of midl */ + for (j = 0; j < spc; j++) + { + /* load 16 bit map descriptors */ + map = (M[midl + (j / 2)]); /* get 2 16 bit map entries */ + if (j & 1) + map = (map & RMASK); /* use right half word map entry */ + else + map = ((map >> 16) & RMASK); /* use left half word map entry */ + /* the map register contents is now in right 16 bits */ + /* now load a 32 bit word with both maps from memory */ + /* and or in the new map entry data */ + if (num & 1) { + /* entry going to rt hw, clean it first */ + map = (MAPC[num/2] & LMASK) | map; /* map is in rt hw */ + } + else { + /* entry going to left hw, clean it first */ + map = (MAPC[num/2] & RMASK) | (map << 16); /* map is in left hw */ + } + MAPC[num++/2] = map; /* store the map reg contents into cache */ + if (num >= 32) + return MAPFLT; /* map loading overflow, map fault error */ + } + } + /* if none loaded, map fault */ + if (num == 0) + return MAPFLT; /* map fault error */ + if (num & 1) { /* clear rest of maps */ + /* left hw of map is good, zero right */ + map = (MAPC[num/2] & LMASK); /* clean rt hw */ + MAPC[num++/2] = map; /* store the map reg contents into cache */ + } + /* num should be even at this point, so zero 32 bit word for remaining maps */ + if ((num/2) > HIWM) /* largerst number of maps loaded so far* */ + HIWM = num/2; /* yes, set new high watter mark */ +// for (i = num/2; i < 32/2; i++) /* zero any remaining entries */ + for (i = num/2; i < HIWM; i++) /* zero any remaining entries */ + MAPC[i] = 0; /* clear the map entry to make not valid */ + return ALLOK; /* all cache is loaded, return OK */ + } + else + { + char n[9]; + uint32 dqe; + /* 32/27, 32/67, 32/87, 32/97 2KW maps */ + /* Concept/32 machine, 2KW maps */ + if ((modes & MAPMODE) == 0) { /* mapped mode? */ +// fprintf(stderr, "not mapping PSD2 %x\r\n", PSD2); + return ALLOK; /* no, all OK, no mapping required */ + } + /* we are mapped, so calculate real address from map information */ + cpix = (thepsd[1] >> 2) & 0xfff; /* get word cpix 11 bit offset from psd wd 2 */ + num = 0; /* no maps loaded yet */ + /* master process list is in 0xf3 of spad for concept */ + mpl = SPAD[0xf3] >> 2; /* get mpl from spad address */ + midl = M[mpl+cpix]; /* get mpl entry wd 0 for given cpix */ + msdl = M[mpl+cpix+1]; /* get mpl entry wd 0 for given cpix */ + dqe = M[0x8e8>>2]; + for (j=0; j<8; j++) { + n[j] = (M[((dqe+0x18)>>2)+(j/4)] >> ((3-(j&7))*8)) & 0xff; + if (n[j] == 0) + n[j] = 0x20; + } + n[8] = 0; +// fprintf(stderr, "mapping SPAD PSD2 %.8x PSD2 %x mpl %x osmidl %x umidl %x C.CURR %x LMN %s\r\n", +// SPAD[0xf5], PSD2, mpl, M[mpl], midl, dqe, n); + /* if bit zero of mpl entry is set, use msd entry 0 first to load maps */ + if (midl & BIT0) + { +/* TODO do not load O/S if already loaded. Bit zero of O/S midl will be set by swapper */ + /* load msd 0 maps first (O/S) */ + osmidl = M[mpl]; /* get midl 0 word address */ + spc = osmidl & MASK16; /* get 16 bit segment description count */ + if (osmidl & BIT0) { /* see f O/S already loaded */ + num = spc; /* set the number of o/s maps loaded */ + goto skipos; /* skip load */ + } + midl = M[mpl+1] & MASK24; /* get 24 bit real address from mpl wd2 */ + midl = midl>>2; /* make word address */ + for (j = 0; j < spc; j++) + { + /* load 16 bit map descriptors */ + map = (M[midl + (j / 2)]); /* get 2 16 bit map entries */ + if (j & 1) + map = (map & RMASK); /* use right half word map entry */ + else + map = ((map >> 16) & RMASK); /* use left half word map entry */ + /* the map register contents is now in right 16 bits */ + /* now load a 32 bit word with both maps from memory */ + /* and or in the new map entry data */ + if (num & 1) { + /* entry going to rt hw, clean it first */ + map = (MAPC[num/2] & LMASK) | map; /* map is in rt hw */ +// fprintf(stderr, "mapping 0x%x O/S num 0x%x midl %x MAPC[%d] %x\r\n", +// spc, num-1, (midl+(j/2))<<2, num/2, map); + } + else { + /* entry going to left hw, clean it first */ + map = (MAPC[num/2] & RMASK) | (map << 16); /* map is in left hw */ + } + MAPC[num/2] = map; /* store the map reg contents into cache */ + if (++num >= 2048) + return MAPFLT; /* map loading overflow, map fault error */ + } +#if 0 + if (num & 1) + fprintf(stderr, "mapping 0x%x O/S num 0x%x midl %x MAPC[%d] %x\r\n", + spc, num-1, (midl+((spc-1)/2))<<2, num/2, map); +#endif + } +skipos: + /* now load cpix maps */ + midl = M[mpl+cpix]; /* get cpix midl word address */ + msdl = M[mpl+cpix+1]; /* get 24 bit real word address of midl */ + spc = midl & RMASK; /* get segment page count from msdl */ + midl = M[mpl+cpix+1] & MASK24; /* get 24 bit real word address of midl */ + midl = midl>>2; /* get word address of midl */ + for (j = 0; j < spc; j++) + { + /* load 16 bit map descriptors */ + map = M[midl + (j / 2)]; /* get 2 16 bit map entries */ + if (j & 1) + map = (map & RMASK); /* use right half word map entry */ + else + map = ((map >> 16) & RMASK); /* use left half word map entry */ + /* the map register contents is now in right 16 bits */ + /* now load a 32 bit word with both maps from memory */ + /* and or in the new map entry data */ + if (num & 1) { + /* entry going to rt hw, clean it first */ + map = (MAPC[num/2] & LMASK) | map; /* map is in rt hw */ +// fprintf(stderr, "mapping 0x%x USER num 0x%x midl %x MAPC[%d] %x\r\n", +// spc, num-1, (midl+(j/2))<<2, num/2, map); + } + else { + /* entry going to left hw, clean it first */ + map = (MAPC[num/2] & RMASK) | (map << 16); /* map is in left hw */ + } + MAPC[num/2] = map; /* store the map reg contents into cache */ + if (++num >= 2048) + return MAPFLT; /* map loading overflow, map fault error */ + } + /* if none loaded, map fault */ + /* we got here without map block found, return map fault error */ + if (num == 0) + return MAPFLT; /* map fault error */ + if (num & 1) { + /* left hw of map is good, zero right */ + map = (MAPC[num/2] & LMASK); /* clean rt hw */ +// if (spc != 0) +// fprintf(stderr, "mapping 0x%x USER num 0x%x midl %x MAPC[%d] %x\r\n", +// spc, num-1, (midl+((spc-1)/2))<<2, num/2, map); + MAPC[num++/2] = map; /* store the map reg contents into cache */ + } + /* num should be even at this point, so zero 32 bit words for remaining maps */ + if ((num/2) > HIWM) /* largerst number of maps loaded so far* */ + HIWM = num/2; /* yes, set new high watter mark */ +// for (i = num/2; i < 2048/2; i++) /* zero any remaining entries */ + for (i = num/2; i < HIWM; i++) /* zero any remaining entries */ + MAPC[i] = 0; /* clear the map entry to make not valid */ + return ALLOK; /* all cache is loaded, retun OK */ + } +} + +/* + * Return the real memory address from the logical address + * Also return the protection status, 1 if write protected address + */ +t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot) +{ + uint32 word, index, map, mask; + + *prot = 0; /* show unprotected memory as default */ + /* unmapped mode is unprotected */ + + /* see what machine we have */ + if (CPU_MODEL < MODEL_27) + { + /* 32/7x machine with 8KW maps */ + if (modes & EXTDBIT) + word = addr & 0xfffff; /* get 20 bit logical word address */ + else + word = addr & 0x7ffff; /* get 19 bit logical word address */ + if ((modes & MAPMODE) == 0) { + /* check if valid real address */ + if (word >= MEMSIZE) /* see if address is within our memory */ + return NPMEM; /* no, none present memory error */ + *realaddr = word; /* return the real address */ + return ALLOK; /* all OK, return instruction */ + } + /* we are mapped, so calculate real address from map information */ + /* 32/7x machine, 8KW maps */ + index = word >> 15; /* get 4 or 5 bit value */ + map = MAPC[index/2]; /* get two hw map entries */ + if (index & 1) + /* entry is in rt hw, clear left hw */ + map &= RMASK; /* map is in rt hw */ + else + /* entry is in left hw, move to rt hw */ + map >>= 16; /* map is in left hw */ + /* see if map is valid */ + if (map & 0x4000) { + /* required map is valid, get 9 bit address and merge with 15 bit page offset */ + word = ((map & 0x1ff) << 15) | (word & 0x7fff); + /* check if valid real address */ + if (word >= MEMSIZE) /* see if address is within our memory */ + return NPMEM; /* no, none present memory error */ + if ((modes & PRIVBIT) == 0) { /* see if we are in unprivileged mode */ + if (map & 0x2000) /* check if protect bit is set in map entry */ + *prot = 1; /* return memory write protection status */ + } + *realaddr = word; /* return the real address */ + return ALLOK; /* all OK, return instruction */ + } + /* map is invalid, so return map fault error */ + return MAPFLT; /* map fault error */ + } + else { + /* 32/27, 32/67, 32/87, 32/97 2KW maps */ + /* Concept 32 machine, 2KW maps */ + if (modes & (BASEBIT | EXTDBIT)) + word = addr & 0xffffff; /* get 24 bit address */ + else + word = addr & 0x7ffff; /* get 19 bit address */ + if ((modes & MAPMODE) == 0) { + /* check if valid real address */ + if (word >= MEMSIZE) /* see if address is within our memory */ + return NPMEM; /* no, none present memory error */ + *realaddr = word; /* return the real address */ +//fprintf(stderr, "Read Real unmapped addr %x\r\n", addr, index, map); + return ALLOK; /* all OK, return instruction */ + } + /* replace bits 8-18 with 11 bits from memory map register */ + /* we are mapped, so calculate real address from map information */ + index = (word >> 13) & 0x7ff; /* get 11 bit value */ + map = MAPC[index/2]; /* get two hw map entries */ +//fprintf(stderr, "read addr %x index %x map %x\r\n", addr, index, map); + if (index & 1) + /* entry is in rt hw, clear left hw */ + map &= RMASK; /* map is in rt hw */ + else + /* entry is in left hw, move to rt hw */ + map >>= 16; /* map is in left hw */ +//fprintf(stderr, "read 2 addr %x index %x map %x\r\n", word, index, map); + if (map & 0x8000) { /* see if map is valid */ + /* required map is valid, get 11 bit address and merge with 13 bit page offset */ + word = ((map & 0x7ff) << 13) | (word & 0x1fff); + /* check if valid real address */ + if (word >= MEMSIZE) /* see if address is within our memory */ + return NPMEM; /* no, none present memory error */ + if ((modes & PRIVBIT) == 0) { /* see if we are in unprivileged mode */ + mask = (word & 0x1800) >> 11; /* get offset of 2kb block for map being addressed */ + if (map & (0x4000 >> mask)) /* check if protect bit is set in map entry */ + *prot = 1; /* return memory write protection status */ + } +//fprintf(stderr, "Read Real addr %x index %x map %x reala %x PSD2 %x\r\n", addr, index, map, word, SPAD[0xf5]); + *realaddr = word; /* return the real address */ + return ALLOK; /* all OK, return instruction */ + } + /* map is invalid, so return map fault error */ +// fprintf(stderr, "RealAddr MAP FAIL %x MAPC %x word %x addr %x index %x\n", +// map, MAPC[index/2], word, addr, index); + sim_debug(DEBUG_CMD, &cpu_dev, "RealAddr MAP FAIL %x MAPC %x word %x addr %x index %x\n", + map, MAPC[index/2], word, addr, index); + return MAPFLT; /* map fault error */ + } +} + +/* fetch the current instruction from the PC address */ +t_stat read_instruction(uint32 thepsd[2], uint32 *instr) +{ + uint32 addr, status; + + if (CPU_MODEL < MODEL_27) + { + /* 32/7x machine with 8KW maps */ + /* instruction must be in first 512KB of address space */ + addr = thepsd[0] & 0x7fffc; /* get 19 bit logical word address */ + } + else + { + /* 32/27, 32/67, 32/87, 32/97 2KW maps */ + /* Concept 32 machine, 2KW maps */ + if (thepsd[0] & BASEBIT) { /* bit 6 is base mode? */ + addr = thepsd[0] & 0xfffffc; /* get 24 bit address */ + } + else + addr = thepsd[0] & 0x7fffc; /* get 19 bit address */ + } + status = Mem_read(addr, instr); /* get the instruction at the specified address */ + sim_debug(DEBUG_DETAIL, &cpu_dev, "read_instr status = %x\n", status); + return status; /* return ALLOK or ERROR */ +} + +/* + * Read a full word from memory + * Return error type if failure, ALLOK if + * success. Addr is logical address. + */ +t_stat Mem_read(uint32 addr, uint32 *data) +{ + uint32 status, realaddr, prot; + + status = RealAddr(addr, &realaddr, &prot); /* convert address to real physical address */ + sim_debug(DEBUG_DETAIL, &cpu_dev, "Mem_read status = %x\n", status); + if (status == ALLOK) { + *data = M[realaddr >> 2]; /* valid address, get physical address contents */ + status = ALLOK; /* good status return */ + sim_debug(DEBUG_DETAIL, &cpu_dev, "Mem_read addr %.8x realaddr %.8x data %.8x prot %d\n", + addr, realaddr, *data, prot); + } + return status; /* return ALLOK or ERROR */ +} + +/* + * Write a full word to memory, checking protection + * and alignment restrictions. Return 1 if failure, 0 if + * success. Addr is logical address, data is 32bit word + */ +t_stat Mem_write(uint32 addr, uint32 *data) +{ + uint32 status, realaddr, prot; + + status = RealAddr(addr, &realaddr, &prot); /* convert address to real physical address */ + sim_debug(DEBUG_DETAIL, &cpu_dev, "Mem_write addr %.8x realaddr %.8x data %.8x prot %d\n", + addr, realaddr, *data, prot); + if (status == ALLOK) { + if (prot) /* check for write protected memory */ + return MPVIOL; /* return memory protection violation */ + M[realaddr >> 2] = *data; /* valid address, put physical address contents */ + status = ALLOK; /* good status return */ + } + return status; /* return ALLOK or ERROR */ +} + +/* function to set the CCs in PSD1 */ +/* ovr is setting for CC1 */ +void set_CCs(uint32 value, int ovr) +{ + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + if (ovr) + CC = CC1BIT; /* CC1 value */ + else + CC = 0; /* CC1 off */ + if (value & FSIGN) + CC |= CC3BIT; /* CC3 for neg */ + else if (value == 0) + CC |= CC4BIT; /* CC4 for zero */ + else + CC |= CC2BIT; /* CC2 for greater than zero */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ +} + +/* Opcode definitions */ +/* called from simulator */ +t_stat +sim_instr(void) +{ + t_stat reason = 0; /* reason for stopping */ + t_uint64 dest; /* Holds destination/source register */ + t_uint64 source; /* Holds source or memory data */ + t_uint64 td; /* Temporary */ + uint32 addr; /* Holds address of last access */ + uint32 temp; /* General holding place for stuff */ + uint32 IR; /* Instruction register */ + uint32 i_flags; /* Instruction description flags from table */ + uint32 t; /* Temporary */ + uint32 temp2; /* Temporary */ + uint32 bc; /* Temporary bit count */ + uint16 opr; /* Top half of Instruction register */ + uint16 OP; /* Six bit instruction opcode */ + uint16 chan; /* I/O channel address */ + uint16 lchan; /* Logical I/O channel address */ + uint16 suba; /* I/O subaddress */ + uint8 FC; /* Current F&C bits */ + uint8 EXM_EXR=0; /* PC Increment for EXM/EXR instructions */ + int reg; /* GPR or Base register bits 6-8 */ + int sreg; /* Source reg in from bits 9-11 reg-reg instructions */ + int ix; /* index register */ + int dbl; /* Double word */ + int ovr; /* Overflow flag */ + int stopnext = 0; /* Stop on next instruction */ + int skipinstr = 0; /* Skip test for interrupt on this instruction */ + uint32 int_icb; /* interrupt context block address */ + uint32 OIR; /* Original Instruction register */ + uint32 OPSD1; /* Original PSD1 */ + uint32 OPC; /* Original PC */ + +wait_loop: + while (reason == 0) { /* loop until halted */ + + // wait_loop: + if (sim_interval <= 0) { /* event queue? */ + reason = sim_process_event(); /* process */ + if (reason != SCPE_OK) { + if (reason == SCPE_STEP) + stopnext = 1; + else + break; /* process */ + } + } + + if (sim_brk_summ && sim_brk_test(PC, SWMASK('E'))) { + reason = STOP_IBKPT; + break; + } + + /* call our fake interval timer to count down 64 instructions per count */ + itm_srv(&itm_unit); /* service interval timer */ + sim_interval--; /* count down */ + + if (skipinstr) { /* need to skip interrupt test? */ + skipinstr = 0; /* skip only once */ + goto skipi; /* skip int test */ + } + + /* process pending I/O interrupts */ + if (!loading && (wait4int || irq_pend)) { /* see if ints are pending */ + int_icb = scan_chan(); /* no, go scan for I/O int pending */ + if (int_icb != 0) { /* was ICB returned for an I/O or interrupt */ + int il; + /* find interrupt level for icb address */ + for (il=0; il<112; il++) { + /* get the address of the interrupt IVL table in main memory */ + uint32 civl = SPAD[0xf1] + (il<<2); /* contents of spad f1 points to chan ivl in mem */ + civl = M[civl >> 2]; /* get the interrupt context block addr in memory */ + if (civl == int_icb) + break; + } +//sim_debug(DEBUG_EXP, &cpu_dev, "Normal int scan return icb %x\n", int_icb); +//fprintf(stderr, "Normal Interrupt scan return icb %x irq_pend %x wait4int %x\r\n", int_icb, irq_pend, wait4int); + /* take interrupt, store the PSD, fetch new PSD */ + bc = PSD2 & 0x3ffc; /* get copy of cpix */ + M[int_icb>>2] = PSD1&0xfffffffe; /* store PSD 1 */ + M[(int_icb>>2)+1] = PSD2; /* store PSD 2 */ + PSD1 = M[(int_icb>>2)+2]; /* get new PSD 1 */ + PSD2 = (M[(int_icb>>2)+3] & ~0x3ffc) | bc; /* get new PSD 2 w/old cpix */ + /* I/O status DW address will be in WD 6 */ + /* set new map mode and interrupt blocking state in CPUSTATUS */ + modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + if (PSD2 & MAPBIT) { + CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ + modes |= MAPMODE; /* set mapped mode */ + } else + CPUSTATUS &= 0xff7fffff; /* reset bit 8 of cpu status */ + if ((PSD2 & 0x8000) == 0) { /* is it retain blocking state */ + if (PSD2 & 0x4000) /* no, is it set blocking state */ + CPUSTATUS |= 0x80; /* yes, set blk state in cpu status bit 24 */ + else + CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ + } + PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ + if (CPUSTATUS & 0x80) /* see if old mode is blocked */ + PSD2 |= 0x00004000; /* set to blocked state */ + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + SPAD[0xf5] = PSD2; /* save the current PSD2 */ + sim_debug(DEBUG_INST, &cpu_dev, + "Interrupt %x OPSD1 %.8x OPSD2 %.8x NPSD1 %.8x NPSD2 %.8x ICBA %x\r\n", + il, M[int_icb>>2], M[(int_icb>>2)+1], PSD1, PSD2, int_icb); + wait4int = 0; /* wait is over for int */ + skipinstr = 1; /* skip next interrupt test only once */ + } + /* see if waiting at a wait instruction */ + if (wait4int || loading) { +// ???? sim_interval++; /* restore count */ + goto wait_loop; /* continue waiting */ + } + } else { + if (loading) { + uint32 chsa = scan_chan(); /* go scan for load complete pending */ + if (chsa != 0) { /* see if a boot channel/subaddress were returned */ + /* take interrupt, store the PSD, fetch new PSD */ + PSD1 = 0x80000000; /* get new PSD 1, priv and addr is 0 */ + PSD2 = 0x00004000; /* get new PSD 2, blocked */ + modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + sim_debug(DEBUG_INST, &cpu_dev, "Boot Loading PSD1 %.8x PSD2 %.8x\n", PSD1, PSD2); + /* set interrupt blocking state in CPUSTATUS */ + CPUSTATUS |= 0x80; /* set blocked state in cpu status, bit 24 too */ + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + SPAD[0xf5] = PSD2; /* save the current PSD2 */ + loading = 0; /* we are done loading */ + skipinstr = 1; /* skip next interrupt test only once */ + } + goto wait_loop; /* continue waiting */ + } + /* see if in wait instruction */ + if (wait4int) /* TRY this */ + goto wait_loop; /* continue waiting */ + } + + /* Check for external interrupt here */ + /* see if we have an attention request from console */ + if (!skipinstr && attention_trap) { + TRAPME = attention_trap; /* get trap number */ + attention_trap = 0; /* do only once */ +// fprintf(stderr, "Attention TRAP %x\r\n", TRAPME); + skipinstr = 1; /* skip next interrupt test only once */ + goto newpsd; /* got process trap */ + } + +skipi: + if (sim_brk_summ && sim_brk_test(PC, SWMASK('E'))) { + reason = STOP_IBKPT; + break; + } + + /* fill IR from logical memory address */ + if ((TRAPME = read_instruction(PSD, &IR))) { + sim_debug(DEBUG_INST, &cpu_dev, "read_instr TRAPME = %x\n", TRAPME); + goto newpsd; /* got process trap */ + } + + /* If executing right half */ + if (PSD1 & 2) + IR <<= 16; +exec: +/*FIXME temp saves */ + OIR = IR; + OPSD1 = PSD1; + OPC = PSD1 & 0xfffffe; /* get 24 bit addr from PSD1 */ + + /* TODO Update history for this instruction */ + if (hst_lnt) + { + hst_p += 1; /* next history location */ + if (hst_p >= hst_lnt) /* check for wrap */ + hst_p = 0; /* start over at beginning */ + hst[hst_p].psd1 = PSD1; /* set execution address */ + hst[hst_p].psd2 = PSD2; /* set mapping/blocking status */ + } + + /* Split instruction into pieces */ + PC = PSD1 & 0xfffffe; /* get 24 bit addr from PSD1 */ + sim_debug(DEBUG_DATA, &cpu_dev, "-----Instr @ PC %x PSD1 %.8x PSD2 %.8x IR %.8x\n", PC, PSD1, PSD2, IR); + opr = (IR >> 16) & MASK16; /* use upper half of instruction */ + OP = (opr >> 8) & 0xFC; /* Get opcode (bits 0-5) left justified */ + FC = ((IR & F_BIT) ? 0x4 : 0) | (IR & 3); /* get F & C bits for addressing */ + reg = (opr >> 7) & 0x7; /* dest reg or xr on base mode */ + sreg = (opr >> 4) & 0x7; /* src reg for reg-reg instructions or BR instr */ + dbl = 0; /* no doubleword instruction */ + ovr = 0; /* no overflow or arithmetic exception either */ + dest = (t_uint64)IR; /* assume memory address specified */ + CC = PSD1 & 0x78000000; /* save CC's if any */ + + if (modes & BASEBIT) { + i_flags = base_mode[OP>>2]; /* set the instruction processing flags */ + addr = IR & RMASK; /* get address offset from instruction */ +// sim_debug(DEBUG_INST, &cpu_dev, "Base i_flags %x addr %.8x\n", i_flags, addr); + switch(i_flags & 0xf) { + case HLF: + source = GPR[sreg]; /* get the src reg from instruction */ + break; + case IMM: + if (PC & 02) { /* if pc is on HW boundry, bad address */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + break; + case ADR: + case WRD: + if (PC & 02) { /* if pc is on HW boundry, bad address */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + ix = (IR >> 20) & 7; /* get index reg from instruction */ + if (ix != 0) + addr += GPR[ix]; /* if not zero, add in reg contents */ + ix = (IR >> 16) & 7; /* get base reg from instruction */ + if (ix != 0) + addr += BR[ix]; /* if not zero, add to base reg contents */ + FC = ((IR & F_BIT) ? 4 : 0); /* get F bit from original instruction */ + FC |= addr & 3; /* set new C bits to address from orig or regs */ + break; + case INV: + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + goto newpsd; /* handle trap */ + break; + } + } else { + i_flags = nobase_mode[OP>>2]; /* set the instruction processing flags */ + addr = IR & 0x7ffff; /* get 19 bit address from instruction */ + +// sim_debug(DEBUG_INST, &cpu_dev, "Non Based i_flags %x addr %.8x\n", i_flags, addr); + /* non base mode instructions have bit 0 of the instruction set */ + /* for word length instructions and zero for halfword instructions */ + /* the LA (op=0x34) is the only exception. So test for PC on a halfword */ + /* address and trap if word opcode is in right hw */ + if (PC & 02) { /* if pc is on HW boundry, addr trap if bit zero set */ + if ((OP == 0x34) || (OP & 0x80)) { + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + } + switch(i_flags & 0xf) { + case HLF: /* halfword instruction */ + source = GPR[sreg]; /* get the src reg contents */ + break; + + case IMM: /* Immediate mode */ + if (PC & 02) { /* if pc is on HW boundry, bad address */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + break; + + case ADR: /* Normal addressing mode */ + ix = (IR >> 21) & 3; /* get the index reg if specified */ + if (ix != 0) { + addr += GPR[ix]; /* if not zero, add in reg contents */ + FC = ((IR & F_BIT) ? 4 : 0); /* get F bit from original instruction */ + FC |= addr & 3; /* set new C bits to address from orig or regs */ + } + + /* wart alert! */ + /* the lea instruction requires special handling for indirection. */ + /* Bit 0,1 are set to 1 of result addr if indirect bit is zero in */ + /* instruction. Bits 0 & 1 are set to the last word */ + /* or instruction in the chain bits 0 & 1 if indirect bit set */ + /* if IX == 00 => dest = IR */ + /* if IX == 0x => dest = IR + reg */ + /* if IX == Ix => dest = ind + reg */ + + /* fall through */ + + case WRD: /* Word addressing, no index */ + bc = 0xC0000000; /* set bits 0, 1 for instruction if not indirect */ + t = IR; /* get current IR */ + while (t & IND) { /* process indirection */ + if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + bc = temp & 0xC0000000; /* save new bits 0, 1 from indirect location */ + CC = (temp & 0x78000000); /* save CC's from the last indirect word */ + if (modes & EXTDBIT) { /* check if in extended mode */ + /* extended mode, so location has 24 bit addr, not X,I ADDR */ +// fprintf(stderr, "Indirect EXT before addr %x contents %x\n", addr, temp); + addr = temp & MASK24; /* get 24 bit addr */ + /* if no C bits set, use original, else new */ + if ((IR & F_BIT) || (addr & 3)) + FC = ((IR & F_BIT) ? 0x4 : 0) | (addr & 3); +// fprintf(stderr, "Indirect EXT after addr %x temp %x\n", addr, temp); + t &= ~IND; /* turn off IND bit to stop while loop */ + } else { + /* non-extended mode, process new X, I, ADDR fields */ +// fprintf(stderr, "Indirect NE before addr %x contents %x\n", addr, temp); + addr = temp & MASK19; /* get just the addr */ + ix = (temp >> 21) & 3; /* get the index reg from indirect word */ + if (ix != 0) + addr += (GPR[ix] & MASK19); /* add the register to the address */ + /* if no F or C bits set, use original, else new */ + if ((temp & F_BIT) || (addr & 3)) + FC = ((temp & F_BIT) ? 0x4 : 0) | (addr & 3); +// fprintf(stderr, "Indirect NE after addr %x temp %x\n", addr, temp); + t = temp; /* go process next indirect location */ + } + } + if (OP == 0xD0) /* test for LEA op */ + addr |= bc; /* insert bits 0,1 values into address */ + dest = (t_uint64)addr; /* make into 64 bit variable */ + break; + case INV: /* Invalid instruction */ + if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + goto newpsd; /* handle trap */ + break; + } + } + + /* Read memory operand */ + if (i_flags & RM) { + if ((TRAPME = Mem_read(addr, &temp))) { /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + } + source = (t_uint64)temp; /* make into 64 bit value */ + switch(FC) { + case 0: /* word address, extend sign */ + source |= (source & MSIGN) ? D32LMASK : 0; + break; + case 1: /* left hw */ + source >>= 16; /* move left hw to right hw*/ + /* Fall through */ + case 3: /* right hw or right shifted left hw */ + source &= 0xffff; /* use just the right hw */ + if (source & 0x8000) { /* check sign of 16 bit value */ + /* sign extend the value to leftmost 48 bits */ + source = 0xFFFF0000 | (source & 0xFFFF); /* extend low 32 bits */ + source |= (D32LMASK); /* extend hi bits */ + } + break; + case 2: /* double word address */ + if ((addr & 2) != 2) { /* must be double word adddress */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + if ((TRAPME = Mem_read(addr+4, &temp))) { /* get the 2nd word from memory */ + goto newpsd; /* memory read error or map fault */ + } + source = (source << 32) | (t_uint64)temp; /* merge in the low order 32 bits */ + dbl = 1; /* double word instruction */ + break; + case 4: /* byte mode, byte 0 */ + case 5: /* byte mode, byte 1 */ + case 6: /* byte mode, byte 2 */ + case 7: /* byte mode, byte 3 */ + source = (source >> (8*(7-FC))) & 0xff; /* right justify addressed byte */ + break; + } + } + + /* Read in if from register */ + if (i_flags & RR) { + if (FC == 2 && (i_flags & HLF) == 0) /* double dest? */ + dbl = 1; /* src must be dbl for dbl dest */ + dest = (t_uint64)GPR[reg]; /* get the register content */ + if (dbl) { /* is it double regs */ + if (reg & 1) { /* check for odd reg load */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + /* merge the regs into the 64bit value */ + dest = (((t_uint64)dest) << 32) | ((t_uint64)GPR[reg+1]); + } else { + /* sign extend the data value */ + dest |= (dest & MSIGN) ? D32LMASK : 0; + } + } + + /* For Base mode */ + if (i_flags & RB) { + dest = (t_uint64)BR[reg]; /* get base reg contents */ + } + + /* For register instructions */ + if (i_flags & R1) { + source = (t_uint64)GPR[sreg]; + if (dbl) { + if (sreg & 1) { + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + /* merge the regs into the 64bit value */ + source = (source << 32) | ((t_uint64)GPR[reg+1]); + } else { + /* sign extend the data value */ + source |= (source & MSIGN) ? ((t_uint64)MASK32) << 32: 0; + } + } + + /* TODO Update other history information for this instruction */ + if(hst_lnt) { + hst[hst_p].inst = IR; /* save the instruction */ + hst[hst_p].dest = dest; /* save the destination */ + hst[hst_p].src = source; /* save the source */ + hst[hst_p].reg = reg; /* save the src/dst reg */ + } + +// sim_debug(DEBUG_INST, &cpu_dev, "SW OP %x Non Based i_flags %x addr %.8x\n", OP, i_flags, addr); + switch (OP>>2) { +/* + * For op-codes=00,04,08,0c,10,14,28,2c,38,3c,40,44,60,64,68 + */ + /* Reg - Reg instruction Format (16 bit) */ + /* |--------------------------------------| */ + /* |0 1 2 3 4 5|6 7 8 |9 10 11|12 13 14 15| */ + /* | Op Code | DReg | SReg | Aug Code | */ + /* |--------------------------------------| */ + case 0x00>>2: /* HLF - HLF */ /* CPU General operations */ + switch(opr & 0xF) { /* switch on aug code */ + case 0x0: /* HALT */ + if ((modes & PRIVBIT) == 0) { /* must be privileged to halt */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ + goto newpsd; /* Privlege violation trap */ + } + if (CPUSTATUS & 0x00000100) { /* Priv mode halt must be enabled */ + TRAPME = PRIVHALT_TRAP; /* set the trap to take */ + goto newpsd; /* Privlege mode halt trap */ + } +/*FIXME*/ reason = STOP_HALT; /* do halt for now */ + break; + case 0x1: /* WAIT */ + if (modes & PRIVBIT == 0) { /* must be privileged to wait */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ + goto newpsd; /* Privlege violation trap */ + } + if (wait4int == 0) { + time_t result = time(NULL); +// fprintf(stderr, "Starting WAIT mode @%ju\r\n", (intmax_t)result); + sim_debug(DEBUG_CMD, &cpu_dev, "Starting WAIT mode %ju\n", (intmax_t)result); + } + wait4int = 1; /* show we are waiting for interrupt */ + i_flags |= BT; /* keep PC from being incremented while waiting */ + break; + case 0x2: /* NOP */ + break; + case 0x3: /* LCS */ + GPR[reg] = M[0x780 >> 2]; /* get console switches from memory loc 0x780 */ + set_CCs(GPR[reg], 0); /* set the CC's, CC1 = 0 */ + break; + case 0x4: /* ES */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + /* reg is reg to extend sign into from reg+1 */ + GPR[reg] = (GPR[reg+1] & FSIGN) ? FMASK : 0; + set_CCs(GPR[reg], 0); /* set CCs, CC2 & CC3 */ + break; + case 0x5: /* RND */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + temp = GPR[reg]; /* save the current contents of specified reg */ + if (GPR[reg+1] & FSIGN) { /* if sign of R+1 is set, incr R by 1 */ + temp++; /* incr temp R value */ + if (temp < GPR[reg]) /* if temp R less than R, we have overflow */ + ovr = 1; /* show we have overflow */ + GPR[reg] = temp; /* update the R value */ + } + set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (modes & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + } + break; + case 0x6: /* BEI */ + if ((modes & PRIVBIT) == 0) { /* must be privileged to BEI */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ + goto newpsd; /* Privlege violation trap */ + } + CPUSTATUS |= 0x80; /* into status word bit 24 too */ + PSD2 &= ~0x0000c000; /* clear bit 48 & 49 */ + PSD2 |= 0x00004000; /* set bit 49 only */ + SPAD[0xf5] = PSD2; /* save the current PSD2 */ + break; + case 0x7: /* UEI */ + if ((modes & PRIVBIT) == 0) { /* must be privileged to UEI */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ + goto newpsd; /* Privlege violation trap */ + } + CPUSTATUS &= ~0x80; /* into status word bit 24 too */ + PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ + SPAD[0xf5] = PSD2; /* save the current PSD2 */ + irq_pend = 1; /* start scanning interrupts again */ + break; + case 0x8: /* EAE */ + PSD1 |= AEXPBIT; /* set the enable AEXP flag in PSD */ + CPUSTATUS |= AEXPBIT; /* into status word too */ + break; + case 0x9: /* RDSTS */ + GPR[reg] = CPUSTATUS; /* get CPU status word */ + break; + case 0xA: /* SIPU */ /* ignore for now */ + break; + case 0xB: /* INV */ /* RWCS ignore for now */ + case 0xC: /* INV */ /* WWCS ignore for now */ + break; + case 0xD: /* SEA */ + modes |= EXTDBIT; /* set new Extended flag in modes & PSD */ + PSD1 |= EXTDBIT; /* set the enable AEXP flag in PSD */ + CPUSTATUS |= EXTDBIT; /* into status word too */ + break; + case 0xE: /* DAE */ + modes &= AEXPBIT; /* set new extended flag in modes & PSD */ + PSD1 &= ~AEXPBIT; /* disable AEXP flag in PSD */ + CPUSTATUS &= ~AEXPBIT; /* into status word too */ + break; + + case 0xF: /* CEA */ + modes &= ~EXTDBIT; /* disable extended mode in modes and PSD */ + PSD1 &= ~EXTDBIT; /* disable extended mode flag in PSD */ + CPUSTATUS &= ~EXTDBIT; /* into status word too */ + break; + } + break; + case 0x04>>2: /* 0x04 SCC|RR|R1|SD|HLF - SD|HLF */ /* ANR, SMC, CMC, RPSWT */ + switch(opr & 0xF) { + case 0x0: /* ANR */ + dest &= source; /* just an and reg to reg */ + i_flags |= SCC; /* make sure we set CC's for dest value */ + break; + case 0xA: /* CMC */ /* Cache Memory Control - Diag use only */ + /* write reg to cache memory controller */ + break; + case 0x7: /* SMC */ /* Shared Memory Control Not Used */ + /* write reg to shared memory controller */ + break; + case 0xB: /* RPSWT */ /* Read Processor Status Word 2 (PSD2) */ + dest = PSD2; /* get PSD2 for user */ + break; + default: /* INV */ /* everything else is invalid instruction */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + goto newpsd; /* handle trap */ + break; + } + break; + + case 0x08>>2: /* 0x08 SCC|RR|R1|SD|HLF - */ /* ORR or ORRM */ + dest |= source; /* or the regs into dest reg */ + if (opr & 0x8) /* is this ORRM op? */ + dest &= GPR[4]; /* mask with reg 4 contents */ + break; + + case 0x0C>>2: /* 0x0c SCC|RR|R1|SD|HLF - SCC|SD|HLF */ /* EOR or EORM */ +//fprintf(stderr, "@EOR dest %.8x source %.8x\r\n", (uint32)dest, (uint32)source); + dest ^= source; /* exclusive or the regs into dest reg */ + if (opr & 0x8) /* is this EORM op? */ + dest &= GPR[4]; /* mask with reg 4 contents */ +//fprintf(stderr, "@EOR dest %.8x source %.8x\r\n", (uint32)dest, (uint32)source); + break; + + case 0x10>>2: /* 0x10 HLF - HLF */ /* CAR or (basemode SACZ ) */ + if (modes & BASEBIT) { /* handle basemode SACZ instruction */ +sacz: /* non basemode SCZ enters here */ + temp = GPR[reg]; /* get destination reg contents to shift */ + CC = 0; /* zero the CC's */ + t = 0; /* start with zero shift count */ + if (temp == 0) { + CC = CC4BIT; /* set CC4 showing dest is zero & cnt is zero too */ + } + else + if (temp & BIT0) { + CC = 0; /* clear CC4 & set count to zero */ + } + else + if (temp != 0) { /* shift non zero values */ + while ((temp & FSIGN) == 0) { /* shift the reg until bit 0 is set */ + temp <<= 1; /* shift left 1 bit */ + t++; /* increment shift count */ + } + temp <<= 1; /* shift the sign bit out */ + } + GPR[reg] = temp; /* save the shifted values */ + GPR[sreg] = t; /* set the shift cnt into the src reg */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + } else { + /* handle non basemode CAR instr */ + temp = GPR[reg] - GPR[sreg]; /* subtract src from destination value */ + set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ + } + break; + + case 0x14>>2: /* 0x14 HLF - HLF */ /* CMR compare masked with reg */ + //FIXME CMD needs both regs to be masked with R4 + temp = GPR[reg] ^ GPR[sreg]; /* exclusive or src and destination values */ + temp &= GPR[4]; /* and with mask reg (GPR 4) */ + CC = 0; /* set all CCs zero */ + if (temp == 0) /* if result is zero, set CC4 */ + CC = CC4BIT; /* set CC4 to show result 0 */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + break; + + case 0x18>>2: /* 0x18 SD|HLF - SD|HLF */ /* SBR, (basemode ZBR, ABR, TBR */ + if (modes & BASEBIT) { /* handle basemode ZBR, ABR, TBR */ + if ((opr & 0xC) == 0x0) /* SBR instruction */ + goto sbr; /* use nonbase SBR code */ + if ((opr & 0xC) == 0x4) /* ZBR instruction */ + goto zbr; /* use nonbase ZBR code */ + if ((opr & 0xC) == 0x8) /* ABR instruction */ + goto abr; /* use nonbase ABR code */ + if ((opr & 0xC) == 0xC) /* TBR instruction */ + goto tbr; /* use nonbase TBR code */ +inv: + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + goto newpsd; /* handle trap */ + + } else { /* handle non basemode SBR */ +sbr: /* handle basemode too */ + /* move the byte field bits 14-15 to bits 27-28 */ + /* or in the bit# from dest reg field bits 6-8 into bit 29-31 */ + bc = (((opr << 3) & 0x18) | reg); /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ + t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ +//fprintf(stderr, "SBR1 bc %.8x PSD1 %.8x GPR[%d] %.8x\r\n", bc, PSD1, sreg, GPR[sreg]); + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + if (GPR[sreg] & bc) /* test the bit in src reg */ + t |= CC1BIT; /* set CC1 to the bit value */ + GPR[sreg] |= bc; /* set the bit in src reg */ + PSD1 |= t; /* update the CC's in the PSD */ +//fprintf(stderr, "SBR2 bc %.8x PSD1 %.8x GPR[%d] %.8x\r\n", bc, PSD1, sreg, GPR[sreg]); + } + break; + + case 0x1C>>2: /* 0x1C SD|HLF - SD|HLF */ /* ZBR (basemode SRA, SRL, SLA, SLL) */ + if (modes & BASEBIT) { /* handle basemode SRA, SRL, SLA, SLL */ + if ((opr & 0x60) == 0x00) /* SRA instruction */ + goto sra; /* use nonbase SRA code */ + if ((opr & 0x60) == 0x20) /* SRL instruction */ + goto srl; /* use nonbase SRL code */ + if ((opr & 0x60) == 0x40) /* SLA instruction */ + goto sla; /* use nonbase SLA code */ + if ((opr & 0x60) == 0x60) /* SLL instruction */ + goto sll; /* use nonbase SLL code */ + } else { /* handle nonbase ZBR */ +zbr: /* handle basemode too */ + /* move the byte field bits 14-15 to bits 27-28 */ + /* or in the bit# from dest reg field bits 6-8 into bit 29-31 */ + bc = (((opr << 3) & 0x18) | reg); /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ + t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ +//fprintf(stderr, "ZBR1 bc %.8x PSD1 %.8x GPR[%d] %.8x\r\n", bc, PSD1, sreg, GPR[sreg]); + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + if (GPR[sreg] & bc) /* test the bit in src reg */ + t |= CC1BIT; /* set CC1 to the bit value */ + GPR[sreg] &= ~bc; /* reset the bit in src reg */ + PSD1 |= t; /* update the CC's in the PSD */ +//fprintf(stderr, "ZBR2 bc %.8x PSD1 %.8x GPR[%d] %.8x\r\n", bc, PSD1, sreg, GPR[sreg]); + } + break; + + case 0x20>>2: /* 0x20 HLF - HLF */ /* ABR (basemode SRAD, SRLD, SLAD, SLLD) */ + if (modes & BASEBIT) { /* handle basemode SRA, SRL, SLA, SLL */ + if ((opr & 0x60) == 0x00) /* SRAD instruction */ + goto sra; /* use nonbase SRAD code */ + if ((opr & 0x60) == 0x20) /* SRLD instruction */ + goto srl; /* use nonbase SRLD code */ + if ((opr & 0x60) == 0x40) /* SLAD instruction */ + goto sla; /* use nonbase SLAD code */ + if ((opr & 0x60) == 0x60) /* SLLD instruction */ + goto sll; /* use nonbase SLLD code */ + } else { /* handle nonbase mode ABR */ +abr: /* basemode ABR too */ + /* move the byte field bits 14-15 to bits 27-28 */ + /* or in the bit# from dest reg field bits 6-8 into bit 29-31 */ + bc = (((opr << 3) & 0x18) | reg); /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ + temp = GPR[sreg]; /* get reg value to add bit to */ +//fprintf(stderr, "ABR bc %.8x addr %.8x PSD1 %.8x temp %.8x\r\n", bc, addr, PSD1, temp); + ovr = ((temp & FSIGN) != 0); /* set ovr to status of sign bit 0 */ + temp += bc; /* add the bit value to the reg */ + ovr ^= ((temp & FSIGN) != 0); /* set ovr if sign bit changed */ +//fprintf(stderr, "ABR bc %.8x addr %.8x PSD1 %.8x temp %.8x ovr %d\r\n", bc, addr, PSD1, temp, ovr); + GPR[sreg] = temp; /* save the new value */ + set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (modes & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + } + } + break; + + case 0x24>>2: /* 0x24 HLF - SD|HLF */ /* TBR (basemode SRC) */ + if (modes & BASEBIT) { /* handle SRC basemode */ + if ((opr & 0x60) == 0x00) /* SRC instruction */ + goto src; /* use nonbase code */ + if ((opr & 0x60) == 0x40) /* SLC instruction */ + goto slc; /* use nonbase code */ + goto inv; /* else invalid */ + } else { /* handle TBR non basemode */ +tbr: /* handle basemode TBR too */ + /* move the byte field bits 14-15 to bits 27-28 */ + /* or in the bit# from dest reg field bits 6-8 into bit 29-31 */ + bc = (((opr << 3) & 0x18) | reg); /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ + t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ +//fprintf(stderr, "TBR1 bc %.8x PSD1 %.8x GPR[%d] %.8x\r\n", bc, PSD1, sreg, GPR[sreg]); + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + if (GPR[sreg] & bc) /* test the bit in src reg */ + t |= CC1BIT; /* set CC1 to the bit value */ + PSD1 |= t; /* update the CC's in the PSD */ +//fprintf(stderr, "TBR2 bc %.8x PSD1 %.8x GPR[%d] %.8x\r\n", bc, PSD1, sreg, GPR[sreg]); + } + break; + + case 0x28>>2: /* 0x28 HLF - HLF */ /* Misc OP REG instructions */ + temp = GPR[reg]; /* get reg value */ + switch(opr & 0xF) { + + case 0x0: /* TRSW */ + if (modes & BASEBIT) + addr = temp & MASK24; /* 24 bits for based mode */ + else + addr = temp & 0x7FFFE; /* 19 bits for non based mode */ + /* we are returning to the addr in reg, set CC's from reg */ + /* update the PSD with new address */ + PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ + PSD1 = ((PSD1 & 0x87ffffff) | (temp & 0x78000000)); /* insert CCs from reg */ + i_flags |= BT; /* we branched, so no PC update */ + break; + + case 0x2: /* XCBR */ /* Exchange base registers */ + if ((modes & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + temp = BR[reg]; /* get dest reg value */ + BR[reg] = BR[sreg]; /* put source reg value int dest reg */ + BR[sreg] = temp; /* put dest reg value into src reg */ + break; + + case 0x4: /* TCCR */ /* Transfer condition codes to GPR */ + if ((modes & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + temp = CC >> 27; /* right justify CC's in reg */ + break; + + case 0x5: /* TRCC */ /* Transfer GPR to condition codes */ + if ((modes & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + PSD1 = ((PSD1 & 0x87fffffe) | (GPR[reg] << 27)); /* insert CCs from reg */ + break; + + case 0x8: /* BSUB */ /* Procedure call */ + if ((modes & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + /* if Rd field is 0 (reg is b6-8), this is a BSUB instruction */ + /* otherwise it is a CALL instruction (Rd != 0) */ + if (reg == 0) { + /* BSUB instruction */ + uint32 fp = BR[2]; /* get dword bounded frame pointer from BR2 */ + if ((BR[2] & 0x7) != 0) { + /* Fault, must be dw bounded address */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + M[fp>>2] = (PSD1 + 2) & 0x01fffffe; /* save AEXP bit and PC into frame */ + M[(fp>>2)+1] = 0x80000000; /* show frame created by BSUB instr */ + BR[3] = GPR[0]; /* GPR 0 to BR 3 (AP) */ + BR[0] = BR[2]; /* set frame pointer from BR 2 into BR 0 */ + BR[1] = BR[sreg]; /* Rs reg to BR 1 */ + PSD1 = (PSD1 & 0xff000000) | (BR[sreg] & 0xffffff); /* New PSD address */ + } else { + /* CALL instruction */ + /* get frame pointer from BR2 - 16 words & make it a dword addr */ + uint32 cfp = ((BR[2]-0x40) & 0xfffffff8); + M[cfp>>2] = (PSD1 + 2) & 0x01fffffe; /* save AEXP bit and PC from PSD1 in to frame */ + M[(cfp>>2)+1] = 0x00000000; /* show frame created by CALL instr */ + for (ix=0; ix<8; ix++) + M[(cfp>>2)+ix+2] = BR[ix]; /* save BRs 0-7 to call frame */ + for (ix=2; ix<8; ix++) + M[(cfp>>2)+ix+10] = GPR[ix]; /* save GPRs 2-7 to call frame */ + BR[3] = GPR[reg]; /* Rd to BR 3 (AP) */ + BR[0] = cfp; /* set current frame pointer into BR[0] */ + BR[2] = cfp; /* set current frame pointer into BR[2] */ + BR[1] = BR[sreg]; /* Rs reg to BR 1 */ + PSD1 = (PSD1 & 0xff000000) | (BR[sreg] & 0xffffff); /* New PSD address */ + } + break; + + case 0xC: /* TPCBR */ /* Transfer program Counter to Base Register */ + if ((modes & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + BR[reg] = PSD1 & 0xfffffe; /* save PC from PSD1 into BR */ + break; + + case 0x1: /* INV */ + case 0x3: /* INV */ + case 0x6: /* INV */ + case 0x7: /* INV */ + case 0x9: /* INV */ + case 0xA: /* INV */ + case 0xB: /* INV */ + case 0xD: /* INV */ + case 0xE: /* INV */ + case 0xF: /* INV */ + break; + } + break; + + case 0x2C>>2: /* 0x2C HLF - HLF */ /* Reg-Reg instructions */ + temp = GPR[reg]; /* reg contents specified by Rd */ + addr = GPR[sreg]; /* reg contents specified by Rs */ + bc = 0; +//fprintf(stderr, "@0x2c temp %.8x addr %.8x\r\n", temp, addr); + + switch(opr & 0xF) { + case 0x0: /* TRR */ /* SCC|SD|R1 */ + temp = addr; /* set value to go to GPR[reg] */ + bc = 1; /* set CC's at end */ + break; + + case 0x1: /* TRBR */ /* Transfer GPR to BR */ + if ((modes & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + BR[reg] = GPR[sreg]; /* copy GPR to BR */ + break; + + case 0x2: /* TBRR */ /* transfer BR to GPR */ + if ((modes & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + temp = BR[sreg]; /* set base reg value */ + bc = 1; /* set CC's at end */ + break; + + case 0x3: /* TRC */ /* Transfer register complement */ + temp = addr ^ FMASK; /* complement Rs */ + bc = 1; /* set CC's at end */ + break; + + case 0x4: /* TRN */ /* Transfer register negative */ + temp = -addr; /* negate Rs value */ + if (temp == addr) /* overflow if nothing changed */ + ovr = 1; /* set overflow flag */ + bc = 1; /* set the CC's */ + break; + + case 0x5: /* XCR */ /* exchange registers Rd & Rs */ + GPR[sreg] = temp; /* Rd to Rs */ + set_CCs(temp, ovr); /* set the CC's from original Rd */ + temp = addr; /* save the Rs value to Rd reg */ + break; + + case 0x6: /* INV */ + goto inv; + break; + + case 0x7: /* LMAP */ /* Load map reg - Diags only */ + goto inv; + break; + + case 0x8: /* TRRM */ /* SCC|SD|R1 */ + temp = addr & GPR[4]; /* transfer reg-reg masked */ + bc = 1; /* set CC's at end */ + break; + + /* CPUSTATUS bits */ + /* Bits 0-19 reserved */ + /* Bit 20 =0 Write to writable control store is disabled */ + /* =1 Write to writable control store is enabled */ + /* Bit 21 =0 Enable PROM mode */ + /* =1 Enable Alterable Control Store Mode */ + /* Bit 22 =0 Enable High Speed Floating Point Accelerator */ + /* =1 Disable High Speed Floating Point Accelerator */ + /* Bit 23 =0 Disable privileged mode halt trap */ + /* =1 Enable privileged mode halt trap */ + /* Bit 24 is reserved */ + /* bit 25 =0 Disable software trap handling (enable automatic trap handling) */ + /* =1 Enable software trap handling */ + /* Bits 26-31 reserved */ + case 0x9: /* SETCPU */ + CPUSTATUS &= 0xfffff0bf; /* zero bits that can change */ + CPUSTATUS |= (temp & 0x0f40); /* or in the new status bits */ + break; + + case 0xA: /* TMAPR */ /* Transfer map to Reg - Diags only */ + goto inv; /* not used */ + break; + + case 0xB: /* TRCM */ /* Transfer register complemented masked */ + temp = (addr ^ FMASK) & GPR[4]; /* compliment & mask */ + bc = 1; /* set the CC's */ + break; + + case 0xC: /* TRNM */ /* Transfer register negative masked */ + temp = -addr; /* complement GPR[reg] */ + if (temp == addr) /* check for overflow */ + ovr = 1; /* overflow */ + temp &= GPR[4]; /* and with negative reg */ + bc = 1; /* set the CC's */ + break; + + case 0xD: /* XCRM */ /* Exchange registers masked */ + addr &= GPR[4]; /* and Rs with mask reg */ + temp &= GPR[4]; /* and Rd with mask reg */ + GPR[sreg] = temp; /* Rs to get Rd masked value */ + set_CCs(temp, ovr); /* set the CC's from original Rd */ + temp = addr; /* save the Rs value to Rd reg */ + break; + + case 0xE: /* TRSC */ /* transfer reg to SPAD */ + t = (GPR[reg] >> 16) & 0xff; /* get SPAD address from Rd (6-8) */ + temp2 = SPAD[t]; /* get old SPAD data */ + SPAD[t] = GPR[sreg]; /* store Rs into SPAD */ +//fprintf(stderr, "TRSC SPAD[%x] old %.8x new %.8x INTS[%x] %.8x\r\n", t, temp2, SPAD[t], t, INTS[t]); + break; + + case 0xF: /* TSCR */ /* Transfer scratchpad to register */ + t = (GPR[sreg] >> 16) & 0xff; /* get SPAD address from Rs (9-11) */ + temp = SPAD[t]; /* get SPAD data into Rd (6-8) */ +//fprintf(stderr, "TSCR SPAD[%x] %.8x\r\n", t, temp); + break; + } + GPR[reg] = temp; /* save the temp value to Rd reg */ + if (bc) /* set cc's if bc set */ + set_CCs(temp, ovr); /* set the CC's */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (modes & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + } + break; + +/*TODO*/ case 0x30>>2: /* 0x30 */ /* CALM */ + fprintf(stderr, "ERROR - CALM called\r\n"); + goto inv; /* TODO */ + break; + + case 0x34>>2: /* 0x34 SD|ADR - inv */ /* LA non-basemode */ + if (modes & BASEBIT) /* see if based */ + goto inv; /* invalid instruction in based mode */ + if (modes & EXTDBIT) { /* see if extended mode */ + dest = (t_uint64)addr; /* just pure 24 bit address */ + } else { /* use bits 13-31 */ + dest = (t_uint64)(addr | ((FC & 4) << 17)); /* F bit to bit 12 */ + } + break; + + case 0x38>>2: /* 0x38 SCC|SD|HLF - SD|HLF */ /* REG - REG floating point instructions */ + temp = GPR[reg]; /* reg contents specified by Rd */ + addr = GPR[sreg]; /* reg contents specified by Rs */ + switch(opr & 0xF) { + case 0x0: /* ADR */ + t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ + t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ + temp = temp + addr; /* add the values */ + if ((t == 3 && (temp & FSIGN) == 0) || + (t == 0 && (addr & FSIGN) != 0)) + ovr = 1; /* we have an overflow */ + break; + + case 0x1: /* ADRFW */ + goto inv; /* TODO */ + break; + case 0x2: /* MPRBR */ + goto inv; /* TODO */ + break; + case 0x3: /* SURFW */ + goto inv; /* TODO */ + break; + case 0x4: /* DVRFW */ + goto inv; /* TODO */ + break; + case 0x5: /* FIXW */ + goto inv; /* TODO */ + break; + case 0x6: /* MPRFW */ + goto inv; /* TODO */ + break; + case 0x7: /* FLTW */ + goto inv; /* TODO */ + break; + case 0x8: /* ADRM */ + t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ + t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ + temp = temp + addr; /* add the values */ + if ((t == 3 && (temp & FSIGN) == 0) || + (t == 0 && (temp & FSIGN) != 0)) + ovr = 1; /* we have an overflow */ + temp &= GPR[4]; /* mask the destination reg */ + break; + case 0x9: /* INV */ + goto inv; /* TODO */ + break; + case 0xA: /* DVRBR */ + goto inv; /* TODO */ + break; + case 0xB: /* SURFD */ + goto inv; /* TODO */ + break; + case 0xC: /* DVRFD */ + goto inv; /* TODO */ + break; + case 0xD: /* FIXD */ + goto inv; /* TODO */ + break; + case 0xE: /* MPRFD */ + goto inv; /* TODO */ + break; + case 0xF: /* FLTD */ + goto inv; /* TODO */ + break; + } + GPR[reg] = temp; /* temp has destination reg value */ + if ((opr & 0xF) < 6) { + set_CCs(temp, ovr); /* set the CC's */ + } + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (modes & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + } + break; + + case 0x3C>>2: /* 0x3C HLF - HLF */ /* SUR and SURM */ + temp = GPR[reg]; /* get negative value to add */ + addr = -GPR[sreg]; /* reg contents specified by Rs */ + switch(opr & 0xF) { + case 0x0: /* SUR */ + t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ + t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ + temp = temp + addr; /* add the values */ + if ((t == 3 && (temp & FSIGN) == 0) || + (t == 0 && (addr & FSIGN) != 0)) + ovr = 1; /* we have an overflow */ + break; + case 0x8: /* SURM */ + t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ + t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ + temp = temp + addr; /* add the values */ + if ((t == 3 && (temp & FSIGN) == 0) || + (t == 0 && (temp & FSIGN) != 0)) + ovr = 1; /* we have an overflow */ + temp &= GPR[4]; /* mask the destination reg */ + break; + case 0x9: /* INV */ + goto inv; /* TODO */ + break; + case 0xA: /* DVRBR */ + goto inv; /* TODO */ + break; + case 0xB: /* SURFD */ + goto inv; /* TODO */ + break; + case 0xC: /* DVRFD */ + goto inv; /* TODO */ + break; + case 0xD: /* FIXD */ + goto inv; /* TODO */ + break; + case 0xE: /* MPRFD */ + goto inv; /* TODO */ + break; + case 0xF: /* FLTD */ + goto inv; /* TODO */ + break; + } + GPR[reg] = temp; /* save the result */ + if ((opr & 0xF) < 6) { + set_CCs(temp, ovr); /* set CCs for result */ + } + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (modes & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + } + break; + + case 0x40>>2: /* 0x40 */ /* MPR */ + if (reg & 1) { + /* Spec fault */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + temp = GPR[reg+1]; /* get multiplicand */ + addr = GPR[sreg]; /* multiplier */ + + /* change immediate value into a 64 bit value */ + dest = ((t_uint64)(addr & FMASK)) | ((addr & FSIGN) ? D32LMASK : 0); +//fprintf(stderr, "MPR reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx\r\n", reg, GPR[reg], GPR[reg+1], dest); + source = ((t_uint64)(temp & FMASK)) | ((temp & FSIGN) ? D32LMASK : 0); +//fprintf(stderr, "MPR reg %d GPR[reg] %.8x GPR[reg+1] %.8x source %llx\r\n", reg, GPR[reg], GPR[reg+1], source); + dest = dest * source; /* do the multiply */ +//fprintf(stderr, "MPR dest result %llx\r\n", dest); + i_flags |= SD|SCC; /* save regs and set CC's */ + dbl = 1; /* double reg save */ + break; + + case 0x44>>2: /* 0x44 ADR - ADR */ /* DVR */ + /* sreg has Rs */ + if (reg & 1) { + /* Spec fault */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + /* get Rs divisor value */ + source = (t_uint64)(GPR[sreg]) | ((GPR[sreg] & FSIGN) ? D32LMASK : 0); +//fprintf(stderr, "DVR reg %d GPR[reg] %.8x GPR[reg+1] %.8x source %llx\r\n", reg, GPR[reg], GPR[reg+1], source); + /* merge the dividend regs into the 64bit value */ + dest = (((t_uint64)GPR[reg]) << 32) | ((t_uint64)GPR[reg+1]); +//fprintf(stderr, "DVR reg %d GPR[reg] %.8x GPR[reg+1] %.8x source %llx\r\n", reg, GPR[reg], GPR[reg+1], dest); + if (source == 0) { + goto doovr3; + break; + } + td = (t_int64)dest % (t_int64)source; /* remainder */ + dbl = (td < 0); /* double reg is neg remainder */ +//fprintf(stderr, "DVR remainder %llx dbl %x \r\n", td, dbl); + if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */ + td = -td; /* dividend and remainder must be same sign */ +//fprintf(stderr, "DVR fix sign %llx dbl %x source %llx dest %llx\r\n", td, dbl, source, dest); + dest = (t_int64)dest / (t_int64)source; /* now do the divide */ +//fprintf(stderr, "DVR dest %llx\r\n", dest); + if ((dest & D32LMASK) != 0 && (dest & D32LMASK) != D32LMASK) { /* test for overflow */ +doovr3: + ovr = 1; /* the quotient exceeds 31 bit, overflow */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (modes & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + } + /* the original regs must be returned unchanged if aexp */ + set_CCs(temp, ovr); /* set the CC's */ +//fprintf(stderr, "DVR ovr %d reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx\r\n", ovr, reg, GPR[reg], GPR[reg+1], dest); + } else { + GPR[reg] = (uint32)(td & FMASK); /* reg gets remainder, reg+1 quotient */ + GPR[reg+1] = (uint32)(dest & FMASK); /* store quotient in reg+1 */ + set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ +//fprintf(stderr, "DVR good reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx rem %llx\r\n", reg, GPR[reg], GPR[reg+1], dest, td); + } + break; +//#endif /* SIMPLE_MODE*/ + + case 0x48>>2: /* 0x48 INV - INV */ /* unused opcodes */ + case 0x4C>>2: /* 0x4C INV - INV */ /* unused opcodes */ + default: +fprintf(stderr, "place @ UI op = %.8x\r\n", IR); + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + goto newpsd; /* handle trap */ + break; + + case 0x50>>2: /* 0x50 INV - SD|ADR */ /* LA basemode */ + if ((modes & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + if (modes & (BASEBIT|EXTDBIT)) { + dest = (t_uint64)addr; /* just pure 24 bit address */ + } else { + dest = (t_uint64)(addr | ((FC & 4) << 17)); /* F bit to bit 12 */ + } + break; + + case 0x54>>2: /* 0x54 SM|ADR - INV */ /* (basemode STWBR) */ + if ((modes & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + if (FC != 0) { /* word address only */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + dest = BR[reg]; /* save the BR to memory */ + break; + + case 0x58>>2: /* 0x58 SB|ADR - INV */ /* (basemode SUABR and LABR) */ + if ((modes & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + if ((FC & 4) != 0) { /* see if SUABR F=0 */ + dest = BR[reg] - addr; /* subtract addr from the BR and store back to BR */ + } else { /* LABR if F=1 */ + dest = addr; /* addr goes to specified BR */ + } + break; + case 0x5C>>2: /* 0x5C RM|SB|ADR - INV */ /* (basemode LWBR and BSUBM) */ + if ((modes & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + if (FC != 0) { /* word address only */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if ((FC & 0x4) != 0x4) { /* this is a LWBR instruction */ + BR[reg] = source; /* load memory location in BR */ + } else { /* this is a CALLM/BSUBM instruction */ + /* if Rd field is 0 (reg is b6-8), this is a BSUBM instruction */ + /* otherwise it is a CALLM instruction (Rd != 0) */ + if (reg == 0) { + /* BSUBM instruction */ + uint32 fp = BR[2]; /* get dword bounded frame pointer from BR2 */ + if ((BR[2] & 0x7) != 0) { + /* Fault, must be dw bounded address */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + M[fp>>2] = (PSD1+4) & 0x01fffffe; /* save AEXP bit and PC into frame */ + M[(fp>>2)+1] = 0x80000000; /* show frame created by BSUB instr */ + BR[3] = GPR[0]; /* GPR 0 to BR 3 (AP) */ + BR[0] = BR[2]; /* set frame pointer from BR 2 into BR 0 */ + BR[1] = (addr+0x80) & 0xfffffe; /* effective address to BR 1 */ + PSD1 = (PSD1 & 0xff000000) | BR[1]; /* New PSD address */ + } else { + /* CALM instruction */ + /* get frame pointer from BR2 - 16 words & make it a dword addr */ + uint32 cfp = ((BR[2]-0x40) & 0xfffffff8); + M[cfp>>2] = (PSD1+4) & 0x01fffffe; /* save AEXP bit and PC from PSD1 in to frame */ + M[(cfp>>2)+1] = 0x00000000; /* show frame created by CALL instr */ + for (ix=0; ix<8; ix++) + M[(cfp>>2)+ix+2] = BR[ix]; /* save BRs 0-7 to call frame */ + for (ix=2; ix<8; ix++) + M[(cfp>>2)+ix+10] = GPR[ix];/* save GPRs 2-7 to call frame */ + BR[3] = GPR[reg]; /* Rd to BR 3 (AP) */ + BR[0] = (uint32)cfp; /* set current frame pointer into BR[0] */ + BR[2] = (uint32)cfp; /* set current frame pointer into BR[2] */ + BR[1] = (addr + 0x80) & 0xfffffe; /* effective address to BR 1 */ + PSD1 = (PSD1 & 0xff000000) | BR[1]; /* New PSD address */ + } + } + break; + + case 0x60>>2: /* 0x60 SH|HLF - INV */ /* NOR Rd,Rs */ + if ((modes & BASEBIT)) { /* only for nonbased mode */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + goto newpsd; /* handle trap */ + } + temp = GPR[reg]; /* Rd */ + t = 0; /* no shifts yet */ + /* exponent must not be zero or all 1's */ + if (temp != 0 && temp != FMASK) { + /* non zero value or not all 1's, so normalize */ + uint32 m = temp & 0xF8000000; + /* shift left 4 bits at a time while left most 5 bits are not zero or all 1's */ + while ((m == 0) || (m == 0xF8000000)) { + temp <<= 4; /* move left 4 bits */ + t++; /* increment number times shifted */ + m = temp & 0xF8000000; /* get left most 5 bits again */ + } + /* temp value is now normalized with non zero nor all 1's value */ + GPR[reg] = temp; /* save the normalized value */ + GPR[(IR >> 20) & 7] = 0x40 - t; /* subtract shift count from 0x40 into Rs */ + } else { + GPR[(IR >> 20) & 7] = 0; /* set exponent to zero for zero value */ + } + break; + + case 0x64>>2: /* 0x64 SD|HLF - INV */ /* NORD */ + if ((modes & BASEBIT)) { /* only for nonbased mode */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + goto newpsd; /* handle trap */ + } + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + addr = GPR[reg]; /* high order 32 bits */ + temp = GPR[reg+1]; /* low order 32 bits */ + t = 0; /* zero shift count */ + if ((temp|addr) != 0 && (temp&addr) != FMASK) { + uint32 m = temp & 0xF8000000; /* upper 5 bit mask */ + /* shift until upper 5 bits are neither 0 or all 1's */ + while ((m == 0) || (m == 0xF8000000)) { + temp <<= 4; /* shift over 4 bits at a time */ + m = temp & 0xF8000000; /* upper 5 bits */ + temp |= (addr >> 28) & 0xf; /* copy in upper 4 bits from R+1 */ + addr <<= 4; /* shift 4 bits of zero int R+1 */ + t++; /* bump shift count */ + } + GPR[reg] = addr; /* save the new values */ + GPR[reg|1] = temp; + } + if (t != 0) + t = 0x40 - t; /* set the shift cnt */ + GPR[(IR >> 20) & 7] = t; /* put 0x40 - shift count or 0 into RS */ + break; + + case 0x68>>2: /* 0x68 SCC|SD|HLF - INV */ /* non basemode SCZ */ + if (modes & BASEBIT) + goto inv; /* invalid instruction */ + goto sacz; /* use basemode sacz instruction */ + + case 0x6C>>2: /* 0x6C SD|HLF - INV */ /* non basemode SRA & SLA */ + if (modes & BASEBIT) + goto inv; /* invalid instruction */ +sra: +sla: + bc = opr & 0x1f; /* get bit shift count */ + temp = GPR[reg]; /* get reg value to shift */ + t = temp & FSIGN; /* sign value */ + if (opr & 0x0040) { /* is this SLA */ + ovr = 0; /* set ovr off */ + for (ix=0; ix>= 1; /* shift bit 0 right one bit */ + temp |= t; /* restore original sign bit */ + } + GPR[reg] = temp; /* save the new value */ + } + break; + + case 0x70>>2: /* 0x70 SD|HLF - INV */ /* non-basemode SRL & SLL */ + if (modes & BASEBIT) + goto inv; /* invalid instruction in basemode */ +sll: +srl: + bc = opr & 0x1f; /* get bit shift count */ + temp = GPR[reg]; /* get reg value to shift */ +//fprintf(stderr, "before SLL/SRL dest %.8x cnt %d\r\n", temp, bc); + if (opr & 0x0040) /* is this SLL, bit 9 set */ + temp <<= bc; /* shift left #bits */ + else + temp >>= bc; /* shift right #bits */ + dest = temp; /* value to be output */ +//fprintf(stderr, "SLL/SRL dest %.8x cnt %d\r\n", (uint32)dest, bc); + break; + + case 0x74>>2: /* 0x74 SD|HLF - INV */ /* non-basemode SRC & SLC */ + if (modes & BASEBIT) + goto inv; /* invalid instruction in basemode */ +slc: +src: + bc = opr & 0x1f; /* get bit shift count */ + temp = GPR[reg]; /* get reg value to shift */ + if (opr & 0x0040) { /* is this SLC, bit 9 set */ + for (ix=0; ix>= 1; /* shift the bit out */ + if (t) + temp |= BIT0; /* put in new sign bit */ + } + } + dest = temp; /* shift result */ + break; + +/*TODO*/ + case 0x78>>2: /* 0x78 HLF - INV */ /* non-basemode SRAD & SLAD */ + if (modes & BASEBIT) /* Base mode? */ + goto inv; /* invalid instruction in basemode */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + bc = opr & 0x1f; /* get bit shift count */ + dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ + dest |= (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ + source = dest & DMSIGN; /* 64 bit sign value */ + if (opr & 0x0040) { /* is this SLAD */ + ovr = 0; /* set ovr off */ + for (ix=0; ix>32) & FMASK);/* save the hi order reg */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + if (ovr) + PSD1 |= BIT1; /* CC1 in PSD */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (modes & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + } + } else { /* this is a SRAD */ + for (ix=0; ix>= 1; /* shift bit 0 right one bit */ + dest |= source; /* restore original sign bit */ + } + GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ + GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ + } + break; + + case 0x7C>>2: /* 0x7C SDD|HLF - INV */ /* non-basemode SRLD & SLLD */ + if (modes & BASEBIT) + goto inv; /* invalid instruction in basemode */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ + dest |= (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ + bc = opr & 0x1f; /* get bit shift count */ + if (opr & 0x0040) /* is this SLL, bit 9 set */ + dest <<= bc; /* shift left #bits */ + else + dest >>= bc; /* shift right #bits */ + GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ + GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ + break; + + case 0x80>>2: /* 0x80 SD|ADR - SD|ADR */ /* LEAR */ + /* convert address to real physical address */ + TRAPME = RealAddr(addr, &temp, &t); + if (TRAPME != ALLOK) + goto newpsd; /* memory read error or map fault */ + /* OS code says F bit is not transferred, so just ignore it */ +// if (FC & 4) /* see if F bit was set */ +// temp |= 0x01000000; /* set bit 7 of address */ + dest = temp; /* put in dest to go out */ +// fprintf(stderr, "LEAR Inst %.8x addr %.8x raddr %.8x PSD %.8x %.8x SPAD PSD@ %x\r\n", +// IR, addr, temp, PSD1, PSD2, SPAD[0xf5]); +// sim_debug(DEBUG_CMD, &cpu_dev, "LEAR Inst %.8x addr %.8x raddr %.8x PSD %.8x %.8x\n", +// IR, addr, temp, PSD1, PSD2); + break; + + case 0x84>>2: /* 0x84 SCC|SD|RR|RM|ADR - SD|RM|ADR */ /* ANMx */ + dest &= source; + break; + + case 0x88>>2: /* 0x88 SCC|SD|RR|RM|ADR - SD|RM|ADR */ /* ORMx */ + dest |= source; + break; + + case 0x8C>>2: /* 0x8C SCC|SD|RR|RM|ADR - SD|RM|ADR */ /* EOMx */ + dest ^= source; + break; + + case 0x90>>2: /* 0x90 SCC|RR|RM|ADR - RM|ADR */ /* CAMx */ +//fprintf(stderr, "CAMW src %llx dest %llx\r\n", source, dest); + dest -= source; + break; + + case 0x94>>2: /* 0x94 RR|RM|ADR - RM|ADR */ /* CMMx */ + //FIXME CMMD need both regs to be masked with R4 + if (dbl) { + /* we need to and both regs */ + t_uint64 nm = (((t_uint64)GPR[4]) << 32) | (((t_uint64)GPR[4]) & D32RMASK); + td = dest; /* save dest */ + dest ^= source; + dest &= nm; /* mask both regs with reg 4 contents */ +// fprintf(stderr, "CMMD PSD %x src %llx dst %llx GPR[4] %llx result %llx CC4 %x\r\n", +// PSD1, source, td, nm, dest, dest==0ll?1:0); + } else { + td = dest; /* save dest */ + dest ^= source; /* <= 32 bits, so just do lower 32 bits */ + dest &= (((t_uint64)GPR[4]) & D32RMASK); /* mask with reg 4 contents */ +// fprintf(stderr, "CMMW PSD %x src %llx dst %llx GPR[4] %llx result %llx CC4 %x\r\n", +// PSD1, source, td, ((t_uint64)GPR[4]), dest, dest==0ll?1:0); + } + CC = 0; + if (dest == 0ll) + CC |= CC4BIT; + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + PSD1 |= CC; /* update the CC's in the PSD */ + break; + + case 0x98>>2: /* 0x98 ADR - ADR */ /* SBM */ + if ((FC & 04) == 0) { + /* Fault, f-bit must be set for SBM instruction */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + + t = (CC & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ + /* use C bits and bits 6-8 (reg) to generate shift bit count */ + bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ +//fprintf(stderr, "SBM bc %.8x addr %.8x CC %0.2x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, PSD1, temp); + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + if (temp & bc) /* test the bit in memory */ + t |= CC1BIT; /* set CC1 to the bit value */ + PSD1 |= t; /* update the CC's in the PSD */ + temp |= bc; /* set the bit in temp */ +//fprintf(stderr, "SBM bc %.8x addr %.8x CC %0.2x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, PSD1, temp); + if ((TRAPME = Mem_write(addr, &temp))) /* put word back into memory */ + goto newpsd; /* memory write error or map fault */ + break; + + case 0x9C>>2: /* 0x9C ADR - ADR */ /* ZBM */ + if ((FC & 04) == 0) { + /* Fault, byte address not allowed */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + + t = (CC & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ + /* use C bits and bits 6-8 (reg) to generate shift bit count */ + bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ +//fprintf(stderr, "ZBM bc %.8x addr %.8x CC %0.2x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, PSD1, temp); + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + if (temp & bc) /* test the bit in memory */ + t |= CC1BIT; /* set CC1 to the bit value */ + PSD1 |= t; /* update the CC's in the PSD */ + temp &= ~bc; /* reset the bit in temp */ +//fprintf(stderr, "ZBM bc %.8x addr %.8x CC %0.2x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, PSD1, temp); + if ((TRAPME = Mem_write(addr, &temp))) /* put word into memory */ + goto newpsd; /* memory write error or map fault */ + break; + + case 0xA0>>2: /* 0xA0 ADR - ADR */ /* ABM */ + if ((FC & 04) == 0) { + /* Fault, byte address not allowed */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + + /* use C bits and bits 6-8 (reg) to generate shift bit count */ + bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ +//fprintf(stderr, "ABM B4 bc %.8x addr %.8x CC %0.2x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, PSD1, temp); + ovr = (temp & FSIGN) != 0; /* set ovr to status of sign bit 0 */ + temp += bc; /* add the bit value to the reg */ + ovr ^= (temp & FSIGN) != 0; /* set ovr if sign bit changed */ + set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ +//fprintf(stderr, "ABM AF bc %.8x addr %.8x CC %0.2x ovr %x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, ovr, PSD1, temp); + if ((TRAPME = Mem_write(addr, &temp))) /* put word into memory */ + goto newpsd; /* memory write error or map fault */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (modes & AEXPBIT)) + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + break; + + case 0xA4>>2: /* 0xA4 ADR - ADR */ /* TBM */ + if ((FC & 04) == 0) { + /* Fault, byte address not allowed */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + + t = (CC & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ + /* use C bits and bits 6-8 (reg) to generate shift bit count */ + bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ +//fprintf(stderr, "TBM bc %.8x addr %.8x CC %0.2x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, PSD1, temp); + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + if (temp & bc) /* test the bit in memory */ + t |= CC1BIT; /* set CC1 to the bit value */ + PSD1 |= t; /* update the CC's in the PSD */ +//fprintf(stderr, "TBM bc %.8x addr %.8x CC %0.2x PSD1 %.8x temp %.8x\r\n", bc, addr, CC, PSD1, temp); + break; + + case 0xA8>>2: /* 0xA8 RM|ADR - RM|ADR */ /* EXM */ + if ((FC & 04) != 0 || FC == 2) { /* can not be byte or doubleword */ + /* Fault */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + + IR = temp; /* get instruction from memory */ + if (FC == 2) /* see if right halfword specified */ + IR <<= 16; /* move over the HW instruction */ + if ((IR & 0xFC7F0000) == 0xC8070000 || + (IR & 0xFF800000) == 0xA8000000 || + (IR & 0xFC000000) == 0x80000000) { + /* Fault, attempt to execute another EXR, EXRR, EXM, or LEAR */ + goto inv; /* invalid instruction */ + } + EXM_EXR = 4; /* set PC increment for EXM */ + goto exec; /* go execute the instruction */ + + case 0xAC>>2: /* 0xAC SCC|SD|RM|ADR - SD|RM|ADR */ /* Lx */ + dest = source; /* set value to load into reg */ + break; + + case 0xB0>>2: /* 0xB0 SCC|SD|RM|ADR - SD|RM|ADR */ /* LMx */ + //FIXME LMD need both regs to be masked with R4 + if (dbl) { + /* we need to and both regs */ + t_uint64 nm = (((t_uint64)GPR[4]) << 32) | (((t_uint64)GPR[4]) & D32RMASK); + dest = source & nm; /* mask both regs with reg 4 contents */ +// fprintf(stderr, "LMD PSD %x src %llx GPR[4] %llx result %llx\r\n", PSD1, source, nm, dest); + } else { + dest = source; /* <= 32 bits, so just do lower 32 bits */ + dest &= (((t_uint64)GPR[4]) & D32RMASK); /* mask with reg 4 contents */ +// fprintf(stderr, "LMW PSD %x src %llx GPR[4] %llx result %llx\r\n", PSD1, source, ((t_uint64)GPR[4]), dest); + } + break; + + case 0xB4>>2: /* 0xB4 SCC|SD|RM|ADR - SD|RM|ADR */ /* LNx */ + dest = -source; /* set the value to load into reg */ + if (dest == source) + ovr = 1; /* set arithmetic exception status */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (modes & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + } + break; + + case 0xBC>>2: /* 0xBC SCC|SD|RR|RM|ADR - SD|RM|ADR */ /* SUMx */ + source = -source; + /* Fall through */ + + case 0xE8>>2: /* 0xE8 SCC|SM|RR|RM|ADR - SM|RM|ADR */ /* ARMx */ + case 0xB8>>2: /* 0xB8 SCC|SD|RR|RM|ADR - SD|RM|ADR */ /* ADMx */ + t = (source & DMSIGN) != 0; + t |= ((dest & DMSIGN) != 0) ? 2 : 0; +//fprintf(stderr, "ARMW t %x src %llx dest %llx", t, source, dest); + dest = dest + source; + if ((t == 3) && ((dest & DMSIGN) == 0)) { + ovr = 1; +//fprintf(stderr, " @ovr0 %d", ovr); + } + if ((t == 0) && ((dest & DMSIGN) != 0)) { + ovr = 1; +//fprintf(stderr, " @ovr1 %d", ovr); + } + if ((dbl == 0) && ((dest & D32LMASK) != 0) && ((dest & D32LMASK) != D32LMASK)) { + ovr = 1; +//fprintf(stderr, " @ovr2 %d", ovr); + } + +//fprintf(stderr, " result %llx\r\n", dest); + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (modes & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + } + break; + + case 0xC0>>2: /* 0xC0 SCC|SD|RM|ADR - SD|RM|ADR */ /* MPMx */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ +//fprintf(stderr, "MPM? before src %llx dest %llx\r\n", source, dest); + dest = (t_uint64)((t_int64)dest * (t_int64)source); +//fprintf(stderr, "MPM? after src %llx dest %llx\r\n", source, dest); + dbl = 1; + break; + + case 0xC4>>2: /* 0xC4 RM|ADR - RM|ADR */ /* DVMx */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } +//fprintf(stderr, "DVM reg %d GPR[reg] %.8x GPR[reg+1] %.8x source %llx\r\n", reg, GPR[reg], GPR[reg+1], source); + dest = (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ + dest |= (t_uint64)GPR[reg+1]; /* get low order reg value */ +//fprintf(stderr, "DVM reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx\r\n", reg, GPR[reg], GPR[reg+1], dest); + if (source == 0) { + goto doovr; /* we have div by zero */ + } + td = ((t_int64)dest % (t_int64)source); /* remainder */ + dbl = (td < 0); /* double reg if neg remainder */ +//fprintf(stderr, "DVM remainder %llx dbl %x \r\n", td, dbl); + if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */ + td = -td; /* dividend and remainder must be same sign */ +//fprintf(stderr, "DVM fix sign %llx dbl %x source %llx dest %llx\r\n", td, dbl, source, dest); + dest = (t_int64)dest / (t_int64)source; /* now do the divide */ +//fprintf(stderr, "DVM dest %llx\r\n", dest); + if ((dest & D32LMASK) != 0 && (dest & D32LMASK) != D32LMASK) { /* test for overflow */ +doovr: + ovr = 1; /* the quotient exceeds 31 bit, overflow */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (modes & AEXPBIT) + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + /* the original regs must be returned unchanged if aexp */ +// i_flags &= ~SD; /* remove the store to reg flag */ +// dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ +// dest |= (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ + set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ +//fprintf(stderr, "DVM ovr %d reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx\r\n", ovr, reg, GPR[reg], GPR[reg+1], dest); + } else { + GPR[reg] = (uint32)(td & FMASK); /* reg gets remainder, reg+1 quotient */ + GPR[reg+1] = (uint32)(dest & FMASK); /* store quotient in reg+1 */ + set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ +//fprintf(stderr, "DVM good reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx rem %llx\r\n", reg, GPR[reg], GPR[reg+1], dest, td); + } + break; + + case 0xC8>>2: /* 0xC8 IMM - IMM */ /* Immedate */ + temp = GPR[reg]; /* get reg contents */ + addr = IR & RMASK; /* sign extend 16 bit imm value from IR */ + if (addr & 0x8000) /* negative */ + addr |= LMASK; /* extend sign */ +//fprintf(stderr, "C8 IMM temp %.8x addr %.8x\r\n", temp, addr); + + switch(opr & 0xF) { /* switch on aug code */ + case 0x0: /* LI */ /* SCC | SD */ + GPR[reg] = addr; /* put immediate value into reg */ + set_CCs(addr, ovr); /* set the CC's, CC1 = ovr */ + break; + + case 0x2: /* SUI */ + addr = -addr; /* just make value a negative add */ + /* drop through */ + case 0x1: /* ADI */ + t = (temp & FSIGN) != 0; /* set flag for sign bit not set in reg value */ + t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the extended immediate value */ + temp = temp + addr; /* now add the numbers */ + if ((t == 3 && (temp & FSIGN) == 0) || + (t == 0 && (temp & FSIGN) != 0)) + ovr = 1; /* we have an overflow */ + GPR[reg] = temp; /* save the result */ + set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (modes & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + } + break; + + case 0x3: /* MPI */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + /* change immediate value into a 64 bit value */ + source = ((t_uint64)(addr & FMASK)) | ((addr & FSIGN) ? D32LMASK : 0); +//fprintf(stderr, "MPI reg %d GPR[reg] %.8x GPR[reg+1] %.8x source %llx\r\n", reg, GPR[reg], GPR[reg+1], source); + temp = GPR[reg+1]; /* get reg multiplier */ + dest = ((t_uint64)(temp & FMASK)) | ((temp & FSIGN) ? D32LMASK : 0); +//fprintf(stderr, "MPI reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx\r\n", reg, GPR[reg], GPR[reg+1], dest); + dest = dest * source; /* do the multiply */ +//fprintf(stderr, "MPI dest result %llx\r\n", dest); + i_flags |= SD|SCC; /* save regs and set CC's */ + dbl = 1; /* double reg save */ + break; + + case 0x4: /* DVI */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + /* change immediate value into a 64 bit value */ + source = ((t_uint64)(addr & FMASK)) | ((addr & FSIGN) ? D32LMASK : 0); +//fprintf(stderr, "DVI reg %d GPR[reg] %.8x GPR[reg+1] %.8x source %llx\r\n", reg, GPR[reg], GPR[reg+1], source); + if (source == 0) { + goto doovr2; + } + dest = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ + dest |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ +//fprintf(stderr, "DVI reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx\r\n", reg, GPR[reg], GPR[reg+1], dest); + td = ((t_int64)dest % (t_int64)source); /* remainder */ + dbl = (td < 0); /* double reg if neg remainder */ +//fprintf(stderr, "DVI remainder %llx dbl %x \r\n", td, dbl); + if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */ + td = -td; /* dividend and remainder must be same sign */ +//fprintf(stderr, "DVI fix sign %llx dbl %x source %llx dest %llx\r\n", td, dbl, source, dest); + dest = (t_int64)dest / (t_int64)source; /* now do the divide */ +//fprintf(stderr, "DVI dest %llx\r\n", dest); + if ((dest & D32LMASK) != 0 && (dest & D32LMASK) != D32LMASK) { /* test for overflow */ +doovr2: + ovr = 1; /* the quotient exceeds 31 bit, overflow */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (modes & AEXPBIT) + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + /* the original regs must be returned unchanged if aexp */ + /* put reg values back in dest for CC test */ +// dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ +// dest |= (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ + set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ +// i_flags |= SCC; /* set CC's */ +//fprintf(stderr, "DVI ovr %d reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx\r\n", ovr, reg, GPR[reg], GPR[reg+1], dest); + } else { + GPR[reg] = (uint32)(td & FMASK); /* reg gets remainder, reg+1 quotient */ + GPR[reg+1] = (uint32)(dest & FMASK); /* store quotient in reg+1 */ + set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ +//fprintf(stderr, "DVI good reg %d GPR[reg] %.8x GPR[reg+1] %.8x dest %llx rem %llx\r\n", reg, GPR[reg], GPR[reg+1], dest, td); + } + break; + + case 0x5: /* CI */ /* SCC */ + temp = ((int)temp - (int)addr); /* subtract imm value from reg value */ + set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ +//fprintf(stderr, "CI IMM temp %.8x addr %.8x PSD1 %.8x flags %.8x\r\n", temp, addr, PSD1, i_flags); + break; + +/* SVC instruction format C806 */ +/* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ +/* |00 01 02 03 04 05|06 07 08|09 10 11|12 13 14 15|16 17 18 19|20 21 22 23 24 25 26 27 28 29 30 31| */ +/* | Op Code | N/U | N/U | Aug | SVC Index | SVC Call Number | */ +/* | 1 1 0 0 1 0| 0 0 0| 0 0 0| 0 1 1 0| x x x x| x x x x x x x x x x x x| */ +/* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ +/* */ + case 0x6: /* SVC none - none */ /* Supervisor Call Trap */ + { +#if 0 + int j; + char n[9]; + uint32 dqe = M[0x8e8>>2]; + for (j=0; j<8; j++) { + n[j] = (M[((dqe+0x18)>>2)+(j/4)] >> ((3-(j&7))*8)) & 0xff; + if (n[j] == 0) + n[j] = 0x20; + } + n[8] = 0; +#endif + addr = SPAD[0xf0]; /* get trap table memory address from SPAD (def 80) */ +//fprintf(stderr, "SVC 1 IMM temp %.8x addr %.8x PSD1 %.8x flags %.8x\r\n", temp, addr, PSD1, i_flags); + if (addr == 0 || addr == 0xffffffff) { /* see if secondary vector table set up */ + TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ + goto newpsd; /* program error */ + } + addr = addr + (0x06 << 2); /* addr has mem addr of SVC trap vector (def 98) */ + temp = M[addr >> 2]; /* get the secondary trap table address from memory */ +//fprintf(stderr, "SVC 2 IMM temp %.8x addr %.8x PSD1 %.8x temp2 %.8x\r\n", temp, addr, PSD1, temp2); + if (temp == 0 || temp == 0xffffffff) { /* see if ICB set up */ + TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ + goto newpsd; /* program error */ + } + temp2 = ((IR>>12) & 0x0f) << 2; /* get SVC index from IR */ +//fprintf(stderr, "SVC 2a IMM temp %.8x addr %.8x PSD1 %.8x temp2 %.8x\r\n", temp, addr, PSD1, temp2>>2); + t = M[(temp+temp2)>>2]; /* get secondary trap vector address ICB address */ + if (t == 0 || t == 0xffffffff) { /* see if ICB set up */ + TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ + goto newpsd; /* program error */ + } +//fprintf(stderr, "SVC 3 IMM temp %.8x svca %.8x PSD1 %.8x temp2 %.8x\r\n", temp+temp2, t, PSD1, temp2); + bc = PSD2 & 0x3ffc; /* get copy of cpix */ + M[t>>2] = (PSD1+4) & 0xfffffffe; /* store PSD 1 + 1W to point to next instruction */ + M[(t>>2)+1] = PSD2; /* store PSD 2 */ + PSD1 = M[(t>>2)+2]; /* get new PSD 1 */ + PSD2 = (M[(t>>2)+3] & ~0x3ffc) | bc; /* get new PSD 2 w/old cpix */ + M[(t>>2)+4] = IR&0xFFF; /* store call number */ +#if 0 +fprintf(stderr, "SVC @ %.8x SVC %x,%x PSD1 %.8x PSD2 %.8x SPAD PSD@ %x C.CURR %x LMN %s\r\n", OPSD1, temp2>>2, IR&0xFFF, PSD1, PSD2, SPAD[0xf5], dqe, n); +fprintf(stderr, " R0=%x R1=%x R2=%x R3=%x", GPR[0], GPR[1], GPR[2], GPR[3]); +fprintf(stderr, " R4=%x R5=%x R6=%x R7=%x", GPR[4], GPR[5], GPR[6], GPR[7]); +fprintf(stderr, "\r\n"); + if (((temp2>>2) == 1) && ((IR&0xfff) == 0x75)) +fprintf(stderr, "SVC %x,%x GPR[6] %x GPR[6] %x\r\n", temp2>>2, IR&0xfff, GPR[6], GPR[7]); +#endif + /* set the mode bits and CCs from the new PSD */ + CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ + modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + /* set new map mode and interrupt blocking state in CPUSTATUS */ + if (PSD2 & MAPBIT) { + CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ + modes |= MAPMODE; /* set mapped mode */ + } else + CPUSTATUS &= 0xff7fffff; /* reset bit 8 of cpu status */ + /* set interrupt blocking state */ + if ((PSD2 & 0x8000) == 0) { /* is it retain blocking state */ + if (PSD2 & 0x4000) /* no, is it set blocking state */ + CPUSTATUS |= 0x80; /* yes, set blk state in cpu status bit 24 */ + else { + CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ + irq_pend = 1; /* start scanning interrupts again */ + } + } + PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ + if (CPUSTATUS & 0x80) /* see if old mode is blocked */ + PSD2 |= 0x00004000; /* set to blocked state */ + + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + SPAD[0xf5] = PSD2; /* save the current PSD2 */ + goto newpsd; /* new psd loaded */ + } + break; + + case 0x7: /* EXR */ + IR = temp; /* get instruction to execute */ + if (addr & 2) /* if bit 30 set, instruction is in right hw, do EXRR */ + IR <<= 16; /* move instruction to left HW */ + if ((IR & 0xFC7F0000) == 0xC8070000 || + (IR & 0xFF800000) == 0xA8000000) { + /* Fault, attempt to execute another EXR, EXRR, or EXM */ + goto inv; /* invalid instruction */ + } + EXM_EXR = 4; /* set PC increment for EXR */ + goto exec; + break; + + /* these instruction were never used by MPX, only diags */ + case 0x8: /* SEM */ + case 0x9: /* LEM */ + case 0xA: /* CEMA */ + case 0xB: /* INV */ + case 0xC: /* INV */ + case 0xD: /* INV */ + case 0xE: /* INV */ + case 0xF: /* INV */ + goto inv; /* invalid instruction */ + break; + } + break; + + case 0xCC>>2: /* 0xCC ADR - ADR */ /* LF */ + /* For machines with Base mode 0xCC08 stores base registers */ + if ((FC & 3) != 0) { /* must be word address */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + bc = addr & 0x20; /* bit 26 initial value */ + while (reg < 8) { + if (bc != (addr & 0x20)) { /* test for crossing file boundry */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if (FC & 0x4) /* LFBR? */ + TRAPME = Mem_read(addr, &BR[reg]); /* read the base reg */ + else /* LF */ + TRAPME = Mem_read(addr, &GPR[reg]); /* read the GPR reg */ + if (TRAPME) /* TRAPME has error */ + goto newpsd; /* go execute the trap now */ + reg++; /* next reg to write */ + addr += 4; /* next addr */ + } + break; + + case 0xD0>>2: /* 0xD0 SD|ADR - INV */ /* LEA none basemode only */ +//fprintf(stderr, "Got LEA @ addr %x\\r\n", addr); + dest = (t_uint64)(addr); + break; + + case 0xD4>>2: /* 0xD4 SM|ADR - SM|ADR */ /* STx */ + break; + + case 0xD8>>2: /* 0xD8 SM|ADR - SM|ADR */ /* STMx */ + //FIXME STMD needs both regs to be masked with R4 + if (dbl) { + /* we need to and both regs */ + td = dest; + t_uint64 nm = (((t_uint64)GPR[4]) << 32) | (((t_uint64)GPR[4]) & D32RMASK); + dest &= nm; /* mask both regs with reg 4 contents */ +// fprintf(stderr, "STMD PSD %x src %llx GPR[4] %llx result %llx\r\n", +// PSD1, td, nm, dest); + } else { + td = dest; + dest &= (((t_uint64)GPR[4]) & D32RMASK); /* mask with reg 4 contents */ +// fprintf(stderr, "STMW PSD %x src %llx GPR[4] %llx result %llx\r\n", +// PSD1, td, ((t_uint64)GPR[4]), dest); + } + break; + + case 0xDC>>2: /* 0xDC INV - */ /* INV nonbasemode (STFx basemode) */ + /* DC00 STF */ /* DC08 STFBR */ + if ((FC & 0x4) && (CPU_MODEL <= MODEL_27)) { + /* basemode undefined for 32/7x & 32/27 */ /* TODO check this */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + goto newpsd; /* handle trap */ + } + /* For machines with Base mode 0xDC08 stores base registers */ + if ((FC & 3) != 0) { /* must be word address */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + bc = addr & 0x20; /* bit 26 initial value */ + while (reg < 8) { + if (bc != (addr & 0x20)) { /* test for crossing file boundry */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if (FC & 0x4) /* STFBR? */ + TRAPME = Mem_write(addr, &BR[reg]); /* store the base reg */ + else /* STF */ + TRAPME = Mem_write(addr, &GPR[reg]); /* store the GPR reg */ + if (TRAPME) /* TRAPME has error */ + goto newpsd; /* go execute the trap now */ + reg++; /* next reg to write */ + addr += 4; /* next addr */ + } + break; + + /* TODO */ + case 0xE0>>2: /* 0xE0 SCC|SD|RM|ADR - SD|RM|ADR */ /* ADFx, SUFx */ + if ((FC & 3) != 0) { /* must be word address */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if (opr & 0x0008) { /* Was it ADFx? */ + /* TODO ADF? call here */ + goto inv; + } else { + /* TODO SUF? call here */ + goto inv; + } /* it is SUFx */ + break; + + /* TODO */ + case 0xE4>>2: /* 0xE4 SCC|RM|ADR - RM|ADR */ /* MPFx, DVFx */ + if ((FC & 3) != 0) { /* must be word address */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if (opr & 0x0008) { /* Was it MPFx? */ + /* TODO MPF? call here */ + goto inv; + } else { + /* TODO DVF? call here */ + goto inv; + } /* it is DVFx */ + break; + + case 0xEC>>2: /* 0xEC ADR - ADR */ /* Branch unconditional or Branch True */ + /* GOOF alert, the assembler sets bit 31 to 1 so this test will fail*/ + /* so just test for F bit and go on */ + /* if ((FC & 5) != 0) { */ + if ((FC & 4) != 0) { + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + CC = PSD1 & 0x78000000; /* get CC's if any */ + switch(reg) { + case 0: t = 1; break; + case 1: t = (CC & CC1BIT) != 0; break; + case 2: t = (CC & CC2BIT) != 0; break; + case 3: t = (CC & CC3BIT) != 0; break; + case 4: t = (CC & CC4BIT) != 0; break; + case 5: t = (CC & (CC2BIT|CC4BIT)) != 0; break; + case 6: t = (CC & (CC3BIT|CC4BIT)) != 0; break; + case 7: t = (CC & (CC1BIT|CC2BIT|CC3BIT|CC4BIT)) != 0; break; + } +//fprintf(stderr, "BCT t %.8x addr %.8x CC %.8x PSD1 %.8x\r\n", t, addr, CC, PSD1); + if (t) { /* see if we are going to branch */ + /* we are taking the branch, set CC's if indirect, else leave'm */ + if (IR & IND) /* see if CCs from last indirect location are wanted */ + PSD1 = (PSD1 & 0x87fffffe) | CC; /* insert last CCs */ + /* update the PSD with new address */ + PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ + i_flags |= BT; /* we branched, so no PC update */ +//fprintf(stderr, "BR t %.8x addr %.8x PSD1 %.8x\r\n", t, addr, PSD1); + } + /* branch not taken, go do next instruction */ + break; + + case 0xF0>>2: /* 0xF0 ADR - ADR */ /* Branch False or Branch Function True */ + /* GOOF alert, the assembler sets bit 31 to 1 so this test will fail*/ + /* so just test for F bit and go on */ + /* if ((FC & 5) != 0) { */ + if ((FC & 4) != 0) { + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + CC = PSD1 & 0x78000000; /* get CC's if any */ + switch(reg) { + case 0: t = (GPR[4] & (0x8000 >> ((CC >> 27) & 0xf))) != 0; break; + case 1: t = (CC & CC1BIT) == 0; break; + case 2: t = (CC & CC2BIT) == 0; break; + case 3: t = (CC & CC3BIT) == 0; break; + case 4: t = (CC & CC4BIT) == 0; break; + case 5: t = (CC & (CC2BIT|CC4BIT)) == 0; break; + case 6: t = (CC & (CC3BIT|CC4BIT)) == 0; break; + case 7: t = (CC & (CC1BIT|CC2BIT|CC3BIT|CC4BIT)) == 0; break; + } +//fprintf(stderr, "BCF reg %d t %.8x addr %.8x CC %.8x PSD1 %.8x\r\n", reg, t, addr, CC, PSD1); + if (t) { /* see if we are going to branch */ + /* we are taking the branch, set CC's if indirect, else leave'm */ + /* update the PSD with new address */ + PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ + i_flags |= BT; /* we branched, so no PC update */ + if (IR & IND) /* see if CCs from last indirect location are wanted */ + PSD1 = (PSD1 & 0x87fffffe) | CC; /* insert last CCs */ +//fprintf(stderr, "BR t %.8x addr %.8x PSD1 %.8x\r\n", t, addr, PSD1); + } + break; + + case 0xF4>>2: /* 0xF4 RR|SD|ADR - RR|SB|WRD */ /* Branch increment */ + dest += 1 << ((IR >> 21) & 3); /* use bits 9 & 10 to incr reg */ + if (dest != 0) { /* if reg is not 0, take the branch */ + /* we are taking the branch, set CC's if indirect, else leave'm */ + /* update the PSD with new address */ +#if 1 +/* FIXME */ if (PC == (addr & 0x7FFFC)) { /* BIB to current PC, bump branch addr */ + addr += 4; +// fprintf(stderr, "BI? stopping BIB $ addr %x PC %x\r\n", addr, PC); + } +#endif + PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ + if (IR & IND) /* see if CCs from last indirect location are wanted */ + PSD1 = (PSD1 & 0x87fffffe) | CC; /* insert last CCs */ + i_flags |= BT; /* we branched, so no PC update */ + } + break; + + case 0xF8>>2: /* 0xF8 SM|ADR - SM|ADR */ /* ZMx, BL, BRI, LPSD, LPSDCM, TPR, TRP */ + switch((opr >> 7) & 0x7) { /* use bits 6-8 to determine instruction */ + case 0x0: /* ZMx F80x */ /* SM */ + dest = 0; /* destination value is zero */ + i_flags |= SM; /* SM not set so set it to store value */ + break; + case 0x1: /* BL F880 */ + /* copy CC's from instruction and PC incremented by 4 */ + GPR[0] = ((PSD1 & 0x78000000) | (PSD1 & 0x7fffe)) + 4; + if (IR & IND) /* see if CC from last indirect loacation are wanted */ + GPR[0] = (CC | (PSD1 & 0x7fffe)) + 4; /* set CC's and incremented PC */ + /* update the PSD with new address */ + PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); + i_flags |= BT; /* we branched, so no PC update */ + break; + + case 0x3: /* LPSD F980 */ + /* fall through */; + case 0x5: /* LPSDCM FA80 */ + { +#if 0 +int j; +char n[9]; +uint32 dqe = M[0x8e8>>2]; +for (j=0; j<8; j++) { + n[j] = (M[((dqe+0x18)>>2)+(j/4)] >> ((3-(j&7))*8)) & 0xff; + if (n[j] == 0) + n[j] = 0x20; +} +n[8] = 0; +#endif + CPUSTATUS |= 0x40; /* enable software traps */ + /* this will allow attn and */ + /* power fail traps */ + if ((TRAPME = Mem_read(addr, &PSD1))) { /* get PSD1 from memory */ + goto newpsd; /* memory read error or map fault */ + } + if ((TRAPME = Mem_read(addr+4, &PSD2))) { /* get PSD2 from memory */ + goto newpsd; /* memory read error or map fault */ + } + /* set the mode bits and CCs from the new PSD */ + CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ + modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + /* set new map mode and interrupt blocking state in CPUSTATUS */ + if (PSD2 & MAPBIT) { + CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ + modes |= MAPMODE; /* set mapped mode */ + } else + CPUSTATUS &= 0xff7fffff; /* reset bit 8 of cpu status */ + /* set interrupt blocking state */ + if ((PSD2 & 0x8000) == 0) { /* is it retain blocking state */ + if (PSD2 & 0x4000) /* no, is it set blocking state */ + CPUSTATUS |= 0x80; /* yes, set blk state in cpu status bit 24 */ + else { + CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ + irq_pend = 1; /* start scanning interrupts again */ + } + } + PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ + if (CPUSTATUS & 0x80) /* see if old mode is blocked */ + PSD2 |= 0x00004000; /* set to blocked state */ + + /* TRY if cpix is zero, copy cpix from PSD2 in SPAD[0xf5] */ + if ((PSD2 & 0x3fff) == 0) + PSD2 |= (SPAD[0xf5] & 0x3fff); /* use new cpix */ + + if (opr & 0x0200) { /* Was it LPSDCM? */ + /* map bit must be on to load maps */ + if (PSD2 & MAPBIT) { +#if 0 + // FIXME DEBUG EDIT +// if (n[0] == 'E' && n[1] == 'D' && n[2] == 'I' && n[3] == 'T') +// traceme = trstart; /* start tracing */ +traceme++; /* start trace */ +//if (traceme >= trstart) { +fprintf(stderr, "LPSDCM #%d LOAD MAPS PSD1 %x PSD2 %x SPAD PSD2 %x CPUSTATUS %x C.CURR %x LMN %s\r\n", traceme, PSD1, PSD2, SPAD[0xf5], CPUSTATUS, dqe, n); +fprintf(stderr, " R0=%x R1=%x R2=%x R3=%x", GPR[0], GPR[1], GPR[2], GPR[3]); +fprintf(stderr, " R4=%x R5=%x R6=%x R7=%x", GPR[4], GPR[5], GPR[6], GPR[7]); +fprintf(stderr, "\r\n"); +//reason = STOP_HALT; /* do halt for now */ +//} +#endif + /* set mapped mode in cpu status */ + CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ + /* we need to load the new maps */ + TRAPME = load_maps(&PSD1); /* load maps for new PSD */ + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + SPAD[0xf5] = PSD2; /* save the current PSD2 */ + sim_debug(DEBUG_EXP, &cpu_dev, + "LPSDCM MAPS LOADED TRAPME = %x PSD1 %x PSD2 %x CPUSTATUS %x\n", + TRAPME, PSD1, PSD2, CPUSTATUS); + } + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + } else { + /* LPSD */ +//traceme++; /* start trace */ +#if 0 +sim_debug(DEBUG_EXP, &cpu_dev, "LPSD PSD1 %x PSD2 %x CPUSTATUS %x\n", PSD1, PSD2, CPUSTATUS); +fprintf(stderr, "LPSD PSD1 %x PSD2 %x SPAD PSD2 %x CPUSTATUS %x C.CURR %x LMN %s\r\n", + PSD1, PSD2, SPAD[0xf5], CPUSTATUS, dqe, n); +fprintf(stderr, " R0=%x R1=%x R2=%x R3=%x", GPR[0], GPR[1], GPR[2], GPR[3]); +fprintf(stderr, " R4=%x R5=%x R6=%x R7=%x", GPR[4], GPR[5], GPR[6], GPR[7]); +fprintf(stderr, "\r\n"); +#endif + } +} + /* TRAPME can be error from LPSDCM or OK here */ + skipinstr = 1; /* skip next interrupt test only once */ + goto newpsd; /* load the new psd */ + break; + + case 0x4: /* JWCS */ /* not used in simulator */ + case 0x2: /* BRI */ /* TODO - only for 32/55 or 32/7X in PSW mode */ + case 0x6: /* TRP */ + case 0x7: /* TPR */ + TRAPME = UNDEFINSTR_TRAP; /* trap condition */ + goto newpsd; /* undefined instruction trap */ + break; + } + break; + +/* F Class I/O device instruction format */ +/* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ +/* |00 01 02 03 04 05|06 07 08|09 10 11 12|13 14 15|16|17 18 19 20 21 22 23|24 25 26 27 28 29 30 31| */ +/* | Op Code | Reg | I/O type | Aug |0 | Channel Address | Device Sub-address | */ +/* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ +/* */ +/* E Class I/O device instruction format */ +/* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ +/* |00 01 02 03 04 05|06 07 08 09 10 11 12|13 14 15|16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31| */ +/* | Op Code | Device Number | Aug | Command Code | */ +/* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ +/* */ + case 0xFC>>2: /* 0xFC IMM - IMM */ /* XIO, CD, TD, Interrupt Control */ + if ((modes & PRIVBIT) == 0) { /* must be privileged to do I/O */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ + TRAPSTATUS |= 0x1000; /* set Bit 19 of Trap Status word */ + goto newpsd; /* Privlege violation trap */ + } + if ((opr & 0x7) != 0x07) { /* aug is 111 for XIO instruction */ + /* Process Non-XIO instructions */ + uint32 status = 0; /* status returned from device */ + uint32 device = (opr >> 3) & 0x7f; /* get device code */ + uint32 prior = device; /* interrupt priority */ + t = SPAD[prior+0x80]; /* get spad entry for interrupt */ + addr = SPAD[0xf1] + (prior<<2); /* vector address in SPAD */ + addr = M[addr>>2]; /* get the interrupt context block addr */ +//fprintf(stderr, "CD/TD etc device %x intr %x spad %.8x addr %x\r\n", device, prior, t, addr); + + switch(opr & 0x7) { /* use bits 13-15 to determine instruction */ + case 0x0: /* EI FC00 Enable Interrupt */ + prior = (opr >> 3) & 0x7f; /* get priority level */ + /* SPAD entries for interrupts begin at 0x80 */ + t = SPAD[prior+0x80]; /* get spad entry for interrupt */ + if (t == 0 || t == 0xffffffff) /* if not set up, die */ + goto syscheck; /* system check */ + INTS[prior] |= INTS_ENAB; /* enable specified int level */ + SPAD[prior+0x80] |= SINT_ENAB; /* enable in SPAD too */ + irq_pend = 1; /* start scanning interrupts again */ +//fprintf(stderr, "EIO EI intr %.2x SPAD %.8x\r\n", prior, t); + if (prior == 0x18) /* is this the clock starting */ + rtc_setup(1, prior); /* tell clock to start */ + if (prior == 0x5f) /* is this the initerval timer starting */ + itm_setup(1, prior); /* tell timer to start */ + break; + + case 0x1: /* DI FC01 */ + prior = (opr >> 3) & 0x7f; /* get priority level */ + /* SPAD entries for interrupts begin at 0x80 */ + t = SPAD[prior+0x80]; /* get spad entry for interrupt */ + if (t == 0 || t == 0xffffffff) /* if not set up, die */ + goto syscheck; /* system check */ + INTS[prior] &= ~INTS_ENAB; /* disable specified int level */ + INTS[prior] &= ~INTS_REQ; /* clears any requests also */ + SPAD[prior+0x80] &= ~SINT_ENAB; /* disable in SPAD too */ +//fprintf(stderr, "EIO DI intr %.2x SPAD %.8x\r\n", prior, t); + if (prior == 0x18) /* is this the clock stopping */ + rtc_setup(0, prior); /* tell clock to stop */ + if (prior == 0x5f) /* is this the initerval timer stopping */ + itm_setup(0, prior); /* tell timer to stop */ + break; + + case 0x2: /* RI FC02 */ + prior = (opr >> 3) & 0x7f; /* get priority level */ + /* SPAD entries for interrupts begin at 0x80 */ + t = SPAD[prior+0x80]; /* get spad entry for interrupt */ + if (t == 0 || t == 0xffffffff) /* if not set up, die */ + goto syscheck; /* system check */ + INTS[prior] |= INTS_REQ; /* set the request flag for this level */ + irq_pend = 1; /* start scanning interrupts again */ +//fprintf(stderr, "EIO RI intr %.2x SPAD %.8x\r\n", prior, t); + break; + + case 0x3: /* AI FC03 */ + prior = (opr >> 3) & 0x7f; /* get priority level */ + /* SPAD entries for interrupts begin at 0x80 */ + t = SPAD[prior+0x80]; /* get spad entry for interrupt */ + if (t == 0 || t == 0xffffffff) /* if not set up, die */ + goto syscheck; /* system check */ + INTS[prior] |= INTS_ACT; /* activate specified int level */ +//fprintf(stderr, "EIO AI intr %.2x SPAD %.8x\r\n", prior, t); + break; + + case 0x4: /* DAI FC04 */ + prior = (opr >> 3) & 0x7f; /* get priority level */ + /* SPAD entries for interrupts begin at 0x80 */ + t = SPAD[prior+0x80]; /* get spad entry for interrupt */ + if (t == 0 || t == 0xffffffff) /* if not set up, die */ + goto syscheck; /* system check */ + INTS[prior] &= ~INTS_ACT; /* deactivate specified int level */ + SPAD[prior+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ +//fprintf(stderr, "EIO DAI intr %.2x SPAD %.8x INTS[%x] %x\r\n", prior, t, prior, INTS[prior]); + irq_pend = 1; /* start scanning interrupts again */ + skipinstr = 1; /* skip interrupt test */ + /* instruction following a DAI can not be interrupted */ + /* skip tests for interrupts if this is the case */ + break; + + case 0x5: /* TD FC05 */ /* bits 13-15 is test code type */ + case 0x6: /* CD FC06 */ + /* If CD or TD, make sure device is not F class device */ + /* the channel must be defined as a non class F I/O channel in SPAD */ + /* if class F, the system will generate a system check trap */ + t = SPAD[device]; /* get spad entry for channel */ + if (t == 0 || t == 0xffffffff) /* if not set up, die */ + goto syscheck; /* system check */ +//fprintf(stderr, "EIO TD/CD chan %.4x spad %.8x\r\n", device, t); + if ((t & 0x0f000000) == 0x0f000000) { /* class in bits 4-7 */ +syscheck: + TRAPME = SYSTEMCHK_TRAP; /* trap condition if F class */ + TRAPSTATUS &= ~BIT0; /* class E error bit */ + TRAPSTATUS &= ~BIT1; /* I/O processing error */ + goto newpsd; /* machine check trap */ + } + if (opr & 0x1) { /* see if CD or TD */ + /* process a TD */ +// if ((TRAPME = testEIO(device, testcode, &status))) +// goto newpsd; /* error returned, trap cpu */ + /* return status has new CC's in bits 1-4 of status word */ + PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status CCs */ +//fprintf(stderr, "EIO TD chan %.4x spad %.8x\r\n", device, t); + goto inv; /* invalid instruction until I fix it */ + } else { + /* process a CD */ +// if ((TRAPME = startEIO(device, &status))) +// goto newpsd; /* error returned, trap cpu */ +// t = SPAD[device]; /* get spad entry for channel */ + /* t has spad entry for device */ + /* get the 1's comp of interrupt address from bits 9-15 SPAD entry */ + ix = (t & 0x007f0000) >> 16; /* get the 1's comp of int level */ +//fprintf(stderr, "XIO1 chan %8x intr %8x spad %.8x\r\n", chan, ix, bc); + ix = 127 - ix; /* get positive number for interrupt */ +//fprintf(stderr, "XIO2 chan %x intr %x spad %.8x\r\n", chan, ix, bc); + temp = (IR & 0x7f); /* get cmd from instruction */ + if (device == 0x7f) { +//fprintf(stderr, "Interval Timer CD call cmd %x GPR[0] %x intr %x\r\n", temp, GPR[0], ix); + status = itm_rdwr(temp, GPR[0], ix); /* read/write the interval timer */ +//fprintf(stderr, "Interval Timer CD return status %x cmd %x GPR[0] %x intr %x\r\n", status, temp, GPR[0], ix); + if (temp != 0x39) /* this cmd does not return value */ + GPR[0] = status; /* return count in reg 0 */ + /* No CC's going out */ + } else { + goto inv; /* invalid instruction until I fix it */ + } + } + break; + case 0x7: /* XIO FC07*/ /* should never get here */ + break; + } + break; /* skip over XIO code */ + } + + /* Process XIO instructions */ + /* if reg is non-zero, add reg to 15 bits from instruction */ + if (reg) + temp2 = (IR & 0x7fff) + (GPR[reg] & 0x7fff); /* set new chan/suba into IR */ + else + temp2 = (IR & 0x7fff); /* set new chan/suba into IR */ + lchan = (temp2 & 0x7F00) >> 8; /* get 7 bit logical channel address */ + suba = temp2 & 0xFF; /* get 8 bit subaddress */ + /* the channel must be defined as a class F I/O channel in SPAD */ + /* if not class F, the system will generate a system check trap */ + t = SPAD[lchan]; /* get spad entry for channel */ + if (t == 0 || t == 0xffffffff) /* if not set up, die */ + goto syscheck; /* machine check */ +//fprintf(stderr, "XIO chan %x sa %x spad %.8x\r\n", chan, suba, t); +//sim_debug(DEBUG_EXP, &cpu_dev, "$$ XIO lchan %x sa %x spad %.8x\n", lchan, suba, t); + if ((t & 0x0f000000) != 0x0f000000) { /* class in bits 4-7 */ +mcheck: + TRAPME = MACHINECHK_TRAP; /* trap condition */ + TRAPSTATUS |= BIT0; /* class F error bit */ + TRAPSTATUS &= ~BIT1; /* I/O processing error */ + goto newpsd; /* machine check trap */ + } + /* get real channel from spad device entry */ + chan = (t & 0x7f00) >> 8; /* real channel */ + /* get the 1's comp of interrupt address from bits 9-15 SPAD entry */ + ix = (t & 0x007f0000) >> 16; /* get the 1's comp of int level */ +//fprintf(stderr, "XIO1 chan %8x intr %8x spad %.8x\r\n", chan, ix, bc); + ix = 127 - ix; /* get positive number for interrupt */ +//fprintf(stderr, "XIO2 chan %x intr %x spad %.8x\r\n", chan, ix, bc); + bc = SPAD[ix+0x80]; /* get interrupt entry for channel */ +//fprintf(stderr, "XIO chan %x intr %x spad %.8x\r\n", chan, ix, bc); + /* SPAD address F1 has interrupt table address */ + addr = SPAD[0xf1] + (ix<<2); /* vector address in SPAD */ +//fprintf(stderr, "XIOa spad %x intr %x spad %.8x addr %x\r\n", SPAD[0xf1], ix, bc, addr); + addr = M[addr>>2]; /* get the interrupt context block addr */ +//fprintf(stderr, "XIOb chan %x intr %x spad %.8x addr %x\r\n", chan, ix, bc, addr); + /* the context block contains the old PSD, */ + /* new PSD, IOCL address, and I/O status address */ + if (addr == 0) /* must be initialized address */ + goto mcheck; /* bad int icb address */ +//fprintf(stderr, "XIO chan %x intr %x addr %x iocla %x\r\n", chan, ix, addr, addr + 16); + if ((TRAPME = Mem_read(addr+16, &temp))) { /* get iocl address from icb wd 4 */ + goto mcheck; /* machine check if not there */ + } +//fprintf(stderr, "XIOx chan %x intr %x addr %x temp %x\r\n", chan, ix, addr, temp); + /* iocla must be valid addr if it is a SIO instruction */ + if (((temp & MASK24) == 0) && (((opr >> 2) & 0xf) == 2)) + goto mcheck; /* bad iocl address */ + +//fprintf(stderr, "XIO ready chan %x intr %x icb %x iocla %x iocd1 %.8x iocd2 %0.x8\r\n", +// chan, ix, addr, addr+16, M[temp>>2], M[(temp+4)>>2]); +//sim_debug(DEBUG_EXP, &cpu_dev, "XIO ready chan %x intr %x icb %x iocla %x iocd1 %.8x iocd2 %.8x\n", +// chan, ix, addr, addr+16, M[temp>>2], M[(temp+4)>>2]); + /* at this point, the channel has a valid SPAD channel entry */ + /* t is SPAD entry contents for chan device */ + /* temp2 has IR + reg contents if reg != 0 */ + /* lchan - logical channel address */ + /* chan - channel address */ + /* suba - channel device subaddress */ + /* ix - positive interrupt level */ + /* addr - ICB for specified interrupt level, points to 6 wd block */ + /* temp - First IOCD address */ +//fprintf(stderr, "XIO switch %x lchan %x chan %x intr %x chsa %x IOCDa %x\r\n", ((opr>>3)&0xf), lchan, chan, ix, (chan<<8)|suba, temp); +//sim_debug(DEBUG_EXP, &cpu_dev, "XIO switch chan %x intr %x chsa %x IOCDa %.8x\n", chan, ix, (chan<<8)|suba, temp); + switch((opr >> 3) & 0xf) { /* use bits 9-12 to determine I/O instruction */ + uint32 status; /* status returned by various functions */ + uint16 chsa; /* logical device address */ + + case 0x00: /* Unassigned */ + case 0x01: /* Unassigned */ + case 0x0A: /* Unassigned */ + TRAPME = UNDEFINSTR_TRAP; /* trap condition */ + goto newpsd; /* undefined instruction trap */ + break; + + case 0x09: /* Enable write channel ECWCS */ + case 0x0B: /* Write channel WCS WCWCS */ + /* for now or maybe forever, return unsupported transaction */ + PSD1 = ((PSD1 & 0x87fffffe) | (CC2BIT|CC4BIT)); /* insert status 5 */ + TRAPME = UNDEFINSTR_TRAP; /* trap condition */ + goto newpsd; /* undefined instruction trap */ + break; + + case 0x02: /* Start I/O SIO */ + chsa = temp2 & 0x7FFF; /* get logical device address */ + if ((TRAPME = startxio(chsa, &status))) + goto newpsd; /* error returned, trap cpu */ + PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ +//fprintf(stderr, "@@XIO SIO ret chan %x chsa %x status %x\r\n", chan, (chan<<8)|suba, status); +sim_debug(DEBUG_EXP, &cpu_dev, "XIO SIO ret chan %x chsa %x status %x\n", chan, (chan<<8)|suba, status); + break; + + case 0x03: /* Test I/O TIO */ + chsa = temp2 & 0x7FFF; /* get logical device address */ + if ((TRAPME = testxio(chsa, &status))) + goto newpsd; /* error returned, trap cpu */ + PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ +//fprintf(stderr, "@@XIO TIO ret chan %x chsa %x status %x\r\n", chan, (chan<<8)|suba, status); +sim_debug(DEBUG_EXP, &cpu_dev, "XIO TIO ret chan %x chsa %x status %x\n", chan, (chan<<8)|suba, status); + break; + + case 0x04: /* Stop I/O STPIO */ + chsa = temp2 & 0x7FFF; /* get logical device address */ + if ((TRAPME = stopxio(chsa, &status))) + goto newpsd; /* error returned, trap cpu */ + /* SPAD entries for interrupts begin at 0x80 */ +/* 07-16-18 chg */ INTS[ix] &= ~INTS_REQ; /* clears any requests also */ + INTS[ix] &= ~INTS_ACT; /* deactivate specified int level */ + SPAD[ix+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ + PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ +//fprintf(stderr, "@@XIO STPIO ret chan %x chsa %x status %x\r\n", chan, (chan<<8)|suba, status); +sim_debug(DEBUG_EXP, &cpu_dev, "XIO STPIO ret chan %x chsa %x status %x\n", chan, (chan<<8)|suba, status); + break; + + /* TODO Finish XIO */ + case 0x05: /* Reset channel RSCHNL */ + chsa = temp2 & 0x7FFF; /* get logical device address */ + /* SPAD entries for interrupts begin at 0x80 */ + INTS[ix] &= ~INTS_REQ; /* clears any requests */ + INTS[ix] &= ~INTS_ACT; /* deactivate specified int level */ + SPAD[ix+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ +//fprintf(stderr, "RSCHNL intr %.2x SPAD %.8x INTS[%x] %x\r\n", ix, bc, ix, INTS[ix]); + if ((TRAPME = rschnlxio(chsa, &status))) + goto newpsd; /* error returned, trap cpu */ + PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ +//fprintf(stderr, "XIO RSCHNL ret chan %x chsa %x status %x\r\n", chan, (chan<<8)|suba, status); +sim_debug(DEBUG_EXP, &cpu_dev, "XIO RSCHNL ret chan %x chsa %x status %x\n", chan, (chan<<8)|suba, status); + break; + + case 0x06: /* Halt I/O HIO */ + chsa = temp2 & 0x7FFF; /* get logical device address */ + if ((TRAPME = haltxio(chsa, &status))) + goto newpsd; /* error returned, trap cpu */ + PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ +//fprintf(stderr, "@@XIO HALTXIO ret chan %x chsa %x status %x\r\n", chan, (chan<<8)|suba, status); +sim_debug(DEBUG_EXP, &cpu_dev, "HIO HALTXIO ret chan %x chsa %x status %x\n", chan, (chan<<8)|suba, status); + break; + + case 0x07: /* Grab controller GRIO n/u */ + chsa = temp2 & 0x7FFF; /* get logical device address */ + if ((TRAPME = grabxio(chsa, &status))) + goto newpsd; /* error returned, trap cpu */ + PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ +//fprintf(stderr, "XIO GRIO ret chan %x chsa %x status %x\r\n", chan, (chan<<8)|suba, status); +sim_debug(DEBUG_EXP, &cpu_dev, "XIO GRIO ret chan %x chsa %x status %x\n", chan, (chan<<8)|suba, status); + break; + + case 0x08: /* Reset controller RSCTL */ + chsa = temp2 & 0x7FFF; /* get logical device address */ + if ((TRAPME = stopxio(chsa, &status))) + goto newpsd; /* error returned, trap cpu */ + PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */ +//fprintf(stderr, "XIO STPIO ret chan %x chsa %x status %x\r\n", chan, (chan<<8)|suba, status); +sim_debug(DEBUG_EXP, &cpu_dev, "XIO RSCTL ret chan %x chsa %x status %x\n", chan, (chan<<8)|suba, status); + break; + + /* TODO Finish XIO interrupts */ + case 0x0C: /* Enable channel interrupt ECI */ + chsa = temp2 & 0x7FFF; /* get logical device address */ +//fprintf(stderr, "XIO ECI chan %x sa %x spad %.8x INTS %x SPAD %x\r\n", chan, suba, t, INTS[ix], SPAD[ix+0x80]); +sim_debug(DEBUG_EXP, &cpu_dev, "XIO ECI chan %x sa %x spad %.8x\n", chan, suba, t); + /* SPAD entries for interrupts begin at 0x80 */ + INTS[ix] |= INTS_ENAB; /* enable specified int level */ + SPAD[ix+0x80] |= SINT_ENAB; /* enable in SPAD too */ + INTS[ix] &= ~INTS_REQ; /* clears any requests also TRY 06-09-18 */ +//TRY 06-09-18 irq_pend = 1; /* start scanning interrupts again */ +//fprintf(stderr, "ECI intr %.2x SPAD %.8x INTS[%x] %x\r\n", ix, bc, ix, INTS[ix]); + break; + + case 0x0D: /* Disable channel interrupt DCI */ + chsa = temp2 & 0x7FFF; /* get logical device address */ +sim_debug(DEBUG_EXP, &cpu_dev, "XIO DCI chan %x sa %x spad %.8x\n", chan, suba, t); + /* SPAD entries for interrupts begin at 0x80 */ + INTS[ix] &= ~INTS_ENAB; /* disable specified int level */ + INTS[ix] &= ~INTS_REQ; /* clears any requests also */ + SPAD[ix+0x80] &= ~SINT_ENAB; /* disable in SPAD too */ +//fprintf(stderr, "DCI intr %.2x SPAD %.8x INTS[%x] %x\r\n", ix, bc, ix, INTS[ix]); + break; + + case 0x0E: /* Activate channel interrupt ACI */ + chsa = temp2 & 0x7FFF; /* get logical device address */ +sim_debug(DEBUG_EXP, &cpu_dev, "XIO ACI chan %x sa %x spad %.8x\n", chan, suba, t); + /* SPAD entries for interrupts begin at 0x80 */ + INTS[ix] |= INTS_ACT; /* activate specified int level */ +//fprintf(stderr, "ACI intr %.2x SPAD %.8x INTS[%x] %x\r\n", ix, bc, ix, INTS[ix]); + break; + + case 0x0F: /* Deactivate channel interrupt DACI */ + /* Note, instruction following DACI is not interruptable */ + chsa = temp2 & 0x7FFF; /* get logical device address */ +sim_debug(DEBUG_EXP, &cpu_dev, "XIO DACI chan %x sa %x spad %.8x\n", chan, suba, t); + /* SPAD entries for interrupts begin at 0x80 */ +/* 07-16-18 chg */ INTS[ix] &= ~INTS_REQ; /* clears any requests also */ + INTS[ix] &= ~INTS_ACT; /* deactivate specified int level */ + SPAD[ix+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ +//fprintf(stderr, "DACI intr %.2x SPAD %.8x INTS[%x] %x\r\n", ix, bc, ix, INTS[ix]); + irq_pend = 1; /* start scanning interrupts again */ + skipinstr = 1; /* skip interrupt test */ +//NOTE CC must be returned */ + break; + } /* end of XIO switch */ + break; + } /* End of Instruction Switch */ + + /* any instruction with an arithmetic exception will still end up here */ + /* after the instruction is done and before incrementing the PC, */ + /* we will trap the cpu if ovl is set nonzero by an instruction */ + + /* Store result to register */ + if (i_flags & SD) { + if (dbl) { /* if double reg, store 2nd reg */ + GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ + GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ + } else { + GPR[reg] = (uint32)(dest & FMASK); /* save the reg */ + } + } + + /* Store result to base register */ + if (i_flags & SB) { + if (dbl) { /* no dbl wd store to base regs */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + BR[reg] = (uint32)(dest & FMASK); /* save the base reg */ +//fprintf(stderr, "SB base reg %x dest(BR) %.8x\r\n", reg, BR[reg]); + } + + /* Store result to memory */ + if (i_flags & SM) { + /* Check if byte of half word */ + if (((FC & 04) || (FC & 5) == 1)) { /* hw or byte requires read first */ + if ((TRAPME = Mem_read(addr, &temp))) { /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + } + } + switch(FC) { + case 2: /* double word store */ + if ((addr & 2) != 2) { + TRAPME = ADDRSPEC_TRAP; /* address not on dbl wd boundry, error */ + goto newpsd; /* go execute the trap now */ + } + temp = (uint32)(dest & MASK32);/* get lo 32 bit */ + if ((TRAPME = Mem_write(addr + 4, &temp))) + goto newpsd; /* memory write error or map fault */ + temp = (uint32)(dest >> 32); /* move upper 32 bits to lo 32 bits */ + break; + + case 0: /* word store */ + temp = (uint32)(dest & FMASK); /* mask 32 bit of reg */ + if ((addr & 3) != 0) { + /* Address fault */ + TRAPME = ADDRSPEC_TRAP; /* address not on wd boundry, error */ + goto newpsd; /* go execute the trap now */ + } + break; + + case 1: /* left halfword write */ + temp &= RMASK; /* mask out 16 left most bits */ + temp |= (uint32)(dest & RMASK) << 16; /* put into left most 16 bits */ + if ((addr & 1) != 1) { + /* Address fault */ + TRAPME = ADDRSPEC_TRAP; /* address not on hw boundry, error */ + goto newpsd; /* go execute the trap now */ + } + break; + + case 3: /* right halfword write */ + temp &= LMASK; /* mask out 16 right most bits */ + temp |= (uint32)(dest & RMASK); /* put into right most 16 bits */ + if ((addr & 3) != 3) { + TRAPME = ADDRSPEC_TRAP; /* address not on hw boundry, error */ + goto newpsd; /* go execute the trap now */ + } + break; + + case 4: + case 5: + case 6: + case 7: /* byte store operation */ + temp &= ~(0xFF << (8 * (7 - FC))); /* clear the byte to store */ + temp |= (uint32)(dest & 0xFF) << (8 * (7 - FC)); /* insert new byte */ + break; + } + /* store back the modified memory location */ + if ((TRAPME = Mem_write(addr, &temp))) /* store back to memory */ + goto newpsd; /* memory write error or map fault */ + } + + /* Update condition code registers */ + if (i_flags & SCC) { + PSD1 &= 0x87FFFFFe; /* clear the old CC's */ + if (ovr) /* if overflow, set CC1 */ + CC |= CC1BIT; /* show we had AEXP */ + else + CC = 0; /* no CC's yet */ + if (dest & MSIGN) /* is it neg */ + CC |= CC3BIT; /* if neg, set CC3 */ + else if (dest == 0) + CC |= CC4BIT; /* if zero, set CC4 */ + else + CC |= CC2BIT; /* if gtr than zero, set CC2 */ + PSD1 |= CC & 0x78000000; /* update the CC's in the PSD */ + } + + /* Update instruction pointer to next instruction */ + if (EXM_EXR != 0) { /* special handling for EXM, EXR, EXRR */ + PSD1 = (PSD1 + 4) | (((PSD1 & 2) >> 1) & 1); + EXM_EXR = 0; /* reset PC increment for EXR */ + } else + if ((i_flags & BT) == 0) { /* see if PSD was replaced on a branch instruction */ +//fprintf(stderr, "@PCI1 temp %.8x addr %.8x PSD1 %.8x flags %.8x\r\n", temp, addr, PSD1, i_flags); + /* branch not taken, so update the PC */ + if (i_flags & HLF) { + PSD1 = (PSD1 + 2) | (((PSD1 & 2) >> 1) & 1); + } else { + PSD1 = (PSD1 + 4) | (((PSD1 & 2) >> 1) & 1); + } +//fprintf(stderr, "@PCI2 temp %.8x addr %.8x PSD1 %.8x flags %.8x\r\n", temp, addr, PSD1, i_flags); + } + + /* check if we had an arithmetic exception on the last instruction*/ + if (ovr && (modes & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* trap the system now */ + goto newpsd; /* process the trap */ + } +#if 0 + /* no trap, so continue with next instruction */ +//PC = PSD1 & 0xfffffe; /* get 24 bit addr from PSD1 */ +// Get CCs from PSD1 and PC from original instruction */ +//if (traceme >= 4) { +if (traceme >= trstart) { +OPSD1 &= 0x87FFFFFE; /* clear the old CC's */ +OPSD1 |= PSD1 & 0x78000000; /* update the CC's in the PSD */ +if (modes & MAPMODE) + fprintf(stderr, "M%.8x %.8x ", OPSD1, OIR); +else + fprintf(stderr, "U%.8x %.8x ", OPSD1, OIR); +fprint_inst(stderr, OIR, 0); /* display instruction */ +fprintf(stderr, " R0=%x R1=%x R2=%x R3=%x", GPR[0], GPR[1], GPR[2], GPR[3]); +fprintf(stderr, " R4=%x R5=%x R6=%x R7=%x", GPR[4], GPR[5], GPR[6], GPR[7]); +fprintf(stderr, "\r\n"); +} +#endif +sim_debug(DEBUG_DATA, &cpu_dev, "R0=%08x R1=%08x R2=%08x R3=%08x\n", GPR[0], GPR[1], GPR[2], GPR[3]); +sim_debug(DEBUG_DATA, &cpu_dev, "R4=%08x R5=%08x R6=%08x R7=%08x\n", GPR[4], GPR[5], GPR[6], GPR[7]); + continue; /* keep running */ +// break; /* quit for now after each instruction */ + +newpsd: +//fprintf(stderr, "place @ newpsd PSD1 %.8x PSD2 %.8x TRAPME %.4x\r\n", PSD1, PSD2, TRAPME); + /* we get here from a LPSD, LPSDCM, INTR, or TRAP */ + if (TRAPME) { + /* SPAD location 0xf0 has trap vector base address */ + uint32 tta = SPAD[0xf0]; /* get trap table address in memory */ + uint32 tvl; /* trap vector location */ + if (tta == 0 || tta == 0xffffffff) + tta = 0x80; /* if not set, assume 0x80 FIXME */ + /* Trap Table Address in memory is pointed to by SPAD 0xF0 */ + /* TODO update cpu status and trap status words with reason too */ + switch(TRAPME) { + case POWERFAIL_TRAP: /* 0x80 power fail trap */ + case POWERON_TRAP: /* 0x84 Power-On trap */ + case MEMPARITY_TRAP: /* 0x88 Memory Parity Error trap */ + case NONPRESMEM_TRAP: /* 0x8C Non Present Memory trap */ + case UNDEFINSTR_TRAP: /* 0x90 Undefined Instruction Trap */ + case PRIVVIOL_TRAP: /* 0x94 Privlege Violation Trap */ +//TODO case SVCCALL_TRAP: /* 0x98 Supervisor Call Trap */ + case MACHINECHK_TRAP: /* 0x9C Machine Check Trap */ + case SYSTEMCHK_TRAP: /* 0xA0 System Check Trap */ + case MAPFAULT_TRAP: /* 0xA4 Map Fault Trap */ + case IPUUNDEFI_TRAP: /* 0xA8 IPU Undefined Instruction Trap */ + case SIGNALIPU_TRAP: /* 0xAC Signal IPU/CPU Trap */ + case ADDRSPEC_TRAP: /* 0xB0 Address Specification Trap */ + case CONSOLEATN_TRAP: /* 0xB4 Console Attention Trap */ + case PRIVHALT_TRAP: /* 0xB8 Privlege Mode Halt Trap */ + case AEXPCEPT_TRAP: /* 0xBC Arithmetic Exception Trap */ + default: + tta = tta + (TRAPME - 0x80); /* tta has mem addr of trap vector */ + tvl = M[tta>>2] & 0x7FFFC; /* get trap vector address from trap vector loc */ +//fprintf(stderr, "tvl %.8x, tta %.8x status %.8x\r\n", tvl, tta, CPUSTATUS); + if (tvl == 0 || tvl == 0x7FFFC || (CPUSTATUS & 0x40) == 0) { + /* vector is zero or software has not enabled traps yet */ + /* execute a trap halt */ + /* set the PSD to trap vector location */ + PSD1 = 0x80000000 + TRAPME; /* just priv and PC to trap vector */ + PSD2 = 0x00004000; /* unmapped, blocked interrupts mode */ + M[0x680>>2] = PSD1; /* store PSD 1 */ + M[0x684>>2] = PSD2; /* store PSD 2 */ + M[0x688>>2] = TRAPSTATUS; /* store trap status */ + M[0x68C>>2] = 0; /* This will be device table entry later TODO */ +fprintf(stderr, "[][][][][][][][][][][] HALT TRAP [][][][][][][][][][][][]\r\n"); +fprintf(stderr, "PSD1 %.8x PSD2 %.8x TRAPME %.4x\r\n", PSD1, PSD2, TRAPME); + for (ix=0; ix<8; ix+=2) { + fprintf(stderr, "GPR[%d] %.8x GPR[%d] %.8x\r\n", ix, GPR[ix], ix+1, GPR[ix+1]); + } +fprintf(stderr, "[][][][][][][][][][][] HALT TRAP [][][][][][][][][][][][]\r\n"); + return STOP_HALT; /* exit to simh for halt */ + } else { + /* valid vector, so store the PSD, fetch new PSD */ + bc = PSD2 & 0x3ffc; /* get copy of cpix */ + M[tvl>>2] = PSD1 & 0xfffffffe; /* store PSD 1 */ + M[(tvl>>2)+1] = PSD2; /* store PSD 2 */ + PSD1 = M[(tvl>>2)+2]; /* get new PSD 1 */ + PSD2 = (M[(tvl>>2)+3] & ~0x3ffc) | bc; /* get new PSD 2 w/old cpix */ + M[(tvl>>2)+4] = TRAPSTATUS; /* store trap status */ + + /* set the mode bits and CCs from the new PSD */ + CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ + modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + /* set new map mode and interrupt blocking state in CPUSTATUS */ + if (PSD2 & MAPBIT) { + CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ + modes |= MAPMODE; /* set mapped mode */ + } else + CPUSTATUS &= 0xff7fffff; /* reset bit 8 of cpu status */ + /* set interrupt blocking state */ + if ((PSD2 & 0x8000) == 0) { /* is it retain blocking state */ + if (PSD2 & 0x4000) /* no, is it set blocking state */ + CPUSTATUS |= 0x80; /* yes, set blk state in cpu status bit 24 */ + else + CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */ + } + PSD2 &= ~0x0000c000; /* clear bit 48 & 49 to be unblocked */ + if (CPUSTATUS & 0x80) /* see if old mode is blocked */ + PSD2 |= 0x00004000; /* set to blocked state */ + + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + SPAD[0xf5] = PSD2; /* save the current PSD2 */ +#if 0 +if (TRAPME == UNDEFINSTR_TRAP) { +sim_debug(DEBUG_EXP, &cpu_dev, "TRAP PSD1 %x PSD2 %x CPUSTATUS %x\n", PSD1, PSD2, CPUSTATUS); +fprintf(stderr, "TRAPS %x LOAD MAPS PSD1 %x PSD2 %x CPUSTATUS %x\r\n", TRAPME, PSD1, PSD2, CPUSTATUS); +goto dumpi; +} +#endif + break; /* Go execute the trap */ + } + break; + } + } + skipinstr = 1; /* skip next instruction */ + /* we have a new PSD loaded via a LPSD or LPSDCM */ + /* TODO finish instruction history, then continue */ + /* update cpu status word too */ +#if 0 +if (traceme >= trstart) { +dumpi: +OPSD1 &= 0x87FFFFFE; /* clear the old CC's */ +OPSD1 |= PSD1 & 0x78000000; /* update the CC's in the PSD */ +if (modes & MAPMODE) + fprintf(stderr, "M%.8x %.8x ", OPSD1, OIR); +else + fprintf(stderr, "U%.8x %.8x ", OPSD1, OIR); +fprint_inst(stderr, OIR, 0); /* display instruction */ +fprintf(stderr, " R0=%x R1=%x R2=%x R3=%x", GPR[0], GPR[1], GPR[2], GPR[3]); +fprintf(stderr, " R4=%x R5=%x R6=%x R7=%x", GPR[4], GPR[5], GPR[6], GPR[7]); +fprintf(stderr, "\r\n"); +} +#endif +sim_debug(DEBUG_DATA, &cpu_dev, "R0=%08x R1=%08x R2=%08x R3=%08x\n", GPR[0], GPR[1], GPR[2], GPR[3]); +sim_debug(DEBUG_DATA, &cpu_dev, "R4=%08x R5=%08x R6=%08x R7=%08x\n", GPR[4], GPR[5], GPR[6], GPR[7]); + continue; /* single step cpu just for now */ +// break; /* quit for now after each instruction */ + } /* end while */ + + /* Simulation halted */ +//fprintf(stderr, "@end PSD1 %.8x PSD2 %.8x addr %.8x\r\n", PSD1, PSD2, addr); + return reason; +} + +/* these are the default ipl devices defined by the CPU jumpers */ +/* they can be overridden by specifying IPL device at ipl time */ +uint32 def_disk = 0x0800; /* disk channel 8, device 0 */ +uint32 def_tape = 0x1000; /* tape device 10, device 0 */ +uint32 def_floppy = 0x7ef0; /* IOP floppy disk channel 7e, device f0 */ +//int once = 0; /* one time inits */ + +/* Reset routine */ +/* do any one time initialization here for cpu */ +t_stat cpu_reset(DEVICE * dptr) +{ + int i; + + /* leave regs alone so values can be passed to boot code */ + PSD1 = 0x80000000; /* privileged, non mapped, non extended, address 0 */ + PSD2 = 0x00004000; /* blocked interrupts mode */ + modes = (PRIVBIT | BLKMODE); /* set modes to privileged and blocked interrupts */ + CC = 0; /* no CCs too */ + CPUSTATUS = CPU_MODEL; /* clear all cpu status except cpu type */ + CPUSTATUS |= 0x80000000; /* set privleged state bit 0 */ + CPUSTATUS |= 0x00000080; /* set blocked mode state bit 24 */ + TRAPSTATUS = CPU_MODEL; /* clear all trap status except cpu type */ + + chan_set_devs(); /* set up the defined devices on the simulator */ + + /* set default breaks to execution tracing */ + sim_brk_types = sim_brk_dflt = SWMASK('E'); + /* zero regs */ + for (i = 0; i < 8; i++) { + GPR[i] = 0; /* clear the registers */ + BR[i] = 0; /* clear the registers */ + } + /* zero interrupt status words */ + for (i = 0; i < 112; i++) + INTS[i] = 0; /* clear interrupt status flags */ + + /* add code here to initialize the SEL32 cpu scratchpad on initial start */ + /* see if spad setup by software, if yes, leave spad alone */ + /* otherwise set the default values into the spad */ + /* CPU key is 0xECDAB897, IPU key is 0x13254768 */ + /* Keys are loaded by the O/S software during the boot loading sequence */ + if (SPAD[0xf7] != 0xecdab897) + { + int ival = 0; /* init value for concept 32 */ + + if (CPU_MODEL < MODEL_27) + ival = 0xfffffff; /* init value for 32/7x int and dev entries */ + for (i = 0; i < 1024; i++) + MAPC[i] = 0; /* clear 2048 halfword map cache */ + for (i = 0; i < 224; i++) + SPAD[i] = ival; /* init 128 devices and 96 ints in the spad */ + for (i = 224; i < 256; i++) /* clear the last 32 extries */ + SPAD[i] = 0; /* clear the spad */ + SPAD[0xf0] = 0x80; /* default Trap Table Address (TTA) */ + SPAD[0xf1] = 0x100; /* Interrupt Table Address (ITA) */ + SPAD[0Xf2] = 0x700; /* IOCD Base Address */ + SPAD[0xf3] = 0x788; /* Master Process List (MPL) table address */ + SPAD[0xf4] = def_tape; /* Default IPL address from console IPL command or jumper */ + SPAD[0xf5] = 0x00004000; /* current PSD2 defaults to blocked */ + SPAD[0xf6] = 0; /* reserved (PSD1 ??) */ + SPAD[0xf7] = 0; /* make sure key is zero */ + SPAD[0xf8] = 0x0000f000; /* set DRT to class f (anything else is E) */ + SPAD[0xf9] = CPU_MODEL; /* set default cpu type in cpu status word */ + SPAD[0xff] = 0x00ffffff; /* interrupt level 7f 1's complament */ + } + M[0] = 0x02000000; /* 0x00 IOCD 1 read into address 0 */ + M[1] = 0x60000078; /* 0x04 IOCD 1 CMD Chain, Suppress incor length, 120 bytes */ + M[2] = 0x53000000; /* 0x08 IOCD 2 BKSR or RZR to re-read boot code */ + M[3] = 0x60000001; /* 0x0C IOCD 2 CMD chain,Supress incor length, 1 byte */ + M[4] = 0x02000000; /* 0x10 IOCD 3 Read into address 0 */ + M[5] = 0x000006EC; /* 0x14 IOCD 3 Read 0x6EC bytes */ + loading = 0; /* not loading yet */ + /* we are good to go */ + return SCPE_OK; +} + +/* Memory examine */ +/* examine a 32bit memory location */ +/* address is byte address with bits 30,31 = 0 */ +t_stat cpu_ex(t_value *vptr, t_addr baddr, UNIT *uptr, int32 sw) +{ + uint32 temp, t; + uint32 addr = (baddr & 0xfffffc) >> 2; /* make 24 bit byte address into word address */ + + /* MSIZE is in 32 bit words */ + if (addr >= MEMSIZE) /* see if address is within our memory */ + return SCPE_NXM; /* no, none existant memory error */ + if (vptr == NULL) /* any address specified by user */ + return SCPE_OK; /* no, just ignore the request */ + *vptr = M[addr]; /* return memory contents */ + return SCPE_OK; /* we are all ok */ +} + +/* Memory deposit */ +/* modify a 32bit memory location */ +/* address is byte address with bits 30,31 = 0 */ +t_stat cpu_dep(t_value val, t_addr baddr, UNIT *uptr, int32 sw) +{ + uint32 addr = (baddr & 0xfffffc) >> 2; /* make 24 bit byte address into word address */ + +//fprintf(stderr, "cpu_dep baddr %0x, sw %x\b\n", baddr, sw); + /* MSIZE is in 32 bit words */ + if (addr >= MEMSIZE) /* see if address is within our memory */ + return SCPE_NXM; /* no, none existant memory error */ + M[addr] = val; /* set the new data value */ + return SCPE_OK; /* all OK */ +} + +/* set the CPU memory size */ +t_stat cpu_set_size(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + t_uint64 mc = 0; + uint32 i; + +//fprintf(stderr, "WE are here 4 \b\n"); + cpu_unit.flags &= ~UNIT_MSIZE; + cpu_unit.flags |= val; /* set new memory size */ + val >>= UNIT_V_MSIZE; /* set size in 32bit words */ + val = (val + 1) * 128 * 1024; /* KW's */ + if ((val < 0) || (val > MAXMEMSIZE)) /* is size valid */ + return SCPE_ARG; /* nope, argument error */ + for (i = val; i < MEMSIZE; i++) /* see if memory contains anything */ + mc |= M[i]; /* or in any bits in memory */ + if ((mc != 0) && (!get_yn("Really truncate memory [N]?", FALSE))) + return SCPE_OK; /* return OK if user says no */ + MEMSIZE = val; /* set new size */ + for (i = MEMSIZE; i < MAXMEMSIZE; i++) + M[i] = 0; /* zero all of the new memory */ + return SCPE_OK; /* we done */ +} + +/* Handle execute history */ + +/* Set history */ +t_stat +cpu_set_hist(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + int32 i, lnt; + t_stat r; + + if (cptr == NULL) { /* check for any user options */ + for (i = 0; i < hst_lnt; i++) /* none, so just zero the history */ + hst[i].psd1 = 0; /* just psd1 for now */ + hst_p = 0; /* start at teh beginning */ + return SCPE_OK; /* all OK */ + } + /* the user has specified options, process them */ + lnt = (int32) get_uint(cptr, 10, HIST_MAX, &r); + if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; /* arg error for bad input or too small a value */ + hst_p = 0; /* start at beginning */ + if (hst_lnt) { /* if a new length was input, resize history buffer */ + free(hst); /* out with the old */ + hst_lnt = 0; /* no length anymore */ + hst = NULL; /* and no pointer either */ + } + if (lnt) { /* see if new size specified, if so get new resized buffer */ + hst = (struct InstHistory *)calloc(sizeof(struct InstHistory), lnt); + if (hst == NULL) + return SCPE_MEM; /* allocation error, so tell user */ + hst_lnt = lnt; /* set new length */ + } + return SCPE_OK; /* we are good to go */ +} + +/* Show history */ +t_stat cpu_show_hist(FILE * st, UNIT * uptr, int32 val, CONST void *desc) +{ + int32 k, di, lnt; + char *cptr = (char *) desc; + t_stat r; + struct InstHistory *h; + + if (hst_lnt == 0) /* see if show history is enabled */ + return SCPE_NOFNC; /* no, so are out of here */ + if (cptr) { /* see if user provided a display count */ + lnt = (int32)get_uint(cptr, 10, hst_lnt, &r); /* get the count */ + if ((r != SCPE_OK) || (lnt == 0)) /* if error or 0 count */ + return SCPE_ARG; /* report argument error */ + } else + lnt = hst_lnt; /* dump all the entries */ + di = hst_p - lnt; /* work forward */ + if (di < 0) + di = di + hst_lnt; /* wrap */ + fprintf(st, "PSD1 PSD2 INST DEST SRC CC\n"); + for (k = 0; k < lnt; k++) { /* print specified entries */ + h = &hst[(++di) % hst_lnt]; /* entry pointer */ + /* display the instruction and results */ + fprintf(st, "%08x %08x %08x %08x %08x %1x", + h->psd1, h->psd2, h->inst, h->dest, h->src, h->cc); + fputc('\n', st); /* end line */ + } /* end for */ + return SCPE_OK; /* all is good */ +} + +/* return description for the specified device */ +const char *cpu_description (DEVICE *dptr) +{ + return "SEL 32 CPU"; /* return description */ +} + +t_stat +cpu_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ + fprintf (st, "The CPU can be set to \n"); + fprintf (st, "The CPU can maintain a history of the most recently executed instructions.\n"); + fprintf (st, "This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:\n\n"); + fprintf (st, " sim> SET CPU HISTORY clear history buffer\n"); + fprintf (st, " sim> SET CPU HISTORY=0 disable history\n"); + fprintf (st, " sim> SET CPU HISTORY=n{:file} enable history, length = n\n"); + fprintf (st, " sim> SHOW CPU HISTORY print CPU history\n"); + return SCPE_OK; +} + diff --git a/SEL32/sel32_defs.h b/SEL32/sel32_defs.h index 42b2103..3f45870 100644 --- a/SEL32/sel32_defs.h +++ b/SEL32/sel32_defs.h @@ -22,24 +22,24 @@ */ -#include "sim_defs.h" /* simh simulator defns */ +#include "sim_defs.h" /* simh simulator defns */ /* Simulator stop codes */ -#define STOP_IONRDY 1 /* I/O dev not ready */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_UUO 4 /* invalid opcode */ -#define STOP_INVINS 5 /* invalid instr */ -#define STOP_INVIOP 6 /* invalid I/O op */ -#define STOP_INDLIM 7 /* indirect limit */ -#define STOP_XECLIM 8 /* XEC limit */ -#define STOP_IOCHECK 9 /* IOCHECK */ -#define STOP_MMTRP 10 /* mm in trap */ -#define STOP_TRPINS 11 /* trap inst not BRM */ -#define STOP_RTCINS 12 /* rtc inst not MIN/SKR */ -#define STOP_ILLVEC 13 /* zero vector */ -#define STOP_CCT 14 /* runaway CCT */ +#define STOP_IONRDY 1 /* I/O dev not ready */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_UUO 4 /* invalid opcode */ +#define STOP_INVINS 5 /* invalid instr */ +#define STOP_INVIOP 6 /* invalid I/O op */ +#define STOP_INDLIM 7 /* indirect limit */ +#define STOP_XECLIM 8 /* XEC limit */ +#define STOP_IOCHECK 9 /* IOCHECK */ +#define STOP_MMTRP 10 /* mm in trap */ +#define STOP_TRPINS 11 /* trap inst not BRM */ +#define STOP_RTCINS 12 /* rtc inst not MIN/SKR */ +#define STOP_ILLVEC 13 /* zero vector */ +#define STOP_CCT 14 /* runaway CCT */ /* I/O equates */ /* Channel sense bytes set by device */ @@ -96,36 +96,36 @@ #define BUFF_NEWCMD 0x10 /* Channel ready for new command */ #define BUFF_CHNEND 0x20 /* Channel end */ -#define MAX_CHAN 128 /* max channels that can be defined */ -#define SUB_CHANS 256 /* max sub channels that can be defined */ -#define MAX_DEV (MAX_CHAN * SUB_CHANS) /* max possible */ +#define MAX_CHAN 128 /* max channels that can be defined */ +#define SUB_CHANS 256 /* max sub channels that can be defined */ +#define MAX_DEV (MAX_CHAN * SUB_CHANS) /* max possible */ /* simulator devices configuration */ -#define NUM_DEVS_IOP 1 /* 1 device IOP channel controller */ -#define NUM_UNITS_IOP 1 /* 1 master IOP channel device */ -#define NUM_DEVS_COM 2 /* 8-Line async controller */ -#define NUM_UNITS_COM 16 /* 8-Line async units */ -#define NUM_DEVS_CON 1 /* 1 I/O console controller */ -#define NUM_UNITS_CON 2 /* 2 console input & output */ -#define NUM_DEVS_MT 1 /* 1 mag tape controllers */ -#define NUM_UNITS_MT 4 /* 4 of 8 devices */ -#define NUM_DEVS_DISK 1 /* 1 DP02 disk drive controller */ -#define NUM_UNITS_DISK 4 /* 4 disk drive devices */ -#define NUM_DEVS_SCFI 2 /* 2 scfi (SCSI) disk drive units */ -#define NUM_UNITS_SCFI 2 /* 2 of 4 disk drive devices */ -#define NUM_DEVS_RTOM 1 /* 1 IOP RTOM channel */ -#define NUM_UNITS_RTOM 1 /* 1 IOP RTOM device (clock & interval timer) */ -#define NUM_DEVS_LPR 1 /* 1 IOP Line printer */ -#define NUM_UNITS_LPR 1 /* 1 IOP Line printer device */ +#define NUM_DEVS_IOP 1 /* 1 device IOP channel controller */ +#define NUM_UNITS_IOP 1 /* 1 master IOP channel device */ +#define NUM_DEVS_COM 2 /* 8-Line async controller */ +#define NUM_UNITS_COM 16 /* 8-Line async units */ +#define NUM_DEVS_CON 1 /* 1 I/O console controller */ +#define NUM_UNITS_CON 2 /* 2 console input & output */ +#define NUM_DEVS_MT 1 /* 1 mag tape controllers */ +#define NUM_UNITS_MT 4 /* 4 of 8 devices */ +#define NUM_DEVS_DISK 1 /* 1 DP02 disk drive controller */ +#define NUM_UNITS_DISK 4 /* 4 disk drive devices */ +#define NUM_DEVS_SCFI 2 /* 2 scfi (SCSI) disk drive units */ +#define NUM_UNITS_SCFI 2 /* 2 of 4 disk drive devices */ +#define NUM_DEVS_RTOM 1 /* 1 IOP RTOM channel */ +#define NUM_UNITS_RTOM 1 /* 1 IOP RTOM device (clock & interval timer) */ +#define NUM_DEVS_LPR 1 /* 1 IOP Line printer */ +#define NUM_UNITS_LPR 1 /* 1 IOP Line printer device */ -extern DEVICE cpu_dev; /* cpu device */ -extern UNIT cpu_unit; /* the cpu unit */ +extern DEVICE cpu_dev; /* cpu device */ +extern UNIT cpu_unit; /* the cpu unit */ #ifdef NUM_DEVS_IOP -extern DEVICE iop_dev; /* IOP channel controller */ +extern DEVICE iop_dev; /* IOP channel controller */ #endif #ifdef NUM_DEVS_RTOM -extern DEVICE rtc_dev; /* RTOM rtc */ -extern DEVICE itm_dev; /* RTOM itm */ +extern DEVICE rtc_dev; /* RTOM rtc */ +extern DEVICE itm_dev; /* RTOM itm */ #endif #ifdef NUM_DEVS_CON extern DEVICE con_dev; @@ -158,49 +158,49 @@ extern DEVICE lpr_dev; /* Memory */ -#define MAXMEMSIZE ((16*1024*1024)/4) /* max memory size */ -#define PAMASK (MAXMEMSIZE - 1) /* physical addr mask */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define MEM_ADDR_OK(x) (((x)) < MEMSIZE) +#define MAXMEMSIZE ((16*1024*1024)/4) /* max memory size */ +#define PAMASK (MAXMEMSIZE - 1) /* physical addr mask */ +#define MEMSIZE (cpu_unit.capac) /* actual memory size */ +#define MEM_ADDR_OK(x) (((x)) < MEMSIZE) /* channel program data for a chan/sub-address */ typedef struct chp { - /* channel program values */ - uint32 chan_inch_addr; /* Channel status dw in memory */ - uint32 chan_caw; /* Channel command address word */ - uint32 ccw_addr; /* Channel address */ - uint16 ccw_count; /* Channel count */ - uint8 ccw_cmd; /* Channel command and flags */ - uint16 ccw_flags; /* Channel flags */ - uint16 chan_status; /* Channel status */ - uint16 chan_dev; /* Device on channel */ - uint32 chan_buf; /* Channel data buffer */ - uint8 chan_byte; /* Current byte, dirty/full */ + /* channel program values */ + uint32 chan_inch_addr; /* Channel status dw in memory */ + uint32 chan_caw; /* Channel command address word */ + uint32 ccw_addr; /* Channel address */ + uint16 ccw_count; /* Channel count */ + uint8 ccw_cmd; /* Channel command and flags */ + uint16 ccw_flags; /* Channel flags */ + uint16 chan_status; /* Channel status */ + uint16 chan_dev; /* Device on channel */ + uint32 chan_buf; /* Channel data buffer */ + uint8 chan_byte; /* Current byte, dirty/full */ } CHANP; /* Device information block */ -#define FIFO_SIZE 256 /* fifo to hold 128 double words of status */ +#define FIFO_SIZE 256 /* fifo to hold 128 double words of status */ typedef struct dib { - /* Pre start I/O operation */ - uint8 (*pre_io)(UNIT *uptr, uint16 chan); - /* Start a channel command SIO */ - uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd); - /* Halt I/O HIO */ - uint8 (*halt_io)(UNIT *uptr); - /* Test I/O TESTIO */ - uint8 (*test_io)(UNIT *uptr); - /* Post I/O processing */ - uint8 (*post_io)(UNIT *uptr); - /* Controller init */ - void (*dev_ini)(UNIT *, t_bool); /* init function */ - UNIT *units; /* Pointer to units structure */ - CHANP *chan_prg; /* Pointer to channel program */ - uint8 numunits; /* number of units */ - uint8 mask; /* device mask */ - uint16 chan_addr; /* parent channel address */ - uint32 chan_fifo_in; /* fifo input index */ - uint32 chan_fifo_out; /* fifo output index */ - uint32 chan_fifo[FIFO_SIZE]; /* interrupt status fifo for each channel */ + /* Pre start I/O operation */ + uint8 (*pre_io)(UNIT *uptr, uint16 chan); + /* Start a channel command SIO */ + uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd); + /* Halt I/O HIO */ + uint8 (*halt_io)(UNIT *uptr); + /* Test I/O TESTIO */ + uint8 (*test_io)(UNIT *uptr); + /* Post I/O processing */ + uint8 (*post_io)(UNIT *uptr); + /* Controller init */ + void (*dev_ini)(UNIT *, t_bool); /* init function */ + UNIT *units; /* Pointer to units structure */ + CHANP *chan_prg; /* Pointer to channel program */ + uint8 numunits; /* number of units */ + uint8 mask; /* device mask */ + uint16 chan_addr; /* parent channel address */ + uint32 chan_fifo_in; /* fifo input index */ + uint32 chan_fifo_out; /* fifo output index */ + uint32 chan_fifo[FIFO_SIZE]; /* interrupt status fifo for each channel */ } DIB; /* DEV 0x7F000000 UNIT 0x00ff0000 */ @@ -234,22 +234,22 @@ typedef struct dib { extern DEBTAB dev_debug[]; /* defines for all programs */ -#define RMASK 0x0000FFFF /* right hw 16 bit mask */ -#define LMASK 0xFFFF0000 /* left hw 16 bit mask */ -#define FMASK 0xFFFFFFFF /* 32 bit mask */ -#define DMASK 0xFFFFFFFFFFFFFFFFLL /* 64 bit all bits mask */ -#define D48LMASK 0xFFFFFFFFFFFF0000LL /* 64 bit left 48 bits mask */ -#define D32LMASK 0xFFFFFFFF00000000LL /* 64 bit left 32 bits mask */ -#define D32RMASK 0x00000000FFFFFFFFLL /* 64 bit right 32 bits mask */ -#define MSIGN 0x80000000 /* 32 bit minus sign */ -#define DMSIGN 0x8000000000000000LL /* 64 bit minus sign */ -#define FSIGN 0x80000000 /* 32 bit minus sign */ +#define RMASK 0x0000FFFF /* right hw 16 bit mask */ +#define LMASK 0xFFFF0000 /* left hw 16 bit mask */ +#define FMASK 0xFFFFFFFF /* 32 bit mask */ +#define DMASK 0xFFFFFFFFFFFFFFFFLL /* 64 bit all bits mask */ +#define D48LMASK 0xFFFFFFFFFFFF0000LL /* 64 bit left 48 bits mask */ +#define D32LMASK 0xFFFFFFFF00000000LL /* 64 bit left 32 bits mask */ +#define D32RMASK 0x00000000FFFFFFFFLL /* 64 bit right 32 bits mask */ +#define MSIGN 0x80000000 /* 32 bit minus sign */ +#define DMSIGN 0x8000000000000000LL /* 64 bit minus sign */ +#define FSIGN 0x80000000 /* 32 bit minus sign */ /* sign extend 16 bit value to uint32 */ -#define SEXT16(x) (x&0x8000?(uint32)(((uint32)x&RMASK)|LMASK):(uint32)x) +#define SEXT16(x) (x&0x8000?(uint32)(((uint32)x&RMASK)|LMASK):(uint32)x) /* sign extend 16 bit value to uint64 */ -#define DSEXT16(x) (x&0x8000?(l_uint64)(((l_uint64)x&RMASK)|D48LMASK):(t_uint64)x) +#define DSEXT16(x) (x&0x8000?(l_uint64)(((l_uint64)x&RMASK)|D48LMASK):(t_uint64)x) /* sign extend 32 bit value to uint64 */ -#define DSEXT32(x) (x&0x8000?(l_uint64)(((l_uint64)x&D32RMASK)|D32LMASK):(t_uint64)x) +#define DSEXT32(x) (x&0x8000?(l_uint64)(((l_uint64)x&D32RMASK)|D32LMASK):(t_uint64)x) #define UNIT_V_MODEL (UNIT_V_UF + 0) #define UNIT_MODEL (7 << UNIT_V_MODEL) @@ -257,7 +257,7 @@ extern DEBTAB dev_debug[]; #define UNIT_V_MSIZE (UNIT_V_MODEL + 3) #define UNIT_MSIZE (0x1F << UNIT_V_MSIZE) #define MEMAMOUNT(x) (x << UNIT_V_MSIZE) -#define CPU_MODEL ((cpu_unit.flags >> UNIT_V_MODEL) & 0x7) /* cpu model 0-7 */ +#define CPU_MODEL ((cpu_unit.flags >> UNIT_V_MODEL) & 0x7) /* cpu model 0-7 */ #define MODEL_55 0 /* 512K Mode Only */ #define MODEL_75 1 /* Extended */ @@ -275,75 +275,75 @@ extern DEBTAB dev_debug[]; #define HIST_PC 0x80000000 /* CC defs Held in CC */ -#define CC1BIT 0x40000000 /* CC1 in PSD1 */ -#define CC2BIT 0x20000000 /* CC2 in PSD1 */ -#define CC3BIT 0x10000000 /* CC3 in PSD1 */ -#define CC4BIT 0x08000000 /* CC4 in PSD1 */ +#define CC1BIT 0x40000000 /* CC1 in PSD1 */ +#define CC2BIT 0x20000000 /* CC2 in PSD1 */ +#define CC3BIT 0x10000000 /* CC3 in PSD1 */ +#define CC4BIT 0x08000000 /* CC4 in PSD1 */ -#define MAPMODE 0x40 /* Map mode, PSD 2 bit 0 */ -#define RETMODE 0x20 /* Retain current maps, PSD 2 bit 15 */ -#define BLKMODE 0x10 /* Set blocked mode, PSD 2 bit 17 */ -#define RETBLKM 0x08 /* Set retain blocked mode, PSD 2 bit 16 */ +#define MAPMODE 0x40 /* Map mode, PSD 2 bit 0 */ +#define RETMODE 0x20 /* Retain current maps, PSD 2 bit 15 */ +#define BLKMODE 0x10 /* Set blocked mode, PSD 2 bit 17 */ +#define RETBLKM 0x08 /* Set retain blocked mode, PSD 2 bit 16 */ /* PSD mode bits in PSD words 1&2 variable */ -#define PRIVBIT 0x80000000 /* Privileged mode PSD 1 bit 0 */ -#define EXTDBIT 0x04000000 /* Extended Addressing PSD 1 bit 5 */ -#define BASEBIT 0x02000000 /* Base Mode PSD 1 bit 6 */ -#define AEXPBIT 0x01000000 /* Arithmetic exception PSD 1 bit 7 */ +#define PRIVBIT 0x80000000 /* Privileged mode PSD 1 bit 0 */ +#define EXTDBIT 0x04000000 /* Extended Addressing PSD 1 bit 5 */ +#define BASEBIT 0x02000000 /* Base Mode PSD 1 bit 6 */ +#define AEXPBIT 0x01000000 /* Arithmetic exception PSD 1 bit 7 */ -#define BLKEDBIT 0x00004000 /* Set blocked mode, PSD 2 bit 17 */ -#define RETBBIT 0x00008000 /* Retain current blocking state, PSD 2 bit 16 */ -#define RETMBIT 0x00010000 /* Retain current maps, PSD 2 bit 15 */ -#define MAPBIT 0x80000000 /* Map mode, PSD 2 bit 0 */ +#define BLKEDBIT 0x00004000 /* Set blocked mode, PSD 2 bit 17 */ +#define RETBBIT 0x00008000 /* Retain current blocking state, PSD 2 bit 16 */ +#define RETMBIT 0x00010000 /* Retain current maps, PSD 2 bit 15 */ +#define MAPBIT 0x80000000 /* Map mode, PSD 2 bit 0 */ /* Trap Table Address in memory is pointed to by SPAD 0xF0 */ -#define POWERFAIL_TRAP 0x80 /* Power fail trap */ -#define POWERON_TRAP 0x84 /* Power-On trap */ -#define MEMPARITY_TRAP 0x88 /* Memory Parity Error trap */ -#define NONPRESMEM_TRAP 0x8C /* Non Present Memory trap */ -#define UNDEFINSTR_TRAP 0x90 /* Undefined Instruction Trap */ -#define PRIVVIOL_TRAP 0x94 /* Privlege Violation Trap */ -#define SVCCALL_TRAP 0x98 /* Supervisor Call Trap */ -#define MACHINECHK_TRAP 0x9C /* Machine Check Trap */ -#define SYSTEMCHK_TRAP 0xA0 /* System Check Trap */ -#define MAPFAULT_TRAP 0xA4 /* Map Fault Trap */ -#define IPUUNDEFI_TRAP 0xA8 /* IPU Undefined Instruction Trap */ -#define SIGNALIPU_TRAP 0xAC /* Signal IPU/CPU Trap */ -#define ADDRSPEC_TRAP 0xB0 /* Address Specification Trap */ -#define CONSOLEATN_TRAP 0xB4 /* Console Attention Trap */ -#define PRIVHALT_TRAP 0xB8 /* Privlege Mode Halt Trap */ -#define AEXPCEPT_TRAP 0xBC /* Arithmetic Exception Trap */ +#define POWERFAIL_TRAP 0x80 /* Power fail trap */ +#define POWERON_TRAP 0x84 /* Power-On trap */ +#define MEMPARITY_TRAP 0x88 /* Memory Parity Error trap */ +#define NONPRESMEM_TRAP 0x8C /* Non Present Memory trap */ +#define UNDEFINSTR_TRAP 0x90 /* Undefined Instruction Trap */ +#define PRIVVIOL_TRAP 0x94 /* Privlege Violation Trap */ +#define SVCCALL_TRAP 0x98 /* Supervisor Call Trap */ +#define MACHINECHK_TRAP 0x9C /* Machine Check Trap */ +#define SYSTEMCHK_TRAP 0xA0 /* System Check Trap */ +#define MAPFAULT_TRAP 0xA4 /* Map Fault Trap */ +#define IPUUNDEFI_TRAP 0xA8 /* IPU Undefined Instruction Trap */ +#define SIGNALIPU_TRAP 0xAC /* Signal IPU/CPU Trap */ +#define ADDRSPEC_TRAP 0xB0 /* Address Specification Trap */ +#define CONSOLEATN_TRAP 0xB4 /* Console Attention Trap */ +#define PRIVHALT_TRAP 0xB8 /* Privlege Mode Halt Trap */ +#define AEXPCEPT_TRAP 0xBC /* Arithmetic Exception Trap */ /* Errors returned from various functions */ -#define ALLOK 0x0000 /* no error, all is OK */ -#define MAPFLT MAPFAULT_TRAP /* map fault error */ -#define NPMEM NONPRESMEM_TRAP /* non present memory */ -#define MPVIOL PRIVVIOL_TRAP /* memory protection violation */ +#define ALLOK 0x0000 /* no error, all is OK */ +#define MAPFLT MAPFAULT_TRAP /* map fault error */ +#define NPMEM NONPRESMEM_TRAP /* non present memory */ +#define MPVIOL PRIVVIOL_TRAP /* memory protection violation */ /* general instruction decode equates */ -#define IND 0x00100000 /* indirect bit in instruction, bit 11 */ -#define F_BIT 0x00080000 /* byte flag addressing bit 11 in instruction */ -#define C_BITS 0x00000003 /* byte number or hw, dw, dw flags bits 20 & 31 */ -#define BIT0 0x80000000 /* general use for bit 0 testing */ -#define BIT1 0x40000000 /* general use for bit 1 testing */ -#define MASK16 0x0000FFFF /* 16 bit address mask */ -#define MASK19 0x0007FFFF /* 19 bit address mask */ -#define MASK20 0x000FFFFF /* 20 bit address mask */ -#define MASK24 0x00FFFFFF /* 24 bit address mask */ -#define MASK32 0xFFFFFFFF /* 32 bit address mask */ +#define IND 0x00100000 /* indirect bit in instruction, bit 11 */ +#define F_BIT 0x00080000 /* byte flag addressing bit 11 in instruction */ +#define C_BITS 0x00000003 /* byte number or hw, dw, dw flags bits 20 & 31 */ +#define BIT0 0x80000000 /* general use for bit 0 testing */ +#define BIT1 0x40000000 /* general use for bit 1 testing */ +#define MASK16 0x0000FFFF /* 16 bit address mask */ +#define MASK19 0x0007FFFF /* 19 bit address mask */ +#define MASK20 0x000FFFFF /* 20 bit address mask */ +#define MASK24 0x00FFFFFF /* 24 bit address mask */ +#define MASK32 0xFFFFFFFF /* 32 bit address mask */ /* SPAD int entry equates, entries accessed by interrupt level number */ -#define SINT_RAML 0x80000000 /* ram loaded (n/u) */ -#define SINT_EWCS 0x40000000 /* Enabled channel WCS executed (XIO) */ -#define SINT_ACT 0x20000000 /* Interrupt active when set (copy is in INTS */ -#define SINT_ENAB 0x10000000 /* Interrupt enabled when set (copy is in INTS */ -#define SINT_EXTL 0x08000000 /* IOP/RTOM ext interrupt if set, I/O if not set (copy in INTS) */ +#define SINT_RAML 0x80000000 /* ram loaded (n/u) */ +#define SINT_EWCS 0x40000000 /* Enabled channel WCS executed (XIO) */ +#define SINT_ACT 0x20000000 /* Interrupt active when set (copy is in INTS */ +#define SINT_ENAB 0x10000000 /* Interrupt enabled when set (copy is in INTS */ +#define SINT_EXTL 0x08000000 /* IOP/RTOM ext interrupt if set, I/O if not set (copy in INTS) */ /* INTS int entry equates, entries accessed by interrupt level number */ -#define INTS_NU1 0x80000000 /* Not used */ -#define INTS_NU2 0x40000000 /* Not used */ -#define INTS_ACT 0x20000000 /* Interrupt active when set (copy is of SPAD */ -#define INTS_ENAB 0x10000000 /* Interrupt enabled when set (copy is of SPAD */ -#define INTS_EXTL 0x08000000 /* IOP/RTOM ext interrupt if set, I/O if not set (copy of SPAD) */ -#define INTS_REQ 0x04000000 /* Interrupt is requesting */ +#define INTS_NU1 0x80000000 /* Not used */ +#define INTS_NU2 0x40000000 /* Not used */ +#define INTS_ACT 0x20000000 /* Interrupt active when set (copy is of SPAD */ +#define INTS_ENAB 0x10000000 /* Interrupt enabled when set (copy is of SPAD */ +#define INTS_EXTL 0x08000000 /* IOP/RTOM ext interrupt if set, I/O if not set (copy of SPAD) */ +#define INTS_REQ 0x04000000 /* Interrupt is requesting */ diff --git a/SEL32/sel32_disk.c b/SEL32/sel32_disk.c index b1490d0..8b52b86 100644 --- a/SEL32/sel32_disk.c +++ b/SEL32/sel32_disk.c @@ -32,8 +32,8 @@ extern void set_devattn(uint16 addr, uint8 flags); extern t_stat chan_boot(uint16 addr, DEVICE *dptr); extern int test_write_byte_end(uint16 chsa); -extern uint32 M[]; /* our memory */ -extern uint32 SPAD[]; /* cpu SPAD memory */ +extern uint32 M[]; /* our memory */ +extern uint32 SPAD[]; /* cpu SPAD memory */ #ifdef NUM_DEVS_DISK #define UNIT_V_TYPE (UNIT_V_UF + 0) @@ -60,13 +60,13 @@ WD 8 Drive 7 Attribute register Memory attribute register layout bits 0-7 - Flags - bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option - bit 2 - 1=Cartridge module drive - bit 3 - 0=Reserved - bit 4 - 1=Drive not present - bit 5 - 1=Dual Port - bit 6 - 0=Reserved - bit 7 - 0=Reserved + bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option + bit 2 - 1=Cartridge module drive + bit 3 - 0=Reserved + bit 4 - 1=Drive not present + bit 5 - 1=Dual Port + bit 6 - 0=Reserved + bit 7 - 0=Reserved bits 8-15 - sector count (sectors per track)(F16=16, F20=20) bits 16-23 - MHD Head count (number of heads on MHD) bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option of mini-module) @@ -118,9 +118,9 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option /* u4 - sector target address register (STAR) */ /* Holds the current cylinder, head(track), sector */ -#define DISK_CYL 0xFFFF0000 /* cylinder mask */ -#define DISK_TRACK 0x0000FF00 /* track mask */ -#define DISK_SECTOR 0x000000ff /* sector mask */ +#define DISK_CYL 0xFFFF0000 /* cylinder mask */ +#define DISK_TRACK 0x0000FF00 /* track mask */ +#define DISK_SECTOR 0x000000ff /* sector mask */ /* u5 */ /* Sense byte 0 - mode register */ @@ -168,13 +168,13 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option /* provided by inch command for controller */ /* bits 0-7 - Flags - bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option - bit 2 - 1=Cartridge module drive - bit 3 - 0=Reserved - bit 4 - 1=Drive not present - bit 5 - 1=Dual Port - bit 6 - 0=Reserved - bit 7 - 0=Reserved + bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option + bit 2 - 1=Cartridge module drive + bit 3 - 0=Reserved + bit 4 - 1=Drive not present + bit 5 - 1=Dual Port + bit 6 - 0=Reserved + bit 7 - 0=Reserved bits 8-15 - sector count (sectors per track)(F16=16, F20=20) bits 16-23 - MHD Head count (number of heads on MHD) bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option of mini-module) @@ -185,62 +185,62 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option /* allocated during attach command for each unit defined */ struct ddata_t { - uint8 rbuf[1024]; /* read buffer, Sector buffer 768 or 1024 */ - uint8 wbuf[1024]; /* write buffer, Sector buffer 768 or 1024 */ - uint32 cpos; /* Position of head of cylinder in file */ - uint32 tstart; /* Location of start of cyl/track/sect in data */ - uint32 spare; /* drive register spare */ - uint16 tsize; /* Size of one track in byte */ - uint16 ssize; /* Size of one sector in bytes */ - uint16 ccyl; /* Current Cylinder number */ - uint16 cyl; /* Cylinder head at */ - uint16 tpos; /* Track position */ - uint16 spos; /* Sector position */ - uint16 dlen; /* remaining in data */ - uint16 rec; /* Current record number */ - uint16 count; /* Remaining in current operation */ + uint8 rbuf[1024]; /* read buffer, Sector buffer 768 or 1024 */ + uint8 wbuf[1024]; /* write buffer, Sector buffer 768 or 1024 */ + uint32 cpos; /* Position of head of cylinder in file */ + uint32 tstart; /* Location of start of cyl/track/sect in data */ + uint32 spare; /* drive register spare */ + uint16 tsize; /* Size of one track in byte */ + uint16 ssize; /* Size of one sector in bytes */ + uint16 ccyl; /* Current Cylinder number */ + uint16 cyl; /* Cylinder head at */ + uint16 tpos; /* Track position */ + uint16 spos; /* Sector position */ + uint16 dlen; /* remaining in data */ + uint16 rec; /* Current record number */ + uint16 count; /* Remaining in current operation */ }; /* disk definition structure */ struct disk_t { - char *name; /* Device ID Name */ - uint32 taus; /* total allocation units */ - uint16 bms; /* bit map size */ - uint16 nhds; /* Number of heads */ - uint16 ssiz; /* sector size in words */ - uint16 spt; /* # sectors per track(cylinder) */ - uint8 spau; /* # sectors per allocation unit */ - uint8 spb; /* # sectors per block (192 WDS)*/ - uint32 cyl; /* Number of cylinders */ - uint8 type; /* Device type code */ + char *name; /* Device ID Name */ + uint32 taus; /* total allocation units */ + uint16 bms; /* bit map size */ + uint16 nhds; /* Number of heads */ + uint16 ssiz; /* sector size in words */ + uint16 spt; /* # sectors per track(cylinder) */ + uint8 spau; /* # sectors per allocation unit */ + uint8 spb; /* # sectors per block (192 WDS)*/ + uint32 cyl; /* Number of cylinders */ + uint8 type; /* Device type code */ } disk_type[] = { - /* Class E Disc Devices */ - {"FE004", 5888, 184, 256, 192, 23, 1, 1, 1, 0x80}, /* 4 M */ - {"CE010", 12800, 200, 2, 96, 16, 1, 2, 400, 0x60}, /* 10 M */ - {"ME040", 23000, 719, 5, 192, 23, 2, 1, 400, 0x40}, /* 40 M */ - {"ME080", 46000, 1438, 5, 192, 23, 2, 1, 800, 0x40}, /* 80 M */ - {"ME300", 87400, 2732, 19, 192, 23, 4, 1, 800, 0x40}, /* 300 M */ - {"FE005", 5888, 184, 4, 192, 23, 1, 1, 64, 0x80}, /* 5 M */ + /* Class E Disc Devices */ + {"FE004", 5888, 184, 256, 192, 23, 1, 1, 1, 0x80}, /* 4 M */ + {"CE010", 12800, 200, 2, 96, 16, 1, 2, 400, 0x60}, /* 10 M */ + {"ME040", 23000, 719, 5, 192, 23, 2, 1, 400, 0x40}, /* 40 M */ + {"ME080", 46000, 1438, 5, 192, 23, 2, 1, 800, 0x40}, /* 80 M */ + {"ME300", 87400, 2732, 19, 192, 23, 4, 1, 800, 0x40}, /* 300 M */ + {"FE005", 5888, 184, 4, 192, 23, 1, 1, 64, 0x80}, /* 5 M */ - /* Class F Disc Devices */ - {"FL001", 1334, 0, 2, 64, 26, 3, 3, 26, 0x40}, /* 1 M */ - {"MH040", 20000, 625, 5, 192, 20, 2, 1, 40, 0x40}, /* 40 M */ - {"MH080", 40000, 1250, 5, 192, 20, 2, 1, 80, 0x40}, /* 80 M */ - {"MH300", 76000, 2375, 19, 192, 20, 4, 1, 800, 0x40}, /* 300 M */ - {"FH005", 5120, 184, 4, 192, 20, 1, 1, 64, 0x80}, /* 5 M */ - {"CD032", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /* 32 M */ - {"CD032", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /* 32 M */ - {"CD064", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /* 64 M */ - {"CD064", 24000, 750, 3, 192, 20, 2, 1, 800, 0x60}, /* 64 M */ - {"CD096", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /* 96 M */ - {"CD096", 40000, 1250, 5, 192, 20, 2, 1, 800, 0x60}, /* 96 M */ - {"MH600", 80000, 2500, 40, 192, 20, 8, 1, 80, 0x40}, /* 600 M */ - {"FM600", 80000, 2500, 40, 192, 20, 8, 1, 80, 0x40}, /* 600 M */ - {"FM600", 1600, 50, 40, 192, 20, 1, 1, 2, 0x80}, /* 600 M */ - {NULL, 0} + /* Class F Disc Devices */ + {"FL001", 1334, 0, 2, 64, 26, 3, 3, 26, 0x40}, /* 1 M */ + {"MH040", 20000, 625, 5, 192, 20, 2, 1, 40, 0x40}, /* 40 M */ + {"MH080", 40000, 1250, 5, 192, 20, 2, 1, 80, 0x40}, /* 80 M */ + {"MH300", 76000, 2375, 19, 192, 20, 4, 1, 800, 0x40}, /* 300 M */ + {"FH005", 5120, 184, 4, 192, 20, 1, 1, 64, 0x80}, /* 5 M */ + {"CD032", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /* 32 M */ + {"CD032", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /* 32 M */ + {"CD064", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /* 64 M */ + {"CD064", 24000, 750, 3, 192, 20, 2, 1, 800, 0x60}, /* 64 M */ + {"CD096", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /* 96 M */ + {"CD096", 40000, 1250, 5, 192, 20, 2, 1, 800, 0x60}, /* 96 M */ + {"MH600", 80000, 2500, 40, 192, 20, 8, 1, 80, 0x40}, /* 600 M */ + {"FM600", 80000, 2500, 40, 192, 20, 8, 1, 80, 0x40}, /* 600 M */ + {"FM600", 1600, 50, 40, 192, 20, 1, 1, 2, 0x80}, /* 600 M */ + {NULL, 0} }; #if 0 @@ -289,32 +289,32 @@ DID FORM 32, 8, 8, 8, 8, 16, 16, 32, 64 * #endif -uint8 disk_preio(UNIT *uptr, uint16 chan) ; -uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; -uint8 disk_haltio(uint16 addr); -t_stat disk_srv(UNIT *); -t_stat disk_boot(int32, DEVICE *); -void disk_ini(UNIT *, t_bool); -t_stat disk_reset(DEVICE *); -t_stat disk_attach(UNIT *, CONST char *); -t_stat disk_detach(UNIT *); -t_stat disk_set_type(UNIT * uptr, int32 val, CONST char *cptr, void *desc); -t_stat disk_get_type(FILE * st, UNIT * uptr, int32 v, CONST void *desc); -t_stat disk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); -const char *disk_description (DEVICE *dptr); +uint8 disk_preio(UNIT *uptr, uint16 chan) ; +uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; +uint8 disk_haltio(uint16 addr); +t_stat disk_srv(UNIT *); +t_stat disk_boot(int32, DEVICE *); +void disk_ini(UNIT *, t_bool); +t_stat disk_reset(DEVICE *); +t_stat disk_attach(UNIT *, CONST char *); +t_stat disk_detach(UNIT *); +t_stat disk_set_type(UNIT * uptr, int32 val, CONST char *cptr, void *desc); +t_stat disk_get_type(FILE * st, UNIT * uptr, int32 v, CONST void *desc); +t_stat disk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +const char *disk_description (DEVICE *dptr); /* channel program information */ -CHANP dda_chp[NUM_UNITS_DISK] = {0}; +CHANP dda_chp[NUM_UNITS_DISK] = {0}; -MTAB disk_mod[] = { - {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "TYPE", "TYPE", - &disk_set_type, &disk_get_type, NULL, "Type of disk"}, - {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, - &show_dev_addr, NULL}, - {0} +MTAB disk_mod[] = { + {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "TYPE", "TYPE", + &disk_set_type, &disk_get_type, NULL, "Type of disk"}, + {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, + &show_dev_addr, NULL}, + {0} }; -UNIT dda_unit[] = { +UNIT dda_unit[] = { /* SET_TYPE(9) DM300 */ {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(9), 0), 0, UNIT_ADDR(0x800)}, /* 0 */ {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(9), 0), 0, UNIT_ADDR(0x801)}, /* 1 */ @@ -328,24 +328,24 @@ UNIT dda_unit[] = { //DIB dda_dib = {NULL, disk_startcmd, NULL, NULL, disk_ini, dda_unit, dda_chp, NUM_UNITS_DISK, 0x0f, 0x0800, 0, 0, 0}; -DIB dda_dib = { - disk_preio, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre start I/O */ - disk_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ - NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ - NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ - disk_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ - dda_unit, /* UNIT* units */ /* Pointer to units structure */ - dda_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ - NUM_UNITS_DISK, /* uint8 numunits */ /* number of units defined */ - 0x0f, /* uint8 mask */ /* 16 devices - device mask */ - 0x0800, /* uint16 chan_addr */ /* parent channel address */ - 0, /* uint32 chan_fifo_in */ /* fifo input index */ - 0, /* uint32 chan_fifo_out */ /* fifo output index */ - 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ +DIB dda_dib = { + disk_preio, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre start I/O */ + disk_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ + NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ + NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ + disk_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ + dda_unit, /* UNIT* units */ /* Pointer to units structure */ + dda_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NUM_UNITS_DISK, /* uint8 numunits */ /* number of units defined */ + 0x0f, /* uint8 mask */ /* 16 devices - device mask */ + 0x0800, /* uint16 chan_addr */ /* parent channel address */ + 0, /* uint32 chan_fifo_in */ /* fifo input index */ + 0, /* uint32 chan_fifo_out */ /* fifo output index */ + 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ }; -DEVICE dda_dev = { +DEVICE dda_dev = { "DMA", dda_unit, NULL, disk_mod, NUM_UNITS_DISK, 16, 24, 4, 16, 32, NULL, NULL, &disk_reset, &disk_boot, &disk_attach, &disk_detach, @@ -356,9 +356,9 @@ DEVICE dda_dev = { #if NUM_DEVS_DISK > 1 /* channel program information */ -CHANP ddb_chp[NUM_UNITS_DISK] = {0}; +CHANP ddb_chp[NUM_UNITS_DISK] = {0}; -UNIT ddb_unit[] = { +UNIT ddb_unit[] = { /* SET_TYPE(9) DM300 */ {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(9), 0), 0, UNIT_ADDR(0xC00)}, /* 0 */ {UDATA(&disk_srv, UNIT_DISK|SET_TYPE(9), 0), 0, UNIT_ADDR(0xC01)}, /* 1 */ @@ -372,24 +372,24 @@ UNIT ddb_unit[] = { //DIB ddb_dib = {disk_startcmd, NULL, NULL, NULL, disk_ini, ddb_unit, ddb_chp, NUM_UNITS_DISK, 0x0f, 0x0C00, 0, 0, 0}; -DIB ddb_dib = { - disk_preio, /* uint8 (*start_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ - disk_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command SIO */ - NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O HIO */ - NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O TIO */ - NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ - disk_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ - ddb_unit, /* UNIT* units */ /* Pointer to units structure */ - ddb_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ - NUM_UNITS_DISK, /* uint8 numunits */ /* number of units defined */ - 0x0f, /* uint8 mask */ /* 16 devices - device mask */ - 0x0C00, /* uint16 chan_addr */ /* parent channel address */ - 0, /* uint32 chan_fifo_in */ /* fifo input index */ - 0, /* uint32 chan_fifo_out */ /* fifo output index */ - 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ +DIB ddb_dib = { + disk_preio, /* uint8 (*start_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ + disk_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command SIO */ + NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O HIO */ + NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O TIO */ + NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ + disk_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ + ddb_unit, /* UNIT* units */ /* Pointer to units structure */ + ddb_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NUM_UNITS_DISK, /* uint8 numunits */ /* number of units defined */ + 0x0f, /* uint8 mask */ /* 16 devices - device mask */ + 0x0C00, /* uint16 chan_addr */ /* parent channel address */ + 0, /* uint32 chan_fifo_in */ /* fifo input index */ + 0, /* uint32 chan_fifo_out */ /* fifo output index */ + 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ }; -DEVICE ddb_dev = { +DEVICE ddb_dev = { "DMB", ddb_unit, NULL, disk_mod, NUM_UNITS_DISK, 16, 24, 4, 16, 32, NULL, NULL, &disk_reset, &disk_boot, &disk_attach, &disk_detach, @@ -405,180 +405,180 @@ uint8 disk_preio(UNIT *uptr, uint16 chan) DEVICE *dptr = find_dev_from_unit(uptr); int unit = (uptr - dptr->units); - if ((uptr->u3 & 0xff00) != 0) { /* just return if busy */ - return SNS_BSY; - } + if ((uptr->u3 & 0xff00) != 0) { /* just return if busy */ + return SNS_BSY; + } - sim_debug(DEBUG_CMD, dptr, "dsk_preio unit=%d\n", unit); - return 0; /* good to go */ + sim_debug(DEBUG_CMD, dptr, "dsk_preio unit=%d\n", unit); + return 0; /* good to go */ } uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { - uint16 addr = GET_UADDR(uptr->u3); - DEVICE *dptr = find_dev_from_unit(uptr); - int unit = (uptr - dptr->units); - uint8 ch; + uint16 addr = GET_UADDR(uptr->u3); + DEVICE *dptr = find_dev_from_unit(uptr); + int unit = (uptr - dptr->units); + uint8 ch; - sim_debug(DEBUG_CMD, dptr, "disk_startcmd unit %d cmd %x u3 %x\n", unit, cmd, uptr->u3); - if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ - uptr->u5 |= SNS_INTVENT; /* unit intervention required */ - if (cmd != DSK_SNS) /* we are completed with unit check status */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - } + sim_debug(DEBUG_CMD, dptr, "disk_startcmd unit %d cmd %x u3 %x\n", unit, cmd, uptr->u3); + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + uptr->u5 |= SNS_INTVENT; /* unit intervention required */ + if (cmd != DSK_SNS) /* we are completed with unit check status */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + } - if ((uptr->u3 & DSK_CMDMSK) != 0) { - uptr->u3 |= DSK_BUSY; /* Flag we we are busy */ - return SNS_BSY; - } - if ((uptr->u3 & 0xff00) != 0) { /* if any status info, we are busy */ - return SNS_BSY; - } - sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD 2 unit=%d %02x\n", unit, cmd); + if ((uptr->u3 & DSK_CMDMSK) != 0) { + uptr->u3 |= DSK_BUSY; /* Flag we we are busy */ + return SNS_BSY; + } + if ((uptr->u3 & 0xff00) != 0) { /* if any status info, we are busy */ + return SNS_BSY; + } + sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD 2 unit=%d %02x\n", unit, cmd); - if ((uptr->flags & UNIT_ATT) == 0) { /* see if unit is attached */ - if (cmd == DSK_SNS) { /* not attached, is cmd Sense 0x04 */ + if ((uptr->flags & UNIT_ATT) == 0) { /* see if unit is attached */ + if (cmd == DSK_SNS) { /* not attached, is cmd Sense 0x04 */ dosns: - sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD sense\n"); - /* bytes 0,1 - Cyl entry from STAR reg in u4 */ - ch = (uptr->u4 >> 24) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b0 unit=%d 1 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - ch = (uptr->u4 >> 16) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b1 unit=%d 1 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - /* byte 2 - Track entry from STAR reg in u4 */ - ch = (uptr->u4 >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b2 unit=%d 1 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - /* byte 3 - Sector entry from STAR reg in u4 */ - ch = (uptr->u4) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b3 unit=%d 1 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - /* bytes 4 - mode reg, byte 0 of u5 */ - ch = (uptr->u5 >> 24) & 0xff; /* return the sense data for device */ - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%d 1 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - /* bytes 5-7 - status bytes, bytes 1-3 of u5 */ - ch = (uptr->u5 >> 16) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%d 2 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - ch = (uptr->u5 >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%d 3 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - ch = (uptr->u5) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%d 4 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - /* bytes 8-11 - drive attribute register (DATR) entries from uptr->u6 via INCH cmd */ - ch = (uptr->u6 >> 24) & 0xff; - chan_write_byte(addr, &ch) ; - ch = (uptr->u6 >> 16) & 0xff; - chan_write_byte(addr, &ch) ; - ch = (uptr->u6 >> 8 ) & 0xff; - chan_write_byte(addr, &ch) ; - ch = (uptr->u6 >> 0) & 0xff; - chan_write_byte(addr, &ch) ; - /* bytes 12 & 13 contain drive related status */ - ch = 0; /* zero for now */ - chan_write_byte(addr, &ch) ; - chan_write_byte(addr, &ch) ; + sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD sense\n"); + /* bytes 0,1 - Cyl entry from STAR reg in u4 */ + ch = (uptr->u4 >> 24) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b0 unit=%d 1 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + ch = (uptr->u4 >> 16) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b1 unit=%d 1 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + /* byte 2 - Track entry from STAR reg in u4 */ + ch = (uptr->u4 >> 8) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b2 unit=%d 1 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + /* byte 3 - Sector entry from STAR reg in u4 */ + ch = (uptr->u4) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense STAR b3 unit=%d 1 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + /* bytes 4 - mode reg, byte 0 of u5 */ + ch = (uptr->u5 >> 24) & 0xff; /* return the sense data for device */ + sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%d 1 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + /* bytes 5-7 - status bytes, bytes 1-3 of u5 */ + ch = (uptr->u5 >> 16) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%d 2 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + ch = (uptr->u5 >> 8) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%d 3 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + ch = (uptr->u5) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "disk_startcmd sense unit=%d 4 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + /* bytes 8-11 - drive attribute register (DATR) entries from uptr->u6 via INCH cmd */ + ch = (uptr->u6 >> 24) & 0xff; + chan_write_byte(addr, &ch) ; + ch = (uptr->u6 >> 16) & 0xff; + chan_write_byte(addr, &ch) ; + ch = (uptr->u6 >> 8 ) & 0xff; + chan_write_byte(addr, &ch) ; + ch = (uptr->u6 >> 0) & 0xff; + chan_write_byte(addr, &ch) ; + /* bytes 12 & 13 contain drive related status */ + ch = 0; /* zero for now */ + chan_write_byte(addr, &ch) ; + chan_write_byte(addr, &ch) ; - uptr->u5 &= 0xff000000; /* clear status bytes, but leave mode data */ - return SNS_CHNEND|SNS_DEVEND; - } - if (cmd == 0x0) /* INCH cmd gives unit check */ + uptr->u5 &= 0xff000000; /* clear status bytes, but leave mode data */ + return SNS_CHNEND|SNS_DEVEND; + } + if (cmd == 0x0) /* INCH cmd gives unit check */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - uptr->u5 |= (SNS_INTVENT|SNS_CMDREJ); /* set new error status */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* we done */ - } + uptr->u5 |= (SNS_INTVENT|SNS_CMDREJ); /* set new error status */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* we done */ + } - /* Unit is online, so process a command */ - switch (cmd) { + /* Unit is online, so process a command */ + switch (cmd) { - case DSK_INCH: /* INCH 0x00 */ - { - uint32 mema; /* memory address */ - int i; - UNIT *up = dptr->units; /* first unit for this device */ - sim_debug(DEBUG_CMD, dptr, "disk_startcmd starting inch cmd addr %x u4 %x\n", addr, uptr->u4); - /* u4 has IOCD word 1 contents. For the disk processor it contains */ - /* a pointer to the INCH buffer followed by 8 drive attribute words that */ - /* contains the flags, sector count, MHD head count, and FHD count */ - /* us9 has the byte count from IOCD wd2 and should be 0x24 (36) */ - /* the INCH buffer address must be returned in u4 and us9 left non-zero */ - /* just return OK and channel software will use up8 as status buffer */ - mema = (uint32)uptr->u4; /* get memory address of buffer */ - uptr->u4 = M[mema>>2]; /* get status buffer address for XIO return status */ - sim_debug(DEBUG_CMD, dptr, "disk_startcmd starting inch cmd addr %x u4 %x mema %x units %d\n", - addr, uptr->u4, mema, dptr->numunits); - /* the next 8 words have drive data for each unit */ - /* WARNING 8 drives must be defined for this controller */ - /* so we will not have a map fault */ - for (i=0; inumunits && i<8; i++) { /* process all drives */ - up->u6 = M[(mema>>2)+i+1]; /* save each unit's drive data */ - up++; /* next unit for this device */ - } - sim_debug(DEBUG_CMD, dptr, "disk_startcmd done inch cmd addr %x\n", addr); - return SNS_CHNEND|SNS_DEVEND; - break; - } + case DSK_INCH: /* INCH 0x00 */ + { + uint32 mema; /* memory address */ + int i; + UNIT *up = dptr->units; /* first unit for this device */ + sim_debug(DEBUG_CMD, dptr, "disk_startcmd starting inch cmd addr %x u4 %x\n", addr, uptr->u4); + /* u4 has IOCD word 1 contents. For the disk processor it contains */ + /* a pointer to the INCH buffer followed by 8 drive attribute words that */ + /* contains the flags, sector count, MHD head count, and FHD count */ + /* us9 has the byte count from IOCD wd2 and should be 0x24 (36) */ + /* the INCH buffer address must be returned in u4 and us9 left non-zero */ + /* just return OK and channel software will use up8 as status buffer */ + mema = (uint32)uptr->u4; /* get memory address of buffer */ + uptr->u4 = M[mema>>2]; /* get status buffer address for XIO return status */ + sim_debug(DEBUG_CMD, dptr, "disk_startcmd starting inch cmd addr %x u4 %x mema %x units %d\n", + addr, uptr->u4, mema, dptr->numunits); + /* the next 8 words have drive data for each unit */ + /* WARNING 8 drives must be defined for this controller */ + /* so we will not have a map fault */ + for (i=0; inumunits && i<8; i++) { /* process all drives */ + up->u6 = M[(mema>>2)+i+1]; /* save each unit's drive data */ + up++; /* next unit for this device */ + } + sim_debug(DEBUG_CMD, dptr, "disk_startcmd done inch cmd addr %x\n", addr); + return SNS_CHNEND|SNS_DEVEND; + break; + } - case DSK_SCK: /* Seek command 0x07 */ - case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ - uptr->u3 &= ~(DSK_STAR); /* show we do not have seek STAR in u4 */ - case DSK_WD: /* Write command 0x01 */ - case DSK_RD: /* Read command 0x02 */ - case DSK_LMR: /* read mode register */ + case DSK_SCK: /* Seek command 0x07 */ + case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ + uptr->u3 &= ~(DSK_STAR); /* show we do not have seek STAR in u4 */ + case DSK_WD: /* Write command 0x01 */ + case DSK_RD: /* Read command 0x02 */ + case DSK_LMR: /* read mode register */ - uptr->u3 |= cmd; /* save cmd */ - sim_debug(DEBUG_CMD, dptr, "disk_startcmd done with disk seek r/w cmd %x addr %x\n", cmd, addr); - sim_activate(uptr, 20); /* start things off */ - return 0; + uptr->u3 |= cmd; /* save cmd */ + sim_debug(DEBUG_CMD, dptr, "disk_startcmd done with disk seek r/w cmd %x addr %x\n", cmd, addr); + sim_activate(uptr, 20); /* start things off */ + return 0; - case DSK_NOP: /* NOP 0x03 */ - return SNS_CHNEND|SNS_DEVEND; /* return OK */ + case DSK_NOP: /* NOP 0x03 */ + return SNS_CHNEND|SNS_DEVEND; /* return OK */ - case DSK_SNS: /* Sense 0x04 */ - goto dosns; /* use code above */ - break; - } - sim_debug(DEBUG_CMD, dptr, "disk_startcmd done with disk_startcmd %x addr %x u5 %x\n", cmd, addr, uptr->u5); - if (uptr->u5 & 0xff) - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - sim_activate(uptr, 20); /* start things off */ - return SNS_CHNEND|SNS_DEVEND; + case DSK_SNS: /* Sense 0x04 */ + goto dosns; /* use code above */ + break; + } + sim_debug(DEBUG_CMD, dptr, "disk_startcmd done with disk_startcmd %x addr %x u5 %x\n", cmd, addr, uptr->u5); + if (uptr->u5 & 0xff) + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + sim_activate(uptr, 20); /* start things off */ + return SNS_CHNEND|SNS_DEVEND; } /* Handle processing of disk requests. */ t_stat disk_srv(UNIT * uptr) { - uint16 chsa = GET_UADDR(uptr->u3); - DEVICE *dptr = find_dev_from_unit(uptr); - DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to Dev Info Blk for this device */ - CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */ - struct ddata_t *data = (struct ddata_t *)(uptr->up7); - int cmd = uptr->u3 & DSK_CMDMSK; - int type = GET_TYPE(uptr->flags); - int count = data->count; - int trk, cyl; - int unit = (uptr - dptr->units); - int i; - uint8 ch; - uint8 buf2[768]; - uint8 buf[768]; + uint16 chsa = GET_UADDR(uptr->u3); + DEVICE *dptr = find_dev_from_unit(uptr); + DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to Dev Info Blk for this device */ + CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */ + struct ddata_t *data = (struct ddata_t *)(uptr->up7); + int cmd = uptr->u3 & DSK_CMDMSK; + int type = GET_TYPE(uptr->flags); + int count = data->count; + int trk, cyl; + int unit = (uptr - dptr->units); + int i; + uint8 ch; + uint8 buf2[768]; + uint8 buf[768]; - sim_debug(DEBUG_DETAIL, &dda_dev, "disk_srv entry unit %d cmd %x chsa %x chan %x count %x\n", - unit, cmd, chsa, chsa>>8, chp->ccw_count); + sim_debug(DEBUG_DETAIL, &dda_dev, "disk_srv entry unit %d cmd %x chsa %x chan %x count %x\n", + unit, cmd, chsa, chsa>>8, chp->ccw_count); - if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ - return SCPE_OK; - } - if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ - uptr->u5 |= SNS_INTVENT; /* unit intervention required */ - if (cmd != DSK_SNS) /* we are completed with unit check status */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - } + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + return SCPE_OK; + } + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + uptr->u5 |= SNS_INTVENT; /* unit intervention required */ + if (cmd != DSK_SNS) /* we are completed with unit check status */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + } sim_debug(DEBUG_CMD, dptr, "disk_srv cmd=%x chsa %04x count %x\n", cmd, chsa, chp->ccw_count); switch (cmd) { @@ -603,330 +603,330 @@ t_stat disk_srv(UNIT * uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case DSK_SCK: /* Seek cylinder, track, sector 0x07 */ + case DSK_SCK: /* Seek cylinder, track, sector 0x07 */ - /* If we are waiting on seek to finish, check if there yet. */ - if (uptr->u3 & DSK_SEEKING) { - /* see if on cylinder yet */ - if ((uptr->u4 >> 16) == data->cyl) { - /* we are on cylinder, seek is done */ - sim_debug(DEBUG_CMD, dptr, "dsk_srv seek on cylinder unit=%d %d %d\n", - unit, uptr->u4 >> 16, data->cyl); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - set_devattn(chsa, SNS_DEVEND); /* start the operation */ - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek end unit=%d %x %x\n", - unit, uptr->u4 >> 16, data->cyl); - sim_activate(uptr, 20); - break; - } else { - /* Compute delay based of difference. */ - /* Set next state = index */ - i = (uptr->u4 >> 16) - data->cyl; - sim_debug(DEBUG_CMD, dptr, "dsk_srv seek unit=%d %x %x\n", unit, uptr->u4 >> 16, i); - if (i > 0 ) { - if (i > 50) { - data->cyl += 50; /* seek 50 cyl */ - sim_activate(uptr, 800); - } else - if (i > 20) { - data->cyl += 20; /* seek 20 cyl */ - sim_activate(uptr, 400); - } else { - data->cyl++; /* Seek 1 cyl */ - sim_activate(uptr, 200); - } - if (data->cyl >= disk_type[type].cyl) /* test for over max */ - data->cyl = disk_type[type].cyl-1; /* make max */ - } else { - if (i < -50) { - data->cyl -= 50; /* seek 50 cyl */ - sim_activate(uptr, 800); - } else - if (i < -20) { - data->cyl -= 20; /* seek 20 cyl */ - sim_activate(uptr, 400); - } else { - data->cyl--; /* seek 1 cyl */ - sim_activate(uptr, 200); - } - if (data->cyl < 0) /* test for less than zero */ - data->cyl = 0; /* make zero */ - } - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek next unit=%d %d %d\n", unit, uptr->u4 >> 16, - data->cyl); - sim_activate(uptr, 2); - break; - } - } + /* If we are waiting on seek to finish, check if there yet. */ + if (uptr->u3 & DSK_SEEKING) { + /* see if on cylinder yet */ + if ((uptr->u4 >> 16) == data->cyl) { + /* we are on cylinder, seek is done */ + sim_debug(DEBUG_CMD, dptr, "dsk_srv seek on cylinder unit=%d %d %d\n", + unit, uptr->u4 >> 16, data->cyl); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + set_devattn(chsa, SNS_DEVEND); /* start the operation */ + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek end unit=%d %x %x\n", + unit, uptr->u4 >> 16, data->cyl); + sim_activate(uptr, 20); + break; + } else { + /* Compute delay based of difference. */ + /* Set next state = index */ + i = (uptr->u4 >> 16) - data->cyl; + sim_debug(DEBUG_CMD, dptr, "dsk_srv seek unit=%d %x %x\n", unit, uptr->u4 >> 16, i); + if (i > 0 ) { + if (i > 50) { + data->cyl += 50; /* seek 50 cyl */ + sim_activate(uptr, 800); + } else + if (i > 20) { + data->cyl += 20; /* seek 20 cyl */ + sim_activate(uptr, 400); + } else { + data->cyl++; /* Seek 1 cyl */ + sim_activate(uptr, 200); + } + if (data->cyl >= disk_type[type].cyl) /* test for over max */ + data->cyl = disk_type[type].cyl-1; /* make max */ + } else { + if (i < -50) { + data->cyl -= 50; /* seek 50 cyl */ + sim_activate(uptr, 800); + } else + if (i < -20) { + data->cyl -= 20; /* seek 20 cyl */ + sim_activate(uptr, 400); + } else { + data->cyl--; /* seek 1 cyl */ + sim_activate(uptr, 200); + } + if (data->cyl < 0) /* test for less than zero */ + data->cyl = 0; /* make zero */ + } + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek next unit=%d %d %d\n", unit, uptr->u4 >> 16, + data->cyl); + sim_activate(uptr, 2); + break; + } + } - /* not seeking, so start a new seek */ - /* Read in 4 character seek code */ - for (i = 0; i < 4; i++) { - if (chan_read_byte(chsa, &buf[i])) { - /* we have error, bail out */ - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - } + /* not seeking, so start a new seek */ + /* Read in 4 character seek code */ + for (i = 0; i < 4; i++) { + if (chan_read_byte(chsa, &buf[i])) { + /* we have error, bail out */ + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + } rezero: - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek unit=%d star %02d%02d %02d %02d\n", - unit, buf[0], buf[1], buf[2], buf[3]); - /* save STAR (target sector) data in u4 */ - uptr->u4 = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]); - cyl = uptr->u4 >> 16; /* get the cylinder */ - trk = buf[2]; /* get the track */ - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv SEEK cyl %d trk %d sec %d unit=%d\n", cyl&0xffff, trk, buf[3], unit); + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek unit=%d star %02d%02d %02d %02d\n", + unit, buf[0], buf[1], buf[2], buf[3]); + /* save STAR (target sector) data in u4 */ + uptr->u4 = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]); + cyl = uptr->u4 >> 16; /* get the cylinder */ + trk = buf[2]; /* get the track */ + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv SEEK cyl %d trk %d sec %d unit=%d\n", cyl&0xffff, trk, buf[3], unit); - /* FIXME do something with FHD here */ - /* Check if seek valid */ - if (cyl > disk_type[type].cyl || trk >= disk_type[type].nhds || buf[3] > disk_type[type].spt) { - sim_debug(DEBUG_CMD, dptr, "dsk_srv seek ERROR cyl %x trk %x sec %x unit=%d\n", cyl, trk, buf[3], unit); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; /* set error status */ + /* FIXME do something with FHD here */ + /* Check if seek valid */ + if (cyl > disk_type[type].cyl || trk >= disk_type[type].nhds || buf[3] > disk_type[type].spt) { + sim_debug(DEBUG_CMD, dptr, "dsk_srv seek ERROR cyl %x trk %x sec %x unit=%d\n", cyl, trk, buf[3], unit); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; /* set error status */ - /* we have an error, tell user */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* end command */ - break; - } + /* we have an error, tell user */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* end command */ + break; + } - uptr->u3 |= DSK_STAR; /* show we have seek STAR in u4 */ - /* calc the sector address of data */ - /* calculate file position in bytes of requested sector */ - data->tstart = (cyl * disk_type[type].nhds * data->tsize) + - (trk * data->tsize) + (buf[3] * 0x300); - data->tpos = trk; /* save the track/head number */ - data->spos = buf[3]; /* save the sector number */ - data->count = 0; /* no data seen yet */ - data->rec = 0; /* number of bytes in this sector */ - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek start %x trk %x sec %x\n", data->tstart, trk, buf[3]); - if ((sim_fseek(uptr->fileref, data->tstart, SEEK_SET)) != 0) { /* seek home */ - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv Error on seek to %x\n", data->tstart); - } + uptr->u3 |= DSK_STAR; /* show we have seek STAR in u4 */ + /* calc the sector address of data */ + /* calculate file position in bytes of requested sector */ + data->tstart = (cyl * disk_type[type].nhds * data->tsize) + + (trk * data->tsize) + (buf[3] * 0x300); + data->tpos = trk; /* save the track/head number */ + data->spos = buf[3]; /* save the sector number */ + data->count = 0; /* no data seen yet */ + data->rec = 0; /* number of bytes in this sector */ + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek start %x trk %x sec %x\n", data->tstart, trk, buf[3]); + if ((sim_fseek(uptr->fileref, data->tstart, SEEK_SET)) != 0) { /* seek home */ + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv Error on seek to %x\n", data->tstart); + } /* Check if already on correct cylinder */ if (trk != data->cyl) { - /* Do seek */ - uptr->u3 |= DSK_SEEKING; /* show we are seeking */ - sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek unit=%d trk %x cyl %x\n", unit, trk, data->cyl); - sim_activate(uptr, 20); - chan_end(chsa, SNS_CHNEND); - } else { - sim_debug(DEBUG_DETAIL, dptr, - "dsk_srv calc sect addr seek start %x trk %x sec %x\n", data->tstart, trk, buf[3]); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - sim_activate(uptr, 20); - chan_end(chsa, SNS_DEVEND|SNS_CHNEND); - } - return SCPE_OK; + /* Do seek */ + uptr->u3 |= DSK_SEEKING; /* show we are seeking */ + sim_debug(DEBUG_DETAIL, dptr, "dsk_srv seek unit=%d trk %x cyl %x\n", unit, trk, data->cyl); + sim_activate(uptr, 20); + chan_end(chsa, SNS_CHNEND); + } else { + sim_debug(DEBUG_DETAIL, dptr, + "dsk_srv calc sect addr seek start %x trk %x sec %x\n", data->tstart, trk, buf[3]); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + sim_activate(uptr, 20); + chan_end(chsa, SNS_DEVEND|SNS_CHNEND); + } + return SCPE_OK; - case DSK_XEZ: /* Rezero & Read IPL record */ + case DSK_XEZ: /* Rezero & Read IPL record */ - sim_debug(DEBUG_CMD, dptr, "RD REZERO IPL unit=%d seek 0\n", unit); - /* Do a seek to 0 */ - uptr->u4 = 0; /* set STAR to 0, 0, 0 */ - uptr->u3 &= ~(0xffff); /* remove old cmd */ - uptr->u3 |= DSK_SCK; /* show as seek command */ - data->tstart = 0; /* byte offset is 0 */ - data->dlen = 0; /* no data written yet */ - /* Read in 1 dummy character for length to inhibit SLI posting */ - if (chan_read_byte(chsa, &buf[0])) { - /* we have error, bail out */ - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - /* zero stuff */ - buf[0] = buf[1] = buf[2] = buf[3] = 0; - goto rezero; /* murge with seek code */ - break; + sim_debug(DEBUG_CMD, dptr, "RD REZERO IPL unit=%d seek 0\n", unit); + /* Do a seek to 0 */ + uptr->u4 = 0; /* set STAR to 0, 0, 0 */ + uptr->u3 &= ~(0xffff); /* remove old cmd */ + uptr->u3 |= DSK_SCK; /* show as seek command */ + data->tstart = 0; /* byte offset is 0 */ + data->dlen = 0; /* no data written yet */ + /* Read in 1 dummy character for length to inhibit SLI posting */ + if (chan_read_byte(chsa, &buf[0])) { + /* we have error, bail out */ + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + /* zero stuff */ + buf[0] = buf[1] = buf[2] = buf[3] = 0; + goto rezero; /* murge with seek code */ + break; - case DSK_LMR: - sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%d\n", unit); - /* Read in 1 character of mode data */ - if (chan_read_byte(chsa, &buf[0])) { - /* we have error, bail out */ - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - uptr->u3 &= ~(0xffff); /* remove old cmd */ - uptr->u5 &= 0x00ffffff; /* clear old mode data */ - uptr->u5 |= (buf[0] << 24); /* save mode value */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - break; + case DSK_LMR: + sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%d\n", unit); + /* Read in 1 character of mode data */ + if (chan_read_byte(chsa, &buf[0])) { + /* we have error, bail out */ + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + uptr->u3 &= ~(0xffff); /* remove old cmd */ + uptr->u5 &= 0x00ffffff; /* clear old mode data */ + uptr->u5 |= (buf[0] << 24); /* save mode value */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; - case DSK_RD: /* Read Data */ - /* data->tstart has start of sector address in bytes */ - if ((uptr->u3 & DSK_READING) == 0) { /* see if we are reading data */ - uptr->u3 |= DSK_READING; /* read from disk starting */ - data->dlen = 0; /* no data read yet */ - sim_debug(DEBUG_CMD, dptr, - "DISK READ starting unit=%d u3 %x count %d rec %d\n", unit, uptr->u3, count, data->rec); - } + case DSK_RD: /* Read Data */ + /* data->tstart has start of sector address in bytes */ + if ((uptr->u3 & DSK_READING) == 0) { /* see if we are reading data */ + uptr->u3 |= DSK_READING; /* read from disk starting */ + data->dlen = 0; /* no data read yet */ + sim_debug(DEBUG_CMD, dptr, + "DISK READ starting unit=%d u3 %x count %d rec %d\n", unit, uptr->u3, count, data->rec); + } - if (uptr->u3 & DSK_READING) { /* see if we are reading data */ - /* read in a sector of data from disk */ - if ((count=sim_fread(buf, 1, data->ssize, uptr->fileref)) != data->ssize) { - sim_debug(DEBUG_CMD, dptr, "Error %d on read %d of diskfile cyl %d hds %d sec %d\n", - count, data->ssize, data->cyl, data->tpos, data->spos); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ -// sim_activate(uptr, 20); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } + if (uptr->u3 & DSK_READING) { /* see if we are reading data */ + /* read in a sector of data from disk */ + if ((count=sim_fread(buf, 1, data->ssize, uptr->fileref)) != data->ssize) { + sim_debug(DEBUG_CMD, dptr, "Error %d on read %d of diskfile cyl %d hds %d sec %d\n", + count, data->ssize, data->cyl, data->tpos, data->spos); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ +// sim_activate(uptr, 20); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } - sim_debug(DEBUG_CMD, dptr, "disk_srv after READ chsa %04x count %x\n", chsa, chp->ccw_count); - /* process the next sector of data */ - data->rec = count; /* no bytes in sector yet */ - count = 0; /* used here as a flag for short write */ - for (i=0; i<(data->rec); i++) { - ch = buf[i]; /* get a char from buffer */ - if (chan_write_byte(chsa, &ch)) { /* put a byte to memory */ - sim_debug(DEBUG_DATAIO, dptr, - "DISK Read %d bytes from dskfile cyl %d hds %d sec %d tstart %x\r\n", - data->dlen+i, data->cyl, data->tpos, data->spos, data->tstart); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - goto rddone; } - } - data->dlen += data->rec; /* add byte read to total count */ + sim_debug(DEBUG_CMD, dptr, "disk_srv after READ chsa %04x count %x\n", chsa, chp->ccw_count); + /* process the next sector of data */ + data->rec = count; /* no bytes in sector yet */ + count = 0; /* used here as a flag for short write */ + for (i=0; i<(data->rec); i++) { + ch = buf[i]; /* get a char from buffer */ + if (chan_write_byte(chsa, &ch)) { /* put a byte to memory */ + sim_debug(DEBUG_DATAIO, dptr, + "DISK Read %d bytes from dskfile cyl %d hds %d sec %d tstart %x\r\n", + data->dlen+i, data->cyl, data->tpos, data->spos, data->tstart); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + goto rddone; } + } + data->dlen += data->rec; /* add byte read to total count */ - sim_debug(DEBUG_CMD, dptr, - "DISK READ from sec end %d bytes end %d from diskfile cyl %d hds %d sec %d tstart %x\n", - data->dlen, data->ssize, data->cyl, data->tpos, data->spos, data->tstart); - data->spos++; - /* set sector to read next one */ - if (data->spos >= (disk_type[type].spt)) { - data->spos = 0; /* number of sectors per track */ - data->tpos++; /* track position */ - if (data->tpos >= (disk_type[type].nhds)) { - data->tpos = 0; /* number of tracks per cylinder */ - data->cyl++; /* cylinder position */ - if (data->cyl >= (disk_type[type].cyl)) { - /* EOM reached, abort */ -// sim_debug(DEBUG_CMD, dptr, "Error %d on read %d from diskfile cyl %d hds %d sec %d\n", -// i, data->ssize, data->cyl, data->tpos, data->spos); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ -// sim_activate(uptr, 20); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - } - } - /* see if we are done reading data */ - if (test_write_byte_end(chsa)) { - sim_debug(DEBUG_DATAIO, dptr, - "DISK Read complete Read %d bytes from diskfile cyl %d hds %d sec %d tstart %x\n", - data->dlen, data->cyl, data->tpos, data->spos, data->tstart); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - } + sim_debug(DEBUG_CMD, dptr, + "DISK READ from sec end %d bytes end %d from diskfile cyl %d hds %d sec %d tstart %x\n", + data->dlen, data->ssize, data->cyl, data->tpos, data->spos, data->tstart); + data->spos++; + /* set sector to read next one */ + if (data->spos >= (disk_type[type].spt)) { + data->spos = 0; /* number of sectors per track */ + data->tpos++; /* track position */ + if (data->tpos >= (disk_type[type].nhds)) { + data->tpos = 0; /* number of tracks per cylinder */ + data->cyl++; /* cylinder position */ + if (data->cyl >= (disk_type[type].cyl)) { + /* EOM reached, abort */ +// sim_debug(DEBUG_CMD, dptr, "Error %d on read %d from diskfile cyl %d hds %d sec %d\n", +// i, data->ssize, data->cyl, data->tpos, data->spos); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ +// sim_activate(uptr, 20); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + } + } + /* see if we are done reading data */ + if (test_write_byte_end(chsa)) { + sim_debug(DEBUG_DATAIO, dptr, + "DISK Read complete Read %d bytes from diskfile cyl %d hds %d sec %d tstart %x\n", + data->dlen, data->cyl, data->tpos, data->spos, data->tstart); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + } rddone: -// sim_activate(uptr, 20); - sim_activate(uptr, 10); /* wait to read next sector */ - break; - } - break; +// sim_activate(uptr, 20); + sim_activate(uptr, 10); /* wait to read next sector */ + break; + } + break; - case DSK_WD: /* Write Data */ - /* data->tstart has start of sector address in bytes */ - if ((uptr->u3 & DSK_WRITING) == 0) { /* see if we are writing data */ - uptr->u3 |= DSK_WRITING; /* write to disk starting */ - data->dlen = 0; /* no data written yet */ - sim_debug(DEBUG_CMD, dptr, "DISK WRITE starting unit=%d u3 %x bytes %d rec %d\n", - unit, uptr->u3, data->dlen, data->rec); - } - if (uptr->u3 & DSK_WRITING) { /* see if we are writing data */ - /* process the next sector of data */ - data->rec = 0; /* no bytes in sector yet */ - count = 0; /* used here as a flag for short read */ - for (i=0; i<(data->ssize); i++) { - if (chan_read_byte(chsa, &ch)) { /* get a byte from memory */ - /* if error on reading 1st byte, we are done writing */ - if (i == 0) { - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - sim_debug(DEBUG_CMD, dptr, - "DISK Wrote %d bytes to diskfile cyl %d hds %d sec %d tstart %x\n", - data->dlen, data->cyl, data->tpos, data->spos, data->tstart); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - goto wrdone; - } - ch = 0; /* finish out the sector with zero */ - count++; /* show we have no more data to write */ - } - buf2[i] = ch; /* save the char */ - } - data->dlen += data->ssize; /* add 1 sector of bytes */ - /* write the sector to disk */ - if ((i=sim_fwrite(buf2, 1, data->ssize, uptr->fileref)) != data->ssize) { - sim_debug(DEBUG_CMD, dptr, "Error %d on write %d to diskfile cyl %d hds %d sec %d\n", - i, data->ssize, data->cyl, data->tpos, data->spos); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - if (count != 0) { /* see if done with write command */ - sim_debug(DEBUG_DATAIO, dptr, - "DISK WroteB %d bytes to diskfile cyl %d hds %d sec %d tstart %x\n", - data->dlen, data->cyl, data->tpos, data->spos, data->tstart); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ - break; - } - sim_debug(DEBUG_CMD, dptr, - "DISK WR to sec end %d bytes end %d to diskfile cyl %d hds %d sec %d tstart %x\n", - data->dlen, data->ssize, data->cyl, data->tpos, data->spos, data->tstart); - data->spos++; - if (data->spos >= (disk_type[type].spt)) { - data->spos = 0; /* number of sectors per track */ - data->tpos++; /* track position */ - if (data->tpos >= (disk_type[type].nhds)) { - data->tpos = 0; /* number of tracks per cylinder */ - data->cyl++; /* cylinder position */ - if (data->cyl >= (disk_type[type].cyl)) { - /* EOM reached, abort */ - sim_debug(DEBUG_DETAIL, dptr, "Error %d on write %d to diskfile cyl %d hds %d sec %d\n", - i, data->ssize, data->cyl, data->tpos, data->spos); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - } - } + case DSK_WD: /* Write Data */ + /* data->tstart has start of sector address in bytes */ + if ((uptr->u3 & DSK_WRITING) == 0) { /* see if we are writing data */ + uptr->u3 |= DSK_WRITING; /* write to disk starting */ + data->dlen = 0; /* no data written yet */ + sim_debug(DEBUG_CMD, dptr, "DISK WRITE starting unit=%d u3 %x bytes %d rec %d\n", + unit, uptr->u3, data->dlen, data->rec); + } + if (uptr->u3 & DSK_WRITING) { /* see if we are writing data */ + /* process the next sector of data */ + data->rec = 0; /* no bytes in sector yet */ + count = 0; /* used here as a flag for short read */ + for (i=0; i<(data->ssize); i++) { + if (chan_read_byte(chsa, &ch)) { /* get a byte from memory */ + /* if error on reading 1st byte, we are done writing */ + if (i == 0) { + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + sim_debug(DEBUG_CMD, dptr, + "DISK Wrote %d bytes to diskfile cyl %d hds %d sec %d tstart %x\n", + data->dlen, data->cyl, data->tpos, data->spos, data->tstart); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + goto wrdone; + } + ch = 0; /* finish out the sector with zero */ + count++; /* show we have no more data to write */ + } + buf2[i] = ch; /* save the char */ + } + data->dlen += data->ssize; /* add 1 sector of bytes */ + /* write the sector to disk */ + if ((i=sim_fwrite(buf2, 1, data->ssize, uptr->fileref)) != data->ssize) { + sim_debug(DEBUG_CMD, dptr, "Error %d on write %d to diskfile cyl %d hds %d sec %d\n", + i, data->ssize, data->cyl, data->tpos, data->spos); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (count != 0) { /* see if done with write command */ + sim_debug(DEBUG_DATAIO, dptr, + "DISK WroteB %d bytes to diskfile cyl %d hds %d sec %d tstart %x\n", + data->dlen, data->cyl, data->tpos, data->spos, data->tstart); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ + break; + } + sim_debug(DEBUG_CMD, dptr, + "DISK WR to sec end %d bytes end %d to diskfile cyl %d hds %d sec %d tstart %x\n", + data->dlen, data->ssize, data->cyl, data->tpos, data->spos, data->tstart); + data->spos++; + if (data->spos >= (disk_type[type].spt)) { + data->spos = 0; /* number of sectors per track */ + data->tpos++; /* track position */ + if (data->tpos >= (disk_type[type].nhds)) { + data->tpos = 0; /* number of tracks per cylinder */ + data->cyl++; /* cylinder position */ + if (data->cyl >= (disk_type[type].cyl)) { + /* EOM reached, abort */ + sim_debug(DEBUG_DETAIL, dptr, "Error %d on write %d to diskfile cyl %d hds %d sec %d\n", + i, data->ssize, data->cyl, data->tpos, data->spos); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + } + } wrdone: -// sim_activate(uptr, 20); - sim_activate(uptr, 10); - break; +// sim_activate(uptr, 20); + sim_activate(uptr, 10); + break; } break; - default: - sim_debug(DEBUG_DETAIL, dptr, "invalid command=%d %x\n", unit, cmd); - uptr->u5 |= SNS_CMDREJ; - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - sim_debug(DEBUG_DETAIL, dptr, "disk_srv done cmd=%x chsa %04x count %x\n", cmd, chsa, chp->ccw_count); - return SCPE_OK; + default: + sim_debug(DEBUG_DETAIL, dptr, "invalid command=%d %x\n", unit, cmd); + uptr->u5 |= SNS_CMDREJ; + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + sim_debug(DEBUG_DETAIL, dptr, "disk_srv done cmd=%x chsa %04x count %x\n", cmd, chsa, chp->ccw_count); + return SCPE_OK; } /* initialize the disk */ void disk_ini(UNIT *uptr, t_bool f) { - DEVICE *dptr = find_dev_from_unit(uptr); - int i = GET_TYPE(uptr->flags); + DEVICE *dptr = find_dev_from_unit(uptr); + int i = GET_TYPE(uptr->flags); - uptr->u3 &= ~0xffff; /* clear out the flags but leave ch/sa */ - /* capacity is tracks per allocation unit time sectors per allocation unit */ - uptr->capac = disk_type[i].taus * disk_type[i].spau; + uptr->u3 &= ~0xffff; /* clear out the flags but leave ch/sa */ + /* capacity is tracks per allocation unit time sectors per allocation unit */ + uptr->capac = disk_type[i].taus * disk_type[i].spau; - sim_debug(DEBUG_EXP, &dda_dev, "DMA init device %s on unit DMA%.1x cap %x\n", - dptr->name, GET_UADDR(uptr->u3), uptr->capac); + sim_debug(DEBUG_EXP, &dda_dev, "DMA init device %s on unit DMA%.1x cap %x\n", + dptr->name, GET_UADDR(uptr->u3), uptr->capac); } t_stat disk_reset(DEVICE * dptr) @@ -936,139 +936,139 @@ t_stat disk_reset(DEVICE * dptr) /* create the disk file for the specified device */ int disk_format(UNIT *uptr) { - struct ddata_t *data = (struct ddata_t *)uptr->up7; - uint16 addr = GET_UADDR(uptr->u3); - int type = GET_TYPE(uptr->flags); - DEVICE *dptr = find_dev_from_unit(uptr); - uint16 tsize = data->tsize; /* get track size in bytes */ - uint16 cyl; - uint16 hds; - uint16 spc = disk_type[type].nhds * disk_type[type].spt; /* sectors/cyl */ - uint8 *buff; + struct ddata_t *data = (struct ddata_t *)uptr->up7; + uint16 addr = GET_UADDR(uptr->u3); + int type = GET_TYPE(uptr->flags); + DEVICE *dptr = find_dev_from_unit(uptr); + uint16 tsize = data->tsize; /* get track size in bytes */ + uint16 cyl; + uint16 hds; + uint16 spc = disk_type[type].nhds * disk_type[type].spt; /* sectors/cyl */ + uint8 *buff; - /* see if user wants to initialize the disk */ + /* see if user wants to initialize the disk */ if (!get_yn("Initialize disk? [Y] ", TRUE)) { return 1; } - /* seek to sector 0 */ - if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ - fprintf(stderr, "Error on seek to 0\r\n"); - } + /* seek to sector 0 */ + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + fprintf(stderr, "Error on seek to 0\r\n"); + } - /* get buffer for track data */ - if ((buff = (uint8 *)calloc(tsize, sizeof(uint8))) == 0) { - detach_unit(uptr); - return SCPE_ARG; - } - sim_debug(DEBUG_CMD, dptr, "Creating disk file of capacity %d\n", - data->tsize * disk_type[type].cyl * disk_type[type].nhds); - /* write zeros to each track of the disk */ - for (cyl = 0; cyl < disk_type[type].cyl; cyl++) { - for (hds=0; hds < disk_type[type].nhds; hds++) { - if ((sim_fwrite(buff, 1, data->tsize, uptr->fileref)) != data->tsize) { - sim_debug(DEBUG_CMD, dptr, "Error on write to diskfile cyl %d hds %d\n", cyl, hds); - } - } - if ((cyl % 20) == 0) - fputc('.', stderr); - } - /* seek home again */ - sim_fseek(uptr->fileref, 0, SEEK_SET); /* seek home */ - free(buff); /* free cylinder buffer */ - data->cpos = 0; - data->ccyl = 0; - set_devattn(addr, SNS_DEVEND); /* start us up */ -// sim_activate(uptr, 100); - return 0; + /* get buffer for track data */ + if ((buff = (uint8 *)calloc(tsize, sizeof(uint8))) == 0) { + detach_unit(uptr); + return SCPE_ARG; + } + sim_debug(DEBUG_CMD, dptr, "Creating disk file of capacity %d\n", + data->tsize * disk_type[type].cyl * disk_type[type].nhds); + /* write zeros to each track of the disk */ + for (cyl = 0; cyl < disk_type[type].cyl; cyl++) { + for (hds=0; hds < disk_type[type].nhds; hds++) { + if ((sim_fwrite(buff, 1, data->tsize, uptr->fileref)) != data->tsize) { + sim_debug(DEBUG_CMD, dptr, "Error on write to diskfile cyl %d hds %d\n", cyl, hds); + } + } + if ((cyl % 20) == 0) + fputc('.', stderr); + } + /* seek home again */ + sim_fseek(uptr->fileref, 0, SEEK_SET); /* seek home */ + free(buff); /* free cylinder buffer */ + data->cpos = 0; + data->ccyl = 0; + set_devattn(addr, SNS_DEVEND); /* start us up */ +// sim_activate(uptr, 100); + return 0; } /* attach the selected file to the disk */ t_stat disk_attach(UNIT *uptr, CONST char *file) { - uint16 addr = GET_UADDR(uptr->u3); - int type = GET_TYPE(uptr->flags); - DEVICE *dptr = find_dev_from_unit(uptr); - t_stat r; - uint16 tsize; /* track size in bytes */ - uint16 ssize; /* sector size in bytes */ - struct ddata_t *data; - uint8 buff[1024]; -// int i; + uint16 addr = GET_UADDR(uptr->u3); + int type = GET_TYPE(uptr->flags); + DEVICE *dptr = find_dev_from_unit(uptr); + t_stat r; + uint16 tsize; /* track size in bytes */ + uint16 ssize; /* sector size in bytes */ + struct ddata_t *data; + uint8 buff[1024]; +// int i; - /* have simulator attach the file to the unit */ - if ((r = attach_unit(uptr, file)) != SCPE_OK) - return r; + /* have simulator attach the file to the unit */ + if ((r = attach_unit(uptr, file)) != SCPE_OK) + return r; - if (disk_type[type].name == 0) { /* does the assigned disk have a name */ - detach_unit(uptr); /* no, reject */ - return SCPE_FMT; /* error */ - } + if (disk_type[type].name == 0) { /* does the assigned disk have a name */ + detach_unit(uptr); /* no, reject */ + return SCPE_FMT; /* error */ + } - /* get a buffer to hold disk_t structure */ - /* extended data structure per unit */ - if ((data = (struct ddata_t *)calloc(1, sizeof(struct ddata_t))) == 0) { - detach_unit(uptr); - return SCPE_FMT; - } + /* get a buffer to hold disk_t structure */ + /* extended data structure per unit */ + if ((data = (struct ddata_t *)calloc(1, sizeof(struct ddata_t))) == 0) { + detach_unit(uptr); + return SCPE_FMT; + } - uptr->up7 = (void *)data; /* save pointer to structure in up7 */ - /* track size in bytes is sectors/track times words/sector time 4 bytse/word */ - tsize = disk_type[type].spt * disk_type[type].ssiz * 4; /* get track size in bytes */ - data->tsize = tsize; /* save size of track in bytes */ - uptr->capac = disk_type[type].taus * disk_type[type].spau; /* disk capacity in sectors */ - ssize = disk_type[type].ssiz * 4; /* disk sector size in bytes */ - uptr->capac *= ssize; /* disk capacity in bytes */ - data->ssize = ssize; /* save sector size bytes */ + uptr->up7 = (void *)data; /* save pointer to structure in up7 */ + /* track size in bytes is sectors/track times words/sector time 4 bytse/word */ + tsize = disk_type[type].spt * disk_type[type].ssiz * 4; /* get track size in bytes */ + data->tsize = tsize; /* save size of track in bytes */ + uptr->capac = disk_type[type].taus * disk_type[type].spau; /* disk capacity in sectors */ + ssize = disk_type[type].ssiz * 4; /* disk sector size in bytes */ + uptr->capac *= ssize; /* disk capacity in bytes */ + data->ssize = ssize; /* save sector size bytes */ - sim_debug(DEBUG_CMD, dptr, "Disk taus %d spau %d ssiz %d cap %d\n", - disk_type[type].taus, disk_type[type].spau, disk_type[type].ssiz * 4, uptr->capac); /* disk capacity */ + sim_debug(DEBUG_CMD, dptr, "Disk taus %d spau %d ssiz %d cap %d\n", + disk_type[type].taus, disk_type[type].spau, disk_type[type].ssiz * 4, uptr->capac); /* disk capacity */ - if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ - detach_unit(uptr); /* if no space, error */ - return SCPE_FMT; /* error */ - } + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ + } - /* read in the 1st sector of the 'disk' */ - if ((r = sim_fread(&buff[0], sizeof(uint8), ssize, uptr->fileref) != ssize)) { - sim_debug(DEBUG_CMD, &dda_dev, "Disk format fread ret = %x\n", r); - goto fmt; - } + /* read in the 1st sector of the 'disk' */ + if ((r = sim_fread(&buff[0], sizeof(uint8), ssize, uptr->fileref) != ssize)) { + sim_debug(DEBUG_CMD, &dda_dev, "Disk format fread ret = %x\n", r); + goto fmt; + } - if ((buff[0] | buff[1] | buff[2] | buff[3]) == 0) { - sim_debug(DEBUG_CMD, &dda_dev, "Disk format buf0 %x buf1 %x buf2 %x buf3 %x\n", - buff[0], buff[1], buff[2], buff[3]); + if ((buff[0] | buff[1] | buff[2] | buff[3]) == 0) { + sim_debug(DEBUG_CMD, &dda_dev, "Disk format buf0 %x buf1 %x buf2 %x buf3 %x\n", + buff[0], buff[1], buff[2], buff[3]); fmt: - /* format the drive */ - if (disk_format(uptr)) { - detach_unit(uptr); /* if no space, error */ - return SCPE_FMT; /* error */ - } - } + /* format the drive */ + if (disk_format(uptr)) { + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ + } + } - if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ - detach_unit(uptr); /* if no space, error */ - return SCPE_FMT; /* error */ - } + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ + } - data->ssize = ssize; /* save sector size in bytes */ - data->tsize = tsize; /* save track size in bytes */ - data->cpos = 0; /* current read/write position in cylinder*/ - data->ccyl = 0; /* current cylinder number */ - data->tpos = 0; /* current track position */ - data->spos = 0; /* current sector position */ - data->rec = 0; /* record length */ - data->count = 0; /* clear count value */ + data->ssize = ssize; /* save sector size in bytes */ + data->tsize = tsize; /* save track size in bytes */ + data->cpos = 0; /* current read/write position in cylinder*/ + data->ccyl = 0; /* current cylinder number */ + data->tpos = 0; /* current track position */ + data->spos = 0; /* current sector position */ + data->rec = 0; /* record length */ + data->count = 0; /* clear count value */ -// sim_debug(DEBUG_CMD, &dda_dev, "Attach %8s hds %d spt %d spc %d cyl %d capacity %d\n", -// disk_type[type].name, disk_type[type].nhds, disk_type[type].spt, -// disk_type[type].nhds * disk_type[type].spt, -// disk_type[type].cyl, uptr->capac); -// sim_debug(DEBUG_CMD, &dda_dev, "File %s attached to %s\r\n", file, disk_type[type].name); +// sim_debug(DEBUG_CMD, &dda_dev, "Attach %8s hds %d spt %d spc %d cyl %d capacity %d\n", +// disk_type[type].name, disk_type[type].nhds, disk_type[type].spt, +// disk_type[type].nhds * disk_type[type].spt, +// disk_type[type].cyl, uptr->capac); +// sim_debug(DEBUG_CMD, &dda_dev, "File %s attached to %s\r\n", file, disk_type[type].name); - set_devattn(addr, SNS_DEVEND); -// sim_activate(uptr, 100); - return SCPE_OK; + set_devattn(addr, SNS_DEVEND); +// sim_activate(uptr, 100); + return SCPE_OK; } /* detach a disk device */ @@ -1077,31 +1077,31 @@ t_stat disk_detach(UNIT * uptr) { if (data != 0) { #ifdef CALLOC_BUFF - free(data->cbuf); /* free cylinder buffer */ + free(data->cbuf); /* free cylinder buffer */ #endif - free(data); /* free disk data structure */ + free(data); /* free disk data structure */ } - uptr->up7 = 0; /* no pointer to disk data */ - uptr->u3 &= ~0xffff; /* no cmd and flags */ - return detach_unit(uptr); /* tell simh we are done with disk */ + uptr->up7 = 0; /* no pointer to disk data */ + uptr->u3 &= ~0xffff; /* no cmd and flags */ + return detach_unit(uptr); /* tell simh we are done with disk */ } /* boot from the specified disk unit */ t_stat disk_boot(int32 unit_num, DEVICE * dptr) { - UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */ + UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */ - sim_debug(DEBUG_CMD, &dda_dev, "Disk Boot dev/unit %x\n", GET_UADDR(uptr->u3)); - SPAD[0xf4] = GET_UADDR(uptr->u3); /* put boot device chan/sa into spad */ - SPAD[0xf8] = 0xF000; /* show as F class device */ - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_UNATT; /* attached? */ - return chan_boot(GET_UADDR(uptr->u3), dptr); /* boot the ch/sa */ + sim_debug(DEBUG_CMD, &dda_dev, "Disk Boot dev/unit %x\n", GET_UADDR(uptr->u3)); + SPAD[0xf4] = GET_UADDR(uptr->u3); /* put boot device chan/sa into spad */ + SPAD[0xf8] = 0xF000; /* show as F class device */ + if ((uptr->flags & UNIT_ATT) == 0) + return SCPE_UNATT; /* attached? */ + return chan_boot(GET_UADDR(uptr->u3), dptr); /* boot the ch/sa */ } /* Disk option setting commands */ t_stat disk_set_type(UNIT * uptr, int32 val, CONST char *cptr, void *desc) { - int i; + int i; if (cptr == NULL) return SCPE_ARG; @@ -1114,7 +1114,7 @@ t_stat disk_set_type(UNIT * uptr, int32 val, CONST char *cptr, void *desc) uptr->flags &= ~UNIT_TYPE; uptr->flags |= SET_TYPE(i); // uptr->capac = disk_type[i].bpt * disk_type[i].heads * disk_type[i].cyl; - uptr->capac = disk_type[i].taus * disk_type[i].spau; + uptr->capac = disk_type[i].taus * disk_type[i].spau; return SCPE_OK; } } @@ -1143,18 +1143,18 @@ t_stat disk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, for (i = 0; disk_type[i].name != 0; i++) { fprintf(st, "%s", disk_type[i].name); if (disk_type[i+1].name != 0) - fprintf(st, ", "); + fprintf(st, ", "); } - fprintf (st, ".\nEach drive has the following storage capacity:\r\n"); - for (i = 0; disk_type[i].name != 0; i++) { - int32 size = disk_type[i].taus * disk_type[i].spau; - size /= 1024; - size = (10 * size) / 1024; - fprintf(st, " %-8s %4d.%1dMB\r\n", disk_type[i].name, size/10, size%10); - } - fprint_set_help (st, dptr); - fprint_show_help (st, dptr); - return SCPE_OK; + fprintf (st, ".\nEach drive has the following storage capacity:\r\n"); + for (i = 0; disk_type[i].name != 0; i++) { + int32 size = disk_type[i].taus * disk_type[i].spau; + size /= 1024; + size = (10 * size) / 1024; + fprintf(st, " %-8s %4d.%1dMB\r\n", disk_type[i].name, size/10, size%10); + } + fprint_set_help (st, dptr); + fprint_show_help (st, dptr); + return SCPE_OK; } const char *disk_description (DEVICE *dptr) diff --git a/SEL32/sel32_mt.c b/SEL32/sel32_mt.c index bd94572..6cbd1e0 100644 --- a/SEL32/sel32_mt.c +++ b/SEL32/sel32_mt.c @@ -45,7 +45,7 @@ extern int chan_read_byte(uint16 chan, uint8 *data); extern int chan_write_byte(uint16 chan, uint8 *data); extern void set_devattn(uint16 addr, uint8 flags); extern t_stat chan_boot(uint16 addr, DEVICE *dptr); -extern uint32 SPAD[]; /* cpu SPAD */ +extern uint32 SPAD[]; /* cpu SPAD */ #ifdef NUM_DEVS_MT #define BUFFSIZE (64 * 1024) @@ -260,22 +260,22 @@ uint8 mt_busy[NUM_DEVS_MT]; /* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ /* Status Bits */ -/* Bit 00 - ECHO Halt I/O and Stop I/O function */ -/* Bit 01 - PCI Program Controlled Interrupt */ -/* Bit 02 - IL Incorrect Length */ -/* Bit 03 - CPC Channel Program Check */ -/* Bit 04 - CDC Channel Data Check */ -/* Bit 05 - CCC Channel Control Check */ -/* Bit 06 - IC Interface Check */ -/* Bit 07 - CHC Chaining Check */ -/* Bit 08 - DB Device Busy */ -/* Bit 09 - SM Status Modifier */ -/* Bit 10 - CNTE Controller End */ -/* Bit 11 - ATTN Attention */ -/* Bit 12 - CE Channel End */ -/* Bit 13 - DE Device End */ -/* Bit 14 - UC Unit Check */ -/* Bit 15 - UE Unit Exception */ +/* Bit 00 - ECHO Halt I/O and Stop I/O function */ +/* Bit 01 - PCI Program Controlled Interrupt */ +/* Bit 02 - IL Incorrect Length */ +/* Bit 03 - CPC Channel Program Check */ +/* Bit 04 - CDC Channel Data Check */ +/* Bit 05 - CCC Channel Control Check */ +/* Bit 06 - IC Interface Check */ +/* Bit 07 - CHC Chaining Check */ +/* Bit 08 - DB Device Busy */ +/* Bit 09 - SM Status Modifier */ +/* Bit 10 - CNTE Controller End */ +/* Bit 11 - ATTN Attention */ +/* Bit 12 - CE Channel End */ +/* Bit 13 - DE Device End */ +/* Bit 14 - UC Unit Check */ +/* Bit 15 - UE Unit Exception */ /* 41 Word Main memory channel buffer provided by INCH command */ /* when software is initializing the channel */ @@ -411,9 +411,9 @@ struct UNIT { #endif /* DEFINED_IN_SIM_DEFS_H */ UNIT mta_unit[] = { - /* Unit data layout for MT devices */ + /* Unit data layout for MT devices */ // {UDATA(&mt_srv, UNIT_MT, 0), 0, UNIT_ADDR(0x1000)}, /* 0 */ - { + { NULL, /* UNIT *next */ /* next active */ mt_srv, /* t_stat (*action) */ /* action routine */ NULL, /* char *filename */ /* open file name */ @@ -421,7 +421,7 @@ UNIT mta_unit[] = { NULL, /* void *filebuf */ /* memory buffer */ 0, /* uint32 hwmark */ /* high water mark */ 0, /* int32 time */ /* time out */ - UNIT_MT, /* uint32 flags */ /* flags */ + UNIT_MT, /* uint32 flags */ /* flags */ 0, /* uint32 dynflags */ /* dynamic flags */ 0, /* t_addr capac */ /* capacity */ 0, /* t_addr pos */ /* file position */ @@ -439,9 +439,9 @@ UNIT mta_unit[] = { 0, /* uint16 us10 */ /* device specific */ NULL, /* void *tmxr */ /* TMXR linkage */ NULL, /* t_bool(*cancel)(UNIT *) *//* Cancel I/O routine */ - 0, /* double usecs_remaining */ /* time balance for long delays */ + 0, /* double usecs_remaining */ /* time balance for long delays */ NULL, /* char *uname */ /* Unit name */ - }, + }, {UDATA(&mt_srv, UNIT_MT, 0), 0, UNIT_ADDR(0x1001)}, /* 1 */ {UDATA(&mt_srv, UNIT_MT, 0), 0, UNIT_ADDR(0x1002)}, /* 2 */ {UDATA(&mt_srv, UNIT_MT, 0), 0, UNIT_ADDR(0x1003)}, /* 3 */ @@ -454,33 +454,33 @@ UNIT mta_unit[] = { #if DEFINED_IN_SEL32_DEFS_H /* Device information block */ typedef struct dib { - /* Pre Start I/O */ - uint8 (*pre_io)(UNIT *uptr, uint16 chan); - /* Start a command */ - uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd); - /* Halt I/O */ - uint8 (*halt_io)(UNIT *uptr); - /* Test I/O */ - uint8 (*test_io)(UNIT *uptr); - /* Post I/O */ - uint8 (*post_io)(UNIT *uptr); - /* Controller init */ - void (*dev_ini)(UNIT *, t_bool); /* init function */ - UNIT *units; /* Pointer to units structure */ - CHANP *chan_prg; /* Pointer to channel program */ - uint8 numunits; /* number of units */ - uint8 mask; /* device mask */ - uint16 chan_addr; /* parent channel address */ - uint32 chan_fifo_in; /* fifo input index */ - uint32 chan_fifo_out; /* fifo output index */ - uint32 chan_fifo[FIFO_SIZE]; /* interrupt status fifo for each channel */ + /* Pre Start I/O */ + uint8 (*pre_io)(UNIT *uptr, uint16 chan); + /* Start a command */ + uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd); + /* Halt I/O */ + uint8 (*halt_io)(UNIT *uptr); + /* Test I/O */ + uint8 (*test_io)(UNIT *uptr); + /* Post I/O */ + uint8 (*post_io)(UNIT *uptr); + /* Controller init */ + void (*dev_ini)(UNIT *, t_bool); /* init function */ + UNIT *units; /* Pointer to units structure */ + CHANP *chan_prg; /* Pointer to channel program */ + uint8 numunits; /* number of units */ + uint8 mask; /* device mask */ + uint16 chan_addr; /* parent channel address */ + uint32 chan_fifo_in; /* fifo input index */ + uint32 chan_fifo_out; /* fifo output index */ + uint32 chan_fifo[FIFO_SIZE]; /* interrupt status fifo for each channel */ } DIB; /* CHAN 0x7F000000 UNIT 0x00ff0000 */ -#define DEV_V_ADDR DEV_V_UF /* Pointer to device address (16) */ -#define DEV_V_DADDR (DEV_V_UF + 8) /* Device address */ -#define DEV_ADDR_MASK (0x7f << DEV_V_DADDR) /* 24 bits shift */ -#define DEV_V_UADDR (DEV_V_UF) /* Device address in Unit */ +#define DEV_V_ADDR DEV_V_UF /* Pointer to device address (16) */ +#define DEV_V_DADDR (DEV_V_UF + 8) /* Device address */ +#define DEV_ADDR_MASK (0x7f << DEV_V_DADDR) /* 24 bits shift */ +#define DEV_V_UADDR (DEV_V_UF) /* Device address in Unit */ #define DEV_UADDR (1 << DEV_V_UADDR) #define GET_DADDR(x) (0x7f & ((x) >> DEV_V_ADDR)) #define DEV_ADDR(x) ((x) << DEV_V_ADDR) @@ -492,27 +492,27 @@ typedef struct dib { #endif /* channel program information */ -CHANP mta_chp[NUM_UNITS_MT] = {0}; +CHANP mta_chp[NUM_UNITS_MT] = {0}; //DIB mta_dib = {NULL, mt_startcmd, NULL, NULL, mt_ini, mta_unit, mta_chp, NUM_UNITS_MT, 0x0f, 0x1000, 0,0,0}; -DIB mta_dib = { - NULL, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ - mt_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ - NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ - NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ - mt_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ - mta_unit, /* UNIT* units */ /* Pointer to units structure */ - mta_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ - NUM_UNITS_MT, /* uint8 numunits */ /* number of units defined */ - 0xFF, /* uint8 mask */ /* 256 devices - device mask */ - 0x1000, /* uint16 chan_addr */ /* parent channel address */ - 0, /* uint32 chan_fifo_in */ /* fifo input index */ - 0, /* uint32 chan_fifo_out */ /* fifo output index */ - 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ +DIB mta_dib = { + NULL, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ + mt_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ + NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ + NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ + mt_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ + mta_unit, /* UNIT* units */ /* Pointer to units structure */ + mta_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NUM_UNITS_MT, /* uint8 numunits */ /* number of units defined */ + 0xFF, /* uint8 mask */ /* 256 devices - device mask */ + 0x1000, /* uint16 chan_addr */ /* parent channel address */ + 0, /* uint32 chan_fifo_in */ /* fifo input index */ + 0, /* uint32 chan_fifo_out */ /* fifo output index */ + 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ }; -DEVICE mta_dev = { +DEVICE mta_dev = { #if 0 "MTA", mta_unit, NULL, mt_mod, NUM_UNITS_MT, 16, 24, 4, 16, 32, @@ -544,15 +544,15 @@ DEVICE mta_dev = { NULL, /* t_stat (*help) */ /* help function */ NULL, /* t_stat (*attach_help) */ /* attach help function */ NULL, /* void *help_ctx */ /* Context available to help routines */ - NULL, /* cchar *(*description) */ /* Device description */ - NULL, /* BRKTYPTB *brk_types */ /* Breakpoint types */ + NULL, /* cchar *(*description) */ /* Device description */ + NULL, /* BRKTYPTB *brk_types */ /* Breakpoint types */ }; #if NUM_DEVS_MT > 1 /* channel program information */ -CHANP mtb_chp[NUM_UNITS_MT] = {0}; +CHANP mtb_chp[NUM_UNITS_MT] = {0}; -UNIT mtb_unit[] = { +UNIT mtb_unit[] = { {UDATA(&mt_srv, UNIT_MT, 0), 0, UNIT_ADDR(0x1800)}, /* 0 */ {UDATA(&mt_srv, UNIT_MT, 0), 0, UNIT_ADDR(0x1801)}, /* 1 */ {UDATA(&mt_srv, UNIT_MT, 0), 0, UNIT_ADDR(0x1802)}, /* 2 */ @@ -564,25 +564,25 @@ UNIT mtb_unit[] = { }; /* device information block */ -//DIB mtb_dib = { NULL, mt_startcmd, NULL, NULL, mt_ini, mtb_unit, mtb_chp, NUM_UNITS_MT, 0x0f, 0x1800, 0, 0, 0}; -DIB mtb_dib = { - NULL, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ - mt_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ - NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ - NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ - mt_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ - mtb_unit, /* UNIT* units */ /* Pointer to units structure */ - mtb_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ - NUM_UNITS_MT, /* uint8 numunits */ /* number of units defined */ - 0xFF, /* uint8 mask */ /* 256 devices - device mask */ - 0x1000, /* uint16 chan_addr */ /* parent channel address */ - 0, /* uint32 chan_fifo_in */ /* fifo input index */ - 0, /* uint32 chan_fifo_out */ /* fifo output index */ - 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ +//DIB mtb_dib = { NULL, mt_startcmd, NULL, NULL, mt_ini, mtb_unit, mtb_chp, NUM_UNITS_MT, 0x0f, 0x1800, 0, 0, 0}; +DIB mtb_dib = { + NULL, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ + mt_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ + NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ + NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ + mt_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ + mtb_unit, /* UNIT* units */ /* Pointer to units structure */ + mtb_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NUM_UNITS_MT, /* uint8 numunits */ /* number of units defined */ + 0xFF, /* uint8 mask */ /* 256 devices - device mask */ + 0x1000, /* uint16 chan_addr */ /* parent channel address */ + 0, /* uint32 chan_fifo_in */ /* fifo input index */ + 0, /* uint32 chan_fifo_out */ /* fifo output index */ + 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ }; -DEVICE mtb_dev = { +DEVICE mtb_dev = { "MTB", mtb_unit, NULL, mt_mod, NUM_UNITS_MT, 8, 15, 1, 8, 8, NULL, NULL, &mt_reset, &mt_boot, &mt_attach, &mt_detach, @@ -593,250 +593,250 @@ DEVICE mtb_dev = { /* start an I/O operation */ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { - DEVICE *dptr = find_dev_from_unit(uptr); - int unit = (uptr - dptr->units); + DEVICE *dptr = find_dev_from_unit(uptr); + int unit = (uptr - dptr->units); - sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd entry chan %x cmd %x\n", chan, cmd); + sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd entry chan %x cmd %x\n", chan, cmd); if (mt_busy[GET_DEV_BUF(dptr->flags)] != 0 || (uptr->u3 & MT_CMDMSK) != 0) { - sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd busy chan %d cmd %x\n", chan, cmd); - uptr->flags |= MT_BUSY; /* Flag we need to send CUE */ + sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd busy chan %d cmd %x\n", chan, cmd); + uptr->flags |= MT_BUSY; /* Flag we need to send CUE */ return SNS_BSY; } - sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd processing unit %x cmd %x\n", unit, cmd); + sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd processing unit %x cmd %x\n", unit, cmd); - switch (cmd & 0xF) { - case 0x0: /* INCH command */ - /* u4 has INCH buffer address and us9 the count */ - /* just return OK and channel software will use u4 as status buffer */ - return SNS_CHNEND|SNS_DEVEND; - break; + switch (cmd & 0xF) { + case 0x0: /* INCH command */ + /* u4 has INCH buffer address and us9 the count */ + /* just return OK and channel software will use u4 as status buffer */ + return SNS_CHNEND|SNS_DEVEND; + break; - case 0x3: /* Tape motion commands */ - if (cmd == MT_NOP) { /* nop */ - return SNS_CHNEND|SNS_DEVEND; /* done doing nothing */ - } - /* fall through */ - case 0x1: /* Write command */ - case 0x2: /* Read command */ - case 0xc: /* Read backward */ - uptr->u5 = (uptr->u5 & 0x0000ff00); /* clear all but byte 2 */ - uptr->u5 |= (SNS_RDY|SNS_ONLN); /* set ready status */ - if (sim_tape_wrp(uptr)) - uptr->u5 |= (SNS_WRP); /* write protected */ - if (sim_tape_bot(uptr)) - uptr->u5 |= (SNS_LOAD); /* tape at load point */ - if (sim_tape_eot(uptr)) { -// fprintf(stderr, "mt_startcmd EOT "); - uptr->u5 |= (SNS_EOT); /* tape at EOM */ - } - /* Fall through */ + case 0x3: /* Tape motion commands */ + if (cmd == MT_NOP) { /* nop */ + return SNS_CHNEND|SNS_DEVEND; /* done doing nothing */ + } + /* fall through */ + case 0x1: /* Write command */ + case 0x2: /* Read command */ + case 0xc: /* Read backward */ + uptr->u5 = (uptr->u5 & 0x0000ff00); /* clear all but byte 2 */ + uptr->u5 |= (SNS_RDY|SNS_ONLN); /* set ready status */ + if (sim_tape_wrp(uptr)) + uptr->u5 |= (SNS_WRP); /* write protected */ + if (sim_tape_bot(uptr)) + uptr->u5 |= (SNS_LOAD); /* tape at load point */ + if (sim_tape_eot(uptr)) { +// fprintf(stderr, "mt_startcmd EOT "); + uptr->u5 |= (SNS_EOT); /* tape at EOM */ + } + /* Fall through */ - case 0x4: /* Sense */ - uptr->u3 &= ~(MT_CMDMSK); /* clear out last cmd */ - uptr->u3 |= cmd & MT_CMDMSK; /* insert new cmd */ - sim_activate(uptr, 100); /* Start unit off */ - CLR_BUF(uptr); /* buffer is empty */ - uptr->u4 = 0; /* reset buffer position pointer */ - mt_busy[GET_DEV_BUF(dptr->flags)] = 1; /* show we are busy */ - if ((cmd & 0x3) == 0x3) { /* Quick end channel on control */ - if (cmd != MT_SETM) { /* mode set command */ - sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd ret CHNEND chan %x unit %x cmd %x\n", chan, unit, cmd); - return SNS_CHNEND; - } - } - sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd return 0 chan %x cmd %x\n", chan, cmd); - return 0; + case 0x4: /* Sense */ + uptr->u3 &= ~(MT_CMDMSK); /* clear out last cmd */ + uptr->u3 |= cmd & MT_CMDMSK; /* insert new cmd */ + sim_activate(uptr, 100); /* Start unit off */ + CLR_BUF(uptr); /* buffer is empty */ + uptr->u4 = 0; /* reset buffer position pointer */ + mt_busy[GET_DEV_BUF(dptr->flags)] = 1; /* show we are busy */ + if ((cmd & 0x3) == 0x3) { /* Quick end channel on control */ + if (cmd != MT_SETM) { /* mode set command */ + sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd ret CHNEND chan %x unit %x cmd %x\n", chan, unit, cmd); + return SNS_CHNEND; + } + } + sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd return 0 chan %x cmd %x\n", chan, cmd); + return 0; - default: /* invalid command */ - sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd CMDREJ return chan %d cmd %x\n", chan, cmd); - uptr->u5 |= SNS_CMDREJ; - break; - } - if (uptr->u5 & 0xff000000) /* errors? */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd ret CHNEND|DEVEND chan %d unit %x cmd %x\n", chan, unit, cmd); - return SNS_CHNEND|SNS_DEVEND; + default: /* invalid command */ + sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd CMDREJ return chan %d cmd %x\n", chan, cmd); + uptr->u5 |= SNS_CMDREJ; + break; + } + if (uptr->u5 & 0xff000000) /* errors? */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd ret CHNEND|DEVEND chan %d unit %x cmd %x\n", chan, unit, cmd); + return SNS_CHNEND|SNS_DEVEND; } /* Map simH errors into machine errors */ t_stat mt_error(UNIT *uptr, uint16 addr, t_stat r, DEVICE *dptr) { - sim_debug(DEBUG_CMD, &mta_dev, "mt_error status %x\n", r); - mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1; /* not busy anymore */ + sim_debug(DEBUG_CMD, &mta_dev, "mt_error status %x\n", r); + mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1; /* not busy anymore */ - switch (r) { /* switch on return value */ - case MTSE_OK: /* no error */ - break; + switch (r) { /* switch on return value */ + case MTSE_OK: /* no error */ + break; - case MTSE_TMK: /* tape mark */ - sim_debug(DEBUG_CMD, &mta_dev, "mt_error FILE MARK\n"); - uptr->u5 |= SNS_FMRKDT; /* file mark detected */ - break; + case MTSE_TMK: /* tape mark */ + sim_debug(DEBUG_CMD, &mta_dev, "mt_error FILE MARK\n"); + uptr->u5 |= SNS_FMRKDT; /* file mark detected */ + break; - case MTSE_WRP: /* write protected */ - uptr->u5 |= SNS_WRP; /* write protected */ - sim_debug(DEBUG_CMD, &mta_dev, "WRITE PROTECT %d ", r); /* operator intervention */ - break; + case MTSE_WRP: /* write protected */ + uptr->u5 |= SNS_WRP; /* write protected */ + sim_debug(DEBUG_CMD, &mta_dev, "WRITE PROTECT %d ", r); /* operator intervention */ + break; - case MTSE_UNATT: /* unattached */ - uptr->u5 |= SNS_INTVENT; /* unit intervention required */ - sim_debug(DEBUG_CMD, &mta_dev, "ATTENTION %d ", r); /* operator intervention */ - chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); - break; + case MTSE_UNATT: /* unattached */ + uptr->u5 |= SNS_INTVENT; /* unit intervention required */ + sim_debug(DEBUG_CMD, &mta_dev, "ATTENTION %d ", r); /* operator intervention */ + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); + break; - case MTSE_IOERR: /* IO error */ - case MTSE_FMT: /* invalid format */ - case MTSE_RECE: /* error in record */ - sim_debug(DEBUG_CMD, &mta_dev, "ERROR %d ", r); - break; + case MTSE_IOERR: /* IO error */ + case MTSE_FMT: /* invalid format */ + case MTSE_RECE: /* error in record */ + sim_debug(DEBUG_CMD, &mta_dev, "ERROR %d ", r); + break; - case MTSE_BOT: /* beginning of tape */ - uptr->u5 |= SNS_LOAD; /* tape at BOT */ - sim_debug(DEBUG_CMD, &mta_dev, "BOT "); - break; + case MTSE_BOT: /* beginning of tape */ + uptr->u5 |= SNS_LOAD; /* tape at BOT */ + sim_debug(DEBUG_CMD, &mta_dev, "BOT "); + break; - case MTSE_INVRL: /* invalid rec lnt */ - case MTSE_EOM: /* end of medium */ - uptr->u5 |= SNS_EOT; /* tape at EOT */ - sim_debug(DEBUG_CMD, &mta_dev, "EOT "); - break; - } - chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ - return SCPE_OK; + case MTSE_INVRL: /* invalid rec lnt */ + case MTSE_EOM: /* end of medium */ + uptr->u5 |= SNS_EOT; /* tape at EOT */ + sim_debug(DEBUG_CMD, &mta_dev, "EOT "); + break; + } + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ + return SCPE_OK; } /* Handle processing of tape requests. */ t_stat mt_srv(UNIT * uptr) { - uint16 addr = GET_UADDR(uptr->u3); - DEVICE *dptr = find_dev_from_unit(uptr); - int unit = (uptr - dptr->units); - int cmd = uptr->u3 & MT_CMDMSK; - int bufnum = GET_DEV_BUF(dptr->flags); - t_mtrlnt reclen; - t_stat r = SCPE_ARG; /* Force error if not set */ - uint8 ch; + uint16 addr = GET_UADDR(uptr->u3); + DEVICE *dptr = find_dev_from_unit(uptr); + int unit = (uptr - dptr->units); + int cmd = uptr->u3 & MT_CMDMSK; + int bufnum = GET_DEV_BUF(dptr->flags); + t_mtrlnt reclen; + t_stat r = SCPE_ARG; /* Force error if not set */ + uint8 ch; - sim_debug(DEBUG_DATA, &mta_dev, "mt_srv unit %d cmd %x\n", unit, cmd); - if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ - uptr->u5 |= SNS_INTVENT; /* unit intervention required */ - if (cmd != MT_SENSE) /* we are completed with unit check status */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - } + sim_debug(DEBUG_DATA, &mta_dev, "mt_srv unit %d cmd %x\n", unit, cmd); + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + uptr->u5 |= SNS_INTVENT; /* unit intervention required */ + if (cmd != MT_SENSE) /* we are completed with unit check status */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + } - switch (cmd) { - case MT_INCH: /* 0x00 */ /* INCH is for channel, nothing for us */ - sim_debug(DEBUG_CMD, &mta_dev, "mt_srv cmd 0 INCH unit=%d\n", unit); - //NEWCODE follows, but not ever executed! - uptr->u3 &= ~MT_CMDMSK; /* clear the cmd */ - mt_busy[bufnum] &= ~1; /* make our buffer not busy */ - chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ - break; + switch (cmd) { + case MT_INCH: /* 0x00 */ /* INCH is for channel, nothing for us */ + sim_debug(DEBUG_CMD, &mta_dev, "mt_srv cmd 0 INCH unit=%d\n", unit); + //NEWCODE follows, but not ever executed! + uptr->u3 &= ~MT_CMDMSK; /* clear the cmd */ + mt_busy[bufnum] &= ~1; /* make our buffer not busy */ + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ + break; - case MT_SENSE: /* 0x04 */ /* get sense data */ - sim_debug(DEBUG_CMD, &mta_dev, "mt_srv cmd 4 SENSE unit=%d\n", unit); - ch = (uptr->u5 >> 24) & 0xff; /* get sense byte 0 status */ - sim_debug(DEBUG_DETAIL, &mta_dev, "sense unit %d byte 0 %x\n", unit, ch); - chan_write_byte(addr, &ch); /* write byte 0 */ - ch = (uptr->u5 >> 16) & 0xff; /* get sense byte 1 status */ - sim_debug(DEBUG_DETAIL, &mta_dev, "sense unit %d byte 1 %x\n", unit, ch); - chan_write_byte(addr, &ch); /* write byte 1 */ - ch = (uptr->u5 >> 8) & 0xff; /* get sense byte 2 status */ - sim_debug(DEBUG_DETAIL, &mta_dev, "sense unit %d byte 2 %x\n", unit, ch); - chan_write_byte(addr, &ch); /* write byte 2 */ - ch = (uptr->u5 >> 0) & 0xff; /* get sense byte 3 status */ - sim_debug(DEBUG_DETAIL, &mta_dev, "sense unit %d byte 3 %x\n", unit, ch); - chan_write_byte(addr, &ch); /* write byte 3 */ - ch = 4; - uptr->u3 &= ~MT_CMDMSK; /* clear the cmd */ - mt_busy[bufnum] &= ~1; /* make our buffer not busy */ - chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ - break; + case MT_SENSE: /* 0x04 */ /* get sense data */ + sim_debug(DEBUG_CMD, &mta_dev, "mt_srv cmd 4 SENSE unit=%d\n", unit); + ch = (uptr->u5 >> 24) & 0xff; /* get sense byte 0 status */ + sim_debug(DEBUG_DETAIL, &mta_dev, "sense unit %d byte 0 %x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 0 */ + ch = (uptr->u5 >> 16) & 0xff; /* get sense byte 1 status */ + sim_debug(DEBUG_DETAIL, &mta_dev, "sense unit %d byte 1 %x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 1 */ + ch = (uptr->u5 >> 8) & 0xff; /* get sense byte 2 status */ + sim_debug(DEBUG_DETAIL, &mta_dev, "sense unit %d byte 2 %x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 2 */ + ch = (uptr->u5 >> 0) & 0xff; /* get sense byte 3 status */ + sim_debug(DEBUG_DETAIL, &mta_dev, "sense unit %d byte 3 %x\n", unit, ch); + chan_write_byte(addr, &ch); /* write byte 3 */ + ch = 4; + uptr->u3 &= ~MT_CMDMSK; /* clear the cmd */ + mt_busy[bufnum] &= ~1; /* make our buffer not busy */ + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ + break; - case MT_READ: /* 0x02 */ /* read a record from the device */ - sim_debug(DEBUG_DATA, &mta_dev, "mt_srv cmd 2 READ unit=%d\n", unit); - if (uptr->u3 & MT_READDONE) { /* is the read complete */ - uptr->u5 &= ~(SNS_LOAD|SNS_EOT); /* reset BOT & EOT */ - if (sim_tape_eot(uptr)) { /* see if at EOM */ - uptr->u5 |= SNS_EOT; /* set EOT status */ - } - uptr->u3 &= ~(MT_CMDMSK|MT_READDONE); /* clear all but readdone & cmd */ - mt_busy[bufnum] &= ~1; /* not busy anymore */ - sim_debug(DEBUG_CMD, &mta_dev, "mt_srv READ %x char complete unit=%d\n", uptr->u4, unit); - chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* set chan end, dev end status */ - break; - } - /* read is not completed, get an input char */ - /* If empty buffer, fill */ - if (BUF_EMPTY(uptr)) { - /* buffer is empty, so fill it with next record data */ - if ((r = sim_tape_rdrecf(uptr, &mt_buffer[bufnum][0], &reclen, BUFFSIZE)) != MTSE_OK) { - sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv READ fill buffer unit=%d\n", unit); - uptr->u3 &= ~(MT_CMDMSK|MT_READDONE); /* clear all but readdone & cmd */ - return mt_error(uptr, addr, r, dptr); /* process any error & return status */ - } - uptr->u4 = 0; /* reset buffer position */ - uptr->hwmark = reclen; /* set buffer chars read in */ - sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv READ fill buffer complete count %x\n", reclen); - } - /* get a char from the buffer */ - ch = mt_buffer[bufnum][uptr->u4++]; + case MT_READ: /* 0x02 */ /* read a record from the device */ + sim_debug(DEBUG_DATA, &mta_dev, "mt_srv cmd 2 READ unit=%d\n", unit); + if (uptr->u3 & MT_READDONE) { /* is the read complete */ + uptr->u5 &= ~(SNS_LOAD|SNS_EOT); /* reset BOT & EOT */ + if (sim_tape_eot(uptr)) { /* see if at EOM */ + uptr->u5 |= SNS_EOT; /* set EOT status */ + } + uptr->u3 &= ~(MT_CMDMSK|MT_READDONE); /* clear all but readdone & cmd */ + mt_busy[bufnum] &= ~1; /* not busy anymore */ + sim_debug(DEBUG_CMD, &mta_dev, "mt_srv READ %x char complete unit=%d\n", uptr->u4, unit); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* set chan end, dev end status */ + break; + } + /* read is not completed, get an input char */ + /* If empty buffer, fill */ + if (BUF_EMPTY(uptr)) { + /* buffer is empty, so fill it with next record data */ + if ((r = sim_tape_rdrecf(uptr, &mt_buffer[bufnum][0], &reclen, BUFFSIZE)) != MTSE_OK) { + sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv READ fill buffer unit=%d\n", unit); + uptr->u3 &= ~(MT_CMDMSK|MT_READDONE); /* clear all but readdone & cmd */ + return mt_error(uptr, addr, r, dptr); /* process any error & return status */ + } + uptr->u4 = 0; /* reset buffer position */ + uptr->hwmark = reclen; /* set buffer chars read in */ + sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv READ fill buffer complete count %x\n", reclen); + } + /* get a char from the buffer */ + ch = mt_buffer[bufnum][uptr->u4++]; - /* Send character over to channel */ - if (chan_write_byte(addr, &ch)) { - sim_debug(DEBUG_CMD, &mta_dev, "Read unit %d EOR\n", unit); - /* If not read whole record, skip till end */ - if (uptr->u4 < uptr->hwmark) { - /* Send dummy character to force SLI */ - chan_write_byte(addr, &ch); /* write the byte */ - sim_debug(DEBUG_CMD, &mta_dev, "Read unit %d send dump SLI\n", unit); - sim_activate(uptr, (uptr->hwmark-uptr->u4) * 20); /* wait again */ - uptr->u3 |= MT_READDONE; /* read is done */ - break; - } - sim_debug(DEBUG_CMD, &mta_dev, - "Read data @1 unit %d cnt %x ch %02x hwm %x\n", unit, uptr->u4, ch, uptr->hwmark); - uptr->u3 &= ~MT_CMDMSK; /* clear the cmd */ - mt_busy[bufnum] &= ~1; /* set not busy */ - chan_end(addr, SNS_DEVEND); /* return end status */ - } else { - sim_debug(DEBUG_DATA, &mta_dev, - "Read data @2 unit %d cnt %x ch %02x hwm %x\n", unit, uptr->u4, ch, uptr->hwmark); - if (uptr->u4 >= uptr->hwmark) { /* In IRG */ - /* Handle end of record */ - uptr->u3 &= ~MT_CMDMSK; /* clear the cmd */ - mt_busy[bufnum] &= ~1; /* set not busy */ - chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* return end status */ - } else - sim_activate(uptr, 20); /* wait again */ - } - break; + /* Send character over to channel */ + if (chan_write_byte(addr, &ch)) { + sim_debug(DEBUG_CMD, &mta_dev, "Read unit %d EOR\n", unit); + /* If not read whole record, skip till end */ + if (uptr->u4 < uptr->hwmark) { + /* Send dummy character to force SLI */ + chan_write_byte(addr, &ch); /* write the byte */ + sim_debug(DEBUG_CMD, &mta_dev, "Read unit %d send dump SLI\n", unit); + sim_activate(uptr, (uptr->hwmark-uptr->u4) * 20); /* wait again */ + uptr->u3 |= MT_READDONE; /* read is done */ + break; + } + sim_debug(DEBUG_CMD, &mta_dev, + "Read data @1 unit %d cnt %x ch %02x hwm %x\n", unit, uptr->u4, ch, uptr->hwmark); + uptr->u3 &= ~MT_CMDMSK; /* clear the cmd */ + mt_busy[bufnum] &= ~1; /* set not busy */ + chan_end(addr, SNS_DEVEND); /* return end status */ + } else { + sim_debug(DEBUG_DATA, &mta_dev, + "Read data @2 unit %d cnt %x ch %02x hwm %x\n", unit, uptr->u4, ch, uptr->hwmark); + if (uptr->u4 >= uptr->hwmark) { /* In IRG */ + /* Handle end of record */ + uptr->u3 &= ~MT_CMDMSK; /* clear the cmd */ + mt_busy[bufnum] &= ~1; /* set not busy */ + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* return end status */ + } else + sim_activate(uptr, 20); /* wait again */ + } + break; - case MT_SETM: /* 0x83 */ /* set mode byte */ - sim_debug(DEBUG_CMD, &mta_dev, "mt_srv cmd 0x83 SETM unit=%d\n", unit); - /* Grab data until channel has no more */ - if (chan_read_byte(addr, &ch)) { - if (uptr->u4 > 0) { /* Only if data in record */ - reclen = uptr->hwmark; /* set record length */ - ch = mt_buffer[bufnum][0]; /* get the first byte read */ - sim_debug(DEBUG_CMD, &mta_dev, "Write mode data done unit %d chars %d char %x\n", unit, reclen, ch); - /* put mode bits into byte 2 of u5 */ - uptr->u5 = (uptr->u5 & 0xffff00ff) | (ch << 8); - uptr->u4 = 0; /* no bytes anymore */ - uptr->u3 &= ~MT_CMDMSK; /* no cmd to do */ - mt_busy[bufnum] &= ~1; /* set not busy */ - chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* return end status */ - } - } else { - mt_buffer[bufnum][uptr->u4++] = ch; /* save the character read in */ - sim_debug(DEBUG_CMD, &mta_dev, "Write mode data in unit %d u4 %d ch %0x\n", unit, uptr->u4, ch); - uptr->hwmark = uptr->u4; /* set high water mark */ - sim_activate(uptr, 20); /* wait time */ - } - break; + case MT_SETM: /* 0x83 */ /* set mode byte */ + sim_debug(DEBUG_CMD, &mta_dev, "mt_srv cmd 0x83 SETM unit=%d\n", unit); + /* Grab data until channel has no more */ + if (chan_read_byte(addr, &ch)) { + if (uptr->u4 > 0) { /* Only if data in record */ + reclen = uptr->hwmark; /* set record length */ + ch = mt_buffer[bufnum][0]; /* get the first byte read */ + sim_debug(DEBUG_CMD, &mta_dev, "Write mode data done unit %d chars %d char %x\n", unit, reclen, ch); + /* put mode bits into byte 2 of u5 */ + uptr->u5 = (uptr->u5 & 0xffff00ff) | (ch << 8); + uptr->u4 = 0; /* no bytes anymore */ + uptr->u3 &= ~MT_CMDMSK; /* no cmd to do */ + mt_busy[bufnum] &= ~1; /* set not busy */ + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* return end status */ + } + } else { + mt_buffer[bufnum][uptr->u4++] = ch; /* save the character read in */ + sim_debug(DEBUG_CMD, &mta_dev, "Write mode data in unit %d u4 %d ch %0x\n", unit, uptr->u4, ch); + uptr->hwmark = uptr->u4; /* set high water mark */ + sim_activate(uptr, 20); /* wait time */ + } + break; - case MT_WRITE: /* 0x01 */ /* write record */ + case MT_WRITE: /* 0x01 */ /* write record */ /* Check if write protected */ if (sim_tape_wrp(uptr)) { uptr->u5 |= SNS_CMDREJ; @@ -848,24 +848,24 @@ t_stat mt_srv(UNIT * uptr) /* Grab data until channel has no more */ if (chan_read_byte(addr, &ch)) { - if (uptr->u4 > 0) { /* Only if data in record */ + if (uptr->u4 > 0) { /* Only if data in record */ reclen = uptr->hwmark; - sim_debug(DEBUG_DETAIL, &mta_dev, "Write unit=%d Block %d chars\n", unit, reclen); + sim_debug(DEBUG_DETAIL, &mta_dev, "Write unit=%d Block %d chars\n", unit, reclen); r = sim_tape_wrrecf(uptr, &mt_buffer[bufnum][0], reclen); uptr->u4 = 0; uptr->u3 &= ~MT_CMDMSK; - mt_error(uptr, addr, r, dptr); /* Record errors */ + mt_error(uptr, addr, r, dptr); /* Record errors */ } - } else { - mt_buffer[bufnum][uptr->u4++] = ch; - sim_debug(DEBUG_DATA, &mta_dev, "Write data unit=%d %d %02o\n", unit, uptr->u4, ch); - uptr->hwmark = uptr->u4; - break; - } - sim_activate(uptr, 20); - break; + } else { + mt_buffer[bufnum][uptr->u4++] = ch; + sim_debug(DEBUG_DATA, &mta_dev, "Write data unit=%d %d %02o\n", unit, uptr->u4, ch); + uptr->hwmark = uptr->u4; + break; + } + sim_activate(uptr, 20); + break; - case MT_RDBK: /* 0x0C */ /* Read Backwards */ + case MT_RDBK: /* 0x0C */ /* Read Backwards */ if (uptr->u3 & MT_READDONE) { uptr->u3 &= ~(MT_CMDMSK|MT_READDONE); mt_busy[bufnum] &= ~1; @@ -875,26 +875,26 @@ t_stat mt_srv(UNIT * uptr) /* If at end of record, fill buffer */ if (BUF_EMPTY(uptr)) { - if (sim_tape_bot(uptr)) { - uptr->u3 &= ~MT_CMDMSK; - mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1; - chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - return SCPE_OK; - } - sim_debug(DEBUG_DETAIL, &mta_dev, "Read backward unit=%d\n", unit); - if ((r = sim_tape_rdrecr(uptr, &mt_buffer[bufnum][0], &reclen, BUFFSIZE)) != MTSE_OK) { - uptr->u3 &= ~(MT_CMDMSK|MT_READDONE); - return mt_error(uptr, addr, r, dptr); - } - uptr->u4 = reclen; - uptr->hwmark = reclen; - sim_debug(DEBUG_DETAIL, &mta_dev, "Binary Block %d chars\n", reclen); + if (sim_tape_bot(uptr)) { + uptr->u3 &= ~MT_CMDMSK; + mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1; + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + return SCPE_OK; + } + sim_debug(DEBUG_DETAIL, &mta_dev, "Read backward unit=%d\n", unit); + if ((r = sim_tape_rdrecr(uptr, &mt_buffer[bufnum][0], &reclen, BUFFSIZE)) != MTSE_OK) { + uptr->u3 &= ~(MT_CMDMSK|MT_READDONE); + return mt_error(uptr, addr, r, dptr); + } + uptr->u4 = reclen; + uptr->hwmark = reclen; + sim_debug(DEBUG_DETAIL, &mta_dev, "Binary Block %d chars\n", reclen); } ch = mt_buffer[bufnum][--uptr->u4]; if (chan_write_byte(addr, &ch)) { - sim_debug(DEBUG_DATA, &mta_dev, "Read unit=%d EOR\n", unit); + sim_debug(DEBUG_DATA, &mta_dev, "Read unit=%d EOR\n", unit); /* If not read whole record, skip till end */ if (uptr->u4 >= 0) { sim_activate(uptr, (uptr->u4) * 20); @@ -905,7 +905,7 @@ t_stat mt_srv(UNIT * uptr) mt_busy[bufnum] &= ~1; chan_end(addr, SNS_CHNEND|SNS_DEVEND); } else { - sim_debug(DEBUG_DATA, &mta_dev, "Read data unit=%d %d %02o\n", unit, uptr->u4, ch); + sim_debug(DEBUG_DATA, &mta_dev, "Read data unit=%d %d %02o\n", unit, uptr->u4, ch); if (uptr->u4 == 0) { /* In IRG */ uptr->u3 &= ~MT_CMDMSK; mt_busy[bufnum] &= ~1; @@ -915,7 +915,7 @@ t_stat mt_srv(UNIT * uptr) } break; - case MT_WTM: /* 0x93 */ /* Write tape filemark */ + case MT_WTM: /* 0x93 */ /* Write tape filemark */ if (uptr->u4 == 0) { if (sim_tape_wrp(uptr)) { uptr->u5 |= SNS_CMDREJ; @@ -927,7 +927,7 @@ t_stat mt_srv(UNIT * uptr) uptr->u4 ++; sim_activate(uptr, 500); } else { - sim_debug(DEBUG_DETAIL, &mta_dev, "Write Mark unit=%d\n", unit); + sim_debug(DEBUG_DETAIL, &mta_dev, "Write Mark unit=%d\n", unit); uptr->u3 &= ~(MT_CMDMSK); r = sim_tape_wrtmk(uptr); set_devattn(addr, SNS_DEVEND); @@ -935,8 +935,8 @@ t_stat mt_srv(UNIT * uptr) } break; - case MT_BSR: /* 0x53 */ /* Backspace record */ - sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv cmd 0x53 BSR unit %d u4 %x\n", unit, uptr->u4); + case MT_BSR: /* 0x53 */ /* Backspace record */ + sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv cmd 0x53 BSR unit %d u4 %x\n", unit, uptr->u4); switch (uptr->u4 ) { case 0: if (sim_tape_bot(uptr)) { @@ -949,17 +949,17 @@ t_stat mt_srv(UNIT * uptr) sim_activate(uptr, 50); break; case 1: - uptr->u4++; - sim_debug(DEBUG_DETAIL, &mta_dev, "Backspace rec unit %x u4 %x\n", unit, uptr->u4); - r = sim_tape_sprecr(uptr, &reclen); - /* We don't set EOF on BSR */ - if (r == MTSE_TMK) { - uptr->u4++; - sim_debug(DEBUG_DETAIL, &mta_dev, "MARK\n"); - sim_activate(uptr, 50); - } else { - sim_debug(DEBUG_DETAIL, &mta_dev, "reclen %x\n", reclen); -// sim_activate(uptr, 10 + (10 * reclen)); + uptr->u4++; + sim_debug(DEBUG_DETAIL, &mta_dev, "Backspace rec unit %x u4 %x\n", unit, uptr->u4); + r = sim_tape_sprecr(uptr, &reclen); + /* We don't set EOF on BSR */ + if (r == MTSE_TMK) { + uptr->u4++; + sim_debug(DEBUG_DETAIL, &mta_dev, "MARK\n"); + sim_activate(uptr, 50); + } else { + sim_debug(DEBUG_DETAIL, &mta_dev, "reclen %x\n", reclen); +// sim_activate(uptr, 10 + (10 * reclen)); sim_activate(uptr, 50); } break; @@ -976,8 +976,8 @@ t_stat mt_srv(UNIT * uptr) } break; - case MT_BSF: /* 0x73 */ /* Backspace file */ - sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv cmd 0x73 BSF unit %d\n", unit); + case MT_BSF: /* 0x73 */ /* Backspace file */ + sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv cmd 0x73 BSF unit %d\n", unit); switch(uptr->u4) { case 0: if (sim_tape_bot(uptr)) { @@ -990,11 +990,11 @@ t_stat mt_srv(UNIT * uptr) sim_activate(uptr, 500); break; case 1: - sim_debug(DEBUG_DETAIL, &mta_dev, "Backspace file unit=%d\n", unit); + sim_debug(DEBUG_DETAIL, &mta_dev, "Backspace file unit=%d\n", unit); r = sim_tape_sprecr(uptr, &reclen); if (r == MTSE_TMK) { uptr->u4++; - sim_debug(DEBUG_DETAIL, &mta_dev, "MARK\n"); + sim_debug(DEBUG_DETAIL, &mta_dev, "MARK\n"); sim_activate(uptr, 50); } else if (r == MTSE_BOT) { uptr->u4+= 2; @@ -1004,12 +1004,12 @@ t_stat mt_srv(UNIT * uptr) sim_activate(uptr, 20); } break; - case 2: /* File Mark */ + case 2: /* File Mark */ uptr->u3 &= ~(MT_CMDMSK); chan_end(addr, SNS_DEVEND); mt_busy[bufnum] &= ~1; break; - case 3: /* BOT */ + case 3: /* BOT */ uptr->u3 &= ~(MT_CMDMSK); chan_end(addr, SNS_DEVEND); mt_busy[bufnum] &= ~1; @@ -1017,7 +1017,7 @@ t_stat mt_srv(UNIT * uptr) } break; - case MT_FSR: /* 0x43 */ /* Advance record */ + case MT_FSR: /* 0x43 */ /* Advance record */ switch(uptr->u4) { case 0: uptr->u4++; @@ -1042,59 +1042,59 @@ t_stat mt_srv(UNIT * uptr) case 2: uptr->u3 &= ~(MT_CMDMSK); // set_devattn(addr, SNS_DEVEND); - chan_end(addr, SNS_DEVEND); + chan_end(addr, SNS_DEVEND); mt_busy[bufnum] &= ~1; break; case 3: uptr->u3 &= ~(MT_CMDMSK); - chan_end(addr, SNS_DEVEND|SNS_UNITEXP); + chan_end(addr, SNS_DEVEND|SNS_UNITEXP); mt_busy[bufnum] &= ~1; break; case 4: uptr->u3 &= ~(MT_CMDMSK); - chan_end(addr, SNS_DEVEND|SNS_UNITCHK); + chan_end(addr, SNS_DEVEND|SNS_UNITCHK); mt_busy[bufnum] &= ~1; break; } break; - case MT_FSF: /* 0x63 */ /* advance filemark */ - switch(uptr->u4) { - case 0: - uptr->u4 ++; - sim_activate(uptr, 500); - break; - case 1: - sim_debug(DEBUG_DETAIL, &mta_dev, "Skip rec unit=%d\n", unit); - r = sim_tape_sprecf(uptr, &reclen); - if (r == MTSE_TMK) { - uptr->u4++; - sim_debug(DEBUG_DETAIL, &mta_dev, "MARK\n"); - sim_activate(uptr, 50); - } else if (r == MTSE_EOM) { - uptr->u5 |= SNS_EOT; /* set EOT status */ - uptr->u4+= 2; - sim_activate(uptr, 50); - } else { - sim_debug(DEBUG_DETAIL, &mta_dev, "%d\n", reclen); - sim_activate(uptr, 10 + (10 * reclen)); - } - break; - case 2: - uptr->u3 &= ~(MT_CMDMSK); - chan_end(addr, SNS_DEVEND); - mt_busy[bufnum] &= ~1; - sim_debug(DEBUG_DETAIL, &mta_dev, "Skip done unit=%d\n", unit); - break; - case 3: - uptr->u3 &= ~(MT_CMDMSK); - chan_end(addr, SNS_DEVEND|SNS_UNITCHK); - mt_busy[bufnum] &= ~1; - break; - } - break; + case MT_FSF: /* 0x63 */ /* advance filemark */ + switch(uptr->u4) { + case 0: + uptr->u4 ++; + sim_activate(uptr, 500); + break; + case 1: + sim_debug(DEBUG_DETAIL, &mta_dev, "Skip rec unit=%d\n", unit); + r = sim_tape_sprecf(uptr, &reclen); + if (r == MTSE_TMK) { + uptr->u4++; + sim_debug(DEBUG_DETAIL, &mta_dev, "MARK\n"); + sim_activate(uptr, 50); + } else if (r == MTSE_EOM) { + uptr->u5 |= SNS_EOT; /* set EOT status */ + uptr->u4+= 2; + sim_activate(uptr, 50); + } else { + sim_debug(DEBUG_DETAIL, &mta_dev, "%d\n", reclen); + sim_activate(uptr, 10 + (10 * reclen)); + } + break; + case 2: + uptr->u3 &= ~(MT_CMDMSK); + chan_end(addr, SNS_DEVEND); + mt_busy[bufnum] &= ~1; + sim_debug(DEBUG_DETAIL, &mta_dev, "Skip done unit=%d\n", unit); + break; + case 3: + uptr->u3 &= ~(MT_CMDMSK); + chan_end(addr, SNS_DEVEND|SNS_UNITCHK); + mt_busy[bufnum] &= ~1; + break; + } + break; - case MT_ERG: /* 0xA3 */ /* Erace 3.5 in tape */ + case MT_ERG: /* 0xA3 */ /* Erace 3.5 in tape */ switch (uptr->u4) { case 0: if (sim_tape_wrp(uptr)) { @@ -1120,21 +1120,21 @@ t_stat mt_srv(UNIT * uptr) } break; - case MT_REW: /* 0x23 */ /* rewind tape */ - if (uptr->u4 == 0) { - uptr->u4 ++; - sim_activate(uptr, 30000); - mt_busy[bufnum] &= ~1; - } else { - sim_debug(DEBUG_DETAIL, &mta_dev, "Rewind unit=%d\n", unit); - uptr->u3 &= ~(MT_CMDMSK); - r = sim_tape_rewind(uptr); - chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ - uptr->u5 |= SNS_LOAD; /* set BOT */ + case MT_REW: /* 0x23 */ /* rewind tape */ + if (uptr->u4 == 0) { + uptr->u4 ++; + sim_activate(uptr, 30000); + mt_busy[bufnum] &= ~1; + } else { + sim_debug(DEBUG_DETAIL, &mta_dev, "Rewind unit=%d\n", unit); + uptr->u3 &= ~(MT_CMDMSK); + r = sim_tape_rewind(uptr); + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ + uptr->u5 |= SNS_LOAD; /* set BOT */ } break; - case MT_RUN: /* 0x33 */ /* Rewind and unload tape */ + case MT_RUN: /* 0x33 */ /* Rewind and unload tape */ if (uptr->u4 == 0) { uptr->u4 ++; mt_busy[bufnum] &= ~1; @@ -1146,50 +1146,50 @@ t_stat mt_srv(UNIT * uptr) } break; } - return SCPE_OK; + return SCPE_OK; } /* initialize the tape chan/unit */ void mt_ini(UNIT *uptr, t_bool f) { - DEVICE *dptr = find_dev_from_unit(uptr); + DEVICE *dptr = find_dev_from_unit(uptr); - uptr->u3 &= ~0xffff; /* clear out the flags but leave ch/sa */ - if ((uptr->flags & MTUF_9TR) == 0) /* if not 9 track tape, make 800 bpi */ - uptr->u3 |= MT_ODD|MT_CONV|MT_MDEN_800; /* set 800 bpi options */ - uptr->u5 = 0; /* clear sense data */ - uptr->u5 |= (SNS_RDY|SNS_ONLN|SNS_LOAD); /* set initial status */ - mt_busy[GET_DEV_BUF(dptr->flags)] = 0; /* set not busy */ - sim_debug(DEBUG_EXP, &mta_dev, "MT init device %s unit %x\n", dptr->name, GET_UADDR(uptr->u3)); + uptr->u3 &= ~0xffff; /* clear out the flags but leave ch/sa */ + if ((uptr->flags & MTUF_9TR) == 0) /* if not 9 track tape, make 800 bpi */ + uptr->u3 |= MT_ODD|MT_CONV|MT_MDEN_800; /* set 800 bpi options */ + uptr->u5 = 0; /* clear sense data */ + uptr->u5 |= (SNS_RDY|SNS_ONLN|SNS_LOAD); /* set initial status */ + mt_busy[GET_DEV_BUF(dptr->flags)] = 0; /* set not busy */ + sim_debug(DEBUG_EXP, &mta_dev, "MT init device %s unit %x\n", dptr->name, GET_UADDR(uptr->u3)); } /* reset the mag tape */ t_stat mt_reset(DEVICE *dptr) { - /* nothing to do?? */ - sim_debug(DEBUG_EXP, &mta_dev, "MT reset name %s\n", dptr->name); + /* nothing to do?? */ + sim_debug(DEBUG_EXP, &mta_dev, "MT reset name %s\n", dptr->name); return SCPE_OK; } /* attach the specified file to the tape device */ t_stat mt_attach(UNIT *uptr, CONST char *file) { - uint16 addr = GET_UADDR(uptr->u3); /* get address of mt device */ + uint16 addr = GET_UADDR(uptr->u3); /* get address of mt device */ t_stat r; - if ((r = sim_tape_attach(uptr, file)) != SCPE_OK) { /* mount the specified file to the MT */ - sim_debug(DEBUG_EXP, &mta_dev, "mt_attach ERROR filename %s status %x\n", file, r); - return r; /* report any error */ - } - sim_debug(DEBUG_EXP, &mta_dev, "mt_attach complete filename %s\n", file); - set_devattn(addr, SNS_DEVEND); /* ready int???? */ - return SCPE_OK; /* return good status */ + if ((r = sim_tape_attach(uptr, file)) != SCPE_OK) { /* mount the specified file to the MT */ + sim_debug(DEBUG_EXP, &mta_dev, "mt_attach ERROR filename %s status %x\n", file, r); + return r; /* report any error */ + } + sim_debug(DEBUG_EXP, &mta_dev, "mt_attach complete filename %s\n", file); + set_devattn(addr, SNS_DEVEND); /* ready int???? */ + return SCPE_OK; /* return good status */ } /* detach the MT device and unload any tape */ t_stat mt_detach(UNIT *uptr) { - sim_debug(DEBUG_EXP, &mta_dev, "mt_detach\n"); + sim_debug(DEBUG_EXP, &mta_dev, "mt_detach\n"); uptr->u3 = 0; return sim_tape_detach(uptr); } @@ -1197,21 +1197,21 @@ t_stat mt_detach(UNIT *uptr) /* boot from the specified tape unit */ t_stat mt_boot(int32 unit_num, DEVICE *dptr) { - UNIT *uptr = &dptr->units[unit_num]; /* find tape unit pointer */ + UNIT *uptr = &dptr->units[unit_num]; /* find tape unit pointer */ - sim_debug(DEBUG_EXP, &mta_dev, "MT Boot dev/unit %x\n", GET_UADDR(uptr->u3)); - if ((uptr->flags & UNIT_ATT) == 0) { /* Is MT device already attached? */ - sim_debug(DEBUG_EXP, &mta_dev, "MT Boot attach error dev/unit %x\n", GET_UADDR(uptr->u3)); - return SCPE_UNATT; /* not attached, return error */ - } - SPAD[0xf4] = GET_UADDR(uptr->u3); /* put boot device chan/sa into spad */ - SPAD[0xf8] = 0xF000; /* show as F class device */ + sim_debug(DEBUG_EXP, &mta_dev, "MT Boot dev/unit %x\n", GET_UADDR(uptr->u3)); + if ((uptr->flags & UNIT_ATT) == 0) { /* Is MT device already attached? */ + sim_debug(DEBUG_EXP, &mta_dev, "MT Boot attach error dev/unit %x\n", GET_UADDR(uptr->u3)); + return SCPE_UNATT; /* not attached, return error */ + } + SPAD[0xf4] = GET_UADDR(uptr->u3); /* put boot device chan/sa into spad */ + SPAD[0xf8] = 0xF000; /* show as F class device */ - if ((uptr->flags & MTUF_9TR) == 0) { /* is tape a 9 track? */ - uptr->u3 &= ~0xffff; /* clear out old status */ - uptr->u3 |= MT_ODD|MT_CONV|MT_MDEN_800; /* set 800bpi & odd parity */ - } - return chan_boot(GET_UADDR(uptr->u3), dptr); /* boot the ch/sa */ + if ((uptr->flags & MTUF_9TR) == 0) { /* is tape a 9 track? */ + uptr->u3 &= ~0xffff; /* clear out old status */ + uptr->u3 |= MT_ODD|MT_CONV|MT_MDEN_800; /* set 800bpi & odd parity */ + } + return chan_boot(GET_UADDR(uptr->u3), dptr); /* boot the ch/sa */ } #endif /* NUM_DEVS_MT */ diff --git a/SEL32/sel32_scfi.c b/SEL32/sel32_scfi.c index b381429..d5470d0 100644 --- a/SEL32/sel32_scfi.c +++ b/SEL32/sel32_scfi.c @@ -32,8 +32,8 @@ extern void set_devattn(uint16 addr, uint8 flags); extern t_stat chan_boot(uint16 addr, DEVICE *dptr); extern int test_write_byte_end(uint16 chsa); -extern uint32 M[]; /* our memory */ -extern uint32 SPAD[]; /* cpu SPAD memory */ +extern uint32 M[]; /* our memory */ +extern uint32 SPAD[]; /* cpu SPAD memory */ #ifdef NUM_DEVS_SCFI #define UNIT_V_TYPE (UNIT_V_UF + 0) @@ -60,13 +60,13 @@ WD 8 Drive 7 Attribute register Memory attribute register layout bits 0-7 - Flags - bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option - bit 2 - 1=Cartridge module drive - bit 3 - 0=Reserved - bit 4 - 1=Drive not present - bit 5 - 1=Dual Port - bit 6 - 0=Reserved - bit 7 - 0=Reserved + bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option + bit 2 - 1=Cartridge module drive + bit 3 - 0=Reserved + bit 4 - 1=Drive not present + bit 5 - 1=Dual Port + bit 6 - 0=Reserved + bit 7 - 0=Reserved bits 8-15 - sector count (sectors per track)(F16=16, F20=20) bits 16-23 - MHD Head count (number of heads on MHD) bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option of mini-module) @@ -118,9 +118,9 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option /* u4 - sector target address register (STAR) */ /* Holds the current cylinder, head(track), sector */ -#define DISK_CYL 0xFFFF0000 /* cylinder mask */ -#define DISK_TRACK 0x0000FF00 /* track mask */ -#define DISK_SECTOR 0x000000ff /* sector mask */ +#define DISK_CYL 0xFFFF0000 /* cylinder mask */ +#define DISK_TRACK 0x0000FF00 /* track mask */ +#define DISK_SECTOR 0x000000ff /* sector mask */ /* u5 */ /* Sense byte 0 - mode register */ @@ -168,13 +168,13 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option /* provided by inch command for controller */ /* bits 0-7 - Flags - bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option - bit 2 - 1=Cartridge module drive - bit 3 - 0=Reserved - bit 4 - 1=Drive not present - bit 5 - 1=Dual Port - bit 6 - 0=Reserved - bit 7 - 0=Reserved + bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option + bit 2 - 1=Cartridge module drive + bit 3 - 0=Reserved + bit 4 - 1=Drive not present + bit 5 - 1=Dual Port + bit 6 - 0=Reserved + bit 7 - 0=Reserved bits 8-15 - sector count (sectors per track)(F16=16, F20=20) bits 16-23 - MHD Head count (number of heads on MHD) bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option of mini-module) @@ -185,69 +185,69 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option /* allocated during attach command for each unit defined */ struct ddata_t { - uint8 rbuf[1024]; /* read buffer, Sector buffer 768 or 1024 */ - uint8 wbuf[1024]; /* write buffer, Sector buffer 768 or 1024 */ - uint32 cpos; /* Position of head of cylinder in file */ - uint32 tstart; /* Location of start of cyl/track/sect in data */ - uint32 spare; /* drive register spare */ - uint16 tsize; /* Size of one track in byte */ - uint16 ssize; /* Size of one sector in bytes */ - uint16 ccyl; /* Current Cylinder number */ - uint16 cyl; /* Cylinder head at */ - uint16 tpos; /* Track position */ - uint16 spos; /* Sector position */ - uint16 dlen; /* remaining in data */ -// uint16 tsize; /* Size of one track in byte */ -// uint16 ssize; /* Size of one sector in bytes */ - uint16 rec; /* Current record number */ - uint16 count; /* Remaining in current operation */ + uint8 rbuf[1024]; /* read buffer, Sector buffer 768 or 1024 */ + uint8 wbuf[1024]; /* write buffer, Sector buffer 768 or 1024 */ + uint32 cpos; /* Position of head of cylinder in file */ + uint32 tstart; /* Location of start of cyl/track/sect in data */ + uint32 spare; /* drive register spare */ + uint16 tsize; /* Size of one track in byte */ + uint16 ssize; /* Size of one sector in bytes */ + uint16 ccyl; /* Current Cylinder number */ + uint16 cyl; /* Cylinder head at */ + uint16 tpos; /* Track position */ + uint16 spos; /* Sector position */ + uint16 dlen; /* remaining in data */ +// uint16 tsize; /* Size of one track in byte */ +// uint16 ssize; /* Size of one sector in bytes */ + uint16 rec; /* Current record number */ + uint16 count; /* Remaining in current operation */ }; /* disk definition structure */ struct scfi_t { - char *name; /* Device ID Name */ - uint32 taus; /* total allocation units */ - uint16 bms; /* bit map size */ - uint16 nhds; /* Number of heads */ - uint16 ssiz; /* sector size in words */ - uint16 spt; /* # sectors per track(cylinder) */ - uint8 spau; /* # sectors per allocation unit */ - uint8 spb; /* # sectors per block (192 WDS)*/ - uint32 cyl; /* Number of cylinders */ - uint8 type; /* Device type code */ + char *name; /* Device ID Name */ + uint32 taus; /* total allocation units */ + uint16 bms; /* bit map size */ + uint16 nhds; /* Number of heads */ + uint16 ssiz; /* sector size in words */ + uint16 spt; /* # sectors per track(cylinder) */ + uint8 spau; /* # sectors per allocation unit */ + uint8 spb; /* # sectors per block (192 WDS)*/ + uint32 cyl; /* Number of cylinders */ + uint8 type; /* Device type code */ } scfi_type[] = { - /* Class E Disc Devices */ - {"FE004", 5888, 184, 256, 192, 23, 1, 1, 1, 0x80}, /*0 4 M */ - {"CE010", 12800, 200, 2, 96, 16, 1, 2, 400, 0x60}, /*1 10 M */ - {"ME040", 23000, 719, 5, 192, 23, 2, 1, 400, 0x40}, /*2 40 M */ - {"ME080", 46000, 1438, 5, 192, 23, 2, 1, 800, 0x40}, /*3 80 M */ - {"ME300", 87400, 2732, 19, 192, 23, 4, 1, 800, 0x40}, /*4 300 M */ - {"FE005", 5888, 184, 4, 192, 23, 1, 1, 64, 0x80}, /*5 5 M */ + /* Class E Disc Devices */ + {"FE004", 5888, 184, 256, 192, 23, 1, 1, 1, 0x80}, /*0 4 M */ + {"CE010", 12800, 200, 2, 96, 16, 1, 2, 400, 0x60}, /*1 10 M */ + {"ME040", 23000, 719, 5, 192, 23, 2, 1, 400, 0x40}, /*2 40 M */ + {"ME080", 46000, 1438, 5, 192, 23, 2, 1, 800, 0x40}, /*3 80 M */ + {"ME300", 87400, 2732, 19, 192, 23, 4, 1, 800, 0x40}, /*4 300 M */ + {"FE005", 5888, 184, 4, 192, 23, 1, 1, 64, 0x80}, /*5 5 M */ - /* Class F Disc Devices */ - {"FL001", 1334, 0, 2, 64, 26, 3, 3, 26, 0x40}, /*6 1 M */ - {"MH040", 20000, 625, 5, 192, 20, 2, 1, 40, 0x40}, /*7 40 M */ - {"MH080", 40000, 1250, 5, 192, 20, 2, 1, 80, 0x40}, /*8 80 M */ - {"MH300", 76000, 2375, 19, 192, 20, 4, 1, 800, 0x40}, /*9 300 M */ - {"MH1GB", 87400, 2732, 1, 192, 20,16, 1,69920, 0x40}, /*10 1000 M */ - {"SG038", 54752, 1711, 1, 192, 20, 8, 1,21900, 0x40}, /*11 38 M */ - {"SG120", 174848, 5464, 1, 192, 20, 8, 1,69939, 0x40}, /*12 120 M */ - {"SG076", 116808, 3491, 1, 192, 20, 8, 1,46723, 0x40}, /*13 76 M */ - {"FH005", 5120, 184, 4, 192, 20, 1, 1, 64, 0x80}, /*14 5 M */ - {"CD032", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*15 32 M */ - {"CD032", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*16 32 M */ - {"CD064", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*17 64 M */ - {"CD064", 24000, 750, 3, 192, 20, 2, 1, 800, 0x60}, /*18 64 M */ - {"CD096", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*19 96 M */ - {"CD096", 40000, 1250, 5, 192, 20, 2, 1, 800, 0x60}, /*20 96 M */ - {"MH600", 80000, 2500, 40, 192, 20, 8, 1, 80, 0x40}, /*21 600 M */ - {"FM600", 80000, 2500, 40, 192, 20, 8, 1, 80, 0x40}, /*22 600 M */ - {"FM600", 1600, 50, 40, 192, 20, 1, 1, 2, 0x80}, /*23 600 M */ - {NULL, 0} + /* Class F Disc Devices */ + {"FL001", 1334, 0, 2, 64, 26, 3, 3, 26, 0x40}, /*6 1 M */ + {"MH040", 20000, 625, 5, 192, 20, 2, 1, 40, 0x40}, /*7 40 M */ + {"MH080", 40000, 1250, 5, 192, 20, 2, 1, 80, 0x40}, /*8 80 M */ + {"MH300", 76000, 2375, 19, 192, 20, 4, 1, 800, 0x40}, /*9 300 M */ + {"MH1GB", 87400, 2732, 1, 192, 20,16, 1,69920, 0x40}, /*10 1000 M */ + {"SG038", 54752, 1711, 1, 192, 20, 8, 1,21900, 0x40}, /*11 38 M */ + {"SG120", 174848, 5464, 1, 192, 20, 8, 1,69939, 0x40}, /*12 120 M */ + {"SG076", 116808, 3491, 1, 192, 20, 8, 1,46723, 0x40}, /*13 76 M */ + {"FH005", 5120, 184, 4, 192, 20, 1, 1, 64, 0x80}, /*14 5 M */ + {"CD032", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*15 32 M */ + {"CD032", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*16 32 M */ + {"CD064", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*17 64 M */ + {"CD064", 24000, 750, 3, 192, 20, 2, 1, 800, 0x60}, /*18 64 M */ + {"CD096", 8000, 250, 1, 192, 20, 2, 1, 800, 0x60}, /*19 96 M */ + {"CD096", 40000, 1250, 5, 192, 20, 2, 1, 800, 0x60}, /*20 96 M */ + {"MH600", 80000, 2500, 40, 192, 20, 8, 1, 80, 0x40}, /*21 600 M */ + {"FM600", 80000, 2500, 40, 192, 20, 8, 1, 80, 0x40}, /*22 600 M */ + {"FM600", 1600, 50, 40, 192, 20, 1, 1, 2, 0x80}, /*23 600 M */ + {NULL, 0} }; #if 0 @@ -300,24 +300,24 @@ DID FORM 32, 8, 8, 8, 8, 16, 16, 32, 64 * #endif -uint8 scfi_preio(UNIT *uptr, uint16 chan); -uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); -uint8 scfi_haltio(uint16 addr); -t_stat scfi_srv(UNIT *); -t_stat scfi_boot(int32, DEVICE *); -void scfi_ini(UNIT *, t_bool); -t_stat scfi_reset(DEVICE *); -t_stat scfi_attach(UNIT *, CONST char *); -t_stat scfi_detach(UNIT *); -t_stat scfi_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc); -t_stat scfi_get_type(FILE * st, UNIT *uptr, int32 v, CONST void *desc); -t_stat scfi_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); -const char *scfi_description (DEVICE *dptr); +uint8 scfi_preio(UNIT *uptr, uint16 chan); +uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); +uint8 scfi_haltio(uint16 addr); +t_stat scfi_srv(UNIT *); +t_stat scfi_boot(int32, DEVICE *); +void scfi_ini(UNIT *, t_bool); +t_stat scfi_reset(DEVICE *); +t_stat scfi_attach(UNIT *, CONST char *); +t_stat scfi_detach(UNIT *); +t_stat scfi_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat scfi_get_type(FILE * st, UNIT *uptr, int32 v, CONST void *desc); +t_stat scfi_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +const char *scfi_description (DEVICE *dptr); /* channel program information */ -CHANP sda_chp[NUM_UNITS_SCFI] = {0}; +CHANP sda_chp[NUM_UNITS_SCFI] = {0}; -MTAB scfi_mod[] = { +MTAB scfi_mod[] = { {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "TYPE", "TYPE", &scfi_set_type, &scfi_get_type, NULL, "Type of disk"}, {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, @@ -325,8 +325,8 @@ MTAB scfi_mod[] = { {0} }; -UNIT sda_unit[] = { -/* SET_TYPE(12) SG120 */ +UNIT sda_unit[] = { +/* SET_TYPE(12) SG120 */ {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(12), 0), 0, UNIT_ADDR(0x400)}, /* 0 */ {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(12), 0), 0, UNIT_ADDR(0x410)}, /* 1 */ {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(12), 0), 0, UNIT_ADDR(0x420)}, /* 2 */ @@ -339,24 +339,24 @@ UNIT sda_unit[] = { //DIB sda_dib = {scfi_preio, scfi_startcmd, NULL, NULL, NULL, scfi_ini, sda_unit, sda_chp, NUM_UNITS_SCFI, 0x0f, 0x0400, 0, 0, 0}; -DIB sda_dib = { - scfi_preio, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ - scfi_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ - NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ - NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ - scfi_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ - sda_unit, /* UNIT* units */ /* Pointer to units structure */ - sda_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ - NUM_UNITS_SCFI, /* uint8 numunits */ /* number of units defined */ - 0xF0, /* uint8 mask */ /* 16 devices - device mask */ - 0x0400, /* uint16 chan_addr */ /* parent channel address */ - 0, /* uint32 chan_fifo_in */ /* fifo input index */ - 0, /* uint32 chan_fifo_out */ /* fifo output index */ - 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ +DIB sda_dib = { + scfi_preio, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ + scfi_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ + NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ + NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ + scfi_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ + sda_unit, /* UNIT* units */ /* Pointer to units structure */ + sda_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NUM_UNITS_SCFI, /* uint8 numunits */ /* number of units defined */ + 0xF0, /* uint8 mask */ /* 16 devices - device mask */ + 0x0400, /* uint16 chan_addr */ /* parent channel address */ + 0, /* uint32 chan_fifo_in */ /* fifo input index */ + 0, /* uint32 chan_fifo_out */ /* fifo output index */ + 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ }; -DEVICE sda_dev = { +DEVICE sda_dev = { "SDA", sda_unit, NULL, scfi_mod, NUM_UNITS_SCFI, 16, 24, 4, 16, 32, NULL, NULL, &scfi_reset, &scfi_boot, &scfi_attach, &scfi_detach, @@ -366,10 +366,10 @@ DEVICE sda_dev = { #if NUM_DEVS_SCFI > 1 /* channel program information */ -CHANP sdb_chp[NUM_UNITS_SCFI] = {0}; +CHANP sdb_chp[NUM_UNITS_SCFI] = {0}; -UNIT sdb_unit[] = { -/* SET_TYPE(10) DM1GB */ +UNIT sdb_unit[] = { +/* SET_TYPE(10) DM1GB */ {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(10), 0), 0, UNIT_ADDR(0xC00)}, /* 0 */ {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(10), 0), 0, UNIT_ADDR(0xC10)}, /* 1 */ {UDATA(&scfi_srv, UNIT_SCFI|SET_TYPE(10), 0), 0, UNIT_ADDR(0xC20)}, /* 2 */ @@ -382,24 +382,24 @@ UNIT sdb_unit[] = { //DIB sdb_dib = {scfi_preio, scfi_startcmd, NULL, NULL, NULL, scfi_ini, sdb_unit, sdb_chp, NUM_UNITS_SCFI, 0x0f, 0x0c00, 0, 0, 0}; -DIB sdb_dib = { - scfi_preio, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ - scfi_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ - NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ - NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ - NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ - scfi_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ - sdb_unit, /* UNIT* units */ /* Pointer to units structure */ - sdb_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ - NUM_UNITS_SCFI, /* uint8 numunits */ /* number of units defined */ - 0xF0, /* uint8 mask */ /* 16 devices - device mask */ - 0x0c00, /* uint16 chan_addr */ /* parent channel address */ - 0, /* uint32 chan_fifo_in */ /* fifo input index */ - 0, /* uint32 chan_fifo_out */ /* fifo output index */ - 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ +DIB sdb_dib = { + scfi_preio, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ + scfi_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */ + NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */ + NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */ + NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */ + scfi_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */ + sdb_unit, /* UNIT* units */ /* Pointer to units structure */ + sdb_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */ + NUM_UNITS_SCFI, /* uint8 numunits */ /* number of units defined */ + 0xF0, /* uint8 mask */ /* 16 devices - device mask */ + 0x0c00, /* uint16 chan_addr */ /* parent channel address */ + 0, /* uint32 chan_fifo_in */ /* fifo input index */ + 0, /* uint32 chan_fifo_out */ /* fifo output index */ + 0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ }; -DEVICE sdb_dev = { +DEVICE sdb_dev = { "SDB", sdb_unit, NULL, scfi_mod, NUM_UNITS_SCFI, 16, 24, 4, 16, 32, NULL, NULL, &scfi_reset, &scfi_boot, &scfi_attach, &scfi_detach, @@ -414,179 +414,179 @@ uint8 scfi_preio(UNIT *uptr, uint16 chan) DEVICE *dptr = find_dev_from_unit(uptr); int unit = (uptr - dptr->units); - sim_debug(DEBUG_CMD, dptr, "scfi_preio u3 %x unit=%d\n", uptr->u3, unit); - if ((uptr->u3 & 0xff00) != 0) { /* just return if busy */ - return SNS_BSY; - } + sim_debug(DEBUG_CMD, dptr, "scfi_preio u3 %x unit=%d\n", uptr->u3, unit); + if ((uptr->u3 & 0xff00) != 0) { /* just return if busy */ + return SNS_BSY; + } sim_debug(DEBUG_CMD, dptr, "scfi_preio unit=%d\n", unit); - return 0; /* good to go */ + return 0; /* good to go */ } uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { - uint16 addr = GET_UADDR(uptr->u3); - DEVICE *dptr = find_dev_from_unit(uptr); - int unit = (uptr - dptr->units); - uint8 ch; + uint16 addr = GET_UADDR(uptr->u3); + DEVICE *dptr = find_dev_from_unit(uptr); + int unit = (uptr - dptr->units); + uint8 ch; - sim_debug(DEBUG_CMD, dptr, "scfi_startcmd unit %d cmd %x u3 %x\n", unit, cmd, uptr->u3); - if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ - uptr->u5 |= SNS_INTVENT; /* unit intervention required */ - if (cmd != DSK_SNS) /* we are completed with unit check status */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - } + sim_debug(DEBUG_CMD, dptr, "scfi_startcmd unit %d cmd %x u3 %x\n", unit, cmd, uptr->u3); + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + uptr->u5 |= SNS_INTVENT; /* unit intervention required */ + if (cmd != DSK_SNS) /* we are completed with unit check status */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + } - if ((uptr->u3 & DSK_CMDMSK) != 0) { - uptr->u3 |= DSK_BUSY; /* Flag we we are busy */ - return SNS_BSY; - } - if ((uptr->u3 & 0xff00) != 0) { /* if any status info, we are busy */ - return SNS_BSY; - } - sim_debug(DEBUG_CMD, dptr, "scfi_startcmd CMD 2 unit=%d %02x\n", unit, cmd); + if ((uptr->u3 & DSK_CMDMSK) != 0) { + uptr->u3 |= DSK_BUSY; /* Flag we we are busy */ + return SNS_BSY; + } + if ((uptr->u3 & 0xff00) != 0) { /* if any status info, we are busy */ + return SNS_BSY; + } + sim_debug(DEBUG_CMD, dptr, "scfi_startcmd CMD 2 unit=%d %02x\n", unit, cmd); - if ((uptr->flags & UNIT_ATT) == 0) { /* see if unit is attached */ - if (cmd == DSK_SNS) { /* not attached, is cmd Sense 0x04 */ + if ((uptr->flags & UNIT_ATT) == 0) { /* see if unit is attached */ + if (cmd == DSK_SNS) { /* not attached, is cmd Sense 0x04 */ dosns: - sim_debug(DEBUG_CMD, dptr, "scfi_startcmd CMD sense\n"); - /* bytes 0,1 - Cyl entry from STAR reg in u4 */ - ch = (uptr->u4 >> 24) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b0 unit=%d 1 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - ch = (uptr->u4 >> 16) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b1 unit=%d 1 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - /* byte 2 - Track entry from STAR reg in u4 */ - ch = (uptr->u4 >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b2 unit=%d 1 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - /* byte 3 - Sector entry from STAR reg in u4 */ - ch = (uptr->u4) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b3 unit=%d 1 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - /* bytes 4 - mode reg, byte 0 of u5 */ - ch = (uptr->u5 >> 24) & 0xff; /* return the sense data for device */ - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%d 1 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - /* bytes 5-7 - status bytes, bytes 1-3 of u5 */ - ch = (uptr->u5 >> 16) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%d 2 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - ch = (uptr->u5 >> 8) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%d 3 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - ch = (uptr->u5) & 0xff; - sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%d 4 %x\n", unit, ch); - chan_write_byte(addr, &ch) ; - /* bytes 8-11 - drive attribute register (DATR) entries from uptr->u6 via INCH cmd */ - ch = (uptr->u6 >> 24) & 0xff; - chan_write_byte(addr, &ch) ; - ch = (uptr->u6 >> 16) & 0xff; - chan_write_byte(addr, &ch) ; - ch = (uptr->u6 >> 8 ) & 0xff; - chan_write_byte(addr, &ch) ; - ch = (uptr->u6 >> 0) & 0xff; - chan_write_byte(addr, &ch) ; - /* bytes 12 & 13 contain drive related status */ - ch = 0; /* zero for now */ - chan_write_byte(addr, &ch) ; - chan_write_byte(addr, &ch) ; + sim_debug(DEBUG_CMD, dptr, "scfi_startcmd CMD sense\n"); + /* bytes 0,1 - Cyl entry from STAR reg in u4 */ + ch = (uptr->u4 >> 24) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b0 unit=%d 1 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + ch = (uptr->u4 >> 16) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b1 unit=%d 1 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + /* byte 2 - Track entry from STAR reg in u4 */ + ch = (uptr->u4 >> 8) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b2 unit=%d 1 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + /* byte 3 - Sector entry from STAR reg in u4 */ + ch = (uptr->u4) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b3 unit=%d 1 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + /* bytes 4 - mode reg, byte 0 of u5 */ + ch = (uptr->u5 >> 24) & 0xff; /* return the sense data for device */ + sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%d 1 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + /* bytes 5-7 - status bytes, bytes 1-3 of u5 */ + ch = (uptr->u5 >> 16) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%d 2 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + ch = (uptr->u5 >> 8) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%d 3 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + ch = (uptr->u5) & 0xff; + sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%d 4 %x\n", unit, ch); + chan_write_byte(addr, &ch) ; + /* bytes 8-11 - drive attribute register (DATR) entries from uptr->u6 via INCH cmd */ + ch = (uptr->u6 >> 24) & 0xff; + chan_write_byte(addr, &ch) ; + ch = (uptr->u6 >> 16) & 0xff; + chan_write_byte(addr, &ch) ; + ch = (uptr->u6 >> 8 ) & 0xff; + chan_write_byte(addr, &ch) ; + ch = (uptr->u6 >> 0) & 0xff; + chan_write_byte(addr, &ch) ; + /* bytes 12 & 13 contain drive related status */ + ch = 0; /* zero for now */ + chan_write_byte(addr, &ch) ; + chan_write_byte(addr, &ch) ; - uptr->u5 &= 0xff000000; /* clear status bytes, but leave mode data */ - return SNS_CHNEND|SNS_DEVEND; - } - if (cmd == 0x0) /* INCH cmd gives unit check */ + uptr->u5 &= 0xff000000; /* clear status bytes, but leave mode data */ + return SNS_CHNEND|SNS_DEVEND; + } + if (cmd == 0x0) /* INCH cmd gives unit check */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - uptr->u5 |= (SNS_INTVENT|SNS_CMDREJ); /* set new error status */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* we done */ - } + uptr->u5 |= (SNS_INTVENT|SNS_CMDREJ); /* set new error status */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* we done */ + } - /* Unit is online, so process a command */ - switch (cmd) { + /* Unit is online, so process a command */ + switch (cmd) { - case DSK_INCH: /* INCH 0x00 */ - { - uint32 mema; /* memory address */ - int i; - UNIT *up = dptr->units; /* first unit for this device */ - sim_debug(DEBUG_CMD, dptr, "scfi_startcmd starting inch cmd addr %x u4 %x\r\n", addr, uptr->u4); - /* u4 has IOCD word 1 contents. For the disk processor it contains */ - /* a pointer to the INCH buffer followed by 8 drive attribute words that */ - /* contains the flags, sector count, MHD head count, and FHD count */ - /* us9 has the byte count from IOCD wd2 and should be 0x24 (36) */ - /* the INCH buffer address must be returned in u4 and us9 left non-zero */ - /* just return OK and channel software will use up8 as status buffer */ - mema = (uint32)uptr->u4; /* get memory address of buffer */ - uptr->u4 = M[mema>>2]; /* get status buffer address for XIO return status */ - sim_debug(DEBUG_CMD, dptr, "scfi_startcmd starting inch cmd addr %x u4 %x mema %x units %d\r\n", - addr, uptr->u4, mema, dptr->numunits); - /* the next 8 words have drive data for each unit */ - /* WARNING 8 drives must be defined for this controller */ - /* so we will not have a map fault */ - for (i=0; inumunits && i<8; i++) { /* process all drives */ - up->u6 = M[(mema>>2)+i+1]; /* save each unit's drive data */ - up++; /* next unit for this device */ - } - sim_debug(DEBUG_CMD, dptr, "scfi_startcmd done inch cmd addr %x\n", addr); - return SNS_CHNEND|SNS_DEVEND; - break; - } + case DSK_INCH: /* INCH 0x00 */ + { + uint32 mema; /* memory address */ + int i; + UNIT *up = dptr->units; /* first unit for this device */ + sim_debug(DEBUG_CMD, dptr, "scfi_startcmd starting inch cmd addr %x u4 %x\r\n", addr, uptr->u4); + /* u4 has IOCD word 1 contents. For the disk processor it contains */ + /* a pointer to the INCH buffer followed by 8 drive attribute words that */ + /* contains the flags, sector count, MHD head count, and FHD count */ + /* us9 has the byte count from IOCD wd2 and should be 0x24 (36) */ + /* the INCH buffer address must be returned in u4 and us9 left non-zero */ + /* just return OK and channel software will use up8 as status buffer */ + mema = (uint32)uptr->u4; /* get memory address of buffer */ + uptr->u4 = M[mema>>2]; /* get status buffer address for XIO return status */ + sim_debug(DEBUG_CMD, dptr, "scfi_startcmd starting inch cmd addr %x u4 %x mema %x units %d\r\n", + addr, uptr->u4, mema, dptr->numunits); + /* the next 8 words have drive data for each unit */ + /* WARNING 8 drives must be defined for this controller */ + /* so we will not have a map fault */ + for (i=0; inumunits && i<8; i++) { /* process all drives */ + up->u6 = M[(mema>>2)+i+1]; /* save each unit's drive data */ + up++; /* next unit for this device */ + } + sim_debug(DEBUG_CMD, dptr, "scfi_startcmd done inch cmd addr %x\n", addr); + return SNS_CHNEND|SNS_DEVEND; + break; + } - case DSK_SCK: /* Seek command 0x07 */ - case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ - uptr->u3 &= ~(DSK_STAR); /* show we do not have seek STAR in u4 */ - case DSK_WD: /* Write command 0x01 */ - case DSK_RD: /* Read command 0x02 */ - case DSK_LMR: /* read mode register */ + case DSK_SCK: /* Seek command 0x07 */ + case DSK_XEZ: /* Rezero & Read IPL record 0x1f */ + uptr->u3 &= ~(DSK_STAR); /* show we do not have seek STAR in u4 */ + case DSK_WD: /* Write command 0x01 */ + case DSK_RD: /* Read command 0x02 */ + case DSK_LMR: /* read mode register */ - uptr->u3 |= cmd; /* save cmd */ - sim_debug(DEBUG_CMD, dptr, "scfi_startcmd done with disk seek r/w cmd %x addr %x\n", cmd, addr); - sim_activate(uptr, 20); /* start things off */ - return 0; + uptr->u3 |= cmd; /* save cmd */ + sim_debug(DEBUG_CMD, dptr, "scfi_startcmd done with disk seek r/w cmd %x addr %x\n", cmd, addr); + sim_activate(uptr, 20); /* start things off */ + return 0; - case DSK_NOP: /* NOP 0x03 */ - return SNS_CHNEND|SNS_DEVEND; /* return OK */ + case DSK_NOP: /* NOP 0x03 */ + return SNS_CHNEND|SNS_DEVEND; /* return OK */ - case DSK_SNS: /* Sense 0x04 */ - goto dosns; /* use code above */ - break; - } - sim_debug(DEBUG_CMD, dptr, "scfi_startcmd done with scfi_startcmd %x addr %x u5 %x\n", cmd, addr, uptr->u5); - if (uptr->u5 & 0xff) - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - sim_activate(uptr, 20); /* start things off */ - return SNS_CHNEND|SNS_DEVEND; + case DSK_SNS: /* Sense 0x04 */ + goto dosns; /* use code above */ + break; + } + sim_debug(DEBUG_CMD, dptr, "scfi_startcmd done with scfi_startcmd %x addr %x u5 %x\n", cmd, addr, uptr->u5); + if (uptr->u5 & 0xff) + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + sim_activate(uptr, 20); /* start things off */ + return SNS_CHNEND|SNS_DEVEND; } /* Handle processing of disk requests. */ t_stat scfi_srv(UNIT *uptr) { - uint16 chsa = GET_UADDR(uptr->u3); - DEVICE *dptr = find_dev_from_unit(uptr); - DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to Dev Info Blk for this device */ - CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */ - struct ddata_t *data = (struct ddata_t *)(uptr->up7); - int cmd = uptr->u3 & DSK_CMDMSK; - int type = GET_TYPE(uptr->flags); - int count = data->count; - int trk, cyl; - int unit = (uptr - dptr->units); - int i; - uint8 ch; - uint8 buf2[768]; - uint8 buf[768]; + uint16 chsa = GET_UADDR(uptr->u3); + DEVICE *dptr = find_dev_from_unit(uptr); + DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to Dev Info Blk for this device */ + CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */ + struct ddata_t *data = (struct ddata_t *)(uptr->up7); + int cmd = uptr->u3 & DSK_CMDMSK; + int type = GET_TYPE(uptr->flags); + int count = data->count; + int trk, cyl; + int unit = (uptr - dptr->units); + int i; + uint8 ch; + uint8 buf2[768]; + uint8 buf[768]; - sim_debug(DEBUG_DETAIL, &sda_dev, "scfi_srv entry unit %d cmd %x chsa %x chan %x count %x\n", - unit, cmd, chsa, chsa>>8, chp->ccw_count); + sim_debug(DEBUG_DETAIL, &sda_dev, "scfi_srv entry unit %d cmd %x chsa %x chan %x count %x\n", + unit, cmd, chsa, chsa>>8, chp->ccw_count); - if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ - return SCPE_OK; - } - if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ - uptr->u5 |= SNS_INTVENT; /* unit intervention required */ - if (cmd != DSK_SNS) /* we are completed with unit check status */ - return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; - } + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + return SCPE_OK; + } + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + uptr->u5 |= SNS_INTVENT; /* unit intervention required */ + if (cmd != DSK_SNS) /* we are completed with unit check status */ + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + } sim_debug(DEBUG_CMD, dptr, "scfi_srv cmd=%x chsa %04x count %x\n", cmd, chsa, chp->ccw_count); switch (cmd) { @@ -606,293 +606,293 @@ t_stat scfi_srv(UNIT *uptr) ch = unit; sim_debug(DEBUG_DETAIL, dptr, "scfi_srv sense unit=%d 4 %x\n", unit, ch); chan_write_byte(chsa, &ch) ; - ch = 4; - sim_debug(DEBUG_CMD, dptr, "DISK SENSE %x chars complete %.8x, unit %d\n", ch, uptr->u5, unit); + ch = 4; + sim_debug(DEBUG_CMD, dptr, "DISK SENSE %x chars complete %.8x, unit %d\n", ch, uptr->u5, unit); uptr->u3 &= ~(0xff00); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case DSK_SCK: /* Seek cylinder, track, sector 0x07 */ + case DSK_SCK: /* Seek cylinder, track, sector 0x07 */ - /* If we are waiting on seek to finish, check if there yet. */ - if (uptr->u3 & DSK_SEEKING) { - /* see if on cylinder yet */ - if ((uptr->u4 >> 16) == data->cyl) { - /* we are on cylinder, seek is done */ - sim_debug(DEBUG_CMD, dptr, "scfi_srv seek on cylinder unit=%d %d %d\n", - unit, uptr->u4 >> 16, data->cyl); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - set_devattn(chsa, SNS_DEVEND); /* start the operation */ - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek end unit=%d %x %x\n", - unit, uptr->u4 >> 16, data->cyl); - sim_activate(uptr, 20); - break; - } else { - /* Compute delay based of difference. */ - /* Set next state = index */ - i = (uptr->u4 >> 16) - data->cyl; - sim_debug(DEBUG_CMD, dptr, "scfi_srv seek unit=%d %x %x\n", unit, uptr->u4 >> 16, i); - if (i > 0 ) { - if (i > 50) { - data->cyl += 50; /* seek 50 cyl */ - sim_activate(uptr, 800); - } else - if (i > 20) { - data->cyl += 20; /* seek 20 cyl */ - sim_activate(uptr, 400); - } else { - data->cyl++; /* Seek 1 cyl */ - sim_activate(uptr, 200); - } - if (data->cyl >= scfi_type[type].cyl) /* test for over max */ - data->cyl = scfi_type[type].cyl-1; /* make max */ - } else { - if (i < -50) { - data->cyl -= 50; /* seek 50 cyl */ - sim_activate(uptr, 800); - } else - if (i < -20) { - data->cyl -= 20; /* seek 20 cyl */ - sim_activate(uptr, 400); - } else { - data->cyl--; /* seek 1 cyl */ - sim_activate(uptr, 200); - } - if (data->cyl < 0) /* test for less than zero */ - data->cyl = 0; /* make zero */ - } - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek next unit=%d %d %d\n", unit, uptr->u4 >> 16, - data->cyl); - sim_activate(uptr, 2); - break; - } - } + /* If we are waiting on seek to finish, check if there yet. */ + if (uptr->u3 & DSK_SEEKING) { + /* see if on cylinder yet */ + if ((uptr->u4 >> 16) == data->cyl) { + /* we are on cylinder, seek is done */ + sim_debug(DEBUG_CMD, dptr, "scfi_srv seek on cylinder unit=%d %d %d\n", + unit, uptr->u4 >> 16, data->cyl); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + set_devattn(chsa, SNS_DEVEND); /* start the operation */ + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek end unit=%d %x %x\n", + unit, uptr->u4 >> 16, data->cyl); + sim_activate(uptr, 20); + break; + } else { + /* Compute delay based of difference. */ + /* Set next state = index */ + i = (uptr->u4 >> 16) - data->cyl; + sim_debug(DEBUG_CMD, dptr, "scfi_srv seek unit=%d %x %x\n", unit, uptr->u4 >> 16, i); + if (i > 0 ) { + if (i > 50) { + data->cyl += 50; /* seek 50 cyl */ + sim_activate(uptr, 800); + } else + if (i > 20) { + data->cyl += 20; /* seek 20 cyl */ + sim_activate(uptr, 400); + } else { + data->cyl++; /* Seek 1 cyl */ + sim_activate(uptr, 200); + } + if (data->cyl >= scfi_type[type].cyl) /* test for over max */ + data->cyl = scfi_type[type].cyl-1; /* make max */ + } else { + if (i < -50) { + data->cyl -= 50; /* seek 50 cyl */ + sim_activate(uptr, 800); + } else + if (i < -20) { + data->cyl -= 20; /* seek 20 cyl */ + sim_activate(uptr, 400); + } else { + data->cyl--; /* seek 1 cyl */ + sim_activate(uptr, 200); + } + if (data->cyl < 0) /* test for less than zero */ + data->cyl = 0; /* make zero */ + } + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek next unit=%d %d %d\n", unit, uptr->u4 >> 16, + data->cyl); + sim_activate(uptr, 2); + break; + } + } - /* not seeking, so start a new seek */ - /* Read in 4 character seek code */ - for (i = 0; i < 4; i++) { - if (chan_read_byte(chsa, &buf[i])) { - /* we have error, bail out */ - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - } + /* not seeking, so start a new seek */ + /* Read in 4 character seek code */ + for (i = 0; i < 4; i++) { + if (chan_read_byte(chsa, &buf[i])) { + /* we have error, bail out */ + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + } rezero: - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek unit=%d star %02d%02d %02d %02d\n", - unit, buf[0], buf[1], buf[2], buf[3]); - /* save STAR (target sector) data in u4 */ - uptr->u4 = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]); - cyl = uptr->u4 >> 16; /* get the cylinder */ - trk = buf[2]; /* get the track */ - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv SEEK %x cyl %d trk %d sec %d unit=%d\n", - uptr->u4, cyl&0xffff, trk, buf[3], unit); - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv Disk %s cyl %d hds %d sec/trk %d unit=%d\n", - scfi_type[type].name, scfi_type[type].cyl, scfi_type[type].nhds, scfi_type[type].spt, unit); + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek unit=%d star %02d%02d %02d %02d\n", + unit, buf[0], buf[1], buf[2], buf[3]); + /* save STAR (target sector) data in u4 */ + uptr->u4 = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]); + cyl = uptr->u4 >> 16; /* get the cylinder */ + trk = buf[2]; /* get the track */ + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv SEEK %x cyl %d trk %d sec %d unit=%d\n", + uptr->u4, cyl&0xffff, trk, buf[3], unit); + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv Disk %s cyl %d hds %d sec/trk %d unit=%d\n", + scfi_type[type].name, scfi_type[type].cyl, scfi_type[type].nhds, scfi_type[type].spt, unit); - uptr->u3 |= DSK_STAR; /* show we have seek STAR in u4 */ - /* calc the sector address of data */ - /* calculate file position in bytes of requested sector */ - data->tstart = uptr->u4 * (scfi_type[type].spb * scfi_type[type].ssiz * 4); /* file offset in bytes */ - data->tpos = trk; /* save the track/head number */ - data->spos = buf[3]; /* save the sector number */ - data->count = 0; /* no data seen yet */ - data->rec = 0; /* number of bytes in this sector */ - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek start %x trk %x sec %x\n", data->tstart, trk, buf[3]); - if ((sim_fseek(uptr->fileref, data->tstart, SEEK_SET)) != 0) { /* seek home */ - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv Error on seek to %x\n", data->tstart); - } + uptr->u3 |= DSK_STAR; /* show we have seek STAR in u4 */ + /* calc the sector address of data */ + /* calculate file position in bytes of requested sector */ + data->tstart = uptr->u4 * (scfi_type[type].spb * scfi_type[type].ssiz * 4); /* file offset in bytes */ + data->tpos = trk; /* save the track/head number */ + data->spos = buf[3]; /* save the sector number */ + data->count = 0; /* no data seen yet */ + data->rec = 0; /* number of bytes in this sector */ + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek start %x trk %x sec %x\n", data->tstart, trk, buf[3]); + if ((sim_fseek(uptr->fileref, data->tstart, SEEK_SET)) != 0) { /* seek home */ + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv Error on seek to %x\n", data->tstart); + } /* Check if already on correct cylinder */ if (trk != data->cyl) { - /* Do seek */ - uptr->u3 |= DSK_SEEKING; /* show we are seeking */ - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek unit=%d trk %x cyl %x\n", - unit, trk, data->cyl); - sim_activate(uptr, 20); - chan_end(chsa, SNS_CHNEND); - } else { - sim_debug(DEBUG_DETAIL, dptr, "scfi_srv calc sect addr seek start %x trk %x sec %x\n", - data->tstart, trk, buf[3]); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - sim_activate(uptr, 20); - chan_end(chsa, SNS_DEVEND|SNS_CHNEND); - } - return SCPE_OK; + /* Do seek */ + uptr->u3 |= DSK_SEEKING; /* show we are seeking */ + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek unit=%d trk %x cyl %x\n", + unit, trk, data->cyl); + sim_activate(uptr, 20); + chan_end(chsa, SNS_CHNEND); + } else { + sim_debug(DEBUG_DETAIL, dptr, "scfi_srv calc sect addr seek start %x trk %x sec %x\n", + data->tstart, trk, buf[3]); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + sim_activate(uptr, 20); + chan_end(chsa, SNS_DEVEND|SNS_CHNEND); + } + return SCPE_OK; - case DSK_XEZ: /* Rezero & Read IPL record */ + case DSK_XEZ: /* Rezero & Read IPL record */ - sim_debug(DEBUG_CMD, dptr, "RD REZERO IPL unit=%d seek 0\n", unit); - /* Do a seek to 0 */ - uptr->u4 = 0; /* set STAR to 0, 0, 0 */ - uptr->u3 &= ~(0xffff); /* remove old cmd */ - uptr->u3 |= DSK_SCK; /* show as seek command */ - data->tstart = 0; /* byte offset is 0 */ - data->dlen = 0; /* no data written yet */ - /* Read in 1 dummy character for length to inhibit SLI posting */ - if (chan_read_byte(chsa, &buf[0])) { - /* we have error, bail out */ - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - /* zero stuff */ - buf[0] = buf[1] = buf[2] = buf[3] = 0; - goto rezero; /* murge with seek code */ - break; + sim_debug(DEBUG_CMD, dptr, "RD REZERO IPL unit=%d seek 0\n", unit); + /* Do a seek to 0 */ + uptr->u4 = 0; /* set STAR to 0, 0, 0 */ + uptr->u3 &= ~(0xffff); /* remove old cmd */ + uptr->u3 |= DSK_SCK; /* show as seek command */ + data->tstart = 0; /* byte offset is 0 */ + data->dlen = 0; /* no data written yet */ + /* Read in 1 dummy character for length to inhibit SLI posting */ + if (chan_read_byte(chsa, &buf[0])) { + /* we have error, bail out */ + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + /* zero stuff */ + buf[0] = buf[1] = buf[2] = buf[3] = 0; + goto rezero; /* murge with seek code */ + break; - case DSK_LMR: - sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%d\n", unit); - /* Read in 1 character of mode data */ - if (chan_read_byte(chsa, &buf[0])) { - /* we have error, bail out */ - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - uptr->u3 &= ~(0xffff); /* remove old cmd */ - uptr->u5 &= 0x00ffffff; /* clear old mode data */ - uptr->u5 |= (buf[0] << 24); /* save mode value */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - break; + case DSK_LMR: + sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%d\n", unit); + /* Read in 1 character of mode data */ + if (chan_read_byte(chsa, &buf[0])) { + /* we have error, bail out */ + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + uptr->u5 |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + uptr->u3 &= ~(0xffff); /* remove old cmd */ + uptr->u5 &= 0x00ffffff; /* clear old mode data */ + uptr->u5 |= (buf[0] << 24); /* save mode value */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + break; - case DSK_RD: /* Read Data */ - /* data->tstart has start of sector address in bytes */ - if ((uptr->u3 & DSK_READING) == 0) { /* see if we are reading data */ - uptr->u3 |= DSK_READING; /* read from disk starting */ - data->dlen = 0; /* no data read yet */ - sim_debug(DEBUG_CMD, dptr, "DISK READ starting unit=%d u3 %x count %d rec %d\r\n", - unit, uptr->u3, count, data->rec); - } + case DSK_RD: /* Read Data */ + /* data->tstart has start of sector address in bytes */ + if ((uptr->u3 & DSK_READING) == 0) { /* see if we are reading data */ + uptr->u3 |= DSK_READING; /* read from disk starting */ + data->dlen = 0; /* no data read yet */ + sim_debug(DEBUG_CMD, dptr, "DISK READ starting unit=%d u3 %x count %d rec %d\r\n", + unit, uptr->u3, count, data->rec); + } - if (uptr->u3 & DSK_READING) { /* see if we are reading data */ - /* read in a sector of data from disk */ - if ((count=sim_fread(buf, 1, data->ssize, uptr->fileref)) != data->ssize) { - sim_debug(DEBUG_CMD, dptr, "Error %d on read %d of diskfile cyl %d hds %d sec %d\n", - count, data->ssize, data->cyl, data->tpos, data->spos); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ -// sim_activate(uptr, 20); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } + if (uptr->u3 & DSK_READING) { /* see if we are reading data */ + /* read in a sector of data from disk */ + if ((count=sim_fread(buf, 1, data->ssize, uptr->fileref)) != data->ssize) { + sim_debug(DEBUG_CMD, dptr, "Error %d on read %d of diskfile cyl %d hds %d sec %d\n", + count, data->ssize, data->cyl, data->tpos, data->spos); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ +// sim_activate(uptr, 20); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } - sim_debug(DEBUG_CMD, dptr, "scfi_srv after READ chsa %04x count %x\n", chsa, chp->ccw_count); - /* process the next sector of data */ - data->rec = count; /* no bytes in sector yet */ - count = 0; /* used here as a flag for short write */ - for (i=0; i<(data->rec); i++) { - ch = buf[i]; /* get a char from buffer */ - if (chan_write_byte(chsa, &ch)) { /* put a byte to memory */ - sim_debug(DEBUG_DATAIO, dptr, "DISK Read %d bytes from diskfile cyl %d hds %d sec %d tstart %d\n", - data->dlen+i, data->cyl, data->tpos, data->spos, data->tstart); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - goto rddone; - } - } - data->dlen += data->rec; /* add byte read to total count */ + sim_debug(DEBUG_CMD, dptr, "scfi_srv after READ chsa %04x count %x\n", chsa, chp->ccw_count); + /* process the next sector of data */ + data->rec = count; /* no bytes in sector yet */ + count = 0; /* used here as a flag for short write */ + for (i=0; i<(data->rec); i++) { + ch = buf[i]; /* get a char from buffer */ + if (chan_write_byte(chsa, &ch)) { /* put a byte to memory */ + sim_debug(DEBUG_DATAIO, dptr, "DISK Read %d bytes from diskfile cyl %d hds %d sec %d tstart %d\n", + data->dlen+i, data->cyl, data->tpos, data->spos, data->tstart); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + goto rddone; + } + } + data->dlen += data->rec; /* add byte read to total count */ - sim_debug(DEBUG_CMD, dptr, - "DISK READ from sec end %d bytes end %d from diskfile cyl %d hds %d sec %d tstart %x\n", - data->dlen, data->ssize, data->cyl, data->tpos, data->spos, data->tstart); - data->spos++; - /* see if we are done reading data */ - if (test_write_byte_end(chsa)) { - sim_debug(DEBUG_DATAIO, dptr, - "DISK Read complete Read %d bytes from diskfile cyl %d hds %d sec %d tstart %x\r\n", - data->dlen, data->cyl, data->tpos, data->spos, data->tstart); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - } + sim_debug(DEBUG_CMD, dptr, + "DISK READ from sec end %d bytes end %d from diskfile cyl %d hds %d sec %d tstart %x\n", + data->dlen, data->ssize, data->cyl, data->tpos, data->spos, data->tstart); + data->spos++; + /* see if we are done reading data */ + if (test_write_byte_end(chsa)) { + sim_debug(DEBUG_DATAIO, dptr, + "DISK Read complete Read %d bytes from diskfile cyl %d hds %d sec %d tstart %x\r\n", + data->dlen, data->cyl, data->tpos, data->spos, data->tstart); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + } rddone: -// sim_activate(uptr, 20); - sim_activate(uptr, 10); /* wait to read next sector */ - break; - } - break; +// sim_activate(uptr, 20); + sim_activate(uptr, 10); /* wait to read next sector */ + break; + } + break; - case DSK_WD: /* Write Data */ - /* data->tstart has start of sector address in bytes */ - if ((uptr->u3 & DSK_WRITING) == 0) { /* see if we are writing data */ - uptr->u3 |= DSK_WRITING; /* write to disk starting */ - data->dlen = 0; /* no data written yet */ - sim_debug(DEBUG_CMD, dptr, "DISK WRITE starting unit=%d u3 %x bytes %d rec %d\n", - unit, uptr->u3, data->dlen, data->rec); - } - if (uptr->u3 & DSK_WRITING) { /* see if we are writing data */ - /* process the next sector of data */ - data->rec = 0; /* no bytes in sector yet */ - count = 0; /* used here as a flag for short read */ - for (i=0; i<(data->ssize); i++) { - if (chan_read_byte(chsa, &ch)) { /* get a byte from memory */ - /* if error on reading 1st byte, we are done writing */ - if (i == 0) { - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - sim_debug(DEBUG_DATAIO, dptr, - "DISK Wrote %d bytes to diskfile cyl %d hds %d sec %d tstart %d\r\n", - data->dlen, data->cyl, data->tpos, data->spos, data->tstart); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); - goto wrdone; - } - ch = 0; /* finish out the sector with zero */ - count++; /* show we have no more data to write */ - } - buf2[i] = ch; /* save the char */ - } - data->dlen += data->ssize; /* add 1 sector of bytes */ - /* write the sector to disk */ - if ((i=sim_fwrite(buf2, 1, data->ssize, uptr->fileref)) != data->ssize) { - sim_debug(DEBUG_CMD, dptr, "Error %d on write %d to diskfile cyl %d hds %d sec %d\n", - i, data->ssize, data->cyl, data->tpos, data->spos); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } - if (count != 0) { /* see if done with write command */ - sim_debug(DEBUG_DATAIO, dptr, - "DISK WroteB %d bytes to diskfile cyl %d hds %d sec %d tstart %d\r\n", - data->dlen, data->cyl, data->tpos, data->spos, data->tstart); - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ - break; - } - sim_debug(DEBUG_CMD, dptr, - "DISK WR to sec end %d bytes end %d to diskfile cyl %d hds %d sec %d tstart %x\n", - data->dlen, data->ssize, data->cyl, data->tpos, data->spos, data->tstart); - data->spos++; + case DSK_WD: /* Write Data */ + /* data->tstart has start of sector address in bytes */ + if ((uptr->u3 & DSK_WRITING) == 0) { /* see if we are writing data */ + uptr->u3 |= DSK_WRITING; /* write to disk starting */ + data->dlen = 0; /* no data written yet */ + sim_debug(DEBUG_CMD, dptr, "DISK WRITE starting unit=%d u3 %x bytes %d rec %d\n", + unit, uptr->u3, data->dlen, data->rec); + } + if (uptr->u3 & DSK_WRITING) { /* see if we are writing data */ + /* process the next sector of data */ + data->rec = 0; /* no bytes in sector yet */ + count = 0; /* used here as a flag for short read */ + for (i=0; i<(data->ssize); i++) { + if (chan_read_byte(chsa, &ch)) { /* get a byte from memory */ + /* if error on reading 1st byte, we are done writing */ + if (i == 0) { + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + sim_debug(DEBUG_DATAIO, dptr, + "DISK Wrote %d bytes to diskfile cyl %d hds %d sec %d tstart %d\r\n", + data->dlen, data->cyl, data->tpos, data->spos, data->tstart); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + goto wrdone; + } + ch = 0; /* finish out the sector with zero */ + count++; /* show we have no more data to write */ + } + buf2[i] = ch; /* save the char */ + } + data->dlen += data->ssize; /* add 1 sector of bytes */ + /* write the sector to disk */ + if ((i=sim_fwrite(buf2, 1, data->ssize, uptr->fileref)) != data->ssize) { + sim_debug(DEBUG_CMD, dptr, "Error %d on write %d to diskfile cyl %d hds %d sec %d\n", + i, data->ssize, data->cyl, data->tpos, data->spos); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } + if (count != 0) { /* see if done with write command */ + sim_debug(DEBUG_DATAIO, dptr, + "DISK WroteB %d bytes to diskfile cyl %d hds %d sec %d tstart %d\r\n", + data->dlen, data->cyl, data->tpos, data->spos, data->tstart); + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ + break; + } + sim_debug(DEBUG_CMD, dptr, + "DISK WR to sec end %d bytes end %d to diskfile cyl %d hds %d sec %d tstart %x\n", + data->dlen, data->ssize, data->cyl, data->tpos, data->spos, data->tstart); + data->spos++; wrdone: -// sim_activate(uptr, 20); - sim_activate(uptr, 10); - break; +// sim_activate(uptr, 20); + sim_activate(uptr, 10); + break; } break; - default: - sim_debug(DEBUG_DETAIL, dptr, "invalid command=%d %x\n", unit, cmd); - uptr->u5 |= SNS_CMDREJ; - uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } + default: + sim_debug(DEBUG_DETAIL, dptr, "invalid command=%d %x\n", unit, cmd); + uptr->u5 |= SNS_CMDREJ; + uptr->u3 &= ~(0xffff); /* remove old status bits & cmd */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; + } sim_debug(DEBUG_DATAIO, dptr, "scfi_srv done cmd=%x chsa %04x count %x\n", cmd, chsa, chp->ccw_count); - return SCPE_OK; + return SCPE_OK; } /* initialize the disk */ void scfi_ini(UNIT *uptr, t_bool f) { - DEVICE *dptr = find_dev_from_unit(uptr); - int i = GET_TYPE(uptr->flags); + DEVICE *dptr = find_dev_from_unit(uptr); + int i = GET_TYPE(uptr->flags); - uptr->u3 &= ~0xffff; /* clear out the flags but leave ch/sa */ - /* capacity is tracks per allocation unit times sectors per allocation unit */ - uptr->capac = scfi_type[i].taus * scfi_type[i].spau; + uptr->u3 &= ~0xffff; /* clear out the flags but leave ch/sa */ + /* capacity is tracks per allocation unit times sectors per allocation unit */ + uptr->capac = scfi_type[i].taus * scfi_type[i].spau; - sim_debug(DEBUG_EXP, &sda_dev, "SDA init device %s on unit SDA%.1x cap %x\n", - dptr->name, GET_UADDR(uptr->u3), uptr->u3); + sim_debug(DEBUG_EXP, &sda_dev, "SDA init device %s on unit SDA%.1x cap %x\n", + dptr->name, GET_UADDR(uptr->u3), uptr->u3); } t_stat scfi_reset(DEVICE * dptr) @@ -902,180 +902,180 @@ t_stat scfi_reset(DEVICE * dptr) /* create the disk file for the specified device */ int scfi_format(UNIT *uptr) { - struct ddata_t *data = (struct ddata_t *)uptr->up7; - uint16 addr = GET_UADDR(uptr->u3); - int type = GET_TYPE(uptr->flags); - DEVICE *dptr = find_dev_from_unit(uptr); - uint16 tsize = data->tsize; /* get track size in bytes */ - uint32 cyl; - uint16 spc = scfi_type[type].nhds * scfi_type[type].spt; /* sectors/cyl */ - uint32 cap = scfi_type[type].taus * scfi_type[type].spau; /* disk capacity in sectors */ - uint32 cylv = cap / spc; /* calc number of cylinders */ - uint8 *buff; + struct ddata_t *data = (struct ddata_t *)uptr->up7; + uint16 addr = GET_UADDR(uptr->u3); + int type = GET_TYPE(uptr->flags); + DEVICE *dptr = find_dev_from_unit(uptr); + uint16 tsize = data->tsize; /* get track size in bytes */ + uint32 cyl; + uint16 spc = scfi_type[type].nhds * scfi_type[type].spt; /* sectors/cyl */ + uint32 cap = scfi_type[type].taus * scfi_type[type].spau; /* disk capacity in sectors */ + uint32 cylv = cap / spc; /* calc number of cylinders */ + uint8 *buff; - /* see if user wants to initialize the disk */ + /* see if user wants to initialize the disk */ if (!get_yn("Initialize disk? [Y] ", TRUE)) { return 1; } - /* seek to sector 0 */ - if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ - fprintf (stderr, "Error on seek to 0\r\n"); - } + /* seek to sector 0 */ + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + fprintf (stderr, "Error on seek to 0\r\n"); + } - /* get buffer for track data */ - if ((buff = (uint8 *)calloc(tsize, sizeof(uint8))) == 0) { - detach_unit(uptr); - return SCPE_ARG; - } - /* put dummy data in first word of disk */ - buff[0] = 'Z'; - buff[1] = 'E'; - buff[2] = 'R'; - buff[3] = 'O'; - sim_debug(DEBUG_CMD, dptr, "Creating disk file of trk size %x capacity %d\r\n", tsize, cap * data->ssize); - /* write zeros to each track of the disk */ - for (cyl = 0; cyl < cylv; cyl++) { - if ((sim_fwrite(buff, 1, data->tsize, uptr->fileref)) != data->tsize) { - sim_debug(DEBUG_CMD, dptr, "Error on write to diskfile cyl %d\r\n", cyl); - } - if (cyl == 0) { - buff[0] = 0; - buff[1] = 0; - buff[2] = 0; - buff[3] = 0; - } - } - if ((cyl % 400) == 0) - fputc('.', stderr); - fputc('\r', stderr); - fputc('\n', stderr); - /* seek home again */ - sim_fseek(uptr->fileref, 0, SEEK_SET); /* seek home */ - free(buff); /* free cylinder buffer */ - data->cpos = 0; - data->ccyl = 0; - set_devattn(addr, SNS_DEVEND); /* start us up */ -// sim_activate(uptr, 100); - return 0; + /* get buffer for track data */ + if ((buff = (uint8 *)calloc(tsize, sizeof(uint8))) == 0) { + detach_unit(uptr); + return SCPE_ARG; + } + /* put dummy data in first word of disk */ + buff[0] = 'Z'; + buff[1] = 'E'; + buff[2] = 'R'; + buff[3] = 'O'; + sim_debug(DEBUG_CMD, dptr, "Creating disk file of trk size %x capacity %d\r\n", tsize, cap * data->ssize); + /* write zeros to each track of the disk */ + for (cyl = 0; cyl < cylv; cyl++) { + if ((sim_fwrite(buff, 1, data->tsize, uptr->fileref)) != data->tsize) { + sim_debug(DEBUG_CMD, dptr, "Error on write to diskfile cyl %d\r\n", cyl); + } + if (cyl == 0) { + buff[0] = 0; + buff[1] = 0; + buff[2] = 0; + buff[3] = 0; + } + } + if ((cyl % 400) == 0) + fputc('.', stderr); + fputc('\r', stderr); + fputc('\n', stderr); + /* seek home again */ + sim_fseek(uptr->fileref, 0, SEEK_SET); /* seek home */ + free(buff); /* free cylinder buffer */ + data->cpos = 0; + data->ccyl = 0; + set_devattn(addr, SNS_DEVEND); /* start us up */ +// sim_activate(uptr, 100); + return 0; } /* attach the selected file to the disk */ t_stat scfi_attach(UNIT *uptr, CONST char *file) { - uint16 addr = GET_UADDR(uptr->u3); - int type = GET_TYPE(uptr->flags); - DEVICE *dptr = find_dev_from_unit(uptr); - t_stat r; - uint16 tsize; /* track size in bytes */ - uint16 ssize; /* sector size in bytes */ - struct ddata_t *data; - uint8 buff[1024]; + uint16 addr = GET_UADDR(uptr->u3); + int type = GET_TYPE(uptr->flags); + DEVICE *dptr = find_dev_from_unit(uptr); + t_stat r; + uint16 tsize; /* track size in bytes */ + uint16 ssize; /* sector size in bytes */ + struct ddata_t *data; + uint8 buff[1024]; - /* have simulator attach the file to the unit */ - if ((r = attach_unit(uptr, file)) != SCPE_OK) - return r; + /* have simulator attach the file to the unit */ + if ((r = attach_unit(uptr, file)) != SCPE_OK) + return r; - if (scfi_type[type].name == 0) { /* does the assigned disk have a name */ - detach_unit(uptr); /* no, reject */ - return SCPE_FMT; /* error */ - } + if (scfi_type[type].name == 0) { /* does the assigned disk have a name */ + detach_unit(uptr); /* no, reject */ + return SCPE_FMT; /* error */ + } - /* get a buffer to hold scfi_t structure */ - /* extended data structure per unit */ - if ((data = (struct ddata_t *)calloc(1, sizeof(struct ddata_t))) == 0) { - detach_unit(uptr); - return SCPE_FMT; - } + /* get a buffer to hold scfi_t structure */ + /* extended data structure per unit */ + if ((data = (struct ddata_t *)calloc(1, sizeof(struct ddata_t))) == 0) { + detach_unit(uptr); + return SCPE_FMT; + } - uptr->up7 = (void *)data; /* save pointer to structure in up7 */ - /* track size in bytes is sectors/track times words/sector time 4 bytse/word */ - tsize = scfi_type[type].spt * scfi_type[type].ssiz * 4; /* get track size in bytes */ - data->tsize = tsize; /* save size of track in bytes */ - uptr->capac = scfi_type[type].taus * scfi_type[type].spau; /* disk capacity in sectors */ - ssize = scfi_type[type].ssiz * 4; /* disk sector size in bytes */ - uptr->capac *= ssize; /* disk capacity in bytes */ - data->ssize = ssize; /* save sector size bytes */ + uptr->up7 = (void *)data; /* save pointer to structure in up7 */ + /* track size in bytes is sectors/track times words/sector time 4 bytse/word */ + tsize = scfi_type[type].spt * scfi_type[type].ssiz * 4; /* get track size in bytes */ + data->tsize = tsize; /* save size of track in bytes */ + uptr->capac = scfi_type[type].taus * scfi_type[type].spau; /* disk capacity in sectors */ + ssize = scfi_type[type].ssiz * 4; /* disk sector size in bytes */ + uptr->capac *= ssize; /* disk capacity in bytes */ + data->ssize = ssize; /* save sector size bytes */ - sim_debug(DEBUG_CMD, dptr, "Disk taus %d spau %d ssiz %d cap %d\n", - scfi_type[type].taus, scfi_type[type].spau, scfi_type[type].ssiz * 4, uptr->capac); /* disk capacity */ + sim_debug(DEBUG_CMD, dptr, "Disk taus %d spau %d ssiz %d cap %d\n", + scfi_type[type].taus, scfi_type[type].spau, scfi_type[type].ssiz * 4, uptr->capac); /* disk capacity */ - if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ - detach_unit(uptr); /* if no space, error */ - return SCPE_FMT; /* error */ - } + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ + } - /* read in the 1st sector of the 'disk' */ - if ((r = sim_fread(&buff[0], sizeof(uint8), ssize, uptr->fileref) != ssize)) { - sim_debug(DEBUG_CMD, &sda_dev, "Disk format fread ret = %x\n", r); - goto fmt; - } + /* read in the 1st sector of the 'disk' */ + if ((r = sim_fread(&buff[0], sizeof(uint8), ssize, uptr->fileref) != ssize)) { + sim_debug(DEBUG_CMD, &sda_dev, "Disk format fread ret = %x\n", r); + goto fmt; + } - if ((buff[0] | buff[1] | buff[2] | buff[3]) == 0) { - sim_debug(DEBUG_CMD, &sda_dev, "Disk format buf0 %x buf1 %x buf2 %x buf3 %x\n", - buff[0], buff[1], buff[2], buff[3]); + if ((buff[0] | buff[1] | buff[2] | buff[3]) == 0) { + sim_debug(DEBUG_CMD, &sda_dev, "Disk format buf0 %x buf1 %x buf2 %x buf3 %x\n", + buff[0], buff[1], buff[2], buff[3]); fmt: - /* format the drive */ - if (scfi_format(uptr)) { - detach_unit(uptr); /* if no space, error */ - return SCPE_FMT; /* error */ - } - } + /* format the drive */ + if (scfi_format(uptr)) { + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ + } + } - if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ - detach_unit(uptr); /* if no space, error */ - return SCPE_FMT; /* error */ - } + if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ + detach_unit(uptr); /* if no space, error */ + return SCPE_FMT; /* error */ + } - data->ssize = ssize; /* save sector size in bytes */ - data->tsize = tsize; /* save track size in bytes */ - data->cpos = 0; /* current read/write position in cylinder*/ - data->ccyl = 0; /* current cylinder number */ - data->tpos = 0; /* current track position */ - data->spos = 0; /* current sector position */ - data->rec = 0; /* record length */ - data->count = 0; /* clear count value */ + data->ssize = ssize; /* save sector size in bytes */ + data->tsize = tsize; /* save track size in bytes */ + data->cpos = 0; /* current read/write position in cylinder*/ + data->ccyl = 0; /* current cylinder number */ + data->tpos = 0; /* current track position */ + data->spos = 0; /* current sector position */ + data->rec = 0; /* record length */ + data->count = 0; /* clear count value */ - sim_debug(DEBUG_CMD, &sda_dev, "Attach %8s hds %d spt %d spc %d cyl %d capacity %d\n", - scfi_type[type].name, scfi_type[type].nhds, scfi_type[type].spt, - scfi_type[type].nhds * scfi_type[type].spt, - scfi_type[type].cyl, uptr->capac); - sim_debug(DEBUG_CMD, &sda_dev, "File %s attached to %s\r\n", file, scfi_type[type].name); + sim_debug(DEBUG_CMD, &sda_dev, "Attach %8s hds %d spt %d spc %d cyl %d capacity %d\n", + scfi_type[type].name, scfi_type[type].nhds, scfi_type[type].spt, + scfi_type[type].nhds * scfi_type[type].spt, + scfi_type[type].cyl, uptr->capac); + sim_debug(DEBUG_CMD, &sda_dev, "File %s attached to %s\r\n", file, scfi_type[type].name); - set_devattn(addr, SNS_DEVEND); - return SCPE_OK; + set_devattn(addr, SNS_DEVEND); + return SCPE_OK; } /* detach a disk device */ t_stat scfi_detach(UNIT *uptr) { - struct ddata_t *data = (struct ddata_t *)uptr->up7; + struct ddata_t *data = (struct ddata_t *)uptr->up7; if (data != 0) { - free(data); /* free disk data structure */ + free(data); /* free disk data structure */ } - uptr->up7 = 0; /* no pointer to disk data */ - uptr->u3 &= ~0xffff; /* no cmd and flags */ - return detach_unit(uptr); /* tell simh we are done with disk */ + uptr->up7 = 0; /* no pointer to disk data */ + uptr->u3 &= ~0xffff; /* no cmd and flags */ + return detach_unit(uptr); /* tell simh we are done with disk */ } /* boot from the specified disk unit */ t_stat scfi_boot(int32 unit_num, DEVICE *dptr) { - UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */ + UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */ - sim_debug(DEBUG_CMD, &sda_dev, "SCFI Disk Boot dev/unit %x\n", GET_UADDR(uptr->u3)); - SPAD[0xf4] = GET_UADDR(uptr->u3); /* put boot device chan/sa into spad */ - SPAD[0xf8] = 0xF000; /* show as F class device */ - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_UNATT; /* attached? */ - return chan_boot(GET_UADDR(uptr->u3), dptr); /* boot the ch/sa */ + sim_debug(DEBUG_CMD, &sda_dev, "SCFI Disk Boot dev/unit %x\n", GET_UADDR(uptr->u3)); + SPAD[0xf4] = GET_UADDR(uptr->u3); /* put boot device chan/sa into spad */ + SPAD[0xf8] = 0xF000; /* show as F class device */ + if ((uptr->flags & UNIT_ATT) == 0) + return SCPE_UNATT; /* attached? */ + return chan_boot(GET_UADDR(uptr->u3), dptr); /* boot the ch/sa */ } /* Disk option setting commands */ t_stat scfi_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { - int i; + int i; if (cptr == NULL) return SCPE_ARG; @@ -1087,7 +1087,7 @@ t_stat scfi_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) if (strcmp(scfi_type[i].name, cptr) == 0) { uptr->flags &= ~UNIT_TYPE; uptr->flags |= SET_TYPE(i); - uptr->capac = scfi_type[i].taus * scfi_type[i].spau; + uptr->capac = scfi_type[i].taus * scfi_type[i].spau; return SCPE_OK; } } @@ -1115,18 +1115,18 @@ t_stat scfi_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, for (i = 0; scfi_type[i].name != 0; i++) { fprintf(st, "%s", scfi_type[i].name); if (scfi_type[i+1].name != 0) - fprintf(st, ", "); + fprintf(st, ", "); } - fprintf (st, ".\nEach drive has the following storage capacity:\r\n"); - for (i = 0; scfi_type[i].name != 0; i++) { - int32 size = scfi_type[i].taus * scfi_type[i].spau; - size /= 1024; - size = (10 * size) / 1024; - fprintf(st, " %-8s %4d.%1dMB\r\n", scfi_type[i].name, size/10, size%10); - } - fprint_set_help (st, dptr); - fprint_show_help (st, dptr); - return SCPE_OK; + fprintf (st, ".\nEach drive has the following storage capacity:\r\n"); + for (i = 0; scfi_type[i].name != 0; i++) { + int32 size = scfi_type[i].taus * scfi_type[i].spau; + size /= 1024; + size = (10 * size) / 1024; + fprintf(st, " %-8s %4d.%1dMB\r\n", scfi_type[i].name, size/10, size%10); + } + fprint_set_help (st, dptr); + fprint_show_help (st, dptr); + return SCPE_OK; } const char *scfi_description (DEVICE *dptr) diff --git a/SEL32/sel32_sys.c b/SEL32/sel32_sys.c index 07ceff7..a7d2873 100644 --- a/SEL32/sel32_sys.c +++ b/SEL32/sel32_sys.c @@ -52,19 +52,19 @@ extern uint32 PSD[]; */ -char sim_name[] = "SEL 32"; /* our simulator name */ +char sim_name[] = "SEL 32"; /* our simulator name */ REG *sim_PC = &cpu_reg[0]; -int32 sim_emax = 1; /* maximum number of instructions/words to examine */ +int32 sim_emax = 1; /* maximum number of instructions/words to examine */ DEVICE *sim_devices[] = { - &cpu_dev, + &cpu_dev, #ifdef NUM_DEVS_IOP - &iop_dev, /* IOP channel controller */ + &iop_dev, /* IOP channel controller */ #endif #ifdef NUM_DEVS_RTOM - &rtc_dev, - &itm_dev, + &rtc_dev, + &itm_dev, #endif #ifdef NUM_DEVS_CON &con_dev, @@ -135,17 +135,17 @@ const char *sim_stop_messages[] = { */ int get_word(FILE *fileref, uint32 *word) { - unsigned char cbuf[4]; + unsigned char cbuf[4]; - /* read in the 4 chars */ - if (sim_fread(cbuf, 1, 4, fileref) != 4) - return 1; /* read error or eof */ - /* byte swap while reading data */ - *word = ((cbuf[0]) << 24) | + /* read in the 4 chars */ + if (sim_fread(cbuf, 1, 4, fileref) != 4) + return 1; /* read error or eof */ + /* byte swap while reading data */ + *word = ((cbuf[0]) << 24) | ((cbuf[1]) << 16) | ((cbuf[2]) << 8) | ((cbuf[3])); - return 0; /* all OK */ + return 0; /* all OK */ } #ifdef NO_TAP_FOR_NOW @@ -156,14 +156,14 @@ int get_word(FILE *fileref, uint32 *word) */ int get_halfword(FILE *fileref, uint16 *word) { - unsigned char cbuf[2]; + unsigned char cbuf[2]; - /* read in the 2 chars */ - if (sim_fread(cbuf, 1, 2, fileref) != 2) - return 1; /* read error or eof */ - /* byte swap while reading data */ - *word = ((uint16)(cbuf[0]) << 8) | ((uint16)(cbuf[1])); - return 0; /* all OK */ + /* read in the 2 chars */ + if (sim_fread(cbuf, 1, 2, fileref) != 2) + return 1; /* read error or eof */ + /* byte swap while reading data */ + *word = ((uint16)(cbuf[0]) << 8) | ((uint16)(cbuf[1])); + return 0; /* all OK */ } #endif @@ -172,15 +172,15 @@ int get_halfword(FILE *fileref, uint16 *word) t_stat load_mem (FILE *fileref) { uint32 data; - uint32 ma = 0; /* start at mem add 0 */ + uint32 ma = 0; /* start at mem add 0 */ - /* read the file until the end */ + /* read the file until the end */ for ( ;; ) { - if (get_word(fileref, &data)) /* get 32 bits of data */ - return SCPE_OK; /* load is complete, return */ - M[ma++] = data; /* put data in memory */ + if (get_word(fileref, &data)) /* get 32 bits of data */ + return SCPE_OK; /* load is complete, return */ + M[ma++] = data; /* put data in memory */ } - return SCPE_OK; /* never here */ + return SCPE_OK; /* never here */ } #ifdef NO_TAP_FOR_NOW @@ -188,33 +188,33 @@ t_stat load_mem (FILE *fileref) /* return SCPE_OK on load complete */ t_stat load_tap (FILE *fileref) { - uint32 bdata, edata; - uint16 hdata; - uint32 ma = 0; /* start loading at loc 0 */ - int32 wc; + uint32 bdata, edata; + uint16 hdata; + uint32 ma = 0; /* start loading at loc 0 */ + int32 wc; - for ( ;; ) { /* loop until EOF read */ - /* look for record byte count or zero for EOF */ - if (get_word(fileref, &bdata)) /* read 4 bytes of data */ - return SCPE_FMT; /* must be error, exit */ - wc = (int32)(bdata); /* byte count in tape record */ - wc = (wc + 1)/2; /* change byte count into hw count */ - if (wc == 0) - return SCPE_OK; /* eof found, return */ - /* copy data to memory in 16 bit halfwords */ - while (wc-- != 0) { - if (get_halfword(fileref, &hdata)) /* get 16 bits of data */ - return SCPE_FMT; /* must be error, exit */ - ((uint16*)M)[ma++] = hdata; /* put the hw into memory */ + for ( ;; ) { /* loop until EOF read */ + /* look for record byte count or zero for EOF */ + if (get_word(fileref, &bdata)) /* read 4 bytes of data */ + return SCPE_FMT; /* must be error, exit */ + wc = (int32)(bdata); /* byte count in tape record */ + wc = (wc + 1)/2; /* change byte count into hw count */ + if (wc == 0) + return SCPE_OK; /* eof found, return */ + /* copy data to memory in 16 bit halfwords */ + while (wc-- != 0) { + if (get_halfword(fileref, &hdata)) /* get 16 bits of data */ + return SCPE_FMT; /* must be error, exit */ + ((uint16*)M)[ma++] = hdata; /* put the hw into memory */ } - /* look only for record byte count */ - if (get_word(fileref, &edata)) /* read 4 bytes of data */ - return SCPE_FMT; /* must be error, exit */ - /* the before and after byte count must be equal */ - if (bdata != edata) - return SCPE_FMT; /* must be error, exit */ + /* look only for record byte count */ + if (get_word(fileref, &edata)) /* read 4 bytes of data */ + return SCPE_FMT; /* must be error, exit */ + /* the before and after byte count must be equal */ + if (bdata != edata) + return SCPE_FMT; /* must be error, exit */ } - return SCPE_OK; /* never here */ + return SCPE_OK; /* never here */ } #endif @@ -223,103 +223,103 @@ t_stat load_tap (FILE *fileref) * * *DEVXX=FCILCASA (,N) * - * *DEV defines a controller definition entry - * XX hex address that will be used by I/O instructions to address controller - * = required delimiter for following 8 hex characters - * F flag used for I/O emulation by CPU, not used but must be zero. - * C defines the class of controller: - * 0 = Line Printer - * 1 = Card Reader - * 2 = Teletype - * 3 = Interval Timer - * 4 = Panel - * 5-D Unassigned - * E = All Others - * F = Extended I/O - * IL Controller interrupt priority level of Service Interrupt (0x14 - 0x23) - * CA Controller address defined by hardware switches on controller - * SA Lowest controller device subaddress. Usually zero when only 1 device configured - * The subaddress field (SA) must reflect the following for TLC controller: - * 00 = Card Reader - * 01 = Teletype - * 02 = Line Printer - * () denotes optional parameter - * ,NN 2 digit hexx number of devices configured on the controller` + * *DEV defines a controller definition entry + * XX hex address that will be used by I/O instructions to address controller + * = required delimiter for following 8 hex characters + * F flag used for I/O emulation by CPU, not used but must be zero. + * C defines the class of controller: + * 0 = Line Printer + * 1 = Card Reader + * 2 = Teletype + * 3 = Interval Timer + * 4 = Panel + * 5-D Unassigned + * E = All Others + * F = Extended I/O + * IL Controller interrupt priority level of Service Interrupt (0x14 - 0x23) + * CA Controller address defined by hardware switches on controller + * SA Lowest controller device subaddress. Usually zero when only 1 device configured + * The subaddress field (SA) must reflect the following for TLC controller: + * 00 = Card Reader + * 01 = Teletype + * 02 = Line Printer + * () denotes optional parameter + * ,NN 2 digit hexx number of devices configured on the controller` * *********************************************** * * *INTXX=RS - * *INT defines interrupt definition entry - * XX Hex interrupt priority level to be defined - * = required delimiter for following 2 hex characters - * R Hex RTOM board number to which the interrupt XX is assigned - * S 1's complement of the hex subaddress of the RTOM board - * assigned to the interrupt XX + * *INT defines interrupt definition entry + * XX Hex interrupt priority level to be defined + * = required delimiter for following 2 hex characters + * R Hex RTOM board number to which the interrupt XX is assigned + * S 1's complement of the hex subaddress of the RTOM board + * assigned to the interrupt XX * - * RTOM physical controller address 0x79 is RTOM board number 1, RTOM - * address 0x7A is board number 2, etc. - * Real-Time Clock is connected tp subaddress 6 on RTOM board - * Interval Timer is connected to subaddress 4 on RTOM board - * RTOM physical address must be 0x79 or above to be able to - * support up to seven RTOM boards for maximum configuration - * of 112 interrupt levels (7 x 16). + * RTOM physical controller address 0x79 is RTOM board number 1, RTOM + * address 0x7A is board number 2, etc. + * Real-Time Clock is connected tp subaddress 6 on RTOM board + * Interval Timer is connected to subaddress 4 on RTOM board + * RTOM physical address must be 0x79 or above to be able to + * support up to seven RTOM boards for maximum configuration + * of 112 interrupt levels (7 x 16). * *********************************************** * * *END - * *END Defines the last record of the Initial Configuration Load file. + * *END Defines the last record of the Initial Configuration Load file. * *********************************************** */ /* Example device entry * *DEV04=0E140100,04 - * The controller is "E" class - * CPU command device address will be 0x04 - * The priority of the Service Interrupt is 0x14 - * The first device has suaddress of 00 and there are 4 devices defined - * There will be four devices defined in SPAD. The I/O commands (CD and TD) - * will address the devices as 0x04, 0x05, 0x06, and 0x07. - * The physical address of the controller is 0x10. - * Assigning SI address of 0x14 means: - * The transfer Interrupt location for priority 0x14 is 0x100. - * The Service Interrupt vector location for priority 0x14 is 0x140. - * The emulation IOCD will be stored at loation 0x700. - * The interrupt control instructions (DI, DI, RI, AI, DAI) will control - * the interrupt of the controller by addressing priority 0x14. + * The controller is "E" class + * CPU command device address will be 0x04 + * The priority of the Service Interrupt is 0x14 + * The first device has suaddress of 00 and there are 4 devices defined + * There will be four devices defined in SPAD. The I/O commands (CD and TD) + * will address the devices as 0x04, 0x05, 0x06, and 0x07. + * The physical address of the controller is 0x10. + * Assigning SI address of 0x14 means: + * The transfer Interrupt location for priority 0x14 is 0x100. + * The Service Interrupt vector location for priority 0x14 is 0x140. + * The emulation IOCD will be stored at loation 0x700. + * The interrupt control instructions (DI, DI, RI, AI, DAI) will control + * the interrupt of the controller by addressing priority 0x14. * - * Example interrupt entry (RTOM) - * *INT28=16 - * The interrupt control instructions (DI, EI, RI, AI, DAI) will control - * the interrupt on the RTOM by addressing priority 0x28. - * The RTOM board is 1 - * The subaddress on the board is 0x06 (jumpered locic subaddress is 9) + * Example interrupt entry (RTOM) + * *INT28=16 + * The interrupt control instructions (DI, EI, RI, AI, DAI) will control + * the interrupt on the RTOM by addressing priority 0x28. + * The RTOM board is 1 + * The subaddress on the board is 0x06 (jumpered locic subaddress is 9) */ /* * Example ICL file - * *DEV04=0E150400,02 Cartridge disc with two platters - * *DEV08=0E160800,04 Moving head disc - * *DEV10=0E181000,04 9-Track magnetic tape - * *DEV20=0E1A2000,10 GPMC with 16 terminals - * *DEV60=0E1E6000,08 ADS - * *DEV78=01207800 Primary card reader - * *DEV7A=00217802 Primary line printer - * *DEV7E=02237801 Primary Teletype - * *INT00=1F Power fail/Auto restart - * *INT01=1E System Overide - * *INT12=1D Memory parity - * *INT13=1C Console Interrupt - * *INT24=1B Nonpresent memory - * *INT25=1A Undefined instruction trap - * *INT26=19 Privlege violation - * *INT27=18 Call Monitor - * *INT28=16 Real-time clock - * *INT29=17 Arithmetic exception - * *INT2A=15 External interrupt - * *INT2B=14 External interrupt - * *INT2C=13 External interrupt - * *INT2D=12 External interrupt + * *DEV04=0E150400,02 Cartridge disc with two platters + * *DEV08=0E160800,04 Moving head disc + * *DEV10=0E181000,04 9-Track magnetic tape + * *DEV20=0E1A2000,10 GPMC with 16 terminals + * *DEV60=0E1E6000,08 ADS + * *DEV78=01207800 Primary card reader + * *DEV7A=00217802 Primary line printer + * *DEV7E=02237801 Primary Teletype + * *INT00=1F Power fail/Auto restart + * *INT01=1E System Overide + * *INT12=1D Memory parity + * *INT13=1C Console Interrupt + * *INT24=1B Nonpresent memory + * *INT25=1A Undefined instruction trap + * *INT26=19 Privlege violation + * *INT27=18 Call Monitor + * *INT28=16 Real-time clock + * *INT29=17 Arithmetic exception + * *INT2A=15 External interrupt + * *INT2B=14 External interrupt + * *INT2C=13 External interrupt + * *INT2D=12 External interrupt * *END */ @@ -331,27 +331,27 @@ t_stat load_tap (FILE *fileref) */ t_value get_2hex(char *pt, uint32 *val) { - int32 hexval; - uint32 c1 = sim_toupper((uint32)pt[0]); /* first hex char */ - uint32 c2 = sim_toupper((uint32)pt[1]); /* next hex char */ + int32 hexval; + uint32 c1 = sim_toupper((uint32)pt[0]); /* first hex char */ + uint32 c2 = sim_toupper((uint32)pt[1]); /* next hex char */ - if (isdigit(c1)) /* digit */ - hexval = c1 - (uint32)'0'; /* get value */ - else - if (isxdigit(c1)) /* hex digit */ - hexval = c1 - (uint32)'A' + 10; /* get hex value */ - else - return SCPE_ARG; /* oops, error */ - hexval <<= 4; /* move to upper nibble */ - if (isdigit(c2)) /* digit */ - hexval += c2 - (uint32)'0'; /* get value */ - else - if (isxdigit(c2)) /* hex digit */ - hexval += c2 - (uint32)'A' + 10; /* get hex value */ - else - return SCPE_ARG; /* oops, error */ - *val = hexval; /* return value to caller */ - return SCPE_OK; /* all OK */ + if (isdigit(c1)) /* digit */ + hexval = c1 - (uint32)'0'; /* get value */ + else + if (isxdigit(c1)) /* hex digit */ + hexval = c1 - (uint32)'A' + 10; /* get hex value */ + else + return SCPE_ARG; /* oops, error */ + hexval <<= 4; /* move to upper nibble */ + if (isdigit(c2)) /* digit */ + hexval += c2 - (uint32)'0'; /* get value */ + else + if (isxdigit(c2)) /* hex digit */ + hexval += c2 - (uint32)'A' + 10; /* get hex value */ + else + return SCPE_ARG; /* oops, error */ + *val = hexval; /* return value to caller */ + return SCPE_OK; /* all OK */ } /* load an ICL file and configure SPAD interupt and device entries */ @@ -359,126 +359,126 @@ t_value get_2hex(char *pt, uint32 *val) /* return SCPE_OK on load complete */ t_stat load_icl(FILE *fileref) { - char *cp; /* work pointer in buf[] */ - uint32 sa; /* spad address */ - uint32 dev; /* device entry */ - uint32 intr; /* interrupt entry */ - uint32 data; /* entry data */ - uint32 cls; /* device class */ - uint32 ivl; /* Interrupt Vector Location */ - int i; /* just a tmp */ - char buf[120]; /* input buffer */ + char *cp; /* work pointer in buf[] */ + uint32 sa; /* spad address */ + uint32 dev; /* device entry */ + uint32 intr; /* interrupt entry */ + uint32 data; /* entry data */ + uint32 cls; /* device class */ + uint32 ivl; /* Interrupt Vector Location */ + int i; /* just a tmp */ + char buf[120]; /* input buffer */ - /* read file input records until the end */ - while (fgets(&buf[0], 120, fileref) != 0) { - /* skip any white spaces */ - for(cp = &buf[0]; *cp == ' ' || *cp == '\t'; cp++); - if (*cp++ != '*') - continue; /* if line does not start with *, ignore */ - if(sim_strncasecmp(cp, "END", 3) == 0) { - return SCPE_OK; /* we are done */ - } - else - if(sim_strncasecmp(cp, "DEV", 3) == 0) { - /* process device entry */ - /* - |----+----+----+----+----+----+----+----| - |Flgs|CLS |0|Int Lev|0|Phy Adr|Sub Addr | - |----+----+----+----+----+----+----+----| - */ - for(cp += 3; *cp == ' ' || *cp == '\t'; cp++); /* skip white spaces */ - if (get_2hex(cp, &dev) != SCPE_OK) /* get the device address */ - return SCPE_ARG; /* unknown input, argument error */ - if (dev > 0x7f) /* devices are 0-7f (0-127) */ - return SCPE_ARG; /* argument error */ - sa = dev + 0x00; /* device entry spad address is dev# + 0x00 */ - cp += 2; /* skip the 2 processed chars */ - if (*cp++ != '=') /* must have = sign */ - return SCPE_ARG; /* unknown input, argument error */ - if (get_2hex(cp, &cls) != SCPE_OK) /* get unused '0" and class */ - return SCPE_ARG; /* unknown input, argument error */ - cp += 2; /* skip the 2 processed chars */ - if (get_2hex(cp, &intr) != SCPE_OK) /* get the interrupt level value */ - return SCPE_ARG; /* unknown input, argument error */ - if (intr > 0x6f) /* ints are 0-6f (0-111) */ - return SCPE_ARG; /* argument error */ - dev = ((~intr & 0x7f) << 16) | ((cls & 0x0f) << 24); /* put class and 1's intr in place */ - cp += 2; /* skip the 2 processed chars */ - if (get_2hex(cp, &data) != SCPE_OK) /* get the selbus physical address */ - return SCPE_ARG; /* unknown input, argument error */ - if (data > 0x7f) /* address is 0-7f (0-127) */ - return SCPE_ARG; /* argument error */ - dev |= (data & 0x7f) << 8; /* insert the physical address */ - cp += 2; /* skip the 2 processed chars */ - if (get_2hex(cp, &data) != SCPE_OK) /* get the starting sub address 0-ff (255) */ - return SCPE_ARG; /* unknown input, argument error */ - if (data > 0x7f) /* sub address is 0-ff (0-256) */ - return SCPE_ARG; /* argument error */ - if ((cls & 0xf) != 0xf) /* sub addr must be zero for class F */ - dev |= (data & 0xff); /* insert the starting sub address for non f class */ - SPAD[sa] = dev; /* put the first device entry into the spad */ - /* see if there is an optional device count for class 'E' I/O */ - if ((cls & 0xf) == 0xe) { - cp += 2; /* skip the 2 processed chars */ - if (*cp++ == ',') { /* must have comma if optional parameters */ - /* check for optional sub addr cnt */ - if (get_2hex(cp, &data) != SCPE_OK) /* get the count */ - return SCPE_ARG; /* unknown input, argument error */ - if (data > 0x10) /* sub address is max of 16 */ - return SCPE_ARG; /* argument error */ - for (i=0; i 0x7f) /* devices are 0-7f (0-127) */ + return SCPE_ARG; /* argument error */ + sa = dev + 0x00; /* device entry spad address is dev# + 0x00 */ + cp += 2; /* skip the 2 processed chars */ + if (*cp++ != '=') /* must have = sign */ + return SCPE_ARG; /* unknown input, argument error */ + if (get_2hex(cp, &cls) != SCPE_OK) /* get unused '0" and class */ + return SCPE_ARG; /* unknown input, argument error */ + cp += 2; /* skip the 2 processed chars */ + if (get_2hex(cp, &intr) != SCPE_OK) /* get the interrupt level value */ + return SCPE_ARG; /* unknown input, argument error */ + if (intr > 0x6f) /* ints are 0-6f (0-111) */ + return SCPE_ARG; /* argument error */ + dev = ((~intr & 0x7f) << 16) | ((cls & 0x0f) << 24); /* put class and 1's intr in place */ + cp += 2; /* skip the 2 processed chars */ + if (get_2hex(cp, &data) != SCPE_OK) /* get the selbus physical address */ + return SCPE_ARG; /* unknown input, argument error */ + if (data > 0x7f) /* address is 0-7f (0-127) */ + return SCPE_ARG; /* argument error */ + dev |= (data & 0x7f) << 8; /* insert the physical address */ + cp += 2; /* skip the 2 processed chars */ + if (get_2hex(cp, &data) != SCPE_OK) /* get the starting sub address 0-ff (255) */ + return SCPE_ARG; /* unknown input, argument error */ + if (data > 0x7f) /* sub address is 0-ff (0-256) */ + return SCPE_ARG; /* argument error */ + if ((cls & 0xf) != 0xf) /* sub addr must be zero for class F */ + dev |= (data & 0xff); /* insert the starting sub address for non f class */ + SPAD[sa] = dev; /* put the first device entry into the spad */ + /* see if there is an optional device count for class 'E' I/O */ + if ((cls & 0xf) == 0xe) { + cp += 2; /* skip the 2 processed chars */ + if (*cp++ == ',') { /* must have comma if optional parameters */ + /* check for optional sub addr cnt */ + if (get_2hex(cp, &data) != SCPE_OK) /* get the count */ + return SCPE_ARG; /* unknown input, argument error */ + if (data > 0x10) /* sub address is max of 16 */ + return SCPE_ARG; /* argument error */ + for (i=0; i 0x6f) /* ints are 0-6f (0-111) */ - return SCPE_ARG; /* argument error */ - sa = intr + 0x80; /* interrupt entry spad address is int# + 0x80 */ + sa = intr + 0x80; /* interrupt entry spad address is int# + 0x80 */ + ivl = (intr << 2) + 0x100; /* default IVL base is 0x100 for Concept machines */ + intr = (intr << 16) | ivl; /* combine int level and ivl */ + SPAD[sa] = intr; /* put the device interrupt entry into the spad */ + } + else + if(sim_strncasecmp(cp, "INT", 3) == 0) { + /* process interrupt entry */ + /* + |----+----+----+----+----+----+----+----| + | Flags |1RRR|SSSS| Int IVL | + |----+----+----+----+----+----+----+----| + */ + for(cp += 3; *cp == ' ' || *cp == '\t'; cp++); /* skip white spaces */ + if (get_2hex(cp, &intr) != SCPE_OK) /* get the interrupt level value */ + return SCPE_ARG; /* unknown input, argument error */ + if (intr > 0x6f) /* ints are 0-6f (0-111) */ + return SCPE_ARG; /* argument error */ + sa = intr + 0x80; /* interrupt entry spad address is int# + 0x80 */ /* TODO call function here to create 32/7x IVL location for interrupt */ /* if (CPU_MODEL < MODEL_27) get_IVL(intr, &ivl); */ - ivl = (intr << 2) + 0x100; /* default IVL base is 0x100 for Concept machines */ - cp += 2; /* skip the 2 processed chars */ - if (*cp++ != '=') /* must have = sign */ - return SCPE_ARG; /* unknown input, argument error */ - if (get_2hex(cp, &data) != SCPE_OK) - return SCPE_ARG; /* unknown input, argument error */ - /* first digit is 3 ls bits of RTOM addr 0x79 is 001 */ - intr = 0x00800000 | ((data & 0x70) << 16); /* put the RTOM 3 LSBs into entry */ - /* second digit is subaddress on RTOM board for interrupt connection, ~6 = 9 */ - intr |= (data & 0xf) << 16; /* put in 1's comp of RTOM subaddress */ - /* add in the correct IVL for 32/7x or concelt machines */ - intr |= ivl; /* set the IVL location */ - SPAD[sa] = intr; /* put the interrupt entry into the spad */ - } - else - return SCPE_ARG; /* unknown input, argument error */ - } - return SCPE_OK; /* file done */ + ivl = (intr << 2) + 0x100; /* default IVL base is 0x100 for Concept machines */ + cp += 2; /* skip the 2 processed chars */ + if (*cp++ != '=') /* must have = sign */ + return SCPE_ARG; /* unknown input, argument error */ + if (get_2hex(cp, &data) != SCPE_OK) + return SCPE_ARG; /* unknown input, argument error */ + /* first digit is 3 ls bits of RTOM addr 0x79 is 001 */ + intr = 0x00800000 | ((data & 0x70) << 16); /* put the RTOM 3 LSBs into entry */ + /* second digit is subaddress on RTOM board for interrupt connection, ~6 = 9 */ + intr |= (data & 0xf) << 16; /* put in 1's comp of RTOM subaddress */ + /* add in the correct IVL for 32/7x or concelt machines */ + intr |= ivl; /* set the IVL location */ + SPAD[sa] = intr; /* put the interrupt entry into the spad */ + } + else + return SCPE_ARG; /* unknown input, argument error */ + } + return SCPE_OK; /* file done */ } @@ -497,42 +497,42 @@ t_stat load_icl(FILE *fileref) #define FMT_ICL 3 t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag) { - int32 fmt; + int32 fmt; - fmt = FMT_NONE; /* no format */ - /* match the extension to .mem for this file */ - if (match_ext(fnam, "MEM")) - fmt = FMT_MEM; /* we have binary format */ - else + fmt = FMT_NONE; /* no format */ + /* match the extension to .mem for this file */ + if (match_ext(fnam, "MEM")) + fmt = FMT_MEM; /* we have binary format */ + else #ifdef NO_TAP_FOR_NOW - if (match_ext(fnam, "TAP")) - fmt = FMT_TAP; /* we have tap tape format */ - else + if (match_ext(fnam, "TAP")) + fmt = FMT_TAP; /* we have tap tape format */ + else #endif - /* match the extension to .icl for this file */ - if (match_ext(fnam, "ICL")) - fmt = FMT_ICL; /* we have initial configuration load (ICL) format */ - else - return SCPE_FMT; /* format error */ + /* match the extension to .icl for this file */ + if (match_ext(fnam, "ICL")) + fmt = FMT_ICL; /* we have initial configuration load (ICL) format */ + else + return SCPE_FMT; /* format error */ - switch (fmt) { + switch (fmt) { - case FMT_MEM: /* binary memory image */ - return load_mem(fileref); + case FMT_MEM: /* binary memory image */ + return load_mem(fileref); #ifdef NO_TAP_FOR_NOW - case FMT_TAP: /* tape file image */ - return load_tap(fileref); + case FMT_TAP: /* tape file image */ + return load_tap(fileref); #endif - case FMT_ICL: /* icl file image */ - return load_icl(fileref); + case FMT_ICL: /* icl file image */ + return load_icl(fileref); - case FMT_NONE: /* nothing */ - default: - break; - } - return SCPE_FMT; /* format error */ + case FMT_NONE: /* nothing */ + default: + break; + } + return SCPE_FMT; /* format error */ } /* Symbol tables */ @@ -570,11 +570,11 @@ t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag) #define TYPE_L 10 #define TYPE_M 11 #define TYPE_N 12 -#define H 0x10 /* halfword instruction */ +#define H 0x10 /* halfword instruction */ /* all instruction unless specified as base/nobase only will be either */ -#define B 0x20 /* base register mode only */ -#define N 0x40 /* non base register mode only */ -#define X 0x80 /* 32/55 or 32/75 only */ +#define B 0x20 /* base register mode only */ +#define N 0x40 /* non base register mode only */ +#define X 0x80 /* 32/55 or 32/75 only */ typedef struct _opcode { uint16 opbase; @@ -791,175 +791,175 @@ t_opcode optab[] = { Inputs: *of = output stream - val = 16/32 bit instruction to print left justified + val = 16/32 bit instruction to print left justified sw = mode switches, 'M'=base mode, 'N'=nonbase mode */ -char *fc_type = "WHDHBBBB"; /* F & C bit values */ +char *fc_type = "WHDHBBBB"; /* F & C bit values */ int fprint_inst(FILE *of, uint32 val, int32 sw) { - uint16 inst = (val >> 16) & 0xFFFF; - int i; - int mode = 0; /* assume non base mode instructions */ - t_opcode *tab; + uint16 inst = (val >> 16) & 0xFFFF; + int i; + int mode = 0; /* assume non base mode instructions */ + t_opcode *tab; #ifdef DO_THIS_UNTIL_FIGURE_IT_OUT - if (sw & SWMASK('M')) /* Base mode printing */ - mode = 1; + if (sw & SWMASK('M')) /* Base mode printing */ + mode = 1; #else - if (PSD[0] & 0x02000000) /* bit 6 is base mode */ - mode = 1; + if (PSD[0] & 0x02000000) /* bit 6 is base mode */ + mode = 1; #endif - /* loop through the instruction table for an opcode match and get the type */ - for (tab = optab; tab->name != NULL; tab++) { - if (tab->opbase == (inst & tab->mask)) { - if (mode && (tab->type & (X | N))) - continue; /* non basemode instruction in base mode, skip */ - if (!mode && (tab->type & B)) - continue; /* basemode instruction in nonbase mde, skip */ + /* loop through the instruction table for an opcode match and get the type */ + for (tab = optab; tab->name != NULL; tab++) { + if (tab->opbase == (inst & tab->mask)) { + if (mode && (tab->type & (X | N))) + continue; /* non basemode instruction in base mode, skip */ + if (!mode && (tab->type & B)) + continue; /* basemode instruction in nonbase mde, skip */ - /* TODO? Maybe want to make sure MODEL is 32/7X for X type instructions */ + /* TODO? Maybe want to make sure MODEL is 32/7X for X type instructions */ - /* match found */ - fputs(tab->name, of); /* output the base opcode */ + /* match found */ + fputs(tab->name, of); /* output the base opcode */ - /* process the other fields of the instruction */ - switch(tab->type & 0xF) { - /* memory reference instruction */ - case TYPE_A: /* r,[*]o[,x] or r,o[(b)][,x] */ - /* zero memory instruction */ - case TYPE_E: /* [*]o[,x] or o[(b)][,x] */ - /* append B, H, W, D to base instruction using F & C bits */ - i = (val & 3) | ((inst >> 1) & 04); - if (((inst&0xfc00) != 0xdc00) && ((inst&0xfc00) != 0xcc00) && - ((inst&0xfc00) != 0x8000)) - fputc(fc_type[i], of); - /* Fall through */ + /* process the other fields of the instruction */ + switch(tab->type & 0xF) { + /* memory reference instruction */ + case TYPE_A: /* r,[*]o[,x] or r,o[(b)][,x] */ + /* zero memory instruction */ + case TYPE_E: /* [*]o[,x] or o[(b)][,x] */ + /* append B, H, W, D to base instruction using F & C bits */ + i = (val & 3) | ((inst >> 1) & 04); + if (((inst&0xfc00) != 0xdc00) && ((inst&0xfc00) != 0xcc00) && + ((inst&0xfc00) != 0x8000)) + fputc(fc_type[i], of); + /* Fall through */ - /* BIx instructions or bit in memory reference instructions */ - case TYPE_D: /* r,[*]o[,x] or r,o[(b)],[,x] */ - if ((tab->type & 0xF) != TYPE_E) { - fputc(' ', of); - /* output the reg or bit number */ - fputc('0'+((inst>>7) & 07), of); - fputc(',', of); - } - /* Fall through */ + /* BIx instructions or bit in memory reference instructions */ + case TYPE_D: /* r,[*]o[,x] or r,o[(b)],[,x] */ + if ((tab->type & 0xF) != TYPE_E) { + fputc(' ', of); + /* output the reg or bit number */ + fputc('0'+((inst>>7) & 07), of); + fputc(',', of); + } + /* Fall through */ - /* branch instruction */ - case TYPE_B: /* [*]o[,x] or o[(b)],[,x] */ - if (((tab->type & 0xf) != TYPE_A) && ((tab->type & 0xf) != TYPE_D)) - fputc(' ', of); - if (mode) { - /* base reg mode */ - fprint_val(of, val&0xffff, 16, 16, PV_RZRO); /* output 16 bit offset */ - if (inst & 07) { - fputc('(', of); - fputc(('0'+(inst & 07)), of); /* output the base reg number */ - fputc(')', of); - } - if (inst & 0x70) { - fputc(',', of); - fputc(('0'+((inst >> 4) & 07)), of); /* output the index reg number */ - } - } else { - /* nonbase reg mode */ - if (inst & 0x10) - fputc('*', of); /* show indirection */ - fprint_val(of, val&0x7ffff, 16, 19, PV_LEFT); /* 19 bit offset */ - if (inst & 0x60) { - fputc(',', of); /* register coming */ - if (tab->type != TYPE_D) - fputc('0'+((inst & 0x60) >> 5), of); /* output the index reg number */ - else { - if ((inst & 0xfc00) != 0xf400) - fputc('0'+((inst & 0x60) >> 5), of); /* output the index reg number */ - } - } - } - break; + /* branch instruction */ + case TYPE_B: /* [*]o[,x] or o[(b)],[,x] */ + if (((tab->type & 0xf) != TYPE_A) && ((tab->type & 0xf) != TYPE_D)) + fputc(' ', of); + if (mode) { + /* base reg mode */ + fprint_val(of, val&0xffff, 16, 16, PV_RZRO); /* output 16 bit offset */ + if (inst & 07) { + fputc('(', of); + fputc(('0'+(inst & 07)), of); /* output the base reg number */ + fputc(')', of); + } + if (inst & 0x70) { + fputc(',', of); + fputc(('0'+((inst >> 4) & 07)), of); /* output the index reg number */ + } + } else { + /* nonbase reg mode */ + if (inst & 0x10) + fputc('*', of); /* show indirection */ + fprint_val(of, val&0x7ffff, 16, 19, PV_LEFT); /* 19 bit offset */ + if (inst & 0x60) { + fputc(',', of); /* register coming */ + if (tab->type != TYPE_D) + fputc('0'+((inst & 0x60) >> 5), of); /* output the index reg number */ + else { + if ((inst & 0xfc00) != 0xf400) + fputc('0'+((inst & 0x60) >> 5), of); /* output the index reg number */ + } + } + } + break; - /* immediate or XIO instructions */ - case TYPE_C: /* r,v */ - fputc(' ', of); - fputc('0'+((inst>>7) & 07), of); /* index reg number */ - fputc(',', of); - fprint_val(of, val&0xffff, 16, 16, PV_LEFT); /* 16 bit imm val or chan/suba */ - break; + /* immediate or XIO instructions */ + case TYPE_C: /* r,v */ + fputc(' ', of); + fputc('0'+((inst>>7) & 07), of); /* index reg number */ + fputc(',', of); + fprint_val(of, val&0xffff, 16, 16, PV_LEFT); /* 16 bit imm val or chan/suba */ + break; - /* reg - reg instructions */ - case TYPE_F: /* rs,rd */ - fputc(' ', of); - fputc('0'+((inst>>4) & 07), of); /* src reg */ - fputc(',', of); - fputc('0'+((inst>>7) & 07), of); /* dest reg */ - break; + /* reg - reg instructions */ + case TYPE_F: /* rs,rd */ + fputc(' ', of); + fputc('0'+((inst>>4) & 07), of); /* src reg */ + fputc(',', of); + fputc('0'+((inst>>7) & 07), of); /* dest reg */ + break; - /* single reg instructions */ - case TYPE_G: /* op r */ - fputc(' ', of); - fputc('0'+((inst>>7) & 07), of); /* output src/dest reg num */ - break; + /* single reg instructions */ + case TYPE_G: /* op r */ + fputc(' ', of); + fputc('0'+((inst>>7) & 07), of); /* output src/dest reg num */ + break; - /* just output the instruction */ - case TYPE_H: /* empty */ - break; + /* just output the instruction */ + case TYPE_H: /* empty */ + break; - /* reg and bit shift cnt */ - case TYPE_I: /* r,b */ - fputc(' ', of); - fputc('0'+((inst>>7) & 07), of); /* reg number */ - fputc(',', of); - fprint_val(of, inst&0x1f, 10, 5, PV_LEFT); /* 5 bit shift count */ - break; + /* reg and bit shift cnt */ + case TYPE_I: /* r,b */ + fputc(' ', of); + fputc('0'+((inst>>7) & 07), of); /* reg number */ + fputc(',', of); + fprint_val(of, inst&0x1f, 10, 5, PV_LEFT); /* 5 bit shift count */ + break; - /* register bit operations */ - case TYPE_K: /* r,rb */ - fputc(' ', of); - fputc('0'+((inst>>4) & 07), of); /* register number */ - fputc(',', of); - i = ((inst & 3) << 3) | ((inst >> 7) & 07); - fprint_val(of, i, 10, 5, PV_LEFT); /* reg bit number to operate on */ - break; + /* register bit operations */ + case TYPE_K: /* r,rb */ + fputc(' ', of); + fputc('0'+((inst>>4) & 07), of); /* register number */ + fputc(',', of); + i = ((inst & 3) << 3) | ((inst >> 7) & 07); + fprint_val(of, i, 10, 5, PV_LEFT); /* reg bit number to operate on */ + break; - /* interrupt control instructions */ - case TYPE_L: /* i */ - fputc(' ', of); - fprint_val(of, (inst>>3)&0x7f, 16, 7, PV_RZRO); /* output 7 bit priority level value */ - break; + /* interrupt control instructions */ + case TYPE_L: /* i */ + fputc(' ', of); + fprint_val(of, (inst>>3)&0x7f, 16, 7, PV_RZRO); /* output 7 bit priority level value */ + break; - /* CD/TD Class E I/O instructions */ - case TYPE_M: /* i,v */ - fputc(' ', of); - fprint_val(of, (inst>>3)&0x7f, 16, 7, PV_RZRO); /* output 7 bit device address */ - fputc(',', of); - fprint_val(of, (val&0xffff), 16, 16, PV_RZRO); /* output 16 bit command code */ - break; + /* CD/TD Class E I/O instructions */ + case TYPE_M: /* i,v */ + fputc(' ', of); + fprint_val(of, (inst>>3)&0x7f, 16, 7, PV_RZRO); /* output 7 bit device address */ + fputc(',', of); + fprint_val(of, (val&0xffff), 16, 16, PV_RZRO); /* output 16 bit command code */ + break; - /* SVC instructions */ - case TYPE_N: /* i,v */ - fputc(' ', of); - fprint_val(of, (val>>12)&0xf, 16, 4, PV_RZRO); /* output 4 bit svc number */ - fputc(',', of); - fprint_val(of, (val & 0xFFF), 16, 12, PV_LEFT); /* output 12 bit command code */ - break; + /* SVC instructions */ + case TYPE_N: /* i,v */ + fputc(' ', of); + fprint_val(of, (val>>12)&0xf, 16, 4, PV_RZRO); /* output 4 bit svc number */ + fputc(',', of); + fprint_val(of, (val & 0xFFF), 16, 12, PV_LEFT); /* output 12 bit command code */ + break; - default: - /* FIXME - return error code here? */ -// /* fputs(" unknown type", of); /* output error message */ -// return SCPE_ARG; /* unknown type */ - break; - } - /* return the size of the instruction */ - return (tab->type & H) ? 2 : 4; - } - } - /* FIXME - should we just return error here? or dump as hex data? */ - /* we get here if opcode not found, print data value */ - fputs(" invld ", of); /* output error message */ - fprint_val(of, val, 16, 32, PV_RZRO); /* output unknown 32 bit instruction code */ - return 4; /* show as full word size */ -// return SCPE_UNK; /* unknown opcode */ + default: + /* FIXME - return error code here? */ +// /* fputs(" unknown type", of); /* output error message */ +// return SCPE_ARG; /* unknown type */ + break; + } + /* return the size of the instruction */ + return (tab->type & H) ? 2 : 4; + } + } + /* FIXME - should we just return error here? or dump as hex data? */ + /* we get here if opcode not found, print data value */ + fputs(" invld ", of); /* output error message */ + fprint_val(of, val, 16, 32, PV_RZRO); /* output unknown 32 bit instruction code */ + return 4; /* show as full word size */ +// return SCPE_UNK; /* unknown opcode */ } /* Symbolic decode @@ -975,64 +975,64 @@ int fprint_inst(FILE *of, uint32 val, int32 sw) */ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) { - int i; - int l = 1; - int rdx = 16; - uint32 num, tmp=*val; + int i; + int l = 1; + int rdx = 16; + uint32 num, tmp=*val; - /* determine base for number output */ - if (sw & SWMASK ('D')) - rdx = 10; /* decimal */ - else - if (sw & SWMASK ('O')) - rdx = 8; /* octal */ - else - if (sw & SWMASK ('H')) - rdx = 16; /* hex */ + /* determine base for number output */ + if (sw & SWMASK ('D')) + rdx = 10; /* decimal */ + else + if (sw & SWMASK ('O')) + rdx = 8; /* octal */ + else + if (sw & SWMASK ('H')) + rdx = 16; /* hex */ - if (sw & SWMASK ('M')) { /* machine base mode? */ - sw &= ~ SWMASK('F'); /* Can't do F and M at same time */ - } else - if (sw & SWMASK('F')) { - l = 4; /* words are 4 bytes */ - } else - if (sw & SWMASK('W')) { - l = 2; /* halfwords are 2 bytes */ - } else - if (sw & SWMASK('B')) { - l = 1; /* bytes */ - } + if (sw & SWMASK ('M')) { /* machine base mode? */ + sw &= ~ SWMASK('F'); /* Can't do F and M at same time */ + } else + if (sw & SWMASK('F')) { + l = 4; /* words are 4 bytes */ + } else + if (sw & SWMASK('W')) { + l = 2; /* halfwords are 2 bytes */ + } else + if (sw & SWMASK('B')) { + l = 1; /* bytes */ + } - if (sw & SWMASK ('C')) { - fputc('\'', of); /* opening apostorphe */ - for(i = 0; i < l; i++) { - char ch = val[i] & 0xff; /* get the char */ - if (ch >= 0x20 && ch <= 0x7f) /* see if printable */ - fprintf(of, "%c", ch); /* output the ascii char */ - else - fputc('_', of); /* use underscore for unprintable char */ - } - fputc('\'', of); /* closing apostorphe */ - } else - /* go print the symbolic instruction for base or nonbase mode */ - if (sw & (SWMASK('M') | SWMASK('N'))) { - unsigned char ch; - num = 0; - for (i = 0; i < 4; i++) { - ch = tmp & 0xff; /* get the char */ - num |= (uint32)ch << ((3-i) * 8); /* get byte swapped 16/32 bit instruction */ - } - if (addr & 0x02) - tmp <<= 16; /* use rt hw */ - l = fprint_inst(of, tmp, sw); /* go print the instruction */ - } else { - /* print the numeric value of the memory data */ - num = 0; - for (i = 0; i < l && i < 4; i++) - num |= (uint32)val[i] << ((l-i-1) * 8); /* collect 8-32 bit data value to print */ - fprint_val(of, num, rdx, l*8, PV_RZRO); /* print it in requested radix */ - } - return -(l-1); /* will be negative if we did anything */ + if (sw & SWMASK ('C')) { + fputc('\'', of); /* opening apostorphe */ + for(i = 0; i < l; i++) { + char ch = val[i] & 0xff; /* get the char */ + if (ch >= 0x20 && ch <= 0x7f) /* see if printable */ + fprintf(of, "%c", ch); /* output the ascii char */ + else + fputc('_', of); /* use underscore for unprintable char */ + } + fputc('\'', of); /* closing apostorphe */ + } else + /* go print the symbolic instruction for base or nonbase mode */ + if (sw & (SWMASK('M') | SWMASK('N'))) { + unsigned char ch; + num = 0; + for (i = 0; i < 4; i++) { + ch = tmp & 0xff; /* get the char */ + num |= (uint32)ch << ((3-i) * 8); /* get byte swapped 16/32 bit instruction */ + } + if (addr & 0x02) + tmp <<= 16; /* use rt hw */ + l = fprint_inst(of, tmp, sw); /* go print the instruction */ + } else { + /* print the numeric value of the memory data */ + num = 0; + for (i = 0; i < l && i < 4; i++) + num |= (uint32)val[i] << ((l-i-1) * 8); /* collect 8-32 bit data value to print */ + fprint_val(of, num, rdx, l*8, PV_RZRO); /* print it in requested radix */ + } + return -(l-1); /* will be negative if we did anything */ } /* @@ -1040,24 +1040,24 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) */ t_stat get_off (CONST char *cptr, CONST char **tptr, uint32 radix, uint32 *val, char *m) { - t_stat r = SCPE_OK; /* assume OK return */ + t_stat r = SCPE_OK; /* assume OK return */ - *m = 0; /* left parend found flag if set */ - *val = (uint32)strtotv(cptr, tptr, radix); /* convert to value */ - if (cptr == *tptr) - r = SCPE_ARG; /* no argument found error */ - else { - cptr = *tptr; /* where to start looking */ - while (sim_isspace(*cptr)) - cptr++; /* skip any spaces */ - if (*cptr++ == '(') { - *m = 1; /* show we found a left parend */ - while (sim_isspace(*cptr)) - cptr++; /* skip any spaces */ - } - *tptr = cptr; /* return next char pointer */ - } - return r; /* return status */ + *m = 0; /* left parend found flag if set */ + *val = (uint32)strtotv(cptr, tptr, radix); /* convert to value */ + if (cptr == *tptr) + r = SCPE_ARG; /* no argument found error */ + else { + cptr = *tptr; /* where to start looking */ + while (sim_isspace(*cptr)) + cptr++; /* skip any spaces */ + if (*cptr++ == '(') { + *m = 1; /* show we found a left parend */ + while (sim_isspace(*cptr)) + cptr++; /* skip any spaces */ + } + *tptr = cptr; /* return next char pointer */ + } + return r; /* return status */ } /* @@ -1065,18 +1065,18 @@ t_stat get_off (CONST char *cptr, CONST char **tptr, uint32 radix, uint32 *val, */ t_stat get_imm (CONST char *cptr, CONST char **tptr, uint32 radix, uint32 *val) { - t_stat r; + t_stat r; - r = SCPE_OK; - *val = (uint32)strtotv (cptr, tptr, radix); - if ((cptr == *tptr) || (*val > 0xffff)) - r = SCPE_ARG; - else { - cptr = *tptr; - while (sim_isspace (*cptr)) cptr++; - *tptr = cptr; - } - return r; + r = SCPE_OK; + *val = (uint32)strtotv (cptr, tptr, radix); + if ((cptr == *tptr) || (*val > 0xffff)) + r = SCPE_ARG; + else { + cptr = *tptr; + while (sim_isspace (*cptr)) cptr++; + *tptr = cptr; + } + return r; } /* Symbolic input @@ -1093,492 +1093,492 @@ t_stat get_imm (CONST char *cptr, CONST char **tptr, uint32 radix, uint32 *val) t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) { - int i; - int x; - int l = 1; - int rdx = 16; - char mod = 0; - t_opcode *tab; - t_stat r; - uint32 num; - uint32 max[5] = {0, 0xff, 0xffff, 0, 0xffffffff}; - CONST char *tptr; - char gbuf[CBUFSIZE]; + int i; + int x; + int l = 1; + int rdx = 16; + char mod = 0; + t_opcode *tab; + t_stat r; + uint32 num; + uint32 max[5] = {0, 0xff, 0xffff, 0, 0xffffffff}; + CONST char *tptr; + char gbuf[CBUFSIZE]; - /* determine base for numbers */ - if (sw & SWMASK ('D')) - rdx = 10; /* decimal */ - else - if (sw & SWMASK ('O')) - rdx = 8; /* octal */ - else - if (sw & SWMASK ('H')) - rdx = 16; /* hex */ + /* determine base for numbers */ + if (sw & SWMASK ('D')) + rdx = 10; /* decimal */ + else + if (sw & SWMASK ('O')) + rdx = 8; /* octal */ + else + if (sw & SWMASK ('H')) + rdx = 16; /* hex */ - /* set instruction size */ - if (sw & SWMASK('F')) { - l = 4; - } else - if (sw & SWMASK('W')) { - l = 2; - } + /* set instruction size */ + if (sw & SWMASK('F')) { + l = 4; + } else + if (sw & SWMASK('W')) { + l = 2; + } - /* process a character string */ - if (sw & SWMASK ('C')) { - cptr = get_glyph_quoted(cptr, gbuf, 0); /* Get string */ - for(i = 0; gbuf[i] != 0; i++) { - val[i] = gbuf[i]; /* copy in the string */ - } - return -(i - 1); - } + /* process a character string */ + if (sw & SWMASK ('C')) { + cptr = get_glyph_quoted(cptr, gbuf, 0); /* Get string */ + for(i = 0; gbuf[i] != 0; i++) { + val[i] = gbuf[i]; /* copy in the string */ + } + return -(i - 1); + } - /* see if we are processing a nonbase instruction */ - if (sw & SWMASK ('N')) { - /* process nonbased instruction */ - cptr = get_glyph(cptr, gbuf, 0); /* Get uppercase opcode */ - l = strlen(gbuf); /* opcode length */ - /* try to find the opcode in the table */ - for (tab = optab; tab->name != NULL; tab++) { - i = tab->type & 0xf; /* get the instruction type */ - /* check for memory reference instruction */ - if (i == TYPE_A || i == TYPE_E) { - /* test for base opcode name without B, H, W, D applied */ - if (sim_strncasecmp(tab->name, gbuf, l - 1) == 0) - break; /* found */ - } else - /* test the full opcode name */ - if (sim_strcasecmp(tab->name, gbuf) == 0) - break; /* found */ - } - if (tab->name == NULL) /* see if anything found */ - return SCPE_ARG; /* no, return invalid argument error */ - num = tab->opbase<<16; /* get the base opcode value */ + /* see if we are processing a nonbase instruction */ + if (sw & SWMASK ('N')) { + /* process nonbased instruction */ + cptr = get_glyph(cptr, gbuf, 0); /* Get uppercase opcode */ + l = strlen(gbuf); /* opcode length */ + /* try to find the opcode in the table */ + for (tab = optab; tab->name != NULL; tab++) { + i = tab->type & 0xf; /* get the instruction type */ + /* check for memory reference instruction */ + if (i == TYPE_A || i == TYPE_E) { + /* test for base opcode name without B, H, W, D applied */ + if (sim_strncasecmp(tab->name, gbuf, l - 1) == 0) + break; /* found */ + } else + /* test the full opcode name */ + if (sim_strcasecmp(tab->name, gbuf) == 0) + break; /* found */ + } + if (tab->name == NULL) /* see if anything found */ + return SCPE_ARG; /* no, return invalid argument error */ + num = tab->opbase<<16; /* get the base opcode value */ - /* process each instruction type */ - switch(i) { - /* mem ref instruction */ - case TYPE_A: /* c r,[*]o[,x] */ - /* zero memory instruction */ - case TYPE_E: /* c [*]o[,x] */ - switch(gbuf[l]) { - case 'B': num |= 0x80000; break; /* byte, set F bit */ - case 'H': num |= 0x00001; break; /* halfword */ - case 'W': num |= 0x00000; break; /* word */ - case 'D': num |= 0x00002; break; /* doubleword */ - default: - return SCPE_ARG; /* base op suffix error */ - } - /* Fall through */ + /* process each instruction type */ + switch(i) { + /* mem ref instruction */ + case TYPE_A: /* c r,[*]o[,x] */ + /* zero memory instruction */ + case TYPE_E: /* c [*]o[,x] */ + switch(gbuf[l]) { + case 'B': num |= 0x80000; break; /* byte, set F bit */ + case 'H': num |= 0x00001; break; /* halfword */ + case 'W': num |= 0x00000; break; /* word */ + case 'D': num |= 0x00002; break; /* doubleword */ + default: + return SCPE_ARG; /* base op suffix error */ + } + /* Fall through */ - /* BIx instructions or memory reference */ - case TYPE_D: /* r,[*]o[,x] */ - while (sim_isspace(*cptr)) - cptr++; /* skip leading blanks */ - if (i != TYPE_E) { - /* get reg number except for zero memory instruction */ - if (*cptr >= '0' || *cptr <= '7') { /* reg# is 0-7 */ - x = *cptr++ - '0'; /* get the reg# */ - while (sim_isspace(*cptr)) - cptr++; /* skip any blanks */ - if (*cptr++ != ',') /* check for required comma */ - return SCPE_ARG; /* anything else is an argument error */ - num |= x << 23; /* position reg number in instruction */ - } else - return SCPE_ARG; /* invalid reg number is an argument error */ - } - /* Fall through */ + /* BIx instructions or memory reference */ + case TYPE_D: /* r,[*]o[,x] */ + while (sim_isspace(*cptr)) + cptr++; /* skip leading blanks */ + if (i != TYPE_E) { + /* get reg number except for zero memory instruction */ + if (*cptr >= '0' || *cptr <= '7') { /* reg# is 0-7 */ + x = *cptr++ - '0'; /* get the reg# */ + while (sim_isspace(*cptr)) + cptr++; /* skip any blanks */ + if (*cptr++ != ',') /* check for required comma */ + return SCPE_ARG; /* anything else is an argument error */ + num |= x << 23; /* position reg number in instruction */ + } else + return SCPE_ARG; /* invalid reg number is an argument error */ + } + /* Fall through */ - /* branch instruction */ - case TYPE_B: /* [*]o[,x] */ - if (*cptr == '*') { /* test for indirection */ - num |= 0x100000; /* set indirect flag */ - cptr++; /* skip past the '*' */ - while (sim_isspace(*cptr)) - cptr++; /* skip blanks */ - } - if ((r = get_off(cptr, &tptr, 16, val, &mod))) /* get operand address */ - return r; /* argument error if a problem */ - cptr = tptr; /* set pointer to returned next char pointer */ - if (*val > 0x7FFFF) /* 19 bit address max */ - return SCPE_ARG; /* argument error */ - num |= *val; /* or our address into instruction */ - if (mod) { - return SCPE_ARG; /* if a '(' found, that is an arg error */ - } - if (*cptr++ == ',') { /* test for optional index reg number */ - if (*cptr >= '0' || *cptr <= '7') { /* reg# is 0-7 */ - x = *cptr++ - '0'; /* get reg number */ - num |= x << 20; /* position and put into instruction */ - } else - return SCPE_ARG; /* reg# not 0-7, so arg error */ - } - break; + /* branch instruction */ + case TYPE_B: /* [*]o[,x] */ + if (*cptr == '*') { /* test for indirection */ + num |= 0x100000; /* set indirect flag */ + cptr++; /* skip past the '*' */ + while (sim_isspace(*cptr)) + cptr++; /* skip blanks */ + } + if ((r = get_off(cptr, &tptr, 16, val, &mod))) /* get operand address */ + return r; /* argument error if a problem */ + cptr = tptr; /* set pointer to returned next char pointer */ + if (*val > 0x7FFFF) /* 19 bit address max */ + return SCPE_ARG; /* argument error */ + num |= *val; /* or our address into instruction */ + if (mod) { + return SCPE_ARG; /* if a '(' found, that is an arg error */ + } + if (*cptr++ == ',') { /* test for optional index reg number */ + if (*cptr >= '0' || *cptr <= '7') { /* reg# is 0-7 */ + x = *cptr++ - '0'; /* get reg number */ + num |= x << 20; /* position and put into instruction */ + } else + return SCPE_ARG; /* reg# not 0-7, so arg error */ + } + break; - /* immediate or XIO instruction */ - case TYPE_C: /* r,v */ - while (sim_isspace(*cptr)) - cptr++; /* skip spaces */ - if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ - x = *cptr++ - '0'; /* get reg# */ - while (sim_isspace(*cptr)) - cptr++; /* skip spaces */ - if (*cptr++ != ',') /* next char need to be a comma */ - return SCPE_ARG; /* it's not, so arg error */ - num |= x << 23; /* position and put into instruction */ - } else - return SCPE_ARG; /* invalid reg#, so arg error */ - while (sim_isspace(*cptr)) - cptr++; /* skip any blanks */ - if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 16 bit immediate value */ - return r; /* return error from conversion */ - num |= *val; /* or in the 16 bit value */ - break; + /* immediate or XIO instruction */ + case TYPE_C: /* r,v */ + while (sim_isspace(*cptr)) + cptr++; /* skip spaces */ + if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ + x = *cptr++ - '0'; /* get reg# */ + while (sim_isspace(*cptr)) + cptr++; /* skip spaces */ + if (*cptr++ != ',') /* next char need to be a comma */ + return SCPE_ARG; /* it's not, so arg error */ + num |= x << 23; /* position and put into instruction */ + } else + return SCPE_ARG; /* invalid reg#, so arg error */ + while (sim_isspace(*cptr)) + cptr++; /* skip any blanks */ + if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 16 bit immediate value */ + return r; /* return error from conversion */ + num |= *val; /* or in the 16 bit value */ + break; - /* reg-reg instructions */ - case TYPE_F: /* r,r */ - while (sim_isspace(*cptr)) - cptr++; /* skip blanks */ - if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ - x = *cptr++ - '0'; /* calc reg# */ - while (sim_isspace(*cptr)) - cptr++; /* skip spaces */ - if (*cptr++ != ',') /* test for required ',' */ - return SCPE_ARG; /* it's not there, so error */ - num |= x << 23; /* insert first reg# into instruction */ - } else - return SCPE_ARG; /* reg# invalid, so arg error */ - while (sim_isspace(*cptr)) - cptr++; /* skip more spaces */ - if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ - x = *cptr++ - '0'; /* calc reg# */ - while (sim_isspace(*cptr)) - cptr++; /* skip any spaces */ - num |= x << 20; /* insert 2nd reg# into instruction */ - } else - return SCPE_ARG; /* reg# invalid, so arg error */ - break; + /* reg-reg instructions */ + case TYPE_F: /* r,r */ + while (sim_isspace(*cptr)) + cptr++; /* skip blanks */ + if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ + x = *cptr++ - '0'; /* calc reg# */ + while (sim_isspace(*cptr)) + cptr++; /* skip spaces */ + if (*cptr++ != ',') /* test for required ',' */ + return SCPE_ARG; /* it's not there, so error */ + num |= x << 23; /* insert first reg# into instruction */ + } else + return SCPE_ARG; /* reg# invalid, so arg error */ + while (sim_isspace(*cptr)) + cptr++; /* skip more spaces */ + if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ + x = *cptr++ - '0'; /* calc reg# */ + while (sim_isspace(*cptr)) + cptr++; /* skip any spaces */ + num |= x << 20; /* insert 2nd reg# into instruction */ + } else + return SCPE_ARG; /* reg# invalid, so arg error */ + break; - /* single reg instructions */ - case TYPE_G: /* r */ - while (sim_isspace(*cptr)) - cptr++; /* skip blanks */ - if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ - x = *cptr++ - '0'; /* calc reg# */ - while (sim_isspace(*cptr)) - cptr++; /* skip spaces */ - num |= x << 23; /* insert first reg# into instruction */ - } else - return SCPE_ARG; /* reg# invalid, so arg error */ - break; + /* single reg instructions */ + case TYPE_G: /* r */ + while (sim_isspace(*cptr)) + cptr++; /* skip blanks */ + if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ + x = *cptr++ - '0'; /* calc reg# */ + while (sim_isspace(*cptr)) + cptr++; /* skip spaces */ + num |= x << 23; /* insert first reg# into instruction */ + } else + return SCPE_ARG; /* reg# invalid, so arg error */ + break; - /* opcode only instructions */ - case TYPE_H: /* empty */ - break; + /* opcode only instructions */ + case TYPE_H: /* empty */ + break; - /* reg and bit shift instructions */ - case TYPE_I: /* r,b */ - while (sim_isspace (*cptr)) - cptr++; /* skip blanks */ - if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ - x = *cptr++ - '0'; /* calc reg# */ - while (sim_isspace(*cptr)) - cptr++; /* skip spaces */ - if (*cptr++ != ',') /* test for required ',' */ - return SCPE_ARG; /* it's not there, so error */ - num |= (x << 23); /* insert first reg# into instruction */ - } else - return SCPE_ARG; /* reg# invalid, so arg error */ - while (sim_isspace(*cptr)) - cptr++; /* skip any blanks */ - if ((r = get_imm(cptr, &tptr, 10, val))) /* get 5 bit shift value */ - return r; /* return error from conversion */ - if (*val > 0x1f) /* 5 bit max count */ - return SCPE_ARG; /* invalid shift count */ - num |= (*val << 16); /* or in the 5 bit value */ - break; + /* reg and bit shift instructions */ + case TYPE_I: /* r,b */ + while (sim_isspace (*cptr)) + cptr++; /* skip blanks */ + if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ + x = *cptr++ - '0'; /* calc reg# */ + while (sim_isspace(*cptr)) + cptr++; /* skip spaces */ + if (*cptr++ != ',') /* test for required ',' */ + return SCPE_ARG; /* it's not there, so error */ + num |= (x << 23); /* insert first reg# into instruction */ + } else + return SCPE_ARG; /* reg# invalid, so arg error */ + while (sim_isspace(*cptr)) + cptr++; /* skip any blanks */ + if ((r = get_imm(cptr, &tptr, 10, val))) /* get 5 bit shift value */ + return r; /* return error from conversion */ + if (*val > 0x1f) /* 5 bit max count */ + return SCPE_ARG; /* invalid shift count */ + num |= (*val << 16); /* or in the 5 bit value */ + break; - /* register bit operations */ - case TYPE_K: /* r,rb */ - while (sim_isspace(*cptr)) - cptr++; /* skip blanks */ - if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ - x = *cptr++ - '0'; /* calc reg# */ - while (sim_isspace(*cptr)) - cptr++; /* skip spaces */ - if (*cptr++ != ',') /* test for required ',' */ - return SCPE_ARG; /* it's not there, so error */ - num |= (x << 20); /* insert reg# into instruction */ - } else - return SCPE_ARG; /* reg# invalid, so arg error */ - while (sim_isspace(*cptr)) - cptr++; /* skip any blanks */ - if ((r = get_imm(cptr, &tptr, 10, val))) /* get 5 bit bit number */ - return r; /* return error from conversion */ - if (*val > 0x1f) /* 5 bit max count */ - return SCPE_ARG; /* invalid bit count */ - x = *val / 8; /* get 2 bit byte number */ - num |= (x & 3) << 16; /* insert 2 bit byte code into instruction */ - x = *val % 8; /* get bit in byte value */ - num |= (x & 7) << 23; /* or in the bit value */ - break; + /* register bit operations */ + case TYPE_K: /* r,rb */ + while (sim_isspace(*cptr)) + cptr++; /* skip blanks */ + if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ + x = *cptr++ - '0'; /* calc reg# */ + while (sim_isspace(*cptr)) + cptr++; /* skip spaces */ + if (*cptr++ != ',') /* test for required ',' */ + return SCPE_ARG; /* it's not there, so error */ + num |= (x << 20); /* insert reg# into instruction */ + } else + return SCPE_ARG; /* reg# invalid, so arg error */ + while (sim_isspace(*cptr)) + cptr++; /* skip any blanks */ + if ((r = get_imm(cptr, &tptr, 10, val))) /* get 5 bit bit number */ + return r; /* return error from conversion */ + if (*val > 0x1f) /* 5 bit max count */ + return SCPE_ARG; /* invalid bit count */ + x = *val / 8; /* get 2 bit byte number */ + num |= (x & 3) << 16; /* insert 2 bit byte code into instruction */ + x = *val % 8; /* get bit in byte value */ + num |= (x & 7) << 23; /* or in the bit value */ + break; - /* interrupt control instructions */ - case TYPE_L: /* i */ - while (sim_isspace(*cptr)) - cptr++; /* skip any blanks */ - if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 7 bit bit number */ - return r; /* return error from conversion */ - if (*val > 0x7f) /* 7 bit max count */ - return SCPE_ARG; /* invalid value */ - num |= (*val & 0x7f) << 19; /* or in the interrupt level */ - break; + /* interrupt control instructions */ + case TYPE_L: /* i */ + while (sim_isspace(*cptr)) + cptr++; /* skip any blanks */ + if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 7 bit bit number */ + return r; /* return error from conversion */ + if (*val > 0x7f) /* 7 bit max count */ + return SCPE_ARG; /* invalid value */ + num |= (*val & 0x7f) << 19; /* or in the interrupt level */ + break; - /* CD/TD Class E I/O instructions */ - case TYPE_M: /* d,v */ - while (sim_isspace(*cptr)) - cptr++; /* skip any blanks */ - if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 7 bit bit number */ - return r; /* return error from conversion */ - if (*val > 0x7f) /* 7 bit max count */ - return SCPE_ARG; /* invalid value */ - num |= (*val & 0x7f) << 19; /* or in the device address */ - while (sim_isspace(*cptr)) - cptr++; /* skip any blanks */ - if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 16 bit command code */ - return r; /* return error from conversion */ - num |= *val; /* or in the 16 bit value */ - break; - } - return (tab->type & H) ? 2 : 4; /* done with nonbased instructions */ - } + /* CD/TD Class E I/O instructions */ + case TYPE_M: /* d,v */ + while (sim_isspace(*cptr)) + cptr++; /* skip any blanks */ + if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 7 bit bit number */ + return r; /* return error from conversion */ + if (*val > 0x7f) /* 7 bit max count */ + return SCPE_ARG; /* invalid value */ + num |= (*val & 0x7f) << 19; /* or in the device address */ + while (sim_isspace(*cptr)) + cptr++; /* skip any blanks */ + if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 16 bit command code */ + return r; /* return error from conversion */ + num |= *val; /* or in the 16 bit value */ + break; + } + return (tab->type & H) ? 2 : 4; /* done with nonbased instructions */ + } - /* see if we are processing a base mode instruction */ - if (sw & SWMASK ('M')) { /* base mode? */ - /* process base mode instruction */ - cptr = get_glyph(cptr, gbuf, 0); /* Get uppercase opcode */ - l = strlen(gbuf); /* save the num of char in opcode */ - /* loop through the instruction table for an opcode match and get the type */ - for (tab = optab; tab->name != NULL; tab++) { - i = tab->type & 0xf; /* get the type */ - /* check for memory reference instruction */ - if (i == TYPE_A || i == TYPE_E) { - /* test for base opcode name without B, H, W, D applied */ - if (sim_strncasecmp(tab->name, gbuf, l - 1) == 0) - break; /* found */ - } else - /* test the full opcode name */ - if (sim_strcasecmp(tab->name, gbuf) == 0) - break; /* found */ - } - if (tab->name == NULL) /* see if anything found */ - return SCPE_ARG; /* no, return invalid argument error */ - num = tab->opbase<<16; /* get the base opcode value */ + /* see if we are processing a base mode instruction */ + if (sw & SWMASK ('M')) { /* base mode? */ + /* process base mode instruction */ + cptr = get_glyph(cptr, gbuf, 0); /* Get uppercase opcode */ + l = strlen(gbuf); /* save the num of char in opcode */ + /* loop through the instruction table for an opcode match and get the type */ + for (tab = optab; tab->name != NULL; tab++) { + i = tab->type & 0xf; /* get the type */ + /* check for memory reference instruction */ + if (i == TYPE_A || i == TYPE_E) { + /* test for base opcode name without B, H, W, D applied */ + if (sim_strncasecmp(tab->name, gbuf, l - 1) == 0) + break; /* found */ + } else + /* test the full opcode name */ + if (sim_strcasecmp(tab->name, gbuf) == 0) + break; /* found */ + } + if (tab->name == NULL) /* see if anything found */ + return SCPE_ARG; /* no, return invalid argument error */ + num = tab->opbase<<16; /* get the base opcode value */ - /* process each instruction type */ - switch(i) { - /* mem ref instruction */ - case TYPE_A: /* c r,o[(b)][,x] */ - /* zero memory instruction */ - case TYPE_E: /* c o[(b)][,x] */ - switch(gbuf[l]) { - case 'B': num |= 0x80000; break; /* byte, set F bit */ - case 'H': num |= 0x00001; break; /* halfword */ - case 'W': num |= 0x00000; break; /* word */ - case 'D': num |= 0x00002; break; /* doubleword */ - default: - return SCPE_ARG; /* base op suffix error */ - } - /* Fall through */ + /* process each instruction type */ + switch(i) { + /* mem ref instruction */ + case TYPE_A: /* c r,o[(b)][,x] */ + /* zero memory instruction */ + case TYPE_E: /* c o[(b)][,x] */ + switch(gbuf[l]) { + case 'B': num |= 0x80000; break; /* byte, set F bit */ + case 'H': num |= 0x00001; break; /* halfword */ + case 'W': num |= 0x00000; break; /* word */ + case 'D': num |= 0x00002; break; /* doubleword */ + default: + return SCPE_ARG; /* base op suffix error */ + } + /* Fall through */ - /* BIx instructions or memory reference */ - case TYPE_D: /* r,o[(b)],[,x] */ - while (sim_isspace(*cptr)) - cptr++; /* skip leading blanks */ - if (i != TYPE_E) { - /* get reg number except for zero memory instruction */ - if (*cptr >= '0' || *cptr <= '7') { /* reg# is 0-7 */ - x = *cptr++ - '0'; /* get the reg# */ - while (sim_isspace(*cptr)) - cptr++; /* skip any blanks */ - if (*cptr++ != ',') /* check for required comma */ - return SCPE_ARG; /* anything else is an argument error */ - num |= x << 23; /* position reg number in instruction */ - } else - return SCPE_ARG; /* invalid reg number is an argument error */ - } + /* BIx instructions or memory reference */ + case TYPE_D: /* r,o[(b)],[,x] */ + while (sim_isspace(*cptr)) + cptr++; /* skip leading blanks */ + if (i != TYPE_E) { + /* get reg number except for zero memory instruction */ + if (*cptr >= '0' || *cptr <= '7') { /* reg# is 0-7 */ + x = *cptr++ - '0'; /* get the reg# */ + while (sim_isspace(*cptr)) + cptr++; /* skip any blanks */ + if (*cptr++ != ',') /* check for required comma */ + return SCPE_ARG; /* anything else is an argument error */ + num |= x << 23; /* position reg number in instruction */ + } else + return SCPE_ARG; /* invalid reg number is an argument error */ + } /* Fall through */ - /* branch instruction */ - case TYPE_B: /* o[(b)],[,x] */ - if ((r = get_off(cptr, &tptr, 16, val, &mod))) /* get offset */ - return r; /* argument error if a problem */ - cptr = tptr; /* set pointer to returned next char pointer */ - if (*val > 0xFFFF) /* 16 bit offset max */ - return SCPE_ARG; /* argument error */ - num |= *val; /* or offset into instruction */ - if (mod) { /* see if '(' found in input */ - if (*cptr >= '0' || *cptr <= '7') { /* base reg# 0-7 */ - x = *cptr++ - '0'; /* get reg number */ - while (sim_isspace(*cptr)) - cptr++; /* skip any spaces */ - if (*cptr++ != ')') /* test for closing right parend */ - return SCPE_ARG; /* arg error if not found */ - num |= x << 16; /* put base reg number into instruction */ - } else - return SCPE_ARG; /* no '(' found, so arg error */ - } - if (*cptr++ == ',') { /* test for optional index reg number */ - if (*cptr >= '0' || *cptr <= '7') { /* reg# is 0-7 */ - x = *cptr++ - '0'; /* get reg number */ - num |= x << 20; /* position and put into instruction */ - } else - return SCPE_ARG; /* reg# not 0-7, so arg error */ - } - break; + /* branch instruction */ + case TYPE_B: /* o[(b)],[,x] */ + if ((r = get_off(cptr, &tptr, 16, val, &mod))) /* get offset */ + return r; /* argument error if a problem */ + cptr = tptr; /* set pointer to returned next char pointer */ + if (*val > 0xFFFF) /* 16 bit offset max */ + return SCPE_ARG; /* argument error */ + num |= *val; /* or offset into instruction */ + if (mod) { /* see if '(' found in input */ + if (*cptr >= '0' || *cptr <= '7') { /* base reg# 0-7 */ + x = *cptr++ - '0'; /* get reg number */ + while (sim_isspace(*cptr)) + cptr++; /* skip any spaces */ + if (*cptr++ != ')') /* test for closing right parend */ + return SCPE_ARG; /* arg error if not found */ + num |= x << 16; /* put base reg number into instruction */ + } else + return SCPE_ARG; /* no '(' found, so arg error */ + } + if (*cptr++ == ',') { /* test for optional index reg number */ + if (*cptr >= '0' || *cptr <= '7') { /* reg# is 0-7 */ + x = *cptr++ - '0'; /* get reg number */ + num |= x << 20; /* position and put into instruction */ + } else + return SCPE_ARG; /* reg# not 0-7, so arg error */ + } + break; - /* immediate or XIO instruction */ - case TYPE_C: /* r,v */ - while (sim_isspace(*cptr)) - cptr++; /* skip spaces */ - if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ - x = *cptr++ - '0'; /* get reg# */ - while (sim_isspace(*cptr)) - cptr++; /* skip spaces */ - if (*cptr++ != ',') /* next char need to be a comma */ - return SCPE_ARG; /* it's not, so arg error */ - num |= x << 23; /* position and put into instruction */ - } else - return SCPE_ARG; /* invalid reg#, so arg error */ - while (sim_isspace(*cptr)) - cptr++; /* skip any blanks */ - if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 16 bit immediate value */ - return r; /* return error from conversion */ - num |= *val; /* or in the 16 bit value */ - break; + /* immediate or XIO instruction */ + case TYPE_C: /* r,v */ + while (sim_isspace(*cptr)) + cptr++; /* skip spaces */ + if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ + x = *cptr++ - '0'; /* get reg# */ + while (sim_isspace(*cptr)) + cptr++; /* skip spaces */ + if (*cptr++ != ',') /* next char need to be a comma */ + return SCPE_ARG; /* it's not, so arg error */ + num |= x << 23; /* position and put into instruction */ + } else + return SCPE_ARG; /* invalid reg#, so arg error */ + while (sim_isspace(*cptr)) + cptr++; /* skip any blanks */ + if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 16 bit immediate value */ + return r; /* return error from conversion */ + num |= *val; /* or in the 16 bit value */ + break; - /* reg-reg instructions */ - case TYPE_F: /* r,r */ - while (sim_isspace(*cptr)) - cptr++; /* skip blanks */ - if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ - x = *cptr++ - '0'; /* calc reg# */ - while (sim_isspace(*cptr)) - cptr++; /* skip spaces */ - if (*cptr++ != ',') /* test for required ',' */ - return SCPE_ARG; /* it's not there, so error */ - num |= x << 23; /* insert first reg# into instruction */ - } else - return SCPE_ARG; /* reg# invalid, so arg error */ - while (sim_isspace(*cptr)) - cptr++; /* skip more spaces */ - if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ - x = *cptr++ - '0'; /* calc reg# */ - while (sim_isspace(*cptr)) - cptr++; /* skip any spaces */ - num |= x << 20; /* insert 2nd reg# into instruction */ - } else - return SCPE_ARG; /* reg# invalid, so arg error */ - break; + /* reg-reg instructions */ + case TYPE_F: /* r,r */ + while (sim_isspace(*cptr)) + cptr++; /* skip blanks */ + if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ + x = *cptr++ - '0'; /* calc reg# */ + while (sim_isspace(*cptr)) + cptr++; /* skip spaces */ + if (*cptr++ != ',') /* test for required ',' */ + return SCPE_ARG; /* it's not there, so error */ + num |= x << 23; /* insert first reg# into instruction */ + } else + return SCPE_ARG; /* reg# invalid, so arg error */ + while (sim_isspace(*cptr)) + cptr++; /* skip more spaces */ + if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ + x = *cptr++ - '0'; /* calc reg# */ + while (sim_isspace(*cptr)) + cptr++; /* skip any spaces */ + num |= x << 20; /* insert 2nd reg# into instruction */ + } else + return SCPE_ARG; /* reg# invalid, so arg error */ + break; - /* single reg instructions */ - case TYPE_G: /* r */ - while (sim_isspace(*cptr)) - cptr++; /* skip blanks */ - if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ - x = *cptr++ - '0'; /* calc reg# */ - while (sim_isspace(*cptr)) - cptr++; /* skip spaces */ - num |= x << 23; /* insert first reg# into instruction */ - } else - return SCPE_ARG; /* reg# invalid, so arg error */ - break; + /* single reg instructions */ + case TYPE_G: /* r */ + while (sim_isspace(*cptr)) + cptr++; /* skip blanks */ + if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ + x = *cptr++ - '0'; /* calc reg# */ + while (sim_isspace(*cptr)) + cptr++; /* skip spaces */ + num |= x << 23; /* insert first reg# into instruction */ + } else + return SCPE_ARG; /* reg# invalid, so arg error */ + break; - /* opcode only instructions */ - case TYPE_H: /* empty */ - break; + /* opcode only instructions */ + case TYPE_H: /* empty */ + break; - /* reg and bit shift instructions */ - case TYPE_I: /* r,b */ - while (sim_isspace(*cptr)) - cptr++; /* skip blanks */ - if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ - x = *cptr++ - '0'; /* calc reg# */ - while (sim_isspace(*cptr)) - cptr++; /* skip spaces */ - if (*cptr++ != ',') /* test for required ',' */ - return SCPE_ARG; /* it's not there, so error */ - num |= (x << 23); /* insert first reg# into instruction */ - } else - return SCPE_ARG; /* reg# invalid, so arg error */ - while (sim_isspace(*cptr)) - cptr++; /* skip any blanks */ - if ((r = get_imm(cptr, &tptr, 10, val))) /* get 5 bit shift value */ - return r; /* return error from conversion */ - if (*val > 0x1f) /* 5 bit max count */ - return SCPE_ARG; /* invalid shift count */ - num |= (*val << 16); /* or in the 5 bit value */ - break; + /* reg and bit shift instructions */ + case TYPE_I: /* r,b */ + while (sim_isspace(*cptr)) + cptr++; /* skip blanks */ + if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ + x = *cptr++ - '0'; /* calc reg# */ + while (sim_isspace(*cptr)) + cptr++; /* skip spaces */ + if (*cptr++ != ',') /* test for required ',' */ + return SCPE_ARG; /* it's not there, so error */ + num |= (x << 23); /* insert first reg# into instruction */ + } else + return SCPE_ARG; /* reg# invalid, so arg error */ + while (sim_isspace(*cptr)) + cptr++; /* skip any blanks */ + if ((r = get_imm(cptr, &tptr, 10, val))) /* get 5 bit shift value */ + return r; /* return error from conversion */ + if (*val > 0x1f) /* 5 bit max count */ + return SCPE_ARG; /* invalid shift count */ + num |= (*val << 16); /* or in the 5 bit value */ + break; - /* register bit operations */ - case TYPE_K: /* r,rb */ - while (sim_isspace(*cptr)) - cptr++; /* skip blanks */ - if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ - x = *cptr++ - '0'; /* calc reg# */ - while (sim_isspace(*cptr)) - cptr++; /* skip spaces */ - if (*cptr++ != ',') /* test for required ',' */ - return SCPE_ARG; /* it's not there, so error */ - num |= (x << 20); /* insert reg# into instruction */ - } else - return SCPE_ARG; /* reg# invalid, so arg error */ - while (sim_isspace(*cptr)) - cptr++; /* skip any blanks */ - if ((r = get_imm(cptr, &tptr, 10, val))) /* get 5 bit bit number */ - return r; /* return error from conversion */ - if (*val > 0x1f) /* 5 bit max count */ - return SCPE_ARG; /* invalid bit count */ - x = *val / 8; /* get 2 bit byte number */ - num |= (x & 3) << 16; /* insert 2 bit byte code into instruction */ - x = *val % 8; /* get bit in byte value */ - num |= (x & 7) << 23; /* or in the bit value */ - break; + /* register bit operations */ + case TYPE_K: /* r,rb */ + while (sim_isspace(*cptr)) + cptr++; /* skip blanks */ + if (*cptr >= '0' || *cptr <= '7') { /* test for valid reg# */ + x = *cptr++ - '0'; /* calc reg# */ + while (sim_isspace(*cptr)) + cptr++; /* skip spaces */ + if (*cptr++ != ',') /* test for required ',' */ + return SCPE_ARG; /* it's not there, so error */ + num |= (x << 20); /* insert reg# into instruction */ + } else + return SCPE_ARG; /* reg# invalid, so arg error */ + while (sim_isspace(*cptr)) + cptr++; /* skip any blanks */ + if ((r = get_imm(cptr, &tptr, 10, val))) /* get 5 bit bit number */ + return r; /* return error from conversion */ + if (*val > 0x1f) /* 5 bit max count */ + return SCPE_ARG; /* invalid bit count */ + x = *val / 8; /* get 2 bit byte number */ + num |= (x & 3) << 16; /* insert 2 bit byte code into instruction */ + x = *val % 8; /* get bit in byte value */ + num |= (x & 7) << 23; /* or in the bit value */ + break; - /* interrupt control instructions */ - case TYPE_L: /* i */ - while (sim_isspace(*cptr)) - cptr++; /* skip any blanks */ - if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 7 bit bit number */ - return r; /* return error from conversion */ - if (*val > 0x7f) /* 7 bit max count */ - return SCPE_ARG; /* invalid value */ - num |= (*val & 0x7f) << 19; /* or in the interrupt level */ - break; + /* interrupt control instructions */ + case TYPE_L: /* i */ + while (sim_isspace(*cptr)) + cptr++; /* skip any blanks */ + if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 7 bit bit number */ + return r; /* return error from conversion */ + if (*val > 0x7f) /* 7 bit max count */ + return SCPE_ARG; /* invalid value */ + num |= (*val & 0x7f) << 19; /* or in the interrupt level */ + break; - /* CD/TD Class E I/O instructions */ - case TYPE_M: /* d,v */ - while (sim_isspace(*cptr)) - cptr++; /* skip any blanks */ - if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 7 bit bit number */ - return r; /* return error from conversion */ - if (*val > 0x7f) /* 7 bit max count */ - return SCPE_ARG; /* invalid value */ - num |= (*val & 0x7f) << 19; /* or in the device address */ - while (sim_isspace(*cptr)) - cptr++; /* skip any blanks */ - if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 16 bit command code */ - return r; /* return error from conversion */ - num |= *val; /* or in the 16 bit value */ - break; - } - return (tab->type & H) ? 2 : 4; /* done with base mode insrructions */ - } + /* CD/TD Class E I/O instructions */ + case TYPE_M: /* d,v */ + while (sim_isspace(*cptr)) + cptr++; /* skip any blanks */ + if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 7 bit bit number */ + return r; /* return error from conversion */ + if (*val > 0x7f) /* 7 bit max count */ + return SCPE_ARG; /* invalid value */ + num |= (*val & 0x7f) << 19; /* or in the device address */ + while (sim_isspace(*cptr)) + cptr++; /* skip any blanks */ + if ((r = get_imm(cptr, &tptr, rdx, val))) /* get 16 bit command code */ + return r; /* return error from conversion */ + num |= *val; /* or in the 16 bit value */ + break; + } + return (tab->type & H) ? 2 : 4; /* done with base mode insrructions */ + } - /* get here for any other switch value */ - /* this code will get a value based on length specified in switches */ - num = get_uint(cptr, rdx, max[l], &r); /* get the unsigned value */ - for (i = 0; i < l && i < 4; i++) - val[i] = (num >> (i * 8)) & 0xff; /* get 1-4 bytes of data */ - return -(l-1); + /* get here for any other switch value */ + /* this code will get a value based on length specified in switches */ + num = get_uint(cptr, rdx, max[l], &r); /* get the unsigned value */ + for (i = 0; i < l && i < 4; i++) + val[i] = (num >> (i * 8)) & 0xff; /* get 1-4 bytes of data */ + return -(l-1); }