Refactored AHA-154x and BusLogic emulation and made them use a common core;
Fixed AHA-154x scatter/gather transfers; Two-phased SCSI read-direction commands; Made scsi_bus.c use a dynamically malloc'd buffer instead of a giant fixed-size buffer; The AHA-154x/BusLogic thread now uses mutexes; The BusLogic BT-545C is now the BT-545S; Added the BusLogic BT-542BH; The AHA-1542CF now again uses the v2.11 BIOS as the CD booting now works; Applied PCem commit that adds NMI support to the recompiler; Applied PCem commit that adds the IBM XT 286; Applied PCem commits that have to do with sound, including the ES1371; Fixed the NCR5380 output data register; Moved the SLiRP mutex stuff from win.c to the appropriate network files; Added sanity checks to everything in win_thread.c.
This commit is contained in:
@@ -23,14 +23,18 @@
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../ibm.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "../cdrom/cdrom.h"
|
||||
#include "../disk/hdc.h"
|
||||
#include "../plat.h"
|
||||
#include "scsi.h"
|
||||
#include "scsi_aha154x.h"
|
||||
#include "scsi_buslogic.h"
|
||||
#include "scsi_ncr5380.h"
|
||||
#include "scsi_x54x.h"
|
||||
|
||||
|
||||
scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX];
|
||||
@@ -44,6 +48,7 @@ int scsi_card_current = 0;
|
||||
int scsi_card_last = 0;
|
||||
|
||||
uint32_t SCSI_BufferLength;
|
||||
void *scsiMutex;
|
||||
|
||||
|
||||
typedef struct {
|
||||
@@ -56,14 +61,15 @@ typedef struct {
|
||||
|
||||
static SCSI_CARD scsi_cards[] = {
|
||||
{ "None", "none", NULL, NULL },
|
||||
{ "[ISA] Adaptec AHA-1540B","aha1540b", &aha1540b_device, aha_device_reset },
|
||||
{ "[ISA] Adaptec AHA-1542C","aha1542c", &aha1542c_device, aha_device_reset },
|
||||
{ "[ISA] Adaptec AHA-1542CF","aha1542cf", &aha1542cf_device, aha_device_reset },
|
||||
{ "[ISA] BusLogic BT-545C", "bt545c", &buslogic_device, BuslogicDeviceReset },
|
||||
{ "[ISA] Adaptec AHA-1540B","aha1540b", &aha1540b_device, x54x_device_reset },
|
||||
{ "[ISA] Adaptec AHA-1542C","aha1542c", &aha1542c_device, x54x_device_reset },
|
||||
{ "[ISA] Adaptec AHA-1542CF","aha1542cf", &aha1542cf_device, x54x_device_reset },
|
||||
{ "[ISA] BusLogic BT-542BH","bt542bh", &buslogic_device, BuslogicDeviceReset },
|
||||
{ "[ISA] BusLogic BT-545S", "bt545s", &buslogic_545s_device,BuslogicDeviceReset },
|
||||
{ "[ISA] Longshine LCS-6821N","lcs6821n", &scsi_lcs6821n_device,NULL },
|
||||
{ "[ISA] Ranco RT1000B", "rt1000b", &scsi_rt1000b_device, NULL },
|
||||
{ "[ISA] Trantor T130B", "t130b", &scsi_t130b_device, NULL },
|
||||
{ "[MCA] Adaptec AHA-1640", "aha1640", &aha1640_device, aha_device_reset },
|
||||
{ "[MCA] Adaptec AHA-1640", "aha1640", &aha1640_device, x54x_device_reset },
|
||||
{ "[PCI] BusLogic BT-958D", "bt958d", &buslogic_pci_device, BuslogicDeviceReset },
|
||||
{ "", "", NULL, NULL },
|
||||
};
|
||||
@@ -118,6 +124,12 @@ int scsi_card_get_from_internal_name(char *s)
|
||||
}
|
||||
|
||||
|
||||
void scsi_mutex_init(void)
|
||||
{
|
||||
scsiMutex = thread_create_mutex(L"86Box.SCSIMutex");
|
||||
}
|
||||
|
||||
|
||||
void scsi_card_init(void)
|
||||
{
|
||||
int i, j;
|
||||
@@ -136,6 +148,7 @@ void scsi_card_init(void)
|
||||
} else {
|
||||
SCSIDevices[i][j].LunType = SCSI_NONE;
|
||||
}
|
||||
SCSIDevices[i][j].CmdBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,3 +197,17 @@ void SCSIReset(uint8_t id, uint8_t lun)
|
||||
SCSIDevices[id][lun].CmdBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
startscsi(void)
|
||||
{
|
||||
thread_wait_mutex(scsiMutex);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
endscsi(void)
|
||||
{
|
||||
thread_release_mutex(scsiMutex);
|
||||
}
|
||||
|
||||
@@ -259,11 +259,10 @@ extern int prev_status;
|
||||
#define SCSI_PHASE_MESSAGE_OUT (BUS_MSG | BUS_CD)
|
||||
#define SCSI_PHASE_MESSAGE_IN (BUS_MSG | BUS_CD | BUS_IO)
|
||||
|
||||
extern uint32_t SCSI_BufferLength;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *CmdBuffer;
|
||||
int LunType;
|
||||
int32_t BufferLength;
|
||||
} scsi_device_t;
|
||||
|
||||
|
||||
@@ -294,7 +293,8 @@ extern device_t *scsi_card_getdevice(int card);
|
||||
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_card_init();
|
||||
extern void scsi_mutex_init(void);
|
||||
extern void scsi_card_init(void);
|
||||
extern void scsi_card_reset(void);
|
||||
|
||||
extern uint8_t scsi_hard_disks[16][8];
|
||||
@@ -351,3 +351,6 @@ typedef struct {
|
||||
#define MODE_SELECT_PHASE_PAGE 4
|
||||
|
||||
#endif /*EMU_SCSI_H*/
|
||||
|
||||
extern void startscsi(void);
|
||||
extern void endscsi(void);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,457 +0,0 @@
|
||||
/*
|
||||
* 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 shared AHA and Buslogic SCSI BIOS command handler.
|
||||
*
|
||||
* Version: @(#)scsi_bios_command.c 1.0.4 2017/10/07
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Copyright 2017 Miran Grca.
|
||||
* Copyright 2017 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <wchar.h>
|
||||
#include "../ibm.h"
|
||||
#include "../dma.h"
|
||||
#include "../device.h"
|
||||
#include "scsi.h"
|
||||
#include "scsi_bios_command.h"
|
||||
#include "scsi_device.h"
|
||||
|
||||
|
||||
#if ENABLE_SCSI_BIOS_COMMAND_LOG
|
||||
int scsi_bios_command_do_log = ENABLE_SCSI_BIOS_COMMAND_LOG;
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
cmd_log(const char *fmt, ...)
|
||||
{
|
||||
#if ENABLE_SCSI_BIOS_COMMAND_LOG
|
||||
va_list ap;
|
||||
|
||||
if (scsi_bios_command_do_log) {
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
target_check(uint8_t id, uint8_t lun)
|
||||
{
|
||||
if (! scsi_device_valid(id, lun)) {
|
||||
fatal("BIOS INT13 device on %02i:%02i has disappeared\n", id, lun);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
completion_code(uint8_t *sense)
|
||||
{
|
||||
switch (sense[12]) {
|
||||
case 0x00:
|
||||
return(0x00);
|
||||
|
||||
case 0x20:
|
||||
return(0x01);
|
||||
|
||||
case 0x12:
|
||||
case 0x21:
|
||||
return(0x02);
|
||||
|
||||
case 0x27:
|
||||
return(0x03);
|
||||
|
||||
case 0x14:
|
||||
case 0x16:
|
||||
return(0x04);
|
||||
|
||||
case 0x10:
|
||||
case 0x11:
|
||||
return(0x10);
|
||||
|
||||
case 0x17:
|
||||
case 0x18:
|
||||
return(0x11);
|
||||
|
||||
case 0x01:
|
||||
case 0x03:
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x1B:
|
||||
case 0x1C:
|
||||
case 0x1D:
|
||||
case 0x40:
|
||||
case 0x41:
|
||||
case 0x42:
|
||||
case 0x43:
|
||||
case 0x44:
|
||||
case 0x45:
|
||||
case 0x46:
|
||||
case 0x47:
|
||||
case 0x48:
|
||||
case 0x49:
|
||||
return(0x20);
|
||||
|
||||
case 0x15:
|
||||
case 0x02:
|
||||
return(0x40);
|
||||
|
||||
case 0x04:
|
||||
case 0x28:
|
||||
case 0x29:
|
||||
case 0x2a:
|
||||
return(0xaa);
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return(0xff);
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
scsi_bios_command_08(uint8_t id, uint8_t lun, uint8_t *buffer)
|
||||
{
|
||||
uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0,0,0,0,0,0,0,0,0,0,0 };
|
||||
uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 };
|
||||
uint32_t len = 0;
|
||||
int i, ret, sc;
|
||||
|
||||
ret = scsi_device_read_capacity(id, lun, cdb, rcbuf, &len);
|
||||
sc = completion_code(scsi_device_sense(id, lun));
|
||||
if (ret == 0) return(sc);
|
||||
|
||||
memset(buffer, 0x00, 6);
|
||||
for (i=0; i<4; i++)
|
||||
buffer[i] = rcbuf[i];
|
||||
for (i=4; i<6; i++)
|
||||
buffer[i] = rcbuf[(i + 2) ^ 1];
|
||||
cmd_log("BIOS Command 0x08: %02X %02X %02X %02X %02X %02X\n",
|
||||
buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
scsi_bios_command_15(uint8_t id, uint8_t lun, uint8_t *buffer)
|
||||
{
|
||||
uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0,0,0,0,0,0,0,0,0,0,0 };
|
||||
uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 };
|
||||
uint32_t len = 0;
|
||||
int i, ret, sc;
|
||||
|
||||
ret = scsi_device_read_capacity(id, lun, cdb, rcbuf, &len);
|
||||
sc = completion_code(scsi_device_sense(id, lun));
|
||||
|
||||
memset(buffer, 0x00, 6);
|
||||
for (i=0; i<4; i++)
|
||||
buffer[i] = (ret == 0) ? 0 : rcbuf[i];
|
||||
|
||||
scsi_device_type_data(id, lun, &(buffer[4]), &(buffer[5]));
|
||||
|
||||
cmd_log("BIOS Command 0x15: %02X %02X %02X %02X %02X %02X\n",
|
||||
buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
|
||||
|
||||
return(sc);
|
||||
}
|
||||
|
||||
|
||||
/* This returns the completion code. */
|
||||
uint8_t
|
||||
scsi_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba)
|
||||
{
|
||||
uint8_t cdb[12] = { 0,0,0,0,0,0,0,0,0,0,0,0 };
|
||||
scsi_device_t *dev;
|
||||
uint32_t dma_address;
|
||||
uint32_t lba;
|
||||
int sector_len = cmd->secount;
|
||||
int block_shift;
|
||||
uint8_t ret;
|
||||
|
||||
if (islba)
|
||||
lba = lba32_blk(cmd);
|
||||
else
|
||||
lba = (cmd->u.chs.cyl << 9) + (cmd->u.chs.head << 5) + cmd->u.chs.sec;
|
||||
|
||||
cmd_log("BIOS Command = 0x%02X\n", cmd->command);
|
||||
|
||||
if ((cmd->id > max_id) || (cmd->lun > 7)) return(0x80);
|
||||
|
||||
/* Get pointer to selected device. */
|
||||
dev = &SCSIDevices[cmd->id][cmd->lun];
|
||||
SCSI_BufferLength = 0;
|
||||
|
||||
if (! scsi_device_present(cmd->id, cmd->lun)) {
|
||||
cmd_log("BIOS Target ID %i and LUN %i have no device attached\n",
|
||||
cmd->id, cmd->lun);
|
||||
return(0x80);
|
||||
}
|
||||
|
||||
dma_address = ADDR_TO_U32(cmd->dma_address);
|
||||
|
||||
cmd_log("BIOS Data Buffer write: length %d, pointer 0x%04X\n",
|
||||
sector_len, dma_address);
|
||||
|
||||
if (dev->CmdBuffer != NULL) {
|
||||
free(dev->CmdBuffer);
|
||||
dev->CmdBuffer = NULL;
|
||||
}
|
||||
|
||||
block_shift = scsi_device_block_shift(cmd->id, cmd->lun);
|
||||
|
||||
switch(cmd->command) {
|
||||
case 0x00: /* Reset Disk System, in practice it's a nop */
|
||||
return(0);
|
||||
|
||||
case 0x01: /* Read Status of Last Operation */
|
||||
target_check(cmd->id, cmd->lun);
|
||||
|
||||
/*
|
||||
* Assuming 14 bytes because that is the default
|
||||
* length for SCSI sense, and no command-specific
|
||||
* indication is given.
|
||||
*/
|
||||
SCSI_BufferLength = 14;
|
||||
dev->CmdBuffer = (uint8_t *)malloc(14);
|
||||
memset(dev->CmdBuffer, 0x00, 14);
|
||||
|
||||
#if 0
|
||||
SCSIStatus = scsi_bios_command_08(cmd->id, cmd->lun, dev->CmdBuffer) ? SCSI_STATUS_OK : SCSI_STATUS_CHECK_CONDITION;
|
||||
#endif
|
||||
|
||||
if (sector_len > 0) {
|
||||
cmd_log("BIOS DMA: Reading 14 bytes at %08X\n",
|
||||
dma_address);
|
||||
DMAPageWrite(dma_address,
|
||||
(char *)scsi_device_sense(cmd->id, cmd->lun), 14);
|
||||
}
|
||||
|
||||
if (dev->CmdBuffer != NULL) {
|
||||
free(dev->CmdBuffer);
|
||||
dev->CmdBuffer = NULL;
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
||||
case 0x02: /* Read Desired Sectors to Memory */
|
||||
target_check(cmd->id, cmd->lun);
|
||||
|
||||
SCSI_BufferLength = sector_len << block_shift;
|
||||
dev->CmdBuffer = (uint8_t *)malloc(SCSI_BufferLength);
|
||||
memset(dev->CmdBuffer, 0x00, SCSI_BufferLength);
|
||||
|
||||
cdb[0] = GPCMD_READ_10;
|
||||
cdb[1] = (cmd->lun & 7) << 5;
|
||||
cdb[2] = (lba >> 24) & 0xff;
|
||||
cdb[3] = (lba >> 16) & 0xff;
|
||||
cdb[4] = (lba >> 8) & 0xff;
|
||||
cdb[5] = lba & 0xff;
|
||||
cdb[7] = (sector_len >> 8) & 0xff;
|
||||
cdb[8] = sector_len & 0xff;
|
||||
#if 0
|
||||
cmd_log("BIOS CMD(READ, %08lx, %d)\n", lba, cmd->secount);
|
||||
#endif
|
||||
|
||||
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
|
||||
if (sector_len > 0) {
|
||||
cmd_log("BIOS DMA: Reading %i bytes at %08X\n",
|
||||
SCSI_BufferLength, dma_address);
|
||||
DMAPageWrite(dma_address,
|
||||
(char *)dev->CmdBuffer, SCSI_BufferLength);
|
||||
}
|
||||
|
||||
if (dev->CmdBuffer != NULL) {
|
||||
free(dev->CmdBuffer);
|
||||
dev->CmdBuffer = NULL;
|
||||
}
|
||||
|
||||
return(completion_code(scsi_device_sense(cmd->id, cmd->lun)));
|
||||
|
||||
case 0x03: /* Write Desired Sectors from Memory */
|
||||
target_check(cmd->id, cmd->lun);
|
||||
|
||||
SCSI_BufferLength = sector_len << block_shift;
|
||||
dev->CmdBuffer = (uint8_t *)malloc(SCSI_BufferLength);
|
||||
memset(dev->CmdBuffer, 0x00, SCSI_BufferLength);
|
||||
|
||||
cdb[0] = GPCMD_WRITE_10;
|
||||
cdb[1] = (cmd->lun & 7) << 5;
|
||||
cdb[2] = (lba >> 24) & 0xff;
|
||||
cdb[3] = (lba >> 16) & 0xff;
|
||||
cdb[4] = (lba >> 8) & 0xff;
|
||||
cdb[5] = lba & 0xff;
|
||||
cdb[7] = (sector_len >> 8) & 0xff;
|
||||
cdb[8] = sector_len & 0xff;
|
||||
#if 0
|
||||
cmd_log("BIOS CMD(WRITE, %08lx, %d)\n", lba, cmd->secount);
|
||||
#endif
|
||||
|
||||
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
|
||||
|
||||
if (sector_len > 0) {
|
||||
cmd_log("BIOS DMA: Reading %i bytes at %08X\n",
|
||||
SCSI_BufferLength, dma_address);
|
||||
DMAPageRead(dma_address,
|
||||
(char *)dev->CmdBuffer, SCSI_BufferLength);
|
||||
}
|
||||
|
||||
scsi_device_command_phase1(cmd->id, cmd->lun);
|
||||
|
||||
if (dev->CmdBuffer != NULL) {
|
||||
free(dev->CmdBuffer);
|
||||
dev->CmdBuffer = NULL;
|
||||
}
|
||||
|
||||
return(completion_code(scsi_device_sense(cmd->id, cmd->lun)));
|
||||
|
||||
case 0x04: /* Verify Desired Sectors */
|
||||
target_check(cmd->id, cmd->lun);
|
||||
|
||||
cdb[0] = GPCMD_VERIFY_10;
|
||||
cdb[1] = (cmd->lun & 7) << 5;
|
||||
cdb[2] = (lba >> 24) & 0xff;
|
||||
cdb[3] = (lba >> 16) & 0xff;
|
||||
cdb[4] = (lba >> 8) & 0xff;
|
||||
cdb[5] = lba & 0xff;
|
||||
cdb[7] = (sector_len >> 8) & 0xff;
|
||||
cdb[8] = sector_len & 0xff;
|
||||
|
||||
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
|
||||
|
||||
return(completion_code(scsi_device_sense(cmd->id, cmd->lun)));
|
||||
|
||||
case 0x05: /* Format Track, invalid since SCSI has no tracks */
|
||||
//FIXME: add a longer delay here --FvK
|
||||
return(1);
|
||||
|
||||
case 0x06: /* Identify SCSI Devices, in practice it's a nop */
|
||||
//FIXME: add a longer delay here --FvK
|
||||
return(0);
|
||||
|
||||
case 0x07: /* Format Unit */
|
||||
target_check(cmd->id, cmd->lun);
|
||||
|
||||
cdb[0] = GPCMD_FORMAT_UNIT;
|
||||
cdb[1] = (cmd->lun & 7) << 5;
|
||||
|
||||
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
|
||||
|
||||
return(completion_code(scsi_device_sense(cmd->id, cmd->lun)));
|
||||
|
||||
case 0x08: /* Read Drive Parameters */
|
||||
target_check(cmd->id, cmd->lun);
|
||||
|
||||
SCSI_BufferLength = 6;
|
||||
dev->CmdBuffer = (uint8_t *)malloc(SCSI_BufferLength);
|
||||
memset(dev->CmdBuffer, 0x00, SCSI_BufferLength);
|
||||
|
||||
ret = scsi_bios_command_08(cmd->id, cmd->lun, dev->CmdBuffer);
|
||||
|
||||
cmd_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address);
|
||||
DMAPageWrite(dma_address,
|
||||
(char *)dev->CmdBuffer, SCSI_BufferLength);
|
||||
|
||||
if (dev->CmdBuffer != NULL) {
|
||||
free(dev->CmdBuffer);
|
||||
dev->CmdBuffer = NULL;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
|
||||
case 0x09: /* Initialize Drive Pair Characteristics, in practice it's a nop */
|
||||
//FIXME: add a longer delay here --FvK
|
||||
return(0);
|
||||
|
||||
case 0x0c: /* Seek */
|
||||
target_check(cmd->id, cmd->lun);
|
||||
|
||||
//FIXME: is this needed? Looks like a copy-paste leftover.. --FvK
|
||||
SCSI_BufferLength = sector_len << block_shift;
|
||||
|
||||
cdb[0] = GPCMD_SEEK_10;
|
||||
cdb[1] = (cmd->lun & 7) << 5;
|
||||
cdb[2] = (lba >> 24) & 0xff;
|
||||
cdb[3] = (lba >> 16) & 0xff;
|
||||
cdb[4] = (lba >> 8) & 0xff;
|
||||
cdb[5] = lba & 0xff;
|
||||
|
||||
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
|
||||
|
||||
return((SCSIStatus == SCSI_STATUS_OK) ? 1 : 0);
|
||||
|
||||
case 0x0d: /* Alternate Disk Reset, in practice it's a nop */
|
||||
//FIXME: add a longer delay here --FvK
|
||||
return(0);
|
||||
|
||||
case 0x10: /* Test Drive Ready */
|
||||
target_check(cmd->id, cmd->lun);
|
||||
|
||||
cdb[0] = GPCMD_TEST_UNIT_READY;
|
||||
cdb[1] = (cmd->lun & 7) << 5;
|
||||
|
||||
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
|
||||
|
||||
return(completion_code(scsi_device_sense(cmd->id, cmd->lun)));
|
||||
|
||||
case 0x11: /* Recalibrate */
|
||||
target_check(cmd->id, cmd->lun);
|
||||
|
||||
cdb[0] = GPCMD_REZERO_UNIT;
|
||||
cdb[1] = (cmd->lun & 7) << 5;
|
||||
|
||||
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
|
||||
|
||||
return(completion_code(scsi_device_sense(cmd->id, cmd->lun)));
|
||||
|
||||
case 0x14: /* Controller Diagnostic */
|
||||
//FIXME: add a longer delay here --FvK
|
||||
return(0);
|
||||
|
||||
case 0x15: /* Read DASD Type */
|
||||
target_check(cmd->id, cmd->lun);
|
||||
|
||||
SCSI_BufferLength = 6;
|
||||
dev->CmdBuffer = (uint8_t *)malloc(SCSI_BufferLength);
|
||||
memset(dev->CmdBuffer, 0x00, SCSI_BufferLength);
|
||||
|
||||
ret = scsi_bios_command_15(cmd->id, cmd->lun, dev->CmdBuffer);
|
||||
|
||||
cmd_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address);
|
||||
DMAPageWrite(dma_address,
|
||||
(char *)dev->CmdBuffer, SCSI_BufferLength);
|
||||
|
||||
if (dev->CmdBuffer != NULL) {
|
||||
free(dev->CmdBuffer);
|
||||
dev->CmdBuffer = NULL;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
|
||||
default:
|
||||
cmd_log("BIOS: Unimplemented command: %02X\n", cmd->command);
|
||||
return(1);
|
||||
}
|
||||
|
||||
cmd_log("BIOS Request complete\n");
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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 shared AHA and Buslogic SCSI BIOS command handler's
|
||||
* headler.
|
||||
*
|
||||
* Version: @(#)scsi_bios_command.h 1.0.0 2017/08/26
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
* Copyright 2017 Fred N. van Kempen.
|
||||
*/
|
||||
#pragma pack(push,1)
|
||||
typedef struct
|
||||
{
|
||||
uint8_t command;
|
||||
uint8_t lun:3,
|
||||
reserved:2,
|
||||
id:3;
|
||||
union {
|
||||
struct {
|
||||
uint16_t cyl;
|
||||
uint8_t head;
|
||||
uint8_t sec;
|
||||
} chs;
|
||||
struct {
|
||||
uint8_t lba0; /* MSB */
|
||||
uint8_t lba1;
|
||||
uint8_t lba2;
|
||||
uint8_t lba3; /* LSB */
|
||||
} lba;
|
||||
} u;
|
||||
uint8_t secount;
|
||||
addr24 dma_address;
|
||||
} BIOSCMD;
|
||||
#pragma pack(pop)
|
||||
#define lba32_blk(p) ((uint32_t)(p->u.lba.lba0<<24) | (p->u.lba.lba1<<16) | \
|
||||
(p->u.lba.lba2<<8) | p->u.lba.lba3)
|
||||
|
||||
extern uint8_t scsi_bios_command(uint8_t last_id, BIOSCMD *BiosCmd, int8_t islba);
|
||||
@@ -38,7 +38,6 @@
|
||||
|
||||
uint32_t SCSI_BufferLength;
|
||||
|
||||
#define ENABLE_SCSI_BUS_LOG 0
|
||||
int scsi_bus_do_log = 0;
|
||||
|
||||
|
||||
@@ -94,12 +93,8 @@ int scsi_bus_update(scsi_bus_t *bus, int bus_assert)
|
||||
scsi_device_t *dev;
|
||||
uint8_t lun = 0;
|
||||
|
||||
dev = &SCSIDevices[bus->dev_id][0];
|
||||
|
||||
if (bus_assert & BUS_ARB)
|
||||
bus->state = STATE_IDLE;
|
||||
|
||||
dev->CmdBuffer = (uint8_t *)bus->buffer;
|
||||
|
||||
switch (bus->state)
|
||||
{
|
||||
@@ -159,12 +154,26 @@ int scsi_bus_update(scsi_bus_t *bus, int bus_assert)
|
||||
{
|
||||
lun = (bus->command[1] >> 5) & 7;
|
||||
bus->data_pos = 0;
|
||||
|
||||
|
||||
dev = &SCSIDevices[bus->dev_id][lun];
|
||||
|
||||
scsi_bus_log("Command 0x%02X\n", bus->command[0]);
|
||||
|
||||
SCSI_BufferLength = -1;
|
||||
dev->BufferLength = -1;
|
||||
|
||||
pclog("(%02X:%02X): Command %02X: Buffer length %i\n", bus->dev_id, lun, bus->command[0], dev->BufferLength);
|
||||
|
||||
scsi_device_command_phase0(bus->dev_id, lun, get_cmd_len(bus->command[0]), bus->command);
|
||||
|
||||
pclog("SCSI Phase: %02X\n", SCSIPhase);
|
||||
|
||||
if ((SCSIPhase == SCSI_PHASE_DATA_IN) || (SCSIPhase == SCSI_PHASE_DATA_OUT))
|
||||
{
|
||||
pclog("dev->CmdBuffer = %08X\n", dev->CmdBuffer);
|
||||
dev->CmdBuffer = (uint8_t *) malloc(dev->BufferLength);
|
||||
pclog("dev->CmdBuffer = %08X\n", dev->CmdBuffer);
|
||||
}
|
||||
|
||||
if (SCSIPhase == SCSI_PHASE_DATA_OUT)
|
||||
{
|
||||
/* Write direction commands have delayed execution - only execute them after the bus has gotten all the data from the host. */
|
||||
@@ -176,8 +185,11 @@ int scsi_bus_update(scsi_bus_t *bus, int bus_assert)
|
||||
else
|
||||
{
|
||||
/* Other command - execute immediately. */
|
||||
scsi_bus_log("Next state is defined by command\n");
|
||||
bus->new_state = SCSIPhase;
|
||||
if (SCSIPhase == SCSI_PHASE_DATA_IN)
|
||||
{
|
||||
scsi_device_command_phase1(bus->dev_id, lun);
|
||||
}
|
||||
|
||||
bus->change_state_delay = 4;
|
||||
}
|
||||
@@ -197,9 +209,15 @@ int scsi_bus_update(scsi_bus_t *bus, int bus_assert)
|
||||
scsi_bus_log("State Data In\n");
|
||||
|
||||
/* This seems to be read, so we first execute the command, then we return the bytes to the host. */
|
||||
|
||||
if (bus->data_pos >= SCSI_BufferLength)
|
||||
|
||||
lun = (bus->command[1] >> 5) & 7;
|
||||
|
||||
dev = &SCSIDevices[bus->dev_id][lun];
|
||||
|
||||
if (bus->data_pos >= SCSIDevices[bus->dev_id][lun].BufferLength)
|
||||
{
|
||||
free(dev->CmdBuffer);
|
||||
dev->CmdBuffer = NULL;
|
||||
bus->bus_out &= ~BUS_REQ;
|
||||
bus->new_state = SCSI_PHASE_STATUS;
|
||||
bus->change_state_delay = 4;
|
||||
@@ -221,17 +239,22 @@ int scsi_bus_update(scsi_bus_t *bus, int bus_assert)
|
||||
if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK))
|
||||
{
|
||||
scsi_bus_log("State Data Out\n");
|
||||
|
||||
lun = (bus->command[1] >> 5) & 7;
|
||||
|
||||
dev = &SCSIDevices[bus->dev_id][lun];
|
||||
|
||||
/* This is write, so first get the data from the host, then execute the last phase of the command. */
|
||||
dev->CmdBuffer[bus->data_pos++] = BUS_GETDATA(bus_assert);
|
||||
|
||||
if (bus->data_pos >= SCSI_BufferLength)
|
||||
if (bus->data_pos >= SCSIDevices[bus->dev_id][lun].BufferLength)
|
||||
{
|
||||
/* pclog("%04X bytes written (%02X %02X)\n", bus->data_pos, bus->command[0], bus->command[1]); */
|
||||
scsi_bus_log("Actually executing write command\n");
|
||||
lun = (bus->command[1] >> 5) & 7;
|
||||
bus->bus_out &= ~BUS_REQ;
|
||||
scsi_device_command_phase1(bus->dev_id, lun);
|
||||
free(dev->CmdBuffer);
|
||||
dev->CmdBuffer = NULL;
|
||||
bus->bus_out &= ~BUS_REQ;
|
||||
bus->new_state = SCSI_PHASE_STATUS;
|
||||
bus->change_state_delay = 4;
|
||||
bus->new_req_delay = 8;
|
||||
@@ -275,10 +298,7 @@ int scsi_bus_update(scsi_bus_t *bus, int bus_assert)
|
||||
int scsi_bus_read(scsi_bus_t *bus)
|
||||
{
|
||||
scsi_device_t *dev;
|
||||
|
||||
dev = &SCSIDevices[bus->dev_id][0];
|
||||
|
||||
dev->CmdBuffer = (uint8_t *)bus->buffer;
|
||||
uint8_t lun = 0;
|
||||
|
||||
if (bus->clear_req)
|
||||
{
|
||||
@@ -306,6 +326,9 @@ int scsi_bus_read(scsi_bus_t *bus)
|
||||
switch (bus->bus_out & SCSI_PHASE_MESSAGE_IN)
|
||||
{
|
||||
case SCSI_PHASE_DATA_IN:
|
||||
lun = (bus->command[1] >> 5) & 7;
|
||||
dev = &SCSIDevices[bus->dev_id][lun];
|
||||
|
||||
scsi_bus_log("Phase data in\n");
|
||||
bus->state = STATE_DATAIN;
|
||||
val = dev->CmdBuffer[bus->data_pos++];
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
||||
* Emulation of BusLogic BT-542B ISA and BT-958D PCI SCSI
|
||||
* controllers.
|
||||
*
|
||||
* Version: @(#)scsi_buslogic.h 1.0.1 2017/08/23
|
||||
* Version: @(#)scsi_buslogic.h 1.0.2 2017/10/14
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
|
||||
extern device_t buslogic_device;
|
||||
extern device_t buslogic_545s_device;
|
||||
extern device_t buslogic_pci_device;
|
||||
|
||||
extern void BuslogicDeviceReset(void *p);
|
||||
|
||||
@@ -295,7 +295,7 @@ void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len,
|
||||
break;
|
||||
default:
|
||||
id = 0;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -322,7 +322,7 @@ void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len,
|
||||
scsi_device_target_phase_callback(lun_type, id);
|
||||
} else {
|
||||
/* Command first phase complete - call the callback to execute the second phase. */
|
||||
if (SCSIPhase != SCSI_PHASE_DATA_OUT)
|
||||
if (SCSIPhase == SCSI_PHASE_STATUS)
|
||||
{
|
||||
scsi_device_target_phase_callback(lun_type, id);
|
||||
SCSIStatus = scsi_device_target_err_stat_to_scsi(lun_type, id);
|
||||
@@ -352,7 +352,7 @@ void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
break;
|
||||
default:
|
||||
id = 0;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
scsi_device_target_phase_callback(lun_type, id);
|
||||
@@ -360,3 +360,8 @@ void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun)
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ typedef struct
|
||||
int command_pos;
|
||||
uint8_t command[20];
|
||||
int data_pos;
|
||||
uint8_t buffer[390144];
|
||||
|
||||
int change_state_delay;
|
||||
int new_req_delay;
|
||||
@@ -51,10 +50,10 @@ extern void scsi_device_command(uint8_t id, uint8_t lun, int cdb_len,
|
||||
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);
|
||||
|
||||
|
||||
#endif /*SCSI_DEVICE_H*/
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
* Emulation of SCSI fixed and removable disks.
|
||||
*
|
||||
* Version: @(#)scsi_disk.c 1.0.14 2017/10/12
|
||||
* Version: @(#)scsi_disk.c 1.0.15 2017/10/14
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2017 Miran Grca.
|
||||
@@ -125,36 +125,36 @@ uint8_t scsi_hd_command_flags[0x100] = {
|
||||
};
|
||||
|
||||
|
||||
uint64_t scsi_hd_mode_sense_page_flags[HDD_NUM] = { (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << GPMODE_ALL_PAGES) };
|
||||
uint64_t scsi_hd_mode_sense_page_flags[HDD_NUM] = { (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F),
|
||||
(1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F) };
|
||||
|
||||
/* This should be done in a better way but for time being, it's been done this way so it's not as huge and more readable. */
|
||||
const uint8_t scsi_hd_mode_sense_pages_default[HDD_NUM][0x40][0x40] =
|
||||
@@ -439,7 +439,6 @@ uint8_t scsi_hd_mode_sense_pages_saved[HDD_NUM][0x40][0x40] =
|
||||
[0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }
|
||||
};
|
||||
|
||||
#define ENABLE_SCSI_HD_LOG 0
|
||||
int scsi_hd_do_log = 0;
|
||||
|
||||
|
||||
@@ -1318,6 +1317,10 @@ void scsi_hd_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length)
|
||||
memset(buffer, 0, alloc_length);
|
||||
memcpy(buffer, shdc[id].sense, alloc_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
buffer[0] = 0x70;
|
||||
|
||||
@@ -1392,9 +1395,9 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
|
||||
uint32_t alloc_length;
|
||||
char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 };
|
||||
char device_identify_ex[15] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 };
|
||||
uint8_t *tempbuffer;
|
||||
uint32_t last_sector = 0;
|
||||
int block_desc = 0;
|
||||
int32_t *BufLen = &SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].BufferLength;
|
||||
|
||||
#if 0
|
||||
int CdbLength;
|
||||
@@ -1469,16 +1472,15 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
|
||||
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. */
|
||||
if ((SCSI_BufferLength == -1) || (cdb[4] < SCSI_BufferLength))
|
||||
if ((*BufLen == -1) || (cdb[4] < *BufLen))
|
||||
{
|
||||
SCSI_BufferLength = cdb[4];
|
||||
*BufLen = cdb[4];
|
||||
}
|
||||
|
||||
if (SCSI_BufferLength < cdb[4])
|
||||
if (*BufLen < cdb[4])
|
||||
{
|
||||
cdb[4] = SCSI_BufferLength;
|
||||
cdb[4] = *BufLen;
|
||||
}
|
||||
scsi_hd_request_sense(id, hdbufferb, cdb[4]);
|
||||
|
||||
SCSIPhase = SCSI_PHASE_DATA_IN;
|
||||
scsi_hd_data_command_finish(id, 18, 18, cdb[4], 0);
|
||||
@@ -1487,14 +1489,11 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
|
||||
case GPCMD_MECHANISM_STATUS:
|
||||
len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
|
||||
|
||||
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
|
||||
if ((*BufLen == -1) || (len < *BufLen))
|
||||
{
|
||||
SCSI_BufferLength = len;
|
||||
*BufLen = len;
|
||||
}
|
||||
|
||||
memset(hdbufferb, 0, 8);
|
||||
hdbufferb[5] = 1;
|
||||
|
||||
SCSIPhase = SCSI_PHASE_DATA_IN;
|
||||
scsi_hd_data_command_finish(id, 8, 8, len, 0);
|
||||
break;
|
||||
@@ -1524,9 +1523,10 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!shdc[id].sector_len) || (SCSI_BufferLength == 0))
|
||||
if ((!shdc[id].sector_len) || (*BufLen == 0))
|
||||
{
|
||||
SCSIPhase = SCSI_PHASE_STATUS;
|
||||
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
|
||||
scsi_hd_log("SCSI HD %i: All done - callback set\n", id);
|
||||
shdc[id].packet_status = CDROM_PHASE_COMPLETE;
|
||||
shdc[id].callback = 20 * SCSI_TIME;
|
||||
@@ -1538,23 +1538,13 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
|
||||
|
||||
alloc_length = shdc[id].packet_len = max_len << 9;
|
||||
|
||||
if ((SCSI_BufferLength == -1) || (alloc_length < SCSI_BufferLength))
|
||||
if ((*BufLen == -1) || (alloc_length < *BufLen))
|
||||
{
|
||||
SCSI_BufferLength = alloc_length;
|
||||
*BufLen = alloc_length;
|
||||
}
|
||||
|
||||
if ((shdc[id].requested_blocks > 0) && (SCSI_BufferLength > 0))
|
||||
{
|
||||
if (alloc_length > SCSI_BufferLength)
|
||||
{
|
||||
hdd_image_read(id, shdc[id].sector_pos, SCSI_BufferLength >> 9, hdbufferb);
|
||||
}
|
||||
else
|
||||
{
|
||||
hdd_image_read(id, shdc[id].sector_pos, max_len, hdbufferb);
|
||||
}
|
||||
}
|
||||
SCSIPhase = SCSI_PHASE_DATA_IN;
|
||||
|
||||
if (shdc[id].requested_blocks > 1)
|
||||
{
|
||||
scsi_hd_data_command_finish(id, alloc_length, alloc_length / shdc[id].requested_blocks, alloc_length, 0);
|
||||
@@ -1564,113 +1554,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
|
||||
scsi_hd_data_command_finish(id, alloc_length, alloc_length, alloc_length, 0);
|
||||
}
|
||||
shdc[id].all_blocks_total = shdc[id].block_total;
|
||||
if (shdc[id].packet_status != CDROM_PHASE_COMPLETE)
|
||||
{
|
||||
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
|
||||
}
|
||||
return;
|
||||
|
||||
case GPCMD_MODE_SENSE_6:
|
||||
case GPCMD_MODE_SENSE_10:
|
||||
SCSIPhase = SCSI_PHASE_DATA_IN;
|
||||
|
||||
block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1;
|
||||
|
||||
if (cdb[0] == GPCMD_MODE_SENSE_6)
|
||||
{
|
||||
len = cdb[4];
|
||||
}
|
||||
else
|
||||
{
|
||||
len = (cdb[8] | (cdb[7] << 8));
|
||||
}
|
||||
|
||||
shdc[id].current_page_code = cdb[2] & 0x3F;
|
||||
|
||||
if (!(scsi_hd_mode_sense_page_flags[id] & (1LL << shdc[id].current_page_code)))
|
||||
{
|
||||
scsi_hd_invalid_field(id);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(hdbufferb, 0, len);
|
||||
alloc_length = len;
|
||||
|
||||
if (cdb[0] == GPCMD_MODE_SENSE_6)
|
||||
{
|
||||
len = scsi_hd_mode_sense(id, hdbufferb, 4, cdb[2], block_desc);
|
||||
if (len > alloc_length)
|
||||
{
|
||||
len = alloc_length;
|
||||
}
|
||||
hdbufferb[0] = len - 1;
|
||||
hdbufferb[1] = 0;
|
||||
if (block_desc)
|
||||
{
|
||||
hdbufferb[3] = 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
len = scsi_hd_mode_sense(id, hdbufferb, 8, cdb[2], block_desc);
|
||||
if (len > alloc_length)
|
||||
{
|
||||
len = alloc_length;
|
||||
}
|
||||
hdbufferb[0]=(len - 2) >> 8;
|
||||
hdbufferb[1]=(len - 2) & 255;
|
||||
hdbufferb[2] = 0;
|
||||
if (block_desc)
|
||||
{
|
||||
hdbufferb[6] = 0;
|
||||
hdbufferb[7] = 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (len > alloc_length)
|
||||
{
|
||||
len = alloc_length;
|
||||
}
|
||||
else if (len < alloc_length)
|
||||
{
|
||||
alloc_length = len;
|
||||
}
|
||||
|
||||
if ((SCSI_BufferLength == -1) || (alloc_length < SCSI_BufferLength))
|
||||
{
|
||||
SCSI_BufferLength = alloc_length;
|
||||
}
|
||||
|
||||
scsi_hd_log("SCSI HDD %i: Reading mode page: %02X...\n", id, cdb[2]);
|
||||
|
||||
scsi_hd_data_command_finish(id, len, len, alloc_length, 0);
|
||||
return;
|
||||
|
||||
case GPCMD_MODE_SELECT_6:
|
||||
case GPCMD_MODE_SELECT_10:
|
||||
SCSIPhase = SCSI_PHASE_DATA_OUT;
|
||||
|
||||
if (cdb[0] == GPCMD_MODE_SELECT_6)
|
||||
{
|
||||
len = cdb[4];
|
||||
}
|
||||
else
|
||||
{
|
||||
len = (cdb[7] << 8) | cdb[8];
|
||||
}
|
||||
|
||||
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
|
||||
{
|
||||
SCSI_BufferLength = len;
|
||||
}
|
||||
|
||||
scsi_hd_mode_select_init(id, cdb[0], len, cdb[1] & 1);
|
||||
|
||||
scsi_hd_data_command_finish(id, len, len, len, 1);
|
||||
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1);
|
||||
return;
|
||||
|
||||
case GPCMD_WRITE_6:
|
||||
@@ -1706,9 +1590,10 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!shdc[id].sector_len) || (SCSI_BufferLength == 0))
|
||||
if ((!shdc[id].sector_len) || (*BufLen == 0))
|
||||
{
|
||||
SCSIPhase = SCSI_PHASE_STATUS;
|
||||
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
|
||||
scsi_hd_log("SCSI HD %i: All done - callback set\n", id);
|
||||
shdc[id].packet_status = CDROM_PHASE_COMPLETE;
|
||||
shdc[id].callback = 20 * SCSI_TIME;
|
||||
@@ -1720,9 +1605,9 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
|
||||
|
||||
alloc_length = shdc[id].packet_len = max_len << 9;
|
||||
|
||||
if ((SCSI_BufferLength == -1) || (alloc_length < SCSI_BufferLength))
|
||||
if ((*BufLen == -1) || (alloc_length < *BufLen))
|
||||
{
|
||||
SCSI_BufferLength = alloc_length;
|
||||
*BufLen = alloc_length;
|
||||
}
|
||||
|
||||
SCSIPhase = SCSI_PHASE_DATA_OUT;
|
||||
@@ -1739,6 +1624,106 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
|
||||
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1);
|
||||
return;
|
||||
|
||||
case GPCMD_MODE_SENSE_6:
|
||||
case GPCMD_MODE_SENSE_10:
|
||||
SCSIPhase = SCSI_PHASE_DATA_IN;
|
||||
|
||||
block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1;
|
||||
|
||||
if (cdb[0] == GPCMD_MODE_SENSE_6)
|
||||
{
|
||||
len = cdb[4];
|
||||
}
|
||||
else
|
||||
{
|
||||
len = (cdb[8] | (cdb[7] << 8));
|
||||
}
|
||||
|
||||
shdc[id].current_page_code = cdb[2] & 0x3F;
|
||||
|
||||
if (!(scsi_hd_mode_sense_page_flags[id] & (1LL << shdc[id].current_page_code)))
|
||||
{
|
||||
scsi_hd_invalid_field(id);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(hdbufferb, 0, len);
|
||||
alloc_length = len;
|
||||
|
||||
shdc[id].temp_buffer = (uint8_t *) malloc(256);
|
||||
if (cdb[0] == GPCMD_MODE_SENSE_6)
|
||||
{
|
||||
len = scsi_hd_mode_sense(id, shdc[id].temp_buffer, 4, cdb[2], block_desc);
|
||||
if (len > alloc_length)
|
||||
{
|
||||
len = alloc_length;
|
||||
}
|
||||
shdc[id].temp_buffer[0] = len - 1;
|
||||
shdc[id].temp_buffer[1] = 0;
|
||||
if (block_desc)
|
||||
{
|
||||
hdbufferb[3] = 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
len = scsi_hd_mode_sense(id, shdc[id].temp_buffer, 8, cdb[2], block_desc);
|
||||
if (len > alloc_length)
|
||||
{
|
||||
len = alloc_length;
|
||||
}
|
||||
shdc[id].temp_buffer[0]=(len - 2) >> 8;
|
||||
shdc[id].temp_buffer[1]=(len - 2) & 255;
|
||||
shdc[id].temp_buffer[2] = 0;
|
||||
if (block_desc)
|
||||
{
|
||||
shdc[id].temp_buffer[6] = 0;
|
||||
shdc[id].temp_buffer[7] = 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (len > alloc_length)
|
||||
{
|
||||
len = alloc_length;
|
||||
}
|
||||
else if (len < alloc_length)
|
||||
{
|
||||
alloc_length = len;
|
||||
}
|
||||
|
||||
if ((*BufLen == -1) || (alloc_length < *BufLen))
|
||||
{
|
||||
*BufLen = alloc_length;
|
||||
}
|
||||
|
||||
scsi_hd_log("SCSI HDD %i: Reading mode page: %02X...\n", id, cdb[2]);
|
||||
|
||||
scsi_hd_data_command_finish(id, len, len, alloc_length, 0);
|
||||
return;
|
||||
|
||||
case GPCMD_MODE_SELECT_6:
|
||||
case GPCMD_MODE_SELECT_10:
|
||||
SCSIPhase = SCSI_PHASE_DATA_OUT;
|
||||
|
||||
if (cdb[0] == GPCMD_MODE_SELECT_6)
|
||||
{
|
||||
len = cdb[4];
|
||||
}
|
||||
else
|
||||
{
|
||||
len = (cdb[7] << 8) | cdb[8];
|
||||
}
|
||||
|
||||
if ((*BufLen == -1) || (len < *BufLen))
|
||||
{
|
||||
*BufLen = len;
|
||||
}
|
||||
|
||||
scsi_hd_mode_select_init(id, cdb[0], len, cdb[1] & 1);
|
||||
|
||||
scsi_hd_data_command_finish(id, len, len, len, 1);
|
||||
return;
|
||||
|
||||
case GPCMD_START_STOP_UNIT:
|
||||
if (hdd[id].bus != HDD_BUS_SCSI_REMOVABLE)
|
||||
{
|
||||
@@ -1768,7 +1753,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
|
||||
max_len <<= 8;
|
||||
max_len |= cdb[4];
|
||||
|
||||
if ((!max_len) || (SCSI_BufferLength == 0))
|
||||
if ((!max_len) || (*BufLen == 0))
|
||||
{
|
||||
SCSIPhase = SCSI_PHASE_STATUS;
|
||||
/* scsi_hd_log("SCSI HD %i: All done - callback set\n", id); */
|
||||
@@ -1777,36 +1762,38 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
|
||||
break;
|
||||
}
|
||||
|
||||
tempbuffer = malloc(1024);
|
||||
shdc[id].temp_buffer = malloc(1024);
|
||||
|
||||
if (cdb[1] & 1)
|
||||
{
|
||||
preamble_len = 4;
|
||||
size_idx = 3;
|
||||
|
||||
tempbuffer[idx++] = 05;
|
||||
tempbuffer[idx++] = cdb[2];
|
||||
tempbuffer[idx++] = 0;
|
||||
shdc[id].temp_buffer[idx++] = 05;
|
||||
shdc[id].temp_buffer[idx++] = cdb[2];
|
||||
shdc[id].temp_buffer[idx++] = 0;
|
||||
|
||||
idx++;
|
||||
|
||||
switch (cdb[2])
|
||||
{
|
||||
case 0x00:
|
||||
tempbuffer[idx++] = 0x00;
|
||||
tempbuffer[idx++] = 0x83;
|
||||
shdc[id].temp_buffer[idx++] = 0x00;
|
||||
shdc[id].temp_buffer[idx++] = 0x83;
|
||||
break;
|
||||
case 0x83:
|
||||
if (idx + 24 > max_len)
|
||||
{
|
||||
free(shdc[id].temp_buffer);
|
||||
shdc[id].temp_buffer = NULL;
|
||||
scsi_hd_data_phase_error(id);
|
||||
return;
|
||||
}
|
||||
|
||||
tempbuffer[idx++] = 0x02;
|
||||
tempbuffer[idx++] = 0x00;
|
||||
tempbuffer[idx++] = 0x00;
|
||||
tempbuffer[idx++] = 20;
|
||||
shdc[id].temp_buffer[idx++] = 0x02;
|
||||
shdc[id].temp_buffer[idx++] = 0x00;
|
||||
shdc[id].temp_buffer[idx++] = 0x00;
|
||||
shdc[id].temp_buffer[idx++] = 20;
|
||||
ide_padstr8(hdbufferb + idx, 20, "53R141"); /* Serial */
|
||||
idx += 20;
|
||||
|
||||
@@ -1814,19 +1801,21 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
|
||||
{
|
||||
goto atapi_out;
|
||||
}
|
||||
tempbuffer[idx++] = 0x02;
|
||||
tempbuffer[idx++] = 0x01;
|
||||
tempbuffer[idx++] = 0x00;
|
||||
tempbuffer[idx++] = 68;
|
||||
ide_padstr8(tempbuffer + idx, 8, EMU_NAME); /* Vendor */
|
||||
shdc[id].temp_buffer[idx++] = 0x02;
|
||||
shdc[id].temp_buffer[idx++] = 0x01;
|
||||
shdc[id].temp_buffer[idx++] = 0x00;
|
||||
shdc[id].temp_buffer[idx++] = 68;
|
||||
ide_padstr8(shdc[id].temp_buffer + idx, 8, EMU_NAME); /* Vendor */
|
||||
idx += 8;
|
||||
ide_padstr8(tempbuffer + idx, 40, device_identify_ex); /* Product */
|
||||
ide_padstr8(shdc[id].temp_buffer + idx, 40, device_identify_ex); /* Product */
|
||||
idx += 40;
|
||||
ide_padstr8(tempbuffer + idx, 20, "53R141"); /* Product */
|
||||
ide_padstr8(shdc[id].temp_buffer + idx, 20, "53R141"); /* Product */
|
||||
idx += 20;
|
||||
break;
|
||||
default:
|
||||
scsi_hd_log("INQUIRY: Invalid page: %02X\n", cdb[2]);
|
||||
free(shdc[id].temp_buffer);
|
||||
shdc[id].temp_buffer = NULL;
|
||||
scsi_hd_invalid_field(id);
|
||||
return;
|
||||
}
|
||||
@@ -1836,48 +1825,46 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
|
||||
preamble_len = 5;
|
||||
size_idx = 4;
|
||||
|
||||
memset(tempbuffer, 0, 8);
|
||||
tempbuffer[0] = 0; /*SCSI HD*/
|
||||
memset(shdc[id].temp_buffer, 0, 8);
|
||||
shdc[id].temp_buffer[0] = 0; /*SCSI HD*/
|
||||
if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE)
|
||||
{
|
||||
tempbuffer[1] = 0x80; /*Removable*/
|
||||
shdc[id].temp_buffer[1] = 0x80; /*Removable*/
|
||||
}
|
||||
else
|
||||
{
|
||||
tempbuffer[1] = 0; /*Fixed*/
|
||||
shdc[id].temp_buffer[1] = 0; /*Fixed*/
|
||||
}
|
||||
tempbuffer[2] = 0x02; /*SCSI-2 compliant*/
|
||||
tempbuffer[3] = 0x02;
|
||||
tempbuffer[4] = 31;
|
||||
shdc[id].temp_buffer[2] = 0x02; /*SCSI-2 compliant*/
|
||||
shdc[id].temp_buffer[3] = 0x02;
|
||||
shdc[id].temp_buffer[4] = 31;
|
||||
|
||||
ide_padstr8(tempbuffer + 8, 8, EMU_NAME); /* Vendor */
|
||||
ide_padstr8(tempbuffer + 16, 16, device_identify); /* Product */
|
||||
ide_padstr8(tempbuffer + 32, 4, EMU_VERSION); /* Revision */
|
||||
ide_padstr8(shdc[id].temp_buffer + 8, 8, EMU_NAME); /* Vendor */
|
||||
ide_padstr8(shdc[id].temp_buffer + 16, 16, device_identify); /* Product */
|
||||
ide_padstr8(shdc[id].temp_buffer + 32, 4, EMU_VERSION); /* Revision */
|
||||
idx = 36;
|
||||
}
|
||||
|
||||
atapi_out:
|
||||
tempbuffer[size_idx] = idx - preamble_len;
|
||||
shdc[id].temp_buffer[size_idx] = idx - preamble_len;
|
||||
len=idx;
|
||||
|
||||
scsi_hd_log("scsi_hd_command(): Inquiry (%08X, %08X)\n", hdbufferb, shdc[id].temp_buffer);
|
||||
|
||||
if (len > max_len)
|
||||
{
|
||||
len = max_len;
|
||||
}
|
||||
|
||||
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
|
||||
if ((*BufLen == -1) || (len < *BufLen))
|
||||
{
|
||||
SCSI_BufferLength = len;
|
||||
*BufLen = len;
|
||||
}
|
||||
|
||||
if (len > SCSI_BufferLength)
|
||||
if (len > *BufLen)
|
||||
{
|
||||
len = SCSI_BufferLength;
|
||||
len = *BufLen;
|
||||
}
|
||||
|
||||
memcpy(hdbufferb, tempbuffer, len);
|
||||
|
||||
free(tempbuffer);
|
||||
|
||||
SCSIPhase = SCSI_PHASE_DATA_IN;
|
||||
scsi_hd_data_command_finish(id, len, len, max_len, 0);
|
||||
@@ -1906,14 +1893,17 @@ atapi_out:
|
||||
break;
|
||||
|
||||
case GPCMD_READ_CDROM_CAPACITY:
|
||||
if (scsi_hd_read_capacity(id, shdc[id].current_cdb, hdbufferb, &len) == 0)
|
||||
shdc[id].temp_buffer = (uint8_t *) malloc(8);
|
||||
|
||||
if (scsi_hd_read_capacity(id, shdc[id].current_cdb, shdc[id].temp_buffer, &len) == 0)
|
||||
{
|
||||
SCSIPhase = SCSI_PHASE_STATUS;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
|
||||
if ((*BufLen == -1) || (len < *BufLen))
|
||||
{
|
||||
SCSI_BufferLength = len;
|
||||
*BufLen = len;
|
||||
}
|
||||
|
||||
SCSIPhase = SCSI_PHASE_DATA_IN;
|
||||
@@ -1967,6 +1957,66 @@ int scsi_hd_mode_select_return(uint8_t id, int ret)
|
||||
}
|
||||
}
|
||||
|
||||
void scsi_hd_phase_data_in(uint8_t id)
|
||||
{
|
||||
uint8_t *hdbufferb = SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].CmdBuffer;
|
||||
int32_t *BufLen = &SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].BufferLength;
|
||||
|
||||
if (!*BufLen)
|
||||
{
|
||||
scsi_hd_log("scsi_hd_phase_data_in(): Buffer length is 0\n");
|
||||
SCSIPhase = SCSI_PHASE_STATUS;
|
||||
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (shdc[id].current_cdb[0])
|
||||
{
|
||||
case GPCMD_REQUEST_SENSE:
|
||||
scsi_hd_log("SCSI HDD %i: %08X, %08X\n", id, hdbufferb, *BufLen);
|
||||
scsi_hd_request_sense(id, hdbufferb, *BufLen);
|
||||
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 ((shdc[id].requested_blocks > 0) && (*BufLen > 0))
|
||||
{
|
||||
if (shdc[id].packet_len > *BufLen)
|
||||
{
|
||||
hdd_image_read(id, shdc[id].sector_pos, *BufLen >> 9, hdbufferb);
|
||||
}
|
||||
else
|
||||
{
|
||||
hdd_image_read(id, shdc[id].sector_pos, shdc[id].requested_blocks, hdbufferb);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GPCMD_MODE_SENSE_6:
|
||||
case GPCMD_MODE_SENSE_10:
|
||||
case GPCMD_INQUIRY:
|
||||
case GPCMD_READ_CDROM_CAPACITY:
|
||||
scsi_hd_log("scsi_hd_phase_data_in(): Filling buffer (%08X, %08X)\n", hdbufferb, shdc[id].temp_buffer);
|
||||
memcpy(hdbufferb, shdc[id].temp_buffer, *BufLen);
|
||||
free(shdc[id].temp_buffer);
|
||||
shdc[id].temp_buffer = NULL;
|
||||
scsi_hd_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", shdc[id].current_cdb[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
SCSIPhase = SCSI_PHASE_STATUS;
|
||||
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
|
||||
}
|
||||
|
||||
void scsi_hd_phase_data_out(uint8_t id)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -1975,11 +2025,36 @@ void scsi_hd_phase_data_out(uint8_t id)
|
||||
int in_data_length = 0;
|
||||
int i;
|
||||
|
||||
int32_t *BufLen = &SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].BufferLength;
|
||||
|
||||
if (!*BufLen)
|
||||
{
|
||||
SCSIPhase = SCSI_PHASE_STATUS;
|
||||
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (shdc[id].current_cdb[0])
|
||||
{
|
||||
case GPCMD_WRITE_6:
|
||||
case GPCMD_WRITE_10:
|
||||
case GPCMD_WRITE_12:
|
||||
if ((shdc[id].requested_blocks > 0) && (*BufLen > 0))
|
||||
{
|
||||
if (shdc[id].packet_len > *BufLen)
|
||||
{
|
||||
hdd_image_write(id, shdc[id].sector_pos, *BufLen >> 9, hdbufferb);
|
||||
}
|
||||
else
|
||||
{
|
||||
hdd_image_write(id, shdc[id].sector_pos, shdc[id].requested_blocks, hdbufferb);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GPCMD_MODE_SELECT_6:
|
||||
case GPCMD_MODE_SELECT_10:
|
||||
in_data_length = SCSI_BufferLength;
|
||||
in_data_length = *BufLen;
|
||||
|
||||
for (i = 0; i < in_data_length; i++)
|
||||
{
|
||||
@@ -1996,30 +2071,13 @@ void scsi_hd_phase_data_out(uint8_t id)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GPCMD_WRITE_6:
|
||||
case GPCMD_WRITE_10:
|
||||
case GPCMD_WRITE_12:
|
||||
if ((shdc[id].requested_blocks > 0) && (SCSI_BufferLength > 0))
|
||||
{
|
||||
if (shdc[id].packet_len > SCSI_BufferLength)
|
||||
{
|
||||
hdd_image_write(id, shdc[id].sector_pos, SCSI_BufferLength >> 9, hdbufferb);
|
||||
}
|
||||
else
|
||||
{
|
||||
hdd_image_write(id, shdc[id].sector_pos, shdc[id].requested_blocks, hdbufferb);
|
||||
}
|
||||
}
|
||||
scsi_hd_log("HDD image written\n");
|
||||
|
||||
SCSIPhase = SCSI_PHASE_STATUS;
|
||||
|
||||
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
|
||||
break;
|
||||
default:
|
||||
fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", shdc[id].current_cdb[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
SCSIPhase = SCSI_PHASE_STATUS;
|
||||
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
|
||||
}
|
||||
|
||||
/* If the result is 1, issue an IRQ, otherwise not. */
|
||||
@@ -2060,6 +2118,7 @@ void scsi_hd_callback(uint8_t id)
|
||||
return;
|
||||
case CDROM_PHASE_DATA_IN_DMA:
|
||||
scsi_hd_log("SCSI HD %i: PHASE_DATA_IN_DMA\n", id);
|
||||
scsi_hd_phase_data_in(id);
|
||||
shdc[id].packet_status = CDROM_PHASE_COMPLETE;
|
||||
shdc[id].status = READY_STAT;
|
||||
shdc[id].phase = 3;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
* Emulation of SCSI fixed and removable disks.
|
||||
*
|
||||
* Version: @(#)scsi_disk.h 1.0.2 2017/09/29
|
||||
* Version: @(#)scsi_disk.h 1.0.3 2017/10/14
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2017 Miran Grca.
|
||||
@@ -54,6 +54,8 @@ typedef struct {
|
||||
|
||||
int do_page_save;
|
||||
int block_descriptor_len;
|
||||
|
||||
uint8_t *temp_buffer;
|
||||
} scsi_hard_disk_t;
|
||||
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ typedef struct {
|
||||
uint8_t tcr;
|
||||
uint8_t ser;
|
||||
uint8_t isr;
|
||||
uint8_t output_data;
|
||||
|
||||
int target_bsy;
|
||||
int target_req;
|
||||
@@ -211,7 +212,7 @@ get_bus_host(ncr5380_t *ncr)
|
||||
if (ncr->mode & MODE_ARBITRATE)
|
||||
bus_host |= BUS_ARB;
|
||||
|
||||
return(bus_host | BUS_SETDATA(SCSI_BufferLength));
|
||||
return(bus_host | BUS_SETDATA(ncr->output_data));
|
||||
}
|
||||
|
||||
|
||||
@@ -227,13 +228,13 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
|
||||
#endif
|
||||
switch (port & 7) {
|
||||
case 0: /* Output data register */
|
||||
SCSI_BufferLength = val;
|
||||
ncr->output_data = val;
|
||||
break;
|
||||
|
||||
case 1: /* Initiator Command Register */
|
||||
if ((val & (ICR_BSY | ICR_SEL)) == (ICR_BSY | ICR_SEL) &&
|
||||
(ncr->icr & (ICR_BSY | ICR_SEL)) == ICR_SEL) {
|
||||
uint8_t temp = SCSI_BufferLength & 0x7f;
|
||||
uint8_t temp = ncr->output_data & 0x7f;
|
||||
|
||||
ncr->target_id = -1;
|
||||
while (temp) {
|
||||
@@ -302,7 +303,7 @@ ncr_read(uint16_t port, void *priv)
|
||||
switch (port & 7) {
|
||||
case 0: /* current SCSI data */
|
||||
if (ncr->icr & ICR_DBP) {
|
||||
temp = SCSI_BufferLength;
|
||||
temp = ncr->output_data;
|
||||
} else {
|
||||
bus = scsi_bus_read(&ncr->bus);
|
||||
temp = BUS_GETDATA(bus);
|
||||
|
||||
1917
src/scsi/scsi_x54x.c
Normal file
1917
src/scsi/scsi_x54x.c
Normal file
File diff suppressed because it is too large
Load Diff
513
src/scsi/scsi_x54x.h
Normal file
513
src/scsi/scsi_x54x.h
Normal file
@@ -0,0 +1,513 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Header of the code common to the AHA-154x series of SCSI
|
||||
* Host Adapters made by Adaptec, Inc. and the BusLogic series
|
||||
* of SCSI Host Adapters made by Mylex.
|
||||
* These controllers were designed for various buses.
|
||||
*
|
||||
* Version: @(#)scsi_x54x.h 1.0.0 2017/10/14
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
* Copyright 2017 Fred N. van Kempen.
|
||||
*/
|
||||
#ifndef SCSI_X54X_H
|
||||
|
||||
#define SCSI_X54X_H
|
||||
|
||||
#define SCSI_DELAY_TM 1 /* was 50 */
|
||||
|
||||
|
||||
#define ROM_SIZE 16384 /* one ROM is 16K */
|
||||
#define NVR_SIZE 32 /* size of NVR */
|
||||
|
||||
|
||||
/* EEPROM map and bit definitions. */
|
||||
#define EE0_HOSTID 0x07 /* EE(0) [2:0] */
|
||||
#define EE0_ALTFLOP 0x80 /* EE(0) [7] FDC at 370h */
|
||||
#define EE1_IRQCH 0x07 /* EE(1) [3:0] */
|
||||
#define EE1_DMACH 0x70 /* EE(1) [7:4] */
|
||||
#define EE2_RMVOK 0x01 /* EE(2) [0] Support removable disks */
|
||||
#define EE2_HABIOS 0x02 /* EE(2) [1] HA Bios Space Reserved */
|
||||
#define EE2_INT19 0x04 /* EE(2) [2] HA Bios Controls INT19 */
|
||||
#define EE2_DYNSCAN 0x08 /* EE(2) [3] Dynamically scan bus */
|
||||
#define EE2_TWODRV 0x10 /* EE(2) [4] Allow more than 2 drives */
|
||||
#define EE2_SEEKRET 0x20 /* EE(2) [5] Immediate return on seek */
|
||||
#define EE2_EXT1G 0x80 /* EE(2) [7] Extended Translation >1GB */
|
||||
#define EE3_SPEED 0x00 /* EE(3) [7:0] DMA Speed */
|
||||
#define SPEED_33 0xFF
|
||||
#define SPEED_50 0x00
|
||||
#define SPEED_56 0x04
|
||||
#define SPEED_67 0x01
|
||||
#define SPEED_80 0x02
|
||||
#define SPEED_10 0x03
|
||||
#define EE4_FLOPTOK 0x80 /* EE(4) [7] Support Flopticals */
|
||||
#define EE6_PARITY 0x01 /* EE(6) [0] parity check enable */
|
||||
#define EE6_TERM 0x02 /* EE(6) [1] host term enable */
|
||||
#define EE6_RSTBUS 0x04 /* EE(6) [2] reset SCSI bus on boot */
|
||||
#define EEE_SYNC 0x01 /* EE(E) [0] Enable Sync Negotiation */
|
||||
#define EEE_DISCON 0x02 /* EE(E) [1] Enable Disconnection */
|
||||
#define EEE_FAST 0x04 /* EE(E) [2] Enable FAST SCSI */
|
||||
#define EEE_START 0x08 /* EE(E) [3] Enable Start Unit */
|
||||
|
||||
|
||||
/*
|
||||
* Host Adapter I/O ports.
|
||||
*
|
||||
* READ Port x+0: STATUS
|
||||
* WRITE Port x+0: CONTROL
|
||||
*
|
||||
* READ Port x+1: DATA
|
||||
* WRITE Port x+1: COMMAND
|
||||
*
|
||||
* READ Port x+2: INTERRUPT STATUS
|
||||
* WRITE Port x+2: (undefined?)
|
||||
*
|
||||
* R/W Port x+3: (undefined)
|
||||
*/
|
||||
|
||||
/* WRITE CONTROL commands. */
|
||||
#define CTRL_HRST 0x80 /* Hard reset */
|
||||
#define CTRL_SRST 0x40 /* Soft reset */
|
||||
#define CTRL_IRST 0x20 /* interrupt reset */
|
||||
#define CTRL_SCRST 0x10 /* SCSI bus reset */
|
||||
|
||||
/* READ STATUS. */
|
||||
#define STAT_STST 0x80 /* self-test in progress */
|
||||
#define STAT_DFAIL 0x40 /* internal diagnostic failure */
|
||||
#define STAT_INIT 0x20 /* mailbox initialization required */
|
||||
#define STAT_IDLE 0x10 /* HBA is idle */
|
||||
#define STAT_CDFULL 0x08 /* Command/Data output port is full */
|
||||
#define STAT_DFULL 0x04 /* Data input port is full */
|
||||
#define STAT_INVCMD 0x01 /* Invalid command */
|
||||
|
||||
/* READ/WRITE DATA. */
|
||||
#define CMD_NOP 0x00 /* No operation */
|
||||
#define CMD_MBINIT 0x01 /* mailbox initialization */
|
||||
#define CMD_START_SCSI 0x02 /* Start SCSI command */
|
||||
#define CMD_BIOSCMD 0x03 /* Execute ROM BIOS command */
|
||||
#define CMD_INQUIRY 0x04 /* Adapter inquiry */
|
||||
#define CMD_EMBOI 0x05 /* enable Mailbox Out Interrupt */
|
||||
#define CMD_SELTIMEOUT 0x06 /* Set SEL timeout */
|
||||
#define CMD_BUSON_TIME 0x07 /* set bus-On time */
|
||||
#define CMD_BUSOFF_TIME 0x08 /* set bus-off time */
|
||||
#define CMD_DMASPEED 0x09 /* set ISA DMA speed */
|
||||
#define CMD_RETDEVS 0x0A /* return installed devices */
|
||||
#define CMD_RETCONF 0x0B /* return configuration data */
|
||||
#define CMD_TARGET 0x0C /* set HBA to target mode */
|
||||
#define CMD_RETSETUP 0x0D /* return setup data */
|
||||
#define CMD_WRITE_CH2 0x1A /* write channel 2 buffer */
|
||||
#define CMD_READ_CH2 0x1B /* read channel 2 buffer */
|
||||
#define CMD_ECHO 0x1F /* ECHO command data */
|
||||
#define CMD_OPTIONS 0x21 /* set adapter options */
|
||||
|
||||
/* READ INTERRUPT STATUS. */
|
||||
#define INTR_ANY 0x80 /* any interrupt */
|
||||
#define INTR_SRCD 0x08 /* SCSI reset detected */
|
||||
#define INTR_HACC 0x04 /* HA command complete */
|
||||
#define INTR_MBOA 0x02 /* MBO empty */
|
||||
#define INTR_MBIF 0x01 /* MBI full */
|
||||
|
||||
|
||||
/* Structure for the INQUIRE_SETUP_INFORMATION reply. */
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint8_t uOffset :4,
|
||||
uTransferPeriod :3,
|
||||
fSynchronous :1;
|
||||
} ReplyInquireSetupInformationSynchronousValue;
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint8_t fSynchronousInitiationEnabled :1,
|
||||
fParityCheckingEnabled :1,
|
||||
uReserved1 :6;
|
||||
uint8_t uBusTransferRate;
|
||||
uint8_t uPreemptTimeOnBus;
|
||||
uint8_t uTimeOffBus;
|
||||
uint8_t cMailbox;
|
||||
addr24 MailboxAddress;
|
||||
ReplyInquireSetupInformationSynchronousValue SynchronousValuesId0To7[8];
|
||||
uint8_t uDisconnectPermittedId0To7;
|
||||
uint8_t VendorSpecificData[28];
|
||||
} ReplyInquireSetupInformation;
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint8_t Count;
|
||||
addr24 Address;
|
||||
} MailboxInit_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
/*
|
||||
* Mailbox Definitions.
|
||||
*
|
||||
* Mailbox Out (MBO) command values.
|
||||
*/
|
||||
#define MBO_FREE 0x00
|
||||
#define MBO_START 0x01
|
||||
#define MBO_ABORT 0x02
|
||||
|
||||
/* Mailbox In (MBI) status values. */
|
||||
#define MBI_FREE 0x00
|
||||
#define MBI_SUCCESS 0x01
|
||||
#define MBI_ABORT 0x02
|
||||
#define MBI_NOT_FOUND 0x03
|
||||
#define MBI_ERROR 0x04
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint8_t CmdStatus;
|
||||
addr24 CCBPointer;
|
||||
} Mailbox_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint32_t CCBPointer;
|
||||
union {
|
||||
struct {
|
||||
uint8_t Reserved[3];
|
||||
uint8_t ActionCode;
|
||||
} out;
|
||||
struct {
|
||||
uint8_t HostStatus;
|
||||
uint8_t TargetStatus;
|
||||
uint8_t Reserved;
|
||||
uint8_t CompletionCode;
|
||||
} in;
|
||||
} u;
|
||||
} Mailbox32_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
/*
|
||||
*
|
||||
* CCB - SCSI Command Control Block
|
||||
*
|
||||
* The CCB is a superset of the CDB (Command Descriptor Block)
|
||||
* and specifies detailed information about a SCSI command.
|
||||
*
|
||||
*/
|
||||
/* Byte 0 Command Control Block Operation Code */
|
||||
#define SCSI_INITIATOR_COMMAND 0x00
|
||||
#define TARGET_MODE_COMMAND 0x01
|
||||
#define SCATTER_GATHER_COMMAND 0x02
|
||||
#define SCSI_INITIATOR_COMMAND_RES 0x03
|
||||
#define SCATTER_GATHER_COMMAND_RES 0x04
|
||||
#define BUS_RESET 0x81
|
||||
|
||||
/* Byte 1 Address and Direction Control */
|
||||
#define CCB_TARGET_ID_SHIFT 0x06 /* CCB Op Code = 00, 02 */
|
||||
#define CCB_INITIATOR_ID_SHIFT 0x06 /* CCB Op Code = 01 */
|
||||
#define CCB_DATA_XFER_IN 0x01
|
||||
#define CCB_DATA_XFER_OUT 0x02
|
||||
#define CCB_LUN_MASK 0x07 /* Logical Unit Number */
|
||||
|
||||
/* Byte 2 SCSI_Command_Length - Length of SCSI CDB
|
||||
Byte 3 Request Sense Allocation Length */
|
||||
#define FOURTEEN_BYTES 0x00 /* Request Sense Buffer size */
|
||||
#define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */
|
||||
|
||||
/* Bytes 4, 5 and 6 Data Length - Data transfer byte count */
|
||||
/* Bytes 7, 8 and 9 Data Pointer - SGD List or Data Buffer */
|
||||
/* Bytes 10, 11 and 12 Link Pointer - Next CCB in Linked List */
|
||||
/* Byte 13 Command Link ID - TBD (I don't know yet) */
|
||||
/* Byte 14 Host Status - Host Adapter status */
|
||||
#define CCB_COMPLETE 0x00 /* CCB completed without error */
|
||||
#define CCB_LINKED_COMPLETE 0x0A /* Linked command completed */
|
||||
#define CCB_LINKED_COMPLETE_INT 0x0B /* Linked complete with intr */
|
||||
#define CCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */
|
||||
#define CCB_DATA_OVER_UNDER_RUN 0x12
|
||||
#define CCB_UNEXPECTED_BUS_FREE 0x13 /* Trg dropped SCSI BSY */
|
||||
#define CCB_PHASE_SEQUENCE_FAIL 0x14 /* Trg bus phase sequence fail */
|
||||
#define CCB_BAD_MBO_COMMAND 0x15 /* MBO command not 0, 1 or 2 */
|
||||
#define CCB_INVALID_OP_CODE 0x16 /* CCB invalid operation code */
|
||||
#define CCB_BAD_LINKED_LUN 0x17 /* Linked CCB LUN diff from 1st */
|
||||
#define CCB_INVALID_DIRECTION 0x18 /* Invalid target direction */
|
||||
#define CCB_DUPLICATE_CCB 0x19 /* Duplicate CCB */
|
||||
#define CCB_INVALID_CCB 0x1A /* Invalid CCB - bad parameter */
|
||||
|
||||
/* Byte 15 Target Status
|
||||
|
||||
See scsi.h files for these statuses.
|
||||
Bytes 16 and 17 Reserved (must be 0)
|
||||
Bytes 18 through 18+n-1, where n=size of CDB Command Descriptor Block */
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint8_t Opcode;
|
||||
uint8_t Reserved1 :3,
|
||||
ControlByte :2,
|
||||
TagQueued :1,
|
||||
QueueTag :2;
|
||||
uint8_t CdbLength;
|
||||
uint8_t RequestSenseLength;
|
||||
uint32_t DataLength;
|
||||
uint32_t DataPointer;
|
||||
uint8_t Reserved2[2];
|
||||
uint8_t HostStatus;
|
||||
uint8_t TargetStatus;
|
||||
uint8_t Id;
|
||||
uint8_t Lun :5,
|
||||
LegacyTagEnable :1,
|
||||
LegacyQueueTag :2;
|
||||
uint8_t Cdb[12];
|
||||
uint8_t Reserved3[6];
|
||||
uint32_t SensePointer;
|
||||
} CCB32;
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint8_t Opcode;
|
||||
uint8_t Lun :3,
|
||||
ControlByte :2,
|
||||
Id :3;
|
||||
uint8_t CdbLength;
|
||||
uint8_t RequestSenseLength;
|
||||
addr24 DataLength;
|
||||
addr24 DataPointer;
|
||||
addr24 LinkPointer;
|
||||
uint8_t LinkId;
|
||||
uint8_t HostStatus;
|
||||
uint8_t TargetStatus;
|
||||
uint8_t Reserved[2];
|
||||
uint8_t Cdb[12];
|
||||
} CCB;
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint8_t Opcode;
|
||||
uint8_t Pad1 :3,
|
||||
ControlByte :2,
|
||||
Pad2 :3;
|
||||
uint8_t CdbLength;
|
||||
uint8_t RequestSenseLength;
|
||||
uint8_t Pad3[9];
|
||||
uint8_t CompletionCode; /* Only used by the 1542C/CF(/CP?) BIOS mailboxes */
|
||||
uint8_t HostStatus;
|
||||
uint8_t TargetStatus;
|
||||
uint8_t Pad4[2];
|
||||
uint8_t Cdb[12];
|
||||
} CCBC;
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef union {
|
||||
CCB32 new;
|
||||
CCB old;
|
||||
CCBC common;
|
||||
} CCBU;
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
CCBU CmdBlock;
|
||||
uint8_t *RequestSenseBuffer;
|
||||
uint32_t CCBPointer;
|
||||
int Is24bit;
|
||||
uint8_t TargetID,
|
||||
LUN,
|
||||
HostStatus,
|
||||
TargetStatus,
|
||||
MailboxCompletionCode;
|
||||
} Req_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct {
|
||||
int8_t type; /* type of device */
|
||||
|
||||
char vendor[16]; /* name of device vendor */
|
||||
char name[16]; /* name of device */
|
||||
|
||||
volatile
|
||||
int8_t Irq;
|
||||
volatile
|
||||
uint8_t IrqEnabled;
|
||||
|
||||
int8_t DmaChannel;
|
||||
int8_t HostID;
|
||||
uint32_t Base;
|
||||
uint8_t pos_regs[8]; /* MCA */
|
||||
|
||||
wchar_t *bios_path; /* path to BIOS image file */
|
||||
uint32_t rom_addr; /* address of BIOS ROM */
|
||||
uint16_t rom_ioaddr; /* offset in BIOS of I/O addr */
|
||||
uint16_t rom_shram; /* index to shared RAM */
|
||||
uint16_t rom_shramsz; /* size of shared RAM */
|
||||
uint16_t rom_fwhigh; /* offset in BIOS of ver ID */
|
||||
rom_t bios; /* BIOS memory descriptor */
|
||||
rom_t uppersck; /* BIOS memory descriptor */
|
||||
uint8_t *rom1; /* main BIOS image */
|
||||
uint8_t *rom2; /* SCSI-Select image */
|
||||
|
||||
wchar_t *nvr_path; /* path to NVR image file */
|
||||
uint8_t *nvr; /* EEPROM buffer */
|
||||
|
||||
int64_t ResetCB;
|
||||
|
||||
volatile uint8_t /* for multi-threading, keep */
|
||||
Status, /* these volatile */
|
||||
Interrupt;
|
||||
|
||||
Req_t Req;
|
||||
uint8_t Geometry;
|
||||
uint8_t Control;
|
||||
uint8_t Command;
|
||||
uint8_t CmdBuf[128];
|
||||
uint8_t CmdParam;
|
||||
uint8_t CmdParamLeft;
|
||||
uint8_t DataBuf[65536];
|
||||
uint16_t DataReply;
|
||||
uint16_t DataReplyLeft;
|
||||
|
||||
volatile
|
||||
uint32_t MailboxInit,
|
||||
MailboxCount,
|
||||
MailboxOutAddr,
|
||||
MailboxOutPosCur,
|
||||
MailboxInAddr,
|
||||
MailboxInPosCur,
|
||||
MailboxReq;
|
||||
|
||||
volatile
|
||||
int Mbx24bit,
|
||||
MailboxOutInterrupts;
|
||||
|
||||
volatile
|
||||
int PendingInterrupt,
|
||||
Lock;
|
||||
|
||||
volatile
|
||||
uint8_t shadow_ram[128];
|
||||
|
||||
volatile
|
||||
uint8_t MailboxIsBIOS,
|
||||
ToRaise;
|
||||
|
||||
uint8_t shram_mode;
|
||||
|
||||
volatile
|
||||
uint8_t dma_buffer[128];
|
||||
|
||||
volatile
|
||||
uint32_t BIOSMailboxInit,
|
||||
BIOSMailboxCount,
|
||||
BIOSMailboxOutAddr,
|
||||
BIOSMailboxOutPosCur,
|
||||
BIOSMailboxReq,
|
||||
Residue;
|
||||
|
||||
volatile
|
||||
uint8_t BusOnTime,
|
||||
BusOffTime,
|
||||
ATBusSpeed;
|
||||
|
||||
char *fw_rev; /* The 4 bytes of the revision command information + 2 extra bytes for BusLogic */
|
||||
uint8_t bus; /* Basically a copy of device flags */
|
||||
uint8_t setup_info_len;
|
||||
uint8_t max_id;
|
||||
|
||||
uint32_t reset_duration;
|
||||
|
||||
uint8_t pci_slot;
|
||||
|
||||
mem_mapping_t mmio_mapping;
|
||||
|
||||
uint8_t int_geom_writable;
|
||||
|
||||
/* Pointer to a structure of vendor-specific data that only the vendor-specific code can understand */
|
||||
void *ven_data;
|
||||
|
||||
/* Pointer to a function that performs vendor-specific operation during the thread */
|
||||
void (*ven_thread)(void *p);
|
||||
/* Pointer to a function that executes the second parameter phase of the vendor-specific command */
|
||||
void (*ven_cmd_phase1)(void *p);
|
||||
/* Pointer to a function that gets the host adapter ID in case it has to be read from a non-standard location */
|
||||
uint8_t (*ven_get_host_id)(void *p);
|
||||
/* Pointer to a function that updates the IRQ in the vendor-specific space */
|
||||
uint8_t (*ven_get_irq)(void *p);
|
||||
/* Pointer to a function that updates the DMA channel in the vendor-specific space */
|
||||
uint8_t (*ven_get_dma)(void *p);
|
||||
/* Pointer to a function that returns whether command is fast */
|
||||
uint8_t (*ven_cmd_is_fast)(void *p);
|
||||
/* Pointer to a function that executes vendor-specific fast path commands */
|
||||
uint8_t (*ven_fast_cmds)(void *p, uint8_t cmd);
|
||||
/* Pointer to a function that gets the parameter length for vendor-specific commands */
|
||||
uint8_t (*get_ven_param_len)(void *p);
|
||||
/* Pointer to a function that executes vendor-specific commands and returns whether or not to suppress the IRQ */
|
||||
uint8_t (*ven_cmds)(void *p);
|
||||
/* Pointer to a function that fills in the vendor-specific setup data */
|
||||
void (*get_ven_data)(void *p);
|
||||
/* Pointer to a function that determines if the mode is aggressive */
|
||||
uint8_t (*is_aggressive_mode)(void *p);
|
||||
/* Pointer to a function that returns interrupt type (0 = edge, 1 = level) */
|
||||
uint8_t (*interrupt_type)(void *p);
|
||||
/* Pointer to a function that resets vendor-specific data */
|
||||
void (*ven_reset)(void *p);
|
||||
} x54x_t;
|
||||
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct
|
||||
{
|
||||
uint8_t command;
|
||||
uint8_t lun:3,
|
||||
reserved:2,
|
||||
id:3;
|
||||
union {
|
||||
struct {
|
||||
uint16_t cyl;
|
||||
uint8_t head;
|
||||
uint8_t sec;
|
||||
} chs;
|
||||
struct {
|
||||
uint8_t lba0; /* MSB */
|
||||
uint8_t lba1;
|
||||
uint8_t lba2;
|
||||
uint8_t lba3; /* LSB */
|
||||
} lba;
|
||||
} u;
|
||||
uint8_t secount;
|
||||
addr24 dma_address;
|
||||
} BIOSCMD;
|
||||
#pragma pack(pop)
|
||||
#define lba32_blk(p) ((uint32_t)(p->u.lba.lba0<<24) | (p->u.lba.lba1<<16) | \
|
||||
(p->u.lba.lba2<<8) | p->u.lba.lba3)
|
||||
|
||||
|
||||
|
||||
extern void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset);
|
||||
extern void x54x_busy_set(void);
|
||||
extern void x54x_thread_start(x54x_t *dev);
|
||||
extern void x54x_busy_clear(void);
|
||||
extern uint8_t x54x_busy(void);
|
||||
extern void x54x_buf_alloc(uint8_t id, uint8_t lun, int length);
|
||||
extern void x54x_buf_free(uint8_t id, uint8_t lun);
|
||||
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);
|
||||
extern void x54x_io_remove(x54x_t *dev, uint32_t base);
|
||||
extern void x54x_mem_init(x54x_t *dev, uint32_t addr);
|
||||
extern void x54x_mem_enable(x54x_t *dev);
|
||||
extern void x54x_mem_set_addr(x54x_t *dev, uint32_t base);
|
||||
extern void x54x_mem_disable(x54x_t *dev);
|
||||
extern void *x54x_init(device_t *info);
|
||||
extern void x54x_close(void *priv);
|
||||
extern void x54x_device_reset(void *priv);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user