/* SCRUB -- a program to spin the motor on an Amiga floppy drive and move the
head back and forth for thirty seconds while a disk cleaner is inserted in
it.  It searches for the lowest numbered drive that has a non-Dos disk in it,
and that's the one it spins.

11/21/90 made it move the head to more different cylinders starting from one
of ten random first cylinders, and recompiled with aztec 5.0 instead of 3.6

12/24/90  oops!  made it notice if you remove the disk in the middle
*/


#include <devices/trackdisk.h>
#include <libraries/dosextens.h>
#include <Paul.h>


#undef put

void put(s) register str s;
{
    register BPTR o = Output();
    if (o) Write(o, s, (long) strlen(s));
}



long _main()
{
    int drive;
    static char dame[] = "df#:";
    struct InfoData *fo = New(struct InfoData);
    struct Process *me = ThisProcess();
    struct MsgPort *p;
    APTR e = me->pr_WindowPtr;
    struct Message *wbs = null;
    void Clean();

    if (!me->pr_CLI) {
	WaitPort(&me->pr_MsgPort);
	wbs = GetMsg(&me->pr_MsgPort);
    }
    me->pr_WindowPtr = (APTR) -1;
    if (!fo)
	put("No memory!\n");
    else {
	for (drive = 0; drive <= 3; drive++) {
	    dame[2] = drive + '0';
	    if ((p = DeviceProc(dame)) &&
			dos_packet(p, ACTION_DISK_INFO, (long) fo >> 2) &&
			fo->id_DiskType == ID_UNREADABLE_DISK) {
		Clean((long) drive);
		break;
	    }
	}
	if (drive > 3)
	    put("Couldn't find a drive with a cleaner in it.\n");
	Free(struct InfoData, fo);
    }
    me->pr_WindowPtr = e;
    if (wbs) {
	Forbid();
	ReplyMsg(wbs);
    }
    return (0L);
}



#define DIVISIONS 30
#define WEIRDNESS 22

void Clean(unit) long unit;
{
    struct DateStamp date_with_rosie_palm;
    struct IOExtTD *qxt = NewPZ(struct IOExtTD);
    short track, trax, tout;
    ulong changes;
#define qr qxt->iotd_Req
#define q ((struct IORequest *) qxt)

    if (!q) {
	put("Out of memory!");
	return;
    }
    qr.io_Message.mn_ReplyPort = &ThisProcess()->pr_MsgPort;
    if (OpenDevice(TD_NAME, unit, q, TDF_ALLOW_NON_3_5)) {
	put("Couldn't open device!\n");
	Free(struct IOExtTD, q);
	return;
    }
    qr.io_Command = TD_GETNUMTRACKS;
    DoIO(q);
    trax = qr.io_Actual;
    qr.io_Command = TD_CHANGENUM;
    DoIO(q);
    changes = qr.io_Actual;
    qr.io_Command = TD_MOTOR;
    qr.io_Length = 1;			/* ON */
    DoIO(q);
    DateStamp(&date_with_rosie_palm);
    track = (date_with_rosie_palm.ds_Tick / TICKS_PER_SECOND) % 10;
    qr.io_Command = ETD_SEEK;
    qxt->iotd_Count = changes;
    for (tout = 0; tout < DIVISIONS; tout++) {
	qr.io_Offset = track * (NUMSECS << TD_SECSHIFT);
	DoIO(q);
	if (qr.io_Error == TDERR_DiskChanged) {
	    put("You popped the disk out!\n");
	    break;
	}
	Delay(1500L / DIVISIONS);
	track = (track + WEIRDNESS) % trax;
    }
    DoIO(q);
    qr.io_Command = TD_MOTOR;
    qr.io_Length = 0;			/* OFF */
    DoIO(q);
    CloseDevice(q);
    Free(struct IOExtTD, q);
}
