From 5a87f91bc521c3e84e3dc198129fdb0b6b32c186 Mon Sep 17 00:00:00 2001 From: waltje Date: Sun, 7 May 2017 23:42:05 -0400 Subject: [PATCH] Splitting Buslogic and Aha154x up, cleanups. First phase. --- src/CPU/808x.c | 2 - src/ibm.h | 27 +- src/scsi.c | 1 + src/scsi.h | 44 +- src/scsi_aha154x.c | 1996 ++++++++++++++++++++++++++++++++++++++++++- src/scsi_buslogic.c | 771 ++++------------- src/scsi_buslogic.h | 24 +- 7 files changed, 2218 insertions(+), 647 deletions(-) diff --git a/src/CPU/808x.c b/src/CPU/808x.c index 1f6f67cca..c102fa45f 100644 --- a/src/CPU/808x.c +++ b/src/CPU/808x.c @@ -577,7 +577,6 @@ void resetx86() codegen_reset(); x86_was_reset = 1; port_92_clear_reset(); - BuslogicSoftReset(); } void softresetx86() @@ -596,7 +595,6 @@ void softresetx86() x86seg_reset(); x86_was_reset = 1; port_92_clear_reset(); - BuslogicSoftReset(); } static void setznp8(uint8_t val) diff --git a/src/ibm.h b/src/ibm.h index c163e5f15..b191154ec 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -556,13 +556,8 @@ wchar_t pcempath[512]; /*Hard disc*/ -#ifdef __MSC__ -# pragma pack(push,1) -typedef struct -#else -typedef struct __attribute((__packed__)) -#endif -{ +#pragma pack(push,1) +typedef struct { FILE *f; uint64_t spt,hpc; /*Sectors per track, heads per cylinder*/ uint64_t tracks; @@ -575,17 +570,10 @@ typedef struct __attribute((__packed__)) uint8_t scsi_id; uint8_t scsi_lun; } hard_disk_t; -#ifdef __MSC__ -# pragma pack(pop) -#endif +#pragma pack(pop) -#ifdef __MSC__ -# pragma pack(push,1) -typedef struct -#else -typedef struct __attribute((__packed__)) -#endif -{ +#pragma pack(push,1) +typedef struct { /* Stuff for SCSI hard disks. */ uint8_t cdb[16]; uint8_t current_cdb[16]; @@ -619,9 +607,7 @@ typedef struct __attribute((__packed__)) uint64_t base; uint8_t hd_cdb[16]; } scsi_hard_disk_t; -#ifdef __MSC__ -# pragma pack(pop) -#endif +#pragma pack(pop) #define HDC_NUM 16 #define IDE_NUM 8 @@ -744,7 +730,6 @@ uint32_t svga_color_transform(uint32_t color); extern int scale; /* Function prototypes. */ -void BuslogicSoftReset(); int checkio(int port); void closepc(); void codegen_block_end(); diff --git a/src/scsi.c b/src/scsi.c index 3b88ed36b..733e2a0a7 100644 --- a/src/scsi.c +++ b/src/scsi.c @@ -10,6 +10,7 @@ #include "device.h" #include "cdrom.h" #include "scsi.h" +#include "scsi_aha154x.h" #include "scsi_buslogic.h" diff --git a/src/scsi.h b/src/scsi.h index 788dcb7f3..2c9280c29 100644 --- a/src/scsi.h +++ b/src/scsi.h @@ -1,14 +1,14 @@ /* Copyright holders: SA1988 see COPYING for more details */ -#ifndef __SCSI_H__ -#define __SCSI_H__ +#ifndef SCSI_H +#define SCSI_H -#include "timer.h" #define SCSI_TIME (5 * 100 * (1 << TIMER_SHIFT)) -/* SCSI Commands */ + +/* SCSI commands. */ #define GPCMD_TEST_UNIT_READY 0x00 #define GPCMD_REZERO_UNIT 0x01 #define GPCMD_REQUEST_SENSE 0x03 @@ -266,4 +266,40 @@ void scsi_hd_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_l void scsi_hd_command(uint8_t id, uint8_t *cdb); void scsi_hd_callback(uint8_t id); + +#pragma pack(push,1) +typedef struct { + uint8_t hi; + uint8_t mid; + uint8_t lo; +} addr24; +#pragma pack(pop) + +#define ADDR_TO_U32(x) (((x).hi<<16)|((x).mid<<8)|((x).lo&0xFF)) +#define U32_TO_ADDR(a,x) do {(a).hi=(x)>>16;(a).mid=(x)>>8;(a).lo=(x)&0xFF;}while(0) + + +/* + * + * Scatter/Gather Segment List Definitions + * + * Adapter limits + */ +#define MAX_SG_DESCRIPTORS 32 /* Always make the array 32 elements long, if less are used, that's not an issue. */ + +#pragma pack(push,1) +typedef struct { + uint32_t Segment; + uint32_t SegmentPointer; +} SGE32; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct { + addr24 Segment; + addr24 SegmentPointer; +} SGE; +#pragma pack(pop) + + #endif diff --git a/src/scsi_aha154x.c b/src/scsi_aha154x.c index 2161fa934..253d4929c 100644 --- a/src/scsi_aha154x.c +++ b/src/scsi_aha154x.c @@ -6,24 +6,34 @@ * * This file is part of the 86Box distribution. * - * Implementation of several low-level support functions for - * the AHA-154x series of ISA Host Adapters made by Adaptec. - * These functions implement the support needed by the ROM - * BIOS of these cards. + * Implementation of the AHA-154x series of SCSI Host Adapters + * made by Adaptec, Inc. These controllers were designed for + * the ISA bus. * - * Version: @(#)scsi_aha154x.c 1.0.5 2017/05/05 + * NOTE: THIS IS CURRENTLY A MESS, but will be cleaned up as I go. * - * Author: Fred N. van Kempen, + * Version: @(#)scsi_aha154x.c 1.0.6 2017/05/06 + * + * Authors: Fred N. van Kempen, + * Original Buslogic version by SA1988. * Copyright 2017 Fred N. van Kempen. */ +#include #include #include #include +#include #include "ibm.h" +#include "io.h" #include "mem.h" #include "rom.h" +#include "dma.h" +#include "pic.h" +#include "timer.h" #include "device.h" -#include "scsi_buslogic.h" +#include "cdrom.h" +#include "scsi.h" +#include "scsi_aha154x.h" #define AHA AHA154xCF /* set desired card type */ @@ -100,6 +110,61 @@ #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_BIOS 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_ECHO 0x1F /* ECHO command data */ + +/* 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 */ + + static rom_t aha_bios; /* active ROM */ static uint8_t *aha_rom1; /* main BIOS */ static uint8_t *aha_rom2; /* SCSI-Select */ @@ -192,8 +257,8 @@ aha_patch(uint8_t *romptr, uint16_t ioaddr) /* Initialize AHA-154xNN-specific stuff. */ -void -aha154x_init(uint16_t ioaddr, uint32_t memaddr, aha_info *aha) +static void +aha154x_bios(uint16_t ioaddr, uint32_t memaddr, aha_info *aha) { uint32_t bios_size; uint32_t bios_addr; @@ -335,7 +400,7 @@ again: /* Mess with the AHA-154xCF's Shadow RAM. */ -uint8_t +static uint8_t aha154x_shram(uint8_t cmd) { #ifdef ROM_SHRAM @@ -359,7 +424,7 @@ aha154x_shram(uint8_t cmd) } -uint8_t +static uint8_t aha154x_eeprom(uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8_t *bufp) { uint8_t r = 0xff; @@ -387,7 +452,7 @@ aha154x_eeprom(uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8_t *bufp) } -uint8_t +static uint8_t aha154x_memory(uint8_t cmd) { uint8_t r = 0xff; @@ -405,3 +470,1910 @@ aha154x_memory(uint8_t cmd) return(0); } + + +#define AHA_RESET_DURATION_NS UINT64_C(50000000) + + +/* + * Auto SCSI structure which is located in host adapter RAM + * and contains several configuration parameters. + */ +#pragma pack(push,1) +typedef struct { + uint8_t aInternalSignature[2]; + uint8_t cbInformation; + uint8_t aHostAdaptertype[6]; + uint8_t uReserved1; + uint8_t fFloppyEnabled :1, + fFloppySecondary :1, + fLevelSensitiveInterrupt:1, + uReserved2 :2, + uSystemRAMAreForBIOS :3; + uint8_t uDMAChannel :7, + fDMAAutoConfiguration :1, + uIrqChannel :7, + fIrqAutoConfiguration :1; + uint8_t uDMATransferRate; + uint8_t uSCSIId; + uint8_t fLowByteTerminated :1, + fParityCheckingEnabled :1, + fHighByteTerminated :1, + fNoisyCablingEnvironment:1, + fFastSyncNegotiation :1, + fBusResetEnabled :1, + fReserved3 :1, + fActiveNegotiationEna :1; + uint8_t uBusOnDelay; + uint8_t uBusOffDelay; + uint8_t fHostAdapterBIOSEnabled :1, + fBIOSRedirectionOfInt19 :1, + fExtendedTranslation :1, + fMapRemovableAsFixed :1, + fReserved4 :1, + fBIOSMoreThan2Drives :1, + fBIOSInterruptMode :1, + fFlopticalSupport :1; + uint16_t u16DeviceEnabledMask; + uint16_t u16WidePermittedMask; + uint16_t u16FastPermittedMask; + uint16_t u16SynchronousPermittedMask; + uint16_t u16DisconnectPermittedMask; + uint16_t u16SendStartUnitCommandMask; + uint16_t u16IgnoreInBIOSScanMask; + unsigned char uPCIInterruptPin : 2; + unsigned char uHostAdapterIoPortAddress : 2; + uint8_t fStrictRoundRobinMode : 1; + uint8_t fVesaBusSpeedGreaterThan33MHz : 1; + uint8_t fVesaBurstWrite : 1; + uint8_t fVesaBurstRead : 1; + uint16_t u16UltraPermittedMask; + uint32_t uReserved5; + uint8_t uReserved6; + uint8_t uAutoSCSIMaximumLUN; + uint8_t fReserved7 : 1; + uint8_t fSCAMDominant : 1; + uint8_t fSCAMenabled : 1; + uint8_t fSCAMLevel2 : 1; + unsigned char uReserved8 : 4; + uint8_t fInt13Extension : 1; + uint8_t fReserved9 : 1; + uint8_t fCDROMBoot : 1; + unsigned char uReserved10 : 5; + unsigned char uBootTargetId : 4; + unsigned char uBootChannel : 4; + uint8_t fForceBusDeviceScanningOrder : 1; + unsigned char uReserved11 : 7; + uint16_t u16NonTaggedToAlternateLunPermittedMask; + uint16_t u16RenegotiateSyncAfterCheckConditionMask; + uint8_t aReserved12[10]; + uint8_t aManufacturingDiagnostic[2]; + uint16_t u16Checksum; +} AutoSCSIRam; +#pragma pack(pop) + +/* The local RAM. */ +#pragma pack(push,1) +typedef union { + uint8_t u8View[256]; /* byte view */ + struct { /* structured view */ + uint8_t u8Bios[64]; /* offset 0 - 63 is for BIOS */ + AutoSCSIRam autoSCSIData; /* Auto SCSI structure */ + } structured; +} HALocalRAM; +#pragma pack(pop) + +/* 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 uSignature; + uint8_t uCharacterD; + uint8_t uHostBusType; + uint8_t uWideTransferPermittedId0To7; + uint8_t uWideTransfersActiveId0To7; + ReplyInquireSetupInformationSynchronousValue SynchronousValuesId8To15[8]; + uint8_t uDisconnectPermittedId8To15; + uint8_t uReserved2; + uint8_t uWideTransferPermittedId8To15; + uint8_t uWideTransfersActiveId8To15; +} ReplyInquireSetupInformation; +#pragma pack(pop) + +/* Structure for the INQUIRE_EXTENDED_SETUP_INFORMATION. */ +#pragma pack(push,1) +typedef struct { + uint8_t uBusType; + uint8_t uBiosAddress; + uint16_t u16ScatterGatherLimit; + uint8_t cMailbox; + uint32_t uMailboxAddressBase; + uint8_t uReserved1 :2, + fFastEISA :1, + uReserved2 :3, + fLevelSensitiveInterrupt:1, + uReserved3 :1; + uint8_t aFirmwareRevision[3]; + uint8_t fHostWideSCSI :1, + fHostDifferentialSCSI :1, + fHostSupportsSCAM :1, + fHostUltraSCSI :1, + fHostSmartTermination :1, + uReserved4 :3; +} ReplyInquireExtendedSetupInformation; +#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[10]; + 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; + uint8_t LUN; + uint8_t HostStatus; + uint8_t TargetStatus; + uint8_t MailboxCompletionCode; +} Req_t; +#pragma pack(pop) + + +#pragma pack(push,1) +typedef struct { + rom_t bios; + int UseLocalRAM; + int StrictRoundRobinMode; + int ExtendedLUNCCBFormat; + HALocalRAM LocalRAM; + Req_t Req; + uint8_t Status; + uint8_t Interrupt; + uint8_t Geometry; + uint8_t Control; + uint8_t Command; + uint8_t CmdBuf[53]; + uint8_t CmdParam; + uint8_t CmdParamLeft; + uint8_t DataBuf[64]; + uint16_t DataReply; + uint16_t DataReplyLeft; + uint32_t MailboxCount; + uint32_t MailboxOutAddr; + uint32_t MailboxOutPosCur; + uint32_t MailboxInAddr; + uint32_t MailboxInPosCur; + int Base; + int Irq; + int DmaChannel; + int IrqEnabled; + int Mbx24bit; + int MailboxOutInterrupts; + int MbiActive[256]; + int PendingInterrupt; + int Lock; + mem_mapping_t mmio_mapping; + aha_info aha; + int chip; +} aha_t; +#pragma pack(pop) + + +static int ResetCB = 0; +static int AHA_Callback = 0; +static int AHA_InOperation = 0; +static aha_t *ResetDev; + + +enum { + CHIP_AHA154XB, + CHIP_AHA154XCF +}; + + +#ifdef WALTJE +int aha_do_log = 1; +# define ENABLE_AHA154X_LOG +#else +int aha_do_log = 0; +#endif + + +static void +aha_log(const char *format, ...) +{ +#ifdef ENABLE_AHA154X_LOG + va_list ap; + + if (aha_do_log) { + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + fflush(stdout); + } +#endif +} +#define pclog aha_log + + +static void +ClearIntr(aha_t *dev) +{ + dev->Interrupt = 0; + pclog("AHA154X: lowering IRQ %i (stat 0x%02x)\n", + dev->Irq, dev->Interrupt); + picintc(1 << dev->Irq); + if (dev->PendingInterrupt) { + dev->Interrupt = dev->PendingInterrupt; + pclog("AHA154X: Raising Interrupt 0x%02X (Pending)\n", dev->Interrupt); + if (dev->MailboxOutInterrupts || !(dev->Interrupt & INTR_MBOA)) { + if (dev->IrqEnabled) picint(1 << dev->Irq); + } + dev->PendingInterrupt = 0; + } +} + + +static void +RaiseIntr(aha_t *dev, uint8_t Interrupt) +{ + if (dev->Interrupt & INTR_HACC) { + pclog("Pending IRQ\n"); + dev->PendingInterrupt = Interrupt; + } else { + dev->Interrupt = Interrupt; + pclog("Raising IRQ %i\n", dev->Irq); + if (dev->IrqEnabled) + picint(1 << dev->Irq); + } +} + + +static void +LocalRAM(aha_t *dev) +{ + /* + * These values are mostly from what I think is right + * looking at the dmesg output from a Linux guest inside + * a VMware server VM. + * + * So they don't have to be right :) + */ + memset(dev->LocalRAM.u8View, 0, sizeof(HALocalRAM)); + dev->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 1; + dev->LocalRAM.structured.autoSCSIData.fParityCheckingEnabled = 1; + dev->LocalRAM.structured.autoSCSIData.fExtendedTranslation = 1; /* Same as in geometry register. */ + dev->LocalRAM.structured.autoSCSIData.u16DeviceEnabledMask = UINT16_MAX; /* All enabled. Maybe mask out non present devices? */ + dev->LocalRAM.structured.autoSCSIData.u16WidePermittedMask = UINT16_MAX; + dev->LocalRAM.structured.autoSCSIData.u16FastPermittedMask = UINT16_MAX; + dev->LocalRAM.structured.autoSCSIData.u16SynchronousPermittedMask = UINT16_MAX; + dev->LocalRAM.structured.autoSCSIData.u16DisconnectPermittedMask = UINT16_MAX; + dev->LocalRAM.structured.autoSCSIData.fStrictRoundRobinMode = dev->StrictRoundRobinMode; + dev->LocalRAM.structured.autoSCSIData.u16UltraPermittedMask = UINT16_MAX; + /** @todo calculate checksum? */ +} + + +static void +aha_reset(aha_t *dev) +{ + AHA_Callback = 0; + ResetCB = 0; + dev->Status = STAT_IDLE | STAT_INIT; + dev->Geometry = 0x80; + dev->Command = 0xFF; + dev->CmdParam = 0; + dev->CmdParamLeft = 0; + dev->IrqEnabled = 1; + dev->StrictRoundRobinMode = 0; + dev->ExtendedLUNCCBFormat = 0; + dev->MailboxOutPosCur = 0; + dev->MailboxInPosCur = 0; + dev->MailboxOutInterrupts = 0; + dev->PendingInterrupt = 0; + dev->Lock = 0; + AHA_InOperation = 0; + + ClearIntr(dev); + + LocalRAM(dev); +} + + +static void +aha_softreset(void) +{ + if (ResetDev != NULL) { + aha_reset(ResetDev); + } +} + + +static void +aha_reset_ctrl(aha_t *dev, uint8_t Reset) +{ + aha_reset(dev); + if (Reset) { + dev->Status |= STAT_STST; + dev->Status &= ~STAT_IDLE; + } + ResetCB = AHA_RESET_DURATION_NS * TIMER_USEC; +} + + +static void +aha_cmd_done(aha_t *dev) +{ + dev->DataReply = 0; + dev->Status |= STAT_IDLE; + + if ((dev->Command != 0x02) && (dev->Command != 0x82)) { + dev->Status &= ~STAT_DFULL; + dev->Interrupt = (INTR_ANY | INTR_HACC); + pclog("Raising IRQ %i\n", dev->Irq); + if (dev->IrqEnabled) + picint(1 << dev->Irq); + } + + dev->Command = 0xFF; + dev->CmdParam = 0; +} + + +static void +aha_mbi_setup(aha_t *dev, uint32_t CCBPointer, CCBU *CmdBlock, + uint8_t HostStatus, uint8_t TargetStatus, uint8_t mbcc) +{ + Req_t *req = &dev->Req; + + req->CCBPointer = CCBPointer; + memcpy(&(req->CmdBlock), CmdBlock, sizeof(CCB32)); + req->Is24bit = dev->Mbx24bit; + req->HostStatus = HostStatus; + req->TargetStatus = TargetStatus; + req->MailboxCompletionCode = mbcc; + + pclog("Mailbox in setup\n"); + + AHA_InOperation = 2; +} + + +static void +aha_mbi(aha_t *dev) +{ + Req_t *req = &dev->Req; + uint32_t CCBPointer = req->CCBPointer; + CCBU *CmdBlock = &(req->CmdBlock); + uint8_t HostStatus = req->HostStatus; + uint8_t TargetStatus = req->TargetStatus; + uint8_t MailboxCompletionCode = req->MailboxCompletionCode; + Mailbox32_t Mailbox32; + Mailbox_t MailboxIn; + uint32_t Incoming; + + Mailbox32.CCBPointer = CCBPointer; + Mailbox32.u.in.HostStatus = HostStatus; + Mailbox32.u.in.TargetStatus = TargetStatus; + Mailbox32.u.in.CompletionCode = MailboxCompletionCode; + + Incoming = dev->MailboxInAddr + (dev->MailboxInPosCur * (dev->Mbx24bit ? sizeof(Mailbox_t) : sizeof(Mailbox32_t))); + + if (MailboxCompletionCode != MBI_NOT_FOUND) { + CmdBlock->common.HostStatus = HostStatus; + CmdBlock->common.TargetStatus = TargetStatus; + + /* Rewrite the CCB up to the CDB. */ + pclog("CCB rewritten to the CDB (pointer %08X, length %i)\n", CCBPointer, offsetof(CCBC, Cdb)); + DMAPageWrite(CCBPointer, (char *)CmdBlock, offsetof(CCBC, Cdb)); + } else { + pclog("Mailbox not found!\n"); + } + + pclog("Host Status 0x%02X, Target Status 0x%02X\n",HostStatus,TargetStatus); + + if (dev->Mbx24bit) { + MailboxIn.CmdStatus = Mailbox32.u.in.CompletionCode; + U32_TO_ADDR(MailboxIn.CCBPointer, Mailbox32.CCBPointer); + pclog("Mailbox 24-bit: Status=0x%02X, CCB at 0x%04X\n", MailboxIn.CmdStatus, ADDR_TO_U32(MailboxIn.CCBPointer)); + + DMAPageWrite(Incoming, (char *)&MailboxIn, sizeof(Mailbox_t)); + pclog("%i bytes of 24-bit mailbox written to: %08X\n", sizeof(Mailbox_t), Incoming); + } else { + pclog("Mailbox 32-bit: Status=0x%02X, CCB at 0x%04X\n", Mailbox32.u.in.CompletionCode, Mailbox32.CCBPointer); + + DMAPageWrite(Incoming, (char *)&Mailbox32, sizeof(Mailbox32_t)); + pclog("%i bytes of 32-bit mailbox written to: %08X\n", sizeof(Mailbox32_t), Incoming); + } + + dev->MailboxInPosCur++; + if (dev->MailboxInPosCur >= dev->MailboxCount) + dev->MailboxInPosCur = 0; + + RaiseIntr(dev, INTR_MBIF | INTR_ANY); + + AHA_InOperation = 0; +} + + +static void +aha_rd_sge(int Is24bit, uint32_t SGList, uint32_t Entries, SGE32 *SG) +{ + uint32_t i; + SGE SGE24[MAX_SG_DESCRIPTORS]; + + if (Is24bit) { + DMAPageRead(SGList, (char *)&SGE24, Entries * sizeof(SGE)); + + for (i=0;iCmdBlock.old.DataPointer); + DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); + } else { + DataPointer = req->CmdBlock.new.DataPointer; + DataLength = req->CmdBlock.new.DataLength; + } + pclog("Data Buffer write: length %d, pointer 0x%04X\n", + DataLength, DataPointer); + + if ((req->CmdBlock.common.ControlByte != 0x03) && DataLength) { + if (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND || + req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) { + uint32_t SGRead; + uint32_t ScatterEntry; + SGE32 SGBuffer[MAX_SG_DESCRIPTORS]; + uint32_t SGLeft = DataLength / SGEntryLength; + uint32_t SGAddrCurrent = DataPointer; + uint32_t DataToTransfer = 0; + + do { + SGRead = (SGLeft < ELEMENTS(SGBuffer)) ? SGLeft : ELEMENTS(SGBuffer); + SGLeft -= SGRead; + + aha_rd_sge(Is24bit, SGAddrCurrent, SGRead, SGBuffer); + + for (ScatterEntry = 0; ScatterEntry < SGRead; ScatterEntry++) { + uint32_t Address; + + pclog("BusLogic S/G Write: ScatterEntry=%u\n", ScatterEntry); + + Address = SGBuffer[ScatterEntry].SegmentPointer; + DataToTransfer += SGBuffer[ScatterEntry].Segment; + + pclog("BusLogic S/G Write: Address=%08X DatatoTransfer=%u\n", Address, DataToTransfer); + } + + SGAddrCurrent += SGRead * SGEntryLength; + } while (SGLeft > 0); + + pclog("Data to transfer (S/G) %d\n", DataToTransfer); + + SCSIDevices[req->TargetID][req->LUN].InitLength = DataToTransfer; + + /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without + checking its length, so do this procedure for both no read/write commands. */ + if ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) || + (req->CmdBlock.common.ControlByte == 0x00)) { + SGLeft = DataLength / SGEntryLength; + SGAddrCurrent = DataPointer; + + do { + SGRead = (SGLeft < ELEMENTS(SGBuffer)) ? SGLeft : ELEMENTS(SGBuffer); + SGLeft -= SGRead; + + aha_rd_sge(Is24bit, SGAddrCurrent, + SGRead, SGBuffer); + + for (ScatterEntry = 0; ScatterEntry < SGRead; ScatterEntry++) { + uint32_t Address; + + pclog("BusLogic S/G Write: ScatterEntry=%u\n", ScatterEntry); + + Address = SGBuffer[ScatterEntry].SegmentPointer; + DataToTransfer = SGBuffer[ScatterEntry].Segment; + + pclog("BusLogic S/G Write: Address=%08X DatatoTransfer=%u\n", Address, DataToTransfer); + + DMAPageRead(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer + sg_buffer_pos, DataToTransfer); + sg_buffer_pos += DataToTransfer; + } + + SGAddrCurrent += SGRead * (Is24bit ? sizeof(SGE) : sizeof(SGE32)); + } while (SGLeft > 0); + } + } else if (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND || + req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { + uint32_t Address = DataPointer; + + SCSIDevices[req->TargetID][req->LUN].InitLength = DataLength; + if (DataLength > 0) { + DMAPageRead(Address, + (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer, + SCSIDevices[req->TargetID][req->LUN].InitLength); + } + } + } +} + + +static void +aha_buf_free(Req_t *req) +{ + SGE32 SGBuffer[MAX_SG_DESCRIPTORS]; + uint32_t DataPointer = 0; + uint32_t DataLength = 0; + uint32_t sg_buffer_pos = 0; + uint32_t SGRead; + uint32_t ScatterEntry; + uint32_t SGEntrySize; + uint32_t SGLeft; + uint32_t SGAddrCurrent; + uint32_t Address; + uint32_t Residual; + + if (req->Is24bit) { + DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer); + DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); + } else { + DataPointer = req->CmdBlock.new.DataPointer; + DataLength = req->CmdBlock.new.DataLength; + } + + if ((DataLength != 0) && (req->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY)) { + pclog("Data length not 0 with TEST UNIT READY: %i (%i)\n", + DataLength, SCSIDevices[req->TargetID][req->LUN].InitLength); + } + + if (req->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY) { + DataLength = 0; + } + + pclog("Data Buffer read: length %d, pointer 0x%04X\n", + DataLength, DataPointer); + + /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without + checking its length, so do this procedure for both read/write commands. */ + if ((DataLength > 0) && + ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) || + (req->CmdBlock.common.ControlByte == 0x00))) { + if ((req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND) || + (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { + SGEntrySize = (req->Is24bit ? sizeof(SGE) : sizeof(SGE32)); + SGLeft = DataLength / SGEntrySize; + SGAddrCurrent = DataPointer; + + do { + SGRead = (SGLeft < ELEMENTS(SGBuffer)) ? SGLeft : ELEMENTS(SGBuffer); + SGLeft -= SGRead; + + aha_rd_sge(req->Is24bit, SGAddrCurrent, + SGRead, SGBuffer); + + for (ScatterEntry = 0; ScatterEntry < SGRead; ScatterEntry++) { + uint32_t Address; + uint32_t DataToTransfer; + + pclog("BusLogic S/G: ScatterEntry=%u\n", ScatterEntry); + + Address = SGBuffer[ScatterEntry].SegmentPointer; + DataToTransfer = SGBuffer[ScatterEntry].Segment; + + pclog("BusLogic S/G: Writing %i bytes at %08X\n", DataToTransfer, Address); + + DMAPageWrite(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer + sg_buffer_pos, DataToTransfer); + sg_buffer_pos += DataToTransfer; + } + + SGAddrCurrent += (SGRead * SGEntrySize); + } while (SGLeft > 0); + } else if (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND || + req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { + Address = DataPointer; + + pclog("BusLogic DMA: Writing %i bytes at %08X\n", DataLength, Address); + DMAPageWrite(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer, DataLength); + } + } + + if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) || + (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { + /* Should be 0 when scatter/gather? */ + if (DataLength >= SCSIDevices[req->TargetID][req->LUN].InitLength) { + Residual = DataLength; + Residual -= SCSIDevices[req->TargetID][req->LUN].InitLength; + } else { + Residual = 0; + } + + if (req->Is24bit) { + U32_TO_ADDR(req->CmdBlock.old.DataLength, Residual); + pclog("24-bit Residual data length for reading: %d\n", + ADDR_TO_U32(req->CmdBlock.old.DataLength)); + } else { + req->CmdBlock.new.DataLength = Residual; + pclog("32-bit Residual data length for reading: %d\n", + req->CmdBlock.new.DataLength); + } + } +} + + +static uint8_t +aha_read(uint16_t port, void *priv) +{ + aha_t *dev = (aha_t *)priv; + uint8_t ret; + + switch (port & 3) { + case 0: + ret = dev->Status; + break; + + case 1: + if (dev->UseLocalRAM) + ret = dev->LocalRAM.u8View[dev->DataReply]; + else + ret = dev->DataBuf[dev->DataReply]; + if (dev->DataReplyLeft) { + dev->DataReply++; + dev->DataReplyLeft--; + if (! dev->DataReplyLeft) + aha_cmd_done(dev); + } + break; + + case 2: + ret = dev->Interrupt; + break; + + case 3: + ret = dev->Geometry; + break; + } + + if (port < 0x1000) { + pclog("AHA154X: Read Port 0x%02X, Returned Value %02X\n", port, ret); + } + + return(ret); +} + + +static uint16_t +aha_readw(uint16_t port, void *priv) +{ + return aha_read(port, priv); +} + + +static uint32_t +aha_readl(uint16_t port, void *priv) +{ + return aha_read(port, priv); +} + + +/* This is BS - we just need a 'dev_present' indication.. --FvK */ +static int +aha_dev_present(uint8_t id, uint8_t lun) +{ + if (lun > 7) return(0); + + if (scsi_cdrom_drives[id][lun] >= CDROM_NUM) return(0); + + if (cdrom_drives[scsi_cdrom_drives[id][lun]].enabled && + cdrom_drives[scsi_cdrom_drives[id][lun]].bus_type && + (cdrom_drives[scsi_cdrom_drives[id][lun]].bus_mode & 2)) return(1); + + return(0); +} + + +static void +aha_write(uint16_t port, uint8_t val, void *priv) +{ + int i = 0; + uint8_t j = 0; + aha_t *dev = (aha_t *)priv; + uint8_t max_id = 8; + uint8_t Offset; + MailboxInit_t *MailboxInit; + ReplyInquireSetupInformation *ReplyISI; + ReplyInquireExtendedSetupInformation *ReplyIESI; + int cCharsToTransfer; + + pclog("AHA154X: Write Port 0x%02X, Value %02X\n", port, val); + + switch (port & 3) { + case 0: + if ((val & CTRL_HRST) || (val & CTRL_SRST)) { + uint8_t Reset = !(val & CTRL_HRST); + aha_reset_ctrl(dev, Reset); + break; + } + + if (val & CTRL_IRST) { + ClearIntr(dev); + } + break; + + case 1: + /* Fast path for the mailbox execution command. */ + if (((val == 0x02) || (val == 0x82)) && + (dev->Command == 0xFF)) { + /* If there are no mailboxes configured, don't even try to do anything. */ + if (dev->MailboxCount) { + if (!AHA_Callback) { + AHA_Callback = 50 * SCSI_TIME; + } + } + return; + } + + if (dev->Command == 0xFF) { + dev->Command = val; + dev->CmdParam = 0; + dev->CmdParamLeft = 0; + + dev->Status &= ~(STAT_INVCMD | STAT_IDLE); + pclog("AHA154X: Operation Code 0x%02X\n", val); + switch (dev->Command) { + case 0x01: + dev->CmdParamLeft = sizeof(MailboxInit_t); + break; + + case 0x03: /* Exec BIOS Command */ + dev->CmdParamLeft = 10; + break; + + case 0x25: + /* Same as 0x01 for AHA. */ + dev->CmdParamLeft = sizeof(MailboxInit_t); + break; + + case 0x05: + case 0x07: + case 0x08: + case 0x09: + case 0x0D: + case 0x1F: + case 0x21: + case 0x24: + dev->CmdParamLeft = 1; + break; + + case 0x06: + dev->CmdParamLeft = 4; + break; + + case 0x1C: + case 0x1D: + dev->CmdParamLeft = 3; + break; + + case 0x22: /* write EEPROM */ + dev->CmdParamLeft = 3+32; + break; + + case 0x23: /* read EEPROM */ + dev->CmdParamLeft = 3; + break; + + case 0x29: + dev->CmdParamLeft = 2; + break; + + case 0x91: + dev->CmdParamLeft = 2; + break; + } + } else { + dev->CmdBuf[dev->CmdParam] = val; + dev->CmdParam++; + dev->CmdParamLeft--; + } + + if (! dev->CmdParamLeft) { + pclog("Running Operation Code 0x%02X\n", dev->Command); + switch (dev->Command) { + case 0x00: + dev->DataReplyLeft = 0; + break; + + case 0x01: +aha_0x01: + { + dev->Mbx24bit = 1; + + MailboxInit = (MailboxInit_t *)dev->CmdBuf; + + dev->MailboxCount = MailboxInit->Count; + dev->MailboxOutAddr = ADDR_TO_U32(MailboxInit->Address); + dev->MailboxInAddr = dev->MailboxOutAddr + (dev->MailboxCount * sizeof(Mailbox_t)); + + pclog("Initialize Mailbox Command\n"); + pclog("Mailbox Out Address=0x%08X\n", dev->MailboxOutAddr); + pclog("Mailbox In Address=0x%08X\n", dev->MailboxInAddr); + pclog("Initialized Mailbox, %d entries at 0x%08X\n", MailboxInit->Count, ADDR_TO_U32(MailboxInit->Address)); + + dev->Status &= ~STAT_INIT; + dev->DataReplyLeft = 0; + } + break; + + case 0x03: + dev->DataBuf[0] = 0x00; + dev->DataReplyLeft = 1; + break; + + case 0x04: + dev->DataBuf[0] = dev->aha.bid; + dev->DataBuf[1] = 0x30; + dev->DataBuf[2] = dev->aha.fwh; + dev->DataBuf[3] = dev->aha.fwl; + dev->DataReplyLeft = 4; + break; + + case 0x05: + if (dev->CmdBuf[0] <= 1) { + dev->MailboxOutInterrupts = dev->CmdBuf[0]; + pclog("Mailbox out interrupts: %s\n", dev->MailboxOutInterrupts ? "ON" : "OFF"); + } else { + dev->Status |= STAT_INVCMD; + } + dev->DataReplyLeft = 0; + break; + + case 0x06: + dev->DataReplyLeft = 0; + break; + + case 0x07: + dev->DataReplyLeft = 0; + dev->LocalRAM.structured.autoSCSIData.uBusOnDelay = dev->CmdBuf[0]; + pclog("Bus-on time: %d\n", dev->CmdBuf[0]); + break; + + case 0x08: + dev->DataReplyLeft = 0; + dev->LocalRAM.structured.autoSCSIData.uBusOffDelay = dev->CmdBuf[0]; + pclog("Bus-off time: %d\n", dev->CmdBuf[0]); + break; + + case 0x09: + dev->DataReplyLeft = 0; + dev->LocalRAM.structured.autoSCSIData.uDMATransferRate = dev->CmdBuf[0]; + pclog("DMA transfer rate: %02X\n", dev->CmdBuf[0]); + break; + + case 0x0A: + memset(dev->DataBuf, 0, 8); + for (i=0; i<7; i++) { + dev->DataBuf[i] = 0; + for (j=0; j<8; j++) { + if (SCSIDevices[i][j].LunType != SCSI_NONE) + dev->DataBuf[i] |= (1<DataBuf[7] = 0; + dev->DataReplyLeft = 8; + break; + + case 0x0B: + dev->DataBuf[0] = (1<DmaChannel); + if (dev->Irq >= 8) + dev->DataBuf[1]=(1<<(dev->Irq-9)); + else + dev->DataBuf[1]=(1<Irq); + dev->DataBuf[2] = 7; /* HOST ID */ + dev->DataReplyLeft = 3; + break; + + case 0x0D: + { + dev->DataReplyLeft = dev->CmdBuf[0]; + + ReplyISI = (ReplyInquireSetupInformation *)dev->DataBuf; + memset(ReplyISI, 0, sizeof(ReplyInquireSetupInformation)); + + ReplyISI->fSynchronousInitiationEnabled = 1; + ReplyISI->fParityCheckingEnabled = 1; + ReplyISI->cMailbox = dev->MailboxCount; + U32_TO_ADDR(ReplyISI->MailboxAddress, dev->MailboxOutAddr); + pclog("Return Setup Information: %d\n", dev->CmdBuf[0]); + } + break; + + case 0x1C: + { + uint32_t FIFOBuf; + addr24 Address; + + dev->DataReplyLeft = 0; + Address.hi = dev->CmdBuf[0]; + Address.mid = dev->CmdBuf[1]; + Address.lo = dev->CmdBuf[2]; + FIFOBuf = ADDR_TO_U32(Address); + DMAPageRead(FIFOBuf, (char *)&dev->LocalRAM.u8View[64], 64); + } + break; + + case 0x1D: + { + uint32_t FIFOBuf; + addr24 Address; + + dev->DataReplyLeft = 0; + Address.hi = dev->CmdBuf[0]; + Address.mid = dev->CmdBuf[1]; + Address.lo = dev->CmdBuf[2]; + FIFOBuf = ADDR_TO_U32(Address); + pclog("FIFO: Writing 64 bytes at %08X\n", FIFOBuf); + DMAPageWrite(FIFOBuf, (char *)&dev->LocalRAM.u8View[64], 64); + } + break; + + case 0x1F: + dev->DataBuf[0] = dev->CmdBuf[0]; + dev->DataReplyLeft = 1; + break; + + case 0x21: + if (dev->CmdParam == 1) + dev->CmdParamLeft = dev->CmdBuf[0]; + dev->DataReplyLeft = 0; + break; + + case 0x22: /* write EEPROM */ + /* Sent by CF BIOS. */ + dev->DataReplyLeft = + aha154x_eeprom(dev->Command, + dev->CmdBuf[0], + dev->CmdBuf[1], + dev->CmdBuf[2], + &dev->CmdBuf[3]); + if (dev->DataReplyLeft == 0xff) { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + } + break; + + case 0x23: + dev->DataReplyLeft = + aha154x_eeprom(dev->Command, + dev->CmdBuf[0], + dev->CmdBuf[1], + dev->CmdBuf[2], + dev->DataBuf); + if (dev->DataReplyLeft == 0xff) { + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + } + break; + + case 0x24: + /* + * For AHA1542CF, this is the command + * to play with the Shadow RAM. BIOS + * gives us one argument (00,02,03) + * and expects a 0x04 back in the INTR + * register. --FvK + */ + dev->Interrupt = aha154x_shram(val); + break; + + case 0x25: + goto aha_0x01; + + case 0x26: /* AHA memory mapper */ + case 0x27: /* AHA memory mapper */ + dev->DataReplyLeft = + aha154x_memory(dev->Command); + break; + + case 0x28: + dev->DataBuf[0] = 0x08; + dev->DataBuf[1] = dev->Lock; + dev->DataReplyLeft = 2; + break; + + case 0x29: + if (dev->CmdBuf[1] == dev->Lock) { + if (dev->CmdBuf[0] & 1) { + dev->Lock = 1; + } else { + dev->Lock = 0; + } + } + dev->DataReplyLeft = 0; + break; + + case 0x2C: /* AHA-1542CP sends this */ + dev->DataBuf[0] = 0x00; + dev->DataReplyLeft = 1; + break; + + case 0x33: /* AHA-1542CP sends this */ + dev->DataBuf[0] = 0x00; + dev->DataBuf[1] = 0x00; + dev->DataBuf[2] = 0x00; + dev->DataBuf[3] = 0x00; + dev->DataReplyLeft = 256; + break; + + case 0x91: + Offset = dev->CmdBuf[0]; + dev->DataReplyLeft = dev->CmdBuf[1]; + + dev->UseLocalRAM = 1; + dev->DataReply = Offset; + break; + + default: + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + break; + } + } + + if (dev->DataReplyLeft) + dev->Status |= STAT_DFULL; + else if (!dev->CmdParamLeft) + aha_cmd_done(dev); + break; + + case 2: + break; + + case 3: + break; + } +} + + +static void +aha_writew(uint16_t Port, uint16_t Val, void *p) +{ + aha_write(Port, Val & 0xFF, p); +} + + +static void +aha_writeL(uint16_t Port, uint32_t Val, void *p) +{ + aha_write(Port, Val & 0xFF, p); +} + + +static uint8_t +ConvertSenseLength(uint8_t RequestSenseLength) +{ + pclog("Unconverted Request Sense length %i\n", RequestSenseLength); + + if (RequestSenseLength == 0) + RequestSenseLength = 14; + else if (RequestSenseLength == 1) + RequestSenseLength = 0; + + pclog("Request Sense length %i\n", RequestSenseLength); + + return(RequestSenseLength); +} + + +static void +SenseBufferFree(Req_t *req, int Copy, int is_hd) +{ + uint8_t SenseLength = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength); + uint8_t cdrom_id = scsi_cdrom_drives[req->TargetID][req->LUN]; + uint8_t hdc_id = scsi_hard_disks[req->TargetID][req->LUN]; + uint32_t SenseBufferAddress; + uint8_t temp_sense[256]; + + if (SenseLength && Copy) { + if (is_hd) + { + scsi_hd_request_sense_for_scsi(hdc_id, temp_sense, SenseLength); + } + else + { + cdrom_request_sense_for_scsi(cdrom_id, temp_sense, SenseLength); + } + + /* + * The sense address, in 32-bit mode, is located in the + * Sense Pointer of the CCB, but in 24-bit mode, it is + * located at the end of the Command Descriptor Block. + */ + if (req->Is24bit) { + SenseBufferAddress = req->CCBPointer; + SenseBufferAddress += req->CmdBlock.common.CdbLength + offsetof(CCB, Cdb); + } else { + SenseBufferAddress = req->CmdBlock.new.SensePointer; + } + + pclog("Request Sense address: %02X\n", SenseBufferAddress); + + pclog("SenseBufferFree(): Writing %i bytes at %08X\n", + SenseLength, SenseBufferAddress); + DMAPageWrite(SenseBufferAddress, (char *)temp_sense, SenseLength); + pclog("Sense data written to buffer: %02X %02X %02X\n", + temp_sense[2], temp_sense[12], temp_sense[13]); + } +} + + +static void +aha_disk_cmd(aha_t *dev) +{ + Req_t *req = &dev->Req; + uint8_t Id, Lun; + uint8_t hdc_id; + uint8_t hd_phase; + uint8_t temp_cdb[12]; + uint32_t i; + + Id = req->TargetID; + Lun = req->LUN; + hdc_id = scsi_hard_disks[Id][Lun]; + + pclog("SCSI HD command being executed on: SCSI ID %i, SCSI LUN %i, HD %i\n", + Id, Lun, hdc_id); + + pclog("SCSI Cdb[0]=0x%02X\n", req->CmdBlock.common.Cdb[0]); + for (i = 1; i < req->CmdBlock.common.CdbLength; i++) { + pclog("SCSI Cdb[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]); + } + + memset(temp_cdb, 0, shdc[hdc_id].cdb_len); + if (req->CmdBlock.common.CdbLength <= shdc[hdc_id].cdb_len) { + memcpy(temp_cdb, req->CmdBlock.common.Cdb, + req->CmdBlock.common.CdbLength); + } else { + memcpy(temp_cdb, req->CmdBlock.common.Cdb, shdc[hdc_id].cdb_len); + } + + /* + * Since that field in the HDC struct is never used when + * the bus type is SCSI, let's use it for this scope. + */ + shdc[hdc_id].request_length = temp_cdb[1]; + + if (req->CmdBlock.common.CdbLength != 12) { + /* + * Make sure the LUN field of the temporary CDB is always 0, + * otherwise Daemon Tools drives will misbehave when a command + * is passed through to them. + */ + temp_cdb[1] &= 0x1f; + } + + /* Finally, execute the SCSI command immediately and get the transfer length. */ + SCSIPhase = SCSI_PHASE_COMMAND; + scsi_hd_command(hdc_id, temp_cdb); + SCSIStatus = scsi_hd_err_stat_to_scsi(hdc_id); + if (SCSIStatus == SCSI_STATUS_OK) { + hd_phase = scsi_hd_phase_to_scsi(hdc_id); + if (hd_phase == 2) { + /* Command completed - call the phase callback to complete the command. */ + scsi_hd_callback(hdc_id); + } else { + /* Command first phase complete - call the callback to execute the second phase. */ + scsi_hd_callback(hdc_id); + SCSIStatus = scsi_hd_err_stat_to_scsi(hdc_id); + /* Command second phase complete - call the callback to complete the command. */ + scsi_hd_callback(hdc_id); + } + } else { + /* Error (Check Condition) - call the phase callback to complete the command. */ + scsi_hd_callback(hdc_id); + } + + pclog("SCSI Status: %s, Sense: %02X, ASC: %02X, ASCQ: %02X\n", (SCSIStatus == SCSI_STATUS_OK) ? "OK" : "CHECK CONDITION", shdc[hdc_id].sense[2], shdc[hdc_id].sense[12], shdc[hdc_id].sense[13]); + + aha_buf_free(req); + + SenseBufferFree(req, (SCSIStatus != SCSI_STATUS_OK), 1); + + pclog("Request complete\n"); + + if (SCSIStatus == SCSI_STATUS_OK) { + aha_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, + CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); + } else if (SCSIStatus == SCSI_STATUS_CHECK_CONDITION) { + aha_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, + CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); + } +} + + +static void +aha_cdrom_cmd(aha_t *dev) +{ + Req_t *req = &dev->Req; + uint8_t Id, Lun; + uint8_t cdrom_id; + uint8_t cdrom_phase; + uint8_t temp_cdb[12]; + uint32_t i; + + Id = req->TargetID; + Lun = req->LUN; + cdrom_id = scsi_cdrom_drives[Id][Lun]; + + pclog("CD-ROM command being executed on: SCSI ID %i, SCSI LUN %i, CD-ROM %i\n", + Id, Lun, cdrom_id); + + pclog("SCSI Cdb[0]=0x%02X\n", req->CmdBlock.common.Cdb[0]); + for (i = 1; i < req->CmdBlock.common.CdbLength; i++) { + pclog("SCSI Cdb[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]); + } + + memset(temp_cdb, 0, cdrom[cdrom_id].cdb_len); + if (req->CmdBlock.common.CdbLength <= cdrom[cdrom_id].cdb_len) { + memcpy(temp_cdb, req->CmdBlock.common.Cdb, + req->CmdBlock.common.CdbLength); + } else { + memcpy(temp_cdb, req->CmdBlock.common.Cdb, cdrom[cdrom_id].cdb_len); + } + + /* + * Since that field in the CDROM struct is never used when + * the bus type is SCSI, let's use it for this scope. + */ + cdrom[cdrom_id].request_length = temp_cdb[1]; + + if (req->CmdBlock.common.CdbLength != 12) { + /* + * Make sure the LUN field of the temporary CDB is always 0, + * otherwise Daemon Tools drives will misbehave when a command + * is passed through to them. + */ + temp_cdb[1] &= 0x1f; + } + + /* Finally, execute the SCSI command immediately and get the transfer length. */ + SCSIPhase = SCSI_PHASE_COMMAND; + cdrom_command(cdrom_id, temp_cdb); + SCSIStatus = cdrom_CDROM_PHASE_to_scsi(cdrom_id); + if (SCSIStatus == SCSI_STATUS_OK) { + cdrom_phase = cdrom_atapi_phase_to_scsi(cdrom_id); + if (cdrom_phase == 2) { + /* Command completed - call the phase callback to complete the command. */ + cdrom_phase_callback(cdrom_id); + } else { + /* Command first phase complete - call the callback to execute the second phase. */ + cdrom_phase_callback(cdrom_id); + SCSIStatus = cdrom_CDROM_PHASE_to_scsi(cdrom_id); + /* Command second phase complete - call the callback to complete the command. */ + cdrom_phase_callback(cdrom_id); + } + } else { + /* Error (Check Condition) - call the phase callback to complete the command. */ + cdrom_phase_callback(cdrom_id); + } + + pclog("SCSI Status: %s, Sense: %02X, ASC: %02X, ASCQ: %02X\n", (SCSIStatus == SCSI_STATUS_OK) ? "OK" : "CHECK CONDITION", cdrom[cdrom_id].sense[2], cdrom[cdrom_id].sense[12], cdrom[cdrom_id].sense[13]); + + aha_buf_free(req); + + SenseBufferFree(req, (SCSIStatus != SCSI_STATUS_OK), 0); + + pclog("Request complete\n"); + + if (SCSIStatus == SCSI_STATUS_OK) { + aha_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, + CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); + } else if (SCSIStatus == SCSI_STATUS_CHECK_CONDITION) { + aha_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, + CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); + } +} + + +static void +aha_req_setup(aha_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) +{ + Req_t *req = &dev->Req; + uint8_t Id, Lun; + uint8_t last_id = 7; + + /* Fetch data from the Command Control Block. */ + DMAPageRead(CCBPointer, (char *)&req->CmdBlock, sizeof(CCB32)); + + req->Is24bit = dev->Mbx24bit; + req->CCBPointer = CCBPointer; + req->TargetID = dev->Mbx24bit ? req->CmdBlock.old.Id : req->CmdBlock.new.Id; + req->LUN = dev->Mbx24bit ? req->CmdBlock.old.Lun : req->CmdBlock.new.Lun; + + Id = req->TargetID; + Lun = req->LUN; + if ((Id > last_id) || (Lun > 7)) { + aha_mbi_setup(dev, CCBPointer, &req->CmdBlock, + CCB_INVALID_CCB, SCSI_STATUS_OK, MBI_ERROR); + return; + } + + pclog("Scanning SCSI Target ID %i\n", Id); + + SCSIStatus = SCSI_STATUS_OK; + SCSIDevices[Id][Lun].InitLength = 0; + + /* Do this here, so MODE SELECT data does not get lost in transit. */ + memset(SCSIDevices[Id][Lun].CmdBuffer, 0, 390144); + + aha_buf_alloc(req, req->Is24bit); + + if (SCSIDevices[Id][Lun].LunType == SCSI_NONE) { + pclog("SCSI Target ID %i and LUN %i have no device attached\n",Id,Lun); + aha_buf_free(req); + SenseBufferFree(req, 0, 0); + aha_mbi_setup(dev, CCBPointer, &req->CmdBlock, + CCB_SELECTION_TIMEOUT,SCSI_STATUS_OK,MBI_ERROR); + } else { + pclog("SCSI Target ID %i and LUN %i detected and working\n", Id, Lun); + + pclog("Transfer Control %02X\n", req->CmdBlock.common.ControlByte); + pclog("CDB Length %i\n", req->CmdBlock.common.CdbLength); + pclog("CCB Opcode %x\n", req->CmdBlock.common.Opcode); + if (req->CmdBlock.common.ControlByte > 0x03) { + pclog("Invalid control byte: %02X\n", + req->CmdBlock.common.ControlByte); + } + + AHA_InOperation = (SCSIDevices[Id][Lun].LunType == SCSI_DISK) ? 0x11 : 1; + pclog("SCSI (%i:%i) -> %i\n", Id, Lun, SCSIDevices[Id][Lun].LunType); + } +} + + +static void +aha_req_abort(aha_t *dev, uint32_t CCBPointer) +{ + CCBU CmdBlock; + + /* Fetch data from the Command Control Block. */ + DMAPageRead(CCBPointer, (char *)&CmdBlock, sizeof(CCB32)); + + aha_mbi_setup(dev, CCBPointer, &CmdBlock, + 0x26, SCSI_STATUS_OK, MBI_NOT_FOUND); +} + + +static uint32_t +aha_mbo(aha_t *dev, Mailbox32_t *Mailbox32) +{ + Mailbox_t MailboxOut; + uint32_t Outgoing; + + if (dev->Mbx24bit) { + Outgoing = dev->MailboxOutAddr + (dev->MailboxOutPosCur * sizeof(Mailbox_t)); + DMAPageRead(Outgoing, (char *)&MailboxOut, sizeof(Mailbox_t)); + + Mailbox32->CCBPointer = ADDR_TO_U32(MailboxOut.CCBPointer); + Mailbox32->u.out.ActionCode = MailboxOut.CmdStatus; + } else { + Outgoing = dev->MailboxOutAddr + (dev->MailboxOutPosCur * sizeof(Mailbox32_t)); + + DMAPageRead(Outgoing, (char *)Mailbox32, sizeof(Mailbox32_t)); + } + + return Outgoing; +} + + +static void +aha_mbo_adv(aha_t *dev) +{ + dev->MailboxOutPosCur = (dev->MailboxOutPosCur + 1) % dev->MailboxCount; +} + + +static void +aha_do_mail(aha_t *dev) +{ + Mailbox32_t mb32; + uint32_t Outgoing; + uint8_t CmdStatus = MBO_FREE; + uint32_t CodeOffset = 0; + + CodeOffset = dev->Mbx24bit ? offsetof(Mailbox_t, CmdStatus) : offsetof(Mailbox32_t, u.out.ActionCode); + + if (! dev->StrictRoundRobinMode) { + uint8_t MailboxCur = dev->MailboxOutPosCur; + + /* Search for a filled mailbox - stop if we have scanned all mailboxes. */ + do { + /* Fetch mailbox from guest memory. */ + Outgoing = aha_mbo(dev, &mb32); + + /* Check the next mailbox. */ + aha_mbo_adv(dev); + } while ((mb32.u.out.ActionCode == MBO_FREE) && (MailboxCur != dev->MailboxOutPosCur)); + } else { + Outgoing = aha_mbo(dev, &mb32); + } + + if (mb32.u.out.ActionCode != MBO_FREE) { + /* We got the mailbox, mark it as free in the guest. */ + pclog("aha_do_mail(): Writing %i bytes at %08X\n", sizeof(CmdStatus), Outgoing + CodeOffset); + DMAPageWrite(Outgoing + CodeOffset, (char *)&CmdStatus, sizeof(CmdStatus)); + } + + if (dev->MailboxOutInterrupts) + RaiseIntr(dev, INTR_MBOA | INTR_ANY); + + /* Check if the mailbox is actually loaded. */ + if (mb32.u.out.ActionCode == MBO_FREE) { + return; + } + + if (mb32.u.out.ActionCode == MBO_START) { + pclog("Start Mailbox Command\n"); + aha_req_setup(dev, mb32.CCBPointer, &mb32); + } else if (mb32.u.out.ActionCode == MBO_ABORT) { + pclog("Abort Mailbox Command\n"); + aha_req_abort(dev, mb32.CCBPointer); + } else { + pclog("Invalid action code: %02X\n", mb32.u.out.ActionCode); + } + + /* Advance to the next mailbox. */ + if (dev->StrictRoundRobinMode) + aha_mbo_adv(dev); +} + + +static void +aha_reset_poll(void *priv) +{ + aha_t *dev = (aha_t *)priv; + + dev->Status &= ~STAT_STST; + dev->Status |= STAT_IDLE; + + ResetCB = 0; +} + + +static void +aha_cmd_cb(void *priv) +{ + aha_t *dev = (aha_t *)priv; + + if (AHA_InOperation == 0) { + if (dev->MailboxCount) { + aha_do_mail(dev); + } else { + AHA_Callback += 50 * SCSI_TIME; + return; + } + } else if (AHA_InOperation == 1) { + pclog("BusLogic Callback: Process CD-ROM request\n"); + aha_cdrom_cmd(dev); + } else if (AHA_InOperation == 2) { + pclog("BusLogic Callback: Send incoming mailbox\n"); + aha_mbi(dev); + } else if (AHA_InOperation == 0x11) { + pclog("BusLogic Callback: Process DISK request\n"); + aha_disk_cmd(dev); + } else { + fatal("Invalid BusLogic callback phase: %i\n", AHA_InOperation); + } + + AHA_Callback += 50 * SCSI_TIME; +} + + +static void * +aha_init(int chip, int has_bios) +{ + aha_t *dev; + int i = 0; + int j = 0; + uint32_t bios_addr = 0; + int bios = 0; + + dev = malloc(sizeof(aha_t)); + memset(dev, 0x00, sizeof(aha_t)); + + ResetDev = dev; + dev->chip = chip; + dev->Base = device_get_config_int("addr"); + dev->Irq = device_get_config_int("irq"); + dev->DmaChannel = device_get_config_int("dma"); + bios = device_get_config_int("bios"); + bios_addr = device_get_config_int("bios_addr"); + + if (dev->Base != 0) { + io_sethandler(dev->Base, 4, + aha_read, aha_readw, NULL, + aha_write, aha_writew, NULL, dev); + } + + pclog("Building SCSI hard disk map...\n"); + build_scsi_hd_map(); + pclog("Building SCSI CD-ROM map...\n"); + build_scsi_cdrom_map(); + + for (i=0; i<16; i++) { + for (j=0; j<8; j++) { + if (scsi_hard_disks[i][j] != 0xff) { + SCSIDevices[i][j].LunType = SCSI_DISK; + } + } + } + + for (i=0; iBase); + + aha_reset_ctrl(dev, CTRL_HRST); + + if (bios) { + /* Perform AHA-154xNN-specific initialization. */ + aha154x_bios(dev->Base, bios_addr, &dev->aha); + } + + return(dev); +} + + +static void * +aha_154xB_init(void) +{ + return(aha_init(CHIP_AHA154XB, 0)); +} + + +static void * +aha_154xCF_init(void) +{ + return(aha_init(CHIP_AHA154XCF, 1)); +} + + +static void +aha_close(void *priv) +{ + aha_t *dev = (aha_t *)priv; + free(dev); + ResetDev = NULL; +} + + +static device_config_t aha_154XCF_config[] = { + { + "addr", "Address", CONFIG_SELECTION, "", 0x334, + { + { + "None", 0 + }, + { + "0x330", 0x330 + }, + { + "0x334", 0x334 + }, + { + "0x230", 0x230 + }, + { + "0x234", 0x234 + }, + { + "0x130", 0x130 + }, + { + "0x134", 0x134 + }, + { + "" + } + }, + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 9, + { + { + "IRQ 9", 9 + }, + { + "IRQ 10", 10 + }, + { + "IRQ 11", 11 + }, + { + "IRQ 12", 12 + }, + { + "IRQ 14", 14 + }, + { + "IRQ 15", 15 + }, + { + "" + } + }, + }, + { + "dma", "DMA channel", CONFIG_SELECTION, "", 6, + { + { + "DMA 5", 5 + }, + { + "DMA 6", 6 + }, + { + "DMA 7", 7 + }, + { + "" + } + }, + }, + { + "bios", "Enable BIOS", CONFIG_BINARY, 0 + }, + { + "bios_addr", "BIOS Address", CONFIG_SELECTION, "", 0xd8000, + { + { + "C800H", 0xc8000 + }, + { + "D000H", 0xd0000 + }, + { + "D800H", 0xd8000 + }, + { + "" + } + }, + }, + { + "", "", -1 + } +}; + + +device_t aha1540b_device = { + "Adaptec AHA-1540B", + 0, + aha_154xB_init, + aha_close, + NULL, + NULL, + NULL, + NULL, + aha_154XCF_config +}; + +device_t aha1542cf_device = { + "Adaptec AHA-1542CF", + 0, + aha_154xCF_init, + aha_close, + NULL, + NULL, + NULL, + NULL, + aha_154XCF_config +}; diff --git a/src/scsi_buslogic.c b/src/scsi_buslogic.c index 39da63367..14e6a249a 100644 --- a/src/scsi_buslogic.c +++ b/src/scsi_buslogic.c @@ -1,13 +1,11 @@ /* Copyright holders: SA1988 see COPYING for more details */ -/*Buslogic SCSI emulation (including Adaptec 154x ISA software backward compatibility) and the Adaptec 154x itself*/ +/*Buslogic SCSI emulation*/ /* Emulated SCSI controllers: - 0 - Adaptec AHA-154xB ISA; - 1 - Adaptec AHA-154xCF ISA; - 2 - BusLogic BT-542B ISA; - 3 - BusLogic BT-958 PCI (but BT-542B ISA on non-PCI machines). */ + 0 - BusLogic BT-542B ISA; + 1 - BusLogic BT-958 PCI (but BT-542B ISA on non-PCI machines). */ #include #include @@ -15,7 +13,6 @@ #include #include #include "ibm.h" -#include "device.h" #include "io.h" #include "mem.h" #include "rom.h" @@ -23,6 +20,7 @@ #include "pic.h" #include "pci.h" #include "timer.h" +#include "device.h" #include "scsi.h" #include "cdrom.h" #include "scsi_buslogic.h" @@ -31,18 +29,6 @@ #define BUSLOGIC_RESET_DURATION_NS UINT64_C(50000000) -#pragma pack(push,1) -typedef struct { - uint8_t hi; - uint8_t mid; - uint8_t lo; -} addr24; -#pragma pack(pop) - -#define ADDR_TO_U32(x) (((x).hi<<16)|((x).mid<<8)|((x).lo&0xFF)) -#define U32_TO_ADDR(a,x) do {(a).hi=(x)>>16;(a).mid=(x)>>8;(a).lo=(x)&0xFF;}while(0) - - /* * Host Adapter I/O ports. * @@ -439,29 +425,6 @@ typedef union { #pragma pack(pop) -/* - * - * Scatter/Gather Segment List Definitions - * - * Adapter limits - */ -/* #define MAX_SG_DESCRIPTORS ((bl->chip >= CHIP_BUSLOGIC_ISA) ? 32 : 17) */ -#define MAX_SG_DESCRIPTORS 32 /* Always make the array 32 elements long, if less are used, that's not an issue. */ - -#pragma pack(push,1) -typedef struct { - uint32_t Segment; - uint32_t SegmentPointer; -} SGE32; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - addr24 Segment; - addr24 SegmentPointer; -} SGE; -#pragma pack(pop) - #pragma pack(push,1) typedef struct { CCBU CmdBlock; @@ -473,7 +436,7 @@ typedef struct { uint8_t HostStatus; uint8_t TargetStatus; uint8_t MailboxCompletionCode; -} BuslogicRequests_t; +} Req_t; #pragma pack(pop) #pragma pack(push,1) @@ -483,7 +446,7 @@ typedef struct { int StrictRoundRobinMode; int ExtendedLUNCCBFormat; HALocalRAM LocalRAM; - BuslogicRequests_t BuslogicRequests; + Req_t Req; uint8_t Status; uint8_t Interrupt; uint8_t Geometry; @@ -512,30 +475,23 @@ typedef struct { int PendingInterrupt; int Lock; mem_mapping_t mmio_mapping; - aha_info aha; int chip; } Buslogic_t; #pragma pack(pop) -int scsi_model = 1; -int BuslogicResetCallback = 0; -int BuslogicCallback = 0; -int BuslogicInOperation = 0; +static int BuslogicResetCallback = 0; +static int BuslogicCallback = 0; +static int BuslogicInOperation = 0; static Buslogic_t *BuslogicResetDevice; -enum -{ - CHIP_AHA154XB, - CHIP_AHA154XCF, - CHIP_BUSLOGIC_ISA, - CHIP_BUSLOGIC_PCI +enum { + CHIP_BUSLOGIC_ISA, + CHIP_BUSLOGIC_PCI }; -static void BuslogicStartMailbox(Buslogic_t *Buslogic); - #ifdef WALTJE int buslogic_do_log = 1; # define ENABLE_BUSLOGIC_LOG @@ -544,7 +500,11 @@ int buslogic_do_log = 0; #endif -static void BuslogicLog(const char *format, ...) +static void BuslogicStartMailbox(Buslogic_t *); + + +static void +BuslogicLog(const char *format, ...) { #ifdef ENABLE_BUSLOGIC_LOG va_list ap; @@ -560,7 +520,8 @@ static void BuslogicLog(const char *format, ...) #define pclog BuslogicLog -static void BuslogicClearInterrupt(Buslogic_t *bl) +static void +BuslogicClearInterrupt(Buslogic_t *bl) { pclog("Buslogic: Lowering Interrupt 0x%02X\n", bl->Interrupt); bl->Interrupt = 0; @@ -577,7 +538,8 @@ static void BuslogicClearInterrupt(Buslogic_t *bl) } -static void BuslogicLocalRAM(Buslogic_t *bl) +static void +BuslogicLocalRAM(Buslogic_t *bl) { /* * These values are mostly from what I think is right @@ -601,7 +563,8 @@ static void BuslogicLocalRAM(Buslogic_t *bl) } -static void BuslogicReset(Buslogic_t *bl) +static void +BuslogicReset(Buslogic_t *bl) { BuslogicCallback = 0; BuslogicResetCallback = 0; @@ -626,7 +589,8 @@ static void BuslogicReset(Buslogic_t *bl) } -void BuslogicSoftReset(void) +static void +BuslogicSoftReset(void) { if (BuslogicResetDevice != NULL) { BuslogicReset(BuslogicResetDevice); @@ -634,7 +598,8 @@ void BuslogicSoftReset(void) } -static void BuslogicResetControl(Buslogic_t *bl, uint8_t Reset) +static void +BuslogicResetControl(Buslogic_t *bl, uint8_t Reset) { BuslogicReset(bl); if (Reset) { @@ -645,16 +610,13 @@ static void BuslogicResetControl(Buslogic_t *bl, uint8_t Reset) } -static void BuslogicCommandComplete(Buslogic_t *bl) +static void +BuslogicCommandComplete(Buslogic_t *bl) { bl->DataReply = 0; bl->Status |= STAT_IDLE; -#ifdef WALTJE - if ((bl->Command != 0x02) && (bl->Command != 0x82)) { -#else if (bl->Command != 0x02) { -#endif bl->Status &= ~STAT_DFULL; bl->Interrupt = (INTR_ANY | INTR_HACC); pclog("Raising IRQ %i\n", bl->Irq); @@ -667,7 +629,8 @@ static void BuslogicCommandComplete(Buslogic_t *bl) } -static void BuslogicRaiseInterrupt(Buslogic_t *bl, uint8_t Interrupt) +static void +BuslogicRaiseInterrupt(Buslogic_t *bl, uint8_t Interrupt) { if (bl->Interrupt & INTR_HACC) { pclog("Pending IRQ\n"); @@ -681,12 +644,12 @@ static void BuslogicRaiseInterrupt(Buslogic_t *bl, uint8_t Interrupt) } -static void BuslogicMailboxInSetup(Buslogic_t *bl, uint32_t CCBPointer, - CCBU *CmdBlock, uint8_t HostStatus, - uint8_t TargetStatus, - uint8_t MailboxCompletionCode) +static void +BuslogicMailboxInSetup(Buslogic_t *bl, uint32_t CCBPointer, CCBU *CmdBlock, + uint8_t HostStatus, uint8_t TargetStatus, + uint8_t MailboxCompletionCode) { - BuslogicRequests_t *req = &bl->BuslogicRequests; + Req_t *req = &bl->Req; req->CCBPointer = CCBPointer; memcpy(&(req->CmdBlock), CmdBlock, sizeof(CCB32)); @@ -701,9 +664,10 @@ static void BuslogicMailboxInSetup(Buslogic_t *bl, uint32_t CCBPointer, } -static void BuslogicMailboxIn(Buslogic_t *bl) +static void +BuslogicMailboxIn(Buslogic_t *bl) { - BuslogicRequests_t *req = &bl->BuslogicRequests; + Req_t *req = &bl->Req; uint32_t CCBPointer = req->CCBPointer; CCBU *CmdBlock = &(req->CmdBlock); uint8_t HostStatus = req->HostStatus; @@ -758,7 +722,8 @@ static void BuslogicMailboxIn(Buslogic_t *bl) } -static void BuslogicReadSGEntries(int Is24bit, uint32_t SGList, uint32_t Entries, SGE32 *SG) +static void +BuslogicReadSGEntries(int Is24bit, uint32_t SGList, uint32_t Entries, SGE32 *SG) { uint32_t i; SGE SGE24[MAX_SG_DESCRIPTORS]; @@ -777,7 +742,8 @@ static void BuslogicReadSGEntries(int Is24bit, uint32_t SGList, uint32_t Entries } -void BuslogicDataBufferAllocate(BuslogicRequests_t *req, int Is24bit) +static void +BuslogicDataBufferAllocate(Req_t *req, int Is24bit) { uint32_t sg_buffer_pos = 0; uint32_t DataPointer, DataLength; @@ -873,7 +839,8 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *req, int Is24bit) } -void BuslogicDataBufferFree(BuslogicRequests_t *req) +static void +BuslogicDataBufferFree(Req_t *req) { uint32_t DataPointer = 0; uint32_t DataLength = 0; @@ -974,7 +941,8 @@ void BuslogicDataBufferFree(BuslogicRequests_t *req) } -static uint8_t BuslogicRead(uint16_t Port, void *p) +static uint8_t +BuslogicRead(uint16_t Port, void *p) { Buslogic_t *bl = (Buslogic_t *)p; uint8_t Temp; @@ -1016,20 +984,22 @@ static uint8_t BuslogicRead(uint16_t Port, void *p) } -static uint16_t BuslogicReadW(uint16_t Port, void *p) +static uint16_t +BuslogicReadW(uint16_t Port, void *p) { return BuslogicRead(Port, p); } -static uint32_t BuslogicReadL(uint16_t Port, void *p) +static uint32_t +BuslogicReadL(uint16_t Port, void *p) { return BuslogicRead(Port, p); } /* This is BS - we just need a 'dev_present' indication.. --FvK */ -int +static int buslogic_dev_present(uint8_t id, uint8_t lun) { if (lun > 7) return(0); @@ -1046,7 +1016,8 @@ buslogic_dev_present(uint8_t id, uint8_t lun) static void BuslogicWriteW(uint16_t Port, uint16_t Val, void *p); static void BuslogicWriteL(uint16_t Port, uint32_t Val, void *p); -static void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) +static void +BuslogicWrite(uint16_t Port, uint8_t Val, void *p) { int i = 0; uint8_t j = 0; @@ -1078,8 +1049,7 @@ static void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) case 1: /* Fast path for the mailbox execution command. */ - if (((Val == 0x02) || (Val == 0x82)) && - (bl->Command == 0xFF)) { + if ((Val == 0x02) && (bl->Command == 0xFF)) { /* If there are no mailboxes configured, don't even try to do anything. */ if (bl->MailboxCount) { if (!BuslogicCallback) { @@ -1101,19 +1071,8 @@ static void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) bl->CmdParamLeft = sizeof(MailboxInit_t); break; - case 0x03: /* Exec BIOS Command */ - if (bl->chip < CHIP_BUSLOGIC_ISA) { - bl->CmdParamLeft = 10; - } - break; - case 0x25: - if (bl->chip < CHIP_BUSLOGIC_ISA) { - /* Same as 0x01 for AHA. */ - bl->CmdParamLeft = sizeof(MailboxInit_t); - } else { bl->CmdParamLeft = 1; - } break; case 0x05: @@ -1136,36 +1095,19 @@ static void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) bl->CmdParamLeft = 3; break; - case 0x22: /* write EEPROM */ - if (bl->chip < CHIP_BUSLOGIC_ISA) { - bl->CmdParamLeft = 3+32; - } - break; - - case 0x23: /* read EEPROM */ - if (bl->chip < CHIP_BUSLOGIC_ISA) { - bl->CmdParamLeft = 3; - } - break; - - case 0x29: - bl->CmdParamLeft = (bl->chip >= CHIP_BUSLOGIC_ISA) ? 0 : 2; - break; - case 0x8B: case 0x8D: case 0x8F: case 0x96: - bl->CmdParamLeft = (bl->chip >= CHIP_BUSLOGIC_ISA) ? 1 : 0; + bl->CmdParamLeft = 1; break; case 0x81: - pclog("Command 0x81 on %s\n", (bl->chip >= CHIP_BUSLOGIC_ISA) ? "BusLogic" : "Adaptec"); - bl->CmdParamLeft = (bl->chip >= CHIP_BUSLOGIC_ISA) ? sizeof(MailboxInitExtended_t) : 0; + bl->CmdParamLeft = sizeof(MailboxInitExtended_t); break; case 0x8C: - bl->CmdParamLeft = (bl->chip >= CHIP_BUSLOGIC_ISA) ? 1 : 0; + bl->CmdParamLeft = 1; break; case 0x91: @@ -1216,17 +1158,10 @@ aha_0x01: break; case 0x04: - if (bl->chip >= CHIP_BUSLOGIC_ISA) { bl->DataBuf[0] = 0x41; bl->DataBuf[1] = 0x41; bl->DataBuf[2] = '5'; bl->DataBuf[3] = '0'; - } else { - bl->DataBuf[0] = bl->aha.bid; - bl->DataBuf[1] = 0x30; - bl->DataBuf[2] = bl->aha.fwh; - bl->DataBuf[3] = bl->aha.fwl; - } bl->DataReplyLeft = 4; break; @@ -1277,14 +1212,7 @@ aha_0x01: case 0x0B: bl->DataBuf[0] = (1 << bl->DmaChannel); - if (bl->chip >= CHIP_BUSLOGIC_ISA) { - bl->DataBuf[1] = (1<<(bl->Irq-9)); - } else { - if (bl->Irq >= 8) - bl->DataBuf[1]=(1<<(bl->Irq-9)); - else - bl->DataBuf[1]=(1<Irq); - } + bl->DataBuf[1] = (1<<(bl->Irq-9)); bl->DataBuf[2] = 7; /* HOST ID */ bl->DataReplyLeft = 3; break; @@ -1301,14 +1229,12 @@ aha_0x01: ReplyISI->cMailbox = bl->MailboxCount; U32_TO_ADDR(ReplyISI->MailboxAddress, bl->MailboxOutAddr); - if (bl->chip >= CHIP_BUSLOGIC_ISA) { - ReplyISI->uSignature = 'B'; - /* The 'D' signature prevents Buslogic's OS/2 drivers from getting too - * friendly with Adaptec hardware and upsetting the HBA state. - */ - ReplyISI->uCharacterD = 'D'; /* BusLogic model. */ - ReplyISI->uHostBusType = (bl->chip == CHIP_BUSLOGIC_PCI) ? 'F' : 'A'; /* ISA bus. */ - } + ReplyISI->uSignature = 'B'; + /* The 'D' signature prevents Buslogic's OS/2 drivers from getting too + * friendly with Adaptec hardware and upsetting the HBA state. + */ + ReplyISI->uCharacterD = 'D'; /* BusLogic model. */ + ReplyISI->uHostBusType = (bl->chip == CHIP_BUSLOGIC_PCI) ? 'F' : 'A'; /* ISA bus. */ pclog("Return Setup Information: %d\n", bl->CmdBuf[0]); } @@ -1350,11 +1276,7 @@ aha_0x01: case 0x20: bl->DataReplyLeft = 0; - if (bl->chip >= CHIP_BUSLOGIC_ISA) { - BuslogicResetControl(bl, 1); - } else { - bl->Status |= STAT_INVCMD; - } + BuslogicResetControl(bl, 1); break; case 0x21: @@ -1363,53 +1285,27 @@ aha_0x01: bl->DataReplyLeft = 0; break; - case 0x22: /* write EEPROM */ - if (bl->chip < CHIP_BUSLOGIC_ISA) { - /* Sent by CF BIOS. */ - bl->DataReplyLeft = - aha154x_eeprom(bl->Command, - bl->CmdBuf[0], - bl->CmdBuf[1], - bl->CmdBuf[2], - &bl->CmdBuf[3]); - if (bl->DataReplyLeft == 0xff) { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - } - } else { - bl->Status |= STAT_INVCMD; - bl->DataReplyLeft = 0; - } - break; - case 0x23: - if (bl->chip >= CHIP_BUSLOGIC_ISA) { memset(bl->DataBuf, 0, 8); for (i = 8; i < 16; i++) { +#if 1 /* FIXME: Kotori, check this! */ + bl->DataBuf[i-8] = 0; + for (j=0; j<8; j++) { + if (SCSIDevices[i][j].LunType != SCSI_NONE) + bl->DataBuf[i-8] |= (1<DataBuf[i] = 0; for (i=0; j<8; j++) { if (SCSIDevices[i][j].LunType != SCSI_NONE) - bl->DataBuf[i] |= (1 << j); + bl->DataBuf[i] |= (1<DataReplyLeft = 8; - } else { - /* Sent by CF BIOS. */ - bl->DataReplyLeft = - aha154x_eeprom(bl->Command, - bl->CmdBuf[0], - bl->CmdBuf[1], - bl->CmdBuf[2], - bl->DataBuf); - if (bl->DataReplyLeft == 0xff) { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - } - } - break; + break; case 0x24: - if (bl->chip >= CHIP_BUSLOGIC_ISA) { + { uint16_t TargetsPresentMask = 0; for (i=0; i<16; i++) { @@ -1421,135 +1317,46 @@ aha_0x01: bl->DataBuf[0] = TargetsPresentMask & 0xFF; bl->DataBuf[1] = TargetsPresentMask >> 8; bl->DataReplyLeft = 2; - } else { - /* - * For AHA1542CF, this is the command - * to play with the Shadow RAM. BIOS - * gives us one argument (00,02,03) - * and expects a 0x04 back in the INTR - * register. --FvK - */ - bl->Interrupt = aha154x_shram(Val); } break; - + case 0x25: - if ((bl->chip < CHIP_BUSLOGIC_ISA)) { - goto aha_0x01; - } else { if (bl->CmdBuf[0] == 0) bl->IrqEnabled = 0; else bl->IrqEnabled = 1; pclog("Lowering IRQ %i\n", bl->Irq); picintc(1 << bl->Irq); - } break; - case 0x26: /* AHA memory mapper */ - case 0x27: /* AHA memory mapper */ - if (bl->chip < CHIP_BUSLOGIC_ISA) { - bl->DataReplyLeft = - aha154x_memory(bl->Command); - } else { - bl->Status |= STAT_INVCMD; - bl->DataReplyLeft = 0; - } - break; - - case 0x28: - if (bl->chip < CHIP_BUSLOGIC_ISA) { - bl->DataBuf[0] = 0x08; - bl->DataBuf[1] = bl->Lock; - bl->DataReplyLeft = 2; - } else { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - } - break; - - case 0x29: - if (bl->chip < CHIP_BUSLOGIC_ISA) { - if (bl->CmdBuf[1] == bl->Lock) { - if (bl->CmdBuf[0] & 1) { - bl->Lock = 1; - } else { - bl->Lock = 0; - } - } - bl->DataReplyLeft = 0; - } else { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - } - break; - - case 0x2C: /* AHA-1542CP sends this */ - if (bl->chip < CHIP_BUSLOGIC_ISA) { - bl->DataBuf[0] = 0x00; - bl->DataReplyLeft = 1; - } else { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - } - break; - - case 0x33: /* AHA-1542CP sends this */ - if (bl->chip < CHIP_BUSLOGIC_ISA) { - bl->DataBuf[0] = 0x00; - bl->DataBuf[1] = 0x00; - bl->DataBuf[2] = 0x00; - bl->DataBuf[3] = 0x00; - bl->DataReplyLeft = 256; - } else { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - } - break; - case 0x81: { - if (bl->chip >= CHIP_BUSLOGIC_ISA) { - bl->Mbx24bit = 0; - - MailboxInitE = (MailboxInitExtended_t *)bl->CmdBuf; + bl->Mbx24bit = 0; - bl->MailboxCount = MailboxInitE->Count; - bl->MailboxOutAddr = MailboxInitE->Address; - bl->MailboxInAddr = MailboxInitE->Address + (bl->MailboxCount * sizeof(Mailbox32_t)); - - pclog("Buslogic Extended Initialize Mailbox Command\n"); - pclog("Mailbox Out Address=0x%08X\n", bl->MailboxOutAddr); - pclog("Mailbox In Address=0x%08X\n", bl->MailboxInAddr); - pclog("Initialized Extended Mailbox, %d entries at 0x%08X\n", MailboxInitE->Count, MailboxInitE->Address); - - bl->Status &= ~STAT_INIT; - bl->DataReplyLeft = 0; - } else { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - } + MailboxInitE = (MailboxInitExtended_t *)bl->CmdBuf; + + bl->MailboxCount = MailboxInitE->Count; + bl->MailboxOutAddr = MailboxInitE->Address; + bl->MailboxInAddr = MailboxInitE->Address + (bl->MailboxCount * sizeof(Mailbox32_t)); + + pclog("Buslogic Extended Initialize Mailbox Command\n"); + pclog("Mailbox Out Address=0x%08X\n", bl->MailboxOutAddr); + pclog("Mailbox In Address=0x%08X\n", bl->MailboxInAddr); + pclog("Initialized Extended Mailbox, %d entries at 0x%08X\n", MailboxInitE->Count, MailboxInitE->Address); + + bl->Status &= ~STAT_INIT; + bl->DataReplyLeft = 0; } break; case 0x84: - if (bl->chip >= CHIP_BUSLOGIC_ISA) { - bl->DataBuf[0] = '7'; - bl->DataReplyLeft = 1; - } else { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - } + bl->DataBuf[0] = '7'; + bl->DataReplyLeft = 1; break; case 0x85: - if (bl->chip >= CHIP_BUSLOGIC_ISA) { - bl->DataBuf[0] = 'B'; - bl->DataReplyLeft = 1; - } else { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - } + bl->DataBuf[0] = 'B'; + bl->DataReplyLeft = 1; break; case 0x86: @@ -1592,64 +1399,47 @@ aha_0x01: case 0x8B: { - if (bl->chip >= CHIP_BUSLOGIC_ISA) { - /* The reply length is set by the guest and is found in the first byte of the command buffer. */ - bl->DataReplyLeft = bl->CmdBuf[0]; - memset(bl->DataBuf, 0, bl->DataReplyLeft); - if (bl->chip == CHIP_BUSLOGIC_PCI) { - aModelName[0] = '9'; - aModelName[1] = '5'; - aModelName[2] = '8'; - aModelName[3] = 'D'; - } - cCharsToTransfer = bl->DataReplyLeft <= sizeof(aModelName) - ? bl->DataReplyLeft - : sizeof(aModelName); - - for (i = 0; i < cCharsToTransfer; i++) - bl->DataBuf[i] = aModelName[i]; - } else { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; + /* The reply length is set by the guest and is found in the first byte of the command buffer. */ + bl->DataReplyLeft = bl->CmdBuf[0]; + memset(bl->DataBuf, 0, bl->DataReplyLeft); + if (bl->chip == CHIP_BUSLOGIC_PCI) { + aModelName[0] = '9'; + aModelName[1] = '5'; + aModelName[2] = '8'; + aModelName[3] = 'D'; } + cCharsToTransfer = bl->DataReplyLeft <= sizeof(aModelName) + ? bl->DataReplyLeft + : sizeof(aModelName); + + for (i = 0; i < cCharsToTransfer; i++) + bl->DataBuf[i] = aModelName[i]; } break; case 0x8C: - if (bl->chip >= CHIP_BUSLOGIC_ISA) { bl->DataReplyLeft = bl->CmdBuf[0]; memset(bl->DataBuf, 0, bl->DataReplyLeft); - } else { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - } - break; + break; case 0x8D: - { - if (bl->chip >= CHIP_BUSLOGIC_ISA) { - bl->DataReplyLeft = bl->CmdBuf[0]; - ReplyIESI = (ReplyInquireExtendedSetupInformation *)bl->DataBuf; - memset(ReplyIESI, 0, sizeof(ReplyInquireExtendedSetupInformation)); + bl->DataReplyLeft = bl->CmdBuf[0]; + ReplyIESI = (ReplyInquireExtendedSetupInformation *)bl->DataBuf; + memset(ReplyIESI, 0, sizeof(ReplyInquireExtendedSetupInformation)); - ReplyIESI->uBusType = (bl->chip == CHIP_BUSLOGIC_PCI) ? 'E' : 'A'; /* ISA style */ - ReplyIESI->uBiosAddress = 0; - ReplyIESI->u16ScatterGatherLimit = 8192; - ReplyIESI->cMailbox = bl->MailboxCount; - ReplyIESI->uMailboxAddressBase = bl->MailboxOutAddr; - if (bl->chip == CHIP_BUSLOGIC_PCI) { - ReplyIESI->fLevelSensitiveInterrupt = 1; - ReplyIESI->fHostWideSCSI = 1; - ReplyIESI->fHostUltraSCSI = 1; - } - memcpy(ReplyIESI->aFirmwareRevision, "07B", sizeof(ReplyIESI->aFirmwareRevision)); - pclog("Return Extended Setup Information: %d\n", bl->CmdBuf[0]); - } else { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; + ReplyIESI->uBusType = (bl->chip == CHIP_BUSLOGIC_PCI) ? 'E' : 'A'; /* ISA style */ + ReplyIESI->uBiosAddress = 0; + ReplyIESI->u16ScatterGatherLimit = 8192; + ReplyIESI->cMailbox = bl->MailboxCount; + ReplyIESI->uMailboxAddressBase = bl->MailboxOutAddr; + if (bl->chip == CHIP_BUSLOGIC_PCI) { + ReplyIESI->fLevelSensitiveInterrupt = 1; + ReplyIESI->fHostWideSCSI = 1; + ReplyIESI->fHostUltraSCSI = 1; } - } - break; + memcpy(ReplyIESI->aFirmwareRevision, "07B", sizeof(ReplyIESI->aFirmwareRevision)); + pclog("Return Extended Setup Information: %d\n", bl->CmdBuf[0]); + break; /* VirtualBox has these two modes implemented in reverse. According to the BusLogic datasheet: @@ -1658,28 +1448,21 @@ aha_0x01: 1 is the aggressive round robin mode, which "hunts" for an active outgoing mailbox and then processes it. */ case 0x8F: - if (bl->chip >= CHIP_BUSLOGIC_ISA) { if (bl->CmdBuf[0] == 0) bl->StrictRoundRobinMode = 1; else if (bl->CmdBuf[0] == 1) bl->StrictRoundRobinMode = 0; bl->DataReplyLeft = 0; - } else { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - } - break; - + break; + case 0x91: - { Offset = bl->CmdBuf[0]; bl->DataReplyLeft = bl->CmdBuf[1]; bl->UseLocalRAM = 1; bl->DataReply = Offset; - } - break; + break; case 0x95: if (bl->chip == CHIP_BUSLOGIC_PCI) { @@ -1734,18 +1517,13 @@ aha_0x01: break; case 0x96: - if (bl->chip >= CHIP_BUSLOGIC_ISA) { if (bl->CmdBuf[0] == 0) bl->ExtendedLUNCCBFormat = 0; else if (bl->CmdBuf[0] == 1) bl->ExtendedLUNCCBFormat = 1; bl->DataReplyLeft = 0; - } else { - bl->DataReplyLeft = 0; - bl->Status |= STAT_INVCMD; - } - break; + break; default: bl->DataReplyLeft = 0; @@ -1761,31 +1539,32 @@ aha_0x01: break; case 2: - if (bl->chip >= CHIP_BUSLOGIC_ISA) - bl->Interrupt = Val; /* For Buslogic */ + bl->Interrupt = Val; break; case 3: - if (bl->chip >= CHIP_BUSLOGIC_ISA) - bl->Geometry = Val; /* For Buslogic */ + bl->Geometry = Val; break; } } -static void BuslogicWriteW(uint16_t Port, uint16_t Val, void *p) +static void +BuslogicWriteW(uint16_t Port, uint16_t Val, void *p) { BuslogicWrite(Port, Val & 0xFF, p); } -static void BuslogicWriteL(uint16_t Port, uint32_t Val, void *p) +static void +BuslogicWriteL(uint16_t Port, uint32_t Val, void *p) { BuslogicWrite(Port, Val & 0xFF, p); } -static uint8_t BuslogicConvertSenseLength(uint8_t RequestSenseLength) +static uint8_t +BuslogicConvertSenseLength(uint8_t RequestSenseLength) { pclog("Unconverted Request Sense length %i\n", RequestSenseLength); @@ -1800,7 +1579,8 @@ static uint8_t BuslogicConvertSenseLength(uint8_t RequestSenseLength) } -static void BuslogicSenseBufferFree(BuslogicRequests_t *req, int Copy, int is_hd) +static void +BuslogicSenseBufferFree(Req_t *req, int Copy, int is_hd) { uint8_t SenseLength = BuslogicConvertSenseLength(req->CmdBlock.common.RequestSenseLength); uint8_t cdrom_id = scsi_cdrom_drives[req->TargetID][req->LUN]; @@ -1841,9 +1621,10 @@ static void BuslogicSenseBufferFree(BuslogicRequests_t *req, int Copy, int is_hd } -static void BuslogicHDCommand(Buslogic_t *bl) +static void +BuslogicHDCommand(Buslogic_t *bl) { - BuslogicRequests_t *req = &bl->BuslogicRequests; + Req_t *req = &bl->Req; uint8_t Id, Lun; uint8_t hdc_id; uint8_t hd_phase; @@ -1923,9 +1704,11 @@ static void BuslogicHDCommand(Buslogic_t *bl) } } -static void BuslogicCDROMCommand(Buslogic_t *bl) + +static void +BuslogicCDROMCommand(Buslogic_t *bl) { - BuslogicRequests_t *req = &bl->BuslogicRequests; + Req_t *req = &bl->Req; uint8_t Id, Lun; uint8_t cdrom_id; uint8_t cdrom_phase; @@ -2006,9 +1789,10 @@ static void BuslogicCDROMCommand(Buslogic_t *bl) } -static void BuslogicSCSIRequestSetup(Buslogic_t *bl, uint32_t CCBPointer, Mailbox32_t *Mailbox32) +static void +BuslogicSCSIRequestSetup(Buslogic_t *bl, uint32_t CCBPointer, Mailbox32_t *Mailbox32) { - BuslogicRequests_t *req = &bl->BuslogicRequests; + Req_t *req = &bl->Req; uint8_t Id, Lun; uint8_t last_id = (bl->chip >= CHIP_BUSLOGIC_ISA) ? 15 : 7; @@ -2061,7 +1845,8 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *bl, uint32_t CCBPointer, Mailbo } -static void BuslogicSCSIRequestAbort(Buslogic_t *bl, uint32_t CCBPointer) +static void +BuslogicSCSIRequestAbort(Buslogic_t *bl, uint32_t CCBPointer) { CCBU CmdBlock; @@ -2074,7 +1859,8 @@ static void BuslogicSCSIRequestAbort(Buslogic_t *bl, uint32_t CCBPointer) } -static uint32_t BuslogicMailboxOut(Buslogic_t *bl, Mailbox32_t *Mailbox32) +static uint32_t +BuslogicMailboxOut(Buslogic_t *bl, Mailbox32_t *Mailbox32) { Mailbox_t MailboxOut; uint32_t Outgoing; @@ -2095,13 +1881,15 @@ static uint32_t BuslogicMailboxOut(Buslogic_t *bl, Mailbox32_t *Mailbox32) } -static void BuslogicMailboxOutAdvance(Buslogic_t *bl) +static void +BuslogicMailboxOutAdvance(Buslogic_t *bl) { bl->MailboxOutPosCur = (bl->MailboxOutPosCur + 1) % bl->MailboxCount; } -static void BuslogicProcessMailbox(Buslogic_t *bl) +static void +BuslogicProcessMailbox(Buslogic_t *bl) { Mailbox32_t mb32; uint32_t Outgoing; @@ -2155,7 +1943,8 @@ static void BuslogicProcessMailbox(Buslogic_t *bl) } -void BuslogicResetPoll(void *p) +static void +BuslogicResetPoll(void *p) { Buslogic_t *bl = (Buslogic_t *)p; @@ -2166,7 +1955,8 @@ void BuslogicResetPoll(void *p) } -void BuslogicCommandCallback(void *p) +static void +BuslogicCommandCallback(void *p) { Buslogic_t *bl = (Buslogic_t *)p; @@ -2194,19 +1984,22 @@ void BuslogicCommandCallback(void *p) } -static uint8_t mem_read_null(uint32_t addr, void *priv) +static uint8_t +mem_read_null(uint32_t addr, void *priv) { return(0); } -static uint16_t mem_read_nullw(uint32_t addr, void *priv) +static uint16_t +mem_read_nullw(uint32_t addr, void *priv) { return(0); } -static uint32_t mem_read_nulll(uint32_t addr, void *priv) +static uint32_t +mem_read_nulll(uint32_t addr, void *priv) { return(0); } @@ -2222,7 +2015,8 @@ uint8_t buslogic_pci_regs[256]; bar_t buslogic_pci_bar[3]; -static uint8_t BuslogicPCIRead(int func, int addr, void *p) +static uint8_t +BuslogicPCIRead(int func, int addr, void *p) { Buslogic_t *bl = (Buslogic_t *)p; @@ -2291,7 +2085,8 @@ static uint8_t BuslogicPCIRead(int func, int addr, void *p) } -static void BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) +static void +BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) { Buslogic_t *bl = (Buslogic_t *)p; @@ -2387,84 +2182,8 @@ static void BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) } -void *AdaptecInit(int has_bios, int chip) -{ - Buslogic_t *bl; - int i = 0; - int j = 0; - uint32_t bios_addr = 0; - int bios = 0; - - bl = malloc(sizeof(Buslogic_t)); - memset(bl, 0x00, sizeof(Buslogic_t)); - - BuslogicResetDevice = bl; - bl->chip = chip; - bl->Base = device_get_config_int("addr"); - bl->PCIBase = 0; - bl->MMIOBase = 0; - bl->Irq = device_get_config_int("irq"); - bl->DmaChannel = device_get_config_int("dma"); - bios = device_get_config_int("bios"); - bios_addr = device_get_config_int("bios_addr"); - - if (bl->Base != 0) { - io_sethandler(bl->Base, 4, - BuslogicRead, BuslogicReadW, NULL, - BuslogicWrite, BuslogicWriteW, NULL, bl); - } - - pclog("Building SCSI hard disk map...\n"); - build_scsi_hd_map(); - pclog("Building SCSI CD-ROM map...\n"); - build_scsi_cdrom_map(); - - for (i=0; i<16; i++) { - for (j=0; j<8; j++) - { - if (scsi_hard_disks[i][j] != 0xff) - { - SCSIDevices[i][j].LunType = SCSI_DISK; - } - } - } - - for (i=0; iBase); - - BuslogicResetControl(bl, CTRL_HRST); - - if (bios) { - /* Perform AHA-154xNN-specific initialization. */ - aha154x_init(bl->Base, bios_addr, &bl->aha); - } - - return(bl); -} - -void *AHA_154xB_Init() -{ - return AdaptecInit(0, CHIP_AHA154XB); -} - -void *AHA_154xCF_Init() -{ - return AdaptecInit(1, CHIP_AHA154XCF); -} - - -void *BuslogicInit(int chip) +static void * +BuslogicInit(int chip) { Buslogic_t *bl; @@ -2550,18 +2269,23 @@ void *BuslogicInit(int chip) return(bl); } -void *Buslogic_542B_Init() + +static void * +Buslogic_542B_Init(void) { return BuslogicInit(CHIP_BUSLOGIC_ISA); } -void *Buslogic_958D_Init() + +static void * +Buslogic_958D_Init(void) { return BuslogicInit(CHIP_BUSLOGIC_PCI); } -void BuslogicClose(void *p) +static void +BuslogicClose(void *p) { Buslogic_t *bl = (Buslogic_t *)p; free(bl); @@ -2569,107 +2293,7 @@ void BuslogicClose(void *p) } -static device_config_t AHA154XCF_Config[] = -{ - { - "addr", "Address", CONFIG_SELECTION, "", 0x334, - { - { - "None", 0 - }, - { - "0x330", 0x330 - }, - { - "0x334", 0x334 - }, - { - "0x230", 0x230 - }, - { - "0x234", 0x234 - }, - { - "0x130", 0x130 - }, - { - "0x134", 0x134 - }, - { - "" - } - }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 9, - { - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } - }, - }, - { - "dma", "DMA channel", CONFIG_SELECTION, "", 6, - { - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "" - } - }, - }, - { - "bios", "Enable BIOS", CONFIG_BINARY, 0 - }, - { - "bios_addr", "BIOS Address", CONFIG_SELECTION, "", 0xd8000, - { - { - "C800H", 0xc8000 - }, - { - "D000H", 0xd0000 - }, - { - "D800H", 0xd8000 - }, - { - "" - } - }, - }, - { - "", "", -1 - } -}; - -static device_config_t BuslogicConfig[] = -{ +static device_config_t BuslogicConfig[] = { { "addr", "Address", CONFIG_SELECTION, "", 0x334, { @@ -2747,34 +2371,8 @@ static device_config_t BuslogicConfig[] = } }; -device_t aha1540b_device = -{ - "Adaptec AHA-1540B", - 0, - AHA_154xB_Init, - BuslogicClose, - NULL, - NULL, - NULL, - NULL, - BuslogicConfig -}; -device_t aha1542cf_device = -{ - "Adaptec AHA-1542CF", - 0, - AHA_154xCF_Init, - BuslogicClose, - NULL, - NULL, - NULL, - NULL, - AHA154XCF_Config -}; - -device_t buslogic_device = -{ +device_t buslogic_device = { "Buslogic BT-542B PCI", 0, Buslogic_542B_Init, @@ -2786,8 +2384,7 @@ device_t buslogic_device = BuslogicConfig }; -device_t buslogic_pci_device = -{ +device_t buslogic_pci_device = { "Buslogic BT-542B PCI", 0, Buslogic_958D_Init, diff --git a/src/scsi_buslogic.h b/src/scsi_buslogic.h index 46ec9bf3b..c2d5dccc5 100644 --- a/src/scsi_buslogic.h +++ b/src/scsi_buslogic.h @@ -1,27 +1,9 @@ -#ifndef BUSLOGIC_H -# define BUSLOGIC_H +#ifndef SCSI_BUSLOGIC_H +# define SCSI_BUSLOGIC_H -typedef struct { - uint8_t flags; /* local flags */ - uint8_t bid; /* board ID */ - char fwl, fwh; /* firmware info */ -} aha_info; -#define AHA_GLAG_MEMEN 0x01 /* BIOS Shadow RAM enabled */ - - -extern device_t aha1540b_device; -extern device_t aha1542cf_device; extern device_t buslogic_device; extern device_t buslogic_pci_device; -extern int buslogic_dev_present(uint8_t id, uint8_t lun); - -extern void aha154x_init(uint16_t, uint32_t, aha_info *); -extern uint8_t aha154x_shram(uint8_t); -extern uint8_t aha154x_eeprom(uint8_t,uint8_t,uint8_t,uint8_t,uint8_t *); -extern uint8_t aha154x_memory(uint8_t); - - -#endif /*BUSLOGIC_H*/ +#endif /*SCSI_BUSLOGIC_H*/