Full Upgrade to the 1.7 tree.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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. */
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user