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