xref: /dflybsd-src/sys/dev/virtual/vkernel/cdrom/vcd.c (revision 14075a68e0c6d2f7d920fec06751e277318c6d3c)
19ed84223SSascha Wildner /*
29ed84223SSascha Wildner  * Copyright (c) 2007 The DragonFly Project.  All rights reserved.
39ed84223SSascha Wildner  *
49ed84223SSascha Wildner  * This code is derived from software contributed to The DragonFly Project
59ed84223SSascha Wildner  * by Matthew Dillon <dillon@backplane.com>
69ed84223SSascha Wildner  *
79ed84223SSascha Wildner  * Redistribution and use in source and binary forms, with or without
89ed84223SSascha Wildner  * modification, are permitted provided that the following conditions
99ed84223SSascha Wildner  * are met:
109ed84223SSascha Wildner  *
119ed84223SSascha Wildner  * 1. Redistributions of source code must retain the above copyright
129ed84223SSascha Wildner  *    notice, this list of conditions and the following disclaimer.
139ed84223SSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
149ed84223SSascha Wildner  *    notice, this list of conditions and the following disclaimer in
159ed84223SSascha Wildner  *    the documentation and/or other materials provided with the
169ed84223SSascha Wildner  *    distribution.
179ed84223SSascha Wildner  * 3. Neither the name of The DragonFly Project nor the names of its
189ed84223SSascha Wildner  *    contributors may be used to endorse or promote products derived
199ed84223SSascha Wildner  *    from this software without specific, prior written permission.
209ed84223SSascha Wildner  *
219ed84223SSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
229ed84223SSascha Wildner  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
239ed84223SSascha Wildner  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
249ed84223SSascha Wildner  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
259ed84223SSascha Wildner  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
269ed84223SSascha Wildner  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
279ed84223SSascha Wildner  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
289ed84223SSascha Wildner  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
299ed84223SSascha Wildner  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
309ed84223SSascha Wildner  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
319ed84223SSascha Wildner  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
329ed84223SSascha Wildner  * SUCH DAMAGE.
339ed84223SSascha Wildner  */
349ed84223SSascha Wildner 
359ed84223SSascha Wildner /*
369ed84223SSascha Wildner  * Virtual CDROM driver
379ed84223SSascha Wildner  */
389ed84223SSascha Wildner #include <sys/types.h>
399ed84223SSascha Wildner #include <sys/param.h>
409ed84223SSascha Wildner #include <sys/systm.h>
419ed84223SSascha Wildner #include <sys/kernel.h>
429ed84223SSascha Wildner #include <sys/malloc.h>
439ed84223SSascha Wildner #include <sys/conf.h>
449ed84223SSascha Wildner #include <sys/buf.h>
459ed84223SSascha Wildner #include <sys/devicestat.h>
469ed84223SSascha Wildner #include <sys/disk.h>
479ed84223SSascha Wildner #include <machine/md_var.h>
489ed84223SSascha Wildner 
499ed84223SSascha Wildner #include <sys/buf2.h>
509ed84223SSascha Wildner 
519ed84223SSascha Wildner #include <sys/stat.h>
529ed84223SSascha Wildner #include <unistd.h>
539ed84223SSascha Wildner 
549ed84223SSascha Wildner struct vcd_softc {
559ed84223SSascha Wildner 	struct bio_queue_head bio_queue;
569ed84223SSascha Wildner 	struct devstat stats;
579ed84223SSascha Wildner 	struct disk disk;
589ed84223SSascha Wildner 	cdev_t dev;
599ed84223SSascha Wildner 	int unit;
609ed84223SSascha Wildner 	int fd;
619ed84223SSascha Wildner };
629ed84223SSascha Wildner 
639ed84223SSascha Wildner static d_strategy_t	vcdstrategy;
649ed84223SSascha Wildner static d_open_t		vcdopen;
659ed84223SSascha Wildner 
669ed84223SSascha Wildner static struct dev_ops vcd_ops = {
679ed84223SSascha Wildner 	{ "vcd", 0, D_DISK },
689ed84223SSascha Wildner         .d_open =	vcdopen,
699ed84223SSascha Wildner         .d_close =	nullclose,
709ed84223SSascha Wildner         .d_read =	physread,
719ed84223SSascha Wildner         .d_write =	physwrite,
729ed84223SSascha Wildner         .d_strategy =	vcdstrategy,
739ed84223SSascha Wildner };
749ed84223SSascha Wildner 
759ed84223SSascha Wildner static void
vcdinit(void * dummy __unused)769ed84223SSascha Wildner vcdinit(void *dummy __unused)
779ed84223SSascha Wildner {
789ed84223SSascha Wildner 	struct vkdisk_info *dsk;
799ed84223SSascha Wildner 	struct vcd_softc *sc;
80*14075a68SAntonio Huete Jimenez 	struct disk_info info;
819ed84223SSascha Wildner 	struct stat st;
829ed84223SSascha Wildner 	int i;
839ed84223SSascha Wildner 
849ed84223SSascha Wildner 	for (i = 0; i < DiskNum; i++) {
859ed84223SSascha Wildner 		/* check that the 'bus device' has been initialized */
869ed84223SSascha Wildner 		dsk = &DiskInfo[i];
879ed84223SSascha Wildner 		if (dsk == NULL || dsk->type != VKD_CD)
889ed84223SSascha Wildner 			continue;
899ed84223SSascha Wildner 		if (dsk->fd < 0 || fstat(dsk->fd, &st) < 0)
909ed84223SSascha Wildner 			continue;
919ed84223SSascha Wildner 
929ed84223SSascha Wildner 		/* and create a new device */
939ed84223SSascha Wildner 		sc = kmalloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
949ed84223SSascha Wildner 		sc->unit = dsk->unit;
959ed84223SSascha Wildner 		sc->fd = dsk->fd;
969ed84223SSascha Wildner 		bioq_init(&sc->bio_queue);
979ed84223SSascha Wildner 		devstat_add_entry(&sc->stats, "vcd", sc->unit, 2048,
989ed84223SSascha Wildner 				  DEVSTAT_NO_ORDERED_TAGS,
999ed84223SSascha Wildner 				  DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER,
1009ed84223SSascha Wildner 				  DEVSTAT_PRIORITY_DISK);
1019ed84223SSascha Wildner 		sc->dev = disk_create(sc->unit, &sc->disk, &vcd_ops);
1029ed84223SSascha Wildner 		sc->dev->si_drv1 = sc;
1039ed84223SSascha Wildner 		sc->dev->si_iosize_max = 256 * 1024;
1049ed84223SSascha Wildner 
1059ed84223SSascha Wildner 		bzero(&info, sizeof(info));
1069ed84223SSascha Wildner 		info.d_media_blksize = 2048;
1079ed84223SSascha Wildner 		info.d_media_blocks = st.st_size / info.d_media_blksize;
1089ed84223SSascha Wildner 		info.d_dsflags = DSO_ONESLICE | DSO_COMPATLABEL | DSO_COMPATPARTA |
1099ed84223SSascha Wildner 		    DSO_RAWEXTENSIONS;
1109ed84223SSascha Wildner 		info.d_nheads = 1;
1119ed84223SSascha Wildner 		info.d_ncylinders = 1;
1129ed84223SSascha Wildner 		info.d_secpertrack = info.d_media_blocks;
1139ed84223SSascha Wildner 		info.d_secpercyl = info.d_secpertrack * info.d_nheads;
1149ed84223SSascha Wildner 
1159ed84223SSascha Wildner 		disk_setdiskinfo(&sc->disk, &info);
116*14075a68SAntonio Huete Jimenez 	}
117*14075a68SAntonio Huete Jimenez }
118*14075a68SAntonio Huete Jimenez 
119*14075a68SAntonio Huete Jimenez SYSINIT(vcdisk, SI_SUB_DRIVERS, SI_ORDER_FIRST, vcdinit, NULL);
120*14075a68SAntonio Huete Jimenez 
121*14075a68SAntonio Huete Jimenez static int
vcdopen(struct dev_open_args * ap)122*14075a68SAntonio Huete Jimenez vcdopen(struct dev_open_args *ap)
123*14075a68SAntonio Huete Jimenez {
124*14075a68SAntonio Huete Jimenez 	struct vcd_softc *sc;
125*14075a68SAntonio Huete Jimenez 	struct stat st;
126*14075a68SAntonio Huete Jimenez 	cdev_t dev;
127*14075a68SAntonio Huete Jimenez 
128*14075a68SAntonio Huete Jimenez 	dev = ap->a_head.a_dev;
129*14075a68SAntonio Huete Jimenez 	sc = dev->si_drv1;
130*14075a68SAntonio Huete Jimenez 	if (fstat(sc->fd, &st) < 0 || st.st_size == 0)
131*14075a68SAntonio Huete Jimenez 		return(ENXIO);
132*14075a68SAntonio Huete Jimenez 
1339ed84223SSascha Wildner 	return(0);
1349ed84223SSascha Wildner }
1359ed84223SSascha Wildner 
1369ed84223SSascha Wildner static int
vcdstrategy(struct dev_strategy_args * ap)1379ed84223SSascha Wildner vcdstrategy(struct dev_strategy_args *ap)
1389ed84223SSascha Wildner {
1399ed84223SSascha Wildner 	struct bio *bio = ap->a_bio;
1409ed84223SSascha Wildner 	struct buf *bp;
1419ed84223SSascha Wildner 	struct vcd_softc *sc;
1429ed84223SSascha Wildner 	cdev_t dev;
1439ed84223SSascha Wildner 	int n;
1449ed84223SSascha Wildner 
1459ed84223SSascha Wildner 	dev = ap->a_head.a_dev;
1469ed84223SSascha Wildner 	sc = dev->si_drv1;
1479ed84223SSascha Wildner 
1489ed84223SSascha Wildner 	bioqdisksort(&sc->bio_queue, bio);
1499ed84223SSascha Wildner 	while ((bio = bioq_takefirst(&sc->bio_queue)) != NULL) {
1509ed84223SSascha Wildner 		bp = bio->bio_buf;
1519ed84223SSascha Wildner 
1529ed84223SSascha Wildner 		devstat_start_transaction(&sc->stats);
1539ed84223SSascha Wildner 
1549ed84223SSascha Wildner 		switch(bp->b_cmd) {
1559ed84223SSascha Wildner 		case BUF_CMD_READ:
1569ed84223SSascha Wildner 			n = pread(sc->fd, bp->b_data,
1579ed84223SSascha Wildner 				  bp->b_bcount, bio->bio_offset);
1589ed84223SSascha Wildner 			break;
1599ed84223SSascha Wildner 		case BUF_CMD_WRITE:
1609ed84223SSascha Wildner 			/* XXX HANDLE SHORT WRITE XXX */
1619ed84223SSascha Wildner 			n = pwrite(sc->fd, bp->b_data,
1629ed84223SSascha Wildner 				   bp->b_bcount, bio->bio_offset);
1639ed84223SSascha Wildner 			break;
1649ed84223SSascha Wildner 		default:
1659ed84223SSascha Wildner 			panic("vcd: bad b_cmd %d", bp->b_cmd);
1669ed84223SSascha Wildner 			break; /* not reached */
1679ed84223SSascha Wildner 		}
1689ed84223SSascha Wildner 		if (n != bp->b_bcount) {
1699ed84223SSascha Wildner 			bp->b_error = EIO;
1709ed84223SSascha Wildner 			bp->b_flags |= B_ERROR;
1719ed84223SSascha Wildner 		}
1729ed84223SSascha Wildner 
1739ed84223SSascha Wildner 		bp->b_resid = bp->b_bcount - n;
1749ed84223SSascha Wildner 		devstat_end_transaction_buf(&sc->stats, bp);
1759ed84223SSascha Wildner 		biodone(bio);
1769ed84223SSascha Wildner 	}
1779ed84223SSascha Wildner 	return(0);
1789ed84223SSascha Wildner }
179