Example #1
0
/*
 *  read or write to floppy.  try up to three times.
 */
static long
floppyxfer(FDrive *dp, int cmd, void *a, long off, long n)
{
    long offset;
    int tries;

    if(off >= dp->t->cap)
        return 0;
    if(off + n > dp->t->cap)
        n = dp->t->cap - off;

    /* retry on error (until it gets ridiculous) */
    for(tries = 0; tries < dp->maxtries; tries++) {

        dp->len = n;
        if(pcfloppyseek(dp, off) < 0) {
            DPRINT("xfer: seek failed\n");
            dp->confused = 1;
            continue;
        }

        /*
         *  set up the dma (dp->len may be trimmed)
         */
        dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);
        if(dp->len < 0) {
buggery:
            dmaend(DMAchan);
            continue;
        }

        /*
         *  start operation
         */
        fl.ncmd = 0;
        fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0);
        fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
        fl.cmd[fl.ncmd++] = dp->tcyl;
        fl.cmd[fl.ncmd++] = dp->thead;
        fl.cmd[fl.ncmd++] = dp->tsec;
        fl.cmd[fl.ncmd++] = dp->t->bcode;
        fl.cmd[fl.ncmd++] = dp->t->sectors;
        fl.cmd[fl.ncmd++] = dp->t->gpl;
        fl.cmd[fl.ncmd++] = 0xFF;
        if(floppycmd() < 0)
            goto buggery;

        /*
         *  give bus to DMA, floppyintr() will read result
         */
        floppywait(0);
        dmaend(DMAchan);

        /*
         *  check for errors
         */
        if(fl.nstat < 7) {
            DPRINT("xfer: confused\n");
            fl.confused = 1;
            continue;
        }
        if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]) {
            DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0],
                   fl.stat[1], fl.stat[2]);
            DPRINT("offset %lud len %ld\n", off, dp->len);
            if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun) {
                DPRINT("DMA overrun: retry\n");
            } else
                dp->confused = 1;
            continue;
        }

        /*
         *  check for correct cylinder
         */
        offset = fl.stat[3] * dp->t->heads + fl.stat[4];
        offset = offset*dp->t->sectors + fl.stat[5] - 1;
        offset = offset * c2b[fl.stat[6]];
        if(offset != off+dp->len) {
            DPRINT("xfer: ends on wrong cyl\n");
            dp->confused = 1;
            continue;
        }

        dp->lasttouched = m->ticks;
        dp->maxtries = 20;
        return dp->len;
    }

    return -1;
}
Example #2
0
/*
 *  format a track
 */
static void
floppyformat(FDrive *dp, Cmdbuf *cb)
{
 	int cyl, h, sec;
	ulong track;
	uchar *buf, *bp;
	FType *t;

	/*
	 *  set the type
	 */
	if(cb->nf == 2){
		for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
			if(strcmp(cb->f[1], t->name)==0 && t->dt==dp->dt){
				dp->t = t;
				floppydir[1+NFDIR*dp->dev].length = dp->t->cap;
				break;
			}
		}
		if(t >= &floppytype[nelem(floppytype)])
			error(Ebadarg);
	} else if(cb->nf == 1){
		floppysetdef(dp);
		t = dp->t;
	} else {
		cmderror(cb, "invalid floppy format command");
		SET(t);
	}

	/*
	 *  buffer for per track info
	 */
	buf = smalloc(t->sectors*4);
	if(waserror()){
		free(buf);
		nexterror();
	}

	/* force a recalibrate to cylinder 0 */
	dp->confused = 1;
	if(!waserror()){
		floppyon(dp);
		poperror();
	}

	/*
	 *  format a track at time
	 */
	for(track = 0; track < t->tracks*t->heads; track++){
		cyl = track/t->heads;
		h = track % t->heads;

		/*
		 *  seek to track, ignore errors
		 */
		floppyseek(dp, track*t->tsize);
		dp->cyl = cyl;
		dp->confused = 0;

		/*
		 *  set up the dma (dp->len may be trimmed)
		 */
		bp = buf;
		for(sec = 1; sec <= t->sectors; sec++){
			*bp++ = cyl;
			*bp++ = h;
			*bp++ = sec;
			*bp++ = t->bcode;
		}
		if(waserror()){
			dmaend(DMAchan);
			nexterror();
		}
		if(dmasetup(DMAchan, buf, bp-buf, 0) < 0)
			error(Eio);

		/*
		 *  start operation
		 */
		fl.ncmd = 0;
		fl.cmd[fl.ncmd++] = Fformat;
		fl.cmd[fl.ncmd++] = (h<<2) | dp->dev;
		fl.cmd[fl.ncmd++] = t->bcode;
		fl.cmd[fl.ncmd++] = t->sectors;
		fl.cmd[fl.ncmd++] = t->fgpl;
		fl.cmd[fl.ncmd++] = 0x5a;
		if(floppycmd() < 0)
			error(Eio);

		/* Poll ready bits and transfer data */
		floppyexec((char *)buf, bp-buf, 0);

		/*
		 *  give bus to DMA, floppyintr() will read result
		 */
		floppywait(1);
		dmaend(DMAchan);
		poperror();

		/*
		 *  check for errors
		 */
		if(fl.nstat < 7){
			DPRINT("format: confused\n");
			fl.confused = 1;
			error(Eio);
		}
		if((fl.stat[0]&Codemask)!=0 || fl.stat[1]|| fl.stat[2]){
			DPRINT("format: failed %ux %ux %ux\n",
				fl.stat[0], fl.stat[1], fl.stat[2]);
			dp->confused = 1;
			error(Eio);
		}
	}
	free(buf);
	dp->confused = 1;
	poperror();
}