Skip to content

Commit

Permalink
Implement Iomega ZIP100 support
Browse files Browse the repository at this point in the history
  • Loading branch information
jokker7718 authored and Troy committed May 4, 2024
1 parent 98c8a4b commit 4c8b6a9
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 8 deletions.
1 change: 1 addition & 0 deletions lib/SCSI2SD/include/scsi2sd.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ typedef enum
S2S_CFG_MO,
S2S_CFG_SEQUENTIAL,
S2S_CFG_NETWORK,
S2S_CFG_ZIP100,
} S2S_CFG_TYPE;

typedef enum
Expand Down
22 changes: 22 additions & 0 deletions lib/SCSI2SD/src/firmware/mode.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,20 @@ static const uint8_t BlueSCSIVendorPage[] =
'S','T','O','L','E','N',' ','F','R','O','M',' ','B','L','U','E','S','C','S','I',0x00
};

static const uint8_t IomegaZip100VendorPage[] =
{
0x2f, // Page Code
4, // Page Length
0x5c, 0xf, 0xff, 0xf
};

static const uint8_t IomegaZip250VendorPage[] =
{
0x2f, // Page Code
4, // Page Length
0x5c, 0xf, 0x3c, 0xf
};

static void pageIn(int pc, int dataIdx, const uint8_t* pageData, int pageLen)
{
memcpy(&scsiDev.data[dataIdx], pageData, pageLen);
Expand Down Expand Up @@ -510,6 +524,14 @@ static void doModeSense(
idx += modeSenseCDDevicePage(pc, idx, pageCode, &pageFound);
idx += modeSenseCDAudioControlPage(pc, idx, pageCode, &pageFound);

if ((scsiDev.target->cfg->deviceType == S2S_CFG_ZIP100) &&
(pageCode == 0x2f || pageCode == 0x3f))
{
pageFound = 1;
pageIn(pc, idx, IomegaZip100VendorPage, sizeof(IomegaZip100VendorPage));
idx += sizeof(IomegaZip100VendorPage);
}

if ((scsiDev.target->cfg->deviceType == S2S_CFG_SEQUENTIAL) &&
(pageCode == 0x10 || pageCode == 0x3F))
{
Expand Down
1 change: 1 addition & 0 deletions lib/SCSI2SD/src/firmware/scsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "geometry.h"
#include "sense.h"
#include "vendor.h"

#include <stdint.h>

Expand Down
79 changes: 78 additions & 1 deletion lib/SCSI2SD/src/firmware/vendor.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "vendor.h"
#include "diagnostic.h"

#include <string.h>

// Callback after the DATA OUT phase is complete.
static void doAssignDiskParameters(void)
{
Expand All @@ -45,8 +47,83 @@ int scsiVendorCommand()
int commandHandled = 1;

uint8_t command = scsiDev.cdb[0];
uint8_t alloc_length = scsiDev.cdb[4];

// iomega sense command
if (command == 0x06 && scsiDev.target->cfg->deviceType == S2S_CFG_ZIP100)
{
int subcommand = scsiDev.cdb[2];
scsiDev.phase = DATA_IN;

// byte 0 is the page
scsiDev.data[0] = subcommand;

if (subcommand == 0x1)
{
// page is 86 bytes in length
scsiDev.dataLen = alloc_length < 0x58 ? alloc_length : 0x58;
memset(&scsiDev.data[1], 0xff, scsiDev.dataLen);
// byte 1 is the page length minus pagecode and length
scsiDev.data[1] = scsiDev.dataLen - 2;

scsiDev.data[2] = 1;
scsiDev.data[3] = 0;
scsiDev.data[4] = 0;
scsiDev.data[5] = 0;
scsiDev.data[6] = 0x5;
scsiDev.data[7] = 0xdc;
scsiDev.data[8] = 0x6;
scsiDev.data[9] = 0xc;
scsiDev.data[10] = 0x5;
scsiDev.data[11] = 0xdc;
scsiDev.data[12] = 0x6;
scsiDev.data[13] = 0xc;
scsiDev.data[14] = 0;
}
else if (subcommand == 0x2) {
// page is 61 bytes in length
scsiDev.dataLen = alloc_length < 0x3f ? alloc_length : 0x3f;
memset(&scsiDev.data[1], 0, scsiDev.dataLen);
// byte 1 is the page length minus pagecode and length
scsiDev.data[1] = scsiDev.dataLen - 2;

scsiDev.data[3] = 2;
scsiDev.data[6] = 0x2;
scsiDev.data[7] = 0xff;
scsiDev.data[8] = 0xff;
scsiDev.data[11] = 0x2;

if (command == 0xC0)
// this has something to do with the format/disk life
// currently this makes it 100%
scsiDev.data[14] = 0x7e;
scsiDev.data[18] = 0x7e;

// byte 21 is the read/write/password settings
// 5 = password for R/W
// 3 = password for W
// 2 = RO
// 0 = RW
scsiDev.data[20] = 0;

// set a serial number ABCDEFGHIJKLMNO
// starts at byte 25 and is 15 bytes long
for(int i = 0; i < 20; i++) {
scsiDev.data[25 + i] = i + 0x41;
}

scsiDev.data[0x3e] = 1;
}
else
{
// anything else is an illegal command
scsiDev.status = CHECK_CONDITION;
scsiDev.target->sense.code = ILLEGAL_REQUEST;
scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_SUPPORTED;
scsiDev.phase = STATUS;
}

}
else if (command == 0xC0)
{
// Define flexible disk format
// OMTI-5204 controller
Expand Down
3 changes: 3 additions & 0 deletions lib/SCSI2SD/src/firmware/vendor.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#ifndef S2S_VENDOR_H
#define S2S_VENDOR_H

#define ZIP100_DISC_SIZE 100663296 // bytes
#define ZIP250_DISC_SIZE 250640384 // bytes

int scsiVendorCommand(void);

#endif
4 changes: 3 additions & 1 deletion src/BlueSCSI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,14 +284,15 @@ bool findHDDImages()
bool is_ne = (tolower(name[0]) == 'n' && tolower(name[1]) == 'e');
bool is_re = (tolower(name[0]) == 'r' && tolower(name[1]) == 'e');
bool is_tp = (tolower(name[0]) == 't' && tolower(name[1]) == 'p');
bool is_zp = (tolower(name[0]) == 'z' && tolower(name[1]) == 'p');

if(strcasecmp(name, "CLEAR_ROM") == 0)
{
romDriveClear();
continue;
}

if (is_hd || is_cd || is_fd || is_mo || is_ne || is_re || is_tp)
if (is_hd || is_cd || is_fd || is_mo || is_ne || is_re || is_tp || is_zp)
{
// Check if the image should be loaded to microcontroller flash ROM drive
bool is_romdrive = false;
Expand Down Expand Up @@ -371,6 +372,7 @@ bool findHDDImages()
if (is_ne) type = S2S_CFG_NETWORK;
if (is_re) type = S2S_CFG_REMOVEABLE;
if (is_tp) type = S2S_CFG_SEQUENTIAL;
if (is_zp) type = S2S_CFG_ZIP100;

// Open the image file
if (id < NUM_SCSIID && is_romdrive)
Expand Down
5 changes: 5 additions & 0 deletions src/BlueSCSI_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@
#define APPLE_DRIVEINFO_NETWORK {"Dayna", "SCSI/Link", "2.0f", ""}
#define APPLE_DRIVEINFO_TAPE {"BlueSCSI", "APPLE_TAPE", "", ""}

// Default Iomega ZIP drive information
#define IOMEGA_DRIVEINFO_ZIP100 {"IOMEGA", "ZIP 100", "E.08", ""}
#define IOMEGA_DRIVEINFO_ZIP250 {"IOMEGA", "ZIP 250", "42.S", ""}
#define IOMEGA_DRIVEINFO_JAZ {"iomega", "jaz", "", ""}

// Default delay for SCSI phases.
// Can be adjusted in ini file
#define DEFAULT_SCSI_DELAY_US 10
Expand Down
33 changes: 27 additions & 6 deletions src/BlueSCSI_disk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,8 @@ static void setDefaultDriveInfo(int target_idx)
static const char *apl_driveinfo_network[4] = APPLE_DRIVEINFO_NETWORK;
static const char *apl_driveinfo_tape[4] = APPLE_DRIVEINFO_TAPE;

static const char *iomega_driveinfo_removeable[4] = IOMEGA_DRIVEINFO_ZIP100;

const char **driveinfo = NULL;

if (img.quirks == S2S_CFG_QUIRKS_APPLE)
Expand Down Expand Up @@ -302,6 +304,7 @@ static void setDefaultDriveInfo(int target_idx)
case S2S_CFG_MO: driveinfo = driveinfo_magopt; break;
case S2S_CFG_NETWORK: driveinfo = driveinfo_network; break;
case S2S_CFG_SEQUENTIAL: driveinfo = driveinfo_tape; break;
case S2S_CFG_ZIP100: driveinfo = iomega_driveinfo_removeable; break;
default: driveinfo = driveinfo_fixed; break;
}
}
Expand Down Expand Up @@ -429,6 +432,18 @@ bool scsiDiskOpenHDDImage(int target_idx, const char *filename, int scsi_id, int
log("---- Configuring as tape drive based on image name");
img.deviceType = S2S_CFG_SEQUENTIAL;
}
else if (type == S2S_CFG_ZIP100)
{
log("---- Configuration as Iomega ZIP100 drive based on image name");
img.deviceType = S2S_CFG_ZIP100;
if(img.file.size() != ZIP100_DISC_SIZE)
{
log("---- ZIP100 disc (", (int)img.file.size(), " bytes) is not exactly ", ZIP100_DISC_SIZE, " bytes, drive is ignored");
img.file.close();
img.clear();
return false;
}
}

if (img.prefetchbytes != PREFETCH_BUFFER_SIZE)
{
Expand Down Expand Up @@ -1863,14 +1878,20 @@ int scsiDiskCommand()
// Enable or disable media access operations.
//int immed = scsiDev.cdb[1] & 1;
int start = scsiDev.cdb[4] & 1;

if (start)
if (scsiDev.target->cfg->deviceType == S2S_CFG_ZIP100)
{
scsiDev.target->started = 1;
if (start)
{
scsiDev.target->started = 1;
}
else
{
scsiDev.target->started = 0;
}
}
else
{
scsiDev.target->started = 0;
else {
scsiDev.target->started = 1;
}
}
else if (unlikely(command == 0x00))
Expand Down
1 change: 1 addition & 0 deletions src/BlueSCSI_log_trace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ static const char *getCommandName(uint8_t cmd)
case 0x03: return "RequestSense";
case 0x04: return "FormatUnit";
case 0x05: return "ReadBlockLimits";
case 0x06: return "IomegaVendorCommand";
case 0x08: return "Read6";
case 0x0A: return "Write6";
case 0x0B: return "Seek6";
Expand Down

0 comments on commit 4c8b6a9

Please sign in to comment.