
/**********************************************************************
**
**   Rigids v1.1 beta © 1997, 1998 by Tadek Knapik. Freeware.
**   Send comments, bug reports etc to  
**   <tadek@nautilus.uwoj.krakow.pl>
**
**   This piece of code is probably something I sould be ashame of.
** But it's my first "platform" C program, first disk access, first
** job I had deadline on (let's say so:) and... still I decided to
** show it. Comments appreciated, but please don't hurt me :)
**
**   1.1 (11.06.98) - added RAW writing to devices, RDB/MBR independent
**
**********************************************************************/



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

#include <dos/dos.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <devices/hardblocks.h>
#include <devices/scsidisk.h>
#include <devices/trackdisk.h>

#include <proto/dos.h>
#include <proto/exec.h>

/*
#define DEBUG
*/

#define IDNAME_OLDRIGID 0xD2CFCCC4			/* 'ROLD' */
#define BYTESONBLOCK 512

struct	RigidDiskBlock *memrdb = NULL;
struct	FileInfoBlock *fib = NULL;
struct	RDArgs *rdargs = NULL;			/* for ReadArgs() */
struct	MsgPort *ioport = NULL;
struct	IOExtTD *ioreq = NULL;
long	*buffer = NULL;
long	*memdata = NULL;
long	*iodata = NULL;
long	theunit = NULL;
long	theoffset = NULL;
long	thesize = NULL;
long	rdbstart = NULL;
long	rdbsize = NULL;
long	rdbshift = NULL;
long	rdbblock = NULL;
long	current = NULL;
int		scsiok = NULL;
int		writeok = NULL;
int		rdbok = NULL;

long BytesPerBlock = BYTESONBLOCK;		/* fixed as for now, but... */

char DevName[80] = "scsi.device";

char argstring[] = "D=DEVICE/K,U=UNIT/K/N,O=OFFSET/K/N,RDB=RDBONLY/S,WRITE/S,FORCE/S,F=FILE/A,RAW/S,S=SIZE/N";
char verstring[] = "$VER: Rigids v1.1b (11.06.98) © 1997, 1998 by Tadek Knapik.";

enum {DEVNAME = 0, DEVUNIT, NOFFSET, RDBONLY, DEVWRITE, RDBFORCE, FILENAME, RAW, NSIZE};
long argarray[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};

void ParseBBB(struct BadBlockBlock *BBB);
void ParsePB(struct PartitionBlock *PB);
void ParseFHB(struct FileSysHeaderBlock *FHB);
void ParseLSB(struct LoadSegBlock *LSB);
long CountChkSum(ULONG *data, ULONG nr);
int ChkRDBSum(struct RigidDiskBlock *RDB);
int ChkBBBSum(struct BadBlockBlock *BBB);
int ChkPBSum(struct PartitionBlock *PB);
int ChkFHBSum(struct FileSysHeaderBlock *FHB);
int ChkLSBSum(struct LoadSegBlock *LSB);

void OpenDev(void);
void CloseAll(void);
int scandev(long block, long *rdbfound);
int SumOK(ULONG *p);

