#include #include #include #include #include #include #include #include #include #include /* Lhwarp version 1.03 */ #define MAJOR_VERSION 1 #define MINOR_VERSION 0 #define DECIMAL_VERSION 3 #define NUM_HEADS 2 #define TRACK_SIZE (TD_SECTOR * NUMSECS * NUM_HEADS) #define SEEK_SET 0 #define WARP_READ 1 #define WARP_WRITE 2 #define IN_BUFFER_SIZE 16384 #define OUT_BUFFER_SIZE 16384 /* Only LZHUF is supported at the moment */ #define COMPTYPE_LHARC 0 /* Note, this has changed! */ #define DATATYPE_NORMAL 0 #define DATATYPE_RAW 1 struct WarpHeader { UBYTE MajorVersion; UBYTE MinorVersion; UBYTE DecimalVersion; UBYTE Reserved; USHORT StartTrack; USHORT EndTrack; ULONG TextLength; ULONG CompressedTextLength; }; struct CompHeader101 { UBYTE CompressionType; UBYTE DataType; UBYTE TrackNumber; UBYTE Unused; ULONG FullLength; ULONG CompressedLength; }; struct CompHeader102 { UBYTE CompressionType; UBYTE DataType; UBYTE TrackNumber; UBYTE Unused; ULONG FullLength; ULONG CompressedLength; ULONG CheckSum; }; #define LABEL_LENGTH (16 * NUMSECS * NUM_HEADS) UBYTE *iotd_SecLabel = NULL; struct WarpHeader WHeader; struct IOExtTD *ReadMsg = NULL; struct IOExtTD *WriteMsg = NULL; struct MsgPort *ReadPort = NULL; struct MsgPort *WritePort = NULL; extern FILE *infile; extern FILE *outfile; extern UBYTE *FilePosition; extern UBYTE *EndOfFilePosition; extern UBYTE *PutFilePosition; /* LZHUF defines and externs */ #define N 4096 /* Size of string buffer */ #define F 60 /* Size of look-ahead buffer */ #define THRESHOLD 2 #define NIL N /* End of tree's node */ extern unsigned char *text_buf; extern short *lson, *rson, *dad; struct CompHeader101 CHeader101; struct CompHeader102 CHeader102; char FileName[256]; char TextFileName[256]; UBYTE Command; UBYTE AppendTextFile; UBYTE Version101; BPTR FHandle; ULONG StartTrack; ULONG EndTrack; ULONG Unit; APTR DataBlock = NULL; APTR NewBlock = NULL; APTR TrackdiskBlock = NULL; ULONG GetFileLength(register char *FileToOpen); ULONG DoSum(UBYTE *Block, ULONG Length); void __regargs Decode(ULONG Size); void main(int argc, char **argv) { if (argc != 2 && argc != 4 && argc != 6 && argc != 7) { Title(); exit (1); } if (!stricmp(argv[1], "READ")) { /* Remove the file if it was already there */ remove(FileName); Command = WARP_READ; } else if (!stricmp(argv[1], "WRITE")) { Command = WARP_WRITE; } else if (!stricmp(argv[1], "HELP")) { exit(0); } else { puts("\nUnknown command\n"); exit(1); } if (argc < 6 && Command == WARP_READ) { Title(); exit (1); } if (argc == 7) { strcpy(TextFileName, argv[6]); AppendTextFile = 1; } else { AppendTextFile = 0; } /* Get the unit number */ Unit = atoi(argv[2]); /* Get the file name */ strcpy(FileName, argv[3]); strupr(FileName); /* Append .LHW if necessary */ if (strcmp(FileName, ".LHW")) { if (strlen(FileName) > 4) { if (strcmp(&FileName[strlen(FileName)-4], ".LHW")) { strcat(FileName, ".LHW"); } } else { strcat(FileName, ".LHW"); } } /* Get the start and end tracks */ if (argc > 5) { StartTrack = atoi(argv[4]); EndTrack = atoi(argv[5]); } if (StartTrack > EndTrack) { puts("Start track is greater than end track\n"); exit (1); } Init(); if (Command == WARP_WRITE) { WriteData(); } else { ReadData(); } } Init() { text_buf = NULL; lson = NULL; rson = NULL; dad = NULL; if (!(ReadPort = CreatePort(0L, 0L))) { puts("Couldn't create read port"); exit (1); } if (!(WritePort = CreatePort(0L, 0L))) { puts("Couldn't create write port"); CleanUp(); exit (1); } if (!(ReadMsg = (struct IORequest *) CreateExtIO(ReadPort, (long) sizeof(struct IOExtTD)))) { puts("Couldn't create i/o read request"); CleanUp(); exit (1); } if (!(WriteMsg = (struct IORequest *) CreateExtIO(WritePort, (long) sizeof(struct IOExtTD)))) { puts("Couldn't create i/o write request"); CleanUp(); exit (1); } ReadMsg->iotd_Req.io_Command = ETD_READ; WriteMsg->iotd_Req.io_Command = ETD_WRITE; if (OpenDevice(TD_NAME, Unit, (struct IORequest *) ReadMsg, 0L)) { puts("Couldn't open trackdisk.device for reading"); CleanUp(); exit (1); } if (OpenDevice(TD_NAME, Unit, (struct IORequest *) WriteMsg, 0L)) { puts("Couldn't open trackdisk.device for writing"); CleanUp(); exit (1); } if (!(DataBlock = AllocMem((ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH, MEMF_PUBLIC))) { puts("Couldn't allocate trackdisk memory buffer"); CleanUp(); exit (1); } if (!(NewBlock = AllocMem((ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH, MEMF_PUBLIC))) { puts("Couldn't allocate trackdisk memory buffer"); CleanUp(); exit (1); } if (!(TrackdiskBlock = AllocMem((ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH, MEMF_CHIP))) { puts("Couldn't allocate trackdisk memory buffer"); CleanUp(); exit (1); } if (!(iotd_SecLabel = AllocMem((ULONG) LABEL_LENGTH, MEMF_CHIP))) { puts("Couldn't allocate trackdisk extended memory buffer"); CleanUp(); exit (1); } if (!(text_buf = AllocMem((ULONG) (N + F - 1), MEMF_PUBLIC))) { puts("Out of memory"); CleanUp(); exit (1); } if (!(lson = AllocMem((ULONG) (N + 1) * (ULONG) (sizeof(short)), MEMF_PUBLIC))) { puts("Out of memory"); CleanUp(); exit (1); } if (!(rson = AllocMem((ULONG) (N + 257) * (ULONG) (sizeof(short)), MEMF_PUBLIC))) { puts("Out of memory"); CleanUp(); exit (1); } if (!(dad = AllocMem((ULONG) (N + 1) * (ULONG) (sizeof(short)), MEMF_PUBLIC))) { puts("Out of memory"); CleanUp(); exit (1); } } Archive(USHORT Track, ULONG DataSize) { UBYTE *OutBuffer; UBYTE CanSetBuffer; ULONG CurrentPosition; ULONG AfterEncodeLength; ULONG TotalEncodeLength; BPTR outfp; if (OutBuffer = AllocMem((ULONG) OUT_BUFFER_SIZE, MEMF_PUBLIC)) { CanSetBuffer = 1; } else { CanSetBuffer = 0; } CurrentPosition = GetFileLength(FileName); /* Lhwarp to a file; this way, if the output is larger than the input */ /* we won't crash the machine */ if (!(outfile = fopen(FileName, "a+b"))) { printf("Couldn't open temporary file for output\n"); if (CanSetBuffer) { FreeMem(OutBuffer, (ULONG) OUT_BUFFER_SIZE); } CleanUp(); exit (1); } if (CanSetBuffer) { setvbuf(outfile, OutBuffer, _IOFBF, (long) OUT_BUFFER_SIZE); } /* Write out a dummy file compression header */ fwrite(&CHeader102, sizeof(struct CompHeader102), 1, outfile); Encode((ULONG) (DataSize)); fclose(outfile); if (CanSetBuffer) { FreeMem(OutBuffer, (ULONG) OUT_BUFFER_SIZE); } AfterEncodeLength = GetFileLength(FileName); TotalEncodeLength = AfterEncodeLength - CurrentPosition - sizeof(struct CompHeader102); if (!(outfp = (BPTR) Open(FileName, (long) MODE_READWRITE))) { printf("Couldn't open temporary file for output\n"); if (CanSetBuffer) { FreeMem(OutBuffer, (ULONG) OUT_BUFFER_SIZE); } CleanUp(); exit (1); } /* Seek back to the CompHeader section */ Seek((BPTR) outfp, (long) CurrentPosition, (long) OFFSET_BEGINNING); CHeader102.CompressedLength = TotalEncodeLength; CHeader102.FullLength = DataSize; CHeader102.TrackNumber = (UBYTE) Track; CHeader102.CompressionType = COMPTYPE_LHARC; CHeader102.DataType = DATATYPE_NORMAL; /* Checksum the block */ CHeader102.CheckSum = (ULONG) DoSum(NewBlock, (ULONG) CHeader102.FullLength); /* Write it to disk */ Write((BPTR) outfp, &CHeader102, (long) sizeof(struct CompHeader102)); /* Close the file */ Close((BPTR) outfp); } WriteData() { ULONG Track; UBYTE *TextMemory; UBYTE *TextCompMemory; UBYTE *ExtendedDataBlock; ULONG CheckSum; ULONG TracksWritten = 0L; printf("\nLHWARP %d.%d%d - Amiga disk tracker - Written by Jonathan Forbes @ 1:250/642\n", (UBYTE) MAJOR_VERSION, (UBYTE) MINOR_VERSION, (UBYTE) DECIMAL_VERSION); puts("Copyright © Xenomiga Technology, 1990.\n"); printf("Writing to disk in drive %ld from file %s\n", Unit, FileName); /* Set up the write request */ WriteMsg->iotd_Req.io_Command = ETD_FORMAT; if (!(infile = fopen(FileName, "r"))) { printf("Cannot open %s for input\n", FileName); CleanUp(); exit (1); } /* Read the Warp header */ fread(&WHeader, sizeof(struct WarpHeader), 1, infile); /* What version of Lhwarp was used to compress the disk? */ if (WHeader.MajorVersion == 1 && WHeader.MinorVersion == 0 && WHeader.DecimalVersion == 1) { printf("Disk was compressed using Lhwarp 1.01\n\n"); Version101 = 1; } else { printf("Disk was compressed using Lhwarp %d.%d%d\n\n", WHeader.MajorVersion, WHeader.MinorVersion, WHeader.DecimalVersion); Version101 = 0; } if ((WHeader.MajorVersion > MAJOR_VERSION) || (WHeader.MajorVersion == MAJOR_VERSION && WHeader.MinorVersion > MINOR_VERSION)) { printf("Sorry, this file was Lhwarp'd with Lhwarp V%d%d.%d\n", WHeader.MajorVersion, WHeader.MinorVersion, WHeader.DecimalVersion); printf("You are using Lhwarp V%d%d.%d\n", MAJOR_VERSION, MINOR_VERSION, DECIMAL_VERSION); CleanUp(); exit(1); } if (WHeader.TextLength) { if (!(TextMemory = AllocMem((ULONG) WHeader.TextLength+1, MEMF_PUBLIC))) { printf("Insufficient memory (%ld bytes required) to read compressed text\n", (ULONG) WHeader.TextLength+1); CleanUp(); exit(1); } if (!(TextCompMemory = AllocMem((ULONG) WHeader.CompressedTextLength, MEMF_PUBLIC))) { printf("Insufficient memory (%ld bytes required) to decompress text\n", (ULONG) WHeader.CompressedTextLength); FreeMem(TextMemory, (ULONG) WHeader.TextLength+1); CleanUp(); exit(1); } fread(TextCompMemory, (ULONG) WHeader.CompressedTextLength, 1, infile); FilePosition = (UBYTE *) TextCompMemory; /* Arbitrary number; just make it greater than TextLength */ EndOfFilePosition = (UBYTE *) ( ((UBYTE *) TextCompMemory) + (WHeader.CompressedTextLength)); PutFilePosition = (UBYTE *) TextMemory; Decode((ULONG) WHeader.TextLength); /* Make sure the text has a null terminator */ TextMemory[WHeader.TextLength] = 0; puts("\n----\n"); puts(TextMemory); puts("----\n"); FreeMem(TextMemory, (ULONG) WHeader.TextLength+1); FreeMem(TextCompMemory, (ULONG) WHeader.CompressedTextLength); } /* Start writing tracks */ for (;;) { if (Version101) { if (!(fread(&CHeader101, sizeof(struct CompHeader101), 1, infile))) { break; } } else { if (!(fread(&CHeader102, sizeof(struct CompHeader102), 1, infile))) { break; } } FilePosition = (UBYTE *) DataBlock; PutFilePosition = (UBYTE *) NewBlock; if (Version101) { EndOfFilePosition = (UBYTE *) ( ((UBYTE *) DataBlock) + CHeader101.CompressedLength); fread(DataBlock, (long) CHeader101.CompressedLength, 1, infile); Decode((ULONG) CHeader101.FullLength); Track = (ULONG) CHeader101.TrackNumber; } else { EndOfFilePosition = (UBYTE *) ( ((UBYTE *) DataBlock) + CHeader102.CompressedLength); fread(DataBlock, (long) CHeader102.CompressedLength, 1, infile); Decode((ULONG) CHeader102.FullLength); CheckSum = (ULONG) DoSum(NewBlock, (ULONG) CHeader102.FullLength); if (CheckSum != CHeader102.CheckSum) { printf("Warning: Track %ld fails checksum\n", Track); } Track = (ULONG) CHeader102.TrackNumber; } ExtendedDataBlock = (UBYTE *) ( ((UBYTE *) NewBlock) + ((ULONG) TRACK_SIZE)); CopyMem(ExtendedDataBlock, (UBYTE *) &iotd_SecLabel[0], (ULONG) LABEL_LENGTH); if (!Track) { puts("Disk contains the following bootblock:\n"); DisplayBootBlock(NewBlock); } /* Copy data into CHIP RAM */ CopyMem(NewBlock, TrackdiskBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH); WriteMsg->iotd_Req.io_Offset = (long) TRACK_SIZE * Track; WriteMsg->iotd_Req.io_Data = (APTR) TrackdiskBlock; WriteMsg->iotd_Req.io_Length = (long) TRACK_SIZE; WriteMsg->iotd_SecLabel = &iotd_SecLabel[0]; WriteMsg->iotd_Count = 0xFFFFFFFF; printf("Writing track %2ld", (ULONG) (Track)); fflush(stdout); if (DoIO((struct IORequest *) WriteMsg)) { fclose(infile); printf("Fatal error writing to disk in unit %ld -terminating\n\n", Unit); MotorOff(); CleanUp(); exit (1); } printf("\n"); fflush(stdout); TracksWritten++; } MotorOff(); WriteMsg->iotd_Req.io_Length = 0L; WriteMsg->iotd_Req.io_Command = CMD_FLUSH; DoIO((struct IORequest *) WriteMsg); fclose(infile); printf("\n\nFinished writing %ld tracks\n\n", TracksWritten); printf("Please remove and re-insert destination disk, to use\n\n"); CleanUp(); } MotorOff() { WriteMsg->iotd_Req.io_Length = 0L; WriteMsg->iotd_Req.io_Command = TD_MOTOR; DoIO((struct IORequest *) WriteMsg); } DisplayBootBlock(UBYTE *Data) { char Line[76]; UBYTE i; register UBYTE j; register UBYTE c; /* End of the line to be displayed */ Line[73] = 10; Line[74] = 13; Line[75] = 0; for (i=0; i<14; i++) { for (j=0; j<73; j++) { c = *((UBYTE *) ( ((UBYTE *) Data) + (i * 64) + j)); if (c < 32 || c > 126) { c = '.'; } Line[j] = c; } printf(Line); } puts(""); } ReadData() { ULONG AfterEncodeLength; ULONG TotalEncodeLength; ULONG TextLength; ULONG i; ULONG FileLength; ULONG OriginalLength = 0L; BPTR OutputFile; ULONG Error; ULONG DataSize; ULONG OnlyDataSize; FILE *TextInFile; UBYTE *TextMemory; UBYTE *ExtendedDataBlock; printf("\nLHWARP %d.%d%d - Amiga disk tracker - Written by Jonathan Forbes @ 1:250/642\n", (UBYTE) MAJOR_VERSION, (UBYTE) MINOR_VERSION, (UBYTE) DECIMAL_VERSION); puts("Copyright © Xenomiga Technology, 1990.\n"); printf("Reading from disk in drive %ld to file %s\n", Unit, FileName); /* Set up the read request */ ReadMsg->iotd_Req.io_Command = ETD_READ; ReadMsg->iotd_Count = 0xFFFFFFFF; /* If we start at track zero, check the boot block */ if (!StartTrack) { ReadMsg->iotd_Req.io_Offset = (long) 0L; ReadMsg->iotd_Req.io_Data = (APTR) TrackdiskBlock; /* Only get the first two sectors */ ReadMsg->iotd_Req.io_Length = (long) 1024L; if (Error = DoIO((struct IORequest *) ReadMsg)) { printf("Error %d reading from trackdisk.device\n", Error); CleanUp(); exit (1); } printf("\nBoot block of floppy disk in drive %d:\n\n", Unit); DisplayBootBlock(TrackdiskBlock); } if (AppendTextFile) { TextLength = GetFileLength(TextFileName); if (!TextLength) { puts("Text file missing or zero length\n"); CleanUp(); exit (1); } WHeader.TextLength = TextLength; } else { WHeader.TextLength = 0L; } /* Build the Warp header */ WHeader.StartTrack = StartTrack; WHeader.EndTrack = EndTrack; /* Version 1.03 */ WHeader.MajorVersion = (UBYTE) MAJOR_VERSION; WHeader.MinorVersion = (UBYTE) MINOR_VERSION; WHeader.DecimalVersion = (UBYTE) DECIMAL_VERSION; /* Write out the Warp header */ if (!(OutputFile = Open(FileName, MODE_NEWFILE))) { printf("Couldn't open output file\n"); CleanUp(); exit (1); } Write(OutputFile, &WHeader, (long) sizeof(struct WarpHeader)); Close(OutputFile); if (AppendTextFile) { printf("Compressing text ... "); fflush(stdout); if (!(TextInFile = fopen(TextFileName, "r"))) { printf("Can't open %s for input\n", TextInFile); CleanUp(); exit(1); } if (!(TextMemory = AllocMem((ULONG) TextLength, MEMF_PUBLIC))) { puts("Couldn't allocate text memory buffer"); CleanUp(); exit(1); } fread(TextMemory, (ULONG) TextLength, 1, TextInFile); fclose(TextInFile); if (!(outfile = fopen(FileName, "a"))) { printf("Can't open %s for append\n", FileName); FreeMem(TextMemory, (ULONG) TextLength); CleanUp(); exit(1); } FilePosition = (UBYTE *) TextMemory; EndOfFilePosition = (UBYTE *) ( ((UBYTE *) TextMemory) + (TextLength)); Encode((ULONG) (TextLength)); fclose(outfile); FreeMem(TextMemory, (ULONG) TextLength); AfterEncodeLength = GetFileLength(FileName); TotalEncodeLength = AfterEncodeLength - (ULONG) sizeof(struct WarpHeader); WHeader.CompressedTextLength = TotalEncodeLength; if (!(outfile = fopen(FileName, "r+w"))) { printf("Can't open %s for append\n", FileName); CleanUp(); exit(1); } fwrite(&WHeader, sizeof(struct WarpHeader), 1, outfile); fclose(outfile); printf("done\n\n"); } /* Start reading tracks */ for (i = StartTrack; i <= EndTrack; i++) { DataSize = (ULONG) TRACK_SIZE + (ULONG) (NUMSECS * NUM_HEADS * 16); OnlyDataSize = (ULONG) TRACK_SIZE; ExtendedDataBlock = (UBYTE *) ( ((UBYTE *) NewBlock) + ((ULONG) OnlyDataSize)); ReadMsg->iotd_Req.io_Offset = (long) TRACK_SIZE * i; ReadMsg->iotd_Req.io_Data = (APTR) TrackdiskBlock; ReadMsg->iotd_Req.io_Length = (long) TRACK_SIZE; ReadMsg->iotd_SecLabel = &iotd_SecLabel[0]; ReadMsg->iotd_Count = 0xFFFFFFFF; printf("Reading track %2ld ... ", (ULONG) (i)); fflush(stdout); DoIO((struct IORequest *) ReadMsg); printf("compressing"); fflush(stdout); /* Copy data out of CHIP RAM */ CopyMem(TrackdiskBlock, NewBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH); CopyMem((UBYTE *) &iotd_SecLabel[0], (UBYTE *) ExtendedDataBlock, (ULONG) NUMSECS * NUM_HEADS * 16); FilePosition = (UBYTE *) NewBlock; EndOfFilePosition = (UBYTE *) ( ((UBYTE *) NewBlock) + (DataSize)); Archive(i, DataSize); OriginalLength += (DataSize); printf("\n"); } ReadMsg->iotd_Req.io_Length = 0; ReadMsg->iotd_Req.io_Command = TD_MOTOR; DoIO((struct IORequest *) ReadMsg); FileLength = GetFileLength(FileName); printf("\n\nFinished reading tracks %d to %d (%d total)\n", WHeader.StartTrack, WHeader.EndTrack, WHeader.EndTrack - WHeader.StartTrack + 1); printf(" Input file: %ld bytes\n", OriginalLength); printf("Output file: %ld bytes\n\n", FileLength); CleanUp(); } CleanUp() { if (ReadMsg) { CloseDevice((struct IORequest *) ReadMsg); DeleteExtIO((struct IORequest *) ReadMsg, (long) sizeof(struct IOExtTD)); } if (WriteMsg) { CloseDevice((struct IORequest *) WriteMsg); DeleteExtIO((struct IORequest *) WriteMsg, (long) sizeof(struct IOExtTD)); } if (ReadPort) { DeletePort(ReadPort); } if (WritePort) { DeletePort(WritePort); } if (DataBlock) { FreeMem(DataBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH); } if (NewBlock) { FreeMem(NewBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH); } if (TrackdiskBlock) { FreeMem(TrackdiskBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH); } if (iotd_SecLabel) { FreeMem(iotd_SecLabel, (ULONG) LABEL_LENGTH); } if (text_buf) { FreeMem(text_buf, (ULONG) (N + F - 1)); } if (lson) { FreeMem(lson, (ULONG) (N + 1) * (ULONG) (sizeof(short))); } if (rson) { FreeMem(rson, (ULONG) (N + 257) * (ULONG) (sizeof(short))); } if (dad) { FreeMem(dad, (ULONG) (N + 1) * (ULONG) (sizeof(short))); } } Title() { printf("\nLHWARP %d.%d%d - Amiga disk tracker - Written by Jonathan Forbes @ 1:250/642\n", (UBYTE) MAJOR_VERSION, (UBYTE) MINOR_VERSION, (UBYTE) DECIMAL_VERSION); puts("Copyright © Xenomiga Technology, 1990.\n"); puts("Usage: LHWARP \n"); puts(" - Drive number (0 for internal, 1 ... 3 for external)"); puts(" - Output|Input filename"); puts(" - Track number (0 ... 79) [only valid in read mode]"); puts(" - Track number (0 ... 79) [only valid in read mode]"); puts(" - Append text in to output file [optional]\n"); } ULONG GetFileLength(register char *FileToOpen) { register ULONG FileLength; register ULONG lock; register struct FileInfoBlock *fileinfo; if (access(FileToOpen, 0)) { return (0L); } fileinfo = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR | MEMF_PUBLIC); if (!fileinfo) { printf("\n\r\n\rUtterly fatal error: Out of memory\n\r\n\r"); return (NULL); } lock = (ULONG) Lock(FileToOpen, ACCESS_READ); if (!lock) { FreeMem(fileinfo, sizeof(struct FileInfoBlock)); return (NULL); } Examine(lock, fileinfo); FileLength = fileinfo->fib_Size; UnLock(lock); FreeMem(fileinfo, sizeof(struct FileInfoBlock)); return (FileLength); } /* If the user presses ^C */ int CXBRK() { if (WriteMsg) { WriteMsg->iotd_Req.io_Length = 0L; WriteMsg->iotd_Req.io_Command = TD_MOTOR; DoIO((struct IORequest *) WriteMsg); } if (ReadMsg) { ReadMsg->iotd_Req.io_Length = 0L; ReadMsg->iotd_Req.io_Command = TD_MOTOR; DoIO((struct IORequest *) ReadMsg); } CleanUp(); return (-1); } ULONG DoSum(UBYTE *Block, ULONG Length) { register ULONG Sum = 0; register ULONG i; for (i = 0; i < Length; i++) { Sum = Sum + Block[i]; } return (Sum); }