Exemplo n.º 1
0
void
fdstart(struct fd_softc *fd)
{
	struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
	int active = !TAILQ_EMPTY(&fdc->sc_link.fdlink.sc_drives);

	/* Link into controller queue. */
	fd->sc_bp = bufq_dequeue(&fd->sc_bufq);
	TAILQ_INSERT_TAIL(&fdc->sc_link.fdlink.sc_drives, fd, sc_drivechain);

	/* If controller not already active, start it. */
	if (!active)
		fdcstart(fdc);
}
Exemplo n.º 2
0
void
fdstart(struct fd_softc *fd)
{
	struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev));
	int active = !TAILQ_EMPTY(&fdc->sc_drives);

	KASSERT(mutex_owned(&fdc->sc_mtx));
	/* Link into controller queue. */
	fd->sc_active = 1;
	TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);

	/* If controller not already active, start it. */
	if (!active)
		fdcstart(fdc);
}
Exemplo n.º 3
0
void
fdstrategy(struct buf *bp)
{
	struct fd_softc *fd = device_lookup_private(&fd_cd, FDUNIT(bp->b_dev));
	struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev));
	int sz;

	/* Valid unit, controller, and request? */
	if (bp->b_blkno < 0 ||
	    ((bp->b_bcount % FDC_BSIZE) != 0 &&
	     (bp->b_flags & B_FORMAT) == 0)) {
		bp->b_error = EINVAL;
		goto done;
	}

	/* If it's a null transfer, return immediately. */
	if (bp->b_bcount == 0)
		goto done;

	sz = howmany(bp->b_bcount, FDC_BSIZE);

	if (bp->b_blkno + sz > fd->sc_type->size) {
		sz = fd->sc_type->size - bp->b_blkno;
		if (sz == 0) {
			/* If exactly at end of disk, return EOF. */
			goto done;
		}
		if (sz < 0) {
			/* If past end of disk, return EINVAL. */
			bp->b_error = EINVAL;
			goto done;
		}
		/* Otherwise, truncate request. */
		bp->b_bcount = sz << DEV_BSHIFT;
	}

	bp->b_rawblkno = bp->b_blkno;
 	bp->b_cylinder =
	    bp->b_blkno / (FDC_BSIZE / DEV_BSIZE) / fd->sc_type->seccyl;

#ifdef FD_DEBUG
	printf("fdstrategy: b_blkno %llu b_bcount %d blkno %llu cylin %d "
	    "sz %d\n", (unsigned long long)bp->b_blkno, bp->b_bcount,
	    (unsigned long long)fd->sc_blkno, bp->b_cylinder, sz);
#endif

	/* Queue transfer on drive, activate drive and controller if idle. */
	mutex_enter(&fdc->sc_mtx);
	BUFQ_PUT(fd->sc_q, bp);
	callout_stop(&fd->sc_motoroff_ch);		/* a good idea */
	if (fd->sc_active == 0)
		fdstart(fd);
#ifdef DIAGNOSTIC
	else {
		if (fdc->sc_state == DEVIDLE) {
			printf("fdstrategy: controller inactive\n");
			fdcstart(fdc);
		}
	}
#endif
	mutex_exit(&fdc->sc_mtx);
	return;

done:
	/* Toss transfer; we're done early. */
	bp->b_resid = bp->b_bcount;
	biodone(bp);
}
Exemplo n.º 4
0
void
fdstrategy(struct buf *bp)
{
	struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(bp->b_dev)];
	int sz;
 	int s;
	int fd_bsize = FD_BSIZE(fd);
	int bf = fd_bsize / DEV_BSIZE;

	/* Valid unit, controller, and request? */
	if (bp->b_blkno < 0 ||
	    (((bp->b_blkno % bf) != 0 ||
	      (bp->b_bcount % fd_bsize) != 0) &&
	     (bp->b_flags & B_FORMAT) == 0)) {
		bp->b_error = EINVAL;
		goto bad;
	}

	/* If it's a null transfer, return immediately. */
	if (bp->b_bcount == 0)
		goto done;

	sz = howmany(bp->b_bcount, DEV_BSIZE);

	if (bp->b_blkno + sz > fd->sc_type->size * bf) {
		sz = fd->sc_type->size * bf - bp->b_blkno;
		if (sz == 0)
			/* If exactly at end of disk, return EOF. */
			goto done;
		if (sz < 0) {
			/* If past end of disk, return EINVAL. */
			bp->b_error = EINVAL;
			goto bad;
		}
		/* Otherwise, truncate request. */
		bp->b_bcount = sz << DEV_BSHIFT;
	}

	bp->b_resid = bp->b_bcount;

#ifdef FD_DEBUG
	printf("fdstrategy: b_blkno %lld b_bcount %d blkno %lld sz %d\n",
	    (long long)bp->b_blkno, bp->b_bcount,
	    (long long)fd->sc_blkno, sz);
#endif

	/* Queue I/O */
	bufq_queue(&fd->sc_bufq, bp);

	/* Queue transfer on drive, activate drive and controller if idle. */
	s = splbio();
	timeout_del(&fd->fd_motor_off_to); /* a good idea */
	if (fd->sc_bp == NULL)
		fdstart(fd);
#ifdef DIAGNOSTIC
	else {
		struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
		if (fdc->sc_state == DEVIDLE) {
			printf("fdstrategy: controller inactive\n");
			fdcstart(fdc);
		}
	}
#endif
	splx(s);
	return;

bad:
	bp->b_flags |= B_ERROR;
done:
	/* Toss transfer; we're done early. */
	bp->b_resid = bp->b_bcount;
	s = splbio();
	biodone(bp);
	splx(s);
}