1 /* @(#)drv_dvdplus.c 1.65 12/03/16 Copyright 2003-2012 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)drv_dvdplus.c 1.65 12/03/16 Copyright 2003-2012 J. Schilling";
6 #endif
7 /*
8 * Copyright (c) 2003-2012 J. Schilling
9 */
10 /*
11 * The contents of this file are subject to the terms of the
12 * Common Development and Distribution License, Version 1.0 only
13 * (the "License"). You may not use this file except in compliance
14 * with the License.
15 *
16 * See the file CDDL.Schily.txt in this distribution for details.
17 *
18 * When distributing Covered Code, include this CDDL HEADER in each
19 * file and include the License file CDDL.Schily.txt from this distribution.
20 */
21
22 /*
23 * DVD+R/RW device implementation for
24 * SCSI-3/mmc-3 conforming drives
25 *
26 * XXX Aktualisieren:
27 * Check recovery - DUMMY
28 * Load Media - OK
29 * Get Disktype - Disk Status & Size (read ATIP -> DVD structure)
30 * Check Session ?? - Nicht vorhanden
31 * Check Disk size - Nach Status & size + Next wr. Addr.
32 * Set Speed/Dummy - Speed auf DVD -> dummy
33 * Open Session - Set Write Parameter & ??? -> DAO
34 * LOOP
35 * Open Track - Set Write Parameter ???
36 * Get Next wr. Addr. -> DUMMY "0" ???
37 * Write Track Data OK
38 * Close Track - Flush Cache -> DUMMY
39 * END
40 * Fixate - Close Track/Session -> Flush Cache
41 * Unload Media - OK
42 *
43 * Verbose levels:
44 * 0 silent
45 * 1 print laser log & track sizes
46 * 2 print disk info & write parameters
47 * 3 print log pages & dvd structure
48 *
49 * Copyright (c) 2003-2009 J. Schilling
50 */
51 /*
52 * The contents of this file are subject to the terms of the
53 * Common Development and Distribution License, Version 1.0 only
54 * (the "License"). You may not use this file except in compliance
55 * with the License.
56 *
57 * See the file CDDL.Schily.txt in this distribution for details.
58 *
59 * When distributing Covered Code, include this CDDL HEADER in each
60 * file and include the License file CDDL.Schily.txt from this distribution.
61 */
62
63 /*#define DVDPLUS_DEBUG*/
64 #ifndef DEBUG
65 #define DEBUG
66 #endif
67 #include <schily/mconfig.h>
68
69 #include <schily/stdio.h>
70 #include <schily/stdlib.h>
71 #include <schily/unistd.h> /* Include sys/types.h to make off_t available */
72 #include <schily/standard.h>
73 #include <schily/string.h>
74 #include <schily/time.h>
75
76 #include <schily/utypes.h>
77 #include <schily/btorder.h>
78 #include <schily/intcvt.h>
79 #include <schily/schily.h>
80 #include <schily/nlsdefs.h>
81
82 #include <scg/scgcmd.h>
83 #include <scg/scsidefs.h>
84 #include <scg/scsireg.h>
85 #include <scg/scsitransp.h>
86
87 #include "scsimmc.h"
88 #include "scsilog.h"
89 #include "mmcvendor.h"
90 #include "cdrecord.h"
91
92
93 extern char *driveropts;
94
95 extern int lverbose;
96 extern int xdebug;
97
98 #define strbeg(s1, s2) (strstr((s2), (s1)) == (s2))
99
100 LOCAL cdr_t *identify_dvdplus __PR((SCSI *scgp, cdr_t *, struct scsi_inquiry *));
101 LOCAL int attach_dvdplus __PR((SCSI *scgp, cdr_t *));
102 LOCAL void di_to_dstat __PR((struct disk_info *dip, dstat_t *dsp));
103 LOCAL int init_dvdplus __PR((SCSI *scgp, cdr_t *dp));
104 LOCAL int getdisktype_dvdplus __PR((SCSI *scgp, cdr_t *dp));
105 LOCAL int prdiskstatus_dvdplus __PR((SCSI *scgp, cdr_t *dp));
106 LOCAL int speed_select_dvdplus __PR((SCSI *scgp, cdr_t *dp, int *speedp));
107 LOCAL int next_wr_addr_dvdplusrw __PR((SCSI *scgp, track_t *trackp, long *ap));
108 LOCAL int next_wr_addr_dvdplusr __PR((SCSI *scgp, track_t *trackp, long *ap));
109 LOCAL int open_track_dvdplus __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
110 LOCAL long rzone_size __PR((track_t *trackp));
111 LOCAL int close_track_dvdplus __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
112 /*LOCAL int open_session_dvdplus __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));*/
113 LOCAL int fixate_dvdplusrw __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
114 LOCAL int fixate_dvdplusr __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
115 LOCAL BOOL dvdplus_ricohbased __PR((SCSI *scgp));
116 LOCAL int blank_dvdplus __PR((SCSI *scgp, cdr_t *dp, long addr, int blanktype));
117 LOCAL int format_dvdplus __PR((SCSI *scgp, cdr_t *dp, int fmtflags));
118 LOCAL int waitformat __PR((SCSI *scgp, int secs));
119 LOCAL int stats_dvdplus __PR((SCSI *scgp, cdr_t *dp));
120
121 EXPORT int format_unit __PR((SCSI *scgp,
122 void *fmt, int length,
123 int list_format, int dgdl,
124 int interlv, int pattern, int timeout));
125 LOCAL int set_p_layerbreak __PR((SCSI *scgp, long tsize, Int32_t lbreak));
126
127 #define CHANGE_SETTING 1
128 #define DVD_PLUS_R 2
129 #define DC_ERASE 4
130 LOCAL int ricoh_dvdsetting __PR((SCSI *scgp, int erase_size, int flags, int immed));
131
132 #ifdef __needed__
133 LOCAL int dummy_plextor __PR((SCSI *scgp, int modecode));
134 #endif
135
136 /*
137 * SCSI-3/mmc-3 conformant DVD+R or DVD+RW writer
138 * Checks the current medium and then returns either
139 * cdr_dvdplusr or cdr_dvdplusrw
140 */
141 cdr_t cdr_dvdplus = {
142 0, 0, 0,
143 CDR_DVD|CDR_SWABAUDIO,
144 CDR2_NOCD,
145 CDR_CDRW_ALL,
146 WM_NONE,
147 1000, 1000,
148 "mmc_dvdplus",
149 "generic SCSI-3/mmc-3 DVD+R/DVD+RW driver (checks media)",
150 0,
151 (dstat_t *)0,
152 identify_dvdplus,
153 attach_dvdplus,
154 (int(*)__PR((SCSI *scgp, cdr_t *)))cmd_ill, /* init */
155 drive_getdisktype,
156 no_diskstatus,
157 scsi_load,
158 scsi_unload,
159 read_buff_cap,
160 cmd_dummy, /* recovery_needed */
161 (int(*)__PR((SCSI *, cdr_t *, int)))cmd_dummy, /* recover */
162 (int(*)__PR((SCSI *scgp, cdr_t *, int *)))cmd_dummy, /* Speed */
163 select_secsize,
164 (int(*)__PR((SCSI *scgp, track_t *, long *)))cmd_ill, /* next_wr_addr */
165 (int(*)__PR((SCSI *, Ulong)))cmd_ill, /* reserve_track */
166 scsi_cdr_write,
167 (int(*)__PR((track_t *, void *, BOOL)))cmd_dummy, /* gen_cue */
168 no_sendcue,
169 (int(*)__PR((SCSI *, cdr_t *, track_t *)))cmd_dummy, /* leadin */
170 (int(*)__PR((SCSI *scgp, cdr_t *, track_t *)))cmd_dummy, /* open track */
171 (int(*)__PR((SCSI *scgp, cdr_t *, track_t *)))cmd_dummy, /* close track */
172 (int(*)__PR((SCSI *scgp, cdr_t *, track_t *)))cmd_dummy, /* open session */
173 cmd_dummy, /* close session */
174 cmd_dummy, /* abort */
175 read_session_offset,
176 (int(*)__PR((SCSI *scgp, cdr_t *, track_t *)))cmd_dummy, /* fixation */
177 cmd_dummy, /* stats */
178 blank_dummy,
179 format_dummy,
180 (int(*)__PR((SCSI *, caddr_t, int, int)))NULL, /* no OPC */
181 cmd_dummy, /* opt1 */
182 cmd_dummy, /* opt2 */
183 };
184
185 /*
186 * SCSI-3/mmc-3 conformant DVD+R writer
187 */
188 cdr_t cdr_dvdplusr = {
189 0, 0, 0,
190 CDR_DVD|CDR_SWABAUDIO,
191 CDR2_NOCD,
192 CDR_CDRW_ALL,
193 WM_SAO,
194 1000, 1000,
195 "mmc_dvdplusr",
196 "generic SCSI-3/mmc-3 DVD+R driver",
197 0,
198 (dstat_t *)0,
199 identify_dvdplus,
200 attach_dvdplus,
201 init_dvdplus,
202 getdisktype_dvdplus,
203 prdiskstatus_dvdplus,
204 scsi_load,
205 scsi_unload,
206 read_buff_cap,
207 cmd_dummy, /* recovery_needed */
208 (int(*)__PR((SCSI *, cdr_t *, int)))cmd_dummy, /* recover */
209 speed_select_dvdplus,
210 select_secsize,
211 next_wr_addr_dvdplusr,
212 (int(*)__PR((SCSI *, Ulong)))cmd_ill, /* reserve_track */
213 scsi_cdr_write,
214 (int(*)__PR((track_t *, void *, BOOL)))cmd_dummy, /* gen_cue */
215 no_sendcue,
216 (int(*)__PR((SCSI *, cdr_t *, track_t *)))cmd_dummy, /* leadin */
217 open_track_dvdplus,
218 close_track_dvdplus,
219 (int(*)__PR((SCSI *scgp, cdr_t *, track_t *)))cmd_dummy, /* open session */
220 cmd_dummy, /* close session */
221 cmd_dummy, /* abort */
222 read_session_offset,
223 fixate_dvdplusr,
224 stats_dvdplus,
225 blank_dvdplus,
226 format_dummy,
227 (int(*)__PR((SCSI *, caddr_t, int, int)))NULL, /* no OPC */
228 cmd_dummy, /* opt1 */
229 cmd_dummy, /* opt2 */
230 };
231
232 /*
233 * SCSI-3/mmc-3 conformant DVD+RW writer
234 */
235 cdr_t cdr_dvdplusrw = {
236 0, 0, 0,
237 CDR_DVD|CDR_SWABAUDIO,
238 CDR2_NOCD,
239 CDR_CDRW_ALL,
240 WM_SAO,
241 1000, 1000,
242 "mmc_dvdplusrw",
243 "generic SCSI-3/mmc-3 DVD+RW driver",
244 0,
245 (dstat_t *)0,
246 identify_dvdplus,
247 attach_dvdplus,
248 init_dvdplus,
249 getdisktype_dvdplus,
250 prdiskstatus_dvdplus,
251 scsi_load,
252 scsi_unload,
253 read_buff_cap,
254 cmd_dummy, /* recovery_needed */
255 (int(*)__PR((SCSI *, cdr_t *, int)))cmd_dummy, /* recover */
256 speed_select_dvdplus,
257 select_secsize,
258 next_wr_addr_dvdplusrw,
259 (int(*)__PR((SCSI *, Ulong)))cmd_ill, /* reserve_track */
260 scsi_cdr_write,
261 (int(*)__PR((track_t *, void *, BOOL)))cmd_dummy, /* gen_cue */
262 no_sendcue,
263 (int(*)__PR((SCSI *, cdr_t *, track_t *)))cmd_dummy, /* leadin */
264 open_track_dvdplus,
265 close_track_dvdplus,
266 (int(*)__PR((SCSI *scgp, cdr_t *, track_t *)))cmd_dummy, /* open session */
267 cmd_dummy, /* close session */
268 cmd_dummy, /* abort */
269 read_session_offset,
270 fixate_dvdplusrw,
271 stats_dvdplus,
272 blank_dvdplus,
273 format_dvdplus,
274 (int(*)__PR((SCSI *, caddr_t, int, int)))NULL, /* no OPC */
275 cmd_dummy, /* opt1 */
276 cmd_dummy, /* opt2 */
277 };
278
279 LOCAL cdr_t *
identify_dvdplus(scgp,dp,ip)280 identify_dvdplus(scgp, dp, ip)
281 SCSI *scgp;
282 cdr_t *dp;
283 struct scsi_inquiry *ip;
284 {
285 Uchar mode[0x100];
286 struct cd_mode_page_2A *mp;
287 int profile;
288
289 if (ip->type != INQ_WORM && ip->type != INQ_ROMD)
290 return ((cdr_t *)0);
291
292 allow_atapi(scgp, TRUE); /* Try to switch to 10 byte mode cmds */
293
294 scgp->silent++;
295 mp = mmc_cap(scgp, mode); /* Get MMC capabilities */
296 scgp->silent--;
297 if (mp == NULL)
298 return (NULL); /* Pre SCSI-3/mmc drive */
299
300 /*
301 * At this point we know that we have a SCSI-3/mmc compliant drive.
302 * Unfortunately ATAPI drives violate the SCSI spec in returning
303 * a response data format of '1' which from the SCSI spec would
304 * tell us not to use the "PF" bit in mode select. As ATAPI drives
305 * require the "PF" bit to be set, we 'correct' the inquiry data.
306 *
307 * XXX xxx_identify() should not have any side_effects ??
308 */
309 if (ip->data_format < 2)
310 ip->data_format = 2;
311
312 profile = get_curprofile(scgp);
313 if (xdebug)
314 printf(_("Current profile: 0x%04X\n"), profile);
315
316 if (profile == 0x001A)
317 dp = &cdr_dvdplusrw;
318 if ((profile == 0x001B) || (profile == 0x002B))
319 dp = &cdr_dvdplusr;
320 #ifdef XX
321 if (!dvd) /* SCSI-3/mmc CD drive */
322 return (NULL);
323 #endif
324
325 return (dp);
326 }
327
328 LOCAL int
attach_dvdplus(scgp,dp)329 attach_dvdplus(scgp, dp)
330 SCSI *scgp;
331 cdr_t *dp;
332 {
333 Uchar mode[0x100];
334 struct cd_mode_page_2A *mp;
335 struct ricoh_mode_page_30 *rp = NULL;
336 Ulong xspeed;
337 Ulong mp2Aspeed;
338
339
340 allow_atapi(scgp, TRUE); /* Try to switch to 10 byte mode cmds */
341
342 scgp->silent++;
343 mp = mmc_cap(scgp, NULL); /* Get MMC capabilities in allocated mp */
344 scgp->silent--;
345 if (mp == NULL)
346 return (-1); /* Pre SCSI-3/mmc drive */
347
348 dp->cdr_cdcap = mp; /* Store MMC cap pointer */
349
350 /*
351 * XXX hier sollte drive max write speed & drive cur write speed
352 * XXX gesetzt werden.
353 */
354 dp->cdr_dstat->ds_dr_max_rspeed = a_to_u_2_byte(mp->max_read_speed)/1385;
355 if (dp->cdr_dstat->ds_dr_max_rspeed == 0)
356 dp->cdr_dstat->ds_dr_max_rspeed = 47;
357 dp->cdr_dstat->ds_dr_cur_rspeed = a_to_u_2_byte(mp->cur_read_speed)/1385;
358 if (dp->cdr_dstat->ds_dr_cur_rspeed == 0)
359 dp->cdr_dstat->ds_dr_cur_rspeed = 47;
360
361 dp->cdr_dstat->ds_dr_max_wspeed = a_to_u_2_byte(mp->max_write_speed)/1385;
362 if (mp->p_len >= 28)
363 dp->cdr_dstat->ds_dr_cur_wspeed = a_to_u_2_byte(mp->v3_cur_write_speed)/1385;
364 else
365 dp->cdr_dstat->ds_dr_cur_wspeed = a_to_u_2_byte(mp->cur_write_speed)/1385;
366
367 /*
368 * NEC drives incorrectly return CD speed values in mode page 2A.
369 * Try MMC3 get performance in hope that values closer to DVD speeds
370 * are always more correct than what is found in mode page 2A.
371 */
372 xspeed = 0;
373 scsi_get_perf_maxspeed(scgp, NULL, &xspeed, NULL);
374
375 mp2Aspeed = a_to_u_2_byte(mp->max_write_speed);
376
377 if (lverbose > 2) {
378 printf(_("max page 2A speed %lu (%lux), max perf speed %lu (%lux)\n"),
379 mp2Aspeed, mp2Aspeed/1385,
380 xspeed, xspeed/1385);
381 }
382
383 if ((is_cdspeed(mp2Aspeed) && !is_cdspeed(xspeed)) ||
384 (mp2Aspeed < 10000 && xspeed > 10000)) {
385 dp->cdr_dstat->ds_dr_max_wspeed = xspeed/1385;
386 xspeed = 0;
387 scsi_get_perf_curspeed(scgp, NULL, &xspeed, NULL);
388 if (xspeed > 0)
389 dp->cdr_dstat->ds_dr_cur_wspeed = xspeed / 1385;
390 }
391
392 if (dp->cdr_speedmax > dp->cdr_dstat->ds_dr_max_wspeed)
393 dp->cdr_speedmax = dp->cdr_dstat->ds_dr_max_wspeed;
394
395 if (dp->cdr_speeddef > dp->cdr_speedmax)
396 dp->cdr_speeddef = dp->cdr_speedmax;
397
398 rp = get_justlink_ricoh(scgp, mode);
399
400 if (mp->p_len >= 28)
401 dp->cdr_flags |= CDR_MMC3;
402 if (get_curprofile(scgp) >= 0)
403 dp->cdr_flags |= CDR_MMC3;
404 if (mp->p_len >= 24)
405 dp->cdr_flags |= CDR_MMC2;
406 dp->cdr_flags |= CDR_MMC;
407
408 if (mp->loading_type == LT_TRAY)
409 dp->cdr_flags |= CDR_TRAYLOAD;
410 else if (mp->loading_type == LT_CADDY)
411 dp->cdr_flags |= CDR_CADDYLOAD;
412
413 if (mp->BUF != 0)
414 dp->cdr_flags |= CDR_BURNFREE;
415
416 check_writemodes_mmc(scgp, dp);
417 /*
418 * To avoid that silly people try to call cdrecord will write modes
419 * that are illegal for DVDs, we clear anything that does now work.
420 */
421 dp->cdr_flags &= ~(CDR_RAW|CDR_RAW16|CDR_RAW96P|CDR_RAW96R|CDR_SRAW96P|CDR_SRAW96R);
422 dp->cdr_flags &= ~(CDR_TAO);
423
424 if (scgp->inq != NULL) {
425 if (strbeg("PIONEER", scgp->inq->inq_vendor_info)) {
426 if (strbeg("DVD-RW DVR-103", scgp->inq->inq_prod_ident) ||
427 strbeg("DVD-R DVD-R7322", scgp->inq->inq_prod_ident)) {
428 mp->BUF = 1;
429 }
430 }
431 }
432 if (mp->BUF != 0) {
433 dp->cdr_flags |= CDR_BURNFREE;
434 } else if (rp) {
435 if ((dp->cdr_cmdflags & F_DUMMY) && rp->TWBFS && rp->BUEFS)
436 dp->cdr_flags |= CDR_BURNFREE;
437
438 if (rp->BUEFS)
439 dp->cdr_flags |= CDR_BURNFREE;
440 }
441
442 if (rp && rp->AWSCS)
443 dp->cdr_flags |= CDR_FORCESPEED;
444
445
446 if ((dp->cdr_flags & (CDR_SAO)) != (CDR_SAO)) {
447 /*
448 * XXX Ist dies ueberhaupt noch notwendig seit wir nicht
449 * XXX mehr CDR_TAO vorgaukeln muessen?
450 *
451 * Das Panasonic DVD-R mag check_writemodes_mmc() nicht
452 * hilft das vielleicht?
453 */
454 dp->cdr_flags |= CDR_SAO;
455 }
456
457 if (driveropts != NULL) {
458 char *p;
459
460 if (strcmp(driveropts, "help") == 0) {
461 mmc_opthelp(scgp, dp, 0);
462 }
463
464 p = hasdrvopt(driveropts, "burnfree");
465 if (p == NULL)
466 p = hasdrvopt(driveropts, "burnproof");
467 if (p != NULL && (dp->cdr_flags & CDR_BURNFREE) != 0) {
468 if (*p == '1') {
469 dp->cdr_dstat->ds_cdrflags |= RF_BURNFREE;
470 } else if (*p == '0') {
471 dp->cdr_dstat->ds_cdrflags &= ~RF_BURNFREE;
472 }
473 }
474
475 p = hasdrvopt(driveropts, "forcespeed");
476 if (p != NULL && *p == '1' && (dp->cdr_flags & CDR_FORCESPEED) != 0) {
477 dp->cdr_dstat->ds_cdrflags |= RF_FORCESPEED;
478 }
479
480 p = hasdrvoptx(driveropts, "layerbreak", 0);
481 if (p != NULL) {
482 char *ep;
483 Llong ll;
484 Int32_t lb;
485
486 ep = astoll(p, &ll);
487 lb = ll;
488 if ((*ep != '\0' && *ep != ',') || *p == '\0' ||
489 ll <= 0 || ll != lb) {
490 errmsgno(EX_BAD,
491 _("Bad layer break value '%s'.\n"), p);
492 return (-1);
493 }
494 dp->cdr_dstat->ds_layer_break = lb;
495 }
496 if (dp->cdr_dstat->ds_layer_break >= 0 &&
497 get_curprofile(scgp) != 0x2B) {
498 errmsgno(EX_BAD,
499 _("Cannot set layer break on this drive/medium.\n"));
500 return (-1);
501 }
502 if (dp->cdr_dstat->ds_layer_break != -1 &&
503 dp->cdr_dstat->ds_layer_break !=
504 roundup(dp->cdr_dstat->ds_layer_break, 16)) {
505 errmsgno(EX_BAD,
506 _("Layer break at %d is not properly aligned.\n"),
507 dp->cdr_dstat->ds_layer_break);
508 return (-1);
509 }
510 }
511
512 /*
513 * Raise the default timeout.
514 * The first write takes a long time as it writes the lead in.
515 */
516 if (scgp->deftimeout < 100)
517 scg_settimeout(scgp, 100); /* 1:40 */
518
519
520 return (0);
521 }
522
523 LOCAL void
di_to_dstat(dip,dsp)524 di_to_dstat(dip, dsp)
525 struct disk_info *dip;
526 dstat_t *dsp;
527 {
528 dsp->ds_diskid = a_to_u_4_byte(dip->disk_id);
529
530 dsp->ds_flags |= DSF_NOCD|DSF_DVD; /* This is a DVD */
531
532 if (dip->did_v)
533 dsp->ds_flags |= DSF_DID_V;
534 dsp->ds_disktype = dip->disk_type;
535 dsp->ds_diskstat = dip->disk_status;
536 dsp->ds_sessstat = dip->sess_status;
537 if (dip->erasable)
538 dsp->ds_flags |= DSF_ERA;
539
540 dsp->ds_trfirst = dip->first_track;
541 dsp->ds_trlast = dip->last_track_ls;
542 dsp->ds_trfirst_ls = dip->first_track_ls;
543
544 #ifdef nono
545 /*
546 * On DVD systems, there is no lead out start time
547 * in the disk info because there is no time based data.
548 */
549 dsp->ds_maxblocks = msf_to_lba(dip->last_lead_out[1],
550 dip->last_lead_out[2],
551 dip->last_lead_out[3], TRUE);
552 #endif
553 }
554
555 LOCAL int
init_dvdplus(scgp,dp)556 init_dvdplus(scgp, dp)
557 SCSI *scgp;
558 cdr_t *dp;
559 {
560 return (speed_select_dvdplus(scgp, dp, NULL));
561 }
562
563 LOCAL int
getdisktype_dvdplus(scgp,dp)564 getdisktype_dvdplus(scgp, dp)
565 SCSI *scgp;
566 cdr_t *dp;
567 {
568 extern char *buf;
569 dstat_t *dsp = dp->cdr_dstat;
570 struct disk_info *dip;
571 Uchar mode[0x100];
572 struct rzone_info *rp;
573 struct dvd_structure_00 *sp;
574 int len;
575 BOOL did_dummy = FALSE;
576 BOOL did_reload = FALSE;
577 int profile;
578 Int32_t maxblocks;
579 Ulong end_lba;
580
581 /* if (lverbose > 0)*/
582 /* print_laserlog(scgp);*/
583
584 /* if (lverbose > 2)*/
585 /* print_logpages(scgp);*/
586
587
588 if (dsp->ds_type == DST_UNKNOWN) {
589 profile = get_curprofile(scgp);
590 if (profile >= 0)
591 dsp->ds_type = profile;
592 }
593
594 if ((dp->cdr_dstat->ds_cdrflags & RF_PRATIP) != 0) {
595 if (((dsp->ds_cdrflags & (RF_WRITE|RF_BLANK)) == 0) ||
596 lverbose > 1) {
597 extern void print_dvd_info __PR((SCSI *_scgp));
598
599 /*
600 * Das DVD Medieninfo ist so lang, da� wir es
601 * beim Schreiben mit -v noch nicht ausgeben.
602 */
603 print_dvd_info(scgp);
604 }
605 }
606
607 again:
608 dip = (struct disk_info *)buf;
609 if (get_diskinfo(scgp, dip, sizeof (*dip)) < 0)
610 return (-1);
611
612 /*
613 * Check for non writable disk first.
614 */
615 #ifdef DVDPLUS_DEBUG
616 error("DISK STATUS %X\n", dip->disk_status);
617 #endif
618 if (dip->disk_status == DS_COMPLETE &&
619 (dsp->ds_cdrflags & (RF_WRITE|RF_BLANK)) == RF_WRITE) {
620
621 profile = get_curprofile(scgp);
622 if (profile == 0x001A) { /* This is a DVD+RW */
623 if (dp->cdr_cmdflags & F_FIX)
624 return (0);
625 }
626
627
628 if (!did_dummy) {
629 int xspeed = 0xFFFF;
630 int oflags = dp->cdr_cmdflags;
631
632 /*
633 * Try to clear the dummy bit to reset the virtual
634 * drive status. Not all drives support it even though
635 * it is mentioned in the MMC standard.
636 */
637 if (lverbose)
638 printf(_("Trying to clear drive status.\n"));
639
640 dp->cdr_cmdflags &= ~F_DUMMY;
641 speed_select_dvdplus(scgp, dp, &xspeed);
642 dp->cdr_cmdflags = oflags;
643 scgp->silent++;
644 rezero_unit(scgp);
645 scgp->silent--;
646 did_dummy = TRUE;
647 goto again;
648 }
649 if (!did_reload && profile == 0x001A) { /* This is a DVD+RW */
650 scgp->silent++;
651 len = read_scsi(scgp, buf, 0, 1);
652 scgp->silent--;
653 if (len < 0) {
654 /*
655 * DVD+RW "complete" but unreadable
656 * Trying to clear drive status did not work...
657 * This happens if the DVD+RW media was erased
658 * by the Ricoh Vendor Unique command
659 */
660 reload_media(scgp, dp);
661 did_reload = TRUE;
662 goto again;
663 }
664 }
665 /*
666 * Trying to clear drive status did not work...
667 * XXX This most likely makes no sense with DVD+R
668 */
669 /* reload_media(scgp, dp);*/
670 }
671 if (get_diskinfo(scgp, dip, sizeof (*dip)) < 0)
672 return (-1);
673 di_to_dstat(dip, dsp);
674
675 #ifdef DVDPLUS_DEBUG
676 error("dtype %d era %d sess stat %d disk stat %d\n",
677 dip->dtype,
678 dip->erasable,
679 dip->sess_status,
680 dip->disk_status);
681 error("Dirty %d Format status %d\n", dip->dbit, dip->bg_format_stat);
682 error("disk type %X\n",
683 dip->disk_type);
684 {
685 long nwa = -1;
686
687 next_wr_addr_dvdplusr(scgp, (track_t *)NULL, &nwa);
688 error("NWA: %ld\n", nwa);
689 }
690 #endif
691
692
693 profile = get_curprofile(scgp);
694 if (profile == 0x001A) {
695 dsp->ds_flags |= DSF_DVD_PLUS_RW; /* This is a DVD+RW */
696 if (dip->disk_status == DS_EMPTY) { /* Unformatted */
697 if (dip->disk_type != SES_UNDEF) { /* Not a CD */
698 printf(_("WARNING: Drive returns illegal Disk type %s.\n"),
699 get_ses_type(dip->disk_type));
700 }
701 dsp->ds_flags |= DSF_NEED_FORMAT;
702 if ((dp->cdr_dstat->ds_cdrflags & RF_PRATIP) != 0)
703 print_format_capacities(scgp);
704 return (0);
705 }
706 } else if (profile == 0x001B) {
707 dsp->ds_flags |= DSF_DVD_PLUS_R; /* This is a DVD+R */
708 }
709 #ifdef DVDPLUS_DEBUG
710 error("profile %X dsp->ds_flags 0x%X\n", profile, dsp->ds_flags);
711 #endif
712
713 /*
714 * This information is based on a logical recording zone
715 * and may not always be correct.
716 * XXX Check this if we want to support anything else but
717 * XXX one data track on DAO mode. The current firmware
718 * XXX of the recorder supports only this method but future
719 * XXX releases may support more.
720 */
721 fillbytes((caddr_t)mode, sizeof (mode), '\0');
722 rp = (struct rzone_info *)mode;
723 read_rzone_info(scgp, (caddr_t)rp, sizeof (struct rzone_info));
724
725 if ((dp->cdr_dstat->ds_cdrflags & RF_PRATIP) != 0) {
726 if (((dsp->ds_cdrflags & (RF_WRITE|RF_BLANK)) == 0) ||
727 lverbose > 1) {
728 przone(rp);
729 print_format_capacities(scgp);
730 }
731 }
732 #define needed_for_pioneer_a06
733 #ifdef needed_for_pioneer_a06
734 /*
735 * Old code used with the S101 seems to be needed for DVD+RW
736 * and the Pioneer A06 if the medium is not yet fully formatted.
737 */
738 dsp->ds_maxblocks = a_to_u_4_byte(rp->rzone_size);
739 #ifdef DVDPLUS_DEBUG
740 error("MAXBLO %d from rzone size\n", dsp->ds_maxblocks);
741 #endif
742 if (dsp->ds_maxblocks == 0)
743 #endif
744 dsp->ds_maxblocks = a_to_u_4_byte(rp->free_blocks);
745 #ifdef DVDPLUS_DEBUG
746 error("MAXBLO %d\n", dsp->ds_maxblocks);
747 error("MAXBLO %d from free_blocks\n", (int)a_to_u_4_byte(rp->free_blocks));
748 #endif
749 if (rp->nwa_v)
750 dsp->ds_maxblocks += a_to_u_4_byte(rp->next_recordable_addr);
751 #ifdef DVDPLUS_DEBUG
752 error("NWAv %d Next rec addr %d\n", rp->nwa_v, (int)a_to_u_4_byte(rp->next_recordable_addr));
753 #endif
754 maxblocks = dsp->ds_maxblocks;
755
756 /*
757 * XXX this was: if (dip->disk_status == DS_EMPTY)
758 * The '_NEC ' 'DVD_RW ND-3500AG' may return written DVD+RW with
759 * status DS_COMPLETE although they may be overwritten.
760 */
761 if (dip->disk_status == DS_COMPLETE && profile != 0x001A)
762 return (drive_getdisktype(scgp, dp));
763
764 /*
765 * This information is based on the physical pre recorded information.
766 * First try to find the len supported by the actual drive.
767 */
768 fillbytes((caddr_t)mode, sizeof (mode), '\0');
769 scgp->silent++;
770 if (read_dvd_structure(scgp, (caddr_t)mode, 2, 0, 0, 0, 0) < 0) {
771 scgp->silent--;
772 if (lverbose > 2)
773 errmsgno(EX_BAD, _("Cannot read DVD structure 00.\n"));
774 return (drive_getdisktype(scgp, dp));
775 }
776 scgp->silent--;
777 len = a_to_u_2_byte(mode);
778 len += 2; /* Data len is not included */
779
780 if (len > sizeof (struct dvd_structure_00)) {
781 len = sizeof (struct dvd_structure_00);
782 /*
783 * The ACARD TECH AEC-7720 ATAPI<->SCSI adaptor
784 * chokes if we try to transfer odd byte counts (rounds up to
785 * even byte counts and thus causes a DMA overflow and a
786 * bus reset), so make the byte count even.
787 */
788 len += 1;
789 len &= ~1;
790 }
791 fillbytes((caddr_t)mode, sizeof (mode), '\0');
792 sp = (struct dvd_structure_00 *)mode;
793 if (read_dvd_structure(scgp, (caddr_t)sp, len, 0, 0, 0, 0) < 0)
794 return (drive_getdisktype(scgp, dp));
795
796 /* if (lverbose > 1)*/
797 /* print_dvd00(sp);*/
798 /*
799 * Bei Pioneer ist Phys End ist nur bei dem S101 != 0.
800 * Bei Panasonic ist Phys End == Phys Start.
801 */
802 if ((profile != 0x001A) &&
803 (dp->cdr_cmdflags & F_MSINFO) == 0 &&
804 (a_to_u_3_byte(sp->phys_end) != 0) &&
805 (dsp->ds_maxblocks !=
806 (long)(a_to_u_3_byte(sp->phys_end) - a_to_u_3_byte(sp->phys_start) + 1))) {
807 #ifdef __nonono__
808 printf("WARNING: Phys disk size %ld differs from rzone size %ld! Prerecorded disk?\n",
809 (long)(a_to_u_3_byte(sp->phys_end) - a_to_u_3_byte(sp->phys_start) + 1),
810 (long)dsp->ds_maxblocks);
811 printf("WARNING: Phys start: %ld Phys end %ld\n",
812 (long)a_to_u_3_byte(sp->phys_start),
813 (long)a_to_u_3_byte(sp->phys_end));
814 #endif
815 /*
816 * Workaround for some drive media combinations.
817 * At least the drive 'HL-DT-ST' 'DVD-RAM GH22NP20' '1.02'
818 * does not report maxblocks correctly with 'CMC MAG' 'M01'
819 * DVD+R media.
820 * Use the information from ADIP instead.
821 */
822 #ifdef DVDPLUS_DEBUG
823 error("MAXBLOx1 %d\n", dsp->ds_maxblocks);
824 #endif
825 if ((long)dsp->ds_maxblocks == 0) {
826 printf(_("WARNING: Drive returns zero media size. Using media size from ADIP.\n"));
827 dsp->ds_maxblocks = a_to_u_3_byte(sp->phys_end) - a_to_u_3_byte(sp->phys_start) + 1;
828 }
829 }
830 #ifdef DVDPLUS_DEBUG
831 error("MAXBLOx %d\n", dsp->ds_maxblocks);
832 error("phys start %d phys end %d\n", a_to_u_3_byte(sp->phys_start), a_to_u_3_byte(sp->phys_end));
833 error("MAXBLO %d from phys end - phys start\n", (int)(a_to_u_3_byte(sp->phys_end) - a_to_u_3_byte(sp->phys_start) + 1));
834 #endif
835
836 end_lba = 0L;
837 scsi_get_perf_maxspeed(scgp, (Ulong *)NULL, (Ulong *)NULL, &end_lba);
838 #ifdef DVDPLUS_DEBUG
839 error("end_lba: %lu\n", end_lba);
840 #endif
841 /*
842 * XXX Note that end_lba is unsigned and dsp->ds_maxblocks is signed.
843 */
844 if ((Int32_t)end_lba > dsp->ds_maxblocks) {
845 if (maxblocks == 0)
846 printf(_("WARNING: Drive returns zero media size, correcting.\n"));
847 dsp->ds_maxblocks = end_lba + 1;
848 }
849
850 return (drive_getdisktype(scgp, dp));
851 }
852
853 LOCAL int
prdiskstatus_dvdplus(scgp,dp)854 prdiskstatus_dvdplus(scgp, dp)
855 SCSI *scgp;
856 cdr_t *dp;
857 {
858 return (prdiskstatus(scgp, dp, FALSE));
859 }
860
861
862 LOCAL int
speed_select_dvdplus(scgp,dp,speedp)863 speed_select_dvdplus(scgp, dp, speedp)
864 SCSI *scgp;
865 cdr_t *dp;
866 int *speedp;
867 {
868 Uchar mode[0x100];
869 Uchar moder[0x100];
870 int len;
871 struct cd_mode_page_05 *mp;
872 struct ricoh_mode_page_30 *rp = NULL;
873 int val;
874 Ulong ul;
875 BOOL forcespeed = FALSE;
876 BOOL dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
877 int curspeed = 1;
878
879 if (speedp)
880 curspeed = *speedp;
881
882 fillbytes((caddr_t)mode, sizeof (mode), '\0');
883
884 if (!get_mode_params(scgp, 0x05, _("CD write parameter"),
885 mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
886 return (-1);
887 if (len == 0)
888 return (-1);
889
890 mp = (struct cd_mode_page_05 *)
891 (mode + sizeof (struct scsi_mode_header) +
892 ((struct scsi_mode_header *)mode)->blockdesc_len);
893 #ifdef DEBUG
894 if (lverbose > 1)
895 scg_prbytes("CD write parameter:", (Uchar *)mode, len);
896 #endif
897
898
899 if (dummy != 0) {
900 errmsgno(EX_BAD, _("DVD+R/DVD+RW has no -dummy mode.\n"));
901 return (-1);
902 }
903 if (get_curprofile(scgp) == 0x001A) { /* This is a DVD+RW */
904 if (dp->cdr_cmdflags & F_FIX)
905 return (0);
906 }
907 mp->test_write = dummy != 0;
908 /*
909 * Set default values:
910 * Write type = 02 (disk at once)
911 * Track mode = 00 Reserved on Pioneer DVR-S101
912 * Data block type = 00 Reserved on Pioneer DVR-S101
913 * Session format = 00 Reserved on Pioneer DVR-S101
914 * XXX DVR-S101 uses ls_v and link size violating
915 * XXX the current MMC2 spec.
916 */
917 mp->write_type = WT_SAO;
918
919 #ifdef DEBUG
920 if (lverbose > 1)
921 scg_prbytes("CD write parameter:", (Uchar *)mode, len);
922 #endif
923 if (!set_mode_params(scgp, _("CD write parameter"), mode, len, 0, -1)) {
924 return (-1);
925 }
926
927 /*
928 * Neither set nor get speed.
929 */
930 if (speedp == 0)
931 return (0);
932
933
934 rp = get_justlink_ricoh(scgp, moder);
935 if ((dp->cdr_flags & CDR_FORCESPEED) != 0) {
936 forcespeed = rp && rp->AWSCD != 0;
937 }
938
939 if (lverbose && (dp->cdr_flags & CDR_FORCESPEED) != 0)
940 printf(_("Forcespeed is %s.\n"), forcespeed?_("ON"):_("OFF"));
941
942 if (!forcespeed && (dp->cdr_dstat->ds_cdrflags & RF_FORCESPEED) != 0) {
943 printf(_("Turning forcespeed on\n"));
944 forcespeed = TRUE;
945 }
946 if (forcespeed && (dp->cdr_dstat->ds_cdrflags & RF_FORCESPEED) == 0) {
947 printf(_("Turning forcespeed off\n"));
948 forcespeed = FALSE;
949 }
950 if ((dp->cdr_flags & CDR_FORCESPEED) != 0) {
951
952 if (rp) {
953 rp->AWSCD = forcespeed?1:0;
954 set_mode_params(scgp, _("Ricoh Vendor Page"), moder, moder[0]+1, 0, -1);
955 rp = get_justlink_ricoh(scgp, moder);
956 }
957 }
958
959 /*
960 * DVD single speed is 1385 kB/s
961 * Rounding down is guaranteed.
962 */
963 val = curspeed*1390;
964 if (val > 0x7FFFFFFF)
965 val = 0x7FFFFFFF;
966 if (dp->cdr_flags & CDR_MMC3) {
967 if (speed_select_mdvd(scgp, -1, val) < 0)
968 errmsgno(EX_BAD, _("MMC-3 speed select did not work.\n"));
969 } else {
970 if (val > 0xFFFF)
971 val = 0xFFFF;
972 scgp->silent++;
973 if (scsi_set_speed(scgp, -1, val, ROTCTL_CLV) < 0) {
974 /*
975 * Don't complain if it does not work,
976 * DVD drives may not have speed setting.
977 * The DVR-S101 and the DVR-S201 difinitely
978 * don't allow to set the speed.
979 */
980 }
981 scgp->silent--;
982 }
983
984 scgp->silent++;
985 if (scsi_get_speed(scgp, 0, &val) >= 0) {
986 if (val > 0) {
987 curspeed = val / 1385;
988 *speedp = curspeed;
989 }
990 }
991 /*
992 * NEC drives incorrectly return CD speed values in mode page 2A.
993 * Try MMC3 get performance in hope that values closer to DVD speeds
994 * are always more correct than what is found in mode page 2A.
995 */
996 ul = 0;
997 if (scsi_get_perf_curspeed(scgp, NULL, &ul, NULL) >= 0) {
998 if (is_cdspeed(val) && !is_cdspeed(ul)) {
999 curspeed = ul / 1385;
1000 *speedp = curspeed;
1001 }
1002 }
1003 scgp->silent--;
1004 return (0);
1005 }
1006 /*--------------------------------------------------------------------------*/
1007
1008 LOCAL long dvd_next_addr;
1009
1010 LOCAL int
next_wr_addr_dvdplusrw(scgp,trackp,ap)1011 next_wr_addr_dvdplusrw(scgp, trackp, ap)
1012 SCSI *scgp;
1013 track_t *trackp;
1014 long *ap;
1015 {
1016 if (trackp == 0 || trackp->track <= 1) {
1017 dvd_next_addr = 0;
1018 }
1019 if (ap)
1020 *ap = dvd_next_addr;
1021 return (0);
1022 }
1023
1024 LOCAL int
next_wr_addr_dvdplusr(scgp,trackp,ap)1025 next_wr_addr_dvdplusr(scgp, trackp, ap)
1026 SCSI *scgp;
1027 track_t *trackp;
1028 long *ap;
1029 {
1030 struct disk_info di;
1031 struct rzone_info rz;
1032 int tracks;
1033 long next_addr = -1;
1034
1035 if (trackp == 0) {
1036 fillbytes((caddr_t)&di, sizeof (di), '\0');
1037 if (get_diskinfo(scgp, &di, sizeof (di)) < 0)
1038 return (-1);
1039
1040 tracks = di.last_track_ls + di.last_track_ls_msb * 256;
1041 fillbytes((caddr_t)&rz, sizeof (rz), '\0');
1042 if (get_trackinfo(scgp, (caddr_t)&rz, TI_TYPE_TRACK, tracks, sizeof (rz)) < 0)
1043 return (-1);
1044 if (!rz.nwa_v)
1045 return (-1);
1046 next_addr = a_to_4_byte(rz.next_recordable_addr);
1047 if (ap)
1048 *ap = next_addr;
1049 return (0);
1050 }
1051 if (trackp->track <= 1) {
1052 /*
1053 * XXX This is a workaround for the filesize > 2GB problem.
1054 * XXX Check this if we support more than one track DAO
1055 * XXX or if we give up this hack in favour of real 64bit
1056 * XXX filesize support.
1057 */
1058 fillbytes((caddr_t)&rz, sizeof (rz), '\0');
1059 read_rzone_info(scgp, (caddr_t)&rz, sizeof (struct rzone_info));
1060 dvd_next_addr = a_to_4_byte(rz.next_recordable_addr);
1061 #ifdef DVDPLUS_DEBUG
1062 error("NWA: %ld valid: %d\n", dvd_next_addr, rz.nwa_v);
1063 #endif
1064 if (lverbose > 1)
1065 printf(_("next writable addr: %ld valid: %d\n"), dvd_next_addr, rz.nwa_v);
1066 }
1067 if (ap)
1068 *ap = dvd_next_addr;
1069 return (0);
1070 }
1071
1072 LOCAL int
open_track_dvdplus(scgp,dp,trackp)1073 open_track_dvdplus(scgp, dp, trackp)
1074 SCSI *scgp;
1075 cdr_t *dp;
1076 track_t *trackp;
1077 {
1078 Uchar mode[0x100];
1079 int len;
1080 long sectors;
1081 struct cd_mode_page_05 *mp;
1082 int profile;
1083
1084 if (trackp->track > 1) /* XXX Hack to make one 'track' from several */
1085 return (0); /* XXX files in Disk at once mode only. */
1086
1087 fillbytes((caddr_t)mode, sizeof (mode), '\0');
1088
1089 if (!get_mode_params(scgp, 0x05, _("CD write parameter"),
1090 mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
1091 return (-1);
1092 if (len == 0)
1093 return (-1);
1094
1095 mp = (struct cd_mode_page_05 *)
1096 (mode + sizeof (struct scsi_mode_header) +
1097 ((struct scsi_mode_header *)mode)->blockdesc_len);
1098
1099 /*
1100 * XXX as long as the Pioneer DVR-S101 only supports a single
1101 * XXX data track in DAO mode,
1102 * XXX do not set:
1103 * XXX track_mode
1104 * XXX copy
1105 * XXX dbtype
1106 *
1107 * Track mode = 00 Reserved on Pioneer DVR-S101
1108 * Data block type = 00 Reserved on Pioneer DVR-S101
1109 * Session format = 00 Reserved on Pioneer DVR-S101
1110 * XXX DVR-S101 uses ls_v and link size violating
1111 * XXX the current MMC2 spec.
1112 */
1113 /* XXX look into drv_mmc.c for re-integration of above settings */
1114
1115 #ifdef DEBUG
1116 if (lverbose > 1)
1117 scg_prbytes("CD write parameter:", (Uchar *)mode, len);
1118 #endif
1119 if (!set_mode_params(scgp, _("CD write parameter"), mode, len, 0, trackp->secsize))
1120 return (-1);
1121
1122 /*
1123 * Compile vitual track list
1124 */
1125 sectors = rzone_size(trackp);
1126 #ifdef __needed_for_dvdplus__
1127 if (sectors < 0)
1128 return (-1);
1129 #endif
1130 profile = get_curprofile(scgp);
1131 if (profile == 0x2B) {
1132 if (set_p_layerbreak(scgp, sectors,
1133 dp->cdr_dstat->ds_layer_break) < 0) {
1134 return (-1);
1135 }
1136 }
1137 #ifdef __needed_for_dvdplus__
1138 return (reserve_tr_rzone(scgp, sectors));
1139 #else
1140 return (0);
1141 #endif
1142 }
1143
1144 /*
1145 * XXX rzone_size(trackp) mu� aufgerufen werden, daher mu�
1146 * XXX auch f�r DVD+RW eine non-dummy open_track() Funktion da sein.
1147 */
1148 /*
1149 * XXX Hack to make one 'track' from several
1150 * XXX files in Disk at once mode only.
1151 * XXX Calculate track size and reserve rzone.
1152 */
1153 LOCAL long
rzone_size(trackp)1154 rzone_size(trackp)
1155 track_t *trackp; /* Called with &track[1] */
1156 {
1157 int i;
1158 BOOL vtracks = FALSE;
1159 long sectors = 0L;
1160 Llong ttrsize = 0L;
1161 Llong tamount = 0L;
1162 Llong amount;
1163 long secsize = trackp->secsize;
1164
1165 for (i = 0; i < MAX_TRACK; i++) {
1166 if (is_last(&trackp[i]))
1167 break;
1168 }
1169 if (i >= 1)
1170 vtracks = TRUE;
1171 if (vtracks && lverbose)
1172 printf(_("Compiling virtual track list ...\n"));
1173
1174 for (i = 0; i < MAX_TRACK; i++) {
1175 if (trackp[i].tracksize < (tsize_t)0) {
1176 errmsgno(EX_BAD, _("VTrack %d has unknown length.\n"), i);
1177 return (-1);
1178 }
1179 amount = roundup(trackp[i].tracksize, secsize);
1180 amount += (Llong)trackp[i].padsecs * secsize;
1181 sectors += amount/secsize;
1182 ttrsize += trackp[i].tracksize;
1183 tamount += amount;
1184 if (vtracks && lverbose)
1185 printf(_("Vtrack: %d size: %lld bytes %lld rounded (%lld sectors)\n"),
1186 (int)trackp[i].track, (Llong)trackp[i].tracksize,
1187 amount, amount / (Llong)secsize);
1188
1189 if (is_last(&trackp[i]))
1190 break;
1191
1192 /*
1193 * XXX Is it possible for a DVD that input sector size
1194 * XXX differes from output sector size?
1195 * XXX I believe that not.
1196 */
1197 if (trackp[i].tracksize % secsize) {
1198 comerrno(EX_BAD, _("Virtual track %d is not a multiple of secsize.\n"), (int)trackp[i].track);
1199 }
1200 }
1201
1202 if (vtracks && lverbose)
1203 printf(_("Vtracks: %d size: %lld bytes %lld rounded (%ld sectors) total\n"),
1204 i+1, ttrsize, tamount, sectors);
1205
1206 return (sectors);
1207 }
1208
1209 LOCAL int
close_track_dvdplus(scgp,dp,trackp)1210 close_track_dvdplus(scgp, dp, trackp)
1211 SCSI *scgp;
1212 cdr_t *dp;
1213 track_t *trackp;
1214 {
1215 long sectors = 0L;
1216 Llong amount;
1217 long secsize = trackp->secsize;
1218
1219 /*
1220 * Compute the start of the next "track" for the hack
1221 * that allows to have a track in more than one file.
1222 * XXX Check this if the vtrack code is removed.
1223 */
1224 amount = roundup(trackp->tracksize, secsize);
1225 amount += (Llong)trackp->padsecs * secsize;
1226 sectors += amount/secsize;
1227
1228 dvd_next_addr += sectors;
1229
1230 return (0);
1231 }
1232
1233 #ifdef __needed_for_dvd_plusr__
1234 LOCAL int
open_session_dvd(scgp,dp,trackp)1235 open_session_dvd(scgp, dp, trackp)
1236 SCSI *scgp;
1237 cdr_t *dp;
1238 track_t *trackp;
1239 {
1240 Uchar mode[0x100];
1241 Uchar moder[0x100];
1242 int len;
1243 struct cd_mode_page_05 *mp;
1244 struct ricoh_mode_page_30 *rp = NULL;
1245 BOOL burnfree = FALSE;
1246
1247 fillbytes((caddr_t)mode, sizeof (mode), '\0');
1248
1249 if (!get_mode_params(scgp, 0x05, _("CD write parameter"),
1250 mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
1251 return (-1);
1252 if (len == 0)
1253 return (-1);
1254
1255 mp = (struct cd_mode_page_05 *)
1256 (mode + sizeof (struct scsi_mode_header) +
1257 ((struct scsi_mode_header *)mode)->blockdesc_len);
1258
1259 /*
1260 * XXX as long as the Pioneer DVR-S101 only supports a single
1261 * XXX data track in DAO mode,
1262 * XXX do not set:
1263 * XXX multi_session
1264 * XXX sessipon_format
1265 *
1266 * Track mode = 00 Reserved on Pioneer DVR-S101
1267 * Data block type = 00 Reserved on Pioneer DVR-S101
1268 * Session format = 00 Reserved on Pioneer DVR-S101
1269 * XXX DVR-S101 uses ls_v and link size violating
1270 * XXX the current MMC2 spec.
1271 */
1272 /* XXX look into drv_mmc.c for re-integration of above settings */
1273 mp->write_type = WT_SAO;
1274
1275
1276 rp = get_justlink_ricoh(scgp, moder);
1277
1278 if (dp->cdr_cdcap->BUF != 0) {
1279 burnfree = mp->BUFE != 0;
1280 } else if ((dp->cdr_flags & CDR_BURNFREE) != 0) {
1281 burnfree = rp && rp->BUEFE != 0;
1282 }
1283
1284 if (lverbose && (dp->cdr_flags & CDR_BURNFREE) != 0)
1285 printf(_("BURN-Free is %s.\n"), burnfree?_("ON"):_("OFF"));
1286
1287 if (!burnfree && (dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) != 0) {
1288 printf(_("Turning BURN-Free on\n"));
1289 burnfree = TRUE;
1290 }
1291 if (burnfree && (dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) == 0) {
1292 printf(_("Turning BURN-Free off\n"));
1293 burnfree = FALSE;
1294 }
1295 if (dp->cdr_cdcap->BUF != 0) {
1296 mp->BUFE = burnfree?1:0;
1297 } else if ((dp->cdr_flags & CDR_BURNFREE) != 0) {
1298
1299 if (rp)
1300 rp->BUEFE = burnfree?1:0;
1301 }
1302 if (rp) {
1303 i_to_2_byte(rp->link_counter, 0);
1304 if (xdebug)
1305 scg_prbytes(_("Mode Select Data "), moder, moder[0]+1);
1306
1307 set_mode_params(scgp, _("Ricoh Vendor Page"), moder, moder[0]+1, 0, -1);
1308 rp = get_justlink_ricoh(scgp, moder);
1309 }
1310
1311 #ifdef DEBUG
1312 if (lverbose > 1)
1313 scg_prbytes("CD write parameter:", (Uchar *)mode, len);
1314 #endif
1315 if (!set_mode_params(scgp, _("CD write parameter"), mode, len, 0, -1))
1316 return (-1);
1317
1318 return (0);
1319 }
1320 #endif
1321
1322 /*
1323 * We need to loop here because of a firmware bug in Pioneer DVD writers.
1324 */
1325 LOCAL int
fixate_dvdplusrw(scgp,dp,trackp)1326 fixate_dvdplusrw(scgp, dp, trackp)
1327 SCSI *scgp;
1328 cdr_t *dp;
1329 track_t *trackp;
1330 {
1331 int oldtimeout = scgp->deftimeout;
1332 int ret = 0;
1333 int i;
1334 #define MAX_TRIES 15
1335
1336 /*
1337 * XXX Is this timeout needed for DVD+RW too?
1338 * XXX It was introduced for DVD-R that writes at least 800 MB
1339 */
1340 if (scgp->deftimeout < 1000)
1341 scg_settimeout(scgp, 1000);
1342
1343 /*scgp->verbose++;*/
1344 scgp->silent++;
1345 for (i = 0; i <= MAX_TRIES; i++) {
1346 if (scsi_flush_cache(scgp, TRUE) < 0) {
1347 if (!scsi_in_progress(scgp) || i >= MAX_TRIES) {
1348 if (scgp->verbose <= 0) {
1349 scg_printerr(scgp);
1350 scg_printresult(scgp); /* XXX restore key/code in future */
1351 }
1352 printf(_("Trouble flushing the cache\n"));
1353 scgp->silent--;
1354 scg_settimeout(scgp, oldtimeout);
1355 return (-1);
1356 }
1357 sleep(1);
1358 } else {
1359 break;
1360 }
1361 }
1362 scgp->silent--;
1363 waitformat(scgp, 300);
1364
1365 scgp->silent++;
1366 for (i = 0; i <= MAX_TRIES; i++) {
1367 if (scsi_close_tr_session(scgp, CL_TYPE_SESSION, 0, TRUE) < 0) {
1368 if (!scsi_in_progress(scgp) || i >= MAX_TRIES) {
1369 if (scgp->verbose <= 0) {
1370 scg_printerr(scgp);
1371 scg_printresult(scgp); /* XXX restore key/code in future */
1372 }
1373 printf(_("Trouble closing the session\n"));
1374 break;
1375 }
1376 sleep(1);
1377 } else {
1378 break;
1379 }
1380 }
1381 scgp->silent--;
1382 waitformat(scgp, 300);
1383 /*scgp->verbose--;*/
1384
1385 scg_settimeout(scgp, oldtimeout);
1386 return (ret);
1387 #undef MAX_TRIES
1388 }
1389
1390
1391 LOCAL int
fixate_dvdplusr(scgp,dp,trackp)1392 fixate_dvdplusr(scgp, dp, trackp)
1393 SCSI *scgp;
1394 cdr_t *dp;
1395 track_t *trackp;
1396 {
1397 int oldtimeout = scgp->deftimeout;
1398 int ret = 0;
1399 int key = 0;
1400 int code = 0;
1401 int trackno;
1402 int i;
1403 #define MAX_TRIES 15
1404
1405 /*
1406 * XXX Is this timeout needed for DVD+R too?
1407 * XXX It was introduced for DVD-R that writes at least 800 MB
1408 */
1409 if (scgp->deftimeout < 1000)
1410 scg_settimeout(scgp, 1000);
1411
1412 /*scgp->verbose++;*/
1413 scgp->silent++;
1414 for (i = 0; i <= MAX_TRIES; i++) {
1415 if (scsi_flush_cache(scgp, TRUE) < 0) {
1416 if (!scsi_in_progress(scgp) || i >= MAX_TRIES) {
1417 if (scgp->verbose <= 0) {
1418 scg_printerr(scgp);
1419 scg_printresult(scgp); /* XXX restore key/code in future */
1420 }
1421 printf(_("Trouble flushing the cache\n"));
1422 scgp->silent--;
1423 scg_settimeout(scgp, oldtimeout);
1424 return (-1);
1425 }
1426 sleep(1);
1427 } else {
1428 break;
1429 }
1430 }
1431 scgp->silent--;
1432 key = scg_sense_key(scgp);
1433 code = scg_sense_code(scgp);
1434 waitformat(scgp, 600);
1435 /*
1436 * With CDs we used to close the invisible track (0xFF) but
1437 * with DVDs this may not work anymore if the unit is MMC-3
1438 * or above. Use the real track/border number instead.
1439 * We always use the "IMMED" flag - is this OK?
1440 */
1441 trackno = trackp->trackno;
1442 if (trackno <= 0)
1443 trackno = 1;
1444 scgp->silent++;
1445 for (i = 0; i <= MAX_TRIES; i++) {
1446 if (scsi_close_tr_session(scgp, CL_TYPE_TRACK, trackno, TRUE) < 0) {
1447 if (!scsi_in_progress(scgp) || i >= MAX_TRIES) {
1448 if (scgp->verbose <= 0) {
1449 scg_printerr(scgp);
1450 scg_printresult(scgp); /* XXX restore key/code in future */
1451 }
1452 printf(_("Trouble closing the track\n"));
1453 break;
1454 }
1455 sleep(1);
1456 } else {
1457 break;
1458 }
1459 }
1460 scgp->silent--;
1461 key = scg_sense_key(scgp);
1462 code = scg_sense_code(scgp);
1463 waitformat(scgp, 600);
1464
1465 scgp->silent++;
1466 for (i = 0; i <= MAX_TRIES; i++) {
1467 if (scsi_close_tr_session(scgp, 0x06, 0, TRUE) < 0) {
1468 if (!scsi_in_progress(scgp) || i >= MAX_TRIES) {
1469 if (scgp->verbose <= 0) {
1470 scg_printerr(scgp);
1471 scg_printresult(scgp); /* XXX restore key/code in future */
1472 }
1473 printf(_("Trouble closing the last session\n"));
1474 break;
1475 }
1476 sleep(1);
1477 } else {
1478 break;
1479 }
1480 }
1481 scgp->silent--;
1482 key = scg_sense_key(scgp);
1483 code = scg_sense_code(scgp);
1484 waitformat(scgp, 600);
1485 /*scgp->verbose--;*/
1486
1487 scg_settimeout(scgp, oldtimeout);
1488 return (ret);
1489 #undef MAX_TRIES
1490 }
1491
1492
1493 /*--------------------------------------------------------------------------*/
1494
1495 LOCAL BOOL
dvdplus_ricohbased(scgp)1496 dvdplus_ricohbased(scgp)
1497 SCSI *scgp;
1498 {
1499 if (scgp->inq == NULL)
1500 return (FALSE);
1501
1502 if (strncmp(scgp->inq->inq_vendor_info, "RICOH", 5) == 0) {
1503 if (strbeg("DVD+RW MP5120", scgp->inq->inq_prod_ident) ||
1504 strbeg("DVD+RW MP5125", scgp->inq->inq_prod_ident))
1505 return (TRUE);
1506 }
1507 if (strncmp(scgp->inq->inq_vendor_info, "HP", 2) == 0) {
1508 if (strbeg("DVD Writer 100j", scgp->inq->inq_prod_ident) ||
1509 strbeg("DVD Writer 200j", scgp->inq->inq_prod_ident))
1510 return (TRUE);
1511 }
1512 return (FALSE);
1513 }
1514
1515 LOCAL int
blank_dvdplus(scgp,dp,addr,blanktype)1516 blank_dvdplus(scgp, dp, addr, blanktype)
1517 SCSI *scgp;
1518 cdr_t *dp;
1519 long addr;
1520 int blanktype;
1521 {
1522 /*XXX*/extern char *blank_types[];
1523
1524 BOOL cdrr = FALSE; /* Read CD-R */
1525 BOOL cdwr = FALSE; /* Write CD-R */
1526 BOOL cdrrw = FALSE; /* Read CD-RW */
1527 BOOL cdwrw = FALSE; /* Write CD-RW */
1528 BOOL dvdwr = FALSE; /* DVD writer */
1529 int profile;
1530
1531 int flags = DC_ERASE;
1532 int blanksize = 0x30000;
1533 int ret;
1534
1535 mmc_check(scgp, &cdrr, &cdwr, &cdrrw, &cdwrw, NULL, &dvdwr);
1536
1537 profile = get_curprofile(scgp);
1538 /*
1539 * XXX How to check for DVD drives that support DVD-RW
1540 */
1541 /* if (!dvdwr)*/
1542 /* return (blank_dummy(scgp, dp, addr, blanktype));*/
1543
1544 if (!dvdplus_ricohbased(scgp)) {
1545 errmsgno(EX_BAD, _("Cannot blank DVD+RW media with non Ricoh based drive.\n"));
1546 if (profile == 0x1A || profile == 0x2A) {
1547 ret = blank_simul(scgp, dp, addr, blanktype);
1548 waitformat(scgp, 600);
1549 scsi_flush_cache(scgp, TRUE);
1550 waitformat(scgp, 600);
1551 return (ret);
1552 }
1553 return (-1);
1554 }
1555
1556
1557 if (blanktype == BLANK_DISC) {
1558 blanksize = 0x26c090;
1559 } else {
1560 blanktype = BLANK_MINIMAL;
1561 blanksize = 0x30000;
1562 }
1563 if (lverbose) {
1564 printf(_("Blanking %s\n"), blank_types[blanktype & 0x07]);
1565 flush();
1566 }
1567 if (driveropts != NULL) {
1568 char *p;
1569
1570 p = hasdrvopt(driveropts, "erase");
1571 if (p == NULL)
1572 p = hasdrvopt(driveropts, "blank");
1573 if (p != NULL) {
1574 if (*p == '1')
1575 flags |= DC_ERASE;
1576 else
1577 flags &= ~DC_ERASE;
1578 }
1579 p = hasdrvopt(driveropts, "set");
1580 if (p != NULL) {
1581 if (*p == '1')
1582 flags |= CHANGE_SETTING;
1583 else
1584 flags &= ~CHANGE_SETTING;
1585 }
1586 p = hasdrvopt(driveropts, "dvdr");
1587 if (p != NULL) {
1588 if (*p == '1')
1589 flags |= DVD_PLUS_R;
1590 else
1591 flags &= ~DVD_PLUS_R;
1592 }
1593 }
1594
1595 /*Size Min is 0x30000, Size Max is: 0x26c090 */
1596 #ifdef DVDPLUS_DEBUG
1597 error("Flags: %d blanksize: %d (0x%X)\n", flags, blanksize, blanksize);
1598 #endif
1599
1600 ret = ricoh_dvdsetting(scgp, blanksize, flags, TRUE);
1601 waitformat(scgp, 2000);
1602 return (ret);
1603 }
1604
1605 LOCAL int
format_dvdplus(scgp,dp,fmtflags)1606 format_dvdplus(scgp, dp, fmtflags)
1607 SCSI *scgp;
1608 cdr_t *dp;
1609 int fmtflags;
1610 {
1611 /*
1612 * 1.3 Formatting
1613 * --------------
1614 *
1615 * - For efficiency, please use the Format command only on blank discs
1616 *
1617 * - The command is:
1618 * - "04 11 00 00 00 00 00 00 00 00 00 00
1619 * ^^^
1620 * 0x10 Format Data
1621 * 0x01 Format Code == 1
1622 * 00 82 00 08 00 23 05 40 98 00 00 01"
1623 * ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
1624 * Format Format
1625 * header descriptor
1626 * 0x80 FOV
1627 * 0x20 IMMED
1628 * len == 0x08
1629 */
1630 char cap_buf[4096];
1631 char fmt_buf[128];
1632 int len;
1633 int i;
1634 struct scsi_cap_data *cp;
1635 struct scsi_format_cap_desc *lp;
1636 struct scsi_format_header *fhp;
1637 long blocks = 0;
1638 struct timeval starttime;
1639 struct timeval stoptime;
1640 #ifdef DVDPLUS_DEBUG
1641 struct timeval stoptime2;
1642 #endif
1643
1644 len = get_format_capacities(scgp, cap_buf, sizeof (cap_buf));
1645 if (len < 0)
1646 return (-1);
1647
1648 #ifdef DVDPLUS_DEBUG
1649 error("Cap len: %d\n", len);
1650 scg_prbytes("Format cap:", (Uchar *)cap_buf, len);
1651 #endif
1652
1653 cp = (struct scsi_cap_data *)cap_buf;
1654 lp = cp->list;
1655 len -= sizeof (struct scsi_format_cap_header);
1656 if (lp->desc_type == 2) {
1657 if ((dp->cdr_cmdflags & F_FORCE) == 0) {
1658 errmsgno(EX_BAD, _("Medium is already formatted.\n"));
1659 return (-1);
1660 }
1661 }
1662 #ifdef DVDPLUS_DEBUG
1663 error("hd len: %d len: %d\n", cp->hd.len, len);
1664 #endif
1665
1666 for (i = len; i >= sizeof (struct scsi_format_cap_desc);
1667 i -= sizeof (struct scsi_format_cap_desc), lp++) {
1668 #ifdef DVDPLUS_DEBUG
1669 error("blocks %ld fmt 0x%X desc %d blen: %ld\n",
1670 (long)a_to_u_4_byte(lp->nblock),
1671 lp->fmt_type,
1672 lp->desc_type,
1673 (long)a_to_u_3_byte(lp->blen));
1674 #endif
1675 if (lp->fmt_type == FCAP_TYPE_DVDPLUS_FULL)
1676 blocks = a_to_u_4_byte(lp->nblock);
1677 }
1678 if (blocks == 0) {
1679 errmsgno(EX_BAD, _("DVD+RW Full format capacity not found.\n"));
1680 return (-1);
1681 }
1682
1683 fhp = (struct scsi_format_header *)fmt_buf;
1684 lp = (struct scsi_format_cap_desc *)&fmt_buf[4];
1685 fillbytes((caddr_t)fmt_buf, sizeof (fmt_buf), '\0');
1686
1687 fhp->enable = 1;
1688 fhp->immed = 1;
1689 i_to_2_byte(fhp->length, 8);
1690 i_to_4_byte(lp->nblock, blocks);
1691 lp->fmt_type = FCAP_TYPE_DVDPLUS_FULL;
1692 i_to_3_byte(lp->blen, 0);
1693 /* i_to_3_byte(lp->blen, 1);*/
1694
1695 #ifdef DVDPLUS_DEBUG
1696 scg_prbytes("Format desc:", (Uchar *)fmt_buf, 12);
1697 #endif
1698
1699 if (lverbose) {
1700 /*
1701 * XXX evt. restart Format ansagen...
1702 */
1703 printf(_("Formatting media\n"));
1704 flush();
1705 }
1706 starttime.tv_sec = 0;
1707 starttime.tv_usec = 0;
1708 stoptime = starttime;
1709 gettimeofday(&starttime, (struct timezone *)0);
1710
1711 if (format_unit(scgp, fhp, /*fhp->length*/ 8 + sizeof (struct scsi_format_header),
1712 1, 0, 0, 0, 3800) < 0) {
1713 return (-1);
1714 }
1715
1716
1717 #ifdef DVDPLUS_DEBUG
1718 /* if (ret >= 0 && lverbose) {*/
1719 if (1) {
1720 gettimeofday(&stoptime, (struct timezone *)0);
1721 prtimediff("Format time: ", &starttime, &stoptime);
1722 }
1723 #endif
1724 waitformat(scgp, 300);
1725
1726 #ifdef DVDPLUS_DEBUG
1727 gettimeofday(&stoptime2, (struct timezone *)0);
1728 prtimediff("Format WAIT time: ", &stoptime, &stoptime2);
1729 prtimediff("Format time TOTAL: ", &starttime, &stoptime2);
1730 #endif
1731
1732
1733 #ifdef DVDPLUS_DEBUG
1734 error("------------> STOP DE-ICE\n");
1735 #endif
1736 scsi_close_tr_session(scgp, CL_TYPE_STOP_DEICE, 0, TRUE);
1737 waitformat(scgp, 300);
1738
1739 #ifdef DVDPLUS_DEBUG
1740 gettimeofday(&stoptime2, (struct timezone *)0);
1741 prtimediff("Format time TOTAL 2 : ", &starttime, &stoptime2);
1742 #endif
1743
1744 #ifdef DVDPLUS_DEBUG
1745 error("------------> CLOSE SESSION\n");
1746 #endif
1747 scsi_close_tr_session(scgp, CL_TYPE_SESSION, 0, TRUE);
1748 waitformat(scgp, 300);
1749
1750 #ifdef DVDPLUS_DEBUG
1751 gettimeofday(&stoptime2, (struct timezone *)0);
1752 prtimediff("Format time TOTAL 3: ", &starttime, &stoptime2);
1753 #endif
1754 return (0);
1755 }
1756
1757 LOCAL int
waitformat(scgp,secs)1758 waitformat(scgp, secs)
1759 SCSI *scgp;
1760 int secs;
1761 {
1762 Uchar sensebuf[CCS_SENSE_LEN];
1763 int printed = 0;
1764 int i;
1765 int key;
1766 #define W_SLEEP 2
1767
1768 scgp->silent++;
1769 for (i = 0; i < secs/W_SLEEP; i++) {
1770 if (test_unit_ready(scgp) >= 0) {
1771 scgp->silent--;
1772 return (0);
1773 }
1774 key = scg_sense_key(scgp);
1775 if (key != SC_UNIT_ATTENTION && key != SC_NOT_READY)
1776 break;
1777 request_sense_b(scgp, (caddr_t)sensebuf, sizeof (sensebuf));
1778 #ifdef XXX
1779 scg_prbytes("Sense:", sensebuf, sizeof (sensebuf));
1780 scgp->scmd->u_scb.cmd_scb[0] = 2;
1781 movebytes(sensebuf, scgp->scmd->u_sense.cmd_sense, sizeof (sensebuf));
1782 scgp->scmd->sense_count = sizeof (sensebuf);
1783 scg_printerr(scgp);
1784 #endif
1785 /*
1786 * status: 0x2 (CHECK CONDITION)
1787 * Sense Bytes: F0 00 00 00 24 1C 10 0C 00 00 00 00 04 04 00 80 03 F6
1788 * Sense Key: 0x0 No Additional Sense, Segment 0
1789 * Sense Code: 0x04 Qual 0x04 (logical unit not ready, format in progress) Fru 0x0
1790 * Sense flags: Blk 2366480 (valid)
1791 * cmd finished after 0.000s timeout 100s
1792 * Das Fehlt:
1793 * operation 1% done
1794 */
1795
1796 if (lverbose && (sensebuf[15] & 0x80)) {
1797 printed++;
1798 error(_("operation %d%% done\r"),
1799 (100*(sensebuf[16] << 8 |
1800 sensebuf[17]))/(unsigned)65536);
1801 }
1802 sleep(W_SLEEP);
1803 }
1804 scgp->silent--;
1805 if (printed)
1806 error("\n");
1807 return (-1);
1808 #undef W_SLEEP
1809 }
1810
1811 LOCAL int
stats_dvdplus(scgp,dp)1812 stats_dvdplus(scgp, dp)
1813 SCSI *scgp;
1814 cdr_t *dp;
1815 {
1816 Uchar mode[256];
1817 struct ricoh_mode_page_30 *rp;
1818 UInt32_t count;
1819
1820 if ((dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) == 0)
1821 return (0);
1822
1823 rp = get_justlink_ricoh(scgp, mode);
1824 if (rp) {
1825 count = a_to_u_2_byte(rp->link_counter);
1826 if (lverbose) {
1827 if (count == 0)
1828 printf(_("BURN-Free was not used.\n"));
1829 else
1830 printf(_("BURN-Free was %d times used.\n"),
1831 (int)count);
1832 }
1833 }
1834 return (0);
1835 }
1836
1837 #define FMTDAT 0x10
1838 #define CMPLST 0x08
1839
1840 EXPORT int
format_unit(scgp,fmt,length,list_format,dgdl,interlv,pattern,timeout)1841 format_unit(scgp, fmt, length, list_format, dgdl, interlv, pattern, timeout)
1842 SCSI *scgp;
1843 void *fmt;
1844 int length;
1845 int list_format; /* 0 if fmt == 0 */
1846 int dgdl; /* disable grown defect list */
1847 int interlv;
1848 int pattern;
1849 int timeout;
1850 {
1851 register struct scg_cmd *scmd = scgp->scmd;
1852
1853 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1854 scmd->addr = (caddr_t)fmt;
1855 scmd->size = length;
1856 scmd->flags = SCG_DISRE_ENA;
1857 scmd->cdb_len = SC_G0_CDBLEN;
1858 scmd->sense_len = CCS_SENSE_LEN;
1859 if (timeout < 0)
1860 timeout = 24*3600; /* Kein Timeout XXX kann haengen */
1861 scmd->timeout = timeout;
1862 scmd->cdb.g0_cdb.cmd = 0x04; /* Format Unit */
1863 scmd->cdb.g0_cdb.lun = scg_lun(scgp);
1864 scmd->cdb.g0_cdb.high_addr = (fmt?FMTDAT:0)|(dgdl?CMPLST:0)|list_format;
1865 scmd->cdb.g0_cdb.mid_addr = pattern;
1866 scmd->cdb.g0_cdb.count = interlv;
1867
1868 #ifdef DVDPLUS_DEBUG
1869 scg_prbytes("Format CDB: ", (u_char *)scmd->cdb.cmd_cdb, scmd->cdb_len);
1870
1871 /* if (scgp->verbose && fmt)*/
1872 scg_prbytes("Format Data:", (u_char *)fmt, length);
1873 #endif
1874
1875 scgp->cmdname = "format unit";
1876
1877 return (scg_cmd(scgp));
1878 }
1879
1880 LOCAL int
set_p_layerbreak(scgp,tsize,lbreak)1881 set_p_layerbreak(scgp, tsize, lbreak)
1882 SCSI *scgp;
1883 long tsize;
1884 Int32_t lbreak;
1885 {
1886 struct dvd_structure_20 lb;
1887 int ret;
1888 UInt32_t dsize;
1889 UInt32_t l0_cap;
1890
1891 /*
1892 * Layer boundary information 0x20
1893 */
1894 fillbytes((caddr_t)&lb, sizeof (lb), '\0');
1895 ret = read_dvd_structure(scgp, (caddr_t)&lb, sizeof (lb), 0, 0, 0, 0x20);
1896 if (ret < 0)
1897 return (ret);
1898
1899 if (lb.res47[0] & 0x80) {
1900 errmsgno(EX_BAD, _("Layer 0 zone capacity already set.\n"));
1901 return (-1);
1902 }
1903
1904 l0_cap = a_to_u_4_byte(lb.l0_area_cap);
1905 if (lbreak > 0 && lbreak > l0_cap) {
1906 errmsgno(EX_BAD, _("Manual layer break %d > %u not allowed.\n"),
1907 lbreak, l0_cap);
1908 return (-1);
1909 }
1910 dsize = roundup(tsize, 16);
1911 if (lbreak <= 0 && dsize <= l0_cap) {
1912 /*
1913 * Allow to write DL media with less than single layer size
1914 * in case of manual layer break set up.
1915 */
1916 errmsgno(EX_BAD,
1917 _("Layer 0 size %u is bigger than expected disk size %u.\n"),
1918 l0_cap, dsize);
1919 errmsgno(EX_BAD, _("Use single layer medium.\n"));
1920 return (-1);
1921 }
1922 l0_cap = dsize / 2;
1923 l0_cap = roundup(l0_cap, 16);
1924 if (lbreak > 0 && lbreak < l0_cap) {
1925 errmsgno(EX_BAD, _("Manual layer break %d < %u not allowed.\n"),
1926 lbreak, l0_cap);
1927 return (-1);
1928 }
1929 if (lbreak > 0)
1930 l0_cap = lbreak;
1931 i_to_4_byte(lb.l0_area_cap, l0_cap);
1932
1933 ret = send_dvd_structure(scgp, (caddr_t)&lb, sizeof (lb), 0x20);
1934 return (ret);
1935 }
1936
1937 LOCAL int
ricoh_dvdsetting(scgp,erase_size,flags,immed)1938 ricoh_dvdsetting(scgp, erase_size, flags, immed)
1939 SCSI *scgp;
1940 int erase_size;
1941 int flags;
1942 int immed;
1943 {
1944 register struct scg_cmd *scmd = scgp->scmd;
1945
1946 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1947 scmd->flags = SCG_DISRE_ENA;
1948 scmd->cdb_len = SC_G1_CDBLEN;
1949 scmd->sense_len = CCS_SENSE_LEN;
1950 scmd->timeout = 3600;
1951 scmd->cdb.g1_cdb.cmd = 0xEA;
1952 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1953 scmd->cdb.cmd_cdb[1] = immed ? 1 : 0;
1954 scmd->cdb.cmd_cdb[2] = flags;
1955 i_to_3_byte(&scmd->cdb.cmd_cdb[3], erase_size);
1956
1957 scgp->cmdname = "set_dummy_dvdr_setttings";
1958
1959 return (scg_cmd(scgp));
1960 }
1961
1962 #ifdef __needed__
1963 /*
1964 * 0x21 Emulation write is OFF
1965 * 0x20 Emulation write is ON
1966 * 0xFF Disk is loading
1967 */
1968 LOCAL int
dummy_plextor(scgp,modecode)1969 dummy_plextor(scgp, modecode)
1970 SCSI *scgp;
1971 int modecode;
1972 {
1973 register struct scg_cmd *scmd = scgp->scmd;
1974
1975 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1976 scmd->flags = SCG_DISRE_ENA;
1977 scmd->cdb_len = SC_G5_CDBLEN;
1978 scmd->sense_len = CCS_SENSE_LEN;
1979 scmd->cdb.g5_cdb.cmd = 0xF3;
1980 scmd->cdb.cmd_cdb[1] = 0x1F;
1981 scmd->cdb.g5_cdb.lun = scg_lun(scgp);
1982 scmd->cdb.cmd_cdb[2] = 0x16;
1983 scmd->cdb.cmd_cdb[3] = modecode;
1984
1985 scgp->cmdname = "plextor dummy";
1986
1987 if (scg_cmd(scgp) < 0)
1988 return (-1);
1989 return (0);
1990 }
1991 #endif
1992