diff options
Diffstat (limited to 'avr/z180-serv.c')
-rw-r--r-- | avr/z180-serv.c | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/avr/z180-serv.c b/avr/z180-serv.c new file mode 100644 index 0000000..a920465 --- /dev/null +++ b/avr/z180-serv.c @@ -0,0 +1,288 @@ +#include "common.h" +#include <util/atomic.h> + +#include "background.h" +#include "serial.h" +#include "z80-if.h" +#include "debug.h" +#include "z180-serv.h" + + + +/*--------------------------------------------------------------------------*/ + + +uint8_t z80_get_byte(uint32_t adr) +{ + uint8_t data; + + z80_bus_cmd(Request); + data = z80_read(adr); + z80_bus_cmd(Release); + + return data; +} + + +/*--------------------------------------------------------------------------*/ + +struct msg_item { + uint8_t fct; + uint8_t sub_min, sub_max; + void (*func)(uint8_t, int, uint8_t *); +}; + +uint32_t msg_to_addr(uint8_t *msg) +{ + union { + uint32_t as32; + uint8_t as8[4]; + } addr; + + addr.as8[0] = msg[0]; + addr.as8[1] = msg[1]; + addr.as8[2] = msg[2]; + addr.as8[3] = 0; + + return addr.as32; +} + + +void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg) +{ + (void)len; + + z80_memfifo_init(subf, msg_to_addr(msg)); +} + + +void do_msg_char_out(uint8_t subf, int len, uint8_t * msg) +{ + (void)subf; + + while (len--) + putchar(*msg++); +} + + +const FLASH struct msg_item z80_messages[] = +{ + { 0, /* fct nr. */ + 1, 3, /* sub fct nr. from, to */ + do_msg_ini_memfifo}, + { 1, + 1, 1, + do_msg_char_out}, + { 0xff, /* end mark */ + 0, 0, + 0}, + +}; + + + + +void do_message(int len, uint8_t *msg) +{ + uint8_t fct, sub_fct; + int_fast8_t i = 0; + + if (len >= 2) { + fct = *msg++; + sub_fct = *msg++; + len -= 2; + + while (fct != z80_messages[i].fct) { + if (z80_messages[i].fct == 0xff) { + DBG_P(1, "do_message: Unknown function: %i, %i\n", + fct, sub_fct); + return; /* TODO: unknown message # */ + } + + ++i; + } + + while (fct == z80_messages[i].fct) { + if (sub_fct >= z80_messages[i].sub_min && + sub_fct <= z80_messages[i].sub_max ) + break; + ++i; + } + + if (z80_messages[i].fct != fct) { + DBG_P(1, "do_message: Unknown sub function: %i, %i\n", + fct, sub_fct); + return; /* TODO: unknown message sub# */ + } + + (z80_messages[i].func)(sub_fct, len, msg); + + + } else { + /* TODO: error */ + DBG_P(1, "do_message: to few arguments (%i); this shouldn't happen!\n", len); + } +} + + + +#define CTRBUF_LEN 256 + +void check_msg_fifo(void) +{ + int ch; + static int_fast8_t state; + static int msglen,idx; + static uint8_t buffer[CTRBUF_LEN]; + + while ((ch = z80_memfifo_getc(fifo_msgin)) >= 0) { + switch (state) { + case 0: /* wait for start of message */ + if (ch == 0xAE) { /* TODO: magic number */ + msglen = 0; + idx = 0; + state = 1; + } + break; + case 1: /* get msg len */ + if (ch > 0 && ch <= CTRBUF_LEN) { + msglen = ch; + state = 2; + } else + state = 0; + break; + case 2: /* get message */ + buffer[idx++] = ch; + if (idx == msglen) { + do_message(msglen, buffer); + state = 0; + } + break; + } + } +} + + +int msg_handling(int state) +{ + uint8_t pending; + + ATOMIC_BLOCK(ATOMIC_FORCEON) { + pending = (Stat & S_MSG_PENDING) != 0; + Stat &= ~S_MSG_PENDING; + } + + if (pending) { + switch (state) { + case 0: + z80_bus_cmd(Request); + uint32_t addr = z80_read(0x40) + + ((uint16_t) z80_read(0x41) << 8) + + ((uint32_t) z80_read(0x42) << 16); + z80_bus_cmd(Release); + if (addr != 0) { + z80_memfifo_init(fifo_msgin, addr); + state = 1; + } + break; + case 1: + check_msg_fifo(); + break; + } + } + + return state; +} + + +static int handle_msg_handling; + +void setup_z180_serv(void) +{ + + handle_msg_handling = bg_register(msg_handling, 0); +} + +void restart_z180_serv(void) +{ + z80_bus_cmd(Request); + z80_write(0x40, 0); + z80_write(0x41, 0); + z80_write(0x42, 0); + z80_bus_cmd(Release); + + for (int i = 0; i < NUM_FIFOS; i++) + z80_memfifo_init(i, 0); + bg_setstat(handle_msg_handling, 0); +} + +/*--------------------------------------------------------------------------*/ + +#if 0 +void dump_mem(const FLASH uint8_t *addr, uint32_t len) +{ + DBG_P(1, "hdrom dump:"); + while (len) { + DBG_P(1, "\n %.5x:", addr); + for (unsigned i = 0; i<16; i++) + DBG_P(1, " %.2x", *addr++); + len -= len > 16 ? 16 : len; + } + DBG_P(1, "\n"); +} +#endif +/*--------------------------------------------------------------------------*/ + + +const FLASH uint8_t iniprog[] = { + 0xAF, // xor a + 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh + 0x3E, 0x30, // ld a,030h + 0xED, 0x39, 0x32 //out0 (dcntl),a ;0 mem, max i/0 wait states +}; + +const FLASH uint8_t sertest[] = { + 0xAF, // xor a + 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh + 0x3E, 0x30, // ld a,030h + 0xED, 0x39, 0x32, // out0 (dcntl),a ;0 mem, max i/0 wait states + 0x3E, 0x80, // ld a,M_MPBT ;no MP, PS=10, DR=16, SS=0 + 0xED, 0x39, 0x03, // out0 (cntlb1),a + 0x3E, 0x64, // ld a,M_RE + M_TE + M_MOD2 ; + 0xED, 0x39, 0x01, // out0 (cntla1),a + 0x3E, 0x00, // ld a,0 + 0xED, 0x39, 0x05, // out0 (stat1),a ;Enable rx interrupts + 0xED, 0x38, 0x05, //l0:in0 a,(stat1) + 0xE6, 0x80, // and 80h + 0x28, 0xF9, // jr z,l0 + 0xED, 0x00, 0x09, // in0 b,(rdr1) + 0xED, 0x38, 0x05, //l1:in0 a,(stat1) + 0xE6, 0x02, // and 02h + 0x28, 0xF9, // jr z,l1 + 0xED, 0x01, 0x07, // out0 (tdr1),b + 0x18, 0xEA, // jr l0 +}; + +const FLASH uint8_t test1[] = { + 0xAF, // xor a + 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh + 0x3E, 0x30, // ld a,030h + 0xED, 0x39, 0x32, // out0 (dcntl),a ;0 mem, max i/0 wait states + 0x21, 0x1E, 0x00, // ld hl,dmclrt ;load DMA registers + 0x06, 0x08, // ld b,dmct_e-dmclrt + 0x0E, 0x20, // ld c,sar0l + 0xED, 0x93, // otimr + 0x3E, 0xC3, // ld a,0c3h ;dst +1, src +1, burst + 0xED, 0x39, 0x31, // out0 (dmode),a ; + 0x3E, 0x62, // ld a,062h ;enable dma0, + 0xED, 0x39, 0x30, //cl_1: out0 (dstat),a ;copy 64k + 0x18, 0xFB, // jr cl_1 ; + 0x00, 0x00, //dmclrt: dw 0 ;src (inc) + 0x00, // db 0 ;src + 0x00, 0x00, // dw 0 ;dst (inc), + 0x00, // db 0 ;dst + 0x00, 0x00, // dw 0 ;count (64k) +}; + + + |