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