static int mcd_playtracks(struct mcd_softc *sc, struct ioc_play_track *pt) { struct mcd_read2 pb; int a = pt->start_track; int z = pt->end_track; int rc, i; if ((rc = mcd_read_toc(sc)) != 0) return (rc); if (sc->data.debug) device_printf(sc->dev, "playtracks from %d:%d to %d:%d\n", a, pt->start_index, z, pt->end_index); if ( a < bcd2bin(sc->data.volinfo.trk_low) || a > bcd2bin(sc->data.volinfo.trk_high) || a > z || z < bcd2bin(sc->data.volinfo.trk_low) || z > bcd2bin(sc->data.volinfo.trk_high)) return (EINVAL); for (i = 0; i < 3; i++) { pb.start_msf[i] = sc->data.toc[a].hd_pos_msf[i]; pb.end_msf[i] = sc->data.toc[z+1].hd_pos_msf[i]; } if (mcd_setmode(sc, MCD_MD_COOKED) != 0) return (EIO); return mcd_play(sc, &pb); }
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 mcd_toc_entry(struct mcd_softc *sc, struct ioc_read_toc_single_entry *te) { struct ioc_toc_header th; int rc, trk; if (te->address_format != CD_MSF_FORMAT && te->address_format != CD_LBA_FORMAT) return (EINVAL); /* Copy the toc header */ if ((rc = mcd_toc_header(sc, &th)) != 0) return (rc); /* verify starting track */ trk = te->track; if (trk == 0) trk = th.starting_track; else if (trk == MCD_LASTPLUS1) trk = th.ending_track + 1; else if (trk < th.starting_track || trk > th.ending_track + 1) return (EINVAL); /* Make sure we have a valid toc */ if ((rc=mcd_read_toc(sc)) != 0) return (rc); /* Copy the TOC data. */ if (sc->data.toc[trk].idx_no == 0) return (EIO); te->entry.control = sc->data.toc[trk].control; te->entry.addr_type = sc->data.toc[trk].addr_type; te->entry.track = sc->data.toc[trk].idx_no > 0x99 ? sc->data.toc[trk].idx_no : bcd2bin(sc->data.toc[trk].idx_no); switch (te->address_format) { case CD_MSF_FORMAT: te->entry.addr.msf.unused = 0; te->entry.addr.msf.minute = bcd2bin(sc->data.toc[trk].hd_pos_msf[0]); te->entry.addr.msf.second = bcd2bin(sc->data.toc[trk].hd_pos_msf[1]); te->entry.addr.msf.frame = bcd2bin(sc->data.toc[trk].hd_pos_msf[2]); break; case CD_LBA_FORMAT: te->entry.addr.lba = htonl(msf2hsg(sc->data.toc[trk].hd_pos_msf, 0)); break; } return (0); }
static int mcd_toc_entrys(struct mcd_softc *sc, struct ioc_read_toc_entry *te) { struct cd_toc_entry entries[MCD_MAXTOCS]; struct ioc_toc_header th; int rc, n, trk, len; if ( te->data_len < sizeof(entries[0]) || (te->data_len % sizeof(entries[0])) != 0 || (te->address_format != CD_MSF_FORMAT && te->address_format != CD_LBA_FORMAT) ) return (EINVAL); /* Copy the toc header */ if ((rc = mcd_toc_header(sc, &th)) != 0) return (rc); /* verify starting track */ trk = te->starting_track; if (trk == 0) trk = th.starting_track; else if (trk == MCD_LASTPLUS1) trk = th.ending_track + 1; else if (trk < th.starting_track || trk > th.ending_track + 1) return (EINVAL); len = ((th.ending_track + 1 - trk) + 1) * sizeof(entries[0]); if (te->data_len < len) len = te->data_len; if (len > sizeof(entries)) return (EINVAL); /* Make sure we have a valid toc */ if ((rc=mcd_read_toc(sc)) != 0) return (rc); /* Copy the TOC data. */ for (n = 0; len > 0 && trk <= th.ending_track + 1; trk++) { if (sc->data.toc[trk].idx_no == 0) continue; entries[n].control = sc->data.toc[trk].control; entries[n].addr_type = sc->data.toc[trk].addr_type; entries[n].track = sc->data.toc[trk].idx_no > 0x99 ? sc->data.toc[trk].idx_no : bcd2bin(sc->data.toc[trk].idx_no); switch (te->address_format) { case CD_MSF_FORMAT: entries[n].addr.msf.unused = 0; entries[n].addr.msf.minute = bcd2bin(sc->data.toc[trk].hd_pos_msf[0]); entries[n].addr.msf.second = bcd2bin(sc->data.toc[trk].hd_pos_msf[1]); entries[n].addr.msf.frame = bcd2bin(sc->data.toc[trk].hd_pos_msf[2]); break; case CD_LBA_FORMAT: entries[n].addr.lba = htonl(msf2hsg(sc->data.toc[trk].hd_pos_msf, 0)); break; } len -= sizeof(struct cd_toc_entry); n++; } /* copy the data back */ return copyout(entries, te->data, n * sizeof(struct cd_toc_entry)); }
int mcdopen(dev_t dev, int flag, int fmt, struct lwp *l) { int error, part; struct mcd_softc *sc; sc = device_lookup_private(&mcd_cd, MCDUNIT(dev)); if (sc == NULL) return ENXIO; mutex_enter(&sc->sc_lock); if (sc->sc_dk.dk_openmask != 0) { /* * If any partition is open, but the disk has been invalidated, * disallow further opens. */ if ((sc->flags & MCDF_LOADED) == 0) { error = EIO; goto bad3; } } else { /* * Lock the drawer. This will also notice any pending disk * change or door open indicator and clear the MCDF_LOADED bit * if necessary. */ (void) mcd_setlock(sc, MCD_LK_LOCK); if ((sc->flags & MCDF_LOADED) == 0) { /* Partially reset the state. */ sc->lastmode = MCD_MD_UNKNOWN; sc->lastupc = MCD_UPC_UNKNOWN; sc->flags |= MCDF_LOADED; /* Set the mode, causing the disk to spin up. */ if ((error = mcd_setmode(sc, MCD_MD_COOKED)) != 0) goto bad2; /* Load the physical device parameters. */ if (mcd_get_parms(sc) != 0) { error = ENXIO; goto bad2; } /* Read the table of contents. */ if ((error = mcd_read_toc(sc)) != 0) goto bad2; /* Fabricate a disk label. */ mcdgetdisklabel(sc); } } part = MCDPART(dev); MCD_TRACE("open: partition=%d disksize=%ld blksize=%d\n", part, sc->disksize, sc->blksize); /* Check that the partition exists. */ if (part != RAW_PART && (part >= sc->sc_dk.dk_label->d_npartitions || sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) { error = ENXIO; goto bad; } /* Insure only one open at a time. */ switch (fmt) { case S_IFCHR: sc->sc_dk.dk_copenmask |= (1 << part); break; case S_IFBLK: sc->sc_dk.dk_bopenmask |= (1 << part); break; } sc->sc_dk.dk_openmask = sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask; mutex_exit(&sc->sc_lock); return 0; bad2: sc->flags &= ~MCDF_LOADED; bad: if (sc->sc_dk.dk_openmask == 0) { #if 0 (void) mcd_setmode(sc, MCD_MD_SLEEP); #endif (void) mcd_setlock(sc, MCD_LK_UNLOCK); } bad3: mutex_exit(&sc->sc_lock); return error; }