/* * sdstart looks to see if there is a buf waiting for the device * and that the device is not already busy. If both are true, * It dequeues the buf and creates a scsi command to perform the * transfer in the buf. The transfer request will call scsi_done * on completion, which will in turn call this routine again * so that the next queued transfer is performed. * The bufs are queued by the strategy routine (sdstrategy) * * This routine is also called after other non-queued requests * have been made of the scsi driver, to ensure that the queue * continues to be drained. */ void sdstart(struct scsi_xfer *xs) { struct scsi_link *link = xs->sc_link; struct sd_softc *sc = link->device_softc; struct buf *bp; u_int64_t secno; int nsecs; int read; struct partition *p; if (sc->flags & SDF_DYING) { scsi_xs_put(xs); return; } if ((link->flags & SDEV_MEDIA_LOADED) == 0) { bufq_drain(&sc->sc_bufq); scsi_xs_put(xs); return; } bp = bufq_dequeue(&sc->sc_bufq); if (bp == NULL) { scsi_xs_put(xs); return; } secno = DL_BLKTOSEC(sc->sc_dk.dk_label, bp->b_blkno); p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)]; secno += DL_GETPOFFSET(p); nsecs = howmany(bp->b_bcount, sc->sc_dk.dk_label->d_secsize); read = bp->b_flags & B_READ; /* * Fill out the scsi command. If the transfer will * fit in a "small" cdb, use it. */ if (!(link->flags & SDEV_ATAPI) && !(link->quirks & SDEV_ONLYBIG) && ((secno & 0x1fffff) == secno) && ((nsecs & 0xff) == nsecs)) sd_cmd_rw6(xs, read, secno, nsecs); else if (((secno & 0xffffffff) == secno) && ((nsecs & 0xffff) == nsecs)) sd_cmd_rw10(xs, read, secno, nsecs); else if (((secno & 0xffffffff) == secno) && ((nsecs & 0xffffffff) == nsecs)) sd_cmd_rw12(xs, read, secno, nsecs); else sd_cmd_rw16(xs, read, secno, nsecs); xs->flags |= (read ? SCSI_DATA_IN : SCSI_DATA_OUT); xs->timeout = 60000; xs->data = bp->b_data; xs->datalen = bp->b_bcount; xs->done = sd_buf_done; xs->cookie = bp; xs->bp = bp; /* Instrumentation. */ disk_busy(&sc->sc_dk); /* Mark disk as dirty. */ if (!read) sc->flags |= SDF_DIRTY; scsi_xs_exec(xs); /* move onto the next io */ if (ISSET(sc->flags, SDF_WAITING)) CLR(sc->flags, SDF_WAITING); else if (bufq_peek(&sc->sc_bufq)) scsi_xsh_add(&sc->sc_xsh); }
/* * sdstart looks to see if there is a buf waiting for the device * and that the device is not already busy. If both are true, * It dequeues the buf and creates a scsi command to perform the * transfer in the buf. The transfer request will call scsi_done * on completion, which will in turn call this routine again * so that the next queued transfer is performed. * The bufs are queued by the strategy routine (sdstrategy) * * This routine is also called after other non-queued requests * have been made of the scsi driver, to ensure that the queue * continues to be drained. */ void sdstart(void *v) { struct sd_softc *sc = (struct sd_softc *)v; struct scsi_link *link = sc->sc_link; struct scsi_xfer *xs; struct buf *bp; daddr64_t blkno; int nblks; int read; struct partition *p; int s; if (sc->flags & SDF_DYING) return; SC_DEBUG(link, SDEV_DB2, ("sdstart\n")); mtx_enter(&sc->sc_start_mtx); if (ISSET(sc->flags, SDF_STARTING)) { mtx_leave(&sc->sc_start_mtx); return; } SET(sc->flags, SDF_STARTING); mtx_leave(&sc->sc_start_mtx); CLR(sc->flags, SDF_WAITING); while (!ISSET(sc->flags, SDF_WAITING) && (bp = sd_buf_dequeue(sc)) != NULL) { /* * If the device has become invalid, abort all the * reads and writes until all files have been closed and * re-opened */ if ((link->flags & SDEV_MEDIA_LOADED) == 0) { bp->b_error = EIO; bp->b_flags |= B_ERROR; bp->b_resid = bp->b_bcount; s = splbio(); biodone(bp); splx(s); continue; } xs = scsi_xs_get(link, SCSI_NOSLEEP); if (xs == NULL) { sd_buf_requeue(sc, bp); break; } blkno = bp->b_blkno / (sc->sc_dk.dk_label->d_secsize / DEV_BSIZE); p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)]; blkno += DL_GETPOFFSET(p); nblks = howmany(bp->b_bcount, sc->sc_dk.dk_label->d_secsize); read = bp->b_flags & B_READ; /* * Fill out the scsi command. If the transfer will * fit in a "small" cdb, use it. */ if (!(link->flags & SDEV_ATAPI) && !(link->quirks & SDEV_ONLYBIG) && ((blkno & 0x1fffff) == blkno) && ((nblks & 0xff) == nblks)) sd_cmd_rw6(xs, read, blkno, nblks); else if (((blkno & 0xffffffff) == blkno) && ((nblks & 0xffff) == nblks)) sd_cmd_rw10(xs, read, blkno, nblks); else if (((blkno & 0xffffffff) == blkno) && ((nblks & 0xffffffff) == nblks)) sd_cmd_rw12(xs, read, blkno, nblks); else sd_cmd_rw16(xs, read, blkno, nblks); xs->flags |= (read ? SCSI_DATA_IN : SCSI_DATA_OUT); xs->timeout = 60000; xs->data = bp->b_data; xs->datalen = bp->b_bcount; xs->done = sd_buf_done; xs->cookie = bp; /* Instrumentation. */ disk_busy(&sc->sc_dk); /* Mark disk as dirty. */ if ((bp->b_flags & B_READ) == 0) sc->flags |= SDF_DIRTY; scsi_xs_exec(xs); } mtx_enter(&sc->sc_start_mtx); CLR(sc->flags, SDF_STARTING); mtx_leave(&sc->sc_start_mtx); }