mirror of
https://github.com/livingcomputermuseum/UniBone.git
synced 2026-02-27 01:00:00 +00:00
CPU20 UNIBUS Interrupt, Experiments to probe UNIBUS arbitrator
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include <stdint.h>
|
||||
#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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user