1 /*
2 * deblock_media.c -
3 *
4 * Written by Eryk Vershen
5 */
6
7 /*
8 * Copyright 1997,1998 by Apple Computer, Inc.
9 * All Rights Reserved
10 *
11 * Permission to use, copy, modify, and distribute this software and
12 * its documentation for any purpose and without fee is hereby granted,
13 * provided that the above copyright notice appears in all copies and
14 * that both the copyright notice and this permission notice appear in
15 * supporting documentation.
16 *
17 * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE.
20 *
21 * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
22 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
23 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
24 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
25 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 */
27
28
29 #include <stdio.h>
30 // for malloc() & free()
31 #include <stdlib.h>
32 // for memcpy()
33 #include <string.h>
34
35 #include "deblock_media.h"
36
37
38 /*
39 * Defines
40 */
41
42
43 /*
44 * Types
45 */
46 typedef struct deblock_media *DEBLOCK_MEDIA;
47
48 struct deblock_media {
49 struct media m;
50 long need_filtering;
51 MEDIA next_media;
52 uint32_t next_block_size;
53 uint8_t *buffer;
54 };
55
56 struct deblock_globals {
57 long exists;
58 long kind;
59 };
60
61
62 /*
63 * Global Constants
64 */
65
66
67 /*
68 * Global Variables
69 */
70 static long deblock_inited = 0;
71 static struct deblock_globals deblock_info;
72
73 /*
74 * Forward declarations
75 */
76 void deblock_init(void);
77 DEBLOCK_MEDIA new_deblock_media(void);
78 long read_deblock_media(MEDIA m, long long offset, uint32_t count, void *address);
79 long write_deblock_media(MEDIA m, long long offset, uint32_t count, void *address);
80 long close_deblock_media(MEDIA m);
81 long os_reload_deblock_media(MEDIA m);
82
83
84 /*
85 * Routines
86 */
87 void
deblock_init(void)88 deblock_init(void)
89 {
90 if (deblock_inited != 0) {
91 return;
92 }
93 deblock_inited = 1;
94
95 deblock_info.kind = allocate_media_kind();
96 }
97
98
99 DEBLOCK_MEDIA
new_deblock_media(void)100 new_deblock_media(void)
101 {
102 return (DEBLOCK_MEDIA) new_media(sizeof(struct deblock_media));
103 }
104
105
106 MEDIA
open_deblock_media(uint32_t new_block_size,MEDIA m)107 open_deblock_media(uint32_t new_block_size, MEDIA m)
108 {
109 DEBLOCK_MEDIA a;
110 uint32_t block_size;
111
112 if (deblock_inited == 0) {
113 deblock_init();
114 }
115
116 a = 0;
117 if (m != 0) {
118 block_size = media_granularity(m);
119
120 if (new_block_size == block_size) {
121 return m;
122
123 } else if (new_block_size > block_size) {
124 if ((new_block_size % block_size) == 0) {
125 /* no filtering necessary */
126 a = new_deblock_media();
127 if (a != 0) {
128 a->need_filtering = 0;
129 a->next_block_size = block_size;
130 a->buffer = 0;
131 }
132 } else {
133 /* too hard to bother with */
134 }
135 } else /* new_block_size < block_size */ {
136 if ((block_size % new_block_size) == 0) {
137 /* block & unblock */
138 a = new_deblock_media();
139 if (a != 0) {
140 a->need_filtering = 1;
141 a->next_block_size = block_size;
142 a->buffer = malloc(block_size);
143 }
144 } else {
145 /* too hard to bother with */
146 }
147 }
148 if (a != 0) {
149 a->m.kind = deblock_info.kind;
150 a->m.grain = new_block_size;
151 a->m.size_in_bytes = media_total_size(m);
152 a->m.do_read = read_deblock_media;
153 a->m.do_write = write_deblock_media;
154 a->m.do_close = close_deblock_media;
155 a->m.do_os_reload = os_reload_deblock_media;
156 a->next_media = m;
157 }
158 }
159 return (MEDIA) a;
160 }
161
162
163 long
read_deblock_media(MEDIA m,long long offset,uint32_t count,void * address)164 read_deblock_media(MEDIA m, long long offset, uint32_t count, void *address)
165 {
166 DEBLOCK_MEDIA a;
167 long rtn_value;
168 uint32_t next_size;
169 uint32_t partial_offset;
170 uint32_t partial_count;
171 long long cur_offset;
172 uint32_t remainder;
173 uint8_t *addr;
174
175 a = (DEBLOCK_MEDIA) m;
176 rtn_value = 0;
177 if (a == 0) {
178 /* no media */
179 } else if (a->m.kind != deblock_info.kind) {
180 /* wrong kind - XXX need to error here - this is an internal problem */
181 } else if (count <= 0 || count % a->m.grain != 0) {
182 /* can't handle size */
183 } else if (offset < 0 || offset % a->m.grain != 0) {
184 /* can't handle offset */
185 } else if (a->need_filtering == 0) {
186 rtn_value = read_media(a->next_media, offset, count, address);
187 } else {
188 next_size = a->next_block_size;
189 addr = address;
190 cur_offset = offset;
191 remainder = count;
192 rtn_value = 1;
193
194 /* read partial */
195 partial_offset = cur_offset % next_size;
196 if (partial_offset != 0) {
197 partial_count = next_size - partial_offset;
198 if (partial_count > remainder) {
199 partial_count = remainder;
200 }
201 rtn_value = read_media(a->next_media, cur_offset - partial_offset, next_size, a->buffer);
202 if (rtn_value != 0) {
203 memcpy (addr, a->buffer + partial_offset, partial_count);
204 addr += partial_count;
205 cur_offset += partial_count;
206 remainder -= partial_count;
207 }
208 }
209 /* read fulls as long as needed */
210 if (rtn_value != 0 && remainder > next_size) {
211 partial_count = remainder - (remainder % next_size);
212 rtn_value = read_media(a->next_media, cur_offset, partial_count, addr);
213 addr += partial_count;
214 cur_offset += partial_count;
215 remainder -= partial_count;
216 }
217 /* read partial */
218 if (rtn_value != 0 && remainder > 0) {
219 partial_count = remainder;
220 rtn_value = read_media(a->next_media, cur_offset, next_size, a->buffer);
221 if (rtn_value != 0) {
222 memcpy (addr, a->buffer, partial_count);
223 }
224 }
225 }
226 return rtn_value;
227 }
228
229
230 long
write_deblock_media(MEDIA m,long long offset,uint32_t count,void * address)231 write_deblock_media(MEDIA m, long long offset, uint32_t count, void *address)
232 {
233 DEBLOCK_MEDIA a;
234 long rtn_value;
235 uint32_t next_size;
236 uint32_t partial_offset;
237 uint32_t partial_count;
238 long long cur_offset;
239 uint32_t remainder;
240 uint8_t *addr;
241
242 a = (DEBLOCK_MEDIA) m;
243 rtn_value = 0;
244 if (a == 0) {
245 /* no media */
246 } else if (a->m.kind != deblock_info.kind) {
247 /* wrong kind - XXX need to error here - this is an internal problem */
248 } else if (count <= 0 || count % a->m.grain != 0) {
249 /* can't handle size */
250 } else if (offset < 0 || offset % a->m.grain != 0) {
251 /* can't handle offset */
252 } else if (a->need_filtering == 0) {
253 rtn_value = write_media(a->next_media, offset, count, address);
254 } else {
255 next_size = a->next_block_size;
256 addr = address;
257 cur_offset = offset;
258 remainder = count;
259 rtn_value = 1;
260
261 /* write partial */
262 partial_offset = cur_offset % next_size;
263 if (partial_offset != 0) {
264 partial_count = next_size - partial_offset;
265 if (partial_count > remainder) {
266 partial_count = remainder;
267 }
268 rtn_value = read_media(a->next_media, cur_offset - partial_offset, next_size, a->buffer);
269 if (rtn_value != 0) {
270 memcpy (a->buffer + partial_offset, addr, partial_count);
271 rtn_value = write_media(a->next_media, cur_offset - partial_offset, next_size, a->buffer);
272 addr += partial_count;
273 cur_offset += partial_count;
274 remainder -= partial_count;
275 }
276 }
277 /* write fulls as long as needed */
278 if (rtn_value != 0 && remainder > next_size) {
279 partial_count = remainder - (remainder % next_size);
280 rtn_value = write_media(a->next_media, cur_offset, partial_count, addr);
281 addr += partial_count;
282 cur_offset += partial_count;
283 remainder -= partial_count;
284 }
285 /* write partial */
286 if (rtn_value != 0 && remainder > 0) {
287 partial_count = remainder;
288 rtn_value = read_media(a->next_media, cur_offset, next_size, a->buffer);
289 if (rtn_value != 0) {
290 memcpy (a->buffer, addr, partial_count);
291 rtn_value = write_media(a->next_media, cur_offset, next_size, a->buffer);
292 }
293 }
294 }
295 /* recompute size to handle file media */
296 a->m.size_in_bytes = media_total_size(a->next_media);
297 return rtn_value;
298 }
299
300
301 long
close_deblock_media(MEDIA m)302 close_deblock_media(MEDIA m)
303 {
304 DEBLOCK_MEDIA a;
305
306 a = (DEBLOCK_MEDIA) m;
307 if (a == 0) {
308 return 0;
309 } else if (a->m.kind != deblock_info.kind) {
310 /* XXX need to error here - this is an internal problem */
311 return 0;
312 }
313
314 close_media(a->next_media);
315 free(a->buffer);
316 return 1;
317 }
318
319
320 long
os_reload_deblock_media(MEDIA m)321 os_reload_deblock_media(MEDIA m)
322 {
323 DEBLOCK_MEDIA a;
324
325 a = (DEBLOCK_MEDIA) m;
326 if (a == 0) {
327 return 0;
328 } else if (a->m.kind != deblock_info.kind) {
329 /* XXX need to error here - this is an internal problem */
330 return 0;
331 }
332
333 os_reload_media(a->next_media);
334 return 1;
335 }
336