From a00f0592dc5460fbbeebdbc413755dfc23c453c8 Mon Sep 17 00:00:00 2001 From: Josh Dersch Date: Tue, 7 May 2019 19:03:49 +0200 Subject: [PATCH] Added small workaround for (possible) bug in VMS secondary bootstrap; improved reset behavior. 4.3bsd still panics during uda bringup. --- 10.01_base/2_src/arm/unibusadapter.cpp | 59 ++++++++++++++------------ 10.01_base/2_src/arm/unibusadapter.hpp | 1 + 10.02_devices/2_src/mscp_server.cpp | 11 +++-- 10.02_devices/2_src/uda.cpp | 13 +++--- 4 files changed, 47 insertions(+), 37 deletions(-) diff --git a/10.01_base/2_src/arm/unibusadapter.cpp b/10.01_base/2_src/arm/unibusadapter.cpp index 7d62e9d..563f31b 100644 --- a/10.01_base/2_src/arm/unibusadapter.cpp +++ b/10.01_base/2_src/arm/unibusadapter.cpp @@ -175,13 +175,9 @@ void unibusadapter_c::worker_init_event() { device->on_init_changed(); } - INFO("clearing due to INIT empty %d", _irqRequests.empty()); // Clear bus request queues - pthread_mutex_lock(&_busWorker_mutex); - while (!_dmaRequests.empty()) _dmaRequests.pop(); - while (!_irqRequests.empty()) _irqRequests.pop(); - pthread_mutex_unlock(&_busWorker_mutex); + rundown_bus_requests(); } void unibusadapter_c::worker_power_event() { @@ -195,13 +191,8 @@ void unibusadapter_c::worker_power_event() { device->on_power_changed(); } - INFO("clearing due to power empty %d", _irqRequests.empty()); - // Clear bus request queues - pthread_mutex_lock(&_busWorker_mutex); - while (!_dmaRequests.empty()) _dmaRequests.pop(); - while (!_irqRequests.empty()) _irqRequests.pop(); - pthread_mutex_unlock(&_busWorker_mutex); + rundown_bus_requests(); } // process DATI/DATO access to active device registers @@ -625,16 +616,6 @@ void unibusadapter_c::dma_worker() // Sanity check: Should be no active DMA or interrupt requests on the PRU. assert (!request_DMA_active(nullptr) && !request_INTR_active(nullptr)); - /* - // If there's an IRQ still active, wait for it to finish. - // TODO: find a way to avoid having to do this. - timeout_c timer; - while (request_INTR_active(nullptr)) - { - INFO("intr active"); - timer.wait_us(50); - } */ - if (dmaReq) { // We do the DMA transfer in chunks so we can handle arbitrary buffer sizes. @@ -693,14 +674,9 @@ void unibusadapter_c::dma_worker() dmaReq->SetUnibusEndAddr(mailbox->dma.cur_addr); dmaReq->SetSuccess(mailbox->dma.cur_status == DMA_STATE_READY); - if(dmaReq->GetUnibusAddr() + dmaReq->GetWordCount() * 2 != mailbox->dma.cur_addr + 2) + assert(dmaReq->GetUnibusAddr() + dmaReq->GetWordCount() * 2 == + mailbox->dma.cur_addr + 2); - { - FATAL("PRU end addr 0x%x, expected 0x%x", - mailbox->dma.cur_addr + 2, - dmaReq->GetUnibusAddr() + dmaReq->GetWordCount() * 2); - } - // // Signal that the request is complete. // @@ -759,6 +735,33 @@ void unibusadapter_c::dma_worker() } } +void unibusadapter_c::rundown_bus_requests() +{ + // + // Cancel all pending DMA and IRQ requests, freeing threads waiting + // on completion. + // + pthread_mutex_lock(&_busWorker_mutex); + while (!_dmaRequests.empty()) + { + dma_request_c* dmaReq = _dmaRequests.front(); + dmaReq->SetSuccess(false); + dmaReq->SetComplete(); + pthread_cond_signal(&_requestFinished_cond); + _dmaRequests.pop(); + } + while (!_irqRequests.empty()) + { + irq_request_c* irqReq = _irqRequests.front(); + irqReq->SetComplete(); + pthread_cond_signal(&_requestFinished_cond); + _irqRequests.pop(); + } + pthread_mutex_unlock(&_busWorker_mutex); + +} + + void unibusadapter_c::request_INTR(uint32_t level, uint32_t vector) { // // Acquire bus mutex; append new request to queue. diff --git a/10.01_base/2_src/arm/unibusadapter.hpp b/10.01_base/2_src/arm/unibusadapter.hpp index d902c1b..a6c45a4 100644 --- a/10.01_base/2_src/arm/unibusadapter.hpp +++ b/10.01_base/2_src/arm/unibusadapter.hpp @@ -124,6 +124,7 @@ public: bool request_DMA(uint8_t unibus_control, uint32_t unibus_addr, uint16_t *buffer, uint32_t wordcount); void request_INTR(uint32_t level, uint32_t vector); + void rundown_bus_requests(void); void print_shared_register_map(void); diff --git a/10.02_devices/2_src/mscp_server.cpp b/10.02_devices/2_src/mscp_server.cpp index b10b47a..3bf63af 100644 --- a/10.02_devices/2_src/mscp_server.cpp +++ b/10.02_devices/2_src/mscp_server.cpp @@ -122,9 +122,6 @@ mscp_server::Poll(void) pthread_mutex_unlock(&polling_mutex); - // timer.wait_us(100); - - if (_abort_polling) { break; @@ -262,6 +259,14 @@ mscp_server::Poll(void) FATAL("no room at the inn."); } + // + // This delay works around an issue in the VMS bootstrap -- unsure of the + // exact cause, it appears to be a race condition exacerbated by the speed + // at which we're able to process commands in the ring buffer (we are much + // faster than any real MSCP device ever was.) + // This is likely a hack, we may be papering over a bug somewhere. + // + timer.wait_us(100); // // Go around and pick up the next one. diff --git a/10.02_devices/2_src/uda.cpp b/10.02_devices/2_src/uda.cpp index 446b917..cf49b26 100644 --- a/10.02_devices/2_src/uda.cpp +++ b/10.02_devices/2_src/uda.cpp @@ -78,10 +78,7 @@ uda_c::~uda_c() void uda_c::Reset(void) { - DEBUG("UDA reset"); - - _sa = 0; - update_SA(); + INFO("UDA reset"); _ringBase = 0; _commandRingLength = 0; @@ -94,11 +91,13 @@ void uda_c::Reset(void) _purgeInterruptEnable = false; _next_step = false; + _server->Reset(); // Signal the worker to begin the initialization sequence. StateTransition(InitializationStep::Uninitialized); - _server->Reset(); + _sa = 0; + update_SA(); } uint32_t uda_c::GetDriveCount(void) @@ -126,7 +125,7 @@ void uda_c::StateTransition( void uda_c::worker(void) { - worker_init_realtime_priority(rt_device); + worker_init_realtime_priority(rt_max); timeout_c timeout; @@ -862,6 +861,7 @@ uda_c::DMAWrite( uint8_t* buffer) { assert ((lengthInBytes % 2) == 0); + assert (address < 0x40000); return unibusadapter->request_DMA( UNIBUS_CONTROL_DATO, @@ -883,6 +883,7 @@ uda_c::DMARead( { assert (bufferSize >= lengthInBytes); assert((lengthInBytes % 2) == 0); + assert (address < 0x40000); uint16_t* buffer = new uint16_t[bufferSize >> 1];