Full Upgrade to the 1.7 tree.

This commit is contained in:
waltje
2018-10-06 18:20:09 -04:00
parent b775d592d4
commit 2f69c95152
395 changed files with 57724 additions and 52823 deletions

View File

@@ -8,7 +8,7 @@
*
* Handling of the SCSI controllers.
*
* Version: @(#)scsi.c 1.0.10 2018/05/12
* Version: @(#)scsi.c 1.0.11 2018/10/05
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -42,16 +42,17 @@
#include <stdarg.h>
#include <wchar.h>
#define HAVE_STDARG_H
#define dbglog scsi_log
#include "../../emu.h"
#include "../../mem.h"
#include "../../rom.h"
#include "../../timer.h"
#include "../../device.h"
#include "../../plat.h"
#include "../disk/hdc.h"
#include "../disk/zip.h"
#include "../cdrom/cdrom.h"
#include "../disk/hdd.h"
#include "scsi.h"
#include "scsi_device.h"
#include "scsi_disk.h"
#include "../cdrom/cdrom.h"
#include "../disk/zip.h"
#include "scsi_aha154x.h"
#include "scsi_buslogic.h"
#include "scsi_ncr5380.h"
@@ -59,104 +60,50 @@
#ifdef USE_WD33C93
# include "scsi_wd33c93.h"
#endif
#include "scsi_x54x.h"
#ifdef ENABLE_SCSI_LOG
int scsi_do_log = ENABLE_SCSI_LOG;
#endif
#ifdef ENABLE_SCSI_DEV_LOG
int scsi_dev_do_log = ENABLE_SCSI_DEV_LOG;
#endif
scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX];
#if 0
uint8_t SCSIPhase = 0xff;
uint8_t SCSIStatus = SCSI_STATUS_OK;
#endif
char scsi_fn[SCSI_NUM][512];
uint16_t scsi_hd_location[SCSI_NUM];
uint32_t SCSI_BufferLength;
static volatile
mutex_t *scsiMutex;
typedef struct {
const char *name;
static struct {
const char *internal_name;
const device_t *device;
void (*reset)(void *p);
} scsidev_t;
} scsi_cards[] = {
{ "none", NULL },
static const scsidev_t scsi_cards[] = {
{ "None", "none", NULL, NULL },
{ "[ISA] Adaptec AHA-1540B","aha1540b", &aha1540b_device, x54x_device_reset },
{ "[ISA] Adaptec AHA-1542C","aha1542c", &aha1542c_device, x54x_device_reset },
{ "[ISA] Adaptec AHA-1542CF","aha1542cf", &aha1542cf_device, x54x_device_reset },
{ "[ISA] BusLogic BT-542BH","bt542bh", &buslogic_device, BuslogicDeviceReset },
{ "[ISA] BusLogic BT-545S", "bt545s", &buslogic_545s_device,BuslogicDeviceReset },
{ "[ISA] Longshine LCS-6821N","lcs6821n", &scsi_lcs6821n_device,NULL },
{ "[ISA] Ranco RT1000B", "rt1000b", &scsi_rt1000b_device, NULL },
{ "[ISA] Trantor T130B", "t130b", &scsi_t130b_device, NULL },
{ "[ISA] Sumo SCSI-AT", "scsiat", &scsi_scsiat_device, NULL },
{ "aha1540b", &aha1540b_device },
{ "aha1542c", &aha1542c_device },
{ "aha1542cf", &aha1542cf_device },
{ "bt542bh", &buslogic_device },
{ "bt545s", &buslogic_545s_device },
{ "lcs6821n", &scsi_lcs6821n_device },
{ "rt1000b", &scsi_rt1000b_device },
{ "t130b", &scsi_t130b_device },
{ "scsiat", &scsi_scsiat_device },
#ifdef USE_WD33C93
{ "[ISA] Generic WDC33C93", "wd33c93", &scsi_wd33c93_device, NULL },
{ "wd33c93", &scsi_wd33c93_device },
#endif
{ "[MCA] Adaptec AHA-1640", "aha1640", &aha1640_device, x54x_device_reset },
{ "[MCA] BusLogic BT-640A", "bt640a", &buslogic_640a_device,BuslogicDeviceReset },
{ "[PCI] BusLogic BT-958D", "bt958d", &buslogic_pci_device, BuslogicDeviceReset },
{ "[PCI] NCR 53C810", "ncr53c810", &ncr53c810_pci_device,NULL },
{ "[VLB] BusLogic BT-445S", "bt445s", &buslogic_445s_device,BuslogicDeviceReset },
{ NULL, NULL, NULL, NULL },
{ "aha1640", &aha1640_device },
{ "bt640a", &buslogic_640a_device },
{ "bt958d", &buslogic_pci_device },
{ "ncr53c810", &ncr53c810_pci_device },
{ "bt445s", &buslogic_445s_device },
{ NULL, NULL }
};
void
scsi_dev_log(const char *fmt, ...)
{
#ifdef ENABLE_SCSI_DEV_LOG
va_list ap;
if (scsi_dev_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
#endif
}
int
scsi_card_available(int card)
{
if (scsi_cards[card].device)
return(device_available(scsi_cards[card].device));
return(1);
}
const char *
scsi_card_getname(int card)
{
return(scsi_cards[card].name);
}
const device_t *
scsi_card_getdevice(int card)
{
return(scsi_cards[card].device);
}
int
scsi_card_has_config(int card)
{
if (! scsi_cards[card].device) return(0);
return(scsi_cards[card].device->config ? 1 : 0);
}
const char *
scsi_card_get_internal_name(int card)
{
@@ -180,13 +127,70 @@ scsi_card_get_from_internal_name(const char *s)
}
void
scsi_mutex(uint8_t start)
const char *
scsi_card_getname(int card)
{
if (start)
scsiMutex = thread_create_mutex(L"VARCem.SCSIMutex");
else
thread_close_mutex((mutex_t *) scsiMutex);
if (scsi_cards[card].device != NULL)
return(scsi_cards[card].device->name);
return(NULL);
}
const device_t *
scsi_card_getdevice(int card)
{
return(scsi_cards[card].device);
}
int
scsi_card_has_config(int card)
{
if (scsi_cards[card].device != NULL)
return(scsi_cards[card].device->config ? 1 : 0);
return(0);
}
void
scsi_log(int level, const char *fmt, ...)
{
#ifdef ENABLE_SCSI_LOG
va_list ap;
if (scsi_do_log >= level) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
#endif
}
void
scsi_dev_log(int level, const char *fmt, ...)
{
#ifdef ENABLE_SCSI_DEV_LOG
va_list ap;
if (scsi_dev_do_log >= level) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
#endif
}
int
scsi_card_available(int card)
{
if (scsi_cards[card].device)
return(device_available(scsi_cards[card].device));
return(1);
}
@@ -195,85 +199,31 @@ scsi_card_init(void)
{
int i, j;
pclog("SCSI: building hard disk map...\n");
build_scsi_hd_map();
if (! scsi_cards[scsi_card].device) return;
pclog("SCSI: building CD-ROM map...\n");
DEBUG("SCSI: building hard disk map...\n");
build_scsi_disk_map();
DEBUG("SCSI: building CD-ROM map...\n");
build_scsi_cdrom_map();
pclog("SCSI: building ZIP map...\n");
build_scsi_zip_map();
DEBUG("SCSI: building ZIP map...\n");
zip_build_scsi_map();
for (i=0; i<SCSI_ID_MAX; i++) {
for (j=0; j<SCSI_LUN_MAX; j++) {
if (scsi_disks[i][j] != 0xff) {
for (i = 0; i < SCSI_ID_MAX; i++) {
for (j = 0; j < SCSI_LUN_MAX; j++) {
if (scsi_disks[i][j] != 0xff)
SCSIDevices[i][j].LunType = SCSI_DISK;
} else if (scsi_cdrom_drives[i][j] != 0xff) {
else if (scsi_cdrom_drives[i][j] != 0xff)
SCSIDevices[i][j].LunType = SCSI_CDROM;
} else if (scsi_zip_drives[i][j] != 0xff) {
else if (scsi_zip_drives[i][j] != 0xff)
SCSIDevices[i][j].LunType = SCSI_ZIP;
} else {
else
SCSIDevices[i][j].LunType = SCSI_NONE;
}
SCSIDevices[i][j].CmdBuffer = NULL;
}
}
if (scsi_cards[scsi_card].device)
device_add(scsi_cards[scsi_card].device);
}
void
scsi_card_reset(void)
{
void *p = NULL;
if (scsi_cards[scsi_card].device) {
p = device_get_priv(scsi_cards[scsi_card].device);
if (p != NULL) {
if (scsi_cards[scsi_card].reset)
scsi_cards[scsi_card].reset(p);
}
}
}
/* Initialization function for the SCSI layer */
void
SCSIReset(uint8_t id, uint8_t lun)
{
uint8_t cdrom_id = scsi_cdrom_drives[id][lun];
uint8_t zip_id = scsi_zip_drives[id][lun];
uint8_t hdd_id = scsi_disks[id][lun];
if (hdd_id != 0xff) {
scsi_hd_reset(hdd_id);
SCSIDevices[id][lun].LunType = SCSI_DISK;
} else {
if (cdrom_id != 0xff) {
cdrom_reset(cdrom_id);
SCSIDevices[id][lun].LunType = SCSI_CDROM;
} else if (zip_id != 0xff) {
zip_reset(zip_id);
SCSIDevices[id][lun].LunType = SCSI_ZIP;
} else {
SCSIDevices[id][lun].LunType = SCSI_NONE;
}
}
if (SCSIDevices[id][lun].CmdBuffer != NULL) {
free(SCSIDevices[id][lun].CmdBuffer);
SCSIDevices[id][lun].CmdBuffer = NULL;
}
}
void
scsi_mutex_wait(uint8_t wait)
{
if (wait)
thread_wait_mutex((mutex_t *) scsiMutex);
else
thread_release_mutex((mutex_t *) scsiMutex);
device_add(scsi_cards[scsi_card].device);
}

View File

@@ -6,9 +6,9 @@
*
* This file is part of the VARCem Project.
*
* SCSI controller handler header.
* SCSI module definitions.
*
* Version: @(#)scsi.h 1.0.7 2018/04/14
* Version: @(#)scsi.h 1.0.8 2018/10/05
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -39,277 +39,7 @@
#define EMU_SCSI_H
#define SCSI_TIME (5 * 100 * (1 << TIMER_SHIFT))
/* Configuration. */
#define SCSI_ID_MAX 16 /* 16 on wide buses */
#define SCSI_LUN_MAX 8 /* always 8 */
/* SCSI commands. */
#define GPCMD_TEST_UNIT_READY 0x00
#define GPCMD_REZERO_UNIT 0x01
#define GPCMD_REQUEST_SENSE 0x03
#define GPCMD_FORMAT_UNIT 0x04
#define GPCMD_IOMEGA_SENSE 0x06
#define GPCMD_READ_6 0x08
#define GPCMD_WRITE_6 0x0a
#define GPCMD_SEEK_6 0x0b
#define GPCMD_IOMEGA_SET_PROTECTION_MODE 0x0c
#define GPCMD_IOMEGA_EJECT 0x0d /* ATAPI only? */
#define GPCMD_INQUIRY 0x12
#define GPCMD_VERIFY_6 0x13
#define GPCMD_MODE_SELECT_6 0x15
#define GPCMD_SCSI_RESERVE 0x16
#define GPCMD_SCSI_RELEASE 0x17
#define GPCMD_MODE_SENSE_6 0x1a
#define GPCMD_START_STOP_UNIT 0x1b
#define GPCMD_SEND_DIAGNOSTIC 0x1d
#define GPCMD_PREVENT_REMOVAL 0x1e
#define GPCMD_READ_FORMAT_CAPACITIES 0x23
#define GPCMD_READ_CDROM_CAPACITY 0x25
#define GPCMD_READ_10 0x28
#define GPCMD_WRITE_10 0x2a
#define GPCMD_SEEK_10 0x2b
#define GPCMD_WRITE_AND_VERIFY_10 0x2e
#define GPCMD_VERIFY_10 0x2f
#define GPCMD_READ_BUFFER 0x3c
#define GPCMD_WRITE_SAME_10 0x41
#define GPCMD_READ_SUBCHANNEL 0x42
#define GPCMD_READ_TOC_PMA_ATIP 0x43
#define GPCMD_READ_HEADER 0x44
#define GPCMD_PLAY_AUDIO_10 0x45
#define GPCMD_GET_CONFIGURATION 0x46
#define GPCMD_PLAY_AUDIO_MSF 0x47
#define GPCMD_PLAY_AUDIO_TRACK_INDEX 0x48
#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
#define GPCMD_PAUSE_RESUME 0x4b
#define GPCMD_STOP_PLAY_SCAN 0x4e
#define GPCMD_READ_DISC_INFORMATION 0x51
#define GPCMD_READ_TRACK_INFORMATION 0x52
#define GPCMD_MODE_SELECT_10 0x55
#define GPCMD_MODE_SENSE_10 0x5a
#define GPCMD_PLAY_AUDIO_12 0xa5
#define GPCMD_READ_12 0xa8
#define GPCMD_WRITE_12 0xaa
#define GPCMD_READ_DVD_STRUCTURE 0xad /* For reading. */
#define GPCMD_WRITE_AND_VERIFY_12 0xae
#define GPCMD_VERIFY_12 0xaf
#define GPCMD_PLAY_CD_OLD 0xb4
#define GPCMD_READ_CD_OLD 0xb8
#define GPCMD_READ_CD_MSF 0xb9
#define GPCMD_SCAN 0xba
#define GPCMD_SET_SPEED 0xbb
#define GPCMD_PLAY_CD 0xbc
#define GPCMD_MECHANISM_STATUS 0xbd
#define GPCMD_READ_CD 0xbe
#define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to PCem. */
#define GPCMD_PAUSE_RESUME_ALT 0xc2
#define GPCMD_SCAN_ALT 0xcd /* Should be equivalent to 0xba */
#define GPCMD_SET_SPEED_ALT 0xda /* Should be equivalent to 0xbb */
/* Mode page codes for mode sense/set */
#define GPMODE_R_W_ERROR_PAGE 0x01
#define GPMODE_CDROM_PAGE 0x0d
#define GPMODE_CDROM_AUDIO_PAGE 0x0e
#define GPMODE_CAPABILITIES_PAGE 0x2a
#define GPMODE_ALL_PAGES 0x3f
/* SCSI Status Codes */
#define SCSI_STATUS_OK 0
#define SCSI_STATUS_CHECK_CONDITION 2
/* SCSI Sense Keys */
#define SENSE_NONE 0
#define SENSE_NOT_READY 2
#define SENSE_ILLEGAL_REQUEST 5
#define SENSE_UNIT_ATTENTION 6
/* SCSI Additional Sense Codes */
#define ASC_AUDIO_PLAY_OPERATION 0x00
#define ASC_NOT_READY 0x04
#define ASC_ILLEGAL_OPCODE 0x20
#define ASC_LBA_OUT_OF_RANGE 0x21
#define ASC_INV_FIELD_IN_CMD_PACKET 0x24
#define ASC_INV_LUN 0x25
#define ASC_INV_FIELD_IN_PARAMETER_LIST 0x26
#define ASC_WRITE_PROTECTED 0x27
#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28
#define ASC_CAPACITY_DATA_CHANGED 0x2A
#define ASC_INCOMPATIBLE_FORMAT 0x30
#define ASC_MEDIUM_NOT_PRESENT 0x3a
#define ASC_DATA_PHASE_ERROR 0x4b
#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK 0x64
#define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01
#define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02
#define ASCQ_CAPACITY_DATA_CHANGED 0x09
#define ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS 0x11
#define ASCQ_AUDIO_PLAY_OPERATION_PAUSED 0x12
#define ASCQ_AUDIO_PLAY_OPERATION_COMPLETED 0x13
/* Tell RISC OS that we have a 4x CD-ROM drive (600kb/sec data, 706kb/sec raw).
Not that it means anything */
#define CDROM_SPEED 706 /* 0x2C2 */
#define BUFFER_SIZE (256*1024)
#define RW_DELAY (TIMER_USEC * 500)
/* Some generally useful CD-ROM information */
#define CD_MINS 75 /* max. minutes per CD */
#define CD_SECS 60 /* seconds per minute */
#define CD_FRAMES 75 /* frames per second */
#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */
#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE)
#define CD_MAX_SECTORS (CD_MAX_BYTES / 512)
/* Event notification classes for GET EVENT STATUS NOTIFICATION */
#define GESN_NO_EVENTS 0
#define GESN_OPERATIONAL_CHANGE 1
#define GESN_POWER_MANAGEMENT 2
#define GESN_EXTERNAL_REQUEST 3
#define GESN_MEDIA 4
#define GESN_MULTIPLE_HOSTS 5
#define GESN_DEVICE_BUSY 6
/* Event codes for MEDIA event status notification */
#define MEC_NO_CHANGE 0
#define MEC_EJECT_REQUESTED 1
#define MEC_NEW_MEDIA 2
#define MEC_MEDIA_REMOVAL 3 /* only for media changers */
#define MEC_MEDIA_CHANGED 4 /* only for media changers */
#define MEC_BG_FORMAT_COMPLETED 5 /* MRW or DVD+RW b/g format completed */
#define MEC_BG_FORMAT_RESTARTED 6 /* MRW or DVD+RW b/g format restarted */
#define MS_TRAY_OPEN 1
#define MS_MEDIA_PRESENT 2
/*
* The MMC values are not IDE specific and might need to be moved
* to a common header if they are also needed for the SCSI emulation
*/
/* Profile list from MMC-6 revision 1 table 91 */
#define MMC_PROFILE_NONE 0x0000
#define MMC_PROFILE_CD_ROM 0x0008
#define MMC_PROFILE_CD_R 0x0009
#define MMC_PROFILE_CD_RW 0x000A
#define MMC_PROFILE_DVD_ROM 0x0010
#define MMC_PROFILE_DVD_R_SR 0x0011
#define MMC_PROFILE_DVD_RAM 0x0012
#define MMC_PROFILE_DVD_RW_RO 0x0013
#define MMC_PROFILE_DVD_RW_SR 0x0014
#define MMC_PROFILE_DVD_R_DL_SR 0x0015
#define MMC_PROFILE_DVD_R_DL_JR 0x0016
#define MMC_PROFILE_DVD_RW_DL 0x0017
#define MMC_PROFILE_DVD_DDR 0x0018
#define MMC_PROFILE_DVD_PLUS_RW 0x001A
#define MMC_PROFILE_DVD_PLUS_R 0x001B
#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A
#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B
#define MMC_PROFILE_BD_ROM 0x0040
#define MMC_PROFILE_BD_R_SRM 0x0041
#define MMC_PROFILE_BD_R_RRM 0x0042
#define MMC_PROFILE_BD_RE 0x0043
#define MMC_PROFILE_HDDVD_ROM 0x0050
#define MMC_PROFILE_HDDVD_R 0x0051
#define MMC_PROFILE_HDDVD_RAM 0x0052
#define MMC_PROFILE_HDDVD_RW 0x0053
#define MMC_PROFILE_HDDVD_R_DL 0x0058
#define MMC_PROFILE_HDDVD_RW_DL 0x005A
#define MMC_PROFILE_INVALID 0xFFFF
#define SCSI_ONLY 32
#define ATAPI_ONLY 16
#define IMPLEMENTED 8
#define NONDATA 4
#define CHECK_READY 2
#define ALLOW_UA 1
extern uint8_t SCSICommandTable[0x100];
extern uint8_t mode_sense_pages[0x40];
extern int readcdmode;
/* Mode sense/select stuff. */
extern uint8_t mode_pages_in[256][256];
extern uint8_t page_flags[256];
extern uint8_t prefix_len;
extern uint8_t page_current;
#define PAGE_CHANGEABLE 1
#define PAGE_CHANGED 2
struct _scsisense_ {
uint8_t SenseBuffer[18];
uint8_t SenseLength;
uint8_t UnitAttention;
uint8_t SenseKey;
uint8_t Asc;
uint8_t Ascq;
} SCSISense;
extern int cd_status;
extern int prev_status;
enum {
SCSI_NONE = 0,
SCSI_DISK,
SCSI_CDROM,
SCSI_ZIP
};
#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f)
#define MSG_COMMAND_COMPLETE 0x00
#define BUS_DBP 0x01
#define BUS_SEL 0x02
#define BUS_IO 0x04
#define BUS_CD 0x08
#define BUS_MSG 0x10
#define BUS_REQ 0x20
#define BUS_BSY 0x40
#define BUS_RST 0x80
#define BUS_ACK 0x200
#define BUS_ATN 0x200
#define BUS_ARB 0x8000
#define BUS_SETDATA(val) ((uint32_t)val << 16)
#define BUS_GETDATA(val) ((val >> 16) & 0xff)
#define BUS_DATAMASK 0xff0000
#define BUS_IDLE (1 << 31)
#define SCSI_PHASE_DATA_OUT 0
#define SCSI_PHASE_DATA_IN BUS_IO
#define SCSI_PHASE_COMMAND BUS_CD
#define SCSI_PHASE_STATUS (BUS_CD | BUS_IO)
#define SCSI_PHASE_MESSAGE_OUT (BUS_MSG | BUS_CD)
#define SCSI_PHASE_MESSAGE_IN (BUS_MSG | BUS_CD | BUS_IO)
typedef struct {
uint8_t *CmdBuffer;
int LunType;
int32_t BufferLength;
uint8_t Status;
uint8_t Phase;
} scsi_device_t;
extern scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX];
extern void SCSIReset(uint8_t id, uint8_t lun);
extern int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type);
extern int cdrom_LBAtoMSF_accurate(void);
extern int mode_select_init(uint8_t command, uint16_t pl_length, uint8_t do_save);
extern int mode_select_terminate(int force);
extern int mode_select_write(uint8_t val);
extern uint8_t scsi_disks[16][8];
extern void scsi_dev_log(const char *fmt, ...);
extern void scsi_log(int level, const char *fmt, ...);
extern int scsi_card_available(int card);
extern const char *scsi_card_getname(int card);
@@ -319,67 +49,7 @@ extern const device_t *scsi_card_getdevice(int card);
extern int scsi_card_has_config(int card);
extern const char *scsi_card_get_internal_name(int card);
extern int scsi_card_get_from_internal_name(const char *s);
extern void scsi_mutex(uint8_t start);
extern void scsi_mutex_wait(uint8_t wait);
extern void scsi_card_init(void);
extern void scsi_card_reset(void);
extern int scsi_hd_err_stat_to_scsi(uint8_t id);
extern int scsi_hd_phase_to_scsi(uint8_t id);
extern int find_hdc_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun);
extern void build_scsi_hd_map(void);
extern void scsi_hd_reset(uint8_t id);
extern void scsi_hd_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length);
extern void scsi_hd_command(uint8_t id, uint8_t *cdb);
extern void scsi_hd_callback(uint8_t id);
#pragma pack(push,1)
typedef struct {
uint8_t hi;
uint8_t mid;
uint8_t lo;
} addr24;
#pragma pack(pop)
#define ADDR_TO_U32(x) (((x).hi<<16)|((x).mid<<8)|((x).lo&0xFF))
#define U32_TO_ADDR(a,x) do {(a).hi=(x)>>16;(a).mid=(x)>>8;(a).lo=(x)&0xFF;}while(0)
/*
*
* Scatter/Gather Segment List Definitions
*
* Adapter limits
*/
#define MAX_SG_DESCRIPTORS 32 /* Always make the array 32 elements long, if less are used, that's not an issue. */
#pragma pack(push,1)
typedef struct {
uint32_t Segment;
uint32_t SegmentPointer;
} SGE32;
#pragma pack(pop)
#pragma pack(push,1)
typedef struct {
addr24 Segment;
addr24 SegmentPointer;
} SGE;
#pragma pack(pop)
#pragma pack(push,1)
typedef struct {
uint8_t pages[0x40][0x40];
} mode_sense_pages_t;
#pragma pack(pop)
#define MODE_SELECT_PHASE_IDLE 0
#define MODE_SELECT_PHASE_HEADER 1
#define MODE_SELECT_PHASE_BLOCK_DESC 2
#define MODE_SELECT_PHASE_PAGE_HEADER 3
#define MODE_SELECT_PHASE_PAGE 4
#endif /*EMU_SCSI_H*/

View File

@@ -10,7 +10,7 @@
* made by Adaptec, Inc. These controllers were designed for
* the ISA bus.
*
* Version: @(#)scsi_aha154x.c 1.0.9 2018/05/06
* Version: @(#)scsi_aha154x.c 1.0.10 2018/10/05
*
* Based on original code from TheCollector1995 and Miran Grca.
*
@@ -44,6 +44,7 @@
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#define dbglog scsi_dev_log
#include "../../emu.h"
#include "../../io.h"
#include "../../mem.h"
@@ -55,13 +56,11 @@
#include "../system/dma.h"
#include "../system/pic.h"
#include "../system/mca.h"
#include "scsi.h"
#include "scsi_device.h"
#include "scsi_aha154x.h"
#include "scsi_x54x.h"
#define aha_log scsi_dev_log
#define AHA1540B_330_BIOS_PATH L"scsi/adaptec/aha1540b320_330.bin"
#define AHA1540B_334_BIOS_PATH L"scsi/adaptec/aha1540b320_334.bin"
#define AHA1540C_BIOS_PATH L"scsi/adaptec/aha1542c102.bin"
@@ -163,13 +162,12 @@ shram_cmd(x54x_t *dev, uint8_t cmd)
static void
eeprom_save(x54x_t *dev)
{
FILE *f;
FILE *fp;
f = plat_fopen(nvr_path(dev->nvr_path), L"wb");
if (f != NULL) {
fwrite(dev->nvr, 1, NVR_SIZE, f);
fclose(f);
f = NULL;
fp = plat_fopen(nvr_path(dev->nvr_path), L"wb");
if (fp != NULL) {
fwrite(dev->nvr, 1, NVR_SIZE, fp);
fclose(fp);
}
}
@@ -180,7 +178,7 @@ eeprom_cmd(x54x_t *dev, uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8_t
uint8_t r = 0xff;
int c;
aha_log("%s: EEPROM cmd=%02x, arg=%02x len=%d, off=%02x\n",
DEBUG("%s: EEPROM cmd=%02x, arg=%02x len=%d, off=%02x\n",
dev->name, cmd, arg, len, off);
/* Only if we can handle it.. */
@@ -210,7 +208,7 @@ eeprom_cmd(x54x_t *dev, uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8_t
static uint8_t
mmap_cmd(x54x_t *dev, uint8_t cmd)
{
aha_log("%s: MEMORY cmd=%02x\n", dev->name, cmd);
DEBUG("%s: MEMORY cmd=%02x\n", dev->name, cmd);
switch(cmd) {
case 0x26:
@@ -229,36 +227,36 @@ mmap_cmd(x54x_t *dev, uint8_t cmd)
static uint8_t
get_host_id(void *p)
get_host_id(void *priv)
{
x54x_t *dev = (x54x_t *)p;
x54x_t *dev = (x54x_t *)priv;
return(dev->nvr[0] & 0x07);
}
static uint8_t
get_irq(void *p)
get_irq(void *priv)
{
x54x_t *dev = (x54x_t *)p;
x54x_t *dev = (x54x_t *)priv;
return((dev->nvr[1] & 0x07) + 9);
}
static uint8_t
get_dma(void *p)
get_dma(void *priv)
{
x54x_t *dev = (x54x_t *)p;
x54x_t *dev = (x54x_t *)priv;
return((dev->nvr[1] >> 4) & 0x07);
}
static uint8_t
cmd_is_fast(void *p)
cmd_is_fast(void *priv)
{
x54x_t *dev = (x54x_t *)p;
x54x_t *dev = (x54x_t *)priv;
if (dev->Command == CMD_BIOS_SCSI)
return(1);
@@ -268,9 +266,9 @@ cmd_is_fast(void *p)
static uint8_t
fast_cmds(void *p, uint8_t cmd)
fast_cmds(void *priv, uint8_t cmd)
{
x54x_t *dev = (x54x_t *)p;
x54x_t *dev = (x54x_t *)priv;
if (cmd == CMD_BIOS_SCSI) {
dev->BIOSMailboxReq++;
@@ -282,9 +280,9 @@ fast_cmds(void *p, uint8_t cmd)
static uint8_t
param_len(void *p)
param_len(void *priv)
{
x54x_t *dev = (x54x_t *)p;
x54x_t *dev = (x54x_t *)priv;
switch (dev->Command) {
case CMD_BIOS_MBINIT:
@@ -322,7 +320,7 @@ aha_cmds(void *priv)
if (dev->CmdParamLeft) return(0);
aha_log("Running Operation Code 0x%02X\n", dev->Command);
DEBUG("Running Operation Code 0x%02X\n", dev->Command);
switch (dev->Command) {
case CMD_WR_EEPROM: /* write EEPROM */
/* Sent by CF BIOS. */
@@ -373,10 +371,8 @@ aha_cmds(void *priv)
dev->BIOSMailboxCount = mbi->Count;
dev->BIOSMailboxOutAddr = ADDR_TO_U32(mbi->Address);
aha_log("Initialize BIOS Mailbox: MBO=0x%08lx, %d entries at 0x%08lx\n",
dev->BIOSMailboxOutAddr,
mbi->Count,
ADDR_TO_U32(mbi->Address));
DEBUG("Initialize BIOS Mailbox: MBO=0x%08lx, %d entries at 0x%08lx\n",
dev->BIOSMailboxOutAddr, mbi->Count, ADDR_TO_U32(mbi->Address));
dev->Status &= ~STAT_INIT;
dev->DataReplyLeft = 0;
@@ -452,7 +448,7 @@ do_bios_mail(x54x_t *dev)
dev->MailboxIsBIOS = 1;
if (! dev->BIOSMailboxCount) {
aha_log("aha_do_bios_mail(): No BIOS Mailboxes\n");
DEBUG("aha_do_bios_mail(): No BIOS Mailboxes\n");
return;
}
@@ -559,7 +555,7 @@ aha_mca_write(int port, uint8_t val, void *priv)
*
* So, remove current address, if any.
*/
mem_mapping_disable(&dev->bios.mapping);
mem_map_disable(&dev->bios.mapping);
/* Initialize the device if fully configured. */
if (dev->pos_regs[2] & 0x01) {
@@ -571,13 +567,14 @@ aha_mca_write(int port, uint8_t val, void *priv)
/* Enable or disable the BIOS ROM. */
if (dev->rom_addr != 0x000000) {
mem_mapping_enable(&dev->bios.mapping);
mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE);
mem_map_enable(&dev->bios.mapping);
mem_map_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE);
}
/* Say hello. */
pclog("AHA-1640: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n",
dev->Base, dev->Irq, dev->DmaChannel, dev->rom_addr, dev->HostID);
INFO("%s: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n",
dev->name, dev->Base, dev->Irq, dev->DmaChannel,
dev->rom_addr, dev->HostID);
}
}
@@ -589,16 +586,16 @@ set_bios(x54x_t *dev)
uint32_t size;
uint32_t mask;
uint32_t temp;
FILE *f;
FILE *fp;
int i;
/* Only if this device has a BIOS ROM. */
if (dev->bios_path == NULL) return;
/* Open the BIOS image file and make sure it exists. */
aha_log("%s: loading BIOS from '%ls'\n", dev->name, dev->bios_path);
if ((f = plat_fopen(rom_path(dev->bios_path), L"rb")) == NULL) {
aha_log("%s: BIOS ROM not found!\n", dev->name);
DEBUG("%s: loading BIOS from '%ls'\n", dev->name, dev->bios_path);
if ((fp = plat_fopen(rom_path(dev->bios_path), L"rb")) == NULL) {
ERRLOG("%s: BIOS ROM not found!\n", dev->name);
return;
}
@@ -609,33 +606,33 @@ set_bios(x54x_t *dev)
* this special case, we can't: we may need WRITE access to the
* memory later on.
*/
(void)fseek(f, 0L, SEEK_END);
temp = ftell(f);
(void)fseek(f, 0L, SEEK_SET);
(void)fseek(fp, 0L, SEEK_END);
temp = ftell(fp);
(void)fseek(fp, 0L, SEEK_SET);
/* Load first chunk of BIOS (which is the main BIOS, aka ROM1.) */
dev->rom1 = malloc(ROM_SIZE);
(void)fread(dev->rom1, ROM_SIZE, 1, f);
dev->rom1 = (uint8_t *)mem_alloc(ROM_SIZE);
(void)fread(dev->rom1, ROM_SIZE, 1, fp);
temp -= ROM_SIZE;
if (temp > 0) {
dev->rom2 = malloc(ROM_SIZE);
(void)fread(dev->rom2, ROM_SIZE, 1, f);
dev->rom2 = (uint8_t *)mem_alloc(ROM_SIZE);
(void)fread(dev->rom2, ROM_SIZE, 1, fp);
temp -= ROM_SIZE;
} else {
dev->rom2 = NULL;
}
if (temp != 0) {
aha_log("%s: BIOS ROM size invalid!\n", dev->name);
ERRLOG("%s: BIOS ROM size invalid!\n", dev->name);
free(dev->rom1);
if (dev->rom2 != NULL)
free(dev->rom2);
(void)fclose(f);
(void)fclose(fp);
return;
}
temp = ftell(f);
temp = ftell(fp);
if (temp > ROM_SIZE)
temp = ROM_SIZE;
(void)fclose(f);
(void)fclose(fp);
/* Adjust BIOS size in chunks of 2K, as per BIOS spec. */
size = 0x10000;
@@ -646,8 +643,8 @@ set_bios(x54x_t *dev)
if (temp <= 0x2000)
size = 0x2000;
mask = (size - 1);
aha_log("%s: BIOS at 0x%06lX, size %lu, mask %08lx\n",
dev->name, dev->rom_addr, size, mask);
INFO("%s: BIOS at 0x%06lX, size %lu, mask %08lx\n",
dev->name, dev->rom_addr, size, mask);
/* Initialize the ROM entry for this BIOS. */
memset(&dev->bios, 0x00, sizeof(rom_t));
@@ -659,11 +656,11 @@ set_bios(x54x_t *dev)
dev->bios.mask = mask;
/* Map this system into the memory map. */
mem_mapping_add(&dev->bios.mapping, dev->rom_addr, size,
mem_read, NULL, NULL, /* aha_mem_readw, aha_mem_readl, */
mem_write, NULL, NULL,
dev->bios.rom, MEM_MAPPING_EXTERNAL, dev);
mem_mapping_disable(&dev->bios.mapping);
mem_map_add(&dev->bios.mapping, dev->rom_addr, size,
mem_read, NULL, NULL, /* aha_mem_readw, aha_mem_readl, */
mem_write, NULL, NULL,
dev->bios.rom, MEM_MAPPING_EXTERNAL, dev);
mem_map_disable(&dev->bios.mapping);
/*
* Patch the ROM BIOS image for stuff Adaptec deliberately
@@ -676,10 +673,10 @@ set_bios(x54x_t *dev)
*/
if (dev->rom_ioaddr != 0x0000) {
/* Look up the I/O address in the table. */
for (i=0; i<8; i++)
for (i = 0; i < 8; i++)
if (aha_ports[i] == dev->Base) break;
if (i == 8) {
aha_log("%s: invalid I/O address %04x selected!\n",
ERRLOG("%s: invalid I/O address %04x selected!\n",
dev->name, dev->Base);
return;
}
@@ -712,20 +709,19 @@ init_nvr(x54x_t *dev)
static void
set_nvr(x54x_t *dev)
{
FILE *f;
FILE *fp;
/* Only if this device has an EEPROM. */
if (dev->nvr_path == NULL) return;
/* Allocate and initialize the EEPROM. */
dev->nvr = (uint8_t *)malloc(NVR_SIZE);
dev->nvr = (uint8_t *)mem_alloc(NVR_SIZE);
memset(dev->nvr, 0x00, NVR_SIZE);
f = plat_fopen(nvr_path(dev->nvr_path), L"rb");
if (f != NULL) {
(void)fread(dev->nvr, 1, NVR_SIZE, f);
fclose(f);
f = NULL;
fp = plat_fopen(nvr_path(dev->nvr_path), L"rb");
if (fp != NULL) {
(void)fread(dev->nvr, 1, NVR_SIZE, fp);
fclose(fp);
} else {
init_nvr(dev);
}
@@ -739,7 +735,7 @@ aha_init(const device_t *info)
x54x_t *dev;
/* Call common initializer. */
dev = x54x_init(info);
dev = (x54x_t *)x54x_init(info);
/*
* Set up the (initial) I/O address, IRQ and DMA info.
@@ -866,8 +862,8 @@ aha_init(const device_t *info)
/* Enable the memory. */
if (dev->rom_addr != 0x000000) {
mem_mapping_enable(&dev->bios.mapping);
mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE);
mem_map_enable(&dev->bios.mapping);
mem_map_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE);
}
}
}
@@ -877,232 +873,232 @@ aha_init(const device_t *info)
static const device_config_t aha_154xb_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x334,
{
"base", "Address", CONFIG_HEX16, "", 0x334,
{
{
"None", 0
},
{
"0x330", 0x330
},
{
"0x334", 0x334
},
{
"0x230", 0x230
},
{
"0x234", 0x234
},
{
"0x130", 0x130
},
{
"0x134", 0x134
},
{
""
}
"None", 0
},
},
{
"0x330", 0x330
},
{
"0x334", 0x334
},
{
"0x230", 0x230
},
{
"0x234", 0x234
},
{
"0x130", 0x130
},
{
"0x134", 0x134
},
{
""
}
}
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 9,
{
"irq", "IRQ", CONFIG_SELECTION, "", 9,
{
{
"IRQ 9", 9
},
{
"IRQ 10", 10
},
{
"IRQ 11", 11
},
{
"IRQ 12", 12
},
{
"IRQ 14", 14
},
{
"IRQ 15", 15
},
{
""
}
"IRQ 9", 9
},
},
{
"IRQ 10", 10
},
{
"IRQ 11", 11
},
{
"IRQ 12", 12
},
{
"IRQ 14", 14
},
{
"IRQ 15", 15
},
{
""
}
}
},
{
"dma", "DMA channel", CONFIG_SELECTION, "", 6,
{
"dma", "DMA channel", CONFIG_SELECTION, "", 6,
{
{
"DMA 5", 5
},
{
"DMA 6", 6
},
{
"DMA 7", 7
},
{
""
}
"DMA 5", 5
},
},
{
"DMA 6", 6
},
{
"DMA 7", 7
},
{
""
}
}
},
{
"hostid", "Host ID", CONFIG_SELECTION, "", 7,
{
"hostid", "Host ID", CONFIG_SELECTION, "", 7,
{
{
"0", 0
},
{
"1", 1
},
{
"2", 2
},
{
"3", 3
},
{
"4", 4
},
{
"5", 5
},
{
"6", 6
},
{
"7", 7
},
{
""
}
"0", 0
},
},
{
"1", 1
},
{
"2", 2
},
{
"3", 3
},
{
"4", 4
},
{
"5", 5
},
{
"6", 6
},
{
"7", 7
},
{
""
}
}
},
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0,
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0,
{
{
"Disabled", 0
},
{
"C800H", 0xc8000
},
{
"D000H", 0xd0000
},
{
"D800H", 0xd8000
},
{
""
}
"Disabled", 0
},
},
{
"", "", -1
}
{
"C800H", 0xc8000
},
{
"D000H", 0xd0000
},
{
"D800H", 0xd8000
},
{
""
}
}
},
{
"", "", -1
}
};
static const device_config_t aha_154x_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x334,
{
"base", "Address", CONFIG_HEX16, "", 0x334,
{
{
"None", 0
},
{
"0x330", 0x330
},
{
"0x334", 0x334
},
{
"0x230", 0x230
},
{
"0x234", 0x234
},
{
"0x130", 0x130
},
{
"0x134", 0x134
},
{
""
}
"None", 0
},
},
{
"0x330", 0x330
},
{
"0x334", 0x334
},
{
"0x230", 0x230
},
{
"0x234", 0x234
},
{
"0x130", 0x130
},
{
"0x134", 0x134
},
{
""
}
}
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 9,
{
"irq", "IRQ", CONFIG_SELECTION, "", 9,
{
{
"IRQ 9", 9
},
{
"IRQ 10", 10
},
{
"IRQ 11", 11
},
{
"IRQ 12", 12
},
{
"IRQ 14", 14
},
{
"IRQ 15", 15
},
{
""
}
"IRQ 9", 9
},
},
{
"IRQ 10", 10
},
{
"IRQ 11", 11
},
{
"IRQ 12", 12
},
{
"IRQ 14", 14
},
{
"IRQ 15", 15
},
{
""
}
}
},
{
"dma", "DMA channel", CONFIG_SELECTION, "", 6,
{
"dma", "DMA channel", CONFIG_SELECTION, "", 6,
{
{
"DMA 5", 5
},
{
"DMA 6", 6
},
{
"DMA 7", 7
},
{
""
}
"DMA 5", 5
},
},
{
"DMA 6", 6
},
{
"DMA 7", 7
},
{
""
}
}
},
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0,
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0,
{
{
"Disabled", 0
},
{
"C800H", 0xc8000
},
{
"D000H", 0xd0000
},
{
"D800H", 0xd8000
},
{
""
}
"Disabled", 0
},
},
{
"", "", -1
}
{
"C800H", 0xc8000
},
{
"D000H", 0xd0000
},
{
"D800H", 0xd8000
},
{
""
}
}
},
{
"", "", -1
}
};

