1 /* @(#)sector.c	1.18 10/12/19 Copyright 2001-2010 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)sector.c	1.18 10/12/19 Copyright 2001-2010 J. Schilling";
6 #endif
7 /*
8  *	Functions needed to use libedc_ecc from cdrecord
9  *
10  *	Copyright (c) 2001-2010 J. Schilling
11  */
12 /*
13  * The contents of this file are subject to the terms of the
14  * Common Development and Distribution License, Version 1.0 only
15  * (the "License").  You may not use this file except in compliance
16  * with the License.
17  *
18  * See the file CDDL.Schily.txt in this distribution for details.
19  * A copy of the CDDL is also available via the Internet at
20  * http://www.opensource.org/licenses/cddl1.txt
21  *
22  * When distributing Covered Code, include this CDDL HEADER in each
23  * file and include the License file CDDL.Schily.txt from this distribution.
24  */
25 
26 #include <schily/mconfig.h>
27 #include <schily/stdio.h>
28 #include <schily/standard.h>
29 #include <schily/utypes.h>
30 #include <schily/time.h>
31 #include <schily/schily.h>
32 #include <schily/nlsdefs.h>
33 
34 #include "cdrecord.h"
35 #include "movesect.h"
36 
37 #ifdef	HAVE_LIB_EDC_ECC
38 
39 
40 #define	LAYER2
41 #define	EDC_LAYER2
42 #define	ENCODER
43 #define	EDC_ENCODER
44 #include <ecc.h>
45 
46 #ifdef	DO8
47 #define	HAVE_NEW_LIB_EDC
48 #endif
49 
50 EXPORT	int	encspeed	__PR((BOOL be_verbose));
51 EXPORT	void	encsectors	__PR((track_t *trackp, Uchar *bp, int address, int nsecs));
52 EXPORT	void	scrsectors	__PR((track_t *trackp, Uchar *bp, int address, int nsecs));
53 EXPORT	void	encodesector	__PR((Uchar *sp, int sectype, int address));
54 EXPORT	void	fillsector	__PR((Uchar *sp, int sectype, int address));
55 
56 /*
57  * Sector types known by lib libedc_ecc:
58  */
59 #ifdef	__comment__
60 				/*   MMC					*/
61 #define	MODE_0		0	/* -> XX  12+4+2336	(12+4uuu von libedc)	*/
62 #define	MODE_1		1	/* -> 8   12+4+2048+288 (124+4uuu+288 von libedc)*/
63 #define	MODE_2		2	/* -> 9	  12+4+2336	(12+4uuu von libedc)	*/
64 #define	MODE_2_FORM_1	3	/* -> 10/11 12+4+8+2048+280 (12+4hhhuuu+280 von libedc)*/
65 #define	MODE_2_FORM_2	4	/* -> 12 (eher 13!) 12+4+8+2324+4 (12+4hhhuuu+4 von libedc)*/
66 #define	AUDIO		5
67 #define	UNKNOWN		6
68 #endif
69 
70 /*
71  * known sector types
72  */
73 #ifndef	EDC_MODE_0
74 #define	EDC_MODE_0	MODE_0
75 #endif
76 #ifndef	EDC_MODE_1
77 #define	EDC_MODE_1	MODE_1
78 #endif
79 #ifndef	EDC_MODE_2
80 #define	EDC_MODE_2	MODE_2
81 #endif
82 #ifndef	EDC_MODE_2_FORM_1
83 #define	EDC_MODE_2_FORM_1	MODE_2_FORM_1
84 #endif
85 #ifndef	EDC_MODE_2_FORM_2
86 #define	EDC_MODE_2_FORM_2	MODE_2_FORM_2
87 #endif
88 #ifndef	EDC_AUDIO
89 #define	EDC_AUDIO	AUDIO
90 #endif
91 #ifndef	EDC_UNKNOWN
92 #define	EDC_UNKNOWN	UNKNOWN
93 #endif
94 
95 /*
96  * Compute max sector encoding speed
97  */
98 EXPORT int
encspeed(be_verbose)99 encspeed(be_verbose)
100 	BOOL	be_verbose;
101 {
102 	track_t	t[1];
103 	Uchar	sect[2352];
104 	int	i;
105 	struct	timeval tv;
106 	struct	timeval tv2;
107 
108 	t[0].sectype = ST_MODE_1;
109 
110 	/*
111 	 * Encoding speed is content dependant.
112 	 * Set up a known non-null pattern in the sector before; to make
113 	 * the result of this test independant of the current stack content.
114 	 */
115 	for (i = 0; i < 2352; ) {
116 		sect[i++] = 'J';
117 		sect[i++] = 'S';
118 	}
119 	gettimeofday(&tv, (struct timezone *)0);
120 	for (i = 0; i < 75000; i++) {		/* Goes up to 1000x */
121 		encsectors(t, sect, 12345, 1);
122 		gettimeofday(&tv2, (struct timezone *)0);
123 		if (tv2.tv_sec >= (tv.tv_sec+1) &&
124 		    tv2.tv_usec >= tv.tv_usec)
125 			break;
126 	}
127 	if (be_verbose) {
128 		printf(_("Encoding speed : %dx (%d sectors/s) for libedc from %s\n"),
129 				(i+74)/75, i,
130 				_("Heiko Eissfeldt"));
131 	}
132 	return ((i+74)/75);
133 }
134 
135 /*
136  * Encode sectors according to trackp->sectype
137  */
138 EXPORT void
encsectors(trackp,bp,address,nsecs)139 encsectors(trackp, bp, address, nsecs)
140 	track_t	*trackp;
141 	Uchar	*bp;
142 	int	address;
143 	int	nsecs;
144 {
145 	int	sectype = trackp->sectype;
146 
147 	if ((sectype & ST_MODE_MASK) == ST_MODE_AUDIO)
148 		return;
149 
150 	while (--nsecs >= 0) {
151 		encodesector(bp, sectype, address);
152 		address++;
153 		bp += trackp->secsize;
154 	}
155 }
156 
157 
158 #ifdef	CLONE_WRITE
159 
160 #define	IS_SECHDR(p)	((p)[0] == 0 &&				\
161 			(p)[1] == 0xFF && (p)[2] == 0xFF &&	\
162 			(p)[3] == 0xFF && (p)[4] == 0xFF &&	\
163 			(p)[5] == 0xFF && (p)[6] == 0xFF &&	\
164 			(p)[7] == 0xFF && (p)[8] == 0xFF &&	\
165 			(p)[9] == 0xFF && (p)[10] == 0xFF &&	\
166 			(p)[11] == 0)
167 /*
168  * Scramble data sectors without coding (needed for clone writing)
169  */
170 EXPORT void
scrsectors(trackp,bp,address,nsecs)171 scrsectors(trackp, bp, address, nsecs)
172 	track_t	*trackp;
173 	Uchar	*bp;
174 	int	address;
175 	int	nsecs;
176 {
177 	/*
178 	 * In Clone write mode, we cannot expect that the sector type
179 	 * of a "track" which really is a file holding the whole disk
180 	 * is flagged with something that makes sense.
181 	 *
182 	 * For this reason, we check each sector if it's a data sector
183 	 * and needs scrambling.
184 	 */
185 	while (--nsecs >= 0) {
186 		if (IS_SECHDR(bp))
187 			scramble_L2(bp);
188 		bp += trackp->secsize;
189 	}
190 }
191 #else
192 EXPORT void
scrsectors(trackp,bp,address,nsecs)193 scrsectors(trackp, bp, address, nsecs)
194 	track_t	*trackp;
195 	Uchar	*bp;
196 	int	address;
197 	int	nsecs;
198 {
199 	comerrno(EX_BAD, _("Cannot write in clone RAW mode.\n"));
200 }
201 #endif
202 
203 /*
204  * Encode one sector according to trackp->sectype
205  */
206 EXPORT void
encodesector(sp,sectype,address)207 encodesector(sp, sectype, address)
208 	Uchar	*sp;
209 	int	sectype;
210 	int	address;
211 {
212 	if (address < -150)
213 		address += 450150;
214 	else
215 		address += 150;
216 #define	_address address
217 
218 
219 	switch (sectype & ST_MODE_MASK) {
220 
221 	case	ST_MODE_0:
222 		do_encode_L2(sp, EDC_MODE_0, _address);
223 		break;
224 
225 	case	ST_MODE_1:
226 		do_encode_L2(sp, EDC_MODE_1, _address);
227 		break;
228 
229 	case	ST_MODE_2:
230 		do_encode_L2(sp, EDC_MODE_2, _address);
231 		break;
232 
233 	case	ST_MODE_2_FORM_1:
234 		sp[16+2]   &= ~0x20;	/* Form 1 sector */
235 		sp[16+4+2] &= ~0x20;	/* Form 1 sector 2nd copy */
236 		/* FALLTHROUGH */
237 
238 	case	ST_MODE_2_MIXED:
239 		do_encode_L2(sp, EDC_MODE_2_FORM_1, _address);
240 		break;
241 
242 	case	ST_MODE_2_FORM_2:
243 		sp[16+2]   |= 0x20;	/* Form 2 sector */
244 		sp[16+4+2] |= 0x20;	/* Form 2 sector 2nd copy */
245 
246 		do_encode_L2(sp, EDC_MODE_2_FORM_2, _address);
247 		break;
248 
249 	case	ST_MODE_AUDIO:
250 		return;
251 	default:
252 		fill2352(sp, '\0');
253 		return;
254 	}
255 	if ((sectype & ST_NOSCRAMBLE) == 0) {
256 		scramble_L2(sp);
257 #ifndef	EDC_SCRAMBLE_NOSWAP
258 		swabbytes(sp, 2352);
259 #endif
260 	}
261 }
262 
263 /*
264  * Create one zero filles encoded sector (according to trackp->sectype)
265  */
266 EXPORT void
fillsector(sp,sectype,address)267 fillsector(sp, sectype, address)
268 	Uchar	*sp;
269 	int	sectype;
270 	int	address;
271 {
272 	fill2352(sp, '\0');
273 	encodesector(sp, sectype, address);
274 }
275 
276 #endif	/* HAVE_LIB_EDC_ECC */
277