void main(int argc, char **argv)
{

	BPTR thefile;						/* file pointer */

	if(!(rdargs=ReadArgs(argstring, argarray, NULL)))
	{
		printf("   %s\n", &verstring[6]);
		return;
	}

	if (argarray[DEVNAME])
		strcpy(DevName, (STRPTR) argarray[DEVNAME]);

	if (argarray[DEVUNIT])
		theunit = * (ULONG *) argarray[DEVUNIT];

	if (argarray[NSIZE])
		thesize = * (ULONG *) argarray[NSIZE];

	if (argarray[NOFFSET])
		theoffset = * (ULONG *) argarray[NOFFSET];

	if (((theoffset >= 0) && (theoffset < RDB_LOCATION_LIMIT)) || (argarray[RAW]))
	{

#ifdef DEBUG
	printf("* Device: %s\n", DevName);
	printf("* Unit: %ld\n", theunit);
	printf("* Offset: %ld\n", theoffset);
	printf("* Size: %ld\n", thesize);
	printf("* RDBOnly: %s\n", argarray[RDBONLY]? "Yes": "No");
	printf("* Mode: %s\n", argarray[DEVWRITE]? "Write": "Read");
	printf("* Raw: %s\n", argarray[RAW]? "On": "Off");
	printf("* Force: %s\n", argarray[RDBFORCE]? "Yes": "No");
	printf("* File: %s\n", argarray[FILENAME]);
	printf("\n");
#endif

		OpenDev();

#ifdef DEBUG
	printf("* %s unit %ld %s\n", DevName, theunit, scsiok? "opened": "not opened");
#endif

		if(scsiok)
		{
			if((buffer=malloc(BytesPerBlock)))			/* buffer to read blocks into */
			{
				if(argarray[DEVWRITE])			/* write */
				{
					if(thefile=Open((STRPTR) argarray[FILENAME], MODE_OLDFILE))
					{
						if(!argarray[RAW])
						{
							if(fib=malloc(sizeof(struct FileInfoBlock)))
							{
								if(ExamineFH(thefile, fib))
								{
									if(memdata=malloc(fib->fib_Size))
									{
										if((fib->fib_Size) && !((fib->fib_Size)%BytesPerBlock))
										{
											if(FRead(thefile, (STRPTR) memdata, (ULONG) fib->fib_Size, (ULONG) 1))
											{
												current = 0;
												memrdb = (struct RigidDiskBlock *) memdata;

												while((current < (fib->fib_Size)/BytesPerBlock) && (current < RDB_LOCATION_LIMIT))
												{
													if(memrdb->rdb_ID==IDNAME_RIGIDDISK)
														break;

													/* to the next "block" */

													memrdb += BytesPerBlock/sizeof(struct RigidDiskBlock);
													++current;
												}

												if(memrdb->rdb_ID==IDNAME_RIGIDDISK)
												{
#ifdef DEBUG
	printf("* RDB found in the file on \"block\" %ld.\n", current);
#endif

/* to know when the user has specified offset 0, and when he/she did not */

													if(!argarray[NOFFSET])
														theoffset = -1;

													if(argarray[RDBONLY] || (theoffset!=-1))
													{
														argarray[RDBONLY] = TRUE;
														iodata = (long *) memrdb;
														rdbsize = (fib->fib_Size)-(current*BytesPerBlock);
													}
													else
													{
														iodata = memdata;
														rdbsize = (fib->fib_Size);
													}

/* data write start is counted from HighRDSKBlock and RDB size, not in-file position */
/* rdbstart and rdbsize are start and size of all data, not RDB structure only! */

													if((rdbstart=(memrdb->rdb_HighRDSKBlock)-(rdbsize/BytesPerBlock)+1) < 0)
														rdbstart = 0;

/* real starting block of RDB, needed for checksum checking */
/* when OFFSET specified, fixed later */

													rdbblock = ((UBYTE *)memrdb-(UBYTE*)memdata)/BytesPerBlock;

/* RDB shifting and checksumming all lists */

													if(theoffset!=-1)
													{

														rdbshift = rdbstart-theoffset;
#ifdef DEBUG
	printf("* Shift value is %ld\n", rdbshift);
#endif

														if(memrdb->rdb_SummedLongs <= 555)
														{
#ifdef DEBUG
	printf("%ld longs to checksum in RDB.\n", memrdb->rdb_SummedLongs);
#endif

															if(memrdb->rdb_BadBlockList != -1)
															{
																ParseBBB((struct BadBlockBlock *) &((UBYTE *)memrdb)[((memrdb->rdb_BadBlockList)-rdbstart)*BytesPerBlock]);
																memrdb->rdb_BadBlockList -= rdbshift;
															}

															if(memrdb->rdb_PartitionList != -1)
															{
																ParsePB((struct PartitionBlock *) &((UBYTE *)memrdb)[((memrdb->rdb_PartitionList)-rdbstart)*BytesPerBlock]);
																memrdb->rdb_PartitionList -= rdbshift;
															}

															if(memrdb->rdb_FileSysHeaderList != -1)
															{
																ParseFHB((struct FileSysHeaderBlock *) &((UBYTE *) memrdb)[((memrdb->rdb_FileSysHeaderList)-rdbstart)*BytesPerBlock]);
																memrdb->rdb_FileSysHeaderList -= rdbshift;
															}

															if(memrdb->rdb_DriveInit != -1)
															{
																memrdb->rdb_DriveInit -= rdbshift;
															}

															memrdb->rdb_HighRDSKBlock -= rdbshift;

															memrdb->rdb_ChkSum = 0;
															memrdb->rdb_ChkSum = CountChkSum((ULONG *) memrdb, (ULONG) memrdb->rdb_SummedLongs);

															rdbstart = theoffset;
															rdbblock = theoffset;

														}
														else
															printf("Can't calculate checksum.\n");

													}

#ifdef DEBUG
	printf("* Checksum is %s.\n", SumOK((ULONG *) memrdb)? "OK": "wrong");
	printf("* Writing RDB at block %ld, size %ld\n", rdbstart, rdbsize);
#endif

													if((ChkRDBSum(memrdb)) || argarray[RDBFORCE])
													{

														current=0;
														while((scandev(current, &theoffset)) && (theoffset<rdbstart))
														{
#ifdef DEBUG
	printf("* Replacing old 'RDSK' with 'ROLD' at block %ld\n", theoffset);
#endif

															buffer[0] = IDNAME_OLDRIGID;
															ioreq->iotd_Req.io_Command = CMD_WRITE;
															ioreq->iotd_Req.io_Flags = 0;
															ioreq->iotd_Req.io_Data = buffer;
															ioreq->iotd_Req.io_Length = BytesPerBlock;
															ioreq->iotd_Req.io_Offset = theoffset * BytesPerBlock;
															DoIO((struct IORequest *) ioreq);
															current = theoffset+1;
														}

														ioreq->iotd_Req.io_Command = CMD_WRITE;
														ioreq->iotd_Req.io_Flags = 0;
														ioreq->iotd_Req.io_Data = iodata;
														ioreq->iotd_Req.io_Length = rdbsize;
														ioreq->iotd_Req.io_Offset = rdbstart * BytesPerBlock;


														if(!rdbok)
															printf("Checksum is corrupt. Forcing write...\n");

														if(!DoIO((struct IORequest *) ioreq))
															printf("%ld bytes%s written at block %ld\n", rdbsize, argarray[RDBONLY]? " (RDB only)": "", rdbstart);
														else
															printf("Device error. Data not written.\n");
													}
													else
														printf("Checksum is corrupt. RDB not written (you can use FORCE switch though).\n");

												}
												else
													printf("RDB not found in file %s\n", (STRPTR) argarray[FILENAME]);

											}
											else
												printf("Error reading from file %s\n", (STRPTR) argarray[FILENAME]);

										}
										else
											printf("Error: size of %s is not a multipler of BytesPerBlock.\n", (STRPTR) argarray[FILENAME]);

										free(memdata);

									}
									else
										printf("Not enough memory.\n");

								}
								else
									printf("Can't get file size.\n");

								free(fib);

							}
							else
								printf("Not enough memory.\n");

							Close(thefile);
						}
						else
						{

/* RAW mode writing */

							if(fib=malloc(sizeof(struct FileInfoBlock)))
							{
								if(buffer=malloc(BytesPerBlock))
								{
									if(ExamineFH(thefile, fib))
									{


#ifdef DEBUG
	printf("* File size is %ld, requested block size is %ld\n", fib->fib_Size, thesize);
#endif

/* is the file size is OK? */

										if((fib->fib_Size)%BytesPerBlock)
										{
											current = FALSE;
#ifdef DEBUG
	printf("* File size is not multipler of BytesPerBlock\n");
#endif

										}
										else
											current = TRUE;

/* do we have to, and if so, can we put it as write size? */

										if(thesize * BytesPerBlock <= fib->fib_Size)
										{
											if(argarray[NSIZE])		/* if size given */
											{
												current = TRUE;
#ifdef DEBUG
	printf("* Using valid SIZE given\n");
#endif
											}
											else
												if(current)
												{
													thesize = (fib->fib_Size)/BytesPerBlock;
#ifdef DEBUG
	printf("* No SIZE given, using valid file size\n");
#endif
												}
										}
										else
										{
											thesize = (fib->fib_Size)/BytesPerBlock;
#ifdef DEBUG
	printf("* SIZE too big, trying to use file size\n");
#endif

										}

#ifdef DEBUG
	printf("* Final write size is %ld blocks\n", thesize);
#endif

										if(current)
										{
											if(thesize)
											{
												writeok = TRUE;

												for(current=theoffset; current != theoffset+thesize; ++current)
												{
													if(FRead(thefile, (STRPTR) buffer, (ULONG) BytesPerBlock, (ULONG) 1))
													{
														ioreq->iotd_Req.io_Command = CMD_WRITE;
														ioreq->iotd_Req.io_Flags = 0;
														ioreq->iotd_Req.io_Data = buffer;
														ioreq->iotd_Req.io_Length = BytesPerBlock;
														ioreq->iotd_Req.io_Offset =  current * BytesPerBlock;

														if(DoIO((struct IORequest *) ioreq))
														{
															printf("Device error. Data not written.\n");
															writeok = FALSE;
															break;
														}
													}
													else
													{
														printf("Error reading from file %s\n", (STRPTR) argarray[FILENAME]);
														writeok = FALSE;
														break;
													}

												}

												if(writeok)
													printf("%ld bytes written at block %ld.\n", thesize * BytesPerBlock, theoffset);
											}
											else
												printf("Writing 0 bytes is not what I'm made for.\n");
										}
										else
											printf("Error: size of %s is not a multipler of BytesPerBlock.\n", (STRPTR) argarray[FILENAME]);
									}
									else
										printf("Can't get file size.\n");

									free(buffer);
									buffer = NULL;
								}
								else
									printf("Not enough memory.\n");

								free(fib);
							}
							else
								printf("Not enough memory.\n");

							Close(thefile);
						}

					}
					else
						printf("Can't open file %s\n", (STRPTR) argarray[FILENAME]);

				}
				else							/* read */
				{
					if(!argarray[RAW])
					{


/* first we search for the start of RDB on the disk... and read its length */

						if(scandev(theoffset, &rdbstart))			/* search for RDB on the disk */
						{

/* remember the real offset of RDB structure */

							rdbblock = rdbstart;

/* now we can open the file and fill it with the data */

							if(thefile=Open((STRPTR) argarray[FILENAME], MODE_NEWFILE))
							{
								if(!argarray[RDBONLY])
									rdbstart = theoffset;
							rdbsize = ((((struct RigidDiskBlock *)buffer)->rdb_HighRDSKBlock)-rdbstart+1) * BytesPerBlock;
	
#ifdef DEBUG
	printf("* RDB size is %ld bytes\n", rdbsize);
#endif

								if(memdata=malloc(rdbsize))
								{

									ioreq->iotd_Req.io_Command = CMD_READ;
									ioreq->iotd_Req.io_Flags = 0;
									ioreq->iotd_Req.io_Data = memdata;
									ioreq->iotd_Req.io_Length = rdbsize;
									ioreq->iotd_Req.io_Offset = rdbstart * BytesPerBlock;

									if(!DoIO((struct IORequest *) ioreq))
									{

/* memrdb pointer for checksumming */

										memrdb = (struct RigidDiskBlock *) &((UBYTE *)memdata)[(rdbblock-rdbstart)*BytesPerBlock];

										if(ChkRDBSum(memrdb) || argarray[RDBFORCE])
										{
											if(!rdbok)
												printf("Checksum is corrupt. Forcing read...\n");

											if(writeok=FWrite(thefile, (STRPTR) memdata, (ULONG) rdbsize, (ULONG) 1))
												printf("%ld bytes%s written to %s\n", rdbsize, argarray[RDBONLY]? " (RDB only)": "", (STRPTR) argarray[FILENAME]);
											else
												printf("Write error\n");

										}
										else
											printf("RDB checksum is corrupt. Use FORCE to read it.\n");

									}
									else
										printf("Device error. File not written.\n");

									free(memdata);

								}
								else
									printf("Not enough memory.\n");

								Close(thefile);
								if(!writeok)
									DeleteFile((STRPTR) argarray[FILENAME]);

							}
							else
								printf("Can't open file %s\n", argarray[FILENAME]);
						}
						else
							printf("Can't find RDB on the disk.\n");
					}
					else
					{

/* RAW mode reading */

						if(thesize)
						{
							if(buffer=malloc(BytesPerBlock))
							{
								if(thefile=Open((STRPTR) argarray[FILENAME], MODE_NEWFILE))
								{
									writeok = TRUE;

									for(current=theoffset; current != theoffset+thesize; ++current)
									{
										ioreq->iotd_Req.io_Command = CMD_READ;
										ioreq->iotd_Req.io_Flags = 0;
										ioreq->iotd_Req.io_Data = buffer;
										ioreq->iotd_Req.io_Length = BytesPerBlock;
										ioreq->iotd_Req.io_Offset =  current * BytesPerBlock;

										if(DoIO((struct IORequest *) ioreq))
										{
											printf("Device error. File not written.\n");
											writeok = FALSE;
											break;
										}

										if(!(writeok=FWrite(thefile, (STRPTR) buffer, (ULONG) BytesPerBlock, (ULONG) 1)))
										{
											printf("Write error\n");
											break;
										}

									}

									Close(thefile);
									if(writeok)
										printf("%ld bytes written to %s\n", thesize * BytesPerBlock, (STRPTR) argarray[FILENAME]);
									else
										DeleteFile((STRPTR) argarray[FILENAME]);
								}
								else
									printf("Can't open file %s\n", argarray[FILENAME]);

								free(buffer);
								buffer = NULL;
							}
							else
								printf("Not enough memory.\n");
						}
						else
							printf("For reading 0 bytes I recommend using HDToolBox.\n");
					}
				}
			}
			else
				printf("Not enough memory.\n");

		}
		else
			printf("Cant't open %s unit %ld\n", DevName, theunit);

		CloseAll();
	}
	else
		printf("Invalid offset value (must be from 0 to %ld).\n", RDB_LOCATION_LIMIT-1);

}


