From 8689c962a08dd52e25725851316aa51a7e22d432 Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 16 May 2011 15:15:17 +0300 Subject: [PATCH] hexed: new pc control code (send/recv only for now) --- hexed/Makefile | 7 +- hexed/hexed.s | 114 ++++--------------- hexed/pc_transfer.c | 267 +++++++++++++++++++++++++++++++++----------- hexed/transfer.S | 174 +++++++++++++++++++++++++++++ hexed/transfer.h | 4 + 5 files changed, 405 insertions(+), 161 deletions(-) create mode 100644 hexed/transfer.S create mode 100644 hexed/transfer.h diff --git a/hexed/Makefile b/hexed/Makefile index f480c15..8b992bd 100644 --- a/hexed/Makefile +++ b/hexed/Makefile @@ -1,12 +1,14 @@ CROSS = m68k-elf- +CC = $(CROSS)gcc AS = $(CROSS)as LD = $(CROSS)ld OBJCOPY = $(CROSS)objcopy ASFLAGS += -m68000 --register-prefix-optional --bitwise-or -pic +CPPFLAGS += -Wa,-m68000 -Wa,--register-prefix-optional -Wa,--bitwise-or -Wa,-pic TARGET = hexed.bin -OBJS = sega_gcc.o hexed.o font.o +OBJS = sega_gcc.o hexed.o transfer.o font.o all : $(TARGET) @@ -23,6 +25,9 @@ pc_transfer: pc_transfer.c gcc -Wall -O2 -ggdb -o $@ $^ +.S.o: + $(CC) -c -o $@ $^ $(CPPFLAGS) + # ----------- release ----------- ifneq ($(findstring rel,$(MAKECMDGOALS)),) ifeq ($(VER),) diff --git a/hexed/hexed.s b/hexed/hexed.s index cdaebcd..b999de1 100644 --- a/hexed/hexed.s +++ b/hexed/hexed.s @@ -37,6 +37,7 @@ .globl main .globl INT .globl VBL +.globl return_to_main ################################################## # # @@ -81,7 +82,7 @@ .equ MMODE_START_MENU, 4 .equ MMODE_GOTO_PREDEF, 5 .equ MMODE_JMP_ADDR, 6 -.equ MMODE_DUMP, 7 +.equ MMODE_PC, 7 .equ predef_addr_cnt, ((predef_addrs_end-predef_addrs)/4) @@ -214,13 +215,6 @@ safe_addrs: dc.l 0xa13000, 0xa130ff safe_addrs_end: -transfer_mode: - dc.l 0x000000 /* 1 for recv */ -transfer_addr: - dc.l 0x000000 -transfer_len: - dc.l 0x000800 - txt_edit: .ascii "- edit -\0" txt_a_confirm: @@ -234,15 +228,13 @@ txt_goto_predef: txt_jmp_addr: .ascii "Jump to address\0" txt_dump: - .ascii "Transfer\0" + .ascii "PC Transfer\0" txt_dtack: .ascii "DTACK safety\0" -txt_ready_send: - .ascii "Ready to send\0" -txt_ready_recv: - .ascii "Ready to recv\0" +txt_transfer_ready: + .ascii "Transfer Ready\0" txt_working: - .ascii "Working.. \0" + .ascii "PC mode \0" txt_dtack_err: .ascii "DTACK err?\0" txt_exc: @@ -265,6 +257,8 @@ txt_exc: .align 2 main: + /* make sure io port 2 is doing inputs */ + move.b #0,(0xa1000b).l /* mask irqs during init */ move.w #0x2700,sr @@ -436,6 +430,12 @@ VBL: addq.b #1,d7 # movem.l d0-d4/a0-a5,-(a7) + btst.b #5,(0xa10005).l + bne no_auto_transfer + change_mode MMODE_PC, MMODE_MAIN + write_vdp_r_dst 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320 | VDP12_STE),(GFXCNTL) + +no_auto_transfer: moveq.l #0,d0 move.w d7,d0 lsr.w #6,d0 @@ -1164,7 +1164,7 @@ msm_no_ud: 0: cmp.b #3,d1 bne 0f - change_mode MMODE_DUMP, MMODE_MAIN + change_mode MMODE_PC, MMODE_MAIN bsr start_menu_box bra vbl_end 0: @@ -1295,20 +1295,11 @@ mode_jmp_finish: move.l d5,a0 jmp (a0) -################### transfer ##################### - mode_transfer: - move.b #0x40,(0xa1000b).l - move.b #0x40,(0xa10005).l + move.b #0x40,(0xa1000b).l /* port 2 ctrl */ + move.b #0x00,(0xa10005).l /* port 2 data - start with TH low */ - move.l (transfer_mode,pc),d0 - tst.l d0 - bne 0f - lea (txt_ready_send,pc),a0 - bra 1f -0: - lea (txt_ready_recv,pc),a0 -1: + lea (txt_transfer_ready,pc),a0 move.l #13,d0 move.l #13,d1 move.l #0x8000,d2 @@ -1320,74 +1311,7 @@ wait_tl_low0: bne wait_tl_low0 menu_text txt_working, 13, 13, 0 - - lea 0xa10005,a1 - move.l (transfer_addr,pc),a0 - move.l (transfer_len,pc),d2 - - move.l (transfer_mode,pc),d0 - tst.l d0 - bne transfer_recv - -transfer_send: - move.b #0x4f,(0xa1000b).l - -tr_send_loop: - move.b (a0),d1 - and.b #0x0f,d1 - -wait_tl_low1: - move.b (a1),d0 - btst.b #4,d0 - bne wait_tl_low1 - - move.b d1,(a1) /* clears TH and writes data */ - - move.b (a0)+,d1 - lsr.b #4,d1 - bset.b #6,d1 /* prepare TH */ - -wait_tl_hi1: - move.b (a1),d0 - btst.b #4,d0 - beq wait_tl_hi1 - - move.b d1,(a1) - subq.l #1,d2 - bne tr_send_loop - - move.b #0,(0xa1000b).l - bra return_to_main - -transfer_recv: - move.b #0,(a1) /* clear TH */ - -tr_recv_loop: -wait_tl_low2: - move.b (a1),d0 - btst.b #4,d0 - bne wait_tl_low2 - - move.b #0x40,(a1) /* set TH */ - move.b d0,d1 - and.b #0x0f,d1 - -wait_tl_hi2: - move.b (a1),d0 - btst.b #4,d0 - beq wait_tl_hi2 - - move.b #0,(a1) /* clear TH */ - lsl.b #4,d0 - or.b d0,d1 - move.b d1,(a0)+ - - subq.l #1,d2 - bne tr_recv_loop - - move.b #0,(0xa1000b).l - bra return_to_main - + bra do_transfer # go back to main mode return_to_main: diff --git a/hexed/pc_transfer.c b/hexed/pc_transfer.c index 844054f..2263a6d 100644 --- a/hexed/pc_transfer.c +++ b/hexed/pc_transfer.c @@ -1,8 +1,12 @@ #include #include +#include #include #include #include +#include + +#include "transfer.h" /* * PC: @@ -26,47 +30,189 @@ * 7 TH --> 10 ACK * 8 GND --- 21 GND * 9 TR <-- 17 /SLCT_IN + * + * start: TH low/high, TL high + * + * TH low - lower nibble: MD ready to recv | MD sent to PC + * TL low - lower niblle: sent to MD | ready to recv from MD + * TH high - upper nibble: MD ready to recv | MD sent to PC + * TL high - upper nibble: sent | ready to recv from MD */ -static void inthandler(int u) +#define ACK_TIMEOUT 2000000 + +#define PORT_DATA 888 +#define PORT_STATUS 889 +#define PORT_CONTROL 890 + +#define timediff(now, start) \ + ((now.tv_sec - start.tv_sec) * 1000000 + now.tv_usec - start.tv_usec) + +static void do_exit(const char *msg) { /* switch TL back to high */ - outb(0xe0, 890); - printf("\n"); + outb(0xe0, PORT_CONTROL); + + if (msg) + printf("%s", msg); exit(1); } -int main(int argc, char *argv[]) +static void inthandler(int u) { - int size, byte, ret, i; - unsigned char *data; - char *p = NULL; - FILE *file; + do_exit("\n"); +} - if (argc != 4 || argv[1][0] != '-' || (argv[1][1] != 'r' && argv[1][1] != 'w')) { - printf("usage:\n%s {-r,-w} \n", argv[0]); - return 1; +static void wait_th_low(void) +{ + struct timeval start, now; + + gettimeofday(&start, NULL); + + while (inb(PORT_STATUS) & 0x40) { + gettimeofday(&now, NULL); + if (timediff(now, start) > ACK_TIMEOUT) + do_exit("timeout waiting TH low\n"); } +} - file = fopen(argv[2], argv[1][1] == 'r' ? "wb" : "rb"); - if (file == NULL) { - fprintf(stderr, "can't open file: %s\n", argv[2]); - return 1; +static void wait_th_high(void) +{ + struct timeval start, now; + + gettimeofday(&start, NULL); + + while (!(inb(PORT_STATUS) & 0x40)) { + gettimeofday(&now, NULL); + if (timediff(now, start) > ACK_TIMEOUT) + do_exit("timeout waiting TH high\n"); } +} + +static unsigned int recv_byte(void) +{ + unsigned int byte; + + outb(0xe2, PORT_CONTROL); /* TL low */ + + wait_th_low(); + + byte = inb(PORT_DATA) & 0x0f; + + outb(0xe0, PORT_CONTROL); /* TL high */ + + wait_th_high(); + + byte |= inb(PORT_DATA) << 4; + + return byte; +} + +static void send_byte(unsigned int byte) +{ + wait_th_low(); + + outb(byte & 0x0f, PORT_DATA); + outb(0xc2, PORT_CONTROL); /* TL low */ + + wait_th_high(); + + outb((byte >> 4) & 0x0f, PORT_DATA); + outb(0xc0, PORT_CONTROL); /* TL high */ +} + +static void send_cmd(unsigned int cmd) +{ + send_byte(CMD_PREFIX); + send_byte(cmd); +} + +static void usage(const char *argv0) +{ + fprintf(stderr, "usage:\n%s [args]\n" + "\tsend [size]\n" + "\trecv \n", argv0); + exit(1); +} + +static unsigned int atoi_or_die(const char *a) +{ + char *p = NULL; + unsigned int i; - size = (int)strtoul(argv[3], &p, 16); + i = strtoul(a, &p, 0); if (p == NULL || *p != 0) { - fprintf(stderr, "can't convert size %s\n", argv[3]); - return 1; + fprintf(stderr, "atoi: can't convert: %s\n", a); + exit(1); } - data = malloc(size); + return i; +} + +int main(int argc, char *argv[]) +{ + unsigned int addr = 0, size = 0, i = 0; + int ret; + unsigned char *data; + FILE *file = NULL; + + if (argc < 2) + usage(argv[0]); + + data = malloc(0x1000000); if (data == NULL) { - fprintf(stderr, "can't alloc %d bytes\n", size); + fprintf(stderr, "can't alloc %d bytes\n", 0x1000000); return 1; } - ret = ioperm(888, 3, 1); + /* parse args, read files.. */ + if (strcmp(argv[1], "send") == 0) + { + if (argc != 4 && argc != 5) + usage(argv[0]); + + file = fopen(argv[2], "rb"); + if (file == NULL) { + fprintf(stderr, "can't open file: %s\n", argv[2]); + return 1; + } + + addr = atoi_or_die(argv[3]); + if (argv[4] == NULL) { + fseek(file, 0, SEEK_END); + size = ftell(file); + fseek(file, 0, SEEK_SET); + } + else + size = atoi_or_die(argv[4]); + + ret = fread(data, 1, size, file); + if (ret != size) { + fprintf(stderr, "fread returned %d/%d\n", ret, size); + perror(NULL); + return 1; + } + } + else if (strcmp(argv[1], "recv") == 0) + { + if (argc != 5) + usage(argv[0]); + + file = fopen(argv[2], "wb"); + if (file == NULL) { + fprintf(stderr, "can't open file: %s\n", argv[2]); + return 1; + } + + addr = atoi_or_die(argv[3]); + size = atoi_or_die(argv[4]); + + memset(data, 0, size); + } + else + usage(argv[0]); + + ret = ioperm(PORT_DATA, 3, 1); if (ret != 0) { perror("ioperm"); return 1; @@ -74,16 +220,28 @@ int main(int argc, char *argv[]) signal(SIGINT, inthandler); - printf("regs: %02x %02x %02x\n", inb(888), inb(889), inb(890)); - outb(0xe0, 890); + printf("regs: %02x %02x %02x\n", + inb(PORT_DATA), inb(PORT_STATUS), inb(PORT_CONTROL)); + outb(0xe8, PORT_CONTROL); /* TR low - request for transfer */ - while (!(inb(889) & 0x40)) { - printf("waiting for TH..\n"); - sleep(5); - } + if (inb(PORT_STATUS) & 0x40) + printf("waiting for TH low..\n"); + while (inb(PORT_STATUS) & 0x40) + sleep(1); + + outb(0xe0, PORT_CONTROL); - if (argv[1][1] == 'r') + if (strcmp(argv[1], "send") == 0) { + printf("send %06x %06x\n", addr, size); + send_cmd(CMD_MD_SEND); + send_byte((addr >> 16) & 0xff); + send_byte((addr >> 8) & 0xff); + send_byte((addr >> 0) & 0xff); + send_byte((size >> 16) & 0xff); + send_byte((size >> 8) & 0xff); + send_byte((size >> 0) & 0xff); + for (i = 0; i < size; i++) { if ((i & 0xff) == 0) { @@ -92,33 +250,19 @@ int main(int argc, char *argv[]) fflush(stdout); } - outb(0xe2, 890); /* TL low */ - - /* wait for TH low */ - while (inb(889) & 0x40) ; - - byte = inb(888) & 0x0f; - - outb(0xe0, 890); /* TL high */ - - /* wait for TH high */ - while (!(inb(889) & 0x40)) ; - - byte |= inb(888) << 4; - data[i] = byte; + send_byte(data[i]); } - - fwrite(data, 1, size, file); } - else + else if (strcmp(argv[1], "recv") == 0) { - ret = fread(data, 1, size, file); - if (ret < size) - printf("warning: read only %d/%d\n", ret, size); - - outb(0xc0, 890); /* out mode, TL hi */ - outb(data[0] & 0x0f, 888); - outb(0xc2, 890); /* out mode, TL low (start condition) */ + send_cmd(CMD_MD_RECV); + send_byte((addr >> 16) & 0xff); + send_byte((addr >> 8) & 0xff); + send_byte((addr >> 0) & 0xff); + send_byte((size >> 16) & 0xff); + send_byte((size >> 8) & 0xff); + send_byte((size >> 0) & 0xff); + outb(0xe0, PORT_CONTROL); /* TL high, recv mode */ for (i = 0; i < size; i++) { @@ -128,25 +272,18 @@ int main(int argc, char *argv[]) fflush(stdout); } - /* wait for TH low */ - while (inb(889) & 0x40) ; - - byte = data[i]; - - outb(byte & 0x0f, 888); - outb(0xc2, 890); /* TL low */ - - /* wait for TH high */ - while (!(inb(889) & 0x40)) ; - - outb(byte >> 4, 888); - outb(0xc0, 890); /* TL high */ + data[i] = recv_byte(); } + + fwrite(data, 1, size, file); } printf("\b\b\b\b\b\b\b\b\b\b\b\b\b"); printf("%06x/%06x\n", i, size); fclose(file); + /* switch TL back to high, disable outputs */ + outb(0xe0, PORT_CONTROL); + return 0; } diff --git a/hexed/transfer.S b/hexed/transfer.S new file mode 100644 index 0000000..0168e49 --- /dev/null +++ b/hexed/transfer.S @@ -0,0 +1,174 @@ +############################################################################### +# +# Copyright (c) 2011, Gražvydas Ignotas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the organization nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Assemble with gas +# --register-prefix-optional --bitwise-or +# + +#include "transfer.h" + +.text +.globl do_transfer + + +# receive 1 byte to d0 +# in: a1 - data port +# trash: d1 +.macro recv_one_byte is_last=0 + move.b #0,(a1) /* clear TH */ + +0: /*L_wait_tl_low*/ + move.b (a1),d1 + btst.b #4,d1 + bne 0b /*L_wait_tl_low*/ + + move.b #0x40,(a1) /* set TH */ + and.b #0x0f,d1 + +0: /*L_wait_tl_hi*/ + move.b (a1),d0 + btst.b #4,d0 + beq 0b /*L_wait_tl_hi*/ + +.if !\is_last + move.b #0,(a1) /* clear TH - ready for next */ +.endif + lsl.b #4,d0 + or.b d1,d0 +.endm + +# send 1 byte in d0 +# in: a1 - data port +# trash: d1,d2 +.macro send_one_byte + move.b d0,d2 + and.b #0x0f,d2 + +0: /*Lwait_tl_low:*/ + move.b (a1),d1 + btst.b #4,d1 + bne 0b /*Lwait_tl_low*/ + + move.b d2,(a1) /* clears TH and writes data */ + + move.b d0,d2 + lsr.b #4,d2 + bset.b #6,d2 /* prepare TH */ + +0: /*wait_tl_hi*/ + move.b (a1),d1 + btst.b #4,d1 + beq 0b /*wait_tl_hi1*/ + + move.b d2,(a1) +.endm + +recv_byte: + recv_one_byte 1 + rts + +# receive address/size to d0 (3 bytes BE) +# in: a1 - data port +# trash: d1,d2 +recv_ad: + moveq.l #0,d2 + bsr recv_byte + move.b d0,d2 + bsr recv_byte + lsl.l #8,d2 + move.b d0,d2 + bsr recv_byte + lsl.l #8,d2 + move.b d0,d2 + move.l d2,d0 + rts + + +do_transfer: + lea 0xa10005,a1 + move.b #0x40,(0xa1000b).l /* ctrl - all inputs except TH */ + move.b #0x00,(a1) + + bsr recv_byte + cmp.b #CMD_PREFIX,d0 + bne return + + bsr recv_byte + cmp.b #CMD_MD_SEND,d0 /* sent to us */ + beq transfer_recv + cmp.b #CMD_MD_RECV,d0 /* recv from us */ + beq transfer_send + bra return + + +transfer_recv: + bsr recv_ad + move.l d0,a0 + bsr recv_ad + move.l d0,d3 + +tr_recv_loop: + recv_one_byte + move.b d0,(a0)+ + subq.l #1,d3 + bne tr_recv_loop + bra return + +transfer_send: + bsr recv_ad + move.l d0,a0 + bsr recv_ad + move.l d0,d3 + +0: /*Lwait_tl_low:*/ + move.b (a1),d0 + btst.b #4,d0 + bne 0b /*Lwait_tl_low*/ + + move.b #0x4f,(0xa1000b).l + move.b #0x40,(a1) + +tr_send_loop: + move.b (a0)+,d0 + send_one_byte + subq.l #1,d3 + bne tr_send_loop + bra return + + +return: + move.b #0,(0xa1000b).l /* all inputs */ + move.l #0xffe000,a1 + move.l d0,(a1)+ /* last state for debug */ + move.l d1,(a1)+ + move.l d2,(a1)+ + move.l d3,(a1)+ + move.l a0,(a1)+ + bra return_to_main + + +# vim:filetype=asmM68k diff --git a/hexed/transfer.h b/hexed/transfer.h new file mode 100644 index 0000000..0fcda0c --- /dev/null +++ b/hexed/transfer.h @@ -0,0 +1,4 @@ +#define CMD_PREFIX 0x5a +#define CMD_MD_SEND 0xc1 /* send to MD: addr[3], len[3], data[] */ +#define CMD_MD_RECV 0xc2 /* recv from MD: addr[3], len[3], data[] */ + -- 2.39.2