Compare commits
8 Commits
v0.3-beta-
...
main
Author | SHA1 | Date |
---|---|---|
Marcio T | 4793ffc0d8 | |
Marcio T | b6fa1cad7a | |
Marcio T | 7d96b63ef0 | |
Marcio T | c719c8d7dd | |
Marcio T | dcfa0958a6 | |
Marcio T | bfa9014432 | |
Marcio T | 6b36dfdc0e | |
Marcio T | 49ce1bc093 |
51
README.md
51
README.md
|
@ -8,6 +8,15 @@ This is the repository for a Macintosh port of [Gibson Research Corp]'s
|
|||
Jaz Drives. A big thanks goes to Steve Gibson for the x86 source that
|
||||
made this project possible!
|
||||
|
||||
[![Trouble in Paradise Demonstration](https://github.com/marciot/mac-tip/raw/main/images/youtube.png)](https://youtu.be/vtBlOaG2pNw)
|
||||
|
||||
:tv: See a demo on [YouTube]!
|
||||
|
||||
[![Mention in Steve Gibson's Security Now Podcast](https://github.com/marciot/mac-tip/raw/main/images/security-now.png)](https://twit.tv/shows/security-now/episodes/845)
|
||||
|
||||
:tv: Watch Steve Gibson react to my unusual request in the November 16th
|
||||
episode of the "Security Now" podcast at the 1:05:10 mark.
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
|
||||
|
@ -20,17 +29,19 @@ Power Macintosh G3, released in 1997.
|
|||
|
||||
It has been tested in on the following environments:
|
||||
|
||||
| Computer | Memory | System | Drive | Firmware |
|
||||
|------------------- |--------|--------|-------------------------|----------|
|
||||
| Macintosh Plus | 4MB | 7.0.1 | Zip Plus 100 Ext. SCSI | J.66 |
|
||||
| PowerBook 3400c | 144MB | 8.6 | Zip 100 Ext. SCSI | E.08 |
|
||||
| Power Macintosh G3 | 256MB | 9.2.1 | Zip 100 Ext. SCSI | C.22 |
|
||||
| Power Macintosh G3 | 256MB | 9.2.1 | Zip 100 Int. SCSI | J.03 |
|
||||
| Computer | Memory | System | Drive | Firmware |
|
||||
|------------------- |--------|--------|-------------------------------------|----------|
|
||||
| Macintosh Plus | 4MB | 7.0.1 | Zip Plus 100 Ext. SCSI | J.66 |
|
||||
| PowerBook 3400c | 144MB | 8.6 | Zip 100 Ext. SCSI | E.08 |
|
||||
| PowerBook 3400c | 144MB | 8.6 | Jaz 2GB Ext. SCSI w/ 1GB media | E.17 |
|
||||
| PowerBook 3400c | 144MB | 8.6 | Jaz 2GB Ext. SCSI w/ 2GB media | E.17 |
|
||||
| Power Macintosh G3 | 256MB | 9.2.1 | Zip 100 Ext. SCSI | C.22 |
|
||||
| Power Macintosh G3 | 256MB | 9.2.1 | Zip 100 Int. SCSI | J.03 |
|
||||
|
||||
What will not work or is missing:
|
||||
|
||||
* USB connected Zip drives have been reported to not work.
|
||||
* The functionality for operating with password or write protected disks is missing.
|
||||
* The functionality for operating with password or write protected disks has not been ported.
|
||||
* The partition recovery feature has been removed, since it is meant for PC disks.
|
||||
|
||||
</details>
|
||||
|
@ -47,13 +58,9 @@ port.**
|
|||
Where are the binaries?
|
||||
-----------------------
|
||||
|
||||
Once they are ready, compiled binaries will be made available on the
|
||||
releases page for people who have signed up for
|
||||
Compiled binaries are available on the releases page for people who have signed up for
|
||||
[beta testing in the discussion forum]
|
||||
|
||||
There is always a risk of data loss with a tool like this, so please
|
||||
use it only on non-critical data if you decide to beta test.
|
||||
|
||||
How can you help?
|
||||
-----------------
|
||||
|
||||
|
@ -61,8 +68,14 @@ You can help this project in one of the following ways:
|
|||
|
||||
* Star this project on GitHub to show your support!
|
||||
* Sign up to [beta testing in the discussion forum]!
|
||||
* Donate a 1 or 2GB Jaz cartridge for testing (I have a 2GB SCSI Jaz drive, but no cartridges!).
|
||||
* Become a GitHub sponsor to help fund my work with this and other open-source projects!
|
||||
* Become a GitHub sponsor to help fund my various open-source projects!
|
||||
|
||||
Other Vintage Macintosh Stuff
|
||||
-----------------------------
|
||||
|
||||
* [MiniVNC]: A remote desktop server for vintage Macintoshes!
|
||||
* [ScreenChooser]: A dynamic background changer for vintage Macintoshes!
|
||||
* [Retroweb Vintage Computer Museum]: A web-based museum of vintage computers, including the Macintosh!
|
||||
|
||||
Got work?
|
||||
---------
|
||||
|
@ -82,7 +95,8 @@ Then, insert the cartridge at the testing screen which indicates "Awaiting media
|
|||
will recognize it if Mac OS mounts newly inserted cartridge and will give you the choice to
|
||||
unmount it.
|
||||
|
||||
Alternatively, you can use the command line to unmount a disk **prior to** starting TIP.
|
||||
Alternatively, you can use the command line from the "Advanced" menu to unmount a disk
|
||||
**prior to** starting a test.
|
||||
|
||||
<details>
|
||||
<summary>Click here to learn how to use the command line</summary></br>
|
||||
|
@ -141,6 +155,7 @@ Credits
|
|||
* Thank you to [Stone Table Software] for providing the tool I used to convert the Windows RTF docs into SimpleText...
|
||||
* ...and to the Internet Archive's Wayback Machine for allowing me to access it long after the website was shut down!
|
||||
* Thank you to Thomas Tempelmann sharing his [LaunchLib code] which I used to open the documents
|
||||
* Thank you to Grant Hutchinson and Nikola Biscan for sending me 1GB and 2GB Jaz cartridges for testing.
|
||||
|
||||
The Original TIP For Windows
|
||||
----------------------------
|
||||
|
@ -174,3 +189,9 @@ his code in this repository with his permission.
|
|||
[beta testing in the discussion forum]: https://github.com/marciot/mac-tip/discussions/1
|
||||
[LaunchLib code]: http://www.tempel.org/macdev/index.html#Libs
|
||||
[Stone Table Software]: https://web.archive.org/web/20010308062807/http://www.stonetablesoftware.com/rtf2text.html
|
||||
[ScreenChooser]: https://archive.org/details/screen-chooser
|
||||
[YouTube]: https://youtu.be/vtBlOaG2pNw
|
||||
[Retroweb Vintage Computer Museum]: http://retroweb.maclab.org
|
||||
[MiniVNC]: https://github.com/marciot/mac-minivnc
|
||||
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 101 KiB |
Binary file not shown.
After Width: | Height: | Size: 693 KiB |
Binary file not shown.
After Width: | Height: | Size: 465 KiB |
|
@ -14,7 +14,8 @@ void mac_list_volumes() {
|
|||
for (;;) {
|
||||
OSErr err = PBHGetVInfo(¶mBlock, false);
|
||||
if (err == nsvErr) break;
|
||||
printf(" %d: %#s\n", paramBlock.volumeParam.ioVolIndex, paramBlock.volumeParam.ioNamePtr);
|
||||
size_t size = paramBlock.volumeParam.ioVAlBlkSiz * paramBlock.volumeParam.ioVNmAlBlks;
|
||||
printf("%4d: [%7.2f MBs] %#s\n", paramBlock.volumeParam.ioVolIndex, float(size)/1024/1024, paramBlock.volumeParam.ioNamePtr);
|
||||
paramBlock.volumeParam.ioVolIndex++;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +24,7 @@ OSErr mac_get_drive_volumes(int driveNum, Str255 str) {
|
|||
HParamBlockRec paramBlock;
|
||||
Str255 volName;
|
||||
Boolean first = true;
|
||||
|
||||
str[0] = '\0';
|
||||
paramBlock.volumeParam.ioCompletion = 0;
|
||||
paramBlock.volumeParam.ioNamePtr = volName;
|
||||
paramBlock.volumeParam.ioVRefNum = 0;
|
||||
|
@ -65,6 +66,38 @@ OSErr mac_unmount_drive(int driveNum) {
|
|||
}
|
||||
}
|
||||
|
||||
OSErr mac_mount_drive(int driveNum) {
|
||||
ParamBlockRec paramBlock;
|
||||
|
||||
paramBlock.volumeParam.ioVRefNum = driveNum;
|
||||
|
||||
OSErr err = PBMountVol(¶mBlock);
|
||||
return err;
|
||||
}
|
||||
|
||||
OSErr mac_mount_drives() {
|
||||
const QHdrPtr qh = GetDrvQHdr();
|
||||
for(DrvQElPtr qe = (DrvQElPtr) qh->qHead; qe; qe = (DrvQElPtr) qe->qLink) {
|
||||
OSErr err = mac_mount_drive(qe->dQDrive);
|
||||
switch(err) {
|
||||
case volOnLinErr: continue;
|
||||
default: printf("Error %d while mounting drive %d\n", err, qe->dQDrive);
|
||||
}
|
||||
}
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSErr mac_list_drives() {
|
||||
Str255 volumeNames;
|
||||
const QHdrPtr qh = GetDrvQHdr();
|
||||
for(DrvQElPtr qe = (DrvQElPtr) qh->qHead; qe; qe = (DrvQElPtr) qe->qLink) {
|
||||
size_t size = size_t(qe->dQDrvSz) | ((qe->qType == 1) ? size_t(qe->dQDrvSz2) << 16 : 0) ;
|
||||
mac_get_drive_volumes(qe->dQDrive, volumeNames);
|
||||
printf("%4d: [%7.2f MBs] %#s\n", qe->dQDrive, float(size)/2/1024, volumeNames);
|
||||
}
|
||||
return noErr;
|
||||
}
|
||||
|
||||
void mac_unmount(int id) {
|
||||
HParamBlockRec paramBlock;
|
||||
paramBlock.volumeParam.ioCompletion = 0;
|
||||
|
|
|
@ -3,3 +3,6 @@ void mac_unmount(int id);
|
|||
void mac_eject(int id);
|
||||
OSErr mac_get_drive_volumes(int driveNum, Str255 str);
|
||||
OSErr mac_unmount_drive(int driveNum);
|
||||
OSErr mac_mount_drive(int driveNum);
|
||||
OSErr mac_mount_drives();
|
||||
OSErr mac_list_drives();
|
|
@ -38,19 +38,24 @@ bool process_command() {
|
|||
printf("\n");
|
||||
|
||||
char *arg_str = strchr(cmd, ' ');
|
||||
while(*arg_str == ' ') arg_str++;
|
||||
if(arg_str) arg_val = atoi(arg_str);
|
||||
if(arg_str) {
|
||||
while(*arg_str == ' ') arg_str++;
|
||||
arg_val = atoi(arg_str);
|
||||
}
|
||||
|
||||
switch( tolower(cmd[0]) ) {
|
||||
case 'h': print_help(); break;
|
||||
case 'l': scan_bus(); break;
|
||||
case 's': iomega_spin_up_cartridge(arg_val); break;
|
||||
case 'p': iomega_spin_down_cartridge(arg_val); break;
|
||||
case 'r': scsi_reset(); break;
|
||||
case 'e': mac_eject(arg_val); break;
|
||||
case 'i': dev_info(arg_val); break;
|
||||
case 'v': mac_list_volumes(); break;
|
||||
case 'u': mac_unmount(arg_val); break;
|
||||
case 'q': return false;
|
||||
case 'd': mac_list_drives(); break;
|
||||
case 'm': if(arg_str) mac_mount_drive(arg_val); else mac_mount_drives(); break;
|
||||
default: printf("Unknown command, type 'h' for help\n");
|
||||
}
|
||||
return true;
|
||||
|
@ -62,10 +67,15 @@ void print_help() {
|
|||
" help : print this help\n"
|
||||
" quit : exit the command line\n"
|
||||
|
||||
"\nMacintosh commands:\n"
|
||||
"\nMacintosh volume commands:\n"
|
||||
" volumes : list Mac volumes\n"
|
||||
" unmount [n] : unmount a volume\n"
|
||||
" eject [n] : eject a volume\n"
|
||||
" unmount [n] : unmount a volume\n"
|
||||
|
||||
"\nMacintosh drive commands:\n"
|
||||
" drives : list all drives\n"
|
||||
" mount [n] : mount a drive\n"
|
||||
" mount : mount all drives\n"
|
||||
|
||||
"\nGeneral SCSI operations:\n"
|
||||
" reset : reset the SCSI bus\n"
|
||||
|
@ -74,6 +84,7 @@ void print_help() {
|
|||
|
||||
"\nIomega device operations on SCSI device:\n"
|
||||
" spin [n] : spin up a cartridge\n"
|
||||
" pause [n] : spin down a cartridge\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -84,9 +95,9 @@ void scan_bus() {
|
|||
for( id=0; id<8; id++ ) {
|
||||
err = scsi_inquiry( id, 0, &reply);
|
||||
if( err != 0 ) {
|
||||
printf( " %hd: (Not installed)\n", id );
|
||||
printf( "%4hd: (Not installed)\n", id );
|
||||
} else {
|
||||
printf( " %hd: ", id );
|
||||
printf( "%4hd: ", id );
|
||||
printn( reply.vend, 8 );
|
||||
printf( ", " );
|
||||
printn( reply.prod, 16 );
|
||||
|
|
|
@ -29,6 +29,19 @@ OSErr iomega_spin_down_and_eject( int id ) {
|
|||
return scsi_cmd(id, cmd, sizeof(cmd), 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
OSErr iomega_spin_down_cartridge( int id ) {
|
||||
// issue an Asynchronous STOP command to induce spindown
|
||||
char cmd[6] = {
|
||||
SCSI_Cmd_StartStopUnit,
|
||||
1, // set the IMMED bit for offline
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
return scsi_cmd(id, cmd, sizeof(cmd), 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
OSErr iomega_set_prevent_removal( int id, bool lock) {
|
||||
OSErr err;
|
||||
char cmd[6] = {
|
||||
|
|
|
@ -4,5 +4,6 @@ typedef Boolean bool;
|
|||
|
||||
OSErr iomega_spin_up_cartridge(int id);
|
||||
OSErr iomega_spin_down_and_eject(int id);
|
||||
OSErr iomega_spin_down_cartridge(int id);
|
||||
OSErr iomega_set_prevent_removal(int id, bool lock);
|
||||
OSErr iomega_eject_cartridge(int id);
|
||||
|
|
|
@ -61,8 +61,11 @@ OSErr scsi_cmd(int id, void *cmd, size_t clen, void *buff, size_t siz, size_t cn
|
|||
case SCSI_READ: io_err = SCSIRead( (Ptr) TIB ); break;
|
||||
default: break;
|
||||
}
|
||||
if (io_err != noErr) {
|
||||
printf("SCSI Read/Write Error: %d\n", io_err);
|
||||
if (io_err == scPhaseErr && flags & SCSI_READ) {
|
||||
printf("\nSCSI phase error; less data delivered than requested\n");
|
||||
}
|
||||
else if (io_err != noErr) {
|
||||
printf("\nSCSI Read/Write Error: %d\n", io_err);
|
||||
}
|
||||
} else {
|
||||
printf("SCSICmd Error: %d\n", err);
|
||||
|
|
|
@ -118,9 +118,6 @@ void WndProc(long iMessage, uint16_t wParam) {
|
|||
LineTo(LOGO_1_LEFT+0, LOGO_1_TOP+32);
|
||||
LineTo(LOGO_1_LEFT+0, LOGO_1_TOP+35);
|
||||
|
||||
// show the current logo bitmap
|
||||
SplashTheBitmap();
|
||||
|
||||
// paint the 3D program title
|
||||
Paint3DHeadline(szIntroTitle, BODY_LEFT, TITLE_TOP);
|
||||
|
||||
|
@ -135,6 +132,9 @@ void WndProc(long iMessage, uint16_t wParam) {
|
|||
SetRect(&rect, WH_RECT(BODY_LEFT, BODY_TOP+64, BODY_WIDTH, 115));
|
||||
TETextBox(szIntroText, strlen(szIntroText), &rect, teFlushDefault);
|
||||
|
||||
// show the current logo bitmap
|
||||
SplashTheBitmap();
|
||||
|
||||
ReleaseDC(hIntroWnd);
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ void WndProc(long iMessage, uint16_t wParam) {
|
|||
SpinUpIomegaCartridge(CurrentDevice);
|
||||
break;
|
||||
case DISK_AT_SPEED:
|
||||
printf("Testing the disk\n");
|
||||
printf("\nTesting the disk\n");
|
||||
if(TestingPhase != READY_TO_TEST) {
|
||||
PrepareToBeginTesting();
|
||||
}
|
||||
|
@ -177,6 +177,7 @@ void WndProc(long iMessage, uint16_t wParam) {
|
|||
EjectIomegaCartridge(CurrentDevice);
|
||||
break;
|
||||
case DISK_LOW_SPARES:
|
||||
CartridgeStatus = DISK_AT_SPEED;
|
||||
SetRichEditText(szNotRunning);
|
||||
SetWindowText(hTestButton, szPressToStart);
|
||||
PrepareToBeginTesting();
|
||||
|
@ -338,6 +339,15 @@ void PaintCenteredValue(int Xleft, int Ytop, int XWidth, int YHeight, long value
|
|||
*
|
||||
* This paints the two columns of testing statistics on the test minitor window.
|
||||
*******************************************************************************/
|
||||
char *FindErrorString(long error) {
|
||||
char *errStr = 0;
|
||||
for (int i = 0; errorTypeList[i].str; i++) {
|
||||
errStr = errorTypeList[i].str;
|
||||
if (errorTypeList[i].code == error) break;
|
||||
}
|
||||
return errStr;
|
||||
}
|
||||
|
||||
void PaintTestStatistics(bool Active) {
|
||||
char szString[40];
|
||||
// assemble and paint the sector testing range
|
||||
|
@ -360,12 +370,7 @@ void PaintTestStatistics(bool Active) {
|
|||
PaintCenteredString(76, 155, 126, 14, szString, Active);
|
||||
|
||||
// show the LastError
|
||||
char *errStr = 0;
|
||||
for (int i = 0; errorTypeList[i].str; i++) {
|
||||
errStr = errorTypeList[i].str;
|
||||
if (errorTypeList[i].code == LastError) break;
|
||||
}
|
||||
PaintCenteredString(76, 172, 126, 14, errStr, Active);
|
||||
PaintCenteredString(76, 172, 126, 14, FindErrorString(LastError), Active);
|
||||
|
||||
// show the elapsed time
|
||||
CvrtSecondsToHMSstring(szString, SecondsElapsed);
|
||||
|
|
|
@ -282,6 +282,8 @@ void PaintTheBarGraphs(bool Active);
|
|||
void PaintTestStatistics(bool Active);
|
||||
void CvrtSecondsToHMSstring(char *szString, long seconds);
|
||||
|
||||
char *FindErrorString(long error);
|
||||
|
||||
void UpdateCurrentSector();
|
||||
void UpdateRunTimeDisplay();
|
||||
void UpdateRunPhaseDisplay();
|
||||
|
@ -301,9 +303,9 @@ void GetCommandDetails(char command, char &cmd_flags, char &cmd_length);
|
|||
long SCSICommand(short Device, char *lpCmdBlk, void *lpIoBuf, size_t IoBufLen);
|
||||
long EnumerateIomegaDevices(uint8_t *DrivesSkipped);
|
||||
long GetModePage(short Device, short PageToGet, void *pBuffer, short BufLen);
|
||||
long SetModePage(short Device, void *pBuffer);
|
||||
long SetModePage(short Device, void *pBuffer, short BufLen);
|
||||
void ModifyModePage(char *PageBuff, char eec, char retries);
|
||||
void SetErrorRecovery(bool Retries, bool ECC, bool Testing);
|
||||
long SetErrorRecovery(bool Retries, bool ECC, bool Testing);
|
||||
long GetNonSenseData(short Device, short DataPage, void *Buffer, short BufLen);
|
||||
long LockCurrentDrive();
|
||||
long UnlockCurrentDrive();
|
||||
|
|
|
@ -6,8 +6,28 @@
|
|||
#include "tip.h"
|
||||
|
||||
//#define DEMO
|
||||
|
||||
/* The original TIP seems to request more data than is supplied by
|
||||
* certain commands. While this appears to be allowed, it causes
|
||||
* SCSI phase errors to be reported. Setting NO_EXCESS_READS will
|
||||
* adjust the reads to to the max size before such errors occur.
|
||||
*/
|
||||
#define NO_EXCESS_READS
|
||||
|
||||
/* The original TIP will always try to enable Early Recovery. This
|
||||
* fails on certain Jaz drives. While the original TIP will then
|
||||
* retry without Early Recovery, this will cause many errors to be
|
||||
* reported. Enable SUPRESS_ER_ERRORS to prevent this from problem
|
||||
* from happening as frequently
|
||||
*/
|
||||
#define SUPRESS_ER_ERRORS
|
||||
|
||||
/* The original TIP will always try to read the defects list, but
|
||||
* not all drives support this, causing many errors to be shown.
|
||||
* Setting SUPPRESS_DEFECTS_ERROR will silence these errors.
|
||||
*/
|
||||
#define SUPPRESS_DEFECTS_ERROR
|
||||
|
||||
#define MAKE_LITTLE_ENDIAN(a) a // Don't do anything on 68000
|
||||
#define MAKE_BIG_ENDIAN(a) a // Don't do anything on 68000
|
||||
|
||||
|
@ -96,6 +116,13 @@ long DriveCount = 0;
|
|||
long JazDrive = 0; // true if the current drive
|
||||
long CartridgeStatus = DISK_NOT_PRESENT;
|
||||
|
||||
#ifdef SUPRESS_ER_ERRORS
|
||||
Boolean SupressEarlyRecovery = false;
|
||||
#endif
|
||||
#ifdef SUPPRESS_DEFECTS_ERROR
|
||||
Boolean SupressDefectsError = false;
|
||||
#endif
|
||||
|
||||
unsigned long StartingInstant;
|
||||
|
||||
// ----------------------------- Run Time Variables ------------------------------
|
||||
|
@ -215,6 +242,7 @@ long SCSICommand(short Device, char *lpCmdBlk, void *lpIoBuf, size_t IoBufLen) {
|
|||
(long(sense_data.ascq) << 8) |
|
||||
(long(sense_data.key) );
|
||||
if(res == MEDIA_CHANGE_CODE) {
|
||||
printf("Media change signalled. Most recent error can be ignored\n\n");
|
||||
int index = GetDriveEntryOffset(Device);
|
||||
DriveArray[index].flags |= MEDIA_CHANGED;
|
||||
return 0;
|
||||
|
@ -312,13 +340,18 @@ long GetModePage(short Device, short PageToGet, void *pBuffer, short BufLen) {
|
|||
/*******************************************************************************
|
||||
* SET MODE PAGE
|
||||
*******************************************************************************/
|
||||
long SetModePage(short Device, void *pBuffer) {
|
||||
char* ebx = (char*) pBuffer; // get a pointer to the top of buffer
|
||||
char ecx = ebx[0] + 1; // adjust it up by one
|
||||
long SetModePage(short Device, void *pBuffer, short BufLen) {
|
||||
unsigned char* ebx = (unsigned char*) pBuffer; // get a pointer to the top of buffer
|
||||
unsigned char ecx = ebx[0] + 1; // adjust it up by one
|
||||
|
||||
ebx[0] = 0; // now clear the two reserved bytes
|
||||
ebx[2] = 0;
|
||||
|
||||
if(ecx != BufLen) {
|
||||
printf("Length error in SetModePage %d != %d\n\n", BufLen, (int) ecx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char Scsi[6] = {0}; // init the SCSI parameter block
|
||||
Scsi[0] = SCSI_Cmd_ModeSelect; // set the command
|
||||
Scsi[1] = 0x10; // set the Page Format bit
|
||||
|
@ -343,16 +376,21 @@ void ModifyModePage(char *PageBuff, char ecc, char retries) {
|
|||
ebx[8] = retries; // then set the write count too
|
||||
}
|
||||
|
||||
void SetErrorRecovery(bool Retries, bool ECC, bool Testing) {
|
||||
long SetErrorRecovery(bool Retries, bool ECC, bool Testing) {
|
||||
char PageBuff[40];
|
||||
|
||||
#ifdef NO_EXCESS_READS
|
||||
// Limit reads to 20 bytes on Zip to prevent controller errors
|
||||
GetModePage(CurrentDevice, ERROR_RECOVERY_PAGE, PageBuff, JazDrive ? sizeof(PageBuff) : 20);
|
||||
// Limit reads to 20 bytes on Zip (24 bytes on Jaz) to prevent controller errors
|
||||
const short pageBuffLen = JazDrive ? 24 : 20;
|
||||
#else
|
||||
GetModePage(CurrentDevice, ERROR_RECOVERY_PAGE, PageBuff, sizeof(PageBuff));
|
||||
const short pageBuffLen = sizeof(PageBuff);
|
||||
#endif
|
||||
|
||||
long eax = GetModePage(CurrentDevice, ERROR_RECOVERY_PAGE, PageBuff, pageBuffLen);
|
||||
if(eax) {
|
||||
printf("SetErrorRecovery failed\n");
|
||||
return eax;
|
||||
}
|
||||
|
||||
#define EARLY_RECOVERY 0x08
|
||||
#define PER 0x04
|
||||
#define SUPPRESS_ECC 0x01
|
||||
|
@ -360,6 +398,9 @@ void SetErrorRecovery(bool Retries, bool ECC, bool Testing) {
|
|||
// set the ECC fields
|
||||
char ecc = SUPPRESS_ECC; // presume ECC suppression
|
||||
if(ECC) {
|
||||
#ifdef SUPRESS_ER_ERRORS
|
||||
if(!SupressEarlyRecovery)
|
||||
#endif
|
||||
ecc = EARLY_RECOVERY; // enable ECC and Early Recovery
|
||||
if(Testing) {
|
||||
ecc = EARLY_RECOVERY | PER; // we're testing, so EER & PER
|
||||
|
@ -374,14 +415,22 @@ void SetErrorRecovery(bool Retries, bool ECC, bool Testing) {
|
|||
retries = 0;
|
||||
|
||||
ModifyModePage(PageBuff, ecc, retries);
|
||||
const long eax = SetModePage(CurrentDevice, PageBuff);
|
||||
|
||||
eax = SetModePage(CurrentDevice, PageBuff, pageBuffLen);
|
||||
// if we had an invalid field in the CDB (the EER bit was on)
|
||||
if (eax == 0x00260005) {
|
||||
GetModePage(CurrentDevice, ERROR_RECOVERY_PAGE, PageBuff, sizeof(PageBuff));
|
||||
ecc &= ~0x08; // same, *BUT*NOT* Early Recovery
|
||||
GetModePage(CurrentDevice, ERROR_RECOVERY_PAGE, PageBuff, pageBuffLen);
|
||||
ecc &= ~EARLY_RECOVERY; // same, *BUT*NOT* Early Recovery
|
||||
ModifyModePage(PageBuff, ecc, retries);
|
||||
SetModePage(CurrentDevice, PageBuff);
|
||||
eax = SetModePage(CurrentDevice, PageBuff, pageBuffLen);
|
||||
#ifdef SUPRESS_ER_ERRORS
|
||||
if(!eax) {
|
||||
printf(" Early recovery not supported on this drive. Ignoring.\n\n");
|
||||
SupressEarlyRecovery = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return eax;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -468,7 +517,18 @@ long GetSpareSectorCounts(char checkPassword) {
|
|||
Scsi[0] = SCSI_Cmd_ReadDefectData;
|
||||
Scsi[2] = 0x1e; // 0b00011110 defect format, G/P bits
|
||||
Scsi[8] = 4; // ask for only FOUR bytes
|
||||
#ifdef SUPPRESS_DEFECTS_ERROR
|
||||
if(SupressDefectsError)
|
||||
eax = INCOMPATIBLE_MEDIA;
|
||||
else
|
||||
#endif
|
||||
eax = SCSICommand(CurrentDevice, Scsi, &DefectHeader, sizeof(DefectHeader));
|
||||
#ifdef SUPPRESS_DEFECTS_ERROR
|
||||
if(!SupressDefectsError && eax == INCOMPATIBLE_MEDIA) {
|
||||
printf("Defects list not supported on this drive. Ignoring.\n\n");
|
||||
SupressDefectsError = true;
|
||||
}
|
||||
#endif
|
||||
if ((!eax) || (eax == INCOMPATIBLE_MEDIA)) {
|
||||
// we could read its defect list ... so show it!
|
||||
// --------------------------------------------------------------------------
|
||||
|
@ -635,7 +695,7 @@ uint8_t GetCartridgeStatus(long Device, uint8_t flags) {
|
|||
long eax;
|
||||
char DiskStat[72];
|
||||
#ifdef NO_EXCESS_READS
|
||||
eax = GetNonSenseData(Device, DISK_STATUS_PAGE, DiskStat, (flags & JAZ_DRIVE) ? sizeof(DiskStat) : 63);
|
||||
eax = GetNonSenseData(Device, DISK_STATUS_PAGE, DiskStat, 4);
|
||||
if (eax) return DISK_STATUS_UNKNOWN;
|
||||
#else
|
||||
eax = GetNonSenseData(Device, DISK_STATUS_PAGE, DiskStat, sizeof(DiskStat));
|
||||
|
@ -674,6 +734,7 @@ void SetCartridgeStatusToEAX(long eax, uint8_t flags) {
|
|||
SetRichEditText(szNotRunning);
|
||||
goto DisableActions;
|
||||
case DISK_AT_SPEED:
|
||||
printf("Disk at speed\n");
|
||||
eax = GetSpareSectorCounts(true); // update the Cart Condition
|
||||
if(eax == MEDIA_NOT_PRESENT) {
|
||||
goto DisableActions;
|
||||
|
@ -686,10 +747,14 @@ void SetCartridgeStatusToEAX(long eax, uint8_t flags) {
|
|||
FirmErrors = 0;
|
||||
// check to see if we have enough spares to start
|
||||
if(JazDrive) {
|
||||
printf("Spare Sectors: %ld/%d\n", Side_0_SparesCount, MAXIMUM_JAZ_SPARES);
|
||||
if(Side_0_SparesCount < MINIMUM_JAZ_SPARES)
|
||||
goto InsufficientSpares;
|
||||
}
|
||||
else {
|
||||
printf("Spare Sectors:\n");
|
||||
printf(" Side 1: %ld/%d\n", Side_0_SparesCount, MAXIMUM_ZIP_SPARES);
|
||||
printf(" Side 2: %ld/%d\n", Side_1_SparesCount, MAXIMUM_ZIP_SPARES);
|
||||
if(Side_0_SparesCount < MINIMUM_ZIP_SPARES) {
|
||||
goto InsufficientSpares;
|
||||
}
|
||||
|
@ -761,6 +826,12 @@ void PrepareToBeginTesting() {
|
|||
HardErrors = 0;
|
||||
UserInterrupt = 0;
|
||||
LastError = 0;
|
||||
#ifdef SUPRESS_ER_ERRORS
|
||||
SupressEarlyRecovery = false;
|
||||
#endif
|
||||
#ifdef SUPPRESS_DEFECTS_ERROR
|
||||
SupressDefectsError = false;
|
||||
#endif
|
||||
#ifdef DEMO
|
||||
LastLBAOnCartridge = 99999;
|
||||
SoftErrors = 6;
|
||||
|
@ -820,12 +891,12 @@ long PerformRegionTransfer(short XferCmd, void *pBuffer) {
|
|||
char Scsi[10] = {0}; // clear out the SCSI CDB
|
||||
const long InitialHardErrors = HardErrors;
|
||||
|
||||
SetErrorRecovery(false, false, true); // disable Retries & ECC
|
||||
long eax = SetErrorRecovery(false, false, true); // disable Retries & ECC
|
||||
|
||||
Scsi[0] = XferCmd;
|
||||
SET_DWORD_AT(Scsi, 2, MAKE_BIG_ENDIAN(FirstLBASector)); // WHICH LBA's to read, BIG endian
|
||||
SET_WORD_AT (Scsi, 7, MAKE_BIG_ENDIAN(NumberOfLBAs)); // HOW MANY to read, BIG endian
|
||||
long eax = SCSICommand(CurrentDevice, Scsi, pBuffer, NumberOfLBAs * BYTES_PER_SECTOR);
|
||||
eax = SCSICommand(CurrentDevice, Scsi, pBuffer, NumberOfLBAs * BYTES_PER_SECTOR);
|
||||
// if we failed somewhere during our transfer ... let's zero in on it
|
||||
if (eax) {
|
||||
if ( eax == SS_ERR || // if it's a CONTROLLER ERROR, skip!
|
||||
|
@ -834,6 +905,8 @@ long PerformRegionTransfer(short XferCmd, void *pBuffer) {
|
|||
goto Exit;
|
||||
}
|
||||
|
||||
printf("Starting detailed search...\n");
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Save error and current Soft + Hard Error count to see if we do FIND the glitch ...
|
||||
const long GlitchError = eax; // save the error which stopped us!
|
||||
|
@ -863,6 +936,7 @@ long PerformRegionTransfer(short XferCmd, void *pBuffer) {
|
|||
if (eax == SS_ERR) goto Exit; // if it's a CONTROLLER ERROR, skip!
|
||||
if (eax & 0xFF == 1) goto PostTheError; // did we recover?
|
||||
|
||||
printf(" Found error, retesting with retries\n");
|
||||
SetErrorRecovery(true, false, true); // enable retries
|
||||
eax = SCSICommand(CurrentDevice, Scsi, LocalBuffer, BYTES_PER_SECTOR);
|
||||
if (eax) {
|
||||
|
@ -870,7 +944,8 @@ long PerformRegionTransfer(short XferCmd, void *pBuffer) {
|
|||
if (eax == SS_ERR) goto Exit; // if it's a CONTROLLER ERROR, skip!
|
||||
if (eax & 0xFF == 1) goto PostTheError; // did we recover?
|
||||
|
||||
SetErrorRecovery(true, true, true); // enable retries AND EEC
|
||||
printf(" Found error, retesting with retries & ECC\n");
|
||||
eax = SetErrorRecovery(true, true, true); // enable retries AND EEC
|
||||
eax = SCSICommand(CurrentDevice, Scsi, LocalBuffer, BYTES_PER_SECTOR);
|
||||
if (eax) {
|
||||
// failed with retries and EEC
|
||||
|
@ -888,6 +963,8 @@ long PerformRegionTransfer(short XferCmd, void *pBuffer) {
|
|||
}
|
||||
|
||||
PostTheError:
|
||||
printf(" %s (Sector %ld)\n", FindErrorString(eax), SingleTransferLBA);
|
||||
printf("--------------------------------------------\n");
|
||||
BumpErrorCounts(eax); // given eax, count the errors
|
||||
GetSpareSectorCounts(false); // update the Cart's Condition
|
||||
UpdateRunTimeDisplay();
|
||||
|
@ -897,6 +974,7 @@ long PerformRegionTransfer(short XferCmd, void *pBuffer) {
|
|||
ProcessPendingMessages();
|
||||
}
|
||||
|
||||
printf("... detailed search finished\n");
|
||||
// now see whether we *did* found something to complain about ...
|
||||
eax = SoftErrors + HardErrors;
|
||||
if (eax == GlitchCount) {
|
||||
|
@ -907,6 +985,7 @@ long PerformRegionTransfer(short XferCmd, void *pBuffer) {
|
|||
long ebx = eax & 0x00FF00FF; // strip the ASCQ byte
|
||||
if(ebx == 0x00110003) // if we're about to say "unrecovered read"
|
||||
eax = 0x170101; // change it to: "Read with Retries"
|
||||
printf("%s\n", FindErrorString(eax));
|
||||
BumpErrorCounts(eax); // given eax, count the errors
|
||||
HardErrors = SavedHardErrors; // restore the counts
|
||||
SoftErrors = SavedSoftErrors;
|
||||
|
@ -917,6 +996,7 @@ long PerformRegionTransfer(short XferCmd, void *pBuffer) {
|
|||
eax = 0; // now let's return happiness to our caller
|
||||
if (HardErrors != InitialHardErrors) // UNRECOVERABLE errors!
|
||||
eax = -1;
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
|
|
@ -83,9 +83,11 @@ void run_tip() {
|
|||
}
|
||||
} while (!gDone);
|
||||
|
||||
EjectAllMedia();
|
||||
DisposeTipWindow();
|
||||
DisposeRgn(cursorRgn);
|
||||
|
||||
// Remount any drives we may have unmounted
|
||||
mac_mount_drives();
|
||||
}
|
||||
|
||||
void NewTipWindow() {
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
/************************************************************
|
||||
|
||||
pstring.c
|
||||
|
||||
AUTHOR: Marcio Luis Teixeira
|
||||
CREATED: 9/17/94
|
||||
|
||||
LAST REVISION: 11/25/21
|
||||
|
||||
(c) 1994-1995 by Marcio Luis Teixeira.
|
||||
All rights reserved.
|
||||
|
||||
*************************************************************/
|
||||
/****************************************************************************
|
||||
* Common Libraries (c) 1994 Marcio Teixeira *
|
||||
* *
|
||||
* 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 *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* To view a copy of the GNU General Public License, go to the following *
|
||||
* location: <http://www.gnu.org/licenses/>. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "pstring.h"
|
||||
#include <ctype.h>
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
/************************************************************
|
||||
|
||||
pstring.h
|
||||
|
||||
AUTHOR: Marcio Luis Teixeira
|
||||
CREATED: 9/17/94
|
||||
|
||||
LAST REVISION: 11/25/21
|
||||
|
||||
(c) 1994-1995 by Marcio Luis Teixeira.
|
||||
All rights reserved.
|
||||
|
||||
*************************************************************/
|
||||
/****************************************************************************
|
||||
* Common Libraries (c) 1994 Marcio Teixeira *
|
||||
* *
|
||||
* 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 *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* To view a copy of the GNU General Public License, go to the following *
|
||||
* location: <http://www.gnu.org/licenses/>. *
|
||||
****************************************************************************/
|
||||
|
||||
short pstrlen( unsigned char *str );
|
||||
void psetlen( unsigned char *str, short len );
|
||||
|
|
Loading…
Reference in New Issue