int scandev(long block, long *rdbfound)
{
	while (block < RDB_LOCATION_LIMIT)
	{
		ioreq->iotd_Req.io_Command = CMD_READ;
		ioreq->iotd_Req.io_Flags = 0;
		ioreq->iotd_Req.io_Data = buffer;
		ioreq->iotd_Req.io_Length = BytesPerBlock;
		ioreq->iotd_Req.io_Offset = block * BytesPerBlock;

		if(DoIO((struct IORequest *) ioreq))
		{
#ifdef DEBUG
	printf("* Error number %ld\n", ioreq->iotd_Req.io_Error);
#endif

			printf("Disk error. ");
			return FALSE;
		}
		else if (((struct RigidDiskBlock *)buffer)->rdb_ID==IDNAME_RIGIDDISK)
		{

			*rdbfound = block;

#ifdef DEBUG
	printf("* RDB found on block %ld\n", block);
	printf("* RDB last block is %ld\n", ((struct RigidDiskBlock *)buffer)->rdb_HighRDSKBlock);
#endif

			return TRUE;
		}
		else
			++block;

	}
	return FALSE;

}



/* list parsing... hope I didn't make a mistake here */

void ParseBBB(struct BadBlockBlock *BBB)
{
	if((BBB->bbb_Next)!=-1)
	{
		ParseBBB((struct BadBlockBlock *) &((UBYTE *) memrdb)[((BBB->bbb_Next)-rdbstart)*BytesPerBlock]);
		BBB->bbb_Next -= rdbshift;

		BBB->bbb_ChkSum = 0;
 	 	BBB->bbb_ChkSum = CountChkSum((ULONG *) BBB, (ULONG) BBB->bbb_SummedLongs);
	}
}

