Support multiple drives at once; fix id of JAZ drives.
This commit is contained in:
parent
e3582f94a0
commit
9a73a4cf0c
|
@ -10,7 +10,7 @@
|
|||
#include "iomega_cmds.h"
|
||||
|
||||
bool process_command();
|
||||
void confirm_run_tip(int id);
|
||||
void confirm_run_tip();
|
||||
void printn( unsigned char *c, int n );
|
||||
void print_help();
|
||||
void scan_bus();
|
||||
|
@ -60,7 +60,7 @@ bool process_command() {
|
|||
case 'i': dev_info(arg_val); break;
|
||||
case 'v': mac_list_volumes(); break;
|
||||
case 'u': mac_unmount(arg_val); break;
|
||||
case 't': confirm_run_tip(arg_val); break;
|
||||
case 't': confirm_run_tip(); break;
|
||||
case 'q': return false;
|
||||
case 'o': SetRichEditText(arg_str); break;
|
||||
default: printf("Unknown command, type 'h' for help\n");
|
||||
|
@ -68,12 +68,12 @@ bool process_command() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void confirm_run_tip(int id) {
|
||||
void confirm_run_tip() {
|
||||
char cmd[80];
|
||||
printf("\nThis program is in BETA TESTING and may cause severe data loss!\n\nProceed [Y/N]? ");
|
||||
gets( cmd );
|
||||
if(tolower(cmd[0]) == 'y') {
|
||||
run_tip(id);
|
||||
run_tip();
|
||||
}
|
||||
printf("\n\nYou may need to REBOOT your Mac before cartridges are recognized by Mac OS.");
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ void print_help() {
|
|||
"\nIomega device operations on SCSI device:\n"
|
||||
" spin [n] : spin up a cartridge\n"
|
||||
" eject [n] : eject cartridge\n"
|
||||
" tip [n] : run Steve Gibson's TIP 2.1\n"
|
||||
" tip : run Steve Gibson's TIP 2.1\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
File diff suppressed because one or more lines are too long
|
@ -1 +1,31 @@
|
|||
/************************************************************
Text Box.h
AUTHOR: Marcio Luis Teixeira
CREATED: 3/16/95
LAST REVISION: 11/29/2021
(c) 1994-2021 by Marcio Luis Teixeira.
All rights reserved.
*************************************************************/
#include "ctype.h"
typedef struct {
TEHandle tbox;
Rect frame;
ControlHandle scroll;
short lastV;
short maxV;
} TBRec, *TBPtr, **TBHandle;
TBHandle TBNew( WindowPtr wind, const Rect *r );
void TBDispose( TBHandle html );
void TBUpdate( TBHandle html );
void TBResize( TBHandle html, const Rect *r );
void TBSetScroll( TBHandle html, short scroll );
bool TBMouseDown( TBHandle html, Point where, WindowPtr whichWindow );
OSErr TBReadSimpleText( TBHandle tb, const FSSpec *docSpec);
|
||||
/************************************************************
|
||||
|
||||
Text Box.h
|
||||
|
||||
AUTHOR: Marcio Luis Teixeira
|
||||
CREATED: 3/16/95
|
||||
|
||||
LAST REVISION: 11/29/2021
|
||||
|
||||
(c) 1994-2021 by Marcio Luis Teixeira.
|
||||
All rights reserved.
|
||||
|
||||
*************************************************************/
|
||||
|
||||
#include "ctype.h"
|
||||
|
||||
typedef struct {
|
||||
TEHandle tbox;
|
||||
Rect frame;
|
||||
ControlHandle scroll;
|
||||
short lastV;
|
||||
short maxV;
|
||||
} TBRec, *TBPtr, **TBHandle;
|
||||
|
||||
TBHandle TBNew( WindowPtr wind, const Rect *r );
|
||||
void TBDispose( TBHandle html );
|
||||
void TBUpdate( TBHandle html );
|
||||
void TBResize( TBHandle html, const Rect *r );
|
||||
void TBSetScroll( TBHandle html, short scroll );
|
||||
bool TBMouseDown( TBHandle html, Point where, WindowPtr whichWindow );
|
||||
OSErr TBReadSimpleText( TBHandle tb, const FSSpec *docSpec);
|
||||
|
|
|
@ -24,12 +24,16 @@ Rect SE_Rect = SET_RECT(222, 154, 255, 221);
|
|||
*
|
||||
* Startup the Windows program.
|
||||
*******************************************************************************/
|
||||
void WinMain(int Device) {
|
||||
CurrentDevice = Device;
|
||||
void WinMain(uint8_t *DrivesSkipped) {
|
||||
CurrentDevice = 0;
|
||||
// test for an Iomega device
|
||||
EnumerateIomegaDevices(CurrentDevice);
|
||||
// Disable testing button when no drives present (added by mlt)
|
||||
if (!DriveCount) {
|
||||
EnumerateIomegaDevices(DrivesSkipped);
|
||||
if (DriveCount == 1) {
|
||||
// we have only one, so select it for the user
|
||||
CurrentDevice = DriveArray[0].scsi_id;
|
||||
}
|
||||
if (DriveCount == 0) {
|
||||
// disable testing button when no drives present (added by mlt)
|
||||
EnableWindow(hTestButton, false);
|
||||
SetRichEditText(szASPITrouble);
|
||||
}
|
||||
|
@ -90,7 +94,7 @@ void WndProc(long iMessage, uint16_t wParam) {
|
|||
case DISK_Z_TRACK_FAILURE:
|
||||
case DISK_TEST_FAILURE:
|
||||
case DISK_PROTECTED:
|
||||
EjectIomegaCartridge();
|
||||
EjectIomegaCartridge(CurrentDevice);
|
||||
break;
|
||||
case DISK_LOW_SPARES:
|
||||
SetRichEditText(szNotRunning);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
extern WindowPtr tipWindow;
|
||||
|
||||
void run_tip(int id);
|
||||
void run_tip();
|
||||
|
||||
#define MINIMUM_JAZ_SPARES 500
|
||||
#define MAXIMUM_JAZ_SPARES 2557
|
||||
|
@ -14,7 +14,7 @@ extern long DriveCount;
|
|||
extern long JazDrive; // true if the current drive
|
||||
extern long CartridgeStatus;
|
||||
extern long LastLBAOnCartridge;
|
||||
extern unsigned long StartingInstant;
|
||||
extern uint32_t StartingInstant;
|
||||
extern long NumberOfLBAs;
|
||||
extern long Side_0_SparesCount; // JAZ has only one count
|
||||
extern long Side_1_SparesCount; // ZIP has counts for both sides
|
||||
|
@ -34,22 +34,38 @@ extern bool UserInterrupt;
|
|||
extern long LastError;
|
||||
extern long SingleTransferLBA;
|
||||
|
||||
//-------------------------- Drive Array Status Flags ---------------------------
|
||||
|
||||
#define JAZ_DRIVE 0x01
|
||||
#define MEDIA_CHANGED 0x02
|
||||
#define DISK_EJECTING 0x04 // we've asked for eject and waiting ...
|
||||
#define ODD_BYTE_COMPENSATION 0x08 // special handling for ODD length PSWD
|
||||
#define MOUNTED_DRIVE 0x10 // drive was mounted at startup, ignore it
|
||||
#define MAX_DRIVE_COUNT 8 // we can handle up to 8 Zip/Jaz drives
|
||||
|
||||
struct DriveEntry {
|
||||
uint8_t flags;
|
||||
uint8_t scsi_id;
|
||||
};
|
||||
|
||||
extern DriveEntry DriveArray[MAX_DRIVE_COUNT];
|
||||
|
||||
// ----------------------- Macintosh Compatibility -----------------------
|
||||
|
||||
enum AlertTypes {
|
||||
ERR_DLG,
|
||||
YN_DLG
|
||||
ERR_DLG,
|
||||
YN_DLG
|
||||
};
|
||||
|
||||
enum {
|
||||
BACK_COLOR = -1,
|
||||
BLACK_COLOR = 0x000000,
|
||||
LTGRAY_COLOR = 0xc0c0c0,
|
||||
GRAY_COLOR = 0x808080,
|
||||
WHITE_COLOR = 0xffffff,
|
||||
BLUE_COLOR = 0x0000ff,
|
||||
RED_COLOR = 0xff0000,
|
||||
GREEN_COLOR = 0x00ff00,
|
||||
BACK_COLOR = -1,
|
||||
BLACK_COLOR = 0x000000,
|
||||
LTGRAY_COLOR = 0xc0c0c0,
|
||||
GRAY_COLOR = 0x808080,
|
||||
WHITE_COLOR = 0xffffff,
|
||||
BLUE_COLOR = 0x0000ff,
|
||||
RED_COLOR = 0xff0000,
|
||||
GREEN_COLOR = 0x00ff00,
|
||||
};
|
||||
|
||||
#define BDR_SUNKENOUTER 1
|
||||
|
@ -59,8 +75,10 @@ enum {
|
|||
#define SW_SHOW 1
|
||||
#define SW_HIDE 2
|
||||
|
||||
void SetRGBColor(long color, RGBColor *rgbColor);
|
||||
void SetColor(long color);
|
||||
void SetColor(long color, long monoColor);
|
||||
void SetBackColor(long color);
|
||||
void DrawLed(int x, int y, long color);
|
||||
void StrToPascal(Str255 pStr, const char *str);
|
||||
int ShowAlert(AlertTypes type, const char* format, ...);
|
||||
|
@ -71,6 +89,7 @@ void TextOut(int x, int y, const char *str);
|
|||
void TextOutCentered(int x, int y, int w, int h, const char *str);
|
||||
void SetWindowText(int id, const char *str);
|
||||
void EnableWindow(int id, bool enabled);
|
||||
void ShowWindow(ControlHandle hCntl, int state);
|
||||
void ShowWindow(int id, int state);
|
||||
void InvalidateRect(int id);
|
||||
void Rectangle(int left, int top, int right, int bottom);
|
||||
|
@ -81,42 +100,42 @@ void PostQuitMessage();
|
|||
unsigned long GetSystemTime();
|
||||
bool PrepareDC(int which);
|
||||
|
||||
#define GetDC(h) {GrafPtr oldPort; \
|
||||
GetPort(&oldPort); \
|
||||
if(PrepareDC(h)) {
|
||||
#define GetDC(h) {GrafPtr oldPort; \
|
||||
GetPort(&oldPort); \
|
||||
if(PrepareDC(h)) {
|
||||
|
||||
#define ReleaseDC(h) } SetOrigin(0,0); \
|
||||
SetPort(oldPort);}
|
||||
SetPort(oldPort);}
|
||||
|
||||
|
||||
// ------------------------------ Cartridge Status -------------------------------
|
||||
// ------------------------------ Cartridge Status -------------------------------
|
||||
|
||||
enum {
|
||||
DISK_STATUS_UNKNOWN = 1,
|
||||
DISK_AT_SPEED = 2,
|
||||
DISK_SPINNING_UP = 3,
|
||||
DISK_NOT_PRESENT = 4,
|
||||
DISK_SPUN_DOWN = 5,
|
||||
DISK_STALLED = 6,
|
||||
DISK_Z_TRACK_FAILURE = 7,
|
||||
DISK_PROTECTED = 8,
|
||||
DISK_LOW_SPARES = 9,
|
||||
DISK_TEST_UNDERWAY = 10,
|
||||
DISK_TEST_FAILURE = 11,
|
||||
DISK_STATUS_UNKNOWN = 1,
|
||||
DISK_AT_SPEED = 2,
|
||||
DISK_SPINNING_UP = 3,
|
||||
DISK_NOT_PRESENT = 4,
|
||||
DISK_SPUN_DOWN = 5,
|
||||
DISK_STALLED = 6,
|
||||
DISK_Z_TRACK_FAILURE = 7,
|
||||
DISK_PROTECTED = 8,
|
||||
DISK_LOW_SPARES = 9,
|
||||
DISK_TEST_UNDERWAY = 10,
|
||||
DISK_TEST_FAILURE = 11,
|
||||
|
||||
LAST_CART_STATUS = 11
|
||||
LAST_CART_STATUS = 11
|
||||
};
|
||||
|
||||
// ---------------------------- Testing Phase Status -----------------------------
|
||||
|
||||
enum {
|
||||
UNTESTED = 0,
|
||||
READY_TO_TEST = 1,
|
||||
TESTING_STARTUP = 2,
|
||||
READING_DATA = 3,
|
||||
WRITING_PATT = 4,
|
||||
READING_PATT = 5,
|
||||
WRITING_DATA = 6
|
||||
UNTESTED = 0,
|
||||
READY_TO_TEST = 1,
|
||||
TESTING_STARTUP = 2,
|
||||
READING_DATA = 3,
|
||||
WRITING_PATT = 4,
|
||||
READING_PATT = 5,
|
||||
WRITING_DATA = 6
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -195,15 +214,6 @@ extern const char *szBack;
|
|||
extern const char *szNext;
|
||||
extern const char *szQuit;
|
||||
|
||||
enum {
|
||||
hMainWnd,
|
||||
hTestMonitor,
|
||||
hTestButton,
|
||||
hExitButton,
|
||||
// Extras added by MLT
|
||||
hExplainWnd
|
||||
};
|
||||
|
||||
#define IDB_BACK 0xFF00
|
||||
#define IDB_NEXT 0xFF01
|
||||
#define IDB_QUIT 0xFF02
|
||||
|
@ -212,14 +222,24 @@ enum {
|
|||
#define IDB_OKAY 0xFF05
|
||||
#define IDB_READ 0xFF06
|
||||
|
||||
enum {
|
||||
hDefault,
|
||||
hMainWnd,
|
||||
hTestMonitor,
|
||||
hTestButton = IDB_TEST,
|
||||
hExitButton = IDB_QUIT,
|
||||
// Extras added by MLT
|
||||
hExplainWnd = IDB_EXPL
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
const char *name;
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
ControlHandle hndl;
|
||||
int id;
|
||||
const char *name;
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
ControlHandle hndl;
|
||||
} BtnList;
|
||||
extern BtnList tipBtns[];
|
||||
|
||||
|
@ -246,15 +266,16 @@ void PreventProgramExit();
|
|||
void AllowProgramExit();
|
||||
void ErrorSound();
|
||||
void ProcessPendingMessages();
|
||||
void WinMain(int Device);
|
||||
void WinMain(uint8_t *DrivesSkipped);
|
||||
void WndProc(long iMessage, uint16_t wParam);
|
||||
void TestMonitorWndProc();
|
||||
void ApplicationTimerProc();
|
||||
void TestButtonClicked();
|
||||
|
||||
int GetDriveEntryOffset(short Device);
|
||||
void GetCommandDetails(char command, char &cmd_flags, char &cmd_length);
|
||||
long SCSICommand(short Device, char *lpCmdBlk, void *lpIoBuf, short IoBufLen);
|
||||
void EnumerateIomegaDevices(long Device);
|
||||
long EnumerateIomegaDevices(uint8_t *DrivesSkipped);
|
||||
long GetModePage(short Device, short PageToGet, void *pBuffer, short BufLen);
|
||||
long SetModePage(short Device, void *pBuffer);
|
||||
void ModifyModePage(char *PageBuff, char eec, char retries);
|
||||
|
@ -262,10 +283,14 @@ void SetErrorRecovery(bool Retries, bool ECC, bool Testing);
|
|||
long GetNonSenseData(short Device, short DataPage, void *Buffer, short BufLen);
|
||||
long LockCurrentDrive();
|
||||
long UnlockCurrentDrive();
|
||||
void UnlockAllMedia();
|
||||
long SpinUpIomegaCartridge(short Device);
|
||||
void EjectAllMedia();
|
||||
long GetSpareSectorCounts(char);
|
||||
uint8_t GetCartridgeStatus(long Device);
|
||||
void HandleDriveChanging();
|
||||
void SetCartridgeStatusToEAX(long eax);
|
||||
void EjectIomegaCartridge(int Device);
|
||||
long PerformRegionTransfer(short XferCmd, void *pBuffer);
|
||||
void TestTheDisk();
|
||||
long GetElapsedTimeInSeconds();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "mac_scsi.h"
|
||||
#include "tip.h"
|
||||
|
||||
|
@ -49,14 +50,6 @@ struct DEFECT_LIST_HEADER {
|
|||
short DLH_DefectListLength;
|
||||
};
|
||||
|
||||
//-------------------------- Drive Array Status Flags ---------------------------
|
||||
|
||||
#define JAZ_DRIVE 0x00010000
|
||||
#define MEDIA_CHANGED 0x00020000
|
||||
#define DISK_EJECTING 0x00040000 // we've asked for eject and waiting ...
|
||||
#define ODD_BYTE_COMPENSATION 0x00080000 // special handling for ODD length PSWD
|
||||
#define MAX_DRIVE_COUNT 16 // we can handle up to 16 Zip/Jaz drives
|
||||
|
||||
#define ERROR_RECOVERY_PAGE 1 // From disassembly
|
||||
#define FORMAT_STATUS_PAGE 1
|
||||
#define DISK_STATUS_PAGE 2
|
||||
|
@ -83,16 +76,20 @@ struct DEFECT_LIST_HEADER {
|
|||
|
||||
#define BADNESS_THRESHOLD 10
|
||||
|
||||
#define SS_ERR 0x00000004 // From disassembly
|
||||
#define BUFFER_TOO_BIG 0x00FFFFE6 // From disassembly
|
||||
#define LBA_TOO_LARGE 0x00210005 // From disassembly
|
||||
#define INCOMPATIBLE_MEDIA 0x00300002 // From disassembly
|
||||
#define MEDIA_NOT_PRESENT 0x003a0002 // From disassembly
|
||||
#define DEFECT_LIST_READ_ERROR 0x001c0003 // From disassembly
|
||||
#define SS_ERR 0x00000004
|
||||
#define DEFECT_LIST_READ_ERROR 0x001c0003
|
||||
#define LBA_TOO_LARGE 0x00210005 // accessed a non-exist LBA
|
||||
#define MEDIA_CHANGE_CODE 0x00280006 // media was changed
|
||||
#define INCOMPATIBLE_MEDIA 0x00300002 // 2Gb / 1Gb combo on "Read Defects"
|
||||
#define MEDIA_NOT_PRESENT 0x003a0002
|
||||
#define DRIVE_COMING_READY 0x00040102
|
||||
#define SCSI_CMD_TIMED_OUT 0x00FFFF00
|
||||
#define BUFFER_TOO_BIG 0x00FFFFE6
|
||||
#define MANUAL_INTERRUPTION 0xFFFFFFFF
|
||||
|
||||
#define CHECK_CONDITION 0x02
|
||||
|
||||
long CurrentDevice = 0;
|
||||
long CurrentDevice = -1; // the device that's been recognized
|
||||
long DriveCount = 0;
|
||||
|
||||
long JazDrive = 0; // true if the current drive
|
||||
|
@ -122,6 +119,20 @@ bool UserInterrupt;
|
|||
long LastError;
|
||||
long SingleTransferLBA;
|
||||
|
||||
DriveEntry DriveArray[MAX_DRIVE_COUNT];
|
||||
|
||||
/*******************************************************************************
|
||||
* GET DRIVE ENTRY OFFSET
|
||||
*
|
||||
* Returns the offset of the chosen drive's status word
|
||||
*******************************************************************************/
|
||||
int GetDriveEntryOffset(short Device) {
|
||||
for(int i = 0; i < MAX_DRIVE_COUNT; i++)
|
||||
if(DriveArray[i].scsi_id == Device) // did we find the right table slot?
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* GET COMMAND DETAILS
|
||||
*
|
||||
|
@ -196,9 +207,15 @@ long SCSICommand(short Device, char *lpCmdBlk, void *lpIoBuf, short IoBufLen) {
|
|||
printf("SCSI CHECK CONDITION (KEY %x, ASC %x, ASCQ %x)\n", sense_data.key, sense_data.asc, sense_data.ascq);
|
||||
// okay, we have an SS_ERR condition, let's check the SENSE DATA
|
||||
// assemble [00 ASC ASCQ SenseKey]
|
||||
return (long(sense_data.asc) << 16) |
|
||||
(long(sense_data.ascq) << 8) |
|
||||
(long(sense_data.key) );
|
||||
long res = (long(sense_data.asc) << 16) |
|
||||
(long(sense_data.ascq) << 8) |
|
||||
(long(sense_data.key) );
|
||||
if(res == MEDIA_CHANGE_CODE) {
|
||||
int index = GetDriveEntryOffset(Device);
|
||||
DriveArray[index].flags |= MEDIA_CHANGED;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
// else, if it's *NOT* a "Sense Data" error (SS_ERR)
|
||||
|
@ -209,33 +226,72 @@ long SCSICommand(short Device, char *lpCmdBlk, void *lpIoBuf, short IoBufLen) {
|
|||
/*******************************************************************************
|
||||
* ENUMERATE IOMEGA DEVICES
|
||||
*******************************************************************************/
|
||||
void EnumerateIomegaDevices(long Device) {
|
||||
short stricmp( const char *str1, const char *str2 );
|
||||
short stricmp( const char *str1, const char *str2 ) {
|
||||
while (*str1 && *str2) {
|
||||
short cmp = tolower( *str1++ ) - tolower( *str2++ );
|
||||
if(cmp != 0) return cmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
long EnumerateIomegaDevices(uint8_t *DrivesSkipped) {
|
||||
DriveCount = 0;
|
||||
JazDrive = 0;
|
||||
//-----------------------------------------------------------
|
||||
char InqData[96];
|
||||
char Scsi[6] = {0};
|
||||
Scsi[0] = SCSI_Cmd_Inquiry;
|
||||
Scsi[4] = sizeof(InqData);
|
||||
long eax = SCSICommand(Device, Scsi, InqData, sizeof(InqData));
|
||||
if(eax) goto TryNextDrive;
|
||||
//-----------------------------------------------------------
|
||||
InqData[14] = '\0';
|
||||
if (strcmp(szIomega, InqData + 8)) goto TryNextDrive;
|
||||
//-----------------------------------------------------------
|
||||
InqData[19] = '\0';
|
||||
if (!strcmp(szZip, InqData + 16)) goto FoundZipOrJaz;
|
||||
//-----------------------------------------------------------
|
||||
if (strcmp(szJaz, InqData + 16)) goto TryNextDrive;
|
||||
JazDrive = 1;
|
||||
FoundZipOrJaz:
|
||||
DriveCount = 1;
|
||||
if(JazDrive)
|
||||
printf("Found Jaz drive\n");
|
||||
else
|
||||
printf("Found Zip drive\n");
|
||||
TryNextDrive:
|
||||
return;
|
||||
if(DrivesSkipped) *DrivesSkipped = 0;
|
||||
|
||||
printf("\nEnumerating Iomega Devices:\n");
|
||||
// now scan the devices on the SCSI host adapter
|
||||
for(int Device = 0; Device < 8; Device++) {
|
||||
char flags = 0;
|
||||
//-----------------------------------------------------------
|
||||
#ifdef NO_EXCESS_READS
|
||||
scsi_inq_reply reply;
|
||||
if(scsi_inquiry(Device, 0, &reply) != noErr) continue;
|
||||
char *InqData = (char*) &reply;
|
||||
#else
|
||||
char InqData[96];
|
||||
char Scsi[6] = {0};
|
||||
Scsi[0] = SCSI_Cmd_Inquiry;
|
||||
Scsi[4] = sizeof(InqData);
|
||||
if(SCSICommand(Device, Scsi, InqData, sizeof(InqData))) continue;
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------
|
||||
InqData[14] = '\0';
|
||||
InqData[19] = '\0';
|
||||
const bool isIomega = !stricmp(szIomega, InqData + 8);
|
||||
const bool isZip = !stricmp(szZip, InqData + 16);
|
||||
const bool isJaz = !stricmp(szJaz, InqData + 16);
|
||||
//-----------------------------------------------------------
|
||||
|
||||
if (isIomega && (isZip || isJaz)) {
|
||||
char flags = isJaz ? JAZ_DRIVE : 0;
|
||||
// check for ANSI SCSI to see whether we need to play
|
||||
// the Odd/Even password length game ...
|
||||
if(InqData[2] & 0x07 == 0) {
|
||||
flags |= ODD_BYTE_COMPENSATION; // turn on compensation
|
||||
}
|
||||
|
||||
// On the Mac, we want to ignore drives that have media in them at
|
||||
// program entry, as this means the volume is mounted in Mac OS
|
||||
const bool driveEmpty = GetCartridgeStatus(Device) == DISK_NOT_PRESENT;
|
||||
if(driveEmpty) {
|
||||
DriveArray[DriveCount].flags = flags;
|
||||
DriveArray[DriveCount].scsi_id = Device;
|
||||
DriveCount++;
|
||||
} else {
|
||||
if(DrivesSkipped) (*DrivesSkipped)++;
|
||||
}
|
||||
|
||||
printf(" %d: %s %s %s\n", Device,
|
||||
(flags & JAZ_DRIVE) ? "JAZ" : "ZIP",
|
||||
(flags & ODD_BYTE_COMPENSATION) ? "OBC" : " ",
|
||||
(driveEmpty) ? "EMPTY" : "MEDIA");
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
return DriveCount;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -358,6 +414,18 @@ long UnlockCurrentDrive() {
|
|||
return SCSICommand(CurrentDevice, Scsi, NULL, 0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* UNLOCK ALL MEDIA
|
||||
*******************************************************************************/
|
||||
void UnlockAllMedia() {
|
||||
// make sure the media is not locked as we exit...
|
||||
char Scsi[6] = {0};
|
||||
Scsi[0] = SCSI_Cmd_PreventAllow;
|
||||
for(int i = 0; i < MAX_DRIVE_COUNT; i++) {
|
||||
SCSICommand(DriveArray[i].scsi_id, Scsi, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* SPIN UP IOMEGA CARTRIDGE
|
||||
*******************************************************************************/
|
||||
|
@ -369,6 +437,16 @@ long SpinUpIomegaCartridge(short Device) {
|
|||
return SCSICommand(Device, Scsi, NULL, 0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* EJECT ALL MEDIA
|
||||
*******************************************************************************/
|
||||
void EjectAllMedia() {
|
||||
// setup the SCSI command block for the operation
|
||||
for(int i = 0; i < MAX_DRIVE_COUNT; i++) {
|
||||
EjectIomegaCartridge(DriveArray[i].scsi_id);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* GET SPARE SECTOR COUNTS
|
||||
*
|
||||
|
@ -475,34 +553,92 @@ long GetSpareSectorCounts(char checkPassword) {
|
|||
|
||||
/*******************************************************************************
|
||||
* HANDLE DRIVE CHANGING
|
||||
*
|
||||
* If we're NOT in the middle of drive testing, check for any new drives
|
||||
* going ready, eject all others, and Select the newer drive.
|
||||
* If we *ARE* in the middle of drive testing, EJECT any new drive that's
|
||||
* attempting to go ready.
|
||||
*******************************************************************************/
|
||||
void HandleDriveChanging() {
|
||||
// MLT: At the moment, we only handle one drive.
|
||||
bool Selecting = false; // true while we're changing selections
|
||||
uint8_t status;
|
||||
Rescan:
|
||||
for(int i = 0; i < DriveCount; i++) {
|
||||
const int scsi_id = DriveArray[i].scsi_id;
|
||||
|
||||
// query the current state of the drive
|
||||
do {
|
||||
// clear media changed status
|
||||
DriveArray[i].flags &= ~MEDIA_CHANGED;
|
||||
GetCartridgeStatus(scsi_id);
|
||||
} while(DriveArray[i].flags & MEDIA_CHANGED); // do it until NO media change!
|
||||
//--------------------------------------------------------------------------
|
||||
status = GetCartridgeStatus(scsi_id);
|
||||
// if the device we have is NOT the currently selected one
|
||||
if(scsi_id != CurrentDevice) {
|
||||
// if the disk is ANYTHING other than not present ...
|
||||
if(status != DISK_NOT_PRESENT) {
|
||||
// we have a PRESENT DISK in a non-current drive
|
||||
// if we're testing, reject it
|
||||
if (Selecting || TestingPhase >= TESTING_STARTUP) {
|
||||
EjectIomegaCartridge(scsi_id);
|
||||
// flag that we're waiting for spindown
|
||||
DriveArray[i].flags |= DISK_EJECTING;
|
||||
}
|
||||
// if we're not testing, and not awaiting eject
|
||||
// then set the current drive ...
|
||||
else if ((DriveArray[i].flags & DISK_EJECTING) == 0) {
|
||||
CurrentDevice = scsi_id;
|
||||
TestingPhase = 0;
|
||||
Selecting = true;
|
||||
//goto Rescan;
|
||||
break;
|
||||
// the PREVIOUS drive (if any) will be ejected on the next pass
|
||||
}
|
||||
} else {
|
||||
// the drive HAS spun down, so clear "waiting"
|
||||
DriveArray[i].flags &= ~DISK_EJECTING;
|
||||
}
|
||||
} else {
|
||||
// we're checking the current drive ... make SURE that
|
||||
// it is *NOT* empty! If it *IS* empty, kill current
|
||||
if(status == DISK_NOT_PRESENT) {
|
||||
CurrentDevice = -1;
|
||||
SetCartridgeStatusToEAX(status);
|
||||
}
|
||||
// if it's not already set correctly *and* either
|
||||
// the cart status is one of the pre-test ones, or
|
||||
// the NEW status from the cart is NOT "at speed" ...
|
||||
if((status != CartridgeStatus) && ((CartridgeStatus <= DISK_STALLED) || (status != DISK_AT_SPEED))) {
|
||||
SetCartridgeStatusToEAX(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if nothing was chosen ... set us to the "Awaiting Cartridge" status
|
||||
if ((CurrentDevice == -1) &&
|
||||
(status == DISK_NOT_PRESENT) &&
|
||||
(CartridgeStatus != DISK_NOT_PRESENT)) {
|
||||
SetCartridgeStatusToEAX(status);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GET CARTRIDGE STATUS
|
||||
//-----------------------------------------------------------------------------
|
||||
uint8_t GetCartridgeStatus(long Device) {
|
||||
long eax;
|
||||
char DiskStat[72];
|
||||
#ifdef NO_EXCESS_READS
|
||||
eax = GetNonSenseData(CurrentDevice, DISK_STATUS_PAGE, DiskStat, JazDrive ? sizeof(DiskStat) : 63);
|
||||
if (eax) return;
|
||||
eax = GetNonSenseData(Device, DISK_STATUS_PAGE, DiskStat, JazDrive ? sizeof(DiskStat) : 63);
|
||||
if (eax) return DISK_STATUS_UNKNOWN;
|
||||
#else
|
||||
eax = GetNonSenseData(CurrentDevice, DISK_STATUS_PAGE, DiskStat, sizeof(DiskStat));
|
||||
if (!eax) return;
|
||||
eax = GetNonSenseData(Device, DISK_STATUS_PAGE, DiskStat, sizeof(DiskStat));
|
||||
if (!eax) return DISK_STATUS_UNKNOWN;
|
||||
#endif
|
||||
char status;
|
||||
if (DiskStat[0] == DISK_STATUS_PAGE) {
|
||||
status = DiskStat[NEW_DISK_STATUS_OFFSET];
|
||||
return DiskStat[NEW_DISK_STATUS_OFFSET];
|
||||
} else {
|
||||
status = DiskStat[OLD_DISK_STATUS_OFFSET];
|
||||
}
|
||||
// we're checking the current drive ... make SURE that
|
||||
// it is *NOT* empty! If it *IS* empty, kill current
|
||||
if(status == DISK_NOT_PRESENT) {
|
||||
SetCartridgeStatusToEAX(status);
|
||||
}
|
||||
// if it's not already set correctly *and* either
|
||||
// the cart status is one of the pre-test ones, or
|
||||
// the NEW status from the cart is NOT "at speed" ...
|
||||
if((status != CartridgeStatus) && ((CartridgeStatus <= DISK_STALLED) || (status != DISK_AT_SPEED))) {
|
||||
SetCartridgeStatusToEAX(status);
|
||||
return DiskStat[OLD_DISK_STATUS_OFFSET];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -514,17 +650,6 @@ void SetCartridgeStatusToEAX(long eax) {
|
|||
long PriorStatus = CartridgeStatus;
|
||||
CartridgeStatus = eax;
|
||||
|
||||
/**************************************************************************
|
||||
* Added by MLT
|
||||
*/
|
||||
// Avoid flickering
|
||||
static long LastCartridgeStatus = -1;
|
||||
if (LastCartridgeStatus == CartridgeStatus) {
|
||||
return;
|
||||
}
|
||||
LastCartridgeStatus = CartridgeStatus;
|
||||
/**************************************************************************/
|
||||
|
||||
// Set the text of the "action initiate button"
|
||||
const char *esi = 0;
|
||||
switch (CartridgeStatus) {
|
||||
|
@ -666,18 +791,18 @@ void BumpErrorCounts(long ErrorCode) {
|
|||
/*******************************************************************************
|
||||
* EJECT IOMEGA CARTRIDGE
|
||||
*******************************************************************************/
|
||||
void EjectIomegaCartridge() {
|
||||
void EjectIomegaCartridge(int Device) {
|
||||
// Could NOT do it through the IOCTL layer ... so eject with SCSI
|
||||
// make sure the media is not locked...
|
||||
char Scsi[6] = {0};
|
||||
Scsi[0] = SCSI_Cmd_PreventAllow;
|
||||
SCSICommand(CurrentDevice, Scsi, 0, 0);
|
||||
SCSICommand(Device, Scsi, 0, 0);
|
||||
// issue an Asynchronous STOP command to induce spindown and ejection
|
||||
memset(Scsi, 0, sizeof(Scsi));
|
||||
Scsi[0] = SCSI_Cmd_StartStopUnit;
|
||||
Scsi[1] = 1; // Set the IMMED bit for offline
|
||||
Scsi[4] = 2; // eject a Jaz disk after stopping
|
||||
SCSICommand(CurrentDevice, Scsi, 0, 0);
|
||||
SCSICommand(Device, Scsi, 0, 0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -883,7 +1008,7 @@ GetOut:
|
|||
free(pUserDataBuffer);
|
||||
|
||||
TestingPhase = UNTESTED;
|
||||
UnlockCurrentDrive();
|
||||
UnlockAllMedia();
|
||||
SetErrorRecovery(true, true, false); // reenable Retries & ECC
|
||||
SetWindowText(hTestButton, szPressToStart);
|
||||
CartridgeStatus = DISK_AT_SPEED;
|
||||
|
|
|
@ -43,7 +43,7 @@ void OpenExplanationInSimpleText();
|
|||
|
||||
const Point mainWndOrigin = SET_POINT(0, 40);
|
||||
|
||||
void run_tip(int id) {
|
||||
void run_tip() {
|
||||
RgnHandle cursorRgn = NewRgn();
|
||||
|
||||
NewTipWindow();
|
||||
|
@ -59,7 +59,19 @@ void run_tip(int id) {
|
|||
printf("Starting tip\n");
|
||||
// Start TIP as soon as the user dismisses the intro screen
|
||||
inited = true;
|
||||
WinMain(id);
|
||||
uint8_t drivesSkipped;
|
||||
WinMain(&drivesSkipped);
|
||||
if(drivesSkipped) {
|
||||
const char *s = drivesSkipped > 1 ? "s" : "";
|
||||
if(ShowAlert(YN_DLG,
|
||||
"Found media in %d drive%s. If you wish to test that "
|
||||
"media, you must quit to the Finder and eject it "
|
||||
"prior to running TIP. Would you like to do so?",
|
||||
drivesSkipped, s
|
||||
) == 1) {
|
||||
gDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(timerEnabled) {
|
||||
|
@ -93,7 +105,9 @@ void NewTipWindow() {
|
|||
NewCWindow(NULL,&rect, title, true, 0, (WindowPtr)-1, true, 0) :
|
||||
NewWindow(NULL,&rect, title, true, 0, (WindowPtr)-1, true, 0);
|
||||
|
||||
GetDC(hMainWnd);
|
||||
SetPort(tipWindow);
|
||||
SetBackColor(BACK_COLOR);
|
||||
EraseRect(&tipWindow->portRect);
|
||||
|
||||
TextSize(10);
|
||||
|
||||
|
@ -107,9 +121,8 @@ void NewTipWindow() {
|
|||
tipBtns[i].y + tipBtns[i].h - mainWndOrigin.v
|
||||
);
|
||||
StrToPascal(title, tipBtns[i].name);
|
||||
tipBtns[i].hndl = NewControl(tipWindow, &rect, title, true, 0, 0, 0, 0, tipBtns[i].id);
|
||||
tipBtns[i].hndl = NewControl(tipWindow, &rect, title, false, 0, 0, 0, 0, tipBtns[i].id);
|
||||
}
|
||||
ReleaseDC(hMainWnd);
|
||||
|
||||
page = kExplainPage;
|
||||
GetDC(hExplainWnd);
|
||||
|
@ -149,6 +162,9 @@ bool PrepareDC(int which) {
|
|||
case hMainWnd:
|
||||
SetOrigin(mainWndOrigin.h, mainWndOrigin.v);
|
||||
break;
|
||||
case hDefault:
|
||||
SetOrigin(0, 0);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -291,28 +307,28 @@ void SetPage(TipPage newPage) {
|
|||
page = newPage;
|
||||
switch(page) {
|
||||
case kTestingPage:
|
||||
ShowWindow(IDB_TEST, SW_SHOW);
|
||||
ShowWindow((*richText)->scroll, SW_HIDE);
|
||||
ShowWindow(IDB_BACK, SW_HIDE);
|
||||
ShowWindow(IDB_NEXT, SW_HIDE);
|
||||
ShowWindow(IDB_EXPL, SW_SHOW);
|
||||
ShowWindow(IDB_OKAY, SW_HIDE);
|
||||
ShowWindow(IDB_QUIT, SW_SHOW);
|
||||
ShowWindow(IDB_READ, SW_HIDE);
|
||||
HideControl((*richText)->scroll);
|
||||
ShowWindow(IDB_TEST, SW_SHOW);
|
||||
ShowWindow(IDB_EXPL, SW_SHOW);
|
||||
ShowWindow(IDB_QUIT, SW_SHOW);
|
||||
break;
|
||||
case kExplainPage:
|
||||
ShowWindow(IDB_TEST, SW_HIDE);
|
||||
ShowWindow(IDB_BACK, SW_HIDE);
|
||||
ShowWindow(IDB_NEXT, SW_HIDE);
|
||||
ShowWindow(IDB_EXPL, SW_HIDE);
|
||||
ShowWindow(IDB_OKAY, SW_SHOW);
|
||||
ShowWindow(IDB_QUIT, SW_HIDE);
|
||||
ShowWindow(IDB_OKAY, SW_SHOW);
|
||||
ShowWindow(IDB_READ, SW_SHOW);
|
||||
ShowControl((*richText)->scroll);
|
||||
ShowWindow((*richText)->scroll, SW_SHOW);
|
||||
TBSetScroll(richText, 0);
|
||||
break;
|
||||
}
|
||||
InvalidateRect(hMainWnd);
|
||||
InvalidateRect(hDefault);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -394,42 +410,44 @@ void OpenExplanationInSimpleText() {
|
|||
*******************************************************************************/
|
||||
|
||||
void SetRichEditText(const char *name) {
|
||||
short fRefNum = 0;
|
||||
|
||||
// Don't reload a file that is already loaded
|
||||
|
||||
if(textFileName == name) return;
|
||||
textFileName = name;
|
||||
|
||||
printf("Loading explanation file \"%s\"\n", name);
|
||||
|
||||
// Get the specification for the explanation file
|
||||
|
||||
FSSpec docSpec;
|
||||
OSErr err = GetExplanationFSSpec(textFileName, &docSpec);
|
||||
if(err != noErr) return;
|
||||
|
||||
// Load the text from the data fork
|
||||
// Load the text from the file
|
||||
|
||||
TBReadSimpleText(richText, &docSpec);
|
||||
|
||||
if (name != szRunning && name != szNotRunning) {
|
||||
SetPage(kExplainPage);
|
||||
} else {
|
||||
InvalidateRect(hDefault);
|
||||
}
|
||||
|
||||
TBReadSimpleText(richText, &docSpec);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* SET COLOR
|
||||
*******************************************************************************/
|
||||
|
||||
void SetRGBColor(long color, RGBColor *rgbColor) {
|
||||
if(color == BACK_COLOR) color = LTGRAY_COLOR;
|
||||
// Use colors when available
|
||||
rgbColor->red = (color & 0xFF0000) >> 8;
|
||||
rgbColor->green = (color & 0x00FF00) >> 0;
|
||||
rgbColor->blue = (color & 0x0000FF) << 8;
|
||||
}
|
||||
|
||||
void SetColor(long color) {
|
||||
if (allowColor) {
|
||||
if(color == BACK_COLOR) color = LTGRAY_COLOR;
|
||||
// Use colors when available
|
||||
RGBColor rgbColor;
|
||||
rgbColor.red = (color & 0xFF0000) >> 8;
|
||||
rgbColor.green = (color & 0x00FF00) >> 0;
|
||||
rgbColor.blue = (color & 0x0000FF) << 8;
|
||||
SetRGBColor(color, &rgbColor);
|
||||
RGBForeColor(&rgbColor);
|
||||
} else {
|
||||
// Use patterns for B&W Macs
|
||||
|
@ -464,6 +482,14 @@ void SetColor(long color, long monoColor) {
|
|||
}
|
||||
}
|
||||
|
||||
void SetBackColor(long color) {
|
||||
if (allowColor) {
|
||||
RGBColor rgbColor;
|
||||
SetRGBColor(color, &rgbColor);
|
||||
RGBBackColor(&rgbColor);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* DRAW LED
|
||||
*******************************************************************************/
|
||||
|
@ -587,9 +613,9 @@ void SetWindowText(int id, const char *str) {
|
|||
StrToPascal(pStr, str);
|
||||
ControlHandle hCntl = FindControl(id);
|
||||
if(hCntl) {
|
||||
GetDC(hMainWnd);
|
||||
GetDC(hDefault);
|
||||
SetCTitle(hCntl, pStr);
|
||||
ReleaseDC(hMainWnd);
|
||||
ReleaseDC(hDefault);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -599,24 +625,27 @@ void SetWindowText(int id, const char *str) {
|
|||
void EnableWindow(int id, bool enabled) {
|
||||
ControlHandle hCntl = FindControl(id);
|
||||
if(hCntl) {
|
||||
GetDC(hMainWnd);
|
||||
GetDC(hDefault);
|
||||
HiliteControl(hCntl, enabled ? 0 : 255);
|
||||
ReleaseDC(hMainWnd);
|
||||
ReleaseDC(hDefault);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* SHOW WINDOW
|
||||
*******************************************************************************/
|
||||
void ShowWindow(ControlHandle hCntl, int state) {
|
||||
// Show/hide a control by invalidating, rather than drawing it
|
||||
(*hCntl)->contrlVis = (state == SW_SHOW) ? 255 : 0;
|
||||
InvalRect(&(*hCntl)->contrlRect);
|
||||
}
|
||||
|
||||
void ShowWindow(int id, int state) {
|
||||
ControlHandle hCntl = FindControl(id);
|
||||
if(hCntl) {
|
||||
GetDC(hMainWnd);
|
||||
if(state == SW_SHOW)
|
||||
ShowControl(hCntl);
|
||||
else
|
||||
HideControl(hCntl);
|
||||
ReleaseDC(hMainWnd);
|
||||
GetDC(hDefault);
|
||||
ShowWindow(hCntl, state);
|
||||
ReleaseDC(hDefault);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1,4 @@
|
|||
typedef Boolean bool;
typedef unsigned short uint16_t;
|
||||
typedef Boolean bool;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned long uint32_t;
|
Loading…
Reference in New Issue