mirror of
https://github.com/rcornwell/sims.git
synced 2026-01-13 15:27:04 +00:00
SEL32: Update console device to pass SEL diags.
SEL32: Update disk devices to hold current STAR in UNIT structure. SEL32: Add new disk geometry macros. SEL32: Revise disk formatting support for UTX. SEL32: Revise INCH command support for all devices.
This commit is contained in:
parent
6d219d06f8
commit
7e3d17ef2c
@ -1,6 +1,6 @@
|
||||
/* sel32_chan.c: SEL 32 Channel functions.
|
||||
|
||||
Copyright (c) 2018, James C. Bevier
|
||||
Copyright (c) 2018-2020, James C. Bevier
|
||||
Portions provided by Richard Cornwell and other SIMH contributers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@ -119,6 +119,7 @@ t_stat rsctlxio(uint16 chsa, uint32 *status); /* reset controller XIO */
|
||||
uint32 find_int_icb(uint16 chsa);
|
||||
uint32 find_int_lev(uint16 chsa);
|
||||
uint32 scan_chan(int *ilev);
|
||||
t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */
|
||||
t_stat chan_boot(uint16 chsa, DEVICE *dptr);
|
||||
t_stat chan_set_devs();
|
||||
t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||
@ -167,6 +168,53 @@ int FIFO_Get(uint16 chsa, uint32 *old)
|
||||
return 0; /* all OK */
|
||||
}
|
||||
|
||||
/* Set INCH buffer address for channel */
|
||||
/* return SCPE_OK or SCPE_MEM if invalid address or SCPE_ARG if already defined */
|
||||
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 */
|
||||
DIB *dibp; /* get DIB pointer for channel */
|
||||
CHANP *chp;
|
||||
int i;
|
||||
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"set_inch chan %04x inch addr %06x\n", chan, inch_addr);
|
||||
|
||||
/* must be valid channel pointer */
|
||||
if (pchp == NULL)
|
||||
return SCPE_MEM; /* return memory error */
|
||||
|
||||
/* see if valid memory address */
|
||||
if (inch_addr >= (MEMSIZE*4)) /* see if mem addr >= MEMSIZE */
|
||||
return SCPE_MEM; /* return memory error */
|
||||
|
||||
#ifdef NOT_YET
|
||||
/* see if inch_addr is already defined */
|
||||
if (pchp->chan_inch_addr != 0)
|
||||
return SCPE_ARG; /* inch already defined */
|
||||
#endif
|
||||
|
||||
/* set parent */
|
||||
pchp->chan_inch_addr = inch_addr; /* set the inch addr */
|
||||
|
||||
/* now go through all the sub addresses for the channel and set inch addr */
|
||||
for (i=0; i<256; i++) {
|
||||
chsa = chan | i; /* merge sa to real channel */
|
||||
dibp = dev_unit[chsa]; /* get the device information pointer */
|
||||
if (dibp == 0)
|
||||
continue; /* must have a DIB, so not used */
|
||||
chp = find_chanp_ptr(chsa); /* find the chanp pointer */
|
||||
if (chp == 0)
|
||||
continue; /* not used */
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"set_inch2 chsa %04x inch addr %06x\n", chsa, inch_addr);
|
||||
/* set the inch buffer addr */
|
||||
chp->chan_inch_addr = inch_addr; /* set inch buffer address */
|
||||
}
|
||||
return SCPE_OK; /* All OK */
|
||||
}
|
||||
|
||||
/* Find interrupt level for the given device (ch/sa) */
|
||||
/* return 0 if not found, otherwise level number */
|
||||
uint32 find_int_lev(uint16 chsa)
|
||||
@ -297,13 +345,18 @@ CHANP *find_chanp_ptr(uint16 chsa)
|
||||
int readfull(CHANP *chp, uint32 maddr, uint32 *word)
|
||||
{
|
||||
maddr &= MASK24; /* mask addr to 24 bits */
|
||||
if (maddr > (MEMSIZE*4)) { /* see if mem addr > MEMSIZE */
|
||||
if (maddr >= (MEMSIZE*4)) { /* see if mem addr >= MEMSIZE */
|
||||
chp->chan_status |= STATUS_PCHK; /* program check error */
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "readfull read %08x from addr %08x ERROR\n", *word, maddr<<2);
|
||||
return 1; /* show we have error */
|
||||
}
|
||||
#define TEST
|
||||
#ifdef TEST
|
||||
maddr >>= 2; /* get 32 bit word index */
|
||||
*word = M[maddr]; /* get the contents */
|
||||
#else
|
||||
*word = RMW(maddr&MASK24); /* get 1 word */
|
||||
#endif
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "READFULL read %08x from addr %08x\n", *word, maddr<<2);
|
||||
return 0; /* return OK */
|
||||
}
|
||||
@ -318,16 +371,21 @@ int readbuff(CHANP *chp)
|
||||
uint32 addr = chp->ccw_addr; /* channel buffer address */
|
||||
uint16 chan = get_chan(chp->chan_dev); /* our channel */
|
||||
|
||||
if ((addr & MASK24) > (MEMSIZE*4)) { /* see if memory address invalid */
|
||||
if ((addr & MASK24) >= (MEMSIZE*4)) { /* see if memory address invalid */
|
||||
chp->chan_status |= STATUS_PCHK; /* bad, program check */
|
||||
chp->chan_byte = BUFF_CHNEND; /* force channel end */
|
||||
irq_pend = 1; /* and we have an interrupt */
|
||||
return 1; /* done, with error */
|
||||
}
|
||||
#ifdef TEST
|
||||
addr &= MASK24; /* address only */
|
||||
addr >>= 2; /* byte to word address */
|
||||
chp->chan_buf = M[addr]; /* get 4 bytes */
|
||||
#else
|
||||
chp->chan_buf = RMB(addr&MASK24); /* get 1 byte */
|
||||
#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);
|
||||
for(k = 24; k >= 0; k -= 8) {
|
||||
@ -337,6 +395,7 @@ int readbuff(CHANP *chp)
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "%c", ch);
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "]\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -348,7 +407,7 @@ int writebuff(CHANP *chp)
|
||||
{
|
||||
uint32 addr = chp->ccw_addr;
|
||||
|
||||
if ((addr & MASK24) > (MEMSIZE*4)) {
|
||||
if ((addr & MASK24) >= (MEMSIZE*4)) {
|
||||
chp->chan_status |= STATUS_PCHK;
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"writebuff PCHK addr %08x to big mem %08x status %04x\n",
|
||||
@ -361,7 +420,11 @@ int writebuff(CHANP *chp)
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev,
|
||||
"writebuff WRITE addr %06x DATA %08x status %04x\n",
|
||||
addr, chp->chan_buf, chp->chan_status);
|
||||
#ifdef TEST
|
||||
M[addr>>2] = chp->chan_buf;
|
||||
#else
|
||||
WMB(addr, chp->chan_buf); /* write byte to bebory */
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -371,10 +434,10 @@ int writebuff(CHANP *chp)
|
||||
int load_ccw(CHANP *chp, int tic_ok)
|
||||
{
|
||||
uint32 word;
|
||||
// uint8 devstat;
|
||||
int docmd = 0;
|
||||
UNIT *uptr;
|
||||
UNIT *uptr = find_unit_ptr(chp->chan_dev); /* find the unit pointer */
|
||||
uint16 chan = get_chan(chp->chan_dev); /* our channel */
|
||||
CHANP *pchp;
|
||||
|
||||
loop:
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
@ -403,14 +466,6 @@ loop:
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"load_ccw read ccw chan %02x caw %06x IOCD wd 1 %08x\n",
|
||||
chan, chp->chan_caw, word);
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"load_ccw read data @ IOCD wd 1 %08x data wd 1 %08x\n",
|
||||
word, M[(word & 0xffffff)>>2]);
|
||||
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
if ((M[(word & 0xffffff)>>2]) == 0x440a0d61)
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ);
|
||||
#endif
|
||||
|
||||
/* TIC can't follow TIC or be first in command chain */
|
||||
if (((word >> 24) & 0xf) == CMD_TIC) {
|
||||
@ -420,7 +475,8 @@ loop:
|
||||
goto loop; /* restart the IOCD processing */
|
||||
}
|
||||
chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw ERROR chan_status[%04x] %04x\n", chan, chp->chan_status);
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"load_ccw ERROR chan_status[%04x] %04x\n", chan, chp->chan_status);
|
||||
irq_pend = 1; /* status pending */
|
||||
return 1; /* error return */
|
||||
}
|
||||
@ -430,20 +486,68 @@ loop:
|
||||
if ((chp->ccw_flags & FLAG_DC) == 0) {
|
||||
chp->ccw_cmd = (word >> 24) & 0xff; /* not DC, so set command from IOCD wd 1 */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"load_ccw No DC, flags %04x cmd %02x\n", chp->ccw_flags, chp->ccw_cmd);
|
||||
"load_ccw No DC, flags %04x cmd %02x\n",
|
||||
chp->ccw_flags, chp->ccw_cmd);
|
||||
docmd = 1; /* show we have a command */
|
||||
}
|
||||
|
||||
/* Set up for this command */
|
||||
/* make a 24 bit address */
|
||||
chp->ccw_addr = word & MASK24; /* set the data address */
|
||||
readfull(chp, chp->chan_caw, &word); /* get IOCD WD 2 */
|
||||
if (readfull(chp, chp->chan_caw, &word) != 0) { /* read word from memory */
|
||||
chp->chan_status |= STATUS_PCHK; /* memory read error, program check */
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"load_ccw data addr ERROR chan_status[%04x] %04x\n",
|
||||
chan, chp->chan_status);
|
||||
return 1; /* error return */
|
||||
}
|
||||
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw read ccw chan %02x caw %06x IOCD wd 2 %08x\n",
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"load_ccw read ccw chan %02x caw %06x IOCD wd 2 %08x\n",
|
||||
chan, chp->chan_caw, word);
|
||||
chp->chan_caw += 4; /* next IOCD address */
|
||||
chp->ccw_count = word & 0xffff; /* get 16 bit byte count from IOCD WD 2*/
|
||||
chp->ccw_flags = (word >> 16) & 0xffff; /* get flags from bits 0-7 of WD 2 of IOCD */
|
||||
chp->chan_byte = BUFF_EMPTY; /* no bytes transferred yet */
|
||||
|
||||
#ifdef INVALID_FOR_INCH
|
||||
/* see if buffer count 0 or < 0x8000 */
|
||||
/* diags want the count from IOCD2 in status */
|
||||
if (chp->ccw_count == 0) { /* see if count is zero */
|
||||
chp->chan_status |= STATUS_PCHK; /* program check error */
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"load_ccw excess data count %08x ERROR chan_status[%04x] %04x\n",
|
||||
chp->ccw_count, chan, chp->chan_status);
|
||||
irq_pend = 1; /* status pending */
|
||||
return 1; /* show we have error */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* only test if non tic command */
|
||||
if ((chp->ccw_cmd & 0xFF) != CMD_TIC) {
|
||||
/* see if buffer address is in real memory */
|
||||
/* diags want the count from IOCD2 in status */
|
||||
if (chp->ccw_addr >= (MEMSIZE*4)) { /* see if mem addr >= MEMSIZE */
|
||||
chp->chan_status |= STATUS_PCHK; /* program check error */
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"load_ccw data start addr %08x ERROR chan_status[%04x] %04x\n",
|
||||
chp->ccw_addr, chan, chp->chan_status);
|
||||
irq_pend = 1; /* status pending */
|
||||
return 1; /* show we have error */
|
||||
}
|
||||
|
||||
/* see if buffer end address is in real memory */
|
||||
/* diags want the count from IOCD2 in status */
|
||||
if ((chp->ccw_addr + chp->ccw_count) > (MEMSIZE*4)) { /* see if mem addr > MEMSIZE */
|
||||
chp->chan_status |= STATUS_PCHK; /* program check error */
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"load_ccw data end addr %08x ERROR chan_status[%04x] %04x\n",
|
||||
chp->ccw_addr, chan, chp->chan_status);
|
||||
irq_pend = 1; /* status pending */
|
||||
return 1; /* show we have error */
|
||||
}
|
||||
}
|
||||
|
||||
chp->ccw_flags = (word >> 16) & 0xffff; /* get flags from bits 0-7 of WD 2 of IOCD */
|
||||
if (chp->ccw_flags & FLAG_PCI) { /* do we have prog controlled int? */
|
||||
chp->chan_status |= STATUS_PCI; /* set PCI flag in status */
|
||||
irq_pend = 1; /* interrupt pending */
|
||||
@ -452,6 +556,7 @@ loop:
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"load_ccw read docmd %02x irq_flag %04x count %04x chan %04x ccw_flags %04x\n",
|
||||
docmd, irq_pend, chp->ccw_count, chan, chp->ccw_flags);
|
||||
|
||||
/* LPR sends CC cmd only without data addr/count */
|
||||
#ifdef HACK_FOR_LPR
|
||||
/* Check invalid count */
|
||||
@ -462,61 +567,29 @@ loop:
|
||||
}
|
||||
#endif
|
||||
if (docmd) { /* see if we need to process command */
|
||||
// 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 */
|
||||
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
// if ((chp->chan_dev == 0x1000) && ((chp->ccw_cmd & 0xff) == 0x80)) {
|
||||
// if ((chp->chan_dev == 0x0800) && ((chp->ccw_cmd & 0xff) == 0x04) &&
|
||||
// (chp->ccw_count == 0x0e)) {
|
||||
if ((chp->chan_dev == 0x0800) && ((chp->ccw_cmd & 0xff) == 0xff))
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ);
|
||||
if ((chp->chan_dev == 0x0800) && ((chp->ccw_cmd & 0xff) == 0x00) &&
|
||||
(chp->ccw_count == 0x24)) {
|
||||
uint32 addr = chp->ccw_addr; /* set the data address */
|
||||
/* start debugging */
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ);
|
||||
// sim_debug(DEBUG_CMD, &cpu_dev, "cmd 80 MT wds @ addr %08x %08x %08x %08x %08x\n",
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "cmd 04 DP wds @ addr %08x %08x %08x %08x %08x\n",
|
||||
addr, M[addr>>2], M[(addr+4)>>2], M[(addr+8)>>2], M[(addr+12)>>2]);
|
||||
}
|
||||
#endif
|
||||
#ifndef CON_BUG
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
// if ((chp->chan_dev == 0x7efc) && ((chp->ccw_cmd & 0xff) == 0x03) && (chp->ccw_count == 0))
|
||||
if ((chp->chan_dev == 0x0800) && ((chp->ccw_cmd & 0xff) == 0x00) && (chp->ccw_count == 0x24))
|
||||
/* start debugging */
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ);
|
||||
#endif
|
||||
#endif
|
||||
/* Check if this is INCH command */
|
||||
if ((chp->ccw_cmd & 0xFF) == 0) { /* see if this is an initialize channel cmd */
|
||||
uptr->u4 = (uint32)chp->ccw_addr; /* save the memory address in wd 1 of iocd */
|
||||
if ((chp->ccw_count&0xffff) == 0) /* see if user said 0 count for INCH */
|
||||
uptr->us9 = 1; /* make non zero for later test */
|
||||
else
|
||||
uptr->us9 = chp->ccw_count & 0xffff; /* get count from IOCD wd 2 */
|
||||
/* just drop through and call the device startcmd function */
|
||||
/* the INCH buffer will be returned in uptr->u4 and uptr->us9 will be non-zero */
|
||||
/* it should just return SNS_CHNEND and SNS_DEVEND status */
|
||||
/*052619*/ chp->chan_inch_addr = uptr->u4; /* save INCH buffer address */
|
||||
pchp = find_chanp_ptr(chp->chan_dev&0x7f00); /* get parent channel prog pointer */
|
||||
/*091119*/ pchp->chan_inch_addr = uptr->u4; /* save INCH buffer address */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"load_ccw INCH buffer save %08x chan %04x status %04x count %04x\n",
|
||||
uptr->u4, chan, chp->chan_status, chp->ccw_count);
|
||||
}
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
/* call the device startcmd function to process command */
|
||||
/* call the device startcmd function to process the current command */
|
||||
#ifndef TRY_THIS_TUESDAY
|
||||
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);
|
||||
#endif
|
||||
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw after start_cmd chan %04x status %08x count %04x\n",
|
||||
chan, chp->chan_status, chp->ccw_count);
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"load_ccw after start_cmd chan %04x status %08x count %04x\n",
|
||||
chan, chp->chan_status, chp->ccw_count);
|
||||
|
||||
/* see if bad status */
|
||||
if (chp->chan_status & (STATUS_ATTN|STATUS_CHECK|STATUS_EXPT)) {
|
||||
@ -524,30 +597,12 @@ loop:
|
||||
chp->ccw_flags = 0; /* no flags */
|
||||
chp->ccw_cmd = 0; /* stop IOCD processing */
|
||||
irq_pend = 1; /* int coming */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "load_ccw bad status chan %04x status %04x\n",
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"load_ccw bad status chan %04x status %04x\n",
|
||||
chan, chp->chan_status);
|
||||
return 1; /* error return */
|
||||
}
|
||||
|
||||
#ifndef TRY_THIS
|
||||
/* INCH cmd will return here too, get INCH buffer addr from uptr->u4 */
|
||||
/* see if this is an initialize channel cmd */
|
||||
if ((chp->ccw_cmd & 0xFF) == 0 && (uptr->us9 != 0)) {
|
||||
/// if ((chp->ccw_cmd & 0xFF) == 0 && (uptr->us9 >= 0)) {
|
||||
chp->chan_inch_addr = uptr->u4; /* save INCH buffer address */
|
||||
pchp = find_chanp_ptr(chp->chan_dev&0x7f00); /* get parent channel prog pointer */
|
||||
pchp->chan_inch_addr = uptr->u4; /* save INCH buffer address */
|
||||
chp->chan_status &= STATUS_DEND; /* inch has only channel end status */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw INCH %08x saved chan %04x\n",
|
||||
chp->chan_inch_addr, chan);
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
if (chp->chan_inch_addr == 0x8580)
|
||||
/* start debugging */
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* see if command completed */
|
||||
if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) {
|
||||
chp->chan_status |= STATUS_CEND; /* set channel end status */
|
||||
@ -559,7 +614,8 @@ loop:
|
||||
chan, chp->chan_status, chp->ccw_count);
|
||||
}
|
||||
}
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw return, chan %04x status %04x count %04x irq %02x\n",
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"load_ccw return, chan %04x status %04x count %04x irq %02x\n",
|
||||
chan, chp->chan_status, chp->ccw_count, irq_pend);
|
||||
return 0; /* good return */
|
||||
}
|
||||
@ -582,11 +638,12 @@ int chan_read_byte(uint16 chsa, uint8 *data)
|
||||
if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if Data Chain */
|
||||
chp->chan_status |= STATUS_CEND; /* no, end of data */
|
||||
chp->chan_byte = BUFF_CHNEND; /* buffer end too */
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "chan_read_byte end status %04x\n", chp->chan_status);
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"chan_read_byte no DC chan end, cnt %04x addr %06x chan %04x\n",
|
||||
chp->ccw_count, chp->ccw_addr, chan);
|
||||
return 1; /* return error */
|
||||
} else {
|
||||
/* we have data chaining, process iocl */
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "chan_read_byte calling load_ccw chan %04x\n", chan);
|
||||
if (load_ccw(chp, 1)) /* process data chaining */
|
||||
return 1; /* return error */
|
||||
}
|
||||
@ -594,13 +651,24 @@ int chan_read_byte(uint16 chsa, uint8 *data)
|
||||
if (chp->chan_byte == BUFF_EMPTY) { /* is buffer empty? */
|
||||
if (readbuff(chp)) /* read next 4 chars */
|
||||
return 1; /* return error */
|
||||
#ifdef TEST
|
||||
chp->chan_byte = chp->ccw_addr & 0x3; /* get byte number from address */
|
||||
chp->ccw_addr += 4 - chp->chan_byte; /* next byte address */
|
||||
#else
|
||||
chp->chan_byte = 0; /* show that we have data byte */
|
||||
chp->ccw_addr += 1; /* next byte address */
|
||||
#endif
|
||||
}
|
||||
chp->ccw_count--; /* one char less to process */
|
||||
/* get the byte of data */
|
||||
#ifdef TEST
|
||||
byte = (chp->chan_buf >> (8 * (3 - (chp->chan_byte & 0x3)))) & 0xff;
|
||||
chp->chan_byte++; /* next byte offset in word */
|
||||
#else
|
||||
/* get the byte of data */
|
||||
byte = chp->chan_buf; /* read byte from memory */
|
||||
chp->chan_byte = BUFF_EMPTY; /* buffer empty too */
|
||||
#endif
|
||||
*data = byte; /* return the data */
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "chan_read_byte transferred %02x\n", byte);
|
||||
return 0; /* good return */
|
||||
@ -642,30 +710,35 @@ int chan_write_byte(uint16 chsa, uint8 *data)
|
||||
|
||||
/* see if at end of buffer */
|
||||
if (chp->chan_byte == BUFF_CHNEND) {
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte BUFF_CHNEND\n");
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte BUFF_CHNEND\n");
|
||||
/* if SLI not set, we have incorrect length */
|
||||
if ((chp->ccw_flags & FLAG_SLI) == 0) {
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte 4 setting SLI ret\n");
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte 4 setting SLI ret\n");
|
||||
chp->chan_status |= STATUS_LENGTH; /* set SLI */
|
||||
}
|
||||
return 1; /* return error */
|
||||
}
|
||||
if (chp->ccw_count == 0) {
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_byte ccw_count is zero ccw_count[%04x] %04x\n",
|
||||
chan, chp->ccw_count);
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"chan_write_byte ZERO ccw_count[%04x] %04x addr %06x\n",
|
||||
chan, chp->ccw_count, chp->ccw_addr);
|
||||
if (chp->chan_byte & BUFF_DIRTY) {
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte 2 BUF DIRTY ret\n");
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte 2 BUF DIRTY ret\n");
|
||||
if (writebuff(chp)) /* write it */
|
||||
return 1; /* return error */
|
||||
#ifndef TEST
|
||||
chp->chan_byte = BUFF_EMPTY; /* no data now */
|
||||
#endif
|
||||
}
|
||||
if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if we have data chaining */
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte no DC\n");
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte no DC\n");
|
||||
chp->chan_status |= STATUS_CEND; /* no, end of data */
|
||||
chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */
|
||||
return 1; /* return error */
|
||||
} else {
|
||||
/* we have data chaining, process iocl */
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte calling load_ccw chan %04x\n", chan);
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"chan_write_byte got DC, calling load_ccw chan %04x\n", chan);
|
||||
if (load_ccw(chp, 1)) /* process data chaining */
|
||||
return 1; /* return error */
|
||||
}
|
||||
@ -687,12 +760,20 @@ int chan_write_byte(uint16 chsa, uint8 *data)
|
||||
if (writebuff(chp))
|
||||
return 1;
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte BUF EMPTY|DIRTY ret\n");
|
||||
#ifdef TEST
|
||||
if ((chp->ccw_cmd & 0xff) == CMD_RDBWD)
|
||||
chp->ccw_addr -= (1 + (chp->ccw_addr & 0x3));
|
||||
else
|
||||
chp->ccw_addr += (4 - (chp->ccw_addr & 0x3));
|
||||
#else
|
||||
if ((chp->ccw_cmd & 0xff) == CMD_RDBWD)
|
||||
chp->ccw_addr -= 1;
|
||||
else
|
||||
chp->ccw_addr += 1;
|
||||
#endif
|
||||
chp->chan_byte = BUFF_EMPTY;
|
||||
}
|
||||
#ifdef TEST
|
||||
if (chp->chan_byte == BUFF_EMPTY)
|
||||
chp->chan_byte = chp->ccw_addr & 0x3;
|
||||
chp->ccw_count--;
|
||||
@ -709,6 +790,11 @@ int chan_write_byte(uint16 chsa, uint8 *data)
|
||||
} else
|
||||
chp->chan_byte++; /* next byte */
|
||||
chp->chan_byte |= BUFF_DIRTY; /* we are used */
|
||||
#else
|
||||
chp->chan_buf = *data; /* get data byte */
|
||||
chp->ccw_count--;
|
||||
chp->chan_byte |= BUFF_DIRTY; /* we are used */
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -747,8 +833,8 @@ void chan_end(uint16 chsa, uint16 flags) {
|
||||
CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */
|
||||
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"chan_end entry chsa %04x flags %04x chan_icb %06x status %04x\n",
|
||||
chsa, flags, chan_icb, chp->chan_status);
|
||||
"chan_end entry chsa %04x flags %04x chan_icb %06x status %04x cmd %02x\n",
|
||||
chsa, flags, chan_icb, chp->chan_status, chp->ccw_cmd);
|
||||
if (chp->chan_byte & BUFF_DIRTY) {
|
||||
if (writebuff(chp)) /* write remaining data */
|
||||
return; /* error */
|
||||
@ -758,8 +844,8 @@ 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_EXP, &cpu_dev,
|
||||
"chan_end SLI test chsa %04x ccw_flags %04x count %04x status %04x\n",
|
||||
sim_debug(DEBUG_XIO, &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
|
||||
/* hack - rewind had byte count of 1, so triggered this error when it is not */
|
||||
@ -771,23 +857,36 @@ void chan_end(uint16 chsa, uint16 flags) {
|
||||
chp->ccw_flags = 0; /* no flags */
|
||||
}
|
||||
#else
|
||||
if (((chp->ccw_cmd & 0xF) == 0x02) || ((chp->ccw_cmd & 0xf) == 0x01)) { /* see if this is a read/write cmd */
|
||||
/* see if this is a read/write cmd */
|
||||
if (((chp->ccw_cmd & 0x7) == 0x02) || ((chp->ccw_cmd & 0x7) == 0x01)) {
|
||||
/* test for incorrect transfer length */
|
||||
if (chp->ccw_count != 0 && ((chp->ccw_flags & FLAG_SLI) == 0)) {
|
||||
chp->chan_status |= STATUS_LENGTH; /* show incorrect length status */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"chan_end setting SLI chsa %04x count %04x ccw_flags %04x status %04x\n",
|
||||
chsa, chp->ccw_count, chp->ccw_flags, chp->chan_status);
|
||||
chp->ccw_flags = 0; /* no flags */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "chan_end SLI test chsa %04x ccw_flags %04x status %04x\n",
|
||||
chsa, chp->ccw_flags, chp->chan_status);
|
||||
sim_debug(DEBUG_XIO, &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 */
|
||||
if ((chp->chan_status & FLAG_SLI) && ((chp->chan_status & STATUS_DEND) == 0))
|
||||
chp->chan_status &= ~FLAG_SLI;
|
||||
|
||||
/* no flags for attention status */
|
||||
if (flags & (SNS_ATTN|SNS_UNITCHK|SNS_UNITEXP)) {
|
||||
chp->ccw_flags = 0; /* no flags */
|
||||
}
|
||||
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "chan_end test end chsa %04x, flags %04x\n", chsa, flags);
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"chan_end test end chsa %04x ccw_flags %04x status %04x\n",
|
||||
chsa, chp->ccw_flags, chp->chan_status);
|
||||
|
||||
/* test for device or controller end */
|
||||
if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) {
|
||||
chp->chan_byte = BUFF_NEWCMD; /* clear byte flag */
|
||||
@ -914,7 +1013,7 @@ t_stat checkxio(uint16 lchsa, uint32 *status) {
|
||||
return SCPE_OK; /* just busy or something, CC3|CC4 */
|
||||
}
|
||||
}
|
||||
*status = CC1BIT; /* CCs = 1, CMD accepted & queued, will not echo status */
|
||||
*status = CC1BIT; /* CCs = 1, CMD accepted & queued, no echo status */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "checkxio done CC1 status %08x\n", *status);
|
||||
return SCPE_OK; /* No CC's all OK */
|
||||
}
|
||||
@ -964,17 +1063,20 @@ t_stat startxio(uint16 lchsa, uint32 *status) {
|
||||
chan_ivl = SPAD[0xf1] + (inta<<2); /* contents of spad f1 points to chan ivl in mem */
|
||||
chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */
|
||||
iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */
|
||||
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"startxio test chsa %04x cmd %02x iocla %08x flags %04x IOCD1 %08x IOCD2 %08x\n",
|
||||
chsa, chp->ccw_cmd, iocla, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]);
|
||||
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "$$$ SIO %04x %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_XIO, &cpu_dev, "startxio busy return CC4 chsa %04x chan %04x\n", chsa, chan);
|
||||
*status = CC4BIT; /* busy, so CC4 */
|
||||
return SCPE_OK; /* just busy CC4 */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"startxio busy return CC3&CC4 chsa %04x chan %04x\n", chsa, chan);
|
||||
*status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */
|
||||
return SCPE_OK; /* just busy CC3&CC4 */
|
||||
}
|
||||
|
||||
/* determine if channel DIB has a pre startio command processor */
|
||||
@ -990,7 +1092,7 @@ t_stat startxio(uint16 lchsa, uint32 *status) {
|
||||
return SCPE_OK; /* just busy or something, CC3|CC4 */
|
||||
}
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"startxio pre_io call return not busy chan %04x cstat %08x\n",
|
||||
"startxio pre_io call return not busy ctan %04x cstat %08x\n",
|
||||
chan, tempa);
|
||||
}
|
||||
|
||||
@ -1001,16 +1103,26 @@ t_stat startxio(uint16 lchsa, uint32 *status) {
|
||||
/* set status words in memory to first IOCD information */
|
||||
tempa = chp->chan_inch_addr; /* get inch status buffer address */
|
||||
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "@ startxio 4 chsa %04x iocla %08x tempa %08x\n",
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"$$ SIO start IOCL processing chsa %04x iocla %08x incha %08x\n",
|
||||
chsa, iocla, tempa);
|
||||
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "$$ SIO starting IOCL processing chsa %04x iocla %08x\n", chsa, iocla);
|
||||
|
||||
/* start processing the IOCL */
|
||||
if (load_ccw(chp, 0) || (chp->chan_status & STATUS_PCI)) {
|
||||
/* we have an error or user requested interrupt, return status */
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "startxio store csw CC2 chan %04x status %08x\n",
|
||||
chan, chp->chan_status);
|
||||
/* DIAG's want CC1 with memory access error */
|
||||
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 */
|
||||
dev_status[chsa] = 0; /* no device status */
|
||||
//DIAG *status = CC2BIT; /* status stored, so CC2 */
|
||||
*status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */
|
||||
irq_pend = 1; /* still pending int */
|
||||
return SCPE_OK; /* CC2 (0x20) status stored */
|
||||
}
|
||||
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 */
|
||||
@ -1019,14 +1131,14 @@ t_stat startxio(uint16 lchsa, uint32 *status) {
|
||||
return SCPE_OK; /* CC2 (0x20) status stored */
|
||||
}
|
||||
|
||||
*status = CC1BIT; /* CCs = 1, SIO accepted & queued, will not echo status */
|
||||
*status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "$$$ SIO done chsa %04x status %08x iocla %08x\n",
|
||||
chsa, chp->chan_status, iocla);
|
||||
return SCPE_OK; /* No CC's all OK */
|
||||
}
|
||||
|
||||
/* TIO - I/O status */
|
||||
t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */
|
||||
t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */
|
||||
// uint32 chan = get_chan(lchsa);
|
||||
int lchan = get_chan(lchsa); /* get the logical channel number */
|
||||
DIB *dibp;
|
||||
@ -1036,7 +1148,7 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */
|
||||
uint32 tempa, inta, spadent, chan;
|
||||
uint16 chsa; /* chan/subaddr */
|
||||
CHANP *chp, *pchp; /* Channel prog pointers */
|
||||
uint32 sw1, sw2; /* status word 1 & 2 */
|
||||
uint32 sw1=0, sw2=0; /* status word 1 & 2 */
|
||||
|
||||
/* get the device entry for the logical channel in SPAD */
|
||||
spadent = SPAD[lchan]; /* get spad device entry for logical channel */
|
||||
@ -1080,7 +1192,8 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */
|
||||
|
||||
/* check for a Command or data chain operation in progresss */
|
||||
if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) {
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "testxio busy return CC4 chsa %04x chan %04x\n", chsa, chan);
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
"testxio busy return CC4 chsa %04x chan %04x\n", chsa, chan);
|
||||
*status = CC4BIT; /* busy, so CC4 */
|
||||
goto tioret; /* just busy CC4 */
|
||||
}
|
||||
@ -1088,12 +1201,13 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */
|
||||
if ((FIFO_Get(chsa, &sw1) == 0) && (FIFO_Get(chsa, &sw2) == 0)) {
|
||||
uint32 chan_icb = find_int_icb(chsa); /* get icb address */
|
||||
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev, "testxio FIFO status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2);
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"testxio FIFO status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2);
|
||||
/* we have status to return, do it now */
|
||||
tempa = pchp->chan_inch_addr; /* get inch status buffer address */
|
||||
M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */
|
||||
/* save the status to memory */
|
||||
M[(tempa+4) >> 2] = sw2; /* save status and residual count in status WD 2 loc */
|
||||
M[(tempa+4) >> 2] = sw2; /* save status and residual cnt in status WD 2 loc */
|
||||
/* now store the status dw address into word 5 of the ICB for the channel */
|
||||
M[(chan_icb + 20) >> 2] = tempa | BIT1; /* post sw addr in ICB+5w & set CC2 in INCH addr */
|
||||
*status = CC2BIT; /* status stored from SIO, so CC2 */
|
||||
@ -1141,7 +1255,7 @@ t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "stopxio dev spad %08x chsa %04x\n", spadent, chsa);
|
||||
|
||||
/* the startio opcode processing software has already checked for F class */
|
||||
inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */
|
||||
inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */
|
||||
inta = 127 - inta; /* get positive int level */
|
||||
spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "stopxio int spad %08x inta %08x chsa %04x\n", spadent, inta, chsa);
|
||||
@ -1163,7 +1277,7 @@ t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */
|
||||
/* reset the DC or CC bits to force completion after current IOCD */
|
||||
chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */
|
||||
dev_status[chsa] |= STATUS_ECHO; /* show we stopped the cmd */
|
||||
*status = CC4BIT; /* busy, so CC4 */
|
||||
*status = CC1BIT; /* request accepted, no status, so CC1 */
|
||||
return SCPE_OK; /* just busy CC4 */
|
||||
}
|
||||
/* the channel is not busy, so return OK */
|
||||
@ -1192,12 +1306,12 @@ t_stat rschnlxio(uint16 lchsa, uint32 *status) { /* reset channel XIO */
|
||||
chp = find_chanp_ptr(chsa); /* find the chanp pointer */
|
||||
uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */
|
||||
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "rschnlxio 1 chan %04x SPAD %08x\n", chsa, spadent);
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "rschnlxio 1 chan %04x SPAD %08x\n", chsa, spadent);
|
||||
if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */
|
||||
*status = CC3BIT; /* not found, so CC3 */
|
||||
return SCPE_OK; /* not found, CC3 */
|
||||
}
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "rschnlxio 2 chan %04x, spad %08x\r\n", chsa, spadent);
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "rschnlxio 2 chan %04x, spad %08x\r\n", chsa, spadent);
|
||||
if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */
|
||||
*status = CC3BIT; /* not attached, so error CC3 */
|
||||
return SCPE_OK; /* not found, CC3 */
|
||||
@ -1232,14 +1346,15 @@ t_stat rschnlxio(uint16 lchsa, uint32 *status) { /* reset channel XIO */
|
||||
chp->ccw_count = 0; /* channel byte count 0 bytes*/
|
||||
chp->ccw_flags = 0; /* clear flags */
|
||||
chp->ccw_cmd = 0; /* read command */
|
||||
chp->chan_inch_addr = 0; /* clear inch addr */
|
||||
}
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "rschnlxio return CC1 chan %04x lev %04x\n", chan, lev);
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "rschnlxio return CC1 chan %04x lev %04x\n", chan, lev);
|
||||
*status = CC1BIT; /* request accepted, no status, so CC1 TRY THIS */
|
||||
return SCPE_OK; /* All OK */
|
||||
}
|
||||
|
||||
/* HIO - Halt I/O */
|
||||
t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */
|
||||
t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */
|
||||
int chan = get_chan(lchsa);
|
||||
DIB *dibp;
|
||||
UNIT *uptr;
|
||||
@ -1248,7 +1363,7 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */
|
||||
uint32 inta, spadent;
|
||||
uint16 chsa;
|
||||
CHANP *chp, *pchp; /* Channel prog pointers */
|
||||
uint32 sw1, sw2; /* status word 1 & 2 */
|
||||
uint32 sw1=0, sw2=0; /* status word 1 & 2 */
|
||||
|
||||
/* get the device entry for the logical channel in SPAD */
|
||||
spadent = SPAD[chan]; /* get spad device entry for logical channel */
|
||||
@ -1257,7 +1372,7 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */
|
||||
dibp = dev_unit[chsa]; /* get the device information pointer */
|
||||
chp = find_chanp_ptr(chsa); /* find the chanp pointer */
|
||||
uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */
|
||||
pchp = find_chanp_ptr(chsa & 0x7f00); /* find the channel chanp pointer */
|
||||
pchp = find_chanp_ptr(chsa & 0x7f00); /* find the parent channel pointer */
|
||||
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "haltxio 1 chsa %04x chan %04x\n", chsa, chan);
|
||||
if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */
|
||||
@ -1283,16 +1398,39 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */
|
||||
chan_ivl = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */
|
||||
iocla = M[(chan_ivl+16)>>2]; /* iocla is in wd 4 of ICB */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"haltxio busy test chsa %04x chan %04x cmd %02x flags %04x IOCD1 %8x IOCD2 %08x\n",
|
||||
"haltxio busy test chsa %04x chan %04x cmd %02x flags %04x IOCD1 %08x IOCD2 %08x\n",
|
||||
chsa, chan, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]);
|
||||
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "$$$ HIO %04x %04x %02x %04x\n",
|
||||
chsa, chan, chp->ccw_cmd, chp->ccw_flags);
|
||||
|
||||
if (chp->ccw_cmd == 0 && (chp->ccw_flags & (FLAG_DC|FLAG_CC)) == 0) {
|
||||
/* the channel is not busy, so return OK */
|
||||
#ifdef DIAGTUE
|
||||
*status = CC1BIT; /* request accepted, no status, so CC1 */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
"$$$ HIO END chsa %04x chan %04x cmd %02x flags %04x status %04x\n",
|
||||
chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status);
|
||||
return SCPE_OK; /* No CC's all OK */
|
||||
#else
|
||||
/* diag wants an interrupt for a non busy HIO ??? */
|
||||
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 */
|
||||
dev_status[chsa] = 0; /* no device status */
|
||||
irq_pend = 1; /* still pending int */
|
||||
// *status = CC2BIT; /* sub channel status posted, CC2BIT */
|
||||
*status = CC1BIT; /* request accepted, no status, so CC1 */
|
||||
goto hioret; /* CC2 and OK */
|
||||
#endif
|
||||
}
|
||||
|
||||
chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */
|
||||
/* see if we have a haltio device entry */
|
||||
if (dibp->halt_io != NULL) { /* NULL if no haltio function */
|
||||
/* call the device controller to get halt_io status */
|
||||
uint32 tempa = dibp->halt_io(uptr); /* get status from device */
|
||||
#ifdef BAD_TUE
|
||||
if (tempa == SNS_BSY) {
|
||||
*status = CC3BIT|CC4BIT; /* sub channel busy, CC3BIT & CC4BIT */
|
||||
irq_pend = 1; /* still pending int */
|
||||
@ -1300,40 +1438,59 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */
|
||||
"haltxio halt_io return busy chan %04x CC3|CC4\n", chan);
|
||||
goto hioret; /* just return */
|
||||
}
|
||||
#endif
|
||||
/* 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,
|
||||
"haltxio halt_io call return busy chan %04x cstat %08x\n",
|
||||
chan, tempa);
|
||||
chp->ccw_count = 0; /* force zero count */
|
||||
chp->chan_status &= ~STATUS_LENGTH; /* remove PCI status bit */
|
||||
store_csw(chp); /* store the status in the inch status dw */
|
||||
"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 */
|
||||
chp->ccw_count = 0; /* force zero count */
|
||||
dev_status[chsa] = 0; /* no device status */
|
||||
|
||||
/* the channel is not busy, see if any status to post */
|
||||
if ((FIFO_Get(chsa, &sw1) == 0) && (FIFO_Get(chsa, &sw2) == 0)) {
|
||||
uint32 chan_icb = find_int_icb(chsa); /* get icb address */
|
||||
if (CPU_MODEL >= MODEL_V6) {
|
||||
/* UTX wants the status posted now, MPX wants interrupt */
|
||||
|
||||
/* the channel is not busy, see if any status to post */
|
||||
if ((FIFO_Get(chsa, &sw1) == 0) && (FIFO_Get(chsa, &sw2) == 0)) {
|
||||
uint32 chan_icb = find_int_icb(chsa); /* get icb address */
|
||||
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"haltxio 0 FIFO status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2);
|
||||
/* we have status to return, do it now */
|
||||
tempa = pchp->chan_inch_addr; /* get inch status buffer address */
|
||||
M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */
|
||||
/* save the status to memory */
|
||||
M[(tempa+4) >> 2] = sw2; /* save status and 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 INCH addr */
|
||||
M[(chan_icb + 20) >> 2] = tempa | BIT2;
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"haltxio 1 FIFO status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2);
|
||||
irq_pend = 1; /* still pending int */
|
||||
// UTX likes this return and does not panic */
|
||||
// The diag's want an interrupt generated, so want
|
||||
*status = CC2BIT; /* status stored from SIO, so CC2 */
|
||||
goto hioret; /* CC2 and OK */
|
||||
}
|
||||
/* nothing going on, so say all OK */
|
||||
*status = CC1BIT; /* request accepted, no status, so CC1 */
|
||||
goto hioret; /* CC2 and OK */
|
||||
} else {
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"haltxio FIFO status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2);
|
||||
/* we have status to return, do it now */
|
||||
tempa = pchp->chan_inch_addr; /* get inch status buffer address */
|
||||
M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */
|
||||
/* save the status to memory */
|
||||
M[(tempa+4) >> 2] = sw2; /* save status and residual count in status WD 2 loc */
|
||||
/* now store the status dw address into word 5 of the ICB for the channel */
|
||||
M[(chan_icb + 20) >> 2] = tempa | BIT2; /* post sw addr in ICB+5w & set CC2 in INCH addr */
|
||||
"haltxio FIFO 2 status stored OK, sw1 %08x sw2 %08x\n", sw1, sw2);
|
||||
irq_pend = 1; /* still pending int */
|
||||
*status = CC2BIT; /* status stored from SIO, so CC2 */
|
||||
//TUE *status = 0; /* request accepted, no status, so CC1 */
|
||||
/*TUE*/ *status = CC1BIT; /* request accepted, no status, so CC1 */
|
||||
goto hioret; /* CC2 and OK */
|
||||
}
|
||||
/* nothing going on, so say all OK */
|
||||
*status = CC1BIT; /* request accepted, no status, so CC1 */
|
||||
}
|
||||
else {
|
||||
/* we have completed the i/o without error */
|
||||
} else {
|
||||
/* we have completed the I/O without error */
|
||||
/* the channel is not busy, so return OK */
|
||||
*status = 0; /* CCs = 0, accepted */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
@ -1462,7 +1619,7 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */
|
||||
t_stat chan_boot(uint16 chsa, DEVICE *dptr) {
|
||||
int chan = get_chan(chsa);
|
||||
DIB *dibp = dev_unit[chsa];
|
||||
CHANP *chp = dibp->chan_prg;
|
||||
CHANP *chp = 0;
|
||||
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Channel Boot chan/device addr %04x\n", chsa);
|
||||
if (dibp == 0) /* if no channel or device, error */
|
||||
@ -1508,14 +1665,12 @@ uint32 scan_chan(int *ilev) {
|
||||
uint32 chan; /* channel num 0-7f */
|
||||
uint32 tempa; /* icb address */
|
||||
uint32 chan_ivl; /* int level table address */
|
||||
// int lev; /* interrupt level */
|
||||
uint32 chan_icba; /* int level context block address */
|
||||
CHANP *chp; /* channel prog pointer */
|
||||
DIB *dibp; /* DIB pointer */
|
||||
|
||||
if (irq_pend == 1) { /* pending int? */
|
||||
/* see if we have a channel completed */
|
||||
// irq_pend = 0; /* not pending anymore */
|
||||
/* loop through all the channels/units for channel with pending I/O completion */
|
||||
for (i = 0; sim_devices[i] != NULL; i++) {
|
||||
DEVICE *dptr = sim_devices[i]; /* get pointer to configured device */
|
||||
@ -1574,7 +1729,6 @@ uint32 scan_chan(int *ilev) {
|
||||
irq_pend = 1; /* still pending int */
|
||||
//WAS goto trythis;
|
||||
return 0; /* just return */
|
||||
// keep looking return 0; /* just return */
|
||||
}
|
||||
}
|
||||
uptr++; /* next UNIT pointer */
|
||||
@ -1611,17 +1765,18 @@ uint32 scan_chan(int *ilev) {
|
||||
chp = find_chanp_ptr(chan); /* find the chanp pointer for channel */
|
||||
/* get the address of the interrupt IVL table in main memory */
|
||||
chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */
|
||||
chan_icba = M[chan_ivl >> 2]; /* get the interrupt context block addr in memory */
|
||||
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 residual count in status WD 2 loc */
|
||||
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 */
|
||||
M[(chan_icba + 20) >> 2] = tempa | BIT1; /* post sw addr in ICB+5w & set CC2 in SW */
|
||||
/* 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 %04x FIFO read, set irq %04x inch %06x chan_icba %06x sw1 %08x sw2 %08x\n",
|
||||
chan, i, tempa, chan_icba, sw1, sw2);
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"scan_chan %04x FIFO read, set irq %04x inch %06x chan_icba %06x sw1 %08x sw2 %08x\n",
|
||||
chan, i, tempa, chan_icba, sw1, sw2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1634,13 +1789,14 @@ uint32 scan_chan(int *ilev) {
|
||||
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 */
|
||||
/* 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 %04x found chan_icba %08x INTS %08x\n",
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"scan_chan INTS REQ irq %04x found chan_icba %08x INTS %08x\n",
|
||||
i, chan_icba, INTS[i]);
|
||||
*ilev = i; /* return interrupt level */
|
||||
irq_pend = 0; /* not pending anymore */
|
||||
@ -1648,10 +1804,6 @@ uint32 scan_chan(int *ilev) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (irq_pend == 0) /* pending int? */
|
||||
// return 0; /* no, so just return */
|
||||
// irq_pend = 0; /* not pending anymore */
|
||||
|
||||
return 0; /* done */
|
||||
}
|
||||
|
||||
@ -1661,7 +1813,7 @@ uint32 scan_chan(int *ilev) {
|
||||
*/
|
||||
DEVICE *get_dev(UNIT *uptr)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DEVICE *dptr = NULL;
|
||||
uint32 i, j;
|
||||
|
||||
if (uptr == NULL) /* must be valid unit */
|
||||
@ -1768,11 +1920,7 @@ t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc) {
|
||||
chan = get_uint(cptr, 16, 0xffff, &r); /* get new device address */
|
||||
if (r != SCPE_OK) /* need good number */
|
||||
return r; /* number error, return error */
|
||||
//printf("finding chan %s (%x) with unit address %04x dptr %x\n",
|
||||
// cptr, chan, GET_UADDR(uptr->u3), uptr->dptr);
|
||||
|
||||
// if ((chan == 0) || ((chan & 0x7f00) != chan)) /* is chan 1-7f */
|
||||
// return SCPE_ARG; /* no, bad channel # */
|
||||
chan &= 0x7f00; /* clean channel address */
|
||||
dibp->chan_addr = chan; /* set new parent channel addr */
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* sel32_clk.c: SEL 32 Class F IOP processor RTOM functions.
|
||||
|
||||
Copyright (c) 2018, James C. Bevier
|
||||
Copyright (c) 2018-2020, James C. Bevier
|
||||
Portions provided by Richard Cornwell and other SIMH contributers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* sel32_com.c: SEL 32 8-Line IOP communications controller
|
||||
|
||||
Copyright (c) 2018, James C. Bevier
|
||||
Copyright (c) 2018-2020, James C. Bevier
|
||||
Portions provided by Richard Cornwell and other SIMH contributers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* sel32_con.c: SEL 32 Class F IOP processor console.
|
||||
|
||||
Copyright (c) 2018, James C. Bevier
|
||||
Copyright (c) 2018-2020, James C. Bevier
|
||||
Portions provided by Richard Cornwell and other SIMH contributers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@ -49,6 +49,8 @@ extern void post_extirq(void);
|
||||
extern uint32 attention_trap; /* set when trap is requested */
|
||||
extern void set_devwake(uint16 addr, uint8 flags);
|
||||
extern DEVICE *get_dev(UNIT *uptr);
|
||||
extern t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */
|
||||
extern CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */
|
||||
|
||||
#define CMD u3
|
||||
/* Held in u3 is the device command and status */
|
||||
@ -123,8 +125,8 @@ MTAB con_mod[] = {
|
||||
};
|
||||
|
||||
UNIT con_unit[] = {
|
||||
{UDATA(con_srvi, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7EFC)}, /* Input */
|
||||
{UDATA(con_srvo, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7EFD)}, /* Output */
|
||||
{UDATA(&con_srvi, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7EFC)}, /* Input */
|
||||
{UDATA(&con_srvo, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7EFD)}, /* Output */
|
||||
};
|
||||
|
||||
//DIB con_dib = {NULL, con_startcmd, NULL, NULL, NULL, con_ini, con_unit, con_chp, NUM_UNITS_CON, 0xf, 0x7e00, 0, 0, 0};
|
||||
@ -157,12 +159,13 @@ DEVICE con_dev = {
|
||||
*/
|
||||
/* initialize the console chan/unit */
|
||||
void con_ini(UNIT *uptr, t_bool f) {
|
||||
// int unit = (uptr - con_unit); /* unit 0 */
|
||||
int unit = (uptr - con_unit); /* unit 0 */
|
||||
// DEVICE *dptr = get_dev(uptr);
|
||||
|
||||
// con_data[unit].incnt = 0; /* no input data */
|
||||
con_data[0].incnt = 0; /* no input data */
|
||||
con_data[1].incnt = 0; /* no output data */
|
||||
uptr->u4 = 0; /* no input cpunt */
|
||||
con_data[unit].incnt = 0; /* no input data */
|
||||
// con_data[0].incnt = 0; /* no input data */
|
||||
// con_data[1].incnt = 0; /* no output data */
|
||||
uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */
|
||||
sim_activate(uptr, 1000); /* time increment */
|
||||
}
|
||||
@ -206,10 +209,6 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
|
||||
case CON_RWD: /* 0x37 */ /* TOF and write line */
|
||||
case CON_WR: /* 0x01 */ /* Write command */
|
||||
/* if input requested for output device, give error */
|
||||
if (unit == 0) {
|
||||
uptr->SNS |= SNS_CMDREJ; /* command rejected */
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */
|
||||
}
|
||||
uptr->CMD &= LMASK; /* leave only chsa */
|
||||
uptr->CMD |= (cmd & CON_MSK); /* save command */
|
||||
uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */
|
||||
@ -221,10 +220,6 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
|
||||
case CON_RD: /* 0x02 */ /* Read command */
|
||||
case CON_ECHO: /* 0x0a */ /* Read command w/ECHO */
|
||||
/* if output requested for input device, give error */
|
||||
if (unit == 1) {
|
||||
uptr->SNS |= SNS_CMDREJ; /* command rejected */
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */
|
||||
}
|
||||
uptr->CMD &= LMASK; /* leave only chsa */
|
||||
uptr->CMD |= (cmd & CON_MSK); /* save command */
|
||||
if (cmd == CON_ECHO) /* echo command? */
|
||||
@ -242,15 +237,16 @@ 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 */
|
||||
// uptr->u4 = 0; /* no I/O yet */
|
||||
// con_data[unit].incnt = 0; /* clear any input data */
|
||||
sim_activate(uptr, 10); /* start us off */
|
||||
//TRIED sim_activate(uptr, 2); /* start us off */
|
||||
return 0; /* no status change */
|
||||
break;
|
||||
|
||||
#ifdef JUNK
|
||||
case 0x0c: /* 0x0C */ /* Unknown command */
|
||||
#ifndef JUNK
|
||||
case 0x0C: /* 0x0C */ /* Unknown command */
|
||||
uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */
|
||||
uptr->CND &= LMASK; /* leave only chsa */
|
||||
uptr->CMD &= LMASK; /* leave only chsa */
|
||||
uptr->CMD |= (cmd & CON_MSK); /* save command */
|
||||
sim_activate(uptr, 10); /* start us off */
|
||||
return 0; /* no status change */
|
||||
@ -269,9 +265,6 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
|
||||
return SNS_CHNEND|SNS_DEVEND; /* good return */
|
||||
break;
|
||||
|
||||
#ifdef JUNK
|
||||
case 0x0c: /* 0x0C */ /* Unknown command */
|
||||
#endif
|
||||
case CON_SNS: /* 0x04 */ /* Sense */
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_startcmd %04x: Cmd Sense %02x\n", chan, uptr->SNS);
|
||||
@ -284,6 +277,8 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
|
||||
|
||||
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);
|
||||
@ -299,35 +294,59 @@ uint8 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
|
||||
/* Handle output transfers for console */
|
||||
t_stat con_srvo(UNIT *uptr) {
|
||||
uint16 chsa = GET_UADDR(uptr->CMD);
|
||||
int unit = (uptr - con_unit); /* unit 0 is read, unit 1 is write */
|
||||
int unit = (uptr - con_unit); /* unit 0 is read, unit 1 is write */
|
||||
int cmd = uptr->CMD & CON_MSK;
|
||||
CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */
|
||||
uint8 ch, cp;
|
||||
|
||||
sim_debug(DEBUG_DETAIL, &con_dev, "con_srvo enter chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
if (cmd == 0x0C) { /* unknown has to do nothing */
|
||||
sim_debug(DEBUG_CMD, &con_dev, "con_srvo Unknown (0x0C) chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */
|
||||
return SCPE_OK;
|
||||
|
||||
/* if input tried from output device, error */
|
||||
if ((cmd == CON_RD) || (cmd == CON_ECHO) || (cmd == 0xC0)) { /* check for output */
|
||||
/* CON_RD: 0x02 */ /* Read command */
|
||||
/* CON_ECHO: 0x0a */ /* Read command w/ECHO */
|
||||
/* if input requested for output device, give error */
|
||||
if (unit == 1) {
|
||||
uptr->SNS |= SNS_CMDREJ; /* command rejected */
|
||||
uptr->CMD &= LMASK; /* nothing left, command complete */
|
||||
//DIAG_TUE chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* unit check */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_UNITCHK); /* unit check */
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_srvo Read to output device chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if ((cmd == CON_NOP) || (cmd == CON_INCH2)) { /* NOP has to do nothing */
|
||||
uptr->CMD &= LMASK; /* nothing left, command complete */
|
||||
if (cmd == CON_INCH2) { /* Channel end only for INCH */
|
||||
sim_debug(DEBUG_CMD, &con_dev, "con_srvo INCH chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
chan_end(chsa, SNS_CHNEND); /* done */
|
||||
uptr->CMD &= LMASK; /* nothing left, command complete */
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_srvo INCH/NOP unit %02x: cmd %02x incnt %02x u4 %02x\n",
|
||||
unit, cmd, con_data[unit].incnt, uptr->u4);
|
||||
if (cmd == CON_INCH2) { /* Channel end only for INCH */
|
||||
int len = chp->ccw_count; /* INCH command count */
|
||||
uint32 mema = chp->ccw_addr; /* get inch or buffer addr */
|
||||
// int i = set_inch(uptr, mema); /* new address */
|
||||
set_inch(uptr, mema); /* new address */
|
||||
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_srvo INCH chsa %04x len %02x inch %06x\n", chsa, len, mema);
|
||||
chan_end(chsa, SNS_CHNEND); /* INCH done */
|
||||
} else {
|
||||
sim_debug(DEBUG_CMD, &con_dev, "con_srvo NOP chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_srvo NOP chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
// static uint32 lastch = 0;
|
||||
if ((cmd == CON_WR) || (cmd == CON_RWD)) {
|
||||
/* Write to device */
|
||||
if (chan_read_byte(chsa, &ch)) { /* get byte from memory */
|
||||
uptr->CMD &= LMASK; /* nothing left, command complete */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_srvo write %02x chsa %04x cmd %02x complete\n",
|
||||
ch, chsa, cmd);
|
||||
} else {
|
||||
/* HACK HACK HACK */
|
||||
ch &= 0x7f; /* make 7 bit w/o parity */
|
||||
@ -339,15 +358,11 @@ t_stat con_srvo(UNIT *uptr) {
|
||||
cp = ch;
|
||||
else
|
||||
cp = '^';
|
||||
sim_debug(DEBUG_CMD, &con_dev, "con_srvo write %01x: putch 0x%02x %c\n", unit, ch, cp);
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
lastch = (lastch << 8) | cp;
|
||||
if ((lastch & 0xffff) == 0x6e29) /* check for ion) */
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ);
|
||||
#endif
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_srvo write %01x: putch 0x%02x %c\n", unit, ch, cp);
|
||||
//WAS sim_putchar(ch); /* output next char to device */
|
||||
sim_putchar(cp); /* output next char to device */
|
||||
sim_activate(uptr, 20); /* start us off */
|
||||
sim_activate(uptr, 20); /* keep going */
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
@ -358,11 +373,27 @@ t_stat con_srvi(UNIT *uptr) {
|
||||
uint16 chsa = GET_UADDR(uptr->CMD);
|
||||
int unit = (uptr - con_unit); /* unit 0 is read, unit 1 is write */
|
||||
int cmd = uptr->CMD & CON_MSK;
|
||||
CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */
|
||||
uint8 ch;
|
||||
t_stat r;
|
||||
|
||||
sim_debug(DEBUG_DETAIL, &con_dev, "con_srvi enter chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
|
||||
/* if output tried to input device, error */
|
||||
if ((cmd == CON_RWD) || (cmd == CON_WR) || (cmd == 0x0C)) { /* check for output */
|
||||
/* CON_RWD: 0x37 */ /* TOF and write line */
|
||||
/* CON_WR: 0x01 */ /* Write command */
|
||||
/* if input requested for output device, give error */
|
||||
if (unit == 0) {
|
||||
uptr->SNS |= SNS_CMDREJ; /* command rejected */
|
||||
uptr->CMD &= LMASK; /* nothing left, command complete */
|
||||
//DIAGTUE chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* unit check */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_UNITCHK); /* unit check */
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_srvi Write to input device chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
//fall thru return SCPE_OK;
|
||||
}
|
||||
}
|
||||
#ifdef JUNK
|
||||
if (cmd == 0x0C) { /* unknown has to do nothing */
|
||||
sim_debug(DEBUG_CMD, &con_dev, "con_srvi Unknown (0x0C) chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
@ -373,14 +404,23 @@ t_stat con_srvi(UNIT *uptr) {
|
||||
|
||||
if ((cmd == CON_NOP) || (cmd == CON_INCH2)) { /* NOP is do nothing */
|
||||
uptr->CMD &= LMASK; /* nothing left, command complete */
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_srvi INCH/NOP unit %02x: cmd %02x incnt %02x u4 %02x\n",
|
||||
unit, cmd, con_data[unit].incnt, uptr->u4);
|
||||
if (cmd == CON_INCH2) { /* Channel end only for INCH */
|
||||
sim_debug(DEBUG_CMD, &con_dev, "con_srvi INCH chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
chan_end(chsa, SNS_CHNEND); /* done */
|
||||
int len = chp->ccw_count; /* INCH command count */
|
||||
uint32 mema = chp->ccw_addr; /* get inch or buffer addr */
|
||||
// int i = set_inch(uptr, mema); /* new address */
|
||||
set_inch(uptr, mema); /* new address */
|
||||
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_srvi INCH chsa %04x len %02x inch %06x\n", chsa, len, mema);
|
||||
chan_end(chsa, SNS_CHNEND); /* INCH done */
|
||||
// chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */
|
||||
} else {
|
||||
sim_debug(DEBUG_CMD, &con_dev, "con_srvi NOP chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */
|
||||
// chan_end(chsa, SNS_CHNEND); /* done */
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_srvi NOP chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* NOP done */
|
||||
}
|
||||
/* drop through to poll input */
|
||||
}
|
||||
@ -390,25 +430,31 @@ t_stat con_srvi(UNIT *uptr) {
|
||||
case CON_RD: /* 0x02 */ /* read from device */
|
||||
case CON_ECHO: /* 0x0a */ /* read from device w/ECHO */
|
||||
if (uptr->CMD & CON_INPUT) { /* input waiting? */
|
||||
int len = chp->ccw_count; /* get command count */
|
||||
ch = con_data[unit].ibuff[uptr->u4++]; /* get char from read buffer */
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ);
|
||||
#endif
|
||||
sim_debug(DEBUG_CMD, &con_dev, "con_srvi unit %02x: read %02x\n", unit, ch);
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_srvi unit %02x: read %02x incnt %02x u4 %02x len %02x\n",
|
||||
unit, ch, con_data[unit].incnt, uptr->u4, len);
|
||||
|
||||
if (chan_write_byte(chsa, &ch)) { /* write byte to memory */
|
||||
con_data[unit].incnt = 0; /* buffer empty */
|
||||
cmd = 0; /* no cmd either */
|
||||
// uptr->u4 = 0; /* no I/O yet */
|
||||
uptr->CMD &= LMASK; /* nothing left, command complete */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */
|
||||
} else {
|
||||
// len = chp->ccw_count; /* INCH command count */
|
||||
// if ((len==0) && uptr->u4 == con_data[unit].incnt) { /* read completed */
|
||||
if (uptr->u4 == con_data[unit].incnt) { /* read completed */
|
||||
con_data[unit].incnt = 0; /* buffer is empty */
|
||||
cmd = 0; /* no cmd either */
|
||||
// uptr->u4 = 0; /* no I/O yet */
|
||||
uptr->CMD &= LMASK; /* nothing left, command complete */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */
|
||||
}
|
||||
}
|
||||
}
|
||||
// default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -471,7 +517,8 @@ t_stat con_srvi(UNIT *uptr) {
|
||||
atbuf = 0; /* reset attention buffer */
|
||||
sim_putchar('\r'); /* return char */
|
||||
sim_putchar('\n'); /* line feed char */
|
||||
sim_debug(DEBUG_CMD, &con_dev, "con_srvi unit %02x: read @@A Console Trap\n", unit);
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_srvi unit %02x: read @@A Console Trap\n", unit);
|
||||
}
|
||||
} else {
|
||||
if (ch == '?') {
|
||||
@ -484,8 +531,10 @@ t_stat con_srvi(UNIT *uptr) {
|
||||
}
|
||||
if ((r & SCPE_KFLAG) && /* got something and */
|
||||
((cmd == CON_RD) || (cmd == CON_ECHO))) /* looking for input */
|
||||
return sim_activate (uptr, 20);
|
||||
return tmxr_clock_coschedule_tmr (uptr, TMR_RTC, 1); /* come back soon */
|
||||
//WAS return sim_activate (uptr, 20);
|
||||
return sim_activate (uptr, 100);
|
||||
return sim_activate (uptr, 500);
|
||||
//WAS return tmxr_clock_coschedule_tmr (uptr, TMR_RTC, 1); /* come back soon */
|
||||
}
|
||||
|
||||
t_stat con_reset(DEVICE *dptr) {
|
||||
@ -497,22 +546,46 @@ t_stat con_reset(DEVICE *dptr) {
|
||||
uint8 con_haltio(UNIT *uptr) {
|
||||
uint16 chsa = GET_UADDR(uptr->CMD);
|
||||
int cmd = uptr->CMD & CON_MSK;
|
||||
// int unit = (uptr - con_unit); /* unit # */
|
||||
int unit = (uptr - con_unit); /* unit # 0 is read, 1 is write */
|
||||
uint8 ch;
|
||||
|
||||
sim_debug(DEBUG_EXP, &con_dev, "con_haltio enter chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
|
||||
// if ((unit == 0) && ((uptr->CMD & 0xff00) != 0)) { /* just return if busy */
|
||||
// return SNS_BSY;
|
||||
// }
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ);
|
||||
con_dev.dctrl |= (DEBUG_CMD | DEBUG_EXP | DEBUG_DETAIL);
|
||||
#endif
|
||||
/* terminate any input command */
|
||||
if ((uptr->CMD & CON_MSK) != 0) { /* is unit busy */
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_haltio HIO chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
if (unit == 0) {
|
||||
if (chan_write_byte(chsa, &ch)) { /* write byte to memory */
|
||||
con_data[unit].incnt = 0; /* buffer empty */
|
||||
uptr->CMD &= LMASK; /* nothing left, command complete */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
// return SCPE_OK; /* not busy anymore */
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
} else {
|
||||
if (chan_read_byte(chsa, &ch)) { /* get byte from memory */
|
||||
uptr->CMD &= LMASK; /* nothing left, command complete */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */
|
||||
sim_debug(DEBUG_CMD, &con_dev,
|
||||
"con_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
// return SCPE_OK; /* not busy anymore */
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
}
|
||||
uptr->CMD &= LMASK; /* make non-busy */
|
||||
uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */
|
||||
sim_debug(DEBUG_CMD, &con_dev, "con_haltio HIO chsa %04x cmd = %02x\n", chsa, cmd);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */
|
||||
// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* done bit 14 */ /* bad status */
|
||||
return SCPE_OK; /* not busy */
|
||||
//no work chan_end(chsa, SNS_CHNEND|SNS_UNITCHK); /* write terminated */
|
||||
// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); /* write terminated */
|
||||
// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* done bit 15 */ /* bad status */
|
||||
return SCPE_IOERR;
|
||||
// return SCPE_IOERR;
|
||||
}
|
||||
return SCPE_OK; /* not busy */
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* sel32_cpu.c: Sel 32 CPU simulator
|
||||
|
||||
Copyright (c) 2018, James C. Bevier
|
||||
Copyright (c) 2018-2020, James C. Bevier
|
||||
Portions provided by Richard Cornwell and other SIMH contributers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@ -316,7 +316,7 @@ UNIT cpu_unit =
|
||||
|
||||
REG cpu_reg[] = {
|
||||
{HRDATAD(PC, PC, 24, "Program Counter"), REG_FIT},
|
||||
{BRDATAD(PSD, PSD, 16, 32, 2, "Progtam Status Doubleword"), REG_FIT},
|
||||
{BRDATAD(PSD, PSD, 16, 32, 2, "Program Status Doubleword"), REG_FIT},
|
||||
{BRDATAD(GPR, GPR, 16, 32, 8, "Index registers"), REG_FIT},
|
||||
{BRDATAD(BR, BR, 16, 32, 8, "Base registers"), REG_FIT},
|
||||
{BRDATAD(BOOTR, BOOTR, 16, 32, 8, "Boot registers"), REG_FIT},
|
||||
@ -1458,6 +1458,9 @@ 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);
|
||||
@ -1554,7 +1557,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access)
|
||||
sim_debug(DEBUG_TRAP, &cpu_dev,
|
||||
"AddrMa %06x RealAddr %06x Map0 HIT %04x, TLB[%3x] %08x MAPC[%03x] %08x\n",
|
||||
addr, word, map, nix, TLB[nix], nix/2, MAPC[nix/2]);
|
||||
/* do a demand page request for the reqired page */
|
||||
/* do a demand page request for the required page */
|
||||
pfault = nix; /* save page number */
|
||||
sim_debug(DEBUG_TRAP, &cpu_dev,
|
||||
"Mem_write Daddr2 %06x page %04x demand page bits set TLB %08x map %04x\n",
|
||||
@ -1592,6 +1595,9 @@ 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 */
|
||||
@ -1708,6 +1714,9 @@ t_stat Mem_read(uint32 addr, uint32 *data)
|
||||
uint32 status, realaddr, prot, page, map, mix, nix, msdl, mpl, nmap;
|
||||
|
||||
status = RealAddr(addr, &realaddr, &prot, MEM_RD); /* convert address to real physical address */
|
||||
// if (addr != realaddr)
|
||||
//sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
//"At Mem_read convert %06x to addr %08x\n", addr, realaddr);
|
||||
|
||||
if (status == ALLOK) {
|
||||
// *data = M[realaddr >> 2]; /* valid address, get physical address contents */
|
||||
@ -2044,9 +2053,17 @@ redo:
|
||||
SPAD[0xf5] = PSD2; /* save the current PSD2 */
|
||||
SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"Interrupt %04x OPSD1 %08x OPSD2 %08x NPSD1 %08x NPSD2 %08x ICBA %08x\n",
|
||||
il, RMW(int_icb), RMW(int_icb+4), PSD1, PSD2, int_icb);
|
||||
// il, M[int_icb>>2], M[(int_icb>>2)+1], PSD1, PSD2, int_icb);
|
||||
"Inter %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",
|
||||
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",
|
||||
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 */
|
||||
@ -2091,14 +2108,6 @@ redo:
|
||||
/* Check for external interrupt here */
|
||||
/* see if we have an attention request from console */
|
||||
if (!skipinstr && attention_trap) {
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
/* start debugging */
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_EXP | DEBUG_IRQ | DEBUG_XIO);
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Attention TRAP %04x skip %01x wait4int %01x irq_pend %01x\n",
|
||||
TRAPME, skipinstr, wait4int, irq_pend);
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Attention TRAPME %04x PSD %08x %08x\n",
|
||||
TRAPME, PSD1, PSD2);
|
||||
#endif
|
||||
TRAPME = attention_trap; /* get trap number */
|
||||
attention_trap = 0; /* clear flag */
|
||||
sim_debug(DEBUG_XIO, &cpu_dev, "Attention TRAP %04x\n", TRAPME);
|
||||
@ -2110,17 +2119,9 @@ skipi:
|
||||
i_flags = 0; /* do not update pc if MF or NPM */
|
||||
skipinstr = 0; /* skip only once */
|
||||
TRAPSTATUS = CPUSTATUS & 0x57; /* clear all trap status except cpu type */
|
||||
//WAS if (sim_brk_summ && sim_brk_test(PC, SWMASK('E'))) {
|
||||
//WAS reason = STOP_IBKPT;
|
||||
//WAS break;
|
||||
//WAS }
|
||||
|
||||
/* fill IR from logical memory address */
|
||||
if ((TRAPME = read_instruction(PSD, &IR))) {
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
/* start debugging */
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ);
|
||||
#endif
|
||||
sim_debug(DEBUG_TRAP, &cpu_dev,
|
||||
"read_instr TRAPME %04x PSD %08x %08x i_flags %04x drop_nop %01x\n",
|
||||
TRAPME, PSD1, PSD2, i_flags, drop_nop);
|
||||
@ -2698,8 +2699,8 @@ exec:
|
||||
break;
|
||||
case 0x9: /* RDSTS */
|
||||
GPR[reg] = CPUSTATUS; /* get CPU status word */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
"RDSTS CPUSTATUS %08x SPAD[0xf9] %08x\n", CPUSTATUS, SPAD[0xf9]);
|
||||
//sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
//"RDSTS CPUSTATUS %08x SPAD[0xf9] %08x\n", CPUSTATUS, SPAD[0xf9]);
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
/* start debugging */
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_TRAP | DEBUG_EXP | DEBUG_IRQ);
|
||||
@ -3689,8 +3690,8 @@ tbr: /* handle basemode TBR too *
|
||||
t = (GPR[reg] >> 16) & 0xff; /* get SPAD address from Rd (6-8) */
|
||||
temp2 = SPAD[t]; /* get old SPAD data */
|
||||
SPAD[t] = GPR[sreg]; /* store Rs into SPAD */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
"At TRSC with spad[%02x] %08x old %08x\n", t, SPAD[t], temp2);
|
||||
//sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
//"At TRSC with spad[%02x] %08x old %08x\n", t, SPAD[t], temp2);
|
||||
break;
|
||||
|
||||
case 0xF: /* TSCR */ /* Transfer scratchpad to register */
|
||||
@ -3704,8 +3705,8 @@ tbr: /* handle basemode TBR too *
|
||||
}
|
||||
t = (GPR[sreg] >> 16) & 0xff; /* get SPAD address from Rs (9-11) */
|
||||
temp = SPAD[t]; /* get SPAD data into Rd (6-8) */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
"At TSCR with spad[%02x] %08x\n", t, SPAD[t]);
|
||||
//sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
//"At TSCR with spad[%02x] %08x\n", t, SPAD[t]);
|
||||
break;
|
||||
}
|
||||
GPR[reg] = temp; /* save the temp value to Rd reg */
|
||||
@ -4013,6 +4014,8 @@ 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 */
|
||||
@ -4641,6 +4644,8 @@ doovr3:
|
||||
case 0x80>>2: /* 0x80 SD|ADR - SD|ADR */ /* LEAR */
|
||||
/* convert address to real physical address */
|
||||
TRAPME = RealAddr(addr, &temp, &t, MEM_RD);
|
||||
//sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
//"At LEAR convert %06x to addr %08x\n", addr, temp);
|
||||
// diag allows any addr if mapped
|
||||
if (TRAPME != ALLOK) {
|
||||
sim_debug(DEBUG_TRAP, &cpu_dev,
|
||||
@ -4687,7 +4692,7 @@ doovr3:
|
||||
WMR((nix<<1), map); /* store the map reg contents into cache */
|
||||
TLB[nix] |= 0x0c000000; /* set the accessed & hit bits in TLB too */
|
||||
WMH(msdl+(mix<<1), mmap); /* save modified memory map with access bit set */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev,
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"LEAR Laddr %06x page %04x set access bit TLB %08x map %04x nmap %04x\n",
|
||||
addr, nix, TLB[nix], map, mmap);
|
||||
}
|
||||
@ -4697,6 +4702,8 @@ doovr3:
|
||||
/* DIAGS needs it, so put it back */
|
||||
if (FC & 4) /* see if F bit was set */
|
||||
temp |= 0x01000000; /* set bit 7 of address */
|
||||
//sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
//"At LEAR convert %06x to addr %08x\n", addr, temp);
|
||||
dest = temp; /* put in dest to go out */
|
||||
break;
|
||||
|
||||
@ -5022,6 +5029,11 @@ meoa: /* merge point for eor, and, or */
|
||||
"\n\tR0=%.8x R1=%.8x R2=%.8x R3=%.8x", GPR[0], GPR[1], GPR[2], GPR[3]);
|
||||
sim_debug(DEBUG_INST, &cpu_dev,
|
||||
" R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]);
|
||||
#ifdef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"EXM skipinstr %x irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
skipinstr, irq_pend, PSD1, PSD2, CPUSTATUS);
|
||||
#endif
|
||||
/*DIAG*/ skipinstr = 0; /* only test this once */
|
||||
goto exec; /* go execute the instruction */
|
||||
break;
|
||||
@ -5320,7 +5332,7 @@ doovr2:
|
||||
TRAPME = ADDRSPEC_TRAP; /* Not setup, error */
|
||||
goto newpsd; /* program error */
|
||||
}
|
||||
temp2 = ((IR>>12) & 0x0f) << 2; /* get SVC index from IR */
|
||||
temp2 = ((IR>>12) & 0x0f) << 2; /* get SVC index from IR */
|
||||
t = M[(temp+temp2)>>2]; /* get secondary trap vector address ICB address */
|
||||
if (t == 0 || t == 0xffffffff) { /* see if ICB set up */
|
||||
TRAPME = ADDRSPEC_TRAP; /* Not setup, error */
|
||||
@ -5403,6 +5415,11 @@ doovr2:
|
||||
"\n\tR0=%.8x R1=%.8x R2=%.8x R3=%.8x", GPR[0], GPR[1], GPR[2], GPR[3]);
|
||||
sim_debug(DEBUG_INST, &cpu_dev,
|
||||
" R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]);
|
||||
#ifdef NOTNOW
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"EXR skipinstr %x irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
skipinstr, irq_pend, PSD1, PSD2, CPUSTATUS);
|
||||
#endif
|
||||
/*DIAG*/ skipinstr = 0; /* only test this once */
|
||||
goto exec; /* go execute the instruction */
|
||||
break;
|
||||
@ -6347,9 +6364,6 @@ mcheck:
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"XIO SIO ret chan %04x chsa %04x status %08x\n",
|
||||
chan, (chan<<8)|suba, status);
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev,
|
||||
"SIO skipinstr %x irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n",
|
||||
skipinstr, irq_pend, PSD1, PSD2, CPUSTATUS);
|
||||
break;
|
||||
|
||||
case 0x03: /* Test I/O TIO */
|
||||
@ -6364,6 +6378,10 @@ mcheck:
|
||||
sim_debug(DEBUG_XIO, &cpu_dev,
|
||||
"XIO TIO ret chan %04x sa %04x status %08x spad %08x INTS[%02x] %08x\n",
|
||||
chan, suba, status, t, ix, INTS[ix]);
|
||||
#ifdef DO_DYNAMIC_DEBUG
|
||||
/* start debugging */
|
||||
cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x04: /* Stop I/O STPIO */
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* sel32_defs.h: SEL-32 Concept/32 simulator definitions
|
||||
|
||||
Copyright (c) 2018-2019, James C. Bevier
|
||||
Copyright (c) 2018-2020, James C. Bevier
|
||||
Portions provided by Richard Cornwell and other SIMH contributers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@ -417,6 +417,8 @@ extern DEBTAB dev_debug[];
|
||||
#define WMW(a,d) (M[(a)>>2]=d) /* write memory addressed word */
|
||||
/* write halfword to memory address */
|
||||
#define WMH(a,d) ((a)&2?(M[(a)>>2]=(M[(a)>>2]&LMASK)|((d)&RMASK)):(M[(a)>>2]=(M[(a)>>2]&RMASK)|((d)<<16)))
|
||||
/* write byte to memory */
|
||||
#define WMB(a,d) (M[(a)>>2]=(M[(a)>>2]&(~(0xff<<(8*(7-(a&3)))))|((d&0xff)<<(8*(7-(a&3))))))
|
||||
|
||||
/* map register access macros */
|
||||
/* The RMR and WMR macros are used to read/write the MAPC cache registers */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
/* sel32_fltpt.c: SEL 32 floating point instructions processing.
|
||||
|
||||
Copyright (c) 2018, James C. Bevier
|
||||
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"),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
/* sel32_iop.c: SEL-32 Model 8000/8001/8002 IOP processor controller
|
||||
|
||||
Copyright (c) 2018-2019, James C. Bevier
|
||||
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"),
|
||||
@ -44,6 +44,8 @@ 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 iop_startcmd(UNIT *uptr, uint16 chan, uint8 cmd);
|
||||
@ -68,7 +70,7 @@ const char *iop_desc(DEVICE *dptr);
|
||||
#define CON_OUTPUT 0x1000 /* Output ready for unit */
|
||||
#define CON_READ 0x2000 /* Read mode selected */
|
||||
|
||||
/* Input buffer pointer held in u4 */
|
||||
/* not used u4 */
|
||||
|
||||
/* in u5 packs sense byte 0,1 and 3 */
|
||||
/* Sense byte 0 */
|
||||
@ -91,18 +93,19 @@ struct _iop_data
|
||||
uint8 ibuff[145]; /* Input line buffer */
|
||||
uint8 incnt; /* char count */
|
||||
}
|
||||
iop_data[NUM_UNITS_CON];
|
||||
iop_data[NUM_UNITS_IOP];
|
||||
|
||||
/* channel program information */
|
||||
CHANP iop_chp[NUM_UNITS_MT] = {0};
|
||||
CHANP iop_chp[NUM_UNITS_IOP] = {0};
|
||||
|
||||
MTAB iop_mod[] = {
|
||||
{MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, &show_dev_addr, NULL},
|
||||
{MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV",
|
||||
&set_dev_addr, &show_dev_addr, NULL, "Device address"},
|
||||
{0}
|
||||
};
|
||||
|
||||
UNIT iop_unit[] = {
|
||||
{UDATA(iop_srv, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7E00)}, /* Channel controlller */
|
||||
{UDATA(&iop_srv, UNIT_IDLE, 0), 0, UNIT_ADDR(0x7E00)}, /* Channel controller */
|
||||
};
|
||||
|
||||
//DIB iop_dib = {NULL, iop_startcmd, NULL, NULL, NULL, iop_ini, iop_unit, iop_chp, NUM_UNITS_IOP, 0xff, 0x7e00,0,0,0};
|
||||
@ -115,7 +118,7 @@ DIB iop_dib = {
|
||||
iop_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */
|
||||
iop_unit, /* UNIT* units */ /* Pointer to units structure */
|
||||
iop_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */
|
||||
NUM_UNITS_IOP, /* uint8 numunits */ /* number of units defined */
|
||||
NUM_UNITS_IOP, /* 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 */
|
||||
@ -129,8 +132,8 @@ DEVICE iop_dev = {
|
||||
NULL, NULL, &iop_reset, /* examine, deposit, reset */
|
||||
NULL, NULL, NULL, /* boot, attach, detach */
|
||||
&iop_dib, DEV_UADDR|DEV_DISABLE|DEV_DEBUG, 0, dev_debug, /* dib, dev flags, debug flags, debug */
|
||||
NULL, NULL, &iop_help, /* ?, ?, help */
|
||||
NULL, NULL, &iop_desc /* ?, ?, description */
|
||||
// NULL, NULL, &iop_help, /* ?, ?, help */
|
||||
// NULL, NULL, &iop_desc /* ?, ?, description */
|
||||
};
|
||||
|
||||
/* IOP controller routines */
|
||||
@ -140,7 +143,9 @@ void iop_ini(UNIT *uptr, t_bool f)
|
||||
int unit = (uptr - iop_unit); /* unit 0 */
|
||||
DEVICE *dptr = &iop_dev; /* one and only dummy device */
|
||||
|
||||
sim_debug(DEBUG_CMD, &iop_dev, "IOP init device %s controller/device %04x\n", dptr->name, GET_UADDR(uptr->u3));
|
||||
sim_debug(DEBUG_CMD, &iop_dev,
|
||||
"IOP init device %s controller/device %04x\n",
|
||||
dptr->name, GET_UADDR(uptr->u3));
|
||||
iop_data[unit].incnt = 0; /* no input data */
|
||||
uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */
|
||||
}
|
||||
@ -148,6 +153,9 @@ void iop_ini(UNIT *uptr, t_bool f)
|
||||
/* start an I/O operation */
|
||||
uint8 iop_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
{
|
||||
sim_debug(DEBUG_CMD, &iop_dev,
|
||||
"IOP startcmd %02x controller/device %04x\n",
|
||||
cmd, GET_UADDR(uptr->u3));
|
||||
if ((uptr->u3 & IOP_MSK) != 0) /* is unit busy */
|
||||
return SNS_BSY; /* yes, return busy */
|
||||
|
||||
@ -158,9 +166,16 @@ uint8 iop_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
case IOP_INCH: /* INCH command */
|
||||
uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */
|
||||
uptr->u3 &= LMASK; /* leave only chsa */
|
||||
sim_debug(DEBUG_CMD, &iop_dev, "iop_startcmd %04x: Cmd INCH\n", chan);
|
||||
sim_debug(DEBUG_CMD, &iop_dev,
|
||||
"iop_startcmd %04x: Cmd INCH iptr %06x INCHa %06x\n",
|
||||
chan, iop_chp[0].ccw_addr, /* set inch buffer addr */
|
||||
iop_chp[0].chan_inch_addr); /* set inch buffer addr */
|
||||
|
||||
iop_chp[0].chan_inch_addr = iop_chp[0].ccw_addr; /* set inch buffer addr */
|
||||
// set_inch(uptr, iop_chp[0].ccw_addr); /* new address */
|
||||
|
||||
uptr->u3 |= IOP_INCH2; /* save INCH command as 0xf0 */
|
||||
sim_activate(uptr, 20); /* TRY 07-13-19 */
|
||||
sim_activate(uptr, 20); /* go on */
|
||||
return 0; /* no status change */
|
||||
break;
|
||||
|
||||
@ -190,44 +205,48 @@ uint8 iop_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
/* Handle transfers for other sub-channels on IOP */
|
||||
t_stat iop_srv(UNIT *uptr)
|
||||
{
|
||||
uint16 chsa = GET_UADDR(uptr->u3);
|
||||
int cmd = uptr->u3 & IOP_MSK;
|
||||
uint16 chsa = GET_UADDR(uptr->u3);
|
||||
int cmd = uptr->u3 & IOP_MSK;
|
||||
// CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */
|
||||
CHANP *chp = &iop_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 == IOP_NOP) || (cmd == IOP_INCH2)) { /* NOP has do nothing */
|
||||
uptr->u3 &= LMASK; /* nothing left, command complete */
|
||||
sim_debug(DEBUG_CMD, &iop_dev, "iop_srv INCH/NOP chan %02x: chnend|devend\n", chsa);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */
|
||||
} else
|
||||
if (cmd) {
|
||||
if ((cmd != IOP_NOP) && (cmd != IOP_INCH2)) { /* NOP or INCH */
|
||||
uptr->u3 &= LMASK; /* nothing left, command complete */
|
||||
sim_debug(DEBUG_CMD, &iop_dev,
|
||||
"iop_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 == IOP_NOP) { /* NOP do nothing */
|
||||
uptr->u3 &= LMASK; /* nothing left, command complete */
|
||||
sim_debug(DEBUG_CMD, &iop_dev, "iop_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 == IOP_INCH2) { /* INCH */
|
||||
sim_debug(DEBUG_CMD, &iop_dev,
|
||||
"iop_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;
|
||||
}
|
||||
|
||||
/* Handle output transfers for console */
|
||||
t_stat iop_srvo(UNIT *uptr)
|
||||
{
|
||||
uint16 chsa = GET_UADDR(uptr->u3);
|
||||
int cmd = uptr->u3 & IOP_MSK;
|
||||
|
||||
sim_debug(DEBUG_CMD, &iop_dev, "iop_srvo start %04x: cmd %02x \n", chsa, cmd);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Handle input transfers for console */
|
||||
t_stat iop_srvi(UNIT *uptr)
|
||||
{
|
||||
uint16 chsa = GET_UADDR(uptr->u3);
|
||||
int cmd = uptr->u3 & IOP_MSK;
|
||||
|
||||
sim_debug(DEBUG_CMD, &iop_dev, "iop_srv start %04x: cmd %02x \n", chsa, cmd);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat iop_reset(DEVICE *dptr)
|
||||
{
|
||||
/* add reset code here */
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* sel32_lpr.c: SEL 32 Line Printer
|
||||
|
||||
Copyright (c) 2018, James C. Bevier
|
||||
Copyright (c) 2018-2020, James C. Bevier
|
||||
Portions provided by Richard Cornwell and other SIMH contributers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@ -161,9 +161,9 @@ MTAB lpr_mod[] = {
|
||||
};
|
||||
|
||||
UNIT lpr_unit[] = {
|
||||
{UDATA(lpr_srv, UNIT_LPR, 66), 300, UNIT_ADDR(0x7EF8)}, /* A */
|
||||
{UDATA(&lpr_srv, UNIT_LPR, 66), 300, UNIT_ADDR(0x7EF8)}, /* A */
|
||||
#if NUM_DEVS_LPR > 1
|
||||
{UDATA(lpr_srv, UNIT_LPR, 66), 300, UNIT_ADDR(0x7EF9)}, /* B */
|
||||
{UDATA(&lpr_srv, UNIT_LPR, 66), 300, UNIT_ADDR(0x7EF9)}, /* B */
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -217,6 +217,7 @@ uint8 lpr_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
/* process the command */
|
||||
switch (cmd & LPR_CMDMSK) {
|
||||
case 0x00: /* INCH command */
|
||||
/* the IOP should already have the inch buffer set, so ignore */
|
||||
sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd %04x: Cmd INCH\n", chan);
|
||||
//fprintf(stderr, "lpr_startcmd %04x: Cmd INCH\n", chan);
|
||||
return SNS_CHNEND|SNS_DEVEND; /* all is well */
|
||||
|
||||
161
SEL32/sel32_mt.c
161
SEL32/sel32_mt.c
@ -1,6 +1,6 @@
|
||||
/* sel32_mt.c: SEL-32 8051 Buffered Tape Processor
|
||||
|
||||
Copyright (c) 2018, James C. Bevier
|
||||
Copyright (c) 2018-2020, James C. Bevier
|
||||
Portions provided by Richard Cornwell and other SIMH contributers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@ -47,8 +47,11 @@ extern int chan_write_byte(uint16 chan, uint8 *data);
|
||||
extern void set_devattn(uint16 addr, uint8 flags);
|
||||
extern t_stat chan_boot(uint16 addr, DEVICE *dptr);
|
||||
extern DEVICE *get_dev(UNIT *uptr);
|
||||
extern t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */
|
||||
extern CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */
|
||||
|
||||
extern uint32 SPAD[]; /* cpu SPAD */
|
||||
extern uint32 M[]; /* our memory */
|
||||
extern uint32 SPAD[]; /* cpu SPAD */
|
||||
|
||||
#ifdef NUM_DEVS_MT
|
||||
#define BUFFSIZE (64 * 1024)
|
||||
@ -56,70 +59,6 @@ extern uint32 SPAD[]; /* cpu SPAD */
|
||||
#define DEV_BUF_NUM(x) (((x) & 07) << DEV_V_UF)
|
||||
#define GET_DEV_BUF(x) (((x) >> DEV_V_UF) & 07)
|
||||
|
||||
#if 0
|
||||
CMNDCODE EQU $-1B
|
||||
/* IOCD cmd bits 0-7 OP */
|
||||
DATAB X'23' 1 REW
|
||||
DATAB X'02' 2 READ
|
||||
DATAB X'01' 3 WRITE
|
||||
DATAB X'93' 4 WEOF
|
||||
DATAB X'FF' 5 XCHANP
|
||||
DATAB X'43' 6 ADVR
|
||||
DATAB X'63' 7 ADVF
|
||||
DATAB X'53' 8 BKSR
|
||||
DATAB X'73' 9 BKXF
|
||||
DATAB X'01' A UPSPACE (REALLY A WRITE)
|
||||
DATAB X'A3' B ERASE
|
||||
SPACE 3
|
||||
* TIMER TABLE VALUES
|
||||
*
|
||||
* ENTRIES CORRESPOND ONE-FOR-ONE WITH ENTRIES IN OTAB
|
||||
* AND REPRESENT THE MAXIMUM NUMBER OF SECONDS WHICH THE
|
||||
* CORRESPONDING FUNCTION WOULD REQUIRE TO COMPLETE ON A 25 IPS
|
||||
* TAPE DRIVE ON WHICH WAS MOUNTED A 2400 ft REEL OF TAPE.
|
||||
BOUND 1W
|
||||
TIMETBL DATAH 0 OPEN
|
||||
DATAH 2 REWIND
|
||||
DATAH 128 READ ASSUME TRANSFER OF 128K
|
||||
DATAH 128 WRITE ASSUME TRANSFER OF 128K
|
||||
DATAH 2 WRITE END-OF-FILE
|
||||
DATAH 0 EXECUTE CHANNEL PROGRAM
|
||||
DATAH 2 ADVANCE RECORD
|
||||
DATAH 1152 SPACE FORWARD TO END-OF-FILE
|
||||
DATAH 2 BACKSPACE RECORD
|
||||
DATAH 1152 SPACE BACKWARD TO END-OF-FILE
|
||||
DATAH 2 UPSPACE
|
||||
DATAH 2 ERASE
|
||||
DATAH 0 EJECT
|
||||
DATAH 0 CLOSE
|
||||
DATAH 0 TERM
|
||||
DATAH 0 TEST
|
||||
TOENTS EQU $-TIMETBL/2 NUMBER OF ENTRIES IN TABLE
|
||||
SPACE 2
|
||||
*
|
||||
* HANDLER OP CODE VECTOR TABLE
|
||||
*
|
||||
BOUND 1W
|
||||
OTAB EQU $
|
||||
ACH OPEN 0 OPEN
|
||||
ACH RWND 1 RWND
|
||||
ACH READ 2 READ
|
||||
ACH WRITE 3 WRITE
|
||||
ACH WEOF 4 WEOF
|
||||
ACH XCHANP 5 EXECUTE CHANNEL PROGRAM
|
||||
ACH ADVR 6 ADVR
|
||||
ACH ADVF 7 ADVF
|
||||
ACH BKSR 8 BKSR
|
||||
ACH BKSF 9 BKSF
|
||||
ACH UPSP A UPSP
|
||||
ACH ERASE B ERASE
|
||||
ACH EJCT C EJCT
|
||||
ACH CLOSE D CLOSE
|
||||
ACH TERM E TERM
|
||||
ACH TEST F TEST
|
||||
SPACE 3
|
||||
#endif
|
||||
|
||||
#define CMD u3
|
||||
/* BTP tape commands */
|
||||
#define MT_INCH 0x00 /* Initialize channel command */
|
||||
@ -436,8 +375,10 @@ DEVICE mtb_dev = {
|
||||
/* start an I/O operation */
|
||||
uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
{
|
||||
uint16 chsa = GET_UADDR(uptr->CMD);
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
int unit = (uptr - dptr->units);
|
||||
CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */
|
||||
|
||||
sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd entry chan %04x cmd %02x\n", chan, cmd);
|
||||
if (mt_busy[GET_DEV_BUF(dptr->flags)] != 0 || (uptr->CMD & MT_CMDMSK) != 0) {
|
||||
@ -450,10 +391,12 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
|
||||
switch (cmd & 0xFF) {
|
||||
case 0x00: /* INCH command */
|
||||
/* POS has INCH buffer address and us9 the count */
|
||||
/* just return OK and channel software will use POS as status buffer */
|
||||
sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd INCH done unit %04x cmd %02x\n",
|
||||
unit, cmd);
|
||||
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);
|
||||
|
||||
/* UTX_needs_interrupt */
|
||||
cmd = MT_CMDMSK; /* insert INCH cmd as 0xff */
|
||||
/* fall through */
|
||||
@ -477,7 +420,6 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
uptr->SNS = (uptr->SNS & 0x0000ff00); /* clear all but byte 2 */
|
||||
uptr->SNS |= (SNS_RDY|SNS_ONLN); /* set ready status */
|
||||
/* Fall through */
|
||||
// case 0x4: /* Sense */
|
||||
if (sim_tape_wrp(uptr))
|
||||
uptr->SNS |= (SNS_WRP); /* write protected */
|
||||
if (sim_tape_bot(uptr))
|
||||
@ -572,28 +514,71 @@ t_stat mt_srv(UNIT *uptr)
|
||||
int unit = (uptr - dptr->units);
|
||||
int cmd = uptr->CMD & MT_CMDMSK;
|
||||
int bufnum = GET_DEV_BUF(dptr->flags);
|
||||
CHANP *chp = find_chanp_ptr(addr); /* find the chanp pointer */
|
||||
t_mtrlnt reclen;
|
||||
t_stat r = SCPE_ARG; /* Force error if not set */
|
||||
t_stat r = SCPE_ARG; /* Force error if not set */
|
||||
int i;
|
||||
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);
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */
|
||||
uptr->SNS |= SNS_INTVENT; /* unit intervention required */
|
||||
mt_busy[bufnum] &= ~1; /* make our buffer not busy */
|
||||
if (cmd != MT_SENSE) { /* we are completed with unit check status */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */
|
||||
uptr->SNS |= SNS_INTVENT; /* unit intervention required */
|
||||
mt_busy[bufnum] &= ~1; /* make our buffer not busy */
|
||||
if (cmd != MT_SENSE) { /* we are completed with unit check status */
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case MT_CMDMSK: /* 0x0ff for inch 0x00 */ /* INCH is for channel, nothing for us */
|
||||
case MT_CMDMSK: /* 0x0ff for inch 0x00 */ /* INCH is for channel, nothing for us */
|
||||
len = chp->ccw_count; /* INCH command count */
|
||||
mema = chp->ccw_addr; /* get inch or buffer addr */
|
||||
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);
|
||||
|
||||
if (len == 0) {
|
||||
/* we have invalid count, error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK;
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
for (i=0; i < len; i++) {
|
||||
if (chan_read_byte(addr, &buf[i])) {
|
||||
/* we have error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK;
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
/* just dump data */
|
||||
}
|
||||
/* uptr->POS has INCH buffer address, just leave it */
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "mt_srv cmd 0 INCH unit=%04x\n", unit);
|
||||
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 */
|
||||
/* 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
|
||||
if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */
|
||||
/* we have error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK;
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"mt_srv cmd INCH chsa %04x addr %06x count %04x completed\n",
|
||||
addr, mema, chp->ccw_count);
|
||||
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 */
|
||||
break;
|
||||
|
||||
#ifndef FIX_DIAG
|
||||
@ -976,7 +961,7 @@ t_stat mt_srv(UNIT *uptr)
|
||||
uptr->CMD &= ~(MT_CMDMSK);
|
||||
mt_busy[bufnum] &= ~1;
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "Skip record at EOT\n");
|
||||
//BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
//BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK);
|
||||
chan_end(addr, SNS_DEVEND|SNS_UNITEXP);
|
||||
break;
|
||||
}
|
||||
@ -1019,7 +1004,7 @@ t_stat mt_srv(UNIT *uptr)
|
||||
uptr->SNS &= ~SNS_LOAD; /* reset BOT */
|
||||
mt_busy[bufnum] &= ~1;
|
||||
sim_debug(DEBUG_CMD, &mta_dev, "Skip file got EOT sense %08x unit %02x\n", uptr->SNS, unit);
|
||||
//BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
//BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK);
|
||||
chan_end(addr, SNS_DEVEND|SNS_UNITEXP);
|
||||
break;
|
||||
}
|
||||
@ -1032,7 +1017,8 @@ t_stat mt_srv(UNIT *uptr)
|
||||
uptr->SNS |= SNS_CMDREJ;
|
||||
uptr->CMD &= ~MT_CMDMSK;
|
||||
mt_busy[bufnum] &= ~1;
|
||||
chan_end(addr, SNS_DEVEND|SNS_UNITCHK); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
//BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK);
|
||||
chan_end(addr, SNS_DEVEND|SNS_UNITEXP);
|
||||
} else {
|
||||
uptr->POS ++;
|
||||
sim_activate(uptr, 500);
|
||||
@ -1048,7 +1034,7 @@ t_stat mt_srv(UNIT *uptr)
|
||||
uptr->CMD &= ~(MT_CMDMSK);
|
||||
mt_busy[bufnum] &= ~1;
|
||||
/* we are done dev|chan end */
|
||||
chan_end(addr, SNS_DEVEND); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND);
|
||||
chan_end(addr, SNS_DEVEND);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -1118,6 +1104,9 @@ t_stat mt_attach(UNIT *uptr, CONST char *file)
|
||||
return r; /* report any error */
|
||||
}
|
||||
sim_debug(DEBUG_EXP, &mta_dev, "mt_attach complete filename %s\n", file);
|
||||
uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */
|
||||
uptr->POS = 0; /* clear position data */
|
||||
uptr->SNS = 0; /* clear sense data */
|
||||
set_devattn(addr, SNS_DEVEND); /* ready int???? */
|
||||
return SCPE_OK; /* return good status */
|
||||
}
|
||||
@ -1127,6 +1116,8 @@ t_stat mt_detach(UNIT *uptr)
|
||||
{
|
||||
sim_debug(DEBUG_EXP, &mta_dev, "mt_detach\n");
|
||||
uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */
|
||||
uptr->POS = 0; /* clear position data */
|
||||
uptr->SNS = 0; /* clear sense data */
|
||||
return sim_tape_detach(uptr);
|
||||
}
|
||||
|
||||
|
||||
@ -32,6 +32,8 @@ extern void set_devattn(uint16 addr, uint8 flags);
|
||||
extern t_stat chan_boot(uint16 addr, DEVICE *dptr);
|
||||
extern int test_write_byte_end(uint16 chsa);
|
||||
extern DEVICE *get_dev(UNIT *uptr);
|
||||
extern t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */
|
||||
extern CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */
|
||||
|
||||
extern uint32 M[]; /* our memory */
|
||||
extern uint32 SPAD[]; /* cpu SPAD memory */
|
||||
@ -40,6 +42,34 @@ extern uint32 SPAD[]; /* cpu SPAD memory */
|
||||
|
||||
#define UNIT_SCFI UNIT_ATTABLE | UNIT_IDLE | UNIT_DISABLE
|
||||
|
||||
/* useful conversions */
|
||||
/* Fill STAR value from cyl, trk, sec data */
|
||||
#define CHS2STAR(c,h,s) (((c<<16) & 0xffff0000)|((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)
|
||||
/* 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 */
|
||||
#define SPT(type) (scfi_type[type].spt)
|
||||
/* get sectors per cylinderfor specified type */
|
||||
#define SPC(type) (scfi_type[type].spt*scfi_type[type].nhds)
|
||||
/* get number of cylinders for specified type */
|
||||
#define CYL(type) (scfi_type[type].cyl)
|
||||
/* get number of heads for specified type */
|
||||
#define HDS(type) (scfi_type[type].nhds)
|
||||
/* get disk capacity in sectors for specified type */
|
||||
#define CAP(type) (CYL(type)*HDS(type)*SPT(type))
|
||||
/* get number of bytes per sector for specified type */
|
||||
#define SSB(type) (scfi_type[type].ssiz*4)
|
||||
/* get disk capacity in bytes for specified type */
|
||||
#define CAPB(type) (CAP(type)*SSB(type))
|
||||
/* get disk geometry as STAR value for specified type */
|
||||
#define GEOM(type) (CHS2STAR(CYL(type),HDS(type),SPT(type)))
|
||||
|
||||
/* INCH command information */
|
||||
/*
|
||||
WD 0 - Data address
|
||||
@ -165,10 +195,12 @@ bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option
|
||||
#define SNS_RTAE 0x02 /* Reserve track access error */
|
||||
#define SNS_UESS 0x01 /* Uncorrectable ECC error */
|
||||
|
||||
#define ATTR u6
|
||||
/* u6 */
|
||||
/* u6 holds drive attribute entry */
|
||||
/* provided by inch command for controller */
|
||||
#define CHS u6
|
||||
/* u6 holds the current cyl, hd, sec for the drive */
|
||||
|
||||
/* this attribute information is provided by the INCH command */
|
||||
/* for each device and is not used. It is reconstructed from */
|
||||
/* the disk_t structure data for the assigned disk */
|
||||
/*
|
||||
bits 0-7 - Flags
|
||||
bits 0&1 - 00=Reserved, 01=MHD, 10=FHD, 11=MHD with FHD option
|
||||
@ -176,24 +208,15 @@ bits 0-7 - Flags
|
||||
bit 3 - 0=Reserved
|
||||
bit 4 - 1=Drive not present
|
||||
bit 5 - 1=Dual Port
|
||||
bit 6 - 0=Reserved
|
||||
bit 7 - 0=Reserved
|
||||
bit 6 - 0=Reserved 00 768 byte sec
|
||||
bit 7 - 0=Reserved 01 1024 byte sec
|
||||
bits 8-15 - sector count (sectors per track)(F16=16, F20=20)
|
||||
bits 16-23 - MHD Head count (number of heads on MHD)
|
||||
bits 24-31 - FHD head count (number of heads on FHD or number head on FHD option of
|
||||
mini-module)
|
||||
*/
|
||||
|
||||
#define DDATA up7
|
||||
/* Pointer held in up7 */
|
||||
/* sects/cylinder = sects/track * numhds */
|
||||
/* allocated during attach command for each unit defined */
|
||||
struct ddata_t
|
||||
{
|
||||
uint16 cyl; /* Cylinder head at */
|
||||
uint16 tpos; /* Track position */
|
||||
uint16 spos; /* Sector position */
|
||||
};
|
||||
/* Not Used up7 */
|
||||
|
||||
/* disk definition structure */
|
||||
struct scfi_t
|
||||
@ -205,7 +228,9 @@ struct scfi_t
|
||||
uint16 ucyl; /* Number of cylinders used */
|
||||
uint16 cyl; /* Number of cylinders on disk */
|
||||
uint8 type; /* Device type code */
|
||||
uint32 geom; /* disk star geometry cyl(16) hsd(8) sec(8) */
|
||||
/* bit 1 mhd */
|
||||
/* bits 6/7 = 0 768 byte blk */ /* not used on UDP/DPII */
|
||||
/* = 1 1024 byte blk */ /* not used on UDP/DPII */
|
||||
}
|
||||
|
||||
scfi_type[] =
|
||||
@ -219,49 +244,6 @@ scfi_type[] =
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
#if 0
|
||||
*****************************************************************
|
||||
* DEVICE ID TABLE
|
||||
*****************************************************************
|
||||
SPACE
|
||||
BOUND 1W
|
||||
DID.TBL EQU $
|
||||
*
|
||||
*DEVICE ID NAME..................................................
|
||||
*TOTAL ALLOC. UNITS..................................... :
|
||||
*BIT MAP SIZE .............................. : :
|
||||
*NO. OF HEADS ........................ : : :
|
||||
*SECTOR SIZE ................... : : : :
|
||||
*SECTORS/TRACK .............. : : : : :
|
||||
*SECTORS/ALOC. UNIT.......... : : : : : :
|
||||
*SECTORS/BLOCK ....... : : : : : : :
|
||||
*OLD DEVICE ID NAME.... : : : : : : : :
|
||||
* : : : : : : : : :
|
||||
* ......:..:..:...:....:....:.....:......:........:
|
||||
DID FORM 32, 8, 8, 8, 8, 16, 16, 32, 64
|
||||
SPACE
|
||||
* CLASS 'F' EXTENDED I/O DISC DEVICES
|
||||
DID C'DF01', 3, 3, 26, 64, 2, , 1334, C'FL001'
|
||||
DID C'DF02', 1, 2, 20, 192, 5, 625, 20000, C'MH040'
|
||||
DID C'DF03', 1, 2, 20, 192, 5, 1250, 40000, C'MH080'
|
||||
DID C'DF04', 1, 4, 20, 192, 19, 2375, 76000, C'MH300'
|
||||
DID C'DF0E', 1,16, 20, 192, 1, 2732, 87400, C'MH1GB'
|
||||
DID C'DF05', 1, 1, 20, 192, 4, 184, 5120, C'FH005'
|
||||
DID C'DF06', 1, 2, 20, 192, 1, 250, 8000, C'CD032'
|
||||
DID C'DF07', 1, 2, 20, 192, 3, 750, 24000, C'CD064'
|
||||
DID C'DF08', 1, 2, 20, 192, 1, 250, 8000, C'CD096'
|
||||
DID C'DF08', 1, 2, 20, 192, 5, 1250, 40000, C'CD096'
|
||||
DID C'DF09', 1, 8, 20, 192, 40, 2500, 80000, C'MH600'
|
||||
DID C'DF0A', 1, 8, 20, 192, 40, 2500, 80000, C'FM600'
|
||||
DID C'DF0B', 1, 8, 20, 192, 1, 1711, 5472, C'SG038'
|
||||
DID C'DF0C', 1, 8, 20, 192, 1, 5464,174848, C'SG120'
|
||||
DID C'DF0D', 1, 8, 20, 192, 1, 3491,116808, C'SG076'
|
||||
DID C'DF0B', 1, 8, 20, 192, 1, 1711, 54752, C'SG038'
|
||||
DID C'DF0C', 1, 8, 20, 192, 1, 5464,174848, C'SG120'
|
||||
DID C'DF0D', 1, 8, 20, 192, 1, 3491,116808, C'SG076'
|
||||
*
|
||||
#endif
|
||||
|
||||
uint8 scfi_preio(UNIT *uptr, uint16 chan);
|
||||
uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd);
|
||||
uint8 scfi_haltio(uint16 addr);
|
||||
@ -370,17 +352,30 @@ DEVICE sdb_dev = {
|
||||
};
|
||||
#endif
|
||||
|
||||
/* convert sector disk address to star values (c,h,s) */
|
||||
uint32 scfisec2star(uint32 daddr, int type)
|
||||
{
|
||||
int32 sec = daddr % scfi_type[type].spt; /* get sector value */
|
||||
int32 spc = scfi_type[type].nhds * scfi_type[type].spt; /* sec per cyl */
|
||||
int32 cyl = daddr / spc; /* cylinders */
|
||||
int32 hds = (daddr % spc) / scfi_type[type].spt; /* heads */
|
||||
|
||||
/* now return the star value */
|
||||
return (CHS2STAR(cyl,hds,sec)); /* return STAR */
|
||||
}
|
||||
|
||||
/* start a disk operation */
|
||||
uint8 scfi_preio(UNIT *uptr, uint16 chan)
|
||||
{
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
int unit = (uptr - dptr->units);
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
uint16 chsa = GET_UADDR(uptr->CMD);
|
||||
int unit = (uptr - dptr->units);
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr, "scfi_preio CMD %08x unit=%02x\n", uptr->CMD, unit);
|
||||
if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */
|
||||
return SNS_BSY;
|
||||
}
|
||||
sim_debug(DEBUG_CMD, dptr, "scfi_preio unit=%02x\n", unit);
|
||||
sim_debug(DEBUG_CMD, dptr, "scfi_preio unit %02x chsa %04x OK\n", unit, chsa);
|
||||
return 0; /* good to go */
|
||||
}
|
||||
|
||||
@ -389,9 +384,11 @@ uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
uint16 addr = GET_UADDR(uptr->CMD);
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
int unit = (uptr - dptr->units);
|
||||
uint8 ch;
|
||||
CHANP *chp = find_chanp_ptr(addr); /* find the chanp pointer */
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr, "scfi_startcmd unit %02x cmd %04x CMD %08x\n", unit, cmd, uptr->CMD);
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"scfi_startcmd unit %02x cmd %04x CMD %08x\n",
|
||||
unit, cmd, uptr->CMD);
|
||||
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 */
|
||||
@ -407,114 +404,21 @@ uint8 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
|
||||
}
|
||||
sim_debug(DEBUG_CMD, dptr, "scfi_startcmd CMD 2 unit=%02x cmd %02x\n", unit, cmd);
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* see if unit is attached */
|
||||
if (cmd == DSK_SNS) { /* not attached, is cmd Sense 0x04 */
|
||||
sim_debug(DEBUG_CMD, dptr, "scfi_startcmd CMD sense\n");
|
||||
/* bytes 0,1 - Cyl entry from STAR reg in STAR */
|
||||
ch = (uptr->STAR >> 24) & 0xff;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b0 unit=%02x 1 %02x\n",
|
||||
unit, ch);
|
||||
chan_write_byte(addr, &ch) ;
|
||||
ch = (uptr->STAR >> 16) & 0xff;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b1 unit=%02x 1 %02x\n",
|
||||
unit, ch);
|
||||
chan_write_byte(addr, &ch) ;
|
||||
/* byte 2 - Track entry from STAR reg in STAR */
|
||||
ch = (uptr->STAR >> 8) & 0xff;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b2 unit=%02x 1 %02x\n",
|
||||
unit, ch);
|
||||
chan_write_byte(addr, &ch) ;
|
||||
/* byte 3 - Sector entry from STAR reg in STAR */
|
||||
ch = (uptr->STAR) & 0xff;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense STAR b3 unit=%02x 1 %02x\n",
|
||||
unit, ch);
|
||||
chan_write_byte(addr, &ch) ;
|
||||
/* bytes 4 - mode reg, byte 0 of SNS */
|
||||
ch = (uptr->SNS >> 24) & 0xff; /* return the sense data for device */
|
||||
sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%02x 1 %02x\n",
|
||||
unit, ch);
|
||||
chan_write_byte(addr, &ch) ;
|
||||
/* bytes 5-7 - status bytes, bytes 1-3 of SNS */
|
||||
ch = (uptr->SNS >> 16) & 0xff;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%02x 2 %02x\n",
|
||||
unit, ch);
|
||||
chan_write_byte(addr, &ch) ;
|
||||
ch = (uptr->SNS >> 8) & 0xff;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%02x 3 %02x\n",
|
||||
unit, ch);
|
||||
chan_write_byte(addr, &ch) ;
|
||||
ch = (uptr->SNS) & 0xff;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "scfi_startcmd sense unit=%02x 4 %02x\n",
|
||||
unit, ch);
|
||||
chan_write_byte(addr, &ch) ;
|
||||
/* bytes 8-11 - drive attribute register (DATR) entries from uptr->ATTR
|
||||
* via INCH cmd */
|
||||
ch = (uptr->ATTR >> 24) & 0xff;
|
||||
chan_write_byte(addr, &ch) ;
|
||||
ch = (uptr->ATTR >> 16) & 0xff;
|
||||
chan_write_byte(addr, &ch) ;
|
||||
ch = (uptr->ATTR >> 8 ) & 0xff;
|
||||
chan_write_byte(addr, &ch) ;
|
||||
ch = (uptr->ATTR >> 0) & 0xff;
|
||||
chan_write_byte(addr, &ch) ;
|
||||
/* bytes 12 & 13 contain drive related status */
|
||||
ch = 0; /* zero for now */
|
||||
chan_write_byte(addr, &ch) ;
|
||||
chan_write_byte(addr, &ch) ;
|
||||
|
||||
uptr->SNS &= 0xff000000; /* clear status bytes, but leave mode data */
|
||||
return SNS_CHNEND|SNS_DEVEND;
|
||||
}
|
||||
if (cmd == 0x0) /* INCH cmd gives unit check */
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
|
||||
|
||||
uptr->SNS |= (SNS_INTVENT|SNS_CMDREJ); /* set new error status */
|
||||
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* we done */
|
||||
}
|
||||
|
||||
/* Unit is online, so process a command */
|
||||
switch (cmd) {
|
||||
|
||||
case DSK_INCH: /* INCH 0x00 */
|
||||
{
|
||||
uint32 mema; /* memory address */
|
||||
uint32 i;
|
||||
UNIT *up = dptr->units; /* first unit for this device */
|
||||
case DSK_INCH: /* INCH 0x00 */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"scfi_startcmd starting inch cmd addr %04x STAR %08x\n",
|
||||
addr, uptr->STAR);
|
||||
/* STAR (u4) has IOCD word 1 contents. For the disk processor it contains */
|
||||
/* a pointer to the INCH buffer followed by 8 drive attribute words that */
|
||||
/* contains the flags, sector count, MHD head count, and FHD count */
|
||||
/* us9 has the byte count from IOCD wd2 and should be 0x24 (36) */
|
||||
/* the INCH buffer address must be returned in STAR and us9 left non-zero */
|
||||
/* just return OK and channel software will use up8 as status buffer */
|
||||
mema = (uint32)uptr->STAR; /* get memory address of buffer */
|
||||
uptr->STAR = M[mema>>2]; /* get status buffer address for XIO return status */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"scfi_startcmd starting inch cmd addr %04x STAR %08x mema %08x units %02x\n",
|
||||
addr, uptr->STAR, mema, dptr->numunits);
|
||||
/* the next 8 words have drive data for each unit */
|
||||
/* WARNING 8 drives must be defined for this controller */
|
||||
/* so we will not have a map fault */
|
||||
for (i=0; i<dptr->numunits && i<8; i++) { /* process all drives */
|
||||
up->ATTR = M[(mema>>2)+i+1]; /* save each unit's drive data */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"scfi_startcmd ATTR data %08x unit %02x flags %02x sec %02x MHD %02x FHD %02x\n",
|
||||
up->ATTR, i, (up->ATTR >> 24)&0xff, (up->ATTR >> 16)&0xff,
|
||||
(up->ATTR >> 8)&0xff, (up->ATTR&0xff));
|
||||
up++; /* next unit for this device */
|
||||
}
|
||||
sim_debug(DEBUG_CMD, dptr, "scfi_startcmd done INCH cmd addr %04x\n", addr);
|
||||
"scfi_startcmd starting INCH %06x cmd, chsa %04x MemBuf %08x cnt %04x\n",
|
||||
uptr->u4, addr, chp->ccw_addr, chp->ccw_count);
|
||||
|
||||
uptr->CMD |= 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 */
|
||||
uptr->CMD &= ~(DSK_STAR); /* show we do not have seek STAR in STAR */
|
||||
case DSK_WD: /* Write command 0x01 */
|
||||
case DSK_RD: /* Read command 0x02 */
|
||||
case DSK_LMR: /* read mode register */
|
||||
@ -554,25 +458,23 @@ t_stat scfi_srv(UNIT *uptr)
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
/* get pointer to Dev Info Blk for this device */
|
||||
DIB *dibp = (DIB *)dptr->ctxt;
|
||||
CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */
|
||||
struct ddata_t *data = (struct ddata_t *)(uptr->up7);
|
||||
CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */
|
||||
int cmd = uptr->CMD & DSK_CMDMSK;
|
||||
int type = GET_TYPE(uptr->flags);
|
||||
uint32 trk, cyl;
|
||||
uint32 trk, cyl, sec;
|
||||
int unit = (uptr - dptr->units);
|
||||
int len;
|
||||
int dlen = 0; /* total bytes processed */
|
||||
int len=0;
|
||||
int i;
|
||||
uint8 ch;
|
||||
uint16 ssize = scfi_type[type].ssiz*4; /* Size of one sector in bytes */
|
||||
int tsize = scfi_type[type].spt * ssize; /* get track size in bytes */
|
||||
int32 tstart = 0; /* Location of start of cyl/track/sect in data */
|
||||
uint16 ssize = scfi_type[type].ssiz*4; /* Size of one sector in bytes */
|
||||
int32 tstart = 0; /* Location of start of cyl/track/sect in data */
|
||||
uint8 buf2[1024];
|
||||
uint8 buf[1024];
|
||||
|
||||
sim_debug(DEBUG_DETAIL, &sda_dev,
|
||||
"scfi_srv entry unit %02x cmd %02x chsa %04x chan %04x count %04x\n",
|
||||
unit, cmd, chsa, chsa>>8, chp->ccw_count);
|
||||
"scfi_srv entry unit %02x CMD %08x chsa %04x count %04x %x/%x/%x \n",
|
||||
unit, uptr->CMD, chsa, chp->ccw_count,
|
||||
STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff));
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */
|
||||
uptr->SNS |= SNS_INTVENT; /* unit intervention required */
|
||||
@ -581,17 +483,92 @@ t_stat scfi_srv(UNIT *uptr)
|
||||
}
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"scfi_srv cmd=%02x chsa %04x count %04x\n",
|
||||
cmd, chsa, chp->ccw_count);
|
||||
"scfi_srv cmd=%02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count);
|
||||
switch (cmd) {
|
||||
case 0: /* No command, stop disk */
|
||||
break;
|
||||
|
||||
case DSK_INCH2: /* use 0xff for inch, just need int */
|
||||
{
|
||||
uint32 mema; /* memory address */
|
||||
// uint32 daws[8]; /* drive attribute registers */
|
||||
// uint32 i, j;
|
||||
uint32 i;
|
||||
|
||||
len = chp->ccw_count; /* INCH command count */
|
||||
mema = chp->ccw_addr; /* get inch or buffer addr */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"scfi_srv starting INCH cmd, chsa %04x MemBuf %06x cnt %04x\n",
|
||||
chsa, chp->ccw_addr, chp->ccw_count);
|
||||
|
||||
/* mema has IOCD word 1 contents. For the disk processor it contains */
|
||||
/* a pointer to the INCH buffer followed by 8 drive attribute words that */
|
||||
/* contains the flags, sector count, MHD head count, and FHD count */
|
||||
/* 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 */
|
||||
/* 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 */
|
||||
|
||||
len = chp->ccw_count; /* INCH command count */
|
||||
|
||||
if (len != 36) {
|
||||
/* we have invalid count, error, bail out */
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK;
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
|
||||
/* read all 36 bytes, stopping every 4 bytes to make words */
|
||||
/* the first word has the inch buffer address */
|
||||
/* the next 8 words have drive data for each unit */
|
||||
/* WARNING 8 drives must be defined for this controller */
|
||||
/* so we will not have a map fault */
|
||||
// for (i=0, j=0; i < 36; i++) {
|
||||
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->SNS |= SNS_CMDREJ|SNS_EQUCHK;
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
if (((i+1)%4) == 0) { /* see if we have a word yet */
|
||||
if (i == 3)
|
||||
/* inch buffer address */
|
||||
mema = (buf[0]<<24) | (buf[1]<<16) |
|
||||
(buf[2]<<8) | (buf[3]);
|
||||
else
|
||||
/* drive attribute registers */
|
||||
// daws[j++] = (buf[i-3]<<24) | (buf[i-2]<<16)
|
||||
// | (buf[i-1]<<8) | (buf[i]);
|
||||
/* may want to use this later */
|
||||
/* clear warning errors */
|
||||
tstart = (buf[i-3]<<24) | (buf[i-2]<<16)
|
||||
| (buf[i-1]<<8) | (buf[i]);
|
||||
}
|
||||
}
|
||||
/* now call set_inch() function to write and test inch bybber addresses */
|
||||
i = set_inch(uptr, mema); /* new address */
|
||||
#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->SNS |= SNS_CMDREJ|SNS_EQUCHK;
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
uptr->CMD &= ~(0xffff); /* remove old cmd */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"scfi_srv cmd INCH chsa %04x count %04x completed\n", chsa, chp->ccw_count);
|
||||
chan_end(chsa, SNS_CHNEND); /* return just channel end */
|
||||
"scfi_srv cmd INCH chsa %04x addr %06x count %04x completed\n",
|
||||
chsa, mema, chp->ccw_count);
|
||||
#ifdef FIX4MPX
|
||||
chan_end(chsa, SNS_CHNEND); /* return just channel end OK */
|
||||
#else
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case DSK_NOP: /* NOP 0x03 */
|
||||
@ -623,58 +600,23 @@ t_stat scfi_srv(UNIT *uptr)
|
||||
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) {
|
||||
/* see if on cylinder yet */
|
||||
if ((uptr->STAR >> 16) == data->cyl) {
|
||||
if (STAR2CYL(uptr->STAR) == STAR2CYL(uptr->CHS)) {
|
||||
/* we are on cylinder, seek is done */
|
||||
sim_debug(DEBUG_CMD, dptr, "scfi_srv seek on cylinder unit=%02x %04x %04x\n",
|
||||
unit, uptr->STAR >> 16, data->cyl);
|
||||
unit, uptr->STAR >> 16, uptr->CHS >> 16);
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
set_devattn(chsa, SNS_DEVEND); /* start the operation */
|
||||
sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek end unit=%02x %04x %04x\n",
|
||||
unit, uptr->STAR >> 16, data->cyl);
|
||||
/* 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);
|
||||
break;
|
||||
} else {
|
||||
/* Compute delay based of difference. */
|
||||
/* Set next state = index */
|
||||
i = (uptr->STAR >> 16) - data->cyl;
|
||||
sim_debug(DEBUG_CMD, dptr, "scfi_srv seek unit=%02x %04x %04x\n",
|
||||
unit, uptr->STAR >> 16, i);
|
||||
if (i > 0 ) {
|
||||
if (i > 50) {
|
||||
data->cyl += 50; /* seek 50 cyl */
|
||||
sim_activate(uptr, 800);
|
||||
} else
|
||||
if (i > 20) {
|
||||
data->cyl += 20; /* seek 20 cyl */
|
||||
sim_activate(uptr, 400);
|
||||
} else {
|
||||
data->cyl++; /* Seek 1 cyl */
|
||||
sim_activate(uptr, 200);
|
||||
}
|
||||
if (data->cyl >= scfi_type[type].cyl) /* test for over max */
|
||||
data->cyl = scfi_type[type].cyl-1; /* make max */
|
||||
} else {
|
||||
if (i < -50) {
|
||||
data->cyl -= 50; /* seek 50 cyl */
|
||||
sim_activate(uptr, 800);
|
||||
} else
|
||||
if (i < -20) {
|
||||
data->cyl -= 20; /* seek 20 cyl */
|
||||
sim_activate(uptr, 400);
|
||||
} else {
|
||||
data->cyl--; /* seek 1 cyl */
|
||||
sim_activate(uptr, 200);
|
||||
}
|
||||
if ((int32)data->cyl < 0) /* test for less than zero */
|
||||
data->cyl = 0; /* make zero */
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek next unit=%02x %04x %04x\n",
|
||||
unit, uptr->STAR >> 16, data->cyl);
|
||||
sim_activate(uptr, 2);
|
||||
/* we have wasted enough time, we there */
|
||||
uptr->CHS = uptr->STAR; /* we are there */
|
||||
sim_activate(uptr, 10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -690,26 +632,35 @@ t_stat scfi_srv(UNIT *uptr)
|
||||
break;
|
||||
}
|
||||
}
|
||||
rezero:
|
||||
sim_debug(DEBUG_DETAIL, dptr, "scfi_srv seek unit=%02x star %02x %02x %02x %02x\n",
|
||||
/* the value is really a sector offset for the disk */
|
||||
/* but will treat as c/h/s for processing */
|
||||
/* the cyl, trk, and sect are ready to update */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"scfi_srv STAR unit=%02x star %02x %02x %02x %02x\n",
|
||||
unit, buf[0], buf[1], buf[2], buf[3]);
|
||||
rezero:
|
||||
sim_debug(DEBUG_DETAIL, dptr,
|
||||
"scfi_srv seek unit=%02x star %02x %02x %02x %02x\n",
|
||||
unit, buf[0], buf[1], buf[2], buf[3]);
|
||||
|
||||
/* save STAR (target sector) data in STAR */
|
||||
uptr->STAR = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]);
|
||||
cyl = uptr->STAR >> 16; /* get the cylinder */
|
||||
cyl = STAR2CYL(uptr->STAR); /* get the cylinder */
|
||||
trk = buf[2]; /* get the track */
|
||||
sim_debug(DEBUG_DETAIL, dptr, "scfi_srv SEEK %08x cyl %04x trk %02x sec %02x unit=%02x\n",
|
||||
uptr->CMD, cyl&0xffff, trk, buf[3], unit);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "scfi_srv Disk %s cyl %04x hds %02x sec/trk %02x unit=%02x\n",
|
||||
scfi_type[type].name, scfi_type[type].cyl, scfi_type[type].nhds, scfi_type[type].spt, unit);
|
||||
|
||||
/* FIXME do something with FHD here */
|
||||
sim_debug(DEBUG_DETAIL, dptr,
|
||||
"scfi_srv SEEK %08x cyl %04x trk %02x sec %02x unit=%02x\n",
|
||||
uptr->CMD, cyl&0xffff, trk, buf[3], unit);
|
||||
|
||||
/* Check if seek valid */
|
||||
if (cyl >= scfi_type[type].cyl ||
|
||||
trk >= scfi_type[type].nhds ||
|
||||
buf[3] >= scfi_type[type].spt) {
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"dsk_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->SNS |= SNS_CMDREJ|SNS_EQUCHK; /* set error status */
|
||||
|
||||
@ -718,35 +669,36 @@ rezero:
|
||||
break;
|
||||
}
|
||||
|
||||
uptr->CMD |= DSK_STAR; /* show we have seek STAR in CMD */
|
||||
/* calc the sector address of data */
|
||||
/* calc the new sector address of data */
|
||||
/* calculate file position in bytes of requested sector */
|
||||
/* file offset in bytes */
|
||||
tstart = (((cyl * scfi_type[type].nhds * tsize) + (trk * tsize) + buf[3]) * ssize);
|
||||
data->tpos = trk; /* save the track/head number */
|
||||
data->spos = buf[3]; /* save the sector number */
|
||||
tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)) * SSB(type);
|
||||
uptr->CHS = CHS2STAR(STAR2CYL(uptr->CHS), trk, buf[3]);
|
||||
|
||||
sim_debug(DEBUG_DETAIL, dptr,
|
||||
"scfi_srv seek start %08x trk %04x sec %02x\n",
|
||||
tstart, trk, buf[3]);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Check if already on correct cylinder */
|
||||
if (cyl != data->cyl) {
|
||||
/* No, Do seek */
|
||||
/* 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,
|
||||
"scfi_srv seek unit=%02x cyl %04x trk %04x sec %04x\n",
|
||||
"scfi_srv seeking unit=%02x to cyl %04x trk %04x sec %04x\n",
|
||||
unit, cyl, trk, buf[3]);
|
||||
sim_activate(uptr, 20);
|
||||
// chan_end(chsa, SNS_CHNEND);
|
||||
} else {
|
||||
/* we are on cylinder/track/sector, so go on */
|
||||
sim_debug(DEBUG_DETAIL, dptr,
|
||||
"scfi_srv calc sect addr seek start %08x cyl %04x trk %04x sec %02x\n",
|
||||
tstart, cyl, trk, buf[3]);
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
// sim_activate(uptr, 20);
|
||||
chan_end(chsa, SNS_DEVEND|SNS_CHNEND);
|
||||
}
|
||||
return SCPE_OK;
|
||||
@ -756,10 +708,10 @@ rezero:
|
||||
sim_debug(DEBUG_CMD, dptr, "RD REZERO IPL unit=%02x seek 0\n", unit);
|
||||
/* 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 */
|
||||
tstart = 0; /* byte offset is 0 */
|
||||
dlen = 0; /* no data written yet */
|
||||
/* Read in 1 dummy character for length to inhibit SLI posting */
|
||||
if (chan_read_byte(chsa, &buf[0])) {
|
||||
/* we have error, bail out */
|
||||
@ -770,7 +722,7 @@ rezero:
|
||||
}
|
||||
/* zero stuff */
|
||||
buf[0] = buf[1] = buf[2] = buf[3] = 0;
|
||||
goto rezero; /* murge with seek code */
|
||||
goto rezero; /* merge with seek code */
|
||||
break;
|
||||
|
||||
case DSK_LMR:
|
||||
@ -783,6 +735,8 @@ rezero:
|
||||
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->SNS |= (buf[0] << 24); /* save mode value */
|
||||
@ -793,17 +747,24 @@ rezero:
|
||||
/* tstart has start of sector address in bytes */
|
||||
if ((uptr->CMD & DSK_READING) == 0) { /* see if we are reading data */
|
||||
uptr->CMD |= DSK_READING; /* read from disk starting */
|
||||
dlen = 0; /* no data read yet */
|
||||
sim_debug(DEBUG_CMD, dptr, "DISK READ starting unit=%02x CMD %08x count %04x\n",
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"DISK READ starting unit=%02x CMD %08x count %04x\n",
|
||||
unit, uptr->CMD, chp->ccw_count);
|
||||
}
|
||||
|
||||
if (uptr->CMD & 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 */
|
||||
/* get sector offset */
|
||||
// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type));
|
||||
tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type));
|
||||
|
||||
/* 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, data->cyl, data->tpos, data->spos);
|
||||
len, ssize, cyl, trk, sec);
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
@ -811,33 +772,53 @@ rezero:
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr, "scfi_srv after READ chsa %04x count %04x\n",
|
||||
chsa, chp->ccw_count);
|
||||
|
||||
/* process the next sector of data */
|
||||
for (i=0; i<len; i++) {
|
||||
ch = buf[i]; /* get a char from buffer */
|
||||
if (chan_write_byte(chsa, &ch)) { /* put a byte to memory */
|
||||
sim_debug(DEBUG_DATA, dptr,
|
||||
"DISK Read %04x bytes from diskfile cyl %04x hds %02x sec %02x tstart %08x\n",
|
||||
dlen+i, data->cyl, data->tpos, data->spos, tstart);
|
||||
"DISK Read %04x bytes from diskfile /%04x/%02x/%02x tstart %08x\n",
|
||||
len, cyl, trk, sec, tstart);
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND);
|
||||
goto rddone;
|
||||
}
|
||||
}
|
||||
dlen += len; /* add byte read to total count */
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"DISK READ from sec end %04x bytes end %04x from diskfile cyl %04x hds %02x sec %02x tstart %08x\n",
|
||||
dlen, ssize, data->cyl, data->tpos, data->spos, tstart);
|
||||
data->spos++;
|
||||
"DISK READ from sec end %04x bytes end %04x from diskfile /%04x/%02x/%02x tstart %08x\n",
|
||||
len, ssize, cyl, trk, sec, tstart);
|
||||
|
||||
/* tstart has file offset in sectors */
|
||||
tstart++; /* bump to next sector */
|
||||
/* convert sect back to chs value */
|
||||
uptr->CHS = scfisec2star(tstart, type);
|
||||
/* see of over end of disk */
|
||||
// if (tstart >= CAPB(type)) {
|
||||
if (tstart >= CAP(type)) {
|
||||
/* EOM reached, abort */
|
||||
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->CHS = 0; /* reset cylinder position */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
}
|
||||
|
||||
/* see if we are done reading data */
|
||||
if (test_write_byte_end(chsa)) {
|
||||
sim_debug(DEBUG_DATA, dptr,
|
||||
"DISK Read complete Read %04x bytes from diskfile cyl %04x hds %02x sec %02x tstart %08x\n",
|
||||
dlen, data->cyl, data->tpos, data->spos, tstart);
|
||||
"DISK Read complete Read %04x bytes from diskfile /%04x/%02x/%02x tstart %08x\n",
|
||||
ssize, cyl, trk, sec, tstart);
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND);
|
||||
break;
|
||||
} else {
|
||||
sim_debug(DEBUG_DATA, dptr,
|
||||
"DISK sector read complete, %x bytes to go from diskfile /%04x/%02x/%02x\n",
|
||||
chp->ccw_count, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff));
|
||||
sim_activate(uptr, 10); /* wait to read next sector */
|
||||
break;
|
||||
}
|
||||
@ -848,14 +829,21 @@ rddone:
|
||||
|
||||
case DSK_WD: /* Write Data */
|
||||
/* tstart has start of sector address in bytes */
|
||||
|
||||
if ((uptr->CMD & DSK_WRITING) == 0) { /* see if we are writing data */
|
||||
uptr->CMD |= DSK_WRITING; /* write to disk starting */
|
||||
dlen = 0; /* no data written yet */
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"DISK WRITE starting unit=%02x CMD %08x bytes %04x\n",
|
||||
unit, uptr->CMD, dlen);
|
||||
unit, uptr->CMD, len);
|
||||
}
|
||||
if (uptr->CMD & DSK_WRITING) { /* see if we are writing data */
|
||||
if (uptr->CMD & 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 */
|
||||
/* get sector offset */
|
||||
// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type));
|
||||
tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type));
|
||||
|
||||
/* process the next sector of data */
|
||||
len = 0; /* used here as a flag for short read */
|
||||
for (i=0; i<ssize; i++) {
|
||||
@ -865,7 +853,7 @@ rddone:
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
sim_debug(DEBUG_DATA, dptr,
|
||||
"DISK Wrote %04x bytes to diskfile cyl %04x hds %02x sec %02x tstart %08x\n",
|
||||
ssize, data->cyl, data->tpos, data->spos, tstart);
|
||||
ssize, cyl, trk, sec, tstart);
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND);
|
||||
goto wrdone;
|
||||
}
|
||||
@ -874,12 +862,12 @@ rddone:
|
||||
}
|
||||
buf2[i] = ch; /* save the char */
|
||||
}
|
||||
dlen += ssize; /* add 1 sector of bytes */
|
||||
|
||||
/* write the sector to disk */
|
||||
if ((i=sim_fwrite(buf2, 1, ssize, uptr->fileref)) != ssize) {
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Error %08x on write %04x to diskfile cyl %04x hds %02x sec %02x\n",
|
||||
i, ssize, data->cyl, data->tpos, data->spos);
|
||||
i, ssize, cyl, trk, sec);
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
break;
|
||||
@ -887,16 +875,32 @@ rddone:
|
||||
if (len != 0) { /* see if done with write command */
|
||||
sim_debug(DEBUG_DATA, dptr,
|
||||
"DISK WroteB %04x bytes to diskfile cyl %04x hds %02x sec %02x tstart %08x\n",
|
||||
ssize, data->cyl, data->tpos, data->spos, tstart);
|
||||
ssize, cyl, trk, sec, tstart);
|
||||
uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */
|
||||
break;
|
||||
}
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"DISK WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x tstart %08x\n",
|
||||
dlen, ssize, data->cyl, data->tpos, data->spos, tstart);
|
||||
data->spos++;
|
||||
sim_activate(uptr, 10);
|
||||
len, ssize, cyl, trk, sec, tstart);
|
||||
|
||||
/* tstart has file offset in sectors */
|
||||
tstart++; /* bump to next sector */
|
||||
/* convert sect back to chs value */
|
||||
uptr->CHS = scfisec2star(tstart, type);
|
||||
/* see of over end of disk */
|
||||
// if (tstart >= CAPB(type)) {
|
||||
if (tstart >= CAP(type)) {
|
||||
/* EOM reached, abort */
|
||||
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->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 */
|
||||
@ -904,7 +908,7 @@ wrdone:
|
||||
break;
|
||||
|
||||
default:
|
||||
sim_debug(DEBUG_DETAIL, dptr, "invalid command %02x unit %02x\n", cmd, unit);
|
||||
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 */
|
||||
chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
@ -919,16 +923,12 @@ wrdone:
|
||||
void scfi_ini(UNIT *uptr, t_bool f)
|
||||
{
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
uint32 i = GET_TYPE(uptr->flags);
|
||||
// uint32 ssize = scfi_type[i].ssiz * 4; /* disk sector size in bytes */
|
||||
uint32 tsize = scfi_type[i].spt; /* get track size in sectors */
|
||||
uint32 csize = scfi_type[i].nhds * tsize; /* get cylinder size in sectors */
|
||||
/* capacity is total cylinders time sectors per cylinder */
|
||||
uint32 tdisk = scfi_type[i].cyl * csize; /* get total disk size in sectors */
|
||||
int i = GET_TYPE(uptr->flags);
|
||||
|
||||
uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */
|
||||
uptr->SNS = ((uptr->SNS & 0x00ffffff) | (scfi_type[i].type << 24)); /* save mode value */
|
||||
/* total sectors on disk */
|
||||
uptr->capac = tdisk; /* disk size in sectors */
|
||||
uptr->capac = CAP(i); /* disk size in sectors */
|
||||
|
||||
sim_debug(DEBUG_EXP, &sda_dev, "SDA init device %s on unit SDA%.1x cap %x\n",
|
||||
dptr->name, GET_UADDR(uptr->CMD), uptr->CMD);
|
||||
@ -976,7 +976,7 @@ int scfi_format(UNIT *uptr) {
|
||||
buff[2] = 'R';
|
||||
buff[3] = 'O';
|
||||
sim_debug(DEBUG_CMD, dptr,
|
||||
"Creating disk file of trk size %04x capacity %d\n",
|
||||
"Creating disk file of trk size %04x bytes, capacity %d\n",
|
||||
tsize*ssize, cap*ssize);
|
||||
/* write zeros to each track of the disk */
|
||||
for (cyl = 0; cyl < cylv; cyl++) {
|
||||
@ -991,7 +991,7 @@ int scfi_format(UNIT *uptr) {
|
||||
buff[3] = 0;
|
||||
}
|
||||
}
|
||||
if ((cyl % 400) == 0)
|
||||
if ((cyl % 100) == 0)
|
||||
fputc('.', stderr);
|
||||
fputc('\r', stderr);
|
||||
fputc('\n', stderr);
|
||||
@ -1006,41 +1006,27 @@ int scfi_format(UNIT *uptr) {
|
||||
t_stat scfi_attach(UNIT *uptr, CONST char *file) {
|
||||
uint16 addr = GET_UADDR(uptr->CMD);
|
||||
int type = GET_TYPE(uptr->flags);
|
||||
// DEVICE *dptr = get_dev(uptr);
|
||||
DEVICE *dptr = get_dev(uptr);
|
||||
t_stat r;
|
||||
uint32 tsize; /* track size in bytes */
|
||||
uint32 ssize; /* sector size in bytes */
|
||||
uint32 csize, tdisk;
|
||||
struct ddata_t *data;
|
||||
uint8 buff[1024];
|
||||
|
||||
/* have simulator attach the file to the unit */
|
||||
if ((r = attach_unit(uptr, file)) != SCPE_OK)
|
||||
return r;
|
||||
|
||||
if (scfi_type[type].name == 0) { /* does the assigned disk have a name */
|
||||
detach_unit(uptr); /* no, reject */
|
||||
return SCPE_FMT; /* error */
|
||||
}
|
||||
|
||||
/* get a buffer to hold scfi_t structure */
|
||||
/* extended data structure per unit */
|
||||
if ((data = (struct ddata_t *)calloc(1, sizeof(struct ddata_t))) == 0) {
|
||||
detach_unit(uptr);
|
||||
return SCPE_FMT;
|
||||
}
|
||||
/* have simulator attach the file to the unit */
|
||||
if ((r = attach_unit(uptr, file)) != SCPE_OK)
|
||||
return r;
|
||||
|
||||
uptr->up7 = (void *)data; /* save pointer to structure in up7 */
|
||||
/* track size in bytes is sectors/track times words/sector time 4 bytse/word */
|
||||
ssize = scfi_type[type].ssiz * 4; /* disk sector size in bytes */
|
||||
tsize = scfi_type[type].spt; /* get track size in sectors */
|
||||
csize = scfi_type[type].nhds * tsize; /* get cylinder size in sectors */
|
||||
/* capacity is total cylinders time sectors per cylinder */
|
||||
tdisk = scfi_type[type].cyl * csize; /* get total disk size in sectors */
|
||||
uptr->capac = tdisk; /* disk capacity in sectors */
|
||||
uptr->capac = CAP(type); /* disk capacity in sectors */
|
||||
ssize = SSB(type); /* get sector size in bytes */
|
||||
|
||||
sim_debug(DEBUG_CMD, dptr, "Disk %s cyl %d hds %d sec %d ssiz %d capacity %d\n",
|
||||
scfi_type[type].name, scfi_type[type].cyl, scfi_type[type].nhds,
|
||||
scfi_type[type].spt, ssize, uptr->capac); /* disk capacity */
|
||||
|
||||
sim_debug(DEBUG_CMD, &sda_dev, "Disk cyl %d spt %d ssiz %d capacity %d\n",
|
||||
csize, tsize, ssize, uptr->capac*ssize); /* disk capacity */
|
||||
|
||||
if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */
|
||||
detach_unit(uptr); /* if no space, error */
|
||||
@ -1070,18 +1056,12 @@ fmt:
|
||||
return SCPE_FMT; /* error */
|
||||
}
|
||||
|
||||
/* set the max configuration geometry */
|
||||
scfi_type[type].geom = (scfi_type[type].cyl << 16) |
|
||||
(scfi_type[type].nhds << 8) | (scfi_type[type].spt);
|
||||
data->cyl = 0; /* current cylinder position */
|
||||
data->tpos = 0; /* current track position */
|
||||
data->spos = 0; /* current sector position */
|
||||
uptr->CHS = 0; /* set CHS to cyl/hd/sec = 0 */
|
||||
|
||||
sim_debug(DEBUG_CMD, &sda_dev,
|
||||
"Attach %8s hds %d spt %d spc %d cyl %d capacity %d\n",
|
||||
scfi_type[type].name, scfi_type[type].nhds, scfi_type[type].spt,
|
||||
scfi_type[type].nhds * scfi_type[type].spt,
|
||||
scfi_type[type].cyl, uptr->capac);
|
||||
"Attach %s cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\n",
|
||||
scfi_type[type].name, CYL(type), HDS(type), SPT(type), SPC(type),
|
||||
CAP(type), CAPB(type));
|
||||
|
||||
sim_debug(DEBUG_CMD, &sda_dev, "File %s attached to %s\r\n",
|
||||
file, scfi_type[type].name);
|
||||
@ -1092,12 +1072,7 @@ fmt:
|
||||
|
||||
/* detach a disk device */
|
||||
t_stat scfi_detach(UNIT *uptr) {
|
||||
struct ddata_t *data = (struct ddata_t *)uptr->up7;
|
||||
|
||||
if (data != 0) {
|
||||
free(data); /* free disk data structure */
|
||||
}
|
||||
uptr->up7 = 0; /* no pointer to disk data */
|
||||
uptr->SNS = 0; /* clear sense data */
|
||||
uptr->CMD &= ~0xffff; /* no cmd and flags */
|
||||
return detach_unit(uptr); /* tell simh we are done with disk */
|
||||
}
|
||||
@ -1125,14 +1100,14 @@ t_stat scfi_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||
return SCPE_IERR; /* no, error */
|
||||
if (uptr->flags & UNIT_ATT) /* is unit attached? */
|
||||
return SCPE_ALATT; /* no, error */
|
||||
|
||||
/* now loop through the units and find named disk */
|
||||
for (i = 0; scfi_type[i].name != 0; i++) {
|
||||
if (strcmp(scfi_type[i].name, cptr) == 0) {
|
||||
uptr->flags &= ~UNIT_TYPE; /* clear the old UNIT type */
|
||||
uptr->flags |= SET_TYPE(i); /* set the new type */
|
||||
/* set capacity of disk in sectors */
|
||||
uptr->capac = scfi_type[i].cyl * scfi_type[i].nhds *
|
||||
scfi_type[i].spt;
|
||||
uptr->capac = CAP(i);
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
@ -1164,13 +1139,11 @@ t_stat scfi_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
|
||||
}
|
||||
fprintf (st, ".\nEach drive has the following storage capacity:\r\n");
|
||||
for (i = 0; scfi_type[i].name != 0; i++) {
|
||||
/* disk capacity in sectors */
|
||||
int32 capac = scfi_type[i].cyl * scfi_type[i].nhds * scfi_type[i].spt;
|
||||
int32 ssize = scfi_type[i].ssiz * 4; /* disk sector size in bytes */
|
||||
int32 size = capac * ssize; /* disk capacity in bytes */
|
||||
int32 size = CAPB(i); /* disk capacity in bytes */
|
||||
size /= 1024; /* make KB */
|
||||
size = (10 * size) / 1024; /* size in MB * 10 */
|
||||
fprintf(st, " %-8s %4d.%1d MB\r\n", scfi_type[i].name, size/10, size%10);
|
||||
fprintf(st, " %-8s %4d.%1d MB cyl %3d hds %3d sec %3d blk %3d\r\n",
|
||||
scfi_type[i].name, size/10, size%10, CYL(i), HDS(i), SPT(i), SSB(i));
|
||||
}
|
||||
fprint_set_help(st, dptr);
|
||||
fprint_show_help(st, dptr);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* sel32_sys.c: SEL-32 Gould Concept/32 (orignal SEL-32) Simulator system interface.
|
||||
|
||||
Copyright (c) 2018, James C. Bevier
|
||||
Copyright (c) 2018-2020, James C. Bevier
|
||||
Portions provided by Richard Cornwell and other SIMH contributers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user