/*
    Find the disk speed, in RPM (revolutions per minute)
    Copyright (C) 1989  by Robert Fischer

	This program costs no money; you can redistribute it and/or modify it
	under the terms of the Lynxware General License as published by Robert
	Fischer; either version 1, or (at your option) any later version. 

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    Lynxware General License for more details.

    You should have received a copy of the Lynxware General License
    along with this program; if not, write to the author.

    To contact the author, call or write:
        Robert Fischer
        80 Killdeer Road
        Hamden, CT    06517
        (203) 288-9599
		E-mail: fischer-robert@cs.yale.edu
*/

#include <stdio.h>

/* ================= Pulled from my Include files ================== */
#define HZ_200          *( (LONG *)0x4BAL )

#define Cconout(a)          gemdos(0x2,a)
#define Cnecin()            gemdos(0x8)
#define Cconws(a)           gemdos(0x9,a)
#define Super(a)            gemdos(0x20,(LONG)(a))
#define Dfree(a,b)          gemdos(0x36,a,b)
#define Getbpb(a)           bios(7,a)
#define Rwabs(a,b,c,d,e)    bios(4,a,(LONG)b,c,d,e)

#   define B_READ 0
#   define B_WRITE 1
#   define B_READ_NOCHANGE 2
#   define B_WRITE_NOCHANGE 3
#   define FLOP_A 0
#   define FLOP_B 1

extern char *lmalloc();
extern long bios();
extern long xbios();
extern long gemdos();

typedef unsigned long LONG;

/* ------------------------------------------------------- */
static char address[] = "\
                  80 Killdeer Road\r\n\
                  Hamden, CT  06517  USA\r\n\
                  (203) 288-9599\r\n";
char buf[512];
#define NUM_TIMES 100
#define COPYRIGHT 0xbd
/* ----------------------------------------------------------- */
waituser()
{
    printf("(Please press <return> to continue)");
    getchar();
}
/* ------------------------------------------------------- */
usage()
{
        Cconws("DSPEED floppy drive speed check 1.0 Copyright \275 1989 by Robert Fischer\r\n");
        Cconws(address);
		Cconws("DSPEED comes with ABSOLUTELY NO WARRANTY.\r\n"
		"This program is Lynxware and is subject to the terms of the Lynxware\r\n"
		"General License; either version 1, or (at your option) any later version.\r\n\n"
		);
        Cconws("Usage:  DSPEED drive[:]\r\n");
        waituser();
        exit(1);
}
/* ----------------------------------------------------------- */
long clock()
{
LONG usp;
long ret;
    usp = Super(0);
    ret = HZ_200;
    Super(usp);
    return ret;
}
/* ------------------------------------------------------- */
move_disk(drive)
int drive;
{
long err;
   
    if (err = Rwabs(B_READ, buf, 1, 17, drive)) {
        printf("Disk error # %ld -- aborting dspeed\n", err);
        waituser();
        exit(1);
    }
}
/* ----------------------------------------------------------- */
int
testdisk(drive)
int drive;
{
int i;
long start_time;
long time;
int rpm;
    Dfree(buf, drive+1);    /* Recognize new disk, if any */
    move_disk(drive);       /* Get drive started and up to speed */

    start_time = clock();   /* Time NUM_TIMES accesses */
    for (i = 0; i < NUM_TIMES; i++) move_disk(drive);
    time = clock();

    rpm = ((NUM_TIMES * 24000L) / (time - start_time) + 1L) / 2L;
    return rpm;
}
/* ----------------------------------------------------------- */
main(argc, argv)
int argc;
char *argv[];
{
    int drive;
    int rpm;
    
    if (argc <= 1 || argc >= 3) usage();
    switch (*(argv[1])) {
        case 'A':
        case 'a':   drive = FLOP_A; break;
        case 'B':
        case 'b':   drive = FLOP_B; break;
        default :   usage();
    }
    
    printf("Please insert a disk in drive %c: and press <return>",
             'A'+drive);
    getchar();
    printf("Please wait --- the disk will run for approximately %d seconds\n",
            NUM_TIMES/5);
    rpm = testdisk(drive);
    printf("The disk spins at %d RPM\n", rpm);
    waituser();
}
