Fixes for the (S)VGA common DAC and some card-specific DAT's (ATi 68860, BT48x family, and the Cirrus Logic DAC), fixes Star Control II among other things.
This commit is contained in:
368
backup code/scsi/scsi - Cópia (2).h
Normal file
368
backup code/scsi/scsi - Cópia (2).h
Normal file
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* SCSI controller handler header.
|
||||
*
|
||||
* Version: @(#)scsi_h 1.0.17 2018/06/02
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2016-2018 TheCollector1995.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#ifndef EMU_SCSI_H
|
||||
#define EMU_SCSI_H
|
||||
|
||||
|
||||
#ifdef WALTJE
|
||||
#define SCSI_TIME (50 * (1 << TIMER_SHIFT))
|
||||
#else
|
||||
#define SCSI_TIME (5 * 100 * (1 << TIMER_SHIFT))
|
||||
#endif
|
||||
|
||||
|
||||
/* 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
|
||||
|
||||
/* Mode page codes for presence */
|
||||
#define GPMODEP_R_W_ERROR_PAGE 0x0000000000000002LL
|
||||
#define GPMODEP_CDROM_PAGE 0x0000000000002000LL
|
||||
#define GPMODEP_CDROM_AUDIO_PAGE 0x0000000000004000LL
|
||||
#define GPMODEP_CAPABILITIES_PAGE 0x0000040000000000LL
|
||||
#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
|
||||
|
||||
/*
|
||||
* 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_NULL,
|
||||
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 int scsi_card_current;
|
||||
|
||||
extern int scsi_card_available(int card);
|
||||
extern char *scsi_card_getname(int card);
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t *scsi_card_getdevice(int card);
|
||||
#endif
|
||||
extern int scsi_card_has_config(int card);
|
||||
extern char *scsi_card_get_internal_name(int card);
|
||||
extern int scsi_card_get_from_internal_name(char *s);
|
||||
extern void scsi_mutex(uint8_t start);
|
||||
extern void scsi_card_init(void);
|
||||
|
||||
|
||||
#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*/
|
||||
|
||||
extern void scsi_mutex_wait(uint8_t wait);
|
||||
236
backup code/scsi/scsi - Cópia.c
Normal file
236
backup code/scsi/scsi - Cópia.c
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Handling of the SCSI controllers.
|
||||
*
|
||||
* Version: @(#)scsi.c 1.0.19 2018/04/29
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* TheCollector1995, <mariogplayer@gmail.com>
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "../disk/hdc.h"
|
||||
#include "../disk/zip.h"
|
||||
#include "../plat.h"
|
||||
#include "scsi.h"
|
||||
#include "../cdrom/cdrom.h"
|
||||
#include "scsi_device.h"
|
||||
#include "scsi_aha154x.h"
|
||||
#include "scsi_buslogic.h"
|
||||
#include "scsi_ncr5380.h"
|
||||
#include "scsi_ncr53c810.h"
|
||||
#ifdef WALTJE
|
||||
# include "scsi_wd33c93.h"
|
||||
#endif
|
||||
#include "scsi_x54x.h"
|
||||
|
||||
|
||||
scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX];
|
||||
// uint8_t SCSIPhase = 0xff;
|
||||
// uint8_t SCSIStatus = SCSI_STATUS_OK;
|
||||
char scsi_fn[SCSI_NUM][512];
|
||||
uint16_t scsi_hd_location[SCSI_NUM];
|
||||
|
||||
int scsi_card_current = 0;
|
||||
int scsi_card_last = 0;
|
||||
|
||||
uint32_t SCSI_BufferLength;
|
||||
static volatile
|
||||
mutex_t *scsiMutex;
|
||||
|
||||
|
||||
typedef const struct {
|
||||
const char *name;
|
||||
const char *internal_name;
|
||||
const device_t *device;
|
||||
} SCSI_CARD;
|
||||
|
||||
|
||||
static SCSI_CARD scsi_cards[] = {
|
||||
{ "None", "none", NULL, },
|
||||
{ "[ISA] Adaptec AHA-1540B","aha1540b", &aha1540b_device, },
|
||||
{ "[ISA] Adaptec AHA-1542C","aha1542c", &aha1542c_device, },
|
||||
{ "[ISA] Adaptec AHA-1542CF","aha1542cf", &aha1542cf_device, },
|
||||
{ "[ISA] BusLogic BT-542BH","bt542bh", &buslogic_device, },
|
||||
{ "[ISA] BusLogic BT-545S", "bt545s", &buslogic_545s_device,},
|
||||
{ "[ISA] Longshine LCS-6821N","lcs6821n", &scsi_lcs6821n_device,},
|
||||
{ "[ISA] Ranco RT1000B", "rt1000b", &scsi_rt1000b_device, },
|
||||
{ "[ISA] Trantor T130B", "t130b", &scsi_t130b_device, },
|
||||
{ "[ISA] Sumo SCSI-AT", "scsiat", &scsi_scsiat_device, },
|
||||
#ifdef WALTJE
|
||||
{ "[ISA] Generic WDC33C93", "wd33c93", &scsi_wd33c93_device, },
|
||||
#endif
|
||||
{ "[MCA] Adaptec AHA-1640", "aha1640", &aha1640_device, },
|
||||
{ "[MCA] BusLogic BT-640A", "bt640a", &buslogic_640a_device,},
|
||||
{ "[PCI] BusLogic BT-958D", "bt958d", &buslogic_pci_device, },
|
||||
{ "[PCI] NCR 53C810", "ncr53c810", &ncr53c810_pci_device,},
|
||||
{ "[VLB] BusLogic BT-445S", "bt445s", &buslogic_445s_device,},
|
||||
{ "", "", NULL, },
|
||||
};
|
||||
|
||||
|
||||
#ifdef ENABLE_SCSI_LOG
|
||||
int scsi_do_log = ENABLE_SCSI_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
scsi_log(const char *fmt, ...)
|
||||
{
|
||||
#ifdef ENABLE_SCSI_LOG
|
||||
va_list ap;
|
||||
|
||||
if (scsi_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);
|
||||
}
|
||||
|
||||
|
||||
char *scsi_card_getname(int card)
|
||||
{
|
||||
return((char *) 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);
|
||||
}
|
||||
|
||||
|
||||
char *scsi_card_get_internal_name(int card)
|
||||
{
|
||||
return((char *) scsi_cards[card].internal_name);
|
||||
}
|
||||
|
||||
|
||||
int scsi_card_get_from_internal_name(char *s)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
while (strlen((char *) scsi_cards[c].internal_name)) {
|
||||
if (!strcmp((char *) scsi_cards[c].internal_name, s))
|
||||
return(c);
|
||||
c++;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
void scsi_mutex(uint8_t start)
|
||||
{
|
||||
if (start)
|
||||
scsiMutex = thread_create_mutex(L"86Box.SCSIMutex");
|
||||
else
|
||||
thread_close_mutex((mutex_t *) scsiMutex);
|
||||
}
|
||||
|
||||
|
||||
void scsi_card_init(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (!scsi_cards[scsi_card_current].device)
|
||||
return;
|
||||
|
||||
scsi_log("Building SCSI hard disk map...\n");
|
||||
build_scsi_hd_map();
|
||||
scsi_log("Building SCSI CD-ROM map...\n");
|
||||
build_scsi_cdrom_map();
|
||||
scsi_log("Building SCSI ZIP map...\n");
|
||||
build_scsi_zip_map();
|
||||
|
||||
for (i=0; i<SCSI_ID_MAX; i++) {
|
||||
for (j=0; j<SCSI_LUN_MAX; j++) {
|
||||
if (scsi_hard_disks[i][j] != 0xff)
|
||||
SCSIDevices[i][j].LunType = SCSI_DISK;
|
||||
else if (scsi_cdrom_drives[i][j] != 0xff)
|
||||
SCSIDevices[i][j].LunType = SCSI_CDROM;
|
||||
else if (scsi_zip_drives[i][j] != 0xff)
|
||||
SCSIDevices[i][j].LunType = SCSI_ZIP;
|
||||
else
|
||||
SCSIDevices[i][j].LunType = SCSI_NONE;
|
||||
SCSIDevices[i][j].CmdBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
device_add(scsi_cards[scsi_card_current].device);
|
||||
|
||||
scsi_card_last = scsi_card_current;
|
||||
}
|
||||
|
||||
|
||||
/* 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 hdc_id = scsi_hard_disks[id][lun];
|
||||
|
||||
if (hdc_id != 0xff)
|
||||
SCSIDevices[id][lun].LunType = SCSI_DISK;
|
||||
else if (cdrom_id != 0xff)
|
||||
SCSIDevices[id][lun].LunType = SCSI_CDROM;
|
||||
else if (zip_id != 0xff)
|
||||
SCSIDevices[id][lun].LunType = SCSI_ZIP;
|
||||
else
|
||||
SCSIDevices[id][lun].LunType = SCSI_NONE;
|
||||
|
||||
scsi_device_reset(id, lun);
|
||||
|
||||
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);
|
||||
}
|
||||
378
backup code/scsi/scsi - Cópia.h
Normal file
378
backup code/scsi/scsi - Cópia.h
Normal file
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* SCSI controller handler header.
|
||||
*
|
||||
* Version: @(#)scsi_h 1.0.16 2018/03/28
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2016-2018 TheCollector1995.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#ifndef EMU_SCSI_H
|
||||
#define EMU_SCSI_H
|
||||
|
||||
|
||||
#ifdef WALTJE
|
||||
#define SCSI_TIME (50 * (1 << TIMER_SHIFT))
|
||||
#else
|
||||
#define SCSI_TIME (5 * 100 * (1 << TIMER_SHIFT))
|
||||
#endif
|
||||
|
||||
|
||||
/* 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
|
||||
|
||||
/* Mode page codes for presence */
|
||||
#define GPMODEP_R_W_ERROR_PAGE 0x0000000000000002LL
|
||||
#define GPMODEP_CDROM_PAGE 0x0000000000002000LL
|
||||
#define GPMODEP_CDROM_AUDIO_PAGE 0x0000000000004000LL
|
||||
#define GPMODEP_CAPABILITIES_PAGE 0x0000040000000000LL
|
||||
#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
|
||||
|
||||
/*
|
||||
* 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 int scsi_card_current;
|
||||
|
||||
extern int scsi_card_available(int card);
|
||||
extern char *scsi_card_getname(int card);
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t *scsi_card_getdevice(int card);
|
||||
#endif
|
||||
extern int scsi_card_has_config(int card);
|
||||
extern char *scsi_card_get_internal_name(int card);
|
||||
extern int scsi_card_get_from_internal_name(char *s);
|
||||
extern void scsi_mutex(uint8_t start);
|
||||
extern void scsi_card_init(void);
|
||||
|
||||
extern uint8_t scsi_hard_disks[16][8];
|
||||
|
||||
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*/
|
||||
|
||||
extern void scsi_mutex_wait(uint8_t wait);
|
||||
415
backup code/scsi/scsi_device - Cópia (2).c
Normal file
415
backup code/scsi/scsi_device - Cópia (2).c
Normal file
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* The generic SCSI device command handler.
|
||||
*
|
||||
* Version: @(#)scsi_device.c 1.0.17 2018/06/02
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../device.h"
|
||||
#include "../disk/hdd.h"
|
||||
#include "scsi.h"
|
||||
#include "scsi_device.h"
|
||||
#include "../cdrom/cdrom.h"
|
||||
#include "../disk/zip.h"
|
||||
#include "scsi_disk.h"
|
||||
|
||||
|
||||
static uint8_t
|
||||
scsi_device_target_command(int lun_type, uint8_t id, uint8_t *cdb)
|
||||
{
|
||||
switch(lun_type) {
|
||||
case SCSI_NULL:
|
||||
scsi_null_command(cdb);
|
||||
return scsi_null_err_stat_to_scsi();
|
||||
case SCSI_DISK:
|
||||
scsi_disk_command(scsi_disk[id], cdb);
|
||||
return scsi_disk_err_stat_to_scsi(scsi_disk[id]);
|
||||
case SCSI_CDROM:
|
||||
cdrom_command(cdrom[id], cdb);
|
||||
return cdrom_CDROM_PHASE_to_scsi(cdrom[id]);
|
||||
case SCSI_ZIP:
|
||||
zip_command(zip[id], cdb);
|
||||
return zip_ZIP_PHASE_to_scsi(zip[id]);
|
||||
default:
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void scsi_device_target_phase_callback(int lun_type, uint8_t id)
|
||||
{
|
||||
switch(lun_type) {
|
||||
case SCSI_NULL:
|
||||
scsi_null_callback();
|
||||
break;
|
||||
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;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int scsi_device_target_err_stat_to_scsi(int lun_type, uint8_t id)
|
||||
{
|
||||
switch(lun_type) {
|
||||
case SCSI_NULL:
|
||||
return scsi_null_err_stat_to_scsi();
|
||||
case SCSI_DISK:
|
||||
return scsi_disk_err_stat_to_scsi(scsi_disk[id]);
|
||||
case SCSI_CDROM:
|
||||
return cdrom_CDROM_PHASE_to_scsi(cdrom[id]);
|
||||
case SCSI_ZIP:
|
||||
return zip_ZIP_PHASE_to_scsi(zip[id]);
|
||||
default:
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void scsi_device_target_save_cdb_byte(int lun_type, uint8_t id, uint8_t cdb_byte)
|
||||
{
|
||||
switch(lun_type) {
|
||||
case SCSI_DISK:
|
||||
scsi_disk[id]->request_length = cdb_byte;
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
cdrom[id]->request_length = cdb_byte;
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
zip[id]->request_length = cdb_byte;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_disks[scsi_id][scsi_lun];
|
||||
return scsi_disk[id]->callback;
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
return cdrom[id]->callback;
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
return zip[id]->callback;
|
||||
break;
|
||||
default:
|
||||
return -1LL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_disks[scsi_id][scsi_lun];
|
||||
return scsi_disk[id]->sense;
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
return cdrom[id]->sense;
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
return zip[id]->sense;
|
||||
break;
|
||||
default:
|
||||
return scsi_null_device_sense;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *buffer, uint8_t alloc_length)
|
||||
{
|
||||
uint8_t main_lun_type = SCSIDevices[scsi_id][0].LunType;
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
if ((main_lun_type != SCSI_NONE) && (lun_type == SCSI_NONE) && scsi_lun)
|
||||
lun_type = SCSI_NULL;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_NULL:
|
||||
scsi_null_request_sense_for_scsi(buffer, alloc_length);
|
||||
break;
|
||||
case SCSI_DISK:
|
||||
id = scsi_disks[scsi_id][scsi_lun];
|
||||
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(cdrom[id], buffer, alloc_length);
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
zip_request_sense_for_scsi(zip[id], buffer, alloc_length);
|
||||
break;
|
||||
default:
|
||||
memcpy(buffer, scsi_null_device_sense, alloc_length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_reset(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t main_lun_type = SCSIDevices[scsi_id][0].LunType;
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
if ((main_lun_type != SCSI_NONE) && (lun_type == SCSI_NONE) && scsi_lun)
|
||||
lun_type = SCSI_NULL;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_NULL:
|
||||
scsi_null_device_sense[2] = scsi_null_device_sense[12] =
|
||||
scsi_null_device_sense[13] = 0x00;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
*type = *rmb = 0x00;
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
*type = 0x05;
|
||||
*rmb = 0x80;
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
*type = 0x00;
|
||||
*rmb = 0x80;
|
||||
break;
|
||||
default:
|
||||
*type = *rmb = 0xff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_disks[scsi_id][scsi_lun];
|
||||
return scsi_disk_read_capacity(scsi_disk[id], cdb, buffer, len);
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
return cdrom_read_capacity(cdrom[id], cdb, buffer, len);
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
return zip_read_capacity(zip[id], cdb, buffer, len);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_present(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t main_lun_type = SCSIDevices[scsi_id][0].LunType;
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
if ((main_lun_type != SCSI_NONE) && (lun_type == SCSI_NONE) && scsi_lun)
|
||||
lun_type = SCSI_NULL;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_NONE:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_valid(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_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;
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_cdb_length(uint8_t scsi_id, uint8_t 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)
|
||||
{
|
||||
uint8_t id = 0;
|
||||
uint8_t main_lun_type = SCSIDevices[scsi_id][0].LunType;
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
if ((main_lun_type != SCSI_NONE) && (lun_type == SCSI_NONE) && scsi_lun)
|
||||
lun_type = SCSI_NULL;
|
||||
|
||||
switch (lun_type) {
|
||||
case SCSI_NULL:
|
||||
id = 0;
|
||||
scsi_null_set_location(scsi_id, scsi_lun);
|
||||
break;
|
||||
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);
|
||||
|
||||
if (SCSIDevices[scsi_id][scsi_lun].Phase == SCSI_PHASE_STATUS) {
|
||||
/* 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)
|
||||
{
|
||||
uint8_t id = 0;
|
||||
uint8_t main_lun_type = SCSIDevices[scsi_id][0].LunType;
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
if ((main_lun_type != SCSI_NONE) && (lun_type == SCSI_NONE) && scsi_lun)
|
||||
lun_type = SCSI_NULL;
|
||||
|
||||
switch (lun_type) {
|
||||
case SCSI_NULL:
|
||||
id = 0;
|
||||
break;
|
||||
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. */
|
||||
scsi_device_target_phase_callback(lun_type, id);
|
||||
}
|
||||
|
||||
int32_t *scsi_device_get_buf_len(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
return &SCSIDevices[scsi_id][scsi_lun].BufferLength;
|
||||
}
|
||||
416
backup code/scsi/scsi_device - Cópia.c
Normal file
416
backup code/scsi/scsi_device - Cópia.c
Normal file
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* The generic SCSI device command handler.
|
||||
*
|
||||
* Version: @(#)scsi_device.c 1.0.16 2018/03/26
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../device.h"
|
||||
#include "../disk/hdd.h"
|
||||
#include "../disk/zip.h"
|
||||
#include "scsi.h"
|
||||
#include "../cdrom/cdrom.h"
|
||||
#include "scsi_disk.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 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(cdrom[id], cdb);
|
||||
return cdrom_CDROM_PHASE_to_scsi(cdrom[id]);
|
||||
}
|
||||
else if (lun_type == SCSI_ZIP)
|
||||
{
|
||||
zip_command(id, cdb);
|
||||
return zip_ZIP_PHASE_to_scsi(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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(cdrom[id]);
|
||||
}
|
||||
else if (lun_type == SCSI_ZIP)
|
||||
{
|
||||
zip_phase_callback(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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(cdrom[id]);
|
||||
}
|
||||
else if (lun_type == SCSI_ZIP)
|
||||
{
|
||||
return zip_ZIP_PHASE_to_scsi(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_hard_disks[scsi_id][scsi_lun];
|
||||
return shdc[id].callback;
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
return cdrom[id]->callback;
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
return zip[id]->callback;
|
||||
break;
|
||||
default:
|
||||
return -1LL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_hard_disks[scsi_id][scsi_lun];
|
||||
return shdc[id].sense;
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
return cdrom[id]->sense;
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
return zip[id]->sense;
|
||||
break;
|
||||
default:
|
||||
return scsi_null_device_sense;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_hard_disks[scsi_id][scsi_lun];
|
||||
scsi_hd_request_sense_for_scsi(id, buffer, alloc_length);
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
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);
|
||||
break;
|
||||
default:
|
||||
memcpy(buffer, scsi_null_device_sense, alloc_length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_hard_disks[scsi_id][scsi_lun];
|
||||
scsi_hd_reset(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(id);
|
||||
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;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
*type = *rmb = 0x00;
|
||||
break;
|
||||
case SCSI_CDROM:
|
||||
*type = 0x05;
|
||||
*rmb = 0x80;
|
||||
break;
|
||||
case SCSI_ZIP:
|
||||
*type = 0x00;
|
||||
*rmb = 0x80;
|
||||
break;
|
||||
default:
|
||||
*type = *rmb = 0xff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_hard_disks[scsi_id][scsi_lun];
|
||||
return scsi_hd_read_capacity(id, cdb, buffer, len);
|
||||
case SCSI_CDROM:
|
||||
id = scsi_cdrom_drives[scsi_id][scsi_lun];
|
||||
return cdrom_read_capacity(cdrom[id], cdb, buffer, len);
|
||||
case SCSI_ZIP:
|
||||
id = scsi_zip_drives[scsi_id][scsi_lun];
|
||||
return zip_read_capacity(id, cdb, buffer, len);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_present(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_NONE:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_valid(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_DISK:
|
||||
id = scsi_hard_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;
|
||||
}
|
||||
|
||||
|
||||
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:
|
||||
return 12;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8_t *cdb)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_hard_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);
|
||||
|
||||
if (SCSIDevices[scsi_id][scsi_lun].Phase == SCSI_PHASE_STATUS) {
|
||||
/* 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)
|
||||
{
|
||||
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
|
||||
|
||||
uint8_t id = 0;
|
||||
|
||||
switch (lun_type)
|
||||
{
|
||||
case SCSI_DISK:
|
||||
id = scsi_hard_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. */
|
||||
scsi_device_target_phase_callback(lun_type, id);
|
||||
}
|
||||
|
||||
int32_t *scsi_device_get_buf_len(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
{
|
||||
return &SCSIDevices[scsi_id][scsi_lun].BufferLength;
|
||||
}
|
||||
69
backup code/scsi/scsi_device - Cópia.h
Normal file
69
backup code/scsi/scsi_device - Cópia.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Definitions for the generic SCSI device command handler.
|
||||
*
|
||||
* Version: @(#)scsi_device.h 1.0.8 2018/06/12
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*/
|
||||
#ifndef SCSI_DEVICE_H
|
||||
# define SCSI_DEVICE_H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int state;
|
||||
int new_state;
|
||||
int clear_req;
|
||||
uint32_t bus_in, bus_out;
|
||||
int dev_id;
|
||||
|
||||
int command_pos;
|
||||
uint8_t command[20];
|
||||
int data_pos;
|
||||
|
||||
int change_state_delay;
|
||||
int new_req_delay;
|
||||
} scsi_bus_t;
|
||||
|
||||
extern uint8_t *scsi_device_sense(uint8_t id, uint8_t lun);
|
||||
extern void scsi_device_type_data(uint8_t id, uint8_t lun,
|
||||
uint8_t *type, uint8_t *rmb);
|
||||
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);
|
||||
extern int scsi_device_present(uint8_t id, uint8_t lun);
|
||||
extern int scsi_device_valid(uint8_t id, uint8_t lun);
|
||||
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);
|
||||
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);
|
||||
|
||||
extern int scsi_null_err_stat_to_scsi(void);
|
||||
extern void scsi_null_request_sense(uint8_t *buffer, uint8_t alloc_length, int desc);
|
||||
extern void scsi_null_request_sense_for_scsi(uint8_t *buffer, uint8_t alloc_length);
|
||||
extern void scsi_null_command(uint8_t *cdb);
|
||||
extern void scsi_null_callback(void);
|
||||
extern void scsi_null_set_location(uint8_t id, uint8_t lun);
|
||||
|
||||
extern uint8_t scsi_null_device_sense[18];
|
||||
|
||||
#endif /*SCSI_DEVICE_H*/
|
||||
1291
backup code/scsi/scsi_disk - Cópia.c
Normal file
1291
backup code/scsi/scsi_disk - Cópia.c
Normal file
File diff suppressed because it is too large
Load Diff
45
backup code/scsi/scsi_disk - Cópia.h
Normal file
45
backup code/scsi/scsi_disk - Cópia.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* Emulation of SCSI fixed and removable disks.
|
||||
*
|
||||
* Version: @(#)scsi_disk.h 1.0.4 2018/04/24
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2017,2018 Miran Grca.
|
||||
*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
/* Stuff for SCSI hard disks. */
|
||||
uint8_t status, phase,
|
||||
error,
|
||||
current_cdb[16],
|
||||
sense[256];
|
||||
|
||||
uint16_t request_length;
|
||||
|
||||
int requested_blocks, block_total,
|
||||
packet_status, callback,
|
||||
block_descriptor_len,
|
||||
total_length, do_page_save;
|
||||
|
||||
uint32_t sector_pos, sector_len,
|
||||
packet_len;
|
||||
|
||||
uint64_t current_page_code;
|
||||
|
||||
uint8_t *temp_buffer;
|
||||
} scsi_hard_disk_t;
|
||||
|
||||
|
||||
extern scsi_hard_disk_t shdc[HDD_NUM];
|
||||
extern FILE *shdf[HDD_NUM];
|
||||
|
||||
|
||||
extern void scsi_loadhd(int scsi_id, int scsi_lun, int id);
|
||||
|
||||
int scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len);
|
||||
395
backup code/scsi/scsi_null.c
Normal file
395
backup code/scsi/scsi_null.c
Normal file
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* Emulation of SCSI null device, used for invalid LUN's where
|
||||
* LUN 0 is valid.
|
||||
*
|
||||
* Version: @(#)scsi_null.c 1.0.0 2018/06/12
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2017,2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "../nvr.h"
|
||||
#include "../disk/hdd.h"
|
||||
#include "../disk/hdc.h"
|
||||
#include "../disk/hdc_ide.h"
|
||||
#include "../plat.h"
|
||||
#include "../ui.h"
|
||||
#include "scsi.h"
|
||||
#include "../cdrom/cdrom.h"
|
||||
#include "scsi_device.h"
|
||||
|
||||
|
||||
/* Bits of 'status' */
|
||||
#define ERR_STAT 0x01
|
||||
#define DRQ_STAT 0x08 /* Data request */
|
||||
#define DSC_STAT 0x10
|
||||
#define SERVICE_STAT 0x10
|
||||
#define READY_STAT 0x40
|
||||
#define BUSY_STAT 0x80
|
||||
|
||||
/* Bits of 'error' */
|
||||
#define ABRT_ERR 0x04 /* Command aborted */
|
||||
#define MCR_ERR 0x08 /* Media change request */
|
||||
|
||||
#define MAX_BLOCKS_AT_ONCE 340
|
||||
|
||||
|
||||
#define scsi_null_sense_key scsi_null_device_sense[2]
|
||||
#define scsi_null_asc scsi_null_device_sense[12]
|
||||
#define scsi_null_ascq scsi_null_device_sense[13]
|
||||
|
||||
|
||||
static uint8_t status, phase, packet_status, error, command, packet_len, sense_desc;
|
||||
static int64_t callback;
|
||||
static uint8_t null_id, null_lun;
|
||||
static uint8_t *temp_buffer;
|
||||
|
||||
|
||||
|
||||
#ifdef ENABLE_SCSI_NULL_LOG
|
||||
int scsi_null_do_log = ENABLE_SCSI_NULL_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_log(const char *fmt, ...)
|
||||
{
|
||||
#ifdef ENABLE_SCSI_NULL_LOG
|
||||
va_list ap;
|
||||
|
||||
if (scsi_null_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */
|
||||
int
|
||||
scsi_null_err_stat_to_scsi(void)
|
||||
{
|
||||
if (status & ERR_STAT)
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
else
|
||||
return SCSI_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_command_common(void)
|
||||
{
|
||||
status = BUSY_STAT;
|
||||
phase = 1;
|
||||
if (packet_status == CDROM_PHASE_COMPLETE) {
|
||||
scsi_null_callback();
|
||||
callback = 0LL;
|
||||
} else
|
||||
callback = -1LL; /* Speed depends on SCSI controller */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_command_complete(void)
|
||||
{
|
||||
packet_status = CDROM_PHASE_COMPLETE;
|
||||
scsi_null_command_common();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_command_read_dma(void)
|
||||
{
|
||||
packet_status = CDROM_PHASE_DATA_IN_DMA;
|
||||
scsi_null_command_common();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_data_command_finish(int len, int block_len, int alloc_len, int direction)
|
||||
{
|
||||
if (alloc_len >= 0) {
|
||||
if (alloc_len < len)
|
||||
len = alloc_len;
|
||||
}
|
||||
if (len == 0)
|
||||
scsi_null_command_complete();
|
||||
else {
|
||||
if (direction == 0)
|
||||
scsi_null_command_read_dma();
|
||||
else
|
||||
fatal("SCSI NULL device write command\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_set_phase(uint8_t phase)
|
||||
{
|
||||
SCSIDevices[null_id][null_lun].Phase = phase;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_cmd_error(void)
|
||||
{
|
||||
scsi_null_set_phase(SCSI_PHASE_STATUS);
|
||||
error = ((scsi_null_sense_key & 0xf) << 4) | ABRT_ERR;
|
||||
status = READY_STAT | ERR_STAT;
|
||||
phase = 3;
|
||||
packet_status = 0x80;
|
||||
callback = 50 * SCSI_TIME;
|
||||
scsi_null_log("SCSI NULL: ERROR: %02X/%02X/%02X\n", scsi_null_sense_key, scsi_null_asc, scsi_null_ascq);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_invalid_lun(void)
|
||||
{
|
||||
scsi_null_sense_key = SENSE_ILLEGAL_REQUEST;
|
||||
scsi_null_asc = ASC_INV_LUN;
|
||||
scsi_null_ascq = 0;
|
||||
scsi_null_set_phase(SCSI_PHASE_STATUS);
|
||||
scsi_null_cmd_error();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_invalid_field(void)
|
||||
{
|
||||
scsi_null_sense_key = SENSE_ILLEGAL_REQUEST;
|
||||
scsi_null_asc = ASC_INV_FIELD_IN_CMD_PACKET;
|
||||
scsi_null_ascq = 0;
|
||||
scsi_null_cmd_error();
|
||||
status = 0x53;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_null_request_sense(uint8_t *buffer, uint8_t alloc_length, int desc)
|
||||
{
|
||||
/*Will return 18 bytes of 0*/
|
||||
if (alloc_length != 0) {
|
||||
memset(buffer, 0, alloc_length);
|
||||
if (!desc)
|
||||
if (alloc_length <= 18)
|
||||
memcpy(buffer, scsi_null_device_sense, alloc_length);
|
||||
else {
|
||||
memset(buffer, 0x00, alloc_length);
|
||||
memcpy(buffer, scsi_null_device_sense, 18);
|
||||
}
|
||||
else {
|
||||
buffer[1] = scsi_null_sense_key;
|
||||
buffer[2] = scsi_null_asc;
|
||||
buffer[3] = scsi_null_ascq;
|
||||
}
|
||||
} else
|
||||
return;
|
||||
|
||||
buffer[0] = 0x70;
|
||||
|
||||
scsi_null_log("SCSI NULL: Reporting sense: %02X %02X %02X\n", buffer[2], buffer[12], buffer[13]);
|
||||
|
||||
/* Clear the sense stuff as per the spec. */
|
||||
scsi_null_sense_key = scsi_null_asc = scsi_null_ascq = 0x00;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_null_request_sense_for_scsi(uint8_t *buffer, uint8_t alloc_length)
|
||||
{
|
||||
scsi_null_request_sense(buffer, alloc_length, 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_null_command(uint8_t *cdb)
|
||||
{
|
||||
int32_t *BufLen;
|
||||
uint32_t len;
|
||||
int max_len;
|
||||
unsigned idx = 0;
|
||||
unsigned size_idx, preamble_len;
|
||||
|
||||
BufLen = &SCSIDevices[null_id][null_lun].BufferLength;
|
||||
|
||||
status &= ~ERR_STAT;
|
||||
packet_len = 0;
|
||||
|
||||
scsi_null_set_phase(SCSI_PHASE_STATUS);
|
||||
|
||||
command = cdb[0];
|
||||
switch (cdb[0]) {
|
||||
case GPCMD_REQUEST_SENSE:
|
||||
/* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE
|
||||
should forget about the not ready, and report unit attention straight away. */
|
||||
sense_desc = cdb [1];
|
||||
|
||||
if ((*BufLen == -1) || (cdb[4] < *BufLen))
|
||||
*BufLen = cdb[4];
|
||||
|
||||
if (*BufLen < cdb[4])
|
||||
cdb[4] = *BufLen;
|
||||
|
||||
len = (cdb[1] & 1) ? 8 : 18;
|
||||
|
||||
scsi_null_set_phase(SCSI_PHASE_DATA_IN);
|
||||
scsi_null_data_command_finish(len, len, cdb[4], 0);
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case GPCMD_INQUIRY:
|
||||
max_len = cdb[3];
|
||||
max_len <<= 8;
|
||||
max_len |= cdb[4];
|
||||
|
||||
if ((!max_len) || (*BufLen == 0)) {
|
||||
scsi_null_set_phase(SCSI_PHASE_STATUS);
|
||||
packet_status = CDROM_PHASE_COMPLETE;
|
||||
callback = 20 * SCSI_TIME;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cdb[1] & 1) {
|
||||
scsi_null_invalid_field();
|
||||
return;
|
||||
} else {
|
||||
temp_buffer = malloc(1024);
|
||||
|
||||
preamble_len = 5;
|
||||
size_idx = 4;
|
||||
|
||||
memset(temp_buffer, 0, 8);
|
||||
temp_buffer[0] = (3 << 5); /*Invalid*/
|
||||
temp_buffer[1] = 0; /*Fixed*/
|
||||
temp_buffer[2] = 0x02; /*SCSI-2 compliant*/
|
||||
temp_buffer[3] = 0x02;
|
||||
temp_buffer[4] = 31;
|
||||
temp_buffer[6] = 1; /* 16-bit transfers supported */
|
||||
temp_buffer[7] = 0x20; /* Wide bus supported */
|
||||
|
||||
ide_padstr8(temp_buffer + 8, 8, EMU_NAME); /* Vendor */
|
||||
ide_padstr8(temp_buffer + 16, 16, "INVALID"); /* Product */
|
||||
ide_padstr8(temp_buffer + 32, 4, EMU_VERSION); /* Revision */
|
||||
idx = 36;
|
||||
|
||||
if (max_len == 96) {
|
||||
temp_buffer[4] = 91;
|
||||
idx = 96;
|
||||
}
|
||||
}
|
||||
|
||||
temp_buffer[size_idx] = idx - preamble_len;
|
||||
len=idx;
|
||||
|
||||
if (len > max_len)
|
||||
len = max_len;
|
||||
|
||||
if ((*BufLen == -1) || (len < *BufLen))
|
||||
*BufLen = len;
|
||||
|
||||
if (len > *BufLen)
|
||||
len = *BufLen;
|
||||
|
||||
scsi_null_set_phase(SCSI_PHASE_DATA_IN);
|
||||
scsi_null_data_command_finish(len, len, max_len, 0);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
scsi_null_invalid_lun();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_null_phase_data_in(void)
|
||||
{
|
||||
uint8_t *hdbufferb = SCSIDevices[null_id][null_lun].CmdBuffer;
|
||||
int32_t *BufLen = &SCSIDevices[null_id][null_lun].BufferLength;
|
||||
|
||||
if (!*BufLen) {
|
||||
scsi_null_log("scsi_null_phase_data_in(): Buffer length is 0\n");
|
||||
scsi_null_set_phase(SCSI_PHASE_STATUS);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (command) {
|
||||
case GPCMD_REQUEST_SENSE:
|
||||
scsi_null_log("SCSI NULL: %08X, %08X\n", hdbufferb, *BufLen);
|
||||
scsi_null_request_sense(hdbufferb, *BufLen, sense_desc & 1);
|
||||
break;
|
||||
#if 0
|
||||
case GPCMD_INQUIRY:
|
||||
memcpy(hdbufferb, temp_buffer, *BufLen);
|
||||
free(temp_buffer);
|
||||
temp_buffer = NULL;
|
||||
scsi_null_log("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
hdbufferb[0], hdbufferb[1], hdbufferb[2], hdbufferb[3], hdbufferb[4], hdbufferb[5], hdbufferb[6], hdbufferb[7],
|
||||
hdbufferb[8], hdbufferb[9], hdbufferb[10], hdbufferb[11], hdbufferb[12], hdbufferb[13], hdbufferb[14], hdbufferb[15]);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fatal("SCSI NULL: Bad Command for phase 2 (%02X)\n", command);
|
||||
break;
|
||||
}
|
||||
|
||||
scsi_null_set_phase(SCSI_PHASE_STATUS);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_null_callback(void)
|
||||
{
|
||||
switch(packet_status) {
|
||||
case CDROM_PHASE_IDLE:
|
||||
scsi_null_log("SCSI NULL: PHASE_IDLE\n");
|
||||
phase = 1;
|
||||
status = READY_STAT | DRQ_STAT | (status & ERR_STAT);
|
||||
return;
|
||||
case CDROM_PHASE_COMPLETE:
|
||||
scsi_null_log("SCSI NULL: PHASE_COMPLETE\n");
|
||||
status = READY_STAT;
|
||||
phase = 3;
|
||||
packet_status = 0xFF;
|
||||
return;
|
||||
case CDROM_PHASE_DATA_IN_DMA:
|
||||
scsi_null_log("SCSI NULL: PHASE_DATA_IN_DMA\n");
|
||||
scsi_null_phase_data_in();
|
||||
packet_status = CDROM_PHASE_COMPLETE;
|
||||
status = READY_STAT;
|
||||
phase = 3;
|
||||
return;
|
||||
case CDROM_PHASE_ERROR:
|
||||
scsi_null_log("SCSI NULL: PHASE_ERROR\n");
|
||||
status = READY_STAT | ERR_STAT;
|
||||
phase = 3;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_null_set_location(uint8_t id, uint8_t lun)
|
||||
{
|
||||
null_id = id;
|
||||
null_lun = lun;
|
||||
}
|
||||
Reference in New Issue
Block a user