Ejemplo n.º 1
0
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));
	}
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
0
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);
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
0
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 {
Ejemplo n.º 16
0
/*
 * 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;
        }
    }
}
Ejemplo n.º 17
0
/* 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;

}
Ejemplo n.º 18
0
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;
}
Ejemplo n.º 19
0
void finish_sound_buffer (void)
{
    uae_sem_post (&data_available_sem);
    uae_sem_wait (&callback_done_sem);
}
Ejemplo n.º 20
0
void uae_nativesem_wait(void)
{
	uae_sem_wait(&n2asem);
}
Ejemplo n.º 21
0
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;
}
Ejemplo n.º 22
0
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;
}
Ejemplo n.º 23
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;
}
Ejemplo n.º 24
0
/* 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;
}
Ejemplo n.º 25
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;
}
Ejemplo n.º 26
0
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);
}