From 3f7e473b793cd3200babe1f688569759f2fc5e2b Mon Sep 17 00:00:00 2001 From: Seth Morabito Date: Wed, 22 Aug 2018 17:13:48 -0700 Subject: [PATCH] 3b2: Fix for erratic CONTTY behavior --- 3B2/3b2_defs.h | 7 ++++++ 3B2/3b2_dmac.c | 4 ++-- 3B2/3b2_if.c | 7 ------ 3B2/3b2_iu.c | 60 +++++++++++++++++++++++++++++++++++++++++-------- 3B2/3b2_iu.h | 3 ++- 3B2/3b2_ports.c | 5 ----- 6 files changed, 62 insertions(+), 24 deletions(-) diff --git a/3B2/3b2_defs.h b/3B2/3b2_defs.h index 343fe13f..c51e3f19 100644 --- a/3B2/3b2_defs.h +++ b/3B2/3b2_defs.h @@ -50,6 +50,13 @@ noret __libc_longjmp (jmp_buf buf, int val); #define longjmp __libc_longjmp #endif +#ifndef MAX +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif +#ifndef MIN +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +#endif + /* -t flag: Translate a virtual address */ #define EX_T_FLAG 1 << 19 /* -v flag for examine routine */ diff --git a/3B2/3b2_dmac.c b/3B2/3b2_dmac.c index bf84ca8d..446ae34d 100644 --- a/3B2/3b2_dmac.c +++ b/3B2/3b2_dmac.c @@ -55,8 +55,8 @@ DEVICE dmac_dev = { dmac_dma_handler device_dma_handlers[] = { {DMA_ID_CHAN, IDBASE+ID_DATA_REG, &id_drq, dmac_generic_dma, id_after_dma}, {DMA_IF_CHAN, IFBASE+IF_DATA_REG, &if_state.drq, dmac_generic_dma, if_after_dma}, - {DMA_IUA_CHAN, IUBASE+IUA_DATA_REG, &iu_console.drq, iu_dma, NULL}, - {DMA_IUB_CHAN, IUBASE+IUB_DATA_REG, &iu_contty.drq, iu_dma, NULL}, + {DMA_IUA_CHAN, IUBASE+IUA_DATA_REG, &iu_console.drq, iu_dma_console, NULL}, + {DMA_IUB_CHAN, IUBASE+IUB_DATA_REG, &iu_contty.drq, iu_dma_contty, NULL}, {0, 0, NULL, NULL, NULL } }; diff --git a/3B2/3b2_if.c b/3B2/3b2_if.c index 5765a738..3fccd5bb 100644 --- a/3B2/3b2_if.c +++ b/3B2/3b2_if.c @@ -36,13 +36,6 @@ static SIM_INLINE void if_clear_irq(); static SIM_INLINE void if_cancel_pending_irq(); static SIM_INLINE uint32 if_buf_offset(); -#ifndef MAX -#define MAX(x,y) ((x) > (y) ? (x) : (y)) -#endif -#ifndef MIN -#define MIN(x,y) ((x) < (y) ? (x) : (y)) -#endif - /* * Disk Format: * ------------ diff --git a/3B2/3b2_iu.c b/3B2/3b2_iu.c index c50e679a..27982143 100644 --- a/3B2/3b2_iu.c +++ b/3B2/3b2_iu.c @@ -426,7 +426,7 @@ t_stat iu_svc_tto(UNIT *uptr) { /* If there's more DMA to do, do it */ if (iu_console.dma && ((dma_state.mask >> DMA_IUA_CHAN) & 0x1) == 0) { - iu_dma(DMA_IUA_CHAN, IUBASE+IUA_DATA_REG); + iu_dma_console(DMA_IUA_CHAN, IUBASE+IUA_DATA_REG); } else { /* The buffer is now empty, we've transmitted, so set TXR */ iu_console.stat |= STS_TXR; @@ -492,9 +492,9 @@ t_stat iu_svc_contty_xmt(UNIT *uptr) tmxr_poll_tx(&contty_desc); + /* If there's more DMA to do, do it */ if (chan->wcount_c >= 0) { - /* More DMA to do */ - iu_dma(DMA_IUB_CHAN, IUBASE+IUB_DATA_REG); + iu_dma_contty(DMA_IUB_CHAN, IUBASE+IUB_DATA_REG); } else { /* The buffer is now empty, we've transmitted, so set TXR */ iu_contty.stat |= STS_TXR; @@ -911,14 +911,14 @@ static SIM_INLINE void iu_w_cmd(uint8 portno, uint8 cmd) /* * Initiate DMA transfer or continue one already in progress. */ -void iu_dma(uint8 channel, uint32 service_address) +void iu_dma_console(uint8 channel, uint32 service_address) { uint8 data; uint32 addr; t_stat status = SCPE_OK; dma_channel *chan = &dma_state.channels[channel]; - UNIT *uptr = (channel == DMA_IUA_CHAN) ? &tto_unit : contty_xmt_unit; - IU_PORT *port = (channel == DMA_IUA_CHAN) ? &iu_console : &iu_contty; + UNIT *uptr = &tto_unit; + IU_PORT *port = &iu_console; /* Immediate acknowledge of DMA */ port->drq = FALSE; @@ -936,9 +936,6 @@ void iu_dma(uint8 channel, uint32 service_address) if (status == SCPE_OK) { chan->ptr++; chan->wcount_c--; - } else if (status == SCPE_LOST) { - chan->ptr = 0; - chan->wcount_c = -1; } sim_activate_abs(uptr, uptr->wait); @@ -956,3 +953,48 @@ void iu_dma(uint8 channel, uint32 service_address) dma_state.status |= (1 << channel); csr_data |= CSRDMA; } + +void iu_dma_contty(uint8 channel, uint32 service_address) +{ + uint8 data; + uint32 addr; + t_stat status = SCPE_OK; + dma_channel *chan = &dma_state.channels[channel]; + UNIT *uptr = contty_xmt_unit; + IU_PORT *port = &iu_contty; + uint32 wait = 0x7fffffff; + + /* Immediate acknowledge of DMA */ + port->drq = FALSE; + + if (!port->dma) { + /* Set DMA transfer type */ + port->dma = 1u << ((dma_state.mode >> 2) & 0xf); + } + + if (port->dma == DMA_READ) { + addr = dma_address(channel, chan->ptr, TRUE); + chan->addr_c = chan->addr + chan->ptr + 1; + data = pread_b(addr); + status = iu_tx(channel - 2, data); + if (status == SCPE_OK) { + wait = MIN(wait, contty_ldsc[0].txdeltausecs); + chan->ptr++; + chan->wcount_c--; + } + + tmxr_activate_after(uptr, wait); + + if (chan->wcount_c >= 0) { + /* Return early so we don't finish DMA */ + return; + } + } + + /* Done with DMA */ + port->dma = DMA_NONE; + + dma_state.mask |= (1 << channel); + dma_state.status |= (1 << channel); + csr_data |= CSRDMA; +} diff --git a/3B2/3b2_iu.h b/3B2/3b2_iu.h index d3004fd5..8ac9150a 100644 --- a/3B2/3b2_iu.h +++ b/3B2/3b2_iu.h @@ -210,6 +210,7 @@ void iua_drq_handled(); void iub_drq_handled(); void iu_txrdy_a_irq(); void iu_txrdy_b_irq(); -void iu_dma(uint8 channel, uint32 service_address); +void iu_dma_console(uint8 channel, uint32 service_address); +void iu_dma_contty(uint8 channel, uint32 service_address); #endif diff --git a/3B2/3b2_ports.c b/3B2/3b2_ports.c index 33f7e7a8..651793d5 100644 --- a/3B2/3b2_ports.c +++ b/3B2/3b2_ports.c @@ -74,11 +74,6 @@ extern UNIT cio_unit; * */ - -#ifndef MIN -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#endif - #define PPQESIZE 12 #define DELAY_ASYNC 25 #define DELAY_DLM 100