1 /* $NetBSD: cd.c,v 1.296 2009/12/06 22:48:17 dyoung Exp $ */
4 * Copyright (c) 1998, 2001, 2003, 2004, 2005, 2008 The NetBSD Foundation,
5 * Inc. All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum.
10 * MMC framework implemented and contributed to the NetBSD Foundation by
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
36 * Originally written by Julian Elischer (julian@tfs.com)
37 * for TRW Financial Systems for use under the MACH(2.5) operating system.
39 * TRW Financial Systems, in accordance with their agreement with Carnegie
40 * Mellon University, makes this software available to CMU to distribute
41 * or use in any manner that they see fit as long as this message is kept with
42 * the software. For this reason TFS also grants any other persons or
43 * organisations permission to use or modify this software.
45 * TFS supplies this software to be publicly redistributed
46 * on the understanding that TFS is not responsible for the correct
47 * functioning of this software in any circumstances.
49 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
52 #include <sys/cdefs.h>
53 __KERNEL_RCSID(0, "$NetBSD: cd.c,v 1.296 2009/12/06 22:48:17 dyoung Exp $");
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/kernel.h>
62 #include <sys/ioctl.h>
66 #include <sys/malloc.h>
67 #include <sys/errno.h>
68 #include <sys/device.h>
69 #include <sys/disklabel.h>
72 #include <sys/dvdio.h>
73 #include <sys/scsiio.h>
76 #include <sys/vnode.h>
81 #include <dev/scsipi/scsi_spc.h>
82 #include <dev/scsipi/scsipi_all.h>
83 #include <dev/scsipi/scsipi_cd.h>
84 #include <dev/scsipi/scsipi_disk.h> /* rw_big and start_stop come */
85 #include <dev/scsipi/scsi_all.h>
87 #include <dev/scsipi/scsi_disk.h> /* rw comes from there */
88 #include <dev/scsipi/scsipiconf.h>
89 #include <dev/scsipi/scsipi_base.h>
90 #include <dev/scsipi/cdvar.h>
92 #include <prop/proplib.h>
94 #define CDUNIT(z) DISKUNIT(z)
95 #define CDPART(z) DISKPART(z)
96 #define CDMINOR(unit, part) DISKMINOR(unit, part)
97 #define MAKECDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part)
100 #define CD_BLOCK_OFFSET 150
104 #define CD_TOC_FORM 0 /* formatted TOC, exposed to userland */
105 #define CD_TOC_MSINFO 1 /* multi-session info */
106 #define CD_TOC_RAW 2 /* raw TOC as on disc, unprocessed */
107 #define CD_TOC_PMA 3 /* PMA, used as intermediate (rare use) */
108 #define CD_TOC_ATIP 4 /* pressed space of recordable */
109 #define CD_TOC_CDTEXT 5 /* special CD-TEXT, rarely used */
112 #define MS5LEN (P5LEN + 8 + 2)
114 struct cd_formatted_toc
{
115 struct ioc_toc_header header
;
116 struct cd_toc_entry entries
[MAXTRACK
+1]; /* One extra for the */
121 struct buf
*obp
; /* original buf */
122 int doff
; /* byte offset in orig. buf */
123 int soff
; /* byte offset in bounce buf */
124 int resid
; /* residual i/o in orig. buf */
125 int bcount
; /* actual obp bytes in bounce */
128 static void cdstart(struct scsipi_periph
*);
129 static void cdrestart(void *);
130 static void cdminphys(struct buf
*);
131 static void cdgetdefaultlabel(struct cd_softc
*, struct cd_formatted_toc
*,
133 static void cdgetdisklabel(struct cd_softc
*);
134 static void cddone(struct scsipi_xfer
*, int);
135 static void cdbounce(struct buf
*);
136 static int cd_interpret_sense(struct scsipi_xfer
*);
137 static u_long
cd_size(struct cd_softc
*, int);
138 static int cd_play(struct cd_softc
*, int, int);
139 static int cd_play_tracks(struct cd_softc
*, struct cd_formatted_toc
*,
141 static int cd_play_msf(struct cd_softc
*, int, int, int, int, int, int);
142 static int cd_pause(struct cd_softc
*, int);
143 static int cd_reset(struct cd_softc
*);
144 static int cd_read_subchannel(struct cd_softc
*, int, int, int,
145 struct cd_sub_channel_info
*, int, int);
146 static int cd_read_toc(struct cd_softc
*, int, int, int,
147 struct cd_formatted_toc
*, int, int, int);
148 static int cd_get_parms(struct cd_softc
*, int);
149 static int cd_load_toc(struct cd_softc
*, int, struct cd_formatted_toc
*, int);
150 static int cdreadmsaddr(struct cd_softc
*, struct cd_formatted_toc
*,int *);
151 static int cdcachesync(struct scsipi_periph
*periph
, int flags
);
153 static int dvd_auth(struct cd_softc
*, dvd_authinfo
*);
154 static int dvd_read_physical(struct cd_softc
*, dvd_struct
*);
155 static int dvd_read_copyright(struct cd_softc
*, dvd_struct
*);
156 static int dvd_read_disckey(struct cd_softc
*, dvd_struct
*);
157 static int dvd_read_bca(struct cd_softc
*, dvd_struct
*);
158 static int dvd_read_manufact(struct cd_softc
*, dvd_struct
*);
159 static int dvd_read_struct(struct cd_softc
*, dvd_struct
*);
161 static int cd_mode_sense(struct cd_softc
*, u_int8_t
, void *, size_t, int,
163 static int cd_mode_select(struct cd_softc
*, u_int8_t
, void *, size_t,
165 static int cd_setchan(struct cd_softc
*, int, int, int, int, int);
166 static int cd_getvol(struct cd_softc
*, struct ioc_vol
*, int);
167 static int cd_setvol(struct cd_softc
*, const struct ioc_vol
*, int);
168 static int cd_set_pa_immed(struct cd_softc
*, int);
169 static int cd_load_unload(struct cd_softc
*, struct ioc_load_unload
*);
170 static int cd_setblksize(struct cd_softc
*);
172 static int cdmatch(device_t
, cfdata_t
, void *);
173 static void cdattach(device_t
, device_t
, void *);
174 static int cddetach(device_t
, int);
176 static int mmc_getdiscinfo(struct scsipi_periph
*, struct mmc_discinfo
*);
177 static int mmc_gettrackinfo(struct scsipi_periph
*, struct mmc_trackinfo
*);
178 static int mmc_do_op(struct scsipi_periph
*, struct mmc_op
*);
179 static int mmc_setup_writeparams(struct scsipi_periph
*, struct mmc_writeparams
*);
181 static void cd_set_properties(struct cd_softc
*);
183 CFATTACH_DECL3_NEW(cd
, sizeof(struct cd_softc
), cdmatch
, cdattach
, cddetach
,
184 NULL
, NULL
, NULL
, DVF_DETACH_SHUTDOWN
);
186 extern struct cfdriver cd_cd
;
188 static const struct scsipi_inquiry_pattern cd_patterns
[] = {
194 {T_CDROM
, T_REMOV
, /* more luns */
195 "PIONEER ", "CD-ROM DRM-600 ", ""},
198 "NEC CD-ROM DRIVE:260", "", ""},
201 static dev_type_open(cdopen
);
202 static dev_type_close(cdclose
);
203 static dev_type_read(cdread
);
204 static dev_type_write(cdwrite
);
205 static dev_type_ioctl(cdioctl
);
206 static dev_type_strategy(cdstrategy
);
207 static dev_type_dump(cddump
);
208 static dev_type_size(cdsize
);
210 const struct bdevsw cd_bdevsw
= {
211 cdopen
, cdclose
, cdstrategy
, cdioctl
, cddump
, cdsize
, D_DISK
214 const struct cdevsw cd_cdevsw
= {
215 cdopen
, cdclose
, cdread
, cdwrite
, cdioctl
,
216 nostop
, notty
, nopoll
, nommap
, nokqfilter
, D_DISK
219 static struct dkdriver cddkdriver
= { cdstrategy
, NULL
};
221 static const struct scsipi_periphsw cd_switch
= {
222 cd_interpret_sense
, /* use our error handler first */
223 cdstart
, /* we have a queue, which is started by this */
224 NULL
, /* we do not have an async handler */
225 cddone
, /* deal with stats at interrupt time */
229 * The routine called by the low level scsi routine when it discovers
230 * A device suitable for this driver
233 cdmatch(device_t parent
, cfdata_t match
, void *aux
)
235 struct scsipibus_attach_args
*sa
= aux
;
238 (void)scsipi_inqmatch(&sa
->sa_inqbuf
,
239 cd_patterns
, sizeof(cd_patterns
) / sizeof(cd_patterns
[0]),
240 sizeof(cd_patterns
[0]), &priority
);
246 cdattach(device_t parent
, device_t self
, void *aux
)
248 struct cd_softc
*cd
= device_private(self
);
249 struct scsipibus_attach_args
*sa
= aux
;
250 struct scsipi_periph
*periph
= sa
->sa_periph
;
252 SC_DEBUG(periph
, SCSIPI_DB2
, ("cdattach: "));
256 mutex_init(&cd
->sc_lock
, MUTEX_DEFAULT
, IPL_NONE
);
258 if (scsipi_periph_bustype(sa
->sa_periph
) == SCSIPI_BUSTYPE_SCSI
&&
259 periph
->periph_version
== 0)
260 cd
->flags
|= CDF_ANCIENT
;
262 bufq_alloc(&cd
->buf_queue
, "disksort", BUFQ_SORT_RAWBLOCK
);
264 callout_init(&cd
->sc_callout
, 0);
267 * Store information needed to contact our base driver
269 cd
->sc_periph
= periph
;
271 periph
->periph_dev
= cd
->sc_dev
;
272 periph
->periph_switch
= &cd_switch
;
275 * Increase our openings to the maximum-per-periph
276 * supported by the adapter. This will either be
277 * clamped down or grown by the adapter if necessary.
279 periph
->periph_openings
=
280 SCSIPI_CHAN_MAX_PERIPH(periph
->periph_channel
);
281 periph
->periph_flags
|= PERIPH_GROW_OPENINGS
;
284 * Initialize and attach the disk structure.
286 disk_init(&cd
->sc_dk
, device_xname(cd
->sc_dev
), &cddkdriver
);
287 disk_attach(&cd
->sc_dk
);
292 rnd_attach_source(&cd
->rnd_source
, device_xname(cd
->sc_dev
),
296 if (!pmf_device_register(self
, NULL
, NULL
))
297 aprint_error_dev(self
, "couldn't establish power handler\n");
301 cddetach(device_t self
, int flags
)
303 struct cd_softc
*cd
= device_private(self
);
304 int s
, bmaj
, cmaj
, i
, mn
;
306 /* locate the major number */
307 bmaj
= bdevsw_lookup_major(&cd_bdevsw
);
308 cmaj
= cdevsw_lookup_major(&cd_cdevsw
);
309 /* Nuke the vnodes for any open instances */
310 for (i
= 0; i
< MAXPARTITIONS
; i
++) {
311 mn
= CDMINOR(device_unit(self
), i
);
312 vdevgone(bmaj
, mn
, mn
, VBLK
);
313 vdevgone(cmaj
, mn
, mn
, VCHR
);
316 /* kill any pending restart */
317 callout_stop(&cd
->sc_callout
);
321 /* Kill off any queued buffers. */
322 bufq_drain(cd
->buf_queue
);
324 bufq_free(cd
->buf_queue
);
326 /* Kill off any pending commands. */
327 scsipi_kill_pending(cd
->sc_periph
);
331 mutex_destroy(&cd
->sc_lock
);
333 /* Detach from the disk list. */
334 disk_detach(&cd
->sc_dk
);
335 disk_destroy(&cd
->sc_dk
);
338 /* Unhook the entropy source. */
339 rnd_detach_source(&cd
->rnd_source
);
346 * open the device. Make sure the partition info is a up-to-date as can be.
349 cdopen(dev_t dev
, int flag
, int fmt
, struct lwp
*l
)
352 struct scsipi_periph
*periph
;
353 struct scsipi_adapter
*adapt
;
358 cd
= device_lookup_private(&cd_cd
, CDUNIT(dev
));
362 periph
= cd
->sc_periph
;
363 adapt
= periph
->periph_channel
->chan_adapter
;
366 SC_DEBUG(periph
, SCSIPI_DB1
,
367 ("cdopen: dev=0x%"PRIu64
" (unit %"PRIu32
" (of %d), partition %"PRId32
")\n",dev
,
368 CDUNIT(dev
), cd_cd
.cd_ndevs
, CDPART(dev
)));
371 * If this is the first open of this device, add a reference
374 if (cd
->sc_dk
.dk_openmask
== 0 &&
375 (error
= scsipi_adapter_addref(adapt
)) != 0)
378 mutex_enter(&cd
->sc_lock
);
380 rawpart
= (part
== RAW_PART
&& fmt
== S_IFCHR
);
381 if ((periph
->periph_flags
& PERIPH_OPEN
) != 0) {
383 * If any partition is open, but the disk has been invalidated,
384 * disallow further opens.
386 if ((periph
->periph_flags
& PERIPH_MEDIA_LOADED
) == 0 &&
395 silent
= XS_CTL_SILENT
;
399 /* Check that it is still responding and ok. */
400 error
= scsipi_test_unit_ready(periph
,
401 XS_CTL_IGNORE_ILLEGAL_REQUEST
| XS_CTL_IGNORE_MEDIA_CHANGE
|
405 * Start the pack spinning if necessary. Always allow the
406 * raw parition to be opened, for raw IOCTLs. Data transfers
407 * will check for SDEV_MEDIA_LOADED.
412 error2
= scsipi_start(periph
, SSS_START
, silent
);
431 periph
->periph_flags
|= PERIPH_OPEN
;
433 /* Lock the pack in. */
434 error
= scsipi_prevent(periph
, SPAMR_PREVENT_DT
,
435 XS_CTL_IGNORE_ILLEGAL_REQUEST
| XS_CTL_IGNORE_MEDIA_CHANGE
);
436 SC_DEBUG(periph
, SCSIPI_DB1
,
437 ("cdopen: scsipi_prevent, error=%d\n", error
));
444 if ((periph
->periph_flags
& PERIPH_MEDIA_LOADED
) == 0) {
445 /* Load the physical device parameters. */
446 if (cd_get_parms(cd
, 0) != 0) {
452 periph
->periph_flags
|= PERIPH_MEDIA_LOADED
;
453 SC_DEBUG(periph
, SCSIPI_DB3
, ("Params loaded "));
455 /* Fabricate a disk label. */
457 SC_DEBUG(periph
, SCSIPI_DB3
, ("Disklabel fabricated "));
459 cd_set_properties(cd
);
463 /* Check that the partition exists. */
464 if (part
!= RAW_PART
&&
465 (part
>= cd
->sc_dk
.dk_label
->d_npartitions
||
466 cd
->sc_dk
.dk_label
->d_partitions
[part
].p_fstype
== FS_UNUSED
)) {
471 out
: /* Insure only one open at a time. */
474 cd
->sc_dk
.dk_copenmask
|= (1 << part
);
477 cd
->sc_dk
.dk_bopenmask
|= (1 << part
);
480 cd
->sc_dk
.dk_openmask
=
481 cd
->sc_dk
.dk_copenmask
| cd
->sc_dk
.dk_bopenmask
;
483 SC_DEBUG(periph
, SCSIPI_DB3
, ("open complete\n"));
484 mutex_exit(&cd
->sc_lock
);
488 if (cd
->sc_dk
.dk_openmask
== 0) {
489 scsipi_prevent(periph
, SPAMR_ALLOW
,
490 XS_CTL_IGNORE_ILLEGAL_REQUEST
| XS_CTL_IGNORE_MEDIA_CHANGE
);
491 periph
->periph_flags
&= ~PERIPH_OPEN
;
495 mutex_exit(&cd
->sc_lock
);
496 if (cd
->sc_dk
.dk_openmask
== 0)
497 scsipi_adapter_delref(adapt
);
502 * close the device.. only called if we are the LAST
503 * occurence of an open device
506 cdclose(dev_t dev
, int flag
, int fmt
, struct lwp
*l
)
508 struct cd_softc
*cd
= device_lookup_private(&cd_cd
, CDUNIT(dev
));
509 struct scsipi_periph
*periph
= cd
->sc_periph
;
510 struct scsipi_adapter
*adapt
= periph
->periph_channel
->chan_adapter
;
511 int part
= CDPART(dev
);
513 mutex_enter(&cd
->sc_lock
);
517 cd
->sc_dk
.dk_copenmask
&= ~(1 << part
);
520 cd
->sc_dk
.dk_bopenmask
&= ~(1 << part
);
523 cd
->sc_dk
.dk_openmask
=
524 cd
->sc_dk
.dk_copenmask
| cd
->sc_dk
.dk_bopenmask
;
526 if (cd
->sc_dk
.dk_openmask
== 0) {
527 /* synchronise caches on last close */
528 cdcachesync(periph
, 0);
530 /* drain outstanding calls */
531 scsipi_wait_drain(periph
);
533 scsipi_prevent(periph
, SPAMR_ALLOW
,
534 XS_CTL_IGNORE_ILLEGAL_REQUEST
| XS_CTL_IGNORE_MEDIA_CHANGE
|
535 XS_CTL_IGNORE_NOT_READY
);
536 periph
->periph_flags
&= ~PERIPH_OPEN
;
538 scsipi_wait_drain(periph
);
540 scsipi_adapter_delref(adapt
);
543 mutex_exit(&cd
->sc_lock
);
548 * Actually translate the requested transfer into one the physical driver can
549 * understand. The transfer is described by a buf and will include only one
553 cdstrategy(struct buf
*bp
)
555 struct cd_softc
*cd
= device_lookup_private(&cd_cd
,CDUNIT(bp
->b_dev
));
556 struct disklabel
*lp
;
557 struct scsipi_periph
*periph
= cd
->sc_periph
;
561 SC_DEBUG(cd
->sc_periph
, SCSIPI_DB2
, ("cdstrategy "));
562 SC_DEBUG(cd
->sc_periph
, SCSIPI_DB1
,
563 ("%d bytes @ blk %" PRId64
"\n", bp
->b_bcount
, bp
->b_blkno
));
565 * If the device has been made invalid, error out
566 * maybe the media changed
568 if ((periph
->periph_flags
& PERIPH_MEDIA_LOADED
) == 0) {
569 if (periph
->periph_flags
& PERIPH_OPEN
)
572 bp
->b_error
= ENODEV
;
576 lp
= cd
->sc_dk
.dk_label
;
579 * The transfer must be a whole number of blocks, offset must not
582 if ((bp
->b_bcount
% lp
->d_secsize
) != 0 ||
584 bp
->b_error
= EINVAL
;
588 * If it's a null transfer, return immediately
590 if (bp
->b_bcount
== 0)
594 * Do bounds checking, adjust transfer. if error, process.
595 * If end of partition, just return.
597 if (CDPART(bp
->b_dev
) == RAW_PART
) {
598 if (bounds_check_with_mediasize(bp
, DEV_BSIZE
,
599 cd
->params
.disksize512
) <= 0)
602 if (bounds_check_with_label(&cd
->sc_dk
, bp
,
603 (cd
->flags
& (CDF_WLABEL
|CDF_LABELLING
)) != 0) <= 0)
608 * Now convert the block number to absolute and put it in
609 * terms of the device's logical block size.
611 blkno
= bp
->b_blkno
/ (lp
->d_secsize
/ DEV_BSIZE
);
612 if (CDPART(bp
->b_dev
) != RAW_PART
)
613 blkno
+= lp
->d_partitions
[CDPART(bp
->b_dev
)].p_offset
;
615 bp
->b_rawblkno
= blkno
;
618 * If the disklabel sector size does not match the device
619 * sector size we may need to do some extra work.
621 if (lp
->d_secsize
!= cd
->params
.blksize
) {
624 * If the xfer is not a multiple of the device block size
625 * or it is not block aligned, we need to bounce it.
627 if ((bp
->b_bcount
% cd
->params
.blksize
) != 0 ||
628 ((blkno
* lp
->d_secsize
) % cd
->params
.blksize
) != 0) {
629 struct cdbounce
*bounce
;
633 if ((bp
->b_flags
& B_READ
) == 0) {
635 /* XXXX We don't support bouncing writes. */
636 bp
->b_error
= EACCES
;
640 bounce
= malloc(sizeof(*bounce
), M_DEVBUF
, M_NOWAIT
);
642 /* No memory -- fail the iop. */
643 bp
->b_error
= ENOMEM
;
648 bounce
->resid
= bp
->b_bcount
;
650 count
= ((blkno
* lp
->d_secsize
) % cd
->params
.blksize
);
651 bounce
->soff
= count
;
652 count
+= bp
->b_bcount
;
653 count
= roundup(count
, cd
->params
.blksize
);
654 bounce
->bcount
= bounce
->resid
;
655 if (count
> MAXPHYS
) {
656 bounce
->bcount
= MAXPHYS
- bounce
->soff
;
660 blkno
= ((blkno
* lp
->d_secsize
) / cd
->params
.blksize
);
661 nbp
= getiobuf(NULL
, false);
663 /* No memory -- fail the iop. */
664 free(bounce
, M_DEVBUF
);
665 bp
->b_error
= ENOMEM
;
668 nbp
->b_data
= malloc(count
, M_DEVBUF
, M_NOWAIT
);
670 /* No memory -- fail the iop. */
671 free(bounce
, M_DEVBUF
);
673 bp
->b_error
= ENOMEM
;
677 /* Set up the IOP to the bounce buffer. */
679 nbp
->b_proc
= bp
->b_proc
;
680 nbp
->b_bcount
= count
;
681 nbp
->b_bufsize
= count
;
682 nbp
->b_rawblkno
= blkno
;
683 nbp
->b_flags
= bp
->b_flags
| B_READ
;
684 nbp
->b_oflags
= bp
->b_oflags
;
685 nbp
->b_cflags
= bp
->b_cflags
;
686 nbp
->b_iodone
= cdbounce
;
688 /* store bounce state in b_private and use new buf */
689 nbp
->b_private
= bounce
;
691 BIO_COPYPRIO(nbp
, bp
);
696 /* Xfer is aligned -- just adjust the start block */
697 bp
->b_rawblkno
= (blkno
* lp
->d_secsize
) /
704 * Place it in the queue of disk activities for this disk.
706 * XXX Only do disksort() if the current operating mode does not
707 * XXX include tagged queueing.
709 bufq_put(cd
->buf_queue
, bp
);
712 * Tell the device to get going on the transfer if it's
713 * not doing anything, otherwise just wait for completion
715 cdstart(cd
->sc_periph
);
722 * Correctly set the buf to indicate a completed xfer
724 bp
->b_resid
= bp
->b_bcount
;
729 * cdstart looks to see if there is a buf waiting for the device
730 * and that the device is not already busy. If both are true,
731 * It deques the buf and creates a scsi command to perform the
732 * transfer in the buf. The transfer request will call scsipi_done
733 * on completion, which will in turn call this routine again
734 * so that the next queued transfer is performed.
735 * The bufs are queued by the strategy routine (cdstrategy)
737 * This routine is also called after other non-queued requests
738 * have been made of the scsi driver, to ensure that the queue
739 * continues to be drained.
741 * must be called at the correct (highish) spl level
742 * cdstart() is called at splbio from cdstrategy, cdrestart and scsipi_done
745 cdstart(struct scsipi_periph
*periph
)
747 struct cd_softc
*cd
= device_private(periph
->periph_dev
);
749 struct scsipi_rw_10 cmd_big
;
750 struct scsi_rw_6 cmd_small
;
751 struct scsipi_generic
*cmdp
;
752 struct scsipi_xfer
*xs
;
753 int flags
, nblks
, cmdlen
, error
;
755 SC_DEBUG(periph
, SCSIPI_DB2
, ("cdstart "));
757 * Check if the device has room for another command
759 while (periph
->periph_active
< periph
->periph_openings
) {
761 * there is excess capacity, but a special waits
762 * It'll need the adapter as soon as we clear out of the
763 * way and let it run (user level wait).
765 if (periph
->periph_flags
& PERIPH_WAITING
) {
766 periph
->periph_flags
&= ~PERIPH_WAITING
;
767 wakeup((void *)periph
);
772 * If the device has become invalid, abort all the
773 * reads and writes until all files have been closed and
777 (periph
->periph_flags
& PERIPH_MEDIA_LOADED
) == 0)) {
778 if ((bp
= bufq_get(cd
->buf_queue
)) != NULL
) {
780 bp
->b_resid
= bp
->b_bcount
;
789 * See if there is a buf with work for us to do..
791 if ((bp
= bufq_peek(cd
->buf_queue
)) == NULL
)
795 * We have a buf, now we should make a command.
798 nblks
= howmany(bp
->b_bcount
, cd
->params
.blksize
);
801 * Fill out the scsi command. If the transfer will
802 * fit in a "small" cdb, use it.
804 if (((bp
->b_rawblkno
& 0x1fffff) == bp
->b_rawblkno
) &&
805 ((nblks
& 0xff) == nblks
) &&
806 !(periph
->periph_quirks
& PQUIRK_ONLYBIG
)) {
808 * We can fit in a small cdb.
810 memset(&cmd_small
, 0, sizeof(cmd_small
));
811 cmd_small
.opcode
= (bp
->b_flags
& B_READ
) ?
812 SCSI_READ_6_COMMAND
: SCSI_WRITE_6_COMMAND
;
813 _lto3b(bp
->b_rawblkno
, cmd_small
.addr
);
814 cmd_small
.length
= nblks
& 0xff;
815 cmdlen
= sizeof(cmd_small
);
816 cmdp
= (struct scsipi_generic
*)&cmd_small
;
821 memset(&cmd_big
, 0, sizeof(cmd_big
));
822 cmd_big
.opcode
= (bp
->b_flags
& B_READ
) ?
824 _lto4b(bp
->b_rawblkno
, cmd_big
.addr
);
825 _lto2b(nblks
, cmd_big
.length
);
826 cmdlen
= sizeof(cmd_big
);
827 cmdp
= (struct scsipi_generic
*)&cmd_big
;
830 /* Instrumentation. */
831 disk_busy(&cd
->sc_dk
);
834 * Figure out what flags to use.
836 flags
= XS_CTL_NOSLEEP
|XS_CTL_ASYNC
|XS_CTL_SIMPLE_TAG
;
837 if (bp
->b_flags
& B_READ
)
838 flags
|= XS_CTL_DATA_IN
;
840 flags
|= XS_CTL_DATA_OUT
;
843 * Call the routine that chats with the adapter.
844 * Note: we cannot sleep as we may be an interrupt
846 xs
= scsipi_make_xs(periph
, cmdp
, cmdlen
,
847 (u_char
*)bp
->b_data
, bp
->b_bcount
,
848 CDRETRIES
, 30000, bp
, flags
);
849 if (__predict_false(xs
== NULL
)) {
851 * out of memory. Keep this buffer in the queue, and
854 callout_reset(&cd
->sc_callout
, hz
/ 2, cdrestart
,
859 * need to dequeue the buffer before queuing the command,
860 * because cdstart may be called recursively from the
864 if (bufq_get(cd
->buf_queue
) != bp
)
865 panic("cdstart(): dequeued wrong buf");
867 bufq_get(cd
->buf_queue
);
869 error
= scsipi_execute_xs(xs
);
870 /* with a scsipi_xfer preallocated, scsipi_command can't fail */
879 cdstart((struct scsipi_periph
*)v
);
884 cddone(struct scsipi_xfer
*xs
, int error
)
886 struct cd_softc
*cd
= device_private(xs
->xs_periph
->periph_dev
);
887 struct buf
*bp
= xs
->bp
;
890 /* note, bp->b_resid is NOT initialised */
892 bp
->b_resid
= xs
->resid
;
894 /* on a read/write error bp->b_resid is zero, so fix */
895 bp
->b_resid
= bp
->b_bcount
;
898 disk_unbusy(&cd
->sc_dk
, bp
->b_bcount
- bp
->b_resid
,
899 (bp
->b_flags
& B_READ
));
901 rnd_add_uint32(&cd
->rnd_source
, bp
->b_rawblkno
);
909 cdbounce(struct buf
*bp
)
911 struct cdbounce
*bounce
= (struct cdbounce
*)bp
->b_private
;
912 struct buf
*obp
= bounce
->obp
;
913 struct cd_softc
*cd
=
914 device_lookup_private(&cd_cd
, CDUNIT(obp
->b_dev
));
915 struct disklabel
*lp
= cd
->sc_dk
.dk_label
;
917 if (bp
->b_error
!= 0) {
918 /* EEK propagate the error and free the memory */
922 KASSERT(obp
->b_flags
& B_READ
);
924 /* copy bounce buffer to final destination */
925 memcpy((char *)obp
->b_data
+ bounce
->doff
,
926 (char *)bp
->b_data
+ bounce
->soff
, bounce
->bcount
);
928 /* check if we need more I/O, i.e. bounce put us over MAXPHYS */
929 KASSERT(bounce
->resid
>= bounce
->bcount
);
930 bounce
->resid
-= bounce
->bcount
;
931 if (bounce
->resid
> 0) {
937 blkno
= obp
->b_rawblkno
+
938 ((obp
->b_bcount
- bounce
->resid
) / lp
->d_secsize
);
939 count
= ((blkno
* lp
->d_secsize
) % cd
->params
.blksize
);
940 blkno
= (blkno
* lp
->d_secsize
) / cd
->params
.blksize
;
941 bounce
->soff
= count
;
942 bounce
->doff
+= bounce
->bcount
;
943 count
+= bounce
->resid
;
944 count
= roundup(count
, cd
->params
.blksize
);
945 bounce
->bcount
= bounce
->resid
;
946 if (count
> MAXPHYS
) {
947 bounce
->bcount
= MAXPHYS
- bounce
->soff
;
951 nbp
= getiobuf(NULL
, false);
953 /* No memory -- fail the iop. */
954 bp
->b_error
= ENOMEM
;
958 /* Set up the IOP to the bounce buffer. */
960 nbp
->b_proc
= obp
->b_proc
;
961 nbp
->b_bcount
= count
;
962 nbp
->b_bufsize
= count
;
963 nbp
->b_data
= bp
->b_data
;
964 nbp
->b_rawblkno
= blkno
;
965 nbp
->b_flags
= obp
->b_flags
| B_READ
;
966 nbp
->b_oflags
= obp
->b_oflags
;
967 nbp
->b_cflags
= obp
->b_cflags
;
968 nbp
->b_iodone
= cdbounce
;
970 /* store bounce state in b_private and use new buf */
971 nbp
->b_private
= bounce
;
973 BIO_COPYPRIO(nbp
, obp
);
978 /* enqueue the request and return */
980 bufq_put(cd
->buf_queue
, nbp
);
981 cdstart(cd
->sc_periph
);
988 obp
->b_error
= bp
->b_error
;
989 obp
->b_resid
= bp
->b_resid
;
990 free(bp
->b_data
, M_DEVBUF
);
991 free(bounce
, M_DEVBUF
);
998 cd_interpret_sense(struct scsipi_xfer
*xs
)
1000 struct scsipi_periph
*periph
= xs
->xs_periph
;
1001 struct scsi_sense_data
*sense
= &xs
->sense
.scsi_sense
;
1002 int retval
= EJUSTRETURN
;
1005 * If it isn't a extended or extended/deferred error, let
1006 * the generic code handle it.
1008 if (SSD_RCODE(sense
->response_code
) != SSD_RCODE_CURRENT
&&
1009 SSD_RCODE(sense
->response_code
) != SSD_RCODE_DEFERRED
)
1013 * If we got a "Unit not ready" (SKEY_NOT_READY) and "Logical Unit
1014 * Is In The Process of Becoming Ready" (Sense code 0x04,0x01), then
1015 * wait a bit for the drive to spin up
1018 if ((SSD_SENSE_KEY(sense
->flags
) == SKEY_NOT_READY
) &&
1019 (sense
->asc
== 0x04) && (sense
->ascq
== 0x01)) {
1021 * Sleep for 5 seconds to wait for the drive to spin up
1024 SC_DEBUG(periph
, SCSIPI_DB1
, ("Waiting 5 sec for CD "
1026 if (!callout_pending(&periph
->periph_callout
))
1027 scsipi_periph_freeze(periph
, 1);
1028 callout_reset(&periph
->periph_callout
,
1029 5 * hz
, scsipi_periph_timed_thaw
, periph
);
1034 * If we got a "Unit not ready" (SKEY_NOT_READY) and "Logical Unit Not
1035 * Ready, Operation In Progress" (Sense code 0x04, 0x07),
1036 * then wait for the specified time
1039 if ((SSD_SENSE_KEY(sense
->flags
) == SKEY_NOT_READY
) &&
1040 (sense
->asc
== 0x04) && (sense
->ascq
== 0x07)) {
1042 * we could listen to the delay; but it looks like the skey
1043 * data is not always returned.
1045 /* cd_delay = _2btol(sense->sks.sks_bytes); */
1047 /* wait for a half second and get going again */
1048 if (!callout_pending(&periph
->periph_callout
))
1049 scsipi_periph_freeze(periph
, 1);
1050 callout_reset(&periph
->periph_callout
,
1051 hz
/2, scsipi_periph_timed_thaw
, periph
);
1056 * If we got a "Unit not ready" (SKEY_NOT_READY) and "Long write in
1057 * progress" (Sense code 0x04, 0x08), then wait for the specified
1061 if ((SSD_SENSE_KEY(sense
->flags
) == SKEY_NOT_READY
) &&
1062 (sense
->asc
== 0x04) && (sense
->ascq
== 0x08)) {
1064 * long write in process; we could listen to the delay; but it
1065 * looks like the skey data is not always returned.
1067 /* cd_delay = _2btol(sense->sks.sks_bytes); */
1069 /* wait for a half second and get going again */
1070 if (!callout_pending(&periph
->periph_callout
))
1071 scsipi_periph_freeze(periph
, 1);
1072 callout_reset(&periph
->periph_callout
,
1073 hz
/2, scsipi_periph_timed_thaw
, periph
);
1081 cdminphys(struct buf
*bp
)
1083 struct cd_softc
*cd
= device_lookup_private(&cd_cd
, CDUNIT(bp
->b_dev
));
1087 * If the device is ancient, we want to make sure that
1088 * the transfer fits into a 6-byte cdb.
1090 * XXX Note that the SCSI-I spec says that 256-block transfers
1091 * are allowed in a 6-byte read/write, and are specified
1092 * by settng the "length" to 0. However, we're conservative
1093 * here, allowing only 255-block transfers in case an
1094 * ancient device gets confused by length == 0. A length of 0
1095 * in a 10-byte read/write actually means 0 blocks.
1097 if (cd
->flags
& CDF_ANCIENT
) {
1098 xmax
= cd
->sc_dk
.dk_label
->d_secsize
* 0xff;
1100 if (bp
->b_bcount
> xmax
)
1101 bp
->b_bcount
= xmax
;
1104 (*cd
->sc_periph
->periph_channel
->chan_adapter
->adapt_minphys
)(bp
);
1108 cdread(dev_t dev
, struct uio
*uio
, int ioflag
)
1110 return (physio(cdstrategy
, NULL
, dev
, B_READ
, cdminphys
, uio
));
1114 cdwrite(dev_t dev
, struct uio
*uio
, int ioflag
)
1116 return (physio(cdstrategy
, NULL
, dev
, B_WRITE
, cdminphys
, uio
));
1119 #if 0 /* XXX Not used */
1121 * conversion between minute-seconde-frame and logical block address
1125 lba2msf(u_long lba
, u_char
*m
, u_char
*s
, u_char
*f
)
1129 tmp
= lba
+ CD_BLOCK_OFFSET
; /* offset of first logical frame */
1130 tmp
&= 0xffffff; /* negative lbas use only 24 bits */
1131 *m
= tmp
/ (CD_SECS
* CD_FRAMES
);
1132 tmp
%= (CD_SECS
* CD_FRAMES
);
1133 *s
= tmp
/ CD_FRAMES
;
1134 *f
= tmp
% CD_FRAMES
;
1136 #endif /* XXX Not used */
1139 * Convert an hour:minute:second:frame address to a logical block adres. In
1140 * theory the number of secs/minute and number of frames/second could be
1141 * configured differently in the device as could the block offset but in
1142 * practice these values are rock solid and most drives don't even allow
1143 * theses values to be changed.
1146 hmsf2lba(uint8_t h
, uint8_t m
, uint8_t s
, uint8_t f
)
1148 return (((((uint32_t) h
* 60 + m
) * CD_SECS
) + s
) * CD_FRAMES
+ f
)
1153 cdreadmsaddr(struct cd_softc
*cd
, struct cd_formatted_toc
*toc
, int *addr
)
1155 struct scsipi_periph
*periph
= cd
->sc_periph
;
1157 struct cd_toc_entry
*cte
;
1159 error
= cd_read_toc(cd
, CD_TOC_FORM
, 0, 0, toc
,
1160 sizeof(struct ioc_toc_header
) + sizeof(struct cd_toc_entry
),
1161 0, 0x40 /* control word for "get MS info" */);
1166 cte
= &toc
->entries
[0];
1167 if (periph
->periph_quirks
& PQUIRK_LITTLETOC
) {
1168 cte
->addr
.lba
= le32toh(cte
->addr
.lba
);
1169 toc
->header
.len
= le16toh(toc
->header
.len
);
1171 cte
->addr
.lba
= be32toh(cte
->addr
.lba
);
1172 toc
->header
.len
= be16toh(toc
->header
.len
);
1175 *addr
= (toc
->header
.len
>= 10 && cte
->track
> 1) ?
1180 /* synchronise caches code from sd.c, move to scsipi_ioctl.c ? */
1182 cdcachesync(struct scsipi_periph
*periph
, int flags
) {
1183 struct scsi_synchronize_cache_10 cmd
;
1186 * Issue a SYNCHRONIZE CACHE. MMC devices have to issue with address 0
1187 * and length 0 as it can't synchronise parts of the disc per spec.
1188 * We ignore ILLEGAL REQUEST in the event that the command is not
1189 * supported by the device, and poll for completion so that we know
1190 * that the cache has actually been flushed.
1192 * XXX should we handle the PQUIRK_NOSYNCCACHE ?
1195 memset(&cmd
, 0, sizeof(cmd
));
1196 cmd
.opcode
= SCSI_SYNCHRONIZE_CACHE_10
;
1198 return (scsipi_command(periph
, (void *)&cmd
, sizeof(cmd
), 0, 0,
1199 CDRETRIES
, 30000, NULL
, flags
| XS_CTL_IGNORE_ILLEGAL_REQUEST
));
1203 do_cdioreadentries(struct cd_softc
*cd
, struct ioc_read_toc_entry
*te
,
1204 struct cd_formatted_toc
*toc
)
1206 /* READ TOC format 0 command, entries */
1207 struct ioc_toc_header
*th
;
1208 struct cd_toc_entry
*cte
;
1209 u_int len
= te
->data_len
;
1215 if (len
> sizeof(toc
->entries
) ||
1216 len
< sizeof(toc
->entries
[0]))
1218 error
= cd_read_toc(cd
, CD_TOC_FORM
, te
->address_format
,
1219 te
->starting_track
, toc
,
1220 sizeof(toc
->header
) + len
,
1224 if (te
->address_format
== CD_LBA_FORMAT
)
1226 th
->ending_track
- th
->starting_track
+ 1;
1227 ntracks
>= 0; ntracks
--) {
1228 cte
= &toc
->entries
[ntracks
];
1229 cte
->addr_type
= CD_LBA_FORMAT
;
1230 if (cd
->sc_periph
->periph_quirks
& PQUIRK_LITTLETOC
)
1231 cte
->addr
.lba
= le32toh(cte
->addr
.lba
);
1233 cte
->addr
.lba
= be32toh(cte
->addr
.lba
);
1235 if (cd
->sc_periph
->periph_quirks
& PQUIRK_LITTLETOC
)
1236 th
->len
= le16toh(th
->len
);
1238 th
->len
= be16toh(th
->len
);
1243 * Perform special action on behalf of the user.
1244 * Knows about the internals of this device
1247 cdioctl(dev_t dev
, u_long cmd
, void *addr
, int flag
, struct lwp
*l
)
1249 struct cd_softc
*cd
= device_lookup_private(&cd_cd
, CDUNIT(dev
));
1250 struct scsipi_periph
*periph
= cd
->sc_periph
;
1251 struct cd_formatted_toc toc
;
1252 int part
= CDPART(dev
);
1255 #ifdef __HAVE_OLD_DISKLABEL
1256 struct disklabel
*newlabel
= NULL
;
1259 SC_DEBUG(cd
->sc_periph
, SCSIPI_DB2
, ("cdioctl 0x%lx ", cmd
));
1262 * If the device is not valid, some IOCTLs can still be
1263 * handled on the raw partition. Check this here.
1265 if ((periph
->periph_flags
& PERIPH_MEDIA_LOADED
) == 0) {
1273 case OSCIOCIDENTIFY
:
1279 case CDIOCSETSTEREO
:
1291 case CDIOCLOADUNLOAD
:
1293 case DVD_READ_STRUCT
:
1296 if (part
== RAW_PART
)
1300 if ((periph
->periph_flags
& PERIPH_OPEN
) == 0)
1307 error
= disk_ioctl(&cd
->sc_dk
, cmd
, addr
, flag
, l
);
1308 if (error
!= EPASSTHROUGH
)
1313 *(struct disklabel
*)addr
= *(cd
->sc_dk
.dk_label
);
1315 #ifdef __HAVE_OLD_DISKLABEL
1317 newlabel
= malloc(sizeof (*newlabel
), M_TEMP
, M_WAITOK
);
1318 if (newlabel
== NULL
)
1320 memcpy(newlabel
, cd
->sc_dk
.dk_label
, sizeof (*newlabel
));
1321 if (newlabel
->d_npartitions
> OLDMAXPARTITIONS
)
1324 memcpy(addr
, newlabel
, sizeof (struct olddisklabel
));
1325 free(newlabel
, M_TEMP
);
1330 ((struct partinfo
*)addr
)->disklab
= cd
->sc_dk
.dk_label
;
1331 ((struct partinfo
*)addr
)->part
=
1332 &cd
->sc_dk
.dk_label
->d_partitions
[part
];
1337 #ifdef __HAVE_OLD_DISKLABEL
1342 struct disklabel
*lp
;
1344 if ((flag
& FWRITE
) == 0)
1347 #ifdef __HAVE_OLD_DISKLABEL
1348 if (cmd
== ODIOCSDINFO
|| cmd
== ODIOCWDINFO
) {
1349 newlabel
= malloc(sizeof (*newlabel
), M_TEMP
, M_WAITOK
);
1350 if (newlabel
== NULL
)
1352 memset(newlabel
, 0, sizeof newlabel
);
1353 memcpy(newlabel
, addr
, sizeof (struct olddisklabel
));
1359 mutex_enter(&cd
->sc_lock
);
1360 cd
->flags
|= CDF_LABELLING
;
1362 error
= setdisklabel(cd
->sc_dk
.dk_label
,
1363 lp
, /*cd->sc_dk.dk_openmask : */0,
1364 cd
->sc_dk
.dk_cpulabel
);
1369 cd
->flags
&= ~CDF_LABELLING
;
1370 mutex_exit(&cd
->sc_lock
);
1371 #ifdef __HAVE_OLD_DISKLABEL
1372 if (newlabel
!= NULL
)
1373 free(newlabel
, M_TEMP
);
1382 cdgetdefaultlabel(cd
, &toc
, addr
);
1385 #ifdef __HAVE_OLD_DISKLABEL
1386 case ODIOCGDEFLABEL
:
1387 newlabel
= malloc(sizeof (*newlabel
), M_TEMP
, M_WAITOK
);
1388 if (newlabel
== NULL
)
1390 cdgetdefaultlabel(cd
, &toc
, newlabel
);
1391 if (newlabel
->d_npartitions
> OLDMAXPARTITIONS
)
1394 memcpy(addr
, newlabel
, sizeof (struct olddisklabel
));
1395 free(newlabel
, M_TEMP
);
1399 case CDIOCPLAYTRACKS
: {
1400 /* PLAY_MSF command */
1401 struct ioc_play_track
*args
= addr
;
1403 if ((error
= cd_set_pa_immed(cd
, 0)) != 0)
1405 return (cd_play_tracks(cd
, &toc
, args
->start_track
,
1406 args
->start_index
, args
->end_track
, args
->end_index
));
1408 case CDIOCPLAYMSF
: {
1409 /* PLAY_MSF command */
1410 struct ioc_play_msf
*args
= addr
;
1412 if ((error
= cd_set_pa_immed(cd
, 0)) != 0)
1414 return (cd_play_msf(cd
, args
->start_m
, args
->start_s
,
1415 args
->start_f
, args
->end_m
, args
->end_s
, args
->end_f
));
1417 case CDIOCPLAYBLOCKS
: {
1419 struct ioc_play_blocks
*args
= addr
;
1421 if ((error
= cd_set_pa_immed(cd
, 0)) != 0)
1423 return (cd_play(cd
, args
->blk
, args
->len
));
1425 case CDIOCREADSUBCHANNEL
: {
1426 /* READ_SUBCHANNEL command */
1427 struct ioc_read_subchannel
*args
= addr
;
1428 struct cd_sub_channel_info data
;
1429 u_int len
= args
->data_len
;
1431 if (len
> sizeof(data
) ||
1432 len
< sizeof(struct cd_sub_channel_header
))
1434 error
= cd_read_subchannel(cd
, args
->address_format
,
1435 args
->data_format
, args
->track
, &data
, len
, 0);
1438 len
= min(len
, _2btol(data
.header
.data_len
) +
1439 sizeof(struct cd_sub_channel_header
));
1440 return (copyout(&data
, args
->data
, len
));
1442 case CDIOCREADSUBCHANNEL_BUF
: {
1443 /* As CDIOCREADSUBCHANNEL, but without a 2nd buffer area */
1444 struct ioc_read_subchannel_buf
*args
= addr
;
1445 if (args
->req
.data_len
!= sizeof args
->info
)
1447 return cd_read_subchannel(cd
, args
->req
.address_format
,
1448 args
->req
.data_format
, args
->req
.track
, &args
->info
,
1449 sizeof(args
->info
), 0);
1451 case CDIOREADTOCHEADER
: {
1452 /* READ TOC format 0 command, static header */
1453 if ((error
= cd_read_toc(cd
, CD_TOC_FORM
, 0, 0,
1454 &toc
, sizeof(toc
.header
), 0, 0)) != 0)
1456 if (cd
->sc_periph
->periph_quirks
& PQUIRK_LITTLETOC
)
1457 toc
.header
.len
= le16toh(toc
.header
.len
);
1459 toc
.header
.len
= be16toh(toc
.header
.len
);
1460 memcpy(addr
, &toc
.header
, sizeof(toc
.header
));
1463 case CDIOREADTOCENTRYS
: {
1464 struct ioc_read_toc_entry
*te
= addr
;
1465 error
= do_cdioreadentries(cd
, te
, &toc
);
1468 return copyout(toc
.entries
, te
->data
, min(te
->data_len
,
1469 toc
.header
.len
- (sizeof(toc
.header
.starting_track
)
1470 + sizeof(toc
.header
.ending_track
))));
1472 case CDIOREADTOCENTRIES_BUF
: {
1473 struct ioc_read_toc_entry_buf
*te
= addr
;
1474 error
= do_cdioreadentries(cd
, &te
->req
, &toc
);
1477 memcpy(te
->entry
, toc
.entries
, min(te
->req
.data_len
,
1478 toc
.header
.len
- (sizeof(toc
.header
.starting_track
)
1479 + sizeof(toc
.header
.ending_track
))));
1482 case CDIOREADMSADDR
: {
1483 /* READ TOC format 0 command, length of first track only */
1484 int sessno
= *(int*)addr
;
1489 return (cdreadmsaddr(cd
, &toc
, addr
));
1491 case CDIOCSETPATCH
: {
1492 struct ioc_patch
*arg
= addr
;
1494 return (cd_setchan(cd
, arg
->patch
[0], arg
->patch
[1],
1495 arg
->patch
[2], arg
->patch
[3], 0));
1498 /* MODE SENSE command (AUDIO page) */
1499 struct ioc_vol
*arg
= addr
;
1501 return (cd_getvol(cd
, arg
, 0));
1504 /* MODE SENSE/MODE SELECT commands (AUDIO page) */
1505 struct ioc_vol
*arg
= addr
;
1507 return (cd_setvol(cd
, arg
, 0));
1510 /* MODE SENSE/MODE SELECT commands (AUDIO page) */
1511 return (cd_setchan(cd
, BOTH_CHANNEL
, BOTH_CHANNEL
,
1512 MUTE_CHANNEL
, MUTE_CHANNEL
, 0));
1514 case CDIOCSETSTEREO
:
1515 /* MODE SENSE/MODE SELECT commands (AUDIO page) */
1516 return (cd_setchan(cd
, LEFT_CHANNEL
, RIGHT_CHANNEL
,
1517 MUTE_CHANNEL
, MUTE_CHANNEL
, 0));
1520 /* MODE SENSE/MODE SELECT commands (AUDIO page) */
1521 return (cd_setchan(cd
, MUTE_CHANNEL
, MUTE_CHANNEL
,
1522 MUTE_CHANNEL
, MUTE_CHANNEL
, 0));
1525 /* MODE SENSE/MODE SELECT commands (AUDIO page) */
1526 return (cd_setchan(cd
, LEFT_CHANNEL
, LEFT_CHANNEL
,
1527 MUTE_CHANNEL
, MUTE_CHANNEL
, 0));
1530 /* MODE SENSE/MODE SELECT commands (AUDIO page) */
1531 return (cd_setchan(cd
, RIGHT_CHANNEL
, RIGHT_CHANNEL
,
1532 MUTE_CHANNEL
, MUTE_CHANNEL
, 0));
1536 return (cd_pause(cd
, PA_RESUME
));
1539 return (cd_pause(cd
, PA_PAUSE
));
1541 return (scsipi_start(periph
, SSS_START
, 0));
1543 return (scsipi_start(periph
, SSS_STOP
, 0));
1545 return (scsipi_start(periph
, SSS_START
|SSS_LOEJ
,
1546 XS_CTL_IGNORE_NOT_READY
| XS_CTL_IGNORE_MEDIA_CHANGE
));
1548 if (*(int *)addr
== 0) {
1550 * Don't force eject: check that we are the only
1551 * partition open. If so, unlock it.
1553 if ((cd
->sc_dk
.dk_openmask
& ~(1 << part
)) == 0 &&
1554 cd
->sc_dk
.dk_bopenmask
+ cd
->sc_dk
.dk_copenmask
==
1555 cd
->sc_dk
.dk_openmask
) {
1556 error
= scsipi_prevent(periph
, SPAMR_ALLOW
,
1557 XS_CTL_IGNORE_NOT_READY
);
1565 case CDIOCEJECT
: /* FALLTHROUGH */
1567 return (scsipi_start(periph
, SSS_STOP
|SSS_LOEJ
, 0));
1569 /* SYNCHRONISE CACHES command */
1570 return (cdcachesync(periph
, 0));
1572 return (scsipi_prevent(periph
, SPAMR_ALLOW
, 0));
1574 return (scsipi_prevent(periph
, SPAMR_PREVENT_DT
, 0));
1576 return (scsipi_prevent(periph
,
1577 (*(int *)addr
) ? SPAMR_PREVENT_DT
: SPAMR_ALLOW
, 0));
1579 cd
->sc_periph
->periph_dbflags
|= (SCSIPI_DB1
| SCSIPI_DB2
);
1582 cd
->sc_periph
->periph_dbflags
&= ~(SCSIPI_DB1
| SCSIPI_DB2
);
1586 return (cd_reset(cd
));
1587 case CDIOCLOADUNLOAD
:
1588 /* LOAD_UNLOAD command */
1589 return (cd_load_unload(cd
, addr
));
1591 /* GPCMD_REPORT_KEY or GPCMD_SEND_KEY command */
1592 return (dvd_auth(cd
, addr
));
1593 case DVD_READ_STRUCT
:
1594 /* GPCMD_READ_DVD_STRUCTURE command */
1595 return (dvd_read_struct(cd
, addr
));
1596 case MMCGETDISCINFO
:
1598 * GET_CONFIGURATION, READ_DISCINFO, READ_TRACKINFO,
1599 * (READ_TOCf2, READ_CD_CAPACITY and GET_CONFIGURATION) commands
1601 return mmc_getdiscinfo(periph
, (struct mmc_discinfo
*) addr
);
1602 case MMCGETTRACKINFO
:
1603 /* READ TOCf2, READ_CD_CAPACITY and READ_TRACKINFO commands */
1604 return mmc_gettrackinfo(periph
, (struct mmc_trackinfo
*) addr
);
1607 * CLOSE TRACK/SESSION, RESERVE_TRACK, REPAIR_TRACK,
1608 * SYNCHRONISE_CACHE commands
1610 return mmc_do_op(periph
, (struct mmc_op
*) addr
);
1611 case MMCSETUPWRITEPARAMS
:
1612 /* MODE SENSE page 5, MODE_SELECT page 5 commands */
1613 return mmc_setup_writeparams(periph
, (struct mmc_writeparams
*) addr
);
1616 struct disk_strategy
*dks
= addr
;
1619 strlcpy(dks
->dks_name
, bufq_getstrategyname(cd
->buf_queue
),
1620 sizeof(dks
->dks_name
));
1622 dks
->dks_paramlen
= 0;
1628 struct disk_strategy
*dks
= addr
;
1629 struct bufq_state
*new;
1630 struct bufq_state
*old
;
1632 if ((flag
& FWRITE
) == 0) {
1635 if (dks
->dks_param
!= NULL
) {
1638 dks
->dks_name
[sizeof(dks
->dks_name
) - 1] = 0; /* ensure term */
1639 error
= bufq_alloc(&new, dks
->dks_name
,
1640 BUFQ_EXACT
|BUFQ_SORT_RAWBLOCK
);
1645 old
= cd
->buf_queue
;
1646 bufq_move(new, old
);
1647 cd
->buf_queue
= new;
1654 if (part
!= RAW_PART
)
1656 return (scsipi_do_ioctl(periph
, dev
, cmd
, addr
, flag
, l
));
1660 panic("cdioctl: impossible");
1665 cdgetdefaultlabel(struct cd_softc
*cd
, struct cd_formatted_toc
*toc
,
1666 struct disklabel
*lp
)
1670 memset(lp
, 0, sizeof(struct disklabel
));
1672 lp
->d_secsize
= cd
->params
.blksize
;
1674 lp
->d_nsectors
= 100;
1675 lp
->d_ncylinders
= (cd
->params
.disksize
/ 100) + 1;
1676 lp
->d_secpercyl
= lp
->d_ntracks
* lp
->d_nsectors
;
1678 switch (scsipi_periph_bustype(cd
->sc_periph
)) {
1679 case SCSIPI_BUSTYPE_SCSI
:
1680 lp
->d_type
= DTYPE_SCSI
;
1682 case SCSIPI_BUSTYPE_ATAPI
:
1683 lp
->d_type
= DTYPE_ATAPI
;
1688 * We could probe the mode pages to figure out what kind of disc it is.
1689 * Is this worthwhile?
1691 strncpy(lp
->d_typename
, "optical media", 16);
1692 strncpy(lp
->d_packname
, "fictitious", 16);
1693 lp
->d_secperunit
= cd
->params
.disksize
;
1695 lp
->d_interleave
= 1;
1696 lp
->d_flags
= D_REMOVABLE
| D_SCSI_MMC
;
1698 if (cdreadmsaddr(cd
, toc
, &lastsession
) != 0)
1701 lp
->d_partitions
[0].p_offset
= 0;
1702 lp
->d_partitions
[0].p_size
= lp
->d_secperunit
;
1703 lp
->d_partitions
[0].p_cdsession
= lastsession
;
1704 lp
->d_partitions
[0].p_fstype
= FS_ISO9660
;
1706 lp
->d_partitions
[RAW_PART
].p_offset
= 0;
1707 lp
->d_partitions
[RAW_PART
].p_size
= lp
->d_secperunit
;
1708 lp
->d_partitions
[RAW_PART
].p_fstype
= FS_UDF
;
1710 lp
->d_npartitions
= RAW_PART
+ 1;
1712 lp
->d_magic
= DISKMAGIC
;
1713 lp
->d_magic2
= DISKMAGIC
;
1714 lp
->d_checksum
= dkcksum(lp
);
1718 * Load the label information on the named device
1719 * Actually fabricate a disklabel
1721 * EVENTUALLY take information about different
1722 * data tracks from the TOC and put it in the disklabel
1725 cdgetdisklabel(struct cd_softc
*cd
)
1727 struct disklabel
*lp
= cd
->sc_dk
.dk_label
;
1728 struct cd_formatted_toc toc
;
1729 const char *errstring
;
1732 memset(cd
->sc_dk
.dk_cpulabel
, 0, sizeof(struct cpu_disklabel
));
1734 cdgetdefaultlabel(cd
, &toc
, lp
);
1737 * Call the generic disklabel extraction routine
1739 * bmajor follows ata_raid code
1741 bmajor
= devsw_name2blk(device_xname(cd
->sc_dev
), NULL
, 0);
1742 errstring
= readdisklabel(MAKECDDEV(bmajor
,
1743 device_unit(cd
->sc_dev
), RAW_PART
),
1744 cdstrategy
, lp
, cd
->sc_dk
.dk_cpulabel
);
1746 /* if all went OK, we are passed a NULL error string */
1747 if (errstring
== NULL
)
1750 /* Reset to default label -- after printing error and the warning */
1751 aprint_error_dev(cd
->sc_dev
, "%s\n", errstring
);
1752 memset(cd
->sc_dk
.dk_cpulabel
, 0, sizeof(struct cpu_disklabel
));
1753 cdgetdefaultlabel(cd
, &toc
, lp
);
1757 * Reading a discs total capacity is aparently a very difficult issue for the
1758 * SCSI standardisation group. Every disc type seems to have its own
1759 * (re)invented size request method and modifiers. The failsafe way of
1760 * determining the total (max) capacity i.e. not the recorded capacity but the
1761 * total maximum capacity is to request the info on the last track and
1762 * calucate the total size.
1764 * For ROM drives, we go for the CD recorded capacity. For recordable devices
1768 read_cd_capacity(struct scsipi_periph
*periph
, u_int
*blksize
, u_long
*size
)
1770 struct scsipi_read_cd_capacity cap_cmd
;
1771 struct scsipi_read_cd_cap_data cap
;
1772 struct scsipi_read_discinfo di_cmd
;
1773 struct scsipi_read_discinfo_data di
;
1774 struct scsipi_read_trackinfo ti_cmd
;
1775 struct scsipi_read_trackinfo_data ti
;
1776 uint32_t track_start
, track_size
;
1777 int error
, flags
, msb
, lsb
, last_track
;
1779 /* if the device doesn't grog capacity, return the dummies */
1780 if (periph
->periph_quirks
& PQUIRK_NOCAPACITY
)
1783 /* first try read CD capacity for blksize and recorded size */
1784 /* issue the cd capacity request */
1785 flags
= XS_CTL_DATA_IN
;
1786 memset(&cap_cmd
, 0, sizeof(cap_cmd
));
1787 cap_cmd
.opcode
= READ_CD_CAPACITY
;
1789 error
= scsipi_command(periph
,
1790 (void *) &cap_cmd
, sizeof(cap_cmd
),
1791 (void *) &cap
, sizeof(cap
),
1792 CDRETRIES
, 30000, NULL
, flags
);
1796 /* retrieve values and sanity check them */
1797 *blksize
= _4btol(cap
.length
);
1798 *size
= _4btol(cap
.addr
);
1800 /* blksize is 2048 for CD, but some drives give gibberish */
1801 if ((*blksize
< 512) || ((*blksize
& 511) != 0))
1802 *blksize
= 2048; /* some drives lie ! */
1804 /* recordables have READ_DISCINFO implemented */
1805 flags
= XS_CTL_DATA_IN
| XS_CTL_SILENT
;
1806 memset(&di_cmd
, 0, sizeof(di_cmd
));
1807 di_cmd
.opcode
= READ_DISCINFO
;
1808 _lto2b(READ_DISCINFO_BIGSIZE
, di_cmd
.data_len
);
1810 error
= scsipi_command(periph
,
1811 (void *) &di_cmd
, sizeof(di_cmd
),
1812 (void *) &di
, READ_DISCINFO_BIGSIZE
,
1813 CDRETRIES
, 30000, NULL
, flags
);
1815 msb
= di
.last_track_last_session_msb
;
1816 lsb
= di
.last_track_last_session_lsb
;
1817 last_track
= (msb
<< 8) | lsb
;
1819 /* request info on last track */
1820 memset(&ti_cmd
, 0, sizeof(ti_cmd
));
1821 ti_cmd
.opcode
= READ_TRACKINFO
;
1822 ti_cmd
.addr_type
= 1; /* on tracknr */
1823 _lto4b(last_track
, ti_cmd
.address
); /* tracknr */
1824 _lto2b(sizeof(ti
), ti_cmd
.data_len
);
1826 error
= scsipi_command(periph
,
1827 (void *) &ti_cmd
, sizeof(ti_cmd
),
1828 (void *) &ti
, sizeof(ti
),
1829 CDRETRIES
, 30000, NULL
, flags
);
1831 track_start
= _4btol(ti
.track_start
);
1832 track_size
= _4btol(ti
.track_size
);
1834 /* overwrite only with a sane value */
1835 if (track_start
+ track_size
>= 100)
1836 *size
= track_start
+ track_size
;
1840 /* sanity check for size */
1848 * Find out from the device what it's capacity is
1851 cd_size(struct cd_softc
*cd
, int flags
)
1857 /* set up fake values */
1861 /* if this function bounces with an error return fake value */
1862 error
= read_cd_capacity(cd
->sc_periph
, &blksize
, &size
);
1866 if (blksize
!= 2048) {
1867 if (cd_setblksize(cd
) == 0)
1870 cd
->params
.blksize
= blksize
;
1871 cd
->params
.disksize
= size
;
1872 cd
->params
.disksize512
= ((u_int64_t
)cd
->params
.disksize
* blksize
) / DEV_BSIZE
;
1874 SC_DEBUG(cd
->sc_periph
, SCSIPI_DB2
,
1875 ("cd_size: %u %lu\n", blksize
, size
));
1881 * Get scsi driver to send a "start playing" command
1884 cd_play(struct cd_softc
*cd
, int blkno
, int nblks
)
1886 struct scsipi_play cmd
;
1888 memset(&cmd
, 0, sizeof(cmd
));
1890 _lto4b(blkno
, cmd
.blk_addr
);
1891 _lto2b(nblks
, cmd
.xfer_len
);
1893 return (scsipi_command(cd
->sc_periph
, (void *)&cmd
, sizeof(cmd
), 0, 0,
1894 CDRETRIES
, 30000, NULL
, 0));
1898 * Get scsi driver to send a "start playing" command
1901 cd_play_tracks(struct cd_softc
*cd
, struct cd_formatted_toc
*toc
, int strack
,
1902 int sindex
, int etrack
, int eindex
)
1908 if (strack
> etrack
)
1911 error
= cd_load_toc(cd
, CD_TOC_FORM
, toc
, 0);
1915 if (++etrack
> (toc
->header
.ending_track
+1))
1916 etrack
= toc
->header
.ending_track
+1;
1918 strack
-= toc
->header
.starting_track
;
1919 etrack
-= toc
->header
.starting_track
;
1923 return (cd_play_msf(cd
, toc
->entries
[strack
].addr
.msf
.minute
,
1924 toc
->entries
[strack
].addr
.msf
.second
,
1925 toc
->entries
[strack
].addr
.msf
.frame
,
1926 toc
->entries
[etrack
].addr
.msf
.minute
,
1927 toc
->entries
[etrack
].addr
.msf
.second
,
1928 toc
->entries
[etrack
].addr
.msf
.frame
));
1932 * Get scsi driver to send a "play msf" command
1935 cd_play_msf(struct cd_softc
*cd
, int startm
, int starts
, int startf
, int endm
,
1938 struct scsipi_play_msf cmd
;
1940 memset(&cmd
, 0, sizeof(cmd
));
1941 cmd
.opcode
= PLAY_MSF
;
1942 cmd
.start_m
= startm
;
1943 cmd
.start_s
= starts
;
1944 cmd
.start_f
= startf
;
1949 return (scsipi_command(cd
->sc_periph
, (void *)&cmd
, sizeof(cmd
), 0, 0,
1950 CDRETRIES
, 30000, NULL
, 0));
1954 * Get scsi driver to send a "start up" command
1957 cd_pause(struct cd_softc
*cd
, int go
)
1959 struct scsipi_pause cmd
;
1961 memset(&cmd
, 0, sizeof(cmd
));
1963 cmd
.resume
= go
& 0xff;
1965 return (scsipi_command(cd
->sc_periph
, (void *)&cmd
, sizeof(cmd
), 0, 0,
1966 CDRETRIES
, 30000, NULL
, 0));
1970 * Get scsi driver to send a "RESET" command
1973 cd_reset(struct cd_softc
*cd
)
1976 return (scsipi_command(cd
->sc_periph
, 0, 0, 0, 0,
1977 CDRETRIES
, 30000, NULL
, XS_CTL_RESET
));
1984 cd_read_subchannel(struct cd_softc
*cd
, int mode
, int format
, int track
,
1985 struct cd_sub_channel_info
*data
, int len
, int flags
)
1987 struct scsipi_read_subchannel cmd
;
1989 memset(&cmd
, 0, sizeof(cmd
));
1990 cmd
.opcode
= READ_SUBCHANNEL
;
1991 if (mode
== CD_MSF_FORMAT
)
1992 cmd
.byte2
|= CD_MSF
;
1993 cmd
.byte3
= SRS_SUBQ
;
1994 cmd
.subchan_format
= format
;
1996 _lto2b(len
, cmd
.data_len
);
1998 return (scsipi_command(cd
->sc_periph
,
1999 (void *)&cmd
, sizeof(struct scsipi_read_subchannel
),
2001 CDRETRIES
, 30000, NULL
, flags
| XS_CTL_DATA_IN
| XS_CTL_SILENT
));
2005 * Read table of contents
2008 cd_read_toc(struct cd_softc
*cd
, int respf
, int mode
, int start
,
2009 struct cd_formatted_toc
*toc
, int len
, int flags
, int control
)
2011 struct scsipi_read_toc cmd
;
2014 memset(&cmd
, 0, sizeof(cmd
));
2016 if (len
!= sizeof(struct ioc_toc_header
))
2017 ntoc
= ((len
) - sizeof(struct ioc_toc_header
)) /
2018 sizeof(struct cd_toc_entry
);
2022 cmd
.opcode
= READ_TOC
;
2023 if (mode
== CD_MSF_FORMAT
)
2024 cmd
.addr_mode
|= CD_MSF
;
2025 cmd
.resp_format
= respf
;
2026 cmd
.from_track
= start
;
2027 _lto2b(ntoc
, cmd
.data_len
);
2028 cmd
.control
= control
;
2030 return (scsipi_command(cd
->sc_periph
,
2031 (void *)&cmd
, sizeof(cmd
), (void *)toc
, len
, CDRETRIES
,
2032 30000, NULL
, flags
| XS_CTL_DATA_IN
));
2036 cd_load_toc(struct cd_softc
*cd
, int respf
, struct cd_formatted_toc
*toc
, int flags
)
2038 int ntracks
, len
, error
;
2040 if ((error
= cd_read_toc(cd
, respf
, 0, 0, toc
, sizeof(toc
->header
),
2044 ntracks
= toc
->header
.ending_track
- toc
->header
.starting_track
+ 1;
2045 len
= (ntracks
+ 1) * sizeof(struct cd_toc_entry
) +
2046 sizeof(toc
->header
);
2047 if ((error
= cd_read_toc(cd
, respf
, CD_MSF_FORMAT
, 0, toc
, len
,
2054 * Get the scsi driver to send a full inquiry to the device and use the
2055 * results to fill out the disk parameter structure.
2058 cd_get_parms(struct cd_softc
*cd
, int flags
)
2062 * give a number of sectors so that sec * trks * cyls
2065 if (cd_size(cd
, flags
) == 0)
2067 disk_blocksize(&cd
->sc_dk
, cd
->params
.blksize
);
2075 /* CD-ROMs are read-only. */
2080 cddump(dev_t dev
, daddr_t blkno
, void *va
, size_t size
)
2083 /* Not implemented. */
2087 #define dvd_copy_key(dst, src) memcpy((dst), (src), sizeof(dvd_key))
2088 #define dvd_copy_challenge(dst, src) memcpy((dst), (src), sizeof(dvd_challenge))
2091 dvd_auth(struct cd_softc
*cd
, dvd_authinfo
*a
)
2093 struct scsipi_generic cmd
;
2097 memset(cmd
.bytes
, 0, 15);
2098 memset(bf
, 0, sizeof(bf
));
2101 case DVD_LU_SEND_AGID
:
2102 cmd
.opcode
= GPCMD_REPORT_KEY
;
2104 cmd
.bytes
[9] = 0 | (0 << 6);
2105 error
= scsipi_command(cd
->sc_periph
, &cmd
, 12, bf
, 8,
2106 CDRETRIES
, 30000, NULL
, XS_CTL_DATA_IN
);
2109 a
->lsa
.agid
= bf
[7] >> 6;
2112 case DVD_LU_SEND_CHALLENGE
:
2113 cmd
.opcode
= GPCMD_REPORT_KEY
;
2115 cmd
.bytes
[9] = 1 | (a
->lsc
.agid
<< 6);
2116 error
= scsipi_command(cd
->sc_periph
, &cmd
, 12, bf
, 16,
2117 CDRETRIES
, 30000, NULL
, XS_CTL_DATA_IN
);
2120 dvd_copy_challenge(a
->lsc
.chal
, &bf
[4]);
2123 case DVD_LU_SEND_KEY1
:
2124 cmd
.opcode
= GPCMD_REPORT_KEY
;
2126 cmd
.bytes
[9] = 2 | (a
->lsk
.agid
<< 6);
2127 error
= scsipi_command(cd
->sc_periph
, &cmd
, 12, bf
, 12,
2128 CDRETRIES
, 30000, NULL
, XS_CTL_DATA_IN
);
2131 dvd_copy_key(a
->lsk
.key
, &bf
[4]);
2134 case DVD_LU_SEND_TITLE_KEY
:
2135 cmd
.opcode
= GPCMD_REPORT_KEY
;
2136 _lto4b(a
->lstk
.lba
, &cmd
.bytes
[1]);
2138 cmd
.bytes
[9] = 4 | (a
->lstk
.agid
<< 6);
2139 error
= scsipi_command(cd
->sc_periph
, &cmd
, 12, bf
, 12,
2140 CDRETRIES
, 30000, NULL
, XS_CTL_DATA_IN
);
2143 a
->lstk
.cpm
= (bf
[4] >> 7) & 1;
2144 a
->lstk
.cp_sec
= (bf
[4] >> 6) & 1;
2145 a
->lstk
.cgms
= (bf
[4] >> 4) & 3;
2146 dvd_copy_key(a
->lstk
.title_key
, &bf
[5]);
2149 case DVD_LU_SEND_ASF
:
2150 cmd
.opcode
= GPCMD_REPORT_KEY
;
2152 cmd
.bytes
[9] = 5 | (a
->lsasf
.agid
<< 6);
2153 error
= scsipi_command(cd
->sc_periph
, &cmd
, 12, bf
, 8,
2154 CDRETRIES
, 30000, NULL
, XS_CTL_DATA_IN
);
2157 a
->lsasf
.asf
= bf
[7] & 1;
2160 case DVD_HOST_SEND_CHALLENGE
:
2161 cmd
.opcode
= GPCMD_SEND_KEY
;
2163 cmd
.bytes
[9] = 1 | (a
->hsc
.agid
<< 6);
2165 dvd_copy_challenge(&bf
[4], a
->hsc
.chal
);
2166 error
= scsipi_command(cd
->sc_periph
, &cmd
, 12, bf
, 16,
2167 CDRETRIES
, 30000, NULL
, XS_CTL_DATA_OUT
);
2170 a
->type
= DVD_LU_SEND_KEY1
;
2173 case DVD_HOST_SEND_KEY2
:
2174 cmd
.opcode
= GPCMD_SEND_KEY
;
2176 cmd
.bytes
[9] = 3 | (a
->hsk
.agid
<< 6);
2178 dvd_copy_key(&bf
[4], a
->hsk
.key
);
2179 error
= scsipi_command(cd
->sc_periph
, &cmd
, 12, bf
, 12,
2180 CDRETRIES
, 30000, NULL
, XS_CTL_DATA_OUT
);
2182 a
->type
= DVD_AUTH_FAILURE
;
2185 a
->type
= DVD_AUTH_ESTABLISHED
;
2188 case DVD_INVALIDATE_AGID
:
2189 cmd
.opcode
= GPCMD_REPORT_KEY
;
2190 cmd
.bytes
[9] = 0x3f | (a
->lsa
.agid
<< 6);
2191 error
= scsipi_command(cd
->sc_periph
, &cmd
, 12, bf
, 16,
2192 CDRETRIES
, 30000, NULL
, 0);
2197 case DVD_LU_SEND_RPC_STATE
:
2198 cmd
.opcode
= GPCMD_REPORT_KEY
;
2200 cmd
.bytes
[9] = 8 | (0 << 6);
2201 error
= scsipi_command(cd
->sc_periph
, &cmd
, 12, bf
, 8,
2202 CDRETRIES
, 30000, NULL
, XS_CTL_DATA_IN
);
2205 a
->lrpcs
.type
= (bf
[4] >> 6) & 3;
2206 a
->lrpcs
.vra
= (bf
[4] >> 3) & 7;
2207 a
->lrpcs
.ucca
= (bf
[4]) & 7;
2208 a
->lrpcs
.region_mask
= bf
[5];
2209 a
->lrpcs
.rpc_scheme
= bf
[6];
2212 case DVD_HOST_SEND_RPC_STATE
:
2213 cmd
.opcode
= GPCMD_SEND_KEY
;
2215 cmd
.bytes
[9] = 6 | (0 << 6);
2217 bf
[4] = a
->hrpcs
.pdrc
;
2218 error
= scsipi_command(cd
->sc_periph
, &cmd
, 12, bf
, 8,
2219 CDRETRIES
, 30000, NULL
, XS_CTL_DATA_OUT
);
2230 dvd_read_physical(struct cd_softc
*cd
, dvd_struct
*s
)
2232 struct scsipi_generic cmd
;
2233 u_int8_t bf
[4 + 4 * 20], *bufp
;
2235 struct dvd_layer
*layer
;
2238 memset(cmd
.bytes
, 0, 15);
2239 memset(bf
, 0, sizeof(bf
));
2240 cmd
.opcode
= GPCMD_READ_DVD_STRUCTURE
;
2241 cmd
.bytes
[6] = s
->type
;
2242 _lto2b(sizeof(bf
), &cmd
.bytes
[7]);
2244 cmd
.bytes
[5] = s
->physical
.layer_num
;
2245 error
= scsipi_command(cd
->sc_periph
, &cmd
, 12, bf
, sizeof(bf
),
2246 CDRETRIES
, 30000, NULL
, XS_CTL_DATA_IN
);
2249 for (i
= 0, bufp
= &bf
[4], layer
= &s
->physical
.layer
[0]; i
< 4;
2250 i
++, bufp
+= 20, layer
++) {
2251 memset(layer
, 0, sizeof(*layer
));
2252 layer
->book_version
= bufp
[0] & 0xf;
2253 layer
->book_type
= bufp
[0] >> 4;
2254 layer
->min_rate
= bufp
[1] & 0xf;
2255 layer
->disc_size
= bufp
[1] >> 4;
2256 layer
->layer_type
= bufp
[2] & 0xf;
2257 layer
->track_path
= (bufp
[2] >> 4) & 1;
2258 layer
->nlayers
= (bufp
[2] >> 5) & 3;
2259 layer
->track_density
= bufp
[3] & 0xf;
2260 layer
->linear_density
= bufp
[3] >> 4;
2261 layer
->start_sector
= _4btol(&bufp
[4]);
2262 layer
->end_sector
= _4btol(&bufp
[8]);
2263 layer
->end_sector_l0
= _4btol(&bufp
[12]);
2264 layer
->bca
= bufp
[16] >> 7;
2270 dvd_read_copyright(struct cd_softc
*cd
, dvd_struct
*s
)
2272 struct scsipi_generic cmd
;
2276 memset(cmd
.bytes
, 0, 15);
2277 memset(bf
, 0, sizeof(bf
));
2278 cmd
.opcode
= GPCMD_READ_DVD_STRUCTURE
;
2279 cmd
.bytes
[6] = s
->type
;
2280 _lto2b(sizeof(bf
), &cmd
.bytes
[7]);
2282 cmd
.bytes
[5] = s
->copyright
.layer_num
;
2283 error
= scsipi_command(cd
->sc_periph
, &cmd
, 12, bf
, sizeof(bf
),
2284 CDRETRIES
, 30000, NULL
, XS_CTL_DATA_IN
);
2287 s
->copyright
.cpst
= bf
[4];
2288 s
->copyright
.rmi
= bf
[5];
2293 dvd_read_disckey(struct cd_softc
*cd
, dvd_struct
*s
)
2295 struct scsipi_generic cmd
;
2299 bf
= malloc(4 + 2048, M_TEMP
, M_WAITOK
|M_ZERO
);
2302 memset(cmd
.bytes
, 0, 15);
2303 cmd
.opcode
= GPCMD_READ_DVD_STRUCTURE
;
2304 cmd
.bytes
[6] = s
->type
;
2305 _lto2b(4 + 2048, &cmd
.bytes
[7]);
2307 cmd
.bytes
[9] = s
->disckey
.agid
<< 6;
2308 error
= scsipi_command(cd
->sc_periph
, &cmd
, 12, bf
, 4 + 2048,
2309 CDRETRIES
, 30000, NULL
, XS_CTL_DATA_IN
);
2311 memcpy(s
->disckey
.value
, &bf
[4], 2048);
2317 dvd_read_bca(struct cd_softc
*cd
, dvd_struct
*s
)
2319 struct scsipi_generic cmd
;
2320 u_int8_t bf
[4 + 188];
2323 memset(cmd
.bytes
, 0, 15);
2324 memset(bf
, 0, sizeof(bf
));
2325 cmd
.opcode
= GPCMD_READ_DVD_STRUCTURE
;
2326 cmd
.bytes
[6] = s
->type
;
2327 _lto2b(sizeof(bf
), &cmd
.bytes
[7]);
2329 error
= scsipi_command(cd
->sc_periph
, &cmd
, 12, bf
, sizeof(bf
),
2330 CDRETRIES
, 30000, NULL
, XS_CTL_DATA_IN
);
2333 s
->bca
.len
= _2btol(&bf
[0]);
2334 if (s
->bca
.len
< 12 || s
->bca
.len
> 188)
2336 memcpy(s
->bca
.value
, &bf
[4], s
->bca
.len
);
2341 dvd_read_manufact(struct cd_softc
*cd
, dvd_struct
*s
)
2343 struct scsipi_generic cmd
;
2347 bf
= malloc(4 + 2048, M_TEMP
, M_WAITOK
|M_ZERO
);
2350 memset(cmd
.bytes
, 0, 15);
2351 cmd
.opcode
= GPCMD_READ_DVD_STRUCTURE
;
2352 cmd
.bytes
[6] = s
->type
;
2353 _lto2b(4 + 2048, &cmd
.bytes
[7]);
2355 error
= scsipi_command(cd
->sc_periph
, &cmd
, 12, bf
, 4 + 2048,
2356 CDRETRIES
, 30000, NULL
, XS_CTL_DATA_IN
);
2358 s
->manufact
.len
= _2btol(&bf
[0]);
2359 if (s
->manufact
.len
>= 0 && s
->manufact
.len
<= 2048)
2360 memcpy(s
->manufact
.value
, &bf
[4], s
->manufact
.len
);
2369 dvd_read_struct(struct cd_softc
*cd
, dvd_struct
*s
)
2373 case DVD_STRUCT_PHYSICAL
:
2374 return (dvd_read_physical(cd
, s
));
2375 case DVD_STRUCT_COPYRIGHT
:
2376 return (dvd_read_copyright(cd
, s
));
2377 case DVD_STRUCT_DISCKEY
:
2378 return (dvd_read_disckey(cd
, s
));
2379 case DVD_STRUCT_BCA
:
2380 return (dvd_read_bca(cd
, s
));
2381 case DVD_STRUCT_MANUFACT
:
2382 return (dvd_read_manufact(cd
, s
));
2389 cd_mode_sense(struct cd_softc
*cd
, u_int8_t byte2
, void *sense
, size_t size
,
2390 int page
, int flags
, int *big
)
2393 if (cd
->sc_periph
->periph_quirks
& PQUIRK_ONLYBIG
) {
2395 return scsipi_mode_sense_big(cd
->sc_periph
, byte2
, page
, sense
,
2396 size
+ sizeof(struct scsi_mode_parameter_header_10
),
2397 flags
, CDRETRIES
, 20000);
2400 return scsipi_mode_sense(cd
->sc_periph
, byte2
, page
, sense
,
2401 size
+ sizeof(struct scsi_mode_parameter_header_6
),
2402 flags
, CDRETRIES
, 20000);
2407 cd_mode_select(struct cd_softc
*cd
, u_int8_t byte2
, void *sense
, size_t size
,
2412 struct scsi_mode_parameter_header_10
*header
= sense
;
2414 _lto2b(0, header
->data_length
);
2415 return scsipi_mode_select_big(cd
->sc_periph
, byte2
, sense
,
2416 size
+ sizeof(struct scsi_mode_parameter_header_10
),
2417 flags
, CDRETRIES
, 20000);
2419 struct scsi_mode_parameter_header_6
*header
= sense
;
2421 header
->data_length
= 0;
2422 return scsipi_mode_select(cd
->sc_periph
, byte2
, sense
,
2423 size
+ sizeof(struct scsi_mode_parameter_header_6
),
2424 flags
, CDRETRIES
, 20000);
2429 cd_set_pa_immed(struct cd_softc
*cd
, int flags
)
2433 struct scsi_mode_parameter_header_6 small
;
2434 struct scsi_mode_parameter_header_10 big
;
2436 struct cd_audio_page page
;
2441 struct cd_audio_page
*page
;
2445 if ((error
= cd_mode_sense(cd
, byte2
, &data
, sizeof(data
.page
),
2446 AUDIO_PAGE
, flags
, &big
)) != 0) {
2447 if (byte2
== SMS_DBD
) {
2448 /* Device may not understand DBD; retry without */
2456 page
= (void *)((u_long
)&data
.header
.big
+
2457 sizeof data
.header
.big
+
2458 _2btol(data
.header
.big
.blk_desc_len
));
2460 page
= (void *)((u_long
)&data
.header
.small
+
2461 sizeof data
.header
.small
+
2462 data
.header
.small
.blk_desc_len
);
2464 oflags
= page
->flags
;
2465 page
->flags
&= ~CD_PA_SOTC
;
2466 page
->flags
|= CD_PA_IMMED
;
2467 if (oflags
== page
->flags
)
2470 return (cd_mode_select(cd
, SMS_PF
, &data
,
2471 sizeof(struct scsi_mode_page_header
) + page
->pg_length
,
2476 cd_setchan(struct cd_softc
*cd
, int p0
, int p1
, int p2
, int p3
, int flags
)
2480 struct scsi_mode_parameter_header_6 small
;
2481 struct scsi_mode_parameter_header_10 big
;
2483 struct cd_audio_page page
;
2487 struct cd_audio_page
*page
;
2491 if ((error
= cd_mode_sense(cd
, byte2
, &data
, sizeof(data
.page
),
2492 AUDIO_PAGE
, flags
, &big
)) != 0) {
2493 if (byte2
== SMS_DBD
) {
2494 /* Device may not understand DBD; retry without */
2502 page
= (void *)((u_long
)&data
.header
.big
+
2503 sizeof data
.header
.big
+
2504 _2btol(data
.header
.big
.blk_desc_len
));
2506 page
= (void *)((u_long
)&data
.header
.small
+
2507 sizeof data
.header
.small
+
2508 data
.header
.small
.blk_desc_len
);
2510 page
->port
[0].channels
= p0
;
2511 page
->port
[1].channels
= p1
;
2512 page
->port
[2].channels
= p2
;
2513 page
->port
[3].channels
= p3
;
2515 return (cd_mode_select(cd
, SMS_PF
, &data
,
2516 sizeof(struct scsi_mode_page_header
) + page
->pg_length
,
2521 cd_getvol(struct cd_softc
*cd
, struct ioc_vol
*arg
, int flags
)
2525 struct scsi_mode_parameter_header_6 small
;
2526 struct scsi_mode_parameter_header_10 big
;
2528 struct cd_audio_page page
;
2532 struct cd_audio_page
*page
;
2536 if ((error
= cd_mode_sense(cd
, byte2
, &data
, sizeof(data
.page
),
2537 AUDIO_PAGE
, flags
, &big
)) != 0) {
2538 if (byte2
== SMS_DBD
) {
2539 /* Device may not understand DBD; retry without */
2547 page
= (void *)((u_long
)&data
.header
.big
+
2548 sizeof data
.header
.big
+
2549 _2btol(data
.header
.big
.blk_desc_len
));
2551 page
= (void *)((u_long
)&data
.header
.small
+
2552 sizeof data
.header
.small
+
2553 data
.header
.small
.blk_desc_len
);
2555 arg
->vol
[0] = page
->port
[0].volume
;
2556 arg
->vol
[1] = page
->port
[1].volume
;
2557 arg
->vol
[2] = page
->port
[2].volume
;
2558 arg
->vol
[3] = page
->port
[3].volume
;
2564 cd_setvol(struct cd_softc
*cd
, const struct ioc_vol
*arg
, int flags
)
2568 struct scsi_mode_parameter_header_6 small
;
2569 struct scsi_mode_parameter_header_10 big
;
2571 struct cd_audio_page page
;
2575 struct cd_audio_page
*page
, *page2
;
2579 if ((error
= cd_mode_sense(cd
, byte2
, &data
, sizeof(data
.page
),
2580 AUDIO_PAGE
, flags
, &big
)) != 0) {
2581 if (byte2
== SMS_DBD
) {
2582 /* Device may not understand DBD; retry without */
2588 if ((error
= cd_mode_sense(cd
, byte2
, &mask
, sizeof(mask
.page
),
2589 AUDIO_PAGE
|SMS_PCTRL_CHANGEABLE
, flags
, &big
)) != 0)
2593 page
= (void *)((u_long
)&data
.header
.big
+
2594 sizeof data
.header
.big
+
2595 _2btol(data
.header
.big
.blk_desc_len
));
2596 page2
= (void *)((u_long
)&mask
.header
.big
+
2597 sizeof mask
.header
.big
+
2598 _2btol(mask
.header
.big
.blk_desc_len
));
2600 page
= (void *)((u_long
)&data
.header
.small
+
2601 sizeof data
.header
.small
+
2602 data
.header
.small
.blk_desc_len
);
2603 page2
= (void *)((u_long
)&mask
.header
.small
+
2604 sizeof mask
.header
.small
+
2605 mask
.header
.small
.blk_desc_len
);
2608 page
->port
[0].volume
= arg
->vol
[0] & page2
->port
[0].volume
;
2609 page
->port
[1].volume
= arg
->vol
[1] & page2
->port
[1].volume
;
2610 page
->port
[2].volume
= arg
->vol
[2] & page2
->port
[2].volume
;
2611 page
->port
[3].volume
= arg
->vol
[3] & page2
->port
[3].volume
;
2613 page
->port
[0].channels
= CHANNEL_0
;
2614 page
->port
[1].channels
= CHANNEL_1
;
2616 return (cd_mode_select(cd
, SMS_PF
, &data
,
2617 sizeof(struct scsi_mode_page_header
) + page
->pg_length
,
2622 cd_load_unload(struct cd_softc
*cd
, struct ioc_load_unload
*args
)
2624 struct scsipi_load_unload cmd
;
2626 memset(&cmd
, 0, sizeof(cmd
));
2627 cmd
.opcode
= LOAD_UNLOAD
;
2628 cmd
.options
= args
->options
; /* ioctl uses MMC values */
2629 cmd
.slot
= args
->slot
;
2631 return (scsipi_command(cd
->sc_periph
, (void *)&cmd
, sizeof(cmd
), 0, 0,
2632 CDRETRIES
, 200000, NULL
, 0));
2636 cd_setblksize(struct cd_softc
*cd
)
2640 struct scsi_mode_parameter_header_6 small
;
2641 struct scsi_mode_parameter_header_10 big
;
2643 struct scsi_general_block_descriptor blk_desc
;
2647 struct scsi_general_block_descriptor
*bdesc
;
2649 if ((error
= cd_mode_sense(cd
, 0, &data
, sizeof(data
.blk_desc
), 0, 0,
2654 bdesc
= (void *)(&data
.header
.big
+ 1);
2655 bsize
= _2btol(data
.header
.big
.blk_desc_len
);
2657 bdesc
= (void *)(&data
.header
.small
+ 1);
2658 bsize
= data
.header
.small
.blk_desc_len
;
2662 printf("cd_setblksize: trying to change bsize, but no blk_desc\n");
2665 if (_3btol(bdesc
->blklen
) == 2048) {
2666 printf("cd_setblksize: trying to change bsize, but blk_desc is correct\n");
2670 _lto3b(2048, bdesc
->blklen
);
2672 return (cd_mode_select(cd
, SMS_PF
, &data
, sizeof(data
.blk_desc
), 0,
2678 mmc_profile2class(uint16_t mmc_profile
)
2680 switch (mmc_profile
) {
2681 case 0x01 : /* SCSI discs */
2683 /* this can't happen really, cd.c wouldn't have matched */
2684 return MMC_CLASS_DISC
;
2685 case 0x03 : /* Magneto Optical with sector erase */
2686 case 0x04 : /* Magneto Optical write once */
2687 case 0x05 : /* Advance Storage Magneto Optical */
2688 return MMC_CLASS_MO
;
2689 case 0x00 : /* Unknown MMC profile, can also be CD-ROM */
2690 case 0x08 : /* CD-ROM */
2691 case 0x09 : /* CD-R */
2692 case 0x0a : /* CD-RW */
2693 return MMC_CLASS_CD
;
2694 case 0x10 : /* DVD-ROM */
2695 case 0x11 : /* DVD-R */
2696 case 0x12 : /* DVD-RAM */
2697 case 0x13 : /* DVD-RW restricted overwrite */
2698 case 0x14 : /* DVD-RW sequential */
2699 case 0x1a : /* DVD+RW */
2700 case 0x1b : /* DVD+R */
2701 case 0x2a : /* DVD+RW Dual layer */
2702 case 0x2b : /* DVD+R Dual layer */
2703 case 0x50 : /* HD DVD-ROM */
2704 case 0x51 : /* HD DVD-R */
2705 case 0x52 : /* HD DVD-RW; DVD-RAM like */
2706 return MMC_CLASS_DVD
;
2707 case 0x40 : /* BD-ROM */
2708 case 0x41 : /* BD-R Sequential recording (SRM) */
2709 case 0x42 : /* BD-R Ramdom Recording (RRM) */
2710 case 0x43 : /* BD-RE */
2711 return MMC_CLASS_BD
;
2713 return MMC_CLASS_UNKN
;
2718 * Drive/media combination is reflected in a series of features that can
2719 * either be current or dormant. We try to make sense out of them to create a
2720 * set of easy to use flags that abstract the device/media capabilities.
2724 mmc_process_feature(struct mmc_discinfo
*mmc_discinfo
,
2725 uint16_t feature
, int cur
, uint8_t *rpos
)
2727 uint32_t blockingnr
;
2731 flags
= mmc_discinfo
->mmc_cur
;
2733 flags
= mmc_discinfo
->mmc_cap
;
2737 case 0x0010 : /* random readable feature */
2738 blockingnr
= rpos
[5] | (rpos
[4] << 8);
2740 flags
|= MMC_CAP_PACKET
;
2744 case 0x0020 : /* random writable feature */
2745 flags
|= MMC_CAP_RECORDABLE
;
2746 flags
|= MMC_CAP_REWRITABLE
;
2747 blockingnr
= rpos
[9] | (rpos
[8] << 8);
2749 flags
|= MMC_CAP_PACKET
;
2751 case 0x0021 : /* incremental streaming write feature */
2752 flags
|= MMC_CAP_RECORDABLE
;
2753 flags
|= MMC_CAP_SEQUENTIAL
;
2755 mmc_discinfo
->link_block_penalty
= rpos
[4];
2757 flags
|= MMC_CAP_ZEROLINKBLK
;
2759 case 0x0022 : /* (obsolete) erase support feature */
2760 flags
|= MMC_CAP_RECORDABLE
;
2761 flags
|= MMC_CAP_ERASABLE
;
2763 case 0x0023 : /* formatting media support feature */
2764 flags
|= MMC_CAP_RECORDABLE
;
2765 flags
|= MMC_CAP_FORMATTABLE
;
2767 case 0x0024 : /* hardware assised defect management feature */
2768 flags
|= MMC_CAP_HW_DEFECTFREE
;
2770 case 0x0025 : /* write once */
2771 flags
|= MMC_CAP_RECORDABLE
;
2773 case 0x0026 : /* restricted overwrite feature */
2774 flags
|= MMC_CAP_RECORDABLE
;
2775 flags
|= MMC_CAP_REWRITABLE
;
2776 flags
|= MMC_CAP_STRICTOVERWRITE
;
2778 case 0x0028 : /* MRW formatted media support feature */
2779 flags
|= MMC_CAP_MRW
;
2781 case 0x002b : /* DVD+R read (and opt. write) support */
2782 flags
|= MMC_CAP_SEQUENTIAL
;
2783 if (rpos
[0] & 1) /* write support */
2784 flags
|= MMC_CAP_RECORDABLE
;
2786 case 0x002c : /* rigid restricted overwrite feature */
2787 flags
|= MMC_CAP_RECORDABLE
;
2788 flags
|= MMC_CAP_REWRITABLE
;
2789 flags
|= MMC_CAP_STRICTOVERWRITE
;
2790 if (rpos
[0] & 1) /* blank bit */
2791 flags
|= MMC_CAP_BLANKABLE
;
2793 case 0x002d : /* track at once recording feature */
2794 flags
|= MMC_CAP_RECORDABLE
;
2795 flags
|= MMC_CAP_SEQUENTIAL
;
2797 case 0x002f : /* DVD-R/-RW write feature */
2798 flags
|= MMC_CAP_RECORDABLE
;
2799 if (rpos
[0] & 2) /* DVD-RW bit */
2800 flags
|= MMC_CAP_BLANKABLE
;
2802 case 0x0038 : /* BD-R SRM with pseudo overwrite */
2803 flags
|= MMC_CAP_PSEUDOOVERWRITE
;
2811 mmc_discinfo
->mmc_cur
= flags
;
2813 mmc_discinfo
->mmc_cap
= flags
;
2818 mmc_getdiscinfo_cdrom(struct scsipi_periph
*periph
,
2819 struct mmc_discinfo
*mmc_discinfo
)
2821 struct scsipi_read_toc gtoc_cmd
;
2822 struct scsipi_toc_header
*toc_hdr
;
2823 struct scsipi_toc_msinfo
*toc_msinfo
;
2824 const uint32_t buffer_size
= 1024;
2829 buffer
= malloc(buffer_size
, M_TEMP
, M_WAITOK
);
2831 * Fabricate mmc_discinfo for CD-ROM. Some values are really `dont
2832 * care' but others might be of interest to programs.
2835 mmc_discinfo
->disc_state
= MMC_STATE_FULL
;
2836 mmc_discinfo
->last_session_state
= MMC_STATE_FULL
;
2837 mmc_discinfo
->bg_format_state
= MMC_BGFSTATE_COMPLETED
;
2838 mmc_discinfo
->link_block_penalty
= 7; /* not relevant */
2840 /* get number of sessions and first tracknr in last session */
2841 flags
= XS_CTL_DATA_IN
;
2842 memset(>oc_cmd
, 0, sizeof(gtoc_cmd
));
2843 gtoc_cmd
.opcode
= READ_TOC
;
2844 gtoc_cmd
.addr_mode
= CD_MSF
; /* not relevant */
2845 gtoc_cmd
.resp_format
= CD_TOC_MSINFO
; /* multisession info */
2846 gtoc_cmd
.from_track
= 0; /* reserved, must be 0 */
2847 req_size
= sizeof(*toc_hdr
) + sizeof(*toc_msinfo
);
2848 _lto2b(req_size
, gtoc_cmd
.data_len
);
2850 error
= scsipi_command(periph
,
2851 (void *)>oc_cmd
, sizeof(gtoc_cmd
),
2852 (void *)buffer
, req_size
,
2853 CDRETRIES
, 30000, NULL
, flags
);
2856 toc_hdr
= (struct scsipi_toc_header
*) buffer
;
2857 toc_msinfo
= (struct scsipi_toc_msinfo
*) (buffer
+ 4);
2858 mmc_discinfo
->num_sessions
= toc_hdr
->last
- toc_hdr
->first
+ 1;
2859 mmc_discinfo
->first_track
= toc_hdr
->first
;
2860 mmc_discinfo
->first_track_last_session
= toc_msinfo
->tracknr
;
2862 /* get last track of last session */
2863 flags
= XS_CTL_DATA_IN
;
2864 gtoc_cmd
.resp_format
= CD_TOC_FORM
; /* formatted toc */
2865 req_size
= sizeof(*toc_hdr
);
2866 _lto2b(req_size
, gtoc_cmd
.data_len
);
2868 error
= scsipi_command(periph
,
2869 (void *)>oc_cmd
, sizeof(gtoc_cmd
),
2870 (void *)buffer
, req_size
,
2871 CDRETRIES
, 30000, NULL
, flags
);
2874 toc_hdr
= (struct scsipi_toc_header
*) buffer
;
2875 mmc_discinfo
->last_track_last_session
= toc_hdr
->last
;
2876 mmc_discinfo
->num_tracks
= toc_hdr
->last
- toc_hdr
->first
+ 1;
2878 /* TODO how to handle disc_barcode and disc_id */
2882 free(buffer
, M_TEMP
);
2887 mmc_getdiscinfo_dvdrom(struct scsipi_periph
*periph
,
2888 struct mmc_discinfo
*mmc_discinfo
)
2890 struct scsipi_read_toc gtoc_cmd
;
2891 struct scsipi_toc_header toc_hdr
;
2896 * Fabricate mmc_discinfo for DVD-ROM. Some values are really `dont
2897 * care' but others might be of interest to programs.
2900 mmc_discinfo
->disc_state
= MMC_STATE_FULL
;
2901 mmc_discinfo
->last_session_state
= MMC_STATE_FULL
;
2902 mmc_discinfo
->bg_format_state
= MMC_BGFSTATE_COMPLETED
;
2903 mmc_discinfo
->link_block_penalty
= 16; /* not relevant */
2905 /* get number of sessions and first tracknr in last session */
2906 flags
= XS_CTL_DATA_IN
;
2907 memset(>oc_cmd
, 0, sizeof(gtoc_cmd
));
2908 gtoc_cmd
.opcode
= READ_TOC
;
2909 gtoc_cmd
.addr_mode
= 0; /* LBA */
2910 gtoc_cmd
.resp_format
= CD_TOC_FORM
; /* multisession info */
2911 gtoc_cmd
.from_track
= 1; /* first track */
2912 req_size
= sizeof(toc_hdr
);
2913 _lto2b(req_size
, gtoc_cmd
.data_len
);
2915 error
= scsipi_command(periph
,
2916 (void *)>oc_cmd
, sizeof(gtoc_cmd
),
2917 (void *)&toc_hdr
, req_size
,
2918 CDRETRIES
, 30000, NULL
, flags
);
2922 /* DVD-ROM squashes the track/session space */
2923 mmc_discinfo
->num_sessions
= toc_hdr
.last
- toc_hdr
.first
+ 1;
2924 mmc_discinfo
->num_tracks
= mmc_discinfo
->num_sessions
;
2925 mmc_discinfo
->first_track
= toc_hdr
.first
;
2926 mmc_discinfo
->first_track_last_session
= toc_hdr
.last
;
2927 mmc_discinfo
->last_track_last_session
= toc_hdr
.last
;
2929 /* TODO how to handle disc_barcode and disc_id */
2935 mmc_getdiscinfo(struct scsipi_periph
*periph
,
2936 struct mmc_discinfo
*mmc_discinfo
)
2938 struct scsipi_get_configuration gc_cmd
;
2939 struct scsipi_get_conf_data
*gc
;
2940 struct scsipi_get_conf_feature
*gcf
;
2941 struct scsipi_read_discinfo di_cmd
;
2942 struct scsipi_read_discinfo_data di
;
2943 const uint32_t buffer_size
= 1024;
2944 uint32_t feat_tbl_len
, pos
;
2946 uint8_t *buffer
, *fpos
;
2947 int feature
, last_feature
, features_len
, feature_cur
, feature_len
;
2948 int lsb
, msb
, error
, flags
;
2950 feat_tbl_len
= buffer_size
;
2952 buffer
= malloc(buffer_size
, M_TEMP
, M_WAITOK
);
2954 /* initialise structure */
2955 memset(mmc_discinfo
, 0, sizeof(struct mmc_discinfo
));
2956 mmc_discinfo
->mmc_profile
= 0x00; /* unknown */
2957 mmc_discinfo
->mmc_class
= MMC_CLASS_UNKN
;
2958 mmc_discinfo
->mmc_cur
= 0;
2959 mmc_discinfo
->mmc_cap
= 0;
2960 mmc_discinfo
->link_block_penalty
= 0;
2962 /* determine mmc profile and class */
2963 flags
= XS_CTL_DATA_IN
;
2964 memset(&gc_cmd
, 0, sizeof(gc_cmd
));
2965 gc_cmd
.opcode
= GET_CONFIGURATION
;
2966 _lto2b(GET_CONF_NO_FEATURES_LEN
, gc_cmd
.data_len
);
2968 gc
= (struct scsipi_get_conf_data
*) buffer
;
2970 error
= scsipi_command(periph
,
2971 (void *)&gc_cmd
, sizeof(gc_cmd
),
2972 (void *) gc
, GET_CONF_NO_FEATURES_LEN
,
2973 CDRETRIES
, 30000, NULL
, flags
);
2977 mmc_discinfo
->mmc_profile
= _2btol(gc
->mmc_profile
);
2978 mmc_discinfo
->mmc_class
= mmc_profile2class(mmc_discinfo
->mmc_profile
);
2980 /* assume 2048 sector size unless told otherwise */
2981 mmc_discinfo
->sector_size
= 2048;
2982 error
= read_cd_capacity(periph
, &mmc_discinfo
->sector_size
, &last_lba
);
2986 mmc_discinfo
->last_possible_lba
= (uint32_t) last_lba
- 1;
2988 /* Read in all features to determine device capabilities */
2989 last_feature
= feature
= 0;
2991 /* determine mmc profile and class */
2992 flags
= XS_CTL_DATA_IN
;
2993 memset(&gc_cmd
, 0, sizeof(gc_cmd
));
2994 gc_cmd
.opcode
= GET_CONFIGURATION
;
2995 _lto2b(last_feature
, gc_cmd
.start_at_feature
);
2996 _lto2b(feat_tbl_len
, gc_cmd
.data_len
);
2998 error
= scsipi_command(periph
,
2999 (void *)&gc_cmd
, sizeof(gc_cmd
),
3000 (void *) gc
, feat_tbl_len
,
3001 CDRETRIES
, 30000, NULL
, flags
);
3003 /* ieeek... break out of loop... i dunno what to do */
3007 features_len
= _4btol(gc
->data_len
);
3008 if (features_len
< 4)
3012 fpos
= &gc
->feature_desc
[0];
3013 while (pos
< features_len
- 4) {
3014 gcf
= (struct scsipi_get_conf_feature
*) fpos
;
3016 feature
= _2btol(gcf
->featurecode
);
3017 feature_cur
= gcf
->flags
& 1;
3018 feature_len
= gcf
->additional_length
;
3020 mmc_process_feature(mmc_discinfo
,
3021 feature
, feature_cur
,
3022 gcf
->feature_dependent
);
3024 last_feature
= MAX(last_feature
, feature
);
3026 /* assert((feature_len & 3) == 0); */
3027 if ((feature_len
& 3) != 0) {
3028 printf("feature %d having length %d\n",
3029 feature
, feature_len
);
3033 pos
+= 4 + feature_len
;
3034 fpos
+= 4 + feature_len
;
3036 /* unlikely to ever grow past our 1kb buffer */
3037 } while (features_len
>= 0xffff);
3040 * Fixup CD-RW drives that are on crack.
3042 * Some drives report the capability to incrementally write
3043 * sequentially on CD-R(W) media... nice, but this should not be
3044 * active for a fixed packet formatted CD-RW media. Other report the
3045 * ability of HW_DEFECTFREE even when the media is NOT MRW
3048 if (mmc_discinfo
->mmc_profile
== 0x0a) {
3049 if ((mmc_discinfo
->mmc_cur
& MMC_CAP_SEQUENTIAL
) == 0)
3050 mmc_discinfo
->mmc_cur
|= MMC_CAP_STRICTOVERWRITE
;
3051 if (mmc_discinfo
->mmc_cur
& MMC_CAP_STRICTOVERWRITE
)
3052 mmc_discinfo
->mmc_cur
&= ~MMC_CAP_SEQUENTIAL
;
3053 if (mmc_discinfo
->mmc_cur
& MMC_CAP_MRW
) {
3054 mmc_discinfo
->mmc_cur
&= ~MMC_CAP_SEQUENTIAL
;
3055 mmc_discinfo
->mmc_cur
&= ~MMC_CAP_STRICTOVERWRITE
;
3057 mmc_discinfo
->mmc_cur
&= ~MMC_CAP_HW_DEFECTFREE
;
3060 if (mmc_discinfo
->mmc_profile
== 0x09) {
3061 mmc_discinfo
->mmc_cur
&= ~MMC_CAP_REWRITABLE
;
3065 printf("CD mmc %d, mmc_cur 0x%"PRIx64
", mmc_cap 0x%"PRIx64
"\n",
3066 mmc_discinfo
->mmc_profile
,
3067 mmc_discinfo
->mmc_cur
, mmc_discinfo
->mmc_cap
);
3070 /* read in disc state and number of sessions and tracks */
3071 flags
= XS_CTL_DATA_IN
| XS_CTL_SILENT
;
3072 memset(&di_cmd
, 0, sizeof(di_cmd
));
3073 di_cmd
.opcode
= READ_DISCINFO
;
3074 di_cmd
.data_len
[1] = READ_DISCINFO_BIGSIZE
;
3076 error
= scsipi_command(periph
,
3077 (void *)&di_cmd
, sizeof(di_cmd
),
3078 (void *)&di
, READ_DISCINFO_BIGSIZE
,
3079 CDRETRIES
, 30000, NULL
, flags
);
3082 /* discinfo call failed, emulate for cd-rom/dvd-rom */
3083 if (mmc_discinfo
->mmc_profile
== 0x08) /* CD-ROM */
3084 return mmc_getdiscinfo_cdrom(periph
, mmc_discinfo
);
3085 if (mmc_discinfo
->mmc_profile
== 0x10) /* DVD-ROM */
3086 return mmc_getdiscinfo_dvdrom(periph
, mmc_discinfo
);
3087 /* CD/DVD drive is violating specs */
3093 mmc_discinfo
->disc_state
= di
.disc_state
& 3;
3094 mmc_discinfo
->last_session_state
= (di
.disc_state
>> 2) & 3;
3095 mmc_discinfo
->bg_format_state
= (di
.disc_state2
& 3);
3097 lsb
= di
.num_sessions_lsb
;
3098 msb
= di
.num_sessions_msb
;
3099 mmc_discinfo
->num_sessions
= lsb
| (msb
<< 8);
3101 mmc_discinfo
->first_track
= di
.first_track
;
3102 lsb
= di
.first_track_last_session_lsb
;
3103 msb
= di
.first_track_last_session_msb
;
3104 mmc_discinfo
->first_track_last_session
= lsb
| (msb
<< 8);
3105 lsb
= di
.last_track_last_session_lsb
;
3106 msb
= di
.last_track_last_session_msb
;
3107 mmc_discinfo
->last_track_last_session
= lsb
| (msb
<< 8);
3109 mmc_discinfo
->num_tracks
= mmc_discinfo
->last_track_last_session
-
3110 mmc_discinfo
->first_track
+ 1;
3112 /* set misc. flags and parameters from this disc info */
3113 if (di
.disc_state
& 16)
3114 mmc_discinfo
->mmc_cur
|= MMC_CAP_BLANKABLE
;
3116 if (di
.disc_state2
& 128) {
3117 mmc_discinfo
->disc_id
= _4btol(di
.discid
);
3118 mmc_discinfo
->disc_flags
|= MMC_DFLAGS_DISCIDVALID
;
3120 if (di
.disc_state2
& 64) {
3121 mmc_discinfo
->disc_barcode
= _8btol(di
.disc_bar_code
);
3122 mmc_discinfo
->disc_flags
|= MMC_DFLAGS_BARCODEVALID
;
3124 if (di
.disc_state2
& 32)
3125 mmc_discinfo
->disc_flags
|= MMC_DFLAGS_UNRESTRICTED
;
3127 if (di
.disc_state2
& 16) {
3128 mmc_discinfo
->application_code
= di
.application_code
;
3129 mmc_discinfo
->disc_flags
|= MMC_DFLAGS_APPCODEVALID
;
3135 free(buffer
, M_TEMP
);
3140 mmc_gettrackinfo_cdrom(struct scsipi_periph
*periph
,
3141 struct mmc_trackinfo
*trackinfo
)
3143 struct scsipi_read_toc gtoc_cmd
;
3144 struct scsipi_toc_header
*toc_hdr
;
3145 struct scsipi_toc_rawtoc
*rawtoc
;
3146 uint32_t track_start
, track_end
, track_size
;
3147 uint32_t last_recorded
, next_writable
;
3148 uint32_t lba
, next_track_start
, lead_out
;
3149 const uint32_t buffer_size
= 4 * 1024; /* worst case TOC estimate */
3151 uint8_t track_sessionnr
, last_tracknr
, sessionnr
, adr
, tno
, point
;
3152 uint8_t control
, tmin
, tsec
, tframe
, pmin
, psec
, pframe
;
3156 buffer
= malloc(buffer_size
, M_TEMP
, M_WAITOK
);
3159 * Emulate read trackinfo for CD-ROM using the raw-TOC.
3161 * Not all information is present and this presents a problem. Track
3162 * starts are known for each track but other values are deducted.
3164 * For a complete overview of `magic' values used here, see the
3165 * SCSI/ATAPI MMC documentation. Note that the `magic' values have no
3166 * names, they are specified as numbers.
3169 /* get raw toc to process, first header to check size */
3170 flags
= XS_CTL_DATA_IN
| XS_CTL_SILENT
;
3171 memset(>oc_cmd
, 0, sizeof(gtoc_cmd
));
3172 gtoc_cmd
.opcode
= READ_TOC
;
3173 gtoc_cmd
.addr_mode
= CD_MSF
; /* not relevant */
3174 gtoc_cmd
.resp_format
= CD_TOC_RAW
; /* raw toc */
3175 gtoc_cmd
.from_track
= 1; /* first session */
3176 req_size
= sizeof(*toc_hdr
);
3177 _lto2b(req_size
, gtoc_cmd
.data_len
);
3179 error
= scsipi_command(periph
,
3180 (void *)>oc_cmd
, sizeof(gtoc_cmd
),
3181 (void *)buffer
, req_size
,
3182 CDRETRIES
, 30000, NULL
, flags
);
3185 toc_hdr
= (struct scsipi_toc_header
*) buffer
;
3186 if (_2btol(toc_hdr
->length
) > buffer_size
- 2) {
3188 printf("increase buffersize in mmc_readtrackinfo_cdrom\n");
3194 /* read in complete raw toc */
3195 req_size
= _2btol(toc_hdr
->length
);
3196 req_size
= 2*((req_size
+ 1) / 2); /* for ATAPI */
3197 _lto2b(req_size
, gtoc_cmd
.data_len
);
3199 error
= scsipi_command(periph
,
3200 (void *)>oc_cmd
, sizeof(gtoc_cmd
),
3201 (void *)buffer
, req_size
,
3202 CDRETRIES
, 30000, NULL
, flags
);
3206 toc_hdr
= (struct scsipi_toc_header
*) buffer
;
3207 rawtoc
= (struct scsipi_toc_rawtoc
*) (buffer
+ 4);
3217 next_track_start
= 0;
3218 track_sessionnr
= MAXTRACK
; /* by definition */
3221 size
= req_size
- sizeof(struct scsipi_toc_header
) + 1;
3223 /* get track start and session end */
3225 sessionnr
= rawtoc
->sessionnr
;
3226 adr
= rawtoc
->adrcontrol
>> 4;
3227 control
= rawtoc
->adrcontrol
& 0xf;
3228 point
= rawtoc
->point
;
3231 tframe
= rawtoc
->frame
;
3232 pmin
= rawtoc
->pmin
;
3233 psec
= rawtoc
->psec
;
3234 pframe
= rawtoc
->pframe
;
3236 if (tno
== 0 && sessionnr
&& adr
== 1) {
3237 lba
= hmsf2lba(0, pmin
, psec
, pframe
);
3238 if (point
== trackinfo
->tracknr
) {
3240 track_sessionnr
= sessionnr
;
3242 if (point
== trackinfo
->tracknr
+ 1) {
3244 track_size
= lba
- track_start
;
3245 next_track_start
= lba
;
3247 if (point
== 0xa2) {
3250 if (point
<= 0x63) {
3251 /* CD's ok, DVD are glued */
3252 last_tracknr
= point
;
3254 if (sessionnr
== track_sessionnr
) {
3255 last_recorded
= lead_out
;
3258 if (tno
== 0 && sessionnr
&& adr
== 5) {
3259 lba
= hmsf2lba(0, tmin
, tsec
, tframe
);
3260 if (sessionnr
== track_sessionnr
) {
3261 next_writable
= lba
;
3265 if ((control
& (3<<2)) == 4) /* 01xxb */
3266 flags
|= MMC_TRACKINFO_DATA
;
3267 if ((control
& (1<<2)) == 0) { /* x0xxb */
3268 flags
|= MMC_TRACKINFO_AUDIO
;
3269 if (control
& 1) /* xxx1b */
3270 flags
|= MMC_TRACKINFO_PRE_EMPH
;
3274 size
-= sizeof(struct scsipi_toc_rawtoc
);
3277 /* process found values; some voodoo */
3278 /* if no tracksize tracknr is the last of the disc */
3279 if ((track_size
== 0) && last_recorded
) {
3280 track_size
= last_recorded
- track_start
;
3282 /* if last_recorded < tracksize, tracksize is overestimated */
3283 if (last_recorded
) {
3284 if (last_recorded
- track_start
<= track_size
) {
3285 track_size
= last_recorded
- track_start
;
3286 flags
|= MMC_TRACKINFO_LRA_VALID
;
3289 /* check if its a the last track of the sector */
3290 if (next_writable
) {
3291 if (next_track_start
> next_writable
)
3292 flags
|= MMC_TRACKINFO_NWA_VALID
;
3295 /* no flag set -> no values */
3296 if ((flags
& MMC_TRACKINFO_LRA_VALID
) == 0)
3298 if ((flags
& MMC_TRACKINFO_NWA_VALID
) == 0)
3302 /* trackinfo->tracknr preserved */
3303 trackinfo
->sessionnr
= track_sessionnr
;
3304 trackinfo
->track_mode
= 7; /* data, incremental */
3305 trackinfo
->data_mode
= 8; /* 2048 bytes mode1 */
3307 trackinfo
->flags
= flags
;
3308 trackinfo
->track_start
= track_start
;
3309 trackinfo
->next_writable
= next_writable
;
3310 trackinfo
->free_blocks
= 0;
3311 trackinfo
->packet_size
= 1;
3312 trackinfo
->track_size
= track_size
;
3313 trackinfo
->last_recorded
= last_recorded
;
3316 free(buffer
, M_TEMP
);
3322 mmc_gettrackinfo_dvdrom(struct scsipi_periph
*periph
,
3323 struct mmc_trackinfo
*trackinfo
)
3325 struct scsipi_read_toc gtoc_cmd
;
3326 struct scsipi_toc_header
*toc_hdr
;
3327 struct scsipi_toc_formatted
*toc
;
3328 uint32_t tracknr
, track_start
, track_size
;
3329 uint32_t lba
, lead_out
;
3330 const uint32_t buffer_size
= 4 * 1024; /* worst case TOC estimate */
3332 uint8_t control
, last_tracknr
;
3337 buffer
= malloc(buffer_size
, M_TEMP
, M_WAITOK
);
3339 * Emulate read trackinfo for DVD-ROM. We can't use the raw-TOC as the
3340 * CD-ROM emulation uses since the specification tells us that no such
3341 * thing is defined for DVD's. The reason for this is due to the large
3342 * number of tracks and that would clash with the `magic' values. This
3345 * Not all information is present and this presents a problem.
3346 * Track starts are known for each track but other values are
3350 /* get formatted toc to process, first header to check size */
3351 flags
= XS_CTL_DATA_IN
| XS_CTL_SILENT
;
3352 memset(>oc_cmd
, 0, sizeof(gtoc_cmd
));
3353 gtoc_cmd
.opcode
= READ_TOC
;
3354 gtoc_cmd
.addr_mode
= 0; /* lba's please */
3355 gtoc_cmd
.resp_format
= CD_TOC_FORM
; /* formatted toc */
3356 gtoc_cmd
.from_track
= 1; /* first track */
3357 req_size
= sizeof(*toc_hdr
);
3358 _lto2b(req_size
, gtoc_cmd
.data_len
);
3360 error
= scsipi_command(periph
,
3361 (void *)>oc_cmd
, sizeof(gtoc_cmd
),
3362 (void *)buffer
, req_size
,
3363 CDRETRIES
, 30000, NULL
, flags
);
3366 toc_hdr
= (struct scsipi_toc_header
*) buffer
;
3367 if (_2btol(toc_hdr
->length
) > buffer_size
- 2) {
3369 printf("incease buffersize in mmc_readtrackinfo_dvdrom\n");
3375 /* read in complete formatted toc */
3376 req_size
= _2btol(toc_hdr
->length
);
3377 _lto2b(req_size
, gtoc_cmd
.data_len
);
3379 error
= scsipi_command(periph
,
3380 (void *)>oc_cmd
, sizeof(gtoc_cmd
),
3381 (void *)buffer
, req_size
,
3382 CDRETRIES
, 30000, NULL
, flags
);
3386 toc_hdr
= (struct scsipi_toc_header
*) buffer
;
3387 toc
= (struct scsipi_toc_formatted
*) (buffer
+ 4);
3389 /* as in read disc info, all sessions are converted to tracks */
3390 /* track 1.. -> offsets, sizes can be (rougly) estimated (16 ECC) */
3391 /* last track -> we got the size from the lead-out */
3394 last_tracknr
= toc_hdr
->last
;
3400 size
= req_size
- sizeof(struct scsipi_toc_header
) + 1;
3402 /* remember, DVD-ROM: tracknr == sessionnr */
3403 lba
= _4btol(toc
->msf_lba
);
3404 tracknr
= toc
->tracknr
;
3405 control
= toc
->adrcontrol
& 0xf;
3407 if (trackinfo
->tracknr
== tracknr
) {
3410 if (trackinfo
->tracknr
== tracknr
+1) {
3411 track_size
= lba
- track_start
;
3412 track_size
-= 16; /* link block ? */
3414 if (tracknr
== 0xAA) {
3418 if ((control
& (3<<2)) == 4) /* 01xxb */
3419 flags
|= MMC_TRACKINFO_DATA
;
3420 if ((control
& (1<<2)) == 0) { /* x0xxb */
3421 flags
|= MMC_TRACKINFO_AUDIO
;
3422 if (control
& (1<<3)) /* 10xxb */
3423 flags
|= MMC_TRACKINFO_AUDIO_4CHAN
;
3424 if (control
& 1) /* xxx1b */
3425 flags
|= MMC_TRACKINFO_PRE_EMPH
;
3429 size
-= sizeof(struct scsipi_toc_formatted
);
3431 if (trackinfo
->tracknr
== last_tracknr
) {
3432 track_size
= lead_out
- track_start
;
3436 /* trackinfo->tracknr preserved */
3437 trackinfo
->sessionnr
= trackinfo
->tracknr
;
3438 trackinfo
->track_mode
= 0; /* unknown */
3439 trackinfo
->data_mode
= 8; /* 2048 bytes mode1 */
3441 trackinfo
->flags
= flags
;
3442 trackinfo
->track_start
= track_start
;
3443 trackinfo
->next_writable
= 0;
3444 trackinfo
->free_blocks
= 0;
3445 trackinfo
->packet_size
= 16; /* standard length 16 blocks ECC */
3446 trackinfo
->track_size
= track_size
;
3447 trackinfo
->last_recorded
= 0;
3450 free(buffer
, M_TEMP
);
3455 mmc_gettrackinfo(struct scsipi_periph
*periph
,
3456 struct mmc_trackinfo
*trackinfo
)
3458 struct scsipi_read_trackinfo ti_cmd
;
3459 struct scsipi_read_trackinfo_data ti
;
3460 struct scsipi_get_configuration gc_cmd
;
3461 struct scsipi_get_conf_data gc
;
3465 /* set up SCSI call with track number from trackinfo.tracknr */
3466 flags
= XS_CTL_DATA_IN
| XS_CTL_SILENT
;
3467 memset(&ti_cmd
, 0, sizeof(ti_cmd
));
3468 ti_cmd
.opcode
= READ_TRACKINFO
;
3469 ti_cmd
.addr_type
= READ_TRACKINFO_ADDR_TRACK
;
3470 ti_cmd
.data_len
[1] = READ_TRACKINFO_RETURNSIZE
;
3472 /* trackinfo.tracknr contains number of tracks to query */
3473 _lto4b(trackinfo
->tracknr
, ti_cmd
.address
);
3474 error
= scsipi_command(periph
,
3475 (void *)&ti_cmd
, sizeof(ti_cmd
),
3476 (void *)&ti
, READ_TRACKINFO_RETURNSIZE
,
3477 CDRETRIES
, 30000, NULL
, flags
);
3480 /* trackinfo call failed, emulate for cd-rom/dvd-rom */
3481 /* first determine mmc profile */
3482 flags
= XS_CTL_DATA_IN
;
3483 memset(&gc_cmd
, 0, sizeof(gc_cmd
));
3484 gc_cmd
.opcode
= GET_CONFIGURATION
;
3485 _lto2b(GET_CONF_NO_FEATURES_LEN
, gc_cmd
.data_len
);
3487 error
= scsipi_command(periph
,
3488 (void *)&gc_cmd
, sizeof(gc_cmd
),
3489 (void *)&gc
, GET_CONF_NO_FEATURES_LEN
,
3490 CDRETRIES
, 30000, NULL
, flags
);
3493 mmc_profile
= _2btol(gc
.mmc_profile
);
3495 /* choose emulation */
3496 if (mmc_profile
== 0x08) /* CD-ROM */
3497 return mmc_gettrackinfo_cdrom(periph
, trackinfo
);
3498 if (mmc_profile
== 0x10) /* DVD-ROM */
3499 return mmc_gettrackinfo_dvdrom(periph
, trackinfo
);
3500 /* CD/DVD drive is violating specs */
3504 /* (re)initialise structure */
3505 memset(trackinfo
, 0, sizeof(struct mmc_trackinfo
));
3507 /* account for short returns screwing up track and session msb */
3508 if ((ti
.data_len
[1] | (ti
.data_len
[0] << 8)) <= 32) {
3513 trackinfo
->tracknr
= ti
.track_lsb
| (ti
.track_msb
<< 8);
3514 trackinfo
->sessionnr
= ti
.session_lsb
| (ti
.session_msb
<< 8);
3515 trackinfo
->track_mode
= ti
.track_info_1
& 0xf;
3516 trackinfo
->data_mode
= ti
.track_info_2
& 0xf;
3519 if (ti
.track_info_1
& 0x10)
3520 flags
|= MMC_TRACKINFO_COPY
;
3521 if (ti
.track_info_1
& 0x20)
3522 flags
|= MMC_TRACKINFO_DAMAGED
;
3523 if (ti
.track_info_2
& 0x10)
3524 flags
|= MMC_TRACKINFO_FIXED_PACKET
;
3525 if (ti
.track_info_2
& 0x20)
3526 flags
|= MMC_TRACKINFO_INCREMENTAL
;
3527 if (ti
.track_info_2
& 0x40)
3528 flags
|= MMC_TRACKINFO_BLANK
;
3529 if (ti
.track_info_2
& 0x80)
3530 flags
|= MMC_TRACKINFO_RESERVED
;
3531 if (ti
.data_valid
& 0x01)
3532 flags
|= MMC_TRACKINFO_NWA_VALID
;
3533 if (ti
.data_valid
& 0x02)
3534 flags
|= MMC_TRACKINFO_LRA_VALID
;
3535 if ((trackinfo
->track_mode
& (3<<2)) == 4) /* 01xxb */
3536 flags
|= MMC_TRACKINFO_DATA
;
3537 if ((trackinfo
->track_mode
& (1<<2)) == 0) { /* x0xxb */
3538 flags
|= MMC_TRACKINFO_AUDIO
;
3539 if (trackinfo
->track_mode
& (1<<3)) /* 10xxb */
3540 flags
|= MMC_TRACKINFO_AUDIO_4CHAN
;
3541 if (trackinfo
->track_mode
& 1) /* xxx1b */
3542 flags
|= MMC_TRACKINFO_PRE_EMPH
;
3545 trackinfo
->flags
= flags
;
3546 trackinfo
->track_start
= _4btol(ti
.track_start
);
3547 trackinfo
->next_writable
= _4btol(ti
.next_writable
);
3548 trackinfo
->free_blocks
= _4btol(ti
.free_blocks
);
3549 trackinfo
->packet_size
= _4btol(ti
.packet_size
);
3550 trackinfo
->track_size
= _4btol(ti
.track_size
);
3551 trackinfo
->last_recorded
= _4btol(ti
.last_recorded
);
3557 mmc_doclose(struct scsipi_periph
*periph
, int param
, int func
) {
3558 struct scsipi_close_tracksession close_cmd
;
3561 /* set up SCSI call with track number */
3562 flags
= XS_CTL_DATA_OUT
;
3563 memset(&close_cmd
, 0, sizeof(close_cmd
));
3564 close_cmd
.opcode
= CLOSE_TRACKSESSION
;
3565 close_cmd
.function
= func
;
3566 _lto2b(param
, close_cmd
.tracksessionnr
);
3568 error
= scsipi_command(periph
,
3569 (void *) &close_cmd
, sizeof(close_cmd
),
3571 CDRETRIES
, 120000, NULL
, flags
);
3577 mmc_do_closetrack(struct scsipi_periph
*periph
, struct mmc_op
*mmc_op
)
3579 int mmc_profile
= mmc_op
->mmc_profile
;
3581 switch (mmc_profile
) {
3582 case 0x12 : /* DVD-RAM */
3583 case 0x1a : /* DVD+RW */
3584 case 0x2a : /* DVD+RW Dual layer */
3585 case 0x42 : /* BD-R Ramdom Recording (RRM) */
3586 case 0x43 : /* BD-RE */
3587 case 0x52 : /* HD DVD-RW ; DVD-RAM like */
3591 return mmc_doclose(periph
, mmc_op
->tracknr
, 1);
3595 mmc_do_close_or_finalise(struct scsipi_periph
*periph
, struct mmc_op
*mmc_op
)
3597 uint8_t blob
[MS5LEN
], *page5
;
3598 int mmc_profile
= mmc_op
->mmc_profile
;
3599 int func
, close
, flags
;
3602 close
= (mmc_op
->operation
== MMC_OP_CLOSESESSION
);
3604 switch (mmc_profile
) {
3605 case 0x09 : /* CD-R */
3606 case 0x0a : /* CD-RW */
3607 /* Special case : need to update MS field in mode page 5 */
3608 memset(blob
, 0, sizeof(blob
));
3611 flags
= XS_CTL_DATA_IN
;
3612 error
= scsipi_mode_sense_big(periph
, SMS_PF
, 5,
3613 (void *)blob
, sizeof(blob
), flags
, CDRETRIES
, 20000);
3617 /* set multi session field when closing a session only */
3622 flags
= XS_CTL_DATA_OUT
;
3623 error
= scsipi_mode_select_big(periph
, SMS_PF
,
3624 (void *)blob
, sizeof(blob
), flags
, CDRETRIES
, 20000);
3627 /* and use funtion 2 */
3630 case 0x11 : /* DVD-R (DL) */
3631 case 0x13 : /* DVD-RW restricted overwrite */
3632 case 0x14 : /* DVD-RW sequential */
3633 func
= close
? 2 : 3;
3635 case 0x1b : /* DVD+R */
3636 case 0x2b : /* DVD+R Dual layer */
3637 case 0x51 : /* HD DVD-R */
3638 case 0x41 : /* BD-R Sequential recording (SRM) */
3639 func
= close
? 2 : 6;
3641 case 0x12 : /* DVD-RAM */
3642 case 0x1a : /* DVD+RW */
3643 case 0x2a : /* DVD+RW Dual layer */
3644 case 0x42 : /* BD-R Ramdom Recording (RRM) */
3645 case 0x43 : /* BD-RE */
3646 case 0x52 : /* HD DVD-RW; DVD-RAM like */
3649 printf("MMC close/finalise passed wrong device type! (%d)\n",
3654 return mmc_doclose(periph
, mmc_op
->sessionnr
, func
);
3658 mmc_do_reserve_track(struct scsipi_periph
*periph
, struct mmc_op
*mmc_op
)
3660 struct scsipi_reserve_track reserve_cmd
;
3664 /* TODO make mmc safeguards? */
3665 extent
= mmc_op
->extent
;
3666 /* TODO min/max support? */
3668 /* set up SCSI call with requested space */
3669 flags
= XS_CTL_DATA_OUT
;
3670 memset(&reserve_cmd
, 0, sizeof(reserve_cmd
));
3671 reserve_cmd
.opcode
= RESERVE_TRACK
;
3672 _lto4b(extent
, reserve_cmd
.reservation_size
);
3674 error
= scsipi_command(periph
,
3675 (void *) &reserve_cmd
, sizeof(reserve_cmd
),
3677 CDRETRIES
, 30000, NULL
, flags
);
3683 mmc_do_reserve_track_nwa(struct scsipi_periph
*periph
, struct mmc_op
*mmc_op
)
3685 /* XXX assumes that NWA given is valid */
3686 switch (mmc_op
->mmc_profile
) {
3687 case 0x09 : /* CD-R */
3688 /* XXX unknown boundary checks XXX */
3689 if (mmc_op
->extent
<= 152)
3691 /* CD-R takes 152 sectors to close track */
3692 mmc_op
->extent
-= 152;
3693 return mmc_do_reserve_track(periph
, mmc_op
);
3694 case 0x11 : /* DVD-R (DL) */
3695 case 0x1b : /* DVD+R */
3696 case 0x2b : /* DVD+R Dual layer */
3697 if (mmc_op
->extent
% 16)
3699 /* upto one ECC block of 16 sectors lost */
3700 mmc_op
->extent
-= 16;
3701 return mmc_do_reserve_track(periph
, mmc_op
);
3702 case 0x41 : /* BD-R Sequential recording (SRM) */
3703 case 0x51 : /* HD DVD-R */
3704 if (mmc_op
->extent
% 32)
3706 /* one ECC block of 32 sectors lost (AFAIK) */
3707 mmc_op
->extent
-= 32;
3708 return mmc_do_reserve_track(periph
, mmc_op
);
3711 /* unknown behaviour or invalid disc type */
3716 mmc_do_repair_track(struct scsipi_periph
*periph
, struct mmc_op
*mmc_op
)
3718 struct scsipi_repair_track repair_cmd
;
3721 /* TODO make mmc safeguards? */
3723 /* set up SCSI call with track number */
3724 flags
= XS_CTL_DATA_OUT
;
3725 memset(&repair_cmd
, 0, sizeof(repair_cmd
));
3726 repair_cmd
.opcode
= REPAIR_TRACK
;
3727 _lto2b(mmc_op
->tracknr
, repair_cmd
.tracknr
);
3729 error
= scsipi_command(periph
,
3730 (void *) &repair_cmd
, sizeof(repair_cmd
),
3732 CDRETRIES
, 30000, NULL
, flags
);
3738 mmc_do_op(struct scsipi_periph
*periph
, struct mmc_op
*mmc_op
)
3740 /* guard operation value */
3741 if (mmc_op
->operation
< 1 || mmc_op
->operation
> MMC_OP_MAX
)
3744 /* synchronise cache is special since it doesn't rely on mmc_profile */
3745 if (mmc_op
->operation
== MMC_OP_SYNCHRONISECACHE
)
3746 return cdcachesync(periph
, 0);
3748 /* zero mmc_profile means unknown disc so operations are not defined */
3749 if (mmc_op
->mmc_profile
== 0) {
3751 printf("mmc_do_op called with mmc_profile = 0\n");
3756 /* do the operations */
3757 switch (mmc_op
->operation
) {
3758 case MMC_OP_CLOSETRACK
:
3759 return mmc_do_closetrack(periph
, mmc_op
);
3760 case MMC_OP_CLOSESESSION
:
3761 case MMC_OP_FINALISEDISC
:
3762 return mmc_do_close_or_finalise(periph
, mmc_op
);
3763 case MMC_OP_RESERVETRACK
:
3764 return mmc_do_reserve_track(periph
, mmc_op
);
3765 case MMC_OP_RESERVETRACK_NWA
:
3766 return mmc_do_reserve_track_nwa(periph
, mmc_op
);
3767 case MMC_OP_REPAIRTRACK
:
3768 return mmc_do_repair_track(periph
, mmc_op
);
3769 case MMC_OP_UNCLOSELASTSESSION
:
3770 /* TODO unclose last session support */
3773 printf("mmc_do_op: unhandled operation %d\n", mmc_op
->operation
);
3780 mmc_setup_writeparams(struct scsipi_periph
*periph
,
3781 struct mmc_writeparams
*mmc_writeparams
)
3783 struct mmc_trackinfo trackinfo
;
3784 uint8_t blob
[MS5LEN
];
3787 int track_mode
, data_mode
;
3789 /* setup mode page 5 for CD only */
3790 if (mmc_writeparams
->mmc_class
!= MMC_CLASS_CD
)
3793 memset(blob
, 0, sizeof(blob
));
3796 /* read mode page 5 (with header) */
3797 flags
= XS_CTL_DATA_IN
;
3798 error
= scsipi_mode_sense_big(periph
, SMS_PF
, 5, (void *)blob
,
3799 sizeof(blob
), flags
, CDRETRIES
, 20000);
3803 /* set page length for reasurance */
3804 page5
[1] = P5LEN
; /* page length */
3806 /* write type packet/incremental */
3809 /* set specified mode parameters */
3810 track_mode
= mmc_writeparams
->track_mode
;
3811 data_mode
= mmc_writeparams
->data_mode
;
3812 if (track_mode
<= 0 || track_mode
> 15)
3814 if (data_mode
< 1 || data_mode
> 2)
3817 /* if a tracknr is passed, setup according to the track */
3818 if (mmc_writeparams
->tracknr
> 0) {
3819 trackinfo
.tracknr
= mmc_writeparams
->tracknr
;
3820 error
= mmc_gettrackinfo(periph
, &trackinfo
);
3823 if ((trackinfo
.flags
& MMC_TRACKINFO_BLANK
) == 0) {
3824 track_mode
= trackinfo
.track_mode
;
3825 data_mode
= trackinfo
.data_mode
;
3827 mmc_writeparams
->blockingnr
= trackinfo
.packet_size
;
3830 /* copy track mode and data mode from trackinfo */
3831 page5
[3] &= 16; /* keep only `Copy' bit */
3832 page5
[3] |= (3 << 6) | track_mode
;
3833 page5
[4] &= 0xf0; /* wipe data block type */
3834 if (data_mode
== 1) {
3835 /* select ISO mode 1 (CD only) */
3837 /* select session format normal disc (CD only) */
3840 /* select ISO mode 2; XA form 1 (CD only) */
3842 /* select session format CD-ROM XA disc (CD only) */
3845 if (mmc_writeparams
->mmc_cur
& MMC_CAP_SEQUENTIAL
) {
3846 if (mmc_writeparams
->mmc_cur
& MMC_CAP_ZEROLINKBLK
) {
3847 /* set BUFE buffer underrun protection */
3850 /* allow for multi session */
3853 /* select fixed packets */
3855 _lto4b(mmc_writeparams
->blockingnr
, &(page5
[10]));
3858 /* write out updated mode page 5 (with header) */
3859 flags
= XS_CTL_DATA_OUT
;
3860 error
= scsipi_mode_select_big(periph
, SMS_PF
, (void *)blob
,
3861 sizeof(blob
), flags
, CDRETRIES
, 20000);
3869 cd_set_properties(struct cd_softc
*cd
)
3871 prop_dictionary_t disk_info
, odisk_info
, geom
;
3873 disk_info
= prop_dictionary_create();
3875 geom
= prop_dictionary_create();
3877 prop_dictionary_set_uint64(geom
, "sectors-per-unit",
3878 cd
->params
.disksize
);
3880 prop_dictionary_set_uint32(geom
, "sector-size",
3881 cd
->params
.blksize
);
3883 prop_dictionary_set(disk_info
, "geometry", geom
);
3884 prop_object_release(geom
);
3886 prop_dictionary_set(device_properties(cd
->sc_dev
),
3887 "disk-info", disk_info
);
3890 * Don't release disk_info here; we keep a reference to it.
3891 * disk_detach() will release it when we go away.
3894 odisk_info
= cd
->sc_dk
.dk_info
;
3895 cd
->sc_dk
.dk_info
= disk_info
;
3897 prop_object_release(odisk_info
);