4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <sys/types.h>
33 #include "transport.h"
39 test_unit_ready(int fd
)
41 struct uscsi_cmd
*scmd
;
43 scmd
= get_uscsi_cmd();
44 scmd
->uscsi_flags
= USCSI_SILENT
;
45 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
46 /* give length of cdb structure */
47 scmd
->uscsi_cdblen
= 6;
48 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
54 inquiry(int fd
, uchar_t
*inq
)
56 struct uscsi_cmd
*scmd
;
58 scmd
= get_uscsi_cmd();
59 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
60 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
61 scmd
->uscsi_cdb
[0] = INQUIRY_CMD
;
62 scmd
->uscsi_cdb
[4] = INQUIRY_DATA_LENGTH
;
63 scmd
->uscsi_cdblen
= 6;
64 scmd
->uscsi_bufaddr
= (char *)inq
;
65 scmd
->uscsi_buflen
= INQUIRY_DATA_LENGTH
;
66 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
72 read_capacity(int fd
, uchar_t
*capbuf
)
74 struct uscsi_cmd
*scmd
;
76 scmd
= get_uscsi_cmd();
77 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
78 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
79 scmd
->uscsi_cdb
[0] = READ_CAP_CMD
;
80 scmd
->uscsi_cdblen
= 10;
81 scmd
->uscsi_bufaddr
= (char *)capbuf
;
82 scmd
->uscsi_buflen
= 8;
83 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
89 mode_sense(int fd
, uchar_t pc
, int dbd
, int page_len
, uchar_t
*buffer
)
91 struct uscsi_cmd
*scmd
;
93 scmd
= get_uscsi_cmd();
94 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
95 scmd
->uscsi_buflen
= page_len
;
96 scmd
->uscsi_bufaddr
= (char *)buffer
;
97 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
98 scmd
->uscsi_cdblen
= 0xa;
99 scmd
->uscsi_cdb
[0] = MODE_SENSE_10_CMD
;
101 /* don't return any block descriptors */
102 scmd
->uscsi_cdb
[1] = 0x8;
104 /* the page code we want */
105 scmd
->uscsi_cdb
[2] = pc
;
106 /* allocation length */
107 scmd
->uscsi_cdb
[7] = (page_len
>> 8) & 0xff;
108 scmd
->uscsi_cdb
[8] = page_len
& 0xff;
110 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
116 mode_select(int fd
, int page_len
, uchar_t
*buffer
)
118 struct uscsi_cmd
*scmd
;
120 scmd
= get_uscsi_cmd();
121 scmd
->uscsi_flags
= USCSI_WRITE
|USCSI_SILENT
;
122 scmd
->uscsi_buflen
= page_len
;
123 scmd
->uscsi_bufaddr
= (char *)buffer
;
124 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
125 scmd
->uscsi_cdblen
= 0xa;
127 /* mode select (10) command */
128 scmd
->uscsi_cdb
[0] = MODE_SELECT_10_CMD
;
129 scmd
->uscsi_cdb
[1] = 0x10;
131 /* parameter list length */
132 scmd
->uscsi_cdb
[7] = (page_len
>> 8) & 0xff;
133 scmd
->uscsi_cdb
[8] = page_len
& 0xff;
135 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
141 read_track_info(int fd
, int trackno
, uchar_t
*ti
)
143 struct uscsi_cmd
*scmd
;
145 scmd
= get_uscsi_cmd();
146 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
147 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
148 scmd
->uscsi_cdb
[0] = READ_TRACK_CMD
;
150 /* tell device we are giving it a track number */
151 scmd
->uscsi_cdb
[1] = 1;
153 /* track number to read */
155 if (device_type
== CD_RW
) {
156 ((uchar_t
*)scmd
->uscsi_cdb
)[5] = 0xff;
158 /* only 1 track is allowed on DVD media */
159 scmd
->uscsi_cdb
[1] = 0;
160 ((uchar_t
*)scmd
->uscsi_cdb
)[5] = 0;
163 scmd
->uscsi_cdb
[5] = (uchar_t
)trackno
;
165 scmd
->uscsi_cdb
[8] = TRACK_INFO_SIZE
;
166 scmd
->uscsi_cdblen
= 10;
167 scmd
->uscsi_bufaddr
= (char *)ti
;
168 scmd
->uscsi_buflen
= TRACK_INFO_SIZE
;
169 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
175 read_toc(int fd
, int format
, int trackno
, int buflen
, uchar_t
*buf
)
177 struct uscsi_cmd
*scmd
;
179 scmd
= get_uscsi_cmd();
180 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
181 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
182 scmd
->uscsi_cdb
[0] = READ_TOC_CMD
;
183 scmd
->uscsi_cdb
[2] = format
& 0xf;
184 scmd
->uscsi_cdb
[6] = trackno
;
185 scmd
->uscsi_cdb
[8] = buflen
& 0xff;
186 scmd
->uscsi_cdb
[7] = (buflen
>> 8) & 0xff;
187 scmd
->uscsi_cdblen
= 10;
188 scmd
->uscsi_bufaddr
= (char *)buf
;
189 scmd
->uscsi_buflen
= buflen
;
190 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
193 /* Fix for old SONY drives */
194 if ((format
== 0) && (buflen
== 4) && (buf
[0] == 0) && (buf
[1] == 2)) {
197 toc_size
= (((uint16_t)(buf
[3] + 1)) * 8) + 2;
198 load_scsi16(buf
, toc_size
);
204 read_header(int fd
, uint32_t lba
, uchar_t
*buf
)
206 struct uscsi_cmd
*scmd
;
208 scmd
= get_uscsi_cmd();
209 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
210 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
211 scmd
->uscsi_cdb
[0] = READ_HDR_CMD
;
213 /* Logical block address */
214 load_scsi32(&scmd
->uscsi_cdb
[2], lba
);
216 /* allocation length */
217 scmd
->uscsi_cdb
[8] = 8;
218 scmd
->uscsi_cdblen
= 10;
219 scmd
->uscsi_bufaddr
= (char *)buf
;
220 scmd
->uscsi_buflen
= 8;
221 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
227 read_disc_info(int fd
, uchar_t
*di
)
229 struct uscsi_cmd
*scmd
;
231 scmd
= get_uscsi_cmd();
232 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
233 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
234 scmd
->uscsi_cdb
[0] = READ_INFO_CMD
;
235 scmd
->uscsi_cdb
[8] = DISC_INFO_BLOCK_SIZE
;
236 scmd
->uscsi_cdblen
= 10;
237 scmd
->uscsi_bufaddr
= (char *)di
;
238 scmd
->uscsi_buflen
= DISC_INFO_BLOCK_SIZE
;
239 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
244 /* Get information about the Logical Unit's capabilities */
246 get_configuration(int fd
, uint16_t feature
, int bufsize
, uchar_t
*buf
)
248 struct uscsi_cmd
*scmd
;
250 scmd
= get_uscsi_cmd();
251 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
252 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
254 /* Set OPERATION CODE in CDB */
255 scmd
->uscsi_cdb
[0] = GET_CONFIG_CMD
;
258 * Set RT field in CDB, currently need at most one
261 scmd
->uscsi_cdb
[1] = 0x2;
263 /* Set Starting Feature Number in CDB */
264 scmd
->uscsi_cdb
[2] = (feature
>> 8) & 0xff;
265 scmd
->uscsi_cdb
[3] = feature
& 0xff;
267 /* Set Allocation Length in CDB */
268 scmd
->uscsi_cdb
[7] = (bufsize
>> 8) & 0xff;
269 scmd
->uscsi_cdb
[8] = bufsize
& 0xff;
271 scmd
->uscsi_cdblen
= 10;
272 scmd
->uscsi_bufaddr
= (char *)buf
;
273 scmd
->uscsi_buflen
= bufsize
;
274 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
280 read10(int fd
, uint32_t start_blk
, uint16_t nblk
, uchar_t
*buf
,
283 struct uscsi_cmd
*scmd
;
285 scmd
= get_uscsi_cmd();
286 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
287 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
288 scmd
->uscsi_cdb
[0] = READ_10_CMD
;
289 load_scsi32(&scmd
->uscsi_cdb
[2], start_blk
);
290 scmd
->uscsi_cdb
[8] = nblk
& 0xff;
291 scmd
->uscsi_cdb
[7] = (nblk
>> 8) & 0xff;
292 scmd
->uscsi_cdblen
= 10;
293 scmd
->uscsi_bufaddr
= (char *)buf
;
294 scmd
->uscsi_buflen
= bufsize
;
295 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
301 write10(int fd
, uint32_t start_blk
, uint16_t nblk
, uchar_t
*buf
,
304 struct uscsi_cmd
*scmd
;
306 scmd
= get_uscsi_cmd();
307 scmd
->uscsi_flags
= USCSI_WRITE
|USCSI_SILENT
;
309 * Some DVD drives take longer to write than
310 * the standard time, since they tend to generate
311 * the media TOC on the fly when the cache is full
313 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
* 3;
314 scmd
->uscsi_cdb
[0] = WRITE_10_CMD
;
315 load_scsi32(&scmd
->uscsi_cdb
[2], start_blk
);
316 scmd
->uscsi_cdb
[8] = nblk
& 0xff;
317 scmd
->uscsi_cdb
[7] = (nblk
>> 8) & 0xff;
318 scmd
->uscsi_cdblen
= 10;
319 scmd
->uscsi_bufaddr
= (char *)buf
;
320 scmd
->uscsi_buflen
= bufsize
;
321 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
327 close_track(int fd
, int trackno
, int close_session
, int immediate
)
329 struct uscsi_cmd
*scmd
;
331 scmd
= get_uscsi_cmd();
332 scmd
->uscsi_flags
= USCSI_SILENT
;
333 scmd
->uscsi_cdb
[0] = CLOSE_TRACK_CMD
;
335 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
336 scmd
->uscsi_cdb
[1] = 1;
338 scmd
->uscsi_timeout
= 240;
340 if ((close_session
) || (device_type
== DVD_PLUS
) ||
341 (device_type
== DVD_PLUS_W
)) {
342 /* close the session */
343 scmd
->uscsi_cdb
[2] = 2;
346 /* Close the track but leave session open */
347 scmd
->uscsi_cdb
[2] = 1;
348 scmd
->uscsi_cdb
[5] = trackno
& 0xff;
352 * DVD+R media are already formatted, we are using
353 * a special case to notify that drive to close
354 * track/session and null-fill the remaining space.
356 if (device_type
== DVD_PLUS
) {
357 scmd
->uscsi_cdb
[5] = 1; /* only 1 track */
360 scmd
->uscsi_cdb
[2] = 6; /* session */
362 scmd
->uscsi_cdb
[2] = 1; /* track */
366 scmd
->uscsi_cdblen
= 10;
367 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
373 blank_disc(int fd
, int type
, int immediate
)
375 struct uscsi_cmd
*scmd
;
377 scmd
= get_uscsi_cmd();
378 scmd
->uscsi_flags
= USCSI_SILENT
;
381 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
382 scmd
->uscsi_cdb
[1] = 0x10;
384 scmd
->uscsi_timeout
= 0x12c0;
386 ((uchar_t
*)scmd
->uscsi_cdb
)[0] = BLANK_CMD
;
388 /* tell it to blank the last session or all of the disk */
389 scmd
->uscsi_cdb
[1] |= type
& 0x07;
390 scmd
->uscsi_cdblen
= 12;
392 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
398 read_cd(int fd
, uint32_t start_blk
, uint16_t nblk
, uchar_t sector_type
,
399 uchar_t
*buf
, uint32_t bufsize
)
401 struct uscsi_cmd
*scmd
;
403 scmd
= get_uscsi_cmd();
404 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
405 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
406 ((uchar_t
*)scmd
->uscsi_cdb
)[0] = READ_CD_CMD
;
407 scmd
->uscsi_cdb
[1] = (sector_type
& 0x7) << 2;
408 scmd
->uscsi_cdb
[5] = start_blk
& 0xff;
409 scmd
->uscsi_cdb
[4] = (start_blk
>> 8) & 0xff;
410 scmd
->uscsi_cdb
[3] = (start_blk
>> 16) & 0xff;
411 scmd
->uscsi_cdb
[2] = (start_blk
>> 24) & 0xff;
412 scmd
->uscsi_cdb
[8] = nblk
& 0xff;
413 scmd
->uscsi_cdb
[7] = (nblk
>> 8) & 0xff;
414 scmd
->uscsi_cdb
[9] = 0x10;
415 scmd
->uscsi_cdblen
= 12;
416 scmd
->uscsi_bufaddr
= (char *)buf
;
417 scmd
->uscsi_buflen
= bufsize
;
418 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
424 load_unload(int fd
, int load
)
426 struct uscsi_cmd
*scmd
;
428 scmd
= get_uscsi_cmd();
429 scmd
->uscsi_flags
= USCSI_SILENT
;
430 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
431 scmd
->uscsi_cdb
[0] = START_STOP_CMD
;
434 scmd
->uscsi_cdb
[4] = 2;
437 scmd
->uscsi_cdb
[4] = 3;
439 scmd
->uscsi_cdblen
= 6;
441 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
447 prevent_allow_mr(int fd
, int op
)
449 struct uscsi_cmd
*scmd
;
451 scmd
= get_uscsi_cmd();
452 scmd
->uscsi_flags
= USCSI_SILENT
;
453 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
454 scmd
->uscsi_cdb
[0] = PREVENT_ALLOW_CMD
;
455 if (!op
) { /* prevent */
456 scmd
->uscsi_cdb
[4] = 1;
458 scmd
->uscsi_cdblen
= 6;
459 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
465 set_cd_speed(int fd
, uint16_t read_speed
, uint16_t write_speed
)
467 struct uscsi_cmd
*scmd
;
469 scmd
= get_uscsi_cmd();
470 scmd
->uscsi_flags
= USCSI_SILENT
;
471 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
472 scmd
->uscsi_cdblen
= 0xc;
473 ((uchar_t
*)scmd
->uscsi_cdb
)[0] = SET_CD_SPEED
;
474 scmd
->uscsi_cdb
[2] = (read_speed
>> 8) & 0xff;
475 scmd
->uscsi_cdb
[3] = read_speed
& 0xff;
476 scmd
->uscsi_cdb
[4] = (write_speed
>> 8) & 0xff;
477 scmd
->uscsi_cdb
[5] = write_speed
& 0xff;
479 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
485 get_performance(int fd
, int get_write_performance
, uchar_t
*perf
)
487 struct uscsi_cmd
*scmd
;
489 scmd
= get_uscsi_cmd();
490 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
491 scmd
->uscsi_buflen
= GET_PERF_DATA_LEN
;
492 scmd
->uscsi_bufaddr
= (char *)perf
;
493 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
494 scmd
->uscsi_cdblen
= 0xc;
495 ((uchar_t
*)scmd
->uscsi_cdb
)[0] = GET_PERFORMANCE_CMD
;
496 scmd
->uscsi_cdb
[1] = 0x10;
497 if (get_write_performance
)
498 scmd
->uscsi_cdb
[1] |= 4;
499 scmd
->uscsi_cdb
[9] = 2;
500 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
506 set_streaming(int fd
, uchar_t
*buf
)
508 struct uscsi_cmd
*scmd
;
510 scmd
= get_uscsi_cmd();
511 scmd
->uscsi_flags
= USCSI_WRITE
|USCSI_SILENT
;
512 scmd
->uscsi_buflen
= SET_STREAM_DATA_LEN
;
513 scmd
->uscsi_bufaddr
= (char *)buf
;
514 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
515 scmd
->uscsi_cdblen
= 0xc;
516 ((uchar_t
*)scmd
->uscsi_cdb
)[0] = STREAM_CMD
;
517 scmd
->uscsi_cdb
[10] = SET_STREAM_DATA_LEN
;
518 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
526 struct uscsi_cmd
*scmd
;
528 scmd
= get_uscsi_cmd();
529 scmd
->uscsi_flags
= USCSI_SILENT
;
530 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
531 scmd
->uscsi_cdblen
= 0x6;
532 scmd
->uscsi_cdb
[0] = REZERO_UNIT_CMD
;
533 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
539 start_stop(int fd
, int start
)
541 struct uscsi_cmd
*scmd
;
543 scmd
= get_uscsi_cmd();
544 scmd
->uscsi_flags
= USCSI_SILENT
;
545 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
546 scmd
->uscsi_cdblen
= 0x6;
547 scmd
->uscsi_cdb
[0] = START_STOP_CMD
;
549 scmd
->uscsi_cdb
[4] = 1;
551 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
559 struct uscsi_cmd
*scmd
;
561 scmd
= get_uscsi_cmd();
562 scmd
->uscsi_flags
= USCSI_SILENT
;
563 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
564 scmd
->uscsi_cdblen
= 10;
565 scmd
->uscsi_cdb
[0] = SYNC_CACHE_CMD
;
566 if (device_type
!= CD_RW
) {
567 scmd
->uscsi_cdb
[1] = 0x2; /* Immediate */
570 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
576 * used for DVD- to reserve the size we want to write.
577 * This is used by the drive to generate a TOC.
580 set_reservation(int fd
, ulong_t size
)
582 struct uscsi_cmd
*scmd
;
584 scmd
= get_uscsi_cmd();
585 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
586 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
587 scmd
->uscsi_cdb
[0] = SET_RESERVATION_CMD
;
588 scmd
->uscsi_cdblen
= 10;
589 scmd
->uscsi_cdb
[5] = (uchar_t
)(size
>> 24);
590 scmd
->uscsi_cdb
[6] = (uchar_t
)(size
>> 16);
591 scmd
->uscsi_cdb
[7] = (uchar_t
)(size
>> 8);
592 scmd
->uscsi_cdb
[8] = (uchar_t
)size
;
593 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
599 * Used for DVD+RW media to prepare the disk to write.
600 * It will also be used for packet mode writing when
601 * it becomes supported.
606 struct uscsi_cmd
*scmd
;
609 (void) memset(buf
, 0, 20);
610 scmd
= get_uscsi_cmd();
611 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
612 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
614 scmd
->uscsi_cdblen
= 12;
615 scmd
->uscsi_cdb
[0] = READ_FORMAT_CAP_CMD
;
616 scmd
->uscsi_cdb
[8] = 0x14; /* buffer length */
617 scmd
->uscsi_buflen
= 20;
618 scmd
->uscsi_bufaddr
= (char *)buf
;
620 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
623 /* RE-use cap structure */
625 scmd
->uscsi_flags
= USCSI_WRITE
|USCSI_SILENT
;
626 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
627 scmd
->uscsi_cdblen
= 6;
628 scmd
->uscsi_cdb
[0] = FORMAT_UNIT_CMD
;
630 scmd
->uscsi_cdb
[1] = 0x11;
631 scmd
->uscsi_buflen
= 12;
632 buf
[1] = 0x82; /* immediate and FOV */
633 buf
[3] = 8; /* descriptor length */
634 buf
[8] = 0x98; /* type = 26 DVD+RW format */
637 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
644 * Prefered method of reading the media size. This is
645 * the only supported method on several newer drives.
648 read_format_capacity(int fd
, uint_t
*bsize
)
650 struct uscsi_cmd
*scmd
;
654 scmd
= get_uscsi_cmd();
655 scmd
->uscsi_flags
= USCSI_READ
|USCSI_SILENT
;
656 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
657 scmd
->uscsi_cdblen
= 12;
658 scmd
->uscsi_cdb
[0] = READ_FORMAT_CAP_CMD
;
659 scmd
->uscsi_cdb
[8] = 0x14;
660 scmd
->uscsi_buflen
= 20;
661 scmd
->uscsi_bufaddr
= buf
;
663 if ((uscsi_error
= uscsi(fd
, scmd
)) < 0)
666 filesize
= (uint32_t)(((uchar_t
)buf
[4] << 24) +
667 ((uchar_t
)buf
[5] << 16) + ((uchar_t
)buf
[6] << 8) + (uchar_t
)buf
[7]);
669 *bsize
= (uint16_t)(((uchar_t
)buf
[10] << 8) + (uchar_t
)buf
[11]);
675 * Used to reset the device. Since, sd(7D) requires a
676 * command to be issued when resetting a device we will
677 * issue an innocuous command. The command chosen for this
678 * purpose is the TEST UNIT READY (TUR) command. We also do
679 * not care about the sucess of the TUR so we will not return
685 struct uscsi_cmd
*scmd
;
688 * Since a TUR has SCSI operation code of 0, we
689 * can make use of the fact that get_uscsi_cmd()
690 * initializes a CDB to all zeros to generate
693 scmd
= get_uscsi_cmd();
695 /* Tell sd(7D) to do a silent reset of the device. */
696 scmd
->uscsi_flags
= USCSI_SILENT
| USCSI_RESET
;
698 scmd
->uscsi_timeout
= DEFAULT_SCSI_TIMEOUT
;
699 scmd
->uscsi_cdblen
= 6;
701 /* Issue the TUR command. */
702 uscsi_error
= uscsi(fd
, scmd
);
707 * Function: ftr_supported
709 * Description: Check to see if a device supports a Feature
711 * Arguments: fd - file descriptor
712 * feature - the MMC Feature for which we'd like to know
715 * Return Code: 1 - Feature is supported
716 * 0 - Feature is not supported
720 ftr_supported(int fd
, uint16_t feature
)
726 response_len
= MMC_FTR_HDR_LEN
+ MMC_FTR_DSCRPTR_BASE_LEN
;
727 bufp
= (uchar_t
*)my_zalloc(response_len
);
730 * If a Feature is supported, a device will return a Feature Descriptor
731 * for that Feature, and its Current Bit will be set.
733 if (get_configuration(fd
, feature
, response_len
, bufp
) == 1) {
735 * To check that a Feature Descriptor was returned, we
736 * check to see if the Data Length field of the Feature
737 * Header holds a value greater than four. To check if
738 * the Current Bit is set, we check bit 1 of byte 10.
740 if (read_scsi32(bufp
) > 4 && bufp
[10] & 1)
745 /* get_configuration failed */
753 * Function: print_profile_name
755 * Description: Prints a list of the Profiles the device supports
757 * Parameters: num - hexadecimal representation of Profile
758 * current - 1 if the Profile is Current, otherwise 0
759 * abbr - 1 if printing abbreviated name, otherwise 0
762 print_profile_name(uint16_t num
, uchar_t current
, uchar_t abbr
)
765 (void) printf(" 0x%04x: ", num
);
769 (void) printf("No Current Profile");
772 (void) printf("Non-Removable Disk");
775 (void) printf("Removable Disk");
778 (void) printf("Magneto-Optical Erasable");
781 (void) printf("Optical Write Once");
784 (void) printf("AS-MO");
787 (void) printf("CD-ROM");
790 (void) printf("CD-R");
793 (void) printf("CD-RW");
796 (void) printf("DVD-ROM");
799 (void) printf("DVD-R");
801 (void) printf(" Sequential Recording");
804 (void) printf("DVD-RAM");
807 (void) printf("DVD-RW");
809 (void) printf(" Restricted Overwrite");
812 (void) printf("DVD-RW");
814 (void) printf(" Sequential Recording");
817 (void) printf("DVD-R");
819 (void) printf(" Dual Layer Sequential Recording");
821 (void) printf(" DL");
824 (void) printf("DVD-R");
826 (void) printf(" Dual Layer Jump Recording");
828 (void) printf(" DL");
831 (void) printf("DVD-RW");
833 (void) printf(" Dual Layer");
835 (void) printf(" DL");
838 (void) printf("DVD+RW");
841 (void) printf("DVD+R");
844 (void) printf("DDCD-ROM");
847 (void) printf("DDCD-R");
850 (void) printf("DDCD-RW");
853 (void) printf("DVD+RW");
855 (void) printf(" Dual Layer");
857 (void) printf(" DL");
860 (void) printf("DVD+R");
862 (void) printf(" Dual Layer");
864 (void) printf(" DL");
867 (void) printf("BD-ROM");
870 (void) printf("BD-R Sequential Recording (SRM) Profile");
873 (void) printf("BD-R Random Recording (RRM) Profile");
876 (void) printf("BD-RE");
879 (void) printf("Nonstandard Profile");
885 (void) printf(" (Current Profile)");
890 * Function: print_profile_list
892 * Description: Print a list of Profiles supported by the Logical Unit.
894 * Parameters: fd - file descriptor for device whose list of
895 * profiles we wish to print
898 print_profile_list(int fd
)
904 uchar_t
*bufp
= (uchar_t
*)my_zalloc(MMC_FTR_HDR_LEN
);
907 * First get_configuration call is used to determine amount of memory
908 * needed to hold all the Profiles. The first four bytes of bufp
909 * concatenated tell us the number of bytes of memory we need but do
910 * not take themselves into account. Therefore, add four, and
911 * allocate that number of bytes.
913 if (get_configuration(fd
, MMC_FTR_PRFL_LIST
, MMC_FTR_HDR_LEN
,
915 buflen
= read_scsi32(bufp
) + 4;
917 bufp
= (uchar_t
*)my_zalloc(buflen
);
920 * Now get all the Profiles
922 if (get_configuration(fd
, MMC_FTR_PRFL_LIST
, buflen
, bufp
)) {
923 (void) printf("\nProfile List\n");
924 (void) printf("---------------------------------\n");
927 * Find out the Logical Unit's Current Profile
929 current
= read_scsi16(&bufp
[6]);
932 * Print out the Profile List and indicate which
935 for (i
= MMC_FTR_HDR_LEN
+ MMC_FTR_DSCRPTR_BASE_LEN
;
936 i
< buflen
; i
+= MMC_PRFL_DSCRPTR_LEN
) {
937 other
= read_scsi16(&bufp
[i
]);
938 if (other
== current
)
939 print_profile_name(other
, 1, 0);
941 print_profile_name(other
, 0, 0);