RASCSI/src/raspberrypi/devices/scsi_daynaport.h
Uwe Seimet 0e8d89e827
Code cleanup, in particular related to MODE SENSE (#699)
* Replace member functions

* Fixed TODO

* Added TODOs

* Added TODOs

* Removed duplicate code

* Fixed return value

* CD-ROM mode pages are provided by the CD-ROM implementation

* MO mode pages are provided by the MO implementation

* Comment update

* Removed duplicate code

* Removed more duplicate code

* Optimization

* Updated mode page size handling

* Addec TODO

* Started more flexible mode page handling

* Map mode pages

* Page 0 must be last

* Error handling update

* Updated size handling

* Updated map handling

* Use map references

* Move superclass call

* Added comment

* Host services also support mode page 0x3f (all pages)

* Updated handling of page 0

* Removed duplicate code

* Updated buffer size handling

* Code cleanup

* Removed duplicate code

* Use calloc()

* Removed duplicate code

* Comment update

* Fixed buffer offset

* Fixed TODO

* Added buffer size check

* Comment udpate

* Logging update

* Updated logging

* Avoid potential memory leak

* Updated handling of page 0

* Added TODO

* Comment update

* Fixed error message

* Use vector instead of byte array

* Optimization

* More optimizations

* Removed duplicate code

* Do not try to add more pages when buffer is full

* Updated error message

* Comment update, fixed host services message length handling

* Code cleanup, optimizations

* Updated payload handling for page 0

* Fixed TODO

* Updated handling of PS field

* Fixed offsets

* Updated handling for page 0

* Code cleanup

* More cleanup

* Updated block descriptor handling

* Result of REPORT LUNS must not depend on whether a device is ready or not

* Printer uses a dynamically allocated buffer

* Use realloc

* Updated memory handling

* Added assertion

* Comment update

* Fixed initialization

* Reset byte transfer flag

* Updated usage of realloc

* Reverted some changes

* Re-added buffer size check

* Renaming

* Inquiry for hard disk must also work when drive is not ready

* Primary device checks EVPD

* Added page code check to Inquiry

* Explicitly set response level format

* Added comment

* Removed useless cast

* Fixed inconsistencies in setting the additional length

* Logging uodate

* Updated logging

* Made methods const

* Moved code

* Added TODO

* Added vendor page

* Reduced visibility

* Code cleanup

* Mark override

* Removed duplicate cast

* Synchronized host services mode page handling with other code

* Added TODO

* Signature update

* Moved code

* Removed duplicate code

* Fixed TODO

* Removed duplicate code

* Added buffer size check

* Improved buffer size check

* Code cleanup

* Removed useless assertions

* Cleanup

* Renaming

* Added overrides

* Removed unnecessary casts

* Cleanup

* Added TODO

* Removed obsolete memset

* Removed duplicate code

* Logging update

* Logging update

* Assertion update

* Removed useless comments

* Code cleanup

* Removed obsolete casts

* User super typedef

* Updated log messages

* Fixed #712

* Updated error handling

* Removed useless assertions

* Reduced casts to Disk*

* Updated sector size list argument

* Removed obsolete casts

* Removed comment
2022-02-27 15:58:01 -06:00

144 lines
4.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2020 akuker
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ Emulation of the DaynaPort SCSI Link Ethernet interface ]
//
// This design is derived from the SLINKCMD.TXT file, as well as David Kuder's
// Tiny SCSI Emulator
// - SLINKCMD: http://www.bitsavers.org/pdf/apple/scsi/dayna/daynaPORT/SLINKCMD.TXT
// - Tiny SCSI : https://hackaday.io/project/18974-tiny-scsi-emulator
//
// Special thanks to @PotatoFi for loaning me his Farallon EtherMac for
// this development. (Farallon's EtherMac is a re-branded DaynaPort
// SCSI/Link-T).
//
// This does NOT include the file system functionality that is present
// in the Sharp X68000 host bridge.
//
// Note: This requires the DaynaPort SCSI Link driver.
//---------------------------------------------------------------------------
#pragma once
#include "os.h"
#include "disk.h"
#include "ctapdriver.h"
#include <map>
#include <string>
//===========================================================================
//
// DaynaPort SCSI Link
//
//===========================================================================
class SCSIDaynaPort: public Disk
{
public:
SCSIDaynaPort();
~SCSIDaynaPort();
bool Init(const map<string, string>&) override;
void Open(const Filepath& path) override;
// Commands
int Inquiry(const DWORD *cdb, BYTE *buffer) override;
int Read(const DWORD *cdb, BYTE *buf, uint64_t block) override;
bool Write(const DWORD *cdb, const BYTE *buf, DWORD block) override;
int WriteCheck(DWORD block) override; // WRITE check
int RetrieveStats(const DWORD *cdb, BYTE *buffer);
bool EnableInterface(const DWORD *cdb);
void SetMacAddr(const DWORD *cdb, BYTE *buffer); // Set MAC address
void TestUnitReady(SASIDEV *) override;
void Read6(SASIDEV *) override;
void Write6(SASIDEV *) override;
void RetrieveStatistics(SASIDEV *);
void SetInterfaceMode(SASIDEV *);
void SetMcastAddr(SASIDEV *);
void EnableInterface(SASIDEV *);
int GetSendDelay() override;
bool Dispatch(SCSIDEV *) override;
const int DAYNAPORT_BUFFER_SIZE = 0x1000000;
static const BYTE CMD_SCSILINK_STATS = 0x09;
static const BYTE CMD_SCSILINK_ENABLE = 0x0E;
static const BYTE CMD_SCSILINK_SET = 0x0C;
static const BYTE CMD_SCSILINK_SETMODE = 0x80;
static const BYTE CMD_SCSILINK_SETMAC = 0x40;
// When we're reading the Linux tap device, most of the messages will not be for us, so we
// need to filter through those. However, we don't want to keep re-reading the packets
// indefinitely. So, we'll pick a large-ish number that will cause the emulated DaynaPort
// to respond with "no data" after MAX_READ_RETRIES tries.
static const int MAX_READ_RETRIES = 50;
// The READ response has a header which consists of:
// 2 bytes - payload size
// 4 bytes - status flags
static const DWORD DAYNAPORT_READ_HEADER_SZ = 2 + 4;
private:
typedef Disk super;
Dispatcher<SCSIDaynaPort, SASIDEV> dispatcher;
typedef struct __attribute__((packed)) {
BYTE operation_code;
BYTE misc_cdb_information;
BYTE logical_block_address;
uint16_t length;
BYTE format;
} scsi_cmd_daynaport_write_t;
enum read_data_flags_t : uint32_t {
e_no_more_data = 0x00000000,
e_more_data_available = 0x00000001,
e_dropped_packets = 0xFFFFFFFF,
};
typedef struct __attribute__((packed)) {
uint32_t length;
read_data_flags_t flags;
BYTE pad;
BYTE data[ETH_FRAME_LEN + sizeof(uint32_t)]; // Frame length + 4 byte CRC
} scsi_resp_read_t;
typedef struct __attribute__((packed)) {
BYTE mac_address[6];
uint32_t frame_alignment_errors;
uint32_t crc_errors;
uint32_t frames_lost;
} scsi_resp_link_stats_t;
scsi_resp_link_stats_t m_scsi_link_stats = {
.mac_address = { 0x00, 0x80, 0x19, 0x10, 0x98, 0xE3 },//MAC address of @PotatoFi's DayanPort
.frame_alignment_errors = 0,
.crc_errors = 0,
.frames_lost = 0,
};
const BYTE m_daynacom_mac_prefix[3] = { 0x00, 0x80, 0x19 };
CTapDriver *m_tap;
// TAP driver
bool m_bTapEnable;
// TAP valid flag
BYTE m_mac_addr[6];
// MAC Address
static const BYTE m_bcast_addr[6];
static const BYTE m_apple_talk_addr[6];
};