void ParsePB(struct PartitionBlock *PB)
{
	if((PB->pb_Next)!=-1)
	{
		ParsePB((struct PartitionBlock *) &((UBYTE *) memrdb)[((PB->pb_Next)-rdbstart)*BytesPerBlock]);
		PB->pb_Next -= rdbshift;

		PB->pb_ChkSum = 0;
	  	PB->pb_ChkSum = CountChkSum((ULONG *) PB, (ULONG) PB->pb_SummedLongs);
	}
}

void ParseFHB(struct FileSysHeaderBlock *FHB)
{
	if((FHB->fhb_Next)!=-1)
	{
		ParseFHB((struct FileSysHeaderBlock *) &((UBYTE *) memrdb)[((FHB->fhb_Next)-rdbstart)*BytesPerBlock]);
		FHB->fhb_Next -= rdbshift;
	}

	if((FHB->fhb_SegListBlocks)!=-1)
	{
		ParseLSB((struct LoadSegBlock *) &((UBYTE *) memrdb)[((FHB->fhb_SegListBlocks)-rdbstart)*BytesPerBlock]);
		FHB->fhb_SegListBlocks -= rdbshift;
	}

	FHB->fhb_ChkSum = 0;
	FHB->fhb_ChkSum = CountChkSum((ULONG *) FHB, (ULONG) FHB->fhb_SummedLongs);

}

