static int
ptopen(struct cdev *dev, int flags, int fmt, struct thread *td)
{
	struct cam_periph *periph;
	struct pt_softc *softc;
	int error = 0;

	periph = (struct cam_periph *)dev->si_drv1;
	if (cam_periph_acquire(periph) != CAM_REQ_CMP)
		return (ENXIO);	

	softc = (struct pt_softc *)periph->softc;

	cam_periph_lock(periph);
	if (softc->flags & PT_FLAG_DEVICE_INVALID) {
		cam_periph_unlock(periph);
		cam_periph_release(periph);
		return(ENXIO);
	}

	if ((softc->flags & PT_FLAG_OPEN) == 0)
		softc->flags |= PT_FLAG_OPEN;
	else {
		error = EBUSY;
		cam_periph_release(periph);
	}

	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
	    ("ptopen: dev=%s\n", devtoname(dev)));

	cam_periph_unlock(periph);
	return (error);
}
示例#2
0
static int
adaclose(struct disk *dp)
{
	struct	cam_periph *periph;
	struct	ada_softc *softc;
	union ccb *ccb;
	int error;

	periph = (struct cam_periph *)dp->d_drv1;
	if (periph == NULL)
		return (ENXIO);	

	cam_periph_lock(periph);
	if ((error = cam_periph_hold(periph, PRIBIO)) != 0) {
		cam_periph_unlock(periph);
		cam_periph_release(periph);
		return (error);
	}

	softc = (struct ada_softc *)periph->softc;
	/* We only sync the cache if the drive is capable of it. */
	if ((softc->flags & ADA_FLAG_CAN_FLUSHCACHE) != 0 &&
	    (softc->flags & ADA_FLAG_PACK_INVALID) == 0) {

		ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
		cam_fill_ataio(&ccb->ataio,
				    1,
				    adadone,
				    CAM_DIR_NONE,
				    0,
				    NULL,
				    0,
				    ada_default_timeout*1000);

		if (softc->flags & ADA_FLAG_CAN_48BIT)
			ata_48bit_cmd(&ccb->ataio, ATA_FLUSHCACHE48, 0, 0, 0);
		else
			ata_28bit_cmd(&ccb->ataio, ATA_FLUSHCACHE, 0, 0, 0);
		cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0,
		    /*sense_flags*/0, softc->disk->d_devstat);

		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
			xpt_print(periph->path, "Synchronize cache failed\n");

		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
			cam_release_devq(ccb->ccb_h.path,
					 /*relsim_flags*/0,
					 /*reduction*/0,
					 /*timeout*/0,
					 /*getcount_only*/0);
		xpt_release_ccb(ccb);
	}

	softc->flags &= ~ADA_FLAG_OPEN;
	cam_periph_unhold(periph);
	cam_periph_unlock(periph);
	cam_periph_release(periph);
	return (0);	
}
示例#3
0
static cam_status
ptctor(struct cam_periph *periph, void *arg)
{
	struct pt_softc *softc;
	struct ccb_getdev *cgd;

	cgd = (struct ccb_getdev *)arg;
	if (periph == NULL) {
		kprintf("ptregister: periph was NULL!!\n");
		return(CAM_REQ_CMP_ERR);
	}

	if (cgd == NULL) {
		kprintf("ptregister: no getdev CCB, can't register device\n");
		return(CAM_REQ_CMP_ERR);
	}

	softc = kmalloc(sizeof(*softc), M_DEVBUF, M_INTWAIT | M_ZERO);
	LIST_INIT(&softc->pending_ccbs);
	softc->state = PT_STATE_NORMAL;
	bioq_init(&softc->bio_queue);

	softc->io_timeout = SCSI_PT_DEFAULT_TIMEOUT * 1000;

	periph->softc = softc;
	
	cam_periph_unlock(periph);
	cam_extend_set(ptperiphs, periph->unit_number, periph);

	devstat_add_entry(&softc->device_stats, "pt",
			  periph->unit_number, 0,
			  DEVSTAT_NO_BLOCKSIZE,
			  SID_TYPE(&cgd->inq_data) | DEVSTAT_TYPE_IF_SCSI,
			  DEVSTAT_PRIORITY_OTHER);

	make_dev(&pt_ops, periph->unit_number, UID_ROOT,
		  GID_OPERATOR, 0600, "%s%d", periph->periph_name,
		  periph->unit_number);
	cam_periph_lock(periph);
	/*
	 * Add async callbacks for bus reset and
	 * bus device reset calls.  I don't bother
	 * checking if this fails as, in most cases,
	 * the system will function just fine without
	 * them and the only alternative would be to
	 * not attach the device on failure.
	 */
	xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE,
			   ptasync, periph, periph->path);

	/* Tell the user we've attached to the device */
	xpt_announce_periph(periph, NULL);

	return(CAM_REQ_CMP);
}
示例#4
0
static void
ptdtor(struct cam_periph *periph)
{
    struct pt_softc *softc;

    softc = (struct pt_softc *)periph->softc;

    devstat_remove_entry(softc->device_stats);
    cam_periph_unlock(periph);
    destroy_dev(softc->dev);
    cam_periph_lock(periph);
    free(softc, M_DEVBUF);
}
示例#5
0
static int
ptioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
{
	struct cam_periph *periph;
	struct pt_softc *softc;
	int unit;
	int error;

	unit = minor(dev);
	periph = cam_extend_get(ptperiphs, unit);

	if (periph == NULL)
		return(ENXIO);

	softc = (struct pt_softc *)periph->softc;

	if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) {
		return (error); /* error code from tsleep */
	}	

	switch(cmd) {
	case PTIOCGETTIMEOUT:
		if (softc->io_timeout >= 1000)
			*(int *)addr = softc->io_timeout / 1000;
		else
			*(int *)addr = 0;
		break;
	case PTIOCSETTIMEOUT:
	{
		int s;

		if (*(int *)addr < 1) {
			error = EINVAL;
			break;
		}

		s = splsoftcam();
		softc->io_timeout = *(int *)addr * 1000;
		splx(s);

		break;
	}
	default:
		error = cam_periph_ioctl(periph, cmd, addr, pterror);
		break;
	}

	cam_periph_unlock(periph);

	return(error);
}
示例#6
0
/*
 * 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.
 */
