static int mcdopen(dev_t dev, int flags, int fmt, struct thread *td) { struct mcd_softc *sc; int r,retry; sc = (struct mcd_softc *)dev->si_drv1; /* not initialized*/ if (!(sc->data.flags & MCDINIT)) return (ENXIO); /* invalidated in the meantime? mark all open part's invalid */ if (!(sc->data.flags & MCDVALID) && sc->data.openflags) return (ENXIO); if (mcd_getstat(sc, 1) == -1) return (EIO); if ( (sc->data.status & (MCDDSKCHNG|MCDDOOROPEN)) || !(sc->data.status & MCDDSKIN)) for (retry = 0; retry < DISK_SENSE_SECS * WAIT_FRAC; retry++) { (void) tsleep((caddr_t)sc, PSOCK | PCATCH, "mcdsn1", hz/WAIT_FRAC); if ((r = mcd_getstat(sc, 1)) == -1) return (EIO); if (r != -2) break; } if (sc->data.status & MCDDOOROPEN) { device_printf(sc->dev, "door is open\n"); return (ENXIO); } if (!(sc->data.status & MCDDSKIN)) { device_printf(sc->dev, "no CD inside\n"); return (ENXIO); } if (sc->data.status & MCDDSKCHNG) { device_printf(sc->dev, "CD not sensed\n"); return (ENXIO); } if (mcdsize(dev) < 0) { device_printf(sc->dev, "failed to get disk size\n"); return (ENXIO); } dev->si_bsize_phys = sc->data.blksize; sc->data.openflags = 1; sc->data.partflags |= MCDREADRAW; sc->data.flags |= MCDVALID; (void) mcd_lock_door(sc, MCD_LK_LOCK); if (!(sc->data.flags & MCDVALID)) return (ENXIO); return mcd_read_toc(sc); }
static int mcdclose(dev_t dev, int flags, int fmt, struct thread *td) { struct mcd_softc *sc; sc = (struct mcd_softc *)dev->si_drv1; if (!(sc->data.flags & MCDINIT) || !sc->data.openflags) return (ENXIO); (void) mcd_lock_door(sc, MCD_LK_UNLOCK); sc->data.openflags = 0; sc->data.partflags &= ~MCDREADRAW; return (0); }
static int mcdclose(struct cdev *dev, int flags, int fmt, struct thread *td) { struct mcd_softc *sc; sc = (struct mcd_softc *)dev->si_drv1; MCD_LOCK(sc); KASSERT(sc->data.openflags, ("device not open")); (void) mcd_lock_door(sc, MCD_LK_UNLOCK); sc->data.openflags = 0; sc->data.partflags &= ~MCDREADRAW; MCD_UNLOCK(sc); return (0); }
static int mcdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td) { struct mcd_softc *sc; int retry,r; sc = (struct mcd_softc *)dev->si_drv1; if (mcd_getstat(sc, 1) == -1) /* detect disk change too */ return (EIO); MCD_TRACE("ioctl called 0x%lx\n", cmd); switch (cmd) { case CDIOCSETPATCH: case CDIOCGETVOL: case CDIOCSETVOL: case CDIOCSETMONO: case CDIOCSETSTERIO: case CDIOCSETMUTE: case CDIOCSETLEFT: case CDIOCSETRIGHT: return (EINVAL); case CDIOCEJECT: return mcd_eject(sc); case CDIOCSETDEBUG: sc->data.debug = 1; return (0); case CDIOCCLRDEBUG: sc->data.debug = 0; return (0); case CDIOCRESET: return mcd_hard_reset(sc); case CDIOCALLOW: return mcd_lock_door(sc, MCD_LK_UNLOCK); case CDIOCPREVENT: return mcd_lock_door(sc, MCD_LK_LOCK); case CDIOCCLOSE: return mcd_inject(sc); } if (!(sc->data.flags & MCDVALID)) { if ( (sc->data.status & (MCDDSKCHNG|MCDDOOROPEN)) || !(sc->data.status & MCDDSKIN)) for (retry = 0; retry < DISK_SENSE_SECS * WAIT_FRAC; retry++) { (void) tsleep((caddr_t)sc, PSOCK | PCATCH, "mcdsn2", hz/WAIT_FRAC); if ((r = mcd_getstat(sc, 1)) == -1) return (EIO); if (r != -2) break; } if ( (sc->data.status & (MCDDOOROPEN|MCDDSKCHNG)) || !(sc->data.status & MCDDSKIN) || mcdsize(dev) < 0 ) return (ENXIO); sc->data.flags |= MCDVALID; sc->data.partflags |= MCDREADRAW; (void) mcd_lock_door(sc, MCD_LK_LOCK); if (!(sc->data.flags & MCDVALID)) return (ENXIO); } switch (cmd) { case DIOCGMEDIASIZE: *(off_t *)addr = (off_t)sc->data.disksize * sc->data.blksize; return (0); break; case DIOCGSECTORSIZE: *(u_int *)addr = sc->data.blksize; return (0); break; case CDIOCPLAYTRACKS: return mcd_playtracks(sc, (struct ioc_play_track *) addr); case CDIOCPLAYBLOCKS: return mcd_playblocks(sc, (struct ioc_play_blocks *) addr); case CDIOCPLAYMSF: return mcd_playmsf(sc, (struct ioc_play_msf *) addr); case CDIOCREADSUBCHANNEL: return mcd_subchan(sc, (struct ioc_read_subchannel *) addr); case CDIOREADTOCHEADER: return mcd_toc_header(sc, (struct ioc_toc_header *) addr); case CDIOREADTOCENTRYS: return mcd_toc_entrys(sc, (struct ioc_read_toc_entry *) addr); case CDIOCRESUME: return mcd_resume(sc); case CDIOCPAUSE: return mcd_pause(sc); case CDIOCSTART: if (mcd_setmode(sc, MCD_MD_COOKED) != 0) return (EIO); return (0); case CDIOCSTOP: return mcd_stop(sc); default: return (ENOTTY); } /*NOTREACHED*/ }