1
0
mirror of https://github.com/livingcomputermuseum/UniBone.git synced 2026-01-27 20:37:36 +00:00

Fixes for MSCP after Joerg's INTR/DMA rewrites:

- Fixed programmable interrupt vector (was broken after changes)
- Fixed interrupts during MSCP 4-stage init to atomically update SA register; 4.3bsd now boots.
This commit is contained in:
Josh Dersch
2019-08-14 09:46:32 +02:00
parent 1d4fe694ae
commit 073a2334b6
2 changed files with 40 additions and 21 deletions

View File

@@ -46,12 +46,12 @@ uda_c::uda_c() :
type_name.value = "UDA50";
log_label = "uda";
// base addr, intr-vector, intr level
set_default_bus_params(0772150, 20, 0154, 5) ;
dma_request.set_priority_slot(default_priority_slot) ;
intr_request.set_priority_slot(default_priority_slot) ;
intr_request.set_level(default_intr_level) ;
intr_request.set_vector(default_intr_vector) ;
// base addr, intr-vector, intr level
set_default_bus_params(0772150, 20, 0154, 5) ;
dma_request.set_priority_slot(default_priority_slot) ;
intr_request.set_priority_slot(default_priority_slot) ;
intr_request.set_level(default_intr_level) ;
intr_request.set_vector(default_intr_vector) ;
// The UDA50 controller has two registers.
register_count = 2;
@@ -98,8 +98,8 @@ uda_c::~uda_c()
}
bool uda_c::on_param_changed(parameter_c *param) {
// no own parameter or "enable" logic
return storagecontroller_c::on_param_changed(param) ; // more actions (for enable)
// no own parameter or "enable" logic
return storagecontroller_c::on_param_changed(param) ; // more actions (for enable)
}
@@ -169,7 +169,7 @@ void uda_c::StateTransition(
//
void uda_c::worker(unsigned instance)
{
UNUSED(instance) ; // only one
UNUSED(instance) ; // only one
worker_init_realtime_priority(rt_device);
@@ -224,8 +224,7 @@ void uda_c::worker(unsigned instance)
// Update the SA read value for step 2:
// S2 is set, unibus port type (0), SA bits 15-8 written
// by the host in step 1.
update_SA(0x1000 | ((_step1Value >> 8) & 0xff));
Interrupt();
Interrupt(0x1000 | ((_step1Value >> 8) & 0xff));
break;
case InitializationStep::Step3:
@@ -234,8 +233,7 @@ void uda_c::worker(unsigned instance)
DEBUG("Transition to Init state S3.");
// Update the SA read value for step 3:
// S3 set, plus SA bits 7-0 written by the host in step 1.
update_SA(0x2000 | (_step1Value & 0xff));
Interrupt();
Interrupt(0x2000 | (_step1Value & 0xff));
break;
case InitializationStep::Step4:
@@ -275,8 +273,7 @@ void uda_c::worker(unsigned instance)
DEBUG("Transition to Init state S4, comm area initialized.");
// Update the SA read value for step 4:
// Bits 7-0 indicating our control microcode version.
update_SA(UDA50_ID); // UDA50 ID, makes RSTS happy
Interrupt();
Interrupt(UDA50_ID); // UDA50 ID, makes RSTS happy
break;
case InitializationStep::Complete:
@@ -304,7 +301,8 @@ uda_c::on_after_register_access(
{
// "When written with any value, it causes a hard initialization
// of the port and the device controller."
DEBUG("Reset due to IP read");
DEBUG("Reset due to IP read");
update_SA(0x0);
StateTransition(InitializationStep::Uninitialized);
}
else
@@ -352,7 +350,9 @@ uda_c::on_after_register_access(
// during initialization.
_step1Value = value;
intr_vector.value = _interruptVector = ((value & 0x7f) << 2);
_interruptVector = ((value & 0x7f) << 2);
intr_request.set_vector(_interruptVector);
_interruptEnable = !!(value & 0x80);
_responseRingLength = (1 << ((value & 0x700) >> 8));
_commandRingLength = (1 << ((value & 0x3800) >> 11));
@@ -802,6 +802,24 @@ uda_c::GetControllerClassModel()
return 0x0102; // Class 1 (mass storage), model 2 (UDA50)
}
//
// Interrupt():
// Invokes a Unibus interrupt if interrupts are enabled and the interrupt
// vector is non-zero. Updates SA to the specified value atomically.
//
void
uda_c::Interrupt(uint16_t sa_value)
{
if ((_interruptEnable || _initStep == InitializationStep::Complete) && _interruptVector != 0)
{
unibusadapter->INTR(intr_request, SA_reg, sa_value);
}
else
{
update_SA(sa_value);
}
}
//
// Interrupt():
// Invokes a Unibus interrupt if interrupts are enabled and the interrupt
@@ -812,7 +830,7 @@ uda_c::Interrupt(void)
{
if ((_interruptEnable || _initStep == InitializationStep::Complete) && _interruptVector != 0)
{
unibusadapter->INTR(intr_request, NULL, 0); // todo: link to interupt register
unibusadapter->INTR(intr_request, NULL, 0);
}
}

View File

@@ -76,9 +76,9 @@ public:
void on_drive_status_changed(storagedrive_c *drive) override;
// As every storage controller UDA has one INTR and DMA
dma_request_c dma_request = dma_request_c(this) ; // operated by unibusadapter
intr_request_c intr_request = intr_request_c(this) ;
// As every storage controller UDA has one INTR and DMA
dma_request_c dma_request = dma_request_c(this) ; // operated by unibusadapter
intr_request_c intr_request = intr_request_c(this) ;
public:
@@ -103,6 +103,7 @@ public:
private:
// TODO: consolidate these private/public groups here
void Reset(void);
void Interrupt(uint16_t sa_value);
void Interrupt(void);
uint32_t GetCommandDescriptorAddress(size_t index);