static int initint (TrapContext *ctx) { uae_u32 tmp1; uaecptr p; if (irq_init) return 1; m68k_dreg (regs, 0) = 26; m68k_dreg (regs, 1) = 65536 + 1; p = CallLib (ctx, get_long (4), -0xC6); /* AllocMem */ if (!p) return 0; tmp1 = here (); calltrap (deftrap2 (uaenet_int_handler, TRAPFLAG_EXTRA_STACK, _T("uaenet_int_handler"))); put_word (p + 8, 0x020a); put_long (p + 10, ROM_netdev_resid); put_long (p + 18, tmp1); m68k_areg (regs, 1) = p; m68k_dreg (regs, 0) = 3; /* PORTS */ dw (0x4a80); /* TST.L D0 */ dw (0x4e75); /* RTS */ CallLib (ctx, get_long (4), -168); /* AddIntServer */ irq_init = 1; return 1; }
uaecptr libemu_InstallFunctionFlags (TrapFunction f, uaecptr libbase, int offset, int flags, const char *tracename) { int i; uaecptr retval; uaecptr execbase = get_long (four); int trnum; uaecptr addr = here(); calltrap (trnum = deftrap2 (f, flags, tracename)); dw (RTS); _68k_areg(1) = libbase; _68k_areg(0) = offset; _68k_dreg(0) = addr; retval = CallLib (execbase, -420); trapoldfunc[trnum] = retval; #if 0 for (i = 0; i < n_libpatches; i++) { if (libpatches[i].libbase == libbase) break; } if (i == n_libpatches) { int j; libpatches[i].libbase = libbase; for (j = 0; j < 300; j++) libpatches[i].functions[j] = NULL; n_libpatches++; } libpatches[i].functions[-offset/6] = f; #endif return retval; }
uaecptr libemu_InstallFunctionFlags (TrapFunction f, uaecptr libbase, int offset, int flags, const char *tracename) { int i; uaecptr retval; uaecptr execbase = get_long (four); int trnum; uaecptr addr = here(); calltrap (trnum = deftrap2 (f, flags, tracename)); dw (RTS); _68k_areg(1) = libbase; _68k_areg(0) = offset; _68k_dreg(0) = addr; retval = CallLib (execbase, -420); trapoldfunc[trnum] = retval; return retval; }
uae_u32 trap_call_lib(TrapContext *ctx, uaecptr base, uae_s16 offset) { uae_u32 v; if (trap_is_indirect_null(ctx)) { uae_u8 *p = ctx->host_trap_data + RTAREA_TRAP_DATA_EXTRA; for (int i = 0; i < 16; i++) { if (ctx->calllib_reg_inuse[i]) { put_long_host(p , ctx->calllib_regs[i]); ctx->calllib_reg_inuse[i] = 0; } else { put_long_host(p, ctx->saved_regs.regs[i]); } p += 4; } v = call_hardware_trap_back(ctx, TRAPCMD_CALL_LIB, base, offset, ctx->amiga_trap_data + RTAREA_TRAP_DATA_EXTRA, 0); } else { uae_u32 storedregs[16]; bool storedregsused[16]; for (int i = 0; i < 16; i++) { storedregsused[i] = false; if (ctx->calllib_reg_inuse[i]) { if ((i & 7) >= 2) { storedregsused[i] = true; storedregs[i] = regs.regs[i]; } regs.regs[i] = ctx->calllib_regs[i]; } ctx->calllib_reg_inuse[i] = 0; } v = CallLib(ctx, base, offset); for (int i = 0; i < 16; i++) { if (storedregsused[i]) { regs.regs[i] = storedregs[i]; } } } return v; }
static uae_u32 REGPARAM2 dev_close_2 (TrapContext *context) { uae_u32 request = m68k_areg (regs, 1); struct priv_s2devstruct *pdev = getps2devstruct (request); struct s2devstruct *dev; if (!pdev) { write_log (_T("%s close with unknown request %08X!?\n"), SANA2NAME, request); return 0; } dev = gets2devstruct (pdev->unit); if (!dev) { write_log (_T("%s:%d close with unknown request %08X!?\n"), SANA2NAME, pdev->unit, request); return 0; } if (log_net) write_log (_T("%s:%d close, open=%d req=%08X\n"), SANA2NAME, pdev->unit, dev->opencnt, request); put_long (request + 24, 0); dev->opencnt--; pdev->inuse = 0; if (!dev->opencnt) { dev->exclusive = 0; if (pdev->tempbuf) { m68k_areg (regs, 1) = pdev->tempbuf; m68k_dreg (regs, 0) = pdev->td->mtu + ETH_HEADER_SIZE + 2; CallLib (context, get_long (4), -0xD2); /* FreeMem */ pdev->tempbuf = 0; } ethernet_close (pdev->td, dev->sysdata); xfree (dev->sysdata); dev->sysdata = NULL; write_comm_pipe_u32 (&dev->requests, 0, 1); write_log (_T("%s: opencnt == 0, all instances closed\n"), SANA2NAME); } put_word (m68k_areg (regs, 6) + 32, get_word (m68k_areg (regs, 6) + 32) - 1); return 0; }
void uae_FreeMem (TrapContext *context, uaecptr memory, uae_u32 size) { m68k_dreg (regs, 0) = size; m68k_areg (regs, 1) = memory; CallLib (context, x_get_long (4), -0xD2); /* FreeMem */ }
uaecptr uae_AllocMem (TrapContext *context, uae_u32 size, uae_u32 flags) { m68k_dreg (regs, 0) = size; m68k_dreg (regs, 1) = flags; return CallLib (context, x_get_long (4), -198); /* AllocMem */ }
void uae_FreeMem (uaecptr memory, uae_u32 size) { m68k_dreg (regs, 0) = size; m68k_areg (regs, 1) = memory; CallLib (get_long (4), -0xD2); /* FreeMem */ }
uaecptr uae_AllocMem (uae_u32 size, uae_u32 flags) { m68k_dreg (regs, 0) = size; m68k_dreg (regs, 1) = flags; return CallLib (get_long (4), -198); /* AllocMem */ }
uaecptr uae_AllocMem (TrapContext *ctx, uae_u32 size, uae_u32 flags, uaecptr sysbase) { trap_set_dreg(ctx, 0, size); trap_set_dreg(ctx, 1, flags); return CallLib (ctx, sysbase, -198); /* AllocMem */ }
void uae_FreeMem (TrapContext *ctx, uaecptr memory, uae_u32 size, uaecptr sysbase) { trap_set_dreg(ctx, 0, size); trap_set_areg(ctx, 1, memory); CallLib (ctx, sysbase, -0xD2); /* FreeMem */ }
static uae_u32 REGPARAM2 dev_open_2 (TrapContext *context) { uaecptr ioreq = m68k_areg (regs, 1); uae_u32 unit = m68k_dreg (regs, 0); uae_u32 flags = m68k_dreg (regs, 1); uaecptr buffermgmt; struct s2devstruct *dev = gets2devstruct (unit); struct priv_s2devstruct *pdev = 0; int i; uaecptr tagp, tagpnext; if (!dev) return openfail (ioreq, IOERR_OPENFAIL); if (!initint(context)) return openfail (ioreq, IOERR_SELFTEST); if (log_net) write_log (_T("opening %s:%d opencnt=%d ioreq=%08X\n"), SANA2NAME, unit, dev->opencnt, ioreq); if (get_word (ioreq + 0x12) < IOSTDREQ_SIZE) return openfail (ioreq, IOERR_BADLENGTH); if ((flags & SANA2OPF_PROM) && dev->opencnt > 0) return openfail (ioreq, IOERR_UNITBUSY); for (i = 0; i < MAX_OPEN_DEVICES; i++) { pdev = &pdevst[i]; if (pdev->inuse == 0) break; } if (i == MAX_OPEN_DEVICES) return openfail (ioreq, IOERR_UNITBUSY); put_long (ioreq + 24, pdev - pdevst); pdev->unit = unit; pdev->flags = flags; pdev->inuse = 1; pdev->td = td ? td[unit] : NULL; pdev->promiscuous = (flags & SANA2OPF_PROM) ? 1 : 0; if (pdev->td == NULL || pdev->td->active == 0) return openfail (ioreq, IOERR_OPENFAIL); if (dev->opencnt == 0) { dev->unit = unit; dev->sysdata = xcalloc (uae_u8, ethernet_getdatalenght (pdev->td)); if (!ethernet_open (pdev->td, dev->sysdata, dev, uaenet_gotdata, uaenet_getdata, pdev->promiscuous)) { xfree (dev->sysdata); dev->sysdata = NULL; return openfail (ioreq, IOERR_OPENFAIL); } write_log (_T("%s: initializing unit %d\n"), getdevname (), unit); dev->td = pdev->td; dev->adapter = pdev->td ? pdev->td->active : 0; if (dev->adapter) { dev->online = 1; dev->configured = 1; } start_thread (dev); } if (kickstart_version >= 36) { m68k_areg (regs, 0) = get_long (4) + 350; m68k_areg (regs, 1) = timerdevname; CallLib (context, get_long (4), -0x114); /* FindName('timer.device') */ pdev->timerbase = m68k_dreg (regs, 0); } pdev->copyfrombuff = pdev->copytobuff = pdev->packetfilter = 0; pdev->tempbuf = 0; if (get_word (ioreq + 0x12) >= SANA2_IOREQSIZE) { buffermgmt = get_long (ioreq + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4 + 4 + 4); tagpnext = buffermgmt; while (tagpnext) { uae_u32 tag = get_long (tagpnext); uae_u32 val = get_long (tagpnext + 4); tagp = tagpnext; tagpnext += 8; switch (tag) { case TAG_DONE: tagpnext = 0; break; case TAG_IGNORE: break; case TAG_MORE: tagpnext = val; break; case TAG_SKIP: tagpnext = tagp + val * 8; break; case S2_CopyToBuff: pdev->copytobuff = val; break; case S2_CopyFromBuff: pdev->copyfrombuff = val; break; case S2_PacketFilter: pdev->packetfilter = val; break; } } if (log_net) write_log (_T("%s:%d CTB=%08x CFB=%08x PF=%08x\n"), getdevname(), unit, pdev->copytobuff, pdev->copyfrombuff, pdev->packetfilter); m68k_dreg (regs, 0) = dev->td->mtu + ETH_HEADER_SIZE + 2; m68k_dreg (regs, 1) = 1; pdev->tempbuf = CallLib (context, get_long (4), -0xC6); /* AllocMem */ if (!pdev->tempbuf) { if (dev->opencnt == 0) { ethernet_close (pdev->td, dev->sysdata); xfree (dev->sysdata); dev->sysdata = NULL; } return openfail (ioreq, S2ERR_BAD_ARGUMENT); } /* buffermanagement */ put_long (ioreq + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4 + 4 + 4, pdev->tempbuf); } dev->exclusive = flags & SANA2OPF_MINE; dev->opencnt++; put_word (m68k_areg (regs, 6) + 32, get_word (m68k_areg (regs, 6) + 32) + 1); put_byte (ioreq + 31, 0); put_byte (ioreq + 8, 7); return 0; }
static uae_u32 REGPARAM2 uaenet_int_handler (TrapContext *ctx) { int i, j; int gotit; struct asyncreq *ar; if (uae_sem_trywait (&async_sem)) { uaenet_int_requested = 0; uaenet_int_late = 1; return 0; } for (i = 0; i < MAX_OPEN_DEVICES; i++) pdevst[i].tmp = 0; for (i = 0; i < MAX_TOTAL_NET_DEVICES; i++) { struct s2devstruct *dev = &devst[i]; struct s2packet *p; if (dev->online) { while (dev->readqueue) { uae_u16 type; p = dev->readqueue; type = (p->data[2 * ADDR_SIZE] << 8) | p->data[2 * ADDR_SIZE + 1]; ar = dev->ar; gotit = 0; while (ar) { if (!ar->ready) { uaecptr request = ar->request; int command = get_word (request + 28); uae_u32 packettype = get_long (request + 32 + 4); if (command == CMD_READ && (packettype == type || (packettype <= 1500 && type <= 1500))) { struct priv_s2devstruct *pdev = getps2devstruct (request); if (pdev && pdev->tmp == 0) { if (handleread (ctx, pdev, request, p->data, p->len, command)) { if (log_net) write_log (_T("-> %p Accepted, CMD_READ, REQ=%08X LEN=%d\n"), p, request, p->len); ar->ready = 1; write_comm_pipe_u32 (&dev->requests, request, 1); dev->packetsreceived++; gotit = 1; pdev->tmp = 1; } else { if (log_net) write_log (_T("-> %p PacketFilter() rejected, CMD_READ, REQ=%08X LEN=%d\n"), p, request, p->len); pdev->tmp = -1; } } } } ar = ar->next; } ar = dev->ar; while (ar) { if (!ar->ready) { uaecptr request = ar->request; int command = get_word (request + 28); if (command == S2_READORPHAN) { struct priv_s2devstruct *pdev = getps2devstruct (request); if (pdev && pdev->tmp <= 0) { if (log_net) write_log (_T("-> %p Accepted, S2_READORPHAN, REQ=%08X LEN=%d\n"), p, request, p->len); handleread (ctx, pdev, request, p->data, p->len, command); ar->ready = 1; write_comm_pipe_u32 (&dev->requests, request, 1); dev->packetsreceived++; dev->unknowntypesreceived++; gotit = 1; pdev->tmp = 1; } } } ar = ar->next; } if (!gotit) { if (log_net) write_log (_T("-> %p packet dropped, LEN=%d\n"), p, p->len); for (j = 0; j < MAX_OPEN_DEVICES; j++) { if (pdevst[j].unit == dev->unit) { if (pdevst[j].tracks[type]) pdevst[j].packetsdropped++; } } } dev->readqueue = dev->readqueue->next; freepacket (p); } } else { while (dev->readqueue) { p = dev->readqueue; dev->readqueue = dev->readqueue->next; freepacket (p); } } ar = dev->ar; while (ar) { if (!ar->ready) { uaecptr request = ar->request; int command = get_word (request + 28); if (command == S2_ONLINE) { struct priv_s2devstruct *pdev = getps2devstruct (request); dev->packetsreceived = 0; dev->packetssent = 0; dev->baddata = 0; dev->overruns = 0; dev->unknowntypesreceived = 0; dev->reconfigurations = 0; if (pdev && pdev->timerbase) { m68k_areg (regs, 0) = pdev->tempbuf; CallLib (ctx, pdev->timerbase, -0x42); /* GetSysTime() */ } else { put_long (pdev->tempbuf + 0, 0); put_long (pdev->tempbuf + 4, 0); } dev->online_secs = get_long (pdev->tempbuf + 0); dev->online_micro = get_long (pdev->tempbuf + 4); checkevents (dev, S2EVENT_ONLINE, 0); dev->online = 1; ar->ready = 1; write_comm_pipe_u32 (&dev->requests, request, 1); uaenet_vsync_requested--; } else if (command == CMD_FLUSH) { /* do not reply CMD_FLUSH until all other requests are gone */ if (dev->ar->next == NULL) { if (log_net) write_log (_T("CMD_FLUSH replied %08x\n"), request); ar->ready = 1; write_comm_pipe_u32 (&dev->requests, request, 1); uaenet_vsync_requested--; } else { struct priv_s2devstruct *pdev = getps2devstruct (request); if (pdev) { dev->flush_timeout--; if (dev->flush_timeout <= 0) { dev->flush_timeout = FLUSH_TIMEOUT; if (dev->flush_timeout_cnt > 1) write_log (_T("WARNING: %s:%d CMD_FLUSH possibly frozen..\n"), getdevname(), pdev->unit); dev->flush_timeout_cnt++; flush (pdev); } } } } } ar = ar->next; } } if (uaenet_int_late) uaenet_int_requested = 1; else uaenet_int_requested = 0; uaenet_int_late = 0; uae_sem_post (&async_sem); return 0; }
static uae_u32 hardfile_beginio (void) { uae_u32 tmp1, tmp2, dataptr, offset; uae_u32 retval = m68k_dreg(regs, 0); int unit; struct hardfiledata *hfd; tmp1 = m68k_areg(regs, 1); unit = get_long (tmp1 + 24); #undef DEBUGME #ifdef DEBUGME printf ("hardfile: unit = %d\n", unit); printf ("hardfile: tmp1 = %08lx\n", (unsigned long)tmp1); printf ("hardfile: cmd = %d\n", (int)get_word(tmp1+28)); #endif hfd = get_hardfile_data (unit); put_byte (tmp1+8, NT_MESSAGE); put_byte (tmp1+31, 0); /* no error yet */ tmp2 = get_word (tmp1+28); /* io_Command */ /* put_byte (tmp1 + 30, get_byte (tmp1 + 30) & ~1);*/ switch (tmp2) { case CMD_READ: gui_data.hdled = HDLED_READ; dataptr = get_long (tmp1 + 40); if (dataptr & 1) goto bad_command; offset = get_long (tmp1 + 44); if (offset & 511) goto bad_command; tmp2 = get_long (tmp1 + 36); /* io_Length */ if (tmp2 & 511) goto bad_command; if (tmp2 + offset > (uae_u32)hfd->size) goto bad_command; put_long (tmp1 + 32, tmp2); /* set io_Actual */ #ifdef __SYMBIAN32__ lseek (fileno(hfd->fd), offset, SEEK_SET); #else fseek (hfd->fd, offset, SEEK_SET); #endif while (tmp2) { int i; char buffer[512]; #ifdef __SYMBIAN32__ /* See the comment in CMD_WRITE */ read (fileno(hfd->fd), buffer, 512); #else fread (buffer, 1, 512, hfd->fd); #endif for (i = 0; i < 512; i++, dataptr++) put_byte(dataptr, buffer[i]); tmp2 -= 512; } break; case CMD_WRITE: case 11: /* Format */ gui_data.hdled = HDLED_WRITE; dataptr = get_long (tmp1 + 40); if (dataptr & 1) goto bad_command; offset = get_long (tmp1 + 44); if (offset & 511) goto bad_command; tmp2 = get_long (tmp1 + 36); /* io_Length */ if (tmp2 & 511) goto bad_command; if (tmp2 + offset > (uae_u32)hfd->size) goto bad_command; put_long (tmp1 + 32, tmp2); /* set io_Actual */ #ifdef __SYMBIAN32__ lseek (fileno(hfd->fd), offset, SEEK_SET); #else fseek (hfd->fd, offset, SEEK_SET); #endif while (tmp2) { char buffer[512]; int i; for (i=0; i < 512; i++, dataptr++) buffer[i] = get_byte(dataptr); #ifdef __SYMBIAN32__ /* For some reason, fwrite() *appends* data at the end of the HDF file, * instead of writing it at fseek() offset, even though fopen() was called * with "r+b" parameter, and not "a+"! * write() works correctly. */ write (fileno(hfd->fd), buffer, 512); #else fwrite (buffer, 1, 512, hfd->fd); #endif tmp2 -= 512; } break; bad_command: break; case 18: /* GetDriveType */ printf ("Shouldn't happen\n"); put_long (tmp1 + 32, 1); /* not exactly a 3.5" drive, but... */ break; case 19: /* GetNumTracks */ printf ("Shouldn't happen 2\n"); put_long (tmp1 + 32, 0); break; /* Some commands that just do nothing and return zero */ case CMD_UPDATE: case CMD_CLEAR: case 9: /* Motor */ case 10: /* Seek */ case 12: /* Remove */ case 13: /* ChangeNum */ case 14: /* ChangeStatus */ case 15: /* ProtStatus */ case 20: /* AddChangeInt */ case 21: /* RemChangeInt */ put_long (tmp1+32, 0); /* io_Actual */ retval = 0; break; default: /* Command not understood. */ put_byte (tmp1+31, (uae_u8)-3); /* io_Error */ retval = 0; break; } #if 0 if ((get_byte (tmp1+30) & 1) == 0) { /* Not IOF_QUICK -- need to ReplyMsg */ m68k_areg(regs, 1) = tmp1; CallLib (get_long(4), -378); } #endif return retval; }
uae_u32 uaenative_call_function (TrapContext *context, int flags) { if (!currprefs.native_code) { return UNI_ERROR_NOT_ENABLED; } struct uni uni; uni.function = m68k_areg (regs, 0); if (flags & UNI_FLAG_COMPAT) { uni.library = 0; #ifdef AHI uni.uaevar_compat = uaenative_get_uaevar(); #else uni.uaevar_compat = NULL; #endif } else if (flags & UNI_FLAG_NAMED_FUNCTION) { uni.library = m68k_dreg (regs, 0); } else { uni.library = 0; } struct library_data *library_data; if (uni.library) { // library handle given, function is pointer to function name const char *function = (const char *) get_real_address (uni.function); library_data = get_library_data_from_handle (uni.library); if (library_data == NULL) { write_log (_T("uni: get_function - invalid library (%d)\n"), uni.library); return UNI_ERROR_INVALID_LIBRARY; } uni.native_function = dl_symbol (library_data->dl_handle, function); if (uni.native_function == NULL) { write_log (_T("uni: get_function - function (%s) not found ") _T("in library %d (%p)\n"), function, uni.library, library_data->dl_handle); return UNI_ERROR_FUNCTION_NOT_FOUND; } } else { // library handle not given, function argument is function handle int index = uni.function - (uae_u32) 0x80000000; if (index >= 0 && index <= g_max_handle) { uni.native_function = g_handles[index].function; library_data = g_handles[index].library; } else { uni.native_function = NULL; } if (uni.native_function == NULL) { // printf ("UNI_ERROR_INVALID_FUNCTION\n"); return UNI_ERROR_INVALID_FUNCTION; } } if (context == NULL) { // we have no context and cannot call into m68k space flags &= ~UNI_FLAG_ASYNCHRONOUS; } uni.d1 = m68k_dreg (regs, 1); uni.d2 = m68k_dreg (regs, 2); uni.d3 = m68k_dreg (regs, 3); uni.d4 = m68k_dreg (regs, 4); uni.d5 = m68k_dreg (regs, 5); uni.d6 = m68k_dreg (regs, 6); uni.d7 = m68k_dreg (regs, 7); uni.a1 = m68k_areg (regs, 1); uni.a2 = m68k_areg (regs, 2); uni.a3 = m68k_areg (regs, 3); uni.a4 = m68k_areg (regs, 4); uni.a5 = m68k_areg (regs, 5); uni.a7 = m68k_areg (regs, 7); uni.flags = flags; uni.error = 0; if (flags & UNI_FLAG_ASYNCHRONOUS) { uaecptr sysbase = get_long (4); uni.task = get_long (sysbase + 276); // ThisTask // make sure signal bit is cleared m68k_dreg (regs, 0) = 0; m68k_dreg (regs, 1) = 1 << SIGBIT; CallLib (context, sysbase, -0x132); // SetSignal // start thread if necessary if (!library_data->thread_id) { uae_sem_init (&library_data->full_count, 0, 0); // we don't have a queue as such, the thread only processes // one item at a time with a "queue size" of 1 uae_sem_init (&library_data->empty_count, 0, 1); uae_start_thread (_T("uaenative"), uaenative_thread, library_data, &library_data->thread_id); } // signal async thread to process new function call uae_sem_wait(&library_data->empty_count); library_data->uni = &uni; uae_sem_post(&library_data->full_count); // wait for signal m68k_dreg (regs, 0) = 1 << SIGBIT; CallLib (context, sysbase, -0x13e); // Wait write_log (_T("uni: -- Got async result --\n")); } else { // synchronous mode, just call the function here and now do_call_function(&uni); } return uni.result; }