static int
ptstrategy(struct dev_strategy_args *ap)
{
	cdev_t dev = ap->a_head.a_dev;
	struct bio *bio = ap->a_bio;
	struct buf *bp = bio->bio_buf;
	struct cam_periph *periph;
	struct pt_softc *softc;
	u_int  unit;
	
	unit = minor(dev);
	periph = cam_extend_get(ptperiphs, unit);
	if (periph == NULL) {
		bp->b_error = ENXIO;
		goto bad;		
	}
	cam_periph_lock(periph);
	softc = (struct pt_softc *)periph->softc;

	/*
	 * If the device has been made invalid, error out
	 */
	if ((softc->flags & PT_FLAG_DEVICE_INVALID)) {
		cam_periph_unlock(periph);
		bp->b_error = ENXIO;
		goto bad;
	}
	
	/*
	 * Place it in the queue of disk activities for this disk
	 */
	bioq_insert_tail(&softc->bio_queue, bio);
	
	/*
	 * Schedule ourselves for performing the work.
	 */
	xpt_schedule(periph, /* XXX priority */1);
	cam_periph_unlock(periph);

	return(0);
bad:
	bp->b_flags |= B_ERROR;

	/*
	 * Correctly set the buf to indicate a completed xfer
	 */
	bp->b_resid = bp->b_bcount;
	biodone(bio);
	return(0);
}
示例#7
0
static int
ptioctl(struct dev_ioctl_args *ap)
{
	cdev_t dev = ap->a_head.a_dev;
	caddr_t addr = ap->a_data;
	struct cam_periph *periph;
	struct pt_softc *softc;
	int unit;
	int error = 0;

	unit = minor(dev);
	periph = cam_extend_get(ptperiphs, unit);

	if (periph == NULL)
		return(ENXIO);

	softc = (struct pt_softc *)periph->softc;

	cam_periph_lock(periph);

	switch(ap->a_cmd) {
	case PTIOCGETTIMEOUT:
		if (softc->io_timeout >= 1000)
			*(int *)addr = softc->io_timeout / 1000;
		else
			*(int *)addr = 0;
		break;
	case PTIOCSETTIMEOUT:
		if (*(int *)addr < 1) {
			error = EINVAL;
			break;
		}

		softc->io_timeout = *(int *)addr * 1000;

		break;
	default:
		error = cam_periph_ioctl(periph, ap->a_cmd, addr, pterror);
		break;
	}

	cam_periph_unlock(periph);

	return(error);
}
示例#8
0
static int
ptopen(dev_t dev, int flags, int fmt, struct thread *td)
{
	struct cam_periph *periph;
	struct pt_softc *softc;
	int unit;
	int error;
	int s;

	unit = minor(dev);
	periph = (struct cam_periph *)dev->si_drv1;
	if (periph == NULL)
		return (ENXIO);	

	softc = (struct pt_softc *)periph->softc;

	s = splsoftcam();
	if (softc->flags & PT_FLAG_DEVICE_INVALID) {
		splx(s);
		return(ENXIO);
	}

	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
	    ("ptopen: dev=%s (unit %d)\n", devtoname(dev), unit));

	if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) {
		splx(s);
		return (error); /* error code from tsleep */
	}

	splx(s);

	if ((softc->flags & PT_FLAG_OPEN) == 0) {
		if (cam_periph_acquire(periph) != CAM_REQ_CMP)
			error = ENXIO;
		else
			softc->flags |= PT_FLAG_OPEN;
	} else
		error = EBUSY;

	cam_periph_unlock(periph);
	return (error);
}
static int
ptclose(struct cdev *dev, int flag, int fmt, struct thread *td)
{
	struct	cam_periph *periph;
	struct	pt_softc *softc;

	periph = (struct cam_periph *)dev->si_drv1;
	if (periph == NULL)
		return (ENXIO);	

	softc = (struct pt_softc *)periph->softc;

	cam_periph_lock(periph);

	softc->flags &= ~PT_FLAG_OPEN;
	cam_periph_unlock(periph);
	cam_periph_release(periph);
	return (0);
}
示例#10
0
static void
pmpcleanup(struct cam_periph *periph)
{
	struct pmp_softc *softc;

	softc = (struct pmp_softc *)periph->softc;

	cam_periph_unlock(periph);

	/*
	 * If we can't free the sysctl tree, oh well...
	 */
	if ((softc->flags & PMP_FLAG_SCTX_INIT) != 0
	    && sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
		xpt_print(periph->path, "can't remove sysctl context\n");
	}

	free(softc, M_DEVBUF);
	cam_periph_lock(periph);
}
示例#11
0
static int
adaopen(struct disk *dp)
{
	struct cam_periph *periph;
	struct ada_softc *softc;
	int unit;
	int error;

	periph = (struct cam_periph *)dp->d_drv1;
	if (periph == NULL) {
		return (ENXIO);	
	}

	if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
		return(ENXIO);
	}

	cam_periph_lock(periph);
	if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) {
		cam_periph_unlock(periph);
		cam_periph_release(periph);
		return (error);
	}

	unit = periph->unit_number;
	softc = (struct ada_softc *)periph->softc;
	softc->flags |= ADA_FLAG_OPEN;

	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
	    ("adaopen: disk=%s%d (unit %d)\n", dp->d_name, dp->d_unit,
	     unit));

	if ((softc->flags & ADA_FLAG_PACK_INVALID) != 0) {
		/* Invalidate our pack information. */
		softc->flags &= ~ADA_FLAG_PACK_INVALID;
	}

	cam_periph_unhold(periph);
	cam_periph_unlock(periph);
	return (0);
}
示例#12
0
/*
 * 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.
 */
