/* The functions read_blocks(start,count,buff) and write_blocks(), read/write
 * 'count' 1K blocks from disk starting at block 'start' into the buffer
 * pointed to by 'buff' . The function init_device(name,rw) initialises the 
 * device 'name' so that read_blocks() and write_blocks() use it. Since this
 * is called once initially, any other machine dependent initialisation can be
 * put here, if it returns non-zero then the operation failed. If 'rw' is not
 * zero, write access is sought also for this device. The function set_size is
 * used to tell the I/O routines the size of the filesystems being accessed,
 * so any special arrangements can be made. If this function returns non-zero
 * then the operation failed and the filesystem cannot be accessed.
 */

#ifdef atarist

#include <stdio.h>
#include <mintbind.h>
#include "fs.h"
#include "global.h"
#include "proto.h"

int _device,_write_ok,shift;

void read_blocks(start,count,buff)
long start;
unsigned count;
void *buff;
{

	long ret;
	ret=block_rwabs(0,buff,count,start,&hdinf);
	if(ret) printf("Rwabs read returned %ld\n",ret);
}

void write_blocks(start,count,buff)
long start;
unsigned count;
void *buff;
{
	long ret;
if(start==0){
 printf("Illegal Write\n");
return;
}
	if(!_write_ok)
	{
		printf("Internal error : Illegal write\n");
		printf("Start %ld Count %d\n",(long)start,count);
		return;
	}
	modified=1;
	ret=block_rwabs(1,buff,count,start,&hdinf);
	if(ret) printf("Rwabs write returned %ld\n",ret);
}

/* Constants for fscntl */

#define MFS_BASE	0x100
#define MFS_VERIFY	(MFS_BASE)	/* Return minixfs magic number */
#define MFS_SYNC	(MFS_BASE|0x01)	/* Sync the filesystem */
#define MFS_CINVALID	(MFS_BASE|0x02)	/* Invalidate cache entries */
#define MFS_FINVALID	(MFS_BASE|0x03)	/* Invalidate Fileptrs */
#define MFS_INFO	(MFS_BASE|0x04)	/* Get info about filesystem */
#define MFS_USAGE	(MFS_BASE|0x05)	/* Get block allocation of a file */
#define MFS_IMODE	(MFS_BASE|0x06)	/* Change all bits in an inode mode */
#define MFS_GTRANS	(MFS_BASE|0x07) /* Get filename translation mode */ 
#define MFS_STRANS	(MFS_BASE|0x08) /* Set filename translation mode */
#define MFS_PHYS	(MFS_BASE|0x09) /* Get physical partition info */
#define MFS_IADDR	(MFS_BASE|0x0a) /* Get start address of minixfs */
#define MFS_UPDATE	(MFS_BASE|0x0b) /* Update daemon controls */
#define MFS_MOUNT	(MFS_BASE|0x0c) /* Mount a filesystem */
#define MFS_UMOUNT	(MFS_BASE|0x0d) /* Umount a filesystem */

#define MFS_MAGIC	0x18970431	/* Magic number from MFS_VERIFY */


int init_device(name,rw)
char *name;
int rw;
{
	long err;
	struct 
	{
		long start;
		long finish;
		char shadow;
		char scsiz;
	} pp;
	_device=(name[0]-'A') & ~32;
	if( (_device < 0) || (_device > 32) || name[1]!=':' )
	{
		fprintf(stderr,"Invalid drive name %s\n",name);
		return 1;
	}

	if( Dcntl(MFS_VERIFY,name,&err) || err!=MFS_MAGIC )
	{
		fprintf(stderr,"Not recognised Minixfs partition or Minixfs not running\n");
		if(!ask("Continue?","Ignored")) return 1;
	}

	if( !Dcntl(MFS_PHYS,name,&pp) && pp.start!=-1)
	/* Is this a physical partition ? */
	{
		long tstack;
		hdinf.start=pp.start;
		hdinf.size=pp.finish-hdinf.start+1;
		hdinf.scsiz=pp.scsiz;
		hdinf.drive=_device;
		hdinf.major = pp.shadow;
		(void)Getbpb(_device); 	/* Satisfy disk changes */
		hdinf.rwmode = RW_PHYS;
		tstack=Super(0l);
		if(init_icd()==2)
		{
			Super(tstack);
			fprintf(stderr,"Can't patch ICD bug\n");
			return 1;
		}
		Super(tstack);

		if(hdinf.start > 0xfff0)
		{
			if(no_plrecno(hdinf.major)) return 1;
			hdinf.rwmode |= RW_LRECNO;
		}
	}
	else if( (err=get_hddinf(_device,&hdinf,0)) ) 
	{
		fprintf(stderr,"Drive %s %s\n",name,hdd_err[err]);
		return 1;
	}

	if(rw) _write_ok=1;

	Dcntl(MFS_UPDATE,name,1);	/* Suspend update */
	/* Sync the filesytem and lock the device */
	if( Dcntl(MFS_SYNC,name,0) || Dlock(1,_device) )
	{
		fprintf(stderr,"Couldn't sync or lock device %s.\n",name);
		if(ask("Continue?","Ignored"))
			fprintf(stderr,"Warning: reboot after running.\n");
		else
		{
			close_device();
			return 1;
		}
	}
	return 0;
}

void close_device()
{
	extern char *drvnam;
	(void) Dlock(0,_device);	/* Unlock drive */
	Dcntl(MFS_UPDATE,drvnam,2);		/* Restart update */
}

int set_size(nblocks)
long nblocks;
{
	long err,tsize;

	tsize=hdinf.size;
	err = set_lrecno(&hdinf,nblocks);

	if(err)
	{
		fprintf(stderr,"set_size %s\n",hdd_err[err]);
		return err;
	}

	if( !tsize && no_size)
	{
		if( (err=get_size(hdinf.drive,&tsize)) ) 
			fprintf(stderr,"get_size: warning %s\n",size_err[err]);
		else if( tsize!=nblocks ) fprintf(stderr,"Warning filesystem "
			 	"size %ldK, Expected %ldK\n",nblocks,tsize);
	}

	return 0;

}

#endif