View File

@@ -1,389 +0,0 @@
/*
* VARCem Virtual ARchaeological Computer EMulator.
* An emulator of (mostly) x86-based PC systems and devices,
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
* spanning the era between 1981 and 1995.
*
* This file is part of the VARCem Project.
*
* The generic SCSI bus operations handler.
*
* NOTES: For now ported from PCem with some modifications
* but at least it's a start.
*
* Version: @(#)scsi_bus.c 1.0.3 2018/09/21
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer@gmail.com>
*
* Copyright 2017,2018 Fred N. van Kempen.
* Copyright 2016-2018 Miran Grca.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include "../../emu.h"
#include "scsi.h"
#include "scsi_device.h"
#define STATE_IDLE 0
#define STATE_COMMAND 1
#define STATE_COMMANDWAIT 2
#define STATE_DATAIN 3
#define STATE_DATAOUT 4
#define STATE_STATUS 5
#define STATE_MESSAGEIN 6
#define STATE_PHASESEL 7
#define SET_BUS_STATE(bus, state) bus->bus_out = (bus->bus_out & ~(SCSI_PHASE_MESSAGE_IN)) | (state & (SCSI_PHASE_MESSAGE_IN))
uint32_t SCSI_BufferLength;
#ifdef ENABLE_SCSI_BUS_LOG
int scsi_bus_do_log = ENABLE_SCSI_BUS_LOG;
#endif
static void
scsi_bus_log(const char *fmt, ...)
{
#ifdef ENABLE_SCSI_BUS_LOG
va_list ap;
if (scsi_bus_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
#endif
}
/* get the length of a SCSI command based on its command byte type */
static int get_cmd_len(int cbyte)
{
int len = -1;
int group;
group = (cbyte>>5) & 7;
if (group == 0) len = 6;
if (group == 1 || group == 2) len = 10;
if (group == 5) len = 12;
// scsi_bus_log("Command group %d, length %d\n", group, len);
return(len);
}
static int
get_dev_id(uint8_t data)
{
int c;
for (c = 0; c < SCSI_ID_MAX; c++) {
if (data & (1 << c)) return(c);
}
return(-1);
}
int
scsi_bus_update(scsi_bus_t *bus, int bus_assert)
{
scsi_device_t *dev;
uint8_t lun = 0;
if (bus_assert & BUS_ARB)
bus->state = STATE_IDLE;
switch (bus->state) {
case STATE_IDLE:
scsi_bus_log("State Idle\n");
bus->clear_req = bus->change_state_delay = bus->new_req_delay = 0;
if ((bus_assert & BUS_SEL) && !(bus_assert & BUS_BSY)) {
uint8_t sel_data = BUS_GETDATA(bus_assert);
bus->dev_id = get_dev_id(sel_data);
if ((bus->dev_id != -1) && scsi_device_present(bus->dev_id, 0)) {
bus->bus_out |= BUS_BSY;
bus->state = STATE_PHASESEL;
}
//scsi_bus_log("Device id %i\n", bus->dev_id);
break;
}
break;
case STATE_PHASESEL:
scsi_bus_log("State Phase Sel\n");
if (! (bus_assert & BUS_SEL)) {
if (! (bus_assert & BUS_ATN)) {
if ((bus->dev_id != -1) &&
scsi_device_present(bus->dev_id, 0)) {
bus->state = STATE_COMMAND;
bus->bus_out = BUS_BSY | BUS_REQ;
bus->command_pos = 0;
SET_BUS_STATE(bus, SCSI_PHASE_COMMAND);
} else {
bus->state = STATE_IDLE;
bus->bus_out = 0;
}
} else
fatal("dropped sel %x\n", bus_assert & BUS_ATN);
}
break;
case STATE_COMMAND:
if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) {
scsi_bus_log("State Command\n");
bus->command[bus->command_pos++] = BUS_GETDATA(bus_assert);
bus->clear_req = 3;
bus->new_state = bus->bus_out & SCSI_PHASE_MESSAGE_IN;
bus->bus_out &= ~BUS_REQ;
if (get_cmd_len(bus->command[0]) == bus->command_pos) {
lun = (bus->command[1] >> 5) & 7;
bus->data_pos = 0;
dev = &SCSIDevices[bus->dev_id][lun];
scsi_bus_log("Command 0x%02X\n", bus->command[0]);
dev->BufferLength = -1;
scsi_device_command_phase0(bus->dev_id, lun,
get_cmd_len(bus->command[0]),
bus->command);
scsi_bus_log("(%02X:%02X): Command %02X: Buffer Length %i, SCSI Phase %02X\n", bus->dev_id, lun, bus->command[0], dev->BufferLength, dev->Phase);
if ((dev->Phase == SCSI_PHASE_DATA_IN) ||
(dev->Phase == SCSI_PHASE_DATA_OUT)) {
scsi_bus_log("dev->CmdBuffer = %08X\n", dev->CmdBuffer);
dev->CmdBuffer = (uint8_t *) malloc(dev->BufferLength);
scsi_bus_log("dev->CmdBuffer = %08X\n", dev->CmdBuffer);
}
if (dev->Phase == SCSI_PHASE_DATA_OUT) {
/* Write direction commands have delayed execution - only execute them after the bus has gotten all the data from the host. */
scsi_bus_log("Next state is data out\n");
bus->state = STATE_COMMANDWAIT;
bus->clear_req = 0;
} else {
/* Other command - execute immediately. */
bus->new_state = dev->Phase;
if (dev->Phase == SCSI_PHASE_DATA_IN) {
scsi_device_command_phase1(bus->dev_id, lun);
}
bus->change_state_delay = 4;
}
}
}
break;
case STATE_COMMANDWAIT:
bus->new_state = SCSI_PHASE_DATA_OUT;
bus->change_state_delay = 4;
bus->clear_req = 4;
break;
case STATE_DATAIN:
if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) {
scsi_bus_log("State Data In\n");
/* This seems to be read, so we first execute the command, then we return the bytes to the host. */
lun = (bus->command[1] >> 5) & 7;
dev = &SCSIDevices[bus->dev_id][lun];
if (bus->data_pos >= SCSIDevices[bus->dev_id][lun].BufferLength) {
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
bus->bus_out &= ~BUS_REQ;
bus->new_state = SCSI_PHASE_STATUS;
bus->change_state_delay = 4;
bus->new_req_delay = 8;
} else {
uint8_t val = dev->CmdBuffer[bus->data_pos++];
bus->bus_out = (bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(val) | BUS_DBP | BUS_REQ;
bus->clear_req = 3;
bus->bus_out &= ~BUS_REQ;
bus->new_state = SCSI_PHASE_DATA_IN;
}
}
break;
case STATE_DATAOUT:
if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) {
scsi_bus_log("State Data Out\n");
lun = (bus->command[1] >> 5) & 7;
dev = &SCSIDevices[bus->dev_id][lun];
/* This is write, so first get the data from the host, then execute the last phase of the command. */
dev->CmdBuffer[bus->data_pos++] = BUS_GETDATA(bus_assert);
if (bus->data_pos >= SCSIDevices[bus->dev_id][lun].BufferLength) {
/* scsi_bus_log("%04X bytes written (%02X %02X)\n", bus->data_pos, bus->command[0], bus->command[1]); */
scsi_bus_log("Actually executing write command\n");
scsi_device_command_phase1(bus->dev_id, lun);
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
bus->bus_out &= ~BUS_REQ;
bus->new_state = SCSI_PHASE_STATUS;
bus->change_state_delay = 4;
bus->new_req_delay = 8;
} else {
bus->bus_out |= BUS_REQ;
}
}
break;
case STATE_STATUS:
scsi_bus_log("State Status\n");
if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) {
/* scsi_bus_log("Preparing for message in\n"); */
bus->bus_out &= ~BUS_REQ;
bus->new_state = SCSI_PHASE_MESSAGE_IN;
bus->change_state_delay = 4;
bus->new_req_delay = 8;
}
break;
case STATE_MESSAGEIN:
scsi_bus_log("State Message In\n");
if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) {
bus->bus_out &= ~BUS_REQ;
bus->new_state = BUS_IDLE;
bus->change_state_delay = 4;
}
break;
}
bus->bus_in = bus_assert;
return(bus->bus_out | bus->bus_in);
}
int
scsi_bus_read(scsi_bus_t *bus)
{
scsi_device_t *dev;
uint8_t lun = 0;
if (bus->clear_req) {
bus->clear_req--;
if (!bus->clear_req) {
scsi_bus_log("Clear REQ\n");
SET_BUS_STATE(bus, bus->new_state);
bus->bus_out |= BUS_REQ;
}
}
if (bus->change_state_delay) {
bus->change_state_delay--;
if (!bus->change_state_delay) {
uint8_t val;
scsi_bus_log("Change state delay\n");
SET_BUS_STATE(bus, bus->new_state);
switch (bus->bus_out & SCSI_PHASE_MESSAGE_IN) {
case SCSI_PHASE_DATA_IN:
lun = (bus->command[1] >> 5) & 7;
dev = &SCSIDevices[bus->dev_id][lun];
scsi_bus_log("Phase data in\n");
bus->state = STATE_DATAIN;
val = dev->CmdBuffer[bus->data_pos++];
bus->bus_out = (bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(val) | BUS_DBP;
break;
case SCSI_PHASE_DATA_OUT:
scsi_bus_log("Phase data out\n");
if (bus->new_state & BUS_IDLE) {
bus->state = STATE_IDLE;
bus->bus_out &= ~BUS_BSY;
} else {
bus->state = STATE_DATAOUT;
}
break;
case SCSI_PHASE_STATUS:
lun = (bus->command[1] >> 5) & 7;
dev = &SCSIDevices[bus->dev_id][lun];
scsi_bus_log("Phase status\n");
bus->state = STATE_STATUS;
bus->bus_out |= BUS_REQ;
bus->bus_out = (bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(dev->Status) | BUS_DBP;
/* scsi_bus_log("SCSI Status (command %02X): %02X (%08X)\n", bus->command[0], dev->Status, bus->bus_out); */
break;
case SCSI_PHASE_MESSAGE_IN:
scsi_bus_log("Phase message in\n");
/* scsi_bus_log("Message in\n"); */
bus->state = STATE_MESSAGEIN;
bus->bus_out = (bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP;
break;
default:
fatal("change_state_delay bad state %x\n", bus->bus_out);
}
}
}
if (bus->new_req_delay) {
bus->new_req_delay--;
if (!bus->new_req_delay) {
bus->bus_out |= BUS_REQ;
}
}
return(bus->bus_out);
}
int
scsi_bus_match(scsi_bus_t *bus, int bus_assert)
{
return((bus_assert & (BUS_CD | BUS_IO | BUS_MSG)) ==
(bus->bus_out & (BUS_CD | BUS_IO | BUS_MSG)));
}

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@
*
* The generic SCSI device command handler.
*
* Version: @(#)scsi_device.c 1.0.6 2018/05/06
* Version: @(#)scsi_device.c 1.0.7 2018/09/15
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -38,51 +38,69 @@
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#define dbglog scsi_log
#include "../../emu.h"
#include "../../device.h"
#include "../cdrom/cdrom.h"
#include "../disk/hdd.h"
#include "../disk/zip.h"
#include "scsi.h"
#include "scsi_device.h"
#include "scsi_disk.h"
#include "../cdrom/cdrom.h"
#include "../disk/zip.h"
static uint8_t scsi_null_device_sense[14] = {
0x70,0,SENSE_ILLEGAL_REQUEST,0,0,0,0,0,0,0,0,0,ASC_INV_LUN,0
static const uint8_t scsi_null_device_sense[18] = {
0x70,0,SENSE_ILLEGAL_REQUEST,0,0,0,0,0,0,0,0,0,ASC_INV_LUN,0,0,0,0,0
};
static uint8_t
scsi_device_target_command(int lun_type, uint8_t id, uint8_t *cdb)
{
if (lun_type == SCSI_DISK) {
scsi_hd_command(id, cdb);
return scsi_hd_err_stat_to_scsi(id);
}
else if (lun_type == SCSI_CDROM) {
cdrom_command(id, cdb);
return cdrom_CDROM_PHASE_to_scsi(id);
}
else if (lun_type == SCSI_ZIP) {
zip_command(id, cdb);
return zip_ZIP_PHASE_to_scsi(id);
uint8_t ret = SCSI_STATUS_CHECK_CONDITION;
switch (lun_type) {
case SCSI_DISK:
scsi_disk_command(scsi_disk[id], cdb);
ret = scsi_disk_err_stat_to_scsi(scsi_disk[id]);
break;
case SCSI_CDROM:
cdrom_command(cdrom[id], cdb);
ret = cdrom_CDROM_PHASE_to_scsi(cdrom[id]);
break;
case SCSI_ZIP:
zip_command(zip[id], cdb);
ret = zip_ZIP_PHASE_to_scsi(zip[id]);
break;
default:
break;
}
return SCSI_STATUS_CHECK_CONDITION;
return ret;
}
static void
scsi_device_target_phase_callback(int lun_type, uint8_t id)
{
if (lun_type == SCSI_DISK) {
scsi_hd_callback(id);
}
else if (lun_type == SCSI_CDROM) {
cdrom_phase_callback(id);
}
else if (lun_type == SCSI_ZIP) {
zip_phase_callback(id);
switch (lun_type) {
case SCSI_DISK:
scsi_disk_callback(scsi_disk[id]);
break;
case SCSI_CDROM:
cdrom_phase_callback(cdrom[id]);
break;
case SCSI_ZIP:
zip_phase_callback(zip[id]);
break;
default:
break;
}
}
@@ -90,32 +108,26 @@ scsi_device_target_phase_callback(int lun_type, uint8_t id)
static int
scsi_device_target_err_stat_to_scsi(int lun_type, uint8_t id)
{
if (lun_type == SCSI_DISK) {
return scsi_hd_err_stat_to_scsi(id);
}
else if (lun_type == SCSI_CDROM) {
return cdrom_CDROM_PHASE_to_scsi(id);
}
else if (lun_type == SCSI_ZIP) {
return zip_ZIP_PHASE_to_scsi(id);
uint8_t ret = SCSI_STATUS_CHECK_CONDITION;
switch (lun_type) {
case SCSI_DISK:
ret = scsi_disk_err_stat_to_scsi(scsi_disk[id]);
break;
case SCSI_CDROM:
ret = cdrom_CDROM_PHASE_to_scsi(cdrom[id]);
break;
case SCSI_ZIP:
ret = zip_ZIP_PHASE_to_scsi(zip[id]);
break;
default:
break;
}
return SCSI_STATUS_CHECK_CONDITION;
}
static void
scsi_device_target_save_cdb_byte(int lun_type, uint8_t id, uint8_t cdb_byte)
{
if (lun_type == SCSI_DISK) {
shdc[id].request_length = cdb_byte;
}
else if (lun_type == SCSI_CDROM) {
cdrom[id]->request_length = cdb_byte;
}
else if (lun_type == SCSI_ZIP) {
zip[id].request_length = cdb_byte;
}
return ret;
}
@@ -123,23 +135,30 @@ int64_t
scsi_device_get_callback(uint8_t scsi_id, uint8_t scsi_lun)
{
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
uint8_t id = 0;
int64_t ret = -1LL;
uint8_t id;
switch (lun_type) {
case SCSI_DISK:
id = scsi_disks[scsi_id][scsi_lun];
return shdc[id].callback;
ret = scsi_disk[id]->callback;
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id][scsi_lun];
return cdrom[id]->callback;
ret = cdrom[id]->callback;
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id][scsi_lun];
return zip[id].callback;
ret = zip[id]->callback;
break;
default:
break;
}
return -1LL;
return ret;
}
@@ -147,23 +166,30 @@ uint8_t *
scsi_device_sense(uint8_t scsi_id, uint8_t scsi_lun)
{
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
uint8_t id = 0;
uint8_t *ret = (uint8_t *)scsi_null_device_sense;
uint8_t id;
switch (lun_type) {
case SCSI_DISK:
id = scsi_disks[scsi_id][scsi_lun];
return shdc[id].sense;
ret = scsi_disk[id]->sense;
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id][scsi_lun];
return cdrom[id]->sense;
ret = cdrom[id]->sense;
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id][scsi_lun];
return zip[id].sense;
ret = zip[id]->sense;
break;
default:
break;
}
return scsi_null_device_sense;
return ret;
}
@@ -171,21 +197,24 @@ void
scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *buffer, uint8_t alloc_length)
{
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
uint8_t id = 0;
uint8_t id;
switch (lun_type) {
case SCSI_DISK:
id = scsi_disks[scsi_id][scsi_lun];
scsi_hd_request_sense_for_scsi(id, buffer, alloc_length);
scsi_disk_request_sense_for_scsi(scsi_disk[id], buffer, alloc_length);
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id][scsi_lun];
cdrom_request_sense_for_scsi(id, buffer, alloc_length);
cdrom_request_sense_for_scsi(cdrom[id], buffer, alloc_length);
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id][scsi_lun];
zip_request_sense_for_scsi(id, buffer, alloc_length);
zip_request_sense_for_scsi(zip[id], buffer, alloc_length);
break;
default:
memcpy(buffer, scsi_null_device_sense, alloc_length);
break;
@@ -193,28 +222,56 @@ scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *buffer, ui
}
void
scsi_device_reset(uint8_t scsi_id, uint8_t scsi_lun)
{
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
uint8_t id;
switch (lun_type) {
case SCSI_DISK:
id = scsi_disks[scsi_id][scsi_lun];
scsi_disk_reset(scsi_disk[id]);
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id][scsi_lun];
cdrom_reset(cdrom[id]);
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id][scsi_lun];
zip_reset(zip[id]);
break;
default:
break;
}
}
void
scsi_device_type_data(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *type, uint8_t *rmb)
{
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
uint8_t id = 0;
switch (lun_type) {
case SCSI_DISK:
id = scsi_disks[scsi_id][scsi_lun];
*type = 0x00;
*rmb = (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 0x80 : 0x00;
*type = *rmb = 0x00;
break;
case SCSI_CDROM:
*type = 0x05;
*rmb = 0x80;
break;
case SCSI_ZIP:
*type = 0x00;
*rmb = 0x80;
break;
default:
*type = *rmb = 0xFF;
*type = *rmb = 0xff;
break;
}
}
@@ -224,23 +281,30 @@ int
scsi_device_read_capacity(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *cdb, uint8_t *buffer, uint32_t *len)
{
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
uint8_t id = 0;
int ret = 0;
uint8_t id;
switch (lun_type) {
case SCSI_DISK:
id = scsi_disks[scsi_id][scsi_lun];
return scsi_hd_read_capacity(id, cdb, buffer, len);
ret = scsi_disk_read_capacity(scsi_disk[id], cdb, buffer, len);
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id][scsi_lun];
return cdrom_read_capacity(id, cdb, buffer, len);
ret = cdrom_read_capacity(cdrom[id], cdb, buffer, len);
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id][scsi_lun];
return zip_read_capacity(id, cdb, buffer, len);
ret = zip_read_capacity(zip[id], cdb, buffer, len);
break;
default:
break;
}
return 0;
return ret;
}
@@ -248,15 +312,19 @@ int
scsi_device_present(uint8_t scsi_id, uint8_t scsi_lun)
{
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
int ret = 0;
switch (lun_type) {
case SCSI_NONE:
return 0;
ret = 0;
break;
default:
ret = 1;
break;
}
return 1;
return ret;
}
@@ -270,44 +338,36 @@ scsi_device_valid(uint8_t scsi_id, uint8_t scsi_lun)
case SCSI_DISK:
id = scsi_disks[scsi_id][scsi_lun];
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id][scsi_lun];
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id][scsi_lun];
break;
default:
id = 0;
break;
}
return (id == 0xFF) ? 0 : 1;
return (id == 0xff) ? 0 : 1;
}
int
scsi_device_cdb_length(uint8_t scsi_id, uint8_t scsi_lun)
{
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
uint8_t id = 0;
switch (lun_type) {
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id][scsi_lun];
return cdrom[id]->cdb_len;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id][scsi_lun];
return zip[id].cdb_len;
default:
break;
}
(void)scsi_id;
(void)scsi_lun;
/* Right now, it's 12 for all devices. */
return 12;
}
void
scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8_t *cdb)
scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *cdb)
{
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
uint8_t id = 0;
@@ -316,34 +376,21 @@ scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8
case SCSI_DISK:
id = scsi_disks[scsi_id][scsi_lun];
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id][scsi_lun];
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id][scsi_lun];
break;
default:
id = 0;
SCSIDevices[scsi_id][scsi_lun].Phase = SCSI_PHASE_STATUS;
SCSIDevices[scsi_id][scsi_lun].Status = SCSI_STATUS_CHECK_CONDITION;
return;
}
/*
* Since that field in the target struct is never used when
* the bus type is SCSI, let's use it for this scope.
*/
scsi_device_target_save_cdb_byte(lun_type, id, cdb[1]);
if (cdb_len != 12) {
/*
* Make sure the LUN field of the temporary CDB is always 0,
* otherwise Daemon Tools drives will misbehave when a command
* is passed through to them.
*/
cdb[1] &= 0x1f;
}
/* Finally, execute the SCSI command immediately and get the transfer length. */
SCSIDevices[scsi_id][scsi_lun].Phase = SCSI_PHASE_COMMAND;
SCSIDevices[scsi_id][scsi_lun].Status = scsi_device_target_command(lun_type, id, cdb);
@@ -352,11 +399,13 @@ scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8
/* Command completed (either OK or error) - call the phase callback to complete the command. */
scsi_device_target_phase_callback(lun_type, id);
}
/* If the phase is DATA IN or DATA OUT, finish this here. */
}
void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun)
void
scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun)
{
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
uint8_t id = 0;
@@ -365,19 +414,22 @@ void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun)
case SCSI_DISK:
id = scsi_disks[scsi_id][scsi_lun];
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id][scsi_lun];
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id][scsi_lun];
break;
default:
id = 0;
return;
}
/* Call the second phase. */
scsi_device_target_phase_callback(lun_type, id);
SCSIDevices[scsi_id][scsi_lun].Status = scsi_device_target_err_stat_to_scsi(lun_type, id);
/* Command second phase complete - call the callback to complete the command. */

