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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user