Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Src/SCSISimpleSampleMain.c
/* SCSISimpleSampleMain.c */ |
/* |
* SCSISimpleSampleMain.c |
* Copyright © 1992-94 Apple Computer Inc. All Rights Reserved. |
* |
* This is a "simple sample" that illustrates calls to the original and the |
* asynchronous SCSI Managers. In particular, it contains "definitive" |
* algorithms for determining the number of SCSI devices attached to a |
* Macintosh system. |
*/ |
#define EXTERN |
#include "SCSISimpleSample.h" |
#include <Packages.h> |
#include <Desk.h> |
#include <OSEvents.h> |
#pragma segment MainCode |
#ifdef __powerc |
/* |
* Power PC does not automatically define the QuickDraw globals. This is because |
* only "application" code-fragments need these globals, and this cannot be |
* determined before the code fragment is constructed. |
*/ |
QDGlobals qd; /* This is not automatically defined on PowerPC */ |
#endif |
void main(void); |
void EventLoop(void); |
void DoMouseEvent(void); |
void DoContentClick( |
WindowPtr theWindow |
); |
void DoCommand( |
WindowPtr theWindow, |
long menuChoice |
); |
void DoWindowKeyDown( |
WindowPtr theWindow |
); |
void SetupEverything(void); |
void AdjustMenus(void); |
void AdjustEditMenu( |
Boolean isDeskAccessory |
); |
void SetupMenus(void); |
void BuildWindow(void); |
void DecorateDisplay( |
WindowPtr theWindow, |
Boolean redraw |
); |
void DrawWindow( |
WindowPtr theWindow |
); |
void DoAbout(void); |
void DoPageSetup(void); |
void HexToString( |
unsigned long value, |
short hexDigits, |
Str255 result |
); |
Boolean HexToNum( |
ConstStr255Param hexString, |
unsigned long *result |
); |
#define IsOurWindow(theWindow) ((theWindow) == gMainWindow) |
/* |
* This preserves the currently-chosen host bus ID in case the user switches |
* between "old" and "new" SCSI Managers. |
*/ |
static unsigned short gOldHostBusID; |
void |
main(void) |
{ |
SetupEverything(); |
BuildWindow(); |
gUpdateMenusNeeded = TRUE; |
gInForeground = TRUE; |
gEnableNewSCSIManager = AsyncSCSIPresent(); |
if (gEnableNewSCSIManager) |
LOG("\pHas asynchronous SCSI Manager"); |
else { |
LOG("\pAsynchronous SCSI Manager not present"); |
} |
gEnableSelectWithATN = gEnableNewSCSIManager; |
InitCursor(); |
while (gQuitNow == FALSE) { |
EventLoop(); |
} |
ExitToShell(); |
} |
/* |
* BuildWindow creates a document window and stores a text log |
* as its content. |
*/ |
void |
BuildWindow() |
{ |
short fontSize; |
short fontNumber; |
Rect viewRect; |
fontSize = 10; |
GetFNum("\pCourier", &fontNumber); |
if (RealFont(fontNumber, fontSize) == FALSE) |
fontNumber = applFont; |
viewRect = qd.screenBits.bounds; |
viewRect.top += (GetMBarHeight() * 2); |
viewRect.bottom -= 4; |
viewRect.left += 4; |
viewRect.right = (width(viewRect) / 2); |
gMainWindow = NewWindow( |
NULL, |
&viewRect, |
"\pSCSI Scan Bus Sample", |
TRUE, |
zoomDocProc, |
(WindowPtr) -1L, |
TRUE, /* Has GoAway box */ |
0 /* No refCon */ |
); |
if (gMainWindow == NULL) { |
SysBeep(10); |
ExitToShell(); |
} |
SetPort(gMainWindow); |
viewRect = gMainWindow->portRect; |
viewRect.right -= kScrollBarOffset; |
viewRect.bottom -= kScrollBarOffset; |
gLogListHandle = CreateLog( |
&viewRect, |
fontNumber, |
fontSize, |
kLogLines |
); |
if (gLogListHandle == NULL) { |
SysBeep(10); |
ExitToShell(); |
} |
} |
void |
EventLoop(void) |
{ |
long menuChoice; |
register WindowPtr theWindow; |
GrafPtr savePort; |
Boolean isActivating; |
if (gUpdateMenusNeeded) { |
gUpdateMenusNeeded = FALSE; |
AdjustMenus(); |
} |
WaitNextEvent( |
everyEvent, |
&EVENT, |
(gInForeground) ? 10L : 60L, |
NULL |
); |
theWindow = FrontWindow(); |
switch (EVENT.what) { |
case nullEvent: |
break; |
case keyDown: |
case autoKey: |
if ((EVENT.message & charCodeMask) == '.' |
&& (EVENT.modifiers & cmdKey) != 0) { |
FlushEvents(keyDown | autoKey, 0); |
gQuitNow = TRUE; |
} |
else if ((EVENT.modifiers & cmdKey) != 0) { |
if (EVENT.what == keyDown) { |
menuChoice = MenuKey(EVENT.message & charCodeMask); |
if (HiWord(menuChoice) != 0) |
DoCommand(theWindow, menuChoice); |
else if (IsOurWindow(theWindow)) { |
DoWindowKeyDown(theWindow); |
} |
} |
} |
else if (IsOurWindow(theWindow)) { |
DoWindowKeyDown(theWindow); |
} |
break; |
case mouseDown: |
DoMouseEvent(); |
break; |
case updateEvt: |
theWindow = (WindowPtr) EVENT.message; |
GetPort(&savePort); |
SetPort(theWindow); |
BeginUpdate(theWindow); |
EraseRect(&theWindow->portRect); |
DrawControls(theWindow); |
DrawGrowIcon(theWindow); |
if (IsOurWindow(theWindow)) |
DrawWindow(theWindow); |
EndUpdate(theWindow); |
SetPort(savePort); |
break; |
case activateEvt: |
theWindow = (WindowPtr) EVENT.message; |
isActivating = ((EVENT.modifiers & activeFlag) != 0); |
goto activateEvent; |
break; |
case osEvt: |
switch (((unsigned long) EVENT.message) >> 24) { |
case mouseMovedMessage: |
break; |
case suspendResumeMessage: |
isActivating = ((EVENT.message & 0x01) != 0); |
activateEvent: if (isActivating) { |
/* |
* Activate this window. Activate events define theWindow |
* from the event record, while suspend/resume uses the |
* pre-set FrontWindow value. |
*/ |
SelectWindow(theWindow); |
(void) TEFromScrap(); |
} |
if (IsOurWindow(theWindow) && gLogListHandle != NULL) |
LActivate(isActivating, gLogListHandle); |
else { |
/* Desk accessory or what? */ |
} |
gInForeground = isActivating; |
gUpdateMenusNeeded = TRUE; |
break; |
} |
break; |
} |
} |
/* |
* DoMouseEvent |
* The user clicked on something. Handle application-wide processing here, or call |
* a Catalog Browser function for specific action. |
*/ |
void |
DoMouseEvent(void) |
{ |
WindowPtr theWindow; |
short whichPart; |
whichPart = FindWindow(EVENT.where, &theWindow); |
if (theWindow == NULL) |
theWindow = FrontWindow(); |
if (whichPart == inMenuBar && IsOurWindow(theWindow) == FALSE) |
theWindow = FrontWindow(); |
switch (whichPart) { |
case inDesk: |
break; |
case inMenuBar: |
InitCursor(); |
DoCommand(theWindow, MenuSelect(EVENT.where)); |
break; |
case inDrag: |
DragWindow(theWindow, EVENT.where, &qd.screenBits.bounds); |
break; |
case inGoAway: |
if (TrackGoAway(theWindow, EVENT.where)) { |
if (IsOurWindow(theWindow)) { |
/* |
* Not quite so simple: we need to handle open files, too. |
*/ |
gQuitNow = TRUE; |
} |
} |
break; |
case inZoomIn: |
case inZoomOut: |
if (IsOurWindow(theWindow) |
&& TrackBox(theWindow, EVENT.where, whichPart)) { |
DoZoomWindow(theWindow, whichPart); |
goto resizeWindow; |
} |
break; |
case inGrow: |
if (IsOurWindow(theWindow)) { |
if (DoGrowWindow( |
theWindow, |
EVENT.where, |
kMinWindowWidth, |
kMinWindowHeight |
)) { |
resizeWindow: DecorateDisplay(theWindow, TRUE); |
} |
} |
break; |
case inContent: |
if (theWindow != FrontWindow()) |
SelectWindow(theWindow); |
else if (IsOurWindow(theWindow)) { |
DoContentClick(theWindow); |
} |
else { |
/* Nothing happens here */ |
} |
break; |
default: |
break; |
} |
/* |
* Do not touch theWindow here. |
*/ |
} |
void |
DoContentClick( |
WindowPtr theWindow |
) |
{ |
if (0) { /* Touch unused variables */ |
theWindow; |
} |
DoClickInLog(gLogListHandle, &EVENT); |
} |
void |
DoWindowKeyDown( |
WindowPtr theWindow |
) |
{ |
if (0) { /* Touch unused variables */ |
theWindow; |
} |
/* Nothing happens here */ |
} |
void |
DrawWindow( |
WindowPtr theWindow |
) |
{ |
if (0) { /* Touch unused variables */ |
theWindow; |
} |
UpdateLog(gLogListHandle); |
} |
void |
DecorateDisplay( |
WindowPtr theWindow, |
Boolean redraw |
) |
{ |
Rect viewRect; |
if (0) { /* Touch unused variables */ |
redraw; |
} |
viewRect = theWindow->portRect; |
viewRect.right -= kScrollBarOffset; |
viewRect.bottom -= kScrollBarOffset; |
if (gLogListHandle != NULL) { |
MoveLog(gLogListHandle, viewRect.left, viewRect.top); |
SizeLog(gLogListHandle, width(viewRect), height(viewRect)); |
} |
} |
void |
DoCommand( |
WindowPtr theWindow, |
long menuChoice |
) |
{ |
short menuItem; |
Str255 menuText; |
GrafPtr savePort; |
OSErr status; |
Boolean useAsynchManager; |
menuItem = LoWord(menuChoice); |
switch (HiWord(menuChoice)) { |
case MENU_Apple: |
if (menuItem == kAppleAbout) |
DoAbout(); |
else { |
GetItem(gAppleMenu, menuItem, menuText); |
AdjustEditMenu(TRUE); |
GetPort(&savePort); |
OpenDeskAcc(menuText); |
SetPort(savePort); |
AdjustEditMenu(IsOurWindow(theWindow) == FALSE); |
} |
break; |
case MENU_File: |
switch (menuItem) { |
case kFileCreateLogFile: |
status = SaveLogFile( |
gLogListHandle, |
"\pSave Log", |
"\pSCSI Test Log", |
'ttxt' |
); |
break; |
case kFileCloseLogFile: |
status = CloseLogFile(gLogListHandle); |
break; |
case kFilePageSetup: |
DoPageSetup(); |
break; |
case kFilePrint: |
PrintLog(gLogListHandle, gPrintHandle); |
break; |
case kFileDebug: |
Debugger(); |
break; |
case kFileQuit: |
gQuitNow = TRUE; |
break; |
} |
break; |
case MENU_Test: |
switch (menuItem) { |
case kTestEnableNewManager: |
/* |
* Note that this menu option is disabled if the asynchronous |
* SCSI Manager is not present. This means that, if it is |
* not present at application start, it can't be enabled later. |
*/ |
gEnableNewSCSIManager = (!gEnableNewSCSIManager); |
if (gEnableNewSCSIManager) |
gCurrentDevice.bus = gOldHostBusID; |
else { |
gOldHostBusID = gCurrentDevice.bus; |
gCurrentDevice.bus = 0; |
} |
gUpdateMenusNeeded = TRUE; |
break; |
case kTestEnableAllLogicalUnits: |
/* |
* The ROM SCSI Manager on the Quadra 660-AV and 840-AV has |
* a bug that will hang the machine if it tries to access |
* a non-zero logical unit. This menu option makes that error |
* harder to elicit. |
*/ |
gMaxLogicalUnit = (gMaxLogicalUnit == 0) ? 7 : 0; |
if (gCurrentDevice.LUN > gMaxLogicalUnit) |
gCurrentDevice.LUN = gMaxLogicalUnit; |
gUpdateMenusNeeded = TRUE; |
break; |
case kTestEnableSelectWithATN: |
gEnableSelectWithATN = !gEnableSelectWithATN; |
gUpdateMenusNeeded = TRUE; |
break; |
case kTestDoDisconnect: |
gDoDisconnect = !gDoDisconnect; |
gUpdateMenusNeeded = TRUE; |
break; |
case kTestDontDisconnect: |
gDontDisconnect = !gDontDisconnect; |
gUpdateMenusNeeded = TRUE; |
break; |
case kTestVerboseDisplay: |
gVerboseDisplay = (!gVerboseDisplay); |
gUpdateMenusNeeded = TRUE; |
break; |
case kTestListSCSIDevices: |
DoListSCSIDevices(); |
break; |
case kTestGetDriveInfo: |
status = SCSIBusAPI(gCurrentDevice, &useAsynchManager); |
if (status != noErr) |
useAsynchManager = FALSE; |
DoGetDriveInfo(gCurrentDevice, FALSE, useAsynchManager); |
break; |
case kTestUnitReady: |
DoTestUnitReady(gCurrentDevice); |
break; |
case kTestReadBlockZero: |
DoReadBlockZero(gCurrentDevice); |
break; |
default: |
break; |
} |
break; |
case MENU_CurrentBus: |
gCurrentDevice.bus = menuItem - 1; |
gUpdateMenusNeeded = TRUE; |
break; |
case MENU_CurrentTarget: |
gCurrentDevice.targetID = menuItem - 1; |
gUpdateMenusNeeded = TRUE; |
break; |
case MENU_CurrentLUN: |
gCurrentDevice.LUN = menuItem - 1; |
gUpdateMenusNeeded = TRUE; |
break; |
} |
HiliteMenu(0); |
} |
void |
SetupEverything() |
{ |
int i; |
MaxApplZone(); |
InitGraf(&qd.thePort); |
InitFonts(); |
InitWindows(); |
InitMenus(); |
TEInit(); |
InitDialogs(0); |
for (i = 0; i < 8; i++) |
MoreMasters(); |
HNoPurge((Handle) GetCursor(watchCursor)); |
SetCursor(*GetCursor(watchCursor)); |
SetupMenus(); |
} |
void |
SetupMenus() |
{ |
register Handle menuBarHdl; |
/* |
* We ought to do some error checking here. |
*/ |
menuBarHdl = GetNewMBar(MBAR_MenuBar); |
SetMenuBar(menuBarHdl); |
gAppleMenu = GetMHandle(MENU_Apple); |
AddResMenu(gAppleMenu, 'DRVR'); |
gFileMenu = GetMHandle(MENU_File); |
gEditMenu = GetMHandle(MENU_Edit); |
gTestMenu = GetMHandle(MENU_Test); |
gCurrentBusMenu = GetMHandle(MENU_CurrentBus); |
gCurrentTargetMenu = GetMHandle(MENU_CurrentTarget); |
gCurrentLUNMenu = GetMHandle(MENU_CurrentLUN); |
DrawMenuBar(); |
gUpdateMenusNeeded = TRUE; |
} |
void |
AdjustMenus(void) |
{ |
short i; |
short nItems; |
unsigned short maxTarget; |
unsigned short lastHostBus; |
OSErr status; |
EnableItem(gFileMenu, kFileQuit); |
EnableItem(gFileMenu, kFileDebug); |
if (IsOurWindow(FrontWindow())) { |
EnableItem(gFileMenu, kFilePageSetup); |
EnableItem(gFileMenu, kFilePrint); |
EnableItem(gTestMenu, kTestListSCSIDevices); |
EnableItem(gTestMenu, kTestGetDriveInfo); |
EnableItem(gTestMenu, kTestUnitReady); |
EnableItem(gTestMenu, kTestVerboseDisplay); |
CheckItem(gTestMenu, kTestVerboseDisplay, gVerboseDisplay); |
EnableItem(gTestMenu, kTestEnableAllLogicalUnits); |
CheckItem(gTestMenu, kTestEnableAllLogicalUnits, (gMaxLogicalUnit == 7)); |
if (AsyncSCSIPresent()) { |
EnableItem(gTestMenu, kTestEnableNewManager); |
} |
else { |
DisableItem(gTestMenu, kTestEnableNewManager); |
} |
if (gEnableNewSCSIManager) { |
EnableItem(gCurrentBusMenu, 0); |
EnableItem(gTestMenu, kTestEnableSelectWithATN); |
EnableItem(gTestMenu, kTestDoDisconnect); |
EnableItem(gTestMenu, kTestDontDisconnect); |
} |
else { |
DisableItem(gCurrentBusMenu, 0); |
DisableItem(gTestMenu, kTestEnableSelectWithATN); |
DisableItem(gTestMenu, kTestDoDisconnect); |
DisableItem(gTestMenu, kTestDontDisconnect); |
} |
CheckItem(gTestMenu, kTestEnableNewManager, gEnableNewSCSIManager); |
CheckItem(gTestMenu, kTestEnableSelectWithATN, gEnableSelectWithATN); |
CheckItem(gTestMenu, kTestDoDisconnect, gDoDisconnect); |
CheckItem(gTestMenu, kTestDontDisconnect, gDontDisconnect); |
EnableItem(gTestMenu, kTestEnableAllLogicalUnits); |
CheckItem(gTestMenu, kTestEnableAllLogicalUnits, (gMaxLogicalUnit == 7)); |
/* */ |
status = SCSIGetMaxTargetID(gCurrentDevice, &maxTarget); |
if (status != noErr) |
maxTarget = 7; |
nItems = CountMItems(gCurrentTargetMenu); |
for (i = 1; i <= nItems; i++) { |
if ((i - 1) <= maxTarget) |
EnableItem(gCurrentTargetMenu, i); |
else { |
DisableItem(gCurrentTargetMenu, i); |
} |
} |
for (i = 1; i <= nItems; i++) |
CheckItem(gCurrentTargetMenu, i, (gCurrentDevice.targetID == (i - 1)) ? TRUE : FALSE); |
status = SCSIGetHighHostBusAdaptor(&lastHostBus); |
nItems = CountMItems(gCurrentBusMenu); |
for (i = 1; i <= nItems; i++) { |
if ((i - 1) <= lastHostBus) |
EnableItem(gCurrentBusMenu, i); |
else { |
DisableItem(gCurrentBusMenu, i); |
} |
} |
for (i = 1; i <= nItems; i++) |
CheckItem(gCurrentBusMenu, i, (gCurrentDevice.bus == (i - 1)) ? TRUE : FALSE); |
nItems = CountMItems(gCurrentLUNMenu); |
for (i = 1; i <= nItems; i++) { |
if ((i - 1) <= gMaxLogicalUnit) |
EnableItem(gCurrentLUNMenu, i); |
else { |
DisableItem(gCurrentLUNMenu, i); |
} |
CheckItem(gCurrentLUNMenu, i, (gCurrentDevice.LUN == (i - 1)) ? TRUE : FALSE); |
} |
/* */ |
if (HasLogFile(gLogListHandle)) { |
EnableItem(gFileMenu, kFileCloseLogFile); |
DisableItem(gFileMenu, kFileCreateLogFile); |
} |
else { |
EnableItem(gFileMenu, kFileCreateLogFile); |
DisableItem(gFileMenu, kFileCloseLogFile); |
} |
} |
AdjustEditMenu(IsOurWindow(FrontWindow()) == FALSE); |
} |
/* |
* AdjustEditMenu |
* Enable/disable Edit Menu options. |
*/ |
void |
AdjustEditMenu( |
Boolean isDeskAcc |
) |
{ |
if (isDeskAcc) { |
EnableItem(gEditMenu, kEditUndo); |
EnableItem(gEditMenu, kEditCut); |
EnableItem(gEditMenu, kEditCopy); |
EnableItem(gEditMenu, kEditPaste); |
EnableItem(gEditMenu, kEditClear); |
} |
else { |
DisableItem(gEditMenu, kEditUndo); |
DisableItem(gEditMenu, kEditCut); |
DisableItem(gEditMenu, kEditCopy); |
DisableItem(gEditMenu, kEditPaste); |
DisableItem(gEditMenu, kEditClear); |
} |
} |
void |
DoAbout() |
{ |
GrafPtr savePort; |
DialogPtr dialog; |
short item; |
GetPort(&savePort); |
dialog = GetNewDialog(DLOG_About, NULL, (WindowPtr) -1L); |
ShowWindow(dialog); |
SetPort(dialog); |
ModalDialog(NULL, &item); |
DisposDialog(dialog); |
SetPort(savePort); |
} |
void |
HexToString( |
unsigned long value, |
short hexDigits, |
Str255 result |
) |
{ |
register unsigned short digit; |
register char *text; |
text = (char *) result; |
text[0] = hexDigits; |
for (; hexDigits > 0; --hexDigits) { |
digit = value & 0xF; |
if (digit >= 10) |
text[hexDigits] = digit - 10 + 'a'; |
else { |
text[hexDigits] = digit + '0'; |
} |
value >>= 4; |
} |
} |
Boolean |
HexToNum( |
ConstStr255Param hexString, |
unsigned long *result |
) |
{ |
register short i; |
register unsigned short digit; |
*result = 0; |
for (i = 1; i <= hexString[0]; i++) { |
digit = hexString[i]; |
if (digit >= '0' && digit <= '9') |
digit -= '0'; |
else if (digit >= 'a' && digit <= 'f') |
digit = digit - 'a' + 10; |
else if (digit >= 'A' && digit <= 'F') |
digit = digit - 'A' + 10; |
else { |
return (FALSE); |
} |
*result <<= 4; |
*result |= digit; |
} |
return (TRUE); |
} |
void |
DoPageSetup(void) |
{ |
PrOpen(); |
if (PrError() == noErr) { |
if (gPrintHandle == NULL) { |
gPrintHandle = (THPrint) NewHandle(sizeof (TPrint)); |
if (gPrintHandle != NULL) |
PrintDefault(gPrintHandle); |
} |
if (gPrintHandle != NULL) |
(void) PrStlDialog(gPrintHandle); |
PrClose(); |
} |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14