diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-12-31 05:04:42 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-12-31 05:04:42 +0400 |
commit | 71dc8760ff4de5f365330d1bc571d934deb54af9 (patch) | |
tree | 7346d42a282562a3937d82307012b5857d642ce6 /wodim/wm_packet.c | |
download | cdrkit-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.c | 306 |
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); +} |