diff options
author | joerg <joerg@FreeBSD.org> | 1997-02-06 22:19:44 +0000 |
---|---|---|
committer | joerg <joerg@FreeBSD.org> | 1997-02-06 22:19:44 +0000 |
commit | e8cf30c80585faaf4379b524bbe3455204d5f894 (patch) | |
tree | 3f4b2cda271ecef544ddf37062ecf6ab32b01b00 | |
parent | 8a921c50ca0654f5fe4120955a2b2e2df251281a (diff) | |
download | FreeBSD-src-e8cf30c80585faaf4379b524bbe3455204d5f894.zip FreeBSD-src-e8cf30c80585faaf4379b524bbe3455204d5f894.tar.gz |
After so many people have been bugging me :), finally implement
read-mode access to CD-ROM media in the worm(4) driver. No whistles
and bells yet, like all the CDIO* commands, but at least a start.
In order to do this, i had to slightly rearrange the semantics of an
open(2) on the worm driver: now, opening it with O_NONBLOCK set means
no actual IO operations will be intended but only ioctls are to be
processed. This mode is used by wormcontrol(8) to prepare a track
and/or session.
I have only been able to test this on a 2.2-GAMMA system by now, and
only the !DEVFS part is tested yet. Also, i have only done a dummy
burn so far, but wouldn't expect many surprises else. Report bugs to
me ASAP, if there's reasonable demand and i hear no objections, i
might consider merging it into the 2.2 branch as well.
-rw-r--r-- | sys/scsi/worm.c | 132 |
1 files changed, 80 insertions, 52 deletions
diff --git a/sys/scsi/worm.c b/sys/scsi/worm.c index 4ac9772..4fa88d7 100644 --- a/sys/scsi/worm.c +++ b/sys/scsi/worm.c @@ -46,13 +46,6 @@ * $FreeBSD$ */ -/* XXX This is PRELIMINARY. - * - * Until Bruce finishes the slice stuff there will be no partitions. - * When it is finished I hope to hoist the partition code up into - * "scsi_driver" and use common code for all devices. - */ - #include "opt_bounce.h" #include "opt_scsi.h" @@ -99,7 +92,9 @@ struct scsi_data u_int32_t n_blks; /* Number of blocks (0 for bogus) */ u_int32_t blk_size; /* Size of each blocks */ #ifdef DEVFS - void *devfs_token; /* more elaborate later */ + void *b_devfs_token; + void *c_devfs_token; + void *ctl_devfs_token; #endif struct worm_quirks *quirks; /* model-specific functions */ @@ -113,6 +108,7 @@ struct scsi_data #define WORMFL_DISK_PREPED 0x01 /* disk parameters have been spec'ed */ #define WORMFL_TRACK_PREPED 0x02 /* track parameters have been spec'ed */ #define WORMFL_WRITTEN 0x04 /* track has been written */ +#define WORMFL_IOCTL_ONLY 0x08 /* O_NDELAY, only ioctls allowed */ }; static void wormstart(u_int32_t unit, u_int32_t flags); @@ -148,10 +144,11 @@ static d_ioctl_t wormioctl; static d_strategy_t wormstrategy; #define CDEV_MAJOR 62 -static struct cdevsw worm_cdevsw = - { wormopen, wormclose, rawread, rawwrite, /*62*/ - wormioctl, nostop, nullreset, nodevtotty,/* worm */ - seltrue, nommap, wormstrategy }; +#define BDEV_MAJOR 23 +static struct cdevsw worm_cdevsw; +static struct bdevsw worm_bdevsw = + { wormopen, wormclose, wormstrategy, wormioctl, /*23*/ + nodump, nopsize, 0, "worm", &worm_cdevsw, -1 }; static int @@ -250,12 +247,15 @@ wormattach(struct scsi_link *sc_link) #ifdef DEVFS mynor = wormunit(sc_link->dev); - worm->devfs_token = + worm->b_devfs_token = + devfs_add_devswf(&worm_bdevsw, mynor, + DV_BLK, 0, 0, 0444, "worm%d", mynor); + worm->c_devfs_token = devfs_add_devswf(&worm_cdevsw, mynor, - DV_CHR, 0, 0, 0600, "rworm%d", mynor); - worm->devfs_token = + DV_CHR, 0, 0, 0644, "rworm%d", mynor); + worm->ctl_devfs_token = devfs_add_devswf(&worm_cdevsw, mynor | SCSI_CONTROL_MASK, - DV_CHR, 0, 0, 0600, "rworm%d.ctl", mynor); + DV_CHR, 0, 0, 0600, "rworm%d.ctl", mynor); #endif return 0; } @@ -374,6 +374,15 @@ worm_strategy(struct buf *bp, struct scsi_link *sc_link) unit = wormunit(bp->b_dev); worm = sc_link->sd; + if ((worm->worm_flags & WORMFL_IOCTL_ONLY) != 0) { + SC_DEBUG(sc_link, SDEV_DB3, + ("attempted IO on ioctl-only descriptor\n")); + bp->b_error = EBADF; + bp->b_flags |= B_ERROR; + biodone(bp); + return; + } + /* * The ugly modulo operation is necessary since audio tracks * have a block size of 2352 bytes. @@ -382,7 +391,11 @@ worm_strategy(struct buf *bp, struct scsi_link *sc_link) bp->b_blkno * DEV_BSIZE > worm->n_blks * worm->blk_size|| (bp->b_bcount % worm->blk_size) != 0) { SC_DEBUG(sc_link, SDEV_DB3, - ("worm block size / capacity error") ); + ("worm block size / capacity error, " + "b_blkno = %d, n_blks = %d, blk_size = %d, " + "b_bcount = %d\n", + bp->b_blkno, worm->n_blks, worm->blk_size, + bp->b_bcount) ); bp->b_error = EIO; bp->b_flags |= B_ERROR; biodone(bp); @@ -453,13 +466,13 @@ worm_open(dev_t dev, int flags, int fmt, struct proc *p, /* * The semantics of the "flags" is as follows: * - * If the device has been opened O_RDONLY, no write will be - * allowed, and the command sequence is only subject to the - * restrictions as in worm_ioctl() below. + * If the device has been opened with O_NONBLOCK set, no + * actual IO will be allowed, and the command sequence is only + * subject to the restrictions as in worm_ioctl() below. * * If the device is to be opened with O_RDWR/O_WRONLY, the * disk and track must have been prepared accordingly by - * preceding ioctls (on an O_RDONLY descriptor for the device), + * preceding ioctls (on an O_NONBLOCK descriptor for the device), * or a sequence error will result here. */ if ((flags & FWRITE) != 0 && @@ -467,11 +480,12 @@ worm_open(dev_t dev, int flags, int fmt, struct proc *p, SC_DEBUG(sc_link, SDEV_DB3, ("sequence error\n")); return ENXIO; } - + /* - * Next time actually take notice of error returns + * Next time actually take notice of error returns, + * unit attn errors are now errors. */ - sc_link->flags |= SDEV_OPEN; /* unit attn errors are now errors */ + sc_link->flags |= SDEV_OPEN; if (scsi_test_unit_ready(sc_link, SCSI_SILENT) != 0) { SC_DEBUG(sc_link, SDEV_DB3, ("not ready\n")); @@ -481,26 +495,35 @@ worm_open(dev_t dev, int flags, int fmt, struct proc *p, return ENXIO; } - /* - * XXX The check might go away if we wanna support CDROM, too. - */ - if ((flags & FWRITE) != 0) { + if ((flags & O_NONBLOCK) == 0) { scsi_start_unit(sc_link, SCSI_SILENT); scsi_prevent(sc_link, PR_PREVENT, SCSI_SILENT); - } - if((flags & FWRITE) != 0 && - ((error = worm_rezero_unit(sc_link)) != 0 || - (error = worm_size(sc_link, 0)) != 0 || - (error = (worm->quirks->prepare_track) - (sc_link, worm->audio, worm->preemp)) != 0)) { - SC_DEBUG(sc_link, SDEV_DB3, - ("rezero, get size, or prepare_track failed\n")); - scsi_stop_unit(sc_link, 0, SCSI_SILENT); - scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT); - worm->worm_flags &= ~WORMFL_TRACK_PREPED; - sc_link->flags &= ~SDEV_OPEN; - } + if((flags & FWRITE) != 0) { + if ((error = worm_rezero_unit(sc_link)) != 0 || + (error = worm_size(sc_link, 0)) != 0 || + (error = (worm->quirks->prepare_track) + (sc_link, worm->audio, worm->preemp)) != 0) { + SC_DEBUG(sc_link, SDEV_DB3, + ("rezero, get size, or prepare_track failed\n")); + scsi_stop_unit(sc_link, 0, SCSI_SILENT); + scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT); + worm->worm_flags &= ~WORMFL_TRACK_PREPED; + sc_link->flags &= ~SDEV_OPEN; + } + } else { + /* read/only */ + if ((error = worm_size(sc_link, 0)) != 0) { + SC_DEBUG(sc_link, SDEV_DB3, + ("get size failed\n")); + scsi_stop_unit(sc_link, 0, SCSI_SILENT); + scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT); + worm->worm_flags &= ~WORMFL_TRACK_PREPED; + sc_link->flags &= ~SDEV_OPEN; + } + } + } else + worm->worm_flags |= WORMFL_IOCTL_ONLY; return error; } @@ -510,18 +533,25 @@ worm_close(dev_t dev, int flags, int fmt, struct proc *p, struct scsi_link *sc_link) { struct scsi_data *worm = sc_link->sd; + errval error; - scsi_stop_unit(sc_link, 0, SCSI_SILENT); - scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT); + error = 0; - sc_link->flags &= ~SDEV_OPEN; + if ((worm->worm_flags & WORMFL_IOCTL_ONLY) == 0) { + scsi_stop_unit(sc_link, 0, SCSI_SILENT); + scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT); + + sc_link->flags &= ~SDEV_OPEN; - if((flags & FWRITE) != 0) { - worm->worm_flags &= ~WORMFL_TRACK_PREPED; - (worm->quirks->finalize_track)(sc_link); + if ((flags & FWRITE) != 0) { + worm->worm_flags &= ~WORMFL_TRACK_PREPED; + error = (worm->quirks->finalize_track)(sc_link); + } } + sc_link->flags &= ~SDEV_OPEN; + worm->worm_flags &= ~WORMFL_IOCTL_ONLY; - return 0; + return error; } /* @@ -675,11 +705,9 @@ worm_quirk_select(struct scsi_link *sc_link, u_int32_t unit, static void worm_drvinit(void *unused) { - dev_t dev; - if (! worm_devsw_installed) { - dev = makedev(CDEV_MAJOR, 0); - cdevsw_add(&dev, &worm_cdevsw, NULL); + if (!worm_devsw_installed) { + bdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &worm_bdevsw); worm_devsw_installed = 1; } } |