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