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 */ 46typedef struct deblock_media *DEBLOCK_MEDIA; 47 48struct 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 56struct deblock_globals { 57 long exists; 58 long kind; 59}; 60 61 62/* 63 * Global Constants 64 */ 65 66 67/* 68 * Global Variables 69 */ 70static long deblock_inited = 0; 71static struct deblock_globals deblock_info; 72 73/* 74 * Forward declarations 75 */ 76void deblock_init(void); 77DEBLOCK_MEDIA new_deblock_media(void); 78long read_deblock_media(MEDIA m, long long offset, uint32_t count, void *address); 79long write_deblock_media(MEDIA m, long long offset, uint32_t count, void *address); 80long close_deblock_media(MEDIA m); 81long os_reload_deblock_media(MEDIA m); 82 83 84/* 85 * Routines 86 */ 87void 88deblock_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 99DEBLOCK_MEDIA 100new_deblock_media(void) 101{ 102 return (DEBLOCK_MEDIA) new_media(sizeof(struct deblock_media)); 103} 104 105 106MEDIA 107open_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 163long 164read_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 230long 231write_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 301long 302close_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 320long 321os_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