1 /* @(#)drv_7501.c 1.30 10/12/19 Copyright 2003-2010 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)drv_7501.c 1.30 10/12/19 Copyright 2003-2010 J. Schilling";
6 #endif
7 /*
8 * Device driver for the Masushita CW-7501
9 *
10 * Copyright (c) 2003-2010 J. Schilling
11 *
12 * Mode Pages:
13 * 0x01 error recovery Seite 100
14 * 0x02 disconnect/reconnect Seite 107
15 * 0x0D CD-ROM device parameter Seite 110
16 * 0x0E CD-ROM Audio control Seite 112
17 * 0x20 Speed & Tray position Seite 115
18 * 0x21 Media catalog number Seite 124
19 * 0x22 ISRC Seite 125
20 * 0x23 Dummy/Write Information Seite 126
21 * 0x24 CD-R disk information Seite 127
22 */
23 /*
24 * The contents of this file are subject to the terms of the
25 * Common Development and Distribution License, Version 1.0 only
26 * (the "License"). You may not use this file except in compliance
27 * with the License.
28 *
29 * See the file CDDL.Schily.txt in this distribution for details.
30 * A copy of the CDDL is also available via the Internet at
31 * http://www.opensource.org/licenses/cddl1.txt
32 *
33 * When distributing Covered Code, include this CDDL HEADER in each
34 * file and include the License file CDDL.Schily.txt from this distribution.
35 */
36
37 #ifndef DEBUG
38 #define DEBUG
39 #endif
40 #include <schily/mconfig.h>
41
42 #include <schily/stdio.h>
43 #include <schily/standard.h>
44 #include <schily/stdlib.h>
45 #include <schily/unistd.h>
46 #include <schily/errno.h>
47 #include <schily/string.h>
48 #include <schily/time.h>
49
50 #include <schily/utypes.h>
51 #include <schily/btorder.h>
52 #include <schily/intcvt.h>
53 #include <schily/schily.h>
54 #include <schily/nlsdefs.h>
55
56 #include <scg/scgcmd.h>
57 #include <scg/scsidefs.h>
58 #include <scg/scsireg.h>
59 #include <scg/scsitransp.h>
60
61 #include <schily/libport.h>
62
63 #include "cdrecord.h"
64
65 extern int silent;
66 extern int debug;
67 extern int verbose;
68 extern int lverbose;
69 extern int xdebug;
70
71 #if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */
72
73 struct cw7501_mode_page_20 { /* Speed control */
74 MP_P_CODE; /* parsave & pagecode */
75 Uchar p_len; /* 0x02 = 2 Bytes */
76 Uchar speed;
77 Ucbit res : 7;
78 Ucbit traypos : 1;
79 };
80
81 #else /* Motorola byteorder */
82
83 struct cw7501_mode_page_20 { /* Speed control */
84 MP_P_CODE; /* parsave & pagecode */
85 Uchar p_len; /* 0x02 = 2 Bytes */
86 Uchar speed;
87 Ucbit traypos : 1;
88 Ucbit res : 7;
89 };
90 #endif
91
92 #if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */
93
94 struct cw7501_mode_page_21 { /* MCN */
95 MP_P_CODE; /* parsave & pagecode */
96 Uchar p_len; /* 0x12 = 20 Bytes */
97 Ucbit control : 4;
98 Ucbit addr : 4;
99 Uchar res_3;
100 Uchar res_4;
101 Uchar mcn[15];
102 };
103
104 #else /* Motorola byteorder */
105
106 struct cw7501_mode_page_21 { /* MCN */
107 MP_P_CODE; /* parsave & pagecode */
108 Uchar p_len; /* 0x12 = 20 Bytes */
109 Ucbit addr : 4;
110 Ucbit control : 4;
111 Uchar res_3;
112 Uchar res_4;
113 Uchar mcn[15];
114 };
115 #endif
116
117
118 #if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */
119
120 struct cw7501_mode_page_22 { /* ISRC */
121 MP_P_CODE; /* parsave & pagecode */
122 Uchar p_len; /* 0x12 = 20 Bytes */
123 Ucbit control : 4;
124 Ucbit addr : 4;
125 Uchar trackno;
126 Uchar res_4;
127 Uchar isrc[15];
128 };
129
130 #else /* Motorola byteorder */
131
132 struct cw7501_mode_page_22 { /* ISRC */
133 MP_P_CODE; /* parsave & pagecode */
134 Uchar p_len; /* 0x12 = 20 Bytes */
135 Ucbit addr : 4;
136 Ucbit control : 4;
137 Uchar trackno;
138 Uchar res_4;
139 Uchar isrc[15];
140 };
141 #endif
142
143 #if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */
144
145 struct cw7501_mode_page_23 { /* Dummy / Write information */
146 MP_P_CODE; /* parsave & pagecode */
147 Uchar p_len; /* 0x02 = 2 Bytes */
148 Uchar res;
149 Ucbit autopg : 1;
150 Ucbit dummy : 1;
151 Ucbit res3_72 : 6;
152 };
153
154 #else /* Motorola byteorder */
155
156 struct cw7501_mode_page_23 { /* Dummy / Write information */
157 MP_P_CODE; /* parsave & pagecode */
158 Uchar p_len; /* 0x02 = 2 Bytes */
159 Uchar res;
160 Ucbit res3_72 : 6;
161 Ucbit dummy : 1;
162 Ucbit autopg : 1;
163 };
164 #endif
165
166 struct cw7501_mode_page_24 { /* CD-R Disk information */
167 MP_P_CODE; /* parsave & pagecode */
168 Uchar p_len; /* 0x0A = 12 Bytes */
169 Uchar disktype;
170 Uchar res;
171 Uchar appl_code[4];
172 Uchar disk_id[4];
173 };
174
175 struct cw7501_mode_data {
176 struct scsi_mode_header header;
177 union cdd_pagex {
178 struct cw7501_mode_page_20 page20;
179 struct cw7501_mode_page_21 page21;
180 struct cw7501_mode_page_22 page22;
181 struct cw7501_mode_page_23 page23;
182 struct cw7501_mode_page_24 page24;
183 } pagex;
184 };
185
186 /*
187 * Mode for read track information
188 */
189 #define TI_TRACKINFO_R 0
190 #define TI_NWA 1
191 #define TI_PMA 2
192 #define TI_TRACKINFO 3
193
194 struct cw7501_nwa {
195 Uchar nwa_length[2];
196 Uchar nwa_res;
197 Uchar nwa_trackno;
198 Uchar nwa_nwa[4];
199 Uchar nwa_freeblocks[4];
200 };
201
202 struct cw7501_cue {
203 Uchar cs_ctladr; /* CTL/ADR for this track */
204 Uchar cs_tno; /* This track number */
205 Uchar cs_index; /* Index within this track */
206 Uchar cs_dataform; /* Data form */
207 /* Bit 0..3 Physical Format */
208 /* Bit 4 Alt Copy (SCMS) */
209 /* Bit 5 SubC Audio + RAW96 sub */
210 Uchar cs_extension; /* Reserved or MCN/ISRC */
211 Uchar cs_min; /* Absolute time minutes */
212 Uchar cs_sec; /* Absolute time seconds */
213 Uchar cs_frame; /* Absolute time frames */
214 };
215
216
217 LOCAL int cw7501_attach __PR((SCSI *scgp, cdr_t *dp));
218 LOCAL int cw7501_init __PR((SCSI *scgp, cdr_t *dp));
219 LOCAL int cw7501_getdisktype __PR((SCSI *scgp, cdr_t *dp));
220 LOCAL int cw7501_speed_select __PR((SCSI *scgp, cdr_t *dp, int *speedp));
221 LOCAL int cw7501_next_wr_addr __PR((SCSI *scgp, track_t *trackp, long *ap));
222 LOCAL int cw7501_write __PR((SCSI *scgp, caddr_t bp, long sectaddr, long size, int blocks, BOOL islast));
223 LOCAL int cw7501_write_leadin __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
224 LOCAL int cw7501_open_track __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
225 LOCAL int cw7501_close_track __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
226 LOCAL int cw7501_open_session __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
227 LOCAL int cw7501_gen_cue __PR((track_t *trackp, void *vcuep, BOOL needgap));
228 LOCAL void fillcue __PR((struct cw7501_cue *cp, int ca, int tno, int idx, int dataform, int scms, msf_t *mp));
229 LOCAL int cw7501_send_cue __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
230 LOCAL int cw7501_fixate __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
231 LOCAL int cw7501_rezero __PR((SCSI *scgp, int reset, int dwreset));
232 LOCAL int cw7501_read_trackinfo __PR((SCSI *scgp, Uchar *bp, int count, int track, int mode));
233 LOCAL int cw7501_write_dao __PR((SCSI *scgp, Uchar *bp, int len, int disktype));
234 LOCAL int cw7501_reserve_track __PR((SCSI *scgp, unsigned long));
235 LOCAL int cw7501_set_mode __PR((SCSI *scgp, int phys_form, int control,
236 int subc, int alt, int trackno, int tindex,
237 int packet_size, int write_mode));
238 LOCAL int cw7501_finalize __PR((SCSI *scgp, int pad, int fixed));
239
240
241 cdr_t cdr_cw7501 = {
242 0, 0, 0,
243 /*
244 * Prinzipiell geht auch: CDR_PACKET & CDR_SRAW96R
245 */
246 CDR_TAO|CDR_SAO|CDR_TRAYLOAD,
247 0,
248 CDR_CDRW_NONE,
249 WM_SAO,
250 2, 2,
251 "cw_7501",
252 "driver for Matsushita/Panasonic CW-7501",
253 0,
254 (dstat_t *)0,
255 drive_identify,
256 cw7501_attach,
257 cw7501_init,
258 cw7501_getdisktype,
259 no_diskstatus,
260 scsi_load,
261 scsi_unload,
262 buf_dummy, /* RD buffer cap not supp. */
263 cmd_dummy, /* recovery_needed */
264 (int(*)__PR((SCSI *, cdr_t *, int)))cmd_dummy, /* recover */
265 cw7501_speed_select,
266 select_secsize,
267 cw7501_next_wr_addr,
268 cw7501_reserve_track,
269 cw7501_write,
270 cw7501_gen_cue,
271 cw7501_send_cue,
272 cw7501_write_leadin,
273 cw7501_open_track,
274 cw7501_close_track,
275 cw7501_open_session,
276 cmd_dummy, /* close seession */
277 cmd_dummy, /* abort */
278 read_session_offset,
279 cw7501_fixate,
280 cmd_dummy, /* stats */
281 blank_dummy,
282 format_dummy,
283 (int(*)__PR((SCSI *, caddr_t, int, int)))NULL, /* no OPC */
284 cmd_dummy, /* opt1 */
285 cmd_dummy, /* opt2 */
286 };
287
288 static const char *sd_cw7501_error_str[] = {
289 "\100\201diagnostic failure on ROM", /* 40 81 */
290 "\100\202diagnostic failure on CPU internal RAM", /* 40 82 */
291 "\100\203diagnostic failure on BUFFER RAM", /* 40 83 */
292 "\100\204diagnostic failure on internal SCSI controller", /* 40 84 */
293 "\100\205diagnostic failure on system mechanism", /* 40 85 */
294
295 "\210\000Illegal Que Sheet (DAO parameter)", /* 88 00 */
296 "\211\000Inappropriate command", /* 89 00 */
297
298 "\250\000Audio Play operation Not in Progress", /* A8 00 */
299 "\251\000Buffer Overrun", /* A9 00 */
300
301 "\300\000Unrecordable Disk", /* C0 00 */
302 "\301\000Illegal Track Status", /* C1 00 */
303 "\302\000Reserved track Status", /* C2 00 */
304 "\304\000Illegal Reserve Length for Reserve Track Command", /* C4 00 */
305 "\304\001Illegal Data Form for Reserve Track Command", /* C4 01 */
306 "\304\002Unable to Reserve Track, Because Track Mode has been Changed", /* C4 02 */
307
308 "\305\000Buffer error during recording", /* C5 00 */
309 "\307\000Disk Style mismatch", /* C7 00 */
310 "\312\000Power Calibration error", /* CA 00 */
311 "\313\000Write error (Fatal Error/Time out)", /* CB 00 */
312 "\314\000Not enough space (Leadin/Leadout space)", /* CC 00 */
313 "\315\000No track present to finalize", /* CD 00 */
314 "\317\000Unable to recover damaged disk", /* CF 00 */
315
316 "\320\000PMA area full (1000 blocks)", /* D0 00 */
317 "\321\000PCA area full (100 counts)", /* D1 00 */
318 "\322\000Recovery failed", /* D2 00 */
319 "\323\000Recovery needed", /* D3 00 */
320 NULL
321 };
322
323 LOCAL int
cw7501_attach(scgp,dp)324 cw7501_attach(scgp, dp)
325 SCSI *scgp;
326 cdr_t *dp;
327 {
328 scg_setnonstderrs(scgp, sd_cw7501_error_str);
329 return (0);
330 }
331
332 LOCAL int
cw7501_init(scgp,dp)333 cw7501_init(scgp, dp)
334 SCSI *scgp;
335 cdr_t *dp;
336 {
337 return (cw7501_speed_select(scgp, dp, NULL));
338 }
339
340 LOCAL int
cw7501_getdisktype(scgp,dp)341 cw7501_getdisktype(scgp, dp)
342 SCSI *scgp;
343 cdr_t *dp;
344 {
345 Ulong maxb = 0;
346 Uchar buf[256];
347 int ret;
348 dstat_t *dsp = dp->cdr_dstat;
349
350 if (xdebug > 0) {
351 scgp->silent++;
352 fillbytes((caddr_t)buf, sizeof (buf), '\0');
353 ret = cw7501_read_trackinfo(scgp, buf, 32, 0, 0);
354 if (ret >= 0)
355 scg_prbytes("TI EXIST-R (0): ", buf, 32 -scg_getresid(scgp));
356
357 fillbytes((caddr_t)buf, sizeof (buf), '\0');
358 ret = cw7501_read_trackinfo(scgp, buf, 32, 0, 1);
359 if (ret >= 0)
360 scg_prbytes("TI NWA (1): ", buf, 32 -scg_getresid(scgp));
361
362 fillbytes((caddr_t)buf, sizeof (buf), '\0');
363 ret = cw7501_read_trackinfo(scgp, buf, 32, 0, 2);
364 if (ret >= 0)
365 scg_prbytes("TI PMA (2): ", buf, 32 -scg_getresid(scgp));
366
367 fillbytes((caddr_t)buf, sizeof (buf), '\0');
368 ret = cw7501_read_trackinfo(scgp, buf, 32, 0, 3);
369 if (ret >= 0)
370 scg_prbytes("TI EXIST-ROM (3): ", buf, 32 -scg_getresid(scgp));
371 scgp->silent--;
372 }
373
374 fillbytes((caddr_t)buf, sizeof (buf), '\0');
375
376 scgp->silent++;
377 ret = cw7501_read_trackinfo(scgp, buf, 12, 0, TI_NWA);
378 if (ret < 0 &&
379 (dsp->ds_cdrflags & (RF_WRITE|RF_BLANK)) == RF_WRITE) {
380
381 /*
382 * Try to clear the dummy bit to reset the virtual
383 * drive status. Not all drives support it even though
384 * it is mentioned in the MMC standard.
385 */
386 if (lverbose)
387 printf(_("Trying to clear drive status.\n"));
388 cw7501_rezero(scgp, 0, 1);
389 wait_unit_ready(scgp, 60);
390 ret = cw7501_read_trackinfo(scgp, buf, 12, 0, TI_NWA);
391 }
392 scgp->silent--;
393
394 if (ret >= 0) {
395 maxb = a_to_u_4_byte(&buf[8]);
396 if (maxb != 0)
397 maxb -= 150;
398 }
399 dsp->ds_maxblocks = maxb;
400
401 return (drive_getdisktype(scgp, dp));
402 }
403
404
405 LOCAL int
cw7501_speed_select(scgp,dp,speedp)406 cw7501_speed_select(scgp, dp, speedp)
407 SCSI *scgp;
408 cdr_t *dp;
409 int *speedp;
410 {
411 struct scsi_mode_page_header *mp;
412 char mode[256];
413 int len = 20;
414 int page = 0x20;
415 struct cw7501_mode_page_20 *xp20;
416 struct cw7501_mode_data md;
417 int count;
418 int speed = 1;
419 BOOL dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
420
421 if (speedp) {
422 speed = *speedp;
423 } else {
424 fillbytes((caddr_t)mode, sizeof (mode), '\0');
425
426 if (!get_mode_params(scgp, page, _("Speed information"),
427 (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
428 return (-1);
429 }
430 if (len == 0)
431 return (-1);
432
433 mp = (struct scsi_mode_page_header *)
434 (mode + sizeof (struct scsi_mode_header) +
435 ((struct scsi_mode_header *)mode)->blockdesc_len);
436
437 xp20 = (struct cw7501_mode_page_20 *)mp;
438 speed = xp20->speed;
439 }
440
441 fillbytes((caddr_t)&md, sizeof (md), '\0');
442
443 count = sizeof (struct scsi_mode_header) +
444 sizeof (struct cw7501_mode_page_20);
445
446 md.pagex.page20.p_code = 0x20;
447 md.pagex.page20.p_len = 0x02;
448 md.pagex.page20.speed = speed;
449
450 if (mode_select(scgp, (Uchar *)&md, count, 0, scgp->inq->data_format >= 2) < 0)
451 return (-1);
452
453 fillbytes((caddr_t)&md, sizeof (md), '\0');
454
455 count = sizeof (struct scsi_mode_header) +
456 sizeof (struct cw7501_mode_page_23);
457
458 md.pagex.page23.p_code = 0x23;
459 md.pagex.page23.p_len = 0x02;
460 md.pagex.page23.dummy = dummy?1:0;
461
462 return (mode_select(scgp, (Uchar *)&md, count, 0, scgp->inq->data_format >= 2));
463 }
464
465 LOCAL int
cw7501_next_wr_addr(scgp,trackp,ap)466 cw7501_next_wr_addr(scgp, trackp, ap)
467 SCSI *scgp;
468 track_t *trackp;
469 long *ap;
470 {
471 struct cw7501_nwa *nwa;
472 Uchar buf[256];
473 long next_addr;
474 int result = -1;
475
476
477 /*
478 * Reading info for current track may require doing the read_track_info
479 * with either the track number (if the track is currently being written)
480 * or with 0 (if the track hasn't been started yet and is invisible
481 */
482 nwa = (struct cw7501_nwa *)buf;
483
484 if (trackp != 0 && trackp->track > 0 && is_packet(trackp)) {
485 fillbytes((caddr_t)buf, sizeof (buf), '\0');
486
487 scgp->silent++;
488 result = cw7501_read_trackinfo(scgp, buf, sizeof (*nwa),
489 trackp->trackno,
490 TI_NWA);
491 scgp->silent--;
492 }
493
494 if (result < 0) {
495 if (cw7501_read_trackinfo(scgp, buf, sizeof (*nwa),
496 0, TI_NWA) < 0)
497 return (-1);
498 }
499 if (scgp->verbose)
500 scg_prbytes(_("track info:"), buf,
501 12-scg_getresid(scgp));
502 next_addr = a_to_4_byte(nwa->nwa_nwa);
503 /*
504 * XXX F�r TAO definitiv notwendig.
505 * XXX ABh�ngig von Auto-Pregap?
506 */
507 /* XXX */ next_addr += 150;
508 if (ap)
509 *ap = next_addr;
510 return (0);
511 }
512
513 LOCAL int
cw7501_write(scgp,bp,sectaddr,size,blocks,islast)514 cw7501_write(scgp, bp, sectaddr, size, blocks, islast)
515 SCSI *scgp;
516 caddr_t bp; /* address of buffer */
517 long sectaddr; /* disk address (sector) to put */
518 long size; /* number of bytes to transfer */
519 int blocks; /* sector count */
520 BOOL islast; /* last write for track */
521 {
522 if (lverbose > 1 && islast)
523 printf(_("\nWriting last record for this track.\n"));
524
525 return (write_xg0(scgp, bp, 0, size, blocks));
526 }
527
528 LOCAL int
cw7501_write_leadin(scgp,dp,trackp)529 cw7501_write_leadin(scgp, dp, trackp)
530 SCSI *scgp;
531 cdr_t *dp;
532 track_t *trackp;
533 {
534 Uint i;
535 long startsec = 0L;
536
537 if (wm_base(dp->cdr_dstat->ds_wrmode) == WM_SAO) {
538 if (debug || lverbose) {
539 printf(_("Sending CUE sheet...\n"));
540 flush();
541 }
542 if ((*dp->cdr_send_cue)(scgp, dp, trackp) < 0) {
543 errmsgno(EX_BAD, _("Cannot send CUE sheet.\n"));
544 return (-1);
545 }
546
547 /*
548 * Next writable address function does not work in DAO
549 * mode for this writer, so we just assume -150.
550 */
551 startsec = -150;
552 if (debug)
553 printf(_("SAO startsec: %ld\n"), startsec);
554
555 if (trackp[0].flags & TI_TEXT) {
556 errmsgno(EX_BAD, _("CD-Text unsupported in CW-7501 - ignoring.\n"));
557 } else for (i = 1; i <= trackp->tracks; i++) {
558 trackp[i].trackstart += startsec +150;
559 }
560 }
561 return (0);
562 }
563
564 LOCAL Uchar db2phys[] = {
565 0x00, /* 0 2352 bytes of raw data */
566 0xFF, /* 1 2368 bytes (raw data + P/Q Subchannel) */
567 0xFF, /* 2 2448 bytes (raw data + P-W Subchannel) */
568 0xFF, /* 3 2448 bytes (raw data + P-W raw Subchannel)*/
569 0xFF, /* 4 - Reserved */
570 0xFF, /* 5 - Reserved */
571 0xFF, /* 6 - Reserved */
572 0xFF, /* 7 - Vendor specific */
573 0x02, /* 8 2048 bytes Mode 1 (ISO/IEC 10149) */
574 0x03, /* 9 2336 bytes Mode 2 (ISO/IEC 10149) */
575 0xFF, /* 10 2048 bytes Mode 2 (CD-ROM XA form 1) */
576 0x04, /* 11 2056 bytes Mode 2 (CD-ROM XA form 1) */
577 0xFF, /* 12 2324 bytes Mode 2 (CD-ROM XA form 2) */
578 0x08, /* 13 2332 bytes Mode 2 (CD-ROM XA 1/2+subhdr) */
579 0xFF, /* 14 - Reserved */
580 0xFF, /* 15 - Vendor specific */
581 };
582
583 LOCAL int
cw7501_open_track(scgp,dp,trackp)584 cw7501_open_track(scgp, dp, trackp)
585 SCSI *scgp;
586 cdr_t *dp;
587 track_t *trackp;
588 {
589 struct scsi_mode_page_header *mp;
590 Uchar mode[256];
591 int len = 0;
592 int page = 0x23;
593 struct cw7501_mode_page_23 *xp23;
594
595 if (!is_tao(trackp) && !is_packet(trackp)) {
596 if (trackp->pregapsize > 0 && (trackp->flags & TI_PREGAP) == 0) {
597 if (lverbose) {
598 printf(_("Writing pregap for track %d at %ld\n"),
599 (int)trackp->trackno,
600 trackp->trackstart-trackp->pregapsize);
601 }
602 if (trackp->track == 1 && is_hidden(trackp)) {
603 pad_track(scgp, dp, trackp,
604 trackp->trackstart-trackp->pregapsize,
605 (Llong)(trackp->pregapsize-trackp->trackstart)*trackp->secsize,
606 FALSE, 0);
607 if (write_track_data(scgp, dp, track_base(trackp)) < 0)
608 return (-1);
609 } else {
610 /*
611 * XXX Do we need to check isecsize too?
612 */
613 pad_track(scgp, dp, trackp,
614 trackp->trackstart-trackp->pregapsize,
615 (Llong)trackp->pregapsize*trackp->secsize,
616 FALSE, 0);
617 }
618 }
619 return (0);
620 }
621
622 if (select_secsize(scgp, trackp->secsize) < 0)
623 return (-1);
624
625 if (!get_mode_params(scgp, page, _("Dummy/autopg information"),
626 (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
627 return (-1);
628 }
629 if (len == 0)
630 return (-1);
631
632 mp = (struct scsi_mode_page_header *)
633 (mode + sizeof (struct scsi_mode_header) +
634 ((struct scsi_mode_header *)mode)->blockdesc_len);
635
636 xp23 = (struct cw7501_mode_page_23 *)mp;
637 xp23->autopg = 1;
638 if (!set_mode_params(scgp, _("Dummy/autopg page"), mode, len, 0, trackp->secsize))
639 return (-1);
640
641 /*
642 * Set write modes for next track.
643 */
644 if (cw7501_set_mode(scgp, db2phys[trackp->dbtype & 0x0F],
645 st2mode[trackp->sectype&ST_MASK] | (is_copy(trackp) ? TM_ALLOW_COPY : 0),
646 0, is_scms(trackp) ? 1 : 0,
647 trackp->trackno, 1, 0,
648 /* write mode TAO */ 0x01) < 0)
649 return (-1);
650
651 return (0);
652 }
653
654
655 LOCAL int
cw7501_close_track(scgp,dp,trackp)656 cw7501_close_track(scgp, dp, trackp)
657 SCSI *scgp;
658 cdr_t *dp;
659 track_t *trackp;
660 {
661 if (!is_tao(trackp) && !is_packet(trackp)) {
662 return (0);
663 }
664 return (scsi_flush_cache(scgp, FALSE));
665 }
666
667 LOCAL int
cw7501_open_session(scgp,dp,trackp)668 cw7501_open_session(scgp, dp, trackp)
669 SCSI *scgp;
670 cdr_t *dp;
671 track_t *trackp;
672 {
673 struct cw7501_mode_data md;
674 int count;
675
676 if (select_secsize(scgp, 2048) < 0)
677 return (-1);
678
679 /*
680 * Disable Auto Pregap when writing in SAO mode.
681 */
682 if (!is_tao(trackp) && !is_packet(trackp)) {
683 struct scsi_mode_page_header *mp;
684 Uchar mode[256];
685 int len = 0;
686 int page = 0x23;
687 struct cw7501_mode_page_23 *xp23;
688
689 if (!get_mode_params(scgp, page, _("Dummy/autopg information"),
690 (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
691 return (-1);
692 }
693 if (len == 0)
694 return (-1);
695
696 mp = (struct scsi_mode_page_header *)
697 (mode + sizeof (struct scsi_mode_header) +
698 ((struct scsi_mode_header *)mode)->blockdesc_len);
699
700 xp23 = (struct cw7501_mode_page_23 *)mp;
701 xp23->autopg = 0;
702 if (!set_mode_params(scgp, _("Dummy/autopg page"), mode, len, 0, trackp->secsize))
703 return (-1);
704
705 return (0);
706 }
707
708 /*
709 * Set Disk Type and Disk ID.
710 */
711 fillbytes((caddr_t)&md, sizeof (md), '\0');
712
713 count = sizeof (struct scsi_mode_header) +
714 sizeof (struct cw7501_mode_page_24);
715
716 md.pagex.page24.p_code = 0x24;
717 md.pagex.page24.p_len = 0x0A;
718 md.pagex.page24.disktype = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
719 i_to_4_byte(md.pagex.page24.disk_id, 0x12345);
720
721 return (mode_select(scgp, (Uchar *)&md, count, 0, scgp->inq->data_format >= 2));
722 }
723
724 LOCAL int
cw7501_fixate(scgp,dp,trackp)725 cw7501_fixate(scgp, dp, trackp)
726 SCSI *scgp;
727 cdr_t *dp;
728 track_t *trackp;
729 {
730 if (!is_tao(trackp) && !is_packet(trackp)) {
731 return (scsi_flush_cache(scgp, FALSE));
732 }
733 /*
734 * 0x00 Finalize Disk (not appendable)
735 * 0x01 Finalize Session (allow next session)
736 * 0x10 Finalize track (variable packet writing) - Must fluch cache before
737 */
738 return (cw7501_finalize(scgp, 0, (track_base(trackp)->tracktype & TOCF_MULTI) ? 0x01 : 0x00));
739 }
740
741 /*--------------------------------------------------------------------------*/
742
743 LOCAL int
cw7501_gen_cue(trackp,vcuep,needgap)744 cw7501_gen_cue(trackp, vcuep, needgap)
745 track_t *trackp;
746 void *vcuep;
747 BOOL needgap;
748 {
749 int tracks = trackp->tracks;
750 int i;
751 struct cw7501_cue **cuep = vcuep;
752 struct cw7501_cue *cue;
753 struct cw7501_cue *cp;
754 int ncue = 0;
755 int icue = 0;
756 int pgsize;
757 msf_t m;
758 int ctl;
759 int df;
760 int scms;
761
762 cue = malloc(1);
763
764 for (i = 0; i <= tracks; i++) {
765 ctl = (st2mode[trackp[i].sectype & ST_MASK]) << 4;
766 if (is_copy(&trackp[i]))
767 ctl |= TM_ALLOW_COPY << 4;
768 df = db2phys[trackp[i].dbtype & 0x0F];
769
770 if (trackp[i].isrc) { /* MCN or ISRC */
771 ncue += 2;
772 cue = realloc(cue, ncue * sizeof (*cue));
773 cp = &cue[icue++];
774 if (i == 0) {
775 cp->cs_ctladr = 0x02;
776 movebytes(&trackp[i].isrc[0], &cp->cs_tno, 7);
777 cp = &cue[icue++];
778 cp->cs_ctladr = 0x02;
779 movebytes(&trackp[i].isrc[7], &cp->cs_tno, 7);
780 } else {
781 cp->cs_ctladr = 0x03;
782 cp->cs_tno = i;
783 movebytes(&trackp[i].isrc[0], &cp->cs_index, 6);
784 cp = &cue[icue++];
785 cp->cs_ctladr = 0x03;
786 cp->cs_tno = i;
787 movebytes(&trackp[i].isrc[6], &cp->cs_index, 6);
788 }
789 }
790 if (i == 0) { /* Lead in */
791 lba_to_msf(-150, &m);
792 cue = realloc(cue, ++ncue * sizeof (*cue));
793 cp = &cue[icue++];
794 fillcue(cp, ctl|0x01, i, 0, df, 0, &m);
795 } else {
796 scms = 0;
797
798 if (is_scms(&trackp[i]))
799 scms = 0x80;
800 pgsize = trackp[i].pregapsize;
801 if (pgsize == 0 && needgap)
802 pgsize++;
803 lba_to_msf(trackp[i].trackstart-pgsize, &m);
804 cue = realloc(cue, ++ncue * sizeof (*cue));
805 cp = &cue[icue++];
806 fillcue(cp, ctl|0x01, i, 0, df, scms, &m);
807
808 if (trackp[i].nindex == 1) {
809 lba_to_msf(trackp[i].trackstart, &m);
810 cue = realloc(cue, ++ncue * sizeof (*cue));
811 cp = &cue[icue++];
812 fillcue(cp, ctl|0x01, i, 1, df, scms, &m);
813 } else {
814 int idx;
815 long *idxlist;
816
817 ncue += trackp[i].nindex;
818 idxlist = trackp[i].tindex;
819 cue = realloc(cue, ncue * sizeof (*cue));
820
821 for (idx = 1; idx <= trackp[i].nindex; idx++) {
822 lba_to_msf(trackp[i].trackstart + idxlist[idx], &m);
823 cp = &cue[icue++];
824 fillcue(cp, ctl|0x01, i, idx, df, scms, &m);
825 }
826 }
827 }
828 }
829 /* Lead out */
830 ctl = (st2mode[trackp[tracks+1].sectype & ST_MASK]) << 4;
831 df = db2phys[trackp[tracks+1].dbtype & 0x0F];
832 lba_to_msf(trackp[tracks+1].trackstart, &m);
833 cue = realloc(cue, ++ncue * sizeof (*cue));
834 cp = &cue[icue++];
835 fillcue(cp, ctl|0x01, 0xAA, 1, df, 0, &m);
836
837 if (lverbose > 1) {
838 for (i = 0; i < ncue; i++) {
839 scg_prbytes("", (Uchar *)&cue[i], 8);
840 }
841 }
842 if (cuep)
843 *cuep = cue;
844 else
845 free(cue);
846 return (ncue);
847 }
848
849 LOCAL void
fillcue(cp,ca,tno,idx,dataform,scms,mp)850 fillcue(cp, ca, tno, idx, dataform, scms, mp)
851 struct cw7501_cue *cp; /* The target cue entry */
852 int ca; /* Control/adr for this entry */
853 int tno; /* Track number for this entry */
854 int idx; /* Index for this entry */
855 int dataform; /* Data format for this entry */
856 int scms; /* Serial copy management */
857 msf_t *mp; /* MSF value for this entry */
858 {
859 cp->cs_ctladr = ca;
860 if (tno <= 99)
861 cp->cs_tno = to_bcd(tno);
862 else
863 cp->cs_tno = tno;
864 cp->cs_index = to_bcd(idx);
865 if (scms != 0)
866 dataform |= 0x10;
867 cp->cs_dataform = dataform;
868 cp->cs_extension = 0;
869 cp->cs_min = to_bcd(mp->msf_min);
870 cp->cs_sec = to_bcd(mp->msf_sec);
871 cp->cs_frame = to_bcd(mp->msf_frame);
872 }
873
874 LOCAL int
cw7501_send_cue(scgp,dp,trackp)875 cw7501_send_cue(scgp, dp, trackp)
876 SCSI *scgp;
877 cdr_t *dp;
878 track_t *trackp;
879 {
880 struct cw7501_cue *cp;
881 int ncue;
882 int ret;
883 Uint i;
884 struct timeval starttime;
885 struct timeval stoptime;
886 int disktype;
887
888 disktype = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
889
890 for (i = 1; i <= trackp->tracks; i++) {
891 if (trackp[i].tracksize < (tsize_t)0) {
892 errmsgno(EX_BAD, _("Track %d has unknown length.\n"), i);
893 return (-1);
894 }
895 }
896 ncue = (*dp->cdr_gen_cue)(trackp, &cp, FALSE);
897
898 starttime.tv_sec = 0;
899 starttime.tv_usec = 0;
900 stoptime = starttime;
901 gettimeofday(&starttime, (struct timezone *)0);
902
903 scgp->silent++;
904 ret = cw7501_write_dao(scgp, (Uchar *)cp, ncue*8, disktype);
905 scgp->silent--;
906 free(cp);
907 if (ret < 0) {
908 errmsgno(EX_BAD, _("CUE sheet not accepted. Retrying with minimum pregapsize = 1.\n"));
909 ncue = (*dp->cdr_gen_cue)(trackp, &cp, TRUE);
910 ret = cw7501_write_dao(scgp, (Uchar *)cp, ncue*8, disktype);
911 free(cp);
912 }
913 if (ret >= 0 && lverbose) {
914 gettimeofday(&stoptime, (struct timezone *)0);
915 prtimediff(_("Write Lead-in time: "), &starttime, &stoptime);
916 }
917 return (ret);
918 }
919
920 /*--------------------------------------------------------------------------*/
921 LOCAL int
cw7501_rezero(scgp,reset,dwreset)922 cw7501_rezero(scgp, reset, dwreset)
923 SCSI *scgp;
924 int reset;
925 int dwreset;
926 {
927 register struct scg_cmd *scmd = scgp->scmd;
928
929 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
930 scmd->addr = (caddr_t)0;
931 scmd->size = 0;
932 scmd->flags = SCG_DISRE_ENA;
933 scmd->cdb_len = SC_G0_CDBLEN;
934 scmd->sense_len = CCS_SENSE_LEN;
935 scmd->cdb.g0_cdb.cmd = SC_REZERO_UNIT;
936 scmd->cdb.g0_cdb.lun = scg_lun(scgp);
937 scmd->cdb.cmd_cdb[5] |= reset ? 0x80 : 0;
938 scmd->cdb.cmd_cdb[5] |= dwreset ? 0x40 : 0;
939
940 scgp->cmdname = "cw7501 rezero";
941
942 return (scg_cmd(scgp));
943 }
944
945
946 LOCAL int
cw7501_read_trackinfo(scgp,bp,count,track,mode)947 cw7501_read_trackinfo(scgp, bp, count, track, mode)
948 SCSI *scgp;
949 Uchar *bp;
950 int count;
951 int track;
952 int mode;
953 {
954 register struct scg_cmd *scmd = scgp->scmd;
955
956 fillbytes((caddr_t) scmd, sizeof (*scmd), '\0');
957 scmd->addr = (caddr_t)bp;
958 scmd->size = count;
959 scmd->flags = SCG_RECV_DATA | SCG_DISRE_ENA;
960 scmd->cdb_len = SC_G1_CDBLEN;
961 scmd->sense_len = CCS_SENSE_LEN;
962 scmd->cdb.g1_cdb.cmd = 0xE9;
963 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
964 scmd->cdb.cmd_cdb[6] = track;
965 g1_cdblen(&scmd->cdb.g1_cdb, count);
966 scmd->cdb.cmd_cdb[9] = (mode & 3) << 6;
967
968 scgp->cmdname = "cw7501 read_track_information";
969
970 if (scg_cmd(scgp) < 0)
971 return (-1);
972
973 return (0);
974 }
975
976 LOCAL int
cw7501_write_dao(scgp,bp,len,disktype)977 cw7501_write_dao(scgp, bp, len, disktype)
978 SCSI *scgp;
979 Uchar *bp;
980 int len;
981 int disktype;
982 {
983 register struct scg_cmd *scmd = scgp->scmd;
984
985 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
986 scmd->addr = (caddr_t)bp;
987 scmd->size = len;
988 scmd->flags = SCG_DISRE_ENA;
989 scmd->cdb_len = SC_G1_CDBLEN;
990 scmd->sense_len = CCS_SENSE_LEN;
991 scmd->cdb.g1_cdb.cmd = 0xE6;
992 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
993 scmd->cdb.cmd_cdb[2] = disktype;
994 g1_cdblen(&scmd->cdb.g1_cdb, len);
995
996 scgp->cmdname = "cw7501 write_dao";
997
998 if (scg_cmd(scgp) < 0)
999 return (-1);
1000 return (0);
1001 }
1002
1003 /*
1004 * XXX CW-7501 also needs "control", so we need to make a different
1005 * XXX driver interface.
1006 */
1007 LOCAL int
cw7501_reserve_track(scgp,len)1008 cw7501_reserve_track(scgp, len)
1009 SCSI *scgp;
1010 unsigned long len;
1011 {
1012 register struct scg_cmd *scmd = scgp->scmd;
1013
1014 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1015 scmd->flags = SCG_DISRE_ENA;
1016 scmd->cdb_len = SC_G1_CDBLEN;
1017 scmd->sense_len = CCS_SENSE_LEN;
1018 scmd->cdb.g1_cdb.cmd = 0xE7;
1019 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1020 /* scmd->cdb.cmd_cdb[2] = control & 0x0F;*/
1021 i_to_4_byte(&scmd->cdb.cmd_cdb[5], len);
1022
1023 scgp->cmdname = "cw7501 reserve_track";
1024
1025 comerrno(EX_BAD, _("Control (as in set mode) missing.\n"));
1026
1027 if (scg_cmd(scgp) < 0)
1028 return (-1);
1029 return (0);
1030 }
1031
1032 LOCAL int
cw7501_set_mode(scgp,phys_form,control,subc,alt,trackno,tindex,packet_size,write_mode)1033 cw7501_set_mode(scgp, phys_form, control, subc, alt, trackno, tindex, packet_size, write_mode)
1034 SCSI *scgp;
1035 int phys_form;
1036 int control;
1037 int subc;
1038 int alt;
1039 int trackno;
1040 int tindex;
1041 int packet_size;
1042 int write_mode;
1043 {
1044 register struct scg_cmd *scmd = scgp->scmd;
1045
1046 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1047 scmd->flags = SCG_DISRE_ENA;
1048 scmd->cdb_len = SC_G1_CDBLEN;
1049 scmd->sense_len = CCS_SENSE_LEN;
1050 scmd->cdb.g1_cdb.cmd = 0xE2;
1051 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1052 scmd->cdb.cmd_cdb[2] = phys_form & 0x0F;
1053 scmd->cdb.cmd_cdb[3] = (control & 0x0F) << 4;
1054 scmd->cdb.cmd_cdb[3] |= subc ? 2 : 0;
1055 scmd->cdb.cmd_cdb[3] |= alt ? 1 : 0;
1056 scmd->cdb.cmd_cdb[4] = trackno;
1057 scmd->cdb.cmd_cdb[5] = tindex;
1058 i_to_3_byte(&scmd->cdb.cmd_cdb[6], packet_size);
1059 scmd->cdb.cmd_cdb[9] = (write_mode & 0x03) << 6;
1060
1061 scgp->cmdname = "cw7501 set_mode";
1062
1063 if (scg_cmd(scgp) < 0)
1064 return (-1);
1065 return (0);
1066 }
1067
1068 LOCAL int
cw7501_finalize(scgp,pad,fixed)1069 cw7501_finalize(scgp, pad, fixed)
1070 SCSI *scgp;
1071 int pad;
1072 int fixed;
1073 {
1074 register struct scg_cmd *scmd = scgp->scmd;
1075
1076 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1077 scmd->flags = SCG_DISRE_ENA;
1078 scmd->cdb_len = SC_G1_CDBLEN;
1079 scmd->sense_len = CCS_SENSE_LEN;
1080 scmd->timeout = 8 * 60; /* Needs up to 4 minutes */
1081 scmd->cdb.g1_cdb.cmd = 0xE3;
1082 scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1083 scmd->cdb.cmd_cdb[1] = pad ? 1 : 0;
1084 scmd->cdb.cmd_cdb[8] = fixed & 0x03;
1085
1086 scgp->cmdname = "cw7501 finalize";
1087
1088 if (scg_cmd(scgp) < 0)
1089 return (-1);
1090 return (0);
1091 }
1092