📄 skyeye_mach_s3c44b0x.c
字号:
} io.rtc_offset = (long int)mktime(curr_tm) - (long int)curr_time.tv_sec;exit: return;}/* DMA Routine */static void s3c44b0x_dma_proccess(ARMul_State *state, int index){ int i = index; int dal, das, dst, opt_tdm; s3c44b0x_dma_read_func read_func; s3c44b0x_dma_write_func write_func; ARMword ccnt, src_addr, dst_addr, data; ccnt = DMA_CCNT(io.dma[i]); if ((ccnt & 0xfffff) == 0x0) { if ((ccnt & 0x200000) == 0x0) return; memcpy(&io.dma[i][4], &io.dma[i][1], 3 * sizeof(ARMword)); /* auto-reload */ DMA_CON(io.dma[i]) &= ~0x30; DMA_CCNT(io.dma[i]) &= ~0x3000000; return; } src_addr = DMA_CSRC(io.dma[i]); dst_addr = DMA_CDES(io.dma[i]); if ((dal = ((src_addr >> 28) & 0x3)) == 0x0) return; if ((das = ((dst_addr >> 28) & 0x3)) == 0x0) return; if ((dst = ((src_addr >> 30) & 0x3)) == 0x3) return; if (i < 2 && dst != 0x2 && ((ccnt >> 26) & 0x3) == 0x2) return; if ((opt_tdm = ((dst_addr >> 30) & 0x3)) == 0x0 && i >= 2) return; if ((ccnt & 0xfffff) >= (1 << dst)) { read_func = dma_read_funcs[i < 2 ? dst : (3 + (dst * 3) + (opt_tdm - 1))]; write_func = dma_write_funcs[i < 2 ? dst : (3 + (dst * 3) + (opt_tdm - 1))]; if (((ccnt >> 26) & 0x3) != 0x3 || ((ccnt >> 24) & 0x3) != 0x2) { /* read */ data = (*read_func)(state, (src_addr & 0xfffffff)); if (i < 2 && dst != 0 && (opt_tdm & 0x1) != 0x0) /* swap */ data = (dst == 1 ? HALFWORD_SWAP(data) : WORD_SWAP(data)); if (dal == 1) src_addr += min(0xfffffff - (src_addr & 0xfffffff), 1 << dst); else if (dal == 2) src_addr -= min((src_addr & 0xfffffff), 1 << dst); DMA_CSRC(io.dma[i]) = src_addr; } if (((ccnt >> 26) & 0x3) != 0x3 || ((ccnt >> 24) & 0x3) == 0x2) { /* write */ if (((ccnt >> 26) & 0x3) == 0x3) data = DMA_FLY(io.dma[i]); (*write_func)(state, (dst_addr & 0xfffffff), data); if (das == 1) dst_addr += min(0xfffffff - (dst_addr & 0xfffffff), 1 << dst); else if (das == 2) dst_addr -= min((dst_addr & 0xfffffff), 1 << dst); DMA_CDES(io.dma[i]) = dst_addr; } if (((ccnt >> 26) & 0x3) == 0x3) { /* on-the-fly mode */ if (((ccnt >> 24) & 0x3) != 0x2) { DMA_FLY(io.dma[i]) = data; ccnt &= ~0x3000000; ccnt |= 0x2000000; /* Read time */ } else { ccnt |= 0x3000000; /* Write time */ } } } if ((ccnt & 0xfffff) <= (1 << dst)) { /* terminated count */ ccnt &= ~0xfffff; if ((ccnt & 0x200000) == 0x0) ccnt &= ~0x100000; /* clear EN bit */ DMA_CON(io.dma[i]) &= ~0x30; DMA_CON(io.dma[i]) |= 0x20; if (((ccnt >> 22) & 0x3) > 1) s3c44b0x_set_interrupt(INT_ZDMA0 - i); } else { ccnt -= (1 << dst); if (((ccnt >> 22) & 0x3) == 2) s3c44b0x_set_interrupt(INT_ZDMA0 - i); } DMA_CCNT(io.dma[i]) = ccnt;}static int s3c44b0x_dma_is_valid(int index){ ARMword ccnt; if ((DMA_CON(io.dma[index]) & 0xc) != 0x0) return -1; if (((ccnt = DMA_CCNT(io.dma[index])) & 0x100000) == 0x0) return -1; if (index < 2) { /* ZDMA */ if (((ccnt >> 30) & 0x3) < 0x2) return 1; /* DMA request, till now it's impossible in simulation */ } else { /* BDMA */ if (((ccnt >> 26) & 0x3) == 0x3) return -1; /* don't support on-the-fly mode */ if (((ccnt >> 30) & 0x3) != 0x0) return 1; /* DMA request */ } return 0;}static void s3c44b0x_dma_do_cycle(ARMul_State *state){ int i; for (i = 0; i < 4; i++) { if (s3c44b0x_dma_is_valid(i) != 0) continue; s3c44b0x_dma_proccess(state, i); }}static void s3c44b0x_dma_read(ARMword addr, ARMword *data){ s3c44b0x_dma_t *dma = &io.dma[(addr & 0xff) / 0x20 + (addr <= ZDCCNT1 ? 0 : 2)]; ARMword *val = (ARMword*)dma + (((addr & 0xff) % 0x20) >> 2); *data = *val; DEBUG("%s(addr:0x%x, data:0x%x)\n", __FUNCTION__, addr, *data);}static void s3c44b0x_dma_write(ARMul_State *state, ARMword addr, ARMword data){ s3c44b0x_dma_t *dma = &io.dma[(addr & 0xff) / 0x20 + (addr <= ZDCCNT1 ? 0 : 2)]; ARMword *val = (ARMword*)dma + (((addr & 0xff) % 0x20) >> 2); DEBUG("%s(addr:0x%x, data:0x%x)\n", __FUNCTION__, addr, data); if ((addr & 0xff) % 0x20 == 0x00) { /* CON */ *val = ((*val & 0x30) | (data & ~0x33)); if ((data & 0x3) == 0x3) DMA_CSRC((*dma)) &= ~0x100000; /* clear EN bit */ return; } else if ((addr & 0xff) % 0x20 < 0x10) { /* ISRC, IDES, ICNT */ *val = data; *(val + 3) = data; return; } PRINT("ERROR: %s(addr:0x%x, data:0x%x)\n", __FUNCTION__, addr, data);}/* IIS Routine */static int s3c44b0x_iis_write_to_device(ARMul_State *state, ARMhword *buf, int count){ ARMword data; if (buf != s3c44b0x_iisfifo_tx) memcpy(s3c44b0x_iisfifo_tx, buf, count * 2); io_write_word(state, IISFIF_TX_CONTROL, ((0xa << 8) | (0x1 << 4) | count));#if 0 data = io_read_word(state, IISFIF_TX_CONTROL); if ((data & 0xff0) != 0xa20) return -1; return (int)(data & 0xf);#else /* don't care */ return count;#endif}static int s3c44b0x_iis_read_from_device(ARMul_State *state, ARMhword *data){ ARMword tmp; tmp = io_read_word(state, IISFIF_RX_CONTROL); if (((tmp >> 16) & 0xff) != 0x15) return -1; *data = (ARMhword)(tmp & 0xffff); return 0;}static void s3c44b0x_iis_do_cycle(ARMul_State *state){ int count; if ((io.iiscon & 0x1) == 0) return; while (((io.iismod >> 7) & 0x1) && (io.iisfifcon & 0x2f0) > 0x200) { /* handling TX FIFO */ int nWritten = -1; if (io.iisfifo_txcnt > 0) { io.iisfifo_txcnt -= 1; break; } count = (io.iisfifcon >> 4) & 0xf; nWritten = s3c44b0x_iis_write_to_device(state, &io.iisfifo_tx[0], count); if (nWritten <= 0) break; count -= nWritten; io.iisfifcon = ((io.iisfifcon & ~0xf0) | (count << 4)); if (count == 0) { io.iiscon &= ~0x80; io.iisfifo_txcnt = 8; } else { memmove(&io.iisfifo_tx[0], &io.iisfifo_tx[nWritten], count * 2); } break; } while (((io.iismod >> 6) & 0x1) && ((io.iisfifcon >> 8) & 0x1)) { /* handling RX FIFO */ ARMhword tmp; if ((count = io.iisfifcon & 0xf) >= 8) break; if (s3c44b0x_iis_read_from_device(state, &tmp) != 0) break; io.iisfifo_rx[count++] = tmp; io.iisfifcon = ((io.iisfifcon & ~0xf) | count); if (count == 8) io.iiscon &= ~0x40; break; } while ((io.iiscon & 0x30) != 0) { /* BDMA request */ int rx_empty = ((io.iisfifcon & 0x100) ? ((io.iisfifcon & 0xf) == 0) : 0); int tx_ready = ((io.iisfifcon & 0x100) ? (((io.iisfifcon >> 4) & 0xf) < 8) : 1); ARMword mask = 0; if (s3c44b0x_dma_is_valid(2) != 1) break; if (((DMA_CCNT(io.dma[2]) >> 30) & 0x3) != 0x1) break; if ((DMA_CDES(io.dma[2]) & 0xfffffff) == IISFIF + state->bigendSig * 2 && tx_ready) mask |= (0x1 << 5); if ((DMA_CSRC(io.dma[2]) & 0xfffffff) == IISFIF + state->bigendSig * 2 && !rx_empty) mask |= (0x1 << 4); if ((io.iiscon & mask) != 0) s3c44b0x_dma_proccess(state, 2); break; }}static void s3c44b0x_iis_read(ARMul_State *state, ARMword addr, ARMword *data){ switch (addr) { case IISCON: *data = io.iiscon; break; case IISMOD: *data = io.iismod; break; case IISPSR: *data = io.iispsr; break; case IISFIFCON: *data = io.iisfifcon; break; case IISFIF: if (!((io.iiscon & 0x1) && ((io.iismod >> 6) & 0x1))) break; if ((io.iisfifcon & 0x100) != 0) { /* FIFO */ int count = (io.iisfifcon & 0xf); if (count > 0) { *data = io.iisfifo_rx[0]; io.iisfifcon = ((io.iisfifcon & ~0xf) | (--count)); if (count > 0) memmove(&io.iisfifo_rx[0], &io.iisfifo_rx[1], count * 2); io.iiscon |= 0x40; } } else { /* non FIFO */ ARMhword tmp; if (s3c44b0x_iis_read_from_device(state, &tmp) == 0) *data = tmp; } break; default: break; } DEBUG("%s(addr:0x%x, data:0x%x)\n", __FUNCTION__, addr, *data);}static void s3c44b0x_iis_write(ARMul_State *state, ARMword addr, ARMword data){ ARMhword tmp, count; DEBUG("%s(addr:0x%x, data:0x%x)\n", __FUNCTION__, addr, data); switch (addr) { case IISCON: io.iiscon = ((io.iiscon & 0x1c0) | (data & ~0x1c0)); break; case IISMOD: io.iismod = data; break; case IISPSR: io.iispsr = data; break; case IISFIFCON: io.iisfifcon = ((io.iisfifcon & 0xff) | (data & ~0xff)); break; case IISFIF: if (!((io.iiscon & 0x1) && ((io.iismod >> 7) & 0x1))) break; tmp = data & 0xffff; if ((io.iisfifcon & 0x200) != 0) { /* FIFO */ if ((count = ((io.iisfifcon >> 4) & 0xf)) < 8) { io.iisfifo_tx[count++] = tmp; io.iisfifcon = ((io.iisfifcon & ~0xf0) | (count << 4)); io.iiscon |= 0x80; } } else { /* non FIFO */ s3c44b0x_iis_write_to_device(state, &tmp, 1); } break; default: break; }}/* IO Read Routine */static ARMword s3c44b0x_io_read_word(ARMul_State *state, ARMword addr){ ARMword data = -1; /* Interrupt */ if (addr >= INTCON && addr <= F_ISPC) { s3c44b0x_interrupt_read(addr, &data); return data; } /* UART */ if (addr >= ULCON0 && addr <= UBRDIV1) { s3c44b0x_uart_read(addr, &data); return data; } /* Timer */ if ((addr >= WTCON && addr <= WTCNT) || (addr >= TCFG0 && addr <= TCNTO5)) { s3c44b0x_timer_read(addr, &data); return data; } /* I/O Ports */ if (addr >= PCONA && addr <= EXTINTPND) { s3c44b0x_ports_read(addr, &data); return data; } /* RTC */ if (addr >= RTCCON && addr <= TICINT) { s3c44b0x_rtc_read(addr, &data); return data; } /* DMA */ if ((addr >= ZDCON0 && addr <= ZDCCNT1) || (addr >= BDCON0 && addr <= BDCCNT1)) { s3c44b0x_dma_read(addr, &data); return data; } /* IIS */ if (addr >= IISCON && addr <= IISFIF) { s3c44b0x_iis_read(state, addr, &data); return data; } /* TODO */ switch (addr) { case SYSCFG: data = 0x01; /* FIXME */ break; case NCACHBE0: data = io.ncachbe0; break; case NCACHBE1: data = io.ncachbe1; break; case SBUSCON: data = io.sbuscon; break; case BWSCON: data = io.bwscon; break; default: DEBUG("UNIMPLEMENTED: %s(addr:0x%08x)\n", __FUNCTION__, addr); break; } return data;}static ARMword s3c44b0x_io_read_byte(ARMul_State *state, ARMword addr){ ARMword data, offset; data = s3c44b0x_io_read_word(state, (addr & ~0x3)); /* bit offset into the word */ offset = ((state->bigendSig * 3) ^ (addr & 3)) << 3; return ((data >> offset) & 0xff);}static ARMword s3c44b0x_io_read_halfword(ARMul_State *state, ARMword addr){ ARMword data, offset; data = s3c44b0x_io_read_word(state, addr & ~0x3); /* bit offset into the word */ offset = ((state->bigendSig * 2) ^ (addr & 2)) << 3; return ((data >> offset) & 0xffff);}/* IO Write Routine */static void s3c44b0x_io_write_word(ARMul_State *state, ARMword addr, ARMword data){ /* Interrupt */ if (addr >= INTCON && addr <= F_ISPC) { s3c44b0x_interrupt_write(state, addr, data); return; } /* UART */ if (addr >= ULCON0 && addr <= UBRDIV1) { s3c44b0x_uart_write(state, addr, data); return; } /* Timer */ if ((addr >= WTCON && addr <= WTCNT) || (addr >= TCFG0 && addr <= TCNTO5)) { s3c44b0x_timer_write(state, addr, data); return; } /* I/O Ports */ if (addr >= PCONA && addr <= EXTINTPND) { s3c44b0x_ports_write(state, addr, data); return; } /* RTC */ if (addr >= RTCCON && addr <= TICINT) { s3c44b0x_rtc_write(state, addr, data); return; } /* DMA */ if ((addr >= ZDCON0 && addr <= ZDCCNT1) || (addr >= BDCON0 && addr <= BDCCNT1)) { s3c44b0x_dma_write(state, addr, data); return; } /* IIS */ if (addr >= IISCON && addr <= IISFIF) { s3c44b0x_iis_write(state, addr, data); return; } /* TODO */ switch (addr) { case SYSCFG: io.syscfg = data; break; case NCACHBE0: io.ncachbe0 = data; break; case NCACHBE1: io.ncachbe1 = data; break; case SBUSCON: io.sbuscon = data; break; case BWSCON: io.bwscon = (io.bwscon & 0x1) | (data & ~0x1); break; default: DEBUG("UNIMPLEMENTED: %s(addr:0x%08x, data:0x%x)\n", __FUNCTION__, addr, data); break; }}static void s3c44b0x_io_write_byte(ARMul_State *state, ARMword addr, ARMword data){ if ((state->bigendSig * 3) == (addr & 3)) { s3c44b0x_io_write_word(state, addr & ~0x3, data); return; } DEBUG("ERROR: %s(addr:0x%08x, data:0x%x)\n", __FUNCTION__, addr, data);}static void s3c44b0x_io_write_halfword(ARMul_State *state, ARMword addr, ARMword data){ if ((state->bigendSig * 2) == (addr & 3)) { s3c44b0x_io_write_word(state, addr & ~0x3, data); return; } DEBUG("ERROR: %s(addr:0x%08x, data:0x%x)\n", __FUNCTION__, addr, data);}static void s3c44b0x_io_do_cycle(ARMul_State *state){ /* TODO */ s3c44b0x_uart_do_cycle(state); s3c44b0x_timer_do_cycle(state); s3c44b0x_rtc_do_cycle(state); s3c44b0x_dma_do_cycle(state); s3c44b0x_iis_do_cycle(state); s3c44b0x_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))#define MACH_IO_SET_INTR_FUNC(f) ((void (*)(u32))(f))#define MACH_IO_PENDING_INTR_FUNC(f) ((int (*)(u32))(f))#define MACH_IO_UPDATE_INTR_FUNC(f) ((void (*)(void*))(f))void s3c44b0x_mach_init(ARMul_State *state, machine_config_t *this_mach){ ARMul_SelectProcessor(state, ARM_v4_Prop); state->lateabtSig = HIGH; state->Reg[1] = 178; /* R1: machine type : found in linux-2.6.x/include/asm/mach-types.h */ this_mach->mach_io_do_cycle = MACH_IO_DO_CYCLE_FUNC(s3c44b0x_io_do_cycle); this_mach->mach_io_reset = MACH_IO_RESET_FUNC(s3c44b0x_io_reset); this_mach->mach_io_read_word = MACH_IO_READ_FUNC(s3c44b0x_io_read_word); this_mach->mach_io_read_halfword = MACH_IO_READ_FUNC(s3c44b0x_io_read_halfword); this_mach->mach_io_read_byte = MACH_IO_READ_FUNC(s3c44b0x_io_read_byte); this_mach->mach_io_write_word = MACH_IO_WRITE_FUNC(s3c44b0x_io_write_word); this_mach->mach_io_write_halfword = MACH_IO_WRITE_FUNC(s3c44b0x_io_write_halfword); this_mach->mach_io_write_byte = MACH_IO_WRITE_FUNC(s3c44b0x_io_write_byte); this_mach->mach_update_int = MACH_IO_UPDATE_INT_FUNC(s3c44b0x_update_int); /* mach_set_intr, mach_pending_intr, mach_update_intr, state : for devices, such as NET,LCD etc. */ this_mach->mach_set_intr = MACH_IO_SET_INTR_FUNC(s3c44b0x_set_interrupt); this_mach->mach_pending_intr = MACH_IO_PENDING_INTR_FUNC(s3c44b0x_pending_intr); this_mach->mach_update_intr = MACH_IO_UPDATE_INTR_FUNC(s3c44b0x_update_intr); this_mach->state = (void*)state;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -