2 * This file has been modified for the cdrkit suite.
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).
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.
13 /* @(#)drv_7501.c 1.16 05/05/16 Copyright 2003-2005 J. Schilling */
15 * Device driver for the Masushita CW-7501
17 * Copyright (c) 2003-2005 J. Schilling
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
27 * 0x23 Dummy/Write Information Seite 126
28 * 0x24 CD-R disk information Seite 127
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.
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.
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.
63 #include <usal/usalcmd.h>
64 #include <usal/scsidefs.h>
65 #include <usal/scsireg.h>
66 #include <usal/scsitransp.h>
78 #if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */
80 struct cw7501_mode_page_20 { /* Speed control */
81 MP_P_CODE; /* parsave & pagecode */
82 Uchar p_len; /* 0x02 = 2 Bytes */
88 #else /* Motorola byteorder */
90 struct cw7501_mode_page_20 { /* Speed control */
91 MP_P_CODE; /* parsave & pagecode */
92 Uchar p_len; /* 0x02 = 2 Bytes */
99 #if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */
101 struct cw7501_mode_page_21 { /* MCN */
102 MP_P_CODE; /* parsave & pagecode */
103 Uchar p_len; /* 0x12 = 20 Bytes */
111 #else /* Motorola byteorder */
113 struct cw7501_mode_page_21 { /* MCN */
114 MP_P_CODE; /* parsave & pagecode */
115 Uchar p_len; /* 0x12 = 20 Bytes */
125 #if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */
127 struct cw7501_mode_page_22 { /* ISRC */
128 MP_P_CODE; /* parsave & pagecode */
129 Uchar p_len; /* 0x12 = 20 Bytes */
137 #else /* Motorola byteorder */
139 struct cw7501_mode_page_22 { /* ISRC */
140 MP_P_CODE; /* parsave & pagecode */
141 Uchar p_len; /* 0x12 = 20 Bytes */
150 #if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */
152 struct cw7501_mode_page_23 { /* Dummy / Write information */
153 MP_P_CODE; /* parsave & pagecode */
154 Uchar p_len; /* 0x02 = 2 Bytes */
161 #else /* Motorola byteorder */
163 struct cw7501_mode_page_23 { /* Dummy / Write information */
164 MP_P_CODE; /* parsave & pagecode */
165 Uchar p_len; /* 0x02 = 2 Bytes */
173 struct cw7501_mode_page_24 { /* CD-R Disk information */
174 MP_P_CODE; /* parsave & pagecode */
175 Uchar p_len; /* 0x0A = 12 Bytes */
182 struct cw7501_mode_data {
183 struct scsi_mode_header header;
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;
194 * Mode for read track information
196 #define TI_TRACKINFO_R 0
199 #define TI_TRACKINFO 3
206 Uchar nwa_freeblocks[4];
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 */
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);
254 * Prinzipiell geht auch: CDR_PACKET & CDR_SRAW96R
256 CDR_TAO|CDR_SAO|CDR_TRAYLOAD,
260 "driver for Matsushita/Panasonic CW-7501",
269 buf_dummy, /* RD buffer cap not supp. */
270 cmd_dummy, /* recovery_needed */
271 (int(*)(SCSI *, cdr_t *, int))cmd_dummy, /* recover */
275 cw7501_reserve_track,
283 cmd_dummy, /* close seession */
284 cmd_dummy, /* abort */
287 cmd_dummy, /* stats */
290 (int(*)(SCSI *, caddr_t, int, int))NULL, /* no OPC */
291 cmd_dummy, /* opt1 */
292 cmd_dummy, /* opt2 */
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 */
302 "\210\000Illegal Que Sheet (DAO parameter)", /* 88 00 */
303 "\211\000Inappropriate command", /* 89 00 */
305 "\250\000Audio Play operation Not in Progress", /* A8 00 */
306 "\251\000Buffer Overrun", /* A9 00 */
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 */
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 */
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 */
331 cw7501_attach(SCSI *usalp, cdr_t *dp)
333 usal_setnonstderrs(usalp, sd_cw7501_error_str);
338 cw7501_init(SCSI *usalp, cdr_t *dp)
340 return (cw7501_speed_select(usalp, dp, NULL));
344 cw7501_getdisktype(SCSI *usalp, cdr_t *dp)
349 dstat_t *dsp = dp->cdr_dstat;
353 fillbytes((caddr_t)buf, sizeof (buf), '\0');
354 ret = cw7501_read_trackinfo(usalp, buf, 32, 0, 0);
356 usal_prbytes("TI EXIST-R (0): ", buf, 32 -usal_getresid(usalp));
358 fillbytes((caddr_t)buf, sizeof (buf), '\0');
359 ret = cw7501_read_trackinfo(usalp, buf, 32, 0, 1);
361 usal_prbytes("TI NWA (1): ", buf, 32 -usal_getresid(usalp));
363 fillbytes((caddr_t)buf, sizeof (buf), '\0');
364 ret = cw7501_read_trackinfo(usalp, buf, 32, 0, 2);
366 usal_prbytes("TI PMA (2): ", buf, 32 -usal_getresid(usalp));
368 fillbytes((caddr_t)buf, sizeof (buf), '\0');
369 ret = cw7501_read_trackinfo(usalp, buf, 32, 0, 3);
371 usal_prbytes("TI EXIST-ROM (3): ", buf, 32 -usal_getresid(usalp));
375 fillbytes((caddr_t)buf, sizeof (buf), '\0');
378 ret = cw7501_read_trackinfo(usalp, buf, 12, 0, TI_NWA);
380 (dsp->ds_cdrflags & (RF_WRITE|RF_BLANK)) == RF_WRITE) {
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.
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);
396 maxb = a_to_u_4_byte(&buf[8]);
400 dsp->ds_maxblocks = maxb;
402 return (drive_getdisktype(usalp, dp));
407 cw7501_speed_select(SCSI *usalp, cdr_t *dp, int *speedp)
409 struct scsi_mode_page_header *mp;
413 struct cw7501_mode_page_20 *xp20;
414 struct cw7501_mode_data md;
417 BOOL dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
422 fillbytes((caddr_t)mode, sizeof (mode), '\0');
424 if (!get_mode_params(usalp, page, "Speed information",
425 (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
431 mp = (struct scsi_mode_page_header *)
432 (mode + sizeof (struct scsi_mode_header) +
433 ((struct scsi_mode_header *)mode)->blockdesc_len);
435 xp20 = (struct cw7501_mode_page_20 *)mp;
439 fillbytes((caddr_t)&md, sizeof (md), '\0');
441 count = sizeof (struct scsi_mode_header) +
442 sizeof (struct cw7501_mode_page_20);
444 md.pagex.page20.p_code = 0x20;
445 md.pagex.page20.p_len = 0x02;
446 md.pagex.page20.speed = speed;
448 if (mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2) < 0)
451 fillbytes((caddr_t)&md, sizeof (md), '\0');
453 count = sizeof (struct scsi_mode_header) +
454 sizeof (struct cw7501_mode_page_23);
456 md.pagex.page23.p_code = 0x23;
457 md.pagex.page23.p_len = 0x02;
458 md.pagex.page23.dummy = dummy?1:0;
460 return (mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2));
464 cw7501_next_wr_addr(SCSI *usalp, track_t *trackp, long *ap)
466 struct cw7501_nwa *nwa;
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
477 nwa = (struct cw7501_nwa *)buf;
479 if (trackp != 0 && trackp->track > 0 && is_packet(trackp)) {
480 fillbytes((caddr_t)buf, sizeof (buf), '\0');
483 result = cw7501_read_trackinfo(usalp, buf, sizeof (*nwa),
490 if (cw7501_read_trackinfo(usalp, buf, sizeof (*nwa),
495 usal_prbytes("track info:", buf,
496 12-usal_getresid(usalp));
497 next_addr = a_to_4_byte(&nwa->nwa_nwa);
499 * XXX Für TAO definitiv notwendig.
500 * XXX ABhängig von Auto-Pregap?
502 /* XXX */ next_addr += 150;
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 */)
516 if (lverbose > 1 && islast)
517 printf("\nWriting last record for this track.\n");
519 return (write_xg0(usalp, bp, 0, size, blocks));
523 cw7501_write_leadin(SCSI *usalp, cdr_t *dp, track_t *trackp)
528 if (wm_base(dp->cdr_dstat->ds_wrmode) == WM_SAO) {
529 if (debug || lverbose) {
530 printf("Sending CUE sheet...\n");
533 if ((*dp->cdr_send_cue)(usalp, dp, trackp) < 0) {
534 errmsgno(EX_BAD, "Cannot send CUE sheet.\n");
539 * Next writable address function does not work in DAO
540 * mode for this writer, so we just assume -150.
544 printf("SAO startsec: %ld\n", startsec);
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;
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 */
575 cw7501_open_track(SCSI *usalp, cdr_t *dp, track_t *trackp)
577 struct scsi_mode_page_header *mp;
581 struct cw7501_mode_page_23 *xp23;
583 if (!is_tao(trackp) && !is_packet(trackp)) {
584 if (trackp->pregapsize > 0 && (trackp->flags & TI_PREGAP) == 0) {
586 printf("Writing pregap for track %d at %ld\n",
587 (int)trackp->trackno,
588 trackp->trackstart-trackp->pregapsize);
591 * XXX Do we need to check isecsize too?
593 pad_track(usalp, dp, trackp,
594 trackp->trackstart-trackp->pregapsize,
595 (Llong)trackp->pregapsize*trackp->secsize,
601 if (select_secsize(usalp, trackp->secsize) < 0)
604 if (!get_mode_params(usalp, page, "Dummy/autopg information",
605 (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
611 mp = (struct scsi_mode_page_header *)
612 (mode + sizeof (struct scsi_mode_header) +
613 ((struct scsi_mode_header *)mode)->blockdesc_len);
615 xp23 = (struct cw7501_mode_page_23 *)mp;
617 if (!set_mode_params(usalp, "Dummy/autopg page", mode, len, 0, trackp->secsize))
621 * Set write modes for next track.
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)
635 cw7501_close_track(SCSI *usalp, cdr_t *dp, track_t *trackp)
637 if (!is_tao(trackp) && !is_packet(trackp)) {
640 return (scsi_flush_cache(usalp, FALSE));
644 cw7501_open_session(SCSI *usalp, cdr_t *dp, track_t *trackp)
646 struct cw7501_mode_data md;
649 if (select_secsize(usalp, 2048) < 0)
653 * Disable Auto Pregap when writing in SAO mode.
655 if (!is_tao(trackp) && !is_packet(trackp)) {
656 struct scsi_mode_page_header *mp;
660 struct cw7501_mode_page_23 *xp23;
662 if (!get_mode_params(usalp, page, "Dummy/autopg information",
663 (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
669 mp = (struct scsi_mode_page_header *)
670 (mode + sizeof (struct scsi_mode_header) +
671 ((struct scsi_mode_header *)mode)->blockdesc_len);
673 xp23 = (struct cw7501_mode_page_23 *)mp;
675 if (!set_mode_params(usalp, "Dummy/autopg page", mode, len, 0, trackp->secsize))
682 * Set Disk Type and Disk ID.
684 fillbytes((caddr_t)&md, sizeof (md), '\0');
686 count = sizeof (struct scsi_mode_header) +
687 sizeof (struct cw7501_mode_page_24);
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);
694 return (mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2));
698 cw7501_fixate(SCSI *usalp, cdr_t *dp, track_t *trackp)
700 if (!is_tao(trackp) && !is_packet(trackp)) {
701 return (scsi_flush_cache(usalp, FALSE));
704 * 0x00 Finalize Disk (not appendable)
705 * 0x01 Finalize Session (allow next session)
706 * 0x10 Finalize track (variable packet writing) - Must fluch cache before
708 return (cw7501_finalize(usalp, 0, (track_base(trackp)->tracktype & TOCF_MULTI) ? 0x01 : 0x00));
711 /*--------------------------------------------------------------------------*/
714 cw7501_gen_cue(track_t *trackp, void *vcuep, BOOL needgap)
716 int tracks = trackp->tracks;
718 struct cw7501_cue **cuep = vcuep;
719 struct cw7501_cue *cue;
720 struct cw7501_cue *cp;
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];
737 if (trackp[i].isrc) { /* MCN or ISRC */
739 cue = realloc(cue, ncue * sizeof (*cue));
742 cp->cs_ctladr = 0x02;
743 movebytes(&trackp[i].isrc[0], &cp->cs_tno, 7);
745 cp->cs_ctladr = 0x02;
746 movebytes(&trackp[i].isrc[7], &cp->cs_tno, 7);
748 cp->cs_ctladr = 0x03;
750 movebytes(&trackp[i].isrc[0], &cp->cs_index, 6);
752 cp->cs_ctladr = 0x03;
754 movebytes(&trackp[i].isrc[6], &cp->cs_index, 6);
757 if (i == 0) { /* Lead in */
758 lba_to_msf(-150, &m);
759 cue = realloc(cue, ++ncue * sizeof (*cue));
761 fillcue(cp, ctl|0x01, i, 0, df, 0, &m);
765 if (is_scms(&trackp[i]))
767 pgsize = trackp[i].pregapsize;
768 if (pgsize == 0 && needgap)
770 lba_to_msf(trackp[i].trackstart-pgsize, &m);
771 cue = realloc(cue, ++ncue * sizeof (*cue));
773 fillcue(cp, ctl|0x01, i, 0, df, scms, &m);
775 if (trackp[i].nindex == 1) {
776 lba_to_msf(trackp[i].trackstart, &m);
777 cue = realloc(cue, ++ncue * sizeof (*cue));
779 fillcue(cp, ctl|0x01, i, 1, df, scms, &m);
784 ncue += trackp[i].nindex;
785 idxlist = trackp[i].tindex;
786 cue = realloc(cue, ncue * sizeof (*cue));
788 for (idx = 1; idx <= trackp[i].nindex; idx++) {
789 lba_to_msf(trackp[i].trackstart + idxlist[idx], &m);
791 fillcue(cp, ctl|0x01, i, idx, df, scms, &m);
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));
802 fillcue(cp, ctl|0x01, 0xAA, 1, df, 0, &m);
805 for (i = 0; i < ncue; i++) {
806 usal_prbytes("", (Uchar *)&cue[i], 8);
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 */)
827 cp->cs_tno = to_bcd(tno);
830 cp->cs_index = to_bcd(idx);
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);
841 cw7501_send_cue(SCSI *usalp, cdr_t *dp, track_t *trackp)
843 struct cw7501_cue *cp;
847 struct timeval starttime;
848 struct timeval stoptime;
851 disktype = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
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);
859 ncue = (*dp->cdr_gen_cue)(trackp, &cp, FALSE);
861 starttime.tv_sec = 0;
862 starttime.tv_usec = 0;
863 stoptime = starttime;
864 gettimeofday(&starttime, (struct timezone *)0);
867 ret = cw7501_write_dao(usalp, (Uchar *)cp, ncue*8, disktype);
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);
876 if (ret >= 0 && lverbose) {
877 gettimeofday(&stoptime, (struct timezone *)0);
878 prtimediff("Write Lead-in time: ", &starttime, &stoptime);
883 /*--------------------------------------------------------------------------*/
885 cw7501_rezero(SCSI *usalp, int reset, int dwreset)
887 register struct usal_cmd *scmd = usalp->scmd;
889 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
890 scmd->addr = (caddr_t)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;
900 usalp->cmdname = "cw7501 rezero";
902 return (usal_cmd(usalp));
907 cw7501_read_trackinfo(SCSI *usalp, Uchar *bp, int count, int track, int mode)
909 register struct usal_cmd *scmd = usalp->scmd;
911 fillbytes((caddr_t) scmd, sizeof (*scmd), '\0');
912 scmd->addr = (caddr_t)bp;
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;
923 usalp->cmdname = "cw7501 read_track_information";
925 if (usal_cmd(usalp) < 0)
932 cw7501_write_dao(SCSI *usalp, Uchar *bp, int len, int disktype)
934 register struct usal_cmd *scmd = usalp->scmd;
936 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
937 scmd->addr = (caddr_t)bp;
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);
947 usalp->cmdname = "cw7501 write_dao";
949 if (usal_cmd(usalp) < 0)
955 * XXX CW-7501 also needs "control", so we need to make a different
956 * XXX driver interface.
959 cw7501_reserve_track(SCSI *usalp, unsigned long len)
961 register struct usal_cmd *scmd = usalp->scmd;
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);
972 usalp->cmdname = "cw7501 reserve_track";
974 comerrno(EX_BAD, "Control (as in set mode) missing.\n");
976 if (usal_cmd(usalp) < 0)
982 cw7501_set_mode(SCSI *usalp, int phys_form, int control, int subc,
983 int alt, int trackno, int tindex, int packet_size,
986 register struct usal_cmd *scmd = usalp->scmd;
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;
1003 usalp->cmdname = "cw7501 set_mode";
1005 if (usal_cmd(usalp) < 0)
1011 cw7501_finalize(SCSI *usalp, int pad, int fixed)
1013 register struct usal_cmd *scmd = usalp->scmd;
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;
1025 usalp->cmdname = "cw7501 finalize";
1027 if (usal_cmd(usalp) < 0)