From 3f71d6f093c940b0ccee0cdf1dc3e4913d2e7d6c Mon Sep 17 00:00:00 2001 From: Joerg Hoppe Date: Tue, 8 Oct 2019 12:36:36 +0200 Subject: [PATCH] CPU20 UNIBUS Interrupt, Experiments to probe UNIBUS arbitrator --- 10.01_base/2_src/arm/unibus.cpp | 150 ++++-- 10.01_base/2_src/arm/unibusadapter.cpp | 8 +- 10.01_base/2_src/pru1/pru1_main_test.c | 1 - 10.01_base/2_src/pru1/pru1_main_unibus.c | 22 +- .../2_src/pru1/pru1_statemachine_data_slave.c | 2 +- 10.01_base/2_src/pru1/pru1_statemachine_dma.c | 2 + 10.01_base/2_src/shared/mailbox.h | 20 +- 10.01_base/2_src/shared/unibus.h | 5 +- 10.02_devices/2_src/cpu.cpp | 3 +- 10.02_devices/2_src/cpu20/ka11.c | 47 +- 10.02_devices/2_src/cpu20/ka11.h | 7 +- 10.02_devices/3_test/cpu20/hello2.lst | 49 +- 10.02_devices/3_test/cpu20/multiarb.lst | 428 +++++++++++------- .../2_src/menu_device_exercisers.cpp | 2 +- 10.03_app_demo/2_src/menu_devices.cpp | 4 +- 10.03_app_demo/2_src/menu_interrupts.cpp | 2 +- 10.03_app_demo/2_src/menu_masterslave.cpp | 2 +- 17 files changed, 499 insertions(+), 255 deletions(-) diff --git a/10.01_base/2_src/arm/unibus.cpp b/10.01_base/2_src/arm/unibus.cpp index eaa12e2..5349665 100644 --- a/10.01_base/2_src/arm/unibus.cpp +++ b/10.01_base/2_src/arm/unibus.cpp @@ -97,43 +97,112 @@ char *unibus_c::control2text(uint8_t control) { /* pulse INIT cycle for some milliseconds */ void unibus_c::init(unsigned pulsewidth_ms) { - timeout_c timeout; mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_INIT; mailbox->initializationsignal.val = 1; mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); - timeout.wait_ms(pulsewidth_ms); + timeout_c::wait_ms(pulsewidth_ms); mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_INIT; mailbox->initializationsignal.val = 0; mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); } +// return: bitmask with shortcount BG*/NPG IN_OUT signals +// Values see PRIORITY_ARBITRATION_BIT_* +// Fiddling with the BG*/NPG signal may crash running CPU, also +// the M9302 will generate a SACK. +// So CPU is stopped with a surrounding a power cycle +uint8_t unibus_c::probe_grant_continuity(bool error_if_closed) { + uint8_t grant_mask = 0; + // simulate POWER OFF + powercycle(1); +#if 0 + // CPU should be stopped now, holding BG*/NPG lines active LOW = logic 0. + // If the power vector 24 does something weird, we may have + // BG*/NPG set and have malfunctions now. + + // Test algorithm is difficult to implement. + + // First, pull INIT low to disable fucntion of other cards + + // 3 cases: + // 1) Running CPU on BUS: set a BR, wait for BGIN + // (not tested here) + // + // 2) If HALTed CPU on bus: BG*/NPG held LOW + // Need M9302 with SACK turnaround. + // - set each BGOUT/NPGOUT (assume IN 0 by CPU) + // - if M9302 responds with SACK: + // it sees a BG 1 => no jumper IN-OUT + // if no SACK: M9302 sees a "0" => jumper set + + // 3) If no CPU on bus: BG*/NPG pulled up + // set BG OUT = 0, if IN 0 -> jumper! + + // Set BG*_OUT/NPG_OUT bits at latch 0 + // and read back + mailbox->buslatch.addr = 0; + mailbox->buslatch.bitmask = PRIORITY_ARBITRATION_BIT_MASK; + mailbox->buslatch.val = 0x00; // output 0 = against pullups + mailbox_execute(ARM2PRU_BUSLATCH_SET); + + // Read back BG*_IN/NPG_IN bits from latch 0 +// mailbox->buslatch.addr = 0; +// mailbox_execute(ARM2PRU_BUSLATCH_GET); + uint8_t grant_mask = ~ (mailbox->buslatch.val & PRIORITY_ARBITRATION_BIT_MASK); +#endif + // simulate POWER ON + powercycle(2); + + if (grant_mask && error_if_closed) { + printf("Error: GRANT IN-OUT closed on UNIBUS backplane:"); + if (grant_mask & PRIORITY_ARBITRATION_BIT_B4) + printf(" BG4"); + if (grant_mask & PRIORITY_ARBITRATION_BIT_B5) + printf(" BG5"); + if (grant_mask & PRIORITY_ARBITRATION_BIT_B6) + printf(" BG6"); + if (grant_mask & PRIORITY_ARBITRATION_BIT_B7) + printf(" BG7"); + if (grant_mask & PRIORITY_ARBITRATION_BIT_NP) + printf(" NPG"); + printf(".\n"); + exit(1); + } + + return grant_mask; +} + /* Simulate a power cycle * Sequence: * 1. Line power fail -> ACLO active * 2. Power supply capacitors empty -> DCLO active * 3. Line power back -> ACLO inactive * 4. Logic power OK -> DCLO inactive + * phase: 0x01 = only OFF, 0x02 = only ON, 0x03 = ON and OFF */ -void unibus_c::powercycle(void) { - timeout_c timeout; +void unibus_c::powercycle(int phase) { const unsigned delay_ms = 200; // time between phases - mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_ACLO; - mailbox->initializationsignal.val = 1; - mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); - timeout.wait_ms(delay_ms); - mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_DCLO; - mailbox->initializationsignal.val = 1; - mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); - timeout.wait_ms(delay_ms); - mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_ACLO; - mailbox->initializationsignal.val = 0; - mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); - timeout.wait_ms(delay_ms); - mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_DCLO; - mailbox->initializationsignal.val = 0; - mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); - // wait for CPU to come up - timeout.wait_ms(delay_ms); + if (phase & 0x01) { + mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_ACLO; + mailbox->initializationsignal.val = 1; + mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); + timeout_c::wait_ms(delay_ms); + mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_DCLO; + mailbox->initializationsignal.val = 1; + mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); + timeout_c::wait_ms(delay_ms); + } + if (phase & 0x02) { + mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_ACLO; + mailbox->initializationsignal.val = 0; + mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); + timeout_c::wait_ms(delay_ms); + mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_DCLO; + mailbox->initializationsignal.val = 0; + mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); + // wait for CPU to come up + timeout_c::wait_ms(delay_ms); + } } void unibus_c::set_arbitrator_active(bool active) { @@ -155,8 +224,8 @@ bool unibus_c::get_arbitrator_active(void) { // 0 = bus time, error address = mailbox->dma.cur_addr // 1 = all transfered // A limit for time used by DMA can be compiled-in -bool unibus_c::dma(bool blocking, - uint8_t control, uint32_t startaddr, uint16_t *buffer, unsigned wordcount) { +bool unibus_c::dma(bool blocking, uint8_t control, uint32_t startaddr, uint16_t *buffer, + unsigned wordcount) { int dma_bandwidth_percent = 50; // use 50% of time for DMA, rest for running PDP-11 CPU uint64_t dmatime_ns, totaltime_ns; // can access bus with DMA when there's a Bus Arbitrator @@ -203,13 +272,12 @@ uint32_t unibus_c::test_sizer(void) { // all words from start_addr to including end_addr // // DMA blocksize can be choosen arbitrarily -void unibus_c::mem_write(uint16_t *words, - unsigned unibus_start_addr, unsigned unibus_end_addr, bool *timeout) { +void unibus_c::mem_write(uint16_t *words, unsigned unibus_start_addr, unsigned unibus_end_addr, +bool *timeout) { unsigned wordcount = (unibus_end_addr - unibus_start_addr) / 2 + 1; uint16_t *buffer_start_addr = words + unibus_start_addr / 2; assert(pru->prucode_id == pru_c::PRUCODE_UNIBUS); - *timeout = !dma(true, UNIBUS_CONTROL_DATO, unibus_start_addr, - buffer_start_addr, wordcount); + *timeout = !dma(true, UNIBUS_CONTROL_DATO, unibus_start_addr, buffer_start_addr, wordcount); if (*timeout) { printf("\nWrite timeout @ 0%6o\n", mailbox->dma.cur_addr); return; @@ -220,14 +288,13 @@ void unibus_c::mem_write(uint16_t *words, // all words from start_addr to including end_addr // DMA blocksize can be choosen arbitrarily // arbitration_active: if 1, perform NPR/NPG/SACK arbitration before mem accesses -void unibus_c::mem_read(uint16_t *words, - uint32_t unibus_start_addr, uint32_t unibus_end_addr, bool *timeout) { +void unibus_c::mem_read(uint16_t *words, uint32_t unibus_start_addr, uint32_t unibus_end_addr, +bool *timeout) { unsigned wordcount = (unibus_end_addr - unibus_start_addr) / 2 + 1; uint16_t *buffer_start_addr = words + unibus_start_addr / 2; assert(pru->prucode_id == pru_c::PRUCODE_UNIBUS); - *timeout = !dma(true, UNIBUS_CONTROL_DATI, unibus_start_addr, - buffer_start_addr, wordcount); + *timeout = !dma(true, UNIBUS_CONTROL_DATI, unibus_start_addr, buffer_start_addr, wordcount); if (*timeout) { printf("\nRead timeout @ 0%6o\n", mailbox->dma.cur_addr); return; @@ -235,9 +302,9 @@ void unibus_c::mem_read(uint16_t *words, } // read or write -void unibus_c::mem_access_random( - uint8_t unibus_control, uint16_t *words, uint32_t unibus_start_addr, - uint32_t unibus_end_addr, bool *timeout, uint32_t *block_counter) { +void unibus_c::mem_access_random(uint8_t unibus_control, uint16_t *words, + uint32_t unibus_start_addr, uint32_t unibus_end_addr, bool *timeout, + uint32_t *block_counter) { uint32_t block_unibus_start_addr, block_unibus_end_addr; // in average, make 16 sub transactions assert(pru->prucode_id == pru_c::PRUCODE_UNIBUS); @@ -260,8 +327,8 @@ void unibus_c::mem_access_random( assert(block_unibus_end_addr <= unibus_end_addr); (*block_counter) += 1; // printf("%06d: %5u words %06o-0%06o\n", *block_counter, block_wordcount, block_unibus_start_addr, block_unibus_end_addr) ; - *timeout = !dma(true, unibus_control, block_unibus_start_addr, - block_buffer_start, block_wordcount); + *timeout = !dma(true, unibus_control, block_unibus_start_addr, block_buffer_start, + block_wordcount); if (*timeout) { printf("\n%s timeout @ 0%6o\n", control2text(unibus_control), mailbox->dma.cur_addr); @@ -272,8 +339,7 @@ void unibus_c::mem_access_random( } // arbitration_active: if 1, perform NPR/NPG/SACK arbitration before mem accesses -void unibus_c::test_mem( - uint32_t start_addr, uint32_t end_addr, unsigned mode) { +void unibus_c::test_mem(uint32_t start_addr, uint32_t end_addr, unsigned mode) { #define MAX_ERROR_COUNT 8 progress_c progress = progress_c(80); bool timeout = 0, mismatch = 0; @@ -332,8 +398,8 @@ void unibus_c::test_mem( // testwords[cur_test_addr / 2] = (cur_test_addr >> 1) & 0xffff; // linear progress.put("W"); //info : full memory write - mem_access_random(UNIBUS_CONTROL_DATO, testwords, start_addr, - end_addr, &timeout, &total_write_block_count); + mem_access_random(UNIBUS_CONTROL_DATO, testwords, start_addr, end_addr, &timeout, + &total_write_block_count); if (SIGINTreceived || timeout) break; // leave loop @@ -341,8 +407,8 @@ void unibus_c::test_mem( // first full read progress.put("R"); //info : full memory write // read back into unibus_membuffer[] - mem_access_random(UNIBUS_CONTROL_DATI, membuffer->data.words, - start_addr, end_addr, &timeout, &total_read_block_count); + mem_access_random(UNIBUS_CONTROL_DATI, membuffer->data.words, start_addr, end_addr, + &timeout, &total_read_block_count); // compare for (mismatch_count = 0, cur_test_addr = start_addr; cur_test_addr <= end_addr; cur_test_addr += 2) { diff --git a/10.01_base/2_src/arm/unibusadapter.cpp b/10.01_base/2_src/arm/unibusadapter.cpp index 036746f..ab6be3e 100644 --- a/10.01_base/2_src/arm/unibusadapter.cpp +++ b/10.01_base/2_src/arm/unibusadapter.cpp @@ -612,7 +612,7 @@ void unibusadapter_c::DMA(dma_request_c& dma_request, bool blocking, uint8_t uni } while (!completed); } else if (blocking) { - pthread_mutex_lock(&dma_request.complete_mutex); + pthread_mutex_lock(&dma_request.complete_mutex) ; // DMA() is blocking: Wait for request to finish. // pthread_mutex_lock(&dma_request.mutex); while (!dma_request.complete) { @@ -1111,15 +1111,17 @@ void unibusadapter_c::worker(unsigned instance) { // ARM2PRU opcodes raised by device logic are processed in midst of bus cycle EVENT_ACK(*mailbox, deviceregister); // PRU continues bus cycle with SSYN now } + if (!EVENT_IS_ACKED(*mailbox, dma) && !mailbox->dma.cpu_access) { // not called for CPU DATI/DATO any_event = true; pthread_mutex_lock(&requests_mutex); worker_device_dma_chunk_complete_event(); + pthread_mutex_unlock(&requests_mutex); - // rpu may have set again event_dma again, if this is called before EVENT signal?? - // call this only on singal, not on timeout! + // PRU may have set again event_dma again, if this is called before EVENT signal?? + // call this only on signal, not on timeout! // this may clear reraised PRU event flag! EVENT_ACK(*mailbox, dma); // PRU may re-raise and change mailbox now diff --git a/10.01_base/2_src/pru1/pru1_main_test.c b/10.01_base/2_src/pru1/pru1_main_test.c index 35ca702..49212a1 100644 --- a/10.01_base/2_src/pru1/pru1_main_test.c +++ b/10.01_base/2_src/pru1/pru1_main_test.c @@ -128,7 +128,6 @@ void main(void) { break; case ARM2PRU_BUSLATCH_SET: { // set a mux register - // don't feed "volatile" vars into buslatch_macros !!! uint8_t reg_sel = mailbox.buslatch.addr & 7; uint8_t bitmask = mailbox.buslatch.bitmask; diff --git a/10.01_base/2_src/pru1/pru1_main_unibus.c b/10.01_base/2_src/pru1/pru1_main_unibus.c index bb38af7..8140c26 100644 --- a/10.01_base/2_src/pru1/pru1_main_unibus.c +++ b/10.01_base/2_src/pru1/pru1_main_unibus.c @@ -230,11 +230,11 @@ void main(void) { // request DMA, arbitrator must've been selected with ARM2PRU_ARB_MODE_* if (mailbox.dma.cpu_access) { // Emulated CPU: no NPR/NPG/SACK protocol - sm_arb.cpu_request = 1 ; + sm_arb.cpu_request = 1; } else { // Emulated device: raise request for emulated or physical Arbitrator. sm_arb.device_request_mask |= PRIORITY_ARBITRATION_BIT_NP; - } + } // request not put on bus for CPU memory access mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done break; @@ -291,6 +291,24 @@ void main(void) { emulate_cpu = mailbox.cpu_enable; mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done break; + case ARM2PRU_BUSLATCH_SET: { // set a mux register + // and read back + // don't feed "volatile" vars into buslatch_macros !!! + uint8_t reg_sel = mailbox.buslatch.addr & 7; + uint8_t bitmask = mailbox.buslatch.bitmask; + uint8_t val = mailbox.buslatch.val; + buslatches_setbits(reg_sel, bitmask, val); + mailbox.buslatch.val = buslatches_getbyte(reg_sel); + } + mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done + break; + case ARM2PRU_BUSLATCH_GET: { + // don't feed "volatile" vars into buslatch_macros !!! + uint8_t reg_sel = mailbox.buslatch.addr & 7; + mailbox.buslatch.val = buslatches_getbyte(reg_sel); + } + mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done + break; case ARM2PRU_HALT: mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done __halt(); // LA: trigger on timeout of REG_WRITE diff --git a/10.01_base/2_src/pru1/pru1_statemachine_data_slave.c b/10.01_base/2_src/pru1/pru1_statemachine_data_slave.c index 70fda3f..2f0c691 100644 --- a/10.01_base/2_src/pru1/pru1_statemachine_data_slave.c +++ b/10.01_base/2_src/pru1/pru1_statemachine_data_slave.c @@ -83,7 +83,7 @@ statemachine_state_func sm_data_slave_start() { // addr8..15 = latch[3] // addr 16,17 = latch[4].0,1 addr = latch2val | ((uint32_t) latch3val << 8) | ((uint32_t) (latch4val & 3) << 16); -//if (addr == 0777560) // DL11 +//if (addr == 01046) // trigger address // PRU_DEBUG_PIN0(1) ; // trigger to LA. diff --git a/10.01_base/2_src/pru1/pru1_statemachine_dma.c b/10.01_base/2_src/pru1/pru1_statemachine_dma.c index 129e256..4f4f0e9 100644 --- a/10.01_base/2_src/pru1/pru1_statemachine_dma.c +++ b/10.01_base/2_src/pru1/pru1_statemachine_dma.c @@ -130,6 +130,8 @@ static statemachine_state_func sm_dma_state_1() { } sm_dma.state_timeout = 0; +//if (addr == 01046) // trigger address +// PRU_DEBUG_PIN0(1) ; // trigger to LA. // addr0..7 = latch[2] buslatches_setbyte(2, addr & 0xff); diff --git a/10.01_base/2_src/shared/mailbox.h b/10.01_base/2_src/shared/mailbox.h index fc01f26..15eb56c 100644 --- a/10.01_base/2_src/shared/mailbox.h +++ b/10.01_base/2_src/shared/mailbox.h @@ -30,7 +30,7 @@ #include #include "unibus.h" -// arm to pru +// ARM to PRU #define ARM2PRU_NONE 0 // Operation complete: must be 0! #define ARM2PRU_NOP 1 // to check wether PRU is running #define ARM2PRU_HALT 2 // run PRU1 into halt @@ -43,14 +43,14 @@ #define ARM2PRU_INITALIZATIONSIGNAL_SET 9 // set an ACL=/DCLO/INIT signal #define ARM2PRU_ARB_MODE_NONE 11 // DMA without NPR/NPG/SACK arbitration #define ARM2PRU_ARB_MODE_CLIENT 12 // DMA with arbitration by external Arbitrator -#define ARM2PRU_DMA 14 // DMA with selected arbitration -//#define PRU2ARM_DMA_CPU_TRANSFER_BLOCKED 15 // possible result of ARM2PRU_DMA -#define ARM2PRU_INTR 16 // INTR with arbitration by external Arbitrator -#define ARM2PRU_INTR_CANCEL 17 // clear INTR which has been requested -#define ARM2PRU_CPU_ENABLE 18 // siwtch CPU master side functions ON/OFF -#define ARM2PRU_DDR_FILL_PATTERN 19 // fill DDR with test pattern -#define ARM2PRU_DDR_SLAVE_MEMORY 20 // use DDR as UNIBUS slave memory -#define ARM2PRU_ARB_GRANT_INTR_REQUESTS 21 // emulated CPU answers device requests +#define ARM2PRU_DMA 13 // DMA with selected arbitration +#define ARM2PRU_INTR 14 // INTR with arbitration by external Arbitrator +#define ARM2PRU_INTR_CANCEL 15 // clear INTR which has been requested +#define ARM2PRU_CPU_ENABLE 16 // siwtch CPU master side functions ON/OFF +#define ARM2PRU_DDR_FILL_PATTERN 17 // fill DDR with test pattern +#define ARM2PRU_DDR_SLAVE_MEMORY 18 // use DDR as UNIBUS slave memory +#define ARM2PRU_ARB_GRANT_INTR_REQUESTS 19 // emulated CPU answers device requests + // signal IDs for ARM2PRU_INITALIZATIONSIGNAL_* @@ -66,7 +66,7 @@ #define DMA_STATE_TIMEOUTSTOP 3 // stop because of UNIBUS timeout #define DMA_STATE_INITSTOP 4 // stop because INIT signal sensed -// bits BR*/NPR interrupts in buslatch 0 and 1 +// Bit masks BR*/NPR and BG*/NPG in buslatch 0 and 1 // bit # is index into arbitration_request[] array. #define PRIORITY_ARBITRATION_BIT_B4 0x01 #define PRIORITY_ARBITRATION_BIT_B5 0x02 diff --git a/10.01_base/2_src/shared/unibus.h b/10.01_base/2_src/shared/unibus.h index eb05e09..971371b 100644 --- a/10.01_base/2_src/shared/unibus.h +++ b/10.01_base/2_src/shared/unibus.h @@ -91,7 +91,10 @@ public: bool get_arbitrator_active(void); - void powercycle(void); + + uint8_t probe_grant_continuity(bool error_if_closed) ; + + void powercycle(int phase = 3); // functions of unibusadapter to do simple DMA dma_request_c *dma_request; diff --git a/10.02_devices/2_src/cpu.cpp b/10.02_devices/2_src/cpu.cpp index afe42f8..e8c57d4 100644 --- a/10.02_devices/2_src/cpu.cpp +++ b/10.02_devices/2_src/cpu.cpp @@ -69,7 +69,6 @@ void unibone_logdump(void) { void unibone_on_before_instruction(void) { // after that the CPU should check for received INTR vectors // in its microcode service() step.c - // allow PRU do to produce GRANT for device requests mailbox_execute (ARM2PRU_ARB_GRANT_INTR_REQUESTS); // Block CPU thread @@ -267,7 +266,7 @@ void cpu_c::on_after_register_access(unibusdevice_register_t *device_reg, } // CPU received interrupt vector from UNIBUS -// PRU triggers this via unibusadapter, +// PRU triggers this via unibusadapter worker thread, // mailbox->arbitrator.cpu_priority_level is CPU_PRIORITY_LEVEL_FETCHING // CPU fetches PSW and calls unibone_prioritylevelchange(), which // sets mailbox->arbitrator.cpu_priority_level and diff --git a/10.02_devices/2_src/cpu20/ka11.c b/10.02_devices/2_src/cpu20/ka11.c index a329129..d0b6b6f 100644 --- a/10.02_devices/2_src/cpu20/ka11.c +++ b/10.02_devices/2_src/cpu20/ka11.c @@ -15,7 +15,7 @@ int dati_bus(Bus *bus) { unsigned int data; - if(!unibone_dati(bus->addr, &data)) + if(!unibone_dati(bus->addr, &data)) return 1; bus->data = data; return 0; @@ -58,7 +58,6 @@ enum { TRAP_BR6 = 010, TRAP_BR5 = 040, TRAP_BR4 = 0100, - TRAP_BRX = 0200, // for unibone TRAP_CSTOP = 01000 // can't happen? }; @@ -66,8 +65,8 @@ enum { enum { STATE_HALTED = 0, - STATE_RUNNING, - STATE_WAITING + STATE_RUNNING = 1, + STATE_WAITING = 2 }; word @@ -118,12 +117,15 @@ printstate(KA11 *cpu) cpu->ba, cpu->ir, cpu->psw); } +// only to be called from ka11_condstep() thread void ka11_reset(KA11 *cpu) { Busdev *bd; cpu->traps = 0; + cpu->external_intr = 0; + cpu->mutex = PTHREAD_MUTEX_INITIALIZER ; for(bd = cpu->bus->devs; bd; bd = bd->next) bd->reset(bd->dev); @@ -133,7 +135,7 @@ int dati(KA11 *cpu, int b) { trace("dati %06o:\n", cpu->ba); - if(!b && cpu->ba&1) + if(!b && cpu->ba&1) goto be; /* internal registers */ @@ -551,7 +553,9 @@ step(KA11 *cpu) /* Operate */ switch(cpu->ir & 7){ case 0: TR(HALT); cpu->state = STATE_HALTED; return; - case 1: TR(WAIT); cpu->state = STATE_WAITING; return; + case 1: TR(WAIT); +printf("WAIT\n") ; + cpu->state = STATE_WAITING; return; case 2: TR(RTI); BA = SP; POP; IN(PC); BA = SP; POP; IN(PSW); @@ -571,7 +575,7 @@ be: if(cpu->be > 1){ cpu->state = STATE_HALTED; return; } -printf("bus error ar %06o\n", cpu->ba); + trace("bus error at %06o\n", cpu->ba); TRAP(4); trap: @@ -589,6 +593,19 @@ trap: // SVC; service: +{ + // external interrupt from parallel threads? + pthread_mutex_lock(&cpu->mutex) ; + bool external_intr = cpu->external_intr ; + word external_intrvec = cpu->external_intrvec ; + cpu->external_intr = 0 ; + pthread_mutex_unlock(&cpu->mutex) ; + if (external_intr){ + TRAP(external_intrvec); + } +} + + c = PSW >> 5; if(oldpsw & PSW_T){ oldpsw &= ~PSW_T; @@ -600,9 +617,6 @@ service: }else if(cpu->traps & TRAP_PWR){ cpu->traps &= ~TRAP_PWR; TRAP(024); - }else if(cpu->traps & TRAP_BRX){ - cpu->traps &= ~TRAP_BRX; - TRAP(cpu->trapvec); }else if(c < 7 && cpu->traps & TRAP_BR7){ cpu->traps &= ~TRAP_BR7; TRAP(cpu->br[3].bg(cpu->br[3].dev)); @@ -621,19 +635,28 @@ service: return; } +// to be called from parallel threads to signal asnyc intr +// (unibusadapter worker thread) void ka11_setintr(KA11 *cpu, unsigned vec) { - cpu->traps |= TRAP_BRX; - cpu->trapvec = vec; + pthread_mutex_lock(&cpu->mutex) ; + cpu->external_intr = true; + cpu->external_intrvec = vec; + trace("INTR vec=%03o\n", vec) ; + pthread_mutex_unlock(&cpu->mutex) ; } +// only to be called from ka11_condstep() thread + void ka11_pwrdown(KA11 *cpu) { cpu->traps |= TRAP_PWR; } +// only to be called from ka11_condstep() thread +// if locked, will lock DATI and unibus adapter()! void ka11_pwrup(KA11 *cpu) { diff --git a/10.02_devices/2_src/cpu20/ka11.h b/10.02_devices/2_src/cpu20/ka11.h index b709d89..cc95415 100644 --- a/10.02_devices/2_src/cpu20/ka11.h +++ b/10.02_devices/2_src/cpu20/ka11.h @@ -16,11 +16,16 @@ struct KA11 int (*bg)(void *dev); void *dev; } br[4]; - word trapvec; // for unibone + + // UniBone + pthread_mutex_t mutex ; + volatile bool external_intr ; // INTR by parallel thread pending + volatile word external_intrvec; // associated vector word sw; }; + void ka11_reset(KA11 *cpu); void ka11_setintr(KA11 *cpu, unsigned vec); void ka11_pwrdown(KA11 *cpu); diff --git a/10.02_devices/3_test/cpu20/hello2.lst b/10.02_devices/3_test/cpu20/hello2.lst index 118f65c..5b4eb22 100644 --- a/10.02_devices/3_test/cpu20/hello2.lst +++ b/10.02_devices/3_test/cpu20/hello2.lst @@ -11,30 +11,33 @@ 11 177560 serial = 177560 ; base addr of DL11 12 13 - 14 002000 .=2000 - 15 - 16 start: - 17 002000 012702 177564 mov #serial+4,r2 ; r2 points to DL11 transmitter section - 18 002004 012701 002032 mov #string,r1 ; r1 points to the current character - 19 nxtchr: - 20 002010 012100 mov (r1)+,r0 ; load xmt char into r0 - 21 002012 001405 beq done ; string ends with 0 - 22 - 23 002014 110062 000002 movb r0,2(r2) ; xmt char - 24 002020 105712 wait: tstb (r2) ; character transmitted? - 25 002022 100376 bpl wait ; no, loop - 26 002024 000771 br nxtchr ; transmit nxt char of string - 27 - 28 002026 000000 done: halt - 29 002030 000763 br start + 14 000000 .=0 ; incomplete + 15 000000 000137 002000 jmp @#start + 16 + 17 002000 .=2000 + 18 + 19 start: + 20 002000 012702 177564 mov #serial+4,r2 ; r2 points to DL11 transmitter section + 21 002004 012701 002032 mov #string,r1 ; r1 points to the current character + 22 nxtchr: + 23 002010 012100 mov (r1)+,r0 ; load xmt char into r0 + 24 002012 001405 beq done ; string ends with 0 + 25 + 26 002014 110062 000002 movb r0,2(r2) ; xmt char + 27 002020 105712 wait: tstb (r2) ; character transmitted? + 28 002022 100376 bpl wait ; no, loop + 29 002024 000771 br nxtchr ; transmit nxt char of string 30 - 31 string: - 32 002032 000110 000145 000154 .word 110,145,154,154,157,054,040 ; "Hello, " + 31 002026 000000 done: halt + 32 002030 000763 br start + 33 + 34 string: + 35 002032 000110 000145 000154 .word 110,145,154,154,157,054,040 ; "Hello, " 002040 000154 000157 000054 002046 000040 - 33 002050 000167 000157 000162 .word 167,157,162,154,144,041 ; "world!" + 36 002050 000167 000157 000162 .word 167,157,162,154,144,041 ; "world!" 002056 000154 000144 000041 - 34 002064 000015 000012 000000 .word 15,12,0 ; CR, LF, NUL=end marker - 35 - 36 .end - 36 + 37 002064 000015 000012 000000 .word 15,12,0 ; CR, LF, NUL=end marker + 38 + 39 .end + 39 diff --git a/10.02_devices/3_test/cpu20/multiarb.lst b/10.02_devices/3_test/cpu20/multiarb.lst index 8eb9663..fdb4e29 100644 --- a/10.02_devices/3_test/cpu20/multiarb.lst +++ b/10.02_devices/3_test/cpu20/multiarb.lst @@ -23,9 +23,9 @@ 23 ; DU - MSCP disk drive on UDA controller 24 25 ; enable tests - 26 000000 kwenab = 0 - 27 000000 rkenab = 0 - 28 000000 rlenab = 0 + 26 000001 kwenab = 1 + 27 000001 rkenab = 1 + 28 000001 rlenab = 1 29 000000 ryenab = 0 ; not yet tested 30 000000 duenab = 0 ; not yet implemeneted 31 @@ -44,28 +44,28 @@ 44 000026 000340 .word 340 ; PSW priority level 7 45 46 000060 . = corvec - 47 000060 001132 .word corisr ; RCV interrupt + 47 000060 001264 .word corisr ; RCV interrupt 48 000062 000340 .word 340 49 000064 . = coxvec - 50 000064 001146 .word coxisr ; XMT interrupt + 50 000064 001300 .word coxisr ; XMT interrupt 51 000066 000340 .word 340 52 - 53 000000 .if ne kwenab - 54 . = kwvect - 55 .word kwisr ; periodic interrupt - 56 .word 340 + 53 000001 .if ne kwenab + 54 000100 . = kwvect + 55 000100 001524 .word kwisr ; periodic interrupt + 56 000102 000340 .word 340 57 .endc 58 - 59 000000 .if ne rlenab - 60 . = rlvect ; RL11 - 61 .word rlisr - 62 .word 340 + 59 000001 .if ne rlenab + 60 000160 . = rlvect ; RL11 + 61 000160 004640 .word rlisr + 62 000162 000340 .word 340 63 .endc 64 - 65 000000 .if ne rkenab - 66 . = rkvect ; RK11 - 67 .word rkisr - 68 .word 340 + 65 000001 .if ne rkenab + 66 000220 . = rkvect ; RK11 + 67 000220 002562 .word rkisr + 68 000222 000340 .word 340 69 .endc 70 71 000000 .if ne ryenab @@ -92,16 +92,16 @@ 92 001004 005037 177776 clr @#psw ; priorty level 0, allow INTR 93 ; Initialize devices 94 001010 000005 reset - 95 001012 004737 001154 call corini - 96 001016 004737 001170 call coxini - 97 000000 .if ne kwenab - 98 call kwinit + 95 001012 004737 001306 call corini + 96 001016 004737 001322 call coxini + 97 000001 .if ne kwenab + 98 001022 004737 001536 call kwinit 99 .endc - 100 000000 .if ne rkenab - 101 call rkinit + 100 000001 .if ne rkenab + 101 001026 004737 002570 call rkinit 102 .endc - 103 000000 .if ne rlenab - 104 call rlinit + 103 000001 .if ne rlenab + 104 001032 004737 004646 call rlinit 105 .endc 106 000000 .if ne ryenab 107 call ryinit @@ -110,67 +110,67 @@ 110 call duinit 111 .endc 112 - 113 001022 012701 001366 mov #shello,r1 ; Print "Hello" message - 114 001026 004737 001204 call puts + 113 001036 012701 004766 mov #shello,r1 ; Print "Hello" message + 114 001042 004737 001336 call puts 115 116 ; main loop: check interrupt flags, restart DMA 117 ; process serial input 118 loop: - 119 001032 004737 001044 call dokbd ; check keyboard input - 120 001036 004737 001104 call dodev ; check device activities - 121 001042 000773 br loop + 119 001046 004737 001060 call dokbd ; check keyboard input + 120 001052 004737 001120 call dodev ; check device activities + 121 001056 000773 br loop 122 123 124 125 ; --- check keyboard input 126 dokbd: - 127 001044 004737 001336 call getc - 128 001050 103014 bcc 9$ ; nothing received + 127 001060 004737 001470 call getc + 128 001064 103014 bcc 9$ ; nothing received 129 ; process char in r0 - 130 001052 120027 000003 cmpb r0,#3 - 131 001056 001007 bne 1$ - 132 001060 012701 001457 mov #sbye,r1 ; ^C: print "Bye", back to monitor - 133 001064 004737 001204 call puts - 134 001070 000005 reset ; stop devices - 135 001072 000137 165020 jmp monitr + 130 001066 120027 000003 cmpb r0,#3 + 131 001072 001007 bne 1$ + 132 001074 012701 005057 mov #sbye,r1 ; ^C: print "Bye", back to monitor + 133 001100 004737 001336 call puts + 134 001104 000005 reset ; stop devices + 135 001106 000137 165020 jmp monitr 136 1$: 137 ; echo chars without special meaning - 138 001076 004737 001316 call putc + 138 001112 004737 001450 call putc 139 9$: - 140 001102 000207 return + 140 001116 000207 return 141 142 ; -- check device activities 143 dodev: 144 ; For all devices: restart device DMA if Interrupt received - 145 000000 .if ne kwenab - 146 tst kwiflg - 147 beq 1$ - 148 clr kwiflg - 149 call kwgo - 150 mov #kwlabl,r0 ; progress printout - 151 mov #kwecnt,r1 - 152 call progrs + 145 000001 .if ne kwenab + 146 001120 005737 001520 tst kwiflg + 147 001124 001412 beq 1$ + 148 001126 005037 001520 clr kwiflg + 149 001132 004737 001552 call kwgo + 150 001136 012700 000127 mov #kwlabl,r0 ; progress printout + 151 001142 012701 001522 mov #kwecnt,r1 + 152 001146 004737 001240 call progrs 153 1$: 154 .endc 155 - 156 000000 .if ne rkenab - 157 tst rkiflg - 158 beq 2$ - 159 clr rkiflg - 160 call rkgo - 161 mov #rklabl,r0 ; progress printout - 162 mov #rkecnt,r1 - 163 call progrs + 156 000001 .if ne rkenab + 157 001152 005737 001554 tst rkiflg + 158 001156 001412 beq 2$ + 159 001160 005037 001554 clr rkiflg + 160 001164 004737 002576 call rkgo + 161 001170 012700 000113 mov #rklabl,r0 ; progress printout + 162 001174 012701 002560 mov #rkecnt,r1 + 163 001200 004737 001240 call progrs 164 2$: 165 .endc - 166 000000 .if ne rlenab - 167 tst rliflg - 168 beq 3$ - 169 clr rliflg - 170 call rlgo - 171 mov #rllabl,r0 ; progress printout - 172 mov #rlecnt,r1 - 173 call progrs + 166 000001 .if ne rlenab + 167 001204 005737 002632 tst rliflg + 168 001210 001412 beq 3$ + 169 001212 005037 002632 clr rliflg + 170 001216 004737 004654 call rlgo + 171 001222 012700 000114 mov #rllabl,r0 ; progress printout + 172 001226 012701 004636 mov #rlecnt,r1 + 173 001232 004737 001240 call progrs 174 3$: 175 .endc 176 000000 .if ne ryenab @@ -194,7 +194,7 @@ 194 5$: 195 .endc 196 - 197 001104 000207 return + 197 001236 000207 return 198 199 200 ; progress @@ -202,12 +202,12 @@ 202 ; 1024. if yes, print the char in r0 203 progrs: 204 ; bic #777700,(r1) ; mask counter to 0..63 - 205 001106 042711 177400 bic #777400,(r1) ; mask counter to 0..255 + 205 001240 042711 177400 bic #777400,(r1) ; mask counter to 0..255 206 ; bic #776000,(r1) ; mask counter to 0..1023 - 207 001112 001002 bne 9$ - 208 001114 004737 001316 call putc ; is at 0: print label character + 207 001244 001002 bne 9$ + 208 001246 004737 001450 call putc ; is at 0: print label character 209 9$: - 210 001120 000207 return + 210 001252 000207 return 211 212 213 @@ -224,30 +224,30 @@ 10 11 ; -- ISRs, increment Interrupt FLags 12 - 13 001122 000001 corifl: .word 1 ; Interrupt flags - 14 001124 000001 coxifl: .word 1 + 13 001254 000001 corifl: .word 1 ; Interrupt flags + 14 001256 000001 coxifl: .word 1 15 - 16 001126 corbuf: .blkw 1 ; data buffer - 17 001130 coxbuf: .blkw 1 + 16 001260 corbuf: .blkw 1 ; data buffer + 17 001262 coxbuf: .blkw 1 18 19 corisr: - 20 001132 013737 177562 001126 mov @#corbas+2,corbuf ; read char, clear INTR - 21 001140 005237 001122 inc corifl - 22 001144 000002 rti + 20 001264 013737 177562 001260 mov @#corbas+2,corbuf ; read char, clear INTR + 21 001272 005237 001254 inc corifl + 22 001276 000002 rti 23 24 coxisr: - 25 001146 005237 001124 inc coxifl - 26 001152 000002 rti + 25 001300 005237 001256 inc coxifl + 26 001304 000002 rti 27 28 ; -- Initialize device after RESET 29 corini: - 30 001154 012737 000100 177560 mov #100,@#corbas ; Bit 6 = Receiver Interrupt Enable - 31 001162 005037 001122 clr corifl - 32 001166 000207 return + 30 001306 012737 000100 177560 mov #100,@#corbas ; Bit 6 = Receiver Interrupt Enable + 31 001314 005037 001254 clr corifl + 32 001320 000207 return 33 coxini: - 34 001170 012737 000100 177564 mov #100,@#coxbas ; Bit 6 = Transmitter Interrupt Enable - 35 001176 005037 001124 clr coxifl - 36 001202 000207 return + 34 001322 012737 000100 177564 mov #100,@#coxbas ; Bit 6 = Transmitter Interrupt Enable + 35 001330 005037 001256 clr coxifl + 36 001334 000207 return 37 38 39 @@ -256,75 +256,199 @@ 42 ; puts - print a string 43 ; r1 = pointer, r0,r1 changed 44 puts: - 45 001204 112100 movb (r1)+,r0 ; load xmt char - 46 001206 001403 beq 1$ ; string ends with 0 - 47 001210 004737 001316 call @#putc - 48 001214 000773 br puts ; transmit nxt char of string - 49 001216 000207 1$: return + 45 001336 112100 movb (r1)+,r0 ; load xmt char + 46 001340 001403 beq 1$ ; string ends with 0 + 47 001342 004737 001450 call @#putc + 48 001346 000773 br puts ; transmit nxt char of string + 49 001350 000207 1$: return 50 51 52 ; putnum - print the octal number in r0 - 53 001220 numbf0: .blkw 10 ; space to mount number string - 54 001240 numbf1 =. + 53 001352 numbf0: .blkw 10 ; space to mount number string + 54 001372 numbf1 =. 55 putnum: - 56 001240 010346 mov r3,-(sp) - 57 001242 010002 mov r0,r2 ; r2 = shifter - 58 001244 012701 001240 mov #numbf1,r1 ; r1 = buffer pointer, backwards - 59 001250 112741 000000 movb #0,-(r1) ; set terminating 0 + 56 001372 010346 mov r3,-(sp) + 57 001374 010002 mov r0,r2 ; r2 = shifter + 58 001376 012701 001372 mov #numbf1,r1 ; r1 = buffer pointer, backwards + 59 001402 112741 000000 movb #0,-(r1) ; set terminating 0 60 ; repeat 6 times - 61 001254 012703 000006 mov #6,r3 + 61 001406 012703 000006 mov #6,r3 62 1$: - 63 001260 010200 mov r2,r0 + 63 001412 010200 mov r2,r0 64 ; extract lower 3 bits = octal digit - 65 001262 042700 177770 bic #177770,r0 ; r0 &= 0x07 - 66 001266 062700 000060 add #60,r0 ; r0 += '0' - 67 001272 110041 movb r0,-(r1) ; write in buffer - 68 001274 000241 clc - 69 001276 006202 asr r2 ; shift to next digit - 70 001300 006202 asr r2 - 71 001302 006202 asr r2 - 72 001304 077313 sob r3,1$ ; loop for all 6 digits + 65 001414 042700 177770 bic #177770,r0 ; r0 &= 0x07 + 66 001420 062700 000060 add #60,r0 ; r0 += '0' + 67 001424 110041 movb r0,-(r1) ; write in buffer + 68 001426 000241 clc + 69 001430 006202 asr r2 ; shift to next digit + 70 001432 006202 asr r2 + 71 001434 006202 asr r2 + 72 001436 077313 sob r3,1$ ; loop for all 6 digits 73 - 74 001306 004737 001204 call @#puts - 75 001312 012603 mov (sp)+,r3 - 76 001314 000207 return + 74 001440 004737 001336 call @#puts + 75 001444 012603 mov (sp)+,r3 + 76 001446 000207 return 77 78 79 ; putc - output a single char 80 ; r0 = char 81 putc: - 82 001316 005037 001124 clr coxifl ; reset interrupt flag - 83 001322 010037 177566 mov r0,@#coxbas+2 ; char into transmit buffer - 84 001326 005737 001124 1$: tst coxifl ; XMT RDY? - 85 001332 001775 beq 1$ ; no, loop + 82 001450 005037 001256 clr coxifl ; reset interrupt flag + 83 001454 010037 177566 mov r0,@#coxbas+2 ; char into transmit buffer + 84 001460 005737 001256 1$: tst coxifl ; XMT RDY? + 85 001464 001775 beq 1$ ; no, loop 86 ; UART is buffering: char only started to sent now 87 ; interrupt active until next putc - 88 001334 000207 return + 88 001466 000207 return 89 90 ; getc - poll and input a single char 91 ; result in r0 92 ; carry clear : nothing received 93 ; carry set: char received 94 getc: - 95 001336 005000 clr r0 - 96 001340 005737 001122 tst corifl - 97 001344 001002 bne 1$ - 98 001346 000241 clc ; Carry clear, no Interrupt, nothing received - 99 001350 000207 return + 95 001470 005000 clr r0 + 96 001472 005737 001254 tst corifl + 97 001476 001002 bne 1$ + 98 001500 000241 clc ; Carry clear, no Interrupt, nothing received + 99 001502 000207 return 100 1$: - 101 001352 013700 001126 mov corbuf,r0 ; Interrupt, return char - 102 001356 005037 001122 clr corifl ; reset interrupt flag - 103 001362 000261 sec ; Carry Set - 104 001364 000207 return + 101 001504 013700 001260 mov corbuf,r0 ; Interrupt, return char + 102 001510 005037 001254 clr corifl ; reset interrupt flag + 103 001514 000261 sec ; Carry Set + 104 001516 000207 return 104 - 215 000000 .if ne kwenab + 215 000001 .if ne kwenab 216 .include ma_kw.mac + 1 .title ma_kw - KW11 test driver + 2 + 3 ; KW11 raises INTR at 50 Hz + 4 + 5 000100 kwvect = 100 ; vector of KW11 line clock + 6 177546 kwbase = 777546 ; base addr of KW11 register + 7 000127 kwlabl = 'W ; label char + 8 + 9 + 10 ; --- ISRs, increment Interrupt FLags + 11 001520 000001 kwiflg: .word 1 ; Interrupt flags + 12 + 13 001522 000001 kwecnt: .word 1 ; event counter + 14 + 15 kwisr: + 16 001524 005237 001522 inc kwecnt ; register as event + 17 001530 005237 001520 inc kwiflg ; set ISR flag + 18 001534 000002 rti + 19 + 20 ; --- Initialize device after RESET + 21 kwinit: + 22 001536 012737 000100 177546 mov #100,@#kwbase ; set interrupt enable + 23 001544 005037 001522 clr kwecnt + 24 001550 000207 return + 25 + 26 ; --- Restart new INTR + 27 kwgo: + 28 ; nothing todo, INTR repeated automatically + 29 ; bic #200,@#kwbase ; clear INTERRUPT MONITOR bit + 30 001552 000207 return + 31 + 31 217 .endc - 218 000000 .if ne rkenab + 218 000001 .if ne rkenab 219 .include ma_rk.mac + 1 + 2 .title ma_rk - RK11/RK05 test driver + 3 ; RK11 DMA is generated by reading cylinder 0, head 0, sector 0 + 4 + 5 000220 rkvect = 220 ; vector of RK11 controller + 6 177400 rkbase = 777400 ; base addr of RK11 controller + 7 000113 rklabl = 'K ; label char + 8 + 9 ; --- ISRs, increment Interrupt FLags + 10 001554 000001 rkiflg: .word 1 ; Interrupt flags + 11 + 12 001556 rkbuff: .blkw 400+1 ; data buffer: 1 sector = 256 words + 13 + 14 002560 000001 rkecnt: .word 1 ; event counter + 15 + 16 rkisr: + 17 002562 005237 001554 inc rkiflg ; set ISR flag + 18 002566 000002 rti + 19 + 20 ; --- Initialize device after RESET + 21 rkinit: + 22 002570 005037 002560 clr rkecnt + 23 002574 000207 return + 24 + 25 ; --- Restart new DMA transmission + 26 rkgo: + 27 ; read first sector into rkbuff + 28 002576 005037 177412 clr @#rkbase+12 ; DA disk address = 0: unit 0, cyl/hd/sec=0 + 29 002602 012737 001556 177410 mov #rkbuff,@#rkbase+10 ; BA bus address of DMA + 30 002610 012737 177400 177406 mov #-400,@#rkbase+6 ; WC word count = 256 words + 31 002616 012737 000105 177404 mov #100+4+1,@#rkbase+4 ; Command INT ENABLE + "READ" + GO + 32 002624 005237 002560 inc rkecnt ; register as event + 33 002630 000207 return + 34 + 34 220 .endc - 221 000000 .if ne rlenab + 221 000001 .if ne rlenab 222 .include ma_rl.mac + 1 .title ma_rl - RL11/RL01/2 test driver + 2 + 3 ; RL11 DMA is generated by reading cylinder 0, head0, sector 0 + 4 + 5 000160 rlvect = 160 ; vector of RL11 controller + 6 174400 rlbase = 774400 ; base addr of RL11 controller + 7 000114 rllabl = 'L ; label char + 8 + 9 + 10 ; --- ISRs, increment Interrupt FLags + 11 002632 000001 rliflg: .word 1 ; Interrupt flags + 12 + 13 002634 rlbuff: .blkw 2*400+1 ; data buffer: 2 sector = 256 words + 14 + 15 004636 000001 rlecnt: .word 1 ; event counter + 16 + 17 rlisr: + 18 004640 005237 002632 inc rliflg ; set ISR flag + 19 004644 000002 rti + 20 + 21 ; --- Initialize device after RESET + 22 rlinit: + 23 004646 005037 004636 clr rlecnt + 24 004652 000207 return + 25 + 26 ; --- Restart new DMA transmission + 27 rlgo: + 28 004654 012701 174400 mov #rlbase,r1 ; r1 = controller base address + 29 + 30 ; sequence from boot loader 23-751A9, lot of testing + 31 ; 1. get status + 32 004660 012761 000013 000004 mov #013,4(r1) ; DA subcmd reset+getstatus + 33 004666 012711 000004 mov #4,(r1) ; CSR do "GET STATUS" + 34 004672 105711 1$: tstb (r1) ; test for ready + 35 004674 100376 bpl 1$ ; wait + 36 ; 2. read current track + 37 004676 012711 000010 mov #10,(r1) ; CSR read header cmd + 38 004702 105711 2$: tstb (r1) ; test for ready + 39 004704 100376 bpl 2$ ; wait + 40 ; 3. seek + 41 004706 016102 000006 mov 6(r1),r2 ; MP retrieve cyl/head/sector + 42 004712 042702 000077 bic #77,r2 ; set sector to zero + 43 004716 005202 inc r2 ; set seek flag, head 0, seek to cyl 0 + 44 004720 010261 000004 mov r2,4(r1) ; DA for seek + 45 004724 012711 000006 mov #6,(r1) ; CSR seek cmd + 46 004730 105711 3$: tstb (r1) ; test for ready + 47 004732 100376 bpl 3$ ; wait + 48 ; 4. read sector 0+1 and interrupt + 49 004734 012761 002634 000002 mov #rlbuff,2(r1) ; BA bus address of DMA + 50 004742 005061 000004 clr 4(r1) ; DA select cyl0/head0/sector0 + 51 004746 012761 177000 000006 mov #-512.,6(r1) ; MP set word count + 52 004754 012711 000114 mov #100+14,(r1) ; CSR read data cmd with Interrupt Enable + 53 + 54 004760 005237 004636 inc rlecnt ; register as event + 55 004764 000207 return + 56 + 56 223 .endc 224 000000 .if ne ryenab 225 .include ma_ry.mac @@ -336,36 +460,36 @@ 1 2 .title ma_strings - String constants 3 shello: - 4 001366 015 012 .byte 15,12 ; space, CR, LF, - 5 001370 052 052 052 .ascii /*** Multi Device Interrupt&DMA test ***/ - 001373 040 115 165 - 001376 154 164 151 - 001401 040 104 145 - 001404 166 151 143 - 001407 145 040 111 - 001412 156 164 145 - 001415 162 162 165 - 001420 160 164 046 - 001423 104 115 101 - 001426 040 164 145 - 001431 163 164 040 - 001434 052 052 052 - 6 001437 015 012 .byte 15,12 ; CR, LF - 7 001441 136 103 040 .ascii /^C to stop./ - 001444 164 157 040 - 001447 163 164 157 - 001452 160 056 - 8 001454 015 012 .byte 15,12 ; CR, LF - 9 001456 000 .byte 0 + 4 004766 015 012 .byte 15,12 ; space, CR, LF, + 5 004770 052 052 052 .ascii /*** Multi Device Interrupt&DMA test ***/ + 004773 040 115 165 + 004776 154 164 151 + 005001 040 104 145 + 005004 166 151 143 + 005007 145 040 111 + 005012 156 164 145 + 005015 162 162 165 + 005020 160 164 046 + 005023 104 115 101 + 005026 040 164 145 + 005031 163 164 040 + 005034 052 052 052 + 6 005037 015 012 .byte 15,12 ; CR, LF + 7 005041 136 103 040 .ascii /^C to stop./ + 005044 164 157 040 + 005047 163 164 157 + 005052 160 056 + 8 005054 015 012 .byte 15,12 ; CR, LF + 9 005056 000 .byte 0 10 11 12 sbye: - 13 001457 015 012 .byte 15,12 - 14 001461 107 157 157 .ascii /Good Bye!/ - 001464 144 040 102 - 001467 171 145 041 - 15 001472 015 012 .byte 15,12 ; CR, LF - 16 001474 000 .byte 0 + 13 005057 015 012 .byte 15,12 + 14 005061 107 157 157 .ascii /Good Bye!/ + 005064 144 040 102 + 005067 171 145 041 + 15 005072 015 012 .byte 15,12 ; CR, LF + 16 005074 000 .byte 0 17 17 231 diff --git a/10.03_app_demo/2_src/menu_device_exercisers.cpp b/10.03_app_demo/2_src/menu_device_exercisers.cpp index 92b99a6..7d37203 100644 --- a/10.03_app_demo/2_src/menu_device_exercisers.cpp +++ b/10.03_app_demo/2_src/menu_device_exercisers.cpp @@ -123,7 +123,7 @@ void application_c::menu_device_exercisers(void) { } else if (!strcasecmp(s_opcode, "init")) { unibus->init(50); } else if (!strcasecmp(s_opcode, "pwr")) { - unibus->powercycle(); + unibus->probe_grant_continuity(true); } else if (!strcasecmp(s_opcode, "dbg") && n_fields == 2) { if (!strcasecmp(s_param[0], "c")) { logger->clear(); diff --git a/10.03_app_demo/2_src/menu_devices.cpp b/10.03_app_demo/2_src/menu_devices.cpp index 13b8ed1..6fbdd1b 100644 --- a/10.03_app_demo/2_src/menu_devices.cpp +++ b/10.03_app_demo/2_src/menu_devices.cpp @@ -182,7 +182,7 @@ void application_c::menu_devices(bool with_emulated_CPU) { } // now devices are "Plugged in". Reset PDP-11. - unibus->powercycle(); + unibus->probe_grant_continuity(true); while (!ready) { @@ -261,7 +261,7 @@ void application_c::menu_devices(bool with_emulated_CPU) { } else if (!strcasecmp(s_opcode, "init")) { unibus->init(50); } else if (!strcasecmp(s_opcode, "pwr")) { - unibus->powercycle(); + unibus->probe_grant_continuity(true) ; } else if (!strcasecmp(s_opcode, "dbg") && n_fields == 2) { if (!strcasecmp(s_param[0], "c")) { logger->clear(); diff --git a/10.03_app_demo/2_src/menu_interrupts.cpp b/10.03_app_demo/2_src/menu_interrupts.cpp index 8450adc..09203f3 100644 --- a/10.03_app_demo/2_src/menu_interrupts.cpp +++ b/10.03_app_demo/2_src/menu_interrupts.cpp @@ -121,7 +121,7 @@ void application_c::menu_interrupts(void) { if (!strcasecmp(s_opcode, "q")) { ready = true; } else if (!strcasecmp(s_opcode, "pwr")) { - unibus->powercycle(); + unibus->probe_grant_continuity(true); } else if (!strcasecmp(s_opcode, "m") && n_fields == 1) { emulate_memory(); } else if (!strcasecmp(s_opcode, "e") && n_fields == 2) { diff --git a/10.03_app_demo/2_src/menu_masterslave.cpp b/10.03_app_demo/2_src/menu_masterslave.cpp index 2d95d54..daccc0a 100644 --- a/10.03_app_demo/2_src/menu_masterslave.cpp +++ b/10.03_app_demo/2_src/menu_masterslave.cpp @@ -158,7 +158,7 @@ void application_c::menu_masterslave(bool with_CPU) { } else if (!strcasecmp(s_opcode, "i")) { iopageregisters_print_tables(); } else if (!strcasecmp(s_opcode, "pwr")) { - unibus->powercycle(); + unibus->probe_grant_continuity(true); } else if (!strcasecmp(s_opcode, "m") && n_fields == 3) { uint32_t start_addr, end_addr; parse_addr18(s_param[0], &start_addr);