summaryrefslogtreecommitdiff
path: root/wodim/wm_packet.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-12-31 05:04:42 +0400
committerIgor Pashev <pashev.igor@gmail.com>2012-12-31 05:04:42 +0400
commit71dc8760ff4de5f365330d1bc571d934deb54af9 (patch)
tree7346d42a282562a3937d82307012b5857d642ce6 /wodim/wm_packet.c
downloadcdrkit-71dc8760ff4de5f365330d1bc571d934deb54af9.tar.gz
Imported Upstream version 1.1.11upstream/1.1.11upstream
Diffstat (limited to 'wodim/wm_packet.c')
-rw-r--r--wodim/wm_packet.c306
1 files changed, 306 insertions, 0 deletions
diff --git a/wodim/wm_packet.c b/wodim/wm_packet.c
new file mode 100644
index 0000000..9566a52
--- /dev/null
+++ b/wodim/wm_packet.c
@@ -0,0 +1,306 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)wm_packet.c 1.25 04/03/01 Copyright 1995, 1997, 2001-2004 J. Schilling */
+/*
+ * CDR write method abtraction layer
+ * packet writing intercace routines
+ *
+ * Copyright (c) 1995, 1997, 2001-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <timedefs.h>
+#include <standard.h>
+#include <utypes.h>
+#include <schily.h>
+
+#include <usal/scsitransp.h>
+#include "wodim.h"
+#include "xio.h"
+
+extern int debug;
+extern int verbose;
+extern int lverbose;
+
+extern char *buf; /* The transfer buffer */
+
+int write_packet_data(SCSI *usalp, cdr_t *dp, track_t *trackp);
+
+int
+write_packet_data(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+ int track = trackp->trackno;
+ int f = -1;
+ int isaudio;
+ long startsec;
+ Llong bytes_read = 0;
+ Llong bytes = 0;
+ Llong savbytes = 0;
+ int count;
+ Llong tracksize;
+ int secsize;
+ int secspt;
+ int bytespt;
+ long amount;
+ int pad;
+ int retried;
+ long nextblock;
+ int bytes_to_read;
+ BOOL neednl = FALSE;
+ BOOL islast = FALSE;
+ char *bp = buf;
+ struct timeval tlast;
+ struct timeval tcur;
+ float secsps = 75.0;
+long bsize;
+long bfree;
+#define BCAP
+#ifdef BCAP
+int per;
+#ifdef XBCAP
+int oper = -1;
+#endif
+#endif
+
+ if (dp->cdr_dstat->ds_flags & DSF_DVD)
+ secsps = 676.27;
+
+ usalp->silent++;
+ if ((*dp->cdr_buffer_cap)(usalp, &bsize, &bfree) < 0)
+ bsize = -1L;
+ if (bsize == 0) /* If we have no (known) buffer, we cannot */
+ bsize = -1L; /* retrieve the buffer fill ratio */
+ else
+ dp->cdr_dstat->ds_buflow = 0;
+ usalp->silent--;
+
+ if (trackp->xfp != NULL)
+ f = xfileno(trackp->xfp);
+
+ isaudio = is_audio(trackp);
+ tracksize = trackp->tracksize;
+ startsec = trackp->trackstart;
+
+ secsize = trackp->secsize;
+ secspt = trackp->secspt;
+ bytespt = secsize * secspt;
+
+ pad = !isaudio && is_pad(trackp); /* Pad only data tracks */
+
+ if (debug) {
+ printf("secsize:%d secspt:%d bytespt:%d audio:%d pad:%d\n",
+ secsize, secspt, bytespt, isaudio, pad);
+ }
+
+ if (lverbose) {
+ if (tracksize > 0)
+ printf("\rTrack %02d: 0 of %4lld MB written.",
+ track, tracksize >> 20);
+ else
+ printf("\rTrack %02d: 0 MB written.", track);
+ flush();
+ neednl = TRUE;
+ }
+
+ gettimeofday(&tlast, (struct timezone *)0);
+ do {
+ bytes_to_read = bytespt;
+ if (tracksize > 0) {
+ if ((tracksize - bytes_read) > bytespt)
+ bytes_to_read = bytespt;
+ else
+ bytes_to_read = tracksize - bytes_read;
+ }
+ /* XXX next wr addr ??? */
+ count = get_buf(f, trackp, startsec, &bp, bytes_to_read);
+ if (count < 0)
+ comerr("read error on input file\n");
+ if (count == 0)
+ break;
+ bytes_read += count;
+ if (tracksize >= 0 && bytes_read >= tracksize) {
+ count -= bytes_read - tracksize;
+ if (trackp->padsecs == 0 || (bytes_read/secsize) >= 300)
+ islast = TRUE;
+ }
+
+ if (count < bytespt) {
+ if (debug) {
+ printf("\nNOTICE: reducing block size for last record.\n");
+ neednl = FALSE;
+ }
+
+ if ((amount = count % secsize) != 0) {
+ amount = secsize - amount;
+ fillbytes(&bp[count], amount, '\0');
+ count += amount;
+ printf("\nWARNING: padding up to secsize.\n");
+ neednl = FALSE;
+ }
+ if (is_packet(trackp) && trackp->pktsize > 0) {
+ if (count < bytespt) {
+ amount = bytespt - count;
+ count += amount;
+ printf("\nWARNING: padding remainder of packet.\n");
+ neednl = FALSE;
+ }
+ }
+ bytespt = count;
+ secspt = count / secsize;
+ if (trackp->padsecs == 0 || (bytes_read/secsize) >= 300)
+ islast = TRUE;
+ }
+
+ retried = 0;
+ retry:
+ /* XXX Fixed-packet writes can be very slow*/
+ if (is_packet(trackp) && trackp->pktsize > 0)
+ usal_settimeout(usalp, 100);
+ /* XXX */
+ if (is_packet(trackp) && trackp->pktsize == 0) {
+ if ((*dp->cdr_next_wr_address)(usalp, trackp, &nextblock) == 0) {
+ /*
+ * Some drives (e.g. Ricoh MPS6201S) do not
+ * increment the Next Writable Address value to
+ * point to the beginning of a new packet if
+ * their write buffer has underflowed.
+ */
+ if (retried && nextblock == startsec) {
+ startsec += 7;
+ } else {
+ startsec = nextblock;
+ }
+ }
+ }
+
+ amount = write_secs(usalp, dp, bp, startsec, bytespt, secspt, islast);
+ if (amount < 0) {
+ if (is_packet(trackp) && trackp->pktsize == 0 && !retried) {
+ printf("%swrite track data: error after %lld bytes, retry with new packet\n",
+ neednl?"\n":"", bytes);
+ retried = 1;
+ neednl = FALSE;
+ goto retry;
+ }
+ printf("%swrite track data: error after %lld bytes\n",
+ neednl?"\n":"", bytes);
+ return (-1);
+ }
+ bytes += amount;
+ startsec += amount / secsize;
+
+ if (lverbose && (bytes >= (savbytes + 0x100000))) {
+ int fper;
+ int nsecs = (bytes - savbytes) / secsize;
+ float fspeed;
+
+ gettimeofday(&tcur, (struct timezone *)0);
+ printf("\rTrack %02d: %4lld", track, bytes >> 20);
+ if (tracksize > 0)
+ printf(" of %4lld MB", tracksize >> 20);
+ else
+ printf(" MB");
+ printf(" written");
+ fper = fifo_percent(TRUE);
+ if (fper >= 0)
+ printf(" (fifo %3d%%)", fper);
+#ifdef BCAP
+ if (bsize > 0) { /* buffer size known */
+ usalp->silent++;
+ per = (*dp->cdr_buffer_cap)(usalp, (long *)0, &bfree);
+ usalp->silent--;
+ if (per >= 0) {
+ per = 100*(bsize - bfree) / bsize;
+ if (per < 5)
+ dp->cdr_dstat->ds_buflow++;
+ if (per < (int)dp->cdr_dstat->ds_minbuf &&
+ (startsec*secsize) > bsize) {
+ dp->cdr_dstat->ds_minbuf = per;
+ }
+ printf(" [buf %3d%%]", per);
+#ifdef BCAPDBG
+ printf(" %3ld %3ld", bsize >> 10, bfree >> 10);
+#endif
+ }
+ }
+#endif
+
+ tlast.tv_sec = tcur.tv_sec - tlast.tv_sec;
+ tlast.tv_usec = tcur.tv_usec - tlast.tv_usec;
+ while (tlast.tv_usec < 0) {
+ tlast.tv_usec += 1000000;
+ tlast.tv_sec -= 1;
+ }
+ fspeed = (nsecs / secsps) /
+ (tlast.tv_sec * 1.0 + tlast.tv_usec * 0.000001);
+ if (fspeed > 999.0)
+ fspeed = 999.0;
+ printf(" %5.1fx", fspeed);
+ printf(".");
+ savbytes = (bytes >> 20) << 20;
+ flush();
+ neednl = TRUE;
+ tlast = tcur;
+ }
+ } while (tracksize < 0 || bytes_read < tracksize);
+
+ if ((bytes / secsize) < 300) {
+ if ((trackp->padsecs + (bytes / secsize)) < 300)
+ trackp->padsecs = 300 - (bytes / secsize);
+ }
+ if (trackp->padsecs > 0) {
+ Llong padbytes;
+
+ /*
+ * pad_track() is based on secsize. Compute the amount of bytes
+ * assumed by pad_track().
+ */
+ padbytes = (Llong)trackp->padsecs * secsize;
+
+ if (neednl) {
+ printf("\n");
+ neednl = FALSE;
+ }
+ if ((padbytes >> 20) > 0) {
+ neednl = TRUE;
+ } else if (lverbose) {
+ printf("Track %02d: writing %3lld KB of pad data.\n",
+ track, (Llong)(padbytes >> 10));
+ neednl = FALSE;
+ }
+ pad_track(usalp, dp, trackp, startsec, padbytes,
+ TRUE, &savbytes);
+ bytes += savbytes;
+ startsec += savbytes / secsize;
+ }
+ printf("%sTrack %02d: Total bytes read/written: %lld/%lld (%lld sectors).\n",
+ neednl?"\n":"", track, bytes_read, bytes, bytes/secsize);
+ return (0);
+}