/* * DiskSpeed v3.0 * by * Michael Sinz * * Copyright (c) 1989 by MKSoft Development * * MKSoft Development * 163 Appledore Drive * Downingtown, PA 19335 * * Yes, this is yet another disk speed testing program, but with a few * differences. It was designed to give the most accurate results of the * true disk performance in the system. For this reason many of * DiskSpeed's results may look either lower or higher than current disk * performance tests. * * This program was thrown together in a few hours because I needed more * accurate and consistent results for disk performance as seen from the * application's standpoint. This program has now served its purpose and * I am now giving it to the rest of the Amiga world to play with as long * as all of the files remain together in unmodified form. (That is, the * files DiskSpeed, DiskSpeed.info, DiskSpeed.c, DiskSpeedWindow.c, * DiskSpeedWindow.h, MakeBoxes.c, MakeBoxes.h, StandardGadgets.c, * StandardGadgets.h, RenderInfo.c, RenderInfo.h, DiskSpeed.doc, and * MakeFile) * * Version 2.0 of this program added a few features and cleaned up the * user interface. I hope you like this... * * Version 3.0 of this program added the performance stress and cleaned up * some parts of the older code. (Fix to RenderInfo.c) * ****************************************************************************** * * * Reading legal mush can turn your brain into guacamole! * * * * So here is some of that legal mush: * * * * Permission is hereby granted to distribute this program's source * * executable, and documentation for non-commercial purposes, so long as the * * copyright notices are not removed from the sources, executable or * * documentation. This program may not be distributed for a profit without * * the express written consent of the author Michael Sinz. * * * * This program is not in the public domain. * * * * Fred Fish is expressly granted permission to distribute this program's * * source and executable as part of the "Fred Fish freely redistributable * * Amiga software library." * * * * Permission is expressly granted for this program and it's source to be * * distributed as part of the Amicus Amiga software disks, and the * * First Amiga User Group's Hot Mix disks. * * * ****************************************************************************** * * Main code and testing sections... */ #include #include #include #include #include #include #include #include #include #include "RenderInfo.h" #include "DiskSpeedWindow.h" extern struct IntuitionBase *IntuitionBase; extern struct GfxBase *GfxBase; struct Library *TimerBase; #define TIMESCALER 256L #define SEEK_READ_SIZE 300L #define IO_BUFFER_SIZE 262144L /* Define the file name limits for file create/delete/open/scan */ #define FINAL 'R' static char ErrorText1[28] ="Can't create test directory"; static char ErrorText2[16] ="Bad device name"; static char ErrorText3[24] ="Can't open results file"; static char ErrorText4[19] ="Can't open printer"; static char PrinterFile[5] ="PRT:"; static char ResultFile[18] ="DiskSpeed.Results"; static char DirectoryName[22] =" Disk Test Directory "; static char FileNameRoot[22] =" -- DiskTest File -- "; static char Testing_String[10] =">Testing<"; /* The Wait pointer I use... */ USHORT __chip WaitPointer[48] = { 0x0000, 0x0000, 0x6700, 0xC700, 0xCFA0, 0xCFA0, 0xBFF0, 0x3FF0, 0x70F8, 0x7FF8, 0x7DFC, 0x7FFC, 0xFBFC, 0xFFFC, 0x70FC, 0x7FFC, 0x7FFE, 0x7FFE, 0x7F0E, 0x7FFE, 0x3FDF, 0x3FFF, 0x7FBE, 0x7FFE, 0x3F0E, 0x3FFE, 0x1FFC, 0x1FFC, 0x07F8, 0x07F8, 0x01E0, 0x01E0, 0x0780, 0x0780, 0x0FE0, 0x0FE0, 0x0740, 0x0740, 0x0000, 0x0000, 0x0070, 0x0070, 0x0078, 0x0078, 0x0030, 0x0030, 0x0000, 0x0000, }; /* * These two defines set up and clear the WaitPointer... */ #define SetWait(x) SetPointer(x,WaitPointer,22L,16L,NULL,NULL) #define ClearWait(x) ClearPointer(x) /* * This does a requester on the window to tell the user something... */ VOID TellUser(struct MyWindow *MyWindow,char *Text) { register struct IntuiMessage *msg; register SHORT flag=TRUE; MyWindow->ReqIText.LeftEdge=(MyWindow->Req.Width>>1)-(strlen(Text)<<2); MyWindow->ReqIText.IText=Text; Request(&(MyWindow->Req),MyWindow->Window); while (flag) { WaitPort(MyWindow->Window->UserPort); while (msg=(struct IntuiMessage *)GetMsg(MyWindow->Window->UserPort)) { if (msg->Class==GADGETUP) { if (((struct Gadget *)(msg->IAddress))->GadgetID==GADGET_REQ) flag=FALSE; } ReplyMsg((struct Message *)msg); } } EndRequest(&(MyWindow->Req),MyWindow->Window); } /* * Returns FALSE if the user clicked on the CLOSE gadget... */ SHORT Check_Quit(struct MyWindow *MyWindow) { register struct IntuiMessage *msg; register SHORT flag=TRUE; while(msg=(struct IntuiMessage *)GetMsg(MyWindow->Window->UserPort)) { if (msg->Class==CLOSEWINDOW) flag=FALSE; ReplyMsg((struct Message *)msg); } return(flag); } /* * Clears a string entry to spaces... */ VOID Clear_Entry(char *String) { register SHORT t; for (t=0;t<9;t++) String[t]=' '; String[9]='\0'; } /* * Sets a string entry to the string >Testing< and does a * PrintIText() to display it... */ VOID Set_Testing(SHORT ResultNum,struct MyWindow *MyWindow) { strcpy(MyWindow->MyResults[ResultNum].text,Testing_String); PrintIText(MyWindow->Window->RPort,&(MyWindow->MyResults[ResultNum].IntuiText),NULL,NULL); } /* * Sets a string entry to the value passed and does a PrintIText() * to display it... */ VOID Set_Entry(SHORT ResultNum,LONG Value,struct MyWindow *MyWindow) { register SHORT t; register SHORT tmp; register char *String; String=MyWindow->MyResults[ResultNum].text; Clear_Entry(String); t=9; while (Value) { tmp=Value%10; Value=Value/10; String[--t]=(char)(tmp)+'0'; } if (!String[t]) String[--t]='0'; PrintIText(MyWindow->Window->RPort,&(MyWindow->MyResults[ResultNum].IntuiText),NULL,NULL); } /* * This gets the starting time... */ VOID Timer_Start(struct MyWindow *MyWindow) { register struct timerequest *Time_Req; Time_Req=&(MyWindow->TimeReq); Time_Req->tr_node.io_Command=TR_GETSYSTIME; Time_Req->tr_node.io_Flags=IOF_QUICK; DoIO((struct IORequest *)Time_Req); MyWindow->StartTime=Time_Req->tr_time; } /* * This gets the ending time and finds out what the per second speed is... * It also does a RefreshGadgets() to display the text... */ VOID Timer_Stop(struct MyWindow *MyWindow,SHORT ResultNum,LONG Number) { register struct timerequest *Time_Req; register LONG Value; Time_Req=&(MyWindow->TimeReq); Time_Req->tr_node.io_Command=TR_GETSYSTIME; Time_Req->tr_node.io_Flags=IOF_QUICK; DoIO((struct IORequest *)Time_Req); MyWindow->StopTime=Time_Req->tr_time; SubTime(&(MyWindow->StopTime),&(MyWindow->StartTime)); /* Now calculate Value based on Number and the time... */ Value=(Number*TIMESCALER) / ( (MyWindow->StopTime.tv_secs*TIMESCALER) + (MyWindow->StopTime.tv_micro/(1000000L/TIMESCALER)) ); Set_Entry(ResultNum,Value,MyWindow); } /* * File create test... * This creates a bunch of files in our test directory... * The delete test deletes these files... */ VOID Do_FileCreate_Test(struct MyWindow *MyWindow) { register char *t1; register char *t2; register BPTR file; register LONG count=0; t1=FileNameRoot+1; t2=t1+1; Set_Testing(RESULTS_CREATE,MyWindow); Timer_Start(MyWindow); for (*t1='A';*t1>1),OFFSET_CURRENT); Read(bigfile,Buffer,SEEK_READ_SIZE); count++; } Timer_Stop(MyWindow,RESULTS_SEEK_READ,count); Close(bigfile); DeleteFile(FileNameRoot); } } /* * This does the testing at a set buffer size... */ SHORT Do_File_Test(LONG BufSize,struct MyWindow *MyWindow,UBYTE *Buffer,SHORT ResultNum) { register SHORT flag=TRUE; register SHORT t; register SHORT loop; register LONG count; register LONG numblocks; register BPTR bigfile; if (bigfile=Open(FileNameRoot,MODE_NEWFILE)) { numblocks=IO_BUFFER_SIZE/BufSize; if (flag&=Check_Quit(MyWindow)) { count=0; Set_Testing(ResultNum,MyWindow); Timer_Start(MyWindow); for (t=0;t<(1<<(MyWindow->TestFlag));t++) { Close(bigfile); bigfile=Open(FileNameRoot,MODE_NEWFILE); for (loop=0;loopTestFlag));t++) { Seek(bigfile,NULL,OFFSET_BEGINNING); for (loop=0;loopTestFlag));t++) { Seek(bigfile,NULL,OFFSET_BEGINNING); for (loop=0;loopMyGadgets[loop].Gadget); RemoveGadget(MyWindow->Window,gad); gad->Flags|=GADGDISABLED; AddGadget(MyWindow->Window,gad,NULL); RefreshGList(gad,MyWindow->Window,NULL,1L); } if (lock=Lock(MyWindow->DeviceName,ACCESS_READ)) { lock=CurrentDir(lock); if (mydir=CreateDir(DirectoryName)) { mydir=CurrentDir(mydir); for (loop=0;loopMyResults[loop].text); } RefreshGList(&(MyWindow->Detail),MyWindow->Window,NULL,1L); Stress_On(MyWindow); if (flag&=Check_Quit(MyWindow)) { Do_FileCreate_Test(MyWindow); if (flag&=Check_Quit(MyWindow)) Do_OpenClose_Test(MyWindow); if (flag&=Check_Quit(MyWindow)) Do_DirScan_Test(MyWindow); Do_FileDelete_Test(MyWindow); } if (Buffer=AllocMem(IO_BUFFER_SIZE,MEMF_PUBLIC)) { if (flag&=Check_Quit(MyWindow)) Do_SeekRead_Test(MyWindow,Buffer); if (flag&=Check_Quit(MyWindow)) flag&=Do_File_Test(512L,MyWindow,Buffer,RESULTS_512_CREATE); if (flag&=Check_Quit(MyWindow)) flag&=Do_File_Test(4096L,MyWindow,Buffer,RESULTS_4096_CREATE); if (flag&=Check_Quit(MyWindow)) flag&=Do_File_Test(32768L,MyWindow,Buffer,RESULTS_32768_CREATE); if (flag&=Check_Quit(MyWindow)) flag&=Do_File_Test(262144L,MyWindow,Buffer,RESULTS_262144_CREATE); FreeMem(Buffer,IO_BUFFER_SIZE); } Stress_Off(MyWindow); mydir=CurrentDir(mydir); UnLock(mydir); DeleteFile(DirectoryName); } else { /* Tell user he messed up... */ TellUser(MyWindow,ErrorText1); } lock=CurrentDir(lock); UnLock(lock); } else { /* Tell user he messed up... */ TellUser(MyWindow,ErrorText2); } for (loop=0;loopMyGadgets[loop].Gadget); RemoveGadget(MyWindow->Window,gad); gad->Flags&=~GADGDISABLED; AddGadget(MyWindow->Window,gad,NULL); } RefreshGadgets(gad,MyWindow->Window,NULL); } /* * This function will open the file, append to the end of it the * test results and close it... */ VOID Save_To_File(struct MyWindow *MyWindow) { register BPTR TheFile; TheFile=Open(ResultFile,MODE_OLDFILE); if (!TheFile) TheFile=Open(ResultFile,MODE_NEWFILE); if (TheFile) { Seek(TheFile,0L,OFFSET_END); Write_Results(MyWindow,TheFile); Close(TheFile); } else { /* Tell the user the file did not open... */ TellUser(MyWindow,ErrorText3); } } /* * This function will open the printer, append to the end of it the * test results and close it... */ VOID Save_To_Printer(struct MyWindow *MyWindow) { register BPTR TheFile; if (TheFile=Open(PrinterFile,MODE_NEWFILE)) { Write_Results(MyWindow,TheFile); Close(TheFile); } else { /* Tell the user the file did not open... */ TellUser(MyWindow,ErrorText4); } } VOID main(VOID) { register struct MyWindow *MyWindow; register struct Window *Window; register struct IntuiMessage *msg; register struct Gadget *gad; register struct timerequest *Time_Req; register SHORT QuitFlag=0; register struct Process *pr; register APTR Old_WindowPtr; register SHORT loop; register LONG oldpri; struct RenderInfo RenderInfo; pr=(struct Process *)FindTask(NULL); Old_WindowPtr=pr->pr_WindowPtr; pr->pr_WindowPtr=(APTR)(-1); oldpri=SetTaskPri((struct Task *)pr,1L); if (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",33L)) { if (GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",33L)) { FillIn_RenderInfo(&RenderInfo); if (MyWindow=OpenMyWindow(&RenderInfo)) { Window=MyWindow->Window; Time_Req=&(MyWindow->TimeReq); if (!OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)Time_Req,NULL)) { Time_Req->tr_node.io_Message.mn_ReplyPort=Window->UserPort; TimerBase=(struct Library *)Time_Req->tr_node.io_Device; while (!QuitFlag) { WaitPort(Window->UserPort); if (msg=(struct IntuiMessage *)GetMsg(Window->UserPort)) { if (msg->Class==CLOSEWINDOW) QuitFlag=TRUE; else if (msg->Class==ACTIVEWINDOW) ActivateGadget(&(MyWindow->DeviceGadget),Window,NULL); else if (msg->Class==GADGETDOWN) { gad=(struct Gadget *)msg->IAddress; if (gad->Flags & SELECTED) { MyWindow->TestFlag=gad->GadgetID; for (loop=0;loop<3;loop++) { gad=&(MyWindow->MyGadgets[loop].Gadget); if (MyWindow->TestFlag!=gad->GadgetID) { if (gad->Flags & SELECTED) { RemoveGadget(Window,gad); gad->Flags&=~SELECTED; AddGadget(Window,gad,NULL); RefreshGList(gad,Window,NULL,1L); } } } } else { RemoveGadget(Window,gad); gad->Flags|=SELECTED; AddGadget(Window,gad,NULL); RefreshGList(gad,Window,NULL,1L); } } else if (msg->Class==GADGETUP) { SetWait(Window); gad=(struct Gadget *)msg->IAddress; switch (gad->GadgetID) { case GADGET_STRING: ActivateGadget((struct Gadget *)gad->UserData,Window,NULL); break; case GADGET_START: Do_Disk_Test(MyWindow); break; case GADGET_SAVE: Save_To_File(MyWindow); break; case GADGET_PRINT: Save_To_Printer(MyWindow); break; } ClearWait(Window); } ReplyMsg((struct Message *)msg); } } CloseDevice((struct IORequest *)Time_Req); } CloseMyWindow(MyWindow); } CloseLibrary((struct Library *)GfxBase); } CloseLibrary((struct Library *)IntuitionBase); } oldpri=SetTaskPri((struct Task *)pr,oldpri); pr->pr_WindowPtr=Old_WindowPtr; }