📄 skyeye_mach_s3c3410x.c
字号:
io.tf4 |= (((uint64_t)min(data, 0xff)) << (io.tfstat << 3)); io.tfstat += (io.tfstat < 7 ? 1 : 8); break; case 0xf: /* TFCON */ if (index == 4) { io.tfcon = min((data & ~0x2), 0xff); if (data & 0x2) io.tfstat = 0; if (data & 0x1) { io.tf4_repeat[1] = (1 << ((data >> 4) & 0x3)) - 1; io.tf4_repeat[0] = io.tf4_repeat[1]; } } break; default: break; }}/* UART Routine */static void s3c3410x_uart_do_cycle(ARMul_State *state){ int i; unsigned char buf; struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 0; if ((io.ustat & 0x20) == 0 && (io.ucon & 0x3) != 0) { if (skyeye_uart_read(-1, &buf, 1, &tv, NULL) > 0) { io.urxh = buf; io.ustat |= 0x20; io.ufstat = (io.ufstat & ~0x7) | 0x1; if ((io.ucon & 0x3) == 0x1) s3c3410x_set_interrupt(INT_URX); } } for (i = 0; i < 2; i++) { /* DMA request */ if ((io.ucon & 0x3) == 0x2 + i || (io.ucon & 0xc) == 0x8 + i) { int rx_empty = ((io.ucon & 0x3) != 0x0 ? ((io.ustat & 0x20) == 0) : 1); int tx_ready = ((io.ucon & 0xc) != 0x0 ? 1 : 0); ARMword mask = 0; do { if (s3c3410x_dma_is_valid(i) != 1) break; if (((io.dma[i].con >> 2) & 0x3) != 0x2) break; if ((io.dma[i].dst == UTXH || io.dma[i].dst == UTXH_HW || io.dma[i].dst == UTXH_W) && tx_ready) mask |= 0x2 + i; if ((io.dma[i].src == URXH || io.dma[i].src == URXH_HW || io.dma[i].src == URXH_W) && !rx_empty) mask |= 0x8 + i; if ((io.ucon & mask) != 0) s3c3410x_dma_proccess(state, i); } while (0); } }}static void s3c3410x_uart_read(ARMword addr, ARMword *data){ switch (addr) { case ULCON: *data = io.ulcon; break; case UCON: *data = io.ucon; break; case USTAT: *data = io.ustat; break; case UFCON: *data = io.ufcon; break; case UFSTAT: *data = io.ufstat; break; case URXH_W: case URXH_HW: case URXH: *data = io.urxh; io.ustat &= ~0x20; io.ufstat &= ~0x7; break; case UBRDIV: *data = io.ubrdiv; break; default: break; } DEBUG("%s(addr:0x%x, data:0x%x)\n", __FUNCTION__, addr, *data);}static void s3c3410x_uart_write(ARMul_State *state, ARMword addr, ARMword data){ int cnt = 0; DEBUG("%s(addr:0x%x, data:0x%x)\n", __FUNCTION__, addr, data); switch (addr) { case ULCON: io.ulcon = data; break; case UCON: io.ucon = data; break; case UFCON: io.ufcon = data; break; case UTXH_W: cnt = 4; break; case UTXH_HW: cnt = 2; break; case UTXH: cnt = 1; break; case UBRDIV: io.ubrdiv = data; break; default: break; } if (cnt > 0 && (io.ucon & 0xc)) { do { char tmp = data & 0xff; data >>= 8; skyeye_uart_write(-1, (void*)&tmp, 1, NULL); } while (--cnt > 0); if ((io.ucon & 0xc) == 0x4) s3c3410x_set_interrupt(INT_UTX); }}/* DMA Routine */static int s3c3410x_dma_is_valid(int index){ if (!(io.dma[index].con & 0x1)) return -1; if (io.dma[index].cnt == 0) return -1; if (((io.dma[index].con >> 2) & 0x3) == 0x1) return -1; if (((io.dma[index].con >> 2) & 0x3) != 0x0) return 1; return 0;}static void s3c3410x_dma_proccess(ARMul_State *state, int index){ ARMword data, bytes, n = 0; if (io.dma[index].cnt == 0) return; io.dma[index].con |= 0x2;restart: switch ((bytes = (1 << ((io.dma[index].con >> 12) & 0x3)))) { case 1: data = mem_read_byte(state, io.dma[index].src); mem_write_byte(state, io.dma[index].dst, data); break; case 2: data = mem_read_halfword(state, io.dma[index].src); mem_write_halfword(state, io.dma[index].dst, data); break; case 4: data = mem_read_word(state, io.dma[index].src); mem_write_word(state, io.dma[index].dst, data); break; default: return; } if (!((io.dma[index].con >> 7) & 0x1)) { if (((io.dma[index].con >> 5) & 0x1) && io.dma[index].src >= bytes) io.dma[index].src -= bytes; else if (io.dma[index].src <= 0xffffffe - bytes) io.dma[index].src++; } if (!((io.dma[index].con >> 6) & 0x1)) { if (((io.dma[index].con >> 4) & 0x1) && io.dma[index].dst >= bytes) io.dma[index].dst -= bytes; else if (io.dma[index].dst <= 0xffffffe - bytes) io.dma[index].dst++; } if (((io.dma[index].con >> 9) & 0x1) && ++n < 4) goto restart; io.dma[index].cnt -= 1; if (io.dma[index].cnt != 0 && ((io.dma[index].con >> 14) & 0x1)) { if (((io.dma[index].con >> 2) & 0x3) == 0x0) { n = 0; goto restart; } } if (io.dma[index].cnt == 0) { io.dma[index].con &= ~0x3; s3c3410x_set_interrupt(INT_DMA0 + index); }}static void s3c3410x_dma_do_cycle(ARMul_State *state){ int i; for (i = 0; i < 2; i++) { if (s3c3410x_dma_is_valid(i) != 0) continue; s3c3410x_dma_proccess(state, i); }}static void s3c3410x_dma_read(ARMword offset, ARMword *data, int index){ switch (offset) { case 0x0: /* DMASRC */ *data = io.dma[index].src; break; case 0x4: /* DMADST */ *data = io.dma[index].dst; break; case 0x8: /* DMACNT */ *data = io.dma[index].cnt; break; case 0xc: /* DMACON */ *data = io.dma[index].con; break; default: break; } DEBUG("%s(DMA%d, offset:0x%x, data:0x%x)\n", __FUNCTION__, index, offset, *data);}static void s3c3410x_dma_write(ARMul_State *state, ARMword offset, ARMword data, int index){ DEBUG("%s(DMA%d, offset:0x%x, data:0x%x)\n", __FUNCTION__, index, offset, data); switch (offset) { case 0x0: /* DMASRC */ io.dma[index].src = (data & 0xffffffe); break; case 0x4: /* DMADST */ io.dma[index].dst = (data & 0xffffffe); break; case 0x8: /* DMACNT */ io.dma[index].cnt = (data & 0x7ffffff); break; case 0xc: /* DMACON */ io.dma[index].con = (io.dma[index].con & 0x2) | (data & ~0x2); if ((data & 0x1) == 0) { /* stop */ io.dma[index].con &= ~0x2; if (data & 0x100) s3c3410x_set_interrupt(INT_DMA0 + index); } break; default: break; }}/* IO Read Routine */static ARMword s3c3410x_io_read_word(ARMul_State *state, ARMword addr){ ARMword data = -1; /* Interrupt */ if (addr >= INTMOD && addr <= INTPRI7) { s3c3410x_interrupt_read(addr, &data); return data; } /* Timer */ if (addr >= TDAT0 && addr <= TFW4) { s3c3410x_timer_read(addr & 0xf, &data, (addr >> 4) & 0xf); return data; } else if (addr == BTCON) { return (io.btcon & 0xffff); } else if (addr == BTCNT) { return io.btcnt; } /* UART */ if (addr >= ULCON && addr <= UBRDIV) { s3c3410x_uart_read(addr, &data); return data; } /* DMA */ if (addr >= DMASRC0 && addr <= DMACON1 && (addr & 0xfff) <= 0xc) { s3c3410x_dma_read(addr & 0xf, &data, ((addr >> 12) & 0xf) - 3); return data; } switch (addr) { case SYSCFG: data = io.syscfg; break; case SYSCON: data = io.syscon; break; default: DEBUG("UNIMPLEMENTED: %s(addr:0x%08x)\n", __FUNCTION__, addr); break; } return data;}static ARMword s3c3410x_io_read_byte(ARMul_State *state, ARMword addr){ return s3c3410x_io_read_word(state, addr);}static ARMword s3c3410x_io_read_halfword(ARMul_State *state, ARMword addr){ return s3c3410x_io_read_word(state, addr);}/* IO Write Routine */static void s3c3410x_io_write_word(ARMul_State *state, ARMword addr, ARMword data){ /* Interrupt */ if (addr >= INTMOD && addr <= INTPRI7) { s3c3410x_interrupt_write(state, addr, data); return; } /* Timer */ if (addr >= TDAT0 && addr <= TFW4) { s3c3410x_timer_write(state, addr & 0xf, data, (addr >> 4) & 0xf); return; } else if (addr == BTCON) { io.btcon &= ~0xffff; io.btcon |= (data & ~0x1ff03); if (((data >> 8) & 0xff) == 0xa5) io.btcon &= ~0x10000; else if ((data & 0x1) == 0) io.btcon |= ((data & 0xff00) | 0x10000); if (data & 0x2) io.btcnt = 0; return; } /* UART */ if (addr >= ULCON && addr <= UBRDIV) { s3c3410x_uart_write(state, addr, data); return; } /* DMA */ if (addr >= DMASRC0 && addr <= DMACON1 && (addr & 0xfff) <= 0xc) { s3c3410x_dma_write(state, addr & 0xf, data, ((addr >> 12) & 0xf) - 3); return; } switch (addr) { case SYSCFG: io.syscfg = data; break; case SYSCON: io.syscon = data; break; default: DEBUG("UNIMPLEMENTED: %s(addr:0x%08x, data:0x%x)\n", __FUNCTION__, addr, data); break; }}static void s3c3410x_io_write_byte(ARMul_State *state, ARMword addr, ARMword data){ s3c3410x_io_write_word(state, addr, data);}static void s3c3410x_io_write_halfword(ARMul_State *state, ARMword addr, ARMword data){ s3c3410x_io_write_word(state, addr, data);}static void s3c3410x_io_do_cycle(ARMul_State *state){ s3c3410x_timer_do_cycle(state); s3c3410x_uart_do_cycle(state); s3c3410x_dma_do_cycle(state); s3c3410x_update_int(state);}/* Machine Initialization */#define MACH_IO_DO_CYCLE_FUNC(f) ((void (*)(void*))(f))#define MACH_IO_RESET_FUNC(f) ((void (*)(void*))(f))#define MACH_IO_READ_FUNC(f) ((uint32_t (*)(void*, uint32_t))(f))#define MACH_IO_WRITE_FUNC(f) ((void (*)(void*, uint32_t, uint32_t))(f))#define MACH_IO_UPDATE_INT_FUNC(f) ((void (*)(void*))(f))void s3c3410x_mach_init(ARMul_State *state, machine_config_t *this_mach){ if (state->bigendSig != HIGH) { PRINT("*** ERROR: Only support big endian, maybe you need to use \"-b\" option !!!\n"); skyeye_exit(-1); } ARMul_SelectProcessor(state, ARM_v4_Prop); state->lateabtSig = HIGH; state->Reg[1] = 377; this_mach->mach_io_do_cycle = MACH_IO_DO_CYCLE_FUNC(s3c3410x_io_do_cycle); this_mach->mach_io_reset = MACH_IO_RESET_FUNC(s3c3410x_io_reset); this_mach->mach_io_read_word = MACH_IO_READ_FUNC(s3c3410x_io_read_word); this_mach->mach_io_read_halfword = MACH_IO_READ_FUNC(s3c3410x_io_read_halfword); this_mach->mach_io_read_byte = MACH_IO_READ_FUNC(s3c3410x_io_read_byte); this_mach->mach_io_write_word = MACH_IO_WRITE_FUNC(s3c3410x_io_write_word); this_mach->mach_io_write_halfword = MACH_IO_WRITE_FUNC(s3c3410x_io_write_halfword); this_mach->mach_io_write_byte = MACH_IO_WRITE_FUNC(s3c3410x_io_write_byte); this_mach->mach_update_int = MACH_IO_UPDATE_INT_FUNC(s3c3410x_update_int); this_mach->state = (void*)state;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -