static void dev_reset (void) { int i; struct devstruct *dev; for (i = 0; i < MAX_TOTAL_DEVICES; i++) { dev = &devst[i]; if (dev->open) { while (dev->ar) abort_async (dev, dev->ar->request); dev_close_3 (dev); uae_sem_wait (&dev->sync_sem); } memset (dev, 0, sizeof (struct devstruct)); } }
static int getsub_deinterleaved (uae_u8 *dst, struct cdunit *cdu, struct cdtoc *t, int sector) { int ret = 0; uae_sem_wait (&cdu->sub_sem); if (t->subcode) { if (t->enctype == ENC_CHD) { const cdrom_track_info *cti = t->chdtrack; ret = do_read (cdu, t, dst, sector, cti->datasize, cti->subsize); if (ret) ret = t->subcode; } else if (t->subhandle) { int offset = 0; int totalsize = SUB_CHANNEL_SIZE; if (t->skipsize) { totalsize += t->size; offset = t->size; } zfile_fseek (t->subhandle, (uae_u64)sector * totalsize + t->suboffset + offset, SEEK_SET); if (zfile_fread (dst, SUB_CHANNEL_SIZE, 1, t->subhandle) > 0) ret = t->subcode; } else { memcpy (dst, t->subdata + sector * SUB_CHANNEL_SIZE + t->suboffset, SUB_CHANNEL_SIZE); ret = t->subcode; } } if (!ret) { memset (dst, 0, SUB_CHANNEL_SIZE); // regenerate Q-subchannel uae_u8 *s = dst + 12; s[0] = (t->ctrl << 4) | (t->adr << 0); s[1] = tobcd (t - &cdu->toc[0] + 1); s[2] = tobcd (1); int msf = lsn2msf (sector); tolongbcd (s + 7, msf); msf = lsn2msf (sector - t->address - 150); tolongbcd (s + 3, msf); ret = 2; } if (ret == 1) { uae_u8 tmp[SUB_CHANNEL_SIZE]; memcpy (tmp, dst, SUB_CHANNEL_SIZE); sub_to_deinterleaved (tmp, dst); ret = 2; } uae_sem_post (&cdu->sub_sem); return ret; }
static struct asyncreq *get_async_request (struct devstruct *dev, uaecptr request, int ready) { struct asyncreq *ar; uae_sem_wait (&async_sem); ar = dev->ar; while (ar) { if (ar->request == request) { if (ready) ar->ready = 1; break; } ar = ar->next; } uae_sem_post (&async_sem); return ar; }
static void *uaenet_trap_threadw (void *arg) { struct uaenetdata *sd = (struct uaenetdata*)arg; uae_set_thread_priority (1); sd->threadactivew = 1; uae_sem_post (&sd->sync_semw); while (sd->threadactivew == 1) { int32_t towrite = sd->mtu; uae_sem_wait (&sd->change_sem); if (sd->getfunc (sd->user, sd->writebuffer, &towrite)) { pcap_sendpacket (sd->fp, sd->writebuffer, towrite); } uae_sem_post (&sd->change_sem); } sd->threadactivew = 0; uae_sem_post (&sd->sync_semw); return 0; }
void scsi_do_disk_change (int device_id, int insert) { int i, j; uae_sem_wait (&change_sem); for (i = 0; i < MAX_TOTAL_DEVICES; i++) { if (devst[i].di.id == device_id) { devst[i].changenum++; j = 0; while (j < MAX_ASYNC_REQUESTS) { if (devst[i].d_request_type[j] == ASYNC_REQUEST_CHANGEINT) { uae_Cause (devst[i].d_request_data[j]); } j++; } } } uae_sem_post (&change_sem); }
void checkevents (struct s2devstruct *dev, int mask, int sem) { struct asyncreq *ar; if (sem) uae_sem_wait (&async_sem); ar = dev->ar; while (ar) { if (!ar->ready) { uaecptr request = ar->request; int command = get_word (request + 28); uae_u32 cmask = get_long (request + 32); if (command == S2_ONEVENT && (mask & cmask)) signalasync (dev, ar, 0, 0); } ar = ar->next; } if (sem) uae_sem_post (&async_sem); }
static int32_t add_async_request (struct devstruct *dev, uaecptr request) { struct asyncreq *ar, *ar2; if (log_uaeserial) write_log (_T("%s:%d async request %x added\n"), getdevname(), dev->unit, request); uae_sem_wait (&async_sem); ar = xcalloc (struct asyncreq, 1); ar->request = request; if (!dev->ar) { dev->ar = ar; } else { ar2 = dev->ar; while (ar2->next) ar2 = ar2->next; ar2->next = ar; } uae_sem_post (&async_sem); return 1; }
static void *uaenative_thread(void *arg) { struct library_data *library_data = (struct library_data *) arg; while (1) { uae_sem_wait(&library_data->full_count); if (library_data->thread_stop_flag) { break; } if (library_data->uni) { do_call_function (library_data->uni); uae_Signal (library_data->uni->task, 1 << SIGBIT); } library_data->uni = NULL; uae_sem_post(&library_data->empty_count); } write_log (_T("uni: uaenative_thread exiting\n")); free_library_data(library_data); return NULL; }
void close_sound (void) { config_changed = 1; gui_data.sndbuf = 0; gui_data.sndbuf_status = 3; if (!have_sound) return; // SDL_PauseAudio (1); clearbuffer(); if (in_callback) { closing_sound = 1; uae_sem_post (&data_available_sem); } write_comm_pipe_int (&to_sound_pipe, 1, 1); uae_sem_wait (&sound_init_sem); // SDL_CloseAudio (); uae_sem_destroy (&data_available_sem); uae_sem_destroy (&sound_init_sem); uae_sem_destroy (&callback_done_sem); have_sound = 0; }
static int uaenet_getdata (struct s2devstruct *dev, uae_u8 *d, int *len) { int gotit; struct asyncreq *ar; uae_sem_wait (&async_sem); ar = dev->ar; gotit = 0; while (ar && !gotit) { if (!ar->ready) { uaecptr request = ar->request; int command = get_word (request + 28); uae_u32 packettype = get_long (request + 32 + 4); if (command == CMD_WRITE || command == S2_BROADCAST || command == S2_MULTICAST) { struct priv_s2devstruct *pdev = getps2devstruct (request); struct asyncreq *ars2p = dev->s2p; while (ars2p) { if (ars2p->request == request) { *len = ars2p->s2p->len; memcpy (d, ars2p->s2p->data, *len); if (log_net) write_log (_T("->DST:%02X.%02X.%02X.%02X.%02X.%02X SRC:%02X.%02X.%02X.%02X.%02X.%02X E=%04X S=%d\n"), d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], packettype, *len); gotit = 1; dev->packetssent++; signalasync (dev, ar, *len, 0); break; } ars2p = ars2p->next; } } } ar = ar->next; } uae_sem_post (&async_sem); return gotit; }
static void *uaenet_trap_threadw (void *arg) { struct uaenetdatawin32 *sd = (struct uaenetdatawin32*)arg; uae_set_thread_priority (NULL, 1); sd->threadactivew = 1; uae_sem_post (&sd->sync_semw); while (sd->threadactivew == 1) { int donotwait = 0; int towrite = sd->mtu; uae_sem_wait (&sd->change_sem); if (sd->getfunc ((struct s2devstruct*)sd->user, sd->writebuffer, &towrite)) { pcap_sendpacket (sd->fp, sd->writebuffer, towrite); donotwait = 1; } uae_sem_post (&sd->change_sem); if (!donotwait) WaitForSingleObject (sd->evttw, INFINITE); } sd->threadactivew = 0; uae_sem_post (&sd->sync_semw); return 0; }
int init_sound(void) { write_log("init_sound\n"); gui_data.sndbuf_status = 3; gui_data.sndbuf = 0; if (!sound_available) return 0; if (currprefs.produce_sound <= 1) return 0; if (have_sound) return 1; in_callback = 0; closing_sound = 0; init_sound_thread (); write_comm_pipe_int (&to_sound_pipe, 0, 1); uae_sem_wait (&sound_init_sem); // SDL_PauseAudio (0); #ifdef DRIVESOUND driveclick_reset (); #endif return have_sound; }
static void rem_async_packet (struct s2devstruct *dev, uaecptr request) { struct asyncreq *ar, *prevar; uae_sem_wait (&async_sem); ar = dev->s2p; prevar = NULL; while (ar) { if (ar->request == request) { if (prevar == NULL) dev->s2p = ar->next; else prevar->next = ar->next; uae_sem_post (&async_sem); freepacket (ar->s2p); xfree (ar); return; } prevar = ar; ar = ar->next; } uae_sem_post (&async_sem); }
static int execscsicmd_direct (int unitnum, uaecptr acmd) { int sactual = 0; struct scsidevdata *sdd = &drives[unitnum]; SCSI *scgp = sdd->scgp; struct scg_cmd *scmd = scgp->scmd; uaecptr scsi_data = get_long (acmd + 0); uae_u32 scsi_len = get_long (acmd + 4); uaecptr scsi_cmd = get_long (acmd + 12); int scsi_cmd_len = get_word (acmd + 16); int scsi_cmd_len_orig = scsi_cmd_len; uae_u8 scsi_flags = get_byte (acmd + 20); uaecptr scsi_sense = get_long (acmd + 22); uae_u16 scsi_sense_len = get_word (acmd + 26); int io_error = 0; int parm; addrbank *bank_data = &get_mem_bank (scsi_data); addrbank *bank_cmd = &get_mem_bank (scsi_cmd); uae_u8 *scsi_datap; uae_u8 *scsi_datap_org; DEBUG_LOG ("SCSIDEV: unit=%d: execscsicmd_direct\n", unitnum); /* do transfer directly to and from Amiga memory */ if (!bank_data || !bank_data->check (scsi_data, scsi_len)) return -5; /* IOERR_BADADDRESS */ uae_sem_wait (&scgp_sem); memset (scmd, 0, sizeof (*scmd)); /* the Amiga does not tell us how long the timeout shall be, so make it * _very_ long (specified in seconds) */ scmd->timeout = 80 * 60; scsi_datap = scsi_datap_org = scsi_len ? bank_data->xlateaddr (scsi_data) : 0; scmd->size = scsi_len; scmd->flags = (scsi_flags & 1) ? SCG_RECV_DATA : SCG_DISRE_ENA; memcpy (&scmd->cdb, bank_cmd->xlateaddr (scsi_cmd), scsi_cmd_len); scmd->target = sdd->target; scmd->sense_len = (scsi_flags & 4) ? 4 : /* SCSIF_OLDAUTOSENSE */ (scsi_flags & 2) ? scsi_sense_len : /* SCSIF_AUTOSENSE */ -1; scmd->sense_count = 0; *(uae_u8 *)&scmd->scb = 0; if (sdd->isatapi) scsi_atapi_fixup_pre (scmd->cdb.cmd_cdb, &scsi_cmd_len, &scsi_datap, &scsi_len, &parm); scmd->addr = (caddr_t)scsi_datap; scmd->cdb_len = scsi_cmd_len; scg_settarget (scgp, sdd->bus, sdd->target, sdd->lun); scgp->cmdname = "???"; scgp->curcmdname = "???"; DEBUG_LOG ("SCSIDEV: sending command: 0x%2x\n", scmd->cdb.g0_cdb.cmd); scg_cmd (scgp); DEBUG_LOG ("SCSIDEV: result: %d %d %s\n", scmd->error, scmd->ux_errno,\ scgp->errstr); gui_flicker_led (LED_CD, 0, 1); put_word (acmd + 18, scmd->error == SCG_FATAL ? 0 : scsi_cmd_len); /* fake scsi_CmdActual */ put_byte (acmd + 21, *(uae_u8 *)&scmd->scb); /* scsi_Status */ if (*(uae_u8 *)&scmd->scb) { io_error = 45; /* HFERR_BadStatus */ /* copy sense? */ for (sactual = 0; scsi_sense && sactual < scsi_sense_len && sactual < scmd->sense_count; sactual++) { put_byte (scsi_sense + sactual, scmd->u_sense.cmd_sense[sactual]); } put_long (acmd + 8, 0); /* scsi_Actual */ } else { int i; for (i = 0; i < scsi_sense_len; i++) put_byte (scsi_sense + i, 0); sactual = 0; if (scmd->error != SCG_NO_ERROR || scmd->ux_errno != 0) { /* We might have been limited by the hosts DMA limits, which is usually indicated by ENOMEM */ if (scsi_len > (unsigned int)sdd->max_dma && scmd->ux_errno == ENOMEM) io_error = (uae_u8)-4; /* IOERR_BADLENGTH */ else { io_error = 20; /* io_Error, but not specified */ put_long (acmd + 8, 0); /* scsi_Actual */ } } else { scsi_len = scmd->size; if (sdd->isatapi) scsi_atapi_fixup_post (scmd->cdb.cmd_cdb, scsi_cmd_len, scsi_datap_org, scsi_datap, &scsi_len, parm); io_error = 0; put_long (acmd + 8, scsi_len); /* scsi_Actual */ } } put_word (acmd + 28, sactual); uae_sem_post (&scgp_sem); if (scsi_datap != scsi_datap_org) free (scsi_datap); return io_error; }
static void scsidev_do_scsi (struct scsidevdata *sdd, uaecptr request) { SCSI *scgp = sdd->scgp; struct scg_cmd *scmd = scgp->scmd; uaecptr acmd = get_long (request + 40); uaecptr scsi_data = get_long (acmd + 0); uae_u32 scsi_len = get_long (acmd + 4); uaecptr scsi_cmd = get_long (acmd + 12); uae_u16 scsi_cmd_len = get_word (acmd + 16); uae_u8 scsi_flags = get_byte (acmd + 20); uaecptr scsi_sense = get_long (acmd + 22); uae_u16 scsi_sense_len = get_word (acmd + 26); int sactual = 0; addrbank *bank_data = &get_mem_bank (scsi_data); addrbank *bank_cmd = &get_mem_bank (scsi_cmd); /* do transfer directly to and from Amiga memory */ if (!bank_data || !bank_data->check (scsi_data, scsi_len) || !bank_cmd || !bank_cmd->check (scsi_cmd, scsi_cmd_len)) { put_byte (request + 31, (uae_u8)-5); /* IOERR_BADADDRESS */ return; } #ifdef SCSI_IS_NOT_THREAD_SAFE uae_sem_wait (&scgp_sem); #endif scmd->timeout = 80 * 60; /* the Amiga does not tell us how long the timeout shall be, so make it _very_ long (specified in seconds) */ scmd->addr = bank_data->xlateaddr (scsi_data); scmd->size = scsi_len; scmd->flags = ((scsi_flags & 1) ? SCG_RECV_DATA : 0) | SCG_DISRE_ENA; scmd->cdb_len = scsi_cmd_len; memcpy(&scmd->cdb, bank_cmd->xlateaddr (scsi_cmd), scsi_cmd_len); scmd->target = sdd->target; scmd->sense_len = (scsi_flags & 4) ? 4 : /* SCSIF_OLDAUTOSENSE */ (scsi_flags & 2) ? scsi_sense_len : /* SCSIF_AUTOSENSE */ -1; scmd->sense_count = 0; *(uae_u8 *)&scmd->scb = 0; #ifdef DEBUG_CDR /* please ignore this code - it can be used to debug raw CD-R writing... */ if (!(scsi_len % 2368)) { /* Structure for generating bytes 2353...2368 if writing in ultra raw mode */ typedef struct QDATAtag { BYTE ControlAdr; BCD Tno; BCD Point; BCD Min; BCD Sec; BCD Frame; BYTE Zero; BCD PMin; BCD PSec; BCD PFrame; WORD Crc; BYTE Reserved[3]; BYTE PChannel; } QDATA; int i = scsi_len / 2368; QDATA *data = (QDATA *)&((unsigned char *)scmd->addr)[2352]; for (; i > 0; i--, data = (QDATA *)&((unsigned char *)data)[2368]) { printf ("$%02x: $%02x $%02x | $%02x:$%02x:$%02x = %6ld | $%02x | $%02x:$%02x:$%02x = %6ld\n", (int)data->ControlAdr, (int)*(UBYTE *)&data->Tno, (int)*(UBYTE *)&data->Point, (int)*(UBYTE *)&data->Min, (int)*(UBYTE *)&data->Sec, (int)*(UBYTE *)&data->Frame, BCDTime2Block_Pointer (&data->Min) + 150, *(UBYTE *)&data->Zero, *(UBYTE *)&data->PMin, *(UBYTE *)&data->PSec, *(UBYTE *)&data->PFrame, BCDTime2Block_Pointer (&data->PMin)); } fflush (stdout); } #endif scgp->scsibus = sdd->bus; scgp->target = sdd->target; scgp->lun = sdd->lun; scgp->cmdname = "???"; scgp->curcmdname = "???"; /* replace MODE_SELECT/SENSE_6 if we access a ATAPI drive, otherwise send it now */ if (sdd->isatapi && (scmd->cdb.g0_cdb.cmd == MODE_SELECT_6 || scmd->cdb.g0_cdb.cmd == MODE_SENSE_6)) { uae_u8 buffer[256 + 2], *data = scmd->addr, *tmp; int len = 0, page_len, i; int do_it = 1; uae_u8 sp = scmd->cdb.g0_cdb.high_addr & 1; uae_u8 alloc_len = scmd->cdb.g0_cdb.count; uae_u8 pcf_page_code = scmd->cdb.g0_cdb.mid_addr; uae_u8 cmd = scmd->cdb.g0_cdb.cmd; memset (&scmd->cdb.g1_cdb, 0, sizeof(scmd->cdb.g1_cdb)); if (cmd == MODE_SELECT_6) { /* expand parameter list */ tmp = data; buffer[len++] = *tmp++; /* first byte, should be 0 */ buffer[len++] = 0; /* reserved */ buffer[len++] = *tmp++; /* medium type */ buffer[len++] = 0; *tmp++; /* ignore host application code */ for (i = 0; i < 4; i++) { buffer[len++] = 0; } if (*tmp) { /* skip block descriptor */ tmp += 8; } tmp++; page_len = scsi_len - (tmp - data); if (page_len > 0) { memcpy (&buffer[len], tmp, page_len); len += page_len; scmd->cdb.g1_cdb.cmd = MODE_SELECT_10; scmd->cdb.g1_cdb.lun = sdd->lun; scmd->cdb.g1_cdb.res = 1 << 3; /* PF bit */ scmd->cdb.g1_cdb.reladr = sp; scmd->cdb.g1_cdb.count[0] = len >> 8; scmd->cdb.g1_cdb.count[1] = len; } else {
/* * gui_handle_events() * * This is called from the main UAE thread to process events sent from * the GUI thread. * * If the UAE emulation proper is not running yet or is paused, * this loops continuously waiting for and responding to events * until the emulation is started or resumed, respectively. When * the emulation is running, this is called periodically from * the main UAE event loop. */ void gui_handle_events (void) { /* Read GUI command if any. */ /* Process it, e.g., call uae_reset(). */ while (comm_pipe_has_data (&from_gui_pipe) || gui_pause_uae) { DEBUG_LOG("gui_handle_events: trying to read...\n"); int32_t cmd = read_comm_pipe_int_blocking (&from_gui_pipe); DEBUG_LOG("gui_handle_events: %i\n", cmd); switch (cmd) { case UAECMD_EJECTDISK: { int32_t n = read_comm_pipe_int_blocking (&from_gui_pipe); uae_sem_wait(&gui_sem); changed_prefs.floppyslots[n].df[0] = '\0'; uae_sem_post(&gui_sem); continue; } case UAECMD_INSERTDISK: { int32_t n = read_comm_pipe_int_blocking (&from_gui_pipe); if (using_restricted_cloanto_rom) { write_log("Loading other disks is not permitted under the " "license for the built-in Cloanto Kickstart " "ROM.\n"); continue; } uae_sem_wait(&gui_sem); strncpy (changed_prefs.floppyslots[n].df, new_disk_string[n], 255); free (new_disk_string[n]); new_disk_string[n] = 0; changed_prefs.floppyslots[n].df[255] = '\0'; uae_sem_post(&gui_sem); continue; } case UAECMD_RESET: uae_reset(1); break; // Stop GUI command processing until UAE is ready again. case UAECMD_PAUSE: gui_pause_uae = 1; continue; case UAECMD_RESUME: gui_pause_uae = 0; continue; case UAECMD_SELECT_ROM: uae_sem_wait(&gui_sem); strncpy(changed_prefs.romfile, gui_romname, 255); changed_prefs.romfile[255] = '\0'; free(gui_romname); gui_romname = 0; /* Switching to non-restricted ROM; rebooting. */ using_restricted_cloanto_rom = 0; uae_reset(1); uae_sem_post(&gui_sem); continue; case UAECMD_RESIZE: { int32_t width = read_comm_pipe_int_blocking(&from_gui_pipe); int32_t height = read_comm_pipe_int_blocking(&from_gui_pipe); screen_size_changed(width, height); continue; } default: DEBUG_LOG("Unknown command %d received from GUI.\n", cmd); continue; } } }
/* read qcode */ static int ioctl_command_qcode (int unitnum, uae_u8 *buf, int sector) { struct dev_info_ioctl *ciw = unitisopen (unitnum); if (!ciw) return 0; uae_u8 *p; int trk; CDROM_TOC *toc = &ciw->cdromtoc; int pos; int msf; int start, end; int status; bool valid = false; bool regenerate = true; memset (buf, 0, SUBQ_SIZE); p = buf; status = AUDIO_STATUS_NO_STATUS; if (ciw->cdda_play) { status = AUDIO_STATUS_IN_PROGRESS; if (ciw->cdda_paused) status = AUDIO_STATUS_PAUSED; } else if (ciw->cdda_play_finished) { status = AUDIO_STATUS_PLAY_COMPLETE; } p[1] = status; p[3] = 12; p = buf + 4; if (sector < 0) pos = ciw->cd_last_pos; else pos = sector; if (!regenerate) { if (sector < 0 && ciw->subcodevalid && ciw->cdda_play) { uae_sem_wait (&ciw->sub_sem2); uae_u8 subbuf[SUB_CHANNEL_SIZE]; sub_deinterleave (ciw->subcodebuf, subbuf); memcpy (p, subbuf + 12, 12); uae_sem_post (&ciw->sub_sem2); valid = true; } if (!valid && sector >= 0) { DWORD len; uae_sem_wait (&ciw->sub_sem); seterrormode (ciw); RAW_READ_INFO rri; rri.DiskOffset.QuadPart = 2048 * (pos + 0); rri.SectorCount = 1; rri.TrackMode = RawWithSubCode; memset (ciw->tempbuffer, 0, CD_RAW_SECTOR_WITH_SUBCODE_SIZE); if (!DeviceIoControl (ciw->h, IOCTL_CDROM_RAW_READ, &rri, sizeof rri, ciw->tempbuffer, CD_RAW_SECTOR_WITH_SUBCODE_SIZE, &len, NULL)) { DWORD err = GetLastError (); write_log (_T("IOCTL_CDROM_RAW_READ SUBQ CDDA sector %d returned %d\n"), pos, err); } reseterrormode (ciw); uae_u8 subbuf[SUB_CHANNEL_SIZE]; sub_deinterleave (ciw->tempbuffer + 2352, subbuf); uae_sem_post (&ciw->sub_sem); memcpy (p, subbuf + 12, 12); valid = true; } } if (!valid) { start = end = 0; for (trk = 0; trk <= toc->LastTrack; trk++) { TRACK_DATA *td = &toc->TrackData[trk]; start = msf2lsn ((td->Address[1] << 16) | (td->Address[2] << 8) | td->Address[3]); end = msf2lsn ((td[1].Address[1] << 16) | (td[1].Address[2] << 8) | td[1].Address[3]); if (pos < start) break; if (pos >= start && pos < end) break; } p[0] = (toc->TrackData[trk].Control << 4) | (toc->TrackData[trk].Adr << 0); p[1] = tobcd (trk + 1); p[2] = tobcd (1); msf = lsn2msf (pos); tolongbcd (p + 7, msf); msf = lsn2msf (pos - start - 150); tolongbcd (p + 3, msf); } // write_log (_T("%6d %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n"), // pos, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11]); return 1; }
static void *cdda_play (void *v) { struct dev_info_ioctl *ciw = (struct dev_info_ioctl*)v; int cdda_pos; int num_sectors = CDDA_BUFFERS; int bufnum; int buffered; int bufon[2]; int i; int oldplay; int idleframes; int muteframes; int readblocksize = 2352 + 96; while (ciw->cdda_play == 0) Sleep (10); oldplay = -1; bufon[0] = bufon[1] = 0; bufnum = 0; buffered = 0; cda_audio *cda = new cda_audio (num_sectors); while (ciw->cdda_play > 0) { cda->wait(bufnum); if (ciw->cdda_play <= 0) goto end; bufon[bufnum] = 0; if (oldplay != ciw->cdda_play) { idleframes = 0; muteframes = 0; bool seensub = false; struct _timeb tb1, tb2; _ftime (&tb1); cdda_pos = ciw->cdda_start; ciw->cd_last_pos = cdda_pos; oldplay = ciw->cdda_play; write_log (_T("IOCTL%s CDDA: playing from %d to %d\n"), ciw->usesptiread ? _T("(SPTI)") : _T(""), ciw->cdda_start, ciw->cdda_end); ciw->subcodevalid = false; idleframes = ciw->cdda_delay_frames; while (ciw->cdda_paused && ciw->cdda_play > 0) { Sleep (10); idleframes = -1; } // force spin up if (isaudiotrack (&ciw->di.toc, cdda_pos)) read_block (ciw, -1, cda->buffers[bufnum], cdda_pos, num_sectors, readblocksize); if (!isaudiotrack (&ciw->di.toc, cdda_pos - 150)) muteframes = 75; if (ciw->cdda_scan == 0) { // find possible P-subchannel=1 and fudge starting point so that // buggy CD32/CDTV software CD+G handling does not miss any frames bool seenindex = false; for (int sector = cdda_pos - 200; sector < cdda_pos; sector++) { uae_u8 *dst = cda->buffers[bufnum]; if (sector >= 0 && isaudiotrack (&ciw->di.toc, sector) && read_block (ciw, -1, dst, sector, 1, readblocksize)) { uae_u8 subbuf[SUB_CHANNEL_SIZE]; sub_deinterleave (dst + 2352, subbuf); if (seenindex) { for (int i = 2 * SUB_ENTRY_SIZE; i < SUB_CHANNEL_SIZE; i++) { if (subbuf[i]) { // non-zero R-W subchannels? int diff = cdda_pos - sector + 2; write_log (_T("-> CD+G start pos fudge -> %d (%d)\n"), sector, -diff); idleframes -= diff; cdda_pos = sector; seensub = true; break; } } } else if (subbuf[0] == 0xff) { // P == 1? seenindex = true; } } } } cdda_pos -= idleframes; _ftime (&tb2); int diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm); diff -= ciw->cdda_delay; if (idleframes >= 0 && diff < 0 && ciw->cdda_play > 0) Sleep (-diff); if (diff > 0 && !seensub) { int ch = diff / 7 + 25; if (ch > idleframes) ch = idleframes; idleframes -= ch; cdda_pos += ch; } setstate (ciw, AUDIO_STATUS_IN_PROGRESS); } if ((cdda_pos < ciw->cdda_end || ciw->cdda_end == 0xffffffff) && !ciw->cdda_paused && ciw->cdda_play) { if (idleframes <= 0 && cdda_pos >= ciw->cdda_start && !isaudiotrack (&ciw->di.toc, cdda_pos)) { setstate (ciw, AUDIO_STATUS_PLAY_ERROR); write_log (_T("IOCTL: attempted to play data track %d\n"), cdda_pos); goto end; // data track? } gui_flicker_led (LED_CD, ciw->di.unitnum - 1, LED_CD_AUDIO); uae_sem_wait (&ciw->sub_sem); ciw->subcodevalid = false; memset (ciw->subcode, 0, sizeof ciw->subcode); memset (cda->buffers[bufnum], 0, num_sectors * readblocksize); if (cdda_pos >= 0) { if (read_block (ciw, -1, cda->buffers[bufnum], cdda_pos, num_sectors, readblocksize)) { for (i = 0; i < num_sectors; i++) { memcpy (ciw->subcode + i * SUB_CHANNEL_SIZE, cda->buffers[bufnum] + readblocksize * i + 2352, SUB_CHANNEL_SIZE); } for (i = 1; i < num_sectors; i++) { memmove (cda->buffers[bufnum] + 2352 * i, cda->buffers[bufnum] + readblocksize * i, 2352); } ciw->subcodevalid = true; } } for (i = 0; i < num_sectors; i++) { if (muteframes > 0) { memset (cda->buffers[bufnum] + 2352 * i, 0, 2352); muteframes--; } if (idleframes > 0) { idleframes--; memset (cda->buffers[bufnum] + 2352 * i, 0, 2352); memset (ciw->subcode + i * SUB_CHANNEL_SIZE, 0, SUB_CHANNEL_SIZE); } else if (cdda_pos < ciw->cdda_start && ciw->cdda_scan == 0) { memset (cda->buffers[bufnum] + 2352 * i, 0, 2352); } } if (idleframes > 0) ciw->subcodevalid = false; if (ciw->cdda_subfunc) ciw->cdda_subfunc (ciw->subcode, num_sectors); uae_sem_post (&ciw->sub_sem); if (ciw->subcodevalid) { uae_sem_wait (&ciw->sub_sem2); memcpy (ciw->subcodebuf, ciw->subcode + (num_sectors - 1) * SUB_CHANNEL_SIZE, SUB_CHANNEL_SIZE); uae_sem_post (&ciw->sub_sem2); } bufon[bufnum] = 1; cda->setvolume (currprefs.sound_volume_cd >= 0 ? currprefs.sound_volume_cd : currprefs.sound_volume, ciw->cdda_volume[0], ciw->cdda_volume[1]); if (!cda->play (bufnum)) { setstate (ciw, AUDIO_STATUS_PLAY_ERROR); goto end; // data track? } if (ciw->cdda_scan) { cdda_pos += ciw->cdda_scan * num_sectors; if (cdda_pos < 0) cdda_pos = 0; } else { if (cdda_pos < 0 && cdda_pos + num_sectors >= 0) cdda_pos = 0; else cdda_pos += num_sectors; } if (idleframes <= 0) { if (cdda_pos - num_sectors < ciw->cdda_end && cdda_pos >= ciw->cdda_end) { setstate (ciw, AUDIO_STATUS_PLAY_COMPLETE); ciw->cdda_play_finished = 1; ciw->cdda_play = -1; cdda_pos = ciw->cdda_end; } ciw->cd_last_pos = cdda_pos; } } while (ciw->cdda_paused && ciw->cdda_play == oldplay) Sleep (10); bufnum = 1 - bufnum; } end: ciw->subcodevalid = false; delete cda; ciw->cdda_play = 0; write_log (_T("IOCTL CDDA: thread killed\n")); return NULL; }
void finish_sound_buffer (void) { uae_sem_post (&data_available_sem); uae_sem_wait (&callback_done_sem); }
void uae_nativesem_wait(void) { uae_sem_wait(&n2asem); }
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; }
static void *uaenet_trap_thread (void *arg) { struct uaenetdatawin32 *sd = arg; HANDLE handles[4]; int cnt, towrite; int readactive, writeactive; DWORD actual; uae_set_thread_priority (NULL, 2); sd->threadactive = 1; uae_sem_post (&sd->sync_sem); readactive = 0; writeactive = 0; while (sd->threadactive == 1) { int donotwait = 0; uae_sem_wait (&sd->change_sem); if (readactive) { if (GetOverlappedResult (sd->hCom, &sd->olr, &actual, FALSE)) { readactive = 0; uaenet_gotdata (sd->user, sd->readbuffer, actual); donotwait = 1; } } if (writeactive) { if (GetOverlappedResult (sd->hCom, &sd->olw, &actual, FALSE)) { writeactive = 0; donotwait = 1; } } if (!readactive) { if (!ReadFile (sd->hCom, sd->readbuffer, sd->mtu, &actual, &sd->olr)) { DWORD err = GetLastError(); if (err == ERROR_IO_PENDING) readactive = 1; } else { uaenet_gotdata (sd->user, sd->readbuffer, actual); donotwait = 1; } } towrite = 0; if (!writeactive && uaenet_getdata (sd->user, sd->writebuffer, &towrite)) { donotwait = 1; if (!WriteFile (sd->hCom, sd->writebuffer, towrite, &actual, &sd->olw)) { DWORD err = GetLastError(); if (err == ERROR_IO_PENDING) writeactive = 1; } } uae_sem_post (&sd->change_sem); if (!donotwait) { cnt = 0; handles[cnt++] = sd->evtt; if (readactive) handles[cnt++] = sd->olr.hEvent; if (writeactive) handles[cnt++] = sd->olw.hEvent; WaitForMultipleObjects(cnt, handles, FALSE, INFINITE); } } sd->threadactive = 0; uae_sem_post (&sd->sync_sem); return 0; }
static int dev_do_io_2 (struct s2devstruct *dev, uaecptr request, int quick) { uae_u8 flags = get_byte (request + 30); uae_u32 command = get_word (request + 28); uae_u32 packettype = get_long (request + 32 + 4); uaecptr data = get_long (request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4); uae_u32 datalength = get_long (request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2); uaecptr srcaddr = request + 32 + 4 + 4; uaecptr dstaddr = request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES; uaecptr statdata = get_long (request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4 + 4); uaecptr buffermgmt = get_long (request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4 + 4 + 4); uae_u32 io_error = 0; uae_u32 wire_error = 0; int i; int async = 0; struct priv_s2devstruct *pdev = getps2devstruct (request); if (log_net) write_log (_T("S2: C=%02d T=%04X S=%02X%02X%02X%02X%02X%02X D=%02X%02X%02X%02X%02X%02X L=%d D=%08X SD=%08X BM=%08X\n"), command, packettype, get_byte (srcaddr + 0), get_byte (srcaddr + 1), get_byte (srcaddr + 2), get_byte (srcaddr + 3), get_byte (srcaddr + 4), get_byte (srcaddr + 5), get_byte (dstaddr + 0), get_byte (dstaddr + 1), get_byte (dstaddr + 2), get_byte (dstaddr + 3), get_byte (dstaddr + 4), get_byte (dstaddr + 5), datalength, data, statdata, buffermgmt); if (command == CMD_READ || command == S2_READORPHAN || command == CMD_WRITE || command == S2_BROADCAST || command == S2_MULTICAST) { if (!pdev->copyfrombuff || !pdev->copytobuff) { io_error = S2ERR_BAD_ARGUMENT; wire_error = S2WERR_BUFF_ERROR; goto end; } } switch (command) { case CMD_READ: if (!dev->online) goto offline; async = 1; break; case S2_READORPHAN: if (!dev->online) goto offline; async = 1; break; case S2_BROADCAST: case CMD_WRITE: if (!dev->online) goto offline; if (!checksize (request, dev)) goto toobig; async = 1; break; case S2_MULTICAST: if (!dev->online) goto offline; if ((get_byte (dstaddr + 0) & 1) == 0) { io_error = S2ERR_BAD_ADDRESS; wire_error = S2WERR_BAD_MULTICAST; goto end; } if (!checksize (request, dev)) goto toobig; async = 1; break; case CMD_FLUSH: dev->flush_timeout_cnt = 0; dev->flush_timeout = FLUSH_TIMEOUT; if (log_net) write_log (_T("CMD_FLUSH started %08x\n"), request); uae_sem_wait (&async_sem); flush (pdev); uae_sem_post (&async_sem); async = 1; uaenet_vsync_requested++; break; case S2_ADDMULTICASTADDRESS: addmulticastaddresses (dev, amigaaddrto64 (srcaddr), 0); break; case S2_DELMULTICASTADDRESS: if (!delmulticastaddresses (dev, amigaaddrto64 (srcaddr), 0)) { io_error = S2ERR_BAD_STATE; wire_error = S2WERR_BAD_MULTICAST; } break; case S2_ADDMULTICASTADDRESSES: addmulticastaddresses (dev, amigaaddrto64 (srcaddr), amigaaddrto64 (dstaddr)); break; case S2_DELMULTICASTADDRESSES: if (!delmulticastaddresses (dev, amigaaddrto64 (srcaddr), amigaaddrto64 (dstaddr))) { io_error = S2ERR_BAD_STATE; wire_error = S2WERR_BAD_MULTICAST; } break; case S2_DEVICEQUERY: { int size = get_long (statdata); if (size > 30) size = 30; put_long (statdata + 4, size); if (size >= 12) put_long (statdata + 8, 0); if (size >= 16) put_long (statdata + 12, 0); if (size >= 18) put_word (statdata + 16, ADDR_SIZE * 8); if (size >= 22) put_long (statdata + 18, dev->td->mtu); if (size >= 26) put_long (statdata + 22, 10000000); if (size >= 30) put_long (statdata + 26, S2WireType_Ethernet); } break; case S2_GETTYPESTATS: if (pdev->trackcnt) { put_long (statdata + 0, pdev->packetssent); put_long (statdata + 4, pdev->packetsreceived); put_long (statdata + 8, pdev->bytessent); put_long (statdata + 12, pdev->bytesreceived); put_long (statdata + 16, pdev->packetsdropped); } else { io_error = S2ERR_BAD_STATE; wire_error = S2WERR_NOT_TRACKED; } break; case S2_GETGLOBALSTATS: put_long (statdata + 0, dev->packetsreceived); put_long (statdata + 4, dev->packetssent); put_long (statdata + 8, dev->baddata); put_long (statdata + 12, dev->overruns); put_long (statdata + 16, 0); put_long (statdata + 20, dev->unknowntypesreceived); put_long (statdata + 24, dev->reconfigurations); put_long (statdata + 28, dev->online_secs); put_long (statdata + 32, dev->online_micro); break; case S2_GETSPECIALSTATS: put_long (statdata + 1, 0); break; case S2_GETSTATIONADDRESS: for (i = 0; i < ADDR_SIZE; i++) { put_byte (srcaddr + i, dev->td->mac[i]); put_byte (dstaddr + i, dev->td->mac[i]); } break; case S2_CONFIGINTERFACE: if (dev->configured) { io_error = S2ERR_BAD_STATE; wire_error = S2WERR_IS_CONFIGURED; } else { dev->configured = TRUE; } break; case S2_ONLINE: if (!dev->configured) { io_error = S2ERR_BAD_STATE; wire_error = S2WERR_NOT_CONFIGURED; } if (!dev->adapter) { io_error = S2ERR_OUTOFSERVICE; wire_error = S2WERR_RCVREL_HDW_ERR; } if (!io_error) { uaenet_vsync_requested++; async = 1; } break; case S2_TRACKTYPE: if (packettype <= 65535) { if (pdev->tracks[packettype]) { io_error = S2ERR_BAD_STATE; wire_error = S2WERR_ALREADY_TRACKED; } else { pdev->tracks[packettype] = 1; pdev->trackcnt++; } } else { io_error = S2ERR_BAD_ARGUMENT; } break; case S2_UNTRACKTYPE: if (packettype <= 65535) { if (!pdev->tracks[packettype]) { io_error = S2ERR_BAD_STATE; wire_error = S2WERR_NOT_TRACKED; } else { pdev->tracks[packettype] = 0; pdev->trackcnt--; } } else { io_error = S2ERR_BAD_ARGUMENT; } break; case S2_OFFLINE: if (dev->online) { dev->online = 0; checkevents (dev, S2EVENT_OFFLINE, 1); } break; case S2_ONEVENT: { uae_u32 events; uae_u32 wanted_events = get_long (request + 32); if (wanted_events & ~KNOWN_EVENTS) { io_error = S2ERR_NOT_SUPPORTED; events = S2WERR_BAD_EVENT; } else { if (dev->online) events = S2EVENT_ONLINE; else events = S2EVENT_OFFLINE; events &= wanted_events; if (events) { wire_error = events; } else { async = 1; } } } break; default: io_error = IOERR_NOCMD; break; offline: io_error = S2ERR_OUTOFSERVICE; wire_error = S2WERR_UNIT_OFFLINE; break; toobig: io_error = S2ERR_MTU_EXCEEDED; wire_error = S2WERR_GENERIC_ERROR; break; } end: if (log_net && (io_error || wire_error)) write_log (_T("-> %d (%d)\n"), io_error, wire_error); put_long (request + 32, wire_error); put_byte (request + 31, io_error); return async; }
/* handle_message() * * This is called from the GUI when a GUI event happened. Specifically, * HandleMessage (PPP_Messaging) forwards dispatched UI action * messages posted from JavaScript to handle_message(). */ int32_t handle_message(const char* msg) { /* Grammar for messages from the UI: * * message ::= 'insert' drive fileURL * | 'rom' fileURL * | 'connect' port input * | 'eject' drive * | 'reset' | 'pause' | 'resume' * | 'resize' <width> <height> * device ::= 'kickstart' | drive * drive ::= 'df0' | 'df1' * port ::= 'port0' | 'port1' * input ::= 'mouse' | 'joy0' | 'joy1' | 'kbd0' | 'kbd1' * fileURL ::= <a URL of the form blob://> */ DEBUG_LOG("%s\n", msg); if (!gui_initialized) { DEBUG_LOG("GUI message refused; not yet initialized.\n"); return -1; } /* TODO(cstefansen): scan the string instead of these shenanigans. */ /* Copy to non-const buffer. */ char buf[1024]; (void) strncpy(buf, msg, sizeof(buf) - 1); buf[sizeof(buf) - 1] = '\0'; /* Ensure NUL termination. */ /* Tokenize message up to 3 tokens (max given the grammar). */ int32_t i = 0; char *t[3], *token, *rest = NULL, *sep = " "; for (token = strtok_r(buf, sep, &rest); token != NULL && i <= 3; token = strtok_r(NULL, sep, &rest), ++i) { t[i] = token; } /* Pipe message to UAE main thread. */ if (i == 1 && !strcmp(t[0], "reset")) { write_comm_pipe_int(&from_gui_pipe, UAECMD_RESET, 1); } else if (i == 1 && !strcmp(t[0], "pause")) { /* It would be cleaner to call pause_sound and resume_sound in * gui_handle_events below, i.e, on the emulator thread. However, * if we're pausing because the tab is no longer in the foreground, * no graphics flush calls will unblock and no graphics callbacks will * be delivered until the tab is back in front. This means that the * emulator is probably already stuck in some call and won't get to * our UI request to pause the sound. */ /* TODO(cstefansen)People are reporting pausing/resuming problems; let's not do this until investigated. */ /* pause_sound(); */ write_comm_pipe_int(&from_gui_pipe, UAECMD_PAUSE, 1); } else if (i == 1 && !strcmp(t[0], "resume")) { /* resume_sound(); */ write_comm_pipe_int(&from_gui_pipe, UAECMD_RESUME, 1); } else if (i == 2 && !strcmp(t[0], "eject")) { int32_t drive_num; if (!strcmp(t[1], "df0")) { drive_num = 0; } else if (!strcmp(t[1], "df1")) { drive_num = 1; } else { return -1; } write_comm_pipe_int(&from_gui_pipe, UAECMD_EJECTDISK, 0); write_comm_pipe_int(&from_gui_pipe, drive_num, 1); } else if (i == 3 && !strcmp(t[0], "resize")) { long width = strtol(t[1], NULL, 10); long height = strtol(t[2], NULL, 10); if (width > INT_MAX || height > INT_MAX || errno == ERANGE || width <= 0 || height <= 0) { write_log("Could not parse width/height in message: %s\n", msg); return -1; } write_comm_pipe_int(&from_gui_pipe, UAECMD_RESIZE, 0); write_comm_pipe_int(&from_gui_pipe, (int32_t) width, 0); write_comm_pipe_int(&from_gui_pipe, (int32_t) height, 1); } else if (i == 3 && !strcmp(t[0], "insert")) { int32_t drive_num; if (!strcmp(t[1], "df0")) { drive_num = 0; } else if (!strcmp(t[1], "df1")) { drive_num = 1; } else { return -1; } uae_sem_wait(&gui_sem); if (new_disk_string[drive_num] != 0) free (new_disk_string[drive_num]); new_disk_string[drive_num] = strdup(t[2]); uae_sem_post(&gui_sem); write_comm_pipe_int (&from_gui_pipe, UAECMD_INSERTDISK, 0); write_comm_pipe_int (&from_gui_pipe, drive_num, 1); } else if (i == 2 && !strcmp(t[0], "rom")) { uae_sem_wait(&gui_sem); if (gui_romname != 0) free (gui_romname); gui_romname = strdup(t[1]); uae_sem_post(&gui_sem); write_comm_pipe_int(&from_gui_pipe, UAECMD_SELECT_ROM, 1); } else if (i == 3 && !strcmp(t[0], "connect")) { int32_t port_num; if (!strcmp(t[1], "port0")) { port_num = 0; } else if (!strcmp(t[1], "port1")) { port_num = 1; } else { return -1; } int32_t input_device = !strcmp(t[2], "mouse") ? JSEM_MICE : !strcmp(t[2], "joy0") ? JSEM_JOYS : !strcmp(t[2], "joy1") ? JSEM_JOYS + 1 : !strcmp(t[2], "kbd0") ? JSEM_KBDLAYOUT + 1 : !strcmp(t[2], "kbd1") ? JSEM_KBDLAYOUT + 2 : JSEM_END; changed_prefs.jports[port_num].id = input_device; if (changed_prefs.jports[port_num].id != currprefs.jports[port_num].id) { /* It's a little fishy that the typical way to update input * devices doesn't use the comm pipe. */ inputdevice_updateconfig (&changed_prefs); inputdevice_config_change(); } } else { return -1; } return 0; }
static int execscsicmd_direct (int unitnum, struct amigascsi *as) { struct dev_info_spti *di = unitisopen (unitnum); if (!di) return -1; SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb; DWORD status; int sactual = 0, i; int io_error = 0, err, parm; uae_u8 *scsi_datap, *scsi_datap_org; uae_u32 scsi_cmd_len_orig = as->cmd_len; memset (&swb, 0, sizeof (swb)); swb.spt.Length = sizeof (SCSI_PASS_THROUGH); swb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, SenseBuf); if (as->len > DEVICE_SCSI_BUFSIZE) as->len = DEVICE_SCSI_BUFSIZE; uae_sem_wait (&scgp_sem); /* the Amiga does not tell us how long the timeout shall be, so make it _very_ long (specified in seconds) */ swb.spt.TimeOutValue = 80 * 60; scsi_datap = scsi_datap_org = as->len ? as->data : 0; swb.spt.DataIn = (as->flags & 1) ? SCSI_IOCTL_DATA_IN : SCSI_IOCTL_DATA_OUT; for (i = 0; i < as->cmd_len; i++) swb.spt.Cdb[i] = as->cmd[i]; if (as->sense_len > 32) as->sense_len = 32; swb.spt.SenseInfoLength = (as->flags & 4) ? 4 : /* SCSIF_OLDAUTOSENSE */ (as->flags & 2) ? as->sense_len : /* SCSIF_AUTOSENSE */ 32; if (dev_info[unitnum].isatapi) scsi_atapi_fixup_pre (swb.spt.Cdb, &as->cmd_len, &scsi_datap, &as->len, &parm); memcpy (di->scsibuf, scsi_datap, as->len); swb.spt.CdbLength = (UCHAR)as->cmd_len; swb.spt.DataTransferLength = as->len; swb.spt.DataBuffer = di->scsibuf; status = doscsi (di, unitnum, &swb, &err); memcpy (scsi_datap, di->scsibuf, as->len); as->cmdactual = status == 0 ? 0 : scsi_cmd_len_orig; /* fake scsi_CmdActual */ as->status = swb.spt.ScsiStatus; /* scsi_Status */ if (swb.spt.ScsiStatus) { io_error = 45; /* HFERR_BadStatus */ /* copy sense? */ for (sactual = 0; sactual < as->sense_len && sactual < swb.spt.SenseInfoLength; sactual++) as->sensedata[sactual] = swb.SenseBuf[sactual]; as->actual = 0; /* scsi_Actual */ } else { int i; for (i = 0; i < as->sense_len; i++) as->sensedata[i] = 0; sactual = 0; if (status == 0) { io_error = 20; /* io_Error, but not specified */ as->actual = 0; /* scsi_Actual */ } else { as->len = swb.spt.DataTransferLength; if (dev_info[unitnum].isatapi) scsi_atapi_fixup_post (swb.spt.Cdb, as->cmd_len, scsi_datap_org, scsi_datap, &as->len, parm); io_error = 0; as->actual = as->len; /* scsi_Actual */ } } as->sactual = sactual; uae_sem_post (&scgp_sem); if (scsi_datap != scsi_datap_org) free (scsi_datap); return io_error; }
void uaeser_signal (void *vdev, int32_t sigmask) { struct devstruct *dev = (struct devstruct*)vdev; struct asyncreq *ar; int32_t i = 0; uae_sem_wait (&async_sem); ar = dev->ar; while (ar) { if (!ar->ready) { uaecptr request = ar->request; uint32_t io_data = get_long (request + 40); // 0x28 uint32_t io_length = get_long (request + 36); // 0x24 int32_t command = get_word (request + 28); uint32_t io_error = 0, io_actual = 0; uint8_t *addr; int32_t io_done = 0; switch (command) { case SDCMD_BREAK: if (ar == dev->ar) { uaeser_break (dev->sysdata, get_long (request + io_BrkTime)); io_done = 1; } break; case CMD_READ: if (sigmask & 1) { addr = memmap(io_data, io_length); if (addr) { if (uaeser_read (dev->sysdata, addr, io_length)) { io_error = 0; io_actual = io_length; io_done = 1; } } else { io_error = IOERR_BADADDRESS; io_done = 1; } } break; case CMD_WRITE: if (sigmask & 2) { io_error = IOERR_BADADDRESS; addr = memmap(io_data, io_length); if (addr && uaeser_write (dev->sysdata, addr, io_length)) io_error = 0; io_actual = io_length; io_done = 1; } break; default: write_log (_T("%s:%d incorrect async request %x (cmd=%d) signaled?!"), getdevname(), dev->unit, request, command); break; } if (io_done) { if (log_uaeserial) write_log (_T("%s:%d async request %x completed\n"), getdevname(), dev->unit, request); put_long (request + 32, io_actual); put_byte (request + 31, io_error); ar->ready = 1; write_comm_pipe_u32 (&dev->requests, request, 1); } } ar = ar->next; } uae_sem_post (&async_sem); }