Extensive rework of SCSI and ATAPI devices and numerous bug fixes and cleanups;
Extensive rework of CD-ROM image handling; The settings save code now forces some devices' (SCSI disk, CD-ROM, etc.) pointers to NULL before resetting the machine - fixes segmentation faults after changing settings; Added the NCR 53c825A and 53c875 SCSI controllers; Fixed IDE/ATAPI DMA; Slight changed to PCI IDE bus master operation.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Handling of the SCSI controllers.
|
||||
*
|
||||
* Version: @(#)scsi.c 1.0.22 2018/10/10
|
||||
* Version: @(#)scsi.c 1.0.24 2018/10/30
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -37,7 +37,7 @@
|
||||
#include "scsi_aha154x.h"
|
||||
#include "scsi_buslogic.h"
|
||||
#include "scsi_ncr5380.h"
|
||||
#include "scsi_ncr53c810.h"
|
||||
#include "scsi_ncr53c8xx.h"
|
||||
#ifdef WALTJE
|
||||
# include "scsi_wd33c93.h"
|
||||
#endif
|
||||
@@ -55,25 +55,27 @@ typedef const struct {
|
||||
|
||||
|
||||
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, },
|
||||
{ "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, },
|
||||
{ "[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, },
|
||||
{ "[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, },
|
||||
{ "[PCI] NCR 53C825A", "ncr53c825a", &ncr53c825a_pci_device, },
|
||||
{ "[PCI] NCR 53C875", "ncr53c875", &ncr53c875_pci_device, },
|
||||
{ "[VLB] BusLogic BT-445S", "bt445s", &buslogic_445s_device, },
|
||||
{ "", "", NULL, },
|
||||
};
|
||||
|
||||
|
||||
@@ -129,17 +131,16 @@ int scsi_card_get_from_internal_name(char *s)
|
||||
void scsi_card_init(void)
|
||||
{
|
||||
int i;
|
||||
scsi_device_t *dev;
|
||||
|
||||
if (!scsi_cards[scsi_card_current].device)
|
||||
return;
|
||||
|
||||
for (i = 0; i < SCSI_ID_MAX; i++) {
|
||||
if (scsi_devices[i].cmd_buffer)
|
||||
free(scsi_devices[i].cmd_buffer);
|
||||
scsi_devices[i].cmd_buffer = NULL;
|
||||
dev = &(scsi_devices[i]);
|
||||
|
||||
memset(&scsi_devices[i], 0, sizeof(scsi_device_t));
|
||||
scsi_devices[i].type = SCSI_NONE;
|
||||
memset(dev, 0, sizeof(scsi_device_t));
|
||||
dev->type = SCSI_NONE;
|
||||
}
|
||||
|
||||
device_add(scsi_cards[scsi_card_current].device);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 1 - BT-545S ISA;
|
||||
* 2 - BT-958D PCI
|
||||
*
|
||||
* Version: @(#)scsi_buslogic.c 1.0.42 2018/10/19
|
||||
* Version: @(#)scsi_buslogic.c 1.0.43 2018/10/28
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -574,10 +574,10 @@ BuslogicSCSIBIOSDMATransfer(ESCMD *ESCSICmd, uint8_t TargetID, int dir)
|
||||
|
||||
if (dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_OUT) || (ESCSICmd->DataDirection == 0x00))) {
|
||||
buslogic_log("BusLogic BIOS DMA: Reading %i bytes from %08X\n", TransferLength, Address);
|
||||
DMAPageRead(Address, (uint8_t *)dev->cmd_buffer, TransferLength);
|
||||
DMAPageRead(Address, (uint8_t *)dev->sc->temp_buffer, TransferLength);
|
||||
} else if (!dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_IN) || (ESCSICmd->DataDirection == 0x00))) {
|
||||
buslogic_log("BusLogic BIOS DMA: Writing %i bytes at %08X\n", TransferLength, Address);
|
||||
DMAPageWrite(Address, (uint8_t *)dev->cmd_buffer, TransferLength);
|
||||
DMAPageWrite(Address, (uint8_t *)dev->sc->temp_buffer, TransferLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -624,8 +624,6 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u
|
||||
}
|
||||
}
|
||||
|
||||
x54x_buf_alloc(ESCSICmd->TargetId, ESCSICmd->DataLength);
|
||||
|
||||
target_cdb_len = 12;
|
||||
|
||||
if (!scsi_device_valid(sd)) fatal("SCSI target on ID %02i has disappeared\n", ESCSICmd->TargetId);
|
||||
@@ -645,19 +643,15 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u
|
||||
}
|
||||
|
||||
sd->buffer_length = ESCSICmd->DataLength;
|
||||
|
||||
scsi_device_command_phase0(sd, temp_cdb);
|
||||
|
||||
phase = sd->phase;
|
||||
if (phase != SCSI_PHASE_STATUS) {
|
||||
if (phase == SCSI_PHASE_DATA_IN)
|
||||
scsi_device_command_phase1(sd);
|
||||
BuslogicSCSIBIOSDMATransfer(ESCSICmd, ESCSICmd->TargetId, (phase == SCSI_PHASE_DATA_OUT));
|
||||
if (phase == SCSI_PHASE_DATA_OUT)
|
||||
scsi_device_command_phase1(sd);
|
||||
scsi_device_command_phase1(sd);
|
||||
}
|
||||
|
||||
x54x_buf_free(ESCSICmd->TargetId);
|
||||
|
||||
buslogic_log("BIOS Request complete\n");
|
||||
|
||||
if (sd->status == SCSI_STATUS_OK) {
|
||||
@@ -1155,7 +1149,8 @@ BuslogicPCIRead(int func, int addr, void *p)
|
||||
case 0x13:
|
||||
return buslogic_pci_bar[0].addr_regs[3];
|
||||
case 0x14:
|
||||
return (buslogic_pci_bar[1].addr_regs[0] & 0xe0); /*Memory space*/
|
||||
// return (buslogic_pci_bar[1].addr_regs[0] & 0xe0); /*Memory space*/
|
||||
return 0x00;
|
||||
case 0x15:
|
||||
return buslogic_pci_bar[1].addr_regs[1];
|
||||
case 0x16:
|
||||
@@ -1255,7 +1250,10 @@ BuslogicPCIWrite(int func, int addr, uint8_t val, void *p)
|
||||
/* Then let's set the PCI regs. */
|
||||
buslogic_pci_bar[1].addr_regs[addr & 3] = val;
|
||||
/* Then let's calculate the new I/O base. */
|
||||
bl->MMIOBase = buslogic_pci_bar[1].addr & 0xffffffe0;
|
||||
// bl->MMIOBase = buslogic_pci_bar[1].addr & 0xffffffe0;
|
||||
/* Give it a 4 kB alignment as that's this emulator's granularity. */
|
||||
buslogic_pci_bar[1].addr &= 0xffffc000;
|
||||
bl->MMIOBase = buslogic_pci_bar[1].addr & 0xffffc000;
|
||||
/* Log the new base. */
|
||||
buslogic_log("BusLogic PCI: New MMIO base is %04X\n" , bl->MMIOBase);
|
||||
/* We're done, so get out of the here. */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -43,19 +43,13 @@ typedef struct {
|
||||
|
||||
int requested_blocks, packet_status,
|
||||
total_length, do_page_save,
|
||||
unit_attention;
|
||||
unit_attention, request_pos,
|
||||
old_len, media_status;
|
||||
|
||||
uint32_t sector_pos, sector_len,
|
||||
packet_len, pos;
|
||||
|
||||
int64_t callback;
|
||||
|
||||
int media_status, data_pos,
|
||||
request_pos, total_read,
|
||||
old_len;
|
||||
|
||||
uint8_t previous_command,
|
||||
pad3, pad4, pad5;
|
||||
} scsi_cdrom_t;
|
||||
#endif
|
||||
|
||||
@@ -69,7 +63,7 @@ extern scsi_cdrom_t *scsi_cdrom[CDROM_NUM];
|
||||
#define scsi_cdrom_drive cdrom_drives[id].host_drive
|
||||
|
||||
|
||||
extern void scsi_cdrom_reset(void *p);
|
||||
extern void scsi_cdrom_reset(scsi_common_t *sc);
|
||||
|
||||
|
||||
#endif /*EMU_SCSI_CDROM_H*/
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* The generic SCSI device command handler.
|
||||
*
|
||||
* Version: @(#)scsi_device.c 1.0.21 2018/10/13
|
||||
* Version: @(#)scsi_device.c 1.0.22 2018/10/28
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -35,71 +35,81 @@ uint8_t scsi_null_device_sense[18] = { 0x70,0,SENSE_ILLEGAL_REQUEST,0,0,0,0,0,0,
|
||||
static uint8_t
|
||||
scsi_device_target_command(scsi_device_t *dev, uint8_t *cdb)
|
||||
{
|
||||
if (dev->command && dev->err_stat_to_scsi) {
|
||||
dev->command(dev->p, cdb);
|
||||
return dev->err_stat_to_scsi(dev->p);
|
||||
if (dev->command) {
|
||||
dev->command(dev->sc, cdb);
|
||||
|
||||
if (dev->sc->status & ERR_STAT)
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
else
|
||||
return SCSI_STATUS_OK;
|
||||
} else
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
}
|
||||
|
||||
|
||||
static void scsi_device_target_callback(scsi_device_t *dev)
|
||||
static void
|
||||
scsi_device_target_callback(scsi_device_t *dev)
|
||||
{
|
||||
if (dev->callback)
|
||||
dev->callback(dev->p);
|
||||
dev->callback(dev->sc);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int scsi_device_target_err_stat_to_scsi(scsi_device_t *dev)
|
||||
static int
|
||||
scsi_device_target_err_stat_to_scsi(scsi_device_t *dev)
|
||||
{
|
||||
if (dev->err_stat_to_scsi)
|
||||
return dev->err_stat_to_scsi(dev->p);
|
||||
if (dev->sc)
|
||||
if (dev->sc->status & ERR_STAT)
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
else
|
||||
return SCSI_STATUS_OK;
|
||||
else
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
}
|
||||
|
||||
|
||||
int64_t scsi_device_get_callback(scsi_device_t *dev)
|
||||
int64_t
|
||||
scsi_device_get_callback(scsi_device_t *dev)
|
||||
{
|
||||
scsi_device_data_t *sdd = (scsi_device_data_t *) dev->p;
|
||||
|
||||
if (sdd)
|
||||
return sdd->callback;
|
||||
if (dev->sc)
|
||||
return dev->sc->callback;
|
||||
else
|
||||
return -1LL;
|
||||
}
|
||||
|
||||
|
||||
uint8_t *scsi_device_sense(scsi_device_t *dev)
|
||||
uint8_t *
|
||||
scsi_device_sense(scsi_device_t *dev)
|
||||
{
|
||||
scsi_device_data_t *sdd = (scsi_device_data_t *) dev->p;
|
||||
|
||||
if (sdd)
|
||||
return sdd->sense;
|
||||
if (dev->sc)
|
||||
return dev->sc->sense;
|
||||
else
|
||||
return scsi_null_device_sense;
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_request_sense(scsi_device_t *dev, uint8_t *buffer, uint8_t alloc_length)
|
||||
void
|
||||
scsi_device_request_sense(scsi_device_t *dev, uint8_t *buffer, uint8_t alloc_length)
|
||||
{
|
||||
if (dev->request_sense)
|
||||
dev->request_sense(dev->p, buffer, alloc_length);
|
||||
dev->request_sense(dev->sc, buffer, alloc_length);
|
||||
else
|
||||
memcpy(buffer, scsi_null_device_sense, alloc_length);
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_reset(scsi_device_t *dev)
|
||||
void
|
||||
scsi_device_reset(scsi_device_t *dev)
|
||||
{
|
||||
if (dev->reset)
|
||||
dev->reset(dev->p);
|
||||
dev->reset(dev->sc);
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_present(scsi_device_t *dev)
|
||||
int
|
||||
scsi_device_present(scsi_device_t *dev)
|
||||
{
|
||||
if (dev->type == SCSI_NONE)
|
||||
return 0;
|
||||
@@ -108,25 +118,28 @@ int scsi_device_present(scsi_device_t *dev)
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_valid(scsi_device_t *dev)
|
||||
int
|
||||
scsi_device_valid(scsi_device_t *dev)
|
||||
{
|
||||
if (dev->p)
|
||||
if (dev->sc)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_cdb_length(scsi_device_t *dev)
|
||||
int
|
||||
scsi_device_cdb_length(scsi_device_t *dev)
|
||||
{
|
||||
/* Right now, it's 12 for all devices. */
|
||||
return 12;
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb)
|
||||
void
|
||||
scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb)
|
||||
{
|
||||
if (!dev->p) {
|
||||
if (!dev->sc) {
|
||||
dev->phase = SCSI_PHASE_STATUS;
|
||||
dev->status = SCSI_STATUS_CHECK_CONDITION;
|
||||
return;
|
||||
@@ -143,9 +156,11 @@ void scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb)
|
||||
/* If the phase is DATA IN or DATA OUT, finish this here. */
|
||||
}
|
||||
|
||||
void scsi_device_command_phase1(scsi_device_t *dev)
|
||||
|
||||
void
|
||||
scsi_device_command_phase1(scsi_device_t *dev)
|
||||
{
|
||||
if (!dev->p)
|
||||
if (!dev->sc)
|
||||
return;
|
||||
|
||||
/* Call the second phase. */
|
||||
@@ -155,7 +170,25 @@ void scsi_device_command_phase1(scsi_device_t *dev)
|
||||
scsi_device_target_callback(dev);
|
||||
}
|
||||
|
||||
int32_t *scsi_device_get_buf_len(scsi_device_t *dev)
|
||||
|
||||
void
|
||||
scsi_device_command_stop(scsi_device_t *dev)
|
||||
{
|
||||
return &dev->buffer_length;
|
||||
if (!dev->command_stop)
|
||||
dev->command_stop(dev->sc);
|
||||
scsi_device_target_callback(dev);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_device_close_all(void)
|
||||
{
|
||||
int i;
|
||||
scsi_device_t *dev;
|
||||
|
||||
for (i = 0; i < SCSI_ID_MAX; i++) {
|
||||
dev = &(scsi_devices[i]);
|
||||
if (dev->command_stop && dev->sc)
|
||||
dev->command_stop(dev->sc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Definitions for the generic SCSI device command handler.
|
||||
*
|
||||
* Version: @(#)scsi_device.h 1.0.12 2018/10/11
|
||||
* Version: @(#)scsi_device.h 1.0.14 2018/10/28
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -28,6 +28,18 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* SCSI commands. */
|
||||
#define GPCMD_TEST_UNIT_READY 0x00
|
||||
#define GPCMD_REZERO_UNIT 0x01
|
||||
@@ -291,59 +303,55 @@ typedef struct
|
||||
} scsi_bus_t;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint8_t *cmd_buffer;
|
||||
|
||||
int32_t buffer_length;
|
||||
|
||||
uint8_t status, phase;
|
||||
uint16_t type;
|
||||
|
||||
void *p;
|
||||
|
||||
void (*command)(void *p, uint8_t *cdb);
|
||||
void (*callback)(void *p);
|
||||
int (*err_stat_to_scsi)(void *p);
|
||||
void (*request_sense)(void *p, uint8_t *buffer, uint8_t alloc_length);
|
||||
void (*reset)(void *p);
|
||||
int (*read_capacity)(void *p, uint8_t *cdb, uint8_t *buffer, uint32_t *len);
|
||||
} scsi_device_t;
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint8_t pages[0x40][0x40];
|
||||
uint8_t pages[0x40][0x40];
|
||||
} mode_sense_pages_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
/* This is so we can access the common elements to all SCSI device structs
|
||||
without knowing the device type. */
|
||||
typedef struct {
|
||||
typedef struct scsi_common_s {
|
||||
mode_sense_pages_t ms_pages_saved;
|
||||
|
||||
void *p;
|
||||
|
||||
uint8_t *temp_buffer,
|
||||
pad[16], /* This is atapi_cdb in ATAPI-supporting devices,
|
||||
and pad in SCSI-only devices. */
|
||||
atapi_cdb[16], /* This is atapi_cdb in ATAPI-supporting devices,
|
||||
and pad in SCSI-only devices. */
|
||||
current_cdb[16],
|
||||
sense[256];
|
||||
|
||||
uint8_t status, phase,
|
||||
error, id,
|
||||
features, pad0,
|
||||
pad1, pad2;
|
||||
features, pad,
|
||||
pad0, pad1;
|
||||
|
||||
uint16_t request_length, max_transfer_len;
|
||||
|
||||
int requested_blocks, packet_status,
|
||||
total_length, do_page_save,
|
||||
unit_attention;
|
||||
unit_attention, request_pos,
|
||||
old_len, media_status;
|
||||
|
||||
uint32_t sector_pos, sector_len,
|
||||
packet_len, pos;
|
||||
|
||||
int64_t callback;
|
||||
} scsi_device_data_t;
|
||||
} scsi_common_t;
|
||||
|
||||
typedef struct {
|
||||
int32_t buffer_length;
|
||||
|
||||
uint8_t status, phase;
|
||||
uint16_t type;
|
||||
|
||||
scsi_common_t *sc;
|
||||
|
||||
void (*command)(scsi_common_t *sc, uint8_t *cdb);
|
||||
void (*callback)(scsi_common_t *sc);
|
||||
void (*request_sense)(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length);
|
||||
void (*reset)(scsi_common_t *sc);
|
||||
void (*command_stop)(scsi_common_t *sc);
|
||||
} scsi_device_t;
|
||||
|
||||
/* These are based on the INQUIRY values. */
|
||||
#define SCSI_NONE 0x0060
|
||||
@@ -371,6 +379,7 @@ extern int scsi_device_valid(scsi_device_t *dev);
|
||||
extern int scsi_device_cdb_length(scsi_device_t *dev);
|
||||
extern void scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb);
|
||||
extern void scsi_device_command_phase1(scsi_device_t *dev);
|
||||
extern int32_t *scsi_device_get_buf_len(scsi_device_t *dev);
|
||||
extern void scsi_device_command_stop(scsi_device_t *dev);
|
||||
extern void scsi_device_close_all(void);
|
||||
|
||||
#endif /*SCSI_DEVICE_H*/
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
* Emulation of SCSI fixed disks.
|
||||
*
|
||||
* Version: @(#)scsi_disk.c 1.0.27 2018/10/27
|
||||
* Version: @(#)scsi_disk.c 1.0.28 2018/10/28
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
@@ -26,27 +26,13 @@
|
||||
#include "../piix.h"
|
||||
#include "../disk/hdd.h"
|
||||
#include "../disk/hdc.h"
|
||||
#include "scsi_device.h"
|
||||
#include "../disk/hdc_ide.h"
|
||||
#include "../plat.h"
|
||||
#include "../ui.h"
|
||||
#include "scsi_device.h"
|
||||
#include "scsi_disk.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_disk_sense_error dev->sense[0]
|
||||
#define scsi_disk_sense_key dev->sense[2]
|
||||
#define scsi_disk_asc dev->sense[12]
|
||||
@@ -136,7 +122,7 @@ static const mode_sense_pages_t scsi_disk_mode_sense_pages_changeable =
|
||||
} };
|
||||
|
||||
|
||||
static void scsi_disk_callback(void *p);
|
||||
static void scsi_disk_callback(scsi_common_t *sc);
|
||||
|
||||
|
||||
#ifdef ENABLE_SCSI_DISK_LOG
|
||||
@@ -159,19 +145,6 @@ scsi_disk_log(const char *fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */
|
||||
static int
|
||||
scsi_disk_err_stat_to_scsi(void *p)
|
||||
{
|
||||
scsi_disk_t *dev = (scsi_disk_t *) p;
|
||||
|
||||
if (dev->status & ERR_STAT)
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
else
|
||||
return SCSI_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_disk_mode_sense_load(scsi_disk_t *dev)
|
||||
{
|
||||
@@ -206,25 +179,6 @@ scsi_disk_mode_sense_save(scsi_disk_t *dev)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
scsi_disk_read_capacity(void *p, uint8_t *cdb, uint8_t *buffer, uint32_t *len)
|
||||
{
|
||||
scsi_disk_t *dev = (scsi_disk_t *) p;
|
||||
int size = 0;
|
||||
|
||||
size = hdd_image_get_last_sector(dev->id);
|
||||
memset(buffer, 0, 8);
|
||||
buffer[0] = (size >> 24) & 0xff;
|
||||
buffer[1] = (size >> 16) & 0xff;
|
||||
buffer[2] = (size >> 8) & 0xff;
|
||||
buffer[3] = size & 0xff;
|
||||
buffer[6] = 2; /* 512 = 0x0200 */
|
||||
*len = 8;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*SCSI Mode Sense 6/10*/
|
||||
uint8_t
|
||||
scsi_disk_mode_sense_read(scsi_disk_t *dev, uint8_t page_control, uint8_t page, uint8_t pos)
|
||||
@@ -292,7 +246,7 @@ scsi_disk_command_common(scsi_disk_t *dev)
|
||||
dev->status = BUSY_STAT;
|
||||
dev->phase = 1;
|
||||
if (dev->packet_status == PHASE_COMPLETE) {
|
||||
scsi_disk_callback((void *) dev);
|
||||
scsi_disk_callback((scsi_common_t *) dev);
|
||||
dev->callback = 0LL;
|
||||
} else
|
||||
dev->callback = -1LL; /* Speed depends on SCSI controller */
|
||||
@@ -485,9 +439,9 @@ scsi_disk_rezero(scsi_disk_t *dev)
|
||||
|
||||
|
||||
static void
|
||||
scsi_disk_reset(void *p)
|
||||
scsi_disk_reset(scsi_common_t *sc)
|
||||
{
|
||||
scsi_disk_t *dev = (scsi_disk_t *) p;
|
||||
scsi_disk_t *dev = (scsi_disk_t *) sc;
|
||||
|
||||
scsi_disk_rezero(dev);
|
||||
dev->status = 0;
|
||||
@@ -522,9 +476,9 @@ scsi_disk_request_sense(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length,
|
||||
|
||||
|
||||
static void
|
||||
scsi_disk_request_sense_for_scsi(void *p, uint8_t *buffer, uint8_t alloc_length)
|
||||
scsi_disk_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length)
|
||||
{
|
||||
scsi_disk_t *dev = (scsi_disk_t *) p;
|
||||
scsi_disk_t *dev = (scsi_disk_t *) sc;
|
||||
|
||||
scsi_disk_request_sense(dev, buffer, alloc_length, 0);
|
||||
}
|
||||
@@ -544,9 +498,29 @@ scsi_disk_set_buf_len(scsi_disk_t *dev, int32_t *BufLen, int32_t *src_len)
|
||||
|
||||
|
||||
static void
|
||||
scsi_disk_command(void *p, uint8_t *cdb)
|
||||
scsi_disk_buf_alloc(scsi_disk_t *dev, uint32_t len)
|
||||
{
|
||||
scsi_disk_t *dev = (scsi_disk_t *) p;
|
||||
scsi_disk_log("SCSI HD %i: Allocated buffer length: %i\n", dev->id, len);
|
||||
if (!dev->temp_buffer)
|
||||
dev->temp_buffer = (uint8_t *) malloc(len);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_disk_buf_free(scsi_disk_t *dev)
|
||||
{
|
||||
if (dev->temp_buffer) {
|
||||
scsi_disk_log("SCSI HD %i: Freeing buffer...\n", dev->id);
|
||||
free(dev->temp_buffer);
|
||||
dev->temp_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_disk_command(scsi_common_t *sc, uint8_t *cdb)
|
||||
{
|
||||
scsi_disk_t *dev = (scsi_disk_t *) sc;
|
||||
#ifdef ENABLE_SCSI_DISK_LOG
|
||||
uint8_t *hdbufferb;
|
||||
#endif
|
||||
@@ -631,6 +605,7 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
break;
|
||||
}
|
||||
|
||||
scsi_disk_buf_alloc(dev, 256);
|
||||
scsi_disk_set_buf_len(dev, BufLen, &len);
|
||||
|
||||
if (*BufLen < cdb[4])
|
||||
@@ -638,14 +613,21 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
|
||||
len = (cdb[1] & 1) ? 8 : 18;
|
||||
|
||||
scsi_disk_request_sense(dev, dev->temp_buffer, *BufLen, cdb[1] & 1);
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN);
|
||||
scsi_disk_data_command_finish(dev, len, len, cdb[4], 0);
|
||||
break;
|
||||
|
||||
case GPCMD_MECHANISM_STATUS:
|
||||
len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
|
||||
scsi_disk_set_buf_len(dev, BufLen, &len);
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN);
|
||||
len = (cdb[8] << 8) | cdb[9];
|
||||
|
||||
scsi_disk_buf_alloc(dev, 8);
|
||||
scsi_disk_set_buf_len(dev, BufLen, &len);
|
||||
|
||||
memset(dev->temp_buffer, 0, 8);
|
||||
dev->temp_buffer[5] = 1;
|
||||
|
||||
scsi_disk_data_command_finish(dev, 8, 8, len, 0);
|
||||
break;
|
||||
|
||||
@@ -684,10 +666,17 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
dev->requested_blocks = max_len;
|
||||
|
||||
alloc_length = dev->packet_len = max_len << 9;
|
||||
|
||||
scsi_disk_buf_alloc(dev, dev->packet_len);
|
||||
scsi_disk_set_buf_len(dev, BufLen, &alloc_length);
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN);
|
||||
|
||||
if ((dev->requested_blocks > 0) && (*BufLen > 0)) {
|
||||
if (dev->packet_len > (uint32_t) *BufLen)
|
||||
hdd_image_read(dev->id, dev->sector_pos, *BufLen >> 9, dev->temp_buffer);
|
||||
else
|
||||
hdd_image_read(dev->id, dev->sector_pos, dev->requested_blocks, dev->temp_buffer);
|
||||
}
|
||||
|
||||
if (dev->requested_blocks > 1)
|
||||
scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 0);
|
||||
else
|
||||
@@ -748,6 +737,7 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
dev->requested_blocks = max_len;
|
||||
|
||||
alloc_length = dev->packet_len = max_len << 9;
|
||||
scsi_disk_buf_alloc(dev, dev->packet_len);
|
||||
|
||||
scsi_disk_set_buf_len(dev, BufLen, &alloc_length);
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT);
|
||||
@@ -759,6 +749,9 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
return;
|
||||
|
||||
case GPCMD_WRITE_SAME_10:
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT);
|
||||
alloc_length = 512;
|
||||
|
||||
if ((cdb[1] & 6) == 6) {
|
||||
scsi_disk_invalid_field(dev);
|
||||
return;
|
||||
@@ -766,7 +759,6 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
|
||||
dev->sector_len = (cdb[7] << 8) | cdb[8];
|
||||
dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
|
||||
scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos);
|
||||
|
||||
if ((dev->sector_pos > last_sector) ||
|
||||
((dev->sector_pos + dev->sector_len - 1) > last_sector)) {
|
||||
@@ -782,18 +774,15 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
break;
|
||||
}
|
||||
|
||||
max_len = 1;
|
||||
dev->requested_blocks = max_len;
|
||||
|
||||
alloc_length = dev->packet_len = max_len << 9;
|
||||
|
||||
scsi_disk_buf_alloc(dev, alloc_length);
|
||||
scsi_disk_set_buf_len(dev, BufLen, &alloc_length);
|
||||
|
||||
max_len = 1;
|
||||
dev->requested_blocks = 1;
|
||||
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT);
|
||||
|
||||
if (dev->requested_blocks > 1)
|
||||
scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 1);
|
||||
else
|
||||
scsi_disk_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 1);
|
||||
scsi_disk_data_command_finish(dev, 512, 512, alloc_length, 1);
|
||||
return;
|
||||
|
||||
case GPCMD_MODE_SENSE_6:
|
||||
@@ -802,16 +791,17 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
|
||||
block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1;
|
||||
|
||||
if (cdb[0] == GPCMD_MODE_SENSE_6)
|
||||
if (cdb[0] == GPCMD_MODE_SENSE_6) {
|
||||
len = cdb[4];
|
||||
else
|
||||
scsi_disk_buf_alloc(dev, 256);
|
||||
} else {
|
||||
len = (cdb[8] | (cdb[7] << 8));
|
||||
scsi_disk_buf_alloc(dev, 65536);
|
||||
}
|
||||
|
||||
memset(dev->temp_buffer, 0, len);
|
||||
alloc_length = len;
|
||||
|
||||
dev->temp_buffer = (uint8_t *) malloc(65536);
|
||||
memset(dev->temp_buffer, 0, 65536);
|
||||
|
||||
if (cdb[0] == GPCMD_MODE_SENSE_6) {
|
||||
len = scsi_disk_mode_sense(dev, dev->temp_buffer, 4, cdb[2], block_desc);
|
||||
if (len > alloc_length)
|
||||
@@ -824,8 +814,8 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
len = scsi_disk_mode_sense(dev, dev->temp_buffer, 8, cdb[2], block_desc);
|
||||
if (len > alloc_length)
|
||||
len = alloc_length;
|
||||
dev->temp_buffer[0]=(len - 2) >> 8;
|
||||
dev->temp_buffer[1]=(len - 2) & 255;
|
||||
dev->temp_buffer[0] = (len - 2) >> 8;
|
||||
dev->temp_buffer[1] = (len - 2) & 255;
|
||||
dev->temp_buffer[2] = 0;
|
||||
if (block_desc) {
|
||||
dev->temp_buffer[6] = 0;
|
||||
@@ -848,10 +838,13 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
case GPCMD_MODE_SELECT_10:
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT);
|
||||
|
||||
if (cdb[0] == GPCMD_MODE_SELECT_6)
|
||||
if (cdb[0] == GPCMD_MODE_SELECT_6) {
|
||||
len = cdb[4];
|
||||
else
|
||||
scsi_disk_buf_alloc(dev, 256);
|
||||
} else {
|
||||
len = (cdb[7] << 8) | cdb[8];
|
||||
scsi_disk_buf_alloc(dev, 65536);
|
||||
}
|
||||
|
||||
scsi_disk_set_buf_len(dev, BufLen, &len);
|
||||
dev->total_length = len;
|
||||
@@ -872,7 +865,7 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
break;
|
||||
}
|
||||
|
||||
dev->temp_buffer = malloc(1024);
|
||||
scsi_disk_buf_alloc(dev, 65536);
|
||||
|
||||
if (cdb[1] & 1) {
|
||||
preamble_len = 4;
|
||||
@@ -891,8 +884,7 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
break;
|
||||
case 0x83:
|
||||
if (idx + 24 > max_len) {
|
||||
free(dev->temp_buffer);
|
||||
dev->temp_buffer = NULL;
|
||||
scsi_disk_buf_free(dev);
|
||||
scsi_disk_data_phase_error(dev);
|
||||
return;
|
||||
}
|
||||
@@ -919,9 +911,8 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
break;
|
||||
default:
|
||||
scsi_disk_log("INQUIRY: Invalid page: %02X\n", cdb[2]);
|
||||
free(dev->temp_buffer);
|
||||
dev->temp_buffer = NULL;
|
||||
scsi_disk_invalid_field(dev);
|
||||
scsi_disk_buf_free(dev);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -988,12 +979,16 @@ atapi_out:
|
||||
break;
|
||||
|
||||
case GPCMD_READ_CDROM_CAPACITY:
|
||||
dev->temp_buffer = (uint8_t *) malloc(8);
|
||||
scsi_disk_buf_alloc(dev, 8);
|
||||
|
||||
if (scsi_disk_read_capacity(dev, dev->current_cdb, dev->temp_buffer, (uint32_t *) &len) == 0) {
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_STATUS);
|
||||
return;
|
||||
}
|
||||
max_len = hdd_image_get_last_sector(dev->id);
|
||||
memset(dev->temp_buffer, 0, 8);
|
||||
dev->temp_buffer[0] = (max_len >> 24) & 0xff;
|
||||
dev->temp_buffer[1] = (max_len >> 16) & 0xff;
|
||||
dev->temp_buffer[2] = (max_len >> 8) & 0xff;
|
||||
dev->temp_buffer[3] = max_len & 0xff;
|
||||
dev->temp_buffer[6] = 2;
|
||||
len = 8;
|
||||
|
||||
scsi_disk_set_buf_len(dev, BufLen, &len);
|
||||
|
||||
@@ -1011,62 +1006,19 @@ atapi_out:
|
||||
|
||||
|
||||
static void
|
||||
scsi_disk_phase_data_in(scsi_disk_t *dev)
|
||||
scsi_disk_command_stop(scsi_common_t *sc)
|
||||
{
|
||||
uint8_t *hdbufferb = scsi_devices[dev->drv->scsi_id].cmd_buffer;
|
||||
int32_t *BufLen = &scsi_devices[dev->drv->scsi_id].buffer_length;
|
||||
scsi_disk_t *dev = (scsi_disk_t *) sc;
|
||||
|
||||
if (!*BufLen) {
|
||||
scsi_disk_log("scsi_disk_phase_data_in(): Buffer length is 0\n");
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_STATUS);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dev->current_cdb[0]) {
|
||||
case GPCMD_REQUEST_SENSE:
|
||||
scsi_disk_log("SCSI HDD %i: %08X, %08X\n", dev->id, hdbufferb, *BufLen);
|
||||
scsi_disk_request_sense(dev, hdbufferb, *BufLen, dev->current_cdb[1] & 1);
|
||||
break;
|
||||
case GPCMD_MECHANISM_STATUS:
|
||||
memset(hdbufferb, 0, *BufLen);
|
||||
hdbufferb[5] = 1;
|
||||
break;
|
||||
case GPCMD_READ_6:
|
||||
case GPCMD_READ_10:
|
||||
case GPCMD_READ_12:
|
||||
if ((dev->requested_blocks > 0) && (*BufLen > 0)) {
|
||||
if (dev->packet_len > (uint32_t) *BufLen)
|
||||
hdd_image_read(dev->id, dev->sector_pos, *BufLen >> 9, hdbufferb);
|
||||
else
|
||||
hdd_image_read(dev->id, dev->sector_pos, dev->requested_blocks, hdbufferb);
|
||||
}
|
||||
break;
|
||||
case GPCMD_MODE_SENSE_6:
|
||||
case GPCMD_MODE_SENSE_10:
|
||||
case GPCMD_INQUIRY:
|
||||
case GPCMD_READ_CDROM_CAPACITY:
|
||||
scsi_disk_log("scsi_disk_phase_data_in(): Filling buffer (%08X, %08X)\n", hdbufferb, dev->temp_buffer);
|
||||
memcpy(hdbufferb, dev->temp_buffer, *BufLen);
|
||||
free(dev->temp_buffer);
|
||||
dev->temp_buffer = NULL;
|
||||
scsi_disk_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;
|
||||
default:
|
||||
fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", dev->id, dev->current_cdb[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_STATUS);
|
||||
scsi_disk_command_complete(dev);
|
||||
scsi_disk_buf_free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_disk_phase_data_out(scsi_disk_t *dev)
|
||||
scsi_disk_phase_data_out(scsi_common_t *sc)
|
||||
{
|
||||
uint8_t *hdbufferb = scsi_devices[dev->drv->scsi_id].cmd_buffer;
|
||||
scsi_disk_t *dev = (scsi_disk_t *) sc;
|
||||
int i;
|
||||
int32_t *BufLen = &scsi_devices[dev->drv->scsi_id].buffer_length;
|
||||
uint32_t last_sector = hdd_image_get_last_sector(dev->id);
|
||||
@@ -1093,9 +1045,9 @@ scsi_disk_phase_data_out(scsi_disk_t *dev)
|
||||
case GPCMD_WRITE_AND_VERIFY_12:
|
||||
if ((dev->requested_blocks > 0) && (*BufLen > 0)) {
|
||||
if (dev->packet_len > (uint32_t) *BufLen)
|
||||
hdd_image_write(dev->id, dev->sector_pos, *BufLen >> 9, hdbufferb);
|
||||
hdd_image_write(dev->id, dev->sector_pos, *BufLen >> 9, dev->temp_buffer);
|
||||
else
|
||||
hdd_image_write(dev->id, dev->sector_pos, dev->requested_blocks, hdbufferb);
|
||||
hdd_image_write(dev->id, dev->sector_pos, dev->requested_blocks, dev->temp_buffer);
|
||||
}
|
||||
break;
|
||||
case GPCMD_WRITE_SAME_10:
|
||||
@@ -1106,24 +1058,24 @@ scsi_disk_phase_data_out(scsi_disk_t *dev)
|
||||
|
||||
for (i = dev->sector_pos; i <= (int) last_to_write; i++) {
|
||||
if (dev->current_cdb[1] & 2) {
|
||||
hdbufferb[0] = (i >> 24) & 0xff;
|
||||
hdbufferb[1] = (i >> 16) & 0xff;
|
||||
hdbufferb[2] = (i >> 8) & 0xff;
|
||||
hdbufferb[3] = i & 0xff;
|
||||
dev->temp_buffer[0] = (i >> 24) & 0xff;
|
||||
dev->temp_buffer[1] = (i >> 16) & 0xff;
|
||||
dev->temp_buffer[2] = (i >> 8) & 0xff;
|
||||
dev->temp_buffer[3] = i & 0xff;
|
||||
} else if (dev->current_cdb[1] & 4) {
|
||||
s = (i % dev->drv->spt);
|
||||
h = ((i - s) / dev->drv->spt) % dev->drv->hpc;
|
||||
c = ((i - s) / dev->drv->spt) / dev->drv->hpc;
|
||||
hdbufferb[0] = (c >> 16) & 0xff;
|
||||
hdbufferb[1] = (c >> 8) & 0xff;
|
||||
hdbufferb[2] = c & 0xff;
|
||||
hdbufferb[3] = h & 0xff;
|
||||
hdbufferb[4] = (s >> 24) & 0xff;
|
||||
hdbufferb[5] = (s >> 16) & 0xff;
|
||||
hdbufferb[6] = (s >> 8) & 0xff;
|
||||
hdbufferb[7] = s & 0xff;
|
||||
dev->temp_buffer[0] = (c >> 16) & 0xff;
|
||||
dev->temp_buffer[1] = (c >> 8) & 0xff;
|
||||
dev->temp_buffer[2] = c & 0xff;
|
||||
dev->temp_buffer[3] = h & 0xff;
|
||||
dev->temp_buffer[4] = (s >> 24) & 0xff;
|
||||
dev->temp_buffer[5] = (s >> 16) & 0xff;
|
||||
dev->temp_buffer[6] = (s >> 8) & 0xff;
|
||||
dev->temp_buffer[7] = s & 0xff;
|
||||
}
|
||||
hdd_image_write(dev->id, i, 1, hdbufferb);
|
||||
hdd_image_write(dev->id, i, 1, dev->temp_buffer);
|
||||
}
|
||||
break;
|
||||
case GPCMD_MODE_SELECT_6:
|
||||
@@ -1134,20 +1086,20 @@ scsi_disk_phase_data_out(scsi_disk_t *dev)
|
||||
hdr_len = 4;
|
||||
|
||||
if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) {
|
||||
block_desc_len = hdbufferb[2];
|
||||
block_desc_len = dev->temp_buffer[2];
|
||||
block_desc_len <<= 8;
|
||||
block_desc_len |= hdbufferb[3];
|
||||
block_desc_len |= dev->temp_buffer[3];
|
||||
} else {
|
||||
block_desc_len = hdbufferb[6];
|
||||
block_desc_len = dev->temp_buffer[6];
|
||||
block_desc_len <<= 8;
|
||||
block_desc_len |= hdbufferb[7];
|
||||
block_desc_len |= dev->temp_buffer[7];
|
||||
}
|
||||
|
||||
pos = hdr_len + block_desc_len;
|
||||
|
||||
while(1) {
|
||||
page = hdbufferb[pos] & 0x3F;
|
||||
page_len = hdbufferb[pos + 1];
|
||||
page = dev->temp_buffer[pos] & 0x3F;
|
||||
page_len = dev->temp_buffer[pos + 1];
|
||||
|
||||
pos += 2;
|
||||
|
||||
@@ -1156,7 +1108,7 @@ scsi_disk_phase_data_out(scsi_disk_t *dev)
|
||||
else {
|
||||
for (i = 0; i < page_len; i++) {
|
||||
ch = scsi_disk_mode_sense_pages_changeable.pages[page][i + 2];
|
||||
val = hdbufferb[pos + i];
|
||||
val = dev->temp_buffer[pos + i];
|
||||
old_val = dev->ms_pages_saved.pages[page][i + 2];
|
||||
if (val != old_val) {
|
||||
if (ch)
|
||||
@@ -1177,54 +1129,48 @@ scsi_disk_phase_data_out(scsi_disk_t *dev)
|
||||
break;
|
||||
}
|
||||
|
||||
if (error)
|
||||
if (error) {
|
||||
scsi_disk_buf_free(dev);
|
||||
scsi_disk_invalid_field_pl(dev);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", dev->id, dev->current_cdb[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_STATUS);
|
||||
scsi_disk_command_stop((scsi_common_t *) dev);
|
||||
}
|
||||
|
||||
|
||||
/* If the result is 1, issue an IRQ, otherwise not. */
|
||||
static void
|
||||
scsi_disk_callback(void *p)
|
||||
scsi_disk_callback(scsi_common_t *sc)
|
||||
{
|
||||
scsi_disk_t *dev = (scsi_disk_t *) p;
|
||||
|
||||
switch(dev->packet_status) {
|
||||
switch(sc->packet_status) {
|
||||
case PHASE_IDLE:
|
||||
scsi_disk_log("SCSI HD %i: PHASE_IDLE\n", dev->id);
|
||||
dev->phase = 1;
|
||||
dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT);
|
||||
sc->phase = 1;
|
||||
sc->status = READY_STAT | DRQ_STAT | (sc->status & ERR_STAT);
|
||||
return;
|
||||
case PHASE_COMPLETE:
|
||||
scsi_disk_log("SCSI HD %i: PHASE_COMPLETE\n", dev->id);
|
||||
dev->status = READY_STAT;
|
||||
dev->phase = 3;
|
||||
dev->packet_status = 0xFF;
|
||||
sc->status = READY_STAT;
|
||||
sc->phase = 3;
|
||||
sc->packet_status = 0xFF;
|
||||
return;
|
||||
case PHASE_DATA_OUT_DMA:
|
||||
scsi_disk_log("SCSI HD %i: PHASE_DATA_OUT_DMA\n", dev->id);
|
||||
scsi_disk_phase_data_out(dev);
|
||||
dev->packet_status = PHASE_COMPLETE;
|
||||
dev->status = READY_STAT;
|
||||
dev->phase = 3;
|
||||
scsi_disk_phase_data_out(sc);
|
||||
return;
|
||||
case PHASE_DATA_IN_DMA:
|
||||
scsi_disk_log("SCSI HD %i: PHASE_DATA_IN_DMA\n", dev->id);
|
||||
scsi_disk_phase_data_in(dev);
|
||||
dev->packet_status = PHASE_COMPLETE;
|
||||
dev->status = READY_STAT;
|
||||
dev->phase = 3;
|
||||
scsi_disk_command_stop(sc);
|
||||
return;
|
||||
case PHASE_ERROR:
|
||||
scsi_disk_log("SCSI HD %i: PHASE_ERROR\n", dev->id);
|
||||
dev->status = READY_STAT | ERR_STAT;
|
||||
dev->phase = 3;
|
||||
sc->status = READY_STAT | ERR_STAT;
|
||||
sc->phase = 3;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1263,13 +1209,12 @@ scsi_disk_hard_reset(void)
|
||||
/* SCSI disk, attach to the SCSI bus. */
|
||||
sd = &scsi_devices[hdd[c].scsi_id];
|
||||
|
||||
sd->p = dev;
|
||||
sd->sc = (scsi_common_t *) dev;
|
||||
sd->command = scsi_disk_command;
|
||||
sd->callback = scsi_disk_callback;
|
||||
sd->err_stat_to_scsi = scsi_disk_err_stat_to_scsi;
|
||||
sd->request_sense = scsi_disk_request_sense_for_scsi;
|
||||
sd->reset = scsi_disk_reset;
|
||||
sd->read_capacity = scsi_disk_read_capacity;
|
||||
sd->command_stop = scsi_disk_command_stop;
|
||||
sd->type = SCSI_FIXED_DISK;
|
||||
|
||||
dev->id = c;
|
||||
@@ -1290,13 +1235,15 @@ scsi_disk_close(void)
|
||||
int c;
|
||||
|
||||
for (c = 0; c < HDD_NUM; c++) {
|
||||
dev = hdd[c].priv;
|
||||
|
||||
if (dev) {
|
||||
if (hdd[c].bus == HDD_BUS_SCSI) {
|
||||
hdd_image_close(c);
|
||||
|
||||
free(dev);
|
||||
hdd[c].priv = NULL;
|
||||
dev = hdd[c].priv;
|
||||
|
||||
if (dev) {
|
||||
free(dev);
|
||||
hdd[c].priv = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@ typedef struct {
|
||||
|
||||
int requested_blocks, packet_status,
|
||||
total_length, do_page_save,
|
||||
unit_attention;
|
||||
unit_attention, pad5,
|
||||
pad6, pad7;
|
||||
|
||||
uint32_t sector_pos, sector_len,
|
||||
packet_len, pos;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Implementation of the NCR 5380 series of SCSI Host Adapters
|
||||
* made by NCR. These controllers were designed for the ISA bus.
|
||||
*
|
||||
* Version: @(#)scsi_ncr5380.c 1.0.23 2018/10/18
|
||||
* Version: @(#)scsi_ncr5380.c 1.0.24 2018/10/28
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* TheCollector1995, <mariogplayer@gmail.com>
|
||||
@@ -286,7 +286,7 @@ ncr_wait_process(ncr5380_t *ncr_dev)
|
||||
|
||||
if (ncr->new_phase == SCSI_PHASE_DATA_IN) {
|
||||
ncr_log("Data In bus phase\n");
|
||||
ncr->tx_data = dev->cmd_buffer[ncr->data_pos++];
|
||||
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
|
||||
ncr->state = STATE_DATAIN;
|
||||
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP;
|
||||
} else if (ncr->new_phase == SCSI_PHASE_STATUS) {
|
||||
@@ -963,8 +963,6 @@ ncr_callback(void *priv)
|
||||
|
||||
/*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/
|
||||
if (dev->buffer_length && (dev->phase == SCSI_PHASE_DATA_IN || dev->phase == SCSI_PHASE_DATA_OUT)) {
|
||||
dev->cmd_buffer = (uint8_t *) malloc(dev->buffer_length);
|
||||
|
||||
p = scsi_device_get_callback(dev);
|
||||
req_len = MIN(64, dev->buffer_length);
|
||||
if (p <= 0LL)
|
||||
@@ -982,10 +980,6 @@ ncr_callback(void *priv)
|
||||
} else {
|
||||
/* Other command - execute immediately. */
|
||||
ncr->new_phase = dev->phase;
|
||||
|
||||
if (ncr->new_phase == SCSI_PHASE_DATA_IN)
|
||||
scsi_device_command_phase1(dev);
|
||||
|
||||
ncr->wait_data = 4;
|
||||
}
|
||||
}
|
||||
@@ -995,17 +989,13 @@ ncr_callback(void *priv)
|
||||
ncr_log("Data In ACK=%02x\n", ncr->bus_host & BUS_ACK);
|
||||
if (ncr->bus_host & BUS_ACK) {
|
||||
if (ncr->data_pos >= dev->buffer_length) {
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
scsi_device_command_phase1(dev);
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
ncr->new_phase = SCSI_PHASE_STATUS;
|
||||
ncr->wait_data = 4;
|
||||
ncr->wait_complete = 8;
|
||||
} else {
|
||||
ncr->tx_data = dev->cmd_buffer[ncr->data_pos++];
|
||||
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
|
||||
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ;
|
||||
ncr->clear_req = 3;
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
@@ -1017,16 +1007,10 @@ ncr_callback(void *priv)
|
||||
|
||||
ncr_log("Data Out ACK=%02x\n", ncr->bus_host & BUS_ACK);
|
||||
if (ncr->bus_host & BUS_ACK) {
|
||||
dev->cmd_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
|
||||
dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
|
||||
|
||||
if (ncr->data_pos >= dev->buffer_length) {
|
||||
scsi_device_command_phase1(dev);
|
||||
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
ncr_log("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus);
|
||||
ncr->new_phase = SCSI_PHASE_STATUS;
|
||||
@@ -1076,17 +1060,13 @@ ncr_callback(void *priv)
|
||||
ncr->bus_host = get_bus_host(ncr);
|
||||
|
||||
if (ncr->data_pos >= dev->buffer_length) {
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
scsi_device_command_phase1(dev);
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
ncr->new_phase = SCSI_PHASE_STATUS;
|
||||
ncr->wait_data = 4;
|
||||
ncr->wait_complete = 8;
|
||||
} else {
|
||||
ncr->tx_data = dev->cmd_buffer[ncr->data_pos++];
|
||||
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
|
||||
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ;
|
||||
ncr->clear_req = 3;
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
@@ -1141,16 +1121,10 @@ ncr_callback(void *priv)
|
||||
ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK;
|
||||
ncr->bus_host |= BUS_SETDATA(data);
|
||||
|
||||
dev->cmd_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
|
||||
dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
|
||||
|
||||
if (ncr->data_pos >= dev->buffer_length) {
|
||||
scsi_device_command_phase1(dev);
|
||||
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
ncr_log("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus);
|
||||
ncr->new_phase = SCSI_PHASE_STATUS;
|
||||
@@ -1199,17 +1173,13 @@ ncr_callback(void *priv)
|
||||
ncr->bus_host = get_bus_host(ncr);
|
||||
|
||||
if (ncr->data_pos >= dev->buffer_length) {
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
scsi_device_command_phase1(dev);
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
ncr->new_phase = SCSI_PHASE_STATUS;
|
||||
ncr->wait_data = 4;
|
||||
ncr->wait_complete = 8;
|
||||
} else {
|
||||
ncr->tx_data = dev->cmd_buffer[ncr->data_pos++];
|
||||
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
|
||||
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ;
|
||||
ncr->clear_req = 3;
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
@@ -1250,16 +1220,10 @@ ncr_callback(void *priv)
|
||||
ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK;
|
||||
ncr->bus_host |= BUS_SETDATA(data);
|
||||
|
||||
dev->cmd_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
|
||||
dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
|
||||
|
||||
if (ncr->data_pos >= dev->buffer_length) {
|
||||
scsi_device_command_phase1(dev);
|
||||
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
ncr_log("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus);
|
||||
ncr->new_phase = SCSI_PHASE_STATUS;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,11 +6,11 @@
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the NCR 53C810 SCSI Host Adapter made by
|
||||
* NCR and later Symbios and LSI. This controller was designed
|
||||
* for the PCI bus.
|
||||
* Implementation of the NCR 53C810 and 53C875 SCSI Host
|
||||
* Adapters made by NCR and later Symbios and LSI. These
|
||||
* controllers were designed for the PCI bus.
|
||||
*
|
||||
* Version: @(#)scsi_ncr53c810.c 1.0.1 2018/03/18
|
||||
* Version: @(#)scsi_ncr53c8xx.c 1.0.2 2018/10/30
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -21,11 +21,13 @@
|
||||
* Copyright 2009-2018 Artyom Tarasenko.
|
||||
* Copyright 2017,2018 Miran Grca.
|
||||
*/
|
||||
#ifndef SCSI_NCR5C3810_H
|
||||
# define SCSI_NCR53C810_H
|
||||
#ifndef SCSI_NCR5C38XX_H
|
||||
# define SCSI_NCR53C8XX_H
|
||||
|
||||
|
||||
extern const device_t ncr53c810_pci_device;
|
||||
extern const device_t ncr53c825a_pci_device;
|
||||
extern const device_t ncr53c875_pci_device;
|
||||
|
||||
|
||||
#endif /*SCSI_NCR53C810_H*/
|
||||
#endif /*SCSI_NCR53C8XX_H*/
|
||||
@@ -11,7 +11,7 @@
|
||||
* series of SCSI Host Adapters made by Mylex.
|
||||
* These controllers were designed for various buses.
|
||||
*
|
||||
* Version: @(#)scsi_x54x.c 1.0.25 2018/10/18
|
||||
* Version: @(#)scsi_x54x.c 1.0.26 2018/10/28
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -261,34 +261,23 @@ x54x_bios_scsi_command(scsi_device_t *dev, uint8_t *cdb, uint8_t *buf, int len,
|
||||
if (dev->phase == SCSI_PHASE_STATUS)
|
||||
return(completion_code(scsi_device_sense(dev)));
|
||||
|
||||
dev->cmd_buffer = (uint8_t *)malloc(dev->buffer_length);
|
||||
|
||||
if (dev->phase == SCSI_PHASE_DATA_IN) {
|
||||
scsi_device_command_phase1(dev);
|
||||
|
||||
if (len > 0) {
|
||||
if (len > 0) {
|
||||
if (dev->phase == SCSI_PHASE_DATA_IN) {
|
||||
if (buf)
|
||||
memcpy(buf, dev->cmd_buffer, dev->buffer_length);
|
||||
memcpy(buf, dev->sc->temp_buffer, dev->buffer_length);
|
||||
else
|
||||
DMAPageWrite(addr, dev->cmd_buffer, dev->buffer_length);
|
||||
}
|
||||
} else if (dev->phase == SCSI_PHASE_DATA_OUT) {
|
||||
if (len > 0) {
|
||||
DMAPageWrite(addr, dev->sc->temp_buffer, dev->buffer_length);
|
||||
} else if (dev->phase == SCSI_PHASE_DATA_OUT) {
|
||||
if (buf)
|
||||
memcpy(dev->cmd_buffer, buf, dev->buffer_length);
|
||||
memcpy(dev->sc->temp_buffer, buf, dev->buffer_length);
|
||||
else
|
||||
DMAPageRead(addr, dev->cmd_buffer, dev->buffer_length);
|
||||
DMAPageRead(addr, dev->sc->temp_buffer, dev->buffer_length);
|
||||
}
|
||||
|
||||
scsi_device_command_phase1(dev);
|
||||
}
|
||||
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
scsi_device_command_phase1(dev);
|
||||
|
||||
return(completion_code(scsi_device_sense(dev)));
|
||||
return (completion_code(scsi_device_sense(dev)));
|
||||
}
|
||||
|
||||
|
||||
@@ -439,11 +428,6 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
|
||||
dev = &scsi_devices[cmd->id];
|
||||
dev->buffer_length = 0;
|
||||
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
if (! scsi_device_present(dev)) {
|
||||
x54x_log("BIOS Target ID %i has no device attached\n", cmd->id);
|
||||
ret = 0x80;
|
||||
@@ -473,10 +457,6 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
|
||||
* length for SCSI sense, and no command-specific
|
||||
* indication is given.
|
||||
*/
|
||||
dev->buffer_length = 14;
|
||||
dev->cmd_buffer = (uint8_t *)malloc(14);
|
||||
memset(dev->cmd_buffer, 0x00, 14);
|
||||
|
||||
if (sector_len > 0) {
|
||||
x54x_log("BIOS DMA: Reading 14 bytes at %08X\n",
|
||||
dma_address);
|
||||
@@ -484,11 +464,6 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
|
||||
scsi_device_sense(dev), 14);
|
||||
}
|
||||
|
||||
if (dev && (dev->cmd_buffer != NULL)) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
return(0);
|
||||
break;
|
||||
|
||||
@@ -506,9 +481,6 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
|
||||
cdb[5] = lba & 0xff;
|
||||
if (cmd->command != 0x0c)
|
||||
cdb[8] = sector_len;
|
||||
#if 0
|
||||
x54x_log("BIOS CMD(READ/WRITE/VERIFY, %08lx, %d)\n", lba, cmd->secount);
|
||||
#endif
|
||||
|
||||
ret = x54x_bios_scsi_command(dev, cdb, NULL, sector_len, dma_address);
|
||||
if (cmd->command == 0x0c)
|
||||
@@ -552,8 +524,6 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
|
||||
target_check(cmd->id);
|
||||
|
||||
dev->buffer_length = 6;
|
||||
dev->cmd_buffer = (uint8_t *)malloc(dev->buffer_length);
|
||||
memset(dev->cmd_buffer, 0x00, dev->buffer_length);
|
||||
|
||||
buf = (uint8_t *) malloc(6);
|
||||
if (cmd->command == 0x08)
|
||||
@@ -565,11 +535,6 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
|
||||
DMAPageWrite(dma_address, buf, 4);
|
||||
free(buf);
|
||||
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -831,11 +796,11 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir)
|
||||
|
||||
if (read_from_host && DataToTransfer) {
|
||||
x54x_log("Reading S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address);
|
||||
DMAPageRead(Address, &(scsi_devices[req->TargetID].cmd_buffer[sg_pos]), DataToTransfer);
|
||||
DMAPageRead(Address, &(scsi_devices[req->TargetID].sc->temp_buffer[sg_pos]), DataToTransfer);
|
||||
}
|
||||
else if (write_to_host && DataToTransfer) {
|
||||
x54x_log("Writing S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address);
|
||||
DMAPageWrite(Address, &(scsi_devices[req->TargetID].cmd_buffer[sg_pos]), DataToTransfer);
|
||||
DMAPageWrite(Address, &(scsi_devices[req->TargetID].sc->temp_buffer[sg_pos]), DataToTransfer);
|
||||
}
|
||||
else
|
||||
x54x_log("No action on S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address);
|
||||
@@ -855,39 +820,15 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir)
|
||||
|
||||
if ((DataLength > 0) && (BufLen > 0) && (req->CmdBlock.common.ControlByte < 0x03)) {
|
||||
if (read_from_host)
|
||||
DMAPageRead(Address, scsi_devices[req->TargetID].cmd_buffer, MIN(BufLen, (int) DataLength));
|
||||
DMAPageRead(Address, scsi_devices[req->TargetID].sc->temp_buffer, MIN(BufLen, (int) DataLength));
|
||||
else if (write_to_host)
|
||||
DMAPageWrite(Address, scsi_devices[req->TargetID].cmd_buffer, MIN(BufLen, (int) DataLength));
|
||||
DMAPageWrite(Address, scsi_devices[req->TargetID].sc->temp_buffer, MIN(BufLen, (int) DataLength));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x54x_buf_alloc(uint8_t id, int length)
|
||||
{
|
||||
if (scsi_devices[id].cmd_buffer != NULL) {
|
||||
free(scsi_devices[id].cmd_buffer);
|
||||
scsi_devices[id].cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
x54x_log("Allocating data buffer (%i bytes)\n", length);
|
||||
scsi_devices[id].cmd_buffer = (uint8_t *) malloc(length);
|
||||
memset(scsi_devices[id].cmd_buffer, 0, length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x54x_buf_free(uint8_t id)
|
||||
{
|
||||
if (scsi_devices[id].cmd_buffer != NULL) {
|
||||
free(scsi_devices[id].cmd_buffer);
|
||||
scsi_devices[id].cmd_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
ConvertSenseLength(uint8_t RequestSenseLength)
|
||||
{
|
||||
@@ -959,7 +900,6 @@ x54x_scsi_cmd(x54x_t *dev)
|
||||
uint8_t temp_cdb[12];
|
||||
uint32_t i, SenseBufferAddress;
|
||||
int target_data_len, target_cdb_len = 12;
|
||||
int32_t *BufLen;
|
||||
int64_t p;
|
||||
scsi_device_t *sd;
|
||||
|
||||
@@ -995,10 +935,7 @@ x54x_scsi_cmd(x54x_t *dev)
|
||||
|
||||
dev->Residue = 0;
|
||||
|
||||
BufLen = scsi_device_get_buf_len(sd);
|
||||
*BufLen = target_data_len;
|
||||
|
||||
x54x_log("Command buffer: %08X\n", scsi_devices[id].cmd_buffer);
|
||||
sd->buffer_length = target_data_len;
|
||||
|
||||
scsi_device_command_phase0(sd, temp_cdb);
|
||||
|
||||
@@ -1009,26 +946,21 @@ x54x_scsi_cmd(x54x_t *dev)
|
||||
if (phase != SCSI_PHASE_STATUS) {
|
||||
if ((temp_cdb[0] == 0x03) && (req->CmdBlock.common.ControlByte == 0x03)) {
|
||||
/* Request sense in non-data mode - sense goes to sense buffer. */
|
||||
*BufLen = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength);
|
||||
x54x_buf_alloc(id, *BufLen);
|
||||
scsi_device_command_phase1(sd);
|
||||
if ((sd->status != SCSI_STATUS_OK) && (*BufLen > 0)) {
|
||||
sd->buffer_length = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength);
|
||||
if ((sd->status != SCSI_STATUS_OK) && (sd->buffer_length > 0)) {
|
||||
SenseBufferAddress = SenseBufferPointer(req);
|
||||
DMAPageWrite(SenseBufferAddress, scsi_devices[id].cmd_buffer, *BufLen);
|
||||
x54x_add_to_period(*BufLen);
|
||||
DMAPageWrite(SenseBufferAddress, scsi_devices[id].sc->temp_buffer, sd->buffer_length);
|
||||
x54x_add_to_period(sd->buffer_length);
|
||||
}
|
||||
scsi_device_command_phase1(sd);
|
||||
} else {
|
||||
p = scsi_device_get_callback(sd);
|
||||
if (p <= 0LL)
|
||||
x54x_add_to_period(*BufLen);
|
||||
x54x_add_to_period(sd->buffer_length);
|
||||
else
|
||||
dev->media_period += p;
|
||||
x54x_buf_alloc(id, MIN(target_data_len, *BufLen));
|
||||
if (phase == SCSI_PHASE_DATA_OUT)
|
||||
x54x_buf_dma_transfer(req, bit24, target_data_len, 1);
|
||||
x54x_buf_dma_transfer(req, bit24, target_data_len, (phase == SCSI_PHASE_DATA_OUT));
|
||||
scsi_device_command_phase1(sd);
|
||||
if (phase == SCSI_PHASE_DATA_IN)
|
||||
x54x_buf_dma_transfer(req, bit24, target_data_len, 0);
|
||||
|
||||
SenseBufferFree(req, (sd->status != SCSI_STATUS_OK));
|
||||
}
|
||||
@@ -1037,8 +969,6 @@ x54x_scsi_cmd(x54x_t *dev)
|
||||
|
||||
x54x_set_residue(req, target_data_len);
|
||||
|
||||
x54x_buf_free(id);
|
||||
|
||||
x54x_log("Request complete\n");
|
||||
|
||||
if (sd->status == SCSI_STATUS_OK) {
|
||||
@@ -1378,9 +1308,6 @@ x54x_in(uint16_t port, void *priv)
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
x54x_log("%s: Read Port 0x%02X, Value %02X\n", dev->name, port, ret);
|
||||
#endif
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* of SCSI Host Adapters made by Mylex.
|
||||
* These controllers were designed for various buses.
|
||||
*
|
||||
* Version: @(#)scsi_x54x.h 1.0.9 2018/10/21
|
||||
* Version: @(#)scsi_x54x.h 1.0.10 2018/10/28
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -500,8 +500,6 @@ typedef struct {
|
||||
|
||||
|
||||
extern void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset);
|
||||
extern void x54x_buf_alloc(uint8_t id, int length);
|
||||
extern void x54x_buf_free(uint8_t id);
|
||||
extern uint8_t x54x_mbo_process(x54x_t *dev);
|
||||
extern void x54x_wait_for_poll(void);
|
||||
extern void x54x_io_set(x54x_t *dev, uint32_t base, uint8_t len);
|
||||
|
||||
Reference in New Issue
Block a user