Add support for accessing individual tracks on a CD.

This is done by misusing the device minor a bit to encode the
track no there.

So to read track #4 just use /dev/acdNt4 where N is the device #.

The driver no automatically sets the blocksize (sectorsize) to
what the track is set to in the TOC.

This has the nice effect that you can now rip audioi tracks
by simply doing:

dd if=/dev/acdNt2 of=audiotrack2.raw bs=2352

it cant be much simpler than that :)

NOTE: the original acdNa & acdNc device still work as usual,
except the blocksize is set according to track0.
This commit is contained in:
sos 2000-08-11 09:21:36 +00:00
parent 85c9a2ddc1
commit 5337af51e2

View File

@ -483,9 +483,17 @@ msf2lba(u_int8_t m, u_int8_t s, u_int8_t f)
static int
acdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
{
struct acd_softc *cdp = dev->si_drv1;
struct acd_softc *cdp;
int track = (dev->si_udev & 0x00ff0000) >> 16;
if (!cdp)
if (track) {
dev_t dev1 = makedev(major(dev), (dev->si_udev & 0xff0000ff));
if (track < ((struct acd_softc *)(dev1->si_drv1))->toc.hdr.ending_track)
dev->si_drv1 = dev1->si_drv1;
}
if (!(cdp = dev->si_drv1))
return ENXIO;
if (flags & FWRITE) {
@ -513,6 +521,9 @@ acdclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
{
struct acd_softc *cdp = dev->si_drv1;
if (!cdp)
return ENXIO;
if (count_dev(dev) == 1) {
if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) {
acd_select_slot(cdp);
@ -530,6 +541,9 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flags, struct proc *p)
struct acd_softc *cdp = dev->si_drv1;
int32_t error = 0;
if (!cdp)
return ENXIO;
if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) {
acd_select_slot(cdp);
tsleep(&cdp->changer_info, PRIBIO, "acdctl", 0);
@ -1079,6 +1093,7 @@ acd_start(struct atapi_softc *atp)
struct bio *bp = bioq_first(&cdp->bio_queue);
u_int32_t lba, count;
int8_t ccb[16];
int track, blocksize;
if (cdp->changer_info) {
int i;
@ -1111,8 +1126,18 @@ acd_start(struct atapi_softc *atp)
}
bzero(ccb, sizeof(ccb));
count = (bp->bio_bcount + (cdp->block_size - 1)) / cdp->block_size;
lba = bp->bio_offset / cdp->block_size;
track = ((bp->bio_dev->si_udev & 0x00ff0000) >> 16) - 1;
if (track) {
lba += ntohl(cdp->toc.tab[track].addr.lba);
blocksize = (cdp->toc.tab[track].control & 4) ? 2048 : 2352;
}
else
blocksize = cdp->block_size;
count = (bp->bio_bcount + (blocksize - 1)) / blocksize;
if (bp->bio_cmd == BIO_READ) {
/* if transfer goes beyond EOM adjust it to be within limits */
@ -1124,7 +1149,7 @@ acd_start(struct atapi_softc *atp)
return;
}
}
if (cdp->block_size == 2048)
if (blocksize == 2048)
ccb[0] = ATAPI_READ_BIG;
else {
ccb[0] = ATAPI_READ_CD;
@ -1144,7 +1169,7 @@ acd_start(struct atapi_softc *atp)
devstat_start_transaction(cdp->stats);
atapi_queue_cmd(cdp->atp, ccb, bp->bio_data, count * cdp->block_size,
atapi_queue_cmd(cdp->atp, ccb, bp->bio_data, count * blocksize,
bp->bio_cmd == BIO_READ ? ATPR_F_READ : 0, 30, acd_done,bp);
}
@ -1215,6 +1240,7 @@ acd_read_toc(struct acd_softc *cdp)
cdp->info.volsize = ntohl(cdp->info.volsize);
cdp->info.blksize = ntohl(cdp->info.blksize);
cdp->block_size = (cdp->toc.tab[0].control & 4) ? 2048 : 2352;
#ifdef ACD_DEBUG
if (cdp->info.volsize && cdp->toc.hdr.ending_track) {