void ParseLSB(struct LoadSegBlock *LSB)
{
	if((LSB->lsb_Next)!=-1)
	{
		ParseLSB((struct LoadSegBlock *) &((UBYTE *) memrdb)[((LSB->lsb_Next)-rdbstart)*BytesPerBlock]);
		LSB->lsb_Next -= rdbshift;

		LSB->lsb_ChkSum = 0;
		LSB->lsb_ChkSum = CountChkSum((ULONG *) LSB, (ULONG) LSB->lsb_SummedLongs);
	}
}



/* checksum checking for all RDB structures */

int ChkRDBSum(struct RigidDiskBlock *RDB)
{
	rdbok = TRUE;

	if(!SumOK((ULONG *) RDB))
	{
		rdbok = FALSE;
		return FALSE;
	}

	if((RDB->rdb_BadBlockList) != -1)
		ChkBBBSum((struct BadBlockBlock *) &((UBYTE *)memrdb)[((RDB->rdb_BadBlockList)-rdbblock)*BytesPerBlock]);

	if((RDB->rdb_PartitionList) != -1)
		ChkPBSum((struct PartitionBlock *) &((UBYTE *)memrdb)[((RDB->rdb_PartitionList)-rdbblock)*BytesPerBlock]);

	if((RDB->rdb_FileSysHeaderList) != -1)
		ChkFHBSum((struct FileSysHeaderBlock *) &((UBYTE *)memrdb)[((RDB->rdb_FileSysHeaderList)-rdbblock)*BytesPerBlock]);

	return rdbok;
}

