DevBusLogic.cpp revision e7737e2f1d45cdadb6807be7db98f1313933204e
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * VBox storage devices: BusLogic SCSI host adapter BT-958.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Copyright (C) 2006-2009 Oracle Corporation
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * This file is part of VirtualBox Open Source Edition (OSE), as
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * available from http://www.virtualbox.org. This file is free software;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * you can redistribute it and/or modify it under the terms of the GNU
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * General Public License (GPL) as published by the Free Software
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Foundation, in version 2 as it comes in the "COPYING" file of the
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/* Implemented looking at the driver source in the linux kernel (drivers/scsi/BusLogic.[ch]).
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/*******************************************************************************
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk* Header Files *
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk*******************************************************************************/
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk//#define DEBUG
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/* Maximum number of attached devices the adapter can handle. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/* Maximum number of scatter gather elements this device can handle. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk#define BUSLOGIC_MAX_SCATTER_GATHER_LIST_SIZE 128
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/* Size of the command buffer. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/* Size of the reply buffer. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/* I/O port registered in the ISA compatible range to let the BIOS access
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * the controller.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/** State saved version. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/** Saved state version before the suspend on error feature was implemented. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk#define BUSLOGIC_SAVED_STATE_MINOR_PRE_ERROR_HANDLING 1
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * State of a device attached to the buslogic host adapter.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @implements PDMIBASE
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @implements PDMISCSIPORT
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @implements PDMILEDPORTS
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Pointer to the owning buslogic device instance. - R3 pointer */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Pointer to the owning buslogic device instance. - R0 pointer */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Pointer to the owning buslogic device instance. - RC pointer */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Flag whether device is present. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** LUN of the device. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Our base interface. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** SCSI port interface. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Led interface. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Pointer to the attached driver's base interface. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Pointer to the underlying SCSI connector interface. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk R3PTRTYPE(PPDMISCSICONNECTOR) pDrvSCSIConnector;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** The status LED state for this device. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Number of outstanding tasks on the port. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Commands the BusLogic adapter supports.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_TEST_COMMAND_COMPLETE_INTERRUPT = 0x00,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_ENABLE_OUTGOING_MAILBOX_AVAILABLE_INTERRUPT = 0x05,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_SET_SCSI_SELECTION_TIMEOUT = 0x06,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_INQUIRE_INSTALLED_DEVICES_ID_0_TO_7 = 0x0a,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_INQUIRE_SETUP_INFORMATION = 0x0d,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_WRITE_BUSMASTER_CHIP_FIFO = 0x1c,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_READ_BUSMASTER_CHIP_FIFO = 0x1d,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_INQUIRE_INSTALLED_DEVICES_ID_8_TO_15 = 0x23,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_DISABLE_HOST_ADAPTER_INTERRUPT = 0x25,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_INITIALIZE_EXTENDED_MAILBOX = 0x81,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_INQUIRE_FIRMWARE_VERSION_3RD_LETTER = 0x84,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_INQUIRE_FIRMWARE_VERSION_LETTER = 0x85,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_INQUIRE_PCI_HOST_ADAPTER_INFORMATION = 0x86,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_INQUIRE_HOST_ADAPTER_MODEL_NUMBER = 0x8b,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_INQUIRE_SYNCHRONOUS_PERIOD = 0x8c,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_INQUIRE_EXTENDED_SETUP_INFORMATION = 0x8d,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_ENABLE_STRICT_ROUND_ROBIN_MODE = 0x8f,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_STORE_HOST_ADAPTER_LOCAL_RAM = 0x90,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_FETCH_HOST_ADAPTER_LOCAL_RAM = 0x91,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_STORE_LOCAL_DATA_IN_EEPROM = 0x92,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICCOMMAND_FLASH_ROM_UPLOAD_DOWNLOAD = 0xa7,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Auto SCSI structure which is located
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * in host adapter RAM and contains several
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * configuration parameters.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk uint16_t u16NonTaggedToAlternateLunPermittedMask;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk uint16_t u16RenegotiateSyncAfterCheckConditionMask;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * The local Ram.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* Byte view. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* Structured view. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Offset 0 - 63 is for BIOS. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Auto SCSI structure. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/** Pointer to a task state structure. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenktypedef struct BUSLOGICTASKSTATE *PBUSLOGICTASKSTATE;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Main BusLogic device state.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @extends PCIDEVICE
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @implements PDMILEDPORTS
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenktypedef struct BUSLOGIC
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** The PCI device structure. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Pointer to the device instance - HC ptr */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Pointer to the device instance - R0 ptr */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Pointer to the device instance - RC ptr. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Whether R0 is enabled. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Whether RC is enabled. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Base address of the I/O ports. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Base address of the memory mapping. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Status register - Readonly. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Interrupt register - Readonly. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Geometry register - Readonly. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Local RAM for the fetch hostadapter local RAM request.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * I don't know how big the buffer really is but the maximum
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * seems to be 256 bytes because the offset and count field in the command request
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * are only one byte big.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Command code the guest issued. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Buffer for the command parameters the adapter is currently receiving from the guest.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Size of the largest command which is possible.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk uint8_t aCommandBuffer[BUSLOGIC_COMMAND_SIZE_MAX]; /* Size of the biggest request. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Current position in the command buffer. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Parameters left until the command is complete. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Whether we are using the RAM or reply buffer. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Buffer to store reply data from the controller to the guest. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk uint8_t aReplyBuffer[BUSLOGIC_REPLY_SIZE_MAX]; /* Size of the biggest reply. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Position in the buffer we are reading next. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Bytes left until the reply buffer is empty. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Flag whether IRQs are enabled. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Flag whether the ISA I/O port range is disabled
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * to prevent the BIOs to access the device. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Number of mailboxes the guest set up. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Physical base address of the outgoing mailboxes. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Current outgoing mailbox position. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Number of mailboxes ready. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Whether a notification to R3 was send. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Physical base address of the incoming mailboxes. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Current incoming mailbox position. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Whether strict round robin is enabled. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Whether the extended LUN CCB format is enabled for 32 possible logical units. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Queue to send tasks to R3. - HC ptr */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Queue to send tasks to R3. - HC ptr */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Queue to send tasks to R3. - RC ptr */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Critical section protecting access to the interrupt status register. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Cache for task states. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** Device state for BIOS access. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /** BusLogic device states. */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk BUSLOGICDEVICE aDeviceStates[BUSLOGIC_MAX_DEVICES];
bool volatile fSignalIdle;
bool volatile fRedo;
typedef struct ReplyInquirePCIHostAdapterInformation
#pragma pack()
typedef struct ReplyInquireConfiguration
#pragma pack()
typedef struct ReplyInquireSetupInformationSynchronousValue
#pragma pack()
typedef struct ReplyInquireSetupInformation
#pragma pack()
typedef struct ReplyInquireExtendedSetupInformation
#pragma pack()
typedef struct RequestInitializeExtendedMailbox
#pragma pack()
typedef struct Mailbox
} out;
} in;
#pragma pack()
enum BUSLOGIC_CCB_OPCODE
typedef struct CommandControlBlock
#pragma pack()
typedef struct ScatterGatherEntry
#pragma pack()
typedef struct BUSLOGICTASKSTATE
bool fBIOS;
#ifndef VBOX_DEVICE_STRUCT_TESTCASE
#define PDMIBASE_2_PBUSLOGICDEVICE(pInterface) ( (PBUSLOGICDEVICE)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGICDEVICE, IBase)) )
#define PDMISCSIPORT_2_PBUSLOGICDEVICE(pInterface) ( (PBUSLOGICDEVICE)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGICDEVICE, ISCSIPort)) )
#define PDMILEDPORTS_2_PBUSLOGICDEVICE(pInterface) ( (PBUSLOGICDEVICE)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGICDEVICE, ILed)) )
#define PDMIBASE_2_PBUSLOGIC(pInterface) ( (PBUSLOGIC)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGIC, IBase)) )
#define PDMILEDPORTS_2_PBUSLOGIC(pInterface) ( (PBUSLOGIC)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGIC, ILeds)) )
#if defined(IN_RING3)
pBusLogic->LocalRam.structured.autoSCSIData.fExtendedTranslation = true; /* Same as in geometry register. */
pBusLogic->LocalRam.structured.autoSCSIData.u16DeviceEnabledMask = ~0; /* All enabled. Maybe mask out non present devices? */
pBusLogic->LocalRam.structured.autoSCSIData.fStrictRoundRobinMode = pBusLogic->fStrictRoundRobinMode;
pBusLogic->regStatus = BUSLOGIC_REGISTER_STATUS_HOST_ADAPTER_READY | BUSLOGIC_REGISTER_STATUS_INITIALIZATION_REQUIRED;
return VINF_SUCCESS;
#if defined(IN_RING3)
RTGCPHYS GCPhysAddrMailboxIncoming = pBusLogic->GCPhysAddrMailboxIncomingBase + (pBusLogic->uMailboxIncomingPositionCurrent * sizeof(Mailbox));
PDMDevHlpPhysWrite(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrCCB, &pTaskState->CommandControlBlockGuest, sizeof(CommandControlBlock));
PDMDevHlpPhysWrite(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrMailboxIncoming, &pTaskState->MailboxGuest, sizeof(Mailbox));
#if defined(DEBUG)
if (fOutgoing)
if ( (pTaskState->CommandControlBlockGuest.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER)
|| (pTaskState->CommandControlBlockGuest.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
ScatterGatherEntry aScatterGatherReadGC[32]; /* Number of scatter gather list entries read from guest memory. */
uint32_t cScatterGatherGCLeft = pTaskState->CommandControlBlockGuest.cbData / sizeof(ScatterGatherEntry);
RTGCPHYS GCPhysAddrScatterGatherCurrent = (RTGCPHYS)pTaskState->CommandControlBlockGuest.u32PhysAddrData;
} while (cScatterGatherGCLeft > 0);
return VERR_NO_MEMORY;
Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u\n", __FUNCTION__, GCPhysAddrDataBase, cbDataToTransfer));
} while (cScatterGatherGCLeft > 0);
|| pTaskState->CommandControlBlockGuest.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH)
return VERR_NO_MEMORY;
PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, pTaskState->DataSeg.pvSeg, pTaskState->DataSeg.cbSeg);
return VINF_SUCCESS;
if ( (pTaskState->CommandControlBlockGuest.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER)
|| (pTaskState->CommandControlBlockGuest.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
ScatterGatherEntry aScatterGatherReadGC[32]; /* Number of scatter gather list entries read from guest memory. */
uint32_t cScatterGatherGCLeft = pTaskState->CommandControlBlockGuest.cbData / sizeof(ScatterGatherEntry);
RTGCPHYS GCPhysAddrScatterGatherCurrent = (RTGCPHYS)pTaskState->CommandControlBlockGuest.u32PhysAddrData;
Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u\n", __FUNCTION__, GCPhysAddrDataBase, cbDataToTransfer));
} while (cScatterGatherGCLeft > 0);
|| pTaskState->CommandControlBlockGuest.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH)
PDMDevHlpPhysWrite(pDevIns, GCPhysAddrDataBase, pTaskState->DataSeg.pvSeg, pTaskState->DataSeg.cbSeg);
RTGCPHYS GCPhysAddrSenseBuffer = (RTGCPHYS)pTaskState->CommandControlBlockGuest.u32PhysAddrSenseData;
if (fCopy)
* @note Current assumption is that the sense buffer is not scattered and does not cross a page boundary.
return VERR_NO_MEMORY;
return VINF_SUCCESS;
bool fSuppressIrq = false;
PReplyInquirePCIHostAdapterInformation pReply = (PReplyInquirePCIHostAdapterInformation)pBusLogic->aReplyBuffer;
fSuppressIrq = true;
for (int i = 0; i < cCharsToTransfer; i++)
PReplyInquireExtendedSetupInformation pReply = (PReplyInquireExtendedSetupInformation)pBusLogic->aReplyBuffer;
PRequestInitializeExtendedMailbox pRequest = (PRequestInitializeExtendedMailbox)pBusLogic->aCommandBuffer;
pBusLogic->GCPhysAddrMailboxIncomingBase = (RTGCPHYS)pRequest->uMailboxBaseAddress + (pBusLogic->cMailbox * sizeof(Mailbox));
pBusLogic->aReplyBuffer[i] = 0; /* @todo Figure if we need something other here. It's not needed for the linux driver */
fSuppressIrq = true;
Log(("uOperationCode=%#x, cbReplyParametersLeft=%d\n", pBusLogic->uOperationCode, pBusLogic->cbReplyParametersLeft));
return rc;
switch (iRegister)
case BUSLOGIC_REGISTER_STATUS:
case BUSLOGIC_REGISTER_DATAIN:
return rc;
switch (iRegister)
return rc;
#ifdef IN_RING3
return rc;
pBusLogic->regStatus &= ~(BUSLOGIC_REGISTER_STATUS_HOST_ADAPTER_READY | BUSLOGIC_REGISTER_STATUS_COMMAND_INVALID);
return rc;
return VINF_SUCCESS;
return VINF_SUCCESS;
return rc;
#ifdef IN_RING3
int rc;
return VINF_SUCCESS;
return rc;
int rc;
rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_DISKFULL",
N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
int rc;
rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_FILETOOBIG",
N_("Host system reported that the file size limit of the host file system has been exceeded. VM execution is suspended. You need to move your virtual hard disk to a filesystem which allows bigger files"));
int rc;
rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_ISCSIDOWN",
N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
int rc2;
LogRel(("BusLogic#%d: Unknown but recoverable error has occurred (rc=%Rrc)\n", pDevIns->iInstance, rc));
rc2 = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_UNKNOWN",
N_("An unknown but recoverable I/O error has occurred (rc=%Rrc). VM execution is suspended. You can resume when the error is fixed"), rc);
int rc;
ScsiInquiryData.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_NOT_CONNECTED_NOT_SUPPORTED;
rc = pTaskState->CTX_SUFF(pTargetDevice)->pDrvSCSIConnector->pfnSCSIRequestSend(pTaskState->CTX_SUFF(pTargetDevice)->pDrvSCSIConnector,
return rc;
int rc;
return VINF_SUCCESS;
return VINF_SUCCESS;
static DECLCALLBACK(int) buslogicIsaIOPortWriteStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrSrc, PRTGCUINTREG pcTransfer, unsigned cb)
int rc;
return rc;
static DECLCALLBACK(int) buslogicIsaIOPortReadStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrDst, PRTGCUINTREG pcTransfer, unsigned cb)
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
static DECLCALLBACK(int) buslogicDeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
int rc;
if (fRedo)
return VINF_SUCCESS;
static DECLCALLBACK(int) buslogicQueryDeviceLocation(PPDMISCSIPORT pInterface, const char **ppcszController,
return VINF_SUCCESS;
PBUSLOGICDEVICE pTargetDevice = &pBusLogic->aDeviceStates[pTaskState->CommandControlBlockGuest.uTargetId];
#ifdef DEBUG
/* Check if device is present on bus. If not return error immediately and don't process this further. */
AssertMsgFailed(("Invalid data direction type %d\n", pTaskState->CommandControlBlockGuest.uDataDirection));
rc = pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pTargetDevice->pDrvSCSIConnector, &pTaskState->PDMScsiRequest);
return rc;
int rc;
AssertMsgReturn(RT_SUCCESS(rc) && (pTaskState != NULL), ("Failed to get task state from cache\n"), rc);
GCPhysAddrMailboxCurrent = pBusLogic->GCPhysAddrMailboxOutgoingBase + (pBusLogic->uMailboxOutgoingPositionCurrent * sizeof(Mailbox));
GCPhysAddrMailboxCurrent = pBusLogic->GCPhysAddrMailboxOutgoingBase + (pBusLogic->uMailboxOutgoingPositionCurrent * sizeof(Mailbox));
#ifdef DEBUG
else if (pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_ABORT_COMMAND)
AssertMsgFailed(("Invalid outgoing mailbox action code %u\n", pTaskState->MailboxGuest.u.out.uActionCode));
PDMDevHlpPhysWrite(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrMailboxCurrent, &pTaskState->MailboxGuest, sizeof(Mailbox));
return rc;
if (!cMailboxesReady)
int rc;
} while (--cMailboxesReady > 0);
while (pTaskState)
return VINF_SSM_DONT_CALL_AGAIN;
while (pTaskState)
cTasks++;
while (pTaskState)
return VINF_SUCCESS;
static DECLCALLBACK(int) buslogicLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
bool fPresent;
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Target %u config mismatch: config=%RTbool state=%RTbool"), i, pDevice->fPresent, fPresent);
return VINF_SUCCESS;
if (cTasks)
if (!pTaskState)
return rc;
static DECLCALLBACK(int) buslogicDeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
if (iLUN == 0)
return VINF_SUCCESS;
return VERR_PDM_LUN_NOT_FOUND;
return NULL;
static DECLCALLBACK(int) buslogicStatusQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
return VINF_SUCCESS;
return VERR_PDM_LUN_NOT_FOUND;
return NULL;
if (fPowerOff)
while (pTaskState)
int rc;
AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE);
return rc;
uint32_t i;
for (i = 0; i < BUSLOGIC_MAX_DEVICES; i++)
while (pTaskState)
return rc;
bool fBootable = true;
return rc;
return rc;
return rc;
if (fBootable)
return rc;
AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE);
return rc;
return rc;
sizeof(BUSLOGIC),
NULL,
NULL,
NULL,
NULL,
NULL,