diff options
Diffstat (limited to 'sys/cam/scsi/scsi_cd.c')
-rw-r--r-- | sys/cam/scsi/scsi_cd.c | 190 |
1 files changed, 79 insertions, 111 deletions
diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c index 0ebc685471917..d1f0a4c52896f 100644 --- a/sys/cam/scsi/scsi_cd.c +++ b/sys/cam/scsi/scsi_cd.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: scsi_cd.c,v 1.13 1999/01/11 17:45:22 eivind Exp $ + * $Id: scsi_cd.c,v 1.6 1998/10/12 17:02:37 ken Exp $ */ /* * Portions of this driver taken from the original FreeBSD cd driver. @@ -187,7 +187,6 @@ static periph_init_t cdinit; static periph_ctor_t cdregister; static periph_dtor_t cdcleanup; static periph_start_t cdstart; -static periph_oninv_t cdoninvalidate; static void cdasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg); static void cdshorttimeout(void *arg); @@ -199,7 +198,7 @@ static int cdrunccb(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags), u_int32_t cam_flags, u_int32_t sense_flags); -static union ccb *cdgetccb(struct cam_periph *periph, +union ccb *cdgetccb(struct cam_periph *periph, u_int32_t priority); static void cddone(struct cam_periph *periph, union ccb *start_ccb); @@ -306,7 +305,7 @@ struct cdchanger { STAILQ_HEAD(chdevlist, cd_softc) chluns; }; -static STAILQ_HEAD(changerlist, cdchanger) changerq; +STAILQ_HEAD(changerlist, cdchanger) changerq; void cdinit(void) @@ -353,74 +352,14 @@ cdinit(void) } static void -cdoninvalidate(struct cam_periph *periph) -{ - int s; - struct cd_softc *softc; - struct buf *q_bp; - struct ccb_setasync csa; - - softc = (struct cd_softc *)periph->softc; - - /* - * De-register any async callbacks. - */ - xpt_setup_ccb(&csa.ccb_h, periph->path, - /* priority */ 5); - csa.ccb_h.func_code = XPT_SASYNC_CB; - csa.event_enable = 0; - csa.callback = cdasync; - csa.callback_arg = periph; - xpt_action((union ccb *)&csa); - - softc->flags |= CD_FLAG_INVALID; - - /* - * Although the oninvalidate() routines are always called at - * splsoftcam, we need to be at splbio() here to keep the buffer - * queue from being modified while we traverse it. - */ - s = splbio(); - - /* - * Return all queued I/O with ENXIO. - * XXX Handle any transactions queued to the card - * with XPT_ABORT_CCB. - */ - while ((q_bp = bufq_first(&softc->buf_queue)) != NULL){ - bufq_remove(&softc->buf_queue, q_bp); - q_bp->b_resid = q_bp->b_bcount; - q_bp->b_error = ENXIO; - q_bp->b_flags |= B_ERROR; - biodone(q_bp); - } - splx(s); - - /* - * If this device is part of a changer, and it was scheduled - * to run, remove it from the run queue since we just nuked - * all of its scheduled I/O. - */ - if ((softc->flags & CD_FLAG_CHANGER) - && (softc->pinfo.index != CAM_UNQUEUED_INDEX)) - camq_remove(&softc->changer->devq, softc->pinfo.index); - - xpt_print_path(periph->path); - printf("lost device\n"); -} - -static void cdcleanup(struct cam_periph *periph) { struct cd_softc *softc; - int s; softc = (struct cd_softc *)periph->softc; xpt_print_path(periph->path); printf("removing device entry\n"); - - s = splsoftcam(); /* * In the queued, non-active case, the device in question * has already been removed from the changer run queue. Since this @@ -490,10 +429,8 @@ cdcleanup(struct cam_periph *periph) free(softc->changer, M_DEVBUF); num_changers--; } - devstat_remove_entry(&softc->device_stats); cam_extend_release(cdperiphs, periph->unit_number); - free(softc, M_DEVBUF); - splx(s); + free(periph->softc, M_DEVBUF); } static void @@ -519,11 +456,9 @@ cdasync(void *callback_arg, u_int32_t code, * this device and start the probe * process. */ - status = cam_periph_alloc(cdregister, cdoninvalidate, - cdcleanup, cdstart, - "cd", CAM_PERIPH_BIO, - cgd->ccb_h.path, cdasync, - AC_FOUND_DEVICE, cgd); + status = cam_periph_alloc(cdregister, cdcleanup, cdstart, + "cd", CAM_PERIPH_BIO, cgd->ccb_h.path, + cdasync, AC_FOUND_DEVICE, cgd); if (status != CAM_REQ_CMP && status != CAM_REQ_INPROG) @@ -533,8 +468,65 @@ cdasync(void *callback_arg, u_int32_t code, break; } case AC_LOST_DEVICE: + { + int s; + struct cd_softc *softc; + struct buf *q_bp; + struct ccb_setasync csa; + + softc = (struct cd_softc *)periph->softc; + + /* + * Insure that no other async callbacks that + * might affect this peripheral can come through. + */ + s = splcam(); + + /* + * De-register any async callbacks. + */ + xpt_setup_ccb(&csa.ccb_h, periph->path, + /* priority */ 5); + csa.ccb_h.func_code = XPT_SASYNC_CB; + csa.event_enable = 0; + csa.callback = cdasync; + csa.callback_arg = periph; + xpt_action((union ccb *)&csa); + + softc->flags |= CD_FLAG_INVALID; + + /* + * Return all queued I/O with ENXIO. + * XXX Handle any transactions queued to the card + * with XPT_ABORT_CCB. + */ + while ((q_bp = bufq_first(&softc->buf_queue)) != NULL){ + bufq_remove(&softc->buf_queue, q_bp); + q_bp->b_resid = q_bp->b_bcount; + q_bp->b_error = ENXIO; + q_bp->b_flags |= B_ERROR; + biodone(q_bp); + } + + /* + * If this device is part of a changer, and it was scheduled + * to run, remove it from the run queue since we just nuked + * all of its scheduled I/O. + */ + if ((softc->flags & CD_FLAG_CHANGER) + && (softc->pinfo.index != CAM_UNQUEUED_INDEX)) + camq_remove(&softc->changer->devq, softc->pinfo.index); + + devstat_remove_entry(&softc->device_stats); + + xpt_print_path(periph->path); + printf("lost device\n"); + + splx(s); + cam_periph_invalidate(periph); break; + } case AC_SENT_BDR: case AC_BUS_RESET: { @@ -880,7 +872,6 @@ cdopen(dev_t dev, int flags, int fmt, struct proc *p) struct ccb_getdev cgd; u_int32_t size; int unit, error; - int s; unit = dkunit(dev); periph = cam_extend_get(cdperiphs, unit); @@ -890,21 +881,11 @@ cdopen(dev_t dev, int flags, int fmt, struct proc *p) softc = (struct cd_softc *)periph->softc; - /* - * Grab splsoftcam and hold it until we lock the peripheral. - */ - s = splsoftcam(); - if (softc->flags & CD_FLAG_INVALID) { - splx(s); + if (softc->flags & CD_FLAG_INVALID) return(ENXIO); - } - if ((error = cam_periph_lock(periph, PRIBIO | PCATCH)) != 0) { - splx(s); + if ((error = cam_periph_lock(periph, PRIBIO | PCATCH)) != 0) return (error); - } - - splx(s); if ((softc->flags & CD_FLAG_OPEN) == 0) { if (cam_periph_acquire(periph) != CAM_REQ_CMP) @@ -964,7 +945,7 @@ cdopen(dev_t dev, int flags, int fmt, struct proc *p) /* Initialize slice tables. */ error = dsopen("cd", dev, fmt, DSO_NOLABELS | DSO_ONESLICE, - &softc->cd_slices, &label, cdstrategy1, + &softc->cd_slices, &label, cdstrategy, (ds_setgeom_t *)NULL, &cd_cdevsw); if (error == 0) { @@ -1330,7 +1311,7 @@ cdrunccb(union ccb *ccb, int (*error_routine)(union ccb *ccb, return(error); } -static union ccb * +union ccb * cdgetccb(struct cam_periph *periph, u_int32_t priority) { struct cd_softc *softc; @@ -1691,7 +1672,7 @@ cddone(struct cam_periph *periph, union ccb *done_ccb) if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { - snprintf(announce_buf, sizeof(announce_buf), + sprintf(announce_buf, "cd present [%lu x %lu byte records]", cdp->disksize, (u_long)cdp->blksize); @@ -1759,8 +1740,7 @@ cddone(struct cam_periph *periph, union ccb *done_ccb) if ((have_sense) && ((asc == 0x3a) || (asc == 0x04)) && (error_code == SSD_CURRENT_ERROR)) - snprintf(announce_buf, - sizeof(announce_buf), + sprintf(announce_buf, "Attempt to query device " "size failed: %s, %s", scsi_sense_key_text[sense_key], @@ -1794,18 +1774,17 @@ cddone(struct cam_periph *periph, union ccb *done_ccb) } xpt_print_path(periph->path); printf("fatal error, failed" - " to attach to device\n"); + " to attach to device"); /* - * Invalidate this peripheral. + * Free up resources. */ cam_periph_invalidate(periph); announce_buf[0] = '\0'; } else { - /* - * Invalidate this peripheral. + * Free up resources. */ cam_periph_invalidate(periph); announce_buf[0] = '\0'; @@ -1813,23 +1792,14 @@ cddone(struct cam_periph *periph, union ccb *done_ccb) } } free(rdcap, M_TEMP); - if (announce_buf[0] != '\0') { + if (announce_buf[0] != '\0') xpt_announce_periph(periph, announce_buf); - if (softc->flags & CD_FLAG_CHANGER) - cdchangerschedule(softc); - } softc->state = CD_STATE_NORMAL; - /* - * Since our peripheral may be invalidated by an error - * above or an external event, we must release our CCB - * before releasing the probe lock on the peripheral. - * The peripheral will only go away once the last lock - * is removed, and we need it around for the CCB release - * operation. - */ - xpt_release_ccb(done_ccb); + if (softc->flags & CD_FLAG_CHANGER) + cdchangerschedule(softc); cam_periph_unlock(periph); - return; + + break; } case CD_CCB_WAITING: { @@ -1840,8 +1810,6 @@ cddone(struct cam_periph *periph, union ccb *done_ccb) wakeup(&done_ccb->ccb_h.cbfcnp); return; } - default: - break; } xpt_release_ccb(done_ccb); } @@ -2486,7 +2454,7 @@ cdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) * don't, dsioctl will pass back an error code of ENOIOCTL. */ error = dsioctl("cd", dev, cmd, addr, flag, &softc->cd_slices, - cdstrategy1, (ds_setgeom_t *)NULL); + cdstrategy, (ds_setgeom_t *)NULL); if (error != ENOIOCTL) break; |