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// for malloc() & free() 30#include <stdlib.h> 31// for memcpy() 32#include <string.h> 33 34#include "deblock_media.h" 35 36 37/* 38 * Defines 39 */ 40 41 42/* 43 * Types 44 */ 45typedef struct deblock_media *DEBLOCK_MEDIA; 46 47struct deblock_media { 48 struct media m; 49 long need_filtering; 50 MEDIA next_media; 51 unsigned long next_block_size; 52 unsigned char *buffer; 53}; 54 55struct deblock_globals { 56 long exists; 57 long kind; 58}; 59 60 61/* 62 * Global Constants 63 */ 64 65 66/* 67 * Global Variables 68 */ 69static long deblock_inited = 0; 70static struct deblock_globals deblock_info; 71 72/* 73 * Forward declarations 74 */ 75void deblock_init(void); 76DEBLOCK_MEDIA new_deblock_media(void); 77long read_deblock_media(MEDIA m, long long offset, unsigned long count, void *address); 78long write_deblock_media(MEDIA m, long long offset, unsigned long count, void *address); 79long close_deblock_media(MEDIA m); 80long os_reload_deblock_media(MEDIA m); 81 82 83/* 84 * Routines 85 */ 86void 87deblock_init(void) 88{ 89 if (deblock_inited != 0) { 90 return; 91 } 92 deblock_inited = 1; 93 94 deblock_info.kind = allocate_media_kind(); 95} 96 97 98DEBLOCK_MEDIA 99new_deblock_media(void) 100{ 101 return (DEBLOCK_MEDIA) new_media(sizeof(struct deblock_media)); 102} 103 104 105MEDIA 106open_deblock_media(unsigned long new_block_size, MEDIA m) 107{ 108 DEBLOCK_MEDIA a; 109 unsigned long block_size; 110 111 if (deblock_inited == 0) { 112 deblock_init(); 113 } 114 115 a = 0; 116 if (m != 0) { 117 block_size = media_granularity(m); 118 119 if (new_block_size == block_size) { 120 return m; 121 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; 130 } 131 } else { 132 /* too hard to bother with */ 133 } 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); 142 } 143 } else { 144 /* too hard to bother with */ 145 } 146 } 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; 156 } 157 } 158 return (MEDIA) a; 159} 160 161 162long 163read_deblock_media(MEDIA m, long long offset, unsigned long count, void *address) 164{ 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; 173 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; 192 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; 199 } 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; 206 } 207 } 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; 215 } 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); 222 } 223 } 224 } 225 return rtn_value; 226} 227 228 229long 230write_deblock_media(MEDIA m, long long offset, unsigned long count, void *address) 231{ 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; 240 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; 259 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; 266 } 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; 274 } 275 } 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; 283 } 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); 291 } 292 } 293 } 294 /* recompute size to handle file media */ 295 a->m.size_in_bytes = media_total_size(a->next_media); 296 return rtn_value; 297} 298 299 300long 301close_deblock_media(MEDIA m) 302{ 303 DEBLOCK_MEDIA a; 304 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; 311 } 312 313 close_media(a->next_media); 314 free(a->buffer); 315 return 1; 316} 317 318 319long 320os_reload_deblock_media(MEDIA m) 321{ 322 DEBLOCK_MEDIA a; 323 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; 330 } 331 332 os_reload_media(a->next_media); 333 return 1; 334} 335