Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/cam/scsi/scsi_cd.c
39482 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 1997 Justin T. Gibbs.
5
* Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Kenneth D. Merry.
6
* All rights reserved.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions, and the following disclaimer,
13
* without modification, immediately at the beginning of the file.
14
* 2. The name of the author may not be used to endorse or promote products
15
* derived from this software without specific prior written permission.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
/*-
31
* Portions of this driver taken from the original FreeBSD cd driver.
32
* Written by Julian Elischer ([email protected])
33
* for TRW Financial Systems for use under the MACH(2.5) operating system.
34
*
35
* TRW Financial Systems, in accordance with their agreement with Carnegie
36
* Mellon University, makes this software available to CMU to distribute
37
* or use in any manner that they see fit as long as this message is kept with
38
* the software. For this reason TFS also grants any other persons or
39
* organisations permission to use or modify this software.
40
*
41
* TFS supplies this software to be publicly redistributed
42
* on the understanding that TFS is not responsible for the correct
43
* functioning of this software in any circumstances.
44
*
45
* Ported to run under 386BSD by Julian Elischer ([email protected]) Sept 1992
46
*
47
* from: cd.c,v 1.83 1997/05/04 15:24:22 joerg Exp $
48
*/
49
50
#include "opt_cd.h"
51
52
#include <sys/param.h>
53
#include <sys/systm.h>
54
#include <sys/kernel.h>
55
#include <sys/bio.h>
56
#include <sys/conf.h>
57
#include <sys/disk.h>
58
#include <sys/malloc.h>
59
#include <sys/cdio.h>
60
#include <sys/cdrio.h>
61
#include <sys/dvdio.h>
62
#include <sys/devicestat.h>
63
#include <sys/proc.h>
64
#include <sys/sbuf.h>
65
#include <sys/sysctl.h>
66
#include <sys/taskqueue.h>
67
#include <geom/geom_disk.h>
68
69
#include <cam/cam.h>
70
#include <cam/cam_ccb.h>
71
#include <cam/cam_periph.h>
72
#include <cam/cam_xpt_periph.h>
73
#include <cam/cam_queue.h>
74
#include <cam/cam_sim.h>
75
76
#include <cam/scsi/scsi_message.h>
77
#include <cam/scsi/scsi_da.h>
78
#include <cam/scsi/scsi_cd.h>
79
80
#define LEADOUT 0xaa /* leadout toc entry */
81
82
struct cd_params {
83
uint32_t blksize;
84
u_long disksize;
85
};
86
87
typedef enum {
88
CD_Q_NONE = 0x00,
89
CD_Q_NO_TOUCH = 0x01,
90
CD_Q_BCD_TRACKS = 0x02,
91
CD_Q_10_BYTE_ONLY = 0x10,
92
CD_Q_RETRY_BUSY = 0x40
93
} cd_quirks;
94
95
#define CD_Q_BIT_STRING \
96
"\020" \
97
"\001NO_TOUCH" \
98
"\002BCD_TRACKS" \
99
"\00510_BYTE_ONLY" \
100
"\007RETRY_BUSY"
101
102
typedef enum {
103
CD_FLAG_NEW_DISC = 0x0002,
104
CD_FLAG_DISC_LOCKED = 0x0004,
105
CD_FLAG_DISC_REMOVABLE = 0x0008,
106
CD_FLAG_ACTIVE = 0x0080,
107
CD_FLAG_SCHED_ON_COMP = 0x0100,
108
CD_FLAG_RETRY_UA = 0x0200,
109
CD_FLAG_VALID_MEDIA = 0x0400,
110
CD_FLAG_VALID_TOC = 0x0800,
111
CD_FLAG_SCTX_INIT = 0x1000,
112
CD_FLAG_MEDIA_WAIT = 0x2000,
113
CD_FLAG_MEDIA_SCAN_ACT = 0x4000
114
} cd_flags;
115
116
typedef enum {
117
CD_CCB_PROBE = 0x01,
118
CD_CCB_BUFFER_IO = 0x02,
119
CD_CCB_TUR = 0x03,
120
CD_CCB_MEDIA_PREVENT = 0x04,
121
CD_CCB_MEDIA_ALLOW = 0x05,
122
CD_CCB_MEDIA_SIZE = 0x06,
123
CD_CCB_MEDIA_TOC_HDR = 0x07,
124
CD_CCB_MEDIA_TOC_FULL = 0x08,
125
CD_CCB_MEDIA_TOC_LEAD = 0x09,
126
CD_CCB_TYPE_MASK = 0x0F,
127
CD_CCB_RETRY_UA = 0x10
128
} cd_ccb_state;
129
130
#define ccb_state ppriv_field0
131
#define ccb_bp ppriv_ptr1
132
133
/*
134
* According to the MMC-6 spec, 6.25.3.2.11, the lead-out is reported by
135
* READ_TOC as logical track 170, so at most 169 tracks may be reported.
136
*/
137
struct cd_tocdata {
138
struct ioc_toc_header header;
139
struct cd_toc_entry entries[170];
140
};
141
142
struct cd_toc_single {
143
struct ioc_toc_header header;
144
struct cd_toc_entry entry;
145
};
146
147
typedef enum {
148
CD_STATE_PROBE,
149
CD_STATE_NORMAL,
150
CD_STATE_MEDIA_PREVENT,
151
CD_STATE_MEDIA_ALLOW,
152
CD_STATE_MEDIA_SIZE,
153
CD_STATE_MEDIA_TOC_HDR,
154
CD_STATE_MEDIA_TOC_FULL,
155
CD_STATE_MEDIA_TOC_LEAD
156
} cd_state;
157
158
struct cd_softc {
159
cam_pinfo pinfo;
160
cd_state state;
161
volatile cd_flags flags;
162
struct bio_queue_head bio_queue;
163
LIST_HEAD(, ccb_hdr) pending_ccbs;
164
struct cd_params params;
165
cd_quirks quirks;
166
struct cam_periph *periph;
167
int minimum_command_size;
168
int outstanding_cmds;
169
int tur;
170
struct task sysctl_task;
171
struct sysctl_ctx_list sysctl_ctx;
172
struct sysctl_oid *sysctl_tree;
173
STAILQ_HEAD(, cd_mode_params) mode_queue;
174
struct cd_tocdata toc;
175
int toc_read_len;
176
struct cd_toc_single leadout;
177
struct disk *disk;
178
struct callout mediapoll_c;
179
180
#define CD_ANNOUNCETMP_SZ 120
181
char announce_temp[CD_ANNOUNCETMP_SZ];
182
#define CD_ANNOUNCE_SZ 400
183
char announce_buf[CD_ANNOUNCE_SZ];
184
};
185
186
struct cd_page_sizes {
187
int page;
188
int page_size;
189
};
190
191
static struct cd_page_sizes cd_page_size_table[] =
192
{
193
{ AUDIO_PAGE, sizeof(struct cd_audio_page)}
194
};
195
196
struct cd_quirk_entry {
197
struct scsi_inquiry_pattern inq_pat;
198
cd_quirks quirks;
199
};
200
201
/*
202
* NOTE ON 10_BYTE_ONLY quirks: Any 10_BYTE_ONLY quirks MUST be because
203
* your device hangs when it gets a 10 byte command. Adding a quirk just
204
* to get rid of the informative diagnostic message is not acceptable. All
205
* 10_BYTE_ONLY quirks must be documented in full in a PR (which should be
206
* referenced in a comment along with the quirk) , and must be approved by
207
* [email protected]. Any quirks added that don't adhere to this policy may
208
* be removed until the submitter can explain why they are needed.
209
* 10_BYTE_ONLY quirks will be removed (as they will no longer be necessary)
210
* when the CAM_NEW_TRAN_CODE work is done.
211
*/
212
static struct cd_quirk_entry cd_quirk_table[] =
213
{
214
{
215
{ T_CDROM, SIP_MEDIA_REMOVABLE, "CHINON", "CD-ROM CDS-535","*"},
216
/* quirks */ CD_Q_BCD_TRACKS
217
},
218
{
219
/*
220
* VMware returns BUSY status when storage has transient
221
* connectivity problems, so better wait.
222
*/
223
{T_CDROM, SIP_MEDIA_REMOVABLE, "NECVMWar", "VMware IDE CDR10", "*"},
224
/*quirks*/ CD_Q_RETRY_BUSY
225
}
226
};
227
228
#ifdef COMPAT_FREEBSD32
229
struct ioc_read_toc_entry32 {
230
u_char address_format;
231
u_char starting_track;
232
u_short data_len;
233
uint32_t data; /* (struct cd_toc_entry *) */
234
};
235
#define CDIOREADTOCENTRYS_32 \
236
_IOC_NEWTYPE(CDIOREADTOCENTRYS, struct ioc_read_toc_entry32)
237
#endif
238
239
static disk_open_t cdopen;
240
static disk_close_t cdclose;
241
static disk_ioctl_t cdioctl;
242
static disk_strategy_t cdstrategy;
243
244
static periph_init_t cdinit;
245
static periph_ctor_t cdregister;
246
static periph_dtor_t cdcleanup;
247
static periph_start_t cdstart;
248
static periph_oninv_t cdoninvalidate;
249
static void cdasync(void *callback_arg, uint32_t code,
250
struct cam_path *path, void *arg);
251
static int cdcmdsizesysctl(SYSCTL_HANDLER_ARGS);
252
static int cdrunccb(union ccb *ccb,
253
int (*error_routine)(union ccb *ccb,
254
uint32_t cam_flags,
255
uint32_t sense_flags),
256
uint32_t cam_flags, uint32_t sense_flags);
257
static void cddone(struct cam_periph *periph,
258
union ccb *start_ccb);
259
static union cd_pages *cdgetpage(struct cd_mode_params *mode_params);
260
static int cdgetpagesize(int page_num);
261
static void cdprevent(struct cam_periph *periph, int action);
262
static void cdmediaprobedone(struct cam_periph *periph);
263
static int cdcheckmedia(struct cam_periph *periph, bool do_wait);
264
static int cd6byteworkaround(union ccb *ccb);
265
static int cderror(union ccb *ccb, uint32_t cam_flags,
266
uint32_t sense_flags);
267
static int cdreadtoc(struct cam_periph *periph, uint32_t mode,
268
uint32_t start, uint8_t *data,
269
uint32_t len, uint32_t sense_flags);
270
static int cdgetmode(struct cam_periph *periph,
271
struct cd_mode_params *data, uint32_t page);
272
static int cdsetmode(struct cam_periph *periph,
273
struct cd_mode_params *data);
274
static int cdplay(struct cam_periph *periph, uint32_t blk,
275
uint32_t len);
276
static int cdreadsubchannel(struct cam_periph *periph,
277
uint32_t mode, uint32_t format,
278
int track,
279
struct cd_sub_channel_info *data,
280
uint32_t len);
281
static int cdplaymsf(struct cam_periph *periph, uint32_t startm,
282
uint32_t starts, uint32_t startf,
283
uint32_t endm, uint32_t ends,
284
uint32_t endf);
285
static int cdplaytracks(struct cam_periph *periph,
286
uint32_t strack, uint32_t sindex,
287
uint32_t etrack, uint32_t eindex);
288
static int cdpause(struct cam_periph *periph, uint32_t go);
289
static int cdstopunit(struct cam_periph *periph, uint32_t eject);
290
static int cdstartunit(struct cam_periph *periph, int load);
291
static int cdsetspeed(struct cam_periph *periph,
292
uint32_t rdspeed, uint32_t wrspeed);
293
static int cdreportkey(struct cam_periph *periph,
294
struct dvd_authinfo *authinfo);
295
static int cdsendkey(struct cam_periph *periph,
296
struct dvd_authinfo *authinfo);
297
static int cdreaddvdstructure(struct cam_periph *periph,
298
struct dvd_struct *dvdstruct);
299
static callout_func_t cdmediapoll;
300
301
static struct periph_driver cddriver =
302
{
303
cdinit, "cd",
304
TAILQ_HEAD_INITIALIZER(cddriver.units), /* generation */ 0
305
};
306
307
PERIPHDRIVER_DECLARE(cd, cddriver);
308
309
#ifndef CD_DEFAULT_POLL_PERIOD
310
#define CD_DEFAULT_POLL_PERIOD 3
311
#endif
312
#ifndef CD_DEFAULT_RETRY
313
#define CD_DEFAULT_RETRY 4
314
#endif
315
#ifndef CD_DEFAULT_TIMEOUT
316
#define CD_DEFAULT_TIMEOUT 30000
317
#endif
318
319
static int cd_poll_period = CD_DEFAULT_POLL_PERIOD;
320
static int cd_retry_count = CD_DEFAULT_RETRY;
321
static int cd_timeout = CD_DEFAULT_TIMEOUT;
322
323
static SYSCTL_NODE(_kern_cam, OID_AUTO, cd, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
324
"CAM CDROM driver");
325
SYSCTL_INT(_kern_cam_cd, OID_AUTO, poll_period, CTLFLAG_RWTUN,
326
&cd_poll_period, 0, "Media polling period in seconds");
327
SYSCTL_INT(_kern_cam_cd, OID_AUTO, retry_count, CTLFLAG_RWTUN,
328
&cd_retry_count, 0, "Normal I/O retry count");
329
SYSCTL_INT(_kern_cam_cd, OID_AUTO, timeout, CTLFLAG_RWTUN,
330
&cd_timeout, 0, "Timeout, in us, for read operations");
331
332
static MALLOC_DEFINE(M_SCSICD, "scsi_cd", "scsi_cd buffers");
333
334
static void
335
cdinit(void)
336
{
337
cam_status status;
338
339
/*
340
* Install a global async callback. This callback will
341
* receive async callbacks like "new device found".
342
*/
343
status = xpt_register_async(AC_FOUND_DEVICE, cdasync, NULL, NULL);
344
345
if (status != CAM_REQ_CMP) {
346
printf("cd: Failed to attach master async callback "
347
"due to status 0x%x!\n", status);
348
}
349
}
350
351
/*
352
* Callback from GEOM, called when it has finished cleaning up its
353
* resources.
354
*/
355
static void
356
cddiskgonecb(struct disk *dp)
357
{
358
struct cam_periph *periph;
359
360
periph = (struct cam_periph *)dp->d_drv1;
361
cam_periph_release(periph);
362
}
363
364
static void
365
cdoninvalidate(struct cam_periph *periph)
366
{
367
struct cd_softc *softc;
368
369
cam_periph_assert(periph, MA_OWNED);
370
softc = (struct cd_softc *)periph->softc;
371
372
/*
373
* De-register any async callbacks.
374
*/
375
xpt_register_async(0, cdasync, periph, periph->path);
376
377
/*
378
* Return all queued I/O with ENXIO.
379
* XXX Handle any transactions queued to the card
380
* with XPT_ABORT_CCB.
381
*/
382
bioq_flush(&softc->bio_queue, NULL, ENXIO);
383
384
disk_gone(softc->disk);
385
}
386
387
static void
388
cdcleanup(struct cam_periph *periph)
389
{
390
struct cd_softc *softc;
391
392
softc = (struct cd_softc *)periph->softc;
393
394
cam_periph_unlock(periph);
395
if ((softc->flags & CD_FLAG_SCTX_INIT) != 0
396
&& sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
397
xpt_print(periph->path, "can't remove sysctl context\n");
398
}
399
400
callout_drain(&softc->mediapoll_c);
401
disk_destroy(softc->disk);
402
free(softc, M_DEVBUF);
403
cam_periph_lock(periph);
404
}
405
406
static void
407
cdasync(void *callback_arg, uint32_t code,
408
struct cam_path *path, void *arg)
409
{
410
struct cam_periph *periph;
411
struct cd_softc *softc;
412
413
periph = (struct cam_periph *)callback_arg;
414
switch (code) {
415
case AC_FOUND_DEVICE:
416
{
417
struct ccb_getdev *cgd;
418
cam_status status;
419
420
cgd = (struct ccb_getdev *)arg;
421
if (cgd == NULL)
422
break;
423
424
if (cgd->protocol != PROTO_SCSI)
425
break;
426
if (SID_QUAL(&cgd->inq_data) != SID_QUAL_LU_CONNECTED)
427
break;
428
if (SID_TYPE(&cgd->inq_data) != T_CDROM
429
&& SID_TYPE(&cgd->inq_data) != T_WORM)
430
break;
431
432
/*
433
* Allocate a peripheral instance for
434
* this device and start the probe
435
* process.
436
*/
437
status = cam_periph_alloc(cdregister, cdoninvalidate,
438
cdcleanup, cdstart,
439
"cd", CAM_PERIPH_BIO,
440
path, cdasync,
441
AC_FOUND_DEVICE, cgd);
442
443
if (status != CAM_REQ_CMP
444
&& status != CAM_REQ_INPROG)
445
printf("cdasync: Unable to attach new device "
446
"due to status 0x%x\n", status);
447
448
return;
449
}
450
case AC_UNIT_ATTENTION:
451
{
452
union ccb *ccb;
453
int error_code, sense_key, asc, ascq;
454
455
softc = (struct cd_softc *)periph->softc;
456
ccb = (union ccb *)arg;
457
458
/*
459
* Handle all media change UNIT ATTENTIONs except
460
* our own, as they will be handled by cderror().
461
*/
462
if (xpt_path_periph(ccb->ccb_h.path) != periph &&
463
scsi_extract_sense_ccb(ccb,
464
&error_code, &sense_key, &asc, &ascq)) {
465
/* 28/0: NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED */
466
if (asc == 0x28 && ascq == 0x00)
467
disk_media_changed(softc->disk, M_NOWAIT);
468
}
469
break;
470
}
471
case AC_SCSI_AEN:
472
cam_periph_assert(periph, MA_OWNED);
473
softc = (struct cd_softc *)periph->softc;
474
if (softc->state == CD_STATE_NORMAL && !softc->tur) {
475
if (cam_periph_acquire(periph) == 0) {
476
softc->tur = 1;
477
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
478
}
479
}
480
/* FALLTHROUGH */
481
case AC_SENT_BDR:
482
case AC_BUS_RESET:
483
{
484
struct ccb_hdr *ccbh;
485
486
cam_periph_assert(periph, MA_OWNED);
487
softc = (struct cd_softc *)periph->softc;
488
/*
489
* Don't fail on the expected unit attention
490
* that will occur.
491
*/
492
softc->flags |= CD_FLAG_RETRY_UA;
493
LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
494
ccbh->ccb_state |= CD_CCB_RETRY_UA;
495
break;
496
}
497
default:
498
break;
499
}
500
501
cam_periph_async(periph, code, path, arg);
502
}
503
504
static void
505
cdsysctlinit(void *context, int pending)
506
{
507
struct cam_periph *periph;
508
struct cd_softc *softc;
509
char tmpstr[32], tmpstr2[16];
510
511
periph = (struct cam_periph *)context;
512
if (cam_periph_acquire(periph) != 0)
513
return;
514
515
softc = (struct cd_softc *)periph->softc;
516
snprintf(tmpstr, sizeof(tmpstr), "CAM CD unit %d", periph->unit_number);
517
snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
518
519
sysctl_ctx_init(&softc->sysctl_ctx);
520
cam_periph_lock(periph);
521
softc->flags |= CD_FLAG_SCTX_INIT;
522
cam_periph_unlock(periph);
523
softc->sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&softc->sysctl_ctx,
524
SYSCTL_STATIC_CHILDREN(_kern_cam_cd), OID_AUTO,
525
tmpstr2, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, tmpstr,
526
"device_index");
527
528
if (softc->sysctl_tree == NULL) {
529
printf("cdsysctlinit: unable to allocate sysctl tree\n");
530
cam_periph_release(periph);
531
return;
532
}
533
534
/*
535
* Now register the sysctl handler, so the user can the value on
536
* the fly.
537
*/
538
SYSCTL_ADD_PROC(&softc->sysctl_ctx,SYSCTL_CHILDREN(softc->sysctl_tree),
539
OID_AUTO, "minimum_cmd_size",
540
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
541
&softc->minimum_command_size, 0, cdcmdsizesysctl, "I",
542
"Minimum CDB size");
543
544
cam_periph_release(periph);
545
}
546
547
/*
548
* We have a handler function for this so we can check the values when the
549
* user sets them, instead of every time we look at them.
550
*/
551
static int
552
cdcmdsizesysctl(SYSCTL_HANDLER_ARGS)
553
{
554
int error, value;
555
556
value = *(int *)arg1;
557
558
error = sysctl_handle_int(oidp, &value, 0, req);
559
560
if ((error != 0)
561
|| (req->newptr == NULL))
562
return (error);
563
564
/*
565
* The only real values we can have here are 6 or 10. I don't
566
* really forsee having 12 be an option at any time in the future.
567
* So if the user sets something less than or equal to 6, we'll set
568
* it to 6. If he sets something greater than 6, we'll set it to 10.
569
*
570
* I suppose we could just return an error here for the wrong values,
571
* but I don't think it's necessary to do so, as long as we can
572
* determine the user's intent without too much trouble.
573
*/
574
if (value < 6)
575
value = 6;
576
else if (value > 6)
577
value = 10;
578
579
*(int *)arg1 = value;
580
581
return (0);
582
}
583
584
static cam_status
585
cdregister(struct cam_periph *periph, void *arg)
586
{
587
struct cd_softc *softc;
588
struct ccb_pathinq cpi;
589
struct ccb_getdev *cgd;
590
char tmpstr[80];
591
caddr_t match;
592
593
cgd = (struct ccb_getdev *)arg;
594
if (cgd == NULL) {
595
printf("cdregister: no getdev CCB, can't register device\n");
596
return(CAM_REQ_CMP_ERR);
597
}
598
599
softc = (struct cd_softc *)malloc(sizeof(*softc),M_DEVBUF,
600
M_NOWAIT | M_ZERO);
601
if (softc == NULL) {
602
printf("cdregister: Unable to probe new device. "
603
"Unable to allocate softc\n");
604
return(CAM_REQ_CMP_ERR);
605
}
606
607
LIST_INIT(&softc->pending_ccbs);
608
STAILQ_INIT(&softc->mode_queue);
609
softc->state = CD_STATE_PROBE;
610
bioq_init(&softc->bio_queue);
611
if (SID_IS_REMOVABLE(&cgd->inq_data))
612
softc->flags |= CD_FLAG_DISC_REMOVABLE;
613
614
periph->softc = softc;
615
softc->periph = periph;
616
617
/*
618
* See if this device has any quirks.
619
*/
620
match = cam_quirkmatch((caddr_t)&cgd->inq_data,
621
(caddr_t)cd_quirk_table,
622
nitems(cd_quirk_table),
623
sizeof(*cd_quirk_table), scsi_inquiry_match);
624
625
if (match != NULL)
626
softc->quirks = ((struct cd_quirk_entry *)match)->quirks;
627
else
628
softc->quirks = CD_Q_NONE;
629
630
/* Check if the SIM does not want 6 byte commands */
631
xpt_path_inq(&cpi, periph->path);
632
if (cpi.ccb_h.status == CAM_REQ_CMP && (cpi.hba_misc & PIM_NO_6_BYTE))
633
softc->quirks |= CD_Q_10_BYTE_ONLY;
634
635
TASK_INIT(&softc->sysctl_task, 0, cdsysctlinit, periph);
636
637
/* The default is 6 byte commands, unless quirked otherwise */
638
if (softc->quirks & CD_Q_10_BYTE_ONLY)
639
softc->minimum_command_size = 10;
640
else
641
softc->minimum_command_size = 6;
642
643
/*
644
* Take a reference on the periph while cdstart is called to finish the
645
* probe. The reference will be dropped in cddone at the end of probe.
646
*/
647
(void)cam_periph_acquire(periph);
648
cam_periph_unlock(periph);
649
/*
650
* Load the user's default, if any.
651
*/
652
snprintf(tmpstr, sizeof(tmpstr), "kern.cam.cd.%d.minimum_cmd_size",
653
periph->unit_number);
654
TUNABLE_INT_FETCH(tmpstr, &softc->minimum_command_size);
655
656
/* 6 and 10 are the only permissible values here. */
657
if (softc->minimum_command_size < 6)
658
softc->minimum_command_size = 6;
659
else if (softc->minimum_command_size > 6)
660
softc->minimum_command_size = 10;
661
662
/*
663
* We need to register the statistics structure for this device,
664
* but we don't have the blocksize yet for it. So, we register
665
* the structure and indicate that we don't have the blocksize
666
* yet. Unlike other SCSI peripheral drivers, we explicitly set
667
* the device type here to be CDROM, rather than just ORing in
668
* the device type. This is because this driver can attach to either
669
* CDROM or WORM devices, and we want this peripheral driver to
670
* show up in the devstat list as a CD peripheral driver, not a
671
* WORM peripheral driver. WORM drives will also have the WORM
672
* driver attached to them.
673
*/
674
softc->disk = disk_alloc();
675
softc->disk->d_devstat = devstat_new_entry("cd",
676
periph->unit_number, 0,
677
DEVSTAT_BS_UNAVAILABLE,
678
DEVSTAT_TYPE_CDROM |
679
XPORT_DEVSTAT_TYPE(cpi.transport),
680
DEVSTAT_PRIORITY_CD);
681
softc->disk->d_open = cdopen;
682
softc->disk->d_close = cdclose;
683
softc->disk->d_strategy = cdstrategy;
684
softc->disk->d_gone = cddiskgonecb;
685
softc->disk->d_ioctl = cdioctl;
686
softc->disk->d_name = "cd";
687
cam_strvis(softc->disk->d_descr, cgd->inq_data.vendor,
688
sizeof(cgd->inq_data.vendor), sizeof(softc->disk->d_descr));
689
strlcat(softc->disk->d_descr, " ", sizeof(softc->disk->d_descr));
690
cam_strvis(&softc->disk->d_descr[strlen(softc->disk->d_descr)],
691
cgd->inq_data.product, sizeof(cgd->inq_data.product),
692
sizeof(softc->disk->d_descr) - strlen(softc->disk->d_descr));
693
softc->disk->d_unit = periph->unit_number;
694
softc->disk->d_drv1 = periph;
695
if (cpi.maxio == 0)
696
softc->disk->d_maxsize = DFLTPHYS; /* traditional default */
697
else if (cpi.maxio > maxphys)
698
softc->disk->d_maxsize = maxphys; /* for safety */
699
else
700
softc->disk->d_maxsize = cpi.maxio;
701
softc->disk->d_flags = 0;
702
softc->disk->d_hba_vendor = cpi.hba_vendor;
703
softc->disk->d_hba_device = cpi.hba_device;
704
softc->disk->d_hba_subvendor = cpi.hba_subvendor;
705
softc->disk->d_hba_subdevice = cpi.hba_subdevice;
706
snprintf(softc->disk->d_attachment, sizeof(softc->disk->d_attachment),
707
"%s%d", cpi.dev_name, cpi.unit_number);
708
cam_periph_lock(periph);
709
710
/*
711
* Add an async callback so that we get
712
* notified if this device goes away.
713
*/
714
xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE |
715
AC_SCSI_AEN | AC_UNIT_ATTENTION, cdasync, periph, periph->path);
716
717
/*
718
* Schedule a periodic media polling events.
719
*/
720
callout_init_mtx(&softc->mediapoll_c, cam_periph_mtx(periph), 0);
721
if ((softc->flags & CD_FLAG_DISC_REMOVABLE) &&
722
(cgd->inq_flags & SID_AEN) == 0 &&
723
cd_poll_period != 0) {
724
callout_reset_sbt(&softc->mediapoll_c, cd_poll_period * SBT_1S,
725
0, cdmediapoll, periph, C_PREL(1));
726
}
727
728
/* Released after probe when disk_create() call pass it to GEOM. */
729
cam_periph_hold_boot(periph);
730
731
xpt_schedule(periph, CAM_PRIORITY_DEV);
732
return(CAM_REQ_CMP);
733
}
734
735
static int
736
cdopen(struct disk *dp)
737
{
738
struct cam_periph *periph;
739
int error;
740
741
periph = (struct cam_periph *)dp->d_drv1;
742
743
if (cam_periph_acquire(periph) != 0)
744
return(ENXIO);
745
746
cam_periph_lock(periph);
747
748
if ((error = cam_periph_hold(periph, PRIBIO | PCATCH)) != 0) {
749
cam_periph_release_locked(periph);
750
cam_periph_unlock(periph);
751
return (error);
752
}
753
754
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
755
("cdopen\n"));
756
757
/*
758
* Check for media, and set the appropriate flags. We don't bail
759
* if we don't have media, but then we don't allow anything but the
760
* CDIOCEJECT/CDIOCCLOSE ioctls if there is no media.
761
*/
762
cdcheckmedia(periph, /*do_wait*/ true);
763
764
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdopen\n"));
765
cam_periph_unhold(periph);
766
767
cam_periph_unlock(periph);
768
769
return (0);
770
}
771
772
static int
773
cdclose(struct disk *dp)
774
{
775
struct cam_periph *periph;
776
struct cd_softc *softc;
777
778
periph = (struct cam_periph *)dp->d_drv1;
779
softc = (struct cd_softc *)periph->softc;
780
781
cam_periph_lock(periph);
782
if (cam_periph_hold(periph, PRIBIO) != 0) {
783
cam_periph_unlock(periph);
784
cam_periph_release(periph);
785
return (0);
786
}
787
788
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
789
("cdclose\n"));
790
791
if ((softc->flags & CD_FLAG_DISC_REMOVABLE) != 0)
792
cdprevent(periph, PR_ALLOW);
793
794
/*
795
* Since we're closing this CD, mark the blocksize as unavailable.
796
* It will be marked as available when the CD is opened again.
797
*/
798
softc->disk->d_devstat->flags |= DEVSTAT_BS_UNAVAILABLE;
799
800
/*
801
* We'll check the media and toc again at the next open().
802
*/
803
softc->flags &= ~(CD_FLAG_VALID_MEDIA|CD_FLAG_VALID_TOC);
804
805
cam_periph_unhold(periph);
806
cam_periph_release_locked(periph);
807
cam_periph_unlock(periph);
808
809
return (0);
810
}
811
812
static int
813
cdrunccb(union ccb *ccb, int (*error_routine)(union ccb *ccb,
814
uint32_t cam_flags,
815
uint32_t sense_flags),
816
uint32_t cam_flags, uint32_t sense_flags)
817
{
818
struct cd_softc *softc;
819
struct cam_periph *periph;
820
int error;
821
822
periph = xpt_path_periph(ccb->ccb_h.path);
823
softc = (struct cd_softc *)periph->softc;
824
825
error = cam_periph_runccb(ccb, error_routine, cam_flags, sense_flags,
826
softc->disk->d_devstat);
827
828
return(error);
829
}
830
831
/*
832
* Actually translate the requested transfer into one the physical driver
833
* can understand. The transfer is described by a buf and will include
834
* only one physical transfer.
835
*/
836
static void
837
cdstrategy(struct bio *bp)
838
{
839
struct cam_periph *periph;
840
struct cd_softc *softc;
841
842
periph = (struct cam_periph *)bp->bio_disk->d_drv1;
843
cam_periph_lock(periph);
844
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
845
("cdstrategy(%p)\n", bp));
846
847
softc = (struct cd_softc *)periph->softc;
848
849
/*
850
* If the device has been made invalid, error out
851
*/
852
if ((periph->flags & CAM_PERIPH_INVALID) != 0) {
853
cam_periph_unlock(periph);
854
biofinish(bp, NULL, ENXIO);
855
return;
856
}
857
858
/*
859
* Place it in the queue of disk activities for this disk
860
*/
861
bioq_disksort(&softc->bio_queue, bp);
862
863
/*
864
* If we don't know that we have valid media, schedule the media
865
* check first. The I/O will get executed after the media check.
866
*/
867
if ((softc->flags & CD_FLAG_VALID_MEDIA) == 0)
868
cdcheckmedia(periph, /*do_wait*/ false);
869
else
870
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
871
872
cam_periph_unlock(periph);
873
return;
874
}
875
876
static void
877
cdstart(struct cam_periph *periph, union ccb *start_ccb)
878
{
879
struct cd_softc *softc;
880
struct bio *bp;
881
struct ccb_scsiio *csio;
882
883
cam_periph_assert(periph, MA_OWNED);
884
softc = (struct cd_softc *)periph->softc;
885
886
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdstart\n"));
887
888
switch (softc->state) {
889
case CD_STATE_NORMAL:
890
{
891
bp = bioq_first(&softc->bio_queue);
892
if (bp == NULL) {
893
if (softc->tur) {
894
softc->tur = 0;
895
csio = &start_ccb->csio;
896
scsi_test_unit_ready(csio,
897
/*retries*/ cd_retry_count,
898
cddone,
899
MSG_SIMPLE_Q_TAG,
900
SSD_FULL_SIZE,
901
cd_timeout);
902
start_ccb->ccb_h.ccb_bp = NULL;
903
start_ccb->ccb_h.ccb_state = CD_CCB_TUR;
904
xpt_action(start_ccb);
905
} else
906
xpt_release_ccb(start_ccb);
907
} else {
908
if (softc->tur) {
909
softc->tur = 0;
910
cam_periph_release_locked(periph);
911
}
912
bioq_remove(&softc->bio_queue, bp);
913
914
if ((bp->bio_cmd != BIO_READ) &&
915
(bp->bio_cmd != BIO_WRITE)) {
916
biofinish(bp, NULL, EOPNOTSUPP);
917
xpt_release_ccb(start_ccb);
918
return;
919
}
920
921
scsi_read_write(&start_ccb->csio,
922
/*retries*/ cd_retry_count,
923
/* cbfcnp */ cddone,
924
MSG_SIMPLE_Q_TAG,
925
/* read */bp->bio_cmd == BIO_READ ?
926
SCSI_RW_READ : SCSI_RW_WRITE,
927
/* byte2 */ 0,
928
/* minimum_cmd_size */ 10,
929
/* lba */ bp->bio_offset /
930
softc->params.blksize,
931
bp->bio_bcount / softc->params.blksize,
932
/* data_ptr */ bp->bio_data,
933
/* dxfer_len */ bp->bio_bcount,
934
/* sense_len */ cd_retry_count ?
935
SSD_FULL_SIZE : SF_NO_PRINT,
936
/* timeout */ cd_timeout);
937
/* Use READ CD command for audio tracks. */
938
if (softc->params.blksize == 2352) {
939
start_ccb->csio.cdb_io.cdb_bytes[0] = READ_CD;
940
start_ccb->csio.cdb_io.cdb_bytes[9] = 0xf8;
941
start_ccb->csio.cdb_io.cdb_bytes[10] = 0;
942
start_ccb->csio.cdb_io.cdb_bytes[11] = 0;
943
start_ccb->csio.cdb_len = 12;
944
}
945
start_ccb->ccb_h.ccb_state = CD_CCB_BUFFER_IO;
946
947
LIST_INSERT_HEAD(&softc->pending_ccbs,
948
&start_ccb->ccb_h, periph_links.le);
949
softc->outstanding_cmds++;
950
951
/* We expect a unit attention from this device */
952
if ((softc->flags & CD_FLAG_RETRY_UA) != 0) {
953
start_ccb->ccb_h.ccb_state |= CD_CCB_RETRY_UA;
954
softc->flags &= ~CD_FLAG_RETRY_UA;
955
}
956
957
start_ccb->ccb_h.ccb_bp = bp;
958
bp = bioq_first(&softc->bio_queue);
959
960
xpt_action(start_ccb);
961
}
962
if (bp != NULL || softc->tur) {
963
/* Have more work to do, so ensure we stay scheduled */
964
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
965
}
966
break;
967
}
968
case CD_STATE_PROBE:
969
case CD_STATE_MEDIA_SIZE:
970
{
971
struct scsi_read_capacity_data *rcap;
972
973
rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap),
974
M_SCSICD, M_NOWAIT | M_ZERO);
975
if (rcap == NULL) {
976
xpt_print(periph->path,
977
"%s: Couldn't malloc read_capacity data\n",
978
__func__);
979
xpt_release_ccb(start_ccb);
980
/*
981
* We can't probe because we can't allocate memory,
982
* so invalidate the peripheral. The system probably
983
* has larger problems at this stage. If we've
984
* already probed (and are re-probing capacity), we
985
* don't need to invalidate.
986
*
987
* XXX KDM need to reset probe state and kick out
988
* pending I/O.
989
*/
990
if (softc->state == CD_STATE_PROBE)
991
cam_periph_invalidate(periph);
992
break;
993
}
994
995
/*
996
* Set the default capacity and sector size to something that
997
* GEOM can handle. This will get reset when a read capacity
998
* completes successfully.
999
*/
1000
softc->disk->d_sectorsize = 2048;
1001
softc->disk->d_mediasize = 0;
1002
1003
csio = &start_ccb->csio;
1004
scsi_read_capacity(csio,
1005
/*retries*/ cd_retry_count,
1006
cddone,
1007
MSG_SIMPLE_Q_TAG,
1008
rcap,
1009
SSD_FULL_SIZE,
1010
/*timeout*/20000);
1011
start_ccb->ccb_h.ccb_bp = NULL;
1012
if (softc->state == CD_STATE_PROBE)
1013
start_ccb->ccb_h.ccb_state = CD_CCB_PROBE;
1014
else
1015
start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_SIZE;
1016
xpt_action(start_ccb);
1017
break;
1018
}
1019
case CD_STATE_MEDIA_ALLOW:
1020
case CD_STATE_MEDIA_PREVENT:
1021
{
1022
/*
1023
* If the CD is already locked, we don't need to do this.
1024
* Move on to the capacity check.
1025
*/
1026
if (softc->state == CD_STATE_MEDIA_PREVENT
1027
&& (softc->flags & CD_FLAG_DISC_LOCKED) != 0) {
1028
softc->state = CD_STATE_MEDIA_SIZE;
1029
xpt_release_ccb(start_ccb);
1030
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
1031
break;
1032
}
1033
1034
scsi_prevent(&start_ccb->csio,
1035
/*retries*/ cd_retry_count,
1036
/*cbfcnp*/ cddone,
1037
/*tag_action*/ MSG_SIMPLE_Q_TAG,
1038
/*action*/ (softc->state == CD_STATE_MEDIA_ALLOW) ?
1039
PR_ALLOW : PR_PREVENT,
1040
/*sense_len*/ SSD_FULL_SIZE,
1041
/*timeout*/ 60000);
1042
1043
start_ccb->ccb_h.ccb_bp = NULL;
1044
if (softc->state == CD_STATE_MEDIA_ALLOW)
1045
start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_ALLOW;
1046
else
1047
start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_PREVENT;
1048
xpt_action(start_ccb);
1049
break;
1050
}
1051
case CD_STATE_MEDIA_TOC_HDR: {
1052
struct ioc_toc_header *toch;
1053
1054
bzero(&softc->toc, sizeof(softc->toc));
1055
1056
toch = &softc->toc.header;
1057
1058
scsi_read_toc(&start_ccb->csio,
1059
/*retries*/ cd_retry_count,
1060
/*cbfcnp*/ cddone,
1061
/*tag_action*/ MSG_SIMPLE_Q_TAG,
1062
/*byte1_flags*/ 0,
1063
/*format*/ SRTOC_FORMAT_TOC,
1064
/*track*/ 0,
1065
/*data_ptr*/ (uint8_t *)toch,
1066
/*dxfer_len*/ sizeof(*toch),
1067
/*sense_len*/ SSD_FULL_SIZE,
1068
/*timeout*/ 50000);
1069
start_ccb->ccb_h.ccb_bp = NULL;
1070
start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_TOC_HDR;
1071
xpt_action(start_ccb);
1072
break;
1073
}
1074
case CD_STATE_MEDIA_TOC_FULL: {
1075
bzero(&softc->toc, sizeof(softc->toc));
1076
1077
scsi_read_toc(&start_ccb->csio,
1078
/*retries*/ cd_retry_count,
1079
/*cbfcnp*/ cddone,
1080
/*tag_action*/ MSG_SIMPLE_Q_TAG,
1081
/*byte1_flags*/ 0,
1082
/*format*/ SRTOC_FORMAT_TOC,
1083
/*track*/ 0,
1084
/*data_ptr*/ (uint8_t *)&softc->toc,
1085
/*dxfer_len*/ softc->toc_read_len ?
1086
softc->toc_read_len :
1087
sizeof(softc->toc),
1088
/*sense_len*/ SSD_FULL_SIZE,
1089
/*timeout*/ 50000);
1090
start_ccb->ccb_h.ccb_bp = NULL;
1091
start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_TOC_FULL;
1092
xpt_action(start_ccb);
1093
break;
1094
}
1095
case CD_STATE_MEDIA_TOC_LEAD: {
1096
struct cd_toc_single *leadout;
1097
1098
leadout = &softc->leadout;
1099
bzero(leadout, sizeof(*leadout));
1100
1101
scsi_read_toc(&start_ccb->csio,
1102
/*retries*/ cd_retry_count,
1103
/*cbfcnp*/ cddone,
1104
/*tag_action*/ MSG_SIMPLE_Q_TAG,
1105
/*byte1_flags*/ CD_MSF,
1106
/*format*/ SRTOC_FORMAT_TOC,
1107
/*track*/ LEADOUT,
1108
/*data_ptr*/ (uint8_t *)leadout,
1109
/*dxfer_len*/ sizeof(*leadout),
1110
/*sense_len*/ SSD_FULL_SIZE,
1111
/*timeout*/ 50000);
1112
start_ccb->ccb_h.ccb_bp = NULL;
1113
start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_TOC_LEAD;
1114
xpt_action(start_ccb);
1115
break;
1116
}
1117
}
1118
}
1119
1120
static void
1121
cddone(struct cam_periph *periph, union ccb *done_ccb)
1122
{
1123
struct cd_softc *softc;
1124
struct ccb_scsiio *csio;
1125
1126
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cddone\n"));
1127
1128
cam_periph_assert(periph, MA_OWNED);
1129
softc = (struct cd_softc *)periph->softc;
1130
csio = &done_ccb->csio;
1131
1132
switch (csio->ccb_h.ccb_state & CD_CCB_TYPE_MASK) {
1133
case CD_CCB_BUFFER_IO:
1134
{
1135
struct bio *bp;
1136
int error;
1137
1138
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
1139
error = 0;
1140
1141
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1142
int sf;
1143
1144
if ((done_ccb->ccb_h.ccb_state & CD_CCB_RETRY_UA) != 0)
1145
sf = SF_RETRY_UA;
1146
else
1147
sf = 0;
1148
1149
error = cderror(done_ccb, CAM_RETRY_SELTO, sf);
1150
if (error == ERESTART) {
1151
/*
1152
* A retry was scheuled, so
1153
* just return.
1154
*/
1155
return;
1156
}
1157
}
1158
1159
if (error != 0) {
1160
xpt_print(periph->path,
1161
"cddone: got error %#x back\n", error);
1162
bioq_flush(&softc->bio_queue, NULL, EIO);
1163
bp->bio_resid = bp->bio_bcount;
1164
bp->bio_error = error;
1165
bp->bio_flags |= BIO_ERROR;
1166
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
1167
cam_release_devq(done_ccb->ccb_h.path,
1168
/*relsim_flags*/0,
1169
/*reduction*/0,
1170
/*timeout*/0,
1171
/*getcount_only*/0);
1172
1173
} else {
1174
bp->bio_resid = csio->resid;
1175
bp->bio_error = 0;
1176
if (bp->bio_resid != 0) {
1177
/*
1178
* Short transfer ???
1179
* XXX: not sure this is correct for partial
1180
* transfers at EOM
1181
*/
1182
bp->bio_flags |= BIO_ERROR;
1183
}
1184
}
1185
1186
LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
1187
softc->outstanding_cmds--;
1188
1189
biofinish(bp, NULL, 0);
1190
break;
1191
}
1192
case CD_CCB_PROBE:
1193
{
1194
struct scsi_read_capacity_data *rdcap;
1195
char *announce_buf;
1196
struct cd_params *cdp;
1197
int error;
1198
1199
cdp = &softc->params;
1200
announce_buf = softc->announce_temp;
1201
bzero(announce_buf, CD_ANNOUNCETMP_SZ);
1202
1203
rdcap = (struct scsi_read_capacity_data *)csio->data_ptr;
1204
1205
cdp->disksize = scsi_4btoul (rdcap->addr) + 1;
1206
cdp->blksize = scsi_4btoul (rdcap->length);
1207
1208
/*
1209
* Retry any UNIT ATTENTION type errors. They
1210
* are expected at boot.
1211
*/
1212
if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP ||
1213
(error = cderror(done_ccb, CAM_RETRY_SELTO,
1214
SF_RETRY_UA | SF_NO_PRINT)) == 0) {
1215
snprintf(announce_buf, CD_ANNOUNCETMP_SZ,
1216
"%juMB (%ju %u byte sectors)",
1217
((uintmax_t)cdp->disksize * cdp->blksize) /
1218
(1024 * 1024),
1219
(uintmax_t)cdp->disksize, cdp->blksize);
1220
} else {
1221
if (error == ERESTART) {
1222
/*
1223
* A retry was scheuled, so
1224
* just return.
1225
*/
1226
return;
1227
} else {
1228
int asc, ascq;
1229
int sense_key, error_code;
1230
int have_sense;
1231
cam_status status;
1232
struct ccb_getdev cgd;
1233
1234
/* Don't wedge this device's queue */
1235
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
1236
cam_release_devq(done_ccb->ccb_h.path,
1237
/*relsim_flags*/0,
1238
/*reduction*/0,
1239
/*timeout*/0,
1240
/*getcount_only*/0);
1241
1242
status = done_ccb->ccb_h.status;
1243
xpt_gdev_type(&cgd, done_ccb->ccb_h.path);
1244
1245
if (scsi_extract_sense_ccb(done_ccb,
1246
&error_code, &sense_key, &asc, &ascq))
1247
have_sense = TRUE;
1248
else
1249
have_sense = FALSE;
1250
1251
/*
1252
* Attach to anything that claims to be a
1253
* CDROM or WORM device, as long as it
1254
* doesn't return a "Logical unit not
1255
* supported" (0x25) error.
1256
*
1257
* 25/0: LOGICAL UNIT NOT SUPPORTED
1258
*/
1259
if ((have_sense) && (asc != 0x25)
1260
&& (error_code == SSD_CURRENT_ERROR
1261
|| error_code == SSD_DESC_CURRENT_ERROR)) {
1262
const char *sense_key_desc;
1263
const char *asc_desc;
1264
1265
scsi_sense_desc(sense_key, asc, ascq,
1266
&cgd.inq_data,
1267
&sense_key_desc,
1268
&asc_desc);
1269
snprintf(announce_buf,
1270
CD_ANNOUNCETMP_SZ,
1271
"Attempt to query device "
1272
"size failed: %s, %s",
1273
sense_key_desc,
1274
asc_desc);
1275
} else if ((have_sense == 0)
1276
&& ((status & CAM_STATUS_MASK) ==
1277
CAM_SCSI_STATUS_ERROR)
1278
&& (csio->scsi_status ==
1279
SCSI_STATUS_BUSY)) {
1280
snprintf(announce_buf,
1281
CD_ANNOUNCETMP_SZ,
1282
"Attempt to query device "
1283
"size failed: SCSI Status: %s",
1284
scsi_status_string(csio));
1285
} else if (SID_TYPE(&cgd.inq_data) == T_CDROM) {
1286
/*
1287
* We only print out an error for
1288
* CDROM type devices. For WORM
1289
* devices, we don't print out an
1290
* error since a few WORM devices
1291
* don't support CDROM commands.
1292
* If we have sense information, go
1293
* ahead and print it out.
1294
* Otherwise, just say that we
1295
* couldn't attach.
1296
*/
1297
1298
/*
1299
* Just print out the error, not
1300
* the full probe message, when we
1301
* don't attach.
1302
*/
1303
if (have_sense)
1304
scsi_sense_print(
1305
&done_ccb->csio);
1306
else {
1307
xpt_print(periph->path,
1308
"got CAM status %#x\n",
1309
done_ccb->ccb_h.status);
1310
}
1311
xpt_print(periph->path, "fatal error, "
1312
"failed to attach to device\n");
1313
/*
1314
* Invalidate this peripheral.
1315
*/
1316
cam_periph_invalidate(periph);
1317
1318
announce_buf = NULL;
1319
} else {
1320
/*
1321
* Invalidate this peripheral.
1322
*/
1323
cam_periph_invalidate(periph);
1324
announce_buf = NULL;
1325
}
1326
}
1327
}
1328
free(rdcap, M_SCSICD);
1329
if (announce_buf != NULL) {
1330
struct sbuf sb;
1331
1332
sbuf_new(&sb, softc->announce_buf, CD_ANNOUNCE_SZ,
1333
SBUF_FIXEDLEN);
1334
xpt_announce_periph_sbuf(periph, &sb, announce_buf);
1335
xpt_announce_quirks_sbuf(periph, &sb, softc->quirks,
1336
CD_Q_BIT_STRING);
1337
sbuf_finish(&sb);
1338
sbuf_putbuf(&sb);
1339
1340
/*
1341
* Create our sysctl variables, now that we know
1342
* we have successfully attached.
1343
*/
1344
taskqueue_enqueue(taskqueue_thread,&softc->sysctl_task);
1345
}
1346
softc->state = CD_STATE_NORMAL;
1347
/*
1348
* Since our peripheral may be invalidated by an error
1349
* above or an external event, we must release our CCB
1350
* before releasing the probe lock on the peripheral.
1351
* The peripheral will only go away once the last lock
1352
* is removed, and we need it around for the CCB release
1353
* operation.
1354
*/
1355
xpt_release_ccb(done_ccb);
1356
1357
/*
1358
* We'll release this reference once GEOM calls us back via
1359
* cddiskgonecb(), telling us that our provider has been freed.
1360
*/
1361
if (cam_periph_acquire(periph) == 0)
1362
disk_create(softc->disk, DISK_VERSION);
1363
1364
cam_periph_release_boot(periph);
1365
cam_periph_release_locked(periph);
1366
return;
1367
}
1368
case CD_CCB_TUR:
1369
{
1370
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1371
if (cderror(done_ccb, CAM_RETRY_SELTO,
1372
SF_RETRY_UA | SF_NO_RECOVERY | SF_NO_PRINT) ==
1373
ERESTART)
1374
return;
1375
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
1376
cam_release_devq(done_ccb->ccb_h.path,
1377
/*relsim_flags*/0,
1378
/*reduction*/0,
1379
/*timeout*/0,
1380
/*getcount_only*/0);
1381
}
1382
xpt_release_ccb(done_ccb);
1383
cam_periph_release_locked(periph);
1384
return;
1385
}
1386
case CD_CCB_MEDIA_ALLOW:
1387
case CD_CCB_MEDIA_PREVENT:
1388
{
1389
int error;
1390
int is_prevent;
1391
1392
error = 0;
1393
1394
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1395
error = cderror(done_ccb, CAM_RETRY_SELTO,
1396
SF_RETRY_UA | SF_NO_PRINT);
1397
}
1398
if (error == ERESTART)
1399
return;
1400
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
1401
cam_release_devq(done_ccb->ccb_h.path,
1402
/*relsim_flags*/0,
1403
/*reduction*/0,
1404
/*timeout*/0,
1405
/*getcount_only*/0);
1406
1407
/*
1408
* Note that just like the original cdcheckmedia(), we do
1409
* a prevent without failing the whole operation if the
1410
* prevent fails. We try, but keep going if it doesn't
1411
* work.
1412
*/
1413
1414
if ((done_ccb->ccb_h.ccb_state & CD_CCB_TYPE_MASK) ==
1415
CD_CCB_MEDIA_PREVENT)
1416
is_prevent = 1;
1417
else
1418
is_prevent = 0;
1419
1420
xpt_release_ccb(done_ccb);
1421
1422
if (is_prevent != 0) {
1423
if (error == 0)
1424
softc->flags |= CD_FLAG_DISC_LOCKED;
1425
else
1426
softc->flags &= ~CD_FLAG_DISC_LOCKED;
1427
softc->state = CD_STATE_MEDIA_SIZE;
1428
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
1429
} else {
1430
if (error == 0)
1431
softc->flags &= ~CD_FLAG_DISC_LOCKED;
1432
softc->state = CD_STATE_NORMAL;
1433
if (bioq_first(&softc->bio_queue) != NULL)
1434
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
1435
}
1436
return;
1437
}
1438
case CD_CCB_MEDIA_SIZE:
1439
{
1440
struct scsi_read_capacity_data *rdcap;
1441
int error;
1442
1443
error = 0;
1444
if ((csio->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1445
error = cderror(done_ccb, CAM_RETRY_SELTO,
1446
SF_RETRY_UA | SF_NO_PRINT);
1447
}
1448
if (error == ERESTART)
1449
return;
1450
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
1451
cam_release_devq(done_ccb->ccb_h.path,
1452
/*relsim_flags*/0,
1453
/*reduction*/0,
1454
/*timeout*/0,
1455
/*getcount_only*/0);
1456
rdcap = (struct scsi_read_capacity_data *)csio->data_ptr;
1457
1458
if (error == 0) {
1459
softc->params.disksize =scsi_4btoul(rdcap->addr) + 1;
1460
softc->params.blksize = scsi_4btoul(rdcap->length);
1461
1462
/* Make sure we got at least some block size. */
1463
if (softc->params.blksize == 0)
1464
error = EIO;
1465
/*
1466
* SCSI-3 mandates that the reported blocksize shall be
1467
* 2048. Older drives sometimes report funny values,
1468
* trim it down to 2048, or other parts of the kernel
1469
* will get confused.
1470
*
1471
* XXX we leave drives alone that might report 512
1472
* bytes, as well as drives reporting more weird
1473
* sizes like perhaps 4K.
1474
*/
1475
if (softc->params.blksize > 2048
1476
&& softc->params.blksize <= 2352)
1477
softc->params.blksize = 2048;
1478
}
1479
free(rdcap, M_SCSICD);
1480
1481
if (error == 0) {
1482
softc->disk->d_sectorsize = softc->params.blksize;
1483
softc->disk->d_mediasize =
1484
(off_t)softc->params.blksize *
1485
softc->params.disksize;
1486
softc->flags |= CD_FLAG_VALID_MEDIA;
1487
softc->state = CD_STATE_MEDIA_TOC_HDR;
1488
} else {
1489
softc->flags &= ~(CD_FLAG_VALID_MEDIA |
1490
CD_FLAG_VALID_TOC);
1491
bioq_flush(&softc->bio_queue, NULL, EINVAL);
1492
softc->state = CD_STATE_MEDIA_ALLOW;
1493
cdmediaprobedone(periph);
1494
}
1495
xpt_release_ccb(done_ccb);
1496
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
1497
return;
1498
}
1499
case CD_CCB_MEDIA_TOC_HDR:
1500
case CD_CCB_MEDIA_TOC_FULL:
1501
case CD_CCB_MEDIA_TOC_LEAD:
1502
{
1503
int error;
1504
struct ioc_toc_header *toch;
1505
int num_entries;
1506
int cdindex;
1507
1508
error = 0;
1509
1510
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1511
error = cderror(done_ccb, CAM_RETRY_SELTO,
1512
SF_RETRY_UA | SF_NO_PRINT);
1513
}
1514
if (error == ERESTART)
1515
return;
1516
1517
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
1518
cam_release_devq(done_ccb->ccb_h.path,
1519
/*relsim_flags*/0,
1520
/*reduction*/0,
1521
/*timeout*/0,
1522
/*getcount_only*/0);
1523
1524
/*
1525
* We will get errors here for media that doesn't have a table
1526
* of contents. According to the MMC-3 spec: "When a Read
1527
* TOC/PMA/ATIP command is presented for a DDCD/CD-R/RW media,
1528
* where the first TOC has not been recorded (no complete
1529
* session) and the Format codes 0000b, 0001b, or 0010b are
1530
* specified, this command shall be rejected with an INVALID
1531
* FIELD IN CDB. Devices that are not capable of reading an
1532
* incomplete session on DDC/CD-R/RW media shall report
1533
* CANNOT READ MEDIUM - INCOMPATIBLE FORMAT."
1534
*
1535
* So this isn't fatal if we can't read the table of contents,
1536
* it just means that the user won't be able to issue the
1537
* play tracks ioctl, and likely lots of other stuff won't
1538
* work either. They need to burn the CD before we can do
1539
* a whole lot with it. So we don't print anything here if
1540
* we get an error back.
1541
*
1542
* We also bail out if the drive doesn't at least give us
1543
* the full TOC header.
1544
*/
1545
if ((error != 0)
1546
|| ((csio->dxfer_len - csio->resid) <
1547
sizeof(struct ioc_toc_header))) {
1548
softc->flags &= ~CD_FLAG_VALID_TOC;
1549
bzero(&softc->toc, sizeof(softc->toc));
1550
/*
1551
* Failing the TOC read is not an error.
1552
*/
1553
softc->state = CD_STATE_NORMAL;
1554
xpt_release_ccb(done_ccb);
1555
1556
cdmediaprobedone(periph);
1557
1558
/*
1559
* Go ahead and schedule I/O execution if there is
1560
* anything in the queue. It'll probably get
1561
* kicked out with an error.
1562
*/
1563
if (bioq_first(&softc->bio_queue) != NULL)
1564
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
1565
return;
1566
}
1567
1568
/*
1569
* Note that this is NOT the storage location used for the
1570
* leadout!
1571
*/
1572
toch = &softc->toc.header;
1573
1574
if (softc->quirks & CD_Q_BCD_TRACKS) {
1575
toch->starting_track = bcd2bin(toch->starting_track);
1576
toch->ending_track = bcd2bin(toch->ending_track);
1577
}
1578
1579
/* Number of TOC entries, plus leadout */
1580
num_entries = toch->ending_track - toch->starting_track + 2;
1581
cdindex = toch->starting_track + num_entries - 1;
1582
1583
if ((done_ccb->ccb_h.ccb_state & CD_CCB_TYPE_MASK) ==
1584
CD_CCB_MEDIA_TOC_HDR) {
1585
if (num_entries <= 0 ||
1586
num_entries > nitems(softc->toc.entries)) {
1587
softc->flags &= ~CD_FLAG_VALID_TOC;
1588
bzero(&softc->toc, sizeof(softc->toc));
1589
/*
1590
* Failing the TOC read is not an error.
1591
*/
1592
softc->state = CD_STATE_NORMAL;
1593
xpt_release_ccb(done_ccb);
1594
1595
cdmediaprobedone(periph);
1596
1597
/*
1598
* Go ahead and schedule I/O execution if
1599
* there is anything in the queue. It'll
1600
* probably get kicked out with an error.
1601
*/
1602
if (bioq_first(&softc->bio_queue) != NULL)
1603
xpt_schedule(periph,
1604
CAM_PRIORITY_NORMAL);
1605
} else {
1606
softc->toc_read_len = num_entries *
1607
sizeof(struct cd_toc_entry);
1608
softc->toc_read_len += sizeof(*toch);
1609
1610
softc->state = CD_STATE_MEDIA_TOC_FULL;
1611
xpt_release_ccb(done_ccb);
1612
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
1613
}
1614
1615
return;
1616
} else if ((done_ccb->ccb_h.ccb_state & CD_CCB_TYPE_MASK) ==
1617
CD_CCB_MEDIA_TOC_LEAD) {
1618
struct cd_toc_single *leadout;
1619
1620
leadout = (struct cd_toc_single *)csio->data_ptr;
1621
softc->toc.entries[cdindex - toch->starting_track] =
1622
leadout->entry;
1623
} else if (((done_ccb->ccb_h.ccb_state & CD_CCB_TYPE_MASK) ==
1624
CD_CCB_MEDIA_TOC_FULL)
1625
&& (cdindex == toch->ending_track + 1)) {
1626
/*
1627
* XXX KDM is this necessary? Probably only if the
1628
* drive doesn't return leadout information with the
1629
* table of contents.
1630
*/
1631
softc->state = CD_STATE_MEDIA_TOC_LEAD;
1632
xpt_release_ccb(done_ccb);
1633
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
1634
return;
1635
}
1636
1637
if (softc->quirks & CD_Q_BCD_TRACKS) {
1638
for (cdindex = 0; cdindex < num_entries - 1; cdindex++){
1639
softc->toc.entries[cdindex].track =
1640
bcd2bin(softc->toc.entries[cdindex].track);
1641
}
1642
}
1643
1644
softc->flags |= CD_FLAG_VALID_TOC;
1645
/* If the first track is audio, correct sector size. */
1646
if ((softc->toc.entries[0].control & 4) == 0) {
1647
softc->disk->d_sectorsize =softc->params.blksize = 2352;
1648
softc->disk->d_mediasize =
1649
(off_t)softc->params.blksize *
1650
softc->params.disksize;
1651
}
1652
softc->state = CD_STATE_NORMAL;
1653
1654
/*
1655
* We unconditionally (re)set the blocksize each time the
1656
* CD device is opened. This is because the CD can change,
1657
* and therefore the blocksize might change.
1658
* XXX problems here if some slice or partition is still
1659
* open with the old size?
1660
*/
1661
if ((softc->disk->d_devstat->flags & DEVSTAT_BS_UNAVAILABLE)!=0)
1662
softc->disk->d_devstat->flags &=
1663
~DEVSTAT_BS_UNAVAILABLE;
1664
softc->disk->d_devstat->block_size = softc->params.blksize;
1665
1666
xpt_release_ccb(done_ccb);
1667
1668
cdmediaprobedone(periph);
1669
1670
if (bioq_first(&softc->bio_queue) != NULL)
1671
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
1672
return;
1673
}
1674
default:
1675
break;
1676
}
1677
xpt_release_ccb(done_ccb);
1678
}
1679
1680
static union cd_pages *
1681
cdgetpage(struct cd_mode_params *mode_params)
1682
{
1683
union cd_pages *page;
1684
1685
if (mode_params->cdb_size == 10)
1686
page = (union cd_pages *)find_mode_page_10(
1687
(struct scsi_mode_header_10 *)mode_params->mode_buf);
1688
else
1689
page = (union cd_pages *)find_mode_page_6(
1690
(struct scsi_mode_header_6 *)mode_params->mode_buf);
1691
1692
return (page);
1693
}
1694
1695
static int
1696
cdgetpagesize(int page_num)
1697
{
1698
u_int i;
1699
1700
for (i = 0; i < nitems(cd_page_size_table); i++) {
1701
if (cd_page_size_table[i].page == page_num)
1702
return (cd_page_size_table[i].page_size);
1703
}
1704
1705
return (-1);
1706
}
1707
1708
static struct cd_toc_entry *
1709
te_data_get_ptr(void *irtep, u_long cmd)
1710
{
1711
union {
1712
struct ioc_read_toc_entry irte;
1713
#ifdef COMPAT_FREEBSD32
1714
struct ioc_read_toc_entry32 irte32;
1715
#endif
1716
} *irteup;
1717
1718
irteup = irtep;
1719
switch (IOCPARM_LEN(cmd)) {
1720
case sizeof(irteup->irte):
1721
return (irteup->irte.data);
1722
#ifdef COMPAT_FREEBSD32
1723
case sizeof(irteup->irte32):
1724
return ((struct cd_toc_entry *)(uintptr_t)irteup->irte32.data);
1725
#endif
1726
default:
1727
panic("Unhandled ioctl command %ld", cmd);
1728
}
1729
}
1730
1731
static int
1732
cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
1733
{
1734
1735
struct cam_periph *periph;
1736
struct cd_softc *softc;
1737
int error = 0;
1738
1739
periph = (struct cam_periph *)dp->d_drv1;
1740
cam_periph_lock(periph);
1741
1742
softc = (struct cd_softc *)periph->softc;
1743
1744
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
1745
("cdioctl(%#lx)\n", cmd));
1746
1747
if ((error = cam_periph_hold(periph, PRIBIO | PCATCH)) != 0) {
1748
cam_periph_unlock(periph);
1749
cam_periph_release(periph);
1750
return (error);
1751
}
1752
1753
/*
1754
* If we don't have media loaded, check for it. If still don't
1755
* have media loaded, we can only do a load or eject.
1756
*
1757
* We only care whether media is loaded if this is a cd-specific ioctl
1758
* (thus the IOCGROUP check below). Note that this will break if
1759
* anyone adds any ioctls into the switch statement below that don't
1760
* have their ioctl group set to 'c'.
1761
*/
1762
if (((softc->flags & CD_FLAG_VALID_MEDIA) == 0)
1763
&& ((cmd != CDIOCCLOSE)
1764
&& (cmd != CDIOCEJECT))
1765
&& (IOCGROUP(cmd) == 'c')) {
1766
error = cdcheckmedia(periph, /*do_wait*/ true);
1767
if (error != 0) {
1768
cam_periph_unhold(periph);
1769
cam_periph_unlock(periph);
1770
return (error);
1771
}
1772
}
1773
/*
1774
* Drop the lock here so later mallocs can use WAITOK. The periph
1775
* is essentially locked still with the cam_periph_hold call above.
1776
*/
1777
cam_periph_unlock(periph);
1778
1779
switch (cmd) {
1780
case CDIOCPLAYTRACKS:
1781
{
1782
struct ioc_play_track *args
1783
= (struct ioc_play_track *) addr;
1784
struct cd_mode_params params;
1785
union cd_pages *page;
1786
1787
params.alloc_len = sizeof(union cd_mode_data_6_10);
1788
params.mode_buf = malloc(params.alloc_len, M_SCSICD,
1789
M_WAITOK | M_ZERO);
1790
1791
cam_periph_lock(periph);
1792
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
1793
("trying to do CDIOCPLAYTRACKS\n"));
1794
1795
error = cdgetmode(periph, &params, AUDIO_PAGE);
1796
if (error) {
1797
free(params.mode_buf, M_SCSICD);
1798
cam_periph_unlock(periph);
1799
break;
1800
}
1801
page = cdgetpage(&params);
1802
1803
page->audio.flags &= ~CD_PA_SOTC;
1804
page->audio.flags |= CD_PA_IMMED;
1805
error = cdsetmode(periph, &params);
1806
free(params.mode_buf, M_SCSICD);
1807
if (error) {
1808
cam_periph_unlock(periph);
1809
break;
1810
}
1811
1812
/*
1813
* This was originally implemented with the PLAY
1814
* AUDIO TRACK INDEX command, but that command was
1815
* deprecated after SCSI-2. Most (all?) SCSI CDROM
1816
* drives support it but ATAPI and ATAPI-derivative
1817
* drives don't seem to support it. So we keep a
1818
* cache of the table of contents and translate
1819
* track numbers to MSF format.
1820
*/
1821
if (softc->flags & CD_FLAG_VALID_TOC) {
1822
union msf_lba *sentry, *eentry;
1823
struct ioc_toc_header *th;
1824
int st, et;
1825
1826
th = &softc->toc.header;
1827
if (args->end_track < th->ending_track + 1)
1828
args->end_track++;
1829
if (args->end_track > th->ending_track + 1)
1830
args->end_track = th->ending_track + 1;
1831
st = args->start_track - th->starting_track;
1832
et = args->end_track - th->starting_track;
1833
if (st < 0 || et < 0 ||
1834
st > th->ending_track - th->starting_track ||
1835
et > th->ending_track - th->starting_track) {
1836
error = EINVAL;
1837
cam_periph_unlock(periph);
1838
break;
1839
}
1840
sentry = &softc->toc.entries[st].addr;
1841
eentry = &softc->toc.entries[et].addr;
1842
error = cdplaymsf(periph,
1843
sentry->msf.minute,
1844
sentry->msf.second,
1845
sentry->msf.frame,
1846
eentry->msf.minute,
1847
eentry->msf.second,
1848
eentry->msf.frame);
1849
} else {
1850
/*
1851
* If we don't have a valid TOC, try the
1852
* play track index command. It is part of
1853
* the SCSI-2 spec, but was removed in the
1854
* MMC specs. ATAPI and ATAPI-derived
1855
* drives don't support it.
1856
*/
1857
if (softc->quirks & CD_Q_BCD_TRACKS) {
1858
args->start_track =
1859
bin2bcd(args->start_track);
1860
args->end_track =
1861
bin2bcd(args->end_track);
1862
}
1863
error = cdplaytracks(periph,
1864
args->start_track,
1865
args->start_index,
1866
args->end_track,
1867
args->end_index);
1868
}
1869
cam_periph_unlock(periph);
1870
}
1871
break;
1872
case CDIOCPLAYMSF:
1873
{
1874
struct ioc_play_msf *args
1875
= (struct ioc_play_msf *) addr;
1876
struct cd_mode_params params;
1877
union cd_pages *page;
1878
1879
params.alloc_len = sizeof(union cd_mode_data_6_10);
1880
params.mode_buf = malloc(params.alloc_len, M_SCSICD,
1881
M_WAITOK | M_ZERO);
1882
1883
cam_periph_lock(periph);
1884
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
1885
("trying to do CDIOCPLAYMSF\n"));
1886
1887
error = cdgetmode(periph, &params, AUDIO_PAGE);
1888
if (error) {
1889
free(params.mode_buf, M_SCSICD);
1890
cam_periph_unlock(periph);
1891
break;
1892
}
1893
page = cdgetpage(&params);
1894
1895
page->audio.flags &= ~CD_PA_SOTC;
1896
page->audio.flags |= CD_PA_IMMED;
1897
error = cdsetmode(periph, &params);
1898
free(params.mode_buf, M_SCSICD);
1899
if (error) {
1900
cam_periph_unlock(periph);
1901
break;
1902
}
1903
error = cdplaymsf(periph,
1904
args->start_m,
1905
args->start_s,
1906
args->start_f,
1907
args->end_m,
1908
args->end_s,
1909
args->end_f);
1910
cam_periph_unlock(periph);
1911
}
1912
break;
1913
case CDIOCPLAYBLOCKS:
1914
{
1915
struct ioc_play_blocks *args
1916
= (struct ioc_play_blocks *) addr;
1917
struct cd_mode_params params;
1918
union cd_pages *page;
1919
1920
params.alloc_len = sizeof(union cd_mode_data_6_10);
1921
params.mode_buf = malloc(params.alloc_len, M_SCSICD,
1922
M_WAITOK | M_ZERO);
1923
1924
cam_periph_lock(periph);
1925
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
1926
("trying to do CDIOCPLAYBLOCKS\n"));
1927
1928
error = cdgetmode(periph, &params, AUDIO_PAGE);
1929
if (error) {
1930
free(params.mode_buf, M_SCSICD);
1931
cam_periph_unlock(periph);
1932
break;
1933
}
1934
page = cdgetpage(&params);
1935
1936
page->audio.flags &= ~CD_PA_SOTC;
1937
page->audio.flags |= CD_PA_IMMED;
1938
error = cdsetmode(periph, &params);
1939
free(params.mode_buf, M_SCSICD);
1940
if (error) {
1941
cam_periph_unlock(periph);
1942
break;
1943
}
1944
error = cdplay(periph, args->blk, args->len);
1945
cam_periph_unlock(periph);
1946
}
1947
break;
1948
case CDIOCREADSUBCHANNEL:
1949
{
1950
struct ioc_read_subchannel *args
1951
= (struct ioc_read_subchannel *) addr;
1952
struct cd_sub_channel_info *data;
1953
uint32_t len = args->data_len;
1954
1955
data = malloc(sizeof(struct cd_sub_channel_info),
1956
M_SCSICD, M_WAITOK | M_ZERO);
1957
1958
cam_periph_lock(periph);
1959
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
1960
("trying to do CDIOCREADSUBCHANNEL\n"));
1961
1962
if ((len > sizeof(struct cd_sub_channel_info)) ||
1963
(len < sizeof(struct cd_sub_channel_header))) {
1964
printf(
1965
"scsi_cd: cdioctl: "
1966
"cdioreadsubchannel: error, len=%d\n",
1967
len);
1968
error = EINVAL;
1969
free(data, M_SCSICD);
1970
cam_periph_unlock(periph);
1971
break;
1972
}
1973
1974
if (softc->quirks & CD_Q_BCD_TRACKS)
1975
args->track = bin2bcd(args->track);
1976
1977
error = cdreadsubchannel(periph, args->address_format,
1978
args->data_format, args->track, data, len);
1979
1980
if (error) {
1981
free(data, M_SCSICD);
1982
cam_periph_unlock(periph);
1983
break;
1984
}
1985
if (softc->quirks & CD_Q_BCD_TRACKS)
1986
data->what.track_info.track_number =
1987
bcd2bin(data->what.track_info.track_number);
1988
len = min(len, ((data->header.data_len[0] << 8) +
1989
data->header.data_len[1] +
1990
sizeof(struct cd_sub_channel_header)));
1991
cam_periph_unlock(periph);
1992
error = copyout(data, args->data, len);
1993
free(data, M_SCSICD);
1994
}
1995
break;
1996
1997
case CDIOREADTOCHEADER:
1998
{
1999
struct ioc_toc_header *th;
2000
2001
th = malloc(sizeof(struct ioc_toc_header), M_SCSICD,
2002
M_WAITOK | M_ZERO);
2003
2004
cam_periph_lock(periph);
2005
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
2006
("trying to do CDIOREADTOCHEADER\n"));
2007
2008
error = cdreadtoc(periph, 0, 0, (uint8_t *)th,
2009
sizeof (*th), /*sense_flags*/SF_NO_PRINT);
2010
if (error) {
2011
free(th, M_SCSICD);
2012
cam_periph_unlock(periph);
2013
break;
2014
}
2015
if (softc->quirks & CD_Q_BCD_TRACKS) {
2016
/* we are going to have to convert the BCD
2017
* encoding on the cd to what is expected
2018
*/
2019
th->starting_track =
2020
bcd2bin(th->starting_track);
2021
th->ending_track = bcd2bin(th->ending_track);
2022
}
2023
th->len = ntohs(th->len);
2024
bcopy(th, addr, sizeof(*th));
2025
free(th, M_SCSICD);
2026
cam_periph_unlock(periph);
2027
}
2028
break;
2029
case CDIOREADTOCENTRYS:
2030
#ifdef COMPAT_FREEBSD32
2031
case CDIOREADTOCENTRYS_32:
2032
#endif
2033
{
2034
struct cd_tocdata *data;
2035
struct cd_toc_single *lead;
2036
struct ioc_read_toc_entry *te =
2037
(struct ioc_read_toc_entry *) addr;
2038
struct ioc_toc_header *th;
2039
uint32_t len, readlen, idx, num;
2040
uint32_t starting_track = te->starting_track;
2041
2042
data = malloc(sizeof(*data), M_SCSICD, M_WAITOK | M_ZERO);
2043
lead = malloc(sizeof(*lead), M_SCSICD, M_WAITOK | M_ZERO);
2044
2045
cam_periph_lock(periph);
2046
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
2047
("trying to do CDIOREADTOCENTRYS\n"));
2048
2049
if (te->data_len < sizeof(struct cd_toc_entry)
2050
|| (te->data_len % sizeof(struct cd_toc_entry)) != 0
2051
|| (te->address_format != CD_MSF_FORMAT
2052
&& te->address_format != CD_LBA_FORMAT)) {
2053
error = EINVAL;
2054
printf("scsi_cd: error in readtocentries, "
2055
"returning EINVAL\n");
2056
free(data, M_SCSICD);
2057
free(lead, M_SCSICD);
2058
cam_periph_unlock(periph);
2059
break;
2060
}
2061
2062
th = &data->header;
2063
error = cdreadtoc(periph, 0, 0, (uint8_t *)th,
2064
sizeof (*th), /*sense_flags*/0);
2065
if (error) {
2066
free(data, M_SCSICD);
2067
free(lead, M_SCSICD);
2068
cam_periph_unlock(periph);
2069
break;
2070
}
2071
2072
if (softc->quirks & CD_Q_BCD_TRACKS) {
2073
/* we are going to have to convert the BCD
2074
* encoding on the cd to what is expected
2075
*/
2076
th->starting_track =
2077
bcd2bin(th->starting_track);
2078
th->ending_track = bcd2bin(th->ending_track);
2079
}
2080
2081
if (starting_track == 0)
2082
starting_track = th->starting_track;
2083
else if (starting_track == LEADOUT)
2084
starting_track = th->ending_track + 1;
2085
else if (starting_track < th->starting_track ||
2086
starting_track > th->ending_track + 1) {
2087
printf("scsi_cd: error in readtocentries, "
2088
"returning EINVAL\n");
2089
free(data, M_SCSICD);
2090
free(lead, M_SCSICD);
2091
cam_periph_unlock(periph);
2092
error = EINVAL;
2093
break;
2094
}
2095
2096
/* calculate reading length without leadout entry */
2097
readlen = (th->ending_track - starting_track + 1) *
2098
sizeof(struct cd_toc_entry);
2099
2100
/* and with leadout entry */
2101
len = readlen + sizeof(struct cd_toc_entry);
2102
if (te->data_len < len) {
2103
len = te->data_len;
2104
if (readlen > len)
2105
readlen = len;
2106
}
2107
if (len > sizeof(data->entries)) {
2108
printf("scsi_cd: error in readtocentries, "
2109
"returning EINVAL\n");
2110
error = EINVAL;
2111
free(data, M_SCSICD);
2112
free(lead, M_SCSICD);
2113
cam_periph_unlock(periph);
2114
break;
2115
}
2116
num = len / sizeof(struct cd_toc_entry);
2117
2118
if (readlen > 0) {
2119
error = cdreadtoc(periph, te->address_format,
2120
starting_track,
2121
(uint8_t *)data,
2122
readlen + sizeof (*th),
2123
/*sense_flags*/0);
2124
if (error) {
2125
free(data, M_SCSICD);
2126
free(lead, M_SCSICD);
2127
cam_periph_unlock(periph);
2128
break;
2129
}
2130
}
2131
2132
/* make leadout entry if needed */
2133
idx = starting_track + num - 1;
2134
if (softc->quirks & CD_Q_BCD_TRACKS)
2135
th->ending_track = bcd2bin(th->ending_track);
2136
if (idx == th->ending_track + 1) {
2137
error = cdreadtoc(periph, te->address_format,
2138
LEADOUT, (uint8_t *)lead,
2139
sizeof(*lead),
2140
/*sense_flags*/0);
2141
if (error) {
2142
free(data, M_SCSICD);
2143
free(lead, M_SCSICD);
2144
cam_periph_unlock(periph);
2145
break;
2146
}
2147
data->entries[idx - starting_track] =
2148
lead->entry;
2149
}
2150
if (softc->quirks & CD_Q_BCD_TRACKS) {
2151
for (idx = 0; idx < num - 1; idx++) {
2152
data->entries[idx].track =
2153
bcd2bin(data->entries[idx].track);
2154
}
2155
}
2156
2157
cam_periph_unlock(periph);
2158
error = copyout(data->entries, te_data_get_ptr(te, cmd),
2159
len);
2160
free(data, M_SCSICD);
2161
free(lead, M_SCSICD);
2162
}
2163
break;
2164
case CDIOREADTOCENTRY:
2165
{
2166
struct cd_toc_single *data;
2167
struct ioc_read_toc_single_entry *te =
2168
(struct ioc_read_toc_single_entry *) addr;
2169
struct ioc_toc_header *th;
2170
uint32_t track;
2171
2172
data = malloc(sizeof(*data), M_SCSICD, M_WAITOK | M_ZERO);
2173
2174
cam_periph_lock(periph);
2175
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
2176
("trying to do CDIOREADTOCENTRY\n"));
2177
2178
if (te->address_format != CD_MSF_FORMAT
2179
&& te->address_format != CD_LBA_FORMAT) {
2180
printf("error in readtocentry, "
2181
" returning EINVAL\n");
2182
free(data, M_SCSICD);
2183
error = EINVAL;
2184
cam_periph_unlock(periph);
2185
break;
2186
}
2187
2188
th = &data->header;
2189
error = cdreadtoc(periph, 0, 0, (uint8_t *)th,
2190
sizeof (*th), /*sense_flags*/0);
2191
if (error) {
2192
free(data, M_SCSICD);
2193
cam_periph_unlock(periph);
2194
break;
2195
}
2196
2197
if (softc->quirks & CD_Q_BCD_TRACKS) {
2198
/* we are going to have to convert the BCD
2199
* encoding on the cd to what is expected
2200
*/
2201
th->starting_track =
2202
bcd2bin(th->starting_track);
2203
th->ending_track = bcd2bin(th->ending_track);
2204
}
2205
track = te->track;
2206
if (track == 0)
2207
track = th->starting_track;
2208
else if (track == LEADOUT)
2209
/* OK */;
2210
else if (track < th->starting_track ||
2211
track > th->ending_track + 1) {
2212
printf("error in readtocentry, "
2213
" returning EINVAL\n");
2214
free(data, M_SCSICD);
2215
error = EINVAL;
2216
cam_periph_unlock(periph);
2217
break;
2218
}
2219
2220
error = cdreadtoc(periph, te->address_format, track,
2221
(uint8_t *)data, sizeof(*data),
2222
/*sense_flags*/0);
2223
if (error) {
2224
free(data, M_SCSICD);
2225
cam_periph_unlock(periph);
2226
break;
2227
}
2228
2229
if (softc->quirks & CD_Q_BCD_TRACKS)
2230
data->entry.track = bcd2bin(data->entry.track);
2231
bcopy(&data->entry, &te->entry,
2232
sizeof(struct cd_toc_entry));
2233
free(data, M_SCSICD);
2234
cam_periph_unlock(periph);
2235
}
2236
break;
2237
case CDIOCSETPATCH:
2238
{
2239
struct ioc_patch *arg = (struct ioc_patch *)addr;
2240
struct cd_mode_params params;
2241
union cd_pages *page;
2242
2243
params.alloc_len = sizeof(union cd_mode_data_6_10);
2244
params.mode_buf = malloc(params.alloc_len, M_SCSICD,
2245
M_WAITOK | M_ZERO);
2246
2247
cam_periph_lock(periph);
2248
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
2249
("trying to do CDIOCSETPATCH\n"));
2250
2251
error = cdgetmode(periph, &params, AUDIO_PAGE);
2252
if (error) {
2253
free(params.mode_buf, M_SCSICD);
2254
cam_periph_unlock(periph);
2255
break;
2256
}
2257
page = cdgetpage(&params);
2258
2259
page->audio.port[LEFT_PORT].channels =
2260
arg->patch[0];
2261
page->audio.port[RIGHT_PORT].channels =
2262
arg->patch[1];
2263
page->audio.port[2].channels = arg->patch[2];
2264
page->audio.port[3].channels = arg->patch[3];
2265
error = cdsetmode(periph, &params);
2266
free(params.mode_buf, M_SCSICD);
2267
cam_periph_unlock(periph);
2268
}
2269
break;
2270
case CDIOCGETVOL:
2271
{
2272
struct ioc_vol *arg = (struct ioc_vol *) addr;
2273
struct cd_mode_params params;
2274
union cd_pages *page;
2275
2276
params.alloc_len = sizeof(union cd_mode_data_6_10);
2277
params.mode_buf = malloc(params.alloc_len, M_SCSICD,
2278
M_WAITOK | M_ZERO);
2279
2280
cam_periph_lock(periph);
2281
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
2282
("trying to do CDIOCGETVOL\n"));
2283
2284
error = cdgetmode(periph, &params, AUDIO_PAGE);
2285
if (error) {
2286
free(params.mode_buf, M_SCSICD);
2287
cam_periph_unlock(periph);
2288
break;
2289
}
2290
page = cdgetpage(&params);
2291
2292
arg->vol[LEFT_PORT] =
2293
page->audio.port[LEFT_PORT].volume;
2294
arg->vol[RIGHT_PORT] =
2295
page->audio.port[RIGHT_PORT].volume;
2296
arg->vol[2] = page->audio.port[2].volume;
2297
arg->vol[3] = page->audio.port[3].volume;
2298
free(params.mode_buf, M_SCSICD);
2299
cam_periph_unlock(periph);
2300
}
2301
break;
2302
case CDIOCSETVOL:
2303
{
2304
struct ioc_vol *arg = (struct ioc_vol *) addr;
2305
struct cd_mode_params params;
2306
union cd_pages *page;
2307
2308
params.alloc_len = sizeof(union cd_mode_data_6_10);
2309
params.mode_buf = malloc(params.alloc_len, M_SCSICD,
2310
M_WAITOK | M_ZERO);
2311
2312
cam_periph_lock(periph);
2313
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
2314
("trying to do CDIOCSETVOL\n"));
2315
2316
error = cdgetmode(periph, &params, AUDIO_PAGE);
2317
if (error) {
2318
free(params.mode_buf, M_SCSICD);
2319
cam_periph_unlock(periph);
2320
break;
2321
}
2322
page = cdgetpage(&params);
2323
2324
page->audio.port[LEFT_PORT].channels = CHANNEL_0;
2325
page->audio.port[LEFT_PORT].volume =
2326
arg->vol[LEFT_PORT];
2327
page->audio.port[RIGHT_PORT].channels = CHANNEL_1;
2328
page->audio.port[RIGHT_PORT].volume =
2329
arg->vol[RIGHT_PORT];
2330
page->audio.port[2].volume = arg->vol[2];
2331
page->audio.port[3].volume = arg->vol[3];
2332
error = cdsetmode(periph, &params);
2333
cam_periph_unlock(periph);
2334
free(params.mode_buf, M_SCSICD);
2335
}
2336
break;
2337
case CDIOCSETMONO:
2338
{
2339
struct cd_mode_params params;
2340
union cd_pages *page;
2341
2342
params.alloc_len = sizeof(union cd_mode_data_6_10);
2343
params.mode_buf = malloc(params.alloc_len, M_SCSICD,
2344
M_WAITOK | M_ZERO);
2345
2346
cam_periph_lock(periph);
2347
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
2348
("trying to do CDIOCSETMONO\n"));
2349
2350
error = cdgetmode(periph, &params, AUDIO_PAGE);
2351
if (error) {
2352
free(params.mode_buf, M_SCSICD);
2353
cam_periph_unlock(periph);
2354
break;
2355
}
2356
page = cdgetpage(&params);
2357
2358
page->audio.port[LEFT_PORT].channels =
2359
LEFT_CHANNEL | RIGHT_CHANNEL;
2360
page->audio.port[RIGHT_PORT].channels =
2361
LEFT_CHANNEL | RIGHT_CHANNEL;
2362
page->audio.port[2].channels = 0;
2363
page->audio.port[3].channels = 0;
2364
error = cdsetmode(periph, &params);
2365
cam_periph_unlock(periph);
2366
free(params.mode_buf, M_SCSICD);
2367
}
2368
break;
2369
case CDIOCSETSTEREO:
2370
{
2371
struct cd_mode_params params;
2372
union cd_pages *page;
2373
2374
params.alloc_len = sizeof(union cd_mode_data_6_10);
2375
params.mode_buf = malloc(params.alloc_len, M_SCSICD,
2376
M_WAITOK | M_ZERO);
2377
2378
cam_periph_lock(periph);
2379
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
2380
("trying to do CDIOCSETSTEREO\n"));
2381
2382
error = cdgetmode(periph, &params, AUDIO_PAGE);
2383
if (error) {
2384
free(params.mode_buf, M_SCSICD);
2385
cam_periph_unlock(periph);
2386
break;
2387
}
2388
page = cdgetpage(&params);
2389
2390
page->audio.port[LEFT_PORT].channels =
2391
LEFT_CHANNEL;
2392
page->audio.port[RIGHT_PORT].channels =
2393
RIGHT_CHANNEL;
2394
page->audio.port[2].channels = 0;
2395
page->audio.port[3].channels = 0;
2396
error = cdsetmode(periph, &params);
2397
free(params.mode_buf, M_SCSICD);
2398
cam_periph_unlock(periph);
2399
}
2400
break;
2401
case CDIOCSETMUTE:
2402
{
2403
struct cd_mode_params params;
2404
union cd_pages *page;
2405
2406
params.alloc_len = sizeof(union cd_mode_data_6_10);
2407
params.mode_buf = malloc(params.alloc_len, M_SCSICD,
2408
M_WAITOK | M_ZERO);
2409
2410
cam_periph_lock(periph);
2411
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
2412
("trying to do CDIOCSETMUTE\n"));
2413
2414
error = cdgetmode(periph, &params, AUDIO_PAGE);
2415
if (error) {
2416
free(params.mode_buf, M_SCSICD);
2417
cam_periph_unlock(periph);
2418
break;
2419
}
2420
page = cdgetpage(&params);
2421
2422
page->audio.port[LEFT_PORT].channels = 0;
2423
page->audio.port[RIGHT_PORT].channels = 0;
2424
page->audio.port[2].channels = 0;
2425
page->audio.port[3].channels = 0;
2426
error = cdsetmode(periph, &params);
2427
free(params.mode_buf, M_SCSICD);
2428
cam_periph_unlock(periph);
2429
}
2430
break;
2431
case CDIOCSETLEFT:
2432
{
2433
struct cd_mode_params params;
2434
union cd_pages *page;
2435
2436
params.alloc_len = sizeof(union cd_mode_data_6_10);
2437
params.mode_buf = malloc(params.alloc_len, M_SCSICD,
2438
M_WAITOK | M_ZERO);
2439
2440
cam_periph_lock(periph);
2441
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
2442
("trying to do CDIOCSETLEFT\n"));
2443
2444
error = cdgetmode(periph, &params, AUDIO_PAGE);
2445
if (error) {
2446
free(params.mode_buf, M_SCSICD);
2447
cam_periph_unlock(periph);
2448
break;
2449
}
2450
page = cdgetpage(&params);
2451
2452
page->audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
2453
page->audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
2454
page->audio.port[2].channels = 0;
2455
page->audio.port[3].channels = 0;
2456
error = cdsetmode(periph, &params);
2457
free(params.mode_buf, M_SCSICD);
2458
cam_periph_unlock(periph);
2459
}
2460
break;
2461
case CDIOCSETRIGHT:
2462
{
2463
struct cd_mode_params params;
2464
union cd_pages *page;
2465
2466
params.alloc_len = sizeof(union cd_mode_data_6_10);
2467
params.mode_buf = malloc(params.alloc_len, M_SCSICD,
2468
M_WAITOK | M_ZERO);
2469
2470
cam_periph_lock(periph);
2471
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
2472
("trying to do CDIOCSETRIGHT\n"));
2473
2474
error = cdgetmode(periph, &params, AUDIO_PAGE);
2475
if (error) {
2476
free(params.mode_buf, M_SCSICD);
2477
cam_periph_unlock(periph);
2478
break;
2479
}
2480
page = cdgetpage(&params);
2481
2482
page->audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
2483
page->audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
2484
page->audio.port[2].channels = 0;
2485
page->audio.port[3].channels = 0;
2486
error = cdsetmode(periph, &params);
2487
free(params.mode_buf, M_SCSICD);
2488
cam_periph_unlock(periph);
2489
}
2490
break;
2491
case CDIOCRESUME:
2492
cam_periph_lock(periph);
2493
error = cdpause(periph, 1);
2494
cam_periph_unlock(periph);
2495
break;
2496
case CDIOCPAUSE:
2497
cam_periph_lock(periph);
2498
error = cdpause(periph, 0);
2499
cam_periph_unlock(periph);
2500
break;
2501
case CDIOCSTART:
2502
cam_periph_lock(periph);
2503
error = cdstartunit(periph, 0);
2504
cam_periph_unlock(periph);
2505
break;
2506
case CDIOCCLOSE:
2507
cam_periph_lock(periph);
2508
error = cdstartunit(periph, 1);
2509
cam_periph_unlock(periph);
2510
break;
2511
case CDIOCSTOP:
2512
cam_periph_lock(periph);
2513
error = cdstopunit(periph, 0);
2514
cam_periph_unlock(periph);
2515
break;
2516
case CDIOCEJECT:
2517
cam_periph_lock(periph);
2518
error = cdstopunit(periph, 1);
2519
cam_periph_unlock(periph);
2520
break;
2521
case CDIOCALLOW:
2522
cam_periph_lock(periph);
2523
cdprevent(periph, PR_ALLOW);
2524
cam_periph_unlock(periph);
2525
break;
2526
case CDIOCPREVENT:
2527
cam_periph_lock(periph);
2528
cdprevent(periph, PR_PREVENT);
2529
cam_periph_unlock(periph);
2530
break;
2531
case CDIOCSETDEBUG:
2532
/* sc_link->flags |= (SDEV_DB1 | SDEV_DB2); */
2533
error = ENOTTY;
2534
break;
2535
case CDIOCCLRDEBUG:
2536
/* sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2); */
2537
error = ENOTTY;
2538
break;
2539
case CDIOCRESET:
2540
/* return (cd_reset(periph)); */
2541
error = ENOTTY;
2542
break;
2543
case CDRIOCREADSPEED:
2544
cam_periph_lock(periph);
2545
error = cdsetspeed(periph, *(uint32_t *)addr, CDR_MAX_SPEED);
2546
cam_periph_unlock(periph);
2547
break;
2548
case CDRIOCWRITESPEED:
2549
cam_periph_lock(periph);
2550
error = cdsetspeed(periph, CDR_MAX_SPEED, *(uint32_t *)addr);
2551
cam_periph_unlock(periph);
2552
break;
2553
case CDRIOCGETBLOCKSIZE:
2554
*(int *)addr = softc->params.blksize;
2555
break;
2556
case CDRIOCSETBLOCKSIZE:
2557
if (*(int *)addr <= 0) {
2558
error = EINVAL;
2559
break;
2560
}
2561
softc->disk->d_sectorsize = softc->params.blksize = *(int *)addr;
2562
break;
2563
case DVDIOCSENDKEY:
2564
case DVDIOCREPORTKEY: {
2565
struct dvd_authinfo *authinfo;
2566
2567
authinfo = (struct dvd_authinfo *)addr;
2568
2569
if (cmd == DVDIOCREPORTKEY)
2570
error = cdreportkey(periph, authinfo);
2571
else
2572
error = cdsendkey(periph, authinfo);
2573
break;
2574
}
2575
case DVDIOCREADSTRUCTURE: {
2576
struct dvd_struct *dvdstruct;
2577
2578
dvdstruct = (struct dvd_struct *)addr;
2579
2580
error = cdreaddvdstructure(periph, dvdstruct);
2581
2582
break;
2583
}
2584
default:
2585
cam_periph_lock(periph);
2586
error = cam_periph_ioctl(periph, cmd, addr, cderror);
2587
cam_periph_unlock(periph);
2588
break;
2589
}
2590
2591
cam_periph_lock(periph);
2592
cam_periph_unhold(periph);
2593
2594
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdioctl\n"));
2595
if (error && bootverbose) {
2596
printf("scsi_cd.c::ioctl cmd=%08lx error=%d\n", cmd, error);
2597
}
2598
cam_periph_unlock(periph);
2599
2600
return (error);
2601
}
2602
2603
static void
2604
cdprevent(struct cam_periph *periph, int action)
2605
{
2606
union ccb *ccb;
2607
struct cd_softc *softc;
2608
int error;
2609
2610
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdprevent\n"));
2611
2612
cam_periph_assert(periph, MA_OWNED);
2613
softc = (struct cd_softc *)periph->softc;
2614
2615
if (((action == PR_ALLOW)
2616
&& (softc->flags & CD_FLAG_DISC_LOCKED) == 0)
2617
|| ((action == PR_PREVENT)
2618
&& (softc->flags & CD_FLAG_DISC_LOCKED) != 0)) {
2619
return;
2620
}
2621
2622
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
2623
2624
scsi_prevent(&ccb->csio,
2625
/*retries*/ cd_retry_count,
2626
/*cbfcnp*/NULL,
2627
MSG_SIMPLE_Q_TAG,
2628
action,
2629
SSD_FULL_SIZE,
2630
/* timeout */60000);
2631
2632
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
2633
/*sense_flags*/SF_RETRY_UA|SF_NO_PRINT);
2634
2635
xpt_release_ccb(ccb);
2636
2637
if (error == 0) {
2638
if (action == PR_ALLOW)
2639
softc->flags &= ~CD_FLAG_DISC_LOCKED;
2640
else
2641
softc->flags |= CD_FLAG_DISC_LOCKED;
2642
}
2643
}
2644
2645
static void
2646
cdmediaprobedone(struct cam_periph *periph)
2647
{
2648
struct cd_softc *softc;
2649
2650
cam_periph_assert(periph, MA_OWNED);
2651
softc = (struct cd_softc *)periph->softc;
2652
2653
softc->flags &= ~CD_FLAG_MEDIA_SCAN_ACT;
2654
2655
if ((softc->flags & CD_FLAG_MEDIA_WAIT) != 0) {
2656
softc->flags &= ~CD_FLAG_MEDIA_WAIT;
2657
wakeup(&softc->toc);
2658
}
2659
cam_periph_release_locked(periph);
2660
}
2661
2662
/*
2663
* XXX: the disk media and sector size is only really able to change
2664
* XXX: while the device is closed.
2665
*/
2666
2667
static int
2668
cdcheckmedia(struct cam_periph *periph, bool do_wait)
2669
{
2670
struct cd_softc *softc;
2671
int error;
2672
2673
cam_periph_assert(periph, MA_OWNED);
2674
softc = (struct cd_softc *)periph->softc;
2675
error = 0;
2676
2677
/* Released by cdmediaprobedone(). */
2678
error = cam_periph_acquire(periph);
2679
if (error != 0)
2680
return (error);
2681
2682
if (do_wait)
2683
softc->flags |= CD_FLAG_MEDIA_WAIT;
2684
if ((softc->flags & CD_FLAG_MEDIA_SCAN_ACT) == 0) {
2685
softc->state = CD_STATE_MEDIA_PREVENT;
2686
softc->flags |= CD_FLAG_MEDIA_SCAN_ACT;
2687
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
2688
}
2689
if (!do_wait)
2690
return (0);
2691
2692
error = msleep(&softc->toc, cam_periph_mtx(periph), PRIBIO,"cdmedia",0);
2693
2694
/*
2695
* Check to see whether we have a valid size from the media. We
2696
* may or may not have a valid TOC.
2697
*/
2698
if (error == 0 && (softc->flags & CD_FLAG_VALID_MEDIA) == 0)
2699
error = EINVAL;
2700
2701
return (error);
2702
}
2703
2704
static int
2705
cd6byteworkaround(union ccb *ccb)
2706
{
2707
uint8_t *cdb;
2708
struct cam_periph *periph;
2709
struct cd_softc *softc;
2710
struct cd_mode_params *params;
2711
int frozen, found;
2712
2713
periph = xpt_path_periph(ccb->ccb_h.path);
2714
softc = (struct cd_softc *)periph->softc;
2715
2716
cdb = ccb->csio.cdb_io.cdb_bytes;
2717
2718
if ((ccb->ccb_h.flags & CAM_CDB_POINTER)
2719
|| ((cdb[0] != MODE_SENSE_6)
2720
&& (cdb[0] != MODE_SELECT_6)))
2721
return (0);
2722
2723
/*
2724
* Because there is no convenient place to stash the overall
2725
* cd_mode_params structure pointer, we have to grab it like this.
2726
* This means that ALL MODE_SENSE and MODE_SELECT requests in the
2727
* cd(4) driver MUST go through cdgetmode() and cdsetmode()!
2728
*
2729
* XXX It would be nice if, at some point, we could increase the
2730
* number of available peripheral private pointers. Both pointers
2731
* are currently used in most every peripheral driver.
2732
*/
2733
found = 0;
2734
2735
STAILQ_FOREACH(params, &softc->mode_queue, links) {
2736
if (params->mode_buf == ccb->csio.data_ptr) {
2737
found = 1;
2738
break;
2739
}
2740
}
2741
2742
/*
2743
* This shouldn't happen. All mode sense and mode select
2744
* operations in the cd(4) driver MUST go through cdgetmode() and
2745
* cdsetmode()!
2746
*/
2747
if (found == 0) {
2748
xpt_print(periph->path,
2749
"mode buffer not found in mode queue!\n");
2750
return (0);
2751
}
2752
2753
params->cdb_size = 10;
2754
softc->minimum_command_size = 10;
2755
xpt_print(ccb->ccb_h.path,
2756
"%s(6) failed, increasing minimum CDB size to 10 bytes\n",
2757
(cdb[0] == MODE_SENSE_6) ? "MODE_SENSE" : "MODE_SELECT");
2758
2759
if (cdb[0] == MODE_SENSE_6) {
2760
struct scsi_mode_sense_10 ms10;
2761
struct scsi_mode_sense_6 *ms6;
2762
int len;
2763
2764
ms6 = (struct scsi_mode_sense_6 *)cdb;
2765
2766
bzero(&ms10, sizeof(ms10));
2767
ms10.opcode = MODE_SENSE_10;
2768
ms10.byte2 = ms6->byte2;
2769
ms10.page = ms6->page;
2770
2771
/*
2772
* 10 byte mode header, block descriptor,
2773
* sizeof(union cd_pages)
2774
*/
2775
len = sizeof(struct cd_mode_data_10);
2776
ccb->csio.dxfer_len = len;
2777
2778
scsi_ulto2b(len, ms10.length);
2779
ms10.control = ms6->control;
2780
bcopy(&ms10, cdb, 10);
2781
ccb->csio.cdb_len = 10;
2782
} else {
2783
struct scsi_mode_select_10 ms10;
2784
struct scsi_mode_select_6 *ms6;
2785
struct scsi_mode_header_6 *header6;
2786
struct scsi_mode_header_10 *header10;
2787
struct scsi_mode_page_header *page_header;
2788
int blk_desc_len, page_num, page_size, len;
2789
2790
ms6 = (struct scsi_mode_select_6 *)cdb;
2791
2792
bzero(&ms10, sizeof(ms10));
2793
ms10.opcode = MODE_SELECT_10;
2794
ms10.byte2 = ms6->byte2;
2795
2796
header6 = (struct scsi_mode_header_6 *)params->mode_buf;
2797
header10 = (struct scsi_mode_header_10 *)params->mode_buf;
2798
2799
page_header = find_mode_page_6(header6);
2800
page_num = page_header->page_code;
2801
2802
blk_desc_len = header6->blk_desc_len;
2803
2804
page_size = cdgetpagesize(page_num);
2805
2806
if (page_size != (page_header->page_length +
2807
sizeof(*page_header)))
2808
page_size = page_header->page_length +
2809
sizeof(*page_header);
2810
2811
len = sizeof(*header10) + blk_desc_len + page_size;
2812
2813
len = min(params->alloc_len, len);
2814
2815
/*
2816
* Since the 6 byte parameter header is shorter than the 10
2817
* byte parameter header, we need to copy the actual mode
2818
* page data, and the block descriptor, if any, so things wind
2819
* up in the right place. The regions will overlap, but
2820
* bcopy() does the right thing.
2821
*/
2822
bcopy(params->mode_buf + sizeof(*header6),
2823
params->mode_buf + sizeof(*header10),
2824
len - sizeof(*header10));
2825
2826
/* Make sure these fields are set correctly. */
2827
scsi_ulto2b(0, header10->data_length);
2828
header10->medium_type = 0;
2829
scsi_ulto2b(blk_desc_len, header10->blk_desc_len);
2830
2831
ccb->csio.dxfer_len = len;
2832
2833
scsi_ulto2b(len, ms10.length);
2834
ms10.control = ms6->control;
2835
bcopy(&ms10, cdb, 10);
2836
ccb->csio.cdb_len = 10;
2837
}
2838
2839
frozen = (ccb->ccb_h.status & CAM_DEV_QFRZN) != 0;
2840
ccb->ccb_h.status = CAM_REQUEUE_REQ;
2841
xpt_action(ccb);
2842
if (frozen) {
2843
cam_release_devq(ccb->ccb_h.path,
2844
/*relsim_flags*/0,
2845
/*openings*/0,
2846
/*timeout*/0,
2847
/*getcount_only*/0);
2848
}
2849
2850
return (ERESTART);
2851
}
2852
2853
static int
2854
cderror(union ccb *ccb, uint32_t cam_flags, uint32_t sense_flags)
2855
{
2856
struct cd_softc *softc;
2857
struct cam_periph *periph;
2858
int error, error_code, sense_key, asc, ascq;
2859
2860
periph = xpt_path_periph(ccb->ccb_h.path);
2861
softc = (struct cd_softc *)periph->softc;
2862
2863
cam_periph_assert(periph, MA_OWNED);
2864
2865
/*
2866
* We use a status of CAM_REQ_INVALID as shorthand -- if a 6 byte
2867
* CDB comes back with this particular error, try transforming it
2868
* into the 10 byte version.
2869
*/
2870
error = 0;
2871
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INVALID) {
2872
error = cd6byteworkaround(ccb);
2873
} else if (scsi_extract_sense_ccb(ccb,
2874
&error_code, &sense_key, &asc, &ascq)) {
2875
if (sense_key == SSD_KEY_ILLEGAL_REQUEST) {
2876
error = cd6byteworkaround(ccb);
2877
} else if (sense_key == SSD_KEY_UNIT_ATTENTION &&
2878
asc == 0x28 && ascq == 0x00) {
2879
/* 28/0: NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED */
2880
disk_media_changed(softc->disk, M_NOWAIT);
2881
} else if (sense_key == SSD_KEY_NOT_READY &&
2882
asc == 0x3a && (softc->flags & CD_FLAG_VALID_MEDIA)) {
2883
/* 3a/0: MEDIUM NOT PRESENT */
2884
/* 3a/1: MEDIUM NOT PRESENT - TRAY CLOSED */
2885
/* 3a/2: MEDIUM NOT PRESENT - TRAY OPEN */
2886
/* 3a/3: MEDIUM NOT PRESENT - LOADABLE */
2887
/* 3a/4: MEDIUM NOT PRESENT - MEDIUM AUXILIARY MEMORY ACCESSIBLE */
2888
softc->flags &= ~CD_FLAG_VALID_MEDIA;
2889
disk_media_gone(softc->disk, M_NOWAIT);
2890
}
2891
}
2892
2893
if (error == ERESTART)
2894
return (error);
2895
2896
/*
2897
* XXX
2898
* Until we have a better way of doing pack validation,
2899
* don't treat UAs as errors.
2900
*/
2901
sense_flags |= SF_RETRY_UA;
2902
2903
if (softc->quirks & CD_Q_RETRY_BUSY)
2904
sense_flags |= SF_RETRY_BUSY;
2905
return (cam_periph_error(ccb, cam_flags, sense_flags));
2906
}
2907
2908
static void
2909
cdmediapoll(void *arg)
2910
{
2911
struct cam_periph *periph = arg;
2912
struct cd_softc *softc = periph->softc;
2913
2914
if (softc->state == CD_STATE_NORMAL && !softc->tur &&
2915
softc->outstanding_cmds == 0) {
2916
if (cam_periph_acquire(periph) == 0) {
2917
softc->tur = 1;
2918
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
2919
}
2920
}
2921
2922
/* Queue us up again */
2923
if (cd_poll_period != 0) {
2924
callout_schedule_sbt(&softc->mediapoll_c,
2925
cd_poll_period * SBT_1S, 0, C_PREL(1));
2926
}
2927
}
2928
2929
/*
2930
* Read table of contents
2931
*/
2932
static int
2933
cdreadtoc(struct cam_periph *periph, uint32_t mode, uint32_t start,
2934
uint8_t *data, uint32_t len, uint32_t sense_flags)
2935
{
2936
struct ccb_scsiio *csio;
2937
union ccb *ccb;
2938
int error;
2939
2940
error = 0;
2941
2942
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
2943
2944
csio = &ccb->csio;
2945
2946
scsi_read_toc(csio,
2947
/* retries */ cd_retry_count,
2948
/* cbfcnp */ NULL,
2949
/* tag_action */ MSG_SIMPLE_Q_TAG,
2950
/* byte1_flags */ (mode == CD_MSF_FORMAT) ? CD_MSF : 0,
2951
/* format */ SRTOC_FORMAT_TOC,
2952
/* track*/ start,
2953
/* data_ptr */ data,
2954
/* dxfer_len */ len,
2955
/* sense_len */ SSD_FULL_SIZE,
2956
/* timeout */ 50000);
2957
2958
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
2959
/*sense_flags*/SF_RETRY_UA | sense_flags);
2960
2961
xpt_release_ccb(ccb);
2962
2963
return(error);
2964
}
2965
2966
static int
2967
cdreadsubchannel(struct cam_periph *periph, uint32_t mode,
2968
uint32_t format, int track,
2969
struct cd_sub_channel_info *data, uint32_t len)
2970
{
2971
struct scsi_read_subchannel *scsi_cmd;
2972
struct ccb_scsiio *csio;
2973
union ccb *ccb;
2974
int error;
2975
2976
error = 0;
2977
2978
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
2979
2980
csio = &ccb->csio;
2981
2982
cam_fill_csio(csio,
2983
/* retries */ cd_retry_count,
2984
/* cbfcnp */ NULL,
2985
/* flags */ CAM_DIR_IN,
2986
/* tag_action */ MSG_SIMPLE_Q_TAG,
2987
/* data_ptr */ (uint8_t *)data,
2988
/* dxfer_len */ len,
2989
/* sense_len */ SSD_FULL_SIZE,
2990
sizeof(struct scsi_read_subchannel),
2991
/* timeout */ 50000);
2992
2993
scsi_cmd = (struct scsi_read_subchannel *)&csio->cdb_io.cdb_bytes;
2994
bzero (scsi_cmd, sizeof(*scsi_cmd));
2995
2996
scsi_cmd->op_code = READ_SUBCHANNEL;
2997
if (mode == CD_MSF_FORMAT)
2998
scsi_cmd->byte1 |= CD_MSF;
2999
scsi_cmd->byte2 = SRS_SUBQ;
3000
scsi_cmd->subchan_format = format;
3001
scsi_cmd->track = track;
3002
scsi_ulto2b(len, (uint8_t *)scsi_cmd->data_len);
3003
scsi_cmd->control = 0;
3004
3005
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
3006
/*sense_flags*/SF_RETRY_UA);
3007
3008
xpt_release_ccb(ccb);
3009
3010
return(error);
3011
}
3012
3013
/*
3014
* All MODE_SENSE requests in the cd(4) driver MUST go through this
3015
* routine. See comments in cd6byteworkaround() for details.
3016
*/
3017
static int
3018
cdgetmode(struct cam_periph *periph, struct cd_mode_params *data,
3019
uint32_t page)
3020
{
3021
struct ccb_scsiio *csio;
3022
struct cd_softc *softc;
3023
union ccb *ccb;
3024
int param_len;
3025
int error;
3026
3027
softc = (struct cd_softc *)periph->softc;
3028
3029
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
3030
3031
csio = &ccb->csio;
3032
3033
data->cdb_size = softc->minimum_command_size;
3034
if (data->cdb_size < 10)
3035
param_len = sizeof(struct cd_mode_data);
3036
else
3037
param_len = sizeof(struct cd_mode_data_10);
3038
3039
/* Don't say we've got more room than we actually allocated */
3040
param_len = min(param_len, data->alloc_len);
3041
3042
scsi_mode_sense_len(csio,
3043
/* retries */ cd_retry_count,
3044
/* cbfcnp */ NULL,
3045
/* tag_action */ MSG_SIMPLE_Q_TAG,
3046
/* dbd */ 0,
3047
/* page_code */ SMS_PAGE_CTRL_CURRENT,
3048
/* page */ page,
3049
/* param_buf */ data->mode_buf,
3050
/* param_len */ param_len,
3051
/* minimum_cmd_size */ softc->minimum_command_size,
3052
/* sense_len */ SSD_FULL_SIZE,
3053
/* timeout */ 50000);
3054
3055
/*
3056
* It would be nice not to have to do this, but there's no
3057
* available pointer in the CCB that would allow us to stuff the
3058
* mode params structure in there and retrieve it in
3059
* cd6byteworkaround(), so we can set the cdb size. The cdb size
3060
* lets the caller know what CDB size we ended up using, so they
3061
* can find the actual mode page offset.
3062
*/
3063
STAILQ_INSERT_TAIL(&softc->mode_queue, data, links);
3064
3065
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
3066
/*sense_flags*/SF_RETRY_UA);
3067
3068
xpt_release_ccb(ccb);
3069
3070
STAILQ_REMOVE(&softc->mode_queue, data, cd_mode_params, links);
3071
3072
/*
3073
* This is a bit of belt-and-suspenders checking, but if we run
3074
* into a situation where the target sends back multiple block
3075
* descriptors, we might not have enough space in the buffer to
3076
* see the whole mode page. Better to return an error than
3077
* potentially access memory beyond our malloced region.
3078
*/
3079
if (error == 0) {
3080
uint32_t data_len;
3081
3082
if (data->cdb_size == 10) {
3083
struct scsi_mode_header_10 *hdr10;
3084
3085
hdr10 = (struct scsi_mode_header_10 *)data->mode_buf;
3086
data_len = scsi_2btoul(hdr10->data_length);
3087
data_len += sizeof(hdr10->data_length);
3088
} else {
3089
struct scsi_mode_header_6 *hdr6;
3090
3091
hdr6 = (struct scsi_mode_header_6 *)data->mode_buf;
3092
data_len = hdr6->data_length;
3093
data_len += sizeof(hdr6->data_length);
3094
}
3095
3096
/*
3097
* Complain if there is more mode data available than we
3098
* allocated space for. This could potentially happen if
3099
* we miscalculated the page length for some reason, if the
3100
* drive returns multiple block descriptors, or if it sets
3101
* the data length incorrectly.
3102
*/
3103
if (data_len > data->alloc_len) {
3104
xpt_print(periph->path, "allocated modepage %d length "
3105
"%d < returned length %d\n", page, data->alloc_len,
3106
data_len);
3107
error = ENOSPC;
3108
}
3109
}
3110
return (error);
3111
}
3112
3113
/*
3114
* All MODE_SELECT requests in the cd(4) driver MUST go through this
3115
* routine. See comments in cd6byteworkaround() for details.
3116
*/
3117
static int
3118
cdsetmode(struct cam_periph *periph, struct cd_mode_params *data)
3119
{
3120
struct ccb_scsiio *csio;
3121
struct cd_softc *softc;
3122
union ccb *ccb;
3123
int cdb_size, param_len;
3124
int error;
3125
3126
softc = (struct cd_softc *)periph->softc;
3127
3128
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
3129
3130
csio = &ccb->csio;
3131
3132
error = 0;
3133
3134
/*
3135
* If the data is formatted for the 10 byte version of the mode
3136
* select parameter list, we need to use the 10 byte CDB.
3137
* Otherwise, we use whatever the stored minimum command size.
3138
*/
3139
if (data->cdb_size == 10)
3140
cdb_size = data->cdb_size;
3141
else
3142
cdb_size = softc->minimum_command_size;
3143
3144
if (cdb_size >= 10) {
3145
struct scsi_mode_header_10 *mode_header;
3146
uint32_t data_len;
3147
3148
mode_header = (struct scsi_mode_header_10 *)data->mode_buf;
3149
3150
data_len = scsi_2btoul(mode_header->data_length);
3151
3152
scsi_ulto2b(0, mode_header->data_length);
3153
/*
3154
* SONY drives do not allow a mode select with a medium_type
3155
* value that has just been returned by a mode sense; use a
3156
* medium_type of 0 (Default) instead.
3157
*/
3158
mode_header->medium_type = 0;
3159
3160
/*
3161
* Pass back whatever the drive passed to us, plus the size
3162
* of the data length field.
3163
*/
3164
param_len = data_len + sizeof(mode_header->data_length);
3165
3166
} else {
3167
struct scsi_mode_header_6 *mode_header;
3168
3169
mode_header = (struct scsi_mode_header_6 *)data->mode_buf;
3170
3171
param_len = mode_header->data_length + 1;
3172
3173
mode_header->data_length = 0;
3174
/*
3175
* SONY drives do not allow a mode select with a medium_type
3176
* value that has just been returned by a mode sense; use a
3177
* medium_type of 0 (Default) instead.
3178
*/
3179
mode_header->medium_type = 0;
3180
}
3181
3182
/* Don't say we've got more room than we actually allocated */
3183
param_len = min(param_len, data->alloc_len);
3184
3185
scsi_mode_select_len(csio,
3186
/* retries */ cd_retry_count,
3187
/* cbfcnp */ NULL,
3188
/* tag_action */ MSG_SIMPLE_Q_TAG,
3189
/* scsi_page_fmt */ 1,
3190
/* save_pages */ 0,
3191
/* param_buf */ data->mode_buf,
3192
/* param_len */ param_len,
3193
/* minimum_cmd_size */ cdb_size,
3194
/* sense_len */ SSD_FULL_SIZE,
3195
/* timeout */ 50000);
3196
3197
/* See comments in cdgetmode() and cd6byteworkaround(). */
3198
STAILQ_INSERT_TAIL(&softc->mode_queue, data, links);
3199
3200
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
3201
/*sense_flags*/SF_RETRY_UA);
3202
3203
xpt_release_ccb(ccb);
3204
3205
STAILQ_REMOVE(&softc->mode_queue, data, cd_mode_params, links);
3206
3207
return (error);
3208
}
3209
3210
static int
3211
cdplay(struct cam_periph *periph, uint32_t blk, uint32_t len)
3212
{
3213
struct ccb_scsiio *csio;
3214
union ccb *ccb;
3215
int error;
3216
uint8_t cdb_len;
3217
3218
error = 0;
3219
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
3220
csio = &ccb->csio;
3221
/*
3222
* Use the smallest possible command to perform the operation.
3223
*/
3224
if ((len & 0xffff0000) == 0) {
3225
/*
3226
* We can fit in a 10 byte cdb.
3227
*/
3228
struct scsi_play_10 *scsi_cmd;
3229
3230
scsi_cmd = (struct scsi_play_10 *)&csio->cdb_io.cdb_bytes;
3231
bzero (scsi_cmd, sizeof(*scsi_cmd));
3232
scsi_cmd->op_code = PLAY_10;
3233
scsi_ulto4b(blk, (uint8_t *)scsi_cmd->blk_addr);
3234
scsi_ulto2b(len, (uint8_t *)scsi_cmd->xfer_len);
3235
cdb_len = sizeof(*scsi_cmd);
3236
} else {
3237
struct scsi_play_12 *scsi_cmd;
3238
3239
scsi_cmd = (struct scsi_play_12 *)&csio->cdb_io.cdb_bytes;
3240
bzero (scsi_cmd, sizeof(*scsi_cmd));
3241
scsi_cmd->op_code = PLAY_12;
3242
scsi_ulto4b(blk, (uint8_t *)scsi_cmd->blk_addr);
3243
scsi_ulto4b(len, (uint8_t *)scsi_cmd->xfer_len);
3244
cdb_len = sizeof(*scsi_cmd);
3245
}
3246
cam_fill_csio(csio,
3247
/*retries*/ cd_retry_count,
3248
/*cbfcnp*/NULL,
3249
/*flags*/CAM_DIR_NONE,
3250
MSG_SIMPLE_Q_TAG,
3251
/*dataptr*/NULL,
3252
/*datalen*/0,
3253
/*sense_len*/SSD_FULL_SIZE,
3254
cdb_len,
3255
/*timeout*/50 * 1000);
3256
3257
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
3258
/*sense_flags*/SF_RETRY_UA);
3259
3260
xpt_release_ccb(ccb);
3261
3262
return(error);
3263
}
3264
3265
static int
3266
cdplaymsf(struct cam_periph *periph, uint32_t startm, uint32_t starts,
3267
uint32_t startf, uint32_t endm, uint32_t ends, uint32_t endf)
3268
{
3269
struct scsi_play_msf *scsi_cmd;
3270
struct ccb_scsiio *csio;
3271
union ccb *ccb;
3272
int error;
3273
3274
error = 0;
3275
3276
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
3277
3278
csio = &ccb->csio;
3279
3280
cam_fill_csio(csio,
3281
/* retries */ cd_retry_count,
3282
/* cbfcnp */ NULL,
3283
/* flags */ CAM_DIR_NONE,
3284
/* tag_action */ MSG_SIMPLE_Q_TAG,
3285
/* data_ptr */ NULL,
3286
/* dxfer_len */ 0,
3287
/* sense_len */ SSD_FULL_SIZE,
3288
sizeof(struct scsi_play_msf),
3289
/* timeout */ 50000);
3290
3291
scsi_cmd = (struct scsi_play_msf *)&csio->cdb_io.cdb_bytes;
3292
bzero (scsi_cmd, sizeof(*scsi_cmd));
3293
3294
scsi_cmd->op_code = PLAY_MSF;
3295
scsi_cmd->start_m = startm;
3296
scsi_cmd->start_s = starts;
3297
scsi_cmd->start_f = startf;
3298
scsi_cmd->end_m = endm;
3299
scsi_cmd->end_s = ends;
3300
scsi_cmd->end_f = endf;
3301
3302
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
3303
/*sense_flags*/SF_RETRY_UA);
3304
3305
xpt_release_ccb(ccb);
3306
3307
return(error);
3308
}
3309
3310
static int
3311
cdplaytracks(struct cam_periph *periph, uint32_t strack, uint32_t sindex,
3312
uint32_t etrack, uint32_t eindex)
3313
{
3314
struct scsi_play_track *scsi_cmd;
3315
struct ccb_scsiio *csio;
3316
union ccb *ccb;
3317
int error;
3318
3319
error = 0;
3320
3321
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
3322
3323
csio = &ccb->csio;
3324
3325
cam_fill_csio(csio,
3326
/* retries */ cd_retry_count,
3327
/* cbfcnp */ NULL,
3328
/* flags */ CAM_DIR_NONE,
3329
/* tag_action */ MSG_SIMPLE_Q_TAG,
3330
/* data_ptr */ NULL,
3331
/* dxfer_len */ 0,
3332
/* sense_len */ SSD_FULL_SIZE,
3333
sizeof(struct scsi_play_track),
3334
/* timeout */ 50000);
3335
3336
scsi_cmd = (struct scsi_play_track *)&csio->cdb_io.cdb_bytes;
3337
bzero (scsi_cmd, sizeof(*scsi_cmd));
3338
3339
scsi_cmd->op_code = PLAY_TRACK;
3340
scsi_cmd->start_track = strack;
3341
scsi_cmd->start_index = sindex;
3342
scsi_cmd->end_track = etrack;
3343
scsi_cmd->end_index = eindex;
3344
3345
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
3346
/*sense_flags*/SF_RETRY_UA);
3347
3348
xpt_release_ccb(ccb);
3349
3350
return(error);
3351
}
3352
3353
static int
3354
cdpause(struct cam_periph *periph, uint32_t go)
3355
{
3356
struct scsi_pause *scsi_cmd;
3357
struct ccb_scsiio *csio;
3358
union ccb *ccb;
3359
int error;
3360
3361
error = 0;
3362
3363
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
3364
3365
csio = &ccb->csio;
3366
3367
cam_fill_csio(csio,
3368
/* retries */ cd_retry_count,
3369
/* cbfcnp */ NULL,
3370
/* flags */ CAM_DIR_NONE,
3371
/* tag_action */ MSG_SIMPLE_Q_TAG,
3372
/* data_ptr */ NULL,
3373
/* dxfer_len */ 0,
3374
/* sense_len */ SSD_FULL_SIZE,
3375
sizeof(struct scsi_pause),
3376
/* timeout */ 50000);
3377
3378
scsi_cmd = (struct scsi_pause *)&csio->cdb_io.cdb_bytes;
3379
bzero (scsi_cmd, sizeof(*scsi_cmd));
3380
3381
scsi_cmd->op_code = PAUSE;
3382
scsi_cmd->resume = go;
3383
3384
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
3385
/*sense_flags*/SF_RETRY_UA);
3386
3387
xpt_release_ccb(ccb);
3388
3389
return(error);
3390
}
3391
3392
static int
3393
cdstartunit(struct cam_periph *periph, int load)
3394
{
3395
union ccb *ccb;
3396
int error;
3397
3398
error = 0;
3399
3400
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
3401
3402
scsi_start_stop(&ccb->csio,
3403
/* retries */ cd_retry_count,
3404
/* cbfcnp */ NULL,
3405
/* tag_action */ MSG_SIMPLE_Q_TAG,
3406
/* start */ TRUE,
3407
/* load_eject */ load,
3408
/* immediate */ FALSE,
3409
/* sense_len */ SSD_FULL_SIZE,
3410
/* timeout */ 50000);
3411
3412
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
3413
/*sense_flags*/SF_RETRY_UA);
3414
3415
xpt_release_ccb(ccb);
3416
3417
return(error);
3418
}
3419
3420
static int
3421
cdstopunit(struct cam_periph *periph, uint32_t eject)
3422
{
3423
union ccb *ccb;
3424
int error;
3425
3426
error = 0;
3427
3428
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
3429
3430
scsi_start_stop(&ccb->csio,
3431
/* retries */ cd_retry_count,
3432
/* cbfcnp */ NULL,
3433
/* tag_action */ MSG_SIMPLE_Q_TAG,
3434
/* start */ FALSE,
3435
/* load_eject */ eject,
3436
/* immediate */ FALSE,
3437
/* sense_len */ SSD_FULL_SIZE,
3438
/* timeout */ 50000);
3439
3440
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
3441
/*sense_flags*/SF_RETRY_UA);
3442
3443
xpt_release_ccb(ccb);
3444
3445
return(error);
3446
}
3447
3448
static int
3449
cdsetspeed(struct cam_periph *periph, uint32_t rdspeed, uint32_t wrspeed)
3450
{
3451
struct scsi_set_speed *scsi_cmd;
3452
struct ccb_scsiio *csio;
3453
union ccb *ccb;
3454
int error;
3455
3456
error = 0;
3457
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
3458
csio = &ccb->csio;
3459
3460
/* Preserve old behavior: units in multiples of CDROM speed */
3461
if (rdspeed < 177)
3462
rdspeed *= 177;
3463
if (wrspeed < 177)
3464
wrspeed *= 177;
3465
3466
cam_fill_csio(csio,
3467
/* retries */ cd_retry_count,
3468
/* cbfcnp */ NULL,
3469
/* flags */ CAM_DIR_NONE,
3470
/* tag_action */ MSG_SIMPLE_Q_TAG,
3471
/* data_ptr */ NULL,
3472
/* dxfer_len */ 0,
3473
/* sense_len */ SSD_FULL_SIZE,
3474
sizeof(struct scsi_set_speed),
3475
/* timeout */ 50000);
3476
3477
scsi_cmd = (struct scsi_set_speed *)&csio->cdb_io.cdb_bytes;
3478
bzero(scsi_cmd, sizeof(*scsi_cmd));
3479
3480
scsi_cmd->opcode = SET_CD_SPEED;
3481
scsi_ulto2b(rdspeed, scsi_cmd->readspeed);
3482
scsi_ulto2b(wrspeed, scsi_cmd->writespeed);
3483
3484
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
3485
/*sense_flags*/SF_RETRY_UA);
3486
3487
xpt_release_ccb(ccb);
3488
3489
return(error);
3490
}
3491
3492
static int
3493
cdreportkey(struct cam_periph *periph, struct dvd_authinfo *authinfo)
3494
{
3495
union ccb *ccb;
3496
uint8_t *databuf;
3497
uint32_t lba;
3498
int error;
3499
int length;
3500
3501
error = 0;
3502
databuf = NULL;
3503
lba = 0;
3504
3505
switch (authinfo->format) {
3506
case DVD_REPORT_AGID:
3507
length = sizeof(struct scsi_report_key_data_agid);
3508
break;
3509
case DVD_REPORT_CHALLENGE:
3510
length = sizeof(struct scsi_report_key_data_challenge);
3511
break;
3512
case DVD_REPORT_KEY1:
3513
length = sizeof(struct scsi_report_key_data_key1_key2);
3514
break;
3515
case DVD_REPORT_TITLE_KEY:
3516
length = sizeof(struct scsi_report_key_data_title);
3517
/* The lba field is only set for the title key */
3518
lba = authinfo->lba;
3519
break;
3520
case DVD_REPORT_ASF:
3521
length = sizeof(struct scsi_report_key_data_asf);
3522
break;
3523
case DVD_REPORT_RPC:
3524
length = sizeof(struct scsi_report_key_data_rpc);
3525
break;
3526
case DVD_INVALIDATE_AGID:
3527
length = 0;
3528
break;
3529
default:
3530
return (EINVAL);
3531
}
3532
3533
if (length != 0) {
3534
databuf = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO);
3535
} else
3536
databuf = NULL;
3537
3538
cam_periph_lock(periph);
3539
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
3540
3541
scsi_report_key(&ccb->csio,
3542
/* retries */ cd_retry_count,
3543
/* cbfcnp */ NULL,
3544
/* tag_action */ MSG_SIMPLE_Q_TAG,
3545
/* lba */ lba,
3546
/* agid */ authinfo->agid,
3547
/* key_format */ authinfo->format,
3548
/* data_ptr */ databuf,
3549
/* dxfer_len */ length,
3550
/* sense_len */ SSD_FULL_SIZE,
3551
/* timeout */ 50000);
3552
3553
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
3554
/*sense_flags*/SF_RETRY_UA);
3555
3556
if (error != 0)
3557
goto bailout;
3558
3559
if (ccb->csio.resid != 0) {
3560
xpt_print(periph->path, "warning, residual for report key "
3561
"command is %d\n", ccb->csio.resid);
3562
}
3563
3564
switch(authinfo->format) {
3565
case DVD_REPORT_AGID: {
3566
struct scsi_report_key_data_agid *agid_data;
3567
3568
agid_data = (struct scsi_report_key_data_agid *)databuf;
3569
3570
authinfo->agid = (agid_data->agid & RKD_AGID_MASK) >>
3571
RKD_AGID_SHIFT;
3572
break;
3573
}
3574
case DVD_REPORT_CHALLENGE: {
3575
struct scsi_report_key_data_challenge *chal_data;
3576
3577
chal_data = (struct scsi_report_key_data_challenge *)databuf;
3578
3579
bcopy(chal_data->challenge_key, authinfo->keychal,
3580
min(sizeof(chal_data->challenge_key),
3581
sizeof(authinfo->keychal)));
3582
break;
3583
}
3584
case DVD_REPORT_KEY1: {
3585
struct scsi_report_key_data_key1_key2 *key1_data;
3586
3587
key1_data = (struct scsi_report_key_data_key1_key2 *)databuf;
3588
3589
bcopy(key1_data->key1, authinfo->keychal,
3590
min(sizeof(key1_data->key1), sizeof(authinfo->keychal)));
3591
break;
3592
}
3593
case DVD_REPORT_TITLE_KEY: {
3594
struct scsi_report_key_data_title *title_data;
3595
3596
title_data = (struct scsi_report_key_data_title *)databuf;
3597
3598
authinfo->cpm = (title_data->byte0 & RKD_TITLE_CPM) >>
3599
RKD_TITLE_CPM_SHIFT;
3600
authinfo->cp_sec = (title_data->byte0 & RKD_TITLE_CP_SEC) >>
3601
RKD_TITLE_CP_SEC_SHIFT;
3602
authinfo->cgms = (title_data->byte0 & RKD_TITLE_CMGS_MASK) >>
3603
RKD_TITLE_CMGS_SHIFT;
3604
bcopy(title_data->title_key, authinfo->keychal,
3605
min(sizeof(title_data->title_key),
3606
sizeof(authinfo->keychal)));
3607
break;
3608
}
3609
case DVD_REPORT_ASF: {
3610
struct scsi_report_key_data_asf *asf_data;
3611
3612
asf_data = (struct scsi_report_key_data_asf *)databuf;
3613
3614
authinfo->asf = asf_data->success & RKD_ASF_SUCCESS;
3615
break;
3616
}
3617
case DVD_REPORT_RPC: {
3618
struct scsi_report_key_data_rpc *rpc_data;
3619
3620
rpc_data = (struct scsi_report_key_data_rpc *)databuf;
3621
3622
authinfo->reg_type = (rpc_data->byte4 & RKD_RPC_TYPE_MASK) >>
3623
RKD_RPC_TYPE_SHIFT;
3624
authinfo->vend_rsts =
3625
(rpc_data->byte4 & RKD_RPC_VENDOR_RESET_MASK) >>
3626
RKD_RPC_VENDOR_RESET_SHIFT;
3627
authinfo->user_rsts = rpc_data->byte4 & RKD_RPC_USER_RESET_MASK;
3628
authinfo->region = rpc_data->region_mask;
3629
authinfo->rpc_scheme = rpc_data->rpc_scheme1;
3630
break;
3631
}
3632
case DVD_INVALIDATE_AGID:
3633
break;
3634
default:
3635
/* This should be impossible, since we checked above */
3636
error = EINVAL;
3637
goto bailout;
3638
break; /* NOTREACHED */
3639
}
3640
3641
bailout:
3642
xpt_release_ccb(ccb);
3643
cam_periph_unlock(periph);
3644
3645
if (databuf != NULL)
3646
free(databuf, M_DEVBUF);
3647
3648
return(error);
3649
}
3650
3651
static int
3652
cdsendkey(struct cam_periph *periph, struct dvd_authinfo *authinfo)
3653
{
3654
union ccb *ccb;
3655
uint8_t *databuf;
3656
int length;
3657
int error;
3658
3659
error = 0;
3660
databuf = NULL;
3661
3662
switch(authinfo->format) {
3663
case DVD_SEND_CHALLENGE: {
3664
struct scsi_report_key_data_challenge *challenge_data;
3665
3666
length = sizeof(*challenge_data);
3667
3668
challenge_data = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO);
3669
3670
databuf = (uint8_t *)challenge_data;
3671
3672
scsi_ulto2b(length - sizeof(challenge_data->data_len),
3673
challenge_data->data_len);
3674
3675
bcopy(authinfo->keychal, challenge_data->challenge_key,
3676
min(sizeof(authinfo->keychal),
3677
sizeof(challenge_data->challenge_key)));
3678
break;
3679
}
3680
case DVD_SEND_KEY2: {
3681
struct scsi_report_key_data_key1_key2 *key2_data;
3682
3683
length = sizeof(*key2_data);
3684
3685
key2_data = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO);
3686
3687
databuf = (uint8_t *)key2_data;
3688
3689
scsi_ulto2b(length - sizeof(key2_data->data_len),
3690
key2_data->data_len);
3691
3692
bcopy(authinfo->keychal, key2_data->key1,
3693
min(sizeof(authinfo->keychal), sizeof(key2_data->key1)));
3694
3695
break;
3696
}
3697
case DVD_SEND_RPC: {
3698
struct scsi_send_key_data_rpc *rpc_data;
3699
3700
length = sizeof(*rpc_data);
3701
3702
rpc_data = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO);
3703
3704
databuf = (uint8_t *)rpc_data;
3705
3706
scsi_ulto2b(length - sizeof(rpc_data->data_len),
3707
rpc_data->data_len);
3708
3709
rpc_data->region_code = authinfo->region;
3710
break;
3711
}
3712
default:
3713
return (EINVAL);
3714
}
3715
3716
cam_periph_lock(periph);
3717
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
3718
3719
scsi_send_key(&ccb->csio,
3720
/* retries */ cd_retry_count,
3721
/* cbfcnp */ NULL,
3722
/* tag_action */ MSG_SIMPLE_Q_TAG,
3723
/* agid */ authinfo->agid,
3724
/* key_format */ authinfo->format,
3725
/* data_ptr */ databuf,
3726
/* dxfer_len */ length,
3727
/* sense_len */ SSD_FULL_SIZE,
3728
/* timeout */ 50000);
3729
3730
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
3731
/*sense_flags*/SF_RETRY_UA);
3732
3733
xpt_release_ccb(ccb);
3734
cam_periph_unlock(periph);
3735
3736
if (databuf != NULL)
3737
free(databuf, M_DEVBUF);
3738
3739
return(error);
3740
}
3741
3742
static int
3743
cdreaddvdstructure(struct cam_periph *periph, struct dvd_struct *dvdstruct)
3744
{
3745
union ccb *ccb;
3746
uint8_t *databuf;
3747
uint32_t address;
3748
int error;
3749
int length;
3750
3751
error = 0;
3752
databuf = NULL;
3753
/* The address is reserved for many of the formats */
3754
address = 0;
3755
3756
switch(dvdstruct->format) {
3757
case DVD_STRUCT_PHYSICAL:
3758
length = sizeof(struct scsi_read_dvd_struct_data_physical);
3759
break;
3760
case DVD_STRUCT_COPYRIGHT:
3761
length = sizeof(struct scsi_read_dvd_struct_data_copyright);
3762
break;
3763
case DVD_STRUCT_DISCKEY:
3764
length = sizeof(struct scsi_read_dvd_struct_data_disc_key);
3765
break;
3766
case DVD_STRUCT_BCA:
3767
length = sizeof(struct scsi_read_dvd_struct_data_bca);
3768
break;
3769
case DVD_STRUCT_MANUFACT:
3770
length = sizeof(struct scsi_read_dvd_struct_data_manufacturer);
3771
break;
3772
case DVD_STRUCT_CMI:
3773
return (ENODEV);
3774
case DVD_STRUCT_PROTDISCID:
3775
length = sizeof(struct scsi_read_dvd_struct_data_prot_discid);
3776
break;
3777
case DVD_STRUCT_DISCKEYBLOCK:
3778
length = sizeof(struct scsi_read_dvd_struct_data_disc_key_blk);
3779
break;
3780
case DVD_STRUCT_DDS:
3781
length = sizeof(struct scsi_read_dvd_struct_data_dds);
3782
break;
3783
case DVD_STRUCT_MEDIUM_STAT:
3784
length = sizeof(struct scsi_read_dvd_struct_data_medium_status);
3785
break;
3786
case DVD_STRUCT_SPARE_AREA:
3787
length = sizeof(struct scsi_read_dvd_struct_data_spare_area);
3788
break;
3789
case DVD_STRUCT_RMD_LAST:
3790
return (ENODEV);
3791
case DVD_STRUCT_RMD_RMA:
3792
return (ENODEV);
3793
case DVD_STRUCT_PRERECORDED:
3794
length = sizeof(struct scsi_read_dvd_struct_data_leadin);
3795
break;
3796
case DVD_STRUCT_UNIQUEID:
3797
length = sizeof(struct scsi_read_dvd_struct_data_disc_id);
3798
break;
3799
case DVD_STRUCT_DCB:
3800
return (ENODEV);
3801
case DVD_STRUCT_LIST:
3802
/*
3803
* This is the maximum allocation length for the READ DVD
3804
* STRUCTURE command. There's nothing in the MMC3 spec
3805
* that indicates a limit in the amount of data that can
3806
* be returned from this call, other than the limits
3807
* imposed by the 2-byte length variables.
3808
*/
3809
length = 65535;
3810
break;
3811
default:
3812
return (EINVAL);
3813
}
3814
3815
if (length != 0) {
3816
databuf = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO);
3817
} else
3818
databuf = NULL;
3819
3820
cam_periph_lock(periph);
3821
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
3822
3823
scsi_read_dvd_structure(&ccb->csio,
3824
/* retries */ cd_retry_count,
3825
/* cbfcnp */ NULL,
3826
/* tag_action */ MSG_SIMPLE_Q_TAG,
3827
/* lba */ address,
3828
/* layer_number */ dvdstruct->layer_num,
3829
/* key_format */ dvdstruct->format,
3830
/* agid */ dvdstruct->agid,
3831
/* data_ptr */ databuf,
3832
/* dxfer_len */ length,
3833
/* sense_len */ SSD_FULL_SIZE,
3834
/* timeout */ 50000);
3835
3836
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
3837
/*sense_flags*/SF_RETRY_UA);
3838
3839
if (error != 0)
3840
goto bailout;
3841
3842
switch(dvdstruct->format) {
3843
case DVD_STRUCT_PHYSICAL: {
3844
struct scsi_read_dvd_struct_data_layer_desc *inlayer;
3845
struct dvd_layer *outlayer;
3846
struct scsi_read_dvd_struct_data_physical *phys_data;
3847
3848
phys_data =
3849
(struct scsi_read_dvd_struct_data_physical *)databuf;
3850
inlayer = &phys_data->layer_desc;
3851
outlayer = (struct dvd_layer *)&dvdstruct->data;
3852
3853
dvdstruct->length = sizeof(*inlayer);
3854
3855
outlayer->book_type = (inlayer->book_type_version &
3856
RDSD_BOOK_TYPE_MASK) >> RDSD_BOOK_TYPE_SHIFT;
3857
outlayer->book_version = (inlayer->book_type_version &
3858
RDSD_BOOK_VERSION_MASK);
3859
outlayer->disc_size = (inlayer->disc_size_max_rate &
3860
RDSD_DISC_SIZE_MASK) >> RDSD_DISC_SIZE_SHIFT;
3861
outlayer->max_rate = (inlayer->disc_size_max_rate &
3862
RDSD_MAX_RATE_MASK);
3863
outlayer->nlayers = (inlayer->layer_info &
3864
RDSD_NUM_LAYERS_MASK) >> RDSD_NUM_LAYERS_SHIFT;
3865
outlayer->track_path = (inlayer->layer_info &
3866
RDSD_TRACK_PATH_MASK) >> RDSD_TRACK_PATH_SHIFT;
3867
outlayer->layer_type = (inlayer->layer_info &
3868
RDSD_LAYER_TYPE_MASK);
3869
outlayer->linear_density = (inlayer->density &
3870
RDSD_LIN_DENSITY_MASK) >> RDSD_LIN_DENSITY_SHIFT;
3871
outlayer->track_density = (inlayer->density &
3872
RDSD_TRACK_DENSITY_MASK);
3873
outlayer->bca = (inlayer->bca & RDSD_BCA_MASK) >>
3874
RDSD_BCA_SHIFT;
3875
outlayer->start_sector = scsi_3btoul(inlayer->main_data_start);
3876
outlayer->end_sector = scsi_3btoul(inlayer->main_data_end);
3877
outlayer->end_sector_l0 =
3878
scsi_3btoul(inlayer->end_sector_layer0);
3879
break;
3880
}
3881
case DVD_STRUCT_COPYRIGHT: {
3882
struct scsi_read_dvd_struct_data_copyright *copy_data;
3883
3884
copy_data = (struct scsi_read_dvd_struct_data_copyright *)
3885
databuf;
3886
3887
dvdstruct->cpst = copy_data->cps_type;
3888
dvdstruct->rmi = copy_data->region_info;
3889
dvdstruct->length = 0;
3890
3891
break;
3892
}
3893
default:
3894
/*
3895
* Tell the user what the overall length is, no matter
3896
* what we can actually fit in the data buffer.
3897
*/
3898
dvdstruct->length = length - ccb->csio.resid -
3899
sizeof(struct scsi_read_dvd_struct_data_header);
3900
3901
/*
3902
* But only actually copy out the smaller of what we read
3903
* in or what the structure can take.
3904
*/
3905
bcopy(databuf + sizeof(struct scsi_read_dvd_struct_data_header),
3906
dvdstruct->data,
3907
min(sizeof(dvdstruct->data), dvdstruct->length));
3908
break;
3909
}
3910
3911
bailout:
3912
xpt_release_ccb(ccb);
3913
cam_periph_unlock(periph);
3914
3915
if (databuf != NULL)
3916
free(databuf, M_DEVBUF);
3917
3918
return(error);
3919
}
3920
3921
void
3922
scsi_report_key(struct ccb_scsiio *csio, uint32_t retries,
3923
void (*cbfcnp)(struct cam_periph *, union ccb *),
3924
uint8_t tag_action, uint32_t lba, uint8_t agid,
3925
uint8_t key_format, uint8_t *data_ptr, uint32_t dxfer_len,
3926
uint8_t sense_len, uint32_t timeout)
3927
{
3928
struct scsi_report_key *scsi_cmd;
3929
3930
scsi_cmd = (struct scsi_report_key *)&csio->cdb_io.cdb_bytes;
3931
bzero(scsi_cmd, sizeof(*scsi_cmd));
3932
scsi_cmd->opcode = REPORT_KEY;
3933
scsi_ulto4b(lba, scsi_cmd->lba);
3934
scsi_ulto2b(dxfer_len, scsi_cmd->alloc_len);
3935
scsi_cmd->agid_keyformat = (agid << RK_KF_AGID_SHIFT) |
3936
(key_format & RK_KF_KEYFORMAT_MASK);
3937
3938
cam_fill_csio(csio,
3939
retries,
3940
cbfcnp,
3941
/*flags*/ (dxfer_len == 0) ? CAM_DIR_NONE : CAM_DIR_IN,
3942
tag_action,
3943
/*data_ptr*/ data_ptr,
3944
/*dxfer_len*/ dxfer_len,
3945
sense_len,
3946
sizeof(*scsi_cmd),
3947
timeout);
3948
}
3949
3950
void
3951
scsi_send_key(struct ccb_scsiio *csio, uint32_t retries,
3952
void (*cbfcnp)(struct cam_periph *, union ccb *),
3953
uint8_t tag_action, uint8_t agid, uint8_t key_format,
3954
uint8_t *data_ptr, uint32_t dxfer_len, uint8_t sense_len,
3955
uint32_t timeout)
3956
{
3957
struct scsi_send_key *scsi_cmd;
3958
3959
scsi_cmd = (struct scsi_send_key *)&csio->cdb_io.cdb_bytes;
3960
bzero(scsi_cmd, sizeof(*scsi_cmd));
3961
scsi_cmd->opcode = SEND_KEY;
3962
3963
scsi_ulto2b(dxfer_len, scsi_cmd->param_len);
3964
scsi_cmd->agid_keyformat = (agid << RK_KF_AGID_SHIFT) |
3965
(key_format & RK_KF_KEYFORMAT_MASK);
3966
3967
cam_fill_csio(csio,
3968
retries,
3969
cbfcnp,
3970
/*flags*/ CAM_DIR_OUT,
3971
tag_action,
3972
/*data_ptr*/ data_ptr,
3973
/*dxfer_len*/ dxfer_len,
3974
sense_len,
3975
sizeof(*scsi_cmd),
3976
timeout);
3977
}
3978
3979
void
3980
scsi_read_dvd_structure(struct ccb_scsiio *csio, uint32_t retries,
3981
void (*cbfcnp)(struct cam_periph *, union ccb *),
3982
uint8_t tag_action, uint32_t address,
3983
uint8_t layer_number, uint8_t format, uint8_t agid,
3984
uint8_t *data_ptr, uint32_t dxfer_len,
3985
uint8_t sense_len, uint32_t timeout)
3986
{
3987
struct scsi_read_dvd_structure *scsi_cmd;
3988
3989
scsi_cmd = (struct scsi_read_dvd_structure *)&csio->cdb_io.cdb_bytes;
3990
bzero(scsi_cmd, sizeof(*scsi_cmd));
3991
scsi_cmd->opcode = READ_DVD_STRUCTURE;
3992
3993
scsi_ulto4b(address, scsi_cmd->address);
3994
scsi_cmd->layer_number = layer_number;
3995
scsi_cmd->format = format;
3996
scsi_ulto2b(dxfer_len, scsi_cmd->alloc_len);
3997
/* The AGID is the top two bits of this byte */
3998
scsi_cmd->agid = agid << 6;
3999
4000
cam_fill_csio(csio,
4001
retries,
4002
cbfcnp,
4003
/*flags*/ CAM_DIR_IN,
4004
tag_action,
4005
/*data_ptr*/ data_ptr,
4006
/*dxfer_len*/ dxfer_len,
4007
sense_len,
4008
sizeof(*scsi_cmd),
4009
timeout);
4010
}
4011
4012
void
4013
scsi_read_toc(struct ccb_scsiio *csio, uint32_t retries,
4014
void (*cbfcnp)(struct cam_periph *, union ccb *),
4015
uint8_t tag_action, uint8_t byte1_flags, uint8_t format,
4016
uint8_t track, uint8_t *data_ptr, uint32_t dxfer_len,
4017
int sense_len, int timeout)
4018
{
4019
struct scsi_read_toc *scsi_cmd;
4020
4021
scsi_cmd = (struct scsi_read_toc *)&csio->cdb_io.cdb_bytes;
4022
bzero(scsi_cmd, sizeof(*scsi_cmd));
4023
scsi_cmd->op_code = READ_TOC;
4024
4025
/*
4026
* The structure is counting from 1, the function counting from 0.
4027
* The spec counts from 0. In MMC-6, there is only one flag, the
4028
* MSF flag. But we put the whole byte in for a bit a future-proofing.
4029
*/
4030
scsi_cmd->byte2 = byte1_flags;
4031
scsi_cmd->format = format;
4032
scsi_cmd->from_track = track;
4033
scsi_ulto2b(dxfer_len, scsi_cmd->data_len);
4034
4035
cam_fill_csio(csio,
4036
/* retries */ retries,
4037
/* cbfcnp */ cbfcnp,
4038
/* flags */ CAM_DIR_IN,
4039
/* tag_action */ tag_action,
4040
/* data_ptr */ data_ptr,
4041
/* dxfer_len */ dxfer_len,
4042
/* sense_len */ sense_len,
4043
sizeof(*scsi_cmd),
4044
/* timeout */ timeout);
4045
}
4046
4047