/* We simply find the first function in this .obj data, and execute it. */ static uae_u32 REGPARAM2 emulib_ExecuteNativeCode (struct regstruct *regs) { #if 0 uaecptr object_AAM = m68k_areg (regs, 0); uae_u32 d1 = m68k_dreg (regs, 1); uae_u32 d2 = m68k_dreg (regs, 2); uae_u32 d3 = m68k_dreg (regs, 3); uae_u32 d4 = m68k_dreg (regs, 4); uae_u32 d5 = m68k_dreg (regs, 5); uae_u32 d6 = m68k_dreg (regs, 6); uae_u32 d7 = m68k_dreg (regs, 7); uae_u32 a1 = m68k_areg (regs, 1); uae_u32 a2 = m68k_areg (regs, 2); uae_u32 a3 = m68k_areg (regs, 3); uae_u32 a4 = m68k_areg (regs, 4); uae_u32 a5 = m68k_areg (regs, 5); uae_u32 a6 = m68k_areg (regs, 6); uae_u8* object_UAM = NULL; CREATE_NATIVE_FUNC_PTR; if( get_mem_bank( object_AAM ).check( object_AAM, 1 ) ) object_UAM = get_mem_bank( object_AAM).xlateaddr( object_AAM ); if( object_UAM ) { SET_NATIVE_FUNC( FindFunctionInObject( object_UAM ) ); CALL_NATIVE_FUNC( d1, d2, d3, d4, d5, d6, d7, a1, a2, a3, a4, a5, a6); } return 1; #endif return 0; }
/** * Write long/word/byte into memory. * NOTE - value will be converted to 68000 endian */ void STMemory_Write ( Uint32 addr , Uint32 val , int size ) { addrbank *pBank; Uint8 *p; //printf ( "mem direct write %x %x %d\n" , addr , val , size ); pBank = &get_mem_bank ( addr ); if ( pBank->baseaddr == NULL ) return; /* No real memory, do nothing */ addr -= pBank->start & pBank->mask; addr &= pBank->mask; p = pBank->baseaddr + addr; /* We modify the memory, so we flush the instr/data caches if needed */ M68000_Flush_All_Caches ( addr , size ); if ( size == 4 ) do_put_mem_long ( p , val ); else if ( size == 2 ) do_put_mem_word ( p , (Uint16)val ); else *p = (Uint8)val; }
static uint8_t *memmap(uint32_t addr, uint32_t len) { addrbank *bank_data = &get_mem_bank (addr); if (!bank_data->check (addr, len)) return NULL; return bank_data->xlateaddr (addr); }
static uae_u8 *memmap(uae_u32 addr, uae_u32 len) { addrbank *bank_data = &get_mem_bank (addr); if (!bank_data->check (addr, len)) return NULL; return bank_data->xlateaddr (addr); }
STATIC_INLINE bool spinlock_pre(uaecptr addr) { addrbank *ab = &get_mem_bank(addr); if ((ab->flags & ABFLAG_THREADSAFE) == 0) { uae_ppc_spinlock_get(); return true; } return false; }
/************************************************************* Converts an amiga address to a native one or NULL if this is not possible, Size specified the number of bytes you want to access *************************************************************/ static uae_u8 *amiga2native (uae_u32 aptr, int size) { addrbank bank = get_mem_bank (aptr); /* Check if the address can be translated to native */ if (bank.check (aptr, size)) { return bank.xlateaddr (aptr); } return NULL; }
/** * Check that the region of 'size' starting at 'addr' is entirely inside * a memory bank of the same memory type */ bool STMemory_CheckAreaType ( Uint32 addr , int size , int mem_type ) { addrbank *pBank; pBank = &get_mem_bank ( addr ); if ( ( pBank->flags & mem_type ) == 0 ) { fprintf(stderr, "pBank flags mismatch: 0x%x & 0x%x (RAM = 0x%x)\n", pBank->flags, mem_type, ABFLAG_RAM); return false; } return pBank->check ( addr , size ); }
/** * Read long/word/byte from memory. * NOTE - value will be converted to 68000 endian */ Uint32 STMemory_Read ( Uint32 addr , int size ) { addrbank *pBank; Uint8 *p; //printf ( "mem direct read %x %d\n" , addr , size ); pBank = &get_mem_bank ( addr ); if ( pBank->baseaddr == NULL ) return 0; /* No real memory, return 0 */ addr -= pBank->start & pBank->mask; addr &= pBank->mask; p = pBank->baseaddr + addr; if ( size == 4 ) return do_get_mem_long ( p ); else if ( size == 2 ) return (Uint32)do_get_mem_word ( p ); else return (Uint32)*p; }
static __inline__ void byteput (uaecptr addr, uae_u32 b) { call_mem_put_func (get_mem_bank (addr).bput, addr, b); }
__inline__ uae_u32 longget (uaecptr addr) { return call_mem_get_func (get_mem_bank (addr).lget, addr); }
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 int execscsicmd_direct_ioctl (int unitnum, struct amigascsi* ascsi) { struct scsidevdata *sdd; struct cdrom_generic_command cmd; struct request_sense sense; uaecptr acmd = VALUE_TO_PTR(ascsi); 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); uae_u8 scsi_flags = get_byte (acmd + 20); uae_u8 scsi_status = get_byte (acmd + 21); uaecptr scsi_sense = get_long (acmd + 22); uae_u16 scsi_sense_len = get_word (acmd + 26); int io_error; unsigned int senselen; int parm, i; addrbank *bank_data = &get_mem_bank (scsi_data); addrbank *bank_cmd = &get_mem_bank (scsi_cmd); addrbank *bank_sense = &get_mem_bank (scsi_sense); uae_u8 *scsi_datap; uae_u8 *scsi_datap_org; DEBUG_LOG ("SCSIDEV: unit = %d: execscsicmd_direct_ioctl\n", unitnum); DEBUG_LOG ("SCSIDEV: scsi_len = %d, scsi_cmd_len = %d, scsi_sense_len = %d, scsi_flags = %x\n", scsi_len, scsi_cmd_len, scsi_sense_len, scsi_flags); if (unitnum >= total_drives) { DEBUG_LOG ("SCSIDEV: illegal unit %d >= total_drives %d.\n", unitnum, total_drives); return -1; /* TODO: better error code */ } sdd = &drives[unitnum]; /* do transfer directly to and from Amiga memory */ if (!bank_data || !bank_data->check (scsi_data, scsi_len)) { DEBUG_LOG ("SCSIDEV: illegal Amiga memory buffer\n"); return -5; /* IOERR_BADADDRESS */ } if (scsi_cmd_len > CDROM_PACKET_SIZE) { DEBUG_LOG ("SCSIDEV: scsi_cmd_len too large (%d)\n", scsi_cmd_len); return -5; /* TODO: better code */ } scsi_datap = scsi_datap_org = (scsi_len ? bank_data->xlateaddr (scsi_data) : 0); memcpy (cmd.cmd, bank_cmd->xlateaddr (scsi_cmd), scsi_cmd_len); cmd.buffer = scsi_datap; cmd.buflen = scsi_len; cmd.stat = scsi_status; if (sdd->isatapi) { scsi_atapi_fixup_pre (cmd.cmd, &scsi_cmd_len, &scsi_datap, &scsi_len, &parm); } senselen = (scsi_flags & 4) ? 4 : /* SCSIF_OLDAUTOSENSE */ (scsi_flags & 2) ? scsi_sense_len : /* SCSIF_AUTOSENSE */ 0; cmd.sense = senselen > 0 ? &sense : 0; cmd.data_direction = (scsi_flags & 1) ? CGC_DATA_READ : CGC_DATA_WRITE; cmd.quiet = 0; cmd.timeout = 80*60; gui_flicker_led (LED_CD, 0, 1); io_error = ioctl (sdd->fd, CDROM_SEND_PACKET, &cmd); DEBUG_LOG ("SCSIDEV: error: %d, stat: %d\n", io_error, cmd.stat); if (cmd.stat != 0) { unsigned int n; io_error = 45; /* HFERR_BadStatus */ put_byte (acmd + 8, 0); put_byte (acmd + 18, 0 /*scsi_cmd_len */); put_byte (acmd + 21, cmd.stat); DEBUG_LOG ("SCSIDEV: bad status\n"); n = cmd.sense ? cmd.sense->add_sense_len + 7 : 0; if (senselen > n) { if (scsi_sense) memset (bank_sense->xlateaddr (scsi_sense), 0, senselen); senselen = n; } DEBUG_LOG ("SCSIDEV: senselen = %d\n", senselen); if (scsi_sense && cmd.sense && senselen > 0) { memcpy (bank_sense->xlateaddr (scsi_sense), cmd.sense, senselen); } put_byte (acmd + 28, senselen); } else { put_byte (acmd + 28, 0); if (scsi_sense && senselen > 0) { memset (bank_sense->xlateaddr (scsi_sense), 0, senselen); } if (io_error == 0) { if (sdd->isatapi) { scsi_atapi_fixup_post (cmd.cmd, scsi_cmd_len, scsi_datap_org, scsi_datap, &scsi_len, parm); } put_long (acmd + 8, scsi_len); put_word (acmd + 18, scsi_cmd_len); put_byte (acmd + 21, cmd.stat); io_error = 0; } else { DEBUG_LOG ("SCSIDEV: errno: %d, %s\n", errno, strerror (errno)); put_long (acmd + 8, 0); put_word (acmd + 18, 0); put_byte (acmd + 21, cmd.stat); io_error = 20; /* TODO: Map errors */ } } if (scsi_datap != scsi_datap_org) xfree (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 {
__inline__ uae_u32 wordget (uaecptr addr) { return call_mem_get_func (get_mem_bank (addr).wget, addr); }
static __inline__ uae_u32 byteget (uaecptr addr) { return call_mem_get_func (get_mem_bank (addr).bget, addr); }
static __inline__ void wordput (uaecptr addr, uae_u32 w) { call_mem_put_func (get_mem_bank (addr).wput, addr, w); }
static __inline__ void longput (uaecptr addr, uae_u32 l) { call_mem_put_func (get_mem_bank (addr).lput, addr, l); }