static void
adastrategy(struct bio *bp)
{
	struct cam_periph *periph;
	struct ada_softc *softc;
	
	periph = (struct cam_periph *)bp->bio_disk->d_drv1;
	if (periph == NULL) {
		biofinish(bp, NULL, ENXIO);
		return;
	}
	softc = (struct ada_softc *)periph->softc;

	cam_periph_lock(periph);

	/*
	 * If the device has been made invalid, error out
	 */
	if ((softc->flags & ADA_FLAG_PACK_INVALID)) {
		cam_periph_unlock(periph);
		biofinish(bp, NULL, ENXIO);
		return;
	}
	
	/*
	 * Place it in the queue of disk activities for this disk
	 */
	if (bp->bio_cmd == BIO_DELETE &&
	    (softc->flags & ADA_FLAG_CAN_TRIM))
		bioq_disksort(&softc->trim_queue, bp);
	else
		bioq_disksort(&softc->bio_queue, bp);

	/*
	 * Schedule ourselves for performing the work.
	 */
	adaschedule(periph);
	cam_periph_unlock(periph);

	return;
}
示例#13
0
static int
ptclose(dev_t dev, int flag, int fmt, struct thread *td)
{
	struct	cam_periph *periph;
	struct	pt_softc *softc;
	int	error;

	periph = (struct cam_periph *)dev->si_drv1;
	if (periph == NULL)
		return (ENXIO);	

	softc = (struct pt_softc *)periph->softc;

	if ((error = cam_periph_lock(periph, PRIBIO)) != 0)
		return (error); /* error code from tsleep */

	softc->flags &= ~PT_FLAG_OPEN;
	cam_periph_unlock(periph);
	cam_periph_release(periph);
	return (0);
}
示例#14
0
static int
ptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
{
	struct cam_periph *periph;
	struct pt_softc *softc;
	int error = 0;

	periph = (struct cam_periph *)dev->si_drv1;
	if (periph == NULL)
		return(ENXIO);

	softc = (struct pt_softc *)periph->softc;

	cam_periph_lock(periph);

	switch(cmd) {
	case PTIOCGETTIMEOUT:
		if (softc->io_timeout >= 1000)
			*(int *)addr = softc->io_timeout / 1000;
		else
			*(int *)addr = 0;
		break;
	case PTIOCSETTIMEOUT:
		if (*(int *)addr < 1) {
			error = EINVAL;
			break;
		}

		softc->io_timeout = *(int *)addr * 1000;

		break;
	default:
		error = cam_periph_ioctl(periph, cmd, addr, pterror);
		break;
	}

	cam_periph_unlock(periph);

	return(error);
}
示例#15
0
static int
ptclose(struct dev_close_args *ap)
{
	cdev_t dev = ap->a_head.a_dev;
	struct	cam_periph *periph;
	struct	pt_softc *softc;
	int	unit;

	unit = minor(dev);
	periph = cam_extend_get(ptperiphs, unit);
	if (periph == NULL)
		return (ENXIO);	

	softc = (struct pt_softc *)periph->softc;

	cam_periph_lock(periph);

	softc->flags &= ~PT_FLAG_OPEN;
	cam_periph_unlock(periph);
	cam_periph_release(periph);
	return (0);
}
示例#16
0
static int
ptclose(dev_t dev, int flag, int fmt, struct proc *p)
{
	struct	cam_periph *periph;
	struct	pt_softc *softc;
	int	unit;
	int	error;

	unit = minor(dev);
	periph = cam_extend_get(ptperiphs, unit);
	if (periph == NULL)
		return (ENXIO);	

	softc = (struct pt_softc *)periph->softc;

	if ((error = cam_periph_lock(periph, PRIBIO)) != 0)
		return (error); /* error code from tsleep */

	softc->flags &= ~PT_FLAG_OPEN;
	cam_periph_unlock(periph);
	cam_periph_release(periph);
	return (0);
}
示例#17
0
/*
 * 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.
 */
