diff options
| author | Joerg Wunsch <joerg@FreeBSD.org> | 1997-02-06 22:19:44 +0000 |
|---|---|---|
| committer | Joerg Wunsch <joerg@FreeBSD.org> | 1997-02-06 22:19:44 +0000 |
| commit | ab865e34356863bc5ba0dc1451325f83bce48d2a (patch) | |
| tree | 3f4b2cda271ecef544ddf37062ecf6ab32b01b00 | |
| parent | e040f03b1cce0241e9ed6fc16ebdf88bd461a9be (diff) | |
Notes
| -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 4ac977226c47..4fa88d779cd7 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; } } |
