					/*										   */
					/* Sous Prog pour utilisation du trackdisk */
					/*										   */

#include "RoutinesTD.h"

#define Prototype extern
#define ON 1L
#define OFF 0L
#define R CMD_READ
#define W CMD_WRITE
#define Actual[drive] ((*DiskReq[drive]).io_Actual)


struct IOStdReq *DiskReq[4]={0,0,0,0};
struct IOStdReq *A;
struct MsgPort  *DiskPort[4]={0,0,0,0};

Prototype BYTE OpenTD(LONG drive);
Prototype BYTE CMDonD(ULONG drive,UWORD Command,UBYTE Flags,ULONG Length,APTR Data,ULONG Offset);
Prototype BYTE Read_WriteB(UWORD CMD,ULONG drive,APTR buffer,ULONG Bloc);
Prototype BYTE Read_WriteT(UWORD CMD,ULONG drive,APTR buffer,ULONG Track);
Prototype BYTE Read_WriteC(UWORD CMD,ULONG drive,APTR buffer,ULONG Cyl);
Prototype BYTE MtrOn(LONG drive);
Prototype BYTE MtrOff(LONG drive);
Prototype void CloseaTD(LONG drive);
Prototype void CloseTD();
Prototype VOID DiskBUSY(UBYTE *drive,LONG onflag);
Prototype ULONG isInserted(ULONG drive);
Prototype ULONG isProtected(LONG drive);

Prototype struct IOStdReq *DiskReq[4];


BYTE OpenTD(LONG drive)
{
	DiskPort[drive] =(struct MsgPort *)CreatePort(0L,0L);
	DiskReq[drive] =(struct IOStdReq *)CreateStdIO(DiskPort[drive]);
	if (!OpenDevice(TD_NAME,(ULONG)drive,(struct IORequest *)DiskReq[drive],0UL)) return(TRUE);
		else
	{
		DeleteStdIO (DiskReq[drive]);
		DeletePort	(DiskPort[drive]);
		DiskReq[drive]=0;
		DiskPort[drive]=0;
	}
		return(FALSE);
}

BYTE CMDonD(ULONG drive,UWORD Command,UBYTE Flags,ULONG Length,APTR Data,ULONG Offset)
{
	A=DiskReq[drive];
	(*A).io_Command = Command;
	(*A).io_Flags = Flags;
	(*A).io_Length = Length;
	(*A).io_Data = Data;
	(*A).io_Offset = Offset;
	
	DoIO((struct IORequest *)DiskReq[drive]);
	return(	(*A).io_Error );
}

BYTE Read_WriteB(UWORD CMD,ULONG drive,APTR buffer,ULONG Bloc)
{
	return (CMDonD(drive,CMD,0,TD_SECTOR,buffer,Bloc * TD_SECTOR));
}

BYTE Read_WriteT(UWORD CMD,ULONG drive,APTR buffer,ULONG Track)
{
	return (CMDonD(drive,CMD,0,11 * TD_SECTOR,buffer,Track * 11 * TD_SECTOR));
}

BYTE Read_WriteC(UWORD CMD,ULONG drive,APTR buffer,ULONG Cyl)
{
	return(CMDonD(drive,CMD,0,22 * TD_SECTOR,buffer,Cyl * 22 * TD_SECTOR));
} 

BYTE MtrOn(LONG drive)
{
	return(CMDonD(drive,TD_MOTOR,0L,1L,0L,0L));
}

BYTE MtrOff(LONG drive)
{
	return(CMDonD(drive,TD_MOTOR,0L,0L,0L,0L));
}

void CloseaTD(LONG drive)
{
	if (DiskReq[drive])
	{
		A=DiskReq[drive];
		CloseDevice((struct IORequest *)A);
		DeleteStdIO (A);
		DeletePort  (DiskPort[drive]);
		DiskReq[drive]=NULL;
		DiskPort[drive]=NULL;
	}
}

void CloseTD()
{
LONG  drive;
	for (drive=0;drive<4;drive++) 
	{
		if (DiskReq[drive]) MtrOff(drive);
		CloseaTD(drive);
	}
}

VOID DiskBUSY(UBYTE *drive,LONG onflag)
{
struct StandardPacket 	*pk;
struct Process			*tsk;

	tsk=(struct Process *)FindTask(NULL);
	if (pk=(APTR)AllocMem (sizeof(struct StandardPacket), MEMF_PUBLIC|MEMF_CLEAR))
	{
		pk->sp_Msg.mn_Node.ln_Name=(UBYTE *)&(pk->sp_Pkt);

		pk->sp_Pkt.dp_Link=&(pk->sp_Msg);
		pk->sp_Pkt.dp_Port=&(tsk->pr_MsgPort);
		pk->sp_Pkt.dp_Type=ACTION_INHIBIT;
		pk->sp_Pkt.dp_Arg1=(onflag ? -1L : 0L);

		PutMsg(DeviceProc(drive),(struct Message*)pk);
		WaitPort(&(tsk->pr_MsgPort));
		GetMsg(&(tsk->pr_MsgPort));
		FreeMem(pk,(long)sizeof(*pk));
	}

}	

/* return -1 if out , 0 if in */
ULONG isInserted(ULONG drive)
{
	if (DiskReq[drive]) {
	CMDonD(drive,TD_CHANGESTATE,0,0,0,0);
	return((*DiskReq[drive]).io_Actual); }
	else return(-1);
}

ULONG isProtected(LONG drive)
{
	if (DiskReq[drive]) {
	CMDonD(drive,TD_PROTSTATUS,0,0,0,0);
	return((*DiskReq[drive]).io_Actual);}
	else return(-1);
}