static void
ptstrategy(struct bio *bp)
{
	struct cam_periph *periph;
	struct pt_softc *softc;
	
	periph = (struct cam_periph *)bp->bio_dev->si_drv1;
	bp->bio_resid = bp->bio_bcount;
	if (periph == NULL) {
		biofinish(bp, NULL, ENXIO);
		return;
	}
	cam_periph_lock(periph);
	softc = (struct pt_softc *)periph->softc;

	/*
	 * If the device has been made invalid, error out
	 */
	if ((softc->flags & PT_FLAG_DEVICE_INVALID)) {
		cam_periph_unlock(periph);
		biofinish(bp, NULL, ENXIO);
		return;
	}
	
	/*
	 * Place it in the queue of disk activities for this disk
	 */
	bioq_insert_tail(&softc->bio_queue, bp);

	/*
	 * Schedule ourselves for performing the work.
	 */
	xpt_schedule(periph, /* XXX priority */1);
	cam_periph_unlock(periph);

	return;
}
示例#18
0
static int
ptopen(struct dev_open_args *ap)
{
	cdev_t dev = ap->a_head.a_dev;
	struct cam_periph *periph;
	struct pt_softc *softc;
	int unit;
	int error = 0;

	unit = minor(dev);
	periph = cam_extend_get(ptperiphs, unit);
	if (cam_periph_acquire(periph) != CAM_REQ_CMP)
		return (ENXIO);	

	softc = (struct pt_softc *)periph->softc;

	cam_periph_lock(periph);
	if (softc->flags & PT_FLAG_DEVICE_INVALID) {
		cam_periph_unlock(periph);
		cam_periph_release(periph);
		return(ENXIO);
	}

	if ((softc->flags & PT_FLAG_OPEN) == 0)
		softc->flags |= PT_FLAG_OPEN;
	else {
		error = EBUSY;
		cam_periph_release(periph);
	}

	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
	    ("ptopen: dev=%s\n", devtoname(dev)));

	cam_periph_unlock(periph);
	return (error);
}
示例#19
0
static cam_status
ptctor(struct cam_periph *periph, void *arg)
{
    struct pt_softc *softc;
    struct ccb_getdev *cgd;
    struct ccb_pathinq cpi;

    cgd = (struct ccb_getdev *)arg;
    if (cgd == NULL) {
        printf("ptregister: no getdev CCB, can't register device\n");
        return(CAM_REQ_CMP_ERR);
    }

    softc = (struct pt_softc *)malloc(sizeof(*softc),M_DEVBUF,M_NOWAIT);

    if (softc == NULL) {
        printf("daregister: Unable to probe new device. "
               "Unable to allocate softc\n");
        return(CAM_REQ_CMP_ERR);
    }

    bzero(softc, sizeof(*softc));
    LIST_INIT(&softc->pending_ccbs);
    softc->state = PT_STATE_NORMAL;
    bioq_init(&softc->bio_queue);

    softc->io_timeout = SCSI_PT_DEFAULT_TIMEOUT * 1000;

    periph->softc = softc;

    bzero(&cpi, sizeof(cpi));
    xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
    cpi.ccb_h.func_code = XPT_PATH_INQ;
    xpt_action((union ccb *)&cpi);

    cam_periph_unlock(periph);
    softc->device_stats = devstat_new_entry("pt",
                                            periph->unit_number, 0,
                                            DEVSTAT_NO_BLOCKSIZE,
                                            SID_TYPE(&cgd->inq_data) |
                                            XPORT_DEVSTAT_TYPE(cpi.transport),
                                            DEVSTAT_PRIORITY_OTHER);

    softc->dev = make_dev(&pt_cdevsw, periph->unit_number, UID_ROOT,
                          GID_OPERATOR, 0600, "%s%d", periph->periph_name,
                          periph->unit_number);
    cam_periph_lock(periph);
    softc->dev->si_drv1 = periph;

    /*
     * Add async callbacks for bus reset and
     * bus device reset calls.  I don't bother
     * checking if this fails as, in most cases,
     * the system will function just fine without
     * them and the only alternative would be to
     * not attach the device on failure.
     */
    xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE,
                       ptasync, periph, periph->path);

    /* Tell the user we've attached to the device */
    xpt_announce_periph(periph, NULL);

    return(CAM_REQ_CMP);
}