Line data Source code
1 : /* $OpenBSD: cd.c,v 1.222 2017/12/30 23:08:29 guenther Exp $ */
2 : /* $NetBSD: cd.c,v 1.100 1997/04/02 02:29:30 mycroft Exp $ */
3 :
4 : /*
5 : * Copyright (c) 1994, 1995, 1997 Charles M. Hannum. All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : * 3. All advertising materials mentioning features or use of this software
16 : * must display the following acknowledgement:
17 : * This product includes software developed by Charles M. Hannum.
18 : * 4. The name of the author may not be used to endorse or promote products
19 : * derived from this software without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : */
32 :
33 : /*
34 : * Originally written by Julian Elischer (julian@tfs.com)
35 : * for TRW Financial Systems for use under the MACH(2.5) operating system.
36 : *
37 : * TRW Financial Systems, in accordance with their agreement with Carnegie
38 : * Mellon University, makes this software available to CMU to distribute
39 : * or use in any manner that they see fit as long as this message is kept with
40 : * the software. For this reason TFS also grants any other persons or
41 : * organisations permission to use or modify this software.
42 : *
43 : * TFS supplies this software to be publicly redistributed
44 : * on the understanding that TFS is not responsible for the correct
45 : * functioning of this software in any circumstances.
46 : *
47 : * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
48 : */
49 :
50 : #include <sys/param.h>
51 : #include <sys/systm.h>
52 : #include <sys/timeout.h>
53 : #include <sys/fcntl.h>
54 : #include <sys/stat.h>
55 : #include <sys/ioctl.h>
56 : #include <sys/mtio.h>
57 : #include <sys/buf.h>
58 : #include <sys/uio.h>
59 : #include <sys/malloc.h>
60 : #include <sys/pool.h>
61 : #include <sys/errno.h>
62 : #include <sys/device.h>
63 : #include <sys/disklabel.h>
64 : #include <sys/disk.h>
65 : #include <sys/cdio.h>
66 : #include <sys/conf.h>
67 : #include <sys/scsiio.h>
68 : #include <sys/dkio.h>
69 : #include <sys/vnode.h>
70 :
71 : #include <scsi/scsi_all.h>
72 : #include <scsi/cd.h>
73 : #include <scsi/scsi_disk.h> /* rw_big and start_stop come from there */
74 : #include <scsi/scsiconf.h>
75 :
76 :
77 : #include <ufs/ffs/fs.h> /* for BBSIZE and SBSIZE */
78 :
79 : #define CDOUTSTANDING 4
80 :
81 : #define MAXTRACK 99
82 : #define CD_FRAMES 75
83 : #define CD_SECS 60
84 :
85 : struct cd_toc {
86 : struct ioc_toc_header header;
87 : struct cd_toc_entry entries[MAXTRACK+1]; /* One extra for the */
88 : /* leadout */
89 : };
90 :
91 : int cdmatch(struct device *, void *, void *);
92 : void cdattach(struct device *, struct device *, void *);
93 : int cdactivate(struct device *, int);
94 : int cddetach(struct device *, int);
95 :
96 : struct cd_softc {
97 : struct device sc_dev;
98 : struct disk sc_dk;
99 :
100 : int sc_flags;
101 : #define CDF_ANCIENT 0x10 /* disk is ancient; for minphys */
102 : #define CDF_DYING 0x40 /* dying, when deactivated */
103 : #define CDF_WAITING 0x100
104 : struct scsi_link *sc_link; /* contains our targ, lun, etc. */
105 : struct cd_parms {
106 : u_int32_t secsize;
107 : u_int64_t disksize; /* total number sectors */
108 : } params;
109 : struct bufq sc_bufq;
110 : struct scsi_xshandler sc_xsh;
111 : struct timeout sc_timeout;
112 : };
113 :
114 : void cdstart(struct scsi_xfer *);
115 : void cd_buf_done(struct scsi_xfer *);
116 : void cdminphys(struct buf *);
117 : int cdgetdisklabel(dev_t, struct cd_softc *, struct disklabel *, int);
118 : int cd_setchan(struct cd_softc *, int, int, int, int, int);
119 : int cd_getvol(struct cd_softc *cd, struct ioc_vol *, int);
120 : int cd_setvol(struct cd_softc *, const struct ioc_vol *, int);
121 : int cd_load_unload(struct cd_softc *, int, int);
122 : int cd_set_pa_immed(struct cd_softc *, int);
123 : int cd_play(struct cd_softc *, int, int);
124 : int cd_play_tracks(struct cd_softc *, int, int, int, int);
125 : int cd_play_msf(struct cd_softc *, int, int, int, int, int, int);
126 : int cd_pause(struct cd_softc *, int);
127 : int cd_reset(struct cd_softc *);
128 : int cd_read_subchannel(struct cd_softc *, int, int, int,
129 : struct cd_sub_channel_info *, int );
130 : int cd_read_toc(struct cd_softc *, int, int, void *, int, int);
131 : int cd_get_parms(struct cd_softc *, int);
132 : int cd_load_toc(struct cd_softc *, struct cd_toc *, int);
133 : int cd_interpret_sense(struct scsi_xfer *);
134 : u_int64_t cd_size(struct scsi_link *, int, u_int32_t *);
135 :
136 : int dvd_auth(struct cd_softc *, union dvd_authinfo *);
137 : int dvd_read_physical(struct cd_softc *, union dvd_struct *);
138 : int dvd_read_copyright(struct cd_softc *, union dvd_struct *);
139 : int dvd_read_disckey(struct cd_softc *, union dvd_struct *);
140 : int dvd_read_bca(struct cd_softc *, union dvd_struct *);
141 : int dvd_read_manufact(struct cd_softc *, union dvd_struct *);
142 : int dvd_read_struct(struct cd_softc *, union dvd_struct *);
143 :
144 : #if defined(__macppc__)
145 : int cd_eject(void);
146 : #endif
147 :
148 : struct cfattach cd_ca = {
149 : sizeof(struct cd_softc), cdmatch, cdattach,
150 : cddetach, cdactivate
151 : };
152 :
153 : struct cfdriver cd_cd = {
154 : NULL, "cd", DV_DISK
155 : };
156 :
157 : const struct scsi_inquiry_pattern cd_patterns[] = {
158 : {T_CDROM, T_REMOV,
159 : "", "", ""},
160 : {T_CDROM, T_FIXED,
161 : "", "", ""},
162 : {T_WORM, T_REMOV,
163 : "", "", ""},
164 : {T_WORM, T_FIXED,
165 : "", "", ""},
166 : {T_DIRECT, T_REMOV,
167 : "NEC CD-ROM DRIVE:260", "", ""},
168 : #if 0
169 : {T_CDROM, T_REMOV, /* more luns */
170 : "PIONEER ", "CD-ROM DRM-600 ", ""},
171 : #endif
172 : };
173 :
174 : #define cdlookup(unit) (struct cd_softc *)disk_lookup(&cd_cd, (unit))
175 :
176 : int
177 0 : cdmatch(struct device *parent, void *match, void *aux)
178 : {
179 0 : struct scsi_attach_args *sa = aux;
180 0 : int priority;
181 :
182 0 : scsi_inqmatch(sa->sa_inqbuf, cd_patterns, nitems(cd_patterns),
183 : sizeof(cd_patterns[0]), &priority);
184 :
185 0 : return (priority);
186 0 : }
187 :
188 : /*
189 : * The routine called by the low level scsi routine when it discovers
190 : * A device suitable for this driver
191 : */
192 : void
193 0 : cdattach(struct device *parent, struct device *self, void *aux)
194 : {
195 0 : struct cd_softc *sc = (struct cd_softc *)self;
196 0 : struct scsi_attach_args *sa = aux;
197 0 : struct scsi_link *link = sa->sa_sc_link;
198 :
199 : SC_DEBUG(link, SDEV_DB2, ("cdattach:\n"));
200 :
201 : /*
202 : * Store information needed to contact our base driver
203 : */
204 0 : sc->sc_link = link;
205 0 : link->interpret_sense = cd_interpret_sense;
206 0 : link->device_softc = sc;
207 0 : if (link->openings > CDOUTSTANDING)
208 0 : link->openings = CDOUTSTANDING;
209 :
210 : /*
211 : * Initialize disk structures.
212 : */
213 0 : sc->sc_dk.dk_name = sc->sc_dev.dv_xname;
214 0 : bufq_init(&sc->sc_bufq, BUFQ_DEFAULT);
215 :
216 : /*
217 : * Note if this device is ancient. This is used in cdminphys().
218 : */
219 0 : if (!(link->flags & SDEV_ATAPI) &&
220 0 : SCSISPC(sa->sa_inqbuf->version) == 0)
221 0 : sc->sc_flags |= CDF_ANCIENT;
222 :
223 0 : printf("\n");
224 :
225 0 : scsi_xsh_set(&sc->sc_xsh, link, cdstart);
226 0 : timeout_set(&sc->sc_timeout, (void (*)(void *))scsi_xsh_add,
227 0 : &sc->sc_xsh);
228 :
229 : /* Attach disk. */
230 0 : sc->sc_dk.dk_flags = DKF_NOLABELREAD;
231 0 : disk_attach(&sc->sc_dev, &sc->sc_dk);
232 0 : }
233 :
234 :
235 : int
236 0 : cdactivate(struct device *self, int act)
237 : {
238 0 : struct cd_softc *sc = (struct cd_softc *)self;
239 : int rv = 0;
240 :
241 0 : switch (act) {
242 : case DVACT_RESUME:
243 : /*
244 : * When resuming, hardware may have forgotten we locked it. So if
245 : * there are any open partitions, lock the CD.
246 : */
247 0 : if (sc->sc_dk.dk_openmask != 0)
248 0 : scsi_prevent(sc->sc_link, PR_PREVENT,
249 : SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE |
250 : SCSI_SILENT | SCSI_AUTOCONF);
251 : break;
252 : case DVACT_DEACTIVATE:
253 0 : sc->sc_flags |= CDF_DYING;
254 0 : scsi_xsh_del(&sc->sc_xsh);
255 0 : break;
256 : }
257 0 : return (rv);
258 : }
259 :
260 : int
261 0 : cddetach(struct device *self, int flags)
262 : {
263 0 : struct cd_softc *sc = (struct cd_softc *)self;
264 :
265 0 : bufq_drain(&sc->sc_bufq);
266 :
267 0 : disk_gone(cdopen, self->dv_unit);
268 :
269 : /* Detach disk. */
270 0 : bufq_destroy(&sc->sc_bufq);
271 0 : disk_detach(&sc->sc_dk);
272 :
273 0 : return (0);
274 : }
275 :
276 : /*
277 : * Open the device. Make sure the partition info is as up-to-date as can be.
278 : */
279 : int
280 0 : cdopen(dev_t dev, int flag, int fmt, struct proc *p)
281 : {
282 : struct scsi_link *link;
283 : struct cd_softc *sc;
284 : int error = 0, part, rawopen, unit;
285 :
286 0 : unit = DISKUNIT(dev);
287 0 : part = DISKPART(dev);
288 :
289 0 : rawopen = (part == RAW_PART) && (fmt == S_IFCHR);
290 :
291 0 : sc = cdlookup(unit);
292 0 : if (sc == NULL)
293 0 : return (ENXIO);
294 0 : if (sc->sc_flags & CDF_DYING) {
295 0 : device_unref(&sc->sc_dev);
296 0 : return (ENXIO);
297 : }
298 :
299 0 : link = sc->sc_link;
300 : SC_DEBUG(link, SDEV_DB1,
301 : ("cdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit,
302 : cd_cd.cd_ndevs, part));
303 :
304 0 : if ((error = disk_lock(&sc->sc_dk)) != 0) {
305 0 : device_unref(&sc->sc_dev);
306 0 : return (error);
307 : }
308 :
309 0 : if (sc->sc_dk.dk_openmask != 0) {
310 : /*
311 : * If any partition is open, but the disk has been invalidated,
312 : * disallow further opens.
313 : */
314 0 : if ((link->flags & SDEV_MEDIA_LOADED) == 0) {
315 : if (rawopen)
316 : goto out;
317 : error = EIO;
318 0 : goto bad;
319 : }
320 : } else {
321 : /*
322 : * Check that it is still responding and ok. Drive can be in
323 : * progress of loading media so use increased retries number
324 : * and don't ignore NOT_READY.
325 : */
326 :
327 : /* Use cd_interpret_sense() now. */
328 0 : link->flags |= SDEV_OPEN;
329 :
330 0 : error = scsi_test_unit_ready(link, TEST_READY_RETRIES,
331 0 : (rawopen ? SCSI_SILENT : 0) | SCSI_IGNORE_ILLEGAL_REQUEST |
332 : SCSI_IGNORE_MEDIA_CHANGE);
333 :
334 : /* Start the cd spinning if necessary. */
335 0 : if (error == EIO)
336 0 : error = scsi_start(link, SSS_START,
337 : SCSI_IGNORE_ILLEGAL_REQUEST |
338 : SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT);
339 :
340 0 : if (error) {
341 0 : if (rawopen) {
342 : error = 0;
343 0 : goto out;
344 : } else
345 : goto bad;
346 : }
347 :
348 : /* Lock the cd in. */
349 0 : error = scsi_prevent(link, PR_PREVENT,
350 : SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE |
351 : SCSI_SILENT);
352 0 : if (error)
353 : goto bad;
354 :
355 : /* Load the physical device parameters. */
356 0 : link->flags |= SDEV_MEDIA_LOADED;
357 0 : if (cd_get_parms(sc, (rawopen ? SCSI_SILENT : 0) |
358 : SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE)) {
359 0 : link->flags &= ~SDEV_MEDIA_LOADED;
360 : error = ENXIO;
361 0 : goto bad;
362 : }
363 : SC_DEBUG(link, SDEV_DB3, ("Params loaded\n"));
364 :
365 : /* Fabricate a disk label. */
366 0 : cdgetdisklabel(dev, sc, sc->sc_dk.dk_label, 0);
367 : SC_DEBUG(link, SDEV_DB3, ("Disklabel fabricated\n"));
368 : }
369 :
370 : out:
371 0 : if ((error = disk_openpart(&sc->sc_dk, part, fmt, 1)) != 0)
372 : goto bad;
373 :
374 0 : link->flags |= SDEV_OPEN;
375 : SC_DEBUG(link, SDEV_DB3, ("open complete\n"));
376 :
377 : /* It's OK to fall through because dk_openmask is now non-zero. */
378 : bad:
379 0 : if (sc->sc_dk.dk_openmask == 0) {
380 0 : scsi_prevent(link, PR_ALLOW,
381 : SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE |
382 : SCSI_SILENT);
383 0 : link->flags &= ~(SDEV_OPEN | SDEV_MEDIA_LOADED);
384 0 : }
385 :
386 0 : disk_unlock(&sc->sc_dk);
387 0 : device_unref(&sc->sc_dev);
388 0 : return (error);
389 0 : }
390 :
391 : /*
392 : * Close the device. Only called if we are the last occurrence of an open
393 : * device.
394 : */
395 : int
396 0 : cdclose(dev_t dev, int flag, int fmt, struct proc *p)
397 : {
398 : struct cd_softc *sc;
399 0 : int part = DISKPART(dev);
400 :
401 0 : sc = cdlookup(DISKUNIT(dev));
402 0 : if (sc == NULL)
403 0 : return ENXIO;
404 0 : if (sc->sc_flags & CDF_DYING) {
405 0 : device_unref(&sc->sc_dev);
406 0 : return (ENXIO);
407 : }
408 :
409 0 : disk_lock_nointr(&sc->sc_dk);
410 :
411 0 : disk_closepart(&sc->sc_dk, part, fmt);
412 :
413 0 : if (sc->sc_dk.dk_openmask == 0) {
414 : /* XXXX Must wait for I/O to complete! */
415 :
416 0 : scsi_prevent(sc->sc_link, PR_ALLOW,
417 : SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY |
418 : SCSI_SILENT);
419 0 : sc->sc_link->flags &= ~(SDEV_OPEN | SDEV_MEDIA_LOADED);
420 :
421 0 : if (sc->sc_link->flags & SDEV_EJECTING) {
422 0 : scsi_start(sc->sc_link, SSS_STOP|SSS_LOEJ, 0);
423 :
424 0 : sc->sc_link->flags &= ~SDEV_EJECTING;
425 0 : }
426 :
427 0 : timeout_del(&sc->sc_timeout);
428 0 : scsi_xsh_del(&sc->sc_xsh);
429 0 : }
430 :
431 0 : disk_unlock(&sc->sc_dk);
432 :
433 0 : device_unref(&sc->sc_dev);
434 0 : return 0;
435 0 : }
436 :
437 : /*
438 : * Actually translate the requested transfer into one the physical driver can
439 : * understand. The transfer is described by a buf and will include only one
440 : * physical transfer.
441 : */
442 : void
443 0 : cdstrategy(struct buf *bp)
444 : {
445 : struct cd_softc *sc;
446 : int s;
447 :
448 0 : sc = cdlookup(DISKUNIT(bp->b_dev));
449 0 : if (sc == NULL) {
450 0 : bp->b_error = ENXIO;
451 0 : goto bad;
452 : }
453 0 : if (sc->sc_flags & CDF_DYING) {
454 0 : bp->b_error = ENXIO;
455 0 : goto bad;
456 : }
457 :
458 : SC_DEBUG(sc->sc_link, SDEV_DB2, ("cdstrategy: %ld bytes @ blk %lld\n",
459 : bp->b_bcount, (long long)bp->b_blkno));
460 : /*
461 : * If the device has been made invalid, error out
462 : * maybe the media changed, or no media loaded
463 : */
464 0 : if ((sc->sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
465 0 : bp->b_error = EIO;
466 0 : goto bad;
467 : }
468 :
469 : /* Validate the request. */
470 0 : if (bounds_check_with_label(bp, sc->sc_dk.dk_label) == -1)
471 : goto done;
472 :
473 : /* Place it in the queue of disk activities for this disk. */
474 0 : bufq_queue(&sc->sc_bufq, bp);
475 :
476 : /*
477 : * Tell the device to get going on the transfer if it's
478 : * not doing anything, otherwise just wait for completion
479 : */
480 0 : scsi_xsh_add(&sc->sc_xsh);
481 :
482 0 : device_unref(&sc->sc_dev);
483 0 : return;
484 :
485 : bad:
486 0 : bp->b_flags |= B_ERROR;
487 0 : bp->b_resid = bp->b_bcount;
488 : done:
489 0 : s = splbio();
490 0 : biodone(bp);
491 0 : splx(s);
492 0 : if (sc != NULL)
493 0 : device_unref(&sc->sc_dev);
494 0 : }
495 :
496 : /*
497 : * cdstart looks to see if there is a buf waiting for the device
498 : * and that the device is not already busy. If both are true,
499 : * It deques the buf and creates a scsi command to perform the
500 : * transfer in the buf. The transfer request will call scsi_done
501 : * on completion, which will in turn call this routine again
502 : * so that the next queued transfer is performed.
503 : * The bufs are queued by the strategy routine (cdstrategy)
504 : *
505 : * This routine is also called after other non-queued requests
506 : * have been made of the scsi driver, to ensure that the queue
507 : * continues to be drained.
508 : *
509 : * must be called at the correct (highish) spl level
510 : * cdstart() is called at splbio from cdstrategy and scsi_done
511 : */
512 : void
513 0 : cdstart(struct scsi_xfer *xs)
514 : {
515 0 : struct scsi_link *link = xs->sc_link;
516 0 : struct cd_softc *sc = link->device_softc;
517 : struct buf *bp;
518 : struct scsi_rw_big *cmd_big;
519 : struct scsi_rw *cmd_small;
520 : u_int64_t secno, nsecs;
521 : struct partition *p;
522 : int read;
523 :
524 : SC_DEBUG(link, SDEV_DB2, ("cdstart\n"));
525 :
526 0 : if (sc->sc_flags & CDF_DYING) {
527 0 : scsi_xs_put(xs);
528 0 : return;
529 : }
530 :
531 : /*
532 : * If the device has become invalid, abort all the
533 : * reads and writes until all files have been closed and
534 : * re-opened
535 : */
536 0 : if ((link->flags & SDEV_MEDIA_LOADED) == 0) {
537 0 : bufq_drain(&sc->sc_bufq);
538 0 : scsi_xs_put(xs);
539 0 : return;
540 : }
541 :
542 0 : bp = bufq_dequeue(&sc->sc_bufq);
543 0 : if (bp == NULL) {
544 0 : scsi_xs_put(xs);
545 0 : return;
546 : }
547 :
548 : /*
549 : * We have a buf, now we should make a command
550 : *
551 : * First, translate the block to absolute and put it in terms
552 : * of the logical blocksize of the device.
553 : */
554 0 : secno = DL_BLKTOSEC(sc->sc_dk.dk_label, bp->b_blkno);
555 0 : p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
556 0 : secno += DL_GETPOFFSET(p);
557 0 : nsecs = howmany(bp->b_bcount, sc->sc_dk.dk_label->d_secsize);
558 :
559 0 : read = (bp->b_flags & B_READ);
560 :
561 : /*
562 : * Fill out the scsi command. If the transfer will
563 : * fit in a "small" cdb, use it.
564 : */
565 0 : if (!(link->flags & SDEV_ATAPI) &&
566 0 : !(link->quirks & SDEV_ONLYBIG) &&
567 0 : ((secno & 0x1fffff) == secno) &&
568 0 : ((nsecs & 0xff) == nsecs)) {
569 : /*
570 : * We can fit in a small cdb.
571 : */
572 0 : cmd_small = (struct scsi_rw *)xs->cmd;
573 0 : cmd_small->opcode = read ?
574 : READ_COMMAND : WRITE_COMMAND;
575 0 : _lto3b(secno, cmd_small->addr);
576 0 : cmd_small->length = nsecs & 0xff;
577 0 : xs->cmdlen = sizeof(*cmd_small);
578 0 : } else {
579 : /*
580 : * Need a large cdb.
581 : */
582 0 : cmd_big = (struct scsi_rw_big *)xs->cmd;
583 0 : cmd_big->opcode = read ?
584 : READ_BIG : WRITE_BIG;
585 0 : _lto4b(secno, cmd_big->addr);
586 0 : _lto2b(nsecs, cmd_big->length);
587 0 : xs->cmdlen = sizeof(*cmd_big);
588 : }
589 :
590 0 : xs->flags |= (read ? SCSI_DATA_IN : SCSI_DATA_OUT);
591 0 : xs->timeout = 30000;
592 0 : xs->data = bp->b_data;
593 0 : xs->datalen = bp->b_bcount;
594 0 : xs->done = cd_buf_done;
595 0 : xs->cookie = bp;
596 0 : xs->bp = bp;
597 :
598 : /* Instrumentation. */
599 0 : disk_busy(&sc->sc_dk);
600 :
601 0 : scsi_xs_exec(xs);
602 :
603 0 : if (ISSET(sc->sc_flags, CDF_WAITING))
604 0 : CLR(sc->sc_flags, CDF_WAITING);
605 0 : else if (bufq_peek(&sc->sc_bufq))
606 0 : scsi_xsh_add(&sc->sc_xsh);
607 0 : }
608 :
609 : void
610 0 : cd_buf_done(struct scsi_xfer *xs)
611 : {
612 0 : struct cd_softc *sc = xs->sc_link->device_softc;
613 0 : struct buf *bp = xs->cookie;
614 : int error, s;
615 :
616 0 : switch (xs->error) {
617 : case XS_NOERROR:
618 0 : bp->b_error = 0;
619 0 : bp->b_resid = xs->resid;
620 0 : break;
621 :
622 : case XS_SENSE:
623 : case XS_SHORTSENSE:
624 : #ifdef SCSIDEBUG
625 : scsi_sense_print_debug(xs);
626 : #endif
627 0 : error = cd_interpret_sense(xs);
628 0 : if (error == 0) {
629 0 : bp->b_error = 0;
630 0 : bp->b_resid = xs->resid;
631 0 : break;
632 : }
633 0 : if (error != ERESTART)
634 0 : xs->retries = 0;
635 : goto retry;
636 :
637 : case XS_BUSY:
638 0 : if (xs->retries) {
639 0 : if (scsi_delay(xs, 1) != ERESTART)
640 0 : xs->retries = 0;
641 : }
642 : goto retry;
643 :
644 : case XS_TIMEOUT:
645 : retry:
646 0 : if (xs->retries--) {
647 0 : scsi_xs_exec(xs);
648 0 : return;
649 : }
650 : /* FALLTHROUGH */
651 :
652 : default:
653 0 : bp->b_error = EIO;
654 0 : bp->b_flags |= B_ERROR;
655 0 : bp->b_resid = bp->b_bcount;
656 0 : break;
657 : }
658 :
659 0 : disk_unbusy(&sc->sc_dk, bp->b_bcount - xs->resid, bp->b_blkno,
660 0 : bp->b_flags & B_READ);
661 :
662 0 : s = splbio();
663 0 : biodone(bp);
664 0 : splx(s);
665 0 : scsi_xs_put(xs);
666 0 : }
667 :
668 : void
669 0 : cdminphys(struct buf *bp)
670 : {
671 : struct cd_softc *sc;
672 : long max;
673 :
674 0 : sc = cdlookup(DISKUNIT(bp->b_dev));
675 0 : if (sc == NULL)
676 0 : return;
677 :
678 : /*
679 : * If the device is ancient, we want to make sure that
680 : * the transfer fits into a 6-byte cdb.
681 : *
682 : * XXX Note that the SCSI-I spec says that 256-block transfers
683 : * are allowed in a 6-byte read/write, and are specified
684 : * by setting the "length" to 0. However, we're conservative
685 : * here, allowing only 255-block transfers in case an
686 : * ancient device gets confused by length == 0. A length of 0
687 : * in a 10-byte read/write actually means 0 blocks.
688 : */
689 0 : if (sc->sc_flags & CDF_ANCIENT) {
690 0 : max = sc->sc_dk.dk_label->d_secsize * 0xff;
691 :
692 0 : if (bp->b_bcount > max)
693 0 : bp->b_bcount = max;
694 : }
695 :
696 0 : (*sc->sc_link->adapter->scsi_minphys)(bp, sc->sc_link);
697 :
698 0 : device_unref(&sc->sc_dev);
699 0 : }
700 :
701 : int
702 0 : cdread(dev_t dev, struct uio *uio, int ioflag)
703 : {
704 :
705 0 : return (physio(cdstrategy, dev, B_READ, cdminphys, uio));
706 : }
707 :
708 : int
709 0 : cdwrite(dev_t dev, struct uio *uio, int ioflag)
710 : {
711 :
712 0 : return (physio(cdstrategy, dev, B_WRITE, cdminphys, uio));
713 : }
714 :
715 : /*
716 : * Perform special action on behalf of the user.
717 : * Knows about the internals of this device
718 : */
719 : int
720 0 : cdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
721 : {
722 : struct cd_softc *sc;
723 : struct disklabel *lp;
724 0 : int part = DISKPART(dev);
725 : int error = 0;
726 :
727 0 : sc = cdlookup(DISKUNIT(dev));
728 0 : if (sc == NULL)
729 0 : return ENXIO;
730 0 : if (sc->sc_flags & CDF_DYING) {
731 0 : device_unref(&sc->sc_dev);
732 0 : return (ENXIO);
733 : }
734 :
735 : SC_DEBUG(sc->sc_link, SDEV_DB2, ("cdioctl 0x%lx\n", cmd));
736 :
737 : /*
738 : * If the device is not valid.. abandon ship
739 : */
740 0 : if ((sc->sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
741 0 : switch (cmd) {
742 : case DIOCLOCK:
743 : case DIOCEJECT:
744 : case SCIOCIDENTIFY:
745 : case SCIOCCOMMAND:
746 : case SCIOCDEBUG:
747 : case CDIOCLOADUNLOAD:
748 : case SCIOCRESET:
749 : case CDIOCGETVOL:
750 : case CDIOCSETVOL:
751 : case CDIOCSETMONO:
752 : case CDIOCSETSTEREO:
753 : case CDIOCSETMUTE:
754 : case CDIOCSETLEFT:
755 : case CDIOCSETRIGHT:
756 : case CDIOCCLOSE:
757 : case CDIOCEJECT:
758 : case CDIOCALLOW:
759 : case CDIOCPREVENT:
760 : case CDIOCSETDEBUG:
761 : case CDIOCCLRDEBUG:
762 : case CDIOCRESET:
763 : case DVD_AUTH:
764 : case DVD_READ_STRUCT:
765 : case MTIOCTOP:
766 0 : if (part == RAW_PART)
767 : break;
768 : /* FALLTHROUGH */
769 : default:
770 0 : if ((sc->sc_link->flags & SDEV_OPEN) == 0)
771 0 : error = ENODEV;
772 : else
773 : error = EIO;
774 : goto exit;
775 : }
776 : }
777 :
778 0 : switch (cmd) {
779 : case DIOCRLDINFO:
780 0 : lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK);
781 0 : cdgetdisklabel(dev, sc, lp, 0);
782 0 : memcpy(sc->sc_dk.dk_label, lp, sizeof(*lp));
783 0 : free(lp, M_TEMP, sizeof(*lp));
784 0 : break;
785 :
786 : case DIOCGPDINFO:
787 0 : cdgetdisklabel(dev, sc, (struct disklabel *)addr, 1);
788 0 : break;
789 :
790 : case DIOCGDINFO:
791 0 : *(struct disklabel *)addr = *(sc->sc_dk.dk_label);
792 0 : break;
793 :
794 : case DIOCGPART:
795 0 : ((struct partinfo *)addr)->disklab = sc->sc_dk.dk_label;
796 0 : ((struct partinfo *)addr)->part =
797 0 : &sc->sc_dk.dk_label->d_partitions[DISKPART(dev)];
798 0 : break;
799 :
800 : case DIOCWDINFO:
801 : case DIOCSDINFO:
802 0 : if ((flag & FWRITE) == 0) {
803 : error = EBADF;
804 0 : break;
805 : }
806 :
807 0 : if ((error = disk_lock(&sc->sc_dk)) != 0)
808 : break;
809 :
810 0 : error = setdisklabel(sc->sc_dk.dk_label,
811 0 : (struct disklabel *)addr, sc->sc_dk.dk_openmask);
812 : if (error == 0) {
813 : }
814 :
815 0 : disk_unlock(&sc->sc_dk);
816 0 : break;
817 :
818 : case CDIOCPLAYTRACKS: {
819 0 : struct ioc_play_track *args = (struct ioc_play_track *)addr;
820 :
821 0 : if ((error = cd_set_pa_immed(sc, 0)) != 0)
822 0 : break;
823 0 : error = cd_play_tracks(sc, args->start_track,
824 0 : args->start_index, args->end_track, args->end_index);
825 0 : break;
826 : }
827 : case CDIOCPLAYMSF: {
828 0 : struct ioc_play_msf *args = (struct ioc_play_msf *)addr;
829 :
830 0 : if ((error = cd_set_pa_immed(sc, 0)) != 0)
831 0 : break;
832 0 : error = cd_play_msf(sc, args->start_m, args->start_s,
833 0 : args->start_f, args->end_m, args->end_s, args->end_f);
834 0 : break;
835 : }
836 : case CDIOCPLAYBLOCKS: {
837 0 : struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr;
838 :
839 0 : if ((error = cd_set_pa_immed(sc, 0)) != 0)
840 0 : break;
841 0 : error = cd_play(sc, args->blk, args->len);
842 0 : break;
843 : }
844 : case CDIOCREADSUBCHANNEL: {
845 : struct ioc_read_subchannel *args =
846 0 : (struct ioc_read_subchannel *)addr;
847 : struct cd_sub_channel_info *data;
848 0 : int len = args->data_len;
849 :
850 0 : if (len > sizeof(*data) ||
851 0 : len < sizeof(struct cd_sub_channel_header)) {
852 : error = EINVAL;
853 0 : break;
854 : }
855 0 : data = dma_alloc(sizeof(*data), PR_WAITOK);
856 0 : error = cd_read_subchannel(sc, args->address_format,
857 0 : args->data_format, args->track, data, len);
858 0 : if (error) {
859 0 : dma_free(data, sizeof(*data));
860 0 : break;
861 : }
862 0 : len = min(len, _2btol(data->header.data_len) +
863 : sizeof(struct cd_sub_channel_header));
864 0 : error = copyout(data, args->data, len);
865 0 : dma_free(data, sizeof(*data));
866 0 : break;
867 : }
868 : case CDIOREADTOCHEADER: {
869 : struct ioc_toc_header *th;
870 :
871 0 : th = dma_alloc(sizeof(*th), PR_WAITOK);
872 0 : if ((error = cd_read_toc(sc, 0, 0, th, sizeof(*th), 0)) != 0) {
873 0 : dma_free(th, sizeof(*th));
874 0 : break;
875 : }
876 0 : if (sc->sc_link->quirks & ADEV_LITTLETOC)
877 0 : th->len = letoh16(th->len);
878 : else
879 0 : th->len = betoh16(th->len);
880 0 : if (th->len > 0)
881 0 : memcpy(addr, th, sizeof(*th));
882 : else
883 : error = EIO;
884 0 : dma_free(th, sizeof(*th));
885 0 : break;
886 : }
887 : case CDIOREADTOCENTRYS: {
888 : struct cd_toc *toc;
889 : struct ioc_read_toc_entry *te =
890 0 : (struct ioc_read_toc_entry *)addr;
891 : struct ioc_toc_header *th;
892 : struct cd_toc_entry *cte;
893 0 : int len = te->data_len;
894 : int ntracks;
895 :
896 0 : toc = dma_alloc(sizeof(*toc), PR_WAITOK | PR_ZERO);
897 :
898 0 : th = &toc->header;
899 :
900 0 : if (len > sizeof(toc->entries) ||
901 0 : len < sizeof(struct cd_toc_entry)) {
902 0 : dma_free(toc, sizeof(*toc));
903 : error = EINVAL;
904 0 : break;
905 : }
906 0 : error = cd_read_toc(sc, te->address_format, te->starting_track,
907 0 : toc, len + sizeof(struct ioc_toc_header), 0);
908 0 : if (error) {
909 0 : dma_free(toc, sizeof(*toc));
910 0 : break;
911 : }
912 0 : if (te->address_format == CD_LBA_FORMAT)
913 0 : for (ntracks =
914 0 : th->ending_track - th->starting_track + 1;
915 0 : ntracks >= 0; ntracks--) {
916 0 : cte = &toc->entries[ntracks];
917 0 : cte->addr_type = CD_LBA_FORMAT;
918 0 : if (sc->sc_link->quirks & ADEV_LITTLETOC) {
919 : #if BYTE_ORDER == BIG_ENDIAN
920 : swap16_multi((u_int16_t *)&cte->addr,
921 : sizeof(cte->addr) / 2);
922 : #endif
923 : } else
924 0 : cte->addr.lba = betoh32(cte->addr.lba);
925 : }
926 0 : if (sc->sc_link->quirks & ADEV_LITTLETOC) {
927 0 : th->len = letoh16(th->len);
928 0 : } else
929 0 : th->len = betoh16(th->len);
930 0 : len = min(len, th->len - (sizeof(th->starting_track) +
931 : sizeof(th->ending_track)));
932 :
933 0 : error = copyout(toc->entries, te->data, len);
934 0 : dma_free(toc, sizeof(*toc));
935 0 : break;
936 : }
937 : case CDIOREADMSADDR: {
938 : struct cd_toc *toc;
939 0 : int sessno = *(int *)addr;
940 : struct cd_toc_entry *cte;
941 :
942 0 : if (sessno != 0) {
943 : error = EINVAL;
944 0 : break;
945 : }
946 :
947 0 : toc = dma_alloc(sizeof(*toc), PR_WAITOK | PR_ZERO);
948 :
949 0 : error = cd_read_toc(sc, 0, 0, toc,
950 : sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry),
951 : 0x40 /* control word for "get MS info" */);
952 :
953 0 : if (error) {
954 0 : dma_free(toc, sizeof(*toc));
955 0 : break;
956 : }
957 :
958 0 : cte = &toc->entries[0];
959 0 : if (sc->sc_link->quirks & ADEV_LITTLETOC) {
960 : #if BYTE_ORDER == BIG_ENDIAN
961 : swap16_multi((u_int16_t *)&cte->addr,
962 : sizeof(cte->addr) / 2);
963 : #endif
964 : } else
965 0 : cte->addr.lba = betoh32(cte->addr.lba);
966 0 : if (sc->sc_link->quirks & ADEV_LITTLETOC)
967 0 : toc->header.len = letoh16(toc->header.len);
968 : else
969 0 : toc->header.len = betoh16(toc->header.len);
970 :
971 0 : *(int *)addr = (toc->header.len >= 10 && cte->track > 1) ?
972 0 : cte->addr.lba : 0;
973 0 : dma_free(toc, sizeof(*toc));
974 0 : break;
975 : }
976 : case CDIOCSETPATCH: {
977 0 : struct ioc_patch *arg = (struct ioc_patch *)addr;
978 :
979 0 : error = cd_setchan(sc, arg->patch[0], arg->patch[1],
980 0 : arg->patch[2], arg->patch[3], 0);
981 : break;
982 : }
983 : case CDIOCGETVOL: {
984 0 : struct ioc_vol *arg = (struct ioc_vol *)addr;
985 :
986 0 : error = cd_getvol(sc, arg, 0);
987 : break;
988 : }
989 : case CDIOCSETVOL: {
990 0 : struct ioc_vol *arg = (struct ioc_vol *)addr;
991 :
992 0 : error = cd_setvol(sc, arg, 0);
993 : break;
994 : }
995 :
996 : case CDIOCSETMONO:
997 0 : error = cd_setchan(sc, BOTH_CHANNEL, BOTH_CHANNEL, MUTE_CHANNEL,
998 : MUTE_CHANNEL, 0);
999 0 : break;
1000 :
1001 : case CDIOCSETSTEREO:
1002 0 : error = cd_setchan(sc, LEFT_CHANNEL, RIGHT_CHANNEL,
1003 : MUTE_CHANNEL, MUTE_CHANNEL, 0);
1004 0 : break;
1005 :
1006 : case CDIOCSETMUTE:
1007 0 : error = cd_setchan(sc, MUTE_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL,
1008 : MUTE_CHANNEL, 0);
1009 0 : break;
1010 :
1011 : case CDIOCSETLEFT:
1012 0 : error = cd_setchan(sc, LEFT_CHANNEL, LEFT_CHANNEL, MUTE_CHANNEL,
1013 : MUTE_CHANNEL, 0);
1014 0 : break;
1015 :
1016 : case CDIOCSETRIGHT:
1017 0 : error = cd_setchan(sc, RIGHT_CHANNEL, RIGHT_CHANNEL,
1018 : MUTE_CHANNEL, MUTE_CHANNEL, 0);
1019 0 : break;
1020 :
1021 : case CDIOCRESUME:
1022 0 : error = cd_pause(sc, 1);
1023 0 : break;
1024 :
1025 : case CDIOCPAUSE:
1026 0 : error = cd_pause(sc, 0);
1027 0 : break;
1028 : case CDIOCSTART:
1029 0 : error = scsi_start(sc->sc_link, SSS_START, 0);
1030 0 : break;
1031 :
1032 : case CDIOCSTOP:
1033 0 : error = scsi_start(sc->sc_link, SSS_STOP, 0);
1034 0 : break;
1035 :
1036 : close_tray:
1037 : case CDIOCCLOSE:
1038 0 : error = scsi_start(sc->sc_link, SSS_START|SSS_LOEJ,
1039 : SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE);
1040 0 : break;
1041 :
1042 : case MTIOCTOP:
1043 0 : if (((struct mtop *)addr)->mt_op == MTRETEN)
1044 : goto close_tray;
1045 0 : if (((struct mtop *)addr)->mt_op != MTOFFL) {
1046 : error = EIO;
1047 0 : break;
1048 : }
1049 : /* FALLTHROUGH */
1050 : case CDIOCEJECT: /* FALLTHROUGH */
1051 : case DIOCEJECT:
1052 0 : sc->sc_link->flags |= SDEV_EJECTING;
1053 0 : break;
1054 : case CDIOCALLOW:
1055 0 : error = scsi_prevent(sc->sc_link, PR_ALLOW, 0);
1056 0 : break;
1057 : case CDIOCPREVENT:
1058 0 : error = scsi_prevent(sc->sc_link, PR_PREVENT, 0);
1059 0 : break;
1060 : case DIOCLOCK:
1061 0 : error = scsi_prevent(sc->sc_link,
1062 0 : (*(int *)addr) ? PR_PREVENT : PR_ALLOW, 0);
1063 0 : break;
1064 : case CDIOCSETDEBUG:
1065 0 : sc->sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
1066 0 : break;
1067 : case CDIOCCLRDEBUG:
1068 0 : sc->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
1069 0 : break;
1070 : case CDIOCRESET:
1071 : case SCIOCRESET:
1072 0 : error = cd_reset(sc);
1073 0 : break;
1074 : case CDIOCLOADUNLOAD: {
1075 0 : struct ioc_load_unload *args = (struct ioc_load_unload *)addr;
1076 :
1077 0 : error = cd_load_unload(sc, args->options, args->slot);
1078 : break;
1079 : }
1080 :
1081 : case DVD_AUTH:
1082 0 : error = dvd_auth(sc, (union dvd_authinfo *)addr);
1083 0 : break;
1084 : case DVD_READ_STRUCT:
1085 0 : error = dvd_read_struct(sc, (union dvd_struct *)addr);
1086 0 : break;
1087 : default:
1088 0 : if (DISKPART(dev) != RAW_PART) {
1089 : error = ENOTTY;
1090 0 : break;
1091 : }
1092 0 : error = scsi_do_ioctl(sc->sc_link, cmd, addr, flag);
1093 0 : break;
1094 : }
1095 :
1096 : exit:
1097 :
1098 0 : device_unref(&sc->sc_dev);
1099 0 : return (error);
1100 0 : }
1101 :
1102 : /*
1103 : * Load the label information on the named device
1104 : * Actually fabricate a disklabel
1105 : *
1106 : * EVENTUALLY take information about different
1107 : * data tracks from the TOC and put it in the disklabel
1108 : */
1109 : int
1110 0 : cdgetdisklabel(dev_t dev, struct cd_softc *sc, struct disklabel *lp,
1111 : int spoofonly)
1112 : {
1113 : struct cd_toc *toc;
1114 : int tocidx, n, audioonly = 1;
1115 :
1116 0 : bzero(lp, sizeof(struct disklabel));
1117 :
1118 0 : lp->d_secsize = sc->params.secsize;
1119 0 : lp->d_ntracks = 1;
1120 0 : lp->d_nsectors = 100;
1121 0 : lp->d_secpercyl = 100;
1122 0 : lp->d_ncylinders = (sc->params.disksize / 100) + 1;
1123 :
1124 0 : if (sc->sc_link->flags & SDEV_ATAPI) {
1125 0 : strncpy(lp->d_typename, "ATAPI CD-ROM", sizeof(lp->d_typename));
1126 0 : lp->d_type = DTYPE_ATAPI;
1127 0 : } else {
1128 0 : strncpy(lp->d_typename, "SCSI CD-ROM", sizeof(lp->d_typename));
1129 0 : lp->d_type = DTYPE_SCSI;
1130 : }
1131 :
1132 0 : strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
1133 0 : DL_SETDSIZE(lp, sc->params.disksize);
1134 0 : lp->d_version = 1;
1135 :
1136 : /* XXX - these values for BBSIZE and SBSIZE assume ffs */
1137 0 : lp->d_bbsize = BBSIZE;
1138 0 : lp->d_sbsize = SBSIZE;
1139 :
1140 0 : lp->d_magic = DISKMAGIC;
1141 0 : lp->d_magic2 = DISKMAGIC;
1142 0 : lp->d_checksum = dkcksum(lp);
1143 :
1144 0 : toc = dma_alloc(sizeof(*toc), PR_WAITOK | PR_ZERO);
1145 0 : if (cd_load_toc(sc, toc, CD_LBA_FORMAT)) {
1146 : audioonly = 0; /* No valid TOC found == not an audio CD. */
1147 0 : goto done;
1148 : }
1149 :
1150 0 : n = toc->header.ending_track - toc->header.starting_track + 1;
1151 0 : for (tocidx = 0; tocidx < n; tocidx++)
1152 0 : if (toc->entries[tocidx].control & 4) {
1153 : audioonly = 0; /* Found a non-audio track. */
1154 0 : goto done;
1155 : }
1156 :
1157 : done:
1158 0 : dma_free(toc, sizeof(*toc));
1159 :
1160 0 : if (audioonly)
1161 0 : return (0);
1162 0 : return readdisklabel(DISKLABELDEV(dev), cdstrategy, lp, spoofonly);
1163 0 : }
1164 :
1165 : int
1166 0 : cd_setchan(struct cd_softc *sc, int p0, int p1, int p2, int p3, int flags)
1167 : {
1168 : union scsi_mode_sense_buf *data;
1169 0 : struct cd_audio_page *audio = NULL;
1170 0 : int error, big;
1171 :
1172 0 : data = dma_alloc(sizeof(*data), PR_NOWAIT);
1173 0 : if (data == NULL)
1174 0 : return (ENOMEM);
1175 :
1176 0 : error = scsi_do_mode_sense(sc->sc_link, AUDIO_PAGE, data,
1177 0 : (void **)&audio, NULL, NULL, NULL, sizeof(*audio), flags, &big);
1178 0 : if (error == 0 && audio == NULL)
1179 : error = EIO;
1180 :
1181 0 : if (error == 0) {
1182 0 : audio->port[LEFT_PORT].channels = p0;
1183 0 : audio->port[RIGHT_PORT].channels = p1;
1184 0 : audio->port[2].channels = p2;
1185 0 : audio->port[3].channels = p3;
1186 0 : if (big)
1187 0 : error = scsi_mode_select_big(sc->sc_link, SMS_PF,
1188 0 : &data->hdr_big, flags, 20000);
1189 : else
1190 0 : error = scsi_mode_select(sc->sc_link, SMS_PF,
1191 0 : &data->hdr, flags, 20000);
1192 : }
1193 :
1194 0 : dma_free(data, sizeof(*data));
1195 0 : return (error);
1196 0 : }
1197 :
1198 : int
1199 0 : cd_getvol(struct cd_softc *sc, struct ioc_vol *arg, int flags)
1200 : {
1201 : union scsi_mode_sense_buf *data;
1202 0 : struct cd_audio_page *audio = NULL;
1203 : int error;
1204 :
1205 0 : data = dma_alloc(sizeof(*data), PR_NOWAIT);
1206 0 : if (data == NULL)
1207 0 : return (ENOMEM);
1208 :
1209 0 : error = scsi_do_mode_sense(sc->sc_link, AUDIO_PAGE, data,
1210 0 : (void **)&audio, NULL, NULL, NULL, sizeof(*audio), flags, NULL);
1211 0 : if (error == 0 && audio == NULL)
1212 : error = EIO;
1213 :
1214 0 : if (error == 0) {
1215 0 : arg->vol[0] = audio->port[0].volume;
1216 0 : arg->vol[1] = audio->port[1].volume;
1217 0 : arg->vol[2] = audio->port[2].volume;
1218 0 : arg->vol[3] = audio->port[3].volume;
1219 0 : }
1220 :
1221 0 : dma_free(data, sizeof(*data));
1222 0 : return (0);
1223 0 : }
1224 :
1225 : int
1226 0 : cd_setvol(struct cd_softc *sc, const struct ioc_vol *arg, int flags)
1227 : {
1228 : union scsi_mode_sense_buf *data;
1229 0 : struct cd_audio_page *audio = NULL;
1230 : u_int8_t mask_volume[4];
1231 0 : int error, big;
1232 :
1233 0 : data = dma_alloc(sizeof(*data), PR_NOWAIT);
1234 0 : if (data == NULL)
1235 0 : return (ENOMEM);
1236 :
1237 0 : error = scsi_do_mode_sense(sc->sc_link,
1238 0 : AUDIO_PAGE | SMS_PAGE_CTRL_CHANGEABLE, data, (void **)&audio, NULL,
1239 : NULL, NULL, sizeof(*audio), flags, NULL);
1240 0 : if (error == 0 && audio == NULL)
1241 : error = EIO;
1242 0 : if (error != 0) {
1243 0 : dma_free(data, sizeof(*data));
1244 0 : return (error);
1245 : }
1246 :
1247 0 : mask_volume[0] = audio->port[0].volume;
1248 0 : mask_volume[1] = audio->port[1].volume;
1249 0 : mask_volume[2] = audio->port[2].volume;
1250 0 : mask_volume[3] = audio->port[3].volume;
1251 :
1252 0 : error = scsi_do_mode_sense(sc->sc_link, AUDIO_PAGE, data,
1253 : (void **)&audio, NULL, NULL, NULL, sizeof(*audio), flags, &big);
1254 0 : if (error == 0 && audio == NULL)
1255 : error = EIO;
1256 0 : if (error != 0) {
1257 0 : dma_free(data, sizeof(*data));
1258 0 : return (error);
1259 : }
1260 :
1261 0 : audio->port[0].volume = arg->vol[0] & mask_volume[0];
1262 0 : audio->port[1].volume = arg->vol[1] & mask_volume[1];
1263 0 : audio->port[2].volume = arg->vol[2] & mask_volume[2];
1264 0 : audio->port[3].volume = arg->vol[3] & mask_volume[3];
1265 :
1266 0 : if (big)
1267 0 : error = scsi_mode_select_big(sc->sc_link, SMS_PF,
1268 0 : &data->hdr_big, flags, 20000);
1269 : else
1270 0 : error = scsi_mode_select(sc->sc_link, SMS_PF,
1271 0 : &data->hdr, flags, 20000);
1272 :
1273 0 : dma_free(data, sizeof(*data));
1274 0 : return (error);
1275 0 : }
1276 :
1277 : int
1278 0 : cd_load_unload(struct cd_softc *sc, int options, int slot)
1279 : {
1280 : struct scsi_load_unload *cmd;
1281 : struct scsi_xfer *xs;
1282 : int error;
1283 :
1284 0 : xs = scsi_xs_get(sc->sc_link, 0);
1285 0 : if (xs == NULL)
1286 0 : return (ENOMEM);
1287 0 : xs->cmdlen = sizeof(*cmd);
1288 0 : xs->timeout = 200000;
1289 :
1290 0 : cmd = (struct scsi_load_unload *)xs->cmd;
1291 0 : cmd->opcode = LOAD_UNLOAD;
1292 0 : cmd->options = options; /* ioctl uses ATAPI values */
1293 0 : cmd->slot = slot;
1294 :
1295 0 : error = scsi_xs_sync(xs);
1296 0 : scsi_xs_put(xs);
1297 :
1298 0 : return (error);
1299 0 : }
1300 :
1301 : int
1302 0 : cd_set_pa_immed(struct cd_softc *sc, int flags)
1303 : {
1304 : union scsi_mode_sense_buf *data;
1305 0 : struct cd_audio_page *audio = NULL;
1306 0 : int error, oflags, big;
1307 :
1308 0 : if (sc->sc_link->flags & SDEV_ATAPI)
1309 : /* XXX Noop? */
1310 0 : return (0);
1311 :
1312 0 : data = dma_alloc(sizeof(*data), PR_NOWAIT);
1313 0 : if (data == NULL)
1314 0 : return (ENOMEM);
1315 :
1316 0 : error = scsi_do_mode_sense(sc->sc_link, AUDIO_PAGE, data,
1317 0 : (void **)&audio, NULL, NULL, NULL, sizeof(*audio), flags, &big);
1318 0 : if (error == 0 && audio == NULL)
1319 : error = EIO;
1320 :
1321 0 : if (error == 0) {
1322 0 : oflags = audio->flags;
1323 0 : audio->flags &= ~CD_PA_SOTC;
1324 0 : audio->flags |= CD_PA_IMMED;
1325 0 : if (audio->flags != oflags) {
1326 0 : if (big)
1327 0 : error = scsi_mode_select_big(sc->sc_link,
1328 0 : SMS_PF, &data->hdr_big, flags, 20000);
1329 : else
1330 0 : error = scsi_mode_select(sc->sc_link, SMS_PF,
1331 0 : &data->hdr, flags, 20000);
1332 : }
1333 : }
1334 :
1335 0 : dma_free(data, sizeof(*data));
1336 0 : return (error);
1337 0 : }
1338 :
1339 : /*
1340 : * Get scsi driver to send a "start playing" command
1341 : */
1342 : int
1343 0 : cd_play(struct cd_softc *sc, int secno, int nsecs)
1344 : {
1345 : struct scsi_play *cmd;
1346 : struct scsi_xfer *xs;
1347 : int error;
1348 :
1349 0 : xs = scsi_xs_get(sc->sc_link, 0);
1350 0 : if (xs == NULL)
1351 0 : return (ENOMEM);
1352 0 : xs->cmdlen = sizeof(*cmd);
1353 0 : xs->timeout = 200000;
1354 :
1355 0 : cmd = (struct scsi_play *)xs->cmd;
1356 0 : cmd->opcode = PLAY;
1357 0 : _lto4b(secno, cmd->blk_addr);
1358 0 : _lto2b(nsecs, cmd->xfer_len);
1359 :
1360 0 : error = scsi_xs_sync(xs);
1361 0 : scsi_xs_put(xs);
1362 :
1363 0 : return (error);
1364 0 : }
1365 :
1366 : /*
1367 : * Get scsi driver to send a "start playing" command
1368 : */
1369 : int
1370 0 : cd_play_tracks(struct cd_softc *sc, int strack, int sindex, int etrack,
1371 : int eindex)
1372 : {
1373 : struct cd_toc *toc;
1374 : u_char endf, ends, endm;
1375 : int error;
1376 :
1377 0 : if (!etrack)
1378 0 : return (EIO);
1379 0 : if (strack > etrack)
1380 0 : return (EINVAL);
1381 :
1382 0 : toc = dma_alloc(sizeof(*toc), PR_WAITOK | PR_ZERO);
1383 :
1384 0 : if ((error = cd_load_toc(sc, toc, CD_MSF_FORMAT)) != 0)
1385 : goto done;
1386 :
1387 0 : if (++etrack > (toc->header.ending_track+1))
1388 0 : etrack = toc->header.ending_track+1;
1389 :
1390 0 : strack -= toc->header.starting_track;
1391 0 : etrack -= toc->header.starting_track;
1392 0 : if (strack < 0) {
1393 : error = EINVAL;
1394 0 : goto done;
1395 : }
1396 :
1397 : /*
1398 : * The track ends one frame before the next begins. The last track
1399 : * is taken care of by the leadoff track.
1400 : */
1401 0 : endm = toc->entries[etrack].addr.msf.minute;
1402 0 : ends = toc->entries[etrack].addr.msf.second;
1403 0 : endf = toc->entries[etrack].addr.msf.frame;
1404 0 : if (endf-- == 0) {
1405 : endf = CD_FRAMES - 1;
1406 0 : if (ends-- == 0) {
1407 : ends = CD_SECS - 1;
1408 0 : if (endm-- == 0) {
1409 : error = EINVAL;
1410 0 : goto done;
1411 : }
1412 : }
1413 : }
1414 :
1415 0 : error = cd_play_msf(sc, toc->entries[strack].addr.msf.minute,
1416 0 : toc->entries[strack].addr.msf.second,
1417 0 : toc->entries[strack].addr.msf.frame,
1418 0 : endm, ends, endf);
1419 :
1420 : done:
1421 0 : dma_free(toc, sizeof(*toc));
1422 0 : return (error);
1423 0 : }
1424 :
1425 : /*
1426 : * Get scsi driver to send a "play msf" command
1427 : */
1428 : int
1429 0 : cd_play_msf(struct cd_softc *sc, int startm, int starts, int startf, int endm,
1430 : int ends, int endf)
1431 : {
1432 : struct scsi_play_msf *cmd;
1433 : struct scsi_xfer *xs;
1434 : int error;
1435 :
1436 0 : xs = scsi_xs_get(sc->sc_link, 0);
1437 0 : if (xs == NULL)
1438 0 : return (ENOMEM);
1439 0 : xs->cmdlen = sizeof(*cmd);
1440 0 : xs->timeout = 20000;
1441 :
1442 0 : cmd = (struct scsi_play_msf *)xs->cmd;
1443 0 : cmd->opcode = PLAY_MSF;
1444 0 : cmd->start_m = startm;
1445 0 : cmd->start_s = starts;
1446 0 : cmd->start_f = startf;
1447 0 : cmd->end_m = endm;
1448 0 : cmd->end_s = ends;
1449 0 : cmd->end_f = endf;
1450 :
1451 0 : error = scsi_xs_sync(xs);
1452 0 : scsi_xs_put(xs);
1453 :
1454 0 : return (error);
1455 0 : }
1456 :
1457 : /*
1458 : * Get scsi driver to send a "start up" command
1459 : */
1460 : int
1461 0 : cd_pause(struct cd_softc *sc, int go)
1462 : {
1463 : struct scsi_pause *cmd;
1464 : struct scsi_xfer *xs;
1465 : int error;
1466 :
1467 0 : xs = scsi_xs_get(sc->sc_link, 0);
1468 0 : if (xs == NULL)
1469 0 : return (ENOMEM);
1470 0 : xs->cmdlen = sizeof(*cmd);
1471 0 : xs->timeout = 2000;
1472 :
1473 0 : cmd = (struct scsi_pause *)xs->cmd;
1474 0 : cmd->opcode = PAUSE;
1475 0 : cmd->resume = go;
1476 :
1477 0 : error = scsi_xs_sync(xs);
1478 0 : scsi_xs_put(xs);
1479 :
1480 0 : return (error);
1481 0 : }
1482 :
1483 : /*
1484 : * Get scsi driver to send a "RESET" command
1485 : */
1486 : int
1487 0 : cd_reset(struct cd_softc *sc)
1488 : {
1489 : struct scsi_xfer *xs;
1490 : int error;
1491 :
1492 0 : xs = scsi_xs_get(sc->sc_link, SCSI_RESET);
1493 0 : if (xs == NULL)
1494 0 : return (ENOMEM);
1495 :
1496 0 : xs->timeout = 2000;
1497 :
1498 0 : error = scsi_xs_sync(xs);
1499 0 : scsi_xs_put(xs);
1500 :
1501 0 : return (error);
1502 0 : }
1503 :
1504 : /*
1505 : * Read subchannel
1506 : */
1507 : int
1508 0 : cd_read_subchannel(struct cd_softc *sc, int mode, int format, int track,
1509 : struct cd_sub_channel_info *data, int len)
1510 : {
1511 : struct scsi_read_subchannel *cmd;
1512 : struct scsi_xfer *xs;
1513 : int error;
1514 :
1515 0 : xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN | SCSI_SILENT);
1516 0 : if (xs == NULL)
1517 0 : return (ENOMEM);
1518 0 : xs->cmdlen = sizeof(*cmd);
1519 0 : xs->data = (void *)data;
1520 0 : xs->datalen = len;
1521 0 : xs->timeout = 5000;
1522 :
1523 0 : cmd = (struct scsi_read_subchannel *)xs->cmd;
1524 0 : cmd->opcode = READ_SUBCHANNEL;
1525 0 : if (mode == CD_MSF_FORMAT)
1526 0 : cmd->byte2 |= CD_MSF;
1527 0 : cmd->byte3 = SRS_SUBQ;
1528 0 : cmd->subchan_format = format;
1529 0 : cmd->track = track;
1530 0 : _lto2b(len, cmd->data_len);
1531 :
1532 0 : error = scsi_xs_sync(xs);
1533 0 : scsi_xs_put(xs);
1534 :
1535 0 : return (error);
1536 0 : }
1537 :
1538 : /*
1539 : * Read table of contents
1540 : */
1541 : int
1542 0 : cd_read_toc(struct cd_softc *sc, int mode, int start, void *data, int len,
1543 : int control)
1544 : {
1545 : struct scsi_read_toc *cmd;
1546 : struct scsi_xfer *xs;
1547 : int error;
1548 :
1549 0 : xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN |
1550 : SCSI_IGNORE_ILLEGAL_REQUEST);
1551 0 : if (xs == NULL)
1552 0 : return (ENOMEM);
1553 0 : xs->cmdlen = sizeof(*cmd);
1554 0 : xs->data = data;
1555 0 : xs->datalen = len;
1556 0 : xs->timeout = 5000;
1557 :
1558 0 : bzero(data, len);
1559 :
1560 0 : cmd = (struct scsi_read_toc *)xs->cmd;
1561 0 : cmd->opcode = READ_TOC;
1562 :
1563 0 : if (mode == CD_MSF_FORMAT)
1564 0 : cmd->byte2 |= CD_MSF;
1565 0 : cmd->from_track = start;
1566 0 : _lto2b(len, cmd->data_len);
1567 0 : cmd->control = control;
1568 :
1569 0 : error = scsi_xs_sync(xs);
1570 0 : scsi_xs_put(xs);
1571 :
1572 0 : return (error);
1573 0 : }
1574 :
1575 : int
1576 0 : cd_load_toc(struct cd_softc *sc, struct cd_toc *toc, int fmt)
1577 : {
1578 : int n, len, error;
1579 :
1580 0 : error = cd_read_toc(sc, 0, 0, toc, sizeof(toc->header), 0);
1581 :
1582 0 : if (error == 0) {
1583 0 : if (toc->header.ending_track < toc->header.starting_track)
1584 0 : return (EIO);
1585 : /* +2 to account for leading out track. */
1586 0 : n = toc->header.ending_track - toc->header.starting_track + 2;
1587 0 : len = n * sizeof(struct cd_toc_entry) + sizeof(toc->header);
1588 0 : error = cd_read_toc(sc, fmt, 0, toc, len, 0);
1589 0 : }
1590 :
1591 0 : return (error);
1592 0 : }
1593 :
1594 :
1595 : /*
1596 : * Get the scsi driver to send a full inquiry to the device and use the
1597 : * results to fill out the disk parameter structure.
1598 : */
1599 : int
1600 0 : cd_get_parms(struct cd_softc *sc, int flags)
1601 : {
1602 : /* Reasonable defaults for drives that don't support READ_CAPACITY */
1603 0 : sc->params.secsize = 2048;
1604 0 : sc->params.disksize = 400000;
1605 :
1606 0 : if (sc->sc_link->quirks & ADEV_NOCAPACITY)
1607 0 : return (0);
1608 :
1609 0 : sc->params.disksize = cd_size(sc->sc_link, flags, &sc->params.secsize);
1610 :
1611 0 : if ((sc->params.secsize < 512) ||
1612 0 : ((sc->params.secsize & 511) != 0))
1613 0 : sc->params.secsize = 2048; /* some drives lie ! */
1614 :
1615 0 : if (sc->params.disksize < 100)
1616 0 : sc->params.disksize = 400000;
1617 :
1618 0 : return (0);
1619 0 : }
1620 :
1621 : daddr_t
1622 0 : cdsize(dev_t dev)
1623 : {
1624 :
1625 : /* CD-ROMs are read-only. */
1626 0 : return -1;
1627 : }
1628 :
1629 : int
1630 0 : cddump(dev_t dev, daddr_t blkno, caddr_t va, size_t size)
1631 : {
1632 : /* Not implemented. */
1633 0 : return ENXIO;
1634 : }
1635 :
1636 : #define dvd_copy_key(dst, src) memcpy((dst), (src), DVD_KEY_SIZE)
1637 : #define dvd_copy_challenge(dst, src) memcpy((dst), (src), DVD_CHALLENGE_SIZE)
1638 :
1639 : #define DVD_AUTH_BUFSIZE 20
1640 :
1641 : int
1642 0 : dvd_auth(struct cd_softc *sc, union dvd_authinfo *a)
1643 : {
1644 : struct scsi_generic *cmd;
1645 : struct scsi_xfer *xs;
1646 : u_int8_t *buf;
1647 : int error;
1648 :
1649 0 : buf = dma_alloc(DVD_AUTH_BUFSIZE, PR_WAITOK | PR_ZERO);
1650 0 : if (buf == NULL)
1651 0 : return (ENOMEM);
1652 :
1653 0 : xs = scsi_xs_get(sc->sc_link, 0);
1654 0 : if (xs == NULL) {
1655 : error = ENOMEM;
1656 0 : goto done;
1657 : }
1658 0 : xs->cmdlen = sizeof(*cmd);
1659 0 : xs->timeout = 30000;
1660 0 : xs->data = buf;
1661 :
1662 0 : cmd = xs->cmd;
1663 :
1664 0 : switch (a->type) {
1665 : case DVD_LU_SEND_AGID:
1666 0 : cmd->opcode = GPCMD_REPORT_KEY;
1667 0 : cmd->bytes[8] = 8;
1668 0 : cmd->bytes[9] = 0 | (0 << 6);
1669 0 : xs->datalen = 8;
1670 0 : xs->flags |= SCSI_DATA_IN;
1671 :
1672 0 : error = scsi_xs_sync(xs);
1673 0 : scsi_xs_put(xs);
1674 :
1675 0 : if (error == 0)
1676 0 : a->lsa.agid = buf[7] >> 6;
1677 : break;
1678 :
1679 : case DVD_LU_SEND_CHALLENGE:
1680 0 : cmd->opcode = GPCMD_REPORT_KEY;
1681 0 : cmd->bytes[8] = 16;
1682 0 : cmd->bytes[9] = 1 | (a->lsc.agid << 6);
1683 0 : xs->datalen = 16;
1684 0 : xs->flags |= SCSI_DATA_IN;
1685 :
1686 0 : error = scsi_xs_sync(xs);
1687 0 : scsi_xs_put(xs);
1688 0 : if (error == 0)
1689 0 : dvd_copy_challenge(a->lsc.chal, &buf[4]);
1690 : break;
1691 :
1692 : case DVD_LU_SEND_KEY1:
1693 0 : cmd->opcode = GPCMD_REPORT_KEY;
1694 0 : cmd->bytes[8] = 12;
1695 0 : cmd->bytes[9] = 2 | (a->lsk.agid << 6);
1696 0 : xs->datalen = 12;
1697 0 : xs->flags |= SCSI_DATA_IN;
1698 :
1699 0 : error = scsi_xs_sync(xs);
1700 0 : scsi_xs_put(xs);
1701 :
1702 0 : if (error == 0)
1703 0 : dvd_copy_key(a->lsk.key, &buf[4]);
1704 : break;
1705 :
1706 : case DVD_LU_SEND_TITLE_KEY:
1707 0 : cmd->opcode = GPCMD_REPORT_KEY;
1708 0 : _lto4b(a->lstk.lba, &cmd->bytes[1]);
1709 0 : cmd->bytes[8] = 12;
1710 0 : cmd->bytes[9] = 4 | (a->lstk.agid << 6);
1711 0 : xs->datalen = 12;
1712 0 : xs->flags |= SCSI_DATA_IN;
1713 :
1714 0 : error = scsi_xs_sync(xs);
1715 0 : scsi_xs_put(xs);
1716 :
1717 0 : if (error == 0) {
1718 0 : a->lstk.cpm = (buf[4] >> 7) & 1;
1719 0 : a->lstk.cp_sec = (buf[4] >> 6) & 1;
1720 0 : a->lstk.cgms = (buf[4] >> 4) & 3;
1721 0 : dvd_copy_key(a->lstk.title_key, &buf[5]);
1722 0 : }
1723 : break;
1724 :
1725 : case DVD_LU_SEND_ASF:
1726 0 : cmd->opcode = GPCMD_REPORT_KEY;
1727 0 : cmd->bytes[8] = 8;
1728 0 : cmd->bytes[9] = 5 | (a->lsasf.agid << 6);
1729 0 : xs->datalen = 8;
1730 0 : xs->flags |= SCSI_DATA_IN;
1731 :
1732 0 : error = scsi_xs_sync(xs);
1733 0 : scsi_xs_put(xs);
1734 :
1735 0 : if (error == 0)
1736 0 : a->lsasf.asf = buf[7] & 1;
1737 : break;
1738 :
1739 : case DVD_HOST_SEND_CHALLENGE:
1740 0 : cmd->opcode = GPCMD_SEND_KEY;
1741 0 : cmd->bytes[8] = 16;
1742 0 : cmd->bytes[9] = 1 | (a->hsc.agid << 6);
1743 0 : buf[1] = 14;
1744 0 : dvd_copy_challenge(&buf[4], a->hsc.chal);
1745 0 : xs->datalen = 16;
1746 0 : xs->flags |= SCSI_DATA_OUT;
1747 :
1748 0 : error = scsi_xs_sync(xs);
1749 0 : scsi_xs_put(xs);
1750 :
1751 0 : if (error == 0)
1752 0 : a->type = DVD_LU_SEND_KEY1;
1753 : break;
1754 :
1755 : case DVD_HOST_SEND_KEY2:
1756 0 : cmd->opcode = GPCMD_SEND_KEY;
1757 0 : cmd->bytes[8] = 12;
1758 0 : cmd->bytes[9] = 3 | (a->hsk.agid << 6);
1759 0 : buf[1] = 10;
1760 0 : dvd_copy_key(&buf[4], a->hsk.key);
1761 0 : xs->datalen = 12;
1762 0 : xs->flags |= SCSI_DATA_OUT;
1763 :
1764 0 : error = scsi_xs_sync(xs);
1765 0 : scsi_xs_put(xs);
1766 :
1767 0 : if (error == 0)
1768 0 : a->type = DVD_AUTH_ESTABLISHED;
1769 : else
1770 0 : a->type = DVD_AUTH_FAILURE;
1771 : break;
1772 :
1773 : case DVD_INVALIDATE_AGID:
1774 0 : cmd->opcode = GPCMD_REPORT_KEY;
1775 0 : cmd->bytes[9] = 0x3f | (a->lsa.agid << 6);
1776 0 : xs->data = NULL;
1777 :
1778 0 : error = scsi_xs_sync(xs);
1779 0 : scsi_xs_put(xs);
1780 0 : break;
1781 :
1782 : case DVD_LU_SEND_RPC_STATE:
1783 0 : cmd->opcode = GPCMD_REPORT_KEY;
1784 0 : cmd->bytes[8] = 8;
1785 0 : cmd->bytes[9] = 8 | (0 << 6);
1786 0 : xs->datalen = 8;
1787 0 : xs->flags |= SCSI_DATA_IN;
1788 :
1789 0 : error = scsi_xs_sync(xs);
1790 0 : scsi_xs_put(xs);
1791 :
1792 0 : if (error == 0) {
1793 0 : a->lrpcs.type = (buf[4] >> 6) & 3;
1794 0 : a->lrpcs.vra = (buf[4] >> 3) & 7;
1795 0 : a->lrpcs.ucca = (buf[4]) & 7;
1796 0 : a->lrpcs.region_mask = buf[5];
1797 0 : a->lrpcs.rpc_scheme = buf[6];
1798 0 : }
1799 : break;
1800 :
1801 : case DVD_HOST_SEND_RPC_STATE:
1802 0 : cmd->opcode = GPCMD_SEND_KEY;
1803 0 : cmd->bytes[8] = 8;
1804 0 : cmd->bytes[9] = 6 | (0 << 6);
1805 0 : buf[1] = 6;
1806 0 : buf[4] = a->hrpcs.pdrc;
1807 0 : xs->datalen = 8;
1808 0 : xs->flags |= SCSI_DATA_OUT;
1809 :
1810 0 : error = scsi_xs_sync(xs);
1811 0 : scsi_xs_put(xs);
1812 0 : break;
1813 :
1814 : default:
1815 0 : scsi_xs_put(xs);
1816 : error = ENOTTY;
1817 0 : break;
1818 : }
1819 : done:
1820 0 : dma_free(buf, DVD_AUTH_BUFSIZE);
1821 0 : return (error);
1822 0 : }
1823 :
1824 : #define DVD_READ_PHYSICAL_BUFSIZE (4 + 4 * 20)
1825 : int
1826 0 : dvd_read_physical(struct cd_softc *sc, union dvd_struct *s)
1827 : {
1828 : struct scsi_generic *cmd;
1829 : struct dvd_layer *layer;
1830 : struct scsi_xfer *xs;
1831 : u_int8_t *buf, *bufp;
1832 : int error, i;
1833 :
1834 0 : buf = dma_alloc(DVD_READ_PHYSICAL_BUFSIZE, PR_WAITOK | PR_ZERO);
1835 0 : if (buf == NULL)
1836 0 : return (ENOMEM);
1837 :
1838 0 : xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN);
1839 0 : if (xs == NULL) {
1840 : error = ENOMEM;
1841 0 : goto done;
1842 : }
1843 0 : xs->cmdlen = sizeof(*cmd);
1844 0 : xs->data = buf;
1845 0 : xs->datalen = DVD_READ_PHYSICAL_BUFSIZE;
1846 0 : xs->timeout = 30000;
1847 :
1848 0 : cmd = xs->cmd;
1849 0 : cmd->opcode = GPCMD_READ_DVD_STRUCTURE;
1850 0 : cmd->bytes[6] = s->type;
1851 0 : _lto2b(xs->datalen, &cmd->bytes[7]);
1852 :
1853 0 : cmd->bytes[5] = s->physical.layer_num;
1854 :
1855 0 : error = scsi_xs_sync(xs);
1856 0 : scsi_xs_put(xs);
1857 :
1858 0 : if (error == 0) {
1859 0 : for (i = 0, bufp = &buf[4], layer = &s->physical.layer[0];
1860 0 : i < 4; i++, bufp += 20, layer++) {
1861 0 : bzero(layer, sizeof(*layer));
1862 0 : layer->book_version = bufp[0] & 0xf;
1863 0 : layer->book_type = bufp[0] >> 4;
1864 0 : layer->min_rate = bufp[1] & 0xf;
1865 0 : layer->disc_size = bufp[1] >> 4;
1866 0 : layer->layer_type = bufp[2] & 0xf;
1867 0 : layer->track_path = (bufp[2] >> 4) & 1;
1868 0 : layer->nlayers = (bufp[2] >> 5) & 3;
1869 0 : layer->track_density = bufp[3] & 0xf;
1870 0 : layer->linear_density = bufp[3] >> 4;
1871 0 : layer->start_sector = _4btol(&bufp[4]);
1872 0 : layer->end_sector = _4btol(&bufp[8]);
1873 0 : layer->end_sector_l0 = _4btol(&bufp[12]);
1874 0 : layer->bca = bufp[16] >> 7;
1875 : }
1876 : }
1877 : done:
1878 0 : dma_free(buf, DVD_READ_PHYSICAL_BUFSIZE);
1879 0 : return (error);
1880 0 : }
1881 :
1882 : #define DVD_READ_COPYRIGHT_BUFSIZE 8
1883 : int
1884 0 : dvd_read_copyright(struct cd_softc *sc, union dvd_struct *s)
1885 : {
1886 : struct scsi_generic *cmd;
1887 : struct scsi_xfer *xs;
1888 : u_int8_t *buf;
1889 : int error;
1890 :
1891 0 : buf = dma_alloc(DVD_READ_COPYRIGHT_BUFSIZE, PR_WAITOK | PR_ZERO);
1892 0 : if (buf == NULL)
1893 0 : return (ENOMEM);
1894 :
1895 0 : xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN);
1896 0 : if (xs == NULL) {
1897 : error = ENOMEM;
1898 0 : goto done;
1899 : }
1900 0 : xs->cmdlen = sizeof(*cmd);
1901 0 : xs->data = buf;
1902 0 : xs->datalen = DVD_READ_COPYRIGHT_BUFSIZE;
1903 0 : xs->timeout = 30000;
1904 :
1905 0 : cmd = xs->cmd;
1906 0 : cmd->opcode = GPCMD_READ_DVD_STRUCTURE;
1907 0 : cmd->bytes[6] = s->type;
1908 0 : _lto2b(xs->datalen, &cmd->bytes[7]);
1909 :
1910 0 : cmd->bytes[5] = s->copyright.layer_num;
1911 :
1912 0 : error = scsi_xs_sync(xs);
1913 0 : scsi_xs_put(xs);
1914 :
1915 0 : if (error == 0) {
1916 0 : s->copyright.cpst = buf[4];
1917 0 : s->copyright.rmi = buf[5];
1918 0 : }
1919 : done:
1920 0 : dma_free(buf, DVD_READ_COPYRIGHT_BUFSIZE);
1921 0 : return (error);
1922 0 : }
1923 :
1924 : int
1925 0 : dvd_read_disckey(struct cd_softc *sc, union dvd_struct *s)
1926 : {
1927 : struct scsi_read_dvd_structure_data *buf;
1928 : struct scsi_read_dvd_structure *cmd;
1929 : struct scsi_xfer *xs;
1930 : int error;
1931 :
1932 0 : buf = dma_alloc(sizeof(*buf), PR_WAITOK | PR_ZERO);
1933 0 : if (buf == NULL)
1934 0 : return (ENOMEM);
1935 :
1936 0 : xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN);
1937 0 : if (xs == NULL) {
1938 : error = ENOMEM;
1939 0 : goto done;
1940 : }
1941 0 : xs->cmdlen = sizeof(*cmd);
1942 0 : xs->data = (void *)buf;
1943 0 : xs->datalen = sizeof(*buf);
1944 0 : xs->timeout = 30000;
1945 :
1946 0 : cmd = (struct scsi_read_dvd_structure *)xs->cmd;
1947 0 : cmd->opcode = GPCMD_READ_DVD_STRUCTURE;
1948 0 : cmd->format = s->type;
1949 0 : cmd->agid = s->disckey.agid << 6;
1950 0 : _lto2b(xs->datalen, cmd->length);
1951 :
1952 0 : error = scsi_xs_sync(xs);
1953 0 : scsi_xs_put(xs);
1954 :
1955 0 : if (error == 0)
1956 0 : memcpy(s->disckey.value, buf->data, sizeof(s->disckey.value));
1957 : done:
1958 0 : dma_free(buf, sizeof(*buf));
1959 0 : return (error);
1960 0 : }
1961 :
1962 : #define DVD_READ_BCA_BUFLEN (4 + 188)
1963 :
1964 : int
1965 0 : dvd_read_bca(struct cd_softc *sc, union dvd_struct *s)
1966 : {
1967 : struct scsi_generic *cmd;
1968 : struct scsi_xfer *xs;
1969 : u_int8_t *buf;
1970 : int error;
1971 :
1972 0 : buf = dma_alloc(DVD_READ_BCA_BUFLEN, PR_WAITOK | PR_ZERO);
1973 0 : if (buf == NULL)
1974 0 : return (ENOMEM);
1975 :
1976 0 : xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN);
1977 0 : if (xs == NULL) {
1978 : error = ENOMEM;
1979 0 : goto done;
1980 : }
1981 0 : xs->cmdlen = sizeof(*cmd);
1982 0 : xs->data = buf;
1983 0 : xs->datalen = DVD_READ_BCA_BUFLEN;
1984 0 : xs->timeout = 30000;
1985 :
1986 0 : cmd = xs->cmd;
1987 0 : cmd->opcode = GPCMD_READ_DVD_STRUCTURE;
1988 0 : cmd->bytes[6] = s->type;
1989 0 : _lto2b(xs->datalen, &cmd->bytes[7]);
1990 :
1991 0 : error = scsi_xs_sync(xs);
1992 0 : scsi_xs_put(xs);
1993 :
1994 0 : if (error == 0) {
1995 0 : s->bca.len = _2btol(&buf[0]);
1996 0 : if (s->bca.len < 12 || s->bca.len > 188)
1997 0 : return (EIO);
1998 0 : memcpy(s->bca.value, &buf[4], s->bca.len);
1999 0 : }
2000 : done:
2001 0 : dma_free(buf, DVD_READ_BCA_BUFLEN);
2002 0 : return (error);
2003 0 : }
2004 :
2005 : int
2006 0 : dvd_read_manufact(struct cd_softc *sc, union dvd_struct *s)
2007 : {
2008 : struct scsi_read_dvd_structure_data *buf;
2009 : struct scsi_read_dvd_structure *cmd;
2010 : struct scsi_xfer *xs;
2011 : int error;
2012 :
2013 0 : buf = dma_alloc(sizeof(*buf), PR_WAITOK | PR_ZERO);
2014 0 : if (buf == NULL)
2015 0 : return (ENOMEM);
2016 :
2017 0 : xs = scsi_xs_get(sc->sc_link, SCSI_DATA_IN);
2018 0 : if (xs == NULL) {
2019 : error = ENOMEM;
2020 0 : goto done;
2021 : }
2022 0 : xs->cmdlen = sizeof(*cmd);
2023 0 : xs->data = (void *)buf;
2024 0 : xs->datalen = sizeof(*buf);
2025 0 : xs->timeout = 30000;
2026 :
2027 0 : cmd = (struct scsi_read_dvd_structure *)xs->cmd;
2028 0 : cmd->opcode = GPCMD_READ_DVD_STRUCTURE;
2029 0 : cmd->format = s->type;
2030 0 : _lto2b(xs->datalen, cmd->length);
2031 :
2032 0 : error = scsi_xs_sync(xs);
2033 0 : scsi_xs_put(xs);
2034 :
2035 0 : if (error == 0) {
2036 0 : s->manufact.len = _2btol(buf->len);
2037 0 : if (s->manufact.len >= 0 && s->manufact.len <= 2048)
2038 0 : memcpy(s->manufact.value, buf->data, s->manufact.len);
2039 : else
2040 : error = EIO;
2041 : }
2042 : done:
2043 0 : dma_free(buf, sizeof(*buf));
2044 0 : return (error);
2045 0 : }
2046 :
2047 : int
2048 0 : dvd_read_struct(struct cd_softc *sc, union dvd_struct *s)
2049 : {
2050 :
2051 0 : switch (s->type) {
2052 : case DVD_STRUCT_PHYSICAL:
2053 0 : return (dvd_read_physical(sc, s));
2054 : case DVD_STRUCT_COPYRIGHT:
2055 0 : return (dvd_read_copyright(sc, s));
2056 : case DVD_STRUCT_DISCKEY:
2057 0 : return (dvd_read_disckey(sc, s));
2058 : case DVD_STRUCT_BCA:
2059 0 : return (dvd_read_bca(sc, s));
2060 : case DVD_STRUCT_MANUFACT:
2061 0 : return (dvd_read_manufact(sc, s));
2062 : default:
2063 0 : return (EINVAL);
2064 : }
2065 0 : }
2066 :
2067 : int
2068 0 : cd_interpret_sense(struct scsi_xfer *xs)
2069 : {
2070 0 : struct scsi_sense_data *sense = &xs->sense;
2071 0 : struct scsi_link *link = xs->sc_link;
2072 0 : u_int8_t skey = sense->flags & SSD_KEY;
2073 0 : u_int8_t serr = sense->error_code & SSD_ERRCODE;
2074 :
2075 0 : if (((link->flags & SDEV_OPEN) == 0) ||
2076 0 : (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED))
2077 0 : return (scsi_interpret_sense(xs));
2078 :
2079 : /*
2080 : * We do custom processing in cd for the unit becoming ready
2081 : * case. We do not allow xs->retries to be decremented on the
2082 : * "Unit Becoming Ready" case. This is because CD drives
2083 : * report "Unit Becoming Ready" when loading media and can
2084 : * take a long time. Rather than having a massive timeout for
2085 : * all operations (which would cause other problems), we allow
2086 : * operations to wait (but be interruptable with Ctrl-C)
2087 : * forever as long as the drive is reporting that it is
2088 : * becoming ready. All other cases of not being ready are
2089 : * handled by the default handler.
2090 : */
2091 0 : switch(skey) {
2092 : case SKEY_NOT_READY:
2093 0 : if ((xs->flags & SCSI_IGNORE_NOT_READY) != 0)
2094 0 : return (0);
2095 0 : if (ASC_ASCQ(sense) == SENSE_NOT_READY_BECOMING_READY) {
2096 : SC_DEBUG(link, SDEV_DB1, ("not ready: busy (%#x)\n",
2097 : sense->add_sense_code_qual));
2098 : /* don't count this as a retry */
2099 0 : xs->retries++;
2100 0 : return (scsi_delay(xs, 1));
2101 : }
2102 : break;
2103 : /* XXX more to come here for a few other cases */
2104 : default:
2105 : break;
2106 : }
2107 0 : return (scsi_interpret_sense(xs));
2108 0 : }
2109 :
2110 : /*
2111 : * Find out from the device what its capacity is.
2112 : */
2113 : u_int64_t
2114 0 : cd_size(struct scsi_link *link, int flags, u_int32_t *blksize)
2115 : {
2116 : struct scsi_read_cap_data_16 *rdcap16;
2117 : struct scsi_read_capacity_16 *cmd;
2118 : struct scsi_read_cap_data *rdcap;
2119 : struct scsi_read_capacity *cmd10;
2120 : struct scsi_xfer *xs;
2121 : u_int64_t max_addr;
2122 : int error;
2123 :
2124 0 : if (blksize != NULL)
2125 0 : *blksize = 0;
2126 :
2127 0 : CLR(flags, SCSI_IGNORE_ILLEGAL_REQUEST);
2128 :
2129 : /*
2130 : * Start with a READ CAPACITY(10).
2131 : */
2132 0 : rdcap = dma_alloc(sizeof(*rdcap), ((flags & SCSI_NOSLEEP) ?
2133 0 : PR_NOWAIT : PR_WAITOK) | PR_ZERO);
2134 0 : if (rdcap == NULL)
2135 0 : return (0);
2136 :
2137 0 : xs = scsi_xs_get(link, flags | SCSI_DATA_IN | SCSI_SILENT);
2138 0 : if (xs == NULL) {
2139 0 : dma_free(rdcap, sizeof(*rdcap));
2140 0 : return (0);
2141 : }
2142 0 : xs->cmdlen = sizeof(*cmd10);
2143 0 : xs->data = (void *)rdcap;
2144 0 : xs->datalen = sizeof(*rdcap);
2145 0 : xs->timeout = 20000;
2146 :
2147 0 : cmd10 = (struct scsi_read_capacity *)xs->cmd;
2148 0 : cmd10->opcode = READ_CAPACITY;
2149 :
2150 0 : error = scsi_xs_sync(xs);
2151 0 : scsi_xs_put(xs);
2152 :
2153 0 : if (error) {
2154 : SC_DEBUG(link, SDEV_DB1, ("READ CAPACITY error (%#x)\n",
2155 : error));
2156 0 : dma_free(rdcap, sizeof(*rdcap));
2157 0 : return (0);
2158 : }
2159 :
2160 0 : max_addr = _4btol(rdcap->addr);
2161 0 : if (blksize != NULL)
2162 0 : *blksize = _4btol(rdcap->length);
2163 0 : dma_free(rdcap, sizeof(*rdcap));
2164 :
2165 0 : if (SCSISPC(link->inqdata.version) < 3 && max_addr != 0xffffffff)
2166 : goto exit;
2167 :
2168 : /*
2169 : * SCSI-3 devices, or devices reporting more than 2^32-1 sectors can
2170 : * try READ CAPACITY(16).
2171 : */
2172 0 : rdcap16 = dma_alloc(sizeof(*rdcap16), ((flags & SCSI_NOSLEEP) ?
2173 : PR_NOWAIT : PR_WAITOK) | PR_ZERO);
2174 0 : if (rdcap16 == NULL)
2175 : goto exit;
2176 :
2177 0 : xs = scsi_xs_get(link, flags | SCSI_DATA_IN | SCSI_SILENT);
2178 0 : if (xs == NULL) {
2179 0 : dma_free(rdcap16, sizeof(*rdcap16));
2180 0 : goto exit;
2181 : }
2182 0 : xs->cmdlen = sizeof(*cmd);
2183 0 : xs->data = (void *)rdcap16;
2184 0 : xs->datalen = sizeof(*rdcap16);
2185 0 : xs->timeout = 20000;
2186 :
2187 0 : cmd = (struct scsi_read_capacity_16 *)xs->cmd;
2188 0 : cmd->opcode = READ_CAPACITY_16;
2189 0 : cmd->byte2 = SRC16_SERVICE_ACTION;
2190 0 : _lto4b(sizeof(*rdcap16), cmd->length);
2191 :
2192 0 : error = scsi_xs_sync(xs);
2193 0 : scsi_xs_put(xs);
2194 0 : if (error) {
2195 : SC_DEBUG(link, SDEV_DB1, ("READ CAPACITY 16 error (%#x)\n",
2196 : error));
2197 0 : dma_free(rdcap16, sizeof(*rdcap16));
2198 0 : goto exit;
2199 : }
2200 :
2201 0 : max_addr = _8btol(rdcap16->addr);
2202 0 : if (blksize != NULL)
2203 0 : *blksize = _4btol(rdcap16->length);
2204 : /* XXX The other READ CAPACITY(16) info could be stored away. */
2205 0 : dma_free(rdcap16, sizeof(*rdcap16));
2206 :
2207 0 : return (max_addr + 1);
2208 :
2209 : exit:
2210 : /* Return READ CAPACITY 10 values. */
2211 0 : if (max_addr != 0xffffffff)
2212 0 : return (max_addr + 1);
2213 0 : else if (blksize != NULL)
2214 0 : *blksize = 0;
2215 0 : return (0);
2216 0 : }
2217 :
2218 : #if defined(__macppc__)
2219 : int
2220 : cd_eject(void)
2221 : {
2222 : struct cd_softc *sc;
2223 : int error = 0;
2224 :
2225 : if (cd_cd.cd_ndevs == 0 || (sc = cd_cd.cd_devs[0]) == NULL)
2226 : return (ENXIO);
2227 :
2228 : if ((error = disk_lock(&sc->sc_dk)) != 0)
2229 : return (error);
2230 :
2231 : if (sc->sc_dk.dk_openmask == 0) {
2232 : sc->sc_link->flags |= SDEV_EJECTING;
2233 :
2234 : scsi_prevent(sc->sc_link, PR_ALLOW,
2235 : SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY |
2236 : SCSI_SILENT | SCSI_IGNORE_MEDIA_CHANGE);
2237 : sc->sc_link->flags &= ~SDEV_MEDIA_LOADED;
2238 :
2239 : scsi_start(sc->sc_link, SSS_STOP|SSS_LOEJ, 0);
2240 :
2241 : sc->sc_link->flags &= ~SDEV_EJECTING;
2242 : }
2243 : disk_unlock(&sc->sc_dk);
2244 :
2245 : return (error);
2246 : }
2247 : #endif
|