--- BasiliskII/src/AmigaOS/scsi_amiga.cpp 1999/10/03 14:16:25 1.1.1.1 +++ BasiliskII/src/AmigaOS/scsi_amiga.cpp 2008/01/01 09:40:31 1.9 @@ -1,7 +1,7 @@ /* * scsi_amiga.cpp - SCSI Manager, Amiga specific stuff * - * Basilisk II (C) 1997-1999 Christian Bauer + * Basilisk II (C) 1997-2008 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,7 +22,9 @@ #include #include #include +#define __USE_SYSBASE #include +#include #include "sysdeps.h" #include "main.h" @@ -44,12 +46,15 @@ static struct MsgPort *the_port = NULL; static ULONG buffer_size; // Size of data buffer static UBYTE *buffer = NULL; // Pointer to data buffer +static ULONG buffer_memf; // Buffer memory flags static UBYTE cmd_buffer[12]; // Buffer for SCSI command const int SENSE_LENGTH = 256; static UBYTE *sense_buffer = NULL; // Buffer for autosense data +static bool direct_transfers_supported = false; // Direct data transfers (bypassing the buffer) are supported + /* * Initialization @@ -59,12 +64,26 @@ void SCSIInit(void) { int id, lun; + int memtype = PrefsFindInt32("scsimemtype"); + switch (memtype) { + case 1: + buffer_memf = MEMF_24BITDMA | MEMF_PUBLIC; + break; + case 2: + buffer_memf = MEMF_ANY | MEMF_PUBLIC; + direct_transfers_supported = true; + break; + default: + buffer_memf = MEMF_CHIP | MEMF_PUBLIC; + break; + } + // Create port and buffers the_port = CreateMsgPort(); - buffer = (UBYTE *)AllocMem(buffer_size = 0x10000, MEMF_CHIP | MEMF_PUBLIC); + buffer = (UBYTE *)AllocMem(buffer_size = 0x10000, buffer_memf); sense_buffer = (UBYTE *)AllocMem(SENSE_LENGTH, MEMF_CHIP | MEMF_PUBLIC); if (the_port == NULL || buffer == NULL || sense_buffer == NULL) { - ErrorAlert(GetString(STR_NO_MEM_ERR)); + ErrorAlert(STR_NO_MEM_ERR); QuitEmulator(); } @@ -83,7 +102,7 @@ void SCSIInit(void) struct IOStdReq *io = (struct IOStdReq *)CreateIORequest(the_port, sizeof(struct IOStdReq)); if (io == NULL) continue; - if (OpenDevice((UBYTE *)dev_name, dev_unit + lun * 10, (struct IORequest *)io, 0)) { + if (OpenDevice((UBYTE *) dev_name, dev_unit + lun * 10, (struct IORequest *)io, 0)) { DeleteIORequest(io); continue; } @@ -142,7 +161,7 @@ static bool try_buffer(int size) if (size <= buffer_size) return true; - UBYTE *new_buffer = (UBYTE *)AllocMem(size, MEMF_CHIP | MEMF_PUBLIC); + UBYTE *new_buffer = (UBYTE *)AllocMem(size, buffer_memf); if (new_buffer == NULL) return false; FreeMem(buffer, buffer_size); @@ -196,23 +215,29 @@ bool scsi_set_target(int id, int lun) bool scsi_send_cmd(size_t data_length, bool reading, int sg_size, uint8 **sg_ptr, uint32 *sg_len, uint16 *stat, uint32 timeout) { - // Check if buffer is large enough, allocate new buffer if needed - if (!try_buffer(data_length)) { - char str[256]; - sprintf(str, GetString(STR_SCSI_BUFFER_ERR), data_length); - ErrorAlert(str); - return false; - } + // Bypass the buffer if there's only one S/G table entry + bool do_direct_transfer = (sg_size == 1 && ((uint32)sg_ptr[0] & 1) == 0 && direct_transfers_supported); + + if (!do_direct_transfer) { - // Process S/G table when writing - if (!reading) { - D(bug(" writing to buffer\n")); - uint8 *buffer_ptr = buffer; - for (int i=0; i