int ChkBBBSum(struct BadBlockBlock *BBB)
{
	if(!rdbok)
		return FALSE;

	if(!SumOK((ULONG *) BBB))
		rdbok = FALSE;

	if((BBB->bbb_Next) != -1)
		ChkBBBSum((struct BadBlockBlock *) &((UBYTE *)memrdb)[((BBB->bbb_Next)-rdbblock)*BytesPerBlock]);

	return rdbok;
}


int ChkPBSum(struct PartitionBlock *PB)
{
	if(!rdbok)
		return FALSE;

	if(!SumOK((ULONG *) PB))
		rdbok = FALSE;

	if((PB->pb_Next) != -1)
		ChkPBSum((struct PartitionBlock *) &((UBYTE *)memrdb)[((PB->pb_Next)-rdbblock)*BytesPerBlock]);

	return rdbok;
}


int ChkFHBSum(struct FileSysHeaderBlock *FHB)
{
	if(!rdbok)
		return FALSE;

	if(!SumOK((ULONG *) FHB))
		rdbok = FALSE;

	if((FHB->fhb_Next) != -1)
		ChkFHBSum((struct FileSysHeaderBlock *) &((UBYTE *)memrdb)[((FHB->fhb_Next)-rdbblock)*BytesPerBlock]);

	if((FHB->fhb_SegListBlocks) != -1)
		ChkLSBSum((struct LoadSegBlock *) &((UBYTE *)memrdb)[((FHB->fhb_SegListBlocks)-rdbblock)*BytesPerBlock]);

	return rdbok;
}

int ChkLSBSum(struct LoadSegBlock *LSB)
{
	if(!rdbok)
		return FALSE;

	if(!SumOK((ULONG *) LSB))
		rdbok = FALSE;

	if((LSB->lsb_Next) != -1)
		ChkLSBSum((struct LoadSegBlock *) &((UBYTE *)memrdb)[((LSB->lsb_Next)-rdbblock)*BytesPerBlock]);

	return rdbok;
}


/* Next two functions had been written looking at David Balazic's
   RDBInformer v0.2. */

long CountChkSum(ULONG *data, ULONG nr)
{
	long i;
	long chksum = 0;

	for(i=0; i<nr; i++)
		chksum -= (*data++);
	return chksum;

}

void CloseAll(void)
{
	if(scsiok)
		CloseDevice((struct IORequest *) ioreq);
	if(ioreq)
		DeleteIORequest(ioreq);
	if(ioport)
		DeleteMsgPort(ioport);
	if (buffer)
		free(buffer);
	if (rdargs)
		FreeArgs(rdargs);
}


/* The source below is took from David Balazic's RDBInformer v0.2 */

void OpenDev(void)
{
if (ioport=CreateMsgPort())
{
#ifdef DEBUG
	printf("* MsgPort created\n");
#endif
 if(ioreq=CreateIORequest(ioport,sizeof(struct IOExtTD)))
#ifdef DEBUG
	printf("* IORequest created\n");
#endif
 {
  if(!OpenDevice(DevName, theunit, (struct IORequest *) ioreq, 0))
  {
   scsiok=TRUE;
   return;
  }
 }
}
scsiok=FALSE;
}

int SumOK(ULONG *p)
{
int i;
LONG chk=0;
ULONG nr=((struct RigidDiskBlock *)p)->rdb_SummedLongs;

if(nr>555) return FALSE;

for(i=0;i<nr;i++)
   chk+=(*p++);
if (chk) return FALSE;
return TRUE;
}

