/* * Actually translate the requested transfer into one the physical driver * can understand. The transfer is described by a buf and will include * only one physical transfer. */ void sdstrategy(struct buf *bp) { struct sd_softc *sc; int s; sc = sdlookup(DISKUNIT(bp->b_dev)); if (sc == NULL) { bp->b_error = ENXIO; goto bad; } if (sc->flags & SDF_DYING) { bp->b_error = ENXIO; goto bad; } SC_DEBUG(sc->sc_link, SDEV_DB2, ("sdstrategy: %ld bytes @ blk %lld\n", bp->b_bcount, (long long)bp->b_blkno)); /* * If the device has been made invalid, error out */ if ((sc->sc_link->flags & SDEV_MEDIA_LOADED) == 0) { if (sc->sc_link->flags & SDEV_OPEN) bp->b_error = EIO; else bp->b_error = ENODEV; goto bad; } /* Validate the request. */ if (bounds_check_with_label(bp, sc->sc_dk.dk_label) == -1) goto done; /* Place it in the queue of disk activities for this disk. */ bufq_queue(&sc->sc_bufq, bp); /* * Tell the device to get going on the transfer if it's * not doing anything, otherwise just wait for completion */ scsi_xsh_add(&sc->sc_xsh); device_unref(&sc->sc_dev); return; bad: bp->b_flags |= B_ERROR; bp->b_resid = bp->b_bcount; done: s = splbio(); biodone(bp); splx(s); if (sc != NULL) device_unref(&sc->sc_dev); }
/* * Read/write routine for a buffer. Validates the arguments and schedules the * transfer. Does not wait for the transfer to complete. */ void wdstrategy(struct buf *bp) { struct wd_softc *wd; int s; wd = wdlookup(DISKUNIT(bp->b_dev)); if (wd == NULL) { bp->b_error = ENXIO; goto bad; } WDCDEBUG_PRINT(("wdstrategy (%s)\n", wd->sc_dev.dv_xname), DEBUG_XFERS); /* If device invalidated (e.g. media change, door open), error. */ if ((wd->sc_flags & WDF_LOADED) == 0) { bp->b_error = EIO; goto bad; } /* Validate the request. */ if (bounds_check_with_label(bp, wd->sc_dk.dk_label) == -1) goto done; /* Check that the number of sectors can fit in a byte. */ if ((bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) { bp->b_error = EINVAL; goto bad; } /* Queue transfer on drive, activate drive and controller if idle. */ bufq_queue(&wd->sc_bufq, bp); s = splbio(); wdstart(wd); splx(s); device_unref(&wd->sc_dev); return; bad: bp->b_flags |= B_ERROR; bp->b_resid = bp->b_bcount; done: s = splbio(); biodone(bp); splx(s); if (wd != NULL) device_unref(&wd->sc_dev); }
/* * Pass I/O requests to the memory filesystem process. */ int mfs_strategy(void *v) { struct vop_strategy_args *ap = v; struct buf *bp = ap->a_bp; struct mfsnode *mfsp; struct vnode *vp; struct proc *p = curproc; if (!vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0) panic("mfs_strategy: bad dev"); mfsp = VTOMFS(vp); if (p != NULL && mfsp->mfs_pid == p->p_pid) { mfs_doio(mfsp, bp); } else { bufq_queue(&mfsp->mfs_bufq, bp); wakeup(vp); } return (0); }
/* * MTP_UNITDATA_IND 20 - Connection-less data receive indication * ------------------------------------------------------------------------- * N_UNITDATA_IND (MTP_TRANSFER_IND) * ------------------------------------------------------------------------- * This covers only the MTP-TRANSFER-Indication primitive. * * Let me ask a question here: why dont we just pass the unitdata on to the * ASP and let the ASP translate it into an M3UA message. That way, if there * are different ASPs supporting different versions, that can be handled at * the ASP instead of here. Also, we don't know the transport type. If it * is an SCTP transport, it can do other things with the message, like select * stream. */ static int mtpp_unitdata_ind(queue_t *q, mblk_t *msg) { sls_t *sls; queue_t *wq; mtpp_t *mtp = Q_MTP(q); mblk_t *mp, *db = msg->b_cont; size_t dlen = msgdsize(db); N_unitdata_ind_t *p = (N_unitdata_req_t *) msg->b_rptr; struct mtp_rl *rl = (mtp_rt *) (((caddr_t) p) + p->SRC_offset); static const size_t mlen = M3UA_MHDR_SIZE + M3UA_PARM_SIZE_RC + M3UA_PARM_SIZE_RL + M3UA_PHDR_SIZE; /* * First let's find out where the data is going. The AS should have * this all set up for us in the SLS tables. */ ensure(mtp, return (-EFAULT)); ensure(mtp->rc, return (-EFAULT)); ensure(mtp->rc->as, return (-EFAULT)); sls = &mtp->rc->as->sls[(rl->sls & UA_SLS_MASK)]; ensure(sls->sp, return (-EFAULT)); ensure(sls->sp->lp, return (-EFAULT)); ensure(sls->sp->lp->q, return (-EFAULT)); if (!(sls->flags & UA_SLS_BUFFERING)) if (!(canput((wq = WR(sls->sp->lp->q))))) return (-EBUSY); /* apply backpressure! */ if ((mp = allocb(mlen, BPRI_MED))) { mp->b_datap->db_type = M_DATA; *((uint32_t *) mp->b_wptr)++ = M3UA_MAUP_DATA; *((uint32_t *) mp->b_wptr)++ = htonl(mlen + dlen); *((uint32_t *) mp->b_wptr)++ = M3UA_PARM_NA; *((uint32_t *) mp->b_wptr)++ = htonl(mtp->na); *((uint32_t *) mp->b_wptr)++ = M3UA_PARM_RC; *((uint32_t *) mp->b_wptr)++ = htonl(mtp->rc); /* * A couple of big arguments on what should be in the * messages here... */ *((uint32_t *) mp->b_wptr)++ = M3UA_PARM_RL; *((uint32_t *) mp->b_wptr)++ = hotnl(rl->opc); *((uint32_t *) mp->b_wptr)++ = hotnl(rl->dpc); *((uint8_t *) mp->b_wptr)++ = 0; *((uint8_t *) mp->b_wptr)++ = hotnl(rl->sls); *((uint8_t *) mp->b_wptr)++ = hotnl(rl->ni); *((uint8_t *) mp->b_wptr)++ = hotnl(rl->mp); *((uint32_t *) mp->b_wptr)++ = M3UA_PARM_DATA; mp->b_cont = db; freeb(msg); if (sls->flags & UA_SLS_BUFFERING) /* hold back data for this sls */ bufq_queue(&sls->buf, mp); else putq(wq, mp); return (0); } return (-ENOBUFS); /* try again later */ }
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); }