1 /* @(#)wm_packet.c 1.31 10/12/19 Copyright 1995, 1997, 2001-2010 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)wm_packet.c 1.31 10/12/19 Copyright 1995, 1997, 2001-2010 J. Schilling";
6 #endif
7 /*
8 * CDR write method abtraction layer
9 * packet writing intercace routines
10 *
11 * Copyright (c) 1995, 1997, 2001-2010 J. Schilling
12 */
13 /*
14 * The contents of this file are subject to the terms of the
15 * Common Development and Distribution License, Version 1.0 only
16 * (the "License"). You may not use this file except in compliance
17 * with the License.
18 *
19 * See the file CDDL.Schily.txt in this distribution for details.
20 * A copy of the CDDL is also available via the Internet at
21 * http://www.opensource.org/licenses/cddl1.txt
22 *
23 * When distributing Covered Code, include this CDDL HEADER in each
24 * file and include the License file CDDL.Schily.txt from this distribution.
25 */
26
27 #include <schily/mconfig.h>
28 #include <schily/stdio.h>
29 #include <schily/stdlib.h>
30 #include <schily/unistd.h>
31 #include <schily/time.h>
32 #include <schily/standard.h>
33 #include <schily/utypes.h>
34 #include <schily/schily.h>
35 #include <schily/nlsdefs.h>
36
37 #include <scg/scsitransp.h>
38 #include "cdrecord.h"
39 #include "xio.h"
40
41 extern int debug;
42 extern int verbose;
43 extern int lverbose;
44
45 extern char *buf; /* The transfer buffer */
46
47 EXPORT int write_packet_data __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
48
49 EXPORT int
write_packet_data(scgp,dp,trackp)50 write_packet_data(scgp, dp, trackp)
51 SCSI *scgp;
52 cdr_t *dp;
53 track_t *trackp;
54 {
55 int track = trackp->trackno;
56 int f = -1;
57 int isaudio;
58 long startsec;
59 Llong bytes_read = 0;
60 Llong bytes = 0;
61 Llong savbytes = 0;
62 int count;
63 Llong tracksize;
64 int secsize;
65 int secspt;
66 int bytespt;
67 int bytes_to_read;
68 long amount;
69 int pad;
70 int retried;
71 long nextblock;
72 BOOL neednl = FALSE;
73 BOOL islast = FALSE;
74 char *bp = buf;
75 struct timeval tlast;
76 struct timeval tcur;
77 float secsps = 75.0;
78 long bsize;
79 long bfree;
80 #define BCAP
81 #ifdef BCAP
82 int per = 0;
83 #ifdef XBCAP
84 int oper = -1;
85 #endif
86 #endif
87
88 if (dp->cdr_dstat->ds_flags & DSF_DVD)
89 secsps = 676.27;
90 if (dp->cdr_dstat->ds_flags & DSF_BD)
91 secsps = 2195.07;
92
93 scgp->silent++;
94 if ((*dp->cdr_buffer_cap)(scgp, &bsize, &bfree) < 0)
95 bsize = -1L;
96 if (bsize == 0) /* If we have no (known) buffer, we cannot */
97 bsize = -1L; /* retrieve the buffer fill ratio */
98 else
99 dp->cdr_dstat->ds_buflow = 0;
100 scgp->silent--;
101
102 if (trackp->xfp != NULL)
103 f = xfileno(trackp->xfp);
104
105 isaudio = is_audio(trackp);
106 tracksize = trackp->tracksize;
107 startsec = trackp->trackstart;
108
109 secsize = trackp->secsize;
110 secspt = trackp->secspt;
111 bytespt = secsize * secspt;
112
113 pad = !isaudio && is_pad(trackp); /* Pad only data tracks */
114
115 if (debug) {
116 printf(_("secsize:%d secspt:%d bytespt:%d audio:%d pad:%d\n"),
117 secsize, secspt, bytespt, isaudio, pad);
118 }
119
120 if (lverbose) {
121 if (tracksize > 0)
122 printf(_("\rTrack %02d: 0 of %4lld MB written."),
123 track, tracksize >> 20);
124 else
125 printf(_("\rTrack %02d: 0 MB written."), track);
126 flush();
127 neednl = TRUE;
128 }
129
130 gettimeofday(&tlast, (struct timezone *)0);
131 do {
132 bytes_to_read = bytespt;
133 if (tracksize > 0) {
134 if ((tracksize - bytes_read) > bytespt)
135 bytes_to_read = bytespt;
136 else
137 bytes_to_read = tracksize - bytes_read;
138 }
139 /* XXX next wr addr ??? */
140 count = get_buf(f, trackp, startsec, &bp, bytes_to_read);
141 if (count < 0)
142 comerr(_("read error on input file\n"));
143 if (count == 0)
144 break;
145 bytes_read += count;
146 if (tracksize >= 0 && bytes_read >= tracksize) {
147 count -= bytes_read - tracksize;
148 if (trackp->padsecs == 0 || (bytes_read/secsize) >= 300)
149 islast = TRUE;
150 }
151
152 if (count < bytespt) {
153 if (debug) {
154 printf(_("\nNOTICE: reducing block size for last record.\n"));
155 neednl = FALSE;
156 }
157
158 if ((amount = count % secsize) != 0) {
159 amount = secsize - amount;
160 fillbytes(&bp[count], amount, '\0');
161 count += amount;
162 printf(_("\nWARNING: padding up to secsize.\n"));
163 neednl = FALSE;
164 }
165 if (is_packet(trackp) && trackp->pktsize > 0) {
166 if (count < bytespt) {
167 amount = bytespt - count;
168 count += amount;
169 printf(_("\nWARNING: padding remainder of packet.\n"));
170 neednl = FALSE;
171 }
172 }
173 bytespt = count;
174 secspt = count / secsize;
175 if (trackp->padsecs == 0 || (bytes_read/secsize) >= 300)
176 islast = TRUE;
177 }
178
179 retried = 0;
180 retry:
181 /* XXX Fixed-packet writes can be very slow*/
182 if (is_packet(trackp) && trackp->pktsize > 0)
183 scg_settimeout(scgp, 100);
184 /* XXX */
185 if (is_packet(trackp) && trackp->pktsize == 0) {
186 if ((*dp->cdr_next_wr_address)(scgp, trackp, &nextblock) == 0) {
187 /*
188 * Some drives (e.g. Ricoh MPS6201S) do not
189 * increment the Next Writable Address value to
190 * point to the beginning of a new packet if
191 * their write buffer has underflowed.
192 */
193 if (retried && nextblock == startsec) {
194 startsec += 7;
195 } else {
196 startsec = nextblock;
197 }
198 }
199 }
200
201 amount = write_secs(scgp, dp, bp, startsec, bytespt, secspt, islast);
202 if (amount < 0) {
203 if (is_packet(trackp) && trackp->pktsize == 0 && !retried) {
204 printf(_("%swrite track data: error after %lld bytes, retry with new packet\n"),
205 neednl?"\n":"", bytes);
206 retried = 1;
207 neednl = FALSE;
208 goto retry;
209 }
210 printf(_("%swrite track data: error after %lld bytes\n"),
211 neednl?"\n":"", bytes);
212 return (-1);
213 }
214 bytes += amount;
215 startsec += amount / secsize;
216
217 if (lverbose && (bytes >= (savbytes + 0x100000))) {
218 int fper;
219 int nsecs = (bytes - savbytes) / secsize;
220 float fspeed;
221
222 gettimeofday(&tcur, (struct timezone *)0);
223 printf(_("\rTrack %02d: %4lld"), track, bytes >> 20);
224 if (tracksize > 0)
225 printf(_(" of %4lld MB"), tracksize >> 20);
226 else
227 printf(" MB");
228 printf(_(" written"));
229 fper = fifo_percent(TRUE);
230 if (fper >= 0)
231 printf(" (fifo %3d%%)", fper);
232 #ifdef BCAP
233 if (bsize > 0) { /* buffer size known */
234 scgp->silent++;
235 per = (*dp->cdr_buffer_cap)(scgp, (long *)0, &bfree);
236 scgp->silent--;
237 if (per >= 0) {
238 per = 100*(bsize - bfree) / bsize;
239 if (per < 5)
240 dp->cdr_dstat->ds_buflow++;
241 if (per < (int)dp->cdr_dstat->ds_minbuf &&
242 (startsec*secsize) > bsize) {
243 dp->cdr_dstat->ds_minbuf = per;
244 }
245 printf(" [buf %3d%%]", per);
246 #ifdef BCAPDBG
247 printf(" %3ld %3ld", bsize >> 10, bfree >> 10);
248 #endif
249 }
250 }
251 #endif
252
253 tlast.tv_sec = tcur.tv_sec - tlast.tv_sec;
254 tlast.tv_usec = tcur.tv_usec - tlast.tv_usec;
255 while (tlast.tv_usec < 0) {
256 tlast.tv_usec += 1000000;
257 tlast.tv_sec -= 1;
258 }
259 fspeed = (nsecs / secsps) /
260 (tlast.tv_sec * 1.0 + tlast.tv_usec * 0.000001);
261 if (fspeed > 999.0)
262 fspeed = 999.0;
263 printf(" %5.1fx", fspeed);
264 printf(".");
265 savbytes = (bytes >> 20) << 20;
266 flush();
267 neednl = TRUE;
268 tlast = tcur;
269 }
270 } while (tracksize < 0 || bytes_read < tracksize);
271
272 if ((bytes / secsize) < 300) {
273 if ((trackp->padsecs + (bytes / secsize)) < 300)
274 trackp->padsecs = 300 - (bytes / secsize);
275 }
276 if (trackp->padsecs > 0) {
277 Llong padbytes;
278
279 /*
280 * pad_track() is based on secsize. Compute the amount of bytes
281 * assumed by pad_track().
282 */
283 padbytes = (Llong)trackp->padsecs * secsize;
284
285 if (neednl) {
286 printf("\n");
287 neednl = FALSE;
288 }
289 if ((padbytes >> 20) > 0) {
290 neednl = TRUE;
291 } else if (lverbose) {
292 printf(_("Track %02d: writing %3lld KB of pad data.\n"),
293 track, (Llong)(padbytes >> 10));
294 neednl = FALSE;
295 }
296 pad_track(scgp, dp, trackp, startsec, padbytes,
297 TRUE, &savbytes);
298 bytes += savbytes;
299 startsec += savbytes / secsize;
300 }
301 printf(_("%sTrack %02d: Total bytes read/written: %lld/%lld (%lld sectors).\n"),
302 neednl?"\n":"", track, bytes_read, bytes, bytes/secsize);
303 return (0);
304 }
305