Home | History | Annotate | Line # | Download | only in g1
      1  1.1  tsutsui /*	$NetBSD: gdrom.c,v 1.1 2016/12/29 11:49:05 tsutsui Exp $	*/
      2  1.1  tsutsui 
      3  1.1  tsutsui /*-
      4  1.1  tsutsui  * Copyright (c) 2001 Marcus Comstedt
      5  1.1  tsutsui  * All rights reserved.
      6  1.1  tsutsui  *
      7  1.1  tsutsui  * Redistribution and use in source and binary forms, with or without
      8  1.1  tsutsui  * modification, are permitted provided that the following conditions
      9  1.1  tsutsui  * are met:
     10  1.1  tsutsui  * 1. Redistributions of source code must retain the above copyright
     11  1.1  tsutsui  *    notice, this list of conditions and the following disclaimer.
     12  1.1  tsutsui  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  tsutsui  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  tsutsui  *    documentation and/or other materials provided with the distribution.
     15  1.1  tsutsui  * 3. All advertising materials mentioning features or use of this software
     16  1.1  tsutsui  *    must display the following acknowledgement:
     17  1.1  tsutsui  *	This product includes software developed by Marcus Comstedt.
     18  1.1  tsutsui  * 4. Neither the name of The NetBSD Foundation nor the names of its
     19  1.1  tsutsui  *    contributors may be used to endorse or promote products derived
     20  1.1  tsutsui  *    from this software without specific prior written permission.
     21  1.1  tsutsui  *
     22  1.1  tsutsui  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     23  1.1  tsutsui  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     24  1.1  tsutsui  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     25  1.1  tsutsui  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     26  1.1  tsutsui  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     27  1.1  tsutsui  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     28  1.1  tsutsui  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     29  1.1  tsutsui  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     30  1.1  tsutsui  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     31  1.1  tsutsui  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     32  1.1  tsutsui  * POSSIBILITY OF SUCH DAMAGE.
     33  1.1  tsutsui  */
     34  1.1  tsutsui 
     35  1.1  tsutsui /*
     36  1.1  tsutsui  * WIP gdrom driver using MI ATA/ATAPI drivers.
     37  1.1  tsutsui  *
     38  1.1  tsutsui  * XXX: Still not functional because GD-ROM driver does not generate
     39  1.1  tsutsui  * XXX: interrupts after ATAPI command packet xfers and such quirks
     40  1.1  tsutsui  * XXX: need to be handled in MI scsipi layer.
     41  1.1  tsutsui  */
     42  1.1  tsutsui 
     43  1.1  tsutsui #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
     44  1.1  tsutsui __KERNEL_RCSID(0, "$NetBSD: gdrom.c,v 1.1 2016/12/29 11:49:05 tsutsui Exp $");
     45  1.1  tsutsui 
     46  1.1  tsutsui #include <sys/param.h>
     47  1.1  tsutsui #include <sys/systm.h>
     48  1.1  tsutsui #include <sys/device.h>
     49  1.1  tsutsui 
     50  1.1  tsutsui #include <sys/buf.h>
     51  1.1  tsutsui #include <sys/bufq.h>
     52  1.1  tsutsui #include <sys/ioctl.h>
     53  1.1  tsutsui #include <sys/fcntl.h>
     54  1.1  tsutsui #include <sys/disklabel.h>
     55  1.1  tsutsui #include <sys/disk.h>
     56  1.1  tsutsui #include <sys/cdio.h>
     57  1.1  tsutsui #include <sys/proc.h>
     58  1.1  tsutsui #include <sys/conf.h>
     59  1.1  tsutsui #include <sys/scsiio.h>
     60  1.1  tsutsui 
     61  1.1  tsutsui #include <dev/scsipi/scsi_spc.h>
     62  1.1  tsutsui #include <dev/scsipi/scsipi_all.h>
     63  1.1  tsutsui #include <dev/scsipi/scsipi_cd.h>
     64  1.1  tsutsui #include <dev/scsipi/scsipi_disk.h>
     65  1.1  tsutsui #include <dev/scsipi/scsi_all.h>
     66  1.1  tsutsui #include <dev/scsipi/scsi_disk.h>
     67  1.1  tsutsui #include <dev/scsipi/scsipiconf.h>
     68  1.1  tsutsui #include <dev/scsipi/scsipi_base.h>
     69  1.1  tsutsui 
     70  1.1  tsutsui #include "ioconf.h"
     71  1.1  tsutsui 
     72  1.1  tsutsui struct gdrom_softc {
     73  1.1  tsutsui 	device_t sc_dev;	/* generic device info */
     74  1.1  tsutsui 	struct disk sc_dk;	/* generic disk info */
     75  1.1  tsutsui 	struct bufq_state *sc_bufq;	/* device buffer queue */
     76  1.1  tsutsui 	struct buf curbuf;	/* state of current I/O operation */
     77  1.1  tsutsui 
     78  1.1  tsutsui 	kmutex_t sc_lock;
     79  1.1  tsutsui 	struct scsipi_periph *sc_periph;
     80  1.1  tsutsui 
     81  1.1  tsutsui 	bool is_open;
     82  1.1  tsutsui 	bool is_busy;
     83  1.1  tsutsui 	bool is_active;
     84  1.1  tsutsui 	int openpart_start;	/* start sector of currently open partition */
     85  1.1  tsutsui 
     86  1.1  tsutsui 	int cmd_active;
     87  1.1  tsutsui 	void *cmd_result_buf;	/* where to store result data (16 bit aligned) */
     88  1.1  tsutsui 	int cmd_result_size;	/* number of bytes allocated for buf */
     89  1.1  tsutsui 	int cmd_actual;		/* number of bytes actually read */
     90  1.1  tsutsui 	int cmd_cond;		/* resulting condition of command */
     91  1.1  tsutsui };
     92  1.1  tsutsui 
     93  1.1  tsutsui struct gd_toc {
     94  1.1  tsutsui 	unsigned int entry[99];
     95  1.1  tsutsui 	unsigned int first, last;
     96  1.1  tsutsui 	unsigned int leadout;
     97  1.1  tsutsui };
     98  1.1  tsutsui 
     99  1.1  tsutsui static int  gdrommatch(device_t, cfdata_t, void *);
    100  1.1  tsutsui static void gdromattach(device_t, device_t, void *);
    101  1.1  tsutsui 
    102  1.1  tsutsui #if 0
    103  1.1  tsutsui static int gdrom_command_sense(struct gdrom_softc *, void *, void *,
    104  1.1  tsutsui     unsigned int, int *);
    105  1.1  tsutsui #endif
    106  1.1  tsutsui static int gdrom_read_toc(struct gdrom_softc *, struct gd_toc *);
    107  1.1  tsutsui static int gdrom_read_sectors(struct gdrom_softc *, struct buf *);
    108  1.1  tsutsui static int gdrom_mount_disk(struct gdrom_softc *);
    109  1.1  tsutsui static void gdrom_start(struct scsipi_periph *);
    110  1.1  tsutsui static void gdrom_done(struct scsipi_xfer *, int);
    111  1.1  tsutsui 
    112  1.1  tsutsui static const struct scsipi_inquiry_pattern gdrom_patterns[] = {
    113  1.1  tsutsui 	{T_DIRECT, T_FIXED,
    114  1.1  tsutsui 	 "", "DCR-MOD", ""},
    115  1.1  tsutsui };
    116  1.1  tsutsui 
    117  1.1  tsutsui static dev_type_open(gdromopen);
    118  1.1  tsutsui static dev_type_close(gdromclose);
    119  1.1  tsutsui static dev_type_read(gdromread);
    120  1.1  tsutsui static dev_type_write(gdromwrite);
    121  1.1  tsutsui static dev_type_ioctl(gdromioctl);
    122  1.1  tsutsui static dev_type_strategy(gdromstrategy);
    123  1.1  tsutsui 
    124  1.1  tsutsui const struct bdevsw gdrom_bdevsw = {
    125  1.1  tsutsui 	.d_open = gdromopen,
    126  1.1  tsutsui 	.d_close = gdromclose,
    127  1.1  tsutsui 	.d_strategy = gdromstrategy,
    128  1.1  tsutsui 	.d_ioctl = gdromioctl,
    129  1.1  tsutsui 	.d_dump = nodump,
    130  1.1  tsutsui 	.d_psize = nosize,
    131  1.1  tsutsui 	.d_discard = nodiscard,
    132  1.1  tsutsui 	.d_flag = D_DISK
    133  1.1  tsutsui };
    134  1.1  tsutsui 
    135  1.1  tsutsui const struct cdevsw gdrom_cdevsw = {
    136  1.1  tsutsui 	.d_open = gdromopen,
    137  1.1  tsutsui 	.d_close = gdromclose,
    138  1.1  tsutsui 	.d_read = gdromread,
    139  1.1  tsutsui 	.d_write = gdromwrite,
    140  1.1  tsutsui 	.d_ioctl = gdromioctl,
    141  1.1  tsutsui 	.d_stop = nostop,
    142  1.1  tsutsui 	.d_tty = notty,
    143  1.1  tsutsui 	.d_poll = nopoll,
    144  1.1  tsutsui 	.d_mmap = nommap,
    145  1.1  tsutsui 	.d_kqfilter = nokqfilter,
    146  1.1  tsutsui 	.d_discard = nodiscard,
    147  1.1  tsutsui 	.d_flag = D_DISK
    148  1.1  tsutsui };
    149  1.1  tsutsui 
    150  1.1  tsutsui CFATTACH_DECL_NEW(gdrom, sizeof(struct gdrom_softc),
    151  1.1  tsutsui     gdrommatch, gdromattach, NULL, NULL);
    152  1.1  tsutsui 
    153  1.1  tsutsui struct dkdriver gdromdkdriver = {
    154  1.1  tsutsui 	.d_strategy = gdromstrategy
    155  1.1  tsutsui };
    156  1.1  tsutsui 
    157  1.1  tsutsui static const struct scsipi_periphsw gdrom_switch = {
    158  1.1  tsutsui 	NULL/*gdrom_interpret_sense*/,	/* use our error handler first */
    159  1.1  tsutsui 	gdrom_start,		/* we have a queue, which is started by this */
    160  1.1  tsutsui 	NULL,			/* we do not have an async handler */
    161  1.1  tsutsui 	gdrom_done,		/* deal with stats at interrupt time */
    162  1.1  tsutsui };
    163  1.1  tsutsui 
    164  1.1  tsutsui #define GDROMDEBUG
    165  1.1  tsutsui #ifdef GDROMDEBUG
    166  1.1  tsutsui int gdrom_debug = 0;		/* patchable */
    167  1.1  tsutsui #define GDROM_DPRINTF(x)	if (gdrom_debug) printf x
    168  1.1  tsutsui #else
    169  1.1  tsutsui #define GDROM_DPRINTF(x)	/**/
    170  1.1  tsutsui #endif
    171  1.1  tsutsui 
    172  1.1  tsutsui #define TOC_LBA(n)	((n) & 0xffffff00)
    173  1.1  tsutsui #define TOC_ADR(n)	((n) & 0x0f)
    174  1.1  tsutsui #define TOC_CTRL(n)	(((n) & 0xf0) >> 4)
    175  1.1  tsutsui #define TOC_TRACK(n)	(((n) & 0x0000ff00) >> 8)
    176  1.1  tsutsui 
    177  1.1  tsutsui #if 0
    178  1.1  tsutsui int gdrom_command_sense(struct gdrom_softc *sc, void *req, void *buf,
    179  1.1  tsutsui     unsigned int nbyt, int *resid)
    180  1.1  tsutsui {
    181  1.1  tsutsui 	/*
    182  1.1  tsutsui 	 *  76543210 76543210
    183  1.1  tsutsui 	 *  0   0x13      -
    184  1.1  tsutsui 	 *  2    -      bufsz(hi)
    185  1.1  tsutsui 	 *  4 bufsz(lo)   -
    186  1.1  tsutsui 	 *  6    -        -
    187  1.1  tsutsui 	 *  8    -        -
    188  1.1  tsutsui 	 * 10    -        -
    189  1.1  tsutsui 	 */
    190  1.1  tsutsui 	uint16_t sense_data[5];
    191  1.1  tsutsui 	uint8_t cmd[12];
    192  1.1  tsutsui 	int cond, sense_key, sense_specific;
    193  1.1  tsutsui 
    194  1.1  tsutsui 	cond = scsipi_command(sc->sc_periph, req, 12, buf, nbyt,
    195  1.1  tsutsui 	    4, 3000, NULL, XS_CTL_DATA_IN);
    196  1.1  tsutsui 	if (resid != NULL)
    197  1.1  tsutsui 		*resid = nbyt;
    198  1.1  tsutsui 
    199  1.1  tsutsui 	if (cond < 0) {
    200  1.1  tsutsui 		GDROM_DPRINTF(("GDROM: not ready (2:58)\n"));
    201  1.1  tsutsui 		return EIO;
    202  1.1  tsutsui 	}
    203  1.1  tsutsui 
    204  1.1  tsutsui 	if ((cond & 1) == 0) {
    205  1.1  tsutsui 		GDROM_DPRINTF(("GDROM: no sense.  0:0\n"));
    206  1.1  tsutsui 		return 0;
    207  1.1  tsutsui 	}
    208  1.1  tsutsui 
    209  1.1  tsutsui 	memset(cmd, 0, sizeof(cmd));
    210  1.1  tsutsui 
    211  1.1  tsutsui 	cmd[0] = 0x13;
    212  1.1  tsutsui 	cmd[4] = sizeof(sense_data);
    213  1.1  tsutsui 
    214  1.1  tsutsui 	scsipi_command(sc->sc_periph, (void *)cmd, sizeof(cmd),
    215  1.1  tsutsui 	    (void *)sense_data, sizeof(sense_data),
    216  1.1  tsutsui 	    4, 3000, NULL, XS_CTL_DATA_IN);
    217  1.1  tsutsui 
    218  1.1  tsutsui 	sense_key = sense_data[1] & 0xf;
    219  1.1  tsutsui 	sense_specific = sense_data[4];
    220  1.1  tsutsui 	if (sense_key == 11 && sense_specific == 0) {
    221  1.1  tsutsui 		GDROM_DPRINTF(("GDROM: aborted (ignored).  0:0\n"));
    222  1.1  tsutsui 		return 0;
    223  1.1  tsutsui 	}
    224  1.1  tsutsui 
    225  1.1  tsutsui 	GDROM_DPRINTF(("GDROM: SENSE %d:", sense_key));
    226  1.1  tsutsui 	GDROM_DPRINTF(("GDROM: %d\n", sense_specific));
    227  1.1  tsutsui 
    228  1.1  tsutsui 	return sense_key == 0 ? 0 : EIO;
    229  1.1  tsutsui }
    230  1.1  tsutsui #endif
    231  1.1  tsutsui 
    232  1.1  tsutsui int gdrom_read_toc(struct gdrom_softc *sc, struct gd_toc *toc)
    233  1.1  tsutsui {
    234  1.1  tsutsui 	/*
    235  1.1  tsutsui 	 *  76543210 76543210
    236  1.1  tsutsui 	 *  0   0x14      -
    237  1.1  tsutsui 	 *  2    -      bufsz(hi)
    238  1.1  tsutsui 	 *  4 bufsz(lo)   -
    239  1.1  tsutsui 	 *  6    -        -
    240  1.1  tsutsui 	 *  8    -        -
    241  1.1  tsutsui 	 * 10    -        -
    242  1.1  tsutsui 	 */
    243  1.1  tsutsui 	uint8_t cmd[12];
    244  1.1  tsutsui 
    245  1.1  tsutsui 	GDROM_DPRINTF(("%s: called\n", __func__));
    246  1.1  tsutsui 	memset(cmd, 0, sizeof(cmd));
    247  1.1  tsutsui 
    248  1.1  tsutsui 	cmd[0] = 0x14;
    249  1.1  tsutsui 	cmd[3] = sizeof(struct gd_toc) >> 8;
    250  1.1  tsutsui 	cmd[4] = sizeof(struct gd_toc) & 0xff;
    251  1.1  tsutsui 
    252  1.1  tsutsui 	return scsipi_command(sc->sc_periph, (void *)cmd, 12,
    253  1.1  tsutsui 	    (void *)toc, sizeof(struct gd_toc),
    254  1.1  tsutsui 	    4, 3000, NULL, XS_CTL_DATA_IN);
    255  1.1  tsutsui }
    256  1.1  tsutsui 
    257  1.1  tsutsui int gdrom_read_sectors(struct gdrom_softc *sc, struct buf *bp)
    258  1.1  tsutsui {
    259  1.1  tsutsui 	/*
    260  1.1  tsutsui 	 *  76543210 76543210
    261  1.1  tsutsui 	 *  0   0x30    datafmt
    262  1.1  tsutsui 	 *  2  sec(hi)  sec(mid)
    263  1.1  tsutsui 	 *  4  sec(lo)    -
    264  1.1  tsutsui 	 *  6    -        -
    265  1.1  tsutsui 	 *  8  cnt(hi)  cnt(mid)
    266  1.1  tsutsui 	 * 10  cnt(lo)    -
    267  1.1  tsutsui 	 */
    268  1.1  tsutsui 	uint8_t cmd[12];
    269  1.1  tsutsui 	void *buf;
    270  1.1  tsutsui 	int sector, cnt;
    271  1.1  tsutsui 	int cond;
    272  1.1  tsutsui 
    273  1.1  tsutsui 	GDROM_DPRINTF(("%s: called\n", __func__));
    274  1.1  tsutsui 
    275  1.1  tsutsui 	buf = bp->b_data;
    276  1.1  tsutsui 	sector = bp->b_rawblkno;
    277  1.1  tsutsui 	cnt = bp->b_bcount >> 11;
    278  1.1  tsutsui 
    279  1.1  tsutsui 	memset(cmd, 0, sizeof(cmd));
    280  1.1  tsutsui 
    281  1.1  tsutsui 	cmd[0]  = 0x30;
    282  1.1  tsutsui 	cmd[1]  = 0x20;
    283  1.1  tsutsui 	cmd[2]  = sector >> 16;
    284  1.1  tsutsui 	cmd[3]  = sector >>  8;
    285  1.1  tsutsui 	cmd[4]  = sector;
    286  1.1  tsutsui 	cmd[8]  = cnt >> 16;
    287  1.1  tsutsui 	cmd[9]  = cnt >>  8;
    288  1.1  tsutsui 	cmd[10] = cnt;
    289  1.1  tsutsui 
    290  1.1  tsutsui 	cond = scsipi_command(sc->sc_periph, (void *)cmd, 12,
    291  1.1  tsutsui 	    (void *)buf, bp->b_bcount,
    292  1.1  tsutsui 	    4, 3000, bp, XS_CTL_DATA_IN);
    293  1.1  tsutsui 
    294  1.1  tsutsui 	GDROM_DPRINTF(("%s: cond = %d\n", __func__, cond));
    295  1.1  tsutsui 
    296  1.1  tsutsui 	return cond;
    297  1.1  tsutsui }
    298  1.1  tsutsui 
    299  1.1  tsutsui int gdrom_mount_disk(struct gdrom_softc *sc)
    300  1.1  tsutsui {
    301  1.1  tsutsui 	/*
    302  1.1  tsutsui 	 *  76543210 76543210
    303  1.1  tsutsui 	 *  0   0x70      -
    304  1.1  tsutsui 	 *  2   0x1f      -
    305  1.1  tsutsui 	 *  4    -        -
    306  1.1  tsutsui 	 *  6    -        -
    307  1.1  tsutsui 	 *  8    -        -
    308  1.1  tsutsui 	 * 10    -        -
    309  1.1  tsutsui 	 */
    310  1.1  tsutsui 	uint8_t cmd[12];
    311  1.1  tsutsui 	int cond;
    312  1.1  tsutsui 
    313  1.1  tsutsui 	GDROM_DPRINTF(("%s: called\n", __func__));
    314  1.1  tsutsui 	memset(cmd, 0, sizeof(cmd));
    315  1.1  tsutsui 
    316  1.1  tsutsui 	cmd[0] = 0x70;
    317  1.1  tsutsui 	cmd[2] = 0x1f;
    318  1.1  tsutsui 
    319  1.1  tsutsui 	cond = scsipi_command(sc->sc_periph, (void *)cmd, 12, NULL, 0,
    320  1.1  tsutsui 	    4, 3000, NULL, 0);
    321  1.1  tsutsui 
    322  1.1  tsutsui 	GDROM_DPRINTF(("%s: cond = %d\n", __func__, cond));
    323  1.1  tsutsui 	return cond;
    324  1.1  tsutsui }
    325  1.1  tsutsui 
    326  1.1  tsutsui int
    327  1.1  tsutsui gdrommatch(device_t parent, cfdata_t cf, void *aux)
    328  1.1  tsutsui {
    329  1.1  tsutsui 	struct scsipibus_attach_args *sa = aux;
    330  1.1  tsutsui 	int priority;
    331  1.1  tsutsui 
    332  1.1  tsutsui 	(void)scsipi_inqmatch(&sa->sa_inqbuf,
    333  1.1  tsutsui 	    gdrom_patterns, __arraycount(gdrom_patterns),
    334  1.1  tsutsui 	    sizeof(gdrom_patterns[0]), &priority);
    335  1.1  tsutsui 
    336  1.1  tsutsui 	if (priority > 0) {
    337  1.1  tsutsui 		/* beat generic direct fixed device */
    338  1.1  tsutsui 		priority = 255;
    339  1.1  tsutsui 	}
    340  1.1  tsutsui 
    341  1.1  tsutsui 	return priority;
    342  1.1  tsutsui }
    343  1.1  tsutsui 
    344  1.1  tsutsui void
    345  1.1  tsutsui gdromattach(device_t parent, device_t self, void *aux)
    346  1.1  tsutsui {
    347  1.1  tsutsui 	struct gdrom_softc *sc;
    348  1.1  tsutsui 	struct scsipibus_attach_args *sa;
    349  1.1  tsutsui 	struct scsipi_periph *periph;
    350  1.1  tsutsui 
    351  1.1  tsutsui 	sc = device_private(self);
    352  1.1  tsutsui 	sa = aux;
    353  1.1  tsutsui 	periph = sa->sa_periph;
    354  1.1  tsutsui 	sc->sc_dev = self;
    355  1.1  tsutsui 	sc->sc_periph = periph;
    356  1.1  tsutsui 	periph->periph_dev = sc->sc_dev;
    357  1.1  tsutsui 	periph->periph_switch = &gdrom_switch;
    358  1.1  tsutsui 
    359  1.1  tsutsui 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    360  1.1  tsutsui 
    361  1.1  tsutsui 	bufq_alloc(&sc->sc_bufq, "disksort", BUFQ_SORT_RAWBLOCK);
    362  1.1  tsutsui 
    363  1.1  tsutsui 	/*
    364  1.1  tsutsui 	 * Initialize and attach the disk structure.
    365  1.1  tsutsui 	 */
    366  1.1  tsutsui 	disk_init(&sc->sc_dk, device_xname(self), &gdromdkdriver);
    367  1.1  tsutsui 	disk_attach(&sc->sc_dk);
    368  1.1  tsutsui 
    369  1.1  tsutsui 	aprint_normal("\n");
    370  1.1  tsutsui 	aprint_naive("\n");
    371  1.1  tsutsui }
    372  1.1  tsutsui 
    373  1.1  tsutsui int
    374  1.1  tsutsui gdromopen(dev_t dev, int flags, int devtype, struct lwp *l)
    375  1.1  tsutsui {
    376  1.1  tsutsui 	struct gdrom_softc *sc;
    377  1.1  tsutsui 	int s, error, unit, cnt;
    378  1.1  tsutsui 	struct gd_toc toc;
    379  1.1  tsutsui 
    380  1.1  tsutsui 	GDROM_DPRINTF(("%s: called\n", __func__));
    381  1.1  tsutsui 
    382  1.1  tsutsui 	unit = DISKUNIT(dev);
    383  1.1  tsutsui 
    384  1.1  tsutsui 	sc = device_lookup_private(&gdrom_cd, unit);
    385  1.1  tsutsui 	if (sc == NULL)
    386  1.1  tsutsui 		return ENXIO;
    387  1.1  tsutsui 
    388  1.1  tsutsui 	if (sc->is_open)
    389  1.1  tsutsui 		return EBUSY;
    390  1.1  tsutsui 
    391  1.1  tsutsui 	s = splbio();
    392  1.1  tsutsui 	while (sc->is_busy)
    393  1.1  tsutsui 		tsleep(&sc->is_busy, PRIBIO, "gdbusy", 0);
    394  1.1  tsutsui 	sc->is_busy = true;
    395  1.1  tsutsui 	splx(s);
    396  1.1  tsutsui 
    397  1.1  tsutsui 	for (cnt = 0; cnt < 1; cnt++)
    398  1.1  tsutsui 		if ((error = gdrom_mount_disk(sc)) == 0)
    399  1.1  tsutsui 			break;
    400  1.1  tsutsui 
    401  1.1  tsutsui 	if (error == 0)
    402  1.1  tsutsui 		error = gdrom_read_toc(sc, &toc);
    403  1.1  tsutsui 
    404  1.1  tsutsui 	sc->is_busy = false;
    405  1.1  tsutsui 	wakeup(&sc->is_busy);
    406  1.1  tsutsui 
    407  1.1  tsutsui 	if (error != 0)
    408  1.1  tsutsui 		return error;
    409  1.1  tsutsui 
    410  1.1  tsutsui 	sc->is_open = true;
    411  1.1  tsutsui 	sc->openpart_start = 150;
    412  1.1  tsutsui 
    413  1.1  tsutsui 	GDROM_DPRINTF(("%s: open OK\n", __func__));
    414  1.1  tsutsui 	return 0;
    415  1.1  tsutsui }
    416  1.1  tsutsui 
    417  1.1  tsutsui int
    418  1.1  tsutsui gdromclose(dev_t dev, int flags, int devtype, struct lwp *l)
    419  1.1  tsutsui {
    420  1.1  tsutsui 	struct gdrom_softc *sc;
    421  1.1  tsutsui 	int unit;
    422  1.1  tsutsui 
    423  1.1  tsutsui 	GDROM_DPRINTF(("%s: called\n", __func__));
    424  1.1  tsutsui 
    425  1.1  tsutsui 	unit = DISKUNIT(dev);
    426  1.1  tsutsui 	sc = device_lookup_private(&gdrom_cd, unit);
    427  1.1  tsutsui 
    428  1.1  tsutsui 	sc->is_open = false;
    429  1.1  tsutsui 
    430  1.1  tsutsui 	return 0;
    431  1.1  tsutsui }
    432  1.1  tsutsui 
    433  1.1  tsutsui void
    434  1.1  tsutsui gdromstrategy(struct buf *bp)
    435  1.1  tsutsui {
    436  1.1  tsutsui 	struct gdrom_softc *sc;
    437  1.1  tsutsui 	struct scsipi_periph *periph;
    438  1.1  tsutsui 	int s, unit;
    439  1.1  tsutsui 
    440  1.1  tsutsui 	GDROM_DPRINTF(("%s: called\n", __func__));
    441  1.1  tsutsui 
    442  1.1  tsutsui 	unit = DISKUNIT(bp->b_dev);
    443  1.1  tsutsui 	sc = device_lookup_private(&gdrom_cd, unit);
    444  1.1  tsutsui 	periph = sc->sc_periph;
    445  1.1  tsutsui 
    446  1.1  tsutsui 	if (bp->b_bcount == 0)
    447  1.1  tsutsui 		goto done;
    448  1.1  tsutsui 
    449  1.1  tsutsui 	bp->b_rawblkno = bp->b_blkno / (2048 / DEV_BSIZE) + sc->openpart_start;
    450  1.1  tsutsui 
    451  1.1  tsutsui 	GDROM_DPRINTF(("%s: read_sectors(%p, %lld, %d) [%d bytes]\n", __func__,
    452  1.1  tsutsui 	    bp->b_data, bp->b_rawblkno,
    453  1.1  tsutsui 	    bp->b_bcount >> 11, bp->b_bcount));
    454  1.1  tsutsui 
    455  1.1  tsutsui 	s = splbio();
    456  1.1  tsutsui 	bufq_put(sc->sc_bufq, bp);
    457  1.1  tsutsui 	splx(s);
    458  1.1  tsutsui 	if (!sc->is_active)
    459  1.1  tsutsui 		gdrom_start(periph);
    460  1.1  tsutsui 	return;
    461  1.1  tsutsui 
    462  1.1  tsutsui  done:
    463  1.1  tsutsui 	bp->b_resid = bp->b_bcount;
    464  1.1  tsutsui 	biodone(bp);
    465  1.1  tsutsui }
    466  1.1  tsutsui 
    467  1.1  tsutsui void
    468  1.1  tsutsui gdrom_start(struct scsipi_periph *periph)
    469  1.1  tsutsui {
    470  1.1  tsutsui 	struct gdrom_softc *sc = device_private(periph->periph_dev);
    471  1.1  tsutsui 	struct buf *bp;
    472  1.1  tsutsui 	int error, s;
    473  1.1  tsutsui 
    474  1.1  tsutsui 	sc->is_active = true;
    475  1.1  tsutsui 
    476  1.1  tsutsui 	for (;;) {
    477  1.1  tsutsui 		s = splbio();
    478  1.1  tsutsui 		bp = bufq_get(sc->sc_bufq);
    479  1.1  tsutsui 		if (bp == NULL) {
    480  1.1  tsutsui 			splx(s);
    481  1.1  tsutsui 			break;
    482  1.1  tsutsui 		}
    483  1.1  tsutsui 
    484  1.1  tsutsui 		while (sc->is_busy)
    485  1.1  tsutsui 			tsleep(&sc->is_busy, PRIBIO, "gdbusy", 0);
    486  1.1  tsutsui 		sc->is_busy = true;
    487  1.1  tsutsui 		disk_busy(&sc->sc_dk);
    488  1.1  tsutsui 		splx(s);
    489  1.1  tsutsui 
    490  1.1  tsutsui 		error = gdrom_read_sectors(sc, bp);
    491  1.1  tsutsui 		bp->b_error = error;
    492  1.1  tsutsui 		if (error != 0)
    493  1.1  tsutsui 			bp->b_resid = bp->b_bcount;
    494  1.1  tsutsui 
    495  1.1  tsutsui 		sc->is_busy = false;
    496  1.1  tsutsui 		wakeup(&sc->is_busy);
    497  1.1  tsutsui 
    498  1.1  tsutsui 		s = splbio();
    499  1.1  tsutsui 		disk_unbusy(&sc->sc_dk, bp->b_bcount - bp->b_resid,
    500  1.1  tsutsui 		    (bp->b_flags & B_READ) != 0);
    501  1.1  tsutsui 		splx(s);
    502  1.1  tsutsui 		biodone(bp);
    503  1.1  tsutsui 	}
    504  1.1  tsutsui 
    505  1.1  tsutsui 	sc->is_active = false;
    506  1.1  tsutsui }
    507  1.1  tsutsui 
    508  1.1  tsutsui void
    509  1.1  tsutsui gdrom_done(struct scsipi_xfer *xs, int error)
    510  1.1  tsutsui {
    511  1.1  tsutsui 
    512  1.1  tsutsui 	GDROM_DPRINTF(("%s: called\n", __func__));
    513  1.1  tsutsui }
    514  1.1  tsutsui 
    515  1.1  tsutsui int
    516  1.1  tsutsui gdromioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
    517  1.1  tsutsui {
    518  1.1  tsutsui 	struct gdrom_softc *sc;
    519  1.1  tsutsui 	int unit, error;
    520  1.1  tsutsui 
    521  1.1  tsutsui 	GDROM_DPRINTF(("%s: cmd %lx\n", __func__, cmd));
    522  1.1  tsutsui 
    523  1.1  tsutsui 	unit = DISKUNIT(dev);
    524  1.1  tsutsui 	sc = device_lookup_private(&gdrom_cd, unit);
    525  1.1  tsutsui 
    526  1.1  tsutsui 	switch (cmd) {
    527  1.1  tsutsui 	case CDIOREADMSADDR: {
    528  1.1  tsutsui 		int s, track, sessno = *(int *)addr;
    529  1.1  tsutsui 		struct gd_toc toc;
    530  1.1  tsutsui 
    531  1.1  tsutsui 		if (sessno != 0)
    532  1.1  tsutsui 			return EINVAL;
    533  1.1  tsutsui 
    534  1.1  tsutsui 		s = splbio();
    535  1.1  tsutsui 		while (sc->is_busy)
    536  1.1  tsutsui 			tsleep(&sc->is_busy, PRIBIO, "gdbusy", 0);
    537  1.1  tsutsui 		sc->is_busy = true;
    538  1.1  tsutsui 		splx(s);
    539  1.1  tsutsui 
    540  1.1  tsutsui 		error = gdrom_read_toc(sc, &toc);
    541  1.1  tsutsui 
    542  1.1  tsutsui 		sc->is_busy = false;
    543  1.1  tsutsui 		wakeup(&sc->is_busy);
    544  1.1  tsutsui 
    545  1.1  tsutsui 		if (error != 0)
    546  1.1  tsutsui 			return error;
    547  1.1  tsutsui #ifdef GDROMDEBUGTOC
    548  1.1  tsutsui 		{ /* Dump the GDROM TOC */
    549  1.1  tsutsui 		unsigned char *ptr = (unsigned char *)&toc;
    550  1.1  tsutsui 		int i;
    551  1.1  tsutsui 
    552  1.1  tsutsui 		printf("gdrom: TOC\n");
    553  1.1  tsutsui 		for(i = 0; i < sizeof(toc); ++i) {
    554  1.1  tsutsui 			printf("%02x", *ptr++);
    555  1.1  tsutsui 			if( i%32 == 31)
    556  1.1  tsutsui 				printf("\n");
    557  1.1  tsutsui 			else if( i%4 == 3)
    558  1.1  tsutsui 				printf(",");
    559  1.1  tsutsui 		}
    560  1.1  tsutsui 		printf("\n");
    561  1.1  tsutsui 		}
    562  1.1  tsutsui #endif
    563  1.1  tsutsui 		for (track = TOC_TRACK(toc.last);
    564  1.1  tsutsui 		    track >= TOC_TRACK(toc.first);
    565  1.1  tsutsui 		    --track) {
    566  1.1  tsutsui 			if (track < 1 || track > 100)
    567  1.1  tsutsui 				return ENXIO;
    568  1.1  tsutsui 			if (TOC_CTRL(toc.entry[track - 1]))
    569  1.1  tsutsui 				break;
    570  1.1  tsutsui 		}
    571  1.1  tsutsui 
    572  1.1  tsutsui #ifdef GDROMDEBUGTOC
    573  1.1  tsutsui 		printf("gdrom: Using track %d, LBA %u\n", track,
    574  1.1  tsutsui 		    TOC_LBA(toc.entry[track - 1]));
    575  1.1  tsutsui #endif
    576  1.1  tsutsui 
    577  1.1  tsutsui 		*(int *)addr = htonl(TOC_LBA(toc.entry[track - 1])) -
    578  1.1  tsutsui 		    sc->openpart_start;
    579  1.1  tsutsui 
    580  1.1  tsutsui 		return 0;
    581  1.1  tsutsui 	}
    582  1.1  tsutsui 	default:
    583  1.1  tsutsui 		return ENOTTY;
    584  1.1  tsutsui 	}
    585  1.1  tsutsui 
    586  1.1  tsutsui #ifdef DIAGNOSTIC
    587  1.1  tsutsui 	panic("gdromioctl: impossible");
    588  1.1  tsutsui #endif
    589  1.1  tsutsui }
    590  1.1  tsutsui 
    591  1.1  tsutsui 
    592  1.1  tsutsui int
    593  1.1  tsutsui gdromread(dev_t dev, struct uio *uio, int flags)
    594  1.1  tsutsui {
    595  1.1  tsutsui 
    596  1.1  tsutsui 	GDROM_DPRINTF(("%s: called\n", __func__));
    597  1.1  tsutsui 	return physio(gdromstrategy, NULL, dev, B_READ, minphys, uio);
    598  1.1  tsutsui }
    599  1.1  tsutsui 
    600  1.1  tsutsui int
    601  1.1  tsutsui gdromwrite(dev_t dev, struct uio *uio, int flags)
    602  1.1  tsutsui {
    603  1.1  tsutsui 
    604  1.1  tsutsui 	return EROFS;
    605  1.1  tsutsui }
    606