1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <stdlib.h> 31 #include <stdio.h> 32 #include <string.h> 33 34 #include "transport.h" 35 #include "mmc.h" 36 #include "util.h" 37 #include "main.h" 38 39 int 40 test_unit_ready(int fd) 41 { 42 struct uscsi_cmd *scmd; 43 44 scmd = get_uscsi_cmd(); 45 scmd->uscsi_flags = USCSI_SILENT; 46 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 47 /* give length of cdb structure */ 48 scmd->uscsi_cdblen = 6; 49 if ((uscsi_error = uscsi(fd, scmd)) < 0) 50 return (0); 51 return (1); 52 } 53 54 int 55 inquiry(int fd, uchar_t *inq) 56 { 57 struct uscsi_cmd *scmd; 58 59 scmd = get_uscsi_cmd(); 60 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 61 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 62 scmd->uscsi_cdb[0] = INQUIRY_CMD; 63 scmd->uscsi_cdb[4] = INQUIRY_DATA_LENGTH; 64 scmd->uscsi_cdblen = 6; 65 scmd->uscsi_bufaddr = (char *)inq; 66 scmd->uscsi_buflen = INQUIRY_DATA_LENGTH; 67 if ((uscsi_error = uscsi(fd, scmd)) < 0) 68 return (0); 69 return (1); 70 } 71 72 int 73 read_capacity(int fd, uchar_t *capbuf) 74 { 75 struct uscsi_cmd *scmd; 76 77 scmd = get_uscsi_cmd(); 78 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 79 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 80 scmd->uscsi_cdb[0] = READ_CAP_CMD; 81 scmd->uscsi_cdblen = 10; 82 scmd->uscsi_bufaddr = (char *)capbuf; 83 scmd->uscsi_buflen = 8; 84 if ((uscsi_error = uscsi(fd, scmd)) < 0) 85 return (0); 86 return (1); 87 } 88 89 int 90 mode_sense(int fd, uchar_t pc, int dbd, int page_len, uchar_t *buffer) 91 { 92 struct uscsi_cmd *scmd; 93 94 scmd = get_uscsi_cmd(); 95 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 96 scmd->uscsi_buflen = page_len; 97 scmd->uscsi_bufaddr = (char *)buffer; 98 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 99 scmd->uscsi_cdblen = 0xa; 100 scmd->uscsi_cdb[0] = MODE_SENSE_10_CMD; 101 if (dbd) { 102 /* don't return any block descriptors */ 103 scmd->uscsi_cdb[1] = 0x8; 104 } 105 /* the page code we want */ 106 scmd->uscsi_cdb[2] = pc; 107 /* allocation length */ 108 scmd->uscsi_cdb[7] = (page_len >> 8) & 0xff; 109 scmd->uscsi_cdb[8] = page_len & 0xff; 110 111 if ((uscsi_error = uscsi(fd, scmd)) < 0) 112 return (0); 113 return (1); 114 } 115 116 int 117 mode_select(int fd, int page_len, uchar_t *buffer) 118 { 119 struct uscsi_cmd *scmd; 120 121 scmd = get_uscsi_cmd(); 122 scmd->uscsi_flags = USCSI_WRITE|USCSI_SILENT; 123 scmd->uscsi_buflen = page_len; 124 scmd->uscsi_bufaddr = (char *)buffer; 125 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 126 scmd->uscsi_cdblen = 0xa; 127 128 /* mode select (10) command */ 129 scmd->uscsi_cdb[0] = MODE_SELECT_10_CMD; 130 scmd->uscsi_cdb[1] = 0x10; 131 132 /* parameter list length */ 133 scmd->uscsi_cdb[7] = (page_len >> 8) & 0xff; 134 scmd->uscsi_cdb[8] = page_len & 0xff; 135 136 if ((uscsi_error = uscsi(fd, scmd)) < 0) 137 return (0); 138 return (1); 139 } 140 141 int 142 read_track_info(int fd, int trackno, uchar_t *ti) 143 { 144 struct uscsi_cmd *scmd; 145 146 scmd = get_uscsi_cmd(); 147 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 148 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 149 scmd->uscsi_cdb[0] = READ_TRACK_CMD; 150 151 /* tell device we are giving it a track number */ 152 scmd->uscsi_cdb[1] = 1; 153 154 /* track number to read */ 155 if (trackno == -1) 156 if (device_type == CD_RW) { 157 ((uchar_t *)scmd->uscsi_cdb)[5] = 0xff; 158 } else { 159 /* only 1 track is allowed on DVD media */ 160 scmd->uscsi_cdb[1] = 0; 161 ((uchar_t *)scmd->uscsi_cdb)[5] = 0; 162 } 163 else 164 scmd->uscsi_cdb[5] = (uchar_t)trackno; 165 166 scmd->uscsi_cdb[8] = TRACK_INFO_SIZE; 167 scmd->uscsi_cdblen = 10; 168 scmd->uscsi_bufaddr = (char *)ti; 169 scmd->uscsi_buflen = TRACK_INFO_SIZE; 170 if ((uscsi_error = uscsi(fd, scmd)) < 0) 171 return (0); 172 return (1); 173 } 174 175 int 176 read_toc(int fd, int format, int trackno, int buflen, uchar_t *buf) 177 { 178 struct uscsi_cmd *scmd; 179 180 scmd = get_uscsi_cmd(); 181 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 182 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 183 scmd->uscsi_cdb[0] = READ_TOC_CMD; 184 scmd->uscsi_cdb[2] = format & 0xf; 185 scmd->uscsi_cdb[6] = trackno; 186 scmd->uscsi_cdb[8] = buflen & 0xff; 187 scmd->uscsi_cdb[7] = (buflen >> 8) & 0xff; 188 scmd->uscsi_cdblen = 10; 189 scmd->uscsi_bufaddr = (char *)buf; 190 scmd->uscsi_buflen = buflen; 191 if ((uscsi_error = uscsi(fd, scmd)) < 0) 192 return (0); 193 194 /* Fix for old SONY drives */ 195 if ((format == 0) && (buflen == 4) && (buf[0] == 0) && (buf[1] == 2)) { 196 uint16_t toc_size; 197 198 toc_size = (((uint16_t)(buf[3] + 1)) * 8) + 2; 199 load_scsi16(buf, toc_size); 200 } 201 return (1); 202 } 203 204 int 205 read_header(int fd, uint32_t lba, uchar_t *buf) 206 { 207 struct uscsi_cmd *scmd; 208 209 scmd = get_uscsi_cmd(); 210 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 211 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 212 scmd->uscsi_cdb[0] = READ_HDR_CMD; 213 214 /* Logical block address */ 215 load_scsi32(&scmd->uscsi_cdb[2], lba); 216 217 /* allocation length */ 218 scmd->uscsi_cdb[8] = 8; 219 scmd->uscsi_cdblen = 10; 220 scmd->uscsi_bufaddr = (char *)buf; 221 scmd->uscsi_buflen = 8; 222 if ((uscsi_error = uscsi(fd, scmd)) < 0) 223 return (0); 224 return (1); 225 } 226 227 int 228 read_disc_info(int fd, uchar_t *di) 229 { 230 struct uscsi_cmd *scmd; 231 232 scmd = get_uscsi_cmd(); 233 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 234 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 235 scmd->uscsi_cdb[0] = READ_INFO_CMD; 236 scmd->uscsi_cdb[8] = DISC_INFO_BLOCK_SIZE; 237 scmd->uscsi_cdblen = 10; 238 scmd->uscsi_bufaddr = (char *)di; 239 scmd->uscsi_buflen = DISC_INFO_BLOCK_SIZE; 240 if ((uscsi_error = uscsi(fd, scmd)) < 0) 241 return (0); 242 return (1); 243 } 244 245 int 246 get_configuration(int fd, uint16_t feature, int bufsize, uchar_t *buf) 247 { 248 struct uscsi_cmd *scmd; 249 250 scmd = get_uscsi_cmd(); 251 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 252 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 253 scmd->uscsi_cdb[0] = GET_CONFIG_CMD; 254 if (feature == 0) 255 scmd->uscsi_cdb[1] = 0x2; 256 else 257 scmd->uscsi_cdb[1] = 0x1; 258 scmd->uscsi_cdb[1] = 0x2; 259 scmd->uscsi_cdb[2] = (feature >> 8) & 0xff; 260 scmd->uscsi_cdb[3] = feature & 0xff; 261 scmd->uscsi_cdb[7] = (bufsize >> 8) & 0xff; 262 scmd->uscsi_cdb[8] = bufsize & 0xff; 263 scmd->uscsi_cdblen = 10; 264 scmd->uscsi_bufaddr = (char *)buf; 265 scmd->uscsi_buflen = bufsize; 266 if ((uscsi_error = uscsi(fd, scmd)) < 0) 267 return (0); 268 return (1); 269 } 270 271 int 272 read10(int fd, uint32_t start_blk, uint16_t nblk, uchar_t *buf, 273 uint32_t bufsize) 274 { 275 struct uscsi_cmd *scmd; 276 277 scmd = get_uscsi_cmd(); 278 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 279 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 280 scmd->uscsi_cdb[0] = READ_10_CMD; 281 load_scsi32(&scmd->uscsi_cdb[2], start_blk); 282 scmd->uscsi_cdb[8] = nblk & 0xff; 283 scmd->uscsi_cdb[7] = (nblk >> 8) & 0xff; 284 scmd->uscsi_cdblen = 10; 285 scmd->uscsi_bufaddr = (char *)buf; 286 scmd->uscsi_buflen = bufsize; 287 if ((uscsi_error = uscsi(fd, scmd)) < 0) 288 return (0); 289 return (1); 290 } 291 292 int 293 write10(int fd, uint32_t start_blk, uint16_t nblk, uchar_t *buf, 294 uint32_t bufsize) 295 { 296 struct uscsi_cmd *scmd; 297 298 scmd = get_uscsi_cmd(); 299 scmd->uscsi_flags = USCSI_WRITE|USCSI_SILENT; 300 /* 301 * Some DVD drives take longer to write than 302 * the standard time, since they tend to generate 303 * the media TOC on the fly when the cache is full 304 */ 305 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT * 3; 306 scmd->uscsi_cdb[0] = WRITE_10_CMD; 307 load_scsi32(&scmd->uscsi_cdb[2], start_blk); 308 scmd->uscsi_cdb[8] = nblk & 0xff; 309 scmd->uscsi_cdb[7] = (nblk >> 8) & 0xff; 310 scmd->uscsi_cdblen = 10; 311 scmd->uscsi_bufaddr = (char *)buf; 312 scmd->uscsi_buflen = bufsize; 313 if ((uscsi_error = uscsi(fd, scmd)) < 0) 314 return (0); 315 return (1); 316 } 317 318 int 319 close_track(int fd, int trackno, int close_session, int immediate) 320 { 321 struct uscsi_cmd *scmd; 322 323 scmd = get_uscsi_cmd(); 324 scmd->uscsi_flags = USCSI_SILENT; 325 scmd->uscsi_cdb[0] = CLOSE_TRACK_CMD; 326 if (immediate) { 327 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 328 scmd->uscsi_cdb[1] = 1; 329 } else { 330 scmd->uscsi_timeout = 240; 331 } 332 if ((close_session) || (device_type == DVD_PLUS) || 333 (device_type == DVD_PLUS_W)) { 334 /* close the session */ 335 scmd->uscsi_cdb[2] = 2; 336 337 } else { 338 /* Close the track but leave session open */ 339 scmd->uscsi_cdb[2] = 1; 340 scmd->uscsi_cdb[5] = trackno & 0xff; 341 } 342 343 /* 344 * DVD+R media are already formatted, we are using 345 * a special case to notify that drive to close 346 * track/session and null-fill the remaining space. 347 */ 348 if (device_type == DVD_PLUS) { 349 scmd->uscsi_cdb[5] = 1; /* only 1 track */ 350 351 if (close_session) { 352 scmd->uscsi_cdb[2] = 6; /* session */ 353 } else { 354 scmd->uscsi_cdb[2] = 1; /* track */ 355 } 356 } 357 358 scmd->uscsi_cdblen = 10; 359 if ((uscsi_error = uscsi(fd, scmd)) < 0) 360 return (0); 361 return (1); 362 } 363 364 int 365 blank_disc(int fd, int type, int immediate) 366 { 367 struct uscsi_cmd *scmd; 368 369 scmd = get_uscsi_cmd(); 370 scmd->uscsi_flags = USCSI_SILENT; 371 372 if (immediate) { 373 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 374 scmd->uscsi_cdb[1] = 0x10; 375 } else { 376 scmd->uscsi_timeout = 0x12c0; 377 } 378 ((uchar_t *)scmd->uscsi_cdb)[0] = BLANK_CMD; 379 380 /* tell it to blank the last session or all of the disk */ 381 scmd->uscsi_cdb[1] |= type & 0x07; 382 scmd->uscsi_cdblen = 12; 383 384 if ((uscsi_error = uscsi(fd, scmd)) < 0) 385 return (0); 386 return (1); 387 } 388 389 int 390 read_cd(int fd, uint32_t start_blk, uint16_t nblk, uchar_t sector_type, 391 uchar_t *buf, uint32_t bufsize) 392 { 393 struct uscsi_cmd *scmd; 394 395 scmd = get_uscsi_cmd(); 396 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 397 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 398 ((uchar_t *)scmd->uscsi_cdb)[0] = READ_CD_CMD; 399 scmd->uscsi_cdb[1] = (sector_type & 0x7) << 2; 400 scmd->uscsi_cdb[5] = start_blk & 0xff; 401 scmd->uscsi_cdb[4] = (start_blk >> 8) & 0xff; 402 scmd->uscsi_cdb[3] = (start_blk >> 16) & 0xff; 403 scmd->uscsi_cdb[2] = (start_blk >> 24) & 0xff; 404 scmd->uscsi_cdb[8] = nblk & 0xff; 405 scmd->uscsi_cdb[7] = (nblk >> 8) & 0xff; 406 scmd->uscsi_cdb[9] = 0x10; 407 scmd->uscsi_cdblen = 12; 408 scmd->uscsi_bufaddr = (char *)buf; 409 scmd->uscsi_buflen = bufsize; 410 if ((uscsi_error = uscsi(fd, scmd)) < 0) 411 return (0); 412 return (1); 413 } 414 415 int 416 load_unload(int fd, int load) 417 { 418 struct uscsi_cmd *scmd; 419 420 scmd = get_uscsi_cmd(); 421 scmd->uscsi_flags = USCSI_SILENT; 422 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 423 scmd->uscsi_cdb[0] = START_STOP_CMD; 424 if (load == 0) { 425 /* unload medium */ 426 scmd->uscsi_cdb[4] = 2; 427 } else { 428 /* load medium */ 429 scmd->uscsi_cdb[4] = 3; 430 } 431 scmd->uscsi_cdblen = 6; 432 433 if ((uscsi_error = uscsi(fd, scmd)) < 0) 434 return (0); 435 return (1); 436 } 437 438 int 439 prevent_allow_mr(int fd, int op) 440 { 441 struct uscsi_cmd *scmd; 442 443 scmd = get_uscsi_cmd(); 444 scmd->uscsi_flags = USCSI_SILENT; 445 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 446 scmd->uscsi_cdb[0] = PREVENT_ALLOW_CMD; 447 if (!op) { /* prevent */ 448 scmd->uscsi_cdb[4] = 1; 449 } 450 scmd->uscsi_cdblen = 6; 451 if ((uscsi_error = uscsi(fd, scmd)) < 0) 452 return (0); 453 return (1); 454 } 455 456 int 457 set_cd_speed(int fd, uint16_t read_speed, uint16_t write_speed) 458 { 459 struct uscsi_cmd *scmd; 460 461 scmd = get_uscsi_cmd(); 462 scmd->uscsi_flags = USCSI_SILENT; 463 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 464 scmd->uscsi_cdblen = 0xc; 465 ((uchar_t *)scmd->uscsi_cdb)[0] = SET_CD_SPEED; 466 scmd->uscsi_cdb[2] = (read_speed >> 8) & 0xff; 467 scmd->uscsi_cdb[3] = read_speed & 0xff; 468 scmd->uscsi_cdb[4] = (write_speed >> 8) & 0xff; 469 scmd->uscsi_cdb[5] = write_speed & 0xff; 470 471 if ((uscsi_error = uscsi(fd, scmd)) < 0) 472 return (0); 473 return (1); 474 } 475 476 int 477 get_performance(int fd, int get_write_performance, uchar_t *perf) 478 { 479 struct uscsi_cmd *scmd; 480 481 scmd = get_uscsi_cmd(); 482 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 483 scmd->uscsi_buflen = GET_PERF_DATA_LEN; 484 scmd->uscsi_bufaddr = (char *)perf; 485 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 486 scmd->uscsi_cdblen = 0xc; 487 ((uchar_t *)scmd->uscsi_cdb)[0] = GET_PERFORMANCE_CMD; 488 scmd->uscsi_cdb[1] = 0x10; 489 if (get_write_performance) 490 scmd->uscsi_cdb[1] |= 4; 491 scmd->uscsi_cdb[9] = 2; 492 if ((uscsi_error = uscsi(fd, scmd)) < 0) 493 return (0); 494 return (1); 495 } 496 497 int 498 set_streaming(int fd, uchar_t *buf) 499 { 500 struct uscsi_cmd *scmd; 501 502 scmd = get_uscsi_cmd(); 503 scmd->uscsi_flags = USCSI_WRITE|USCSI_SILENT; 504 scmd->uscsi_buflen = SET_STREAM_DATA_LEN; 505 scmd->uscsi_bufaddr = (char *)buf; 506 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 507 scmd->uscsi_cdblen = 0xc; 508 ((uchar_t *)scmd->uscsi_cdb)[0] = STREAM_CMD; 509 scmd->uscsi_cdb[10] = SET_STREAM_DATA_LEN; 510 if ((uscsi_error = uscsi(fd, scmd)) < 0) 511 return (0); 512 return (1); 513 } 514 515 int 516 rezero_unit(int fd) 517 { 518 struct uscsi_cmd *scmd; 519 520 scmd = get_uscsi_cmd(); 521 scmd->uscsi_flags = USCSI_SILENT; 522 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 523 scmd->uscsi_cdblen = 0x6; 524 scmd->uscsi_cdb[0] = REZERO_UNIT_CMD; 525 if ((uscsi_error = uscsi(fd, scmd)) < 0) 526 return (0); 527 return (1); 528 } 529 530 int 531 start_stop(int fd, int start) 532 { 533 struct uscsi_cmd *scmd; 534 535 scmd = get_uscsi_cmd(); 536 scmd->uscsi_flags = USCSI_SILENT; 537 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 538 scmd->uscsi_cdblen = 0x6; 539 scmd->uscsi_cdb[0] = START_STOP_CMD; 540 if (start) { 541 scmd->uscsi_cdb[4] = 1; 542 } 543 if ((uscsi_error = uscsi(fd, scmd)) < 0) 544 return (0); 545 return (1); 546 } 547 548 int 549 flush_cache(int fd) 550 { 551 struct uscsi_cmd *scmd; 552 553 scmd = get_uscsi_cmd(); 554 scmd->uscsi_flags = USCSI_SILENT; 555 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 556 scmd->uscsi_cdblen = 10; 557 scmd->uscsi_cdb[0] = SYNC_CACHE_CMD; 558 if (device_type != CD_RW) { 559 scmd->uscsi_cdb[1] = 0x2; /* Immediate */ 560 } 561 562 if ((uscsi_error = uscsi(fd, scmd)) < 0) 563 return (0); 564 return (1); 565 } 566 567 /* 568 * used for DVD- to reserve the size we want to write. 569 * This is used by the drive to generate a TOC. 570 */ 571 int 572 set_reservation(int fd, ulong_t size) 573 { 574 struct uscsi_cmd *scmd; 575 576 scmd = get_uscsi_cmd(); 577 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 578 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 579 scmd->uscsi_cdb[0] = SET_RESERVATION_CMD; 580 scmd->uscsi_cdblen = 10; 581 scmd->uscsi_cdb[5] = (uchar_t)(size >> 24); 582 scmd->uscsi_cdb[6] = (uchar_t)(size >> 16); 583 scmd->uscsi_cdb[7] = (uchar_t)(size >> 8); 584 scmd->uscsi_cdb[8] = (uchar_t)size; 585 if ((uscsi_error = uscsi(fd, scmd)) < 0) 586 return (0); 587 return (1); 588 } 589 590 /* 591 * Used for DVD+RW media to prepare the disk to write. 592 * It will also be used for packet mode writing when 593 * it becomes supported. 594 */ 595 int 596 format_media(int fd) 597 { 598 struct uscsi_cmd *scmd; 599 uchar_t buf[20]; 600 601 (void) memset(buf, 0, 20); 602 scmd = get_uscsi_cmd(); 603 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 604 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 605 606 scmd->uscsi_cdblen = 12; 607 scmd->uscsi_cdb[0] = READ_FORMAT_CAP_CMD; 608 scmd->uscsi_cdb[8] = 0x14; /* buffer length */ 609 scmd->uscsi_buflen = 20; 610 scmd->uscsi_bufaddr = (char *)buf; 611 612 if ((uscsi_error = uscsi(fd, scmd)) < 0) 613 return (0); 614 615 /* RE-use cap structure */ 616 617 scmd->uscsi_flags = USCSI_WRITE|USCSI_SILENT; 618 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 619 scmd->uscsi_cdblen = 6; 620 scmd->uscsi_cdb[0] = FORMAT_UNIT_CMD; 621 /* full format */ 622 scmd->uscsi_cdb[1] = 0x11; 623 scmd->uscsi_buflen = 12; 624 buf[1] = 0x82; /* immediate and FOV */ 625 buf[3] = 8; /* descriptor length */ 626 buf[8] = 0x98; /* type = 26 DVD+RW format */ 627 buf[10] = 0; 628 629 if ((uscsi_error = uscsi(fd, scmd)) < 0) 630 return (0); 631 return (1); 632 } 633 634 635 /* 636 * Prefered method of reading the media size. This is 637 * the only supported method on several newer drives. 638 */ 639 uint32_t 640 read_format_capacity(int fd, uint_t *bsize) 641 { 642 struct uscsi_cmd *scmd; 643 uint32_t filesize; 644 char buf[20]; 645 646 scmd = get_uscsi_cmd(); 647 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 648 scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT; 649 scmd->uscsi_cdblen = 12; 650 scmd->uscsi_cdb[0] = READ_FORMAT_CAP_CMD; 651 scmd->uscsi_cdb[8] = 0x14; 652 scmd->uscsi_buflen = 20; 653 scmd->uscsi_bufaddr = buf; 654 655 if ((uscsi_error = uscsi(fd, scmd)) < 0) 656 return (0); 657 658 filesize = (uint32_t)(((uchar_t)buf[4] << 24) + 659 ((uchar_t)buf[5] << 16) + ((uchar_t)buf[6] << 8) + (uchar_t)buf[7]); 660 661 *bsize = (uint16_t)(((uchar_t)buf[10] << 8) + (uchar_t)buf[11]); 662 663 return (filesize); 664 } 665