From 288e6adb900acb11bc4ef0e5e8abc30c15c439e3 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 11 Feb 2021 23:06:54 -0500 Subject: [PATCH] KA10: KS10 now will run Tops 10 7.03. Still has stablity issues. --- PDP10/ks10_cty.c | 18 ++++- PDP10/ks10_rp.c | 153 +++++++++++++++++++++++++-------------- PDP10/ks10_tu.c | 181 +++++++++++++++++++++++++++++----------------- PDP10/ks10_uba.c | 100 +++++++++++++++++-------- PDP10/kx10_cpu.c | 99 +++++++++++++++++++------ PDP10/kx10_defs.h | 5 +- 6 files changed, 379 insertions(+), 177 deletions(-) diff --git a/PDP10/ks10_cty.c b/PDP10/ks10_cty.c index 919095f..8fe7441 100644 --- a/PDP10/ks10_cty.c +++ b/PDP10/ks10_cty.c @@ -96,8 +96,8 @@ MTAB cty_mod[] = { }; UNIT cty_unit[] = { - { UDATA (&ctyo_svc, TT_MODE_7B, 0), 500}, - { UDATA (&ctyi_svc, TT_MODE_7B|UNIT_DIS, 0), 1000 }, + { UDATA (&ctyo_svc, TT_MODE_7B, 0), 2000}, + { UDATA (&ctyi_svc, TT_MODE_7B|UNIT_DIS, 0), 2000 }, { UDATA (&ctyrtc_srv, UNIT_IDLE|UNIT_DIS, 0), 1000 } }; @@ -121,6 +121,7 @@ void cty_wakeup() { sim_debug(DEBUG_EXP, &cty_dev, "CTY wakeup\n"); + sim_cancel(&cty_unit[0]); sim_activate(&cty_unit[0], cty_unit[0].wait); } @@ -186,7 +187,16 @@ t_stat ctyo_svc (UNIT *uptr) cty_interrupt(); } } else { - sim_activate(uptr, uptr->wait); + sim_activate(uptr, tmxr_poll); + } + } + + if (Mem_read_word(KLINK_OUT, &buffer, 0)) + return SCPE_OK; + if (buffer != 0) { + buffer = 0; + if (Mem_write_word(CTY_OUT, &buffer, 0) == 0) { + cty_interrupt(); } } @@ -195,7 +205,7 @@ t_stat ctyo_svc (UNIT *uptr) char ch = cty_out.buff[cty_out.out_ptr]; if (ch != 0) { if (sim_putchar_s(ch) != SCPE_OK) { - sim_activate(uptr, uptr->wait); + sim_activate(uptr, tmxr_poll); return SCPE_OK; } } diff --git a/PDP10/ks10_rp.c b/PDP10/ks10_rp.c index f1647c3..2db6346 100644 --- a/PDP10/ks10_rp.c +++ b/PDP10/ks10_rp.c @@ -80,6 +80,8 @@ #define CS1_TRE 0040000 /* Set if CS2 0177400 */ #define CS1_SC 0100000 /* Set if TRE or ATTN */ +#define CSX_BUSY 02 /* RH11 is doing a transfer */ + /* RPWC - 176702 - word count */ @@ -262,6 +264,8 @@ struct drvtyp rp_drv_tab[] = { int rp_write(t_addr addr, uint16 data, int32 access); int rp_read(t_addr addr, uint16 *data, int32 access); +uint16 rp_vect(struct pdp_dib *dibp); + t_stat rp_svc(UNIT *); t_stat rp_boot(int32, DEVICE *); void rp_ini(UNIT *, t_bool); @@ -300,7 +304,7 @@ UNIT rpa_unit[] = { UNIT_ROABLE+DTYPE(RP06_DTYPE), RP06_SIZE) }, }; -DIB rpa_dib = {0776700, 077, 0254, 6, 1, &rp_read, &rp_write, 0}; +DIB rpa_dib = {0776700, 077, 0254, 6, 1, &rp_read, &rp_write, &rp_vect, 0}; MTAB rp_mod[] = { @@ -345,23 +349,22 @@ rp_write(t_addr addr, uint16 data, int32 access) { UNIT *uptr = &rpa_unit[rp_unit]; int dtype = GET_DTYPE(uptr->flags); - /* If drive not ready don't do anything */ - if ((rp_ie & CS1_GO) != 0|| (uptr->STATUS & DS_PIP) != 0) { - uptr->CMD |= (ER1_RMR << 16); -// rp_cs2 |= CS2_PGE; - sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o not ready\n", rp_unit); - return 0; - } - switch(addr & 076) { /* u3 low */ case 000: /* RPC - 176700 - control */ + sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o Status=%06o\n", rp_unit, uptr->CMD); if (access == BYTE && addr & 1) break; - sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o Status=%06o\n", rp_unit, uptr->CMD); + rp_ie &= ~(CS1_IE); + rp_ie |= data & (CS1_IE); + if ((uptr->CMD & CS1_GO) != 0) { + uptr->CMD |= (ER1_RMR << 16); + sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o not ready %02o %06o\n", rp_unit, + addr & 077, data); + return 0; + } rp_ba = ((data << 8) & 0600000) | (rp_ba & 0177777); - rp_ie = data & (CS1_IE); uptr->CMD = data & 076; /* Check if GO bit set */ if ((data & 1) == 0) { @@ -372,6 +375,7 @@ rp_write(t_addr addr, uint16 data, int32 access) { sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o unattached %06o\n", rp_unit, data); return 0; /* No, nop */ } + uba_clr_irq(&rpa_dib); switch (GET_FNC(data)) { case FNC_NOP: break; @@ -403,27 +407,28 @@ rp_write(t_addr addr, uint16 data, int32 access) { break; } - rp_ie |= CS1_GO; + if (GET_FNC(data) >= FNC_XFER) + rp_ie |= CSX_BUSY; + uptr->CMD |= CS1_GO; CLR_BUF(uptr); uptr->DATAPTR = 0; break; case FNC_DCLR: /* drive clear */ - uptr->STATUS &= ~(DS_ATA); - rp_ie &= ~(CS1_GO); + uptr->STATUS &= DS_VV; uptr->DA &= 003400177777; uptr->CCYL &= 0177777; - rp_ie = 0; break; case FNC_PRESET: /* read-in preset */ uptr->DA = 0; uptr->CCYL &= 0177777; /* Fall through */ - - case FNC_RELEASE: /* port release */ case FNC_PACK: /* pack acknowledge */ + uptr->STATUS |= DS_VV; + /* Fall through */ + case FNC_RELEASE: /* port release */ break; default: @@ -431,12 +436,18 @@ rp_write(t_addr addr, uint16 data, int32 access) { uptr->CMD |= (ER1_ILF << 16); } if (GET_FNC(data) >= FNC_XFER) - uptr->STATUS = 0; - if (rp_ie & CS1_GO) + uptr->STATUS &= (DS_VV); + if (uptr->CMD & CS1_GO) sim_activate(uptr, 1000); sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o AStatus=%06o\n", rp_unit, uptr->CMD); break; case 002: /* RPWC - 176702 - word count */ + if ((rp_ie & (CSX_BUSY)) != 0) { + uptr->CMD |= (ER1_RMR << 16); + sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o not ready %02o %06o\n", rp_unit, + addr & 077, data); + return 0; + } if (access == BYTE) { if (addr & 1) data = data | (rp_wc & 0377); @@ -446,6 +457,12 @@ rp_write(t_addr addr, uint16 data, int32 access) { rp_wc = data; break; case 004: /* RPBA - 176704 - base address */ + if ((rp_ie & (CSX_BUSY)) != 0) { + uptr->CMD |= (ER1_RMR << 16); + sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o not ready %02o %06o\n", rp_unit, + addr & 077, data); + return 0; + } if (access == BYTE) { if (addr & 1) data = data | (rp_ba & 0377); @@ -466,6 +483,12 @@ rp_write(t_addr addr, uint16 data, int32 access) { break; case 010: /* RPCS2 - 176710 - Control and Status register 2 */ +// if ((rp_ie & (CSX_BUSY)) != 0) { +// uptr->CMD |= (ER1_RMR << 16); +// sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o not ready %02o %06o\n", rp_unit, +// addr & 077, data); +// return 0; +// } if (access == BYTE) { if (addr & 1) data = data | (rp_cs2 & 0377); @@ -549,13 +572,21 @@ rp_read(t_addr addr, uint16 *data, int32 access) { /* RPDB - 176722 - data buffer */ switch(addr & 076) { case 000: /* RPC - 176700 - control */ - temp = uptr->CMD & 076; - temp |= (uint16)rp_ie; + temp = uptr->CMD & 077; + temp |= (uint16)(rp_ie & (CS1_IE)); temp |= (rp_ba & 0600000) >> 8; - if ((rp_ie & CS1_GO) == 0 && (uptr->STATUS & DS_PIP) == 0) + if ((rp_ie & CSX_BUSY) == 0) temp |= CS1_RDY; - if (uptr->flags & UNIT_ATT) { + if (uptr->flags & UNIT_ATT) temp |= CS1_DVA; + if (rp_cs2 & (CS2_MDPE|CS2_MXF|CS2_PGE|CS2_NEM|CS2_NED|CS2_PE|CS2_WCE|CS2_DLT)) + temp |= CS1_TRE|CS1_SC; + for (i = 0; i < 8; i++) { + UNIT *u = &rpa_unit[i]; + if (u->STATUS & DS_ATA) { + temp |= CS1_SC; + break; + } } break; case 002: /* RPWC - 176702 - word count */ @@ -579,10 +610,10 @@ rp_read(t_addr addr, uint16 *data, int32 access) { if ((uptr->flags & UNIT_DIS) == 0) temp |= DS_DPR; if ((uptr->flags & UNIT_ATT) != 0) - temp |= DS_VV|DS_MOL; + temp |= DS_MOL; if ((uptr->flags & UNIT_WLK) != 0) temp |= DS_WRL; - if ((rp_ie & CS1_GO) == 0 && (uptr->STATUS & DS_PIP) == 0) + if ((uptr->CMD & CS1_GO) == 0) temp |= DS_DRY; break; case 014: /* RPER1 - 176714 - error status 1 */ @@ -639,11 +670,19 @@ rp_read(t_addr addr, uint16 *data, int32 access) { return 0; } +uint16 +rp_vect(struct pdp_dib *dibp) +{ + rp_ie &= ~CS1_IE; + return dibp->uba_vect; +} /* Set the attention flag for a unit */ -void rp_setattn(int unit) +void rp_setattn(UNIT *uptr) { - if (rp_ie) + uptr->STATUS |= DS_ATA; + uptr->CMD &= ~CS1_GO; + if ((rp_ie & CSX_BUSY) == 0 && (rp_ie & CS1_IE) != 0) uba_set_irq(&rpa_dib); } @@ -664,12 +703,13 @@ t_stat rp_svc (UNIT *uptr) if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ uptr->CMD |= (ER1_UNS << 16); /* set drive error */ uptr->STATUS |= DS_ATA; - rp_ie &= ~(CS1_GO); + rp_ie &= ~(CSX_BUSY); + uptr->CMD &= ~CS1_GO; if (GET_FNC(uptr->CMD) >= FNC_XFER) { /* xfr? set done */ - if (rp_ie) + if ((rp_ie & CSX_BUSY) == 0 && (rp_ie & CS1_IE) != 0) uba_set_irq(&rpa_dib); } else { - rp_setattn(unit); + rp_setattn(uptr); } return (SCPE_OK); } @@ -679,10 +719,10 @@ t_stat rp_svc (UNIT *uptr) sim_debug(DEBUG_DETAIL, dptr, "%s%o seek %d %d\n", dptr->name, unit, cyl, uptr->CCYL); if (cyl >= rp_drv_tab[dtype].cyl) { uptr->STATUS &= ~DS_PIP; - uptr->STATUS |= DS_ATA; + // uptr->STATUS |= DS_ATA; uptr->CMD |= (ER1_IAE << 16); - rp_ie &= ~CS1_GO; - rp_setattn(unit); +// uptr->CMD &= ~CS1_GO; + rp_setattn(uptr); } diff = cyl - (uptr->CCYL & 01777); if (diff < 0) { @@ -733,9 +773,7 @@ t_stat rp_svc (UNIT *uptr) if (GET_SC(uptr->DA) >= rp_drv_tab[dtype].sect || GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf) uptr->CMD |= (ER1_IAE << 16); - uptr->STATUS |= DS_ATA; - rp_ie &= ~CS1_GO; - rp_setattn(unit); + rp_setattn(uptr); sim_debug(DEBUG_DETAIL, dptr, "%s%o seekdone %d %o\n", dptr->name, unit, cyl, uptr->CMD); break; @@ -743,9 +781,7 @@ t_stat rp_svc (UNIT *uptr) if (GET_SC(uptr->DA) >= rp_drv_tab[dtype].sect || GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf) uptr->CMD |= (ER1_IAE << 16); - uptr->STATUS |= DS_ATA; - rp_ie &= ~CS1_GO; - rp_setattn(unit); + rp_setattn( uptr); sim_debug(DEBUG_DETAIL, dptr, "%s%o searchdone %d %o\n", dptr->name, unit, cyl, uptr->CMD); break; @@ -757,8 +793,9 @@ t_stat rp_svc (UNIT *uptr) GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf) { uptr->CMD |= (ER1_IAE << 16); uptr->STATUS |= DS_ATA; - rp_ie &= ~CS1_GO; - if (uptr->CMD & CS1_IE) + rp_ie &= ~(CSX_BUSY); + uptr->CMD &= ~CS1_GO; + if (rp_ie & CS1_IE) uba_set_irq(&rpa_dib); sim_debug(DEBUG_DETAIL, dptr, "%s%o readx done\n", dptr->name, unit); return SCPE_OK; @@ -832,8 +869,9 @@ t_stat rp_svc (UNIT *uptr) } rd_end: sim_debug(DEBUG_DETAIL, dptr, "%s%o read done\n", dptr->name, unit); - rp_ie &= ~CS1_GO; - if (rp_ie) + uptr->CMD &= ~CS1_GO; + rp_ie &= ~(CSX_BUSY); + if (rp_ie & CS1_IE) uba_set_irq(&rpa_dib); return SCPE_OK; @@ -843,8 +881,10 @@ rd_end: GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf) { uptr->CMD |= (ER1_IAE << 16); uptr->STATUS |= DS_ATA; - rp_ie &= ~CS1_GO; - uba_set_irq(&rpa_dib); + rp_ie &= ~(CSX_BUSY); + uptr->CMD &= ~CS1_GO; + if (rp_ie & CS1_IE) + uba_set_irq(&rpa_dib); sim_debug(DEBUG_DETAIL, dptr, "%s%o writex done\n", dptr->name, unit); return SCPE_OK; } @@ -917,8 +957,9 @@ wr_done: } else { sim_debug(DEBUG_DETAIL, dptr, "RP%o write done\n", unit); uptr->STATUS &= ~DS_PIP; - rp_ie &= ~CS1_GO; - if (rp_ie) + rp_ie &= ~(CSX_BUSY); + uptr->CMD &= ~CS1_GO; + if (rp_ie & CS1_IE) uba_set_irq(&rpa_dib); } return SCPE_OK; @@ -947,11 +988,13 @@ rp_reset(DEVICE * dptr) int i; rp_ba = 0; rp_wc = 0177777; + rp_ie = 0; rp_cs2 = CS2_IR; for (i = 0; i < 8; i++) { UNIT *u = &rpa_unit[i]; - u->STATUS = 0; + u->STATUS &= DS_VV; } + uba_clr_irq(&rpa_dib); sim_debug(DEBUG_DETAIL, dptr, "RP reset done\n"); return SCPE_OK; } @@ -968,6 +1011,10 @@ rp_boot(int32 unit_num, DEVICE * rptr) uint64 len; int i; int da; + t_stat r; + + if ((r = rp_reset(dptr) )!= SCPE_OK) + return r; /* Read in block 1 and see if it is a home block */ disk_read(uptr, &rp_buf[0], 1, RP_NUMWD); if (rp_buf[0] != 0505755000000LL) { @@ -1043,14 +1090,12 @@ t_stat rp_attach (UNIT *uptr, CONST char *cptr) if (rptr == 0) return SCPE_OK; dib = (DIB *) rptr->ctxt; -// if (uptr->flags & UNIT_WLK) - // uptr->CMD |= DS_WRL; if (sim_switches & SIM_SW_REST) return SCPE_OK; uptr->DA = 0; -// uptr->CMD &= ~DS_VV; - // uptr->CMD |= DS_DPR|DS_MOL|DS_DRY; - rp_setattn(uptr - &rpa_unit[0]); + uptr->STATUS = DS_ATA; + if ((rp_ie & CSX_BUSY) == 0 && (rp_ie & CS1_IE) != 0) + uba_set_irq(&rpa_dib); return SCPE_OK; } @@ -1062,7 +1107,7 @@ t_stat rp_detach (UNIT *uptr) return SCPE_OK; if (sim_is_active (uptr)) /* unit active? */ sim_cancel (uptr); /* cancel operation */ -// uptr->CMD &= ~(DS_VV|DS_WRL|DS_DPR|DS_DRY); + uptr->STATUS = 0; return disk_detach (uptr); } diff --git a/PDP10/ks10_tu.c b/PDP10/ks10_tu.c index 3b534c4..1544c6e 100644 --- a/PDP10/ks10_tu.c +++ b/PDP10/ks10_tu.c @@ -73,6 +73,8 @@ #define CS1_TRE 0040000 /* */ #define CS1_SC 0100000 /* */ +#define CSX_BUSY 02 /* RH11 is doing a transfer */ + /* TUWC - 772442 - word count. */ /* TUBA - 772444 - bus address */ @@ -197,6 +199,7 @@ static uint64 tu_boot_buffer; int tu_write(t_addr addr, uint16 data, int32 access); int tu_read(t_addr addr, uint16 *data, int32 access); +uint16 tu_vect(struct pdp_dib *dibp); void tu_rst(DEVICE *dptr); t_stat tu_srv(UNIT *); t_stat tu_boot(int32, DEVICE *); @@ -217,7 +220,7 @@ UNIT tua_unit[] = { { UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) }, }; -DIB tua_dib = {0772440, 037, 0224, 6, 3, &tu_read, &tu_write, 0}; +DIB tua_dib = {0772440, 037, 0224, 6, 3, &tu_read, &tu_write, &tu_vect, 0}; MTAB tu_mod[] = { {MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL}, @@ -277,69 +280,86 @@ tu_write(t_addr addr, uint16 data, int32 access) { if (access == BYTE && addr & 1) return 0; + tu_ie &= ~CS1_IE; + tu_ie |= data & CS1_IE; tu_ba = ((data << 8) & 0600000) | (tu_ba & 0177777); - tu_ie = data & CS1_IE; uptr->CMD = data & 076; - if ((data & 01) != 0 && (uptr->flags & UNIT_ATT) != 0) { - switch (GET_FNC(data)) { - case FNC_NOP: - break; - - case FNC_PRESET: /* read-in preset */ - case FNC_READ: /* read */ - case FNC_READREV: /* read w/ headers */ - tu_frame = 0; - tu_tcr |= TC_FCS; - /* Fall through */ - - case FNC_WRITE: /* write */ - case FNC_SPACEF: /* Space forward */ - case FNC_SPACEB: /* Space backward */ - if ((tu_tcr & TC_FCS) == 0) { - uptr->STATUS |= ER1_NEF << 16; - break; - } - /* Fall through */ - - case FNC_ERASE: /* Erase gap */ - case FNC_WTM: /* Write tape mark */ - case FNC_WCHK: /* write check */ - case FNC_REWIND: /* rewind */ - case FNC_UNLOAD: /* unload */ - case FNC_WCHKREV: /* write w/ headers */ - uptr->CMD |= CS1_GO; - uptr->STATUS = DS_PIP; - tu_attn = 0; - for (i = 0; i < NUM_UNITS_TU; i++) { - if (tua_unit[i].STATUS & DS_ATA) - tu_attn = 1; - } - CLR_BUF(uptr); - uptr->DATAPTR = 0; - sim_activate(uptr, 100); - break; - - case FNC_DCLR: /* drive clear */ - uptr->CMD &= ~(CS1_GO); - uptr->STATUS = 0; - tu_ie = 0; - tu_attn = 0; - for (i = 0; i < NUM_UNITS_TU; i++) { - if (tua_unit[i].STATUS & DS_ATA) - tu_attn = 1; - } - break; - default: - uptr->STATUS |= (ER1_ILF << 16) | DS_ATA; - tu_attn = 1; - } - sim_debug(DEBUG_DETAIL, &tua_dev, "TU %o AStatus=%06o\n", unit, uptr->CMD); - if (tu_attn && tu_ie) - uba_set_irq(&tua_dib); + if ((data & 1) == 0) { + sim_debug(DEBUG_DETAIL, &tua_dev, "RP%o no go %06o\n", unit, data); + return 0; /* No, nop */ } + if ((uptr->flags & UNIT_ATT) == 0) { + sim_debug(DEBUG_DETAIL, &tua_dev, "RP%o unattached %06o\n", unit, data); + return 0; /* No, nop */ + } + + uba_clr_irq(&tua_dib); + switch (GET_FNC(data)) { + case FNC_NOP: + break; + + case FNC_PRESET: /* read-in preset */ + case FNC_READ: /* read */ + case FNC_READREV: /* read w/ headers */ + tu_frame = 0; + tu_tcr |= TC_FCS; + /* Fall through */ + + case FNC_WRITE: /* write */ + case FNC_SPACEF: /* Space forward */ + case FNC_SPACEB: /* Space backward */ + if ((tu_tcr & TC_FCS) == 0) { + uptr->STATUS |= ER1_NEF << 16; + break; + } + /* Fall through */ + + case FNC_ERASE: /* Erase gap */ + case FNC_WTM: /* Write tape mark */ + case FNC_WCHK: /* write check */ + case FNC_REWIND: /* rewind */ + case FNC_UNLOAD: /* unload */ + case FNC_WCHKREV: /* write w/ headers */ + uptr->CMD |= CS1_GO; + uptr->STATUS = DS_PIP; + tu_attn = 0; + for (i = 0; i < NUM_UNITS_TU; i++) { + if (tua_unit[i].STATUS & DS_ATA) + tu_attn = 1; + } + CLR_BUF(uptr); + uptr->DATAPTR = 0; + if (GET_FNC(data) >= FNC_XFER) + tu_ie |= CSX_BUSY; + sim_activate(uptr, 100); + break; + + case FNC_DCLR: /* drive clear */ + uptr->CMD &= ~(CS1_GO); + uptr->STATUS = 0; + tu_ie = 0; + tu_attn = 0; + for (i = 0; i < NUM_UNITS_TU; i++) { + if (tua_unit[i].STATUS & DS_ATA) + tu_attn = 1; + } + break; + default: + uptr->STATUS |= (ER1_ILF << 16) | DS_ATA; + tu_attn = 1; + } + sim_debug(DEBUG_DETAIL, &tua_dev, "TU %o AStatus=%06o\n", unit, uptr->CMD); + if (tu_attn && tu_ie) + uba_set_irq(&tua_dib); break; case 002: /* TUWC - 172442 - word count */ + if ((tu_ie & (CSX_BUSY)) != 0) { + uptr->CMD |= (ER1_RMR << 16); + sim_debug(DEBUG_DETAIL, &tua_dev, "RP%o not ready %02o %06o\n", unit, + addr & 077, data); + return 0; + } if (access == BYTE) { if (addr & 1) data = data | (tu_wc & 0377); @@ -349,6 +369,12 @@ tu_write(t_addr addr, uint16 data, int32 access) { tu_wc = data; break; case 004: /* TUBA - 172444 - base address */ + if ((tu_ie & (CSX_BUSY)) != 0) { + uptr->CMD |= (ER1_RMR << 16); + sim_debug(DEBUG_DETAIL, &tua_dev, "RP%o not ready %02o %06o\n", unit, + addr & 077, data); + return 0; + } if (access == BYTE) { if (addr & 1) data = data | (tu_ba & 0377); @@ -364,6 +390,12 @@ tu_write(t_addr addr, uint16 data, int32 access) { break; case 010: /* 772450 CS2 */ +// if ((tu_ie & (CSX_BUSY)) != 0) { +// uptr->CMD |= (ER1_RMR << 16); +// sim_debug(DEBUG_DETAIL, &tua_dev, "RP%o not ready %02o %06o\n", unit, +// addr & 077, data); +// return 0; +// } if (access == BYTE) { if (addr & 1) data = data | tu_cs2; @@ -420,17 +452,17 @@ tu_read(t_addr addr, uint16 *data, int32 access) switch(addr & 036) { case 000: /* 772440 control */ - temp = uptr->CMD & 076; + temp = uptr->CMD & 077; if ((tu_cs2 & 07) == 0) temp |= CS1_DVA; - temp |= (uint16)tu_ie; + temp |= (uint16)(tu_ie & CS1_IE); temp |= (tu_ba & 0600000) >> 8; - if (uptr->CMD & CS1_GO) - temp |= CS1_GO; - else if ((uptr->STATUS & DS_PIP) == 0) + if ((tu_ie & CSX_BUSY) == 0) temp |= CS1_RDY; if ((tu_cs2 & 07) != 0 || (uptr->STATUS & (ER1_RMR << 16)) != 0) temp |= CS1_TRE; + if (tu_cs2 & (CS2_MDPE|CS2_MXF|CS2_PGE|CS2_NEM|CS2_NED|CS2_PE|CS2_WCE|CS2_DLT)) + temp |= CS1_TRE; if (tu_attn || temp & CS1_TRE) temp |= CS1_SC; break; @@ -511,6 +543,12 @@ tu_read(t_addr addr, uint16 *data, int32 access) return 0; } +uint16 +tu_vect(struct pdp_dib *dibp) +{ + tu_ie &= ~CS1_IE; + return dibp->uba_vect; +} /* Map simH errors into machine errors */ void tu_error(UNIT * uptr, t_stat r) @@ -553,7 +591,7 @@ void tu_error(UNIT * uptr, t_stat r) uptr->CMD &= ~(CS1_GO); uptr->STATUS &= ~DS_PIP; sim_debug(DEBUG_EXP, dptr, "Setting status %d\n", r); - if (tu_ie) + if ((tu_ie & CSX_BUSY) == 0 && (tu_ie & CS1_IE) != 0) uba_set_irq(&tua_dib); } @@ -593,7 +631,7 @@ t_stat tu_srv(UNIT * uptr) uptr->STATUS |= DS_SSC|DS_ATA; uptr->STATUS &= ~DS_PIP; tu_attn = 1; - if (tu_ie) + if ((tu_ie & CSX_BUSY) == 0 && (tu_ie & CS1_IE) != 0) uba_set_irq(&tua_dib); (void)sim_tape_rewind(uptr); } @@ -613,6 +651,7 @@ t_stat tu_srv(UNIT * uptr) if ((r = sim_tape_rdrecr(uptr, &tu_buf[0], &reclen, TU_NUMFR)) != MTSE_OK) { sim_debug(DEBUG_DETAIL, dptr, "%s%o read error %d\n", dptr->name, unit, r); + tu_ie &= ~(CSX_BUSY); if (r == MTSE_BOT) uptr->STATUS |= ER1_NEF << 16; tu_error(uptr, r); @@ -640,6 +679,7 @@ t_stat tu_srv(UNIT * uptr) uptr->CPOS = cc_max; if (GET_FNC(uptr->CMD) == FNC_READREV && uba_write_npr(tu_ba, tua_dib.uba_ctl, tu_cbuf) == 0) { + tu_ie &= ~(CSX_BUSY); tu_error(uptr, MTSE_OK); return SCPE_OK; } @@ -650,6 +690,7 @@ t_stat tu_srv(UNIT * uptr) tu_ba -= 4; tu_wc = (tu_wc + 2) & 0177777; if (tu_wc == 0) { + tu_ie &= ~(CSX_BUSY); tu_error(uptr, MTSE_OK); return SCPE_OK; } @@ -657,6 +698,7 @@ t_stat tu_srv(UNIT * uptr) } else { if (uptr->CPOS != cc_max) uba_write_npr(tu_ba, tua_dib.uba_ctl, tu_cbuf); + tu_ie &= ~(CSX_BUSY); tu_error(uptr, MTSE_OK); return SCPE_OK; } @@ -668,6 +710,7 @@ t_stat tu_srv(UNIT * uptr) if ((r = sim_tape_rdrecf(uptr, &tu_buf[0], &reclen, TU_NUMFR)) != MTSE_OK) { sim_debug(DEBUG_DETAIL, dptr, "%s%o read error %d\n", dptr->name, unit, r); + tu_ie &= ~(CSX_BUSY); if (r == MTSE_TMK) uptr->STATUS |= ER1_FCE << 16; tu_error(uptr, r); @@ -697,6 +740,7 @@ t_stat tu_srv(UNIT * uptr) uba_write_npr(tu_ba, tua_dib.uba_ctl, tu_cbuf) == 0) { if ((uint32)uptr->DATAPTR == uptr->hwmark) goto rd_end; + tu_ie &= ~(CSX_BUSY); tu_error(uptr, MTSE_OK); return SCPE_OK; } @@ -718,6 +762,7 @@ t_stat tu_srv(UNIT * uptr) rd_end: if (tu_frame != 0) uptr->STATUS |= ER1_FCE << 16; + tu_ie &= ~(CSX_BUSY); tu_error(uptr, MTSE_OK); return SCPE_OK; } @@ -727,10 +772,12 @@ rd_end: if (BUF_EMPTY(uptr)) { if (tu_frame == 0) { uptr->STATUS |= (ER1_NEF << 16) | DS_ATA; + tu_ie &= ~(CSX_BUSY); tu_error(uptr, MTSE_OK); return SCPE_OK; } if ((uptr->flags & MTUF_WLK) != 0) { + tu_ie &= ~(CSX_BUSY); tu_error(uptr, MTSE_WRP); return SCPE_OK; } @@ -783,6 +830,7 @@ wr_end: dptr->name, unit, reclen, uptr->CPOS); uptr->DATAPTR = 0; uptr->hwmark = 0; + tu_ie &= ~(CSX_BUSY); tu_error(uptr, r); /* Record errors */ return SCPE_OK; } @@ -864,6 +912,7 @@ tu_reset(DEVICE * dptr) for (i = 0; i < NUM_UNITS_TU; i++) { tua_unit[i].STATUS = 0; } + uba_clr_irq(&tua_dib); return SCPE_OK; } @@ -935,7 +984,7 @@ tu_attach(UNIT * uptr, CONST char *file) if (r == SCPE_OK && (sim_switches & SIM_SW_REST) == 0) { uptr->STATUS = DS_ATA|DS_SSC; tu_attn = 1; - if (tu_ie) + if ((tu_ie & CSX_BUSY) == 0 && (tu_ie & CS1_IE) != 0) uba_set_irq(&tua_dib); } return r; diff --git a/PDP10/ks10_uba.c b/PDP10/ks10_uba.c index 18db9ba..ee41003 100644 --- a/PDP10/ks10_uba.c +++ b/PDP10/ks10_uba.c @@ -68,7 +68,22 @@ uba_read(t_addr addr, int ctl, uint64 *data, int access) *data = (uint64)uba_map[ubm][addr & 077]; return 0; } else if ((addr & 077) == 0) { + int pih, pil; *data = (uint64)uba_status[ubm]; + pih = 0200 >> ((uba_status[ubm] >> 3) & 07); + pil = 0200 >> (uba_status[ubm] & 07); + for(i = 0; (dptr = sim_devices[i]) != NULL; i++) { + DIB *dibp = (DIB *) dptr->ctxt; + if (dibp == NULL) + continue; + /* If device is pending on this level save */ + if (dibp->uba_ctl == ctl) { + if ((dibp->uba_irq_pend & pil) != 0) + *data |= UBST_INTL; + if ((dibp->uba_irq_pend & pih) != 0) + *data |= UBST_INTH; + } + } return 0; } else if ((addr & 077) == 1) { *data = 0; @@ -81,11 +96,10 @@ uba_read(t_addr addr, int ctl, uint64 *data, int access) DIB *dibp = (DIB *) dptr->ctxt; if (dibp == NULL) continue; - if (ctl == dibp->uba_ctl && dibp->uba_addr == (addr & (~dibp->uba_mask))) { + if (ctl == dibp->uba_ctl && + dibp->uba_addr == (addr & (~dibp->uba_mask))) { uint16 buf; int r = dibp->rd_io(addr, &buf, access); -// if (access == BYTE && (addr & 1) != 0) - // buf >>= 8; *data = (uint64)buf; return r; } @@ -120,7 +134,8 @@ uba_write(t_addr addr, int ctl, uint64 data, int access) uint32 map = (uint32)(data & 03777) << 9; map |= (uint32)(data & 0740000) << 13; uba_map[ubm][addr & 077] = map; - sim_debug(DEBUG_EXP, &cpu_dev, "Wr MAP %02o %012llo %06o\n\r", addr & 077, data, map); + sim_debug(DEBUG_EXP, &cpu_dev, "Wr MAP %02o %012llo %06o\n\r", + addr & 077, data, map); return 0; } else if ((addr & 077) == 0) { uba_status[ubm] &= (uint32)(074000 ^ data) | 0746000; @@ -232,29 +247,62 @@ uba_set_irq(DIB *dibp) /* Figure out what channel device should IRQ on */ if (dibp->uba_br > 5) { pi = uba_status[ubm] >> 3; - uba_status[ubm] |= UBST_INTH; } else { pi = uba_status[ubm]; - uba_status[ubm] |= UBST_INTL; } /* Save in device temp the irq value */ dibp->uba_irq_pend = 0200 >> (pi & 07); - set_interrupt(dibp->uba_ctl << 2, pi); + set_interrupt(dibp->uba_ctl<<2, pi); } +void +uba_clr_irq(DIB *idev) +{ + DEVICE *dptr; + int ubm = uba_device[idev->uba_ctl]; + int pi; + int i; + int high = 0; + + if (ubm < 0) + return; + /* Figure out what channel device should IRQ on */ + if (idev->uba_br > 5) { + pi = uba_status[ubm] >> 3; + } else { + pi = uba_status[ubm]; + } + /* Save in device temp the irq value */ + idev->uba_irq_pend = 0; + for(i = 0; (dptr = sim_devices[i]) != NULL; i++) { + DIB *dibp = (DIB *) dptr->ctxt; + if (dibp == NULL) + continue; + /* If device is pending on this level save */ + if (dibp->uba_ctl == idev->uba_ctl && + dibp->uba_irq_pend != 0) { + /* At least one, no need to continue */ + return; + } + } + /* Nothing, so clear it */ + clr_interrupt(idev->uba_ctl<<2); +} + + t_addr -uba_get_vect(t_addr addr, int lvl) +uba_get_vect(t_addr addr, int lvl, int *dev, int *new_lvl) { DEVICE *dptr; DIB *idev = NULL; uint64 buffer; uint16 ivect; int i; - int high = 0; int ctl = 17; int pi; int ubm; + *dev = 0; /* Adaptor 0 is special */ /* Look for device */ for(i = 0; (dptr = sim_devices[i]) != NULL; i++) { DIB *dibp = (DIB *) dptr->ctxt; @@ -271,40 +319,32 @@ uba_get_vect(t_addr addr, int lvl) } /* Should have a device */ if (idev != NULL) { + *new_lvl = 0; + *dev = idev->uba_ctl; /* Figure out what pi channel this will interrupt on */ ubm = uba_device[idev->uba_ctl]; - if (idev->uba_br > 5) { - pi = (uba_status[ubm] >> 3) & 07; - high = 1; - uba_status[ubm] &= ~UBST_INTH; - } else { - pi = uba_status[ubm] & 07; - uba_status[ubm] &= ~UBST_INTL; - } /* Clear interrupts */ idev->uba_irq_pend = 0; + /* Fetch vector */ + if (Mem_read_word(0100 | idev->uba_ctl, &buffer, 1)) + return addr; + idev->uba_irq_pend = 0; + ivect = idev->uba_vect; + if (idev->irqv != NULL) + ivect = (idev->irqv)(idev); + addr = (buffer + (ivect >> 2)) & RMASK; /* Any other devices waiting on this PI channel? */ - clr_interrupt(idev->uba_ctl << 2); - for(i = 0; (dptr = sim_devices[i]) != NULL; i++) { + for(pi = i = 0; (dptr = sim_devices[i]) != NULL; i++) { DIB *dibp = (DIB *) dptr->ctxt; if (dibp == NULL) continue; /* If device is pending on this level save */ if (dibp->uba_ctl == idev->uba_ctl && - (dibp->uba_irq_pend & lvl) != 0) { - set_interrupt(idev->uba_ctl << 2, pi); - uba_status[ubm] |= UBST_INTL << high; + dibp->uba_irq_pend != 0) { /* At least one, no need to continue */ - break; + *new_lvl |= dibp->uba_irq_pend; } } - /* Fetch vector */ - if (Mem_read_word(0100 | idev->uba_ctl, &buffer, 1)) - return addr; - ivect = idev->uba_vect; - if (idev->irqv != NULL) - ivect = (idev->irqv)(idev); - addr = (buffer & RMASK) + (idev->uba_vect >> 2); } return addr; } diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 6e84c03..1357ec9 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -280,6 +280,7 @@ int watch_stop; /* Stop at memory watch point */ int maoff = 0; /* Offset for traps */ uint16 dev_irq[128]; /* Pending irq by device */ +uint8 dev_map[128]; /* Map device to irq slot */ t_stat (*dev_tab[128])(uint32 dev, uint64 *data); t_addr (*dev_irqv[128])(uint32 dev, t_addr addr); t_stat rtc_srv(UNIT * uptr); @@ -1074,7 +1075,11 @@ get_quantum() void set_interrupt(int dev, int lvl) { lvl &= 07; if (lvl) { - dev_irq[dev>>2] = 0200 >> lvl; +#if KS + dev_irq[dev>>2] |= 0200 >> lvl; +#else + dev_irq[dev_map[dev>>2]] = 0200 >> lvl; +#endif pi_pending = 1; sim_debug(DEBUG_IRQ, &cpu_dev, "set irq %o %o %03o %03o %03o\n", dev & 0774, lvl, PIE, PIR, PIH); @@ -1085,9 +1090,9 @@ void set_interrupt(int dev, int lvl) { void set_interrupt_mpx(int dev, int lvl, int mpx) { lvl &= 07; if (lvl) { - dev_irq[dev>>2] = 0200 >> lvl; + dev_irq[dev_map[dev>>2]] = 0200 >> lvl; if (lvl == 1 && mpx != 0) - dev_irq[dev>>2] |= mpx << 8; + dev_irq[dev_map[dev>>2]] |= mpx << 8; pi_pending = 1; sim_debug(DEBUG_IRQ, &cpu_dev, "set mpx irq %o %o %o %03o %03o %03o\n", dev & 0774, lvl, mpx, PIE, PIR, PIH); @@ -1099,7 +1104,7 @@ void set_interrupt_mpx(int dev, int lvl, int mpx) { * Clear the interrupt flag for a device */ void clr_interrupt(int dev) { - dev_irq[dev>>2] = 0; + dev_irq[dev_map[dev>>2]] = 0; if (dev > 4) sim_debug(DEBUG_IRQ, &cpu_dev, "clear irq %o\n", dev & 0774); } @@ -1134,7 +1139,7 @@ int check_irq_level() { } /* Scan all devices */ - for(i = lvl = 0; i <= (int)max_dev; i++) + for(i = lvl = 0; i < (int)max_dev; i++) lvl |= dev_irq[i]; if (lvl == 0) pi_pending = 0; @@ -1144,7 +1149,7 @@ int check_irq_level() { if (mpx_enable && cpu_unit[0].flags & UNIT_MPX && (pi_req & 0100) && (PIH & 0100) == 0) { pi_enc = 010; - for(i = lvl = 0; i <= (int)max_dev; i++) { + for(i = lvl = 0; i < (int)max_dev; i++) { if (dev_irq[i] & 0100) { int l = dev_irq[i] >> 8; if (l != 0 && l < pi_enc) @@ -4778,7 +4783,14 @@ st_pi: AB |= eb_ptr; extend = 0; if ((dev_irq[0] & pi_mask) == 0) { - AB = uba_get_vect(AB, pi_mask); + int new_lvl; + int dev; + AB = uba_get_vect(AB, pi_mask, &dev, &new_lvl); + if (dev != 0) { + dev_irq[dev] = new_lvl; + if (new_lvl != 0) + pi_pending = 1; + } sim_debug(DEBUG_IRQ, &cpu_dev, "vect irq %o %06o\n", pi_enc, AB); } Mem_read_nopage(); @@ -4789,11 +4801,11 @@ st_pi: * Scan through the devices and allow KI devices to have first * hit at a given level. */ - for (f = 0; f <= (int)max_dev; f++) { - if (dev_irqv[f] != 0 && dev_irq[f] & pi_mask) { + for (f = 0; f < 128; f++) { + if (dev_irqv[f] != 0 && dev_irq[dev_map[f]] & pi_mask) { AB = dev_irqv[f](f << 2, AB); sim_debug(DEBUG_IRQ, &cpu_dev, "vect irq %o %03o %06o\n", - pi_enc, dev_irq[f], AB); + pi_enc, dev_irq[dev_map[f]], AB); break; } } @@ -9688,7 +9700,7 @@ test_op: xct_flag = 0; break; - case 010: /* TIOE */ + case 010: /* TIOE , ITS RDIOI */ #if KS_ITS if (QITS) { ctl = 3; @@ -9707,7 +9719,7 @@ io_fault: PC = (PC + 1) & RMASK; break; - case 011: /* TION */ + case 011: /* TION, ITS RDIOQ */ #if KS_ITS if (QITS) { ctl = 1; @@ -9751,7 +9763,7 @@ its_wr: goto io_fault; break; - case 014: /* BSIO */ + case 014: /* BSIO, ITS WRIOI */ #if KS_ITS if (QITS) { ctl = 3; @@ -9766,7 +9778,7 @@ its_wr: goto io_fault; break; - case 015: /* BCIO */ + case 015: /* BCIO, ITS WRIOQ */ #if KS_ITS if (QITS) { ctl = 1; @@ -9782,6 +9794,12 @@ its_wr: break; case 020: /* TIOEB */ +#if KS_ITS + if (QITS) { + ctl = 3; + goto its_rdb; + } +#endif BR = get_reg(AC); if (uba_read(AB, ctl, &MB, BYTE)) goto io_fault; @@ -9790,6 +9808,12 @@ its_wr: break; case 021: /* TIONB */ +#if KS_ITS + if (QITS) { + ctl = 1; + goto its_rdb; + } +#endif BR = get_reg(AC); if (uba_read(AB, ctl, &MB, BYTE)) goto io_fault; @@ -9798,18 +9822,42 @@ its_wr: break; case 022: /* RDIOB */ +#if KS_ITS + if (QITS) { + if (Mem_read(pi_cycle, 0, 0)) + goto last; + AB = MB & RMASK; + ctl = (int)((MB >> 18) & 017); + } +its_rdb: +#endif if (uba_read(AB, ctl, &AR, BYTE)) goto io_fault; i_flags = SAC; break; case 023: /* WRIOB */ +#if KS_ITS + if (QITS) { + if (Mem_read(pi_cycle, 0, 0)) + goto last; + AB = MB & RMASK; + ctl = (int)((MB >> 18) & 017); + } +its_wrb: +#endif MB = get_reg(AC); if (uba_write(AB, ctl, MB, BYTE)) goto io_fault; break; case 024: /* BSIOB */ +#if KS_ITS + if (QITS) { + ctl = 3; + goto its_wrb; + } +#endif BR = get_reg(AC); if (uba_read(AB, ctl, &MB, BYTE)) goto io_fault; @@ -9819,6 +9867,12 @@ its_wr: break; case 025: /* BCIOB */ +#if KS_ITS + if (QITS) { + ctl = 1; + goto its_wrb; + } +#endif BR = get_reg(AC); if (uba_read(AB, ctl, &MB, BYTE)) goto io_fault; @@ -11749,6 +11803,7 @@ max_dev = 16; #endif for(i=0; i < 128; dev_irq[i++] = 0); +for(i=0; i < 128; dev_map[i++] = 0); sim_brk_types = SWMASK('E') | SWMASK('W') | SWMASK('R'); sim_brk_dflt = SWMASK ('E'); sim_clock_precalibrate_commands = pdp10_clock_precalibrate_commands; @@ -11882,7 +11937,6 @@ t_bool build_dev_tab (void) /* Set trap offset based on MAOFF flag */ maoff = (cpu_unit[0].flags & UNIT_MAOFF)? 0100 : 0; - max_dev = 2; #if KA /* Set up memory access routines based on current CPU type. */ @@ -11914,11 +11968,13 @@ t_bool build_dev_tab (void) for (i = 0; i < 128; i++) { dev_tab[i] = &null_dev; dev_irqv[i] = NULL; + dev_map[i] = 0; } /* Set up basic devices. */ dev_tab[0] = &dev_apr; dev_tab[1] = &dev_pi; + max_dev = 2; #if KI | KL dev_tab[2] = &dev_pag; max_dev++; @@ -11927,13 +11983,16 @@ t_bool build_dev_tab (void) dev_tab[4] = &dev_tim; dev_irqv[4] = &tim_irq; dev_tab[5] = &dev_mtr; - max_dev+=4; + max_dev+=3; #endif #endif + for (i = 0; i < max_dev; i++) { + dev_map[i] = i; + } #if BBN if (QBBN) { dev_tab[024>>2] = &dev_pag; - max_dev = 024>>2; + dev_map[024>>2] = max_dev++; } #endif @@ -11970,13 +12029,12 @@ t_bool build_dev_tab (void) #endif } dev_tab[(d >> 2)] = dibp->io; + dev_map[(d >> 2)] = max_dev++; dev_irqv[(d >> 2)] = dibp->irq; rh[rh_idx].dev_num = d; rh[rh_idx].dev = dptr; rh[rh_idx].rh = dibp->rh; dibp->rh->devnum = d; - if ((d >> 2) > max_dev) - max_dev = d >> 2; rh_idx++; } } @@ -11998,9 +12056,8 @@ t_bool build_dev_tab (void) return TRUE; } dev_tab[(d >> 2) + j] = dibp->io; /* fill */ + dev_map[(d >> 2) + j] = max_dev++; dev_irqv[(d >> 2) + j] = dibp->irq; - if (((d >> 2) + j)> max_dev) - max_dev = (d >> 2) + j; } } } diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index 10cbf41..f7e440b 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -528,7 +528,7 @@ struct pdp_dib { uint16 uba_ctl; /* Unibus controller number */ t_stat (*rd_io)(t_addr addr, uint16 *data, int32 access); t_stat (*wr_io)(t_addr addr, uint16 data, int32 access); - uint8 (*irqv)(struct pdp_dib *dibp); + uint16 (*irqv)(struct pdp_dib *dibp); uint8 uba_irq_pend; /* Device has pending */ }; typedef struct pdp_dib DIB; @@ -549,7 +549,8 @@ int uba_write_npr_byte(t_addr addr, uint16 ctl, uint16 data); int uba_read_npr_word(t_addr addr, uint16 ctl, uint16 *data); int uba_write_npr_word(t_addr addr, uint16 ctl, uint16 data); void uba_set_irq(DIB *dibp); -t_addr uba_get_vect(t_addr addr, int lvl); +void uba_clr_irq(DIB *dibp); +t_addr uba_get_vect(t_addr addr, int lvl, int *dev, int *new_lvl); t_stat uba_set_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat uba_show_addr (FILE *st, UNIT *uptr, int32 val, CONST void *desc);