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 /* @(#)wm_packet.c 1.25 04/03/01 Copyright 1995, 1997, 2001-2004 J. Schilling */
15 * CDR write method abtraction layer
16 * packet writing intercace routines
18 * Copyright (c) 1995, 1997, 2001-2004 J. Schilling
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2
23 * as published by the Free Software Foundation.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License along with
31 * this program; see the file COPYING. If not, write to the Free Software
32 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
44 #include <usal/scsitransp.h>
52 extern char *buf; /* The transfer buffer */
54 int write_packet_data(SCSI *usalp, cdr_t *dp, track_t *trackp);
57 write_packet_data(SCSI *usalp, cdr_t *dp, track_t *trackp)
59 int track = trackp->trackno;
92 if (dp->cdr_dstat->ds_flags & DSF_DVD)
96 if ((*dp->cdr_buffer_cap)(usalp, &bsize, &bfree) < 0)
98 if (bsize == 0) /* If we have no (known) buffer, we cannot */
99 bsize = -1L; /* retrieve the buffer fill ratio */
101 dp->cdr_dstat->ds_buflow = 0;
104 if (trackp->xfp != NULL)
105 f = xfileno(trackp->xfp);
107 isaudio = is_audio(trackp);
108 tracksize = trackp->tracksize;
109 startsec = trackp->trackstart;
111 secsize = trackp->secsize;
112 secspt = trackp->secspt;
113 bytespt = secsize * secspt;
115 pad = !isaudio && is_pad(trackp); /* Pad only data tracks */
118 printf("secsize:%d secspt:%d bytespt:%d audio:%d pad:%d\n",
119 secsize, secspt, bytespt, isaudio, pad);
124 printf("\rTrack %02d: 0 of %4lld MB written.",
125 track, tracksize >> 20);
127 printf("\rTrack %02d: 0 MB written.", track);
132 gettimeofday(&tlast, (struct timezone *)0);
134 bytes_to_read = bytespt;
136 if ((tracksize - bytes_read) > bytespt)
137 bytes_to_read = bytespt;
139 bytes_to_read = tracksize - bytes_read;
141 /* XXX next wr addr ??? */
142 count = get_buf(f, trackp, startsec, &bp, bytes_to_read);
144 comerr("read error on input file\n");
148 if (tracksize >= 0 && bytes_read >= tracksize) {
149 count -= bytes_read - tracksize;
150 if (trackp->padsecs == 0 || (bytes_read/secsize) >= 300)
154 if (count < bytespt) {
156 printf("\nNOTICE: reducing block size for last record.\n");
160 if ((amount = count % secsize) != 0) {
161 amount = secsize - amount;
162 fillbytes(&bp[count], amount, '\0');
164 printf("\nWARNING: padding up to secsize.\n");
167 if (is_packet(trackp) && trackp->pktsize > 0) {
168 if (count < bytespt) {
169 amount = bytespt - count;
171 printf("\nWARNING: padding remainder of packet.\n");
176 secspt = count / secsize;
177 if (trackp->padsecs == 0 || (bytes_read/secsize) >= 300)
183 /* XXX Fixed-packet writes can be very slow*/
184 if (is_packet(trackp) && trackp->pktsize > 0)
185 usal_settimeout(usalp, 100);
187 if (is_packet(trackp) && trackp->pktsize == 0) {
188 if ((*dp->cdr_next_wr_address)(usalp, trackp, &nextblock) == 0) {
190 * Some drives (e.g. Ricoh MPS6201S) do not
191 * increment the Next Writable Address value to
192 * point to the beginning of a new packet if
193 * their write buffer has underflowed.
195 if (retried && nextblock == startsec) {
198 startsec = nextblock;
203 amount = write_secs(usalp, dp, bp, startsec, bytespt, secspt, islast);
205 if (is_packet(trackp) && trackp->pktsize == 0 && !retried) {
206 printf("%swrite track data: error after %lld bytes, retry with new packet\n",
207 neednl?"\n":"", bytes);
212 printf("%swrite track data: error after %lld bytes\n",
213 neednl?"\n":"", bytes);
217 startsec += amount / secsize;
219 if (lverbose && (bytes >= (savbytes + 0x100000))) {
221 int nsecs = (bytes - savbytes) / secsize;
224 gettimeofday(&tcur, (struct timezone *)0);
225 printf("\rTrack %02d: %4lld", track, bytes >> 20);
227 printf(" of %4lld MB", tracksize >> 20);
231 fper = fifo_percent(TRUE);
233 printf(" (fifo %3d%%)", fper);
235 if (bsize > 0) { /* buffer size known */
237 per = (*dp->cdr_buffer_cap)(usalp, (long *)0, &bfree);
240 per = 100*(bsize - bfree) / bsize;
242 dp->cdr_dstat->ds_buflow++;
243 if (per < (int)dp->cdr_dstat->ds_minbuf &&
244 (startsec*secsize) > bsize) {
245 dp->cdr_dstat->ds_minbuf = per;
247 printf(" [buf %3d%%]", per);
249 printf(" %3ld %3ld", bsize >> 10, bfree >> 10);
255 tlast.tv_sec = tcur.tv_sec - tlast.tv_sec;
256 tlast.tv_usec = tcur.tv_usec - tlast.tv_usec;
257 while (tlast.tv_usec < 0) {
258 tlast.tv_usec += 1000000;
261 fspeed = (nsecs / secsps) /
262 (tlast.tv_sec * 1.0 + tlast.tv_usec * 0.000001);
265 printf(" %5.1fx", fspeed);
267 savbytes = (bytes >> 20) << 20;
272 } while (tracksize < 0 || bytes_read < tracksize);
274 if ((bytes / secsize) < 300) {
275 if ((trackp->padsecs + (bytes / secsize)) < 300)
276 trackp->padsecs = 300 - (bytes / secsize);
278 if (trackp->padsecs > 0) {
282 * pad_track() is based on secsize. Compute the amount of bytes
283 * assumed by pad_track().
285 padbytes = (Llong)trackp->padsecs * secsize;
291 if ((padbytes >> 20) > 0) {
293 } else if (lverbose) {
294 printf("Track %02d: writing %3lld KB of pad data.\n",
295 track, (Llong)(padbytes >> 10));
298 pad_track(usalp, dp, trackp, startsec, padbytes,
301 startsec += savbytes / secsize;
303 printf("%sTrack %02d: Total bytes read/written: %lld/%lld (%lld sectors).\n",
304 neednl?"\n":"", track, bytes_read, bytes, bytes/secsize);