mirror of
https://github.com/livingcomputermuseum/UniBone.git
synced 2026-02-26 16:54:04 +00:00
Power OFF event now from ACLO
PRU bugfix: if DMA cycle started by register access cycle Extended interface for emulated CPU
This commit is contained in:
@@ -102,8 +102,13 @@ void mailbox_test1() {
|
||||
* mailbox union members must have been filled.
|
||||
*/
|
||||
//uint32_t xxx;
|
||||
|
||||
pthread_mutex_t arm2pru_mutex = PTHREAD_MUTEX_INITIALIZER ;
|
||||
|
||||
bool mailbox_execute(uint8_t request) {
|
||||
// write to arm2pru_req must be last memory operation
|
||||
pthread_mutex_lock(&arm2pru_mutex) ;
|
||||
|
||||
__sync_synchronize();
|
||||
while (mailbox->arm2pru_req != ARM2PRU_NONE)
|
||||
; // wait to complete
|
||||
@@ -121,5 +126,7 @@ bool mailbox_execute(uint8_t request) {
|
||||
; // wait until processed
|
||||
*/
|
||||
// result false = error
|
||||
return (mailbox->arm2pru_req == ARM2PRU_NONE) ;
|
||||
bool result = (mailbox->arm2pru_req == ARM2PRU_NONE) ;
|
||||
pthread_mutex_unlock(&arm2pru_mutex) ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ unibusadapter_c::unibusadapter_c() :
|
||||
devices[i] = NULL;
|
||||
line_INIT = false;
|
||||
line_DCLO = false;
|
||||
line_ACLO = false ;
|
||||
|
||||
requests_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
@@ -756,14 +757,14 @@ void unibusadapter_c::worker_init_event() {
|
||||
pthread_mutex_unlock(&requests_mutex);
|
||||
}
|
||||
|
||||
void unibusadapter_c::worker_power_event() {
|
||||
void unibusadapter_c::worker_power_event(bool power_down) {
|
||||
unsigned device_handle;
|
||||
unibusdevice_c *device;
|
||||
// notify device on change of DC_LO line
|
||||
DEBUG("worker_power_event(): DCLO %s", line_DCLO ? "asserted" : "deasserted");
|
||||
DEBUG("worker_power_event(power_down=%d)", power_down);
|
||||
for (device_handle = 0; device_handle <= MAX_DEVICE_HANDLE; device_handle++)
|
||||
if ((device = devices[device_handle])) {
|
||||
device->power_down = line_DCLO;
|
||||
device->power_down = power_down;
|
||||
device->on_power_changed();
|
||||
}
|
||||
|
||||
@@ -1004,6 +1005,8 @@ void unibusadapter_c::worker(unsigned instance) {
|
||||
bool init_falling_edge = false;
|
||||
bool dclo_raising_edge = false;
|
||||
bool dclo_falling_edge = false;
|
||||
bool aclo_raising_edge = false;
|
||||
bool aclo_falling_edge = false;
|
||||
// DEBUG("mailbox->events: mask=0x%x", mailbox->events.eventmask);
|
||||
if (mailbox->events.event_init) {
|
||||
any_event = true;
|
||||
@@ -1031,16 +1034,27 @@ void unibusadapter_c::worker(unsigned instance) {
|
||||
dclo_falling_edge = true;
|
||||
line_DCLO = false;
|
||||
}
|
||||
if (mailbox->events.initialization_signals_cur & INITIALIZATIONSIGNAL_ACLO) {
|
||||
if (!line_ACLO)
|
||||
aclo_raising_edge = true;
|
||||
line_ACLO = true;
|
||||
} else {
|
||||
if (line_ACLO)
|
||||
aclo_falling_edge = true;
|
||||
line_ACLO = false;
|
||||
}
|
||||
mailbox->events.event_power = 0; // PRU may re-raise and change mailbox now
|
||||
DEBUG(
|
||||
"EVENT_INITIALIZATIONSIGNALS: (sigprev=0x%x,) cur=0x%x, init_raise=%d, init_fall=%d, dclo_raise=%d, dclo_fall=%d",
|
||||
"EVENT_INITIALIZATIONSIGNALS: (sigprev=0x%x,) cur=0x%x, init_raise=%d, init_fall=%d, dclo_raise/fall=%d%/d, aclo_raise/fall=%d/%d",
|
||||
mailbox->events.initialization_signals_prev,
|
||||
mailbox->events.initialization_signals_cur, init_raising_edge,
|
||||
init_falling_edge, dclo_raising_edge, dclo_falling_edge);
|
||||
init_falling_edge, dclo_raising_edge, dclo_falling_edge, aclo_raising_edge, aclo_falling_edge);
|
||||
|
||||
}
|
||||
if (dclo_raising_edge || dclo_falling_edge)
|
||||
worker_power_event(); // power signal power change
|
||||
if (dclo_raising_edge)
|
||||
worker_power_event(true); // power signal power change
|
||||
else if (aclo_falling_edge)
|
||||
worker_power_event(false); // power signal power change
|
||||
if (init_falling_edge) // INIT asserted -> deasserted. DATI/DATO cycle only possible after that.
|
||||
worker_init_event();
|
||||
if (mailbox->events.event_deviceregister) {
|
||||
@@ -1050,7 +1064,7 @@ void unibusadapter_c::worker(unsigned instance) {
|
||||
// DEBUG("EVENT_DEVICEREGISTER: control=%d, addr=%06o", (int)mailbox->events.unibus_control, mailbox->events.addr);
|
||||
worker_deviceregister_event();
|
||||
// ARM2PRU opcodes raised by device logic are processed in midst of bus cycle
|
||||
mailbox->events.event_deviceregister = 0; // PRU continous bus cycle with SSYN now
|
||||
mailbox->events.event_deviceregister = 0; // PRU continues bus cycle with SSYN now
|
||||
}
|
||||
if (mailbox->events.event_dma) {
|
||||
any_event = true;
|
||||
|
||||
@@ -62,7 +62,7 @@ private:
|
||||
pthread_mutex_t requests_mutex;
|
||||
|
||||
void worker_init_event(void);
|
||||
void worker_power_event(void);
|
||||
void worker_power_event(bool power_down);
|
||||
void worker_deviceregister_event(void);
|
||||
void worker_dma_chunk_complete_event(bool cpu_DATA_transfer);
|
||||
void worker_intr_complete_event(uint8_t level_index);
|
||||
@@ -80,6 +80,7 @@ public:
|
||||
|
||||
volatile bool line_INIT; // current state of these UNIBUS signals
|
||||
volatile bool line_DCLO;
|
||||
volatile bool line_ACLO;
|
||||
|
||||
void on_power_changed(void) override; // must implement
|
||||
void on_init_changed(void) override; // must implement
|
||||
|
||||
@@ -125,31 +125,35 @@ void main(void) {
|
||||
while ((sm_data_slave_state = sm_data_slave_state())
|
||||
&& !mailbox.events.event_deviceregister)
|
||||
// throws signals to ARM,
|
||||
// Acess to interna lregsitres may may issue AMR2PRU opcode, so exit loop then
|
||||
// Acess to internal registers may may issue AMR2PRU opcode, so exit loop then
|
||||
;// execute complete slave cycle, then check NPR/INTR
|
||||
|
||||
// signal INT or PWR FAIL to ARM
|
||||
do_event_initializationsignals();
|
||||
|
||||
// Priority Arbitration
|
||||
// execute one of the arbitration workers
|
||||
uint8_t grant_mask = sm_arb_worker();
|
||||
// sm_arb_worker()s include State 2 "BBSYWAIT".
|
||||
// So now SACK maybe set, even if grant_mask is still 0
|
||||
// Delay INTR or DMA while BUS halted via SSYN.
|
||||
// ARM may start DMA within deviceregister event!
|
||||
if (!mailbox.events.event_deviceregister) {
|
||||
// execute one of the arbitration workers
|
||||
uint8_t grant_mask = sm_arb_worker();
|
||||
// sm_arb_worker()s include State 2 "BBSYWAIT".
|
||||
// So now SACK maybe set, even if grant_mask is still 0
|
||||
|
||||
if (grant_mask & PRIORITY_ARBITRATION_BIT_NP) {
|
||||
sm_data_master_state = (statemachine_state_func) &sm_dma_start;
|
||||
// can data_master_state be overwritten in the midst of a running data_master_state ?
|
||||
// no: when running, SACK is set, no new GRANTs
|
||||
} else if (grant_mask & PRIORITY_ARBITRATION_INTR_MASK) {
|
||||
// convert bit in grant_mask to INTR index
|
||||
uint8_t idx = PRIORITY_ARBITRATION_INTR_BIT2IDX(grant_mask);
|
||||
// now transfer INTR vector for interupt of GRANted level.
|
||||
// vector and ARM context have been setup by ARM before ARM2PRU_INTR already
|
||||
sm_intr.vector = mailbox.intr.vector[idx];
|
||||
sm_intr.level_index = idx; // to be returned to ARM on complete
|
||||
if (grant_mask & PRIORITY_ARBITRATION_BIT_NP) {
|
||||
sm_data_master_state = (statemachine_state_func) &sm_dma_start;
|
||||
// can data_master_state be overwritten in the midst of a running data_master_state ?
|
||||
// no: when running, SACK is set, no new GRANTs
|
||||
} else if (grant_mask & PRIORITY_ARBITRATION_INTR_MASK) {
|
||||
// convert bit in grant_mask to INTR index
|
||||
uint8_t idx = PRIORITY_ARBITRATION_INTR_BIT2IDX(grant_mask);
|
||||
// now transfer INTR vector for interupt of GRANted level.
|
||||
// vector and ARM context have been setup by ARM before ARM2PRU_INTR already
|
||||
sm_intr.vector = mailbox.intr.vector[idx];
|
||||
sm_intr.level_index = idx; // to be returned to ARM on complete
|
||||
|
||||
sm_data_master_state = (statemachine_state_func) &sm_intr_start;
|
||||
sm_data_master_state = (statemachine_state_func) &sm_intr_start;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// State 3 "MASTER"
|
||||
|
||||
@@ -150,7 +150,7 @@ static statemachine_state_func sm_dma_state_1() {
|
||||
tmpval |= BIT(3); // DATO: c1=1, c0=0
|
||||
// bit 2,4,5 == 0 -> C0,MSYN,SSYN not asserted
|
||||
buslatches_setbits(4, 0x3f, tmpval);
|
||||
// write data. SSYN may still be active???
|
||||
// write data. SSYN may still be active and cleared now? by sm_slave_10 etc?
|
||||
// data = mailbox.dma.words[sm_dma.cur_wordidx];
|
||||
data = *sm_dma.dataptr;
|
||||
buslatches_setbyte(5, data & 0xff); // DATA[0..7] = latch[5]
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
//statemachine_state_func sm_slave_start(void);
|
||||
static statemachine_state_func sm_slave_state_10(void);
|
||||
static statemachine_state_func sm_slave_state_20(void);
|
||||
static statemachine_state_func sm_slave_state_99(void);
|
||||
//static statemachine_state_func sm_slave_state_99(void);
|
||||
|
||||
// check for MSYN active
|
||||
statemachine_state_func sm_slave_start() {
|
||||
@@ -115,7 +115,8 @@ statemachine_state_func sm_slave_start() {
|
||||
// perhaps PRU2ARM_INTERRUPT now active
|
||||
} else
|
||||
// no address match: wait for MSYN to go inactive
|
||||
return (statemachine_state_func) &sm_slave_state_99;
|
||||
// return (statemachine_state_func) &sm_slave_state_99;
|
||||
return NULL ;
|
||||
case UNIBUS_CONTROL_DATO:
|
||||
// fetch data in any case
|
||||
// DATA[0..7] = latch[5]
|
||||
@@ -131,7 +132,8 @@ statemachine_state_func sm_slave_start() {
|
||||
// perhaps PRU2ARM_INTERRUPT now active
|
||||
} else
|
||||
// no address match: wait for MSYN to go inactive
|
||||
return (statemachine_state_func) &sm_slave_state_99;
|
||||
// return (statemachine_state_func) &sm_slave_state_99;
|
||||
return NULL ;
|
||||
case UNIBUS_CONTROL_DATOB:
|
||||
// A00 = 1, odd address: get upper byte
|
||||
// A00 = 0: even address, get lower byte
|
||||
@@ -151,7 +153,8 @@ statemachine_state_func sm_slave_start() {
|
||||
// perhaps PRU2ARM_INTERRUPT now active
|
||||
} else
|
||||
// no address match: wait for MSYN to go inactive
|
||||
return (statemachine_state_func) &sm_slave_state_99;
|
||||
// return (statemachine_state_func) &sm_slave_state_99;
|
||||
return NULL ;
|
||||
}
|
||||
return NULL; // not reached
|
||||
}
|
||||
@@ -198,11 +201,15 @@ static statemachine_state_func sm_slave_state_20() {
|
||||
return NULL; // ready
|
||||
}
|
||||
|
||||
|
||||
// end of inactive cycle: wait for MSYN to go inactive
|
||||
// Not necessary, start() state simply checks addr again if MSYN still set.
|
||||
static statemachine_state_func sm_slave_state_99() {
|
||||
// MSYN = latch[4], bit 4
|
||||
if (buslatches_getbyte(4) & BIT(4))
|
||||
if (buslatches_getbyte(4) & BIT(4)) {
|
||||
return (statemachine_state_func) &sm_slave_state_99; // wait, MSYN still active
|
||||
}
|
||||
// PRU_DEBUG_PIN(1) ;
|
||||
|
||||
return NULL; // ready
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user