1 /*
2  * This file has been modified for the cdrkit suite.
3  *
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).
6  *
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.
10  *
11  */
12 
13 /* @(#)sector.c	1.13 04/03/01 Copyright 2001-2004 J. Schilling */
14 /*
15  *	Functions needed to use libedc_ecc from cdrecord
16  *
17  *	Copyright (c) 2001-2004 J. Schilling
18  */
19 /*
20  * This program is free software; you can redistribute it and/or modify
21  * it under the terms of the GNU General Public License version 2
22  * as published by the Free Software Foundation.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License along with
30  * this program; see the file COPYING.  If not, write to the Free Software
31  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32  */
33 
34 #include <mconfig.h>
35 #include <stdio.h>
36 #include <standard.h>
37 #include <utypes.h>
38 #include <timedefs.h>
39 #include <schily.h>
40 
41 #include "wodim.h"
42 #include "movesect.h"
43 
44 #ifdef	HAVE_LIB_EDC_ECC
45 
46 
47 #define	LAYER2
48 #define	EDC_LAYER2
49 #define	ENCODER
50 #define	EDC_ENCODER
51 #include <ecc.h>
52 
53 #ifdef	DO8
54 #define	HAVE_NEW_LIB_EDC
55 #endif
56 
57 int	encspeed(BOOL be_verbose);
58 void	encsectors(track_t *trackp, Uchar *bp, int address, int nsecs);
59 void	scrsectors(track_t *trackp, Uchar *bp, int address, int nsecs);
60 void	encodesector(Uchar *sp, int sectype, int address);
61 void	fillsector(Uchar *sp, int sectype, int address);
62 
63 /*
64  * Sector types known by lib libedc_ecc:
65  */
66 #ifdef	__comment__
67 				/*   MMC					*/
68 #define	MODE_0		0	/* -> XX  12+4+2336	(12+4uuu von libedc)	*/
69 #define	MODE_1		1	/* -> 8   12+4+2048+288 (124+4uuu+288 von libedc)*/
70 #define	MODE_2		2	/* -> 9	  12+4+2336	(12+4uuu von libedc)	*/
71 #define	MODE_2_FORM_1	3	/* -> 10/11 12+4+8+2048+280 (12+4hhhuuu+280 von libedc)*/
72 #define	MODE_2_FORM_2	4	/* -> 12 (eher 13!) 12+4+8+2324+4 (12+4hhhuuu+4 von libedc)*/
73 #define	AUDIO		5
74 #define	UNKNOWN		6
75 #endif
76 
77 /*
78  * known sector types
79  */
80 #ifndef	EDC_MODE_0
81 #define	EDC_MODE_0	MODE_0
82 #endif
83 #ifndef	EDC_MODE_1
84 #define	EDC_MODE_1	MODE_1
85 #endif
86 #ifndef	EDC_MODE_2
87 #define	EDC_MODE_2	MODE_2
88 #endif
89 #ifndef	EDC_MODE_2_FORM_1
90 #define	EDC_MODE_2_FORM_1	MODE_2_FORM_1
91 #endif
92 #ifndef	EDC_MODE_2_FORM_2
93 #define	EDC_MODE_2_FORM_2	MODE_2_FORM_2
94 #endif
95 #ifndef	EDC_AUDIO
96 #define	EDC_AUDIO	AUDIO
97 #endif
98 #ifndef	EDC_UNKNOWN
99 #define	EDC_UNKNOWN	UNKNOWN
100 #endif
101 
102 /*
103  * Compute max sector encoding speed
104  */
105 int
106 encspeed(BOOL be_verbose)
107 {
108 	track_t	t[1];
109 	Uchar	sect[2352];
110 	int	i;
111 	struct	timeval tv;
112 	struct	timeval tv2;
113 
114 	t[0].sectype = ST_MODE_1;
115 
116 	/*
117 	 * Encoding speed is content dependant.
118 	 * Set up a known non-null pattern in the sector before; to make
119 	 * the result of this test independant of the current stack content.
120 	 */
121 	for (i = 0; i < 2352; ) {
122 		sect[i++] = 'J';
123 		sect[i++] = 'S';
124 	}
125 	gettimeofday(&tv, (struct timezone *)0);
126 	for (i = 0; i < 75000; i++) {		/* Goes up to 1000x */
127 		encsectors(t, sect, 12345, 1);
128 		gettimeofday(&tv2, (struct timezone *)0);
129 		if (tv2.tv_sec >= (tv.tv_sec+1) &&
130 		    tv2.tv_usec >= tv.tv_usec)
131 			break;
132 	}
133 	if (be_verbose) {
134 		printf("Encoding speed : %dx (%d sectors/s) for libedc from Heiko Ei�feldt\n",
135 				(i+74)/75, i);
136 	}
137 	return ((i+74)/75);
138 }
139 
140 /*
141  * Encode sectors according to trackp->sectype
142  */
143 void
144 encsectors(track_t *trackp, Uchar *bp, int address, int nsecs)
145 {
146 	int	sectype = trackp->sectype;
147 
148 	if ((sectype & ST_MODE_MASK) == ST_MODE_AUDIO)
149 		return;
150 
151 	while (--nsecs >= 0) {
152 		encodesector(bp, sectype, address);
153 		address++;
154 		bp += trackp->secsize;
155 	}
156 }
157 
158 
159 #ifdef	CLONE_WRITE
160 
161 #define	IS_SECHDR(p)	((p)[0] == 0 &&				\
162 			(p)[1] == 0xFF && (p)[2] == 0xFF &&	\
163 			(p)[3] == 0xFF && (p)[4] == 0xFF &&	\
164 			(p)[5] == 0xFF && (p)[6] == 0xFF &&	\
165 			(p)[7] == 0xFF && (p)[8] == 0xFF &&	\
166 			(p)[9] == 0xFF && (p)[10] == 0xFF &&	\
167 			(p)[11] == 0)
168 /*
169  * Scramble data sectors without coding (needed for clone writing)
170  */
171 void
172 scrsectors(track_t *trackp, Uchar *bp, int address, int nsecs)
173 {
174 	/*
175 	 * In Clone write mode, we cannot expect that the sector type
176 	 * of a "track" which really is a file holding the whole disk
177 	 * is flagged with something that makes sense.
178 	 *
179 	 * For this reason, we check each sector if it's a data sector
180 	 * and needs scrambling.
181 	 */
182 	while (--nsecs >= 0) {
183 		if (IS_SECHDR(bp))
184 			scramble_L2(bp);
185 		bp += trackp->secsize;
186 	}
187 }
188 #else
189 void
190 scrsectors(track_t *trackp, Uchar *bp, int address, int nsecs)
191 {
192 	comerrno(EX_BAD, "Cannot write in clone RAW mode.\n");
193 }
194 #endif
195 
196 /*
197  * Encode one sector according to trackp->sectype
198  */
199 void
200 encodesector(Uchar *sp, int sectype, int address)
201 {
202 	if (address < -150)
203 		address += 450150;
204 	else
205 		address += 150;
206 #define	_address address
207 
208 
209 	switch (sectype & ST_MODE_MASK) {
210 
211 	case	ST_MODE_0:
212 		do_encode_L2(sp, EDC_MODE_0, _address);
213 		break;
214 
215 	case	ST_MODE_1:
216 		do_encode_L2(sp, EDC_MODE_1, _address);
217 		break;
218 
219 	case	ST_MODE_2:
220 		do_encode_L2(sp, EDC_MODE_2, _address);
221 		break;
222 
223 	case	ST_MODE_2_FORM_1:
224 		sp[16+2]   &= ~0x20;	/* Form 1 sector */
225 		sp[16+4+2] &= ~0x20;	/* Form 1 sector 2nd copy */
226 		/* FALLTHROUGH */
227 
228 	case	ST_MODE_2_MIXED:
229 		do_encode_L2(sp, EDC_MODE_2_FORM_1, _address);
230 		break;
231 
232 	case	ST_MODE_2_FORM_2:
233 		sp[16+2]   |= 0x20;	/* Form 2 sector */
234 		sp[16+4+2] |= 0x20;	/* Form 2 sector 2nd copy */
235 
236 		do_encode_L2(sp, EDC_MODE_2_FORM_2, _address);
237 		break;
238 
239 	case	ST_MODE_AUDIO:
240 		return;
241 	default:
242 		fill2352(sp, '\0');
243 		return;
244 	}
245 	if ((sectype & ST_NOSCRAMBLE) == 0) {
246 		scramble_L2(sp);
247 #ifndef	EDC_SCRAMBLE_NOSWAP
248 		swabbytes(sp, 2352);
249 #endif
250 	}
251 }
252 
253 /*
254  * Create one zero filles encoded sector (according to trackp->sectype)
255  */
256 void
257 fillsector(Uchar *sp, int sectype, int address)
258 {
259 	fill2352(sp, '\0');
260 	encodesector(sp, sectype, address);
261 }
262 
263 #endif	/* HAVE_LIB_EDC_ECC */
264