static bool istrapwait(void) { for (int i = 0; i < RTAREA_TRAP_DATA_NUM + RTAREA_TRAP_DATA_SEND_NUM; i++) { uae_u8 *data = rtarea_bank.baseaddr + RTAREA_TRAP_DATA + i * RTAREA_TRAP_DATA_SLOT_SIZE; uae_u8 *status = rtarea_bank.baseaddr + RTAREA_TRAP_STATUS + i * RTAREA_TRAP_STATUS_SIZE; if (get_long_host(data + RTAREA_TRAP_DATA_TASKWAIT) && status[3] && status[2] >= 0x80) { return true; } } return false; }
void trap_get_longs(TrapContext *ctx, uae_u32 *haddr, uaecptr addr, int cnt) { if (cnt <= 0) return; if (trap_is_indirect_null(ctx)) { while (cnt > 0) { int max = cnt > RTAREA_TRAP_DATA_EXTRA_SIZE / sizeof(uae_u32) ? RTAREA_TRAP_DATA_EXTRA_SIZE / sizeof(uae_u32) : cnt; call_hardware_trap_back(ctx, TRAPCMD_GET_LONGS, addr, ctx->amiga_trap_data + RTAREA_TRAP_DATA_EXTRA, max, 0); for (int i = 0; i < max; i++) { *haddr++ = get_long_host(ctx->host_trap_data + RTAREA_TRAP_DATA_EXTRA + i * sizeof(uae_u32)); } addr += max * sizeof(uae_u32); cnt -= max; } } else { uae_u32 *p = (uae_u32*)haddr; for (int i = 0; i < cnt; i++) { *p++ = get_long(addr); addr += 4; } } }
static void hardware_trap_ack(TrapContext *ctx) { uae_u8 *data = ctx->host_trap_data; uae_u8 *status = ctx->host_trap_status; uaecptr addr = ctx->amiga_trap_status; // ack call_hardware_trap uaecptr task = get_long_host(data + RTAREA_TRAP_DATA_TASKWAIT); #if NEW_TRAP_DEBUG write_log(_T("TRAP SLOT %d: ACK. TASK = %08x\n"), ctx->trap_slot, task); #endif put_byte_host(status + 2, 0xff); if (task && trap_mode == 1) { atomic_or(&uae_int_requested, 0x4000); set_special_exter(SPCFLAG_UAEINT); } if (!trap_in_use[ctx->trap_slot]) write_log(_T("TRAP SLOT %d ACK WIIHOUT ALLOCATION!\n")); trap_in_use[ctx->trap_slot] = false; xfree(ctx); }
static uae_u32 call_hardware_trap_back(TrapContext *ctx, uae_u16 cmd, uae_u32 p1, uae_u32 p2, uae_u32 p3, uae_u32 p4) { int trap_slot = ((ctx->amiga_trap_data & 0xffff) - RTAREA_TRAP_DATA) / RTAREA_TRAP_DATA_SLOT_SIZE; uae_u8 *data = ctx->host_trap_data + RTAREA_TRAP_DATA_SECOND; uae_u8 *status = ctx->host_trap_status + RTAREA_TRAP_STATUS_SECOND; #if NEW_TRAP_DEBUG write_log(_T("TRAP BACK SLOT %d: CMD=%d P=%08x %08x %08x %08x TASK=%08x\n"), trap_slot, cmd, p1, p2, p3, p4, get_long_host(ctx->host_trap_data + RTAREA_TRAP_DATA_TASKWAIT)); #endif if (trap_slot != ctx->trap_slot) write_log(_T("Trap trap slot mismatch %d <> %d!\n"), trap_slot, ctx->trap_slot); if (trap_in_use2[trap_slot]) write_log(_T("Trap slot %d already in use2!\n"), trap_slot); trap_in_use2[trap_slot] = true; put_long_host(data + 4, p1); put_long_host(data + 8, p2); put_long_host(data + 12, p3); put_long_host(data + 16, p4); put_word_host(status, cmd); volatile uae_u8 *d = status + 3; if (ctx->trap_mode == 2) { *d = 0xfe; // signal rtarea_bget wait uae_sem_post(&hardware_trap_event2[trap_slot]); } else if (ctx->trap_mode == 0) { *d = 0xfe; } else { atomic_inc(&hwtrap_waiting); atomic_or(&uae_int_requested, 0x2000); set_special_exter(SPCFLAG_UAEINT); *d = 0xff; } for (;;) { if (hardware_trap_kill[trap_slot] < 0) return 0; uae_u8 v = *d; if (v == 0x01 || v == 0x02 || v == 0x03) break; if (hardware_trap_kill[trap_slot] == 0) { hardware_trap_kill[trap_slot] = 2; return 0; } if (uae_sem_trywait_delay(&hardware_trap_event[trap_slot], 100) == -2) { hardware_trap_kill[trap_slot] = 3; return 0; } } // get result uae_u32 v = get_long_host(data + 4); if (!trap_in_use2[trap_slot]) write_log(_T("Trap slot %d in use2 unexpected release!\n"), trap_slot); trap_in_use2[trap_slot] = false; put_long_host(status, 0); #if NEW_TRAP_DEBUG write_log(_T("TRAP BACK SLOT %d: RET = %08x TASK = %08x\n"), trap_slot, v, get_long_host(ctx->host_trap_data + RTAREA_TRAP_DATA_TASKWAIT)); #endif return v; }
static void *hardware_trap_thread(void *arg) { int tid = (uae_u32)arg; for (;;) { TrapContext *ctx = (TrapContext*)read_comm_pipe_pvoid_blocking(&trap_thread_pipe[tid]); if (!ctx) break; if (trap_in_use[ctx->trap_slot]) { write_log(_T("TRAP SLOT %d ALREADY IN USE!\n")); } trap_in_use[ctx->trap_slot] = true; uae_u8 *data = ctx->host_trap_data; uae_u8 *status = ctx->host_trap_status; ctx->tindex = tid; ctx->tcnt = ++trap_cnt; for (int i = 0; i < 15; i++) { uae_u32 v = get_long_host(data + 4 + i * 4); ctx->saved_regs.regs[i] = v; } put_long_host(status + RTAREA_TRAP_STATUS_SECOND, 0); #if NEW_TRAP_DEBUG //if (_tcscmp(trap->name, _T("exter_int_helper"))) write_log(_T("TRAP SLOT %d: NUM %d\n"), ctx->trap_slot, trap_num); #endif uae_u32 ret; struct Trap *trap = NULL; if (ctx->trap_done) write_log(_T("hardware_trap_thread #1: trap_done set!")); if (ctx->callback) { ret = ctx->callback(ctx, ctx->callback_ud); } else { int trap_num = get_word_host(status); trap = &traps[trap_num]; ret = trap->handler(ctx); } if (ctx->trap_done) write_log(_T("hardware_trap_thread #2: trap_done set!")); if (!ctx->trap_background) { for (int i = 0; i < 15; i++) { uae_u32 v = ctx->saved_regs.regs[i]; put_long_host(data + 4 + i * 4, v); } if (trap && (trap->flags & TRAPFLAG_NO_RETVAL) == 0) { put_long_host(data + 4, ret); } hardware_trap_ack(ctx); } else { ctx->trap_done = true; } } hardware_trap_kill[tid] = -1; return 0; }
void trap_multi(TrapContext *ctx, struct trapmd *data, int items) { if (trap_is_indirect_null(ctx)) { uae_u8 *p = ctx->host_trap_data + RTAREA_TRAP_DATA_EXTRA; for (int i = 0; i < items; i++) { struct trapmd *md = &data[i]; put_word_host(p + 0, md->cmd); put_byte_host(p + 2, md->trapmd_index); put_byte_host(p + 3, md->parm_num); put_long_host(p + 4, md->params[0]); put_long_host(p + 8, md->params[1]); put_long_host(p + 12, md->params[2]); put_long_host(p + 16, md->params[3]); p += 5 * 4; } call_hardware_trap_back(ctx, TRAPCMD_MULTI, ctx->amiga_trap_data + RTAREA_TRAP_DATA_EXTRA, items, 0, 0); p = ctx->host_trap_data + RTAREA_TRAP_DATA_EXTRA; for (int i = 0; i < items; i++) { struct trapmd *md = &data[i]; md->params[0] = get_long_host(p + 4); p += 5 * 4; } } else { uae_u32 v = 0; for (int i = 0; i < items; i++) { struct trapmd *md = &data[i]; switch (md->cmd) { case TRAPCMD_PUT_LONG: trap_put_long(ctx, md->params[0], md->params[1]); break; case TRAPCMD_PUT_WORD: trap_put_word(ctx, md->params[0], md->params[1]); break; case TRAPCMD_PUT_BYTE: trap_put_byte(ctx, md->params[0], md->params[1]); break; case TRAPCMD_GET_LONG: v = md->params[0] = trap_get_long(ctx, md->params[0]); break; case TRAPCMD_GET_WORD: v = md->params[0] = trap_get_word(ctx, md->params[0]); break; case TRAPCMD_GET_BYTE: v = md->params[0] = trap_get_byte(ctx, md->params[0]); break; case TRAPCMD_PUT_BYTES: trap_put_bytes(ctx, md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_GET_BYTES: trap_get_bytes(ctx, md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_PUT_WORDS: trap_put_words(ctx, (uae_u16*)md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_GET_WORDS: trap_get_words(ctx, (uae_u16*)md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_PUT_LONGS: trap_put_longs(ctx, (uae_u32*)md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_GET_LONGS: trap_get_longs(ctx, (uae_u32*)md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_PUT_STRING: trap_put_string(ctx, md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_GET_STRING: trap_get_string(ctx, md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_SET_LONGS: trap_set_longs(ctx, md->params[0], md->params[1], md->params[2]); break; case TRAPCMD_SET_WORDS: trap_set_words(ctx, md->params[0], md->params[1], md->params[2]); break; case TRAPCMD_SET_BYTES: trap_set_bytes(ctx, md->params[0], md->params[1], md->params[2]); break; case TRAPCMD_NOP: break; } if (md->trapmd_index) { data[md->trapmd_index].params[md->parm_num] = v; } } } }
uae_u64 trap_get_quad(TrapContext *ctx, uaecptr addr) { uae_u8 in[8]; trap_get_bytes(ctx, in, addr, 8); return ((uae_u64)get_long_host(in + 0) << 32) | get_long_host(in + 4); }