View File

@@ -8,7 +8,7 @@
*
* Definitions for the generic SCSI device command handler.
*
* Version: @(#)scsi_device.h 1.0.2 2018/03/08
* Version: @(#)scsi_device.h 1.0.3 2018/10/05
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -38,6 +38,234 @@
# define SCSI_DEVICE_H
/* Configuration. */
#define SCSI_ID_MAX 16 /* 16 on wide buses */
#define SCSI_LUN_MAX 8 /* always 8 */
#define SCSI_TIME (5 * 100 * (1 << TIMER_SHIFT))
/* SCSI commands. */
#define GPCMD_TEST_UNIT_READY 0x00
#define GPCMD_REZERO_UNIT 0x01
#define GPCMD_REQUEST_SENSE 0x03
#define GPCMD_FORMAT_UNIT 0x04
#define GPCMD_IOMEGA_SENSE 0x06
#define GPCMD_READ_6 0x08
#define GPCMD_WRITE_6 0x0a
#define GPCMD_SEEK_6 0x0b
#define GPCMD_IOMEGA_SET_PROTECTION_MODE 0x0c
#define GPCMD_IOMEGA_EJECT 0x0d /* ATAPI only? */
#define GPCMD_INQUIRY 0x12
#define GPCMD_VERIFY_6 0x13
#define GPCMD_MODE_SELECT_6 0x15
#define GPCMD_SCSI_RESERVE 0x16
#define GPCMD_SCSI_RELEASE 0x17
#define GPCMD_MODE_SENSE_6 0x1a
#define GPCMD_START_STOP_UNIT 0x1b
#define GPCMD_SEND_DIAGNOSTIC 0x1d
#define GPCMD_PREVENT_REMOVAL 0x1e
#define GPCMD_READ_FORMAT_CAPACITIES 0x23
#define GPCMD_READ_CDROM_CAPACITY 0x25
#define GPCMD_READ_10 0x28
#define GPCMD_WRITE_10 0x2a
#define GPCMD_SEEK_10 0x2b
#define GPCMD_WRITE_AND_VERIFY_10 0x2e
#define GPCMD_VERIFY_10 0x2f
#define GPCMD_READ_BUFFER 0x3c
#define GPCMD_WRITE_SAME_10 0x41
#define GPCMD_READ_SUBCHANNEL 0x42
#define GPCMD_READ_TOC_PMA_ATIP 0x43
#define GPCMD_READ_HEADER 0x44
#define GPCMD_PLAY_AUDIO_10 0x45
#define GPCMD_GET_CONFIGURATION 0x46
#define GPCMD_PLAY_AUDIO_MSF 0x47
#define GPCMD_PLAY_AUDIO_TRACK_INDEX 0x48
#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
#define GPCMD_PAUSE_RESUME 0x4b
#define GPCMD_STOP_PLAY_SCAN 0x4e
#define GPCMD_READ_DISC_INFORMATION 0x51
#define GPCMD_READ_TRACK_INFORMATION 0x52
#define GPCMD_MODE_SELECT_10 0x55
#define GPCMD_MODE_SENSE_10 0x5a
#define GPCMD_PLAY_AUDIO_12 0xa5
#define GPCMD_READ_12 0xa8
#define GPCMD_WRITE_12 0xaa
#define GPCMD_READ_DVD_STRUCTURE 0xad /* For reading. */
#define GPCMD_WRITE_AND_VERIFY_12 0xae
#define GPCMD_VERIFY_12 0xaf
#define GPCMD_PLAY_CD_OLD 0xb4
#define GPCMD_READ_CD_OLD 0xb8
#define GPCMD_READ_CD_MSF 0xb9
#define GPCMD_SCAN 0xba
#define GPCMD_SET_SPEED 0xbb
#define GPCMD_PLAY_CD 0xbc
#define GPCMD_MECHANISM_STATUS 0xbd
#define GPCMD_READ_CD 0xbe
#define GPCMD_SEND_DVD_STRUCTURE 0xbf /* this is for writing only */
#define GPCMD_PAUSE_RESUME_ALT 0xc2
#define GPCMD_SCAN_ALT 0xcd /* should be equiv to 0xba */
#define GPCMD_SET_SPEED_ALT 0xda /* should be equiv to 0xbb */
/* Mode page codes for mode sense/set */
#define GPMODE_R_W_ERROR_PAGE 0x01
#define GPMODE_CDROM_PAGE 0x0d
#define GPMODE_CDROM_AUDIO_PAGE 0x0e
#define GPMODE_CAPABILITIES_PAGE 0x2a
#define GPMODE_ALL_PAGES 0x3f
/* Mode page codes for presence */
#define GPMODEP_R_W_ERROR_PAGE 0x0000000000000002LL
#define GPMODEP_UNK_PAGE_02 0x0000000000000004LL
#define GPMODEP_UNK_PAGE_03 0x0000000000000008LL
#define GPMODEP_UNK_PAGE_04 0x0000000000000010LL
#define GPMODEP_UNK_PAGE_05 0x0000000000000020LL
#define GPMODEP_UNK_PAGE_08 0x0000000000000100LL
#define GPMODEP_CDROM_PAGE 0x0000000000002000LL
#define GPMODEP_CDROM_AUDIO_PAGE 0x0000000000004000LL
#define GPMODEP_CAPABILITIES_PAGE 0x0000040000000000LL
#define GPMODEP_UNK_PAGE_2F 0x0000800000000000LL
#define GPMODEP_UNK_PAGE_30 0x0001000000000000LL
#define GPMODEP_ALL_PAGES 0x8000000000000000LL
/* SCSI Status Codes */
#define SCSI_STATUS_OK 0
#define SCSI_STATUS_CHECK_CONDITION 2
/* SCSI Sense Keys */
#define SENSE_NONE 0
#define SENSE_NOT_READY 2
#define SENSE_ILLEGAL_REQUEST 5
#define SENSE_UNIT_ATTENTION 6
/* SCSI Additional Sense Codes */
#define ASC_AUDIO_PLAY_OPERATION 0x00
#define ASC_NOT_READY 0x04
#define ASC_ILLEGAL_OPCODE 0x20
#define ASC_LBA_OUT_OF_RANGE 0x21
#define ASC_INV_FIELD_IN_CMD_PACKET 0x24
#define ASC_INV_LUN 0x25
#define ASC_INV_FIELD_IN_PARAMETER_LIST 0x26
#define ASC_WRITE_PROTECTED 0x27
#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28
#define ASC_CAPACITY_DATA_CHANGED 0x2A
#define ASC_INCOMPATIBLE_FORMAT 0x30
#define ASC_MEDIUM_NOT_PRESENT 0x3a
#define ASC_DATA_PHASE_ERROR 0x4b
#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK 0x64
#define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01
#define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02
#define ASCQ_CAPACITY_DATA_CHANGED 0x09
#define ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS 0x11
#define ASCQ_AUDIO_PLAY_OPERATION_PAUSED 0x12
#define ASCQ_AUDIO_PLAY_OPERATION_COMPLETED 0x13
/* Tell RISC OS that we have a 4x CD-ROM drive (600kb/sec data, 706kb/sec raw).
Not that it means anything */
#define CDROM_SPEED 706 /* 0x2C2 */
#define BUFFER_SIZE (256*1024)
#define RW_DELAY (TIMER_USEC * 500)
/* Some generally useful CD-ROM information */
#define CD_MINS 75 /* max. minutes per CD */
#define CD_SECS 60 /* seconds per minute */
#define CD_FRAMES 75 /* frames per second */
#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */
#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE)
#define CD_MAX_SECTORS (CD_MAX_BYTES / 512)
/* Event notification classes for GET EVENT STATUS NOTIFICATION */
#define GESN_NO_EVENTS 0
#define GESN_OPERATIONAL_CHANGE 1
#define GESN_POWER_MANAGEMENT 2
#define GESN_EXTERNAL_REQUEST 3
#define GESN_MEDIA 4
#define GESN_MULTIPLE_HOSTS 5
#define GESN_DEVICE_BUSY 6
/* Event codes for MEDIA event status notification */
#define MEC_NO_CHANGE 0
#define MEC_EJECT_REQUESTED 1
#define MEC_NEW_MEDIA 2
#define MEC_MEDIA_REMOVAL 3 /* only for media changers */
#define MEC_MEDIA_CHANGED 4 /* only for media changers */
#define MEC_BG_FORMAT_COMPLETED 5 /* MRW or DVD+RW b/g format completed */
#define MEC_BG_FORMAT_RESTARTED 6 /* MRW or DVD+RW b/g format restarted */
#define MS_TRAY_OPEN 1
#define MS_MEDIA_PRESENT 2
/* Profile list from MMC-6 revision 1 table 91 */
#define MMC_PROFILE_NONE 0x0000
#define MMC_PROFILE_CD_ROM 0x0008
#define MMC_PROFILE_CD_R 0x0009
#define MMC_PROFILE_CD_RW 0x000A
#define MMC_PROFILE_DVD_ROM 0x0010
#define MMC_PROFILE_DVD_R_SR 0x0011
#define MMC_PROFILE_DVD_RAM 0x0012
#define MMC_PROFILE_DVD_RW_RO 0x0013
#define MMC_PROFILE_DVD_RW_SR 0x0014
#define MMC_PROFILE_DVD_R_DL_SR 0x0015
#define MMC_PROFILE_DVD_R_DL_JR 0x0016
#define MMC_PROFILE_DVD_RW_DL 0x0017
#define MMC_PROFILE_DVD_DDR 0x0018
#define MMC_PROFILE_DVD_PLUS_RW 0x001A
#define MMC_PROFILE_DVD_PLUS_R 0x001B
#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A
#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B
#define MMC_PROFILE_BD_ROM 0x0040
#define MMC_PROFILE_BD_R_SRM 0x0041
#define MMC_PROFILE_BD_R_RRM 0x0042
#define MMC_PROFILE_BD_RE 0x0043
#define MMC_PROFILE_HDDVD_ROM 0x0050
#define MMC_PROFILE_HDDVD_R 0x0051
#define MMC_PROFILE_HDDVD_RAM 0x0052
#define MMC_PROFILE_HDDVD_RW 0x0053
#define MMC_PROFILE_HDDVD_R_DL 0x0058
#define MMC_PROFILE_HDDVD_RW_DL 0x005A
#define MMC_PROFILE_INVALID 0xFFFF
#define SCSI_ONLY 32
#define ATAPI_ONLY 16
#define IMPLEMENTED 8
#define NONDATA 4
#define CHECK_READY 2
#define ALLOW_UA 1
#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f)
#define MSG_COMMAND_COMPLETE 0x00
#define BUS_DBP 0x01
#define BUS_SEL 0x02
#define BUS_IO 0x04
#define BUS_CD 0x08
#define BUS_MSG 0x10
#define BUS_REQ 0x20
#define BUS_BSY 0x40
#define BUS_RST 0x80
#define BUS_ACK 0x200
#define BUS_ATN 0x200
#define BUS_ARB 0x8000
#define BUS_SETDATA(val) ((uint32_t)val << 16)
#define BUS_GETDATA(val) ((val >> 16) & 0xff)
#define BUS_DATAMASK 0xff0000
#define BUS_IDLE (1 << 31)
#define SCSI_PHASE_DATA_OUT 0
#define SCSI_PHASE_DATA_IN BUS_IO
#define SCSI_PHASE_COMMAND BUS_CD
#define SCSI_PHASE_STATUS (BUS_CD | BUS_IO)
#define SCSI_PHASE_MESSAGE_OUT (BUS_MSG | BUS_CD)
#define SCSI_PHASE_MESSAGE_IN (BUS_MSG | BUS_CD | BUS_IO)
#define MODE_SELECT_PHASE_IDLE 0
#define MODE_SELECT_PHASE_HEADER 1
#define MODE_SELECT_PHASE_BLOCK_DESC 2
#define MODE_SELECT_PHASE_PAGE_HEADER 3
#define MODE_SELECT_PHASE_PAGE 4
typedef struct {
int state;
int new_state;
@@ -53,6 +281,38 @@ typedef struct {
int new_req_delay;
} scsi_bus_t;
typedef struct {
uint8_t *CmdBuffer;
int LunType;
int32_t BufferLength;
uint8_t Status;
uint8_t Phase;
} scsi_device_t;
#pragma pack(push,1)
typedef struct {
uint8_t pages[0x40][0x40];
} mode_sense_pages_t;
#pragma pack(pop)
enum {
SCSI_NONE = 0,
SCSI_DISK,
SCSI_CDROM,
SCSI_ZIP
};
extern scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX];
extern void scsi_dev_log(int level, const char *fmt, ...);
extern int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type);
extern int cdrom_LBAtoMSF_accurate(void);
extern int mode_select_init(uint8_t command, uint16_t pl_length, uint8_t do_save);
extern int mode_select_terminate(int force);
extern int mode_select_write(uint8_t val);
extern uint8_t *scsi_device_sense(uint8_t id, uint8_t lun);
extern void scsi_device_type_data(uint8_t id, uint8_t lun,
@@ -61,6 +321,7 @@ extern int64_t scsi_device_get_callback(uint8_t scsi_id, uint8_t scsi_lun);
extern void scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun,
uint8_t *buffer,
uint8_t alloc_length);
extern void scsi_device_reset(uint8_t scsi_id, uint8_t scsi_lun);
extern int scsi_device_read_capacity(uint8_t id, uint8_t lun,
uint8_t *cdb, uint8_t *buffer,
uint32_t *len);
@@ -70,13 +331,9 @@ extern int scsi_device_cdb_length(uint8_t id, uint8_t lun);
extern void scsi_device_command(uint8_t id, uint8_t lun, int cdb_len,
uint8_t *cdb);
extern void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun,
int cdb_len, uint8_t *cdb);
uint8_t *cdb);
extern void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun);
extern int32_t *scsi_device_get_buf_len(uint8_t scsi_id, uint8_t scsi_lun);
extern int scsi_bus_update(scsi_bus_t *bus, int bus_assert);
extern int scsi_bus_read(scsi_bus_t *bus);
extern int scsi_bus_match(scsi_bus_t *bus, int bus_assert);
#endif /*SCSI_DEVICE_H*/

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@
*
* Emulation of SCSI fixed and removable disks.
*
* Version: @(#)scsi_disk.h 1.0.2 2018/03/19
* Version: @(#)scsi_disk.h 1.0.3 2018/09/19
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -39,62 +39,60 @@
typedef struct {
/* Stuff for SCSI hard disks. */
uint8_t cdb[16];
uint8_t current_cdb[16];
uint8_t max_cdb_len;
int requested_blocks;
int max_blocks_at_once;
uint16_t request_length;
int block_total;
int all_blocks_total;
uint32_t packet_len;
int packet_status;
uint8_t status;
uint8_t phase;
uint32_t pos;
int callback;
int total_read;
int unit_attention;
uint8_t sense[256];
uint8_t previous_command;
uint8_t error;
uint32_t sector_pos;
uint32_t sector_len;
uint32_t seek_pos;
int data_pos;
int old_len;
int request_pos;
uint8_t hd_cdb[16];
mode_sense_pages_t ms_pages_saved;
uint64_t current_page_code;
int current_page_len;
hard_disk_t *drv;
int current_page_pos;
/* Stuff for SCSI hard disks. */
uint8_t status, phase,
error, id,
current_cdb[16],
sense[256];
int mode_select_phase;
uint16_t request_length;
int total_length;
int written_length;
int requested_blocks, block_total,
packet_status, callback,
block_descriptor_len,
total_length, do_page_save;
int do_page_save;
int block_descriptor_len;
uint32_t sector_pos, sector_len,
packet_len;
uint8_t *temp_buffer;
uint64_t current_page_code;
uint8_t *temp_buffer;
} scsi_disk_t;
extern scsi_disk_t shdc[HDD_NUM];
extern FILE *shdf[HDD_NUM];
extern scsi_disk_t *scsi_disk[HDD_NUM];
extern uint8_t scsi_disks[16][8];
extern void scsi_disk_insert(uint8_t id);
extern void scsi_loadhd(int scsi_id, int scsi_lun, int id);
#ifdef USE_REMOVABLE_DISK
extern void scsi_disk_insert(int id);
extern void scsi_reloadhd(int id);
extern void scsi_unloadhd(int scsi_id, int scsi_lun, int id);
#endif
extern int scsi_hd_read_capacity(uint8_t id, uint8_t *cdb,
uint8_t *buffer, uint32_t *len);
extern void scsi_disk_log(int level, const char *fmt, ...);
extern void scsi_disk_global_init(void);
extern void scsi_disk_hard_reset(void);
extern void scsi_disk_close(void);
extern void scsi_loadhd(int scsi_id, int scsi_lun, int id);
extern int scsi_disk_read_capacity(scsi_disk_t *dev, uint8_t *cdb,
uint8_t *buffer, uint32_t *len);
extern int scsi_disk_err_stat_to_scsi(scsi_disk_t *dev);
extern int scsi_disk_phase_to_scsi(scsi_disk_t *dev);
extern int find_hdd_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun);
extern void build_scsi_disk_map(void);
extern void scsi_disk_reset(scsi_disk_t *dev);
extern void scsi_disk_request_sense_for_scsi(scsi_disk_t *dev,
uint8_t *buffer,
uint8_t alloc_length);
extern void scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb);
extern void scsi_disk_callback(scsi_disk_t *dev);
#endif /*SCSI_DISK_H*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@
*
* Definitions for the common AHA/BL code.
*
* Version: @(#)scsi_x54x.h 1.0.3 2018/03/15
* Version: @(#)scsi_x54x.h 1.0.4 2018/10/05
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -133,6 +133,18 @@
#define INTR_MBIF 0x01 /* MBI full */
#pragma pack(push,1)
typedef struct {
uint8_t hi;
uint8_t mid;
uint8_t lo;
} addr24;
#pragma pack(pop)
#define ADDR_TO_U32(x) (((x).hi<<16)|((x).mid<<8)|((x).lo&0xFF))
#define U32_TO_ADDR(a,x) do {(a).hi=(x)>>16;(a).mid=(x)>>8;(a).lo=(x)&0xFF;}while(0)
/* Structure for the INQUIRE_SETUP_INFORMATION reply. */
#pragma pack(push,1)
typedef struct {
@@ -321,8 +333,8 @@ typedef struct {
#pragma pack(push,1)
typedef union {
CCB32 new;
CCB old;
CCB32 new_fmt;
CCB old_fmt;
CCBC common;
} CCBU;
#pragma pack(pop)
@@ -348,6 +360,7 @@ typedef struct {
char name[16]; /* name of device */
int64_t timer_period, temp_period;
uint8_t callback_phase;
int64_t media_period;
double ha_bps; /* bytes per second */
@@ -440,7 +453,7 @@ typedef struct {
uint8_t bit32;
uint8_t lba_bios;
mem_mapping_t mmio_mapping;
mem_map_t mmio_mapping;
uint8_t int_geom_writable;
uint8_t cdrom_boot;
@@ -480,30 +493,52 @@ typedef struct {
#pragma pack(push,1)
typedef struct
{
uint8_t command;
uint8_t lun:3,
uint8_t command;
uint8_t lun:3,
reserved:2,
id:3;
union {
struct {
union {
struct {
uint16_t cyl;
uint8_t head;
uint8_t sec;
} chs;
struct {
} chs;
struct {
uint8_t lba0; /* MSB */
uint8_t lba1;
uint8_t lba2;
uint8_t lba3; /* LSB */
} lba;
} u;
uint8_t secount;
addr24 dma_address;
} lba;
} u;
uint8_t secount;
addr24 dma_address;
} BIOSCMD;
#pragma pack(pop)
#define lba32_blk(p) ((uint32_t)(p->u.lba.lba0<<24) | (p->u.lba.lba1<<16) | \
(p->u.lba.lba2<<8) | p->u.lba.lba3)
/*
*
* Scatter/Gather Segment List Definitions
*
* Adapter limits
*/
#define MAX_SG_DESCRIPTORS 32 /* Always make the array 32 elements long, if less are used, that's not an issue. */
#pragma pack(push,1)
typedef struct {
uint32_t Segment;
uint32_t SegmentPointer;
} SGE32;
#pragma pack(pop)
#pragma pack(push,1)
typedef struct {
addr24 Segment;
addr24 SegmentPointer;
} SGE;
#pragma pack(pop)
extern void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset);
extern void x54x_buf_alloc(uint8_t id, uint8_t lun, int length);