/*
 * ResetTest.c
 * (former Key_Reset.c)
 *
 * This is in two parts..
 * here we've part one, part two is written in assembly and
 * contains the reset-handler
 * See: LSAVE:KeyHandler.a
 *
 * From: "AMIGA ROM Kernal Reference Manual" Part "Devices"
 * typed in and modified by THOR in 12/26/91
 *
 * Additional note: YEAAAH ! works ! (never thought it will)
 * 2. addit.  note: it is not save that this will work at your amiga, depends
 *                  on your keyboard release
 * 3. note:         Removed assembler stuff, now completely in C
 *
 */
 
/*******************************************
 ** KeyBoard device reset handler example **
 *******************************************/

#define INCLUDE_ALIB_PROTOS

#include <exec/types.h>
#include <exec/io.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <devices/keyboard.h>
#include <intuition/intuition.h>
#include <exec/interrupts.h>

#include <proto/exec.h>
#include <proto/intuition.h>
#define DOS_IO
#include <proto/dos.h>

#include <stdio.h>
#include <string.h>

#include <Startup.h>

struct IntuitionBase *IntuitionBase;

#ifdef LATTICE
int CXBRK(void) { return(0); }          /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }       /* really */
void main();
#endif

struct MyData
        {
                struct Task *MyTask;
                ULONG MySignal;
        };

int __asm __saveds ResetHandler(register __a1 struct MyData *data);



UBYTE NameString[]="Reset Handler Test";
struct NewWindow mywin={0,0,222,10,0,1,CLOSEWINDOW,
                        WINDOWDRAG|WINDOWCLOSE|SIMPLE_REFRESH|NOCAREREFRESH,
                        NULL,NULL,NameString,NULL,NULL,0,0,0,0,WBENCHSCREEN};
                
extern struct IntuitionBase *IntuitionBase;


/*
 *
 * This is the reset handler itself, here as SAS-C inline !
 *
 */
int __asm __saveds ResetHandler(register __a1 struct MyData *data)
{
        Signal(data->MyTask,data->MySignal);

        return 0;
}

/*
 * This routine opens a window and waits for the one event that
 * can happen (CLOSEWINDOW)
 */
short WaitForUser(ULONG MySignal)
{
struct Window *win;
short ret=0;

        if (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0L))
                {
                        if (win=OpenWindow(&mywin))
                                {
                                        ret=(MySignal==Wait(MySignal | (1L<<win->UserPort->mp_SigBit)));
                                        CloseWindow(win);
                                }
                        else
                                printf("Error: Could not open window\n");
                        CloseLibrary((struct Library *)IntuitionBase);
                }
        else
                printf ("Error: Could not open intuition.library\n");
        
        return(ret);
}

VOID main(int argc,char *argv[])
{
struct IOStdReq         *KeyIO;
struct MsgPort          *KeyMP;
struct Interrupt        *keyHandler;
struct MyData           MyDataStuff;
ULONG                   MySignal;
int                     i;

        if ((MySignal=AllocSignal(-1L))!=-1) {
                MyDataStuff.MyTask=FindTask(NULL);
                MyDataStuff.MySignal=1L<<MySignal;
                
                if (KeyMP=CreatePort(NULL,NULL)) {
                        if (keyHandler=AllocMem(sizeof(struct Interrupt),MEMF_PUBLIC|MEMF_CLEAR)) {
                                if (KeyIO=CreateStdIO(KeyMP)) {
                                        if (!OpenDevice("keyboard.device",NULL,(struct IORequest *)KeyIO,NULL)) {
                                                keyHandler->is_Code=(APTR)&ResetHandler;
                                                keyHandler->is_Data=(APTR)&MyDataStuff;
                                                
                                                /*
                                                 * Note that only software interrupt priorities
                                                 * can be used for the .ln_Pri on the reset
                                                 * handler, that means use ONLY
                                                 * -32,-16,0,16 or 32...
                                                 */
                                                keyHandler->is_Node.ln_Pri=16;
                                                
                                                keyHandler->is_Node.ln_Name=NameString;
                                                KeyIO->io_Data=(APTR)keyHandler;
                                                KeyIO->io_Command=KBD_ADDRESETHANDLER;
                                                DoIO((struct IORequest *)KeyIO);
                                                
                                                if (WaitForUser(MyDataStuff.MySignal)) {
                                                        if (argc) /* Check if run from CLI */ {
                                                                printf("System going down\n");
                                                                printf("Cleaning up...\n");
                                                                /* Do a little countdown, just to have a nice show... */
                                                                for (i=10;i>=0;i--) {
                                                                        printf("%d\n",i);
                                                                        Delay(30L);
                                                                };
                                                                /*
                                                                 * Please node that we've only
                                                                 * 10 (TEN) seconds time to do our reset stuff
                                                                 * After this period the keyboard will hard-reset the computer
                                                                 * without any chance to stop it.
                                                                 *
                                                                 */
                                                                printf("*** POOF ***\n");
                                                                Delay(20L);

                                                        };
                                                        /* We are done with our cleanup */
                                                        
                                                        KeyIO->io_Data=(APTR)keyHandler;
                                                        KeyIO->io_Command=KBD_RESETHANDLERDONE;
                                                        DoIO((struct IORequest *)KeyIO);
                                                        
                                                        /*
                                                         * Note that since the above call
                                                         * tells the system it is sage to reboot
                                                         * and will cause the reboot if this
                                                         * task was the last to say so, the call
                                                         * never really returns... The system
                                                         * just reboots...
                                                         */
                                                         
                                                }
                                                
                                                KeyIO->io_Data=(APTR)keyHandler;
                                                KeyIO->io_Command=KBD_REMRESETHANDLER;
                                                DoIO((struct IORequest *)KeyIO);
                                                
                                                CloseDevice((struct IORequest *)KeyIO);
                                        }
                                        else
                                                printf ("Error: Could not open keyboard.device\n");
                                                
                                        DeleteStdIO(KeyIO);
                                }
                                else
                                        printf("Error: Could not create I/O request\n");
                                        
                                FreeMem(keyHandler,sizeof(struct Interrupt));
                        }
                        else
                                printf("Error: Could not allocate memory for interrupt\n");
                                
                        DeletePort(KeyMP);
                }
                else
                        printf("Error: Could not create message port\n");
                        
                FreeSignal(MySignal);
        }
        else
                printf("Error: Could not allocate signal\n");
                
}
                                                        
                                                
                                                
                                        
