/***********************************************************************
***
***  CDTV NoReset Command 1.0 (26-SEP-90)
***
***	By CARL SASSENRATH, Ukiah, CA  (707)-462-4878
***
***	Free to Distribute amoung CDTV developers, but...
***	do not modify and pass it along without checking with me.
***
***	A simple program to stop a CD eject reset:  This would normally
***	be a part of a CDTV application.  This code creates an IOPort,
***	IORequest, and Change Interrupt, then posts an ADDCHANGEINT
***	to the device driver.  The CD File System will not reset on
***	an Eject (nor Insert for that matter) so long as some other
***	program is interested in knowing about the event.  As long
***	as your request is linked to the change interrupt list, the
***	FS will not reset the system.
***
***	The code below is not quite the same as you would put in a
***	CDTV application.  Here we must keep our structures active
***	even after the program completes and returns to the shell.
***	Note that we allocate the structures and leave them intact
***	after exiting.  Also note that the interrupt name and code
***	must be located in one of these allocated structures, not
***	within the program (as its memory will be freed on exit).
***	Your application would not have to do this because it would
***	stay present until it has completed, and at that time it
***	would free the structures.
***
***	There is other nastiness here because the IOPort might end
***	up containing an invalid task pointer.  This should not be a
***	problem so long as the SendIO never completes (which it
***	shouldn't because we don't do a REMCHANGEINT).  Your CDTV
***	application must do a REMCHANGEINT before it exits.
***
***********************************************************************/

#include <exec/types.h>
#include <exec/interrupts.h>
#include <exec/memory.h>
#include <exec/io.h>
#include "cd.h"

extern	void	*AllocMem();
extern	struct	IOStdReq *CreateStdIO();
extern	struct	MsgPort  *CreatePort();
struct	IOStdReq *IORequest = NULL;
struct	MsgPort  *IOPort = NULL;
struct  sChgInt
{
	struct	Interrupt intr;
	UWORD	IntCode;
	char	Name[20];
} *ChangeInt;

#define	MUST(expr)  if (!(expr)) Quit();

main(argc,argv)
	int argc;
	char *argv[];
{
	int track;

	if (argc < 2) track = 1;
	else
	{
		track = atoi(argv[1]);
		if (!track) track = 1;
	}

	MUST(IOPort = CreatePort(0,0));
	MUST(IORequest = CreateStdIO(IOPort));
	MUST(ChangeInt = AllocMem(sizeof(*ChangeInt),MEMF_CLEAR));

	if (OpenDevice("cdtv.device",0,IORequest,0))
		{printf("CDTV Device will not open\n");	Quit();}

	ChangeInt->IntCode = 0x4E75;	/* RTS instruction */
	strcpy(ChangeInt->Name,"noreset.int");
	ChangeInt->intr.is_Node.ln_Type = NT_INTERRUPT;
	ChangeInt->intr.is_Node.ln_Name = ChangeInt->Name;
	ChangeInt->intr.is_Code = &ChangeInt->IntCode;

	IORequest->io_Command = CD_ADDCHANGEINT;
	IORequest->io_Data = (APTR)ChangeInt;
	SendIO(IORequest);

	/* Exit, but DO NOT deallocate structures! */
}

Quit()
{
	if (IORequest->io_Device) CloseDevice(IORequest);
	if (IORequest)	DeleteStdIO(IORequest);
	if (IOPort)	DeletePort(IOPort);
	if (ChangeInt)	FreeMem(ChangeInt,sizeof(*ChangeInt));
}

