Beispiel #1
0
/*
 *  check if the floppy has been replaced under foot.  cause
 *  an error if it has.
 *
 *  a seek and a read clears the condition.  this was determined
 *  experimentally, there has to be a better way.
 *
 *  if the read fails, cycle through the possible floppy
 *  density till one works or we've cycled through all
 *  possibilities for this drive.
 */
static void
changed(Chan *c, FDrive *dp)
{
	ulong old;
	FType *start;

	/*
	 *  if floppy has changed or first time through
	 */
	if((inb(Pdir)&Fchange) || dp->vers == 0){
		DPRINT("changed\n");
		fldump();
		dp->vers++;
		start = dp->t;
		dp->maxtries = 3;	/* limit it when we're probing */

		/* floppyon will fail if there's a controller but no drive */
		dp->confused = 1;	/* make floppyon recal */
		if(floppyon(dp) < 0)
			error(Eio);

		/* seek to the first track */
		floppyseek(dp, dp->t->heads*dp->t->tsize);
		while(waserror()){
			/*
			 *  if first attempt doesn't reset changed bit, there's
			 *  no floppy there
			 */
			if(inb(Pdir)&Fchange)
				nexterror();

			while(++dp->t){
				if(dp->t == &floppytype[nelem(floppytype)])
					dp->t = floppytype;
				if(dp->dt == dp->t->dt)
					break;
			}
			floppydir[1+NFDIR*dp->dev].length = dp->t->cap;

			/* floppyon will fail if there's a controller but no drive */
			if(floppyon(dp) < 0)
				error(Eio);

			DPRINT("changed: trying %s\n", dp->t->name);
			fldump();
			if(dp->t == start)
				nexterror();
		}

		/* if the read succeeds, we've got the density right */
		floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize);
		poperror();
		dp->maxtries = 20;
	}

	old = c->qid.vers;
	c->qid.vers = dp->vers;
	if(old && old != dp->vers)
		error(Eio);
}
Beispiel #2
0
/*
 *  check if the floppy has been replaced under foot.  cause
 *  an error if it has.
 *
 *  a seek and a read clears the condition.  this was determined
 *  experimentally, there has to be a better way.
 *
 *  if the read fails, cycle through the possible floppy
 *  density till one works or we've cycled through all
 *  possibilities for this drive.
 */
static int
changed(FDrive *dp)
{
    FType *start;

    /*
     *  if floppy has changed or first time through
     */
    if((inb(Pdir)&Fchange) || dp->vers == 0) {
        DPRINT("changed\n");
        fldump();
        dp->vers++;
        floppysetdef(dp);
        dp->maxtries = 3;
        start = dp->t;

        /* flopppyon fails if there's no drive */
        dp->confused = 1;	/* make floppyon recal */
        if(floppyon(dp) < 0)
            return -1;

        pcfloppyseek(dp, dp->t->heads*dp->t->tsize);

        while(floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize) <= 0) {

            /*
             *  if the xfer attempt doesn't clear the changed bit,
             *  there's no floppy in the drive
             */
            if(inb(Pdir)&Fchange)
                return -1;

            while(++dp->t) {
                if(dp->t == &floppytype[nelem(floppytype)])
                    dp->t = floppytype;
                if(dp->dt == dp->t->dt)
                    break;
            }

            /* flopppyon fails if there's no drive */
            if(floppyon(dp) < 0)
                return -1;

            DPRINT("changed: trying %s\n", dp->t->name);
            fldump();
            if(dp->t == start)
                return -1;
        }
    }

    return 0;
}
Beispiel #3
0
/*
 *  get a command result from the floppy
 *
 *  when the controller goes ready waiting for a command
 *  (instead of sending results), we're done
 *
 */
static int
floppyresult(void)
{
    int i, s;
    int tries;

    /* get the result of the operation */
    for(i = 0; i < sizeof(fl.stat); i++) {
        /* wait for status byte */
        for(tries = 0; ; tries++) {
            s = inb(Pmsr)&(Ffrom|Fready);
            if(s == Fready) {
                fl.nstat = i;
                return fl.nstat;
            }
            if(s == (Ffrom|Fready))
                break;
            if(tries > 1000) {
                DPRINT("floppyresult: %d stats\n", i);
                fldump();
                fl.confused = 1;
                return -1;
            }
            microdelay(1);
        }
        fl.stat[i] = inb(Pfdata);
    }
    fl.nstat = sizeof(fl.stat);
    return fl.nstat;
}
Beispiel #4
0
/*
 *  send a command to the floppy
 */
static int
floppycmd(void)
{
    int i;
    int tries;

    fl.nstat = 0;
    for(i = 0; i < fl.ncmd; i++) {
        for(tries = 0; ; tries++) {
            if((inb(Pmsr)&(Ffrom|Fready)) == Fready)
                break;
            if(tries > 1000) {
                DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i);
                fldump();

                /* empty fifo, might have been a bad command */
                floppyresult();
                return -1;
            }
            microdelay(1);
        }
        outb(Pfdata, fl.cmd[i]);
    }
    return 0;
}
Beispiel #5
0
/*
 *  if the controller or a specific drive is in a confused state,
 *  reset it and get back to a kown state
 */
static void
floppyrevive(void)
{
    FDrive *dp;

    /*
     *  reset the controller if it's confused
     */
    if(fl.confused) {
        DPRINT("floppyrevive in\n");
        fldump();

        /* reset controller and turn all motors off */
        splhi();
        fl.ncmd = 1;
        fl.cmd[0] = 0;
        outb(Pdor, 0);
        delay(10);
        outb(Pdor, Fintena|Fena);
        delay(10);
        spllo();
        fl.motor = 0;
        fl.confused = 0;
        floppywait(0);

        /* mark all drives in an unknown state */
        for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++)
            dp->confused = 1;

        /* set rate to a known value */
        outb(Pdsr, 0);
        fl.rate = 0;

        DPRINT("floppyrevive out\n");
        fldump();
    }
}
Beispiel #6
0
/*
 *  get the interrupt cause from the floppy.
 */
static int
floppysense(void)
{
    fl.ncmd = 0;
    fl.cmd[fl.ncmd++] = Fsense;
    if(floppycmd() < 0)
        return -1;
    if(floppyresult() < 2) {
        DPRINT("can't read sense response\n");
        fldump();
        fl.confused = 1;
        return -1;
    }
    return 0;
}