--- src/sys/bus/cam/scsi/scsi_cd.c 2007/11/29 02:32:43 1.41 +++ src/sys/bus/cam/scsi/scsi_cd.c 2008/05/18 20:30:19 1.42 @@ -74,6 +74,7 @@ #include "../cam_periph.h" #include "../cam_xpt_periph.h" #include "../cam_queue.h" +#include "../cam_sim.h" #include "scsi_message.h" #include "scsi_da.h" @@ -107,8 +108,8 @@ typedef enum { CD_FLAG_RETRY_UA = 0x0200, CD_FLAG_VALID_MEDIA = 0x0400, CD_FLAG_VALID_TOC = 0x0800, - CD_FLAG_OPEN = 0x1000, - CD_FLAG_SCTX_INIT = 0x2000 + CD_FLAG_SCTX_INIT = 0x1000, + CD_FLAG_OPEN = 0x2000 } cd_flags; typedef enum { @@ -296,10 +297,6 @@ static struct periph_driver cddriver = PERIPHDRIVER_DECLARE(cd, cddriver); -/* For 2.2-stable support */ -#ifndef D_DISK -#define D_DISK 0 -#endif static struct dev_ops cd_ops = { { "cd", SCSICD_CDEV_MAJOR, D_DISK }, .d_open = cdopen, @@ -311,7 +308,6 @@ static struct dev_ops cd_ops = { }; static struct extend_array *cdperiphs; -static int num_changers; #ifndef CHANGER_MIN_BUSY_SECONDS #define CHANGER_MIN_BUSY_SECONDS 5 @@ -346,13 +342,19 @@ struct cdchanger { STAILQ_HEAD(chdevlist, cd_softc) chluns; }; +static struct lock changerq_lock; static STAILQ_HEAD(changerlist, cdchanger) changerq; +static int num_changers; + +MALLOC_DEFINE(M_SCSICD, "scsi_cd", "scsi_cd buffers"); static void cdinit(void) { cam_status status; - struct cam_path *path; + + lockinit(&changerq_lock, "cdchangerq", 0, LK_CANRECURSE); + STAILQ_INIT(&changerq); /* * Create our extend array for storing the devices we attach to. @@ -367,21 +369,7 @@ cdinit(void) * Install a global async callback. This callback will * receive async callbacks like "new device found". */ - status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID, - CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); - - if (status == CAM_REQ_CMP) { - struct ccb_setasync csa; - - xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); - csa.ccb_h.func_code = XPT_SASYNC_CB; - csa.event_enable = AC_FOUND_DEVICE; - csa.callback = cdasync; - csa.callback_arg = NULL; - xpt_action((union ccb *)&csa); - status = csa.ccb_h.status; - xpt_free_path(path); - } + status = xpt_register_async(AC_FOUND_DEVICE, cdasync, NULL, NULL); if (status != CAM_REQ_CMP) { kprintf("cd: Failed to attach master async callback " @@ -395,31 +383,17 @@ cdoninvalidate(struct cam_periph *periph struct cd_softc *softc; struct buf *q_bp; struct bio *q_bio; - 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); + xpt_register_async(0, cdasync, periph, periph->path); softc->flags |= CD_FLAG_INVALID; /* - * Although the oninvalidate() routines are always while in a - * critical section, we need to be in a critical section here to - * keep the buffer queue from being modified while we traverse it. - */ - crit_enter(); - - /* * Return all queued I/O with ENXIO. * XXX Handle any transactions queued to the card * with XPT_ABORT_CCB. @@ -432,7 +406,6 @@ cdoninvalidate(struct cam_periph *periph q_bp->b_flags |= B_ERROR; biodone(q_bio); } - crit_exit(); /* * If this device is part of a changer, and it was scheduled @@ -443,8 +416,7 @@ cdoninvalidate(struct cam_periph *periph && (softc->pinfo.index != CAM_UNQUEUED_INDEX)) camq_remove(&softc->changer->devq, softc->pinfo.index); - xpt_print_path(periph->path); - kprintf("lost device\n"); + xpt_print(periph->path, "lost device\n"); } static void @@ -454,16 +426,13 @@ cdcleanup(struct cam_periph *periph) softc = (struct cd_softc *)periph->softc; - xpt_print_path(periph->path); - kprintf("removing device entry\n"); + xpt_print(periph->path, "removing device entry\n"); if ((softc->flags & CD_FLAG_SCTX_INIT) != 0 && sysctl_ctx_free(&softc->sysctl_ctx) != 0) { - xpt_print_path(periph->path); - kprintf("can't remove sysctl context\n"); + xpt_print(periph->path, "can't remove sysctl context\n"); } - crit_enter(); /* * In the queued, non-active case, the device in question * has already been removed from the changer run queue. Since this @@ -523,20 +492,22 @@ cdcleanup(struct cam_periph *periph) softc->changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED; } + lockmgr(&changerq_lock, LK_EXCLUSIVE); STAILQ_REMOVE(&changerq, softc->changer, cdchanger, changer_links); - xpt_print_path(periph->path); - kprintf("removing changer entry\n"); - kfree(softc->changer, M_DEVBUF); num_changers--; + lockmgr(&changerq_lock, LK_RELEASE); + xpt_print(periph->path, "removing changer entry\n"); + kfree(softc->changer, M_DEVBUF); } devstat_remove_entry(&softc->device_stats); cam_extend_release(cdperiphs, periph->unit_number); if (softc->disk.d_rawdev) { + cam_periph_unlock(periph); disk_destroy(&softc->disk); + cam_periph_lock(periph); } kfree(softc, M_DEVBUF); - crit_exit(); } static void @@ -585,7 +556,6 @@ cdasync(void *callback_arg, u_int32_t co struct ccb_hdr *ccbh; softc = (struct cd_softc *)periph->softc; - crit_enter(); /* * Don't fail on the expected unit attention * that will occur. @@ -593,7 +563,6 @@ cdasync(void *callback_arg, u_int32_t co softc->flags |= CD_FLAG_RETRY_UA; LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le) ccbh->ccb_state |= CD_CCB_RETRY_UA; - crit_exit(); /* FALLTHROUGH */ } default: @@ -610,8 +579,10 @@ cdsysctlinit(void *context, int pending) char tmpstr[80], tmpstr2[80]; periph = (struct cam_periph *)context; - softc = (struct cd_softc *)periph->softc; + if (cam_periph_acquire(periph) != CAM_REQ_CMP) + return; + softc = (struct cd_softc *)periph->softc; ksnprintf(tmpstr, sizeof(tmpstr), "CAM CD unit %d", periph->unit_number); ksnprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number); @@ -623,6 +594,7 @@ cdsysctlinit(void *context, int pending) if (softc->sysctl_tree == NULL) { kprintf("cdsysctlinit: unable to allocate sysctl tree\n"); + cam_periph_release(periph); return; } @@ -634,6 +606,8 @@ cdsysctlinit(void *context, int pending) OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW, &softc->minimum_command_size, 0, cdcmdsizesysctl, "I", "Minimum CDB size"); + + cam_periph_release(periph); } /* @@ -677,7 +651,6 @@ static cam_status cdregister(struct cam_periph *periph, void *arg) { struct cd_softc *softc; - struct ccb_setasync csa; struct ccb_pathinq cpi; struct ccb_getdev *cgd; char tmpstr[80]; @@ -761,6 +734,7 @@ cdregister(struct cam_periph *periph, vo * WORM peripheral driver. WORM drives will also have the WORM * driver attached to them. */ + cam_periph_unlock(periph); devstat_add_entry(&softc->device_stats, "cd", periph->unit_number, 0, DEVSTAT_BS_UNAVAILABLE, @@ -770,18 +744,14 @@ cdregister(struct cam_periph *periph, vo softc->disk.d_rawdev->si_iosize_max = MAXPHYS; softc->disk.d_info.d_dsflags = DSO_ONESLICE | DSO_COMPATLABEL | DSO_COMPATPARTA; + cam_periph_lock(periph); /* * Add an async callback so that we get * notified if this device goes away. */ - xpt_setup_ccb(&csa.ccb_h, periph->path, - /* priority */ 5); - csa.ccb_h.func_code = XPT_SASYNC_CB; - csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE; - csa.callback = cdasync; - csa.callback_arg = periph; - xpt_action((union ccb *)&csa); + xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE, + cdasync, periph, periph->path); /* * If the target lun is greater than 0, we most likely have a CD @@ -804,13 +774,11 @@ cdregister(struct cam_periph *periph, vo /* Set the changer flag in the current device's softc */ softc->flags |= CD_FLAG_CHANGER; - if (num_changers == 0) - STAILQ_INIT(&changerq); - /* * Now, look around for an existing changer device with the * same path and target ID as the current device. */ + lockmgr(&changerq_lock, LK_EXCLUSIVE); for (found = 0, nchanger = (struct cdchanger *)STAILQ_FIRST(&changerq); nchanger != NULL; @@ -821,6 +789,7 @@ cdregister(struct cam_periph *periph, vo break; } } + lockmgr(&changerq_lock, LK_RELEASE); /* * If we found a matching entry, just add this device to @@ -911,8 +880,6 @@ cdregister(struct cam_periph *periph, vo goto cdregisterexit; } - num_changers++; - nchanger->path_id = cgd->ccb_h.path_id; nchanger->target_id = cgd->ccb_h.target_id; @@ -921,8 +888,14 @@ cdregister(struct cam_periph *periph, vo STAILQ_INIT(&nchanger->chluns); + callout_init(&nchanger->long_handle); + callout_init(&nchanger->short_handle); + + lockmgr(&changerq_lock, LK_EXCLUSIVE); + num_changers++; STAILQ_INSERT_TAIL(&changerq, nchanger, changer_links); + lockmgr(&changerq_lock, LK_RELEASE); /* * Create a path with lun id 0, and see if we can @@ -984,9 +957,11 @@ cdregister(struct cam_periph *periph, vo cdregisterexit: - /* Lock this peripheral until we are setup */ - /* Can't block */ - cam_periph_lock(periph, 0); + /* + * Refcount and block open attempts until we are setup + * Can't block + */ + cam_periph_hold(periph, 0); if ((softc->flags & CD_FLAG_CHANGER) == 0) xpt_schedule(periph, /*priority*/5); @@ -1012,24 +987,28 @@ cdopen(struct dev_open_args *ap) softc = (struct cd_softc *)periph->softc; - /* - * Grab a critical section and hold it until we lock the peripheral. - */ - crit_enter(); + if (cam_periph_acquire(periph) != CAM_REQ_CMP) + return(ENXIO); + + cam_periph_lock(periph); + if (softc->flags & CD_FLAG_INVALID) { - crit_exit(); + cam_periph_unlock(periph); + cam_periph_release(periph); return(ENXIO); } - if ((error = cam_periph_lock(periph, PCATCH)) != 0) { - crit_exit(); + if ((error = cam_periph_hold(periph, PCATCH)) != 0) { + cam_periph_unlock(periph); + cam_periph_release(periph); return (error); } - crit_exit(); - - if (cam_periph_acquire(periph) != CAM_REQ_CMP) - return(ENXIO); + /* Closes aren't symmetrical with opens, so fix up the refcounting. */ + if (softc->flags & CD_FLAG_OPEN) + cam_periph_release(periph); + else + softc->flags |= CD_FLAG_OPEN; /* * Check for media, and set the appropriate flags. We don't bail @@ -1045,11 +1024,11 @@ cdopen(struct dev_open_args *ap) if (error == 0) softc->flags |= CD_FLAG_OPEN; - cam_periph_unlock(periph); - CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdopen\n")); + cam_periph_unhold(periph); + cam_periph_unlock(periph); - return (error); + return (0); } static int @@ -1059,7 +1038,7 @@ cdclose(struct dev_close_args *ap) struct cam_periph *periph; struct cd_softc *softc; struct disk_info *info; - int unit, error; + int unit; unit = dkunit(dev); periph = cam_extend_get(cdperiphs, unit); @@ -1068,8 +1047,8 @@ cdclose(struct dev_close_args *ap) softc = (struct cd_softc *)periph->softc; - if ((error = cam_periph_lock(periph, 0)) != 0) - return (error); + cam_periph_lock(periph); + cam_periph_hold(periph, 0); if ((softc->flags & CD_FLAG_DISC_REMOVABLE) != 0) cdprevent(periph, PR_ALLOW); @@ -1091,10 +1070,9 @@ cdclose(struct dev_close_args *ap) /* * We'll check the media and toc again at the next open(). */ - softc->flags &= ~(CD_FLAG_VALID_MEDIA|CD_FLAG_VALID_TOC); - - softc->flags &= ~CD_FLAG_OPEN; + softc->flags &= ~(CD_FLAG_VALID_MEDIA|CD_FLAG_VALID_TOC|CD_FLAG_OPEN); + cam_periph_unhold(periph); cam_periph_unlock(periph); cam_periph_release(periph); @@ -1106,8 +1084,6 @@ cdshorttimeout(void *arg) { struct cdchanger *changer; - crit_enter(); - changer = (struct cdchanger *)arg; /* Always clear the short timeout flag, since that's what we're in */ @@ -1122,7 +1098,6 @@ cdshorttimeout(void *arg) changer->flags |= CHANGER_MANUAL_CALL; cdrunchangerqueue(changer); } - crit_exit(); } /* @@ -1133,8 +1108,6 @@ cdschedule(struct cam_periph *periph, in { struct cd_softc *softc; - crit_enter(); - softc = (struct cd_softc *)periph->softc; /* @@ -1173,7 +1146,6 @@ cdschedule(struct cam_periph *periph, in && ((softc->flags & CD_FLAG_SCHED_ON_COMP) == 0)) { xpt_schedule(periph, priority); } - crit_exit(); } static void @@ -1183,8 +1155,6 @@ cdrunchangerqueue(void *arg) struct cdchanger *changer; int called_from_timeout; - crit_enter(); - changer = (struct cdchanger *)arg; /* @@ -1203,7 +1173,6 @@ cdrunchangerqueue(void *arg) /* nothing to do if the queue is empty */ if (changer->devq.entries <= 0) { - crit_exit(); return; } @@ -1213,6 +1182,14 @@ cdrunchangerqueue(void *arg) */ if (changer->devq.qfrozen_cnt > 0) { + /* + * We always need to reset the frozen count and clear the + * active flag. + */ + changer->devq.qfrozen_cnt--; + changer->cur_device->flags &= ~CD_FLAG_ACTIVE; + changer->cur_device->flags &= ~CD_FLAG_SCHED_ON_COMP; + if (changer->cur_device->outstanding_cmds > 0) { changer->cur_device->flags |= CD_FLAG_SCHED_ON_COMP; changer->cur_device->bufs_left = @@ -1223,19 +1200,10 @@ cdrunchangerqueue(void *arg) cdrunchangerqueue, changer); changer->flags |= CHANGER_TIMEOUT_SCHED; } - crit_exit(); return; } /* - * We always need to reset the frozen count and clear the - * active flag. - */ - changer->devq.qfrozen_cnt--; - changer->cur_device->flags &= ~CD_FLAG_ACTIVE; - changer->cur_device->flags &= ~CD_FLAG_SCHED_ON_COMP; - - /* * Check to see whether the current device has any I/O left * to do. If so, requeue it at the end of the queue. If * not, there is no need to requeue it. @@ -1280,8 +1248,6 @@ cdrunchangerqueue(void *arg) * switch time. */ changer->flags |= CHANGER_NEED_TIMEOUT; - - crit_exit(); } static void @@ -1289,8 +1255,6 @@ cdchangerschedule(struct cd_softc *softc { struct cdchanger *changer; - crit_enter(); - changer = softc->changer; /* @@ -1359,7 +1323,6 @@ cdchangerschedule(struct cd_softc *softc changer->flags &= ~CHANGER_NEED_TIMEOUT; } - crit_exit(); } static int @@ -1392,8 +1355,6 @@ cdgetccb(struct cam_periph *periph, u_in softc = (struct cd_softc *)periph->softc; if (softc->flags & CD_FLAG_CHANGER) { - crit_enter(); - /* * This should work the first time this device is woken up, * but just in case it doesn't, we use a while loop. @@ -1416,9 +1377,9 @@ cdgetccb(struct cam_periph *periph, u_in softc->changer->flags |= CHANGER_MANUAL_CALL; cdrunchangerqueue(softc->changer); } else - tsleep(&softc->changer, 0, "cgticb", 0); + sim_lock_sleep(&softc->changer, 0, "cgticb", 0, + periph->sim->lock); } - crit_exit(); } return(cam_periph_getccb(periph, priority)); } @@ -1445,22 +1406,16 @@ cdstrategy(struct dev_strategy_args *ap) goto bad; } + cam_periph_lock(periph); CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdstrategy\n")); softc = (struct cd_softc *)periph->softc; /* - * Mask interrupts so that the pack cannot be invalidated until - * after we are in the queue. Otherwise, we might not properly - * clean up one of the buffers. - */ - crit_enter(); - - /* * If the device has been made invalid, error out */ if ((softc->flags & CD_FLAG_INVALID)) { - crit_exit(); + cam_periph_unlock(periph); bp->b_error = ENXIO; goto bad; } @@ -1474,7 +1429,7 @@ cdstrategy(struct dev_strategy_args *ap) error = cdcheckmedia(periph); if (error != 0) { - crit_exit(); + cam_periph_unlock(periph); bp->b_error = error; goto bad; } @@ -1485,8 +1440,6 @@ cdstrategy(struct dev_strategy_args *ap) */ bioqdisksort(&softc->bio_queue, bio); - crit_exit(); - /* * Schedule ourselves for performing the work. We do things * differently for changers. @@ -1496,6 +1449,7 @@ cdstrategy(struct dev_strategy_args *ap) else cdschedule(periph, /* priority */ 1); + cam_periph_unlock(periph); return(0); bad: bp->b_flags |= B_ERROR; @@ -1523,7 +1477,6 @@ cdstart(struct cam_periph *periph, union switch (softc->state) { case CD_STATE_NORMAL: { - crit_enter(); bio = bioq_first(&softc->bio_queue); if (periph->immediate_priority <= periph->pinfo.priority) { start_ccb->ccb_h.ccb_state = CD_CCB_WAITING; @@ -1531,10 +1484,8 @@ cdstart(struct cam_periph *periph, union SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, periph_links.sle); periph->immediate_priority = CAM_PRIORITY_NONE; - crit_exit(); wakeup(&periph->ccb_list); } else if (bio == NULL) { - crit_exit(); xpt_release_ccb(start_ccb); } else { bp = bio->bio_buf; @@ -1563,10 +1514,6 @@ cdstart(struct cam_periph *periph, union start_ccb->ccb_h.ccb_state = CD_CCB_BUFFER_IO; - /* - * Block out any asyncronous callbacks - * while we touch the pending ccb list. - */ LIST_INSERT_HEAD(&softc->pending_ccbs, &start_ccb->ccb_h, periph_links.le); @@ -1579,7 +1526,6 @@ cdstart(struct cam_periph *periph, union start_ccb->ccb_h.ccb_bio = bio; bio = bioq_first(&softc->bio_queue); - crit_exit(); xpt_action(start_ccb); } @@ -1592,7 +1538,7 @@ cdstart(struct cam_periph *periph, union case CD_STATE_PROBE: { - rcap = kmalloc(sizeof(*rcap), M_TEMP, M_INTWAIT); + rcap = kmalloc(sizeof(*rcap), M_SCSICD, M_INTWAIT); csio = &start_ccb->csio; scsi_read_capacity(csio, /*retries*/1, @@ -1653,9 +1599,8 @@ cddone(struct cam_periph *periph, union struct bio *q_bio; struct buf *q_bp; - xpt_print_path(periph->path); - kprintf("cddone: got error %#x back\n", error); - crit_enter(); + xpt_print(periph->path, + "cddone: got error %#x back\n", error); while ((q_bio = bioq_first(&softc->bio_queue)) != NULL) { bioq_remove(&softc->bio_queue, q_bio); q_bp = q_bio->bio_buf; @@ -1664,7 +1609,6 @@ cddone(struct cam_periph *periph, union q_bp->b_flags |= B_ERROR; biodone(q_bio); } - crit_exit(); bp->b_resid = bp->b_bcount; bp->b_error = error; bp->b_flags |= B_ERROR; @@ -1683,14 +1627,8 @@ cddone(struct cam_periph *periph, union } } - /* - * Block out any asyncronous callbacks - * while we touch the pending ccb list. - */ - crit_enter(); LIST_REMOVE(&done_ccb->ccb_h, periph_links.le); softc->outstanding_cmds--; - crit_exit(); if (softc->flags & CD_FLAG_CHANGER) cdchangerschedule(softc); @@ -1829,14 +1767,12 @@ cddone(struct cam_periph *periph, union scsi_sense_print( &done_ccb->csio); else { - xpt_print_path(periph->path); - kprintf("got CAM status %#x\n", - done_ccb->ccb_h.status); + xpt_print(periph->path, + "got CAM status %#x\n", + done_ccb->ccb_h.status); } - xpt_print_path(periph->path); - kprintf("fatal error, failed" - " to attach to device\n"); - + xpt_print(periph->path, "fatal error, " + "failed to attach to device\n"); /* * Invalidate this peripheral. */ @@ -1853,7 +1789,7 @@ cddone(struct cam_periph *periph, union } } } - kfree(rdcap, M_TEMP); + kfree(rdcap, M_SCSICD); if (announce_buf[0] != '\0') { xpt_announce_periph(periph, announce_buf); if (softc->flags & CD_FLAG_CHANGER) @@ -1875,7 +1811,7 @@ cddone(struct cam_periph *periph, union * operation. */ xpt_release_ccb(done_ccb); - cam_periph_unlock(periph); + cam_periph_unhold(periph); return; } case CD_CCB_WAITING: @@ -1928,7 +1864,7 @@ cdioctl(struct dev_ioctl_args *ap) caddr_t addr = ap->a_data; struct cam_periph *periph; struct cd_softc *softc; - int error, unit; + int unit, error = 0; unit = dkunit(dev); @@ -1936,6 +1872,7 @@ cdioctl(struct dev_ioctl_args *ap) if (periph == NULL) return(ENXIO); + cam_periph_lock(periph); CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdioctl\n")); softc = (struct cd_softc *)periph->softc; @@ -1943,10 +1880,11 @@ cdioctl(struct dev_ioctl_args *ap) CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("trying to do ioctl %#lx\n", ap->a_cmd)); - error = cam_periph_lock(periph, PCATCH); - - if (error != 0) - return(error); + if ((error = cam_periph_hold(periph, PCATCH)) != 0) { + cam_periph_unlock(periph); + cam_periph_release(periph); + return (error); + } /* * If we don't have media loaded, check for it. If still don't @@ -1963,10 +1901,16 @@ cdioctl(struct dev_ioctl_args *ap) && (IOCGROUP(ap->a_cmd) == 'c')) { error = cdcheckmedia(periph); if (error != 0) { + cam_periph_unhold(periph); cam_periph_unlock(periph); return (error); } } + /* + * Drop the lock here so later mallocs can use WAITOK. The periph + * is essentially locked still with the cam_periph_hold call above. + */ + cam_periph_unlock(periph); switch (ap->a_cmd) { @@ -1978,15 +1922,17 @@ cdioctl(struct dev_ioctl_args *ap) union cd_pages *page; params.alloc_len = sizeof(union cd_mode_data_6_10); - params.mode_buf = kmalloc(params.alloc_len, M_TEMP, + params.mode_buf = kmalloc(params.alloc_len, M_SCSICD, M_WAITOK | M_ZERO); + cam_periph_lock(periph); CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, ("trying to do CDIOCPLAYTRACKS\n")); error = cdgetmode(periph, ¶ms, AUDIO_PAGE); if (error) { - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); break; } page = cdgetpage(¶ms); @@ -1994,9 +1940,11 @@ cdioctl(struct dev_ioctl_args *ap) page->audio.flags &= ~CD_PA_SOTC; page->audio.flags |= CD_PA_IMMED; error = cdsetmode(periph, ¶ms); - kfree(params.mode_buf, M_TEMP); - if (error) + kfree(params.mode_buf, M_SCSICD); + if (error) { + cam_periph_unlock(periph); break; + } /* * This was originally implemented with the PLAY @@ -2058,6 +2006,7 @@ cdioctl(struct dev_ioctl_args *ap) args->end_track, args->end_index); } + cam_periph_unlock(periph); } break; case CDIOCPLAYMSF: @@ -2068,15 +2017,17 @@ cdioctl(struct dev_ioctl_args *ap) union cd_pages *page; params.alloc_len = sizeof(union cd_mode_data_6_10); - params.mode_buf = kmalloc(params.alloc_len, M_TEMP, + params.mode_buf = kmalloc(params.alloc_len, M_SCSICD, M_WAITOK | M_ZERO); + cam_periph_lock(periph); CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, ("trying to do CDIOCPLAYMSF\n")); error = cdgetmode(periph, ¶ms, AUDIO_PAGE); if (error) { - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); break; } page = cdgetpage(¶ms); @@ -2084,9 +2035,11 @@ cdioctl(struct dev_ioctl_args *ap) page->audio.flags &= ~CD_PA_SOTC; page->audio.flags |= CD_PA_IMMED; error = cdsetmode(periph, ¶ms); - kfree(params.mode_buf, M_TEMP); - if (error) + kfree(params.mode_buf, M_SCSICD); + if (error) { + cam_periph_unlock(periph); break; + } error = cdplaymsf(periph, args->start_m, args->start_s, @@ -2094,6 +2047,7 @@ cdioctl(struct dev_ioctl_args *ap) args->end_m, args->end_s, args->end_f); + cam_periph_unlock(periph); } break; case CDIOCPLAYBLOCKS: @@ -2103,16 +2057,18 @@ cdioctl(struct dev_ioctl_args *ap) struct cd_mode_params params; union cd_pages *page; + params.alloc_len = sizeof(union cd_mode_data_6_10); + params.mode_buf = kmalloc(params.alloc_len, M_SCSICD, + M_WAITOK | M_ZERO); + cam_periph_lock(periph); CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, ("trying to do CDIOCPLAYBLOCKS\n")); - params.alloc_len = sizeof(union cd_mode_data_6_10); - params.mode_buf = kmalloc(params.alloc_len, M_TEMP, - M_WAITOK | M_ZERO); error = cdgetmode(periph, ¶ms, AUDIO_PAGE); if (error) { - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); break; } page = cdgetpage(¶ms); @@ -2120,10 +2076,13 @@ cdioctl(struct dev_ioctl_args *ap) page->audio.flags &= ~CD_PA_SOTC; page->audio.flags |= CD_PA_IMMED; error = cdsetmode(periph, ¶ms); - kfree(params.mode_buf, M_TEMP); - if (error) + kfree(params.mode_buf, M_SCSICD); + if (error) { + cam_periph_unlock(periph); break; + } error = cdplay(periph, args->blk, args->len); + cam_periph_unlock(periph); } break; case CDIOCREADSUBCHANNEL: @@ -2133,12 +2092,13 @@ cdioctl(struct dev_ioctl_args *ap) struct cd_sub_channel_info *data; u_int32_t len = args->data_len; + data = kmalloc(sizeof(struct cd_sub_channel_info), + M_SCSICD, M_WAITOK); + + cam_periph_lock(periph); CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, ("trying to do CDIOCREADSUBCHANNEL\n")); - data = kmalloc(sizeof(struct cd_sub_channel_info), - M_TEMP, M_WAITOK); - if ((len > sizeof(struct cd_sub_channel_info)) || (len < sizeof(struct cd_sub_channel_header))) { kprintf( @@ -2146,7 +2106,8 @@ cdioctl(struct dev_ioctl_args *ap) "cdioreadsubchannel: error, len=%d\n", len); error = EINVAL; - kfree(data, M_TEMP); + kfree(data, M_SCSICD); + cam_periph_unlock(periph); break; } @@ -2157,7 +2118,8 @@ cdioctl(struct dev_ioctl_args *ap) args->data_format, args->track, data, len); if (error) { - kfree(data, M_TEMP); + kfree(data, M_SCSICD); + cam_periph_unlock(periph); break; } if (softc->quirks & CD_Q_BCD_TRACKS) @@ -2166,10 +2128,11 @@ cdioctl(struct dev_ioctl_args *ap) len = min(len, ((data->header.data_len[0] << 8) + data->header.data_len[1] + sizeof(struct cd_sub_channel_header))); + cam_periph_unlock(periph); if (copyout(data, args->data, len) != 0) { error = EFAULT; } - kfree(data, M_TEMP); + kfree(data, M_SCSICD); } break; @@ -2177,15 +2140,18 @@ cdioctl(struct dev_ioctl_args *ap) { struct ioc_toc_header *th; + th = kmalloc(sizeof(struct ioc_toc_header), M_SCSICD, + M_WAITOK); + + cam_periph_lock(periph); CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, ("trying to do CDIOREADTOCHEADER\n")); - th = kmalloc(sizeof(struct ioc_toc_header), M_TEMP, - M_WAITOK); error = cdreadtoc(periph, 0, 0, (u_int8_t *)th, sizeof (*th), /*sense_flags*/0); if (error) { - kfree(th, M_TEMP); + kfree(th, M_SCSICD); + cam_periph_unlock(periph); break; } if (softc->quirks & CD_Q_BCD_TRACKS) { @@ -2198,7 +2164,8 @@ cdioctl(struct dev_ioctl_args *ap) } th->len = ntohs(th->len); bcopy(th, addr, sizeof(*th)); - kfree(th, M_TEMP); + kfree(th, M_SCSICD); + cam_periph_unlock(periph); } break; case CDIOREADTOCENTRYS: @@ -2211,12 +2178,13 @@ cdioctl(struct dev_ioctl_args *ap) u_int32_t len, readlen, idx, num; u_int32_t starting_track = te->starting_track; + data = kmalloc(sizeof(*data), M_SCSICD, M_WAITOK); + lead = kmalloc(sizeof(*lead), M_SCSICD, M_WAITOK); + + cam_periph_lock(periph); CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, ("trying to do CDIOREADTOCENTRYS\n")); - data = kmalloc(sizeof(*data), M_TEMP, M_WAITOK); - lead = kmalloc(sizeof(*lead), M_TEMP, M_WAITOK); - if (te->data_len < sizeof(struct cd_toc_entry) || (te->data_len % sizeof(struct cd_toc_entry)) != 0 || (te->address_format != CD_MSF_FORMAT @@ -2224,8 +2192,9 @@ cdioctl(struct dev_ioctl_args *ap) error = EINVAL; kprintf("scsi_cd: error in readtocentries, " "returning EINVAL\n"); - kfree(data, M_TEMP); - kfree(lead, M_TEMP); + kfree(data, M_SCSICD); + kfree(lead, M_SCSICD); + cam_periph_unlock(periph); break; } @@ -2233,8 +2202,9 @@ cdioctl(struct dev_ioctl_args *ap) error = cdreadtoc(periph, 0, 0, (u_int8_t *)th, sizeof (*th), /*sense_flags*/0); if (error) { - kfree(data, M_TEMP); - kfree(lead, M_TEMP); + kfree(data, M_SCSICD); + kfree(lead, M_SCSICD); + cam_periph_unlock(periph); break; } @@ -2255,8 +2225,9 @@ cdioctl(struct dev_ioctl_args *ap) starting_track > th->ending_track + 1) { kprintf("scsi_cd: error in readtocentries, " "returning EINVAL\n"); - kfree(data, M_TEMP); - kfree(lead, M_TEMP); + kfree(data, M_SCSICD); + kfree(lead, M_SCSICD); + cam_periph_unlock(periph); error = EINVAL; break; } @@ -2276,8 +2247,9 @@ cdioctl(struct dev_ioctl_args *ap) kprintf("scsi_cd: error in readtocentries, " "returning EINVAL\n"); error = EINVAL; - kfree(data, M_TEMP); - kfree(lead, M_TEMP); + kfree(data, M_SCSICD); + kfree(lead, M_SCSICD); + cam_periph_unlock(periph); break; } num = len / sizeof(struct cd_toc_entry); @@ -2289,8 +2261,9 @@ cdioctl(struct dev_ioctl_args *ap) readlen + sizeof (*th), /*sense_flags*/0); if (error) { - kfree(data, M_TEMP); - kfree(lead, M_TEMP); + kfree(data, M_SCSICD); + kfree(lead, M_SCSICD); + cam_periph_unlock(periph); break; } } @@ -2305,8 +2278,9 @@ cdioctl(struct dev_ioctl_args *ap) sizeof(*lead), /*sense_flags*/0); if (error) { - kfree(data, M_TEMP); - kfree(lead, M_TEMP); + kfree(data, M_SCSICD); + kfree(lead, M_SCSICD); + cam_periph_unlock(periph); break; } data->entries[idx - starting_track] = @@ -2319,9 +2293,10 @@ cdioctl(struct dev_ioctl_args *ap) } } + cam_periph_unlock(periph); error = copyout(data->entries, te->data, len); - kfree(data, M_TEMP); - kfree(lead, M_TEMP); + kfree(data, M_SCSICD); + kfree(lead, M_SCSICD); } break; case CDIOREADTOCENTRY: @@ -2332,17 +2307,19 @@ cdioctl(struct dev_ioctl_args *ap) struct ioc_toc_header *th; u_int32_t track; - CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, - ("trying to do CDIOREADTOCENTRY\n")); + data = kmalloc(sizeof(*data), M_SCSICD, M_WAITOK); - data = kmalloc(sizeof(*data), M_TEMP, M_WAITOK); + cam_periph_lock(periph); + CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, + ("trying to do CDIOREADTOCENTRY\n")); if (te->address_format != CD_MSF_FORMAT && te->address_format != CD_LBA_FORMAT) { kprintf("error in readtocentry, " " returning EINVAL\n"); - kfree(data, M_TEMP); + kfree(data, M_SCSICD); error = EINVAL; + cam_periph_unlock(periph); break; } @@ -2350,7 +2327,8 @@ cdioctl(struct dev_ioctl_args *ap) error = cdreadtoc(periph, 0, 0, (u_int8_t *)th, sizeof (*th), /*sense_flags*/0); if (error) { - kfree(data, M_TEMP); + kfree(data, M_SCSICD); + cam_periph_unlock(periph); break; } @@ -2371,8 +2349,9 @@ cdioctl(struct dev_ioctl_args *ap) track > th->ending_track + 1) { kprintf("error in readtocentry, " " returning EINVAL\n"); - kfree(data, M_TEMP); + kfree(data, M_SCSICD); error = EINVAL; + cam_periph_unlock(periph); break; } @@ -2380,7 +2359,8 @@ cdioctl(struct dev_ioctl_args *ap) (u_int8_t *)data, sizeof(*data), /*sense_flags*/0); if (error) { - kfree(data, M_TEMP); + kfree(data, M_SCSICD); + cam_periph_unlock(periph); break; } @@ -2388,7 +2368,8 @@ cdioctl(struct dev_ioctl_args *ap) data->entry.track = bcd2bin(data->entry.track); bcopy(&data->entry, &te->entry, sizeof(struct cd_toc_entry)); - kfree(data, M_TEMP); + kfree(data, M_SCSICD); + cam_periph_unlock(periph); } break; case CDIOCSETPATCH: @@ -2397,15 +2378,18 @@ cdioctl(struct dev_ioctl_args *ap) struct cd_mode_params params; union cd_pages *page; + params.alloc_len = sizeof(union cd_mode_data_6_10); + params.mode_buf = kmalloc(params.alloc_len, M_SCSICD, + M_WAITOK | M_ZERO); + + cam_periph_lock(periph); CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, ("trying to do CDIOCSETPATCH\n")); - params.alloc_len = sizeof(union cd_mode_data_6_10); - params.mode_buf = kmalloc(params.alloc_len, M_TEMP, - M_WAITOK | M_ZERO); error = cdgetmode(periph, ¶ms, AUDIO_PAGE); if (error) { - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); break; } page = cdgetpage(¶ms); @@ -2417,7 +2401,8 @@ cdioctl(struct dev_ioctl_args *ap) page->audio.port[2].channels = arg->patch[2]; page->audio.port[3].channels = arg->patch[3]; error = cdsetmode(periph, ¶ms); - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); } break; case CDIOCGETVOL: @@ -2426,15 +2411,18 @@ cdioctl(struct dev_ioctl_args *ap) struct cd_mode_params params; union cd_pages *page; + params.alloc_len = sizeof(union cd_mode_data_6_10); + params.mode_buf = kmalloc(params.alloc_len, M_SCSICD, + M_WAITOK | M_ZERO); + + cam_periph_lock(periph); CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, ("trying to do CDIOCGETVOL\n")); - params.alloc_len = sizeof(union cd_mode_data_6_10); - params.mode_buf = kmalloc(params.alloc_len, M_TEMP, - M_WAITOK | M_ZERO); error = cdgetmode(periph, ¶ms, AUDIO_PAGE); if (error) { - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); break; } page = cdgetpage(¶ms); @@ -2445,7 +2433,8 @@ cdioctl(struct dev_ioctl_args *ap) page->audio.port[RIGHT_PORT].volume; arg->vol[2] = page->audio.port[2].volume; arg->vol[3] = page->audio.port[3].volume; - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); } break; case CDIOCSETVOL: @@ -2454,15 +2443,18 @@ cdioctl(struct dev_ioctl_args *ap) struct cd_mode_params params; union cd_pages *page; + params.alloc_len = sizeof(union cd_mode_data_6_10); + params.mode_buf = kmalloc(params.alloc_len, M_SCSICD, + M_WAITOK | M_ZERO); + + cam_periph_lock(periph); CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, ("trying to do CDIOCSETVOL\n")); - params.alloc_len = sizeof(union cd_mode_data_6_10); - params.mode_buf = kmalloc(params.alloc_len, M_TEMP, - M_WAITOK | M_ZERO); error = cdgetmode(periph, ¶ms, AUDIO_PAGE); if (error) { - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); break; } page = cdgetpage(¶ms); @@ -2476,7 +2468,8 @@ cdioctl(struct dev_ioctl_args *ap) page->audio.port[2].volume = arg->vol[2]; page->audio.port[3].volume = arg->vol[3]; error = cdsetmode(periph, ¶ms); - kfree(params.mode_buf, M_TEMP); + cam_periph_unlock(periph); + kfree(params.mode_buf, M_SCSICD); } break; case CDIOCSETMONO: @@ -2484,15 +2477,18 @@ cdioctl(struct dev_ioctl_args *ap) struct cd_mode_params params; union cd_pages *page; + params.alloc_len = sizeof(union cd_mode_data_6_10); + params.mode_buf = kmalloc(params.alloc_len, M_SCSICD, + M_WAITOK | M_ZERO); + + cam_periph_lock(periph); CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, ("trying to do CDIOCSETMONO\n")); - params.alloc_len = sizeof(union cd_mode_data_6_10); - params.mode_buf = kmalloc(params.alloc_len, M_TEMP, - M_WAITOK | M_ZERO); error = cdgetmode(periph, ¶ms, AUDIO_PAGE); if (error) { - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); break; } page = cdgetpage(¶ms); @@ -2504,7 +2500,8 @@ cdioctl(struct dev_ioctl_args *ap) page->audio.port[2].channels = 0; page->audio.port[3].channels = 0; error = cdsetmode(periph, ¶ms); - kfree(params.mode_buf, M_TEMP); + cam_periph_unlock(periph); + kfree(params.mode_buf, M_SCSICD); } break; case CDIOCSETSTEREO: @@ -2512,15 +2509,18 @@ cdioctl(struct dev_ioctl_args *ap) struct cd_mode_params params; union cd_pages *page; + params.alloc_len = sizeof(union cd_mode_data_6_10); + params.mode_buf = kmalloc(params.alloc_len, M_SCSICD, + M_WAITOK | M_ZERO); + + cam_periph_lock(periph); CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, ("trying to do CDIOCSETSTEREO\n")); - params.alloc_len = sizeof(union cd_mode_data_6_10); - params.mode_buf = kmalloc(params.alloc_len, M_TEMP, - M_WAITOK | M_ZERO); error = cdgetmode(periph, ¶ms, AUDIO_PAGE); if (error) { - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); break; } page = cdgetpage(¶ms); @@ -2532,7 +2532,8 @@ cdioctl(struct dev_ioctl_args *ap) page->audio.port[2].channels = 0; page->audio.port[3].channels = 0; error = cdsetmode(periph, ¶ms); - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); } break; case CDIOCSETMUTE: @@ -2540,15 +2541,18 @@ cdioctl(struct dev_ioctl_args *ap) struct cd_mode_params params; union cd_pages *page; + params.alloc_len = sizeof(union cd_mode_data_6_10); + params.mode_buf = kmalloc(params.alloc_len, M_SCSICD, + M_WAITOK | M_ZERO); + + cam_periph_lock(periph); CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, ("trying to do CDIOCSETMUTE\n")); - params.alloc_len = sizeof(union cd_mode_data_6_10); - params.mode_buf = kmalloc(params.alloc_len, M_TEMP, - M_WAITOK | M_ZERO); error = cdgetmode(periph, ¶ms, AUDIO_PAGE); if (error) { - kfree(¶ms, M_TEMP); + kfree(¶ms, M_SCSICD); + cam_periph_unlock(periph); break; } page = cdgetpage(¶ms); @@ -2558,7 +2562,8 @@ cdioctl(struct dev_ioctl_args *ap) page->audio.port[2].channels = 0; page->audio.port[3].channels = 0; error = cdsetmode(periph, ¶ms); - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); } break; case CDIOCSETLEFT: @@ -2566,16 +2571,18 @@ cdioctl(struct dev_ioctl_args *ap) struct cd_mode_params params; union cd_pages *page; + params.alloc_len = sizeof(union cd_mode_data_6_10); + params.mode_buf = kmalloc(params.alloc_len, M_SCSICD, + M_WAITOK | M_ZERO); + + cam_periph_lock(periph); CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, ("trying to do CDIOCSETLEFT\n")); - params.alloc_len = sizeof(union cd_mode_data_6_10); - params.mode_buf = kmalloc(params.alloc_len, M_TEMP, - M_WAITOK | M_ZERO); - error = cdgetmode(periph, ¶ms, AUDIO_PAGE); if (error) { - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); break; } page = cdgetpage(¶ms); @@ -2585,7 +2592,8 @@ cdioctl(struct dev_ioctl_args *ap) page->audio.port[2].channels = 0; page->audio.port[3].channels = 0; error = cdsetmode(periph, ¶ms); - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); } break; case CDIOCSETRIGHT: @@ -2593,16 +2601,18 @@ cdioctl(struct dev_ioctl_args *ap) struct cd_mode_params params; union cd_pages *page; - CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, - ("trying to do CDIOCSETRIGHT\n")); - params.alloc_len = sizeof(union cd_mode_data_6_10); - params.mode_buf = kmalloc(params.alloc_len, M_TEMP, + params.mode_buf = kmalloc(params.alloc_len, M_SCSICD, M_WAITOK | M_ZERO); + cam_periph_lock(periph); + CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, + ("trying to do CDIOCSETRIGHT\n")); + error = cdgetmode(periph, ¶ms, AUDIO_PAGE); if (error) { - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); break; } page = cdgetpage(¶ms); @@ -2612,56 +2622,49 @@ cdioctl(struct dev_ioctl_args *ap) page->audio.port[2].channels = 0; page->audio.port[3].channels = 0; error = cdsetmode(periph, ¶ms); - kfree(params.mode_buf, M_TEMP); + kfree(params.mode_buf, M_SCSICD); + cam_periph_unlock(periph); } break; case CDIOCRESUME: + cam_periph_lock(periph); error = cdpause(periph, 1); + cam_periph_unlock(periph); break; case CDIOCPAUSE: + cam_periph_lock(periph); error = cdpause(periph, 0); + cam_periph_unlock(periph); break; case CDIOCSTART: + cam_periph_lock(periph); error = cdstartunit(periph, 0); + cam_periph_unlock(periph); break; case CDIOCCLOSE: + cam_periph_lock(periph); error = cdstartunit(periph, 1); - -#ifdef notyet - if (error != 0) - break; - - /* - * The user successfully closed the tray, run - * cdcheckmedia() again so we can re-sync the disklabel - * information. - */ - cdcheckmedia(periph); -#endif /* notyet */ + cam_periph_unlock(periph); break; case CDIOCSTOP: + cam_periph_lock(periph); error = cdstopunit(periph, 0); + cam_periph_unlock(periph); break; case CDIOCEJECT: + cam_periph_lock(periph); error = cdstopunit(periph, 1); - -#ifdef notyet - if (error != 0) - break; - - /* - * Since we've successfully ejected the media, run - * cdcheckmedia() again so we re-sync the disklabel - * information. - */ - cdcheckmedia(periph); -#endif /* notyet */ + cam_periph_unlock(periph); break; case CDIOCALLOW: + cam_periph_lock(periph); cdprevent(periph, PR_ALLOW); + cam_periph_unlock(periph); break; case CDIOCPREVENT: + cam_periph_lock(periph); cdprevent(periph, PR_PREVENT); + cam_periph_unlock(periph); break; case CDIOCSETDEBUG: /* sc_link->flags |= (SDEV_DB1 | SDEV_DB2); */ @@ -2676,10 +2679,14 @@ cdioctl(struct dev_ioctl_args *ap) error = ENOTTY; break; case CDRIOCREADSPEED: + cam_periph_lock(periph); error = cdsetspeed(periph, *(u_int32_t *)addr, CDR_MAX_SPEED); + cam_periph_unlock(periph); break; case CDRIOCWRITESPEED: + cam_periph_lock(periph); error = cdsetspeed(periph, CDR_MAX_SPEED, *(u_int32_t *)addr); + cam_periph_unlock(periph); break; case DVDIOCSENDKEY: case DVDIOCREPORTKEY: { @@ -2687,10 +2694,12 @@ cdioctl(struct dev_ioctl_args *ap) authinfo = (struct dvd_authinfo *)addr; + cam_periph_lock(periph); if (ap->a_cmd == DVDIOCREPORTKEY) error = cdreportkey(periph, authinfo); else error = cdsendkey(periph, authinfo); + cam_periph_unlock(periph); break; } case DVDIOCREADSTRUCTURE: { @@ -2698,19 +2707,26 @@ cdioctl(struct dev_ioctl_args *ap) dvdstruct = (struct dvd_struct *)addr; + cam_periph_lock(periph); error = cdreaddvdstructure(periph, dvdstruct); + cam_periph_unlock(periph); break; } default: + cam_periph_lock(periph); error = cam_periph_ioctl(periph, ap->a_cmd, addr, cderror); + cam_periph_unlock(periph); break; } - cam_periph_unlock(periph); + cam_periph_lock(periph); + cam_periph_unhold(periph); CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdioctl\n")); + cam_periph_unlock(periph); + return (error); } @@ -3034,7 +3050,7 @@ cdsize(struct cam_periph *periph, u_int3 ccb = cdgetccb(periph, /* priority */ 1); rcap_buf = kmalloc(sizeof(struct scsi_read_capacity_data), - M_TEMP, M_INTWAIT | M_ZERO); + M_SCSICD, M_INTWAIT | M_ZERO); scsi_read_capacity(&ccb->csio, /*retries*/ 1, @@ -3062,7 +3078,7 @@ cdsize(struct cam_periph *periph, u_int3 if (softc->params.blksize > 2048 && softc->params.blksize <= 2352) softc->params.blksize = 2048; - kfree(rcap_buf, M_TEMP); + kfree(rcap_buf, M_SCSICD); *size = softc->params.disksize; return (error); @@ -3113,16 +3129,16 @@ cd6byteworkaround(union ccb *ccb) * cdsetmode()! */ if (found == 0) { - xpt_print_path(periph->path); - kprintf("mode buffer not found in mode queue!\n"); + xpt_print(periph->path, + "mode buffer not found in mode queue!\n"); return (0); } params->cdb_size = 10; softc->minimum_command_size = 10; - xpt_print_path(ccb->ccb_h.path); - kprintf("%s(6) failed, increasing minimum CDB size to 10 bytes\n", - (cdb[0] == MODE_SENSE_6) ? "MODE_SENSE" : "MODE_SELECT"); + xpt_print(ccb->ccb_h.path, + "%s(6) failed, increasing minimum CDB size to 10 bytes\n", + (cdb[0] == MODE_SENSE_6) ? "MODE_SENSE" : "MODE_SELECT"); if (cdb[0] == MODE_SENSE_6) { struct scsi_mode_sense_10 ms10; @@ -3453,10 +3469,9 @@ cdgetmode(struct cam_periph *periph, str * the data length incorrectly. */ if (data_len > data->alloc_len) { - xpt_print_path(periph->path); - kprintf("allocated modepage %d length %d < returned " - "length %d\n", page, data->alloc_len, data_len); - + xpt_print(periph->path, "allocated modepage %d length " + "%d < returned length %d\n", page, data->alloc_len, + data_len); error = ENOSPC; } } @@ -3916,9 +3931,8 @@ cdreportkey(struct cam_periph *periph, s goto bailout; if (ccb->csio.resid != 0) { - xpt_print_path(periph->path); - kprintf("warning, residual for report key command is %d\n", - ccb->csio.resid); + xpt_print(periph->path, "warning, residual for report key " + "command is %d\n", ccb->csio.resid); } switch(authinfo->format) {