From: notaz Date: Fri, 20 May 2011 11:41:28 +0000 (+0300) Subject: hexed: add simple io commands X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=93c5aa8a4e294c0736b3ddd02b57b3b4f353e539;p=megadrive.git hexed: add simple io commands seems to have some race condition/timing issues.. --- diff --git a/hexed/pc_transfer.c b/hexed/pc_transfer.c index 9e2681a..569acfc 100644 --- a/hexed/pc_transfer.c +++ b/hexed/pc_transfer.c @@ -74,22 +74,28 @@ #define timediff(now, start) \ ((now.tv_sec - start.tv_sec) * 1000000 + now.tv_usec - start.tv_usec) -static void do_exit(const char *msg) +#define PBE2(p) ((*(p) << 8) | *(p+1)) +#define PBE3(p) ((*(p) << 16) | (*(p + 1) << 8) | *(p + 2)) +#define PBE4(p) ((*(p) << 24) | (*(p + 1) << 16) | (*(p + 2) << 8) | *(p + 3)) + +static void do_exit(const char *msg, const char *where) { /* switch TL back to high */ outb(0xe0, PORT_CONTROL); + if (where) + fprintf(stderr, "%s: ", where); if (msg) - printf("%s", msg); + fprintf(stderr, "%s", msg); exit(1); } static void inthandler(int u) { - do_exit("\n"); + do_exit("\n", NULL); } -static void wait_th_low(void) +static void wait_th_low(const char *where) { struct timeval start, now; @@ -98,11 +104,11 @@ static void wait_th_low(void) while (inb(PORT_STATUS) & 0x40) { gettimeofday(&now, NULL); if (timediff(now, start) > ACK_TIMEOUT) - do_exit("timeout waiting TH low\n"); + do_exit("timeout waiting TH low\n", where); } } -static void wait_th_high(void) +static void wait_th_high(const char *where) { struct timeval start, now; @@ -111,42 +117,68 @@ static void wait_th_high(void) while (!(inb(PORT_STATUS) & 0x40)) { gettimeofday(&now, NULL); if (timediff(now, start) > ACK_TIMEOUT) - do_exit("timeout waiting TH high\n"); + do_exit("timeout waiting TH high\n", where); } } +static void output_to_input(void) +{ + /* TL high, recv mode; also give time + * MD to see TL before we lower it in recv_byte */ + outb(0xe0, PORT_CONTROL); + usleep(4*10); /* must be at least 12+8+8 M68k cycles, 28/7.67M */ +} + +static void input_to_output(void) +{ + wait_th_low("input_to_output"); + outb(0xc0, PORT_CONTROL); /* TL high, out mode */ +} + static unsigned int recv_byte(void) { unsigned int byte; outb(0xe2, PORT_CONTROL); /* TL low */ - wait_th_low(); + wait_th_low("recv_byte"); byte = inb(PORT_DATA) & 0x0f; outb(0xe0, PORT_CONTROL); /* TL high */ - wait_th_high(); + wait_th_high("recv_byte"); byte |= inb(PORT_DATA) << 4; return byte; } +static void recv_bytes(unsigned char *b, size_t count) +{ + while (count-- > 0) + *b++ = recv_byte(); +} + static void send_byte(unsigned int byte) { - wait_th_low(); + wait_th_low("recv_bytes"); outb(byte & 0x0f, PORT_DATA); outb(0xc2, PORT_CONTROL); /* TL low */ - wait_th_high(); + wait_th_high("recv_bytes"); outb((byte >> 4) & 0x0f, PORT_DATA); outb(0xc0, PORT_CONTROL); /* TL high */ } +static void send_bytes(unsigned char *b, size_t count) +{ + while (count-- > 0) + send_byte(*b++); +} + static void send_cmd(unsigned int cmd) { send_byte(CMD_PREFIX); @@ -178,7 +210,8 @@ static unsigned int atoi_or_die(const char *a) int main(int argc, char *argv[]) { - unsigned int addr = 0, size = 0, i = 0; + unsigned int addr = 0, size = 0; + unsigned int count = 0, i = 0; int ret; unsigned char *data; FILE *file = NULL; @@ -243,6 +276,52 @@ int main(int argc, char *argv[]) addr = atoi_or_die(argv[2]); } + else if (strcmp(argv[1], "io") == 0) + { + unsigned int cmd = 0, value, iosize; + unsigned char *p = data; + + for (i = 2; i < argc; ) { + if (argv[i][0] == 'r') + cmd = IOSEQ_R8; + else if (argv[i][0] == 'w') + cmd = IOSEQ_W8; + else + usage(argv[0]); + + iosize = atoi_or_die(&argv[i][1]); + if (iosize == 32) + cmd += 2; + else if (iosize == 16) + cmd += 1; + else if (iosize != 8) + usage(argv[0]); + *p++ = cmd; + i++; + + addr = atoi_or_die(argv[i]); + *p++ = addr >> 16; + *p++ = addr >> 8; + *p++ = addr >> 0; + i++; + + if (cmd == IOSEQ_W8 || cmd == IOSEQ_W16 || cmd == IOSEQ_W32) { + value = atoi_or_die(argv[i]); + switch (iosize) { + case 32: + *p++ = value >> 24; + *p++ = value >> 16; + case 16: + *p++ = value >> 8; + case 8: + *p++ = value >> 0; + } + i++; + } + + count++; + } + } else usage(argv[0]); @@ -295,7 +374,7 @@ int main(int argc, char *argv[]) send_byte((size >> 16) & 0xff); send_byte((size >> 8) & 0xff); send_byte((size >> 0) & 0xff); - outb(0xe0, PORT_CONTROL); /* TL high, recv mode */ + output_to_input(); for (i = 0; i < size; i++) { @@ -317,6 +396,58 @@ int main(int argc, char *argv[]) send_byte((addr >> 8) & 0xff); send_byte((addr >> 0) & 0xff); } + else if (strcmp(argv[1], "io") == 0) + { + unsigned char *p = data; + unsigned char rdata[4]; + send_cmd(CMD_IOSEQ); + send_byte((count >> 8) & 0xff); + send_byte((count >> 0) & 0xff); + + for (; count > 0; count--) { + input_to_output(); + send_bytes(p, 4); /* cmd + addr */ + + switch (p[0]) { + case IOSEQ_R8: + output_to_input(); + recv_bytes(rdata, 1); + printf("r8 %06x %02x\n", PBE3(p + 1), rdata[0]); + p += 4; + break; + case IOSEQ_R16: + output_to_input(); + recv_bytes(rdata, 2); + printf("r16 %06x %04x\n", PBE3(p + 1), PBE2(rdata)); + p += 4; + break; + case IOSEQ_R32: + output_to_input(); + recv_bytes(rdata, 4); + printf("r32 %06x %08x\n", PBE3(p + 1), PBE4(rdata)); + p += 4; + break; + case IOSEQ_W8: + send_bytes(&p[4], 1); + printf("w8 %06x %02x\n", PBE3(p + 1), p[4]); + p += 5; + break; + case IOSEQ_W16: + send_bytes(&p[4], 2); + printf("w16 %06x %04x\n", PBE3(p + 1), PBE2(p + 4)); + p += 6; + break; + case IOSEQ_W32: + send_bytes(&p[4], 4); + printf("w32 %06x %08x\n", PBE3(p + 1), PBE4(p + 4)); + p += 8; + break; + default: + do_exit("error in ioseq data\n", NULL); + break; + } + } + } if (file != NULL) { printf("\b\b\b\b\b\b\b\b\b\b\b\b\b"); diff --git a/hexed/transfer.S b/hexed/transfer.S index 4ab3aff..0115dd9 100644 --- a/hexed/transfer.S +++ b/hexed/transfer.S @@ -108,6 +108,10 @@ recv_ad: move.l d2,d0 rts +send_byte: + send_one_byte + rts + do_transfer: lea 0xa10005,a1 @@ -132,9 +136,11 @@ jumptab: bra pcc_transfer_recv /* sent to us */ bra pcc_transfer_send /* recv from us */ bra pcc_jump + bra pcc_io bra pcc_test_code +/* receive data from PC */ pcc_transfer_recv: bsr recv_ad move.l d0,a0 @@ -149,13 +155,14 @@ tr_recv_loop: bra return +/* send data to PC */ pcc_transfer_send: bsr recv_ad move.l d0,a0 bsr recv_ad move.l d0,d3 -0: /*Lwait_tl_low:*/ +0: /*Lwait_tl_low: it should switch to rx mode before lowering tl */ move.b (a1),d0 btst.b #4,d0 bne 0b /*Lwait_tl_low*/ @@ -171,16 +178,124 @@ tr_send_loop: bra return +/* call specified location */ pcc_jump: bsr recv_ad move.l d0,a0 - jmp (a0) + jsr (a0) + bra return + + +/* do simple i/o commands */ +pcc_io: + moveq.l #0,d4 + bsr recv_byte + move.b d0,d4 + bsr recv_byte + lsl.l #8,d4 + move.b d0,d4 +pcc_io_loop: + move.b #0x40,(0xa1000b).l /* input mode */ + sub.w #1,d4 + bmi return + + bsr recv_byte + move.b d0,d3 /* cmd */ + + bsr recv_ad + move.l d0,a2 /* addr */ + + cmp.b #IOSEQ_W32, d3 + beq pcc_io_w32 + cmp.b #IOSEQ_W16, d3 + beq pcc_io_w16 + cmp.b #IOSEQ_W8, d3 + bne pcc_io_rx + +pcc_io_w8: + bsr recv_byte + move.b d0,(a2) + bra pcc_io_loop + +pcc_io_w16: + bsr recv_byte + move.b d0,d3 + bsr recv_byte + lsl.w #8,d3 + move.b d0,d3 + move.w d3,(a2) + bra pcc_io_loop + +pcc_io_w32: + bsr recv_byte + move.b d0,d3 + bsr recv_byte + lsl.w #8,d3 + move.b d0,d3 + bsr recv_byte + lsl.l #8,d3 + move.b d0,d3 + bsr recv_byte + lsl.l #8,d3 + move.b d0,d3 + move.l d3,(a2) + bra pcc_io_loop + +pcc_io_rx: +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) + + cmp.b #IOSEQ_R32, d3 + beq pcc_io_r32 + cmp.b #IOSEQ_R16, d3 + beq pcc_io_r16 + cmp.b #IOSEQ_R8, d3 + bne return + +pcc_io_r8: + move.b (a2),d0 + bsr send_byte + bra pcc_io_loop + +pcc_io_r16: + move.w (a2),d3 + move.w d3,d0 + lsr.w #8,d0 + bsr send_byte + move.b d3,d0 + bsr send_byte + bra pcc_io_loop + +pcc_io_r32: + move.l (a2),d3 + move.l d3,d0 + swap d0 + lsr.l #8,d0 + bsr send_byte + move.l d3,d0 + swap d0 + bsr send_byte + move.w d3,d0 + lsr.w #8,d0 + bsr send_byte + move.b d3,d0 + bsr send_byte + bra pcc_io_loop + + +/* some random code */ pcc_test_code: bra return + return: move.b #0,(0xa1000b).l /* all inputs */ move.l #0xffe000,a1 diff --git a/hexed/transfer.h b/hexed/transfer.h index b1aa7cd..b5a9817 100644 --- a/hexed/transfer.h +++ b/hexed/transfer.h @@ -1,8 +1,18 @@ +/* all data is big endian */ + #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[] */ #define CMD_JUMP 0xc3 /* jump to addr: addr[3] */ -#define CMD_TEST 0xc4 /* test code */ +#define CMD_IOSEQ 0xc4 /* perform i/o ops: count[2], [type[1], addr[3], data[{0,1,2,4}]]* */ +#define CMD_TEST 0xc5 /* test code */ #define CMD_FIRST CMD_MD_SEND #define CMD_LAST CMD_TEST + +#define IOSEQ_R8 0xb0 +#define IOSEQ_R16 0xb1 +#define IOSEQ_R32 0xb2 +#define IOSEQ_W8 0xb3 +#define IOSEQ_W16 0xb4 +#define IOSEQ_W32 0xb5