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); }
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); }
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); }
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); }