mirror of
https://github.com/rcornwell/sims.git
synced 2026-01-13 07:19:26 +00:00
SEL32: Correct real time clock interrupt processing.
SEL32: start code cleanup. SEL32: add mfp and mfp scsi disk intitial support code. SEL32: add new files sel32_mfp.c and sel32_scsi.c to makefile. SEL32: modify sel32_mt.c code to define tape as BTP for UTX.
This commit is contained in:
parent
5ae42ddddd
commit
d198882980
@ -102,11 +102,11 @@ uint16 loading; /* set when booting */
|
||||
/* forward definitions */
|
||||
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);
|
||||
int chan_read_byte(uint16 chsa, uint8 *data);
|
||||
int chan_write_byte(uint16 chsa, uint8 *data);
|
||||
void set_devattn(uint16 chsa, uint16 flags);
|
||||
void set_devwake(uint16 chsa, uint16 flags); /* wakeup O/S for async line */
|
||||
void chan_end(uint16 chan, uint16 flags);
|
||||
void chan_end(uint16 chsa, uint16 flags);
|
||||
int test_write_byte_end(uint16 chsa);
|
||||
t_stat checkxio(uint16 chsa, uint32 *status); /* check XIO */
|
||||
t_stat startxio(uint16 chsa, uint32 *status); /* start XIO */
|
||||
@ -125,6 +125,7 @@ t_stat chan_set_devs();
|
||||
t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||
t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc);
|
||||
DEVICE *get_dev(UNIT *uptr);
|
||||
void store_csw(CHANP *chp);
|
||||
|
||||
/* FIFO support */
|
||||
/* These are FIFO queues which return an error when full.
|
||||
@ -173,7 +174,7 @@ int FIFO_Get(uint16 chsa, uint32 *old)
|
||||
t_stat set_inch(UNIT *uptr, uint32 inch_addr) {
|
||||
uint16 chsa = GET_UADDR(uptr->u3); /* get channel & sub address */
|
||||
uint32 chan = chsa & 0x7f00; /* get just channel address */
|
||||
CHANP *pchp = find_chanp_ptr(chan); /* get channel channel prog ptr */
|
||||
CHANP *pchp = find_chanp_ptr(chan); /* get channel prog ptr */
|
||||
DIB *dibp; /* get DIB pointer for channel */
|
||||
CHANP *chp;
|
||||
int i;
|
||||
@ -320,7 +321,7 @@ CHANP *find_chanp_ptr(uint16 chsa)
|
||||
CHANP *chp; /* CHANP pointer */
|
||||
int i;
|
||||
|
||||
dibp = dev_unit[chsa]; /* get DIB pointer from device pointers */
|
||||
dibp = dev_unit[chsa&0x7fff]; /* 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 */
|
||||
@ -369,10 +370,13 @@ int readbuff(CHANP *chp)
|
||||
{
|
||||
int k;
|
||||
uint32 addr = chp->ccw_addr; /* channel buffer address */
|
||||
uint16 chan = get_chan(chp->chan_dev); /* our channel */
|
||||
//XXX uint16 chan = get_chan(chp->chan_dev); /* our channel */
|
||||
|
||||
if ((addr & MASK24) >= (MEMSIZE*4)) { /* see if memory address invalid */
|
||||
chp->chan_status |= STATUS_PCHK; /* bad, program check */
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"readbuff PCHK addr %08x to big mem %08x status %04x\n",
|
||||
addr, MEMSIZE, chp->chan_status);
|
||||
chp->chan_byte = BUFF_CHNEND; /* force channel end */
|
||||
irq_pend = 1; /* and we have an interrupt */
|
||||
return 1; /* done, with error */
|
||||
@ -386,8 +390,9 @@ int readbuff(CHANP *chp)
|
||||
#endif
|
||||
|
||||
#ifdef TEST
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "readbuff read memory bytes into buffer %02x %06x %06x %04x [",
|
||||
chan, chp->ccw_addr & 0xFFFFFC, chp->chan_buf, chp->ccw_count);
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"readbuff read memory chsa %04x into buffer %06x %06x %04x [",
|
||||
chp->chan_dev, 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)
|
||||
@ -409,7 +414,7 @@ int writebuff(CHANP *chp)
|
||||
|
||||
if ((addr & MASK24) >= (MEMSIZE*4)) {
|
||||
chp->chan_status |= STATUS_PCHK;
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"writebuff PCHK addr %08x to big mem %08x status %04x\n",
|
||||
addr, MEMSIZE, chp->chan_status);
|
||||
chp->chan_byte = BUFF_CHNEND;
|
||||
@ -423,7 +428,7 @@ int writebuff(CHANP *chp)
|
||||
#ifdef TEST
|
||||
M[addr>>2] = chp->chan_buf;
|
||||
#else
|
||||
WMB(addr, chp->chan_buf); /* write byte to bebory */
|
||||
WMB(addr, chp->chan_buf); /* write byte to memory */
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -434,7 +439,6 @@ int writebuff(CHANP *chp)
|
||||
int load_ccw(CHANP *chp, int tic_ok)
|
||||
{
|
||||
uint32 word;
|
||||
// uint8 devstat;
|
||||
int docmd = 0;
|
||||
UNIT *uptr = find_unit_ptr(chp->chan_dev); /* find the unit pointer */
|
||||
uint16 chan = get_chan(chp->chan_dev); /* our channel */
|
||||
@ -567,24 +571,27 @@ loop:
|
||||
}
|
||||
#endif
|
||||
if (docmd) { /* see if we need to process command */
|
||||
#ifdef TRY_THIS_TUESDAY_0301
|
||||
uint8 devstat;
|
||||
#endif
|
||||
// DEVICE *dptr = get_dev(uptr); /* find the device from unit pointer */
|
||||
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_XIO, &cpu_dev,
|
||||
"load_ccw before start_cmd chan %04x status %04x count %04x\n",
|
||||
// chan, chp->chan_status, chp->ccw_count, dptr->name);
|
||||
chan, chp->chan_status, chp->ccw_count);
|
||||
|
||||
/* call the device startcmd function to process the current command */
|
||||
#ifndef TRY_THIS_TUESDAY
|
||||
#ifndef TRY_THIS_TUESDAY_0301
|
||||
chp->chan_status = dibp->start_cmd(uptr, chan, chp->ccw_cmd);
|
||||
#else
|
||||
/* just replace device status bits */
|
||||
devstat = dibp->start_cmd(uptr, chan, chp->ccw_cmd);
|
||||
chp->chan_status = (chp->chan_status & 0xffffff00) | (devstat & 0xff);
|
||||
chp->chan_status = (chp->chan_status & 0xff00) | (devstat & 0xff);
|
||||
#endif
|
||||
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
@ -612,6 +619,9 @@ loop:
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"load_ccw cmd complete chan %04x status %04x count %04x\n",
|
||||
chan, chp->chan_status, chp->ccw_count);
|
||||
/* we want to terminate if command is complete */
|
||||
/* go store status and return CC2 */
|
||||
/*NEW*/ return 1; /* return cmd complete */
|
||||
}
|
||||
}
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
@ -720,7 +730,7 @@ int chan_write_byte(uint16 chsa, uint8 *data)
|
||||
}
|
||||
if (chp->ccw_count == 0) {
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"chan_write_byte ZERO ccw_count[%04x] %04x addr %06x\n",
|
||||
"chan_write_byte ZERO chan %04x ccw_count %04x addr %06x\n",
|
||||
chan, chp->ccw_count, chp->ccw_addr);
|
||||
if (chp->chan_byte & BUFF_DIRTY) {
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte 2 BUF DIRTY ret\n");
|
||||
@ -844,7 +854,7 @@ void chan_end(uint16 chsa, uint16 flags) {
|
||||
chp->chan_status |= ((uint16)flags); /* add in the callers flags */
|
||||
// chp->ccw_cmd = 0; /* reset the completed channel command */
|
||||
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"chan_end SLI test1 chsa %04x ccw_flags %04x count %04x status %04x\n",
|
||||
chsa, chp->ccw_flags, chp->ccw_count, chp->chan_status);
|
||||
#ifdef HACK_HACK
|
||||
@ -869,12 +879,12 @@ void chan_end(uint16 chsa, uint16 flags) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"chan_end SLI2 test chsa %04x ccw_flags %04x status %04x\n",
|
||||
chsa, chp->ccw_flags, chp->chan_status);
|
||||
chp->ccw_cmd = 0; /* reset the completed channel command */
|
||||
|
||||
/* Diags dos not want SLI if we have no device end status */
|
||||
/* Diags do not want SLI if we have no device end status */
|
||||
if ((chp->chan_status & FLAG_SLI) && ((chp->chan_status & STATUS_DEND) == 0))
|
||||
chp->chan_status &= ~FLAG_SLI;
|
||||
|
||||
@ -883,7 +893,7 @@ void chan_end(uint16 chsa, uint16 flags) {
|
||||
chp->ccw_flags = 0; /* no flags */
|
||||
}
|
||||
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"chan_end test end chsa %04x ccw_flags %04x status %04x\n",
|
||||
chsa, chp->ccw_flags, chp->chan_status);
|
||||
|
||||
@ -898,8 +908,57 @@ void chan_end(uint16 chsa, uint16 flags) {
|
||||
chp->ccw_flags = 0; /* no flags */
|
||||
}
|
||||
}
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"chan_end IOCL done chsa %04x ccw_flags %04x status %04x\n",
|
||||
chsa, chp->ccw_flags, chp->chan_status);
|
||||
#ifndef NEW_METHOD
|
||||
/* If channel end, check if we should continue */
|
||||
if (chp->chan_status & STATUS_CEND) { /* do we have channel end */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"chan_end chan end chsa %04x flags %04x status %04x\n",
|
||||
chsa, chp->ccw_flags, chp->chan_status);
|
||||
if (chp->ccw_flags & FLAG_CC) { /* command chain flag */
|
||||
/* we have channel end and CC flag, continue channel prog */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"chan_end chan end & CC chsa %04x status %04x\n",
|
||||
chsa, chp->chan_status);
|
||||
if (chp->chan_status & STATUS_DEND) { /* device end? */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"chan_end dev end & CC chsa %04x status %04x\n",
|
||||
chsa, chp->chan_status);
|
||||
(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 */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"chan_end chan end & no CC chsa %04x status %04x\n",
|
||||
chsa, chp->chan_status);
|
||||
dev_status[chsa] = 0; /* no device status anymore */
|
||||
/* we have completed channel program */
|
||||
/* handle case where we are loading the O/S on boot */
|
||||
/* if loading, leave status to be discovered by scan_chan */
|
||||
if (!loading) {
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"chan_end call store_csw dev end & chan end chsa %04x cpustatus %08x\n",
|
||||
chsa, CPUSTATUS);
|
||||
store_csw(chp); /* store the status */
|
||||
}
|
||||
else
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"chan_end we are loading with DE & CE, keep status chsa %04x status %08x\n",
|
||||
chsa, chp->chan_status);
|
||||
//XXX irq_pend = 1; /* still pending int */
|
||||
}
|
||||
}
|
||||
else
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"chan_end IOCL2 done chsa %04x ccw_flags %04x status %04x\n",
|
||||
chsa, chp->ccw_flags, chp->chan_status);
|
||||
#endif
|
||||
}
|
||||
irq_pend = 1; /* flag to test for int condition */
|
||||
//XXX irq_pend = 1; /* flag to test for int condition */
|
||||
}
|
||||
|
||||
/* store the device status into the status DW in memory */
|
||||
@ -965,24 +1024,26 @@ t_stat checkxio(uint16 lchsa, uint32 *status) {
|
||||
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, "checkxio 1 chsa %04x chan %04x\n", chsa, chan);
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "checkxio 1 chsa %04x chan %04x\n", chsa, chan);
|
||||
if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */
|
||||
*status = CC3BIT; /* not found, so CC3 */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "checkxio chsa %04x is not found, CC3 return\n", chsa);
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"checkxio chsa %04x is not found, CC3 return\n", chsa);
|
||||
return SCPE_OK; /* not found, CC3 */
|
||||
}
|
||||
if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "checkxio chsa %04x is not attached, CC3 return\n", chsa);
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"checkxio chsa %04x is not attached, CC3 return\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 */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "checkxio dev spad %08x chsa %04x\n", spadent, chsa);
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "checkxio dev spad %08x chsa %04x\n", spadent, chsa);
|
||||
|
||||
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, "checkxio int spad %08x inta %04x chan %04x\n", spadent, inta, chan);
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "checkxio int spad %08x inta %04x chan %04x\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 */
|
||||
@ -990,8 +1051,11 @@ t_stat checkxio(uint16 lchsa, uint32 *status) {
|
||||
iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */
|
||||
tempa = M[(chan_ivl+20)>>2]; /* status is in wd 5 of ICB */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
"checkxio busy ck chsa %04x cmd %02x iocla %08x flags %04x IOCD1 %08x IOCD2 %08x status %08x\n",
|
||||
chsa, chp->ccw_cmd, iocla, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2], tempa);
|
||||
"checkxio busy ck1 chsa %04x cmd %02x iocla %06x flags %04x\n",
|
||||
chsa, chp->ccw_cmd, iocla, chp->ccw_flags);
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
"checkxio busy ck2 chsa %04x IOCD1 %08x IOCD2 %08x INCH %08x\n",
|
||||
chsa, M[iocla>>2], M[(iocla+4)>>2], tempa);
|
||||
|
||||
/* check for a Command or data chain operation in progresss */
|
||||
if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) {
|
||||
@ -1007,7 +1071,8 @@ t_stat checkxio(uint16 lchsa, uint32 *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_XIO, &cpu_dev, "checkxio CC3 & CC4 return busy chan %04x cstat %08x\n",
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"checkxio CC3 & CC4 return busy chan %04x cstat %08x\n",
|
||||
chan, tempa);
|
||||
*status = CC3BIT|CC4BIT; /* sub channel busy, so CC3|CC4 */
|
||||
return SCPE_OK; /* just busy or something, CC3|CC4 */
|
||||
@ -1116,7 +1181,7 @@ t_stat startxio(uint16 lchsa, uint32 *status) {
|
||||
if (chp->chan_status & STATUS_PCHK) {
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */
|
||||
chp->chan_status &= ~STATUS_LENGTH; /* clear incorrect length */
|
||||
store_csw(chp); /* store the status in the inch status dw */
|
||||
//XXX store_csw(chp); /* store the status in the inch status dw */
|
||||
dev_status[chsa] = 0; /* no device status */
|
||||
//DIAG *status = CC2BIT; /* status stored, so CC2 */
|
||||
*status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */
|
||||
@ -1159,24 +1224,24 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */
|
||||
uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */
|
||||
pchp = find_chanp_ptr(chsa & 0x7f00); /* find the channel chanp pointer */
|
||||
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "testxio 1 chsa %04x chan %04x\n", chsa, chan);
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "testxio 1 chsa %04x chan %04x\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_XIO, &cpu_dev, "testxio 2 chsa %04x chan %04x\n", chsa, chan);
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "testxio 2 chsa %04x chan %04x\n", chsa, chan);
|
||||
if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit 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_XIO, &cpu_dev, "testxio dev spad %08x chsa %04x chan %04x\n", spadent, chsa, chan);
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "testxio dev spad %08x chsa %04x chan %04x\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_XIO, &cpu_dev, "testxio int spad %08x inta %04x chan %04x\n", spadent, inta, chan);
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "testxio int spad %08x inta %04x chan %04x\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 */
|
||||
@ -1187,9 +1252,6 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */
|
||||
"testxio busy test chsa %04x cmd %02x flags %04x IOCD1 %08x IOCD2 %08x IOCLA %08x\n",
|
||||
chsa, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2], iocla);
|
||||
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "$$ TIO chsa %04x chan %04x cmd %02x flags %04x\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,
|
||||
@ -1197,7 +1259,20 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */
|
||||
*status = CC4BIT; /* busy, so CC4 */
|
||||
goto tioret; /* just busy CC4 */
|
||||
}
|
||||
|
||||
//#define NEW_LOOK
|
||||
#ifdef NEW_LOOK
|
||||
/* see if status already posted and requesting interrupt */
|
||||
if (INTS[inta] & INTS_REQ) {
|
||||
/* we have status and a request, tell caller */
|
||||
*status = CC2BIT; /* status stored from SIO, so CC2 */
|
||||
INTS[inta] &= ~INTS_REQ; /* turn off request bit */
|
||||
goto tioret; /* CC2 and OK */
|
||||
}
|
||||
#endif
|
||||
/* the channel is not busy, see if any status to post */
|
||||
/* see if the FIFO is empty */
|
||||
if (dibp->chan_fifo_in != dibp->chan_fifo_out) {
|
||||
if ((FIFO_Get(chsa, &sw1) == 0) && (FIFO_Get(chsa, &sw2) == 0)) {
|
||||
uint32 chan_icb = find_int_icb(chsa); /* get icb address */
|
||||
|
||||
@ -1213,6 +1288,7 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */
|
||||
*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 */
|
||||
tioret:
|
||||
@ -1323,8 +1399,8 @@ t_stat rschnlxio(uint16 lchsa, uint32 *status) { /* reset channel XIO */
|
||||
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 */
|
||||
INTS[lev] &= ~INTS_REQ; /* clear level request */
|
||||
|
||||
/* now go through all the sa for the channel and stop any IOCLs */
|
||||
for (i=0; i<256; i++) {
|
||||
@ -1414,9 +1490,12 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */
|
||||
return SCPE_OK; /* No CC's all OK */
|
||||
#else
|
||||
/* diag wants an interrupt for a non busy HIO ??? */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"$$$ HIO DIAG chsa %04x chan %04x cmd %02x flags %04x status %04x\n",
|
||||
chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status);
|
||||
dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */
|
||||
store_csw(chp); /* store the status in the inch status dw */
|
||||
//XXX store_csw(chp); /* store the status in the inch status dw */
|
||||
dev_status[chsa] = 0; /* no device status */
|
||||
irq_pend = 1; /* still pending int */
|
||||
// *status = CC2BIT; /* sub channel status posted, CC2BIT */
|
||||
@ -1443,14 +1522,14 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */
|
||||
/* test for SCPE_IOERR */
|
||||
if (tempa != 0) { /* sub channel has status ready */
|
||||
/* The device I/O has been terminated and status stored. */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"haltxio halt_io call return ERROR chan %04x retstat %08x cstat %08x\n",
|
||||
chan, tempa, chp->chan_status);
|
||||
/*TUE*/ chp->chan_status &= ~STATUS_LENGTH; /* remove SLI status bit */
|
||||
chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */
|
||||
//TUE dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */
|
||||
/* chan_end called in hio device service routine */
|
||||
store_csw(chp); /* store the status in the inch status dw */
|
||||
//XXX store_csw(chp); /* store the status in the inch status dw */
|
||||
chp->ccw_count = 0; /* force zero count */
|
||||
dev_status[chsa] = 0; /* no device status */
|
||||
|
||||
@ -1465,6 +1544,8 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */
|
||||
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"haltxio 0 FIFO status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2);
|
||||
/*TUE*/ sw2 &= ~STATUS_LENGTH; /* remove SLI status bit */
|
||||
sw2 |= STATUS_ECHO; /* show we stopped the cmd */
|
||||
/* 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 */
|
||||
@ -1479,7 +1560,7 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */
|
||||
// UTX likes this return and does not panic */
|
||||
// The diag's want an interrupt generated, so wait
|
||||
*status = CC2BIT; /* status stored from HIO, so CC2 */
|
||||
/* if 0 returned, UTX hans on input */
|
||||
/* if 0 returned, UTX hangs on input */
|
||||
goto hioret; /* CC2 and OK */
|
||||
}
|
||||
/* nothing going on, so say all OK */
|
||||
@ -1500,8 +1581,8 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */
|
||||
/* we have completed the I/O without error */
|
||||
/* the channel is not busy, so return OK */
|
||||
//WAS *status = 0; /* CCs = 0, accepted */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
"$$$ HALTIO good return chsa %04x chan %04x cmd %02x flags %04x status %04x\n",
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"$$$ HALTXIO good return chsa %04x chan %04x cmd %02x flags %04x status %04x\n",
|
||||
chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status);
|
||||
*status = CC1BIT; /* request accepted, no status, so CC1 */
|
||||
goto hioret; /* just return */
|
||||
@ -1514,11 +1595,11 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "haltxio busy return CC4 chsa %04x chan %04x\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 */
|
||||
//CHG dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */
|
||||
dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */
|
||||
/*ADD*/ chp->ccw_count = 0; /* clear remaining count */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */
|
||||
/*ADD*/ chp->chan_status &= ~STATUS_LENGTH; /* remove SLI status bit */
|
||||
store_csw(chp); /* store the status in the inch status dw */
|
||||
//XXX store_csw(chp); /* store the status in the inch status dw */
|
||||
chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */
|
||||
dev_status[chsa] = 0; /* no device status */
|
||||
irq_pend = 1; /* still pending int */
|
||||
@ -1596,8 +1677,8 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */
|
||||
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 */
|
||||
INTS[lev] &= ~INTS_REQ; /* clear level request */
|
||||
|
||||
/* now go through all the sa for the channel and stop any IOCLs */
|
||||
for (i=0; i<256; i++) {
|
||||
@ -1629,7 +1710,8 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */
|
||||
/* 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];
|
||||
//Z DIB *dibp = dev_unit[chsa];
|
||||
DIB *dibp = (DIB *)dptr->ctxt; /* get pointer to DIB for this device */
|
||||
CHANP *chp = 0;
|
||||
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Channel Boot chan/device addr %04x\n", chsa);
|
||||
@ -1671,7 +1753,8 @@ t_stat chan_boot(uint16 chsa, DEVICE *dptr) {
|
||||
interrupt pending. Return icb address and interrupt level
|
||||
*/
|
||||
uint32 scan_chan(int *ilev) {
|
||||
int i,j;
|
||||
int i;
|
||||
//XXint j;
|
||||
uint32 chsa = 0; /* No device */
|
||||
uint32 chan; /* channel num 0-7f */
|
||||
uint32 tempa; /* icb address */
|
||||
@ -1680,7 +1763,9 @@ uint32 scan_chan(int *ilev) {
|
||||
CHANP *chp; /* channel prog pointer */
|
||||
DIB *dibp; /* DIB pointer */
|
||||
|
||||
if (irq_pend == 1) { /* pending int? */
|
||||
#ifdef OLD_METHOD
|
||||
//WAS if (irq_pend == 1) { /* pending int? */
|
||||
if ((irq_pend == 1) && loading) { /* pending int? */
|
||||
/* see if we have a channel completed */
|
||||
/* loop through all the channels/units for channel with pending I/O completion */
|
||||
for (i = 0; sim_devices[i] != NULL; i++) {
|
||||
@ -1701,16 +1786,16 @@ uint32 scan_chan(int *ilev) {
|
||||
|
||||
/* If channel end, check if we should continue */
|
||||
if (chp->chan_status & STATUS_CEND) { /* do we have channel end */
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"scan_chan loading %02x chan end chsa %04x flags %04x status %04x\n",
|
||||
loading, chsa, chp->ccw_flags, chp->chan_status);
|
||||
if (chp->ccw_flags & FLAG_CC) { /* command chain flag */
|
||||
/* we have channel end and CC flag, continue channel prog */
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"scan_chan loading %02x chan end & CC chsa %04x status %04x\n",
|
||||
loading, chsa, chp->chan_status);
|
||||
if (chp->chan_status & STATUS_DEND) { /* device end? */
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"scan_chan loading %02x dev end & CC chsa %04x status %04x\n",
|
||||
loading, chsa, chp->chan_status);
|
||||
(void)load_ccw(chp, 1); /* go load the next IOCB */
|
||||
@ -1719,7 +1804,7 @@ uint32 scan_chan(int *ilev) {
|
||||
} else {
|
||||
/* we have channel end and no CC flag, end command */
|
||||
chsa = chp->chan_dev; /* get the chan/sa */
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"scan_chan loading %02x chan end & no CC chsa %04x status %04x\n",
|
||||
loading, chsa, chp->chan_status);
|
||||
dev_status[chsa] = 0; /* no device status anymore */
|
||||
@ -1748,6 +1833,105 @@ uint32 scan_chan(int *ilev) {
|
||||
}
|
||||
}
|
||||
//WAS trythis:
|
||||
#else
|
||||
if ((irq_pend == 1) && loading) { /* pending int? */
|
||||
/* see if we have a channel completed for the boot channel */
|
||||
chp = find_chanp_ptr(loading); /* find the chanp pointer for channel */
|
||||
/* If channel end, check if we should continue */
|
||||
if (chp->chan_status & STATUS_CEND) { /* do we have channel end */
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"scan_chan loading %02x chan end chsa %04x flags %04x status %02x\n",
|
||||
loading, chsa, chp->ccw_flags, chp->chan_status);
|
||||
if (chp->ccw_flags & FLAG_CC) { /* command chain flag */
|
||||
/* we have channel end and CC flag, continue channel prog */
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"scan_chan loading %02x chan end & CC chsa %04x status %02x\n",
|
||||
loading, chsa, chp->chan_status);
|
||||
if (chp->chan_status & STATUS_DEND) { /* device end? */
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"scan_chan loading %02x dev end & CC chsa %04x status %02x\n",
|
||||
loading, chsa, chp->chan_status);
|
||||
(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 */
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"scan_chan loading %02x chan end & no CC chsa %04x status %02x\n",
|
||||
loading, chsa, chp->chan_status);
|
||||
dev_status[chsa] = 0; /* no device status anymore */
|
||||
/* handle case where we are loading the O/S on boot */
|
||||
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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//#define NEW_LOOK
|
||||
#ifdef NEW_LOOK
|
||||
/* Look for channels that are not active and not requesting, */
|
||||
/* but have status to post. Store the status and make them */
|
||||
/* into an interest request. They will be found when we scan */
|
||||
/* for the highest requesting interrupt. */
|
||||
for (i=0; i<112; i++) {
|
||||
if (SPAD[i+0x80] == 0) /* not initialize? */
|
||||
continue; /* skip this one */
|
||||
if (SPAD[i+0x80] == 0xffffffff) /* not initialize? */
|
||||
continue; /* skip this one */
|
||||
/* see if interrupt is enabled */
|
||||
if (!((INTS[i] & INTS_ENAB) || (SPAD[i+0x80] & SINT_ENAB)))
|
||||
continue; /* skip this one */
|
||||
/* we are enabled, see if already active */
|
||||
if ((INTS[i] & INTS_ACT) || (SPAD[i+0x80] & SINT_ACT))
|
||||
continue; /* this level active, keep looking */
|
||||
/* see if status already posted and requesting */
|
||||
if (INTS[i] & INTS_REQ)
|
||||
continue; /* this level requesting, keep looking */
|
||||
/* see if there is pending status for this channel */
|
||||
/* if there is, load it and request interrupt */
|
||||
/* get the device entry for the logical channel in SPAD */
|
||||
chan = (SPAD[i+0x80] & 0x7f00); /* get real channel and zero sa */
|
||||
dibp = dev_unit[chan]; /* get the device information pointer */
|
||||
/* no status for non-device entries */
|
||||
if (dibp == 0) {
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"scan_chan %04x int %02x no DIB pointer for requesting interrupt\n", chan, i);
|
||||
continue; /* skip unconfigured channel */
|
||||
}
|
||||
/* see if FIFO has status to post */
|
||||
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 blk addr in memory */
|
||||
tempa = chp->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 count in status WD 2 loc */
|
||||
/* now store the status dw address into word 5 of the ICB for the channel */
|
||||
/* post sw addr in ICB+5w & set CC2 in SW */
|
||||
M[(chan_icba + 20) >> 2] = tempa | BIT1;
|
||||
INTS[i] |= INTS_REQ; /* turn on channel interrupt request */
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"scan_chan REQ %04x FIFO read, irq %02x inch %06x chan_icba %06x sw1 %08x sw2 %08x\n",
|
||||
chan, i, tempa, chan_icba, sw1, sw2);
|
||||
irq_pend = 1; /* still pending int */
|
||||
continue; /* keep looking */
|
||||
}
|
||||
}
|
||||
/* no status to post, so go on */
|
||||
}
|
||||
#endif
|
||||
/* 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 */
|
||||
@ -1757,8 +1941,37 @@ uint32 scan_chan(int *ilev) {
|
||||
if (SPAD[i+0x80] == 0xffffffff) /* not initialize? */
|
||||
continue; /* skip this one */
|
||||
// if (INTS[i]&INTS_ACT) /* look for level active */
|
||||
if (SPAD[i+0x80] & SINT_ACT) /* look for level active */
|
||||
if (SPAD[i+0x80] & SINT_ACT) { /* look for level active */
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"scan_chan INTS ACT irq %02x SPAD %08x INTS %08x\n",
|
||||
i, SPAD[i+0x80], INTS[i]);
|
||||
break; /* this level active, so stop looking */
|
||||
}
|
||||
#ifndef OLD3
|
||||
/* look for the highest requesting interrupt */
|
||||
/* that is enabled */
|
||||
if (((INTS[i] & INTS_ENAB) && (INTS[i] & INTS_REQ)) ||
|
||||
((SPAD[i+0x80] & SINT_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 */
|
||||
/* should already be enabled */
|
||||
// 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_IRQ, &cpu_dev,
|
||||
"scan_chan INTS REQ irq %02x found chan_icba %08x INTS %08x\n",
|
||||
i, chan_icba, INTS[i]);
|
||||
*ilev = i; /* return interrupt level */
|
||||
irq_pend = 0; /* not pending anymore */
|
||||
return(chan_icba); /* return ICB address */
|
||||
}
|
||||
#endif
|
||||
#ifndef OLD1
|
||||
/* 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)) {
|
||||
@ -1786,11 +1999,15 @@ uint32 scan_chan(int *ilev) {
|
||||
M[(chan_icba + 20) >> 2] = tempa | BIT1;
|
||||
INTS[i] |= INTS_REQ; /* turn on channel interrupt request */
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"scan_chan %04x FIFO read, set irq %04x inch %06x chan_icba %06x sw1 %08x sw2 %08x\n",
|
||||
"scan_chan %04x FIFO read, set irq %02x inch %06x chan_icba %06x sw1 %08x sw2 %08x\n",
|
||||
chan, i, tempa, chan_icba, sw1, sw2);
|
||||
irq_pend = 1; /* still pending int */
|
||||
break; /* quit looking */
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef OLD2
|
||||
/* look for the highest requesting interrupt */
|
||||
/* that is enabled */
|
||||
if (((INTS[i] & INTS_ENAB) && (INTS[i] & INTS_REQ)) ||
|
||||
@ -1813,11 +2030,13 @@ uint32 scan_chan(int *ilev) {
|
||||
irq_pend = 0; /* not pending anymore */
|
||||
return(chan_icba); /* return ICB address */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return 0; /* done */
|
||||
}
|
||||
|
||||
/* part of find_dev_from_unit(UNIT *uptr) in scp.c */
|
||||
/* Find_dev pointer for a unit
|
||||
Input: uptr = pointer to unit
|
||||
Output: dptr = pointer to device
|
||||
@ -1892,8 +2111,10 @@ t_stat chan_set_devs() {
|
||||
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? */
|
||||
if (dev_unit[chsa] != 0)
|
||||
printf("Channel/SubAddress %04x multiple defined\n", chsa);
|
||||
if (dev_unit[chsa] != 0) {
|
||||
printf("Channel/SubAddress %04x multiple defined, aborting\n", chsa);
|
||||
return SCPE_IERR; /* no, arg error */
|
||||
}
|
||||
dev_unit[chsa] = dibp; /* no, save the dib address */
|
||||
}
|
||||
if (dibp->dev_ini != NULL) /* if there is an init routine, call it now */
|
||||
@ -1962,7 +2183,7 @@ t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc) {
|
||||
return SCPE_IERR; /* no, error return */
|
||||
dptr = get_dev(uptr); /* get the device pointer from unit */
|
||||
if (dptr == NULL) /* valid pointer? */
|
||||
return SCPE_IERR; /* retunr error */
|
||||
return SCPE_IERR; /* return error */
|
||||
chsa = GET_UADDR(uptr->u3); /* get the unit address */
|
||||
fprintf(st, "CHAN/SA %04x", chsa); /* display channel/subaddress */
|
||||
return SCPE_OK; /* we done */
|
||||
|
||||
@ -115,8 +115,10 @@ t_stat rtc_srv (UNIT *uptr)
|
||||
time_t result = time(NULL);
|
||||
// fprintf(stderr, "Clock int time %08x\r\n", (uint32)result);
|
||||
sim_debug(DEBUG_CMD, &rtc_dev, "RT Clock int time %08x\n", (uint32)result);
|
||||
if ((INTS[rtc_lvl] & INTS_ENAB) && /* make sure enabled */
|
||||
(INTS[rtc_lvl] & INTS_ACT) == 0) { /* and not active */
|
||||
if (((INTS[rtc_lvl] & INTS_ENAB) || /* make sure enabled */
|
||||
(SPAD[rtc_lvl+0x80] & SINT_ENAB)) && /* in spad too */
|
||||
(((INTS[rtc_lvl] & INTS_ACT) == 0) || /* and not active */
|
||||
((SPAD[rtc_lvl+0x80] & SINT_ACT) == 0))) { /* in spad too */
|
||||
INTS[rtc_lvl] |= INTS_REQ; /* request the interrupt */
|
||||
irq_pend = 1; /* make sure we scan for int */
|
||||
}
|
||||
@ -149,6 +151,7 @@ void rtc_setup(uint32 ss, uint32 level)
|
||||
SPAD[level+0x80] &= ~SINT_ENAB; /* in spad too */
|
||||
// INTS[level] &= ~INTS_REQ; /* make sure request not requesting */
|
||||
// INTS[level] &= ~INTS_ACT; /* make sure request not active */
|
||||
// SPAD[level+0x80] &= ~SINT_ACT; /* in spad too */
|
||||
sim_debug(DEBUG_CMD, &rtc_dev,
|
||||
"RT Clock setup disable int %02x rtc_pie %01x ss %01x\n",
|
||||
rtc_lvl, rtc_pie, ss);
|
||||
@ -274,9 +277,11 @@ t_stat itm_srv (UNIT *uptr)
|
||||
sim_debug(DEBUG_CMD, &itm_dev,
|
||||
"Intv Timer expired status %08x interrupt %02x @ time %08x\n",
|
||||
INTS[itm_lvl], itm_lvl, (uint32)result);
|
||||
if ((INTS[itm_lvl] & INTS_ENAB) && /* make sure enabled */
|
||||
(INTS[itm_lvl] & INTS_ACT) == 0) { /* and not active */
|
||||
INTS[itm_lvl] |= INTS_REQ; /* request the interrupt on zero value */
|
||||
if (((INTS[itm_lvl] & INTS_ENAB) || /* make sure enabled */
|
||||
(SPAD[itm_lvl+0x80] & SINT_ENAB)) && /* in spad too */
|
||||
(((INTS[itm_lvl] & INTS_ACT) == 0) || /* and not active */
|
||||
((SPAD[itm_lvl+0x80] & SINT_ACT) == 0))) { /* in spad too */
|
||||
INTS[itm_lvl] |= INTS_REQ; /* request the interrupt */
|
||||
irq_pend = 1; /* make sure we scan for int */
|
||||
}
|
||||
if ((INTS[itm_lvl] & INTS_ENAB) && (itm_cmd == 0x3d) && (itm_cnt != 0)) {
|
||||
|
||||
@ -96,10 +96,10 @@ TMXR com_desc = { COM_LINES_DFLT, 0, 0, com_ldsc }; /* com descr */
|
||||
|
||||
/* 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_INPUT 0x0100 /* Input ready for unit */
|
||||
#define COM_CR 0x0200 /* Output at beginning of line */
|
||||
#define COM_REQ 0x0400 /* Request key pressed */
|
||||
#define COM_EKO 0x0800 /* Echo input character */
|
||||
#define COM_OUTPUT 0x1000 /* Output ready for unit */
|
||||
#define COM_READ 0x2000 /* Read mode selected */
|
||||
|
||||
@ -193,7 +193,7 @@ TMXR com_desc = { COM_LINES_DFLT, 0, 0, com_ldsc }; /* com descr */
|
||||
/* u6 */
|
||||
|
||||
uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd);
|
||||
uint8 com_haltio(uint16 addr);
|
||||
uint8 com_haltio(UNIT *uptr);
|
||||
void com_ini(UNIT *, t_bool);
|
||||
void coml_ini(UNIT *, t_bool);
|
||||
t_stat com_reset(DEVICE *);
|
||||
@ -260,7 +260,7 @@ DIB com_dib = {
|
||||
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 */
|
||||
0xFF, /* 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 */
|
||||
@ -282,6 +282,7 @@ 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,
|
||||
/* ctxt is the DIB pointer */
|
||||
&com_dib, DEV_NET | DEV_DISABLE | DEV_DEBUG, 0, dev_debug,
|
||||
NULL, NULL, NULL, NULL, NULL, &com_description
|
||||
};
|
||||
@ -330,7 +331,7 @@ DIB coml_dib = {
|
||||
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 */
|
||||
0xff, /* uint8 mask */ /* 16 devices - device mask */
|
||||
0x7E00, /* uint16 chan_addr */ /* parent channel address */
|
||||
};
|
||||
|
||||
@ -358,6 +359,7 @@ DEVICE coml_dev = {
|
||||
COM_LINES*2, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &com_reset,
|
||||
NULL, NULL, NULL,
|
||||
/* ctxt is the DIB pointer */
|
||||
&coml_dib, DEV_DISABLE | DEV_DEBUG, 0, dev_debug,
|
||||
NULL, NULL, NULL, NULL, NULL, &com_description
|
||||
};
|
||||
@ -380,7 +382,7 @@ void com_ini(UNIT *uptr, t_bool f)
|
||||
{
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
|
||||
sim_debug(DEBUG_CMD, &com_dev, "COM init device %s controller 0x7e00\n", dptr->name);
|
||||
sim_debug(DEBUG_CMD, dptr, "COM init device %s controller 0x7e00\n", dptr->name);
|
||||
sim_activate(uptr, 1000); /* time increment */
|
||||
}
|
||||
|
||||
@ -395,12 +397,12 @@ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
return SNS_BSY; /* yes, return busy */
|
||||
}
|
||||
|
||||
sim_debug(DEBUG_CMD, &com_dev, "CMD unit %04x chan %04x cmd %02x", unit, chan, cmd);
|
||||
sim_debug(DEBUG_CMD, dptr, "CMD unit %04x chan %04x cmd %02x\n", unit, chan, cmd);
|
||||
|
||||
/* process the commands */
|
||||
switch (cmd & 0xFF) {
|
||||
case COM_INCH: /* 00 */ /* INCH command */
|
||||
sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: CMD INCH\n", chan);
|
||||
sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: CMD INCH\n", chan);
|
||||
uptr->u3 &= LMASK; /* leave only chsa */
|
||||
uptr->u3 |= (0x7f & COM_MSK); /* save 0x7f as INCH cmd command */
|
||||
uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */
|
||||
@ -412,7 +414,7 @@ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
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 %04x: Cmd WRITE %02x\n", chan, cmd);
|
||||
sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd WRITE %02x\n", chan, cmd);
|
||||
|
||||
uptr->u3 &= LMASK; /* leave only chsa */
|
||||
uptr->u3 |= (cmd & COM_MSK); /* save command */
|
||||
@ -434,19 +436,20 @@ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
/* 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 %04x: Cmd read\n", chan);
|
||||
sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: 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 */
|
||||
sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: input cnt = %04x\n", chan, coml_chp[unit].ccw_count);
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"com_startcmd %04x: input cnt = %04x\n", chan, coml_chp[unit].ccw_count);
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case COM_NOP: /* 0x03 */ /* NOP has do nothing */
|
||||
sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd %02x NOP\n", chan, cmd);
|
||||
sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x NOP\n", chan, cmd);
|
||||
uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */
|
||||
uptr->u3 &= LMASK; /* leave only chsa */
|
||||
uptr->u3 |= (cmd & COM_MSK); /* save command */
|
||||
@ -459,7 +462,8 @@ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
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 %04x: unit %04x Cmd Sense %02x\n", chan, unit, uptr->u5);
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"com_startcmd %04x: unit %04x 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) */
|
||||
@ -522,51 +526,54 @@ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
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,
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"com_startcmd Cmd SENSE return chan %04x u5-status %04x ls0 %08x ls1 %08x\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 %04x: Cmd %02x DEFSC\n", chan, cmd);
|
||||
chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char */
|
||||
sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x DEFSC\n", chan, cmd);
|
||||
if (chan_read_byte(GET_UADDR(uptr->u3), &ch)) { /* read char from memory */
|
||||
/* nothing to read, error */
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* good return */
|
||||
}
|
||||
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 %04x: Cmd %02x RRTS\n", chan, cmd);
|
||||
sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x 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 %04x: Cmd %02x SRTS\n", chan, cmd);
|
||||
sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x 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 %04x: Cmd %02x RBRK\n", chan, cmd);
|
||||
sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x 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 %04x: Cmd %02x SBRK\n", chan, cmd);
|
||||
sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x 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 %04x: Cmd %02x DTR\n", chan, cmd);
|
||||
sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x RDTR\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 %04x: Cmd %02x NOP\n", chan, cmd);
|
||||
sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x SDTR\n", chan, cmd);
|
||||
uptr->u5 |= SNS_DTR; /* Data terminal ready */
|
||||
return SNS_CHNEND|SNS_DEVEND; /* good return */
|
||||
break;
|
||||
@ -611,21 +618,38 @@ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
#endif
|
||||
|
||||
case COM_SACE: /* 0xff */ /* Set ACE parameters (3 chars) */
|
||||
sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd %02x SACE\n", chan, cmd);
|
||||
chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char 0 */
|
||||
sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x SACE\n", chan, cmd);
|
||||
if (chan_read_byte(GET_UADDR(uptr->u3), &ch)) { /* read char 0 */
|
||||
/* nothing to read, error */
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* good return */
|
||||
}
|
||||
uptr->u4 = ((uint32)ch)<<24; /* byte 0 of ACE data */
|
||||
chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char 1 */
|
||||
if (chan_read_byte(GET_UADDR(uptr->u3), &ch)) { /* read char 1 */
|
||||
/* nothing to read, error */
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* good return */
|
||||
}
|
||||
uptr->u4 |= ((uint32)ch)<<16; /* byte 1 of ACE data */
|
||||
chan_read_byte(GET_UADDR(uptr->u3), &ch); /* read char 2 */
|
||||
if (chan_read_byte(GET_UADDR(uptr->u3), &ch)) { /* read char 2 */
|
||||
/* nothing to read, error */
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* good return */
|
||||
}
|
||||
uptr->u4 |= ((uint32)ch)<<8; /* byte 2 of ACE data */
|
||||
sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd %02x ACE bytes %08x\n",
|
||||
sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x ACE bytes %08x\n",
|
||||
chan, cmd, uptr->u4);
|
||||
#ifdef USE_INTERUPT
|
||||
uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */
|
||||
uptr->u3 &= LMASK; /* leave only chsa */
|
||||
uptr->u3 |= (cmd & COM_MSK); /* save command */
|
||||
sim_activate(uptr, 20); /* start us up */
|
||||
#else
|
||||
return SNS_CHNEND|SNS_DEVEND; /* good return */
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
||||
default: /* invalid command */
|
||||
uptr->u5 |= SNS_CMDREJ; /* command rejected */
|
||||
sim_debug(DEBUG_CMD, &com_dev, "com_startcmd %04x: Cmd Invald %02x status %02x\n",
|
||||
sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd Invald %02x status %02x\n",
|
||||
chan, cmd, uptr->u5);
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */
|
||||
break;
|
||||
@ -643,23 +667,33 @@ uint8 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
t_stat comi_srv(UNIT *uptr)
|
||||
{
|
||||
uint8 ch;
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
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 */
|
||||
|
||||
ln = uptr - com_unit; /* line # */
|
||||
sim_debug(DEBUG_CMD, &com_dev, "comi_srv entry chsa %04x line %04x cmd %02x\n", chsa, ln, cmd);
|
||||
/* handle NOP and INCH cmds */
|
||||
sim_debug(DEBUG_CMD, &com_dev, "comi_srv entry chsa %04x line %04x cmd %02x\n", chsa, ln, cmd);
|
||||
sim_debug(DEBUG_CMD, dptr, "comi_srv entry chsa %04x line %02x cmd %02x\n", chsa, ln, cmd);
|
||||
if (cmd == COM_NOP || cmd == 0x7f) { /* check for NOP or INCH */
|
||||
uptr->u3 &= LMASK; /* leave only chsa */
|
||||
sim_debug(DEBUG_CMD, &com_dev, "comi_srv NOP or INCH done chsa %04x line %04x cmd %02x\n",
|
||||
sim_debug(DEBUG_CMD, dptr, "comi_srv NOP or INCH done chsa %04x line %02x cmd %02x\n",
|
||||
chsa, ln, cmd);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */
|
||||
return SCPE_OK; /* return */
|
||||
}
|
||||
|
||||
/* handle SACE, 3 char alread read, so we are done */
|
||||
if (cmd == COM_SACE) { /* check for SACE 0xff */
|
||||
uptr->u3 &= LMASK; /* leave only chsa */
|
||||
sim_debug(DEBUG_CMD, &com_dev,
|
||||
"comi_srv SACE done chsa %04x line %02x cmd %02x ACE %08x\n",
|
||||
chsa, ln, cmd, uptr->u4);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */
|
||||
return SCPE_OK; /* return */
|
||||
}
|
||||
|
||||
ln = uptr - com_unit; /* line # */
|
||||
if ((com_unit[COMC].flags & UNIT_ATT) == 0){ /* attached? */
|
||||
return SCPE_OK;
|
||||
@ -740,6 +774,7 @@ t_stat comi_srv(UNIT *uptr)
|
||||
/* Unit service - output transfers */
|
||||
t_stat como_srv(UNIT *uptr)
|
||||
{
|
||||
DEVICE *dptr = get_dev(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;
|
||||
@ -747,7 +782,7 @@ t_stat como_srv(UNIT *uptr)
|
||||
uint8 ch;
|
||||
|
||||
/* handle NOP and INCH cmds */
|
||||
sim_debug(DEBUG_CMD, &com_dev, "como_srv entry chsa %04x line %04x cmd %02x\n", chsa, ln, cmd);
|
||||
sim_debug(DEBUG_CMD, dptr, "como_srv entry chsa %04x line %04x cmd %02x\n", chsa, ln, cmd);
|
||||
if (cmd == COM_NOP || cmd == 0x7f) { /* check for NOP or INCH */
|
||||
uptr->u3 &= LMASK; /* leave only chsa */
|
||||
sim_debug(DEBUG_CMD, &com_dev, "como_srv NOP or INCH done chsa %04x line %04x cmd %02x\n",
|
||||
@ -756,7 +791,17 @@ t_stat como_srv(UNIT *uptr)
|
||||
return SCPE_OK; /* return */
|
||||
}
|
||||
|
||||
sim_debug(DEBUG_CMD, &com_dev, "como_srv entry 1 chsa %04x line %04x cmd %02x\n", chsa, ln, cmd);
|
||||
/* handle SACE, 3 char already read, so we are done */
|
||||
if (cmd == COM_SACE) { /* check for SACE 0xff */
|
||||
uptr->u3 &= LMASK; /* leave only chsa */
|
||||
sim_debug(DEBUG_CMD, &com_dev,
|
||||
"como_srv SACE done chsa %04x line %02x cmd %02x ACE %08x\n",
|
||||
chsa, ln, cmd, uptr->u4);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */
|
||||
return SCPE_OK; /* return */
|
||||
}
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr, "como_srv entry 1 chsa %04x line %04x cmd %02x\n", chsa, ln, cmd);
|
||||
if (cmd) {
|
||||
/* get a user byte from memory */
|
||||
done = chan_read_byte(chsa, &ch); /* get byte from memory */
|
||||
@ -766,28 +811,28 @@ t_stat como_srv(UNIT *uptr)
|
||||
return SCPE_OK;
|
||||
|
||||
if (com_dev.flags & DEV_DIS) { /* disabled */
|
||||
sim_debug(DEBUG_CMD, &com_dev, "como_srv chsa %04x line %04x DEV_DIS set\n", chsa, ln);
|
||||
sim_debug(DEBUG_CMD, dptr, "como_srv chsa %04x line %04x DEV_DIS set\n", chsa, ln);
|
||||
if (done) {
|
||||
sim_debug(DEBUG_CMD, &com_dev, "como_srv Write DONE %04x status %04x\n",
|
||||
sim_debug(DEBUG_CMD, dptr, "como_srv Write DONE %04x status %04x\n",
|
||||
ln, SNS_CHNEND|SNS_DEVEND);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */
|
||||
}
|
||||
return SCPE_OK; /* return */
|
||||
}
|
||||
sim_debug(DEBUG_CMD, &com_dev, "como_srv poll chsa %04x line %04x DEV_DIS set\n", chsa, ln);
|
||||
sim_debug(DEBUG_CMD, dptr, "como_srv poll chsa %04x line %04x DEV_DIS set\n", chsa, ln);
|
||||
|
||||
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 %04x: chnend|devend\n", ln);
|
||||
sim_debug(DEBUG_CMD, dptr, "com_srvo write %04x: chnend|devend\n", ln);
|
||||
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 */
|
||||
sim_debug(DEBUG_CMD, &com_dev, "com_srvo writing char 0x%02x to ln %04x\n", ch, ln);
|
||||
sim_debug(DEBUG_CMD, dptr, "com_srvo writing char 0x%02x to ln %04x\n", ch, ln);
|
||||
tmxr_poll_tx(&com_desc); /* poll xmt */
|
||||
sim_activate(uptr, uptr->wait); /* wait */
|
||||
return SCPE_OK;
|
||||
@ -796,7 +841,7 @@ endit:
|
||||
goto endit; /* done */
|
||||
/* just dump the char */
|
||||
// /* xmt disabled, just wait around */
|
||||
sim_debug(DEBUG_CMD, &com_dev, "com_srvo write dumping char 0x%02x on line %04x\n", ch, ln);
|
||||
sim_debug(DEBUG_CMD, dptr, "com_srvo write dumping char 0x%02x on line %04x\n", ch, ln);
|
||||
tmxr_poll_tx(&com_desc); /* poll xmt */
|
||||
//?? sim_activate(uptr, coml_unit[ln].wait); /* wait */
|
||||
sim_activate(uptr, uptr->wait); /* wait */
|
||||
@ -805,10 +850,10 @@ endit:
|
||||
} else {
|
||||
/* not connected, so dump char on ground */
|
||||
if (done) {
|
||||
sim_debug(DEBUG_CMD, &com_dev, "com_srvo write dump DONE line %04x status %04x\n",
|
||||
sim_debug(DEBUG_CMD, dptr, "com_srvo write dump DONE line %04x status %04x\n",
|
||||
ln, SNS_CHNEND|SNS_DEVEND);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */
|
||||
uptr->u3 &= LMASK; /* nothing left, command complete */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */
|
||||
}
|
||||
sim_activate(uptr, uptr->wait); /* wait */
|
||||
return SCPE_OK;
|
||||
@ -837,14 +882,16 @@ t_stat com_reset (DEVICE *dptr)
|
||||
/* 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;
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
// uint16 chsa = GET_UADDR(com_unit[COMC].u3); /* get channel/subaddress */
|
||||
// uint16 chsa = GET_UADDR(uptr->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 */
|
||||
r = tmxr_attach(&com_desc, uptr, cptr); /* attach */
|
||||
if (r != SCPE_OK) /* error? */
|
||||
return r; /* return error */
|
||||
sim_debug(DEBUG_CMD, &com_dev, "com_srv com is now attached chsa %04x\n", chsa);
|
||||
sim_debug(DEBUG_CMD, dptr, "com_srv comc is now attached\n");
|
||||
sim_activate(uptr, 0); /* start poll at once */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@ -163,7 +163,7 @@ void con_ini(UNIT *uptr, t_bool f) {
|
||||
int unit = (uptr - con_unit); /* unit 0 */
|
||||
// DEVICE *dptr = get_dev(uptr);
|
||||
|
||||
uptr->u4 = 0; /* no input cpunt */
|
||||
uptr->u4 = 0; /* no input count */
|
||||
con_data[unit].incnt = 0; /* no input data */
|
||||
// con_data[0].incnt = 0; /* no input data */
|
||||
// con_data[1].incnt = 0; /* no output data */
|
||||
@ -208,7 +208,6 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
|
||||
uptr->CMD |= CON_INCH2; /* save INCH command as 0xf0 */
|
||||
uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */
|
||||
sim_activate(uptr, 20); /* start us off */
|
||||
//WAS sim_activate(uptr, 10); /* start us off */
|
||||
return 0; /* no status change */
|
||||
break;
|
||||
|
||||
@ -219,7 +218,6 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
|
||||
uptr->CMD |= (cmd & CON_MSK); /* save command */
|
||||
uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */
|
||||
sim_activate(uptr, 20); /* start us off */
|
||||
//TRIED sim_activate(uptr, 10); /* start us off */
|
||||
return 0; /* no status change */
|
||||
break;
|
||||
|
||||
@ -245,7 +243,7 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
|
||||
uptr->CMD |= (cmd & CON_MSK); /* save command */
|
||||
// uptr->u4 = 0; /* no I/O yet */
|
||||
// con_data[unit].incnt = 0; /* clear any input data */
|
||||
sim_activate(uptr, 10); /* start us off */
|
||||
sim_activate(uptr, 20); /* start us off */
|
||||
return 0; /* no status change */
|
||||
break;
|
||||
|
||||
@ -254,7 +252,7 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
|
||||
uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */
|
||||
uptr->CMD &= LMASK; /* leave only chsa */
|
||||
uptr->CMD |= (cmd & CON_MSK); /* save command */
|
||||
sim_activate(uptr, 10); /* start us off */
|
||||
sim_activate(uptr, 20); /* start us off */
|
||||
return 0; /* no status change */
|
||||
break;
|
||||
#endif
|
||||
@ -282,19 +280,16 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
|
||||
break;
|
||||
|
||||
default: /* invalid command */
|
||||
uptr->SNS |= SNS_CMDREJ; /* command rejected */
|
||||
// uptr->u4 = 0; /* no I/O yet */
|
||||
// con_data[unit].incnt = 0; /* clear any input data */
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_startcmd %04x: Invalid command %02x Sense %02x\n",
|
||||
chan, cmd, uptr->SNS);
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */
|
||||
break;
|
||||
}
|
||||
|
||||
if (uptr->SNS & (~(SNS_RDY|SNS_ONLN|SNS_DSR)))
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
|
||||
return SNS_CHNEND|SNS_DEVEND;
|
||||
/* invalid command */
|
||||
uptr->SNS |= SNS_CMDREJ; /* command rejected */
|
||||
// uptr->u4 = 0; /* no I/O yet */
|
||||
// con_data[unit].incnt = 0; /* clear any input data */
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_startcmd %04x: Invalid command %02x Sense %02x\n",
|
||||
chan, cmd, uptr->SNS);
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */
|
||||
}
|
||||
|
||||
/* Handle output transfers for console */
|
||||
@ -317,7 +312,6 @@ t_stat con_srvo(UNIT *uptr) {
|
||||
uptr->CMD &= LMASK; /* nothing left, command complete */
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_srvo Read to output device chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
//DIAG_TUE chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* unit check */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_UNITCHK); /* unit check */
|
||||
return SCPE_OK;
|
||||
}
|
||||
@ -401,9 +395,8 @@ t_stat con_srvi(UNIT *uptr) {
|
||||
uptr->CMD &= LMASK; /* nothing left, command complete */
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_srvi Write to input device chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
//DIAGTUE chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* unit check */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_UNITCHK); /* unit check */
|
||||
//fall thru return SCPE_OK;
|
||||
// fall thru return SCPE_OK;
|
||||
}
|
||||
}
|
||||
#ifdef JUNK
|
||||
|
||||
@ -172,7 +172,7 @@ 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[128]; /* Interrupt status flags */
|
||||
uint32 INTS[112]; /* Interrupt status flags */
|
||||
uint32 CPUSTATUS; /* cpu status word */
|
||||
uint32 TRAPSTATUS; /* trap status word */
|
||||
uint32 CMCR; /* Cache Memory Control Register */
|
||||
@ -689,7 +689,7 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap)
|
||||
uint32 MAXMAP = MAX2048; /* default to 2048 maps */
|
||||
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
"Load Maps Entry PSD %08x %08x STATUS %08x lmap %01x CPU Type %2x\n",
|
||||
"Load Maps Entry PSD %08x %08x STATUS %08x lmap %01x CPU Mode %2x\n",
|
||||
thepsd[0], thepsd[1], CPUSTATUS, lmap, CPU_MODEL);
|
||||
|
||||
/* process 32/7X computers */
|
||||
@ -887,19 +887,19 @@ npmem:
|
||||
BPIX = 0; /* no os maps loaded */
|
||||
CPIXPL = 0; /* no user pages */
|
||||
CPIX = cpix; /* save user CPIX */
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9))
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) {
|
||||
TRAPSTATUS |= BIT1; /* set bit 1 of trap status */
|
||||
else
|
||||
TRAPSTATUS |= BIT8; /* set bit 8 of trap status */
|
||||
} else
|
||||
TRAPSTATUS |= BIT10; /* set bit 8 of trap status */
|
||||
return NPMEM; /* non present memory error */
|
||||
}
|
||||
|
||||
/* output O/S and User MPX entries */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"#MEMORY %06x MPL %06x MPL[0] %08x %06x MPL[%04x] %08x %06x\n",
|
||||
MEMSIZE*4, mpl, RMW(mpl), RMW(mpl+4), cpix,
|
||||
RMW(cpix+mpl), RMW(cpix+mpl+4));
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"MEMORY2 %06x BPIX %04x cpix %04x CPIX %04x CPIXPL %04x HIWM %04x\n",
|
||||
MEMSIZE*4, BPIX, cpix, CPIX, CPIXPL, HIWM);
|
||||
|
||||
@ -1068,9 +1068,9 @@ loaduser:
|
||||
sim_debug(DEBUG_TRAP, &cpu_dev,
|
||||
"load_maps MEM SIZE4 %06x user page list address %06x invalid\n",
|
||||
MEMSIZE*4, msdl);
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9))
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) {
|
||||
TRAPSTATUS |= BIT1; /* set bit 1 of trap status */
|
||||
else
|
||||
} else
|
||||
TRAPSTATUS |= BIT28; /* set bit 28 of trap status */
|
||||
return NPMEM; /* non present memory error */
|
||||
}
|
||||
@ -1101,7 +1101,7 @@ loaduser:
|
||||
if ((CPU_MODEL == MODEL_27) || (CPU_MODEL == MODEL_87)) {
|
||||
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
"load_maps Processing 32/27 & 32/87 Model# %04x\n", CPU_MODEL);
|
||||
"load_maps Processing 32/27 & 32/87 Model# %02x\n", CPU_MODEL);
|
||||
|
||||
/* handle non virtual page loading or diag LMAP instruction */
|
||||
/* do 32/27 and 32/87 that force load all maps */
|
||||
@ -1296,9 +1296,9 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access)
|
||||
if (word >= (MEMSIZE*4)) { /* see if address is within our memory */
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) {
|
||||
if (access == MEM_RD)
|
||||
TRAPSTATUS |= 0x40000000; /* set bit 1 of trap status */
|
||||
TRAPSTATUS |= BIT1; /* set bit 1 of trap status */
|
||||
if (access == MEM_WR)
|
||||
TRAPSTATUS |= 0x20000000; /* set bit 2 of trap status */
|
||||
TRAPSTATUS |= BIT2; /* set bit 2 of trap status */
|
||||
} else {
|
||||
TRAPSTATUS |= BIT10; /* set bit 10 of trap status */
|
||||
}
|
||||
@ -1333,6 +1333,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access)
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) {
|
||||
// V9 & 32/97 wants MACHINECHK for test 37/1 in CN.MMM & VM.MMM */
|
||||
TRAPSTATUS |= BIT7; /* set bit 7 of trap status */
|
||||
TRAPSTATUS |= BIT28; /* set bit 28 of trap status */
|
||||
return MACHINECHK_TRAP; /* diags want machine check error */
|
||||
}
|
||||
}
|
||||
@ -1398,7 +1399,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access)
|
||||
if ((BIT1 >> offset) & raddr) { /* is 1/4 page write protected */
|
||||
*prot = 1; /* return memory write protection status */
|
||||
}
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"RealAddrRa address %08x, TLB %08x MAPC[%03x] %08x wprot %02x prot %02x\n",
|
||||
word, TLB[index], index/2, MAPC[index/2], (word>>11)&3, *prot);
|
||||
return ALLOK; /* all OK, return instruction */
|
||||
@ -1419,16 +1420,23 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access)
|
||||
"RealAddr loadmap 2a non present memory fault addr %08x raddr %08x index %04x\n",
|
||||
addr, raddr, index);
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) {
|
||||
#ifndef TRY_AGAIN
|
||||
if (access == MEM_RD)
|
||||
TRAPSTATUS |= BIT1; /* set bit 1 of trap status */
|
||||
else
|
||||
if (access == MEM_WR)
|
||||
TRAPSTATUS |= BIT2; /* set bit 2 of trap status */
|
||||
/* returning this error fails test 34/2 of mmm diag */
|
||||
/*NEW*/// return MAPFLT; /* map fault error on memory access */
|
||||
/*NEW*/// return MACHINECHK_TRAP; /* diags want machine check error */
|
||||
/* returning this error fixes 34/2, but still fails 46/2 */
|
||||
return NPMEM; /* none present memory error */
|
||||
#else
|
||||
TRAPSTATUS |= BIT7; /* set bit 7 of trap status */
|
||||
TRAPSTATUS |= BIT12; /* set bit 12 of trap status */
|
||||
/* returning this error fails test 34/2 of mmm diag */
|
||||
return MAPFLT; /* map fault error on memory access */
|
||||
#endif
|
||||
/*NEW*/// return MAPFLT; /* map fault error on memory access */
|
||||
/* returning this error fails test 34/2 of mmm diag */
|
||||
/*NEW*/// return MACHINECHK_TRAP; /* diags want machine check error */
|
||||
} else
|
||||
TRAPSTATUS |= BIT28; /* set bit 28 of trap status */
|
||||
return NPMEM; /* none present memory error */
|
||||
@ -1449,7 +1457,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access)
|
||||
if ((BIT1 >> offset) & raddr) { /* is 1/4 page write protected */
|
||||
*prot = 1; /* return memory write protection status */
|
||||
}
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"RealAddrR address %08x, TLB %08x MAPC[%03x] %08x wprot %02x prot %02x\n",
|
||||
word, TLB[index], index/2, MAPC[index/2], (word>>11)&3, *prot);
|
||||
return ALLOK; /* all OK, return instruction */
|
||||
@ -1463,9 +1471,6 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access)
|
||||
else
|
||||
*prot = offset; /* return memory write protection status */
|
||||
|
||||
// if (addr != word)
|
||||
//sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
//"At RealAddr Hit convert %06x to addr %08x\n", addr, word);
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"RealAddrX address %06x, TLB %06x MAPC[%03x] %08x wprot %02x prot %02x\n",
|
||||
word, TLB[index], index/2, MAPC[index/2], (word>>11)&3, *prot);
|
||||
@ -1473,7 +1478,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access)
|
||||
}
|
||||
|
||||
/* Hit bit is off in TLB, so lets go get some maps */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"$MEMORY %06x HIT MPL %06x MPL[0] %08x %06x MPL[%04x] %08x %06x\n",
|
||||
MEMSIZE*4, mpl, RMW(mpl), RMW(mpl+4), CPIX, RMW(CPIX+mpl), RMW(CPIX+mpl+4));
|
||||
|
||||
@ -1481,7 +1486,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access)
|
||||
msdl = RMW(mpl+CPIX+4); /* get msdl entry for given CPIX */
|
||||
if ((msdl & MASK24) >= (MEMSIZE*4)) { /* check user midl */
|
||||
sim_debug(DEBUG_TRAP, &cpu_dev,
|
||||
"RealAddr Non Present Memory User msdl %06x CPIX %04x\n",
|
||||
"RealAddr User CPIX Non Present Memory User msdl %06x CPIX %04x\n",
|
||||
msdl, CPIX);
|
||||
|
||||
if (CPU_MODEL == MODEL_67) {
|
||||
@ -1550,7 +1555,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access)
|
||||
else
|
||||
mix = nix-BPIX; /* get map index in memory */
|
||||
map = RMH(msdl+(mix<<1)); /* map content from memory */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"Addr %06x RealAddr %06x Map0[%04x] HIT %04x TLB[%3x] %08x MAPC[%03x] %08x\n",
|
||||
addr, word, mix, map, nix, TLB[nix], nix/2, MAPC[nix/2]);
|
||||
|
||||
@ -1558,10 +1563,6 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access)
|
||||
if ((map & 0x8000) == 0) {
|
||||
/* for V6 & V9 handle demand paging */
|
||||
if (CPU_MODEL >= MODEL_V6) {
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
/* start debugging */
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ);
|
||||
#endif
|
||||
/* map is not valid, so we have map fault */
|
||||
sim_debug(DEBUG_TRAP, &cpu_dev,
|
||||
"AddrMa %06x RealAddr %06x Map0 HIT %04x, TLB[%3x] %08x MAPC[%03x] %08x\n",
|
||||
@ -1589,24 +1590,16 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access)
|
||||
TLB[nix] = ((map & 0x7ff) << 13) | ((map << 16) & 0xf8000000) | 0x04000000;
|
||||
word = (TLB[nix] & 0xffe000) | offset; /* combine map and offset */
|
||||
WMR((nix<<1), map); /* store the map reg contents into MAPC cache */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"RealAddrm RMH %04x mix %04x TLB[%04x] %08x B+C %04x RMR[nix] %04x\n",
|
||||
map, mix, nix, TLB[nix], BPIX+CPIXPL, RMR(nix<<1));
|
||||
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"Addr1c %06x RealAddr %06x Map1[%04x] HIT %04x, TLB[%3x] %08x MAPC[%03x] %08x RMR %04x\n",
|
||||
addr, word, mix, map, nix, TLB[nix], nix/2, MAPC[nix/2], RMR(nix<<1));
|
||||
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
/* start debugging */
|
||||
if(word == 0x27000)
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_XIO);
|
||||
#endif
|
||||
*realaddr = word; /* return the real address */
|
||||
raddr = TLB[nix]; /* get the base address & bits */
|
||||
// if (addr != word)
|
||||
//sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
//"At RealAddr Miss convert %06x to addr %08x\n", addr, word);
|
||||
|
||||
if ((CPU_MODEL == MODEL_67) || (CPU_MODEL == MODEL_97)) {
|
||||
/* get protection status of map */
|
||||
@ -1644,13 +1637,13 @@ cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_XIO);
|
||||
nix -= 1; /* point to last map in MAPC */
|
||||
}
|
||||
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"RealAddrp mix %04x nix %04x TLB[%04x] %08x B+C %04x RMR[nix] %04x\n",
|
||||
mix, nix, nix, TLB[nix], BPIX+CPIXPL, RMR(nix<<1));
|
||||
|
||||
/* allow the excess map entry to be loaded, even though bad */
|
||||
if (nix <= (BPIX+CPIXPL)) { /* needs to be a mapped reg */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"Addr1d BPIX %03x CPIXPL %03x RealAddr %06x TLB[%3x] %08x MAPC[%03x] %08x RMR %04x\n",
|
||||
BPIX, CPIXPL, word, nix, TLB[nix], nix/2, MAPC[nix/2], RMR(nix<<1));
|
||||
|
||||
@ -1660,7 +1653,7 @@ cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_XIO);
|
||||
/* allow the excess map entry to be loaded, even though bad */
|
||||
if (nix <= (BPIX+CPIXPL)) { /* needs to be a mapped reg */
|
||||
map = RMH(msdl+(mix<<1)); /* map content from memory */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"Addr2a %06x MapX[%04x] HIT %04x, TLB[%3x] %08x MAPC[%03x] %08x\n",
|
||||
addr, mix, map, nix, TLB[nix], nix/2, MAPC[nix/2]);
|
||||
|
||||
@ -1669,7 +1662,7 @@ cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_XIO);
|
||||
TLB[nix] = ((map & 0x7ff) << 13) | ((map << 16) & 0xf8000000) | 0x04000000;
|
||||
word = (TLB[nix] & 0xffe000); /* combine map and offset */
|
||||
WMR((nix<<1), map); /* store the map reg contents into MAPC cache */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"Addr2b %06x RealAddr %06x Map2[%04x] HIT %04x, TLB[%3x] %08x MAPC[%03x] %08x\n",
|
||||
addr, word, mix, map, nix, TLB[nix], nix/2, MAPC[nix/2]);
|
||||
}
|
||||
@ -1784,14 +1777,14 @@ t_stat Mem_read(uint32 addr, uint32 *data)
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Mem_read error addr %.8x realaddr %.8x data %.8x prot %02x status %04x\n",
|
||||
addr, realaddr, *data, prot, status);
|
||||
if (status == NPMEM) { /* operand nonpresent memory error */
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9))
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) {
|
||||
TRAPSTATUS |= BIT1; /* set bit 1 of trap status */
|
||||
else
|
||||
} else
|
||||
TRAPSTATUS |= BIT10; /* set bit 10 of trap status */
|
||||
}
|
||||
if (status == MAPFLT) {
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9))
|
||||
TRAPSTATUS |= BIT1; /* set bit 1 of trap status */
|
||||
TRAPSTATUS |= BIT12; /* set bit 12 of trap status */
|
||||
else
|
||||
TRAPSTATUS |= BIT10; /* set bit 10 of trap status */
|
||||
}
|
||||
@ -1892,14 +1885,14 @@ t_stat Mem_write(uint32 addr, uint32 *data)
|
||||
"Mem_write error addr %.8x realaddr %.8x data %.8x prot %02x status %04x\n",
|
||||
addr, realaddr, *data, prot, status);
|
||||
if (status == NPMEM) { /* operand nonpresent memory error */
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9))
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) {
|
||||
TRAPSTATUS |= BIT2; /* set bit 2 of trap status */
|
||||
else
|
||||
} else
|
||||
TRAPSTATUS |= BIT10; /* set bit 10 of trap status */
|
||||
}
|
||||
if (status == MAPFLT) {
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9))
|
||||
TRAPSTATUS |= BIT2; /* set bit 2 of trap status */
|
||||
TRAPSTATUS |= BIT12; /* set bit 12 of trap status */
|
||||
else
|
||||
TRAPSTATUS |= BIT10; /* set bit 10 of trap status */
|
||||
}
|
||||
@ -1999,10 +1992,10 @@ wait_loop:
|
||||
PSD1 &= ~1; /* clear bit 31, no lr */
|
||||
drop_nop = 0; /* we dropped the nop */
|
||||
}
|
||||
redo:
|
||||
|
||||
if (skipinstr) { /* need to skip interrupt test? */
|
||||
#ifdef NOTNOW
|
||||
sim_debug(DEBUG_TRAP, &cpu_dev,
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"Skipinstr set to zero PSD1 %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
PSD1, PSD2, CPUSTATUS);
|
||||
#endif
|
||||
@ -2016,7 +2009,7 @@ redo:
|
||||
if (int_icb != 0) { /* was ICB returned for an I/O or interrupt */
|
||||
int il = ilev; /* get the interrupt level */
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"Normal int scan return icb %08x level %02x irq_pend %02x wait4int %02x\n",
|
||||
"<>Normal int return icb %06x level %02x irq_pend %01x wait4int %01x\n",
|
||||
int_icb, il, irq_pend, wait4int);
|
||||
|
||||
/* take interrupt, store the PSD, fetch new PSD */
|
||||
@ -2029,28 +2022,30 @@ redo:
|
||||
/* set new map mode and interrupt blocking state in CPUSTATUS */
|
||||
modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */
|
||||
CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */
|
||||
CPUSTATUS |= modes; /* not insert into CPUSTATUS */
|
||||
CPUSTATUS |= modes; /* now insert into CPUSTATUS */
|
||||
if (PSD2 & MAPBIT) {
|
||||
CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */
|
||||
CPUSTATUS |= BIT8; /* 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 */
|
||||
t = SPAD[il+0x80]; /* get spad entry for interrupt */
|
||||
|
||||
/* This test fixed the hangs on terminal input for diags & UTX! */
|
||||
/*TRY*/ t = SPAD[il+0x80]; /* get spad entry for interrupt */
|
||||
/* Class F I/O spec says to reset interrupt active if user's */
|
||||
/* interrupt service routine runs with interrupts blocked */
|
||||
// if ((t & 0x0f000000) == 0x0f000000) { /* if class F clear interrupt */
|
||||
/*TRY*/ if ((t & 0x0f000000) == 0x0f000000) { /* if class F clear interrupt */
|
||||
/* if this is F class I/O interrupt, clear the active level */
|
||||
/* SPAD entries for interrupts begin at 0x80 */
|
||||
INTS[il] &= ~INTS_ACT; /* deactivate specified int level */
|
||||
SPAD[il+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */
|
||||
irq_pend = 1; /* scan for interrupts again */
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"Auto-reset interrupt INTS[%02x] %08x SPAD[%03x] %08x\n",
|
||||
"<>Auto-reset interrupt INTS[%02x] %08x SPAD[%03x] %08x\n",
|
||||
il, INTS[il], il+0x80, SPAD[il+0x80]);
|
||||
// }
|
||||
/*TRY*/ }
|
||||
}
|
||||
else
|
||||
CPUSTATUS &= ~0x80; /* no, reset blk state in cpu status bit 24 */
|
||||
@ -2062,20 +2057,25 @@ redo:
|
||||
SPAD[0xf5] = PSD2; /* save the current PSD2 */
|
||||
SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"Inter %03x OPSD1 %08x OPSD2 %08x NPSD1 %08x NPSD2 %08x\n",
|
||||
"<>Int %03x OPSD1 %08x OPSD2 %08x NPSD1 %08x NPSD2 %08x\n",
|
||||
il, RMW(int_icb), RMW(int_icb+4), PSD1, PSD2);
|
||||
bc = RMW(int_icb+20) & 0xffffff;
|
||||
if (RMW(int_icb+16) == 0)
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"Inter2 %03x ICBA %06x IOCLA %06x\n",
|
||||
"<>Int2 %03x ICBA %06x IOCLA %06x\n",
|
||||
il, int_icb, RMW(int_icb+16));
|
||||
else
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"Inter2 %03x ICBA %06x IOCLA %06x STAT %08x SW1 %08x SW2 %08x\n",
|
||||
"<>Int2 %03x ICBA %06x IOCLA %06x STAT %08x SW1 %08x SW2 %08x\n",
|
||||
il, int_icb, RMW(int_icb+16), RMW(int_icb+20), RMW(bc), RMW(bc+4));
|
||||
wait4int = 0; /* wait is over for int */
|
||||
irq_pend = 1; /* scan for interrupts again */
|
||||
skipinstr = 1; /* skip next inter test after this instr */
|
||||
#ifdef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
PSD1, PSD2, CPUSTATUS);
|
||||
#endif
|
||||
goto skipi; /* skip int test */
|
||||
}
|
||||
/* see if waiting at a wait instruction */
|
||||
@ -2094,7 +2094,7 @@ redo:
|
||||
PSD2 = M[4>>2]; /* PSD2 from location 4 */
|
||||
modes = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */
|
||||
CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */
|
||||
CPUSTATUS |= modes; /* not insert into CPUSTATUS */
|
||||
CPUSTATUS |= modes; /* now insert into CPUSTATUS */
|
||||
sim_debug(DEBUG_IRQ, &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 */
|
||||
@ -2103,6 +2103,11 @@ redo:
|
||||
SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */
|
||||
loading = 0; /* we are done loading */
|
||||
skipinstr = 1; /* skip next interrupt test only once */
|
||||
#ifdef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
PSD1, PSD2, CPUSTATUS);
|
||||
#endif
|
||||
}
|
||||
goto wait_loop; /* continue waiting */
|
||||
}
|
||||
@ -2121,12 +2126,17 @@ redo:
|
||||
attention_trap = 0; /* clear flag */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "Attention TRAP %04x\n", TRAPME);
|
||||
skipinstr = 1; /* skip next interrupt test only once */
|
||||
#ifdef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
PSD1, PSD2, CPUSTATUS);
|
||||
#endif
|
||||
goto newpsd; /* got process trap */
|
||||
}
|
||||
|
||||
skipi:
|
||||
i_flags = 0; /* do not update pc if MF or NPM */
|
||||
skipinstr = 0; /* skip only once */
|
||||
//XXX skipinstr = 0; /* skip only once */
|
||||
TRAPSTATUS = CPUSTATUS & 0x57; /* clear all trap status except cpu type */
|
||||
|
||||
/* fill IR from logical memory address */
|
||||
@ -2172,10 +2182,6 @@ skipi:
|
||||
if (IR == 0x00020000) { /* is this a NOP from rt hw? */
|
||||
PSD1 = (PSD1 + 2) | (((PSD1 & 2) >> 1) & 1); /* skip this instruction */
|
||||
// fprintf(stderr, "RIGHT HW skip NOP instr %x skip nop at %x\n", IR, PSD1);
|
||||
if (skipinstr == 2) { /* last instr was lf hw and rt NOP, try ints again */
|
||||
skipinstr = 0; /* only test this once */
|
||||
goto redo; /* check for ints now */
|
||||
}
|
||||
skipinstr = 0; /* only test this once */
|
||||
goto skipi; /* go read next instruction */
|
||||
}
|
||||
@ -2920,9 +2926,11 @@ exec:
|
||||
case 0xB: /* RPSWT */ /* Read Processor Status Word 2 (PSD2) */
|
||||
if ((GPR[reg] & 0x80000000) && (CPU_MODEL < MODEL_V9)) {
|
||||
/* if bit 0 of reg set, return (default 0) CPU Configuration Word */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
#ifdef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"RPSWT READ CCW GPR[%x] %08x CCW %04x SPAD[0xf5] %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
reg, GPR[reg], CCW, SPAD[0xf5], PSD2, CPUSTATUS);
|
||||
#endif
|
||||
dest = CCW; /* no cache or shared memory */
|
||||
//NO WCS dest |= 0x0000c000; /* set SIM bit for DIAGS */
|
||||
/* make sure bit 19 is zero saying IPU not present */
|
||||
@ -2940,31 +2948,39 @@ exec:
|
||||
CMSMC |= 0x00000200; /* bit 22, Access Protection ECO present */
|
||||
CMSMC |= 0x00000010; /* CPU Firmware Version 1/Rev level 0 */
|
||||
dest = CMSMC; /* return starus */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
#ifdef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"RPSWT READ Cache/Shadow CW GPR[%x] = %08x CMSMC %04x SPAD[0xf5] %x PSD2 %x\n",
|
||||
reg, GPR[reg], CMSMC, SPAD[0xf5], PSD2);
|
||||
#endif
|
||||
} else
|
||||
if ((GPR[reg] & 0x40000000) && (CPU_MODEL == MODEL_V9)) {
|
||||
/* if bit 1 of reg set, return CPU Shadow Memory Configuration Word */
|
||||
CSMCW = 0x00000000; /* no Shadow unit present */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
#ifdef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"RPSWT READ V9 CPU Shadow Memory CW GPR[%x] = %08x CSMCW %04x SPAD[0xf5] %x PSD2 %x\n",
|
||||
reg, GPR[reg], CSMCW, SPAD[0xf5], PSD2);
|
||||
#endif
|
||||
dest = CSMCW; /* return starus */
|
||||
} else
|
||||
if ((GPR[reg] & 0x20000000) && (CPU_MODEL == MODEL_V9)) {
|
||||
/* if bit 2 of reg set, return Cache Memory Configuration Word */
|
||||
ISMCW = 0x00000000; /* no Shadow unit present */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
#ifdef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"RPSWT READ V9 IPU Shadow Memory CW GPR[%x] = %08x ISMCW %04x SPAD[0xf5] %x PSD2 %x\n",
|
||||
reg, GPR[reg], ISMCW, SPAD[0xf5], PSD2);
|
||||
#endif
|
||||
dest = ISMCW; /* return starus */
|
||||
} else
|
||||
if ((GPR[reg] & BIT0) == 0x00000000) {
|
||||
/* if bit 0 of reg not set, return PSD2 */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
#ifdef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"RPSWT READ PSW2 GPR[%x] %08x SPAD[0xf5] %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
reg, GPR[reg], SPAD[0xf5], PSD2, CPUSTATUS);
|
||||
#endif
|
||||
/* make sure bit 49 (block state is current stat */
|
||||
dest = SPAD[0xf5]; /* get PSD2 for user from SPAD 0xf5 */
|
||||
dest &= ~0x0000c000; /* clear bits 48 & 49 */
|
||||
@ -4023,9 +4039,6 @@ skipit:
|
||||
break;
|
||||
}
|
||||
td = (t_int64)dest % (t_int64)source; /* remainder */
|
||||
// dbl = !(td >= 0); /* double reg is neg remainder */
|
||||
// dbl = ((t_int64)td < 0); /* double reg is neg remainder */
|
||||
dbl = (td < 0); /* double reg is neg remainder */
|
||||
if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */
|
||||
td = NEGATE32(td); /* dividend and remainder must be same sign */
|
||||
dest = (t_int64)dest / (t_int64)source; /* now do the divide */
|
||||
@ -5906,9 +5919,10 @@ doovr2:
|
||||
goto newpsd; /* go execute the trap now */
|
||||
}
|
||||
if ((TRAPME = Mem_read(addr, &temp))) { /* get PSD1 from memory */
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9))
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) {
|
||||
TRAPSTATUS |= BIT10; /* set bit 10 of trap status */
|
||||
else
|
||||
TRAPSTATUS |= BIT7; /* set bit 7 of trap status */
|
||||
} else
|
||||
TRAPSTATUS |= BIT18; /* set bit 18 of trap status */
|
||||
goto newpsd; /* memory read error or map fault */
|
||||
}
|
||||
@ -5921,18 +5935,20 @@ doovr2:
|
||||
|
||||
if (opr & 0x0200) { /* Was it LPSDCM? */
|
||||
if ((TRAPME = Mem_read(addr+4, &temp2))) { /* get PSD2 from memory */
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9))
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) {
|
||||
TRAPSTATUS |= BIT10; /* set bit 10 of trap status */
|
||||
else
|
||||
TRAPSTATUS |= BIT7; /* set bit 7 of trap status */
|
||||
} else
|
||||
TRAPSTATUS |= BIT18; /* set bit 18 of trap status */
|
||||
goto newpsd; /* memory read error or map fault */
|
||||
}
|
||||
PSD2 = temp2; /* PSD2 access good, so save it */
|
||||
} else {
|
||||
if ((TRAPME = Mem_read(addr+4, &temp2))) { /* get PSD2 from memory */
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9))
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) {
|
||||
TRAPSTATUS |= BIT10; /* set bit 10 of trap status */
|
||||
else
|
||||
TRAPSTATUS |= BIT7; /* set bit 7 of trap status */
|
||||
} else
|
||||
TRAPSTATUS |= BIT18; /* set bit 18 of trap status */
|
||||
goto newpsd; /* memory read error or map fault */
|
||||
}
|
||||
@ -6025,7 +6041,7 @@ doovr2:
|
||||
PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */
|
||||
SPAD[0xf5] = PSD2; /* save the current PSD2 */
|
||||
SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"LPSDCM MAPS LOADED TRAPME = %02x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
TRAPME, PSD1, PSD2, CPUSTATUS);
|
||||
}
|
||||
@ -6052,14 +6068,25 @@ doovr2:
|
||||
SPAD[0xf5] = ix; /* restore the current PSD2 to SPAD */
|
||||
SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */
|
||||
irq_pend = reg; /* restore intr status */
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9))
|
||||
if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) {
|
||||
TRAPSTATUS |= BIT10; /* set bit 10 of trap status */
|
||||
else
|
||||
TRAPSTATUS |= BIT7; /* set bit 7 of trap status */
|
||||
} else
|
||||
TRAPSTATUS |= BIT18; /* set bit 18 of trap status */
|
||||
goto newpsd; /* go process error */
|
||||
}
|
||||
skipinstr = 1; /* do not allow intr on next instruction */
|
||||
#ifdef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
PSD1, PSD2, CPUSTATUS);
|
||||
#endif
|
||||
drop_nop = 0; /* nothing to drop */
|
||||
#ifdef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"LPSD(CM) Done PSD1 %08x PSD2 %08x CPUSTATUS %08x irq %01x\n",
|
||||
PSD1, PSD2, CPUSTATUS, irq_pend);
|
||||
#endif
|
||||
goto newpsd; /* load the new psd, or process error */
|
||||
break;
|
||||
|
||||
@ -6128,6 +6155,8 @@ doovr2:
|
||||
// break; /* ignore */
|
||||
if ((t & 0x0f000000) == 0x0f000000) /* if class F ignore instruction */
|
||||
break; /* ignore for F class */
|
||||
|
||||
/* does not effect REQ status */
|
||||
INTS[prior] |= INTS_ENAB; /* enable specified int level */
|
||||
SPAD[prior+0x80] |= SINT_ENAB; /* enable in SPAD too */
|
||||
irq_pend = 1; /* start scanning interrupts again */
|
||||
@ -6143,6 +6172,11 @@ doovr2:
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev, "Intv Timer EI %02x Turn on\n", prior);
|
||||
itm_setup(1, prior); /* tell timer to start */
|
||||
}
|
||||
#ifndef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"EI lev %02x Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
prior, PSD1, PSD2, CPUSTATUS);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x1: /* DI FC01 */
|
||||
@ -6155,10 +6189,11 @@ doovr2:
|
||||
break; /* ignore */
|
||||
if ((t & 0x0f000000) == 0x0f000000) /* if class F ignore instruction */
|
||||
break; /* ignore for F class */
|
||||
|
||||
/* active state is left alone */
|
||||
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 */
|
||||
INTS[prior] &= ~INTS_REQ; /* clears any requests also */
|
||||
|
||||
/* test for clock at address 0x7f06 and interrupt level 0x18 */
|
||||
/* the diags want the type to be 0, others want 3, so ignore */
|
||||
@ -6171,6 +6206,11 @@ doovr2:
|
||||
itm_setup(0, prior); /* tell timer to stop */
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev, "Intv Timer DI %02x Turn off\n", prior);
|
||||
}
|
||||
#ifndef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"DI lev %02x Skipinstr set to %01x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
prior, skipinstr, PSD1, PSD2, CPUSTATUS);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x2: /* RI FC02 */
|
||||
@ -6185,6 +6225,11 @@ doovr2:
|
||||
break; /* ignore for F class */
|
||||
INTS[prior] |= INTS_REQ; /* set the request flag for this level */
|
||||
irq_pend = 1; /* start scanning interrupts again */
|
||||
#ifndef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"RI lev %02x Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
prior, PSD1, PSD2, CPUSTATUS);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x3: /* AI FC03 */
|
||||
@ -6199,6 +6244,11 @@ doovr2:
|
||||
INTS[prior] |= INTS_ACT; /* activate specified int level */
|
||||
SPAD[prior+0x80] |= SINT_ACT; /* activate in SPAD too */
|
||||
irq_pend = 1; /* start scanning interrupts again */
|
||||
#ifndef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"AI lev %02x Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
prior, PSD1, PSD2, CPUSTATUS);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x4: /* DAI FC04 */
|
||||
@ -6217,6 +6267,11 @@ doovr2:
|
||||
/* instruction following a DAI can not be interrupted */
|
||||
/* skip tests for interrupts if this is the case */
|
||||
skipinstr = 1; /* skip interrupt test */
|
||||
#ifndef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"DAI lev %02x Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
prior, PSD1, PSD2, CPUSTATUS);
|
||||
#endif
|
||||
drop_nop = 0; /* nothing to drop */
|
||||
break;
|
||||
|
||||
@ -6503,15 +6558,17 @@ mcheck:
|
||||
/* SPAD entries for interrupts begin at 0x80 */
|
||||
INTS[ix] &= ~INTS_ACT; /* deactivate specified int level */
|
||||
SPAD[ix+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */
|
||||
irq_pend = 1; /* start scanning interrupts again */
|
||||
skipinstr = 1; /* skip interrupt test */
|
||||
if ((TRAPME = checkxio(chsa, &status)))
|
||||
goto newpsd; /* error returned, trap cpu */
|
||||
PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
/* start debugging */
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ);
|
||||
irq_pend = 1; /* start scanning interrupts again */
|
||||
skipinstr = 1; /* skip interrupt test */
|
||||
#ifdef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"Skipinstr set to one PSD1 %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
PSD1, PSD2, CPUSTATUS);
|
||||
#endif
|
||||
/*XXX*/ drop_nop = 0; /* nothing to drop */
|
||||
PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); /* insert status */
|
||||
break;
|
||||
} /* end of XIO switch */
|
||||
break;
|
||||
|
||||
@ -102,6 +102,8 @@
|
||||
/* 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_MFP 1 /* 1 device MFP channel controller */
|
||||
#define NUM_UNITS_MFP 1 /* 1 master MFP 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 */
|
||||
@ -129,6 +131,9 @@ extern UNIT cpu_unit; /* the cpu unit */
|
||||
#ifdef NUM_DEVS_IOP
|
||||
extern DEVICE iop_dev; /* IOP channel controller */
|
||||
#endif
|
||||
#ifdef NUM_DEVS_MFP
|
||||
extern DEVICE mfp_dev; /* MFP channel controller */
|
||||
#endif
|
||||
#ifdef NUM_DEVS_RTOM
|
||||
extern DEVICE rtc_dev; /* RTOM rtc */
|
||||
extern DEVICE itm_dev; /* RTOM itm */
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
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 void chan_end(uint16 chsa, uint8 flags);
|
||||
extern int chan_read_byte(uint16 chsa, uint8 *data);
|
||||
extern int chan_write_byte(uint16 chsa, uint8 *data);
|
||||
extern void set_devattn(uint16 addr, uint8 flags);
|
||||
@ -44,13 +44,13 @@ extern uint32 SPAD[]; /* cpu SPAD memory */
|
||||
|
||||
/* useful conversions */
|
||||
/* Fill STAR value from cyl, trk, sec data */
|
||||
#define CHS2STAR(c,h,s) (((c<<16) & 0xffff0000)|((h<<8) & 0xff00)|(s & 0xff))
|
||||
#define CHS2STAR(c,h,s) (((c<<16) & LMASK)|((h<<8) & 0xff00)|(s & 0xff))
|
||||
/* convert STAR value to number of sectors */
|
||||
#define STAR2SEC(star,spt,spc) ((star&0xff)+(((star>>8)&0xff)*spt)+((star>>16)*spc))
|
||||
/* convert STAR value to number of heads or tracks */
|
||||
#define STAR2TRK(star,tpc) ((star >> 16) * tpc + ((star >> 8) & 0x0ff))
|
||||
/* convert STAR value to number of cylinders */
|
||||
#define STAR2CYL(star) ((star >> 16) & 0xffff)
|
||||
#define STAR2CYL(star) ((star >> 16) & RMASK)
|
||||
/* convert byte value to number of sectors mod sector size */
|
||||
#define BYTES2SEC(bytes,ssize) (((bytes) + (ssize-1)) >> 10)
|
||||
/* get sectors per track for specified type */
|
||||
@ -144,7 +144,7 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option
|
||||
char ldatrfhdc; FHD head count
|
||||
*/
|
||||
|
||||
#define CMD u3
|
||||
#define CMDu3 u3
|
||||
/* u3 */
|
||||
/* in u3 is device command code and status */
|
||||
#define DSK_CMDMSK 0x00ff /* Command being run */
|
||||
@ -254,7 +254,7 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option
|
||||
mini-module)
|
||||
*/
|
||||
|
||||
/* Not Used up7 */
|
||||
/* INCH addr up7 */
|
||||
|
||||
#ifdef NOUSED
|
||||
/* registers */
|
||||
@ -298,9 +298,9 @@ disk_type[] =
|
||||
|
||||
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 *);
|
||||
uint8 disk_haltio(UNIT *uptr);
|
||||
t_stat disk_srv(UNIT *uptr);
|
||||
t_stat disk_boot(int32 unitnum, DEVICE *dptr);
|
||||
void disk_ini(UNIT *, t_bool);
|
||||
t_stat disk_reset(DEVICE *);
|
||||
t_stat disk_attach(UNIT *, CONST char *);
|
||||
@ -363,6 +363,7 @@ DEVICE dda_dev = {
|
||||
"DMA", dda_unit, NULL/*dda_reg*/, disk_mod,
|
||||
NUM_UNITS_DISK, 16, 24, 4, 16, 32,
|
||||
NULL, NULL, &disk_reset, &disk_boot, &disk_attach, &disk_detach,
|
||||
/* ctxt is the DIB pointer */
|
||||
&dda_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug,
|
||||
NULL, NULL, &disk_help, NULL, NULL, &disk_description
|
||||
};
|
||||
@ -413,6 +414,7 @@ DEVICE ddb_dev = {
|
||||
"DMB", ddb_unit, NULL, /*ddb_reg*/, disk_mod,
|
||||
NUM_UNITS_DISK, 16, 24, 4, 16, 32,
|
||||
NULL, NULL, &disk_reset, &disk_boot, &disk_attach, &disk_detach,
|
||||
/* ctxt is the DIB pointer */
|
||||
&ddb_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug,
|
||||
NULL, NULL, &disk_help, NULL, NULL, &disk_description
|
||||
};
|
||||
@ -434,11 +436,11 @@ uint32 disksec2star(uint32 daddr, int type)
|
||||
uint8 disk_preio(UNIT *uptr, uint16 chan)
|
||||
{
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
uint16 chsa = GET_UADDR(uptr->CMD);
|
||||
uint16 chsa = GET_UADDR(uptr->CMDu3);
|
||||
int unit = (uptr - dptr->units);
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr, "disk_preio CMD %08x unit %02x\n", uptr->CMD, unit);
|
||||
if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */
|
||||
sim_debug(DEBUG_CMD, dptr, "disk_preio CMD %08x unit %02x\n", uptr->CMDu3, unit);
|
||||
if ((uptr->CMDu3 & 0xff00) != 0) { /* just return if busy */
|
||||
return SNS_BSY;
|
||||
}
|
||||
|
||||
@ -448,25 +450,25 @@ uint8 disk_preio(UNIT *uptr, uint16 chan)
|
||||
|
||||
uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
{
|
||||
uint16 chsa = GET_UADDR(uptr->CMD);
|
||||
uint16 chsa = GET_UADDR(uptr->CMDu3);
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
int unit = (uptr - dptr->units);
|
||||
CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"disk_startcmd chsa %04x unit %02x cmd %02x CMD %08x\n",
|
||||
chsa, unit, cmd, uptr->CMD);
|
||||
chsa, unit, cmd, uptr->CMDu3);
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */
|
||||
uptr->SNS |= 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->CMD & DSK_CMDMSK) != 0) {
|
||||
uptr->CMD |= DSK_BUSY; /* Flag we are busy */
|
||||
if ((uptr->CMDu3 & DSK_CMDMSK) != 0) {
|
||||
uptr->CMDu3 |= DSK_BUSY; /* Flag we are busy */
|
||||
return SNS_BSY;
|
||||
}
|
||||
if ((uptr->CMD & 0xff00) != 0) { /* if any status info, we are busy */
|
||||
if ((uptr->CMDu3 & 0xff00) != 0) { /* if any status info, we are busy */
|
||||
return SNS_BSY;
|
||||
}
|
||||
sim_debug(DEBUG_CMD, dptr, "disk_startcmd CMD continue unit=%02x cmd %02x\n", unit, cmd);
|
||||
@ -479,18 +481,18 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
"disk_startcmd starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n",
|
||||
uptr->u4, chsa, chp->ccw_addr, chp->ccw_count);
|
||||
|
||||
uptr->CMD |= DSK_INCH2; /* use 0xf0 for inch, just need int */
|
||||
uptr->CMDu3 |= DSK_INCH2; /* use 0xf0 for inch, just need int */
|
||||
sim_activate(uptr, 20); /* start things off */
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case DSK_SCK: /* Seek command 0x07 */
|
||||
case DSK_XEZ: /* Rezero & Read IPL record 0x1f */
|
||||
case DSK_XEZ: /* Rezero & Read IPL record 0x37 */
|
||||
case DSK_WD: /* Write command 0x01 */
|
||||
case DSK_RD: /* Read command 0x02 */
|
||||
case DSK_LMR: /* read mode register */
|
||||
case DSK_LMR: /* read mode register 0x15 */
|
||||
|
||||
uptr->CMD |= cmd; /* save cmd */
|
||||
uptr->CMDu3 |= cmd; /* save cmd */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"disk_startcmd starting disk seek r/w cmd %02x chsa %04x\n",
|
||||
cmd, chsa);
|
||||
@ -499,36 +501,36 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
break;
|
||||
|
||||
case DSK_NOP: /* NOP 0x03 */
|
||||
uptr->CMD |= cmd; /* save cmd */
|
||||
uptr->CMDu3 |= cmd; /* save cmd */
|
||||
sim_activate(uptr, 20); /* start things off */
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case DSK_SNS: /* Sense 0x04 */
|
||||
uptr->CMD |= cmd; /* save cmd */
|
||||
uptr->CMDu3 |= cmd; /* save cmd */
|
||||
sim_activate(uptr, 20); /* start things off */
|
||||
break;
|
||||
|
||||
case DSK_WSL: /* WSL 0x31 */
|
||||
uptr->CMD |= cmd; /* save cmd */
|
||||
uptr->CMDu3 |= cmd; /* save cmd */
|
||||
sim_activate(uptr, 20); /* start things off */
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case DSK_RSL: /* RSL 0x32 */
|
||||
uptr->CMD |= cmd; /* save cmd */
|
||||
uptr->CMDu3 |= cmd; /* save cmd */
|
||||
sim_activate(uptr, 20); /* start things off */
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case DSK_WTL: /* WTL 0x51 */
|
||||
uptr->CMD |= cmd; /* save cmd */
|
||||
uptr->CMDu3 |= cmd; /* save cmd */
|
||||
sim_activate(uptr, 20); /* start things off */
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case DSK_RTL: /* RTL 0x52 */
|
||||
uptr->CMD |= cmd; /* save cmd */
|
||||
uptr->CMDu3 |= cmd; /* save cmd */
|
||||
sim_activate(uptr, 20); /* start things off */
|
||||
return 0;
|
||||
break;
|
||||
@ -546,11 +548,11 @@ uint8 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
/* Handle processing of disk requests. */
|
||||
t_stat disk_srv(UNIT *uptr)
|
||||
{
|
||||
uint16 chsa = GET_UADDR(uptr->CMD);
|
||||
uint16 chsa = GET_UADDR(uptr->CMDu3);
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
DIB *dibp = (DIB *)dptr->ctxt; /* get DIB address */
|
||||
CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */
|
||||
int cmd = uptr->CMD & DSK_CMDMSK;
|
||||
int cmd = uptr->CMDu3 & DSK_CMDMSK;
|
||||
int type = GET_TYPE(uptr->flags);
|
||||
uint32 trk, cyl, sec;
|
||||
int unit = (uptr - dptr->units);
|
||||
@ -564,7 +566,7 @@ t_stat disk_srv(UNIT *uptr)
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"disk_srv entry unit %02x CMD %08x chsa %04x count %04x %x/%x/%x \n",
|
||||
unit, uptr->CMD, chsa, chp->ccw_count,
|
||||
unit, uptr->CMDu3, chsa, chp->ccw_count,
|
||||
STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff));
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */
|
||||
@ -597,7 +599,7 @@ t_stat disk_srv(UNIT *uptr)
|
||||
/* a pointer to the INCH buffer followed by 8 drive attribute words that */
|
||||
/* contains the flags, sector count, MHD head count, and FHD count */
|
||||
/* len has the byte count from IOCD wd2 and should be 0x24 (36) */
|
||||
/* the INCH buffer address must be set for the parrent channel as well */
|
||||
/* the INCH buffer address must be set for the parent channel as well */
|
||||
/* as all other devices on the channel. Call set_inch() to do this for us */
|
||||
/* just return OK and channel software will use u4 as status buffer addr */
|
||||
|
||||
@ -605,7 +607,7 @@ t_stat disk_srv(UNIT *uptr)
|
||||
|
||||
if (len != 36) {
|
||||
/* we have invalid count, error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK;
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
@ -620,7 +622,7 @@ t_stat disk_srv(UNIT *uptr)
|
||||
for (i=0; i < 36; i++) {
|
||||
if (chan_read_byte(chsa, &buf[i])) {
|
||||
/* we have error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK;
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
@ -645,13 +647,13 @@ t_stat disk_srv(UNIT *uptr)
|
||||
#ifdef NOTYET
|
||||
if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */
|
||||
/* we have error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK;
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
uptr->CMD &= ~(0xffff); /* remove old cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"disk_srv cmd INCH chsa %04x addr %06x count %04x completed\n",
|
||||
chsa, mema, chp->ccw_count);
|
||||
@ -664,7 +666,7 @@ t_stat disk_srv(UNIT *uptr)
|
||||
break;
|
||||
|
||||
case DSK_WSL: /* WSL 0x31 make into NOP */
|
||||
uptr->CMD &= ~(0xffff); /* remove old cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"disk_srv cmd WSL chsa %04x count %04x completed\n",
|
||||
chsa, chp->ccw_count);
|
||||
@ -675,8 +677,10 @@ t_stat disk_srv(UNIT *uptr)
|
||||
for (i = 0; i < len; i++) {
|
||||
if (chan_read_byte(chsa, &buf[i])) {
|
||||
/* we have write error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
//XXX goto goout;
|
||||
return SCPE_OK;
|
||||
break;
|
||||
}
|
||||
if ((i%16) == 0)
|
||||
@ -684,12 +688,12 @@ t_stat disk_srv(UNIT *uptr)
|
||||
sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]);
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, dptr, "\n");
|
||||
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */
|
||||
//XXXgoout:
|
||||
break;
|
||||
|
||||
case DSK_WTL: /* WTL 0x51 make into NOP */
|
||||
uptr->CMD &= ~(0xffff); /* remove old cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"disk_srv cmd WTL chsa %04x count %04x completed\n",
|
||||
chsa, chp->ccw_count);
|
||||
@ -699,8 +703,10 @@ t_stat disk_srv(UNIT *uptr)
|
||||
for (i = 0; i < 30; i++) {
|
||||
if (chan_read_byte(chsa, &buf[i])) {
|
||||
/* we have read error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
return SCPE_OK;
|
||||
//XXX goto goout;
|
||||
break;
|
||||
}
|
||||
if (i == 16)
|
||||
@ -708,12 +714,11 @@ t_stat disk_srv(UNIT *uptr)
|
||||
sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]);
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, dptr, "\n");
|
||||
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */
|
||||
break;
|
||||
|
||||
case DSK_NOP: /* NOP 0x03 */
|
||||
uptr->CMD &= ~(0xffff); /* remove old cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"disk_srv cmd NOP chsa %04x count %04x completed\n",
|
||||
chsa, chp->ccw_count);
|
||||
@ -794,33 +799,36 @@ t_stat disk_srv(UNIT *uptr)
|
||||
unit, ch);
|
||||
chan_write_byte(chsa, &ch);
|
||||
}
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND);
|
||||
break;
|
||||
|
||||
case DSK_SCK: /* Seek cylinder, track, sector 0x07 */
|
||||
/* If we are waiting on seek to finish, check if there yet. */
|
||||
if (uptr->CMD & DSK_SEEKING) {
|
||||
if (uptr->CMDu3 & DSK_SEEKING) {
|
||||
/* see if on cylinder yet */
|
||||
if (STAR2CYL(uptr->STAR) == STAR2CYL(uptr->CHS)) {
|
||||
/* we are on cylinder, seek is done */
|
||||
sim_debug(DEBUG_CMD, dptr, "disk_srv seek on cylinder unit=%02x %04x %04x\n",
|
||||
unit, uptr->STAR >> 16, uptr->CHS >> 16);
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
/* we have already seeked to the required sector */
|
||||
/* we do not need to seek again, so move on */
|
||||
chan_end(chsa, SNS_DEVEND|SNS_CHNEND);
|
||||
sim_activate(uptr, 20);
|
||||
return SCPE_OK;
|
||||
//XXX sim_activate(uptr, 20);
|
||||
break;
|
||||
} else {
|
||||
/* we have wasted enough time, we are there */
|
||||
#ifndef DO_SEEK_AGAIN
|
||||
#ifdef DO_SEEK_AGAIN
|
||||
/* calculate file position in bytes of requested sector */
|
||||
/* file offset in bytes */
|
||||
tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type);
|
||||
/* just reseek to the location where we will r/w data */
|
||||
if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */
|
||||
sim_debug(DEBUG_DETAIL, dptr, "disk_srv Error on seek to %04x\n", tstart);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
return SCPE_OK;
|
||||
}
|
||||
#endif
|
||||
uptr->CHS = uptr->STAR; /* we are there */
|
||||
@ -849,25 +857,26 @@ t_stat disk_srv(UNIT *uptr)
|
||||
"disk_srv seek error unit=%02x star %02x %02x %02x %02x\n",
|
||||
unit, buf[0], buf[1], buf[2], buf[3]);
|
||||
/* we have error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK;
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
return SCPE_OK;
|
||||
break;
|
||||
}
|
||||
/* done reading, see how many we read */
|
||||
if (i == 1) {
|
||||
/* UTX wants to set seek STAR to zero */
|
||||
buf[0] = buf[1] = buf[2] = buf[3] = 0;
|
||||
break;
|
||||
}
|
||||
/* just read the next byte */
|
||||
}
|
||||
}
|
||||
/* done reading, see how many we read */
|
||||
if (i == 1) {
|
||||
/* UTX wants to set seek STAR to zero */
|
||||
buf[0] = buf[1] = buf[2] = buf[3] = 0;
|
||||
}
|
||||
/* else the cyl, trk, and sect are ready to update */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"disk_srv STAR unit=%02x star %02x %02x %02x %02x\n",
|
||||
unit, buf[0], buf[1], buf[2], buf[3]);
|
||||
rezero:
|
||||
//XXXrezero:
|
||||
sim_debug(DEBUG_DETAIL, dptr,
|
||||
"disk_srv seek unit=%02x star %02x %02x %02x %02x\n",
|
||||
unit, buf[0], buf[1], buf[2], buf[3]);
|
||||
@ -886,11 +895,11 @@ rezero:
|
||||
trk >= disk_type[type].nhds ||
|
||||
buf[3] >= disk_type[type].spt) {
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
sim_debug(DEBUG_EXP, dptr,
|
||||
"disk_srv seek ERROR cyl %04x trk %02x sec %02x unit=%02x\n",
|
||||
cyl, trk, buf[3], unit);
|
||||
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; /* set error status */
|
||||
|
||||
/* we have an error, tell user */
|
||||
@ -911,15 +920,18 @@ rezero:
|
||||
|
||||
/* just seek to the location where we will r/w data */
|
||||
if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */
|
||||
sim_debug(DEBUG_DETAIL, dptr, "disk_srv Error on seek to %04x\n", tstart);
|
||||
sim_debug(DEBUG_EXP, dptr, "disk_srv Error on seek to %04x\n", tstart);
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Check if already on correct cylinder */
|
||||
/* if not, do a delay to slow things down */
|
||||
if (STAR2CYL(uptr->STAR) != STAR2CYL(uptr->CHS)) {
|
||||
/* Do a fake seek to kill time */
|
||||
uptr->CMD |= DSK_SEEKING; /* show we are seeking */
|
||||
sim_debug(DEBUG_DETAIL, dptr,
|
||||
uptr->CMDu3 |= DSK_SEEKING; /* show we are seeking */
|
||||
sim_debug(DEBUG_EXP, dptr,
|
||||
"disk_srv seeking unit=%02x to cyl %04x trk %02x sec %02x\n",
|
||||
unit, cyl, trk, buf[3]);
|
||||
sim_activate(uptr, 20); /* start us off */
|
||||
@ -928,7 +940,7 @@ rezero:
|
||||
sim_debug(DEBUG_DETAIL, dptr,
|
||||
"disk_srv done seeking to %04x cyl %04x trk %02x sec %02x\n",
|
||||
tstart, cyl, trk, buf[3]);
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_DEVEND|SNS_CHNEND);
|
||||
}
|
||||
return SCPE_OK;
|
||||
@ -939,20 +951,38 @@ rezero:
|
||||
/* Do a seek to 0 */
|
||||
uptr->STAR = 0; /* set STAR to 0, 0, 0 */
|
||||
uptr->CHS = 0; /* set current CHS to 0, 0, 0 */
|
||||
uptr->CMD &= ~(0xffff); /* remove old cmd */
|
||||
uptr->CMD |= DSK_SCK; /* show as seek command */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
uptr->CMDu3 |= DSK_SCK; /* show as seek command */
|
||||
tstart = 0; /* byte offset is 0 */
|
||||
#ifdef NOT_NEEDED
|
||||
/* Read in 1 dummy character for length to inhibit SLI posting */
|
||||
if (chan_read_byte(chsa, &buf[0])) {
|
||||
/* we have error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK;
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
return SCPE_OK;
|
||||
//XXX break;
|
||||
}
|
||||
#endif
|
||||
#ifndef DO_NEW_WAY
|
||||
/* just seek to the location where we will r/w data */
|
||||
if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */
|
||||
sim_debug(DEBUG_EXP, dptr, "disk_srv Error on seek to %04x\n", tstart);
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
return SCPE_OK;
|
||||
}
|
||||
/* we are on cylinder/track/sector zero, so go on */
|
||||
sim_debug(DEBUG_DETAIL, dptr, "disk_srv done seek trk 0\n");
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_DEVEND|SNS_CHNEND);
|
||||
return SCPE_OK;
|
||||
#else
|
||||
/* zero stuff */
|
||||
buf[0] = buf[1] = buf[2] = buf[3] = 0;
|
||||
goto rezero; /* merge with seek code */
|
||||
#endif
|
||||
break;
|
||||
|
||||
case DSK_LMR:
|
||||
@ -960,28 +990,28 @@ rezero:
|
||||
/* Read in 1 character of mode data */
|
||||
if (chan_read_byte(chsa, &buf[0])) {
|
||||
/* we have error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK;
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
sim_debug(DEBUG_CMD, dptr, "Load Mode Reg unit=%02x old %x new %x\n",
|
||||
unit, (uptr->SNS)&0xff, buf[0]);
|
||||
uptr->CMD &= ~(0xffff); /* remove old cmd */
|
||||
uptr->SNS &= 0x00ffffff; /* clear old mode data */
|
||||
uptr->CMDu3 &= LMASK; /* remove old cmd */
|
||||
uptr->SNS &= MASK24; /* clear old mode data */
|
||||
uptr->SNS |= (buf[0] << 24); /* save mode value */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND);
|
||||
break;
|
||||
|
||||
case DSK_RD: /* Read Data */
|
||||
if ((uptr->CMD & DSK_READING) == 0) { /* see if we are reading data */
|
||||
uptr->CMD |= DSK_READING; /* read from disk starting */
|
||||
if ((uptr->CMDu3 & DSK_READING) == 0) { /* see if we are reading data */
|
||||
uptr->CMDu3 |= DSK_READING; /* read from disk starting */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"DISK READ starting CMD %08x chsa %04x buffer %06x count %04x\n",
|
||||
uptr->CMD, chsa, chp->ccw_addr, chp->ccw_count);
|
||||
uptr->CMDu3, chsa, chp->ccw_addr, chp->ccw_count);
|
||||
}
|
||||
|
||||
if (uptr->CMD & DSK_READING) { /* see if we are reading data */
|
||||
if (uptr->CMDu3 & DSK_READING) { /* see if we are reading data */
|
||||
cyl = STAR2CYL(uptr->CHS); /* get current cyl */
|
||||
trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */
|
||||
sec = uptr->CHS & 0xff; /* get sec */
|
||||
@ -989,12 +1019,16 @@ rezero:
|
||||
// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type));
|
||||
tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type));
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"DISK READ reading CMD %08x chsa %04x tstart %04x buffer %06x count %04x\n",
|
||||
uptr->CMDu3, chsa, tstart, chp->ccw_addr, chp->ccw_count);
|
||||
|
||||
/* read in a sector of data from disk */
|
||||
if ((len=sim_fread(buf, 1, ssize, uptr->fileref)) != ssize) {
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error %08x on read %04x of diskfile cyl %04x hds %02x sec %02x\n",
|
||||
len, ssize, cyl, trk, sec);
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
@ -1010,10 +1044,14 @@ rezero:
|
||||
sim_debug(DEBUG_DATA, dptr,
|
||||
"DISK Read %04x bytes leaving %04x from diskfile /%04x/%02x/%02x\n",
|
||||
i, chp->ccw_count, cyl, trk, sec);
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND);
|
||||
goto rddone;
|
||||
return SCPE_OK;
|
||||
//XXX goto rddone;
|
||||
}
|
||||
// sim_debug(DEBUG_DATA, dptr,
|
||||
// "DISK Read2 %04x bytes leaving %04x from diskfile /%04x/%02x/%02x\n",
|
||||
// i, chp->ccw_count, cyl, trk, sec);
|
||||
}
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
@ -1025,7 +1063,7 @@ rezero:
|
||||
sim_debug(DEBUG_DATA, dptr,
|
||||
"DISK Read complete for read from diskfile /%04x/%02x/%02x\n",
|
||||
STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff));
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND);
|
||||
break;
|
||||
}
|
||||
@ -1041,7 +1079,7 @@ rezero:
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"DISK Read reached EOM for read from disk @ /%04x/%02x/%02x\n",
|
||||
STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff));
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
uptr->CHS = 0; /* reset cylinder position */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
@ -1052,18 +1090,18 @@ rezero:
|
||||
chp->ccw_count, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff));
|
||||
sim_activate(uptr, 10); /* wait to read next sector */
|
||||
break;
|
||||
rddone:
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
//XXXrddone:
|
||||
//XXX uptr->CMDu3 &= ~(0xffff); /* remove old status bits & cmd */
|
||||
}
|
||||
break;
|
||||
|
||||
case DSK_WD: /* Write Data */
|
||||
if ((uptr->CMD & DSK_WRITING) == 0) { /* see if we are writing data */
|
||||
uptr->CMD |= DSK_WRITING; /* write to disk starting */
|
||||
if ((uptr->CMDu3 & DSK_WRITING) == 0) { /* see if we are writing data */
|
||||
uptr->CMDu3 |= DSK_WRITING; /* write to disk starting */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"DISK WRITE starting unit=%02x CMD %02x\n", unit, uptr->CMD);
|
||||
"DISK WRITE starting unit=%02x CMD %02x\n", unit, uptr->CMDu3);
|
||||
}
|
||||
if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */
|
||||
if (uptr->CMDu3 & DSK_WRITING) { /* see if we are writing data */
|
||||
cyl = STAR2CYL(uptr->CHS); /* get current cyl */
|
||||
trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */
|
||||
sec = uptr->CHS & 0xff; /* get sec */
|
||||
@ -1077,12 +1115,13 @@ rddone:
|
||||
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->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"DISK Wrote %04x bytes to diskfile cyl %04x hds %02x sec %02x\n",
|
||||
ssize, cyl, trk, sec);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND);
|
||||
goto wrdone;
|
||||
return SCPE_OK;
|
||||
//XXX goto wrdone;
|
||||
}
|
||||
ch = 0; /* finish out the sector with zero */
|
||||
len++; /* show we have no more data to write */
|
||||
@ -1095,7 +1134,7 @@ rddone:
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error %08x on write %04x bytes to diskfile cyl %04x hds %02x sec %02x\n",
|
||||
i, ssize, cyl, trk, sec);
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
@ -1103,7 +1142,7 @@ rddone:
|
||||
sim_debug(DEBUG_DATA, dptr,
|
||||
"DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x\n",
|
||||
ssize, cyl, trk, sec);
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */
|
||||
break;
|
||||
}
|
||||
@ -1122,15 +1161,15 @@ rddone:
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"DISK Write reached EOM for write to disk @ /%04x/%02x/%02x\n",
|
||||
STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff));
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
uptr->CHS = 0; /* reset cylinder position */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
sim_activate(uptr, 10); /* keep writing */
|
||||
break;
|
||||
wrdone:
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
//XXXwrdone:
|
||||
//XXX uptr->CMDu3 &= ~(0xffff); /* remove old status bits & cmd */
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1216,7 +1255,7 @@ wrdone:
|
||||
for (i = 0; i < 30; i++) {
|
||||
if (chan_write_byte(chsa, &buf[i])) {
|
||||
/* we have write error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
@ -1227,7 +1266,7 @@ wrdone:
|
||||
sim_debug(DEBUG_DETAIL, dptr, "\n");
|
||||
|
||||
/* command done */
|
||||
uptr->CMD &= ~(0xffff); /* remove old cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd RSL done chsa %04x count %04x completed\n",
|
||||
chsa, chp->ccw_count);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */
|
||||
@ -1331,7 +1370,7 @@ wrdone:
|
||||
for (i = 0; i < 30; i++) {
|
||||
if (chan_write_byte(chsa, &buf[i])) {
|
||||
/* we have write error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
@ -1342,7 +1381,7 @@ wrdone:
|
||||
sim_debug(DEBUG_DETAIL, dptr, "\n");
|
||||
|
||||
/* command done */
|
||||
uptr->CMD &= ~(0xffff); /* remove old cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
sim_debug(DEBUG_CMD, dptr, "disk_srv cmd RTL done chsa %04x count %04x completed\n",
|
||||
chsa, chp->ccw_count);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */
|
||||
@ -1351,7 +1390,7 @@ wrdone:
|
||||
default:
|
||||
sim_debug(DEBUG_CMD, dptr, "invalid command %02x unit %02x\n", cmd, unit);
|
||||
uptr->SNS |= SNS_CMDREJ;
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
@ -1366,13 +1405,16 @@ void disk_ini(UNIT *uptr, t_bool f)
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
int i = GET_TYPE(uptr->flags);
|
||||
|
||||
uptr->CMD &= ~0x7fff; /* clear out the flags but leave ch/sa */
|
||||
/* start out at sector 0 */
|
||||
uptr->CHS = 0; /* set CHS to cyl/hd/sec = 0 */
|
||||
uptr->STAR = 0; /* set STAR to cyl/hd/sec = 0 */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
uptr->SNS = ((uptr->SNS & 0x00ffffff) | (disk_type[i].type << 24)); /* save mode value */
|
||||
/* total sectors on disk */
|
||||
uptr->capac = CAP(i); /* size in sectors */
|
||||
|
||||
sim_debug(DEBUG_EXP, &dda_dev, "DMA init device %s on unit DMA%.1x cap %x %d\n",
|
||||
dptr->name, GET_UADDR(uptr->CMD), uptr->capac, uptr->capac);
|
||||
dptr->name, GET_UADDR(uptr->CMDu3), uptr->capac, uptr->capac);
|
||||
}
|
||||
|
||||
t_stat disk_reset(DEVICE *dptr)
|
||||
@ -1472,6 +1514,7 @@ int disk_format(UNIT *uptr) {
|
||||
/* seek to sector 0 */
|
||||
if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */
|
||||
fprintf (stderr, "Error on seek to 0\r\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* get buffer for track data in bytes */
|
||||
@ -1524,10 +1567,15 @@ int disk_format(UNIT *uptr) {
|
||||
/* setup dmap pointed to by track label 0 wd[3] = (cyl-4) * spt + (spt - 1) */
|
||||
|
||||
/* write dmap data to last sector on disk */
|
||||
sim_fseek(uptr->fileref, laddr*ssize, SEEK_SET); /* seek last sector */
|
||||
if ((sim_fseek(uptr->fileref, laddr*ssize, SEEK_SET)) != 0) { /* seek last sector */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on last sector seek to diskfile sect %06x\n", (cap-1) * ssize);
|
||||
return 1;
|
||||
}
|
||||
if ((sim_fwrite((char *)&dmap, sizeof(uint32), 4, uptr->fileref)) != 4) {
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on vendor map write to diskfile sect %06x\n", (cap-1) * ssize);
|
||||
"Error on last sector write to diskfile sect %06x\n", (cap-1) * ssize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 1 cylinder is saved for disk manufacture */
|
||||
@ -1537,26 +1585,41 @@ int disk_format(UNIT *uptr) {
|
||||
/* vaddr is (cap) - 3 cyl - 1 track */
|
||||
|
||||
/* seek to vendor label area */
|
||||
sim_fseek(uptr->fileref, (vaddr)*ssize, SEEK_SET); /* seek VMAP */
|
||||
if ((sim_fseek(uptr->fileref, vaddr*ssize, SEEK_SET)) != 0) { /* seek VMAP */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on vendor map seek to diskfile sect %06x\n", (cap-1) * ssize);
|
||||
return 1;
|
||||
}
|
||||
if ((sim_fwrite((char *)&vmap, sizeof(uint32), 2, uptr->fileref)) != 2) {
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on vendor map write to diskfile sect %06x\n", vaddr * ssize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* write dmap to daddr that is the address in trk 0 label */
|
||||
/* daddr is (cap) - 3 cyl - 2 tracks */
|
||||
/* vaddr is daddr - spt */
|
||||
|
||||
sim_fseek(uptr->fileref, (daddr)*ssize, SEEK_SET); /* seek DMAP */
|
||||
if ((sim_fseek(uptr->fileref, daddr*ssize, SEEK_SET)) != 0) { /* seek DMAP */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on daddr seek to diskfile sect %06x\n", (cap-1) * ssize);
|
||||
return 1;
|
||||
}
|
||||
if ((sim_fwrite((char *)&dmap, sizeof(uint32), 4, uptr->fileref)) != 4) {
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on dmap write to diskfile sect %06x\n", daddr * ssize);
|
||||
"Error on daddr write to diskfile sect %06x\n", daddr * ssize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sim_fseek(uptr->fileref, (uaddr)*ssize, SEEK_SET); /* seek UMAP */
|
||||
if ((sim_fseek(uptr->fileref, uaddr*ssize, SEEK_SET)) != 0) { /* seek UMAP */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on umap seek to diskfile sect %06x\n", (cap-1) * ssize);
|
||||
return 1;
|
||||
}
|
||||
if ((sim_fwrite((char *)&umap, sizeof(uint32), 256, uptr->fileref)) != 256) {
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on umap write to diskfile sect %06x\n", uaddr * ssize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("writing to vmap sec %x (%d) bytes %x (%d)\n",
|
||||
@ -1568,7 +1631,10 @@ int disk_format(UNIT *uptr) {
|
||||
daddr, daddr, daddr*ssize, daddr*ssize);
|
||||
|
||||
/* seek home again */
|
||||
sim_fseek(uptr->fileref, 0, SEEK_SET); /* seek home */
|
||||
if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */
|
||||
fprintf (stderr, "Error on seek to 0\r\n");
|
||||
return 1;
|
||||
}
|
||||
free(buff); /* free cylinder buffer */
|
||||
return 0;
|
||||
}
|
||||
@ -1576,7 +1642,7 @@ int disk_format(UNIT *uptr) {
|
||||
/* attach the selected file to the disk */
|
||||
t_stat disk_attach(UNIT *uptr, CONST char *file)
|
||||
{
|
||||
uint16 chsa = GET_UADDR(uptr->CMD);
|
||||
uint16 chsa = GET_UADDR(uptr->CMDu3);
|
||||
int type = GET_TYPE(uptr->flags);
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
t_stat r;
|
||||
@ -1647,7 +1713,7 @@ fmt:
|
||||
/* detach a disk device */
|
||||
t_stat disk_detach(UNIT *uptr) {
|
||||
uptr->SNS = 0; /* clear sense data */
|
||||
uptr->CMD &= ~0xffff; /* no cmd and flags */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
return detach_unit(uptr); /* tell simh we are done with disk */
|
||||
}
|
||||
|
||||
@ -1655,13 +1721,19 @@ t_stat disk_detach(UNIT *uptr) {
|
||||
t_stat disk_boot(int32 unit_num, DEVICE *dptr) {
|
||||
UNIT *uptr = &dptr->units[unit_num]; /* find disk unit number */
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr, "Disk Boot dev/unit %x\n", GET_UADDR(uptr->CMD));
|
||||
SPAD[0xf4] = GET_UADDR(uptr->CMD); /* put boot device chan/sa into spad */
|
||||
SPAD[0xf8] = 0xF000; /* show as F class device */
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
sim_debug(DEBUG_CMD, dptr, "Disk Boot dev/unit %x\n", GET_UADDR(uptr->CMDu3));
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) {
|
||||
sim_debug(DEBUG_EXP, &mta_dev, "Disk Boot attach error dev/unit %04x\n",
|
||||
GET_UADDR(uptr->CMDu3));
|
||||
return SCPE_UNATT; /* attached? */
|
||||
}
|
||||
SPAD[0xf4] = GET_UADDR(uptr->CMDu3); /* put boot device chan/sa into spad */
|
||||
SPAD[0xf8] = 0xF000; /* show as F class device */
|
||||
|
||||
/* now boot the disk */
|
||||
return chan_boot(GET_UADDR(uptr->CMD), dptr); /* boot the ch/sa */
|
||||
uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */
|
||||
return chan_boot(GET_UADDR(uptr->CMDu3), dptr); /* boot the ch/sa */
|
||||
}
|
||||
|
||||
/* Disk option setting commands */
|
||||
|
||||
@ -833,7 +833,7 @@ uint32 s_dvfw(uint32 reg, uint32 mem, uint32 *cc) {
|
||||
if (temp2 >= 0x7fffffc0) /* check for special rounding */
|
||||
goto RRND2; /* no special handling */
|
||||
/* FIXME dead code */
|
||||
if (temp2 == MSIGN) { /* check for minux zero */
|
||||
if (temp2 == MSIGN) { /* check for minus zero */
|
||||
temp2 = 0xF8000000; /* yes, fixup value */
|
||||
expr++; /* bump exponent */
|
||||
}
|
||||
@ -844,9 +844,11 @@ uint32 s_dvfw(uint32 reg, uint32 mem, uint32 *cc) {
|
||||
if ((sign & MSIGN) == 0)
|
||||
goto RRND1; /* if sign set, don't round yet */
|
||||
expr += temp; /* add exponent */
|
||||
if (expr < 0) /* test for underflow */
|
||||
/* FIX unsigned CMP */
|
||||
// if (expr < 0) /* test for underflow */
|
||||
if ((int32)expr < 0) /* test for underflow */
|
||||
goto DUNFLO; /* go process underflow */
|
||||
if (expr > 0x7f) /* test for overflow */
|
||||
if ((int32)expr > 0x7f) /* test for overflow */
|
||||
goto DOVFLO; /* go process overflow */
|
||||
expr ^= FMASK; /* complement exponent */
|
||||
temp2 += 0x40; /* round at bit 25 */
|
||||
@ -858,7 +860,7 @@ RRND2:
|
||||
if ((int32)expr < 0) { /* test for underflow */
|
||||
goto DUNFLO; /* go process underflow */
|
||||
}
|
||||
if (expr > 0x7f) { /* test for overflow */
|
||||
if ((int32)expr > 0x7f) { /* test for overflow */
|
||||
goto DOVFLO; /* go process overflow */
|
||||
}
|
||||
if (sign & MSIGN) /* test for negative */
|
||||
|
||||
@ -352,9 +352,9 @@ hsdp_type[] =
|
||||
|
||||
uint8 hsdp_preio(UNIT *uptr, uint16 chan) ;
|
||||
uint8 hsdp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ;
|
||||
uint8 hsdp_haltio(uint16 addr);
|
||||
uint8 hsdp_haltio(UNIT *uptr);
|
||||
t_stat hsdp_srv(UNIT *);
|
||||
t_stat hsdp_boot(int32, DEVICE *);
|
||||
t_stat hsdp_boot(int32 unitnum, DEVICE *);
|
||||
void hsdp_ini(UNIT *, t_bool);
|
||||
t_stat hsdp_reset(DEVICE *);
|
||||
t_stat hsdp_attach(UNIT *, CONST char *);
|
||||
@ -409,6 +409,7 @@ DEVICE dpa_dev = {
|
||||
"DPA", dpa_unit, NULL, hsdp_mod,
|
||||
NUM_UNITS_HSDP, 16, 24, 4, 16, 32,
|
||||
NULL, NULL, &hsdp_reset, &hsdp_boot, &hsdp_attach, &hsdp_detach,
|
||||
/* ctxt is the DIB pointer */
|
||||
&dpa_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug,
|
||||
NULL, NULL, &hsdp_help, NULL, NULL, &hsdp_description
|
||||
};
|
||||
@ -451,6 +452,7 @@ DEVICE dpb_dev = {
|
||||
"DPB", dpb_unit, NULL, hsdp_mod,
|
||||
NUM_UNITS_HSDP, 16, 24, 4, 16, 32,
|
||||
NULL, NULL, &hsdp_reset, &hsdp_boot, &hsdp_attach, &hsdp_detach,
|
||||
/* ctxt is the DIB pointer */
|
||||
&dpb_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug,
|
||||
NULL, NULL, &hsdp_help, NULL, NULL, &hsdp_description
|
||||
};
|
||||
@ -723,6 +725,7 @@ t_stat hsdp_srv(UNIT *uptr)
|
||||
/* we have write error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
goto goout;
|
||||
break;
|
||||
}
|
||||
if ((i%16) == 0)
|
||||
@ -730,8 +733,8 @@ t_stat hsdp_srv(UNIT *uptr)
|
||||
sim_debug(DEBUG_DETAIL, dptr, " %02x", buf[i]);
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, dptr, "\n");
|
||||
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */
|
||||
goout:
|
||||
break;
|
||||
|
||||
case DSK_WTL: /* WTL 0x51 make into NOP */
|
||||
@ -747,6 +750,7 @@ t_stat hsdp_srv(UNIT *uptr)
|
||||
/* we have read error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
goto goout;
|
||||
break;
|
||||
}
|
||||
if (i == 16)
|
||||
@ -857,17 +861,20 @@ t_stat hsdp_srv(UNIT *uptr)
|
||||
/* we have already seeked to the required sector */
|
||||
/* we do not need to seek again, so move on */
|
||||
chan_end(chsa, SNS_DEVEND|SNS_CHNEND);
|
||||
sim_activate(uptr, 20);
|
||||
return SCPE_OK;
|
||||
//XXX sim_activate(uptr, 20);
|
||||
break;
|
||||
} else {
|
||||
/* we have wasted enough time, we there */
|
||||
#ifndef DO_SEEK_AGAIN
|
||||
#ifdef DO_SEEK_AGAIN
|
||||
/* calculate file position in bytes of requested sector */
|
||||
/* file offseet in bytes */
|
||||
tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type);
|
||||
/* just reseek to the location where we will r/w data */
|
||||
if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* do seek */
|
||||
sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv Error on seek to %04x\n", tstart);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
return SCPE_OK;
|
||||
}
|
||||
#endif
|
||||
uptr->CHS = uptr->STAR; /* we are there */
|
||||
@ -903,13 +910,14 @@ t_stat hsdp_srv(UNIT *uptr)
|
||||
break;
|
||||
}
|
||||
/* just read the next byte */
|
||||
/* done reading, see how many we read */
|
||||
if (i == 1) {
|
||||
/* UTX wants to set seek STAR to zero */
|
||||
buf[0] = buf[1] = buf[2] = buf[3] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* done reading, see how many we read */
|
||||
if (i == 1) {
|
||||
/* UTX wants to set seek STAR to zero */
|
||||
buf[0] = buf[1] = buf[2] = buf[3] = 0;
|
||||
}
|
||||
/* else the cyl, trk, and sect are ready to update */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"hsdp_srv STAR unit=%02x star %02x %02x %02x %02x\n",
|
||||
@ -958,6 +966,8 @@ rezero:
|
||||
/* just seek to the location where we will r/w data */
|
||||
if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* seek home */
|
||||
sim_debug(DEBUG_DETAIL, dptr, "hsdp_srv Error on seek to %08x\n", tstart);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Check if already on correct cylinder */
|
||||
@ -1471,6 +1481,9 @@ void hsdp_ini(UNIT *uptr, t_bool f)
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
int i = GET_TYPE(uptr->flags);
|
||||
|
||||
/* start out at sector 0 */
|
||||
uptr->CHS = 0; /* set CHS to cyl/hd/sec = 0 */
|
||||
uptr->STAR = 0; /* set STAR to cyl/hd/sec = 0 */
|
||||
uptr->CMD &= ~0x7fff; /* clear out the flags but leave ch/sa */
|
||||
uptr->SNS = ((uptr->SNS & 0x00ffffff) | (hsdp_type[i].type << 24)); /* save mode value */
|
||||
/* total sectors on disk */
|
||||
@ -1600,6 +1613,7 @@ int hsdp_format(UNIT *uptr) {
|
||||
/* seek to sector 0 */
|
||||
if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */
|
||||
fprintf (stderr, "Error on seek to 0\r\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* get buffer for track data in bytes */
|
||||
@ -1652,10 +1666,14 @@ int hsdp_format(UNIT *uptr) {
|
||||
/* setup dmap pointed to by track label 0 wd[3] = (cyl-4) * spt + (spt - 1) */
|
||||
|
||||
/* write dmap data to last sector on disk */
|
||||
sim_fseek(uptr->fileref, laddr*ssize, SEEK_SET); /* seek last sector */
|
||||
if ((sim_fseek(uptr->fileref, laddr*ssize, SEEK_SET)) != 0) { /* seek last sector */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on last sector seek to diskfile sect %06x\n", (cap-1) * ssize);
|
||||
return 1;
|
||||
}
|
||||
if ((sim_fwrite((char *)&dmap, sizeof(uint32), 4, uptr->fileref)) != 4) {
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on vendor map write to diskfile sect %06x\n", (cap-1) * ssize);
|
||||
"Error on last sectdor write to diskfile sect %06x\n", (cap-1) * ssize);
|
||||
}
|
||||
|
||||
/* 1 cylinder is saved for disk manufacture */
|
||||
@ -1665,7 +1683,11 @@ int hsdp_format(UNIT *uptr) {
|
||||
/* vaddr is (cap) - 3 cyl - 1 track */
|
||||
|
||||
/* seek to vendor label area */
|
||||
sim_fseek(uptr->fileref, (vaddr)*ssize, SEEK_SET); /* seek UMAP */
|
||||
if ((sim_fseek(uptr->fileref, vaddr*ssize, SEEK_SET)) != 0) { /* seek VMAP */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on vendor map seek to diskfile sect %06x\n", (cap-1) * ssize);
|
||||
return 1;
|
||||
}
|
||||
if ((sim_fwrite((char *)&vmap, sizeof(uint32), 2, uptr->fileref)) != 2) {
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on vendor map write to diskfile sect %06x\n", vaddr * ssize);
|
||||
@ -1675,16 +1697,26 @@ int hsdp_format(UNIT *uptr) {
|
||||
/* daddr is (cap) - 3 cyl - 2 tracks */
|
||||
/* vaddr is daddr - spt */
|
||||
|
||||
sim_fseek(uptr->fileref, (daddr)*ssize, SEEK_SET); /* seek DMAP */
|
||||
if ((sim_fseek(uptr->fileref, daddr*ssize, SEEK_SET)) != 0) { /* seek DMAP */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on dmap seek to diskfile sect %06x\n", (cap-1) * ssize);
|
||||
return 1;
|
||||
}
|
||||
if ((sim_fwrite((char *)&dmap, sizeof(uint32), 4, uptr->fileref)) != 4) {
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on dmap write to diskfile sect %06x\n", daddr * ssize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sim_fseek(uptr->fileref, (uaddr)*ssize, SEEK_SET); /* seek UMAP */
|
||||
if ((sim_fseek(uptr->fileref, uaddr*ssize, SEEK_SET)) != 0) { /* seek UMAP */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on umap seek to diskfile sect %06x\n", (cap-1) * ssize);
|
||||
return 1;
|
||||
}
|
||||
if ((sim_fwrite((char *)&umap, sizeof(uint32), 256, uptr->fileref)) != 256) {
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error on umap write to diskfile sect %06x\n", uaddr * ssize);
|
||||
"Error on umap write to diskfile sect %06x\n", uaddr * ssize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("writing to vmap sec %x (%d) bytes %x (%d)\n",
|
||||
@ -1696,7 +1728,11 @@ int hsdp_format(UNIT *uptr) {
|
||||
daddr, daddr, daddr*ssize, daddr*ssize);
|
||||
|
||||
/* seek home again */
|
||||
sim_fseek(uptr->fileref, 0, SEEK_SET); /* seek home */
|
||||
if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */
|
||||
fprintf (stderr, "Error on seek to 0\r\n");
|
||||
return 1;
|
||||
}
|
||||
free(buff); /* free cylinder buffer */
|
||||
free(buff); /* free cylinder buffer */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -190,6 +190,7 @@ DEVICE lpr_dev = {
|
||||
"LPR", lpr_unit, NULL, lpr_mod,
|
||||
NUM_DEVS_LPR, 8, 15, 1, 8, 8,
|
||||
NULL, NULL, NULL, NULL, &lpr_attach, &lpr_detach,
|
||||
/* ctxt is the DIB pointer */
|
||||
&lpr_dib, DEV_UADDR | DEV_DISABLE | DEV_DEBUG, 0, dev_debug
|
||||
};
|
||||
|
||||
|
||||
275
SEL32/sel32_mfp.c
Normal file
275
SEL32/sel32_mfp.c
Normal file
@ -0,0 +1,275 @@
|
||||
/* sel32_mfp.c: SEL-32 Model 8000/8001/8002 MFP processor controller
|
||||
|
||||
Copyright (c) 2018-2020, James C. Bevier
|
||||
|
||||
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.
|
||||
|
||||
This channel is the interrupt fielder for all of the MFP sub channels. It's
|
||||
channel address is 7600. This code handles the INCH command for the MFP
|
||||
devices and controls the status FIFO for the mfp devices on interrupts and
|
||||
TIO instructions..
|
||||
|
||||
Possible devices:
|
||||
The f8iop communication controller (TY76A0), (TY76B0), (TY76C0)
|
||||
The ctiop console communications controller (CT76FC & CT76FD)
|
||||
The lpiop line printer controller (LP76F8), (LP76F9)
|
||||
The scsi SCSI disk controller (DM7600), (DM7640)
|
||||
|
||||
*/
|
||||
|
||||
#include "sel32_defs.h"
|
||||
|
||||
#ifdef NUM_DEVS_MFP
|
||||
|
||||
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_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */
|
||||
extern CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */
|
||||
|
||||
/* forward definitions */
|
||||
uint8 mfp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd);
|
||||
void mfp_ini(UNIT *uptr, t_bool f);
|
||||
t_stat mfp_srv(UNIT *uptr);
|
||||
t_stat mfp_reset(DEVICE *dptr);
|
||||
t_stat mfp_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
||||
const char *mfp_desc(DEVICE *dptr);
|
||||
|
||||
/* Held in u3 is the device command and status */
|
||||
#define MFP_INCH 0x00 /* Initialize channel command */
|
||||
#define MFP_INCH2 0xf0 /* Initialize channel command after start */
|
||||
#define MFP_NOP 0x03 /* NOP command */
|
||||
#define MFP_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 */
|
||||
|
||||
/* not used 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 */
|
||||
/* sense byte 3 */
|
||||
#define SNS_RDY 0x80 /* device ready */
|
||||
#define SNS_ONLN 0x40 /* device online */
|
||||
|
||||
/* std devices. data structures
|
||||
|
||||
mfp_dev Console device descriptor
|
||||
mfp_unit Console unit descriptor
|
||||
mfp_reg Console register list
|
||||
mfp_mod Console modifiers list
|
||||
*/
|
||||
|
||||
struct _mfp_data
|
||||
{
|
||||
uint8 ibuff[145]; /* Input line buffer */
|
||||
uint8 incnt; /* char count */
|
||||
}
|
||||
mfp_data[NUM_UNITS_MFP];
|
||||
|
||||
/* channel program information */
|
||||
CHANP mfp_chp[NUM_UNITS_MFP] = {0};
|
||||
|
||||
MTAB mfp_mod[] = {
|
||||
{MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV",
|
||||
&set_dev_addr, &show_dev_addr, NULL, "Device address"},
|
||||
{0}
|
||||
};
|
||||
|
||||
UNIT mfp_unit[] = {
|
||||
{UDATA(&mfp_srv, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7600)}, /* Channel controller */
|
||||
};
|
||||
|
||||
//DIB mfp_dib = {NULL, mfp_startcmd, NULL, NULL, NULL, mfp_ini, mfp_unit, mfp_chp, NUM_UNITS_MFP, 0xff, 0x7e00,0,0,0};
|
||||
DIB mfp_dib = {
|
||||
NULL, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Start I/O */
|
||||
mfp_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 */
|
||||
mfp_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */
|
||||
mfp_unit, /* UNIT* units */ /* Pointer to units structure */
|
||||
mfp_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */
|
||||
NUM_UNITS_MFP, /* uint8 numunits */ /* number of units defined */
|
||||
0xff, /* 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 */
|
||||
};
|
||||
|
||||
DEVICE mfp_dev = {
|
||||
"MFP", mfp_unit, NULL, mfp_mod,
|
||||
NUM_UNITS_MFP, 8, 15, 1, 8, 8,
|
||||
NULL, NULL, &mfp_reset, /* examine, deposit, reset */
|
||||
NULL, NULL, NULL, /* boot, attach, detach */
|
||||
&mfp_dib, DEV_UADDR|DEV_DISABLE|DEV_DEBUG, 0, dev_debug, /* dib, dev flags, debug flags, debug */
|
||||
// NULL, NULL, &mfp_help, /* ?, ?, help */
|
||||
// NULL, NULL, &mfp_desc /* ?, ?, description */
|
||||
};
|
||||
|
||||
/* MFP controller routines */
|
||||
/* initialize the console chan/unit */
|
||||
void mfp_ini(UNIT *uptr, t_bool f)
|
||||
{
|
||||
int unit = (uptr - mfp_unit); /* unit 0 */
|
||||
DEVICE *dptr = &mfp_dev; /* one and only dummy device */
|
||||
|
||||
sim_debug(DEBUG_CMD, &mfp_dev,
|
||||
"MFP init device %s controller/device %04x\n",
|
||||
dptr->name, GET_UADDR(uptr->u3));
|
||||
mfp_data[unit].incnt = 0; /* no input data */
|
||||
uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */
|
||||
}
|
||||
|
||||
/* start an I/O operation */
|
||||
uint8 mfp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
{
|
||||
sim_debug(DEBUG_CMD, &mfp_dev,
|
||||
"MFP startcmd %02x controller/device %04x\n",
|
||||
cmd, GET_UADDR(uptr->u3));
|
||||
if ((uptr->u3 & MFP_MSK) != 0) /* is unit busy */
|
||||
return SNS_BSY; /* yes, return busy */
|
||||
|
||||
/* process the commands */
|
||||
switch (cmd & 0xFF) {
|
||||
/* UTX uses the INCH cmd to detect the MFP or MFP */
|
||||
/* MFP has INCH cmd of 0, while MFP uses 0x80 */
|
||||
case MFP_INCH: /* INCH command */
|
||||
uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */
|
||||
uptr->u3 &= LMASK; /* leave only chsa */
|
||||
sim_debug(DEBUG_CMD, &mfp_dev,
|
||||
"mfp_startcmd %04x: Cmd INCH iptr %06x INCHa %06x\n",
|
||||
chan, mfp_chp[0].ccw_addr, /* set inch buffer addr */
|
||||
mfp_chp[0].chan_inch_addr); /* set inch buffer addr */
|
||||
|
||||
mfp_chp[0].chan_inch_addr = mfp_chp[0].ccw_addr; /* set inch buffer addr */
|
||||
// set_inch(uptr, mfp_chp[0].ccw_addr); /* new address */
|
||||
|
||||
uptr->u3 |= MFP_INCH2; /* save INCH command as 0xf0 */
|
||||
sim_activate(uptr, 20); /* go on */
|
||||
return 0; /* no status change */
|
||||
break;
|
||||
|
||||
case MFP_NOP: /* NOP command */
|
||||
sim_debug(DEBUG_CMD, &mfp_dev, "mfp_startcmd %04x: Cmd NOP\n", chan);
|
||||
uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */
|
||||
uptr->u3 &= LMASK; /* leave only chsa */
|
||||
uptr->u3 |= (cmd & MFP_MSK); /* save NOP command */
|
||||
sim_activate(uptr, 20); /* TRY 07-13-19 */
|
||||
return 0; /* no status change */
|
||||
break;
|
||||
|
||||
default: /* invalid command */
|
||||
uptr->u5 |= SNS_CMDREJ; /* command rejected */
|
||||
sim_debug(DEBUG_CMD, &mfp_dev, "mfp_startcmd %04x: Cmd Invalid %02x status %02x\n",
|
||||
chan, cmd, uptr->u5);
|
||||
uptr->u3 &= LMASK; /* leave only chsa */
|
||||
uptr->u3 |= (cmd & MFP_MSK); /* save command */
|
||||
sim_activate(uptr, 20); /* force interrupt */
|
||||
return 0; /* no status change */
|
||||
break;
|
||||
}
|
||||
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* not reachable for now */
|
||||
}
|
||||
|
||||
/* Handle transfers for other sub-channels on MFP */
|
||||
t_stat mfp_srv(UNIT *uptr)
|
||||
{
|
||||
uint16 chsa = GET_UADDR(uptr->u3);
|
||||
int cmd = uptr->u3 & MFP_MSK;
|
||||
// CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */
|
||||
CHANP *chp = &mfp_chp[0]; /* find the chanp pointer */
|
||||
// int i;
|
||||
// int len = chp->ccw_count; /* INCH command count */
|
||||
uint32 mema = chp->ccw_addr; /* get inch or buffer addr */
|
||||
|
||||
/* test for NOP or INCH cmds */
|
||||
if ((cmd != MFP_NOP) && (cmd != MFP_INCH2)) { /* NOP or INCH */
|
||||
uptr->u3 &= LMASK; /* nothing left, command complete */
|
||||
sim_debug(DEBUG_CMD, &mfp_dev,
|
||||
"mfp_srv Unknown cmd %02x chan %02x: chnend|devend|unitexp\n", cmd, chsa);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* done */
|
||||
return SCPE_OK;
|
||||
} else
|
||||
|
||||
if (cmd == MFP_NOP) { /* NOP do nothing */
|
||||
uptr->u3 &= LMASK; /* nothing left, command complete */
|
||||
sim_debug(DEBUG_CMD, &mfp_dev, "mfp_srv INCH/NOP chan %02x: chnend|devend\n", chsa);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */
|
||||
return SCPE_OK;
|
||||
} else
|
||||
|
||||
/* test for INCH cmd */
|
||||
if (cmd == MFP_INCH2) { /* INCH */
|
||||
sim_debug(DEBUG_CMD, &mfp_dev,
|
||||
"mfp_srv starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n",
|
||||
mema, chsa, chp->ccw_addr, chp->ccw_count);
|
||||
|
||||
/* the chp->ccw_addr location contains the inch address */
|
||||
/* call set_inch() to setup inch buffer */
|
||||
// i = set_inch(uptr, mema); /* new address */
|
||||
set_inch(uptr, mema); /* new address */
|
||||
// chp->chan_inch_addr = mema; /* set inch buffer addr */
|
||||
uptr->u3 &= LMASK; /* clear the cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */
|
||||
// chan_end(chsa, SNS_CHNEND); /* we are done dev|chan end */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat mfp_reset(DEVICE *dptr)
|
||||
{
|
||||
/* add reset code here */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* sho help mfp */
|
||||
t_stat mfp_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr)
|
||||
{
|
||||
fprintf(st, "SEL-32 MFP Model 8002 Channel Controller at 0x7600\r\n");
|
||||
fprintf(st, "The MFP fields all interrupts and status posting\r\n");
|
||||
fprintf(st, "for each of the controllers on the system.\r\n");
|
||||
fprintf(st, "Nothing can be configured for this Channel.\r\n");
|
||||
// fprint_set_help(st, dptr);
|
||||
// fprint_show_help(st, dptr);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
const char *mfp_desc(DEVICE *dptr)
|
||||
{
|
||||
return("SEL-32 MFP Model 8002 Channel Controller @ 0x7600");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
126
SEL32/sel32_mt.c
126
SEL32/sel32_mt.c
@ -160,20 +160,19 @@ extern uint32 SPAD[]; /* cpu SPAD */
|
||||
#define BUF_EMPTY(u) (u->hwmark == 0xFFFFFFFF)
|
||||
#define CLR_BUF(u) u->hwmark = 0xFFFFFFFF
|
||||
|
||||
uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ;
|
||||
t_stat mt_srv(UNIT *);
|
||||
t_stat mt_boot(int32, DEVICE *);
|
||||
void mt_ini(UNIT *, t_bool);
|
||||
t_stat mt_reset(DEVICE *);
|
||||
t_stat mt_attach(UNIT *, CONST char *);
|
||||
t_stat mt_detach(UNIT *);
|
||||
t_stat mt_boot(int32, DEVICE *);
|
||||
t_stat mt_help(FILE *, DEVICE *, UNIT *, int32, const char *);
|
||||
const char *mt_description(DEVICE *);
|
||||
uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ;
|
||||
t_stat mt_srv(UNIT *uptr);
|
||||
t_stat mt_boot(int32 unitnum, DEVICE *dptr);
|
||||
void mt_ini(UNIT *uptr, t_bool);
|
||||
t_stat mt_reset(DEVICE *dptr);
|
||||
t_stat mt_attach(UNIT *uptr, CONST char *);
|
||||
t_stat mt_detach(UNIT *uptr);
|
||||
t_stat mt_help(FILE *, DEVICE *dptr, UNIT *uptr, int32, const char *);
|
||||
const char *mt_description(DEVICE *);
|
||||
|
||||
/* One buffer per channel */
|
||||
uint8 mt_buffer[NUM_DEVS_MT][BUFFSIZE];
|
||||
uint8 mt_busy[NUM_DEVS_MT];
|
||||
uint8 mt_buffer[NUM_DEVS_MT][BUFFSIZE];
|
||||
uint8 mt_busy[NUM_DEVS_MT];
|
||||
|
||||
/* Gould Buffered Tape Processor (BTP) - Model 8051 */
|
||||
/* Integrated channel controller */
|
||||
@ -313,7 +312,7 @@ DIB mta_dib = {
|
||||
mta_unit, /* Pointer to units structure */
|
||||
mta_chp, /* Pointer to chan_prg structure */
|
||||
NUM_UNITS_MT, /* number of units defined */
|
||||
0xFF, /* 256 devices - device mask */
|
||||
0x07, /* 8 devices - device mask */
|
||||
0x1000, /* parent channel address */
|
||||
0, /* fifo input index */
|
||||
0, /* fifo output index */
|
||||
@ -356,8 +355,8 @@ DIB mtb_dib = {
|
||||
mtb_unit, /* Pointer to units structure */
|
||||
mtb_chp, /* Pointer to chan_prg structure */
|
||||
NUM_UNITS_MT, /* number of units defined */
|
||||
0xFF, /* 256 devices - device mask */
|
||||
0x1000, /* parent channel address */
|
||||
0x07, /* 6 devices - device mask */
|
||||
0x1800, /* parent channel address */
|
||||
0, /* fifo input index */
|
||||
0, /* fifo output index */
|
||||
0, /* interrupt status fifo for channel */
|
||||
@ -387,15 +386,15 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
return SNS_BSY;
|
||||
}
|
||||
|
||||
sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd processing unit %04x cmd %02x\n", unit, cmd);
|
||||
sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd processing unit %01x cmd %02x\n", unit, cmd);
|
||||
|
||||
switch (cmd & 0xFF) {
|
||||
case 0x00: /* INCH command */
|
||||
sim_debug(DEBUG_CMD, dptr, "start INCH command\n");
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"mt_startcmd starting INCH %06x cmd, chsa %04x MemBuf %08x cnt %04x\n",
|
||||
uptr->u4, chsa, chp->ccw_addr, chp->ccw_count);
|
||||
"mt_startcmd starting INCH cmd, chsa %04x MemBuf %08x cnt %04x\n",
|
||||
chsa, chp->ccw_addr, chp->ccw_count);
|
||||
|
||||
/* UTX_needs_interrupt */
|
||||
cmd = MT_CMDMSK; /* insert INCH cmd as 0xff */
|
||||
@ -431,17 +430,21 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
case 0x4: /* Sense */
|
||||
#ifndef FIX_DIAG
|
||||
case 0x80: /* Unknown diag cmd with byte cnt of 0x0c */
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
if ((cmd & 0xff) == 0x80) {
|
||||
/* start debugging */
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
uptr->CMD &= ~(MT_CMDMSK); /* clear out last cmd */
|
||||
uptr->CMD |= cmd & MT_CMDMSK; /* insert new cmd */
|
||||
CLR_BUF(uptr); /* buffer is empty */
|
||||
/* INCH cmd has INCH buffer address in POS, so leave it */
|
||||
if (cmd != MT_CMDMSK)
|
||||
uptr->POS = 0; /* reset buffer position pointer */
|
||||
sim_activate(uptr, 100); /* Start unit off */
|
||||
uptr->POS = 0; /* reset buffer position pointer */
|
||||
mt_busy[GET_DEV_BUF(dptr->flags)] = 1; /* show we are busy */
|
||||
sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd sense %08x return 0 chan %04x cmd %02x\n",
|
||||
uptr->SNS, chan, cmd);
|
||||
sim_activate(uptr, 100); /* Start unit off */
|
||||
return 0;
|
||||
|
||||
default: /* invalid command */
|
||||
@ -465,6 +468,7 @@ t_stat mt_error(UNIT *uptr, uint16 addr, t_stat r, DEVICE *dptr)
|
||||
|
||||
switch (r) { /* switch on return value */
|
||||
case MTSE_OK: /* no error */
|
||||
/*NEW*/ chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */
|
||||
break;
|
||||
|
||||
case MTSE_TMK: /* tape mark */
|
||||
@ -476,6 +480,7 @@ t_stat mt_error(UNIT *uptr, uint16 addr, t_stat r, DEVICE *dptr)
|
||||
case MTSE_WRP: /* write protected */
|
||||
uptr->SNS |= SNS_WRP; /* write protected */
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "WRITE PROTECT %08x\n", r); /* operator intervention */
|
||||
/*NEW*/ chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */
|
||||
break;
|
||||
|
||||
case MTSE_UNATT: /* unattached */
|
||||
@ -488,11 +493,13 @@ t_stat mt_error(UNIT *uptr, uint16 addr, t_stat r, DEVICE *dptr)
|
||||
case MTSE_FMT: /* invalid format */
|
||||
case MTSE_RECE: /* error in record */
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "ERROR %08x\n", r);
|
||||
/*NEW*/ chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */
|
||||
break;
|
||||
|
||||
case MTSE_BOT: /* beginning of tape */
|
||||
uptr->SNS |= SNS_LOAD; /* tape at BOT */
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "BOT\n");
|
||||
/*NEW*/ chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */
|
||||
break;
|
||||
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
@ -502,7 +509,7 @@ t_stat mt_error(UNIT *uptr, uint16 addr, t_stat r, DEVICE *dptr)
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP);
|
||||
break;
|
||||
}
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */
|
||||
//WAS chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@ -521,7 +528,6 @@ t_stat mt_srv(UNIT *uptr)
|
||||
uint32 mema;
|
||||
uint16 len;
|
||||
uint8 ch;
|
||||
uint8 zc = 0;
|
||||
uint8 buf[1024];
|
||||
|
||||
sim_debug(DEBUG_DETAIL, &mta_dev, "mt_srv unit %04x cmd %02x\n", unit, cmd);
|
||||
@ -541,6 +547,12 @@ t_stat mt_srv(UNIT *uptr)
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"mt_srv starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n",
|
||||
mema, addr, chp->ccw_addr, chp->ccw_count);
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
if (mema == 0x149d8) {
|
||||
/* start debugging */
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len == 0) {
|
||||
/* we have invalid count, error, bail out */
|
||||
@ -559,12 +571,24 @@ t_stat mt_srv(UNIT *uptr)
|
||||
}
|
||||
/* just dump data */
|
||||
}
|
||||
/* uptr->POS has INCH buffer address, just leave it */
|
||||
/* a BTP uses a 41 word INCH memory buffer */
|
||||
// for (i=0; i<41; i++) {
|
||||
for (i=0; i<9; i++) {
|
||||
int32 data = RMW(mema+(4*i)); /* get data word */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"mt_srv INCH buffer addr %06x, wd %02x data %08x\n",
|
||||
mema+(4*i), 4*i, data);
|
||||
/* zero the data */
|
||||
if (i == 8)
|
||||
WMW(mema+(4*i),0x00050005); /* show we are a BTP */
|
||||
else
|
||||
WMW(mema+(4*i),0); /* zero work location */
|
||||
}
|
||||
/* the chp->ccw_addr location contains the inch address */
|
||||
/* call set_inch() to setup inch buffer */
|
||||
i = set_inch(uptr, mema); /* new address */
|
||||
|
||||
#ifdef NOTYET
|
||||
#ifndef NOTYET
|
||||
if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */
|
||||
/* we have error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
@ -573,6 +597,11 @@ t_stat mt_srv(UNIT *uptr)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
/* set halfwords 16 & 17 to 5 as default retry count in inch data */
|
||||
/* UTX uses this value to see if the device is a buffered tape processor */
|
||||
/* they must be non-zero and equal to be BTP */
|
||||
WMH(mema+(16*2),5); /* write left HW with count */
|
||||
WMH(mema+(17*2),5); /* write right HW with count */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"mt_srv cmd INCH chsa %04x addr %06x count %04x completed\n",
|
||||
addr, mema, chp->ccw_count);
|
||||
@ -596,15 +625,44 @@ t_stat mt_srv(UNIT *uptr)
|
||||
ch = (uptr->SNS >> 0) & 0xff; /* get sense byte 3 status */
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 3 %02x\n", unit, ch);
|
||||
chan_write_byte(addr, &ch); /* write byte 3 */
|
||||
#ifdef TRYTHIS
|
||||
/* write zero extra status */
|
||||
for (ch=4; ch < 0xc; ch++) {
|
||||
// chan_write_byte(addr, &ch); /* write byte */
|
||||
uint8 zc = 0;
|
||||
chan_write_byte(addr, &zc); /* write zero byte */
|
||||
}
|
||||
#else
|
||||
/* write status 2 more times */
|
||||
ch = (uptr->SNS >> 24) & 0xff; /* get sense byte 0 status */
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 0 %02x\n", unit, ch);
|
||||
chan_write_byte(addr, &ch); /* write byte 0 */
|
||||
ch = (uptr->SNS >> 16) & 0xff; /* get sense byte 1 status */
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 1 %02x\n", unit, ch);
|
||||
chan_write_byte(addr, &ch); /* write byte 1 */
|
||||
ch = (uptr->SNS >> 8) & 0xff; /* get sense byte 2 status */
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 2 %02x\n", unit, ch);
|
||||
chan_write_byte(addr, &ch); /* write byte 2 */
|
||||
ch = (uptr->SNS >> 0) & 0xff; /* get sense byte 3 status */
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 3 %02x\n", unit, ch);
|
||||
chan_write_byte(addr, &ch); /* write byte 3 */
|
||||
ch = (uptr->SNS >> 24) & 0xff; /* get sense byte 0 status */
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 0 %02x\n", unit, ch);
|
||||
chan_write_byte(addr, &ch); /* write byte 0 */
|
||||
ch = (uptr->SNS >> 16) & 0xff; /* get sense byte 1 status */
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 1 %02x\n", unit, ch);
|
||||
chan_write_byte(addr, &ch); /* write byte 1 */
|
||||
ch = (uptr->SNS >> 8) & 0xff; /* get sense byte 2 status */
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 2 %02x\n", unit, ch);
|
||||
chan_write_byte(addr, &ch); /* write byte 2 */
|
||||
ch = (uptr->SNS >> 0) & 0xff; /* get sense byte 3 status */
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 3 %02x\n", unit, ch);
|
||||
chan_write_byte(addr, &ch); /* write byte 3 */
|
||||
#endif
|
||||
uptr->CMD &= ~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 */
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "mt_srv DIAG SNS %08x char complete unit=%02x\n",
|
||||
uptr->SNS, unit);
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */
|
||||
break;
|
||||
|
||||
#endif
|
||||
@ -631,9 +689,9 @@ t_stat mt_srv(UNIT *uptr)
|
||||
ch = 4;
|
||||
uptr->CMD &= ~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 */
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "mt_srv SENSE %08x char complete unit=%02x\n",
|
||||
uptr->SNS, unit);
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */
|
||||
break;
|
||||
|
||||
case MT_READ: /* 0x02 */ /* read a record from the device */
|
||||
@ -646,10 +704,10 @@ t_stat mt_srv(UNIT *uptr)
|
||||
uptr->CMD &= ~(MT_CMDMSK|MT_READDONE); /* clear all but readdone & cmd */
|
||||
uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */
|
||||
mt_busy[bufnum] &= ~1; /* not busy anymore */
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* set chan end, dev end status */
|
||||
sim_debug(DEBUG_CMD, &mta_dev,
|
||||
"mt_srv READ %04x char complete unit=%02x sense %08x\n",
|
||||
uptr->POS, unit, uptr->SNS);
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* set chan end, dev end status */
|
||||
break;
|
||||
}
|
||||
/* read is not completed, get an input char */
|
||||
@ -657,7 +715,7 @@ t_stat mt_srv(UNIT *uptr)
|
||||
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=%02x\n", unit);
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "mt_srv READ fill buffer unit=%02x\n", unit);
|
||||
uptr->CMD &= ~(MT_CMDMSK|MT_READDONE); /* clear all but readdone & cmd */
|
||||
return mt_error(uptr, addr, r, dptr); /* process any error & return status */
|
||||
}
|
||||
@ -954,8 +1012,8 @@ t_stat mt_srv(UNIT *uptr)
|
||||
case 3:
|
||||
uptr->CMD &= ~(MT_CMDMSK);
|
||||
mt_busy[bufnum] &= ~1;
|
||||
chan_end(addr, SNS_DEVEND|SNS_UNITEXP); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP);
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "Skip record at EOF\n");
|
||||
chan_end(addr, SNS_DEVEND|SNS_UNITEXP); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP);
|
||||
break;
|
||||
case 4:
|
||||
uptr->CMD &= ~(MT_CMDMSK);
|
||||
@ -1128,8 +1186,8 @@ t_stat mt_boot(int32 unit_num, DEVICE *dptr)
|
||||
|
||||
sim_debug(DEBUG_EXP, &mta_dev, "MT Boot dev/unit %04x\n", GET_UADDR(uptr->CMD));
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* Is MT device already attached? */
|
||||
sim_debug(DEBUG_EXP, &mta_dev, "MT Boot attach error dev/unit %04x\n",
|
||||
GET_UADDR(uptr->CMD));
|
||||
sim_debug(DEBUG_EXP, &mta_dev,
|
||||
"MT Boot attach error dev/unit %04x\n", GET_UADDR(uptr->CMD));
|
||||
return SCPE_UNATT; /* not attached, return error */
|
||||
}
|
||||
SPAD[0xf4] = GET_UADDR(uptr->CMD); /* put boot device chan/sa into spad */
|
||||
|
||||
@ -246,9 +246,9 @@ scfi_type[] =
|
||||
|
||||
uint8 scfi_preio(UNIT *uptr, uint16 chan);
|
||||
uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd);
|
||||
uint8 scfi_haltio(uint16 addr);
|
||||
uint8 scfi_haltio(UNIT *uptr);
|
||||
t_stat scfi_srv(UNIT *);
|
||||
t_stat scfi_boot(int32, DEVICE *);
|
||||
t_stat scfi_boot(int32 unitnum, DEVICE *);
|
||||
void scfi_ini(UNIT *, t_bool);
|
||||
t_stat scfi_reset(DEVICE *);
|
||||
t_stat scfi_attach(UNIT *, CONST char *);
|
||||
@ -304,6 +304,7 @@ 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,
|
||||
/* ctxt is the DIB pointer */
|
||||
&sda_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug,
|
||||
NULL, NULL, &scfi_help, NULL, NULL, &scfi_description
|
||||
};
|
||||
@ -347,6 +348,7 @@ 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,
|
||||
/* ctxt is the DIB pointer */
|
||||
&sdb_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug,
|
||||
NULL, NULL, &scfi_help, NULL, NULL, &scfi_description
|
||||
};
|
||||
@ -682,6 +684,8 @@ rezero:
|
||||
/* just seek to the location where we will r/w data */
|
||||
if ((sim_fseek(uptr->fileref, tstart, SEEK_SET)) != 0) { /* seek home */
|
||||
sim_debug(DEBUG_DETAIL, dptr, "scfi_srv Error on seek to %08x\n", tstart);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Check if already on correct cylinder */
|
||||
@ -963,6 +967,7 @@ int scfi_format(UNIT *uptr) {
|
||||
/* seek to sector 0 */
|
||||
if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */
|
||||
fprintf (stderr, "Error on seek to 0\r\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* get buffer for track data */
|
||||
@ -996,7 +1001,10 @@ int scfi_format(UNIT *uptr) {
|
||||
fputc('\r', stderr);
|
||||
fputc('\n', stderr);
|
||||
/* seek home again */
|
||||
sim_fseek(uptr->fileref, 0, SEEK_SET); /* seek home */
|
||||
if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */
|
||||
fprintf (stderr, "Error on seek to 0\r\n");
|
||||
return 1;
|
||||
}
|
||||
free(buff); /* free cylinder buffer */
|
||||
set_devattn(addr, SNS_DEVEND); /* start us up */
|
||||
return 0;
|
||||
|
||||
1160
SEL32/sel32_scsi.c
Normal file
1160
SEL32/sel32_scsi.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -62,6 +62,9 @@ DEVICE *sim_devices[] = {
|
||||
#ifdef NUM_DEVS_IOP
|
||||
&iop_dev, /* IOP channel controller */
|
||||
#endif
|
||||
#ifdef NUM_DEVS_MFP
|
||||
&mfp_dev, /* MFP channel controller */
|
||||
#endif
|
||||
#ifdef NUM_DEVS_RTOM
|
||||
&rtc_dev,
|
||||
&itm_dev,
|
||||
@ -532,7 +535,9 @@ t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag)
|
||||
case FMT_ICL: /* icl file image */
|
||||
return load_icl(fileref);
|
||||
|
||||
#ifdef NO_TAP_FOR_NOW
|
||||
case FMT_NONE: /* nothing */
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -159,25 +159,21 @@ int main (int argc, char *argv[])
|
||||
/* get lines until eof */
|
||||
while ((ll=getloi(buf, buf_size)) != EOF)
|
||||
{
|
||||
if (ll == 0)
|
||||
{
|
||||
if (ll == 0) {
|
||||
/* eof found, process new file */
|
||||
skipfile = 0;
|
||||
file_byte_count = 0;
|
||||
fileaddr = 0;
|
||||
printf("\nfile %d:\n", filen);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
int cc = 0;
|
||||
buffptr = 0;
|
||||
char buff[257];
|
||||
int ans;
|
||||
|
||||
{
|
||||
/* dump first 2 words */
|
||||
int w1, w2, i, j;
|
||||
char path[64], command[128];
|
||||
{
|
||||
/* dump first 2 words */
|
||||
w1 = (buf[0] & 0xff) << 24 | buf[1] << 16 | buf[2] << 8 | (buf[3] & 0xff);
|
||||
w2 = (buf[4] & 0xff) << 24 | buf[5] << 16 | buf[6] << 8 | (buf[7] & 0xff);
|
||||
if (filen > 480)
|
||||
|
||||
2
makefile
2
makefile
@ -1982,7 +1982,7 @@ SEL32 = ${SEL32D}/sel32_cpu.c ${SEL32D}/sel32_sys.c ${SEL32D}/sel32_chan.c \
|
||||
${SEL32D}/sel32_iop.c ${SEL32D}/sel32_com.c ${SEL32D}/sel32_con.c \
|
||||
${SEL32D}/sel32_clk.c ${SEL32D}/sel32_mt.c ${SEL32D}/sel32_lpr.c \
|
||||
${SEL32D}/sel32_scfi.c ${SEL32D}/sel32_fltpt.c ${SEL32D}/sel32_disk.c \
|
||||
${SEL32D}/sel32_hsdp.c
|
||||
${SEL32D}/sel32_hsdp.c ${SEL32D}/sel32_mfp.c ${SEL32D}/sel32_scsi.c
|
||||
SEL32_OPT = -I $(SEL32D) -DSEL32
|
||||
#SEL32_OPT = -I $(SEL32D) -DUSE_INT64 -DSEL32
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user