Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdlib.h>
- #include <string.h>
- #include <assert.h>
- #include "ibm.h"
- #include "device.h"
- #include "io.h"
- #include "mem.h"
- #include "rom.h"
- #include "aha1540.h"
- #include "pic.h"
- #include "dma.h"
- #include "scsi.h"
- #include "timer.h"
- #include "sg.h"
- #define elements(a) (sizeof(a) / sizeof(a[0]))
- #define ADDR_TO_U32(x) (((x[0]) << 16) | ((x[1]) << 8) | (x[2]))
- #define U32_TO_ADDR(a, x) do {(a[0]) = (x) >> 16; (a[1]) = (x) >> 8; (a[2]) = (x);} while(0)
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CCB - Adaptec 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_OLD_COMMAND 0x00
- #define TARGET_MODE_COMMAND 0x01
- #define SCATTER_GATHER_OLD_COMMAND 0x02
- #define SCSI_INITIATOR_COMMAND 0x03
- #define SCATTER_GATHER_COMMAND 0x04
- //
- // 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_NONE 3 // No Data
- #define CCB_DATA_XFER_OUT 2 // Write
- #define CCB_DATA_XFER_IN 1 // Read
- #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 interrupt
- #define CCB_SELECTION_TIMEOUT 0x11 // Set SCSI selection timed out
- #define CCB_DATA_OVER_UNDER_RUN 0x12
- #define CCB_UNEXPECTED_BUS_FREE 0x13 // Target dropped SCSI BSY
- #define CCB_PHASE_SEQUENCE_FAIL 0x14 // Target bus phase sequence failure
- #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 different from first
- #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
- //
- //
- // Bytes 18+n through 18+m-1, where m=buffer size Allocated for Sense Data
- //
- #define REQUEST_SENSE_BUFFER_SIZE 18
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CCB Typedef
- //
- typedef struct CCB
- {
- uint8_t OperationCode;
- uint8_t ControlByte:2;
- uint8_t CdbLength;
- uint8_t RequestSenseLength;
- uint8_t DataLength[3];
- uint8_t DataPointer[3];
- uint8_t LinkPointer[3];
- uint8_t LinkIdentifier;
- uint8_t HostStatus;
- uint8_t TargetStatus;
- uint8_t Reserved[2];
- uint8_t Cdb[12];
- uint8_t Lun:3;
- uint8_t Id:3;
- } CCB;
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Adapter Command Overview
- //
- // Adapter commands are issued by writing to the Command/Data Out port.
- // They are used to initialize the host adapter and to establish control
- // conditions within the host adapter. They may not be issued when there
- // are outstanding SCSI commands.
- //
- // All adapter commands except Start SCSI(02) and Enable Mailbox-Out
- // Interrupt(05) must be executed only when the IDLE bit (Status bit 4)
- // is one. Many commands require additional parameter bytes which are
- // then written to the Command/Data Out I/O port (base+1). Before each
- // byte is written by the host to the host adapter, the host must verify
- // that the CDF bit (Status bit 3) is zero, indicating that the command
- // port is ready for another byte of information. The host adapter usually
- // clears the Command/Data Out port within 100 microseconds. Some commands
- // require information bytes to be returned from the host adapter to the
- // host. In this case, the host monitors the DF bit (Status bit 2) to
- // determine when the host adapter has placed a byte in the Data In I/O
- // port for the host to read. The DF bit is reset automatically when the
- // host reads the byte. The format of each adapter command is strictly
- // defined, so the host adapter and host system can always agree upon the
- // correct number of parameter bytes to be transferred during a command.
- //
- //
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Host Adapter Command Operation Codes
- //
- #define AC_NO_OPERATION 0x00
- #define AC_MAILBOX_INITIALIZATION 0x01
- #define AC_START_SCSI_COMMAND 0x02
- #define AC_START_BIOS_COMMAND 0x03
- #define AC_ADAPTER_INQUIRY 0x04
- #define AC_ENABLE_MBO_AVAIL_INT 0x05
- #define AC_SET_SELECTION_TIMEOUT 0x06
- #define AC_SET_BUS_ON_TIME 0x07
- #define AC_SET_BUS_OFF_TIME 0x08
- #define AC_SET_TRANSFER_SPEED 0x09
- #define AC_RET_INSTALLED_DEVICES 0x0A
- #define AC_RET_CONFIGURATION_DATA 0x0B
- #define AC_ENABLE_TARGET_MODE 0x0C
- #define AC_RETURN_SETUP_DATA 0x0D
- #define AC_WRITE_CHANNEL_2_BUFFER 0x1A
- #define AC_READ_CHANNEL_2_BUFFER 0x1B
- #define AC_WRITE_FIFO_BUFFER 0x1C
- #define AC_READ_FIFO_BUFFER 0x1D
- #define AC_ECHO_COMMAND_DATA 0x1F
- #define AC_SET_HA_OPTION 0x21
- #define AC_GET_BIOS_INFO 0x28
- #define AC_SET_MAILBOX_INTERFACE 0x29
- #define AC_EXTENDED_SETUP_INFO 0x8D
- //
- // Base+0 Write: Control Register
- //
- #define IOP_HARD_RESET 0x80 // bit 7
- #define IOP_SOFT_RESET 0x40 // bit 6
- #define IOP_INTERRUPT_RESET 0x20 // bit 5
- #define IOP_SCSI_BUS_RESET 0x10 // bit 4
- //
- // Base+0 Read: Status
- //
- #define IOP_SELF_TEST 0x80 // bit 7
- #define IOP_INTERNAL_DIAG_FAILURE 0x40 // bit 6
- #define IOP_MAILBOX_INIT_REQUIRED 0x20 // bit 5
- #define IOP_SCSI_HBA_IDLE 0x10 // bit 4
- #define IOP_COMMAND_DATA_OUT_FULL 0x08 // bit 3
- #define IOP_DATA_IN_PORT_FULL 0x04 // bit 2
- #define IOP_INVALID_COMMAND 0x01 // bit 1
- //
- // Base+1 Write: Command/Data Out
- //
- //
- // Base+1 Read: Data In
- //
- //
- // Base+2 Read: Interrupt Flags
- //
- #define IOP_ANY_INTERRUPT 0x80 // bit 7
- #define IOP_SCSI_RESET_DETECTED 0x08 // bit 3
- #define IOP_COMMAND_COMPLETE 0x04 // bit 2
- #define IOP_MBO_EMPTY 0x02 // bit 1
- #define IOP_MBI_FULL 0x01 // bit 0
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Mailbox Definitions
- //
- //
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Mailbox Definition
- //
- //
- // MBO Command Values
- //
- #define MBO_FREE 0x00
- #define MBO_START 0x01
- #define MBO_ABORT 0x02
- //
- // MBI Status Values
- //
- #define MBI_FREE 0x00
- #define MBI_SUCCESS 0x01
- #define MBI_ABORT 0x02
- #define MBI_NOT_FOUND 0x03
- #define MBI_ERROR 0x04
- typedef struct MAILBOX
- {
- uint8_t Address[3];
- union
- {
- struct
- {
- uint8_t Reserved[3];
- uint8_t Command;
- } out;
- struct
- {
- uint8_t HostStatus;
- uint8_t TargetStatus;
- uint8_t Reserved;
- uint8_t Status;
- } in;
- } u;
- } MAILBOX;
- typedef struct SGD32
- {
- uint32_t Length;
- uint32_t Address;
- } SGD32;
- typedef struct SGD
- {
- uint8_t Length[3];
- uint8_t Address[3];
- } SGD;
- //
- // Mailbox Initialization
- //
- typedef struct MAILBOX_INIT {
- uint8_t Count;
- uint8_t Address[3];
- } MAILBOX_INIT;
- void readphys(uint32_t physsrc, void *pvdst, size_t cb)
- {
- if (!cb)
- return;
- const void *pvsrc;
- size_t page = 4096 - (physsrc & 0xfff);
- if (cb <= page)
- {
- memcpy(pvdst, pvsrc, cb);
- return;
- }
- memcpy(pvdst, pvsrc, page);
- physsrc += page;
- pvdst = (uint8_t *)pvdst + page;
- cb -= page;
- for (;;)
- {
- if (cb <= 4096)
- {
- memcpy(pvdst, pvsrc, cb);
- return;
- }
- memcpy(pvdst, pvsrc, 4096);
- physsrc += 4096;
- pvdst = (uint8_t *)pvdst + 4096;
- cb -= 4096;
- }
- }
- void writephys(uint32_t physdst, const void *pvsrc, size_t cb)
- {
- if (!cb)
- return;
- void *pvdst;
- size_t page = 4096 - (physdst & 0xfff);
- if (cb <= page)
- {
- memcpy(pvdst, pvsrc, cb);
- return;
- }
- memcpy(pvdst, pvsrc, page);
- physdst += page;
- pvsrc = (const uint8_t *)pvsrc + page;
- cb -= page;
- for (;;)
- {
- if (cb <= 4096)
- {
- memcpy(pvdst, pvsrc, cb);
- return;
- }
- memcpy(pvdst, pvsrc, 4096);
- physdst += 4096;
- pvsrc = (const uint8_t *)pvsrc + 4096;
- cb -= 4096;
- }
- }
- typedef struct aha1540_t
- {
- rom_t bios_rom;
- MAILBOX Mbx;
- CCB CmdBlock;
- SGSEG DataSeg;
- SCSI scsi[7];
- uint8_t status;
- uint8_t control;
- uint8_t interrupt;
- uint8_t mb_count;
- uint32_t mbo_pos_cur;
- uint32_t mbi_pos_cur;
- uint32_t mbo_base_phys;
- uint32_t mbi_base_phys;
- uint8_t command;
- uint8_t command_param;
- uint8_t command_param_left;
- uint8_t command_buffer[5];
- uint8_t reply_pos;
- uint8_t reply_left;
- uint8_t reply_buffer[64];
- uint32_t ccb32_phys;
- uint8_t SGEntry;
- int ctrl_timer;
- int irq;
- int dma;
- } aha1540_t;
- void aha1540_write_mbi(aha1540_t *aha1540, uint8_t HostStatus, uint8_t TargetStatus, uint8_t Status);
- void aha1540_buffer_free(aha1540_t *aha1540);
- inline void aha1540_mbo_next(aha1540_t *aha1540)
- {
- aha1540->mbo_pos_cur = (aha1540->mbo_pos_cur + 1) % aha1540->mb_count;
- }
- void aha1540_reset(void *p)
- {
- aha1540_t *aha1540 = (aha1540_t *)p;
- aha1540->status = IOP_SCSI_HBA_IDLE | IOP_MAILBOX_INIT_REQUIRED;
- aha1540->command = 0xff;
- aha1540->command_param = 0;
- aha1540->command_param_left = 0;
- aha1540->mbo_pos_cur = 0;
- aha1540->mbi_pos_cur = 0;
- aha1540->interrupt = 0;
- }
- void aha1540_command_complete(aha1540_t *aha1540)
- {
- aha1540->status |= IOP_SCSI_HBA_IDLE;
- aha1540->reply_pos = 0;
- if (aha1540->command != AC_START_SCSI_COMMAND)
- {
- aha1540->status &= ~IOP_DATA_IN_PORT_FULL;
- aha1540->interrupt = IOP_COMMAND_COMPLETE | IOP_ANY_INTERRUPT;
- picint(1 << aha1540->irq);
- }
- aha1540->command = 0xff;
- aha1540->command_param = 0;
- }
- void aha1540_init_reset(aha1540_t *aha1540, int hardreset)
- {
- aha1540_reset(aha1540);
- if (hardreset)
- {
- aha1540->status |= IOP_SELF_TEST;
- aha1540->status &= ~IOP_SCSI_HBA_IDLE;
- }
- }
- void aha1540_write_mbi(aha1540_t *aha1540, uint8_t HostStatus, uint8_t TargetStatus, uint8_t Status)
- {
- aha1540->Mbx.u.in.HostStatus = HostStatus;
- aha1540->Mbx.u.in.TargetStatus = TargetStatus;
- aha1540->Mbx.u.in.Status = Status;
- uint32_t mbi_phys = aha1540->mbi_base_phys + (aha1540->mbi_pos_cur * sizeof(MAILBOX));
- if (Status != MBI_NOT_FOUND)
- {
- uint32_t ccb_phys = aha1540->ccb32_phys;
- aha1540->CmdBlock.HostStatus = HostStatus;
- aha1540->CmdBlock.TargetStatus = TargetStatus;
- writephys(ccb_phys, &aha1540->CmdBlock, offsetof(CCB, Cdb));
- }
- if (Status != MBI_FREE)
- {
- uint8_t Code;
- unsigned CodeOffset = offsetof(MAILBOX, u.out.Command);
- readphys(mbi_phys + CodeOffset, &Code, sizeof(Code));
- }
- U32_TO_ADDR(aha1540->Mbx.Address, aha1540->ccb32_phys);
- writephys(mbi_phys, &aha1540->Mbx, sizeof(MAILBOX));
- aha1540->mbi_pos_cur++;
- if (aha1540->mbi_pos_cur >= aha1540->mb_count)
- aha1540->mbi_pos_cur = 0;
- aha1540->interrupt = IOP_MBI_FULL | IOP_ANY_INTERRUPT;
- picint(1 << aha1540->irq);
- }
- void aha1540_read_sg(aha1540_t *aha1540, uint32_t PhysSG, uint32_t Entries, SGD32 *SGList)
- {
- SGD aSGD[32];
- uint32_t i;
- assert(Entries <= elements(aSGD));
- readphys(PhysSG, &aSGD, Entries * sizeof(SGD));
- for (i=0;i<Entries;++i)
- {
- SGList[i].Length = ADDR_TO_U32(aSGD[i].Length);
- SGList[i].Address = ADDR_TO_U32(aSGD[i].Address);
- }
- }
- void aha1540_buffer_alloc(aha1540_t *aha1540)
- {
- uint32_t DataPointer = ADDR_TO_U32(aha1540->CmdBlock.DataPointer);
- uint32_t DataLength = ADDR_TO_U32(aha1540->CmdBlock.DataLength);
- if ((aha1540->CmdBlock.ControlByte != CCB_DATA_XFER_NONE) && DataLength)
- {
- if ((aha1540->CmdBlock.OperationCode == SCATTER_GATHER_OLD_COMMAND) || (aha1540->CmdBlock.OperationCode == SCATTER_GATHER_COMMAND))
- {
- uint32_t ScatterGatherRead;
- uint32_t i;
- SGD32 aScatterGatherRead[32];
- uint32_t ScatterGatherLeft = DataLength / aha1540->SGEntry;
- uint32_t ScatterGatherPhys = DataPointer;
- size_t DataTx = 0;
- while (ScatterGatherLeft < 0)
- {
- ScatterGatherRead = (ScatterGatherLeft < elements(aScatterGatherRead)) ? ScatterGatherLeft : elements(aScatterGatherRead);
- ScatterGatherLeft -= ScatterGatherRead;
- aha1540_read_sg(aha1540, ScatterGatherPhys, ScatterGatherRead, aScatterGatherRead);
- for (i=0;i<ScatterGatherLeft;i++)
- {
- uint32_t PhysPointer;
- PhysPointer = aScatterGatherRead[i].Address;
- DataTx += aScatterGatherRead[i].Length;
- }
- ScatterGatherPhys += ScatterGatherRead * aha1540->SGEntry;
- }
- aha1540->DataSeg.segment = DataTx;
- aha1540->DataSeg.segment_ptr = malloc(aha1540->DataSeg.segment);
- }
- }
- else if (aha1540->CmdBlock.OperationCode == SCSI_INITIATOR_OLD_COMMAND || aha1540->CmdBlock.OperationCode == SCSI_INITIATOR_COMMAND)
- {
- uint32_t PhysPointer = DataPointer;
- aha1540->DataSeg.segment = DataLength;
- aha1540->DataSeg.segment_ptr = malloc(aha1540->DataSeg.segment);
- readphys(PhysPointer, aha1540->DataSeg.segment_ptr, aha1540->DataSeg.segment);
- }
- }
- void aha1540_buffer_free(aha1540_t *aha1540)
- {
- uint32_t DataPointer = ADDR_TO_U32(aha1540->CmdBlock.DataPointer);
- uint32_t DataLength = ADDR_TO_U32(aha1540->CmdBlock.DataLength);
- #if 1
- if (aha1540->CmdBlock.Cdb[0] == 0)
- DataLength = 0;
- #endif
- if ((DataLength > 0) && ((aha1540->CmdBlock.ControlByte == CCB_DATA_XFER_IN)))
- {
- if ((aha1540->CmdBlock.OperationCode == SCATTER_GATHER_OLD_COMMAND) || (aha1540->CmdBlock.OperationCode == SCATTER_GATHER_COMMAND))
- {
- uint32_t ScatterGatherRead;
- uint32_t i;
- SGD32 aScatterGatherRead[32];
- uint32_t ScatterGatherLeft = DataLength / aha1540->SGEntry;
- uint32_t ScatterGatherPhys = DataPointer;
- uint8_t *Data = (uint8_t *)aha1540->DataSeg.segment_ptr;
- while (ScatterGatherLeft < 0)
- {
- ScatterGatherRead = (ScatterGatherLeft < elements(aScatterGatherRead)) ? ScatterGatherLeft : elements(aScatterGatherRead);
- ScatterGatherLeft -= ScatterGatherRead;
- aha1540_read_sg(aha1540, ScatterGatherPhys, ScatterGatherRead, aScatterGatherRead);
- for (i=0;i<ScatterGatherLeft;i++)
- {
- uint32_t PhysPointer;
- size_t DataTx;
- PhysPointer = aScatterGatherRead[i].Address;
- DataTx = aScatterGatherRead[i].Length;
- writephys(PhysPointer, Data, DataTx);
- Data += DataTx;
- }
- ScatterGatherPhys += ScatterGatherRead * aha1540->SGEntry;
- }
- }
- else if (aha1540->CmdBlock.OperationCode == SCSI_INITIATOR_OLD_COMMAND || aha1540->CmdBlock.OperationCode == SCSI_INITIATOR_COMMAND)
- {
- uint32_t PhysPointer = DataPointer;
- writephys(PhysPointer, aha1540->DataSeg.segment_ptr, aha1540->DataSeg.segment);
- }
- }
- if ((aha1540->CmdBlock.OperationCode == SCSI_INITIATOR_COMMAND) || (aha1540->CmdBlock.OperationCode == SCATTER_GATHER_COMMAND))
- {
- uint32_t Residual = 0;
- U32_TO_ADDR(aha1540->CmdBlock.DataLength, Residual);
- }
- free(aha1540->DataSeg.segment_ptr);
- aha1540->DataSeg.segment = 0;
- }
- void aha1540_command(void *p)
- {
- aha1540_t *aha1540 = (aha1540_t *)p;
- switch (aha1540->command)
- {
- case AC_NO_OPERATION:
- aha1540->reply_left = 0;
- break;
- case AC_MAILBOX_INITIALIZATION:
- {
- MAILBOX_INIT *MbxInit = (MAILBOX_INIT *)aha1540->command_buffer;
- aha1540->mb_count = MbxInit->Count;
- aha1540->mbo_base_phys = ADDR_TO_U32(MbxInit->Address);
- aha1540->mbi_base_phys = aha1540->mbo_base_phys + (aha1540->mb_count * sizeof(MAILBOX));
- aha1540->status &= ~IOP_MAILBOX_INIT_REQUIRED;
- aha1540->reply_left = 0;
- break;
- }
- case AC_ADAPTER_INQUIRY:
- aha1540->reply_buffer[0] = 0x41;
- aha1540->reply_buffer[1] = 0x41;
- aha1540->reply_buffer[2] = 0x33;
- aha1540->reply_buffer[3] = 0x31;
- aha1540->reply_left = 4;
- break;
- case AC_SET_SELECTION_TIMEOUT:
- aha1540->reply_left = 0;
- break;
- case AC_SET_BUS_ON_TIME:
- {
- int BusOn;
- aha1540->reply_left = 0;
- BusOn = aha1540->command_buffer[0];
- break;
- }
- case AC_SET_BUS_OFF_TIME:
- {
- int BusOff;
- aha1540->reply_left = 0;
- BusOff = aha1540->command_buffer[0];
- break;
- }
- case AC_SET_TRANSFER_SPEED:
- {
- int TxSpeed;
- aha1540->reply_left = 0;
- TxSpeed = aha1540->command_buffer[0];
- break;
- }
- case AC_RET_CONFIGURATION_DATA:
- aha1540->reply_buffer[0] = aha1540->dma;
- if (aha1540->dma)
- {
- dma_channel_write(0xD6, 0xC2);
- dma_channel_write(0xD4, 0x02);
- }
- aha1540->reply_buffer[1] = aha1540->irq;
- aha1540->reply_buffer[2] = 0x07;
- aha1540->reply_left = 3;
- break;
- case AC_RETURN_SETUP_DATA:
- aha1540->reply_left = aha1540->command_buffer[0];
- aha1540->reply_buffer[4] = aha1540->mb_count;
- aha1540->reply_buffer[5] = aha1540->mbo_base_phys >> 16;
- aha1540->reply_buffer[6] = aha1540->mbo_base_phys >> 8;
- aha1540->reply_buffer[7] = aha1540->mbo_base_phys;
- break;
- case AC_ECHO_COMMAND_DATA:
- aha1540->reply_buffer[0] = aha1540->command_buffer[0];
- aha1540->reply_left = 1;
- break;
- default:
- aha1540->status |= IOP_INVALID_COMMAND;
- break;
- }
- pclog("aha1540: operation code 0x%02X, replies left %d\n", aha1540->command, aha1540->reply_left);
- if (aha1540->reply_left)
- aha1540->status |= IOP_DATA_IN_PORT_FULL;
- else if (!aha1540->command_param_left)
- aha1540_command_complete(aha1540);
- }
- uint32_t aha1540_read_mbo(aha1540_t *aha1540)
- {
- uint32_t mbo_base_phys = aha1540->mbo_base_phys + (aha1540->mbo_pos_cur * sizeof(MAILBOX));
- readphys(mbo_base_phys, &aha1540->Mbx, sizeof(MAILBOX));
- aha1540->ccb32_phys = ADDR_TO_U32(aha1540->Mbx.Address);
- return mbo_base_phys;
- }
- uint8_t aha1540_read(uint16_t port, void *p)
- {
- aha1540_t *aha1540 = (aha1540_t *)p;
- uint8_t ret;
- switch (port)
- {
- case 0x334:
- ret = aha1540->status;
- if (aha1540->status & IOP_SELF_TEST)
- {
- aha1540->status &= ~IOP_SELF_TEST;
- aha1540->status |= IOP_SCSI_HBA_IDLE;
- ret = aha1540->status;
- }
- break;
- case 0x335:
- ret = aha1540->reply_buffer[aha1540->reply_pos++];
- if (aha1540->reply_left)
- {
- aha1540->reply_left--;
- if (!aha1540->reply_left)
- {
- aha1540_command_complete(aha1540);
- }
- }
- break;
- case 0x336:
- ret = aha1540->interrupt;
- break;
- }
- pclog("aha1540: read port 0x%04X, ret %02X\n", port, ret);
- return ret;
- }
- void aha1540_write(uint16_t port, uint8_t val, void *p)
- {
- aha1540_t *aha1540 = (aha1540_t *)p;
- pclog("aha1540: write port 0x%04X, val %02X\n", port, val);
- switch (port)
- {
- case 0x334:
- if ((val & IOP_HARD_RESET) || (val & IOP_SOFT_RESET))
- {
- int hardreset = !!(val & IOP_HARD_RESET);
- aha1540_init_reset(aha1540, hardreset);
- break;
- }
- if (val & IOP_INTERRUPT_RESET)
- {
- aha1540->interrupt = 0;
- picintc(1 << aha1540->irq);
- }
- break;
- case 0x335:
- if ((val == AC_START_SCSI_COMMAND) && (aha1540->command == 0xff))
- {
- uint32_t mbo_phys;
- aha1540->SGEntry = sizeof(SGD);
- mbo_phys = aha1540_read_mbo(aha1540);
- uint8_t Command = MBO_FREE;
- unsigned CodeOffset = offsetof(MAILBOX, u.out.Command);
- writephys(mbo_phys + CodeOffset, &Command, sizeof(Command));
- aha1540->Mbx.u.out.Command = MBO_START;
- uint8_t id;
- uint32_t ccb_phys = aha1540->ccb32_phys;
- readphys(ccb_phys, &aha1540->CmdBlock, sizeof(CCB));
- id = (scsi_id << 5) & 7;
- if (id)
- {
- SCSI *scsi = &aha1540->scsi[id];
- aha1540_buffer_alloc(aha1540);
- scsi->lun = aha1540->CmdBlock.Lun;
- if (aha1540->CmdBlock.ControlByte == CCB_DATA_XFER_IN)
- scsi->txdir = SCSI_READ_TX;
- else if (aha1540->CmdBlock.ControlByte == CCB_DATA_XFER_OUT)
- scsi->txdir = SCSI_WRITE_TX;
- else if (aha1540->CmdBlock.ControlByte == CCB_DATA_XFER_NONE)
- scsi->txdir = SCSI_NONE_TX;
- scsi->cmdlen = aha1540->CmdBlock.CdbLength;
- scsi->cdb = aha1540->CmdBlock.Cdb;
- scsi_command(scsi);
- }
- aha1540_mbo_next(aha1540);
- break;
- }
- if (aha1540->command == 0xff)
- {
- aha1540->command = val;
- aha1540->command_param = 0;
- aha1540->status &= ~IOP_INVALID_COMMAND;
- switch (aha1540->command)
- {
- case AC_NO_OPERATION:
- case AC_ADAPTER_INQUIRY:
- case AC_RET_CONFIGURATION_DATA:
- aha1540->command_param_left = 0;
- break;
- case AC_MAILBOX_INITIALIZATION:
- aha1540->command_param_left = sizeof(MAILBOX);
- break;
- case AC_SET_BUS_ON_TIME:
- case AC_SET_BUS_OFF_TIME:
- case AC_SET_TRANSFER_SPEED:
- case AC_RETURN_SETUP_DATA:
- case AC_ECHO_COMMAND_DATA:
- aha1540->command_param_left = 1;
- break;
- case AC_SET_SELECTION_TIMEOUT:
- aha1540->command_param_left = 4;
- break;
- default:
- break;
- }
- }
- else
- {
- aha1540->command_buffer[aha1540->command_param++] = val;
- aha1540->command_param_left--;
- }
- if (!aha1540->command_param_left)
- aha1540_command(aha1540);
- break;
- }
- }
- void *aha1540_init()
- {
- aha1540_t *aha1540 = malloc(sizeof(aha1540_t));
- memset(aha1540, 0, sizeof(aha1540_t));
- //rom_init(&aha1540->bios_rom, "roms/154XP334.bin", 0xd8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
- aha1540->dma |= 0x40; //DMA 6
- aha1540->irq |= 0x04; //IRQ 11
- io_sethandler(0x0334, 0x0004, aha1540_read, NULL, NULL, aha1540_write, NULL, NULL, aha1540);
- //timer_add(aha1540_poll, &aha1540->ctrl_timer, TIMER_ALWAYS_ENABLED, aha1540);
- aha1540_reset(aha1540);
- return aha1540;
- }
- static int aha1540_available()
- {
- return rom_present("roms/154XP334.bin");
- }
- void aha1540_close(void *p)
- {
- aha1540_t *aha1540 = (aha1540_t *)p;
- free(aha1540);
- }
- device_t aha1540_device =
- {
- "Adaptec AHA-1540 series",
- 0,
- aha1540_init,
- aha1540_close,
- NULL,//aha1540_available,
- NULL,
- NULL,
- NULL
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement