Src/SCSIAsyncSample.h

/*                              SCSIAsyncSample.h                               */
/*
 * SCSIAsyncSample.h
 * Copyright © 1992-93 Apple Computer Inc. All Rights Reserved.
 */
#define kApplicationCreator '????'
 
#define MBAR_MenuBar        1000
#define MENU_Apple          1
#define MENU_File           128
#define MENU_Edit           129
#define STRS_SenseBase      1000
#define DLOG_About          128
#define DLOG_Query          129
#define ALRT_NoNewSCSI      9000
#define ALRT_FatalError     9001
#define ALRT_NoMemory       9002
#define ALRT_NonFatalError  9003
#define ACUR_Animator       128
 
#define kMinWindowWidth     200
#define kMinWindowHeight    300
#define kLogLines           512
#define kRequestMemory      100
 
#ifndef REZ
#ifndef THINK_C             /* MPW includes         */
#include <Errors.h>
#include <Script.h>
#include <Types.h>
#include <Resources.h>
#include <QuickDraw.h>
#include <Fonts.h>
#include <Events.h>
#include <Windows.h>
#include <ToolUtils.h>
#include <Memory.h>
#include <Menus.h>
#include <Lists.h>
#include <Printing.h>
#include <Dialogs.h>
#include <Packages.h>
#include <Controls.h>
#endif
 
/*
 * These definitions are only for the code files.
 */
#ifndef TRUE
#define TRUE    1
#define FALSE   0
#endif
#ifndef EXTERN
#define EXTERN  extern
#endif
 
#include "SCSIDefinitions.h"
#include "LogManager.h"
#include "MicrosecondTrap.h"
 
/*
 * Include the O.S. files in a specific order to make sure that we have
 * a definition for the _SCSIAtomic trap.
 */
#include <Traps.h>
#ifndef _SCSIAtomic
#define _SCSIAtomic 0xA089
#endif
/*
 * Note that this uses a later version of <Scsi.h> than is available in
 * the published headers.
 */
#include "Scsi.h"
 
#define kScrollBarWidth     16
#define kScrollBarOffset    (kScrollBarWidth - 1)
 
/*
 * Items in the Apple Menu
 */
enum {
    kAppleAbout = 1
};
 
/*
 * Items in the File Menu
 */
enum {
    kFileCreateLogFile = 1,
    kFileCloseLogFile,
    kFileUnused1,
    kFilePageSetup,
    kFilePrint,
    kFileUnused2,
    kFileDebug,
    kFileUnused3,
    kFileQuit
};
 
enum EditMenu {
    kEditUndo               = 1,
    kEditUnused,
    kEditCut,
    kEditCopy,
    kEditPaste,
    kEditClear
};
 
/*
 * Items in the Query Dialog
 */
enum {
    kQueryTest = 1,
    kQueryFinished,
    kQueryHostBus,
    kQueryTargetID,
    kQueryTotalRequests,
    kQueryBlocksPerTransfer,
    kQueryTimeout,
    kQueryEnableAsync,
    kQueryEnableDisconnect,
    kQueryRandomSeek,
    kQueryThreadNumber,
    kQueryVendorID,
    kQueryProduct,
    kQueryLogicalBlockLength,
    kQueryBlocksOnDevice
};
 
typedef struct VMHoldRecord {
    void                *ptr;
    unsigned long       size;
} VMHoldRecord, *VMHoldPtr;
enum {
    kVMFunction = 0,
    kVMStack,
    kVMParam,
    kVMBuffer,
    kVMSense,
    kVMSize         /* Must be last */
};
 
typedef struct RequestMemory {
    unsigned long       blockNumber;
    UnsignedWide        startTime;
    UnsignedWide        endTime;
} RequestMemory, *RequestMemoryPtr;
/*
 * This is the information we need for each execution thread. They are
 * created by the query dialog loop. These records are stored in
 * permanent physical memory (HoldMemory)
 */
struct InfoRecord {
    struct ScsiCmdBlock *link;                  /* Queue link pointer           */
    short               qType;                  /* Unused for OSQueue           */
    SCSIExecIOPB        *pb;                    /* For SCSI Mgr Request         */
    unsigned long       pbSize;                 /* Sizeof param block           */
    Ptr                 bufferPtr;              /* -> transfer buffer           */
    unsigned long       bufferLength;           /* == allocated length          */
    unsigned short      threadIndex;            /* Which thread is it           */
    Boolean             deviceActive;           /* TRUE when busy               */
    Boolean             testCompleted;          /* TRUE when finished           */
    unsigned long       completionTimeout;      /* I/O Timeout                  */
    unsigned long       transferQuantum;        /* Transfer quantum             */
    unsigned long       randomSeed;             /* Random number for seek test  */
/* Data from the dialog */
    DeviceIdent         deviceIdent;            /* Bus/Target/LUN               */
    unsigned long       transferSizeBlocks;     /* Blocks to transfer           */
    unsigned long       totalTransfers;         /* Transfers to perform         */
    unsigned long       transfersAttempted;     /* Calls to SCSIAction          */
    Boolean             enableAsync;            /* Asynch checked?              */
    Boolean             enableDisconnect;       /* Disconnect checked?          */
    Boolean             enableRandomSeek;       /* Random seek test             */
/* Data resulting from Read Capacity */
    unsigned long       totalLogicalBlocks;     /* Blocks on device             */
    unsigned long       logicalBlockLength;     /* Logical block size           */
/* Data resulting from Device Inquiry */
    unsigned char       vendor[9];              /* Vendor name (pascal)         */
    unsigned char       product[17];            /* Product ID (pascal)          */
/* Data changed by/for each transfer request */
    OSErr               finalStatus;            /* First detected error         */
    SCSI_Command        command;                /* == Current command           */
    unsigned long       blockNumber;            /* Read from this block         */
    unsigned long       blockCount;             /* Blocks to transfer           */
    unsigned long       byteCount;              /* Bytes to transfer            */
    unsigned long       nextBlockNumber;        /* Block to start next time     */
    unsigned long       transfersCompleted;     /* I/O Completion count         */
    unsigned long       asynchRequests;         /* Truely asychronous           */
    unsigned char       statusByte;             /* Status Phase byte            */
    SCSI_Sense_Data     senseData;              /* Gets Sense data              */
    unsigned long       actualTransferCount;    /* TRUE transfer length         */
/* VM state (set by DoSCSIExecIO, cleared by command completion) */
    VMHoldRecord        vmHoldInfo[kVMSize];
/* This is used for the setup dialog */
    Boolean             validDevice;
/* Statistics */
    UnsignedWide        testStartTime;          /* Total testing start time     */
    UnsignedWide        testEndTime;            /* Total testing end time       */
    double              sampleSum;              /* For mean time (sum in uSec)  */
    double              sampleSumSquare;        /* And standard deviation       */
    RequestMemoryPtr    requestMemoryPtr;       /* Current request slot         */
    RequestMemory       requestMemory[kRequestMemory];
};
typedef struct InfoRecord InfoRecord, *InfoPtr;
 
/*
 * Processing functions
 */
void                            GetDevicesToTest(void);
void                            DisplayTestParameters(void);
void                            DisplayTestResults(void);
void                            StartTesting(void);
void                            ContinueTesting(void);
pascal Boolean                  NumericFilter(
        DialogPtr                   dp,
        EventRecord                 *eventPtr,
        short                       *itemHit
    );
 
/*
 * SCSI Executor
 */
OSErr                           DoSCSISynchronousIO(
        InfoPtr                     infoPtr,
        SCSI_CommandPtr             commandPtr,
        unsigned long               scsiFlags,
        Ptr                         bufferPtr,
        unsigned long               transferLength
    );
short                           GetSCSICDBLength(
        const SCSI_CommandPtr       scsiCommandPtr
    );
 
/*
 * Utility functions
 */
OSErr                           CheckForDevicePresent(
        unsigned short              busID,
        unsigned short              target,
        unsigned short              LUN
    );
Boolean                         AsyncSCSIPresent(void);
OSErr                           GetHostBusCount(
        short                       *busCount
    );
void                            DoTestUnitReady(
        unsigned short              busID,
        unsigned short              target,
        unsigned short              LUN
    );
void                            ExecuteSCSICommand(
        register InfoPtr            infoPtr
    );
void                            IOCompletion(
        SCSIExecIOPB                *ioPBPtr
    );
 
/*
 * Display and error logging
 */
void                            DisplayDeviceInfo(
        register InfoPtr            infoPtr
    );
void                            AppendSCSIBusID(
        StringPtr                   result,
        DeviceIdent                 deviceIdent
    );
void                            ShowSCSIBusID(
        register InfoPtr            infoPtr
    );
void                            ShowRequestSense(
        register InfoPtr            infoPtr
    );
void                            ShowStatusError(
        OSErr                       errorStatus,
        unsigned short              cmdByte
    );
void                            DisplaySCSIErrorMessage(
        OSErr                       errorStatus,
        ConstStr255Param            errorText
    );
void                            NonFatalError(
        OSErr                       errorStatus,
        ConstStr255Param            errorMsg
    );
void                            FatalError(
        OSErr                       errorStatus,
        ConstStr255Param            errorMsg
    );
/*
 * String formatting utilities.
 */
/*
 * AppendChar writes a character into the string. Note that
 * it wraps around if the string size exceeds 255 bytes.
 */
#define AppendChar(result, c) (result[++result[0]] = (c))
void                            AppendUnsigned(
        StringPtr                   result,
        unsigned long               value
    );
void                            AppendSigned(
        StringPtr                   result,
        signed long                 value
    );
void                            AppendUnsignedLeadingZeros(
        StringPtr                   result,
        unsigned long               value,
        short                       fieldWidth,
        short                       terminatorChar
    );
void                        AppendHexLeadingZeros(
        StringPtr                   result,
        unsigned long               value,
        short                       fieldWidth
    );
void                        AppendUnsignedInField(
        StringPtr                   result,
        unsigned long               value,
        short                       fieldWidth
    );
void                        AppendBytes(
        StringPtr                   result,
        const Ptr                   source,
        unsigned short              length
    );
void                        AppendPascalString(
        StringPtr                   result,
        const StringPtr             value
    );
void                        AppendCString(
        StringPtr                   result,
        const char                  *source,
        unsigned short              maxLength       /* Ignored if zero  */
    );
void                        AppendOSType(
        StringPtr                   result,
        OSType                      value
    );
void                        AppendDouble(
        StringPtr                   result,
        double                      value,
        unsigned short              decimalPlaces
    );
 
/*
 * Window Utilities
 */
void                            DoZoomWindow(
        WindowPtr                   theWindow,
        short                       whichPart
    );
Boolean                         DoGrowWindow(
        WindowPtr                   theWindow,
        Point                       eventWhere,
        short                       minimumWidth,
        short                       minimumHeight
    );
void                            MyDrawGrowIcon(
        WindowPtr                   theWindow
    );
 
/*
 * Format a block of data into the log.
 */
void                            DisplayDataBlock(
        Ptr                         dataPtr,
        unsigned short              dataLength
    );
 
void                            pstrcpy(
        StringPtr                   destination,
        ConstStr255Param            source
    );
void                            pstrcat(
        StringPtr                   destination,
        ConstStr255Param            source
    );
void                            ClearMemory(
        Ptr                         dataPtr,
        unsigned long               dataSize
    );
#define width(r)        ((r).right - (r).left)
#define height(r)       ((r).bottom - (r).top)
#define CLEAR(record)   ClearMemory((Ptr) &record, sizeof record);
 
/*
 * Global variables.
 */
EXTERN WindowPtr                gMainWindow;
EXTERN EventRecord              gCurrentEvent;
#define EVENT                   (gCurrentEvent)
EXTERN ListHandle               gLogListHandle;
EXTERN THPrint                  gPrintHandle;
EXTERN Boolean                  gQuitNow;
EXTERN Boolean                  gStopNow;
EXTERN Boolean                  gUpdateMenusNeeded;
EXTERN Boolean                  gInForeground;
EXTERN Boolean                  gVirtualMemoryEnabled;
EXTERN MenuHandle               gAppleMenu;
EXTERN MenuHandle               gFileMenu;
EXTERN MenuHandle               gEditMenu;
EXTERN short                    gMaxHostBus;
EXTERN QHdr                     infoPtrQueue;   /* Known execution threads  */
 
/*
 * VM Stuff
 */
extern void                     VMStartMarker(void);
extern void                     VMEndMarker(void);
#define kVMStackSize            4096
EXTERN VMHoldRecord             gVMHoldRecord[kVMStack + 1];
 
#endif      /* REZ          */