snj doesn't like my accent, so use proper English month names.
[netbsd-mini2440.git] / dist / pdisk / deblock_media.c
blobf8c691c78cc8562481cc9439cef10958cfa20c22
1 /*
2 * deblock_media.c -
4 * Written by Eryk Vershen
5 */
7 /*
8 * Copyright 1997,1998 by Apple Computer, Inc.
9 * All Rights Reserved
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.
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.
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.
29 // for malloc() & free()
30 #include <stdlib.h>
31 // for memcpy()
32 #include <string.h>
34 #include "deblock_media.h"
38 * Defines
43 * Types
45 typedef struct deblock_media *DEBLOCK_MEDIA;
47 struct deblock_media {
48 struct media m;
49 long need_filtering;
50 MEDIA next_media;
51 unsigned long next_block_size;
52 unsigned char *buffer;
55 struct deblock_globals {
56 long exists;
57 long kind;
62 * Global Constants
67 * Global Variables
69 static long deblock_inited = 0;
70 static struct deblock_globals deblock_info;
73 * Forward declarations
75 void deblock_init(void);
76 DEBLOCK_MEDIA new_deblock_media(void);
77 long read_deblock_media(MEDIA m, long long offset, unsigned long count, void *address);
78 long write_deblock_media(MEDIA m, long long offset, unsigned long count, void *address);
79 long close_deblock_media(MEDIA m);
80 long os_reload_deblock_media(MEDIA m);
84 * Routines
86 void
87 deblock_init(void)
89 if (deblock_inited != 0) {
90 return;
92 deblock_inited = 1;
94 deblock_info.kind = allocate_media_kind();
98 DEBLOCK_MEDIA
99 new_deblock_media(void)
101 return (DEBLOCK_MEDIA) new_media(sizeof(struct deblock_media));
105 MEDIA
106 open_deblock_media(unsigned long new_block_size, MEDIA m)
108 DEBLOCK_MEDIA a;
109 unsigned long block_size;
111 if (deblock_inited == 0) {
112 deblock_init();
115 a = 0;
116 if (m != 0) {
117 block_size = media_granularity(m);
119 if (new_block_size == block_size) {
120 return m;
122 } else if (new_block_size > block_size) {
123 if ((new_block_size % block_size) == 0) {
124 /* no filtering necessary */
125 a = new_deblock_media();
126 if (a != 0) {
127 a->need_filtering = 0;
128 a->next_block_size = block_size;
129 a->buffer = 0;
131 } else {
132 /* too hard to bother with */
134 } else /* new_block_size < block_size */ {
135 if ((block_size % new_block_size) == 0) {
136 /* block & unblock */
137 a = new_deblock_media();
138 if (a != 0) {
139 a->need_filtering = 1;
140 a->next_block_size = block_size;
141 a->buffer = malloc(block_size);
143 } else {
144 /* too hard to bother with */
147 if (a != 0) {
148 a->m.kind = deblock_info.kind;
149 a->m.grain = new_block_size;
150 a->m.size_in_bytes = media_total_size(m);
151 a->m.do_read = read_deblock_media;
152 a->m.do_write = write_deblock_media;
153 a->m.do_close = close_deblock_media;
154 a->m.do_os_reload = os_reload_deblock_media;
155 a->next_media = m;
158 return (MEDIA) a;
162 long
163 read_deblock_media(MEDIA m, long long offset, unsigned long count, void *address)
165 DEBLOCK_MEDIA a;
166 long rtn_value;
167 unsigned long next_size;
168 unsigned long partial_offset;
169 unsigned long partial_count;
170 long long cur_offset;
171 unsigned long remainder;
172 unsigned char *addr;
174 a = (DEBLOCK_MEDIA) m;
175 rtn_value = 0;
176 if (a == 0) {
177 /* no media */
178 } else if (a->m.kind != deblock_info.kind) {
179 /* wrong kind - XXX need to error here - this is an internal problem */
180 } else if (count <= 0 || count % a->m.grain != 0) {
181 /* can't handle size */
182 } else if (offset < 0 || offset % a->m.grain != 0) {
183 /* can't handle offset */
184 } else if (a->need_filtering == 0) {
185 rtn_value = read_media(a->next_media, offset, count, address);
186 } else {
187 next_size = a->next_block_size;
188 addr = address;
189 cur_offset = offset;
190 remainder = count;
191 rtn_value = 1;
193 /* read partial */
194 partial_offset = cur_offset % next_size;
195 if (partial_offset != 0) {
196 partial_count = next_size - partial_offset;
197 if (partial_count > remainder) {
198 partial_count = remainder;
200 rtn_value = read_media(a->next_media, cur_offset - partial_offset, next_size, a->buffer);
201 if (rtn_value != 0) {
202 memcpy (addr, a->buffer + partial_offset, partial_count);
203 addr += partial_count;
204 cur_offset += partial_count;
205 remainder -= partial_count;
208 /* read fulls as long as needed */
209 if (rtn_value != 0 && remainder > next_size) {
210 partial_count = remainder - (remainder % next_size);
211 rtn_value = read_media(a->next_media, cur_offset, partial_count, addr);
212 addr += partial_count;
213 cur_offset += partial_count;
214 remainder -= partial_count;
216 /* read partial */
217 if (rtn_value != 0 && remainder > 0) {
218 partial_count = remainder;
219 rtn_value = read_media(a->next_media, cur_offset, next_size, a->buffer);
220 if (rtn_value != 0) {
221 memcpy (addr, a->buffer, partial_count);
225 return rtn_value;
229 long
230 write_deblock_media(MEDIA m, long long offset, unsigned long count, void *address)
232 DEBLOCK_MEDIA a;
233 long rtn_value;
234 unsigned long next_size;
235 unsigned long partial_offset;
236 unsigned long partial_count;
237 long long cur_offset;
238 unsigned long remainder;
239 unsigned char *addr;
241 a = (DEBLOCK_MEDIA) m;
242 rtn_value = 0;
243 if (a == 0) {
244 /* no media */
245 } else if (a->m.kind != deblock_info.kind) {
246 /* wrong kind - XXX need to error here - this is an internal problem */
247 } else if (count <= 0 || count % a->m.grain != 0) {
248 /* can't handle size */
249 } else if (offset < 0 || offset % a->m.grain != 0) {
250 /* can't handle offset */
251 } else if (a->need_filtering == 0) {
252 rtn_value = write_media(a->next_media, offset, count, address);
253 } else {
254 next_size = a->next_block_size;
255 addr = address;
256 cur_offset = offset;
257 remainder = count;
258 rtn_value = 1;
260 /* write partial */
261 partial_offset = cur_offset % next_size;
262 if (partial_offset != 0) {
263 partial_count = next_size - partial_offset;
264 if (partial_count > remainder) {
265 partial_count = remainder;
267 rtn_value = read_media(a->next_media, cur_offset - partial_offset, next_size, a->buffer);
268 if (rtn_value != 0) {
269 memcpy (a->buffer + partial_offset, addr, partial_count);
270 rtn_value = write_media(a->next_media, cur_offset - partial_offset, next_size, a->buffer);
271 addr += partial_count;
272 cur_offset += partial_count;
273 remainder -= partial_count;
276 /* write fulls as long as needed */
277 if (rtn_value != 0 && remainder > next_size) {
278 partial_count = remainder - (remainder % next_size);
279 rtn_value = write_media(a->next_media, cur_offset, partial_count, addr);
280 addr += partial_count;
281 cur_offset += partial_count;
282 remainder -= partial_count;
284 /* write partial */
285 if (rtn_value != 0 && remainder > 0) {
286 partial_count = remainder;
287 rtn_value = read_media(a->next_media, cur_offset, next_size, a->buffer);
288 if (rtn_value != 0) {
289 memcpy (a->buffer, addr, partial_count);
290 rtn_value = write_media(a->next_media, cur_offset, next_size, a->buffer);
294 /* recompute size to handle file media */
295 a->m.size_in_bytes = media_total_size(a->next_media);
296 return rtn_value;
300 long
301 close_deblock_media(MEDIA m)
303 DEBLOCK_MEDIA a;
305 a = (DEBLOCK_MEDIA) m;
306 if (a == 0) {
307 return 0;
308 } else if (a->m.kind != deblock_info.kind) {
309 /* XXX need to error here - this is an internal problem */
310 return 0;
313 close_media(a->next_media);
314 free(a->buffer);
315 return 1;
319 long
320 os_reload_deblock_media(MEDIA m)
322 DEBLOCK_MEDIA a;
324 a = (DEBLOCK_MEDIA) m;
325 if (a == 0) {
326 return 0;
327 } else if (a->m.kind != deblock_info.kind) {
328 /* XXX need to error here - this is an internal problem */
329 return 0;
332 os_reload_media(a->next_media);
333 return 1;