1
0
mirror of https://github.com/livingcomputermuseum/UniBone.git synced 2026-04-03 04:19:01 +00:00

Added small workaround for (possible) bug in VMS secondary bootstrap; improved reset behavior.

4.3bsd still panics during uda bringup.
This commit is contained in:
Josh Dersch
2019-05-07 19:03:49 +02:00
parent 3204e65499
commit a00f0592dc
4 changed files with 47 additions and 37 deletions

View File

@@ -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.

View File

@@ -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);

View File

@@ -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.

View File

@@ -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];