xref: /netbsd/external/bsd/pdisk/dist/deblock_media.c (revision 6f993757)
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