Rev 3542 | Rev 3544 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3542 | Rev 3543 | ||
---|---|---|---|
Line 275... | Line 275... | ||
275 | 275 | ||
276 | devcon->cache = cache; |
276 | devcon->cache = cache; |
277 | return EOK; |
277 | return EOK; |
278 | } |
278 | } |
279 | 279 | ||
280 | /** Read data from a block device. |
- | |
281 | * |
- | |
282 | * @param dev_handle Device handle of the block device. |
- | |
283 | * @param bufpos Pointer to the first unread valid offset within the |
- | |
284 | * communication buffer. |
- | |
285 | * @param buflen Pointer to the number of unread bytes that are ready in |
- | |
286 | * the communication buffer. |
- | |
287 | * @param pos Device position to be read. |
- | |
288 | * @param dst Destination buffer. |
- | |
289 | * @param size Size of the destination buffer. |
- | |
290 | * @param block_size Block size to be used for the transfer. |
- | |
291 | * |
- | |
292 | * @return EOK on success or a negative return code on failure. |
- | |
293 | */ |
- | |
294 | int |
- | |
295 | block_read(int dev_handle, off_t *bufpos, size_t *buflen, off_t *pos, void *dst, |
- | |
296 | size_t size, size_t block_size) |
- | |
297 | { |
- | |
298 | off_t offset = 0; |
- | |
299 | size_t left = size; |
- | |
300 | devcon_t *devcon = devcon_search(dev_handle); |
- | |
301 | assert(devcon); |
- | |
302 | - | ||
303 | while (left > 0) { |
- | |
304 | size_t rd; |
- | |
305 | - | ||
306 | if (*bufpos + left < *buflen) |
- | |
307 | rd = left; |
- | |
308 | else |
- | |
309 | rd = *buflen - *bufpos; |
- | |
310 | - | ||
311 | if (rd > 0) { |
- | |
312 | /* |
- | |
313 | * Copy the contents of the communication buffer to the |
- | |
314 | * destination buffer. |
- | |
315 | */ |
- | |
316 | memcpy(dst + offset, devcon->com_area + *bufpos, rd); |
- | |
317 | offset += rd; |
- | |
318 | *bufpos += rd; |
- | |
319 | *pos += rd; |
- | |
320 | left -= rd; |
- | |
321 | } |
- | |
322 | - | ||
323 | if (*bufpos == *buflen) { |
- | |
324 | /* Refill the communication buffer with a new block. */ |
- | |
325 | ipcarg_t retval; |
- | |
326 | int rc = async_req_2_1(devcon->dev_phone, RD_READ_BLOCK, |
- | |
327 | *pos / block_size, block_size, &retval); |
- | |
328 | if ((rc != EOK) || (retval != EOK)) |
- | |
329 | return (rc != EOK ? rc : retval); |
- | |
330 | - | ||
331 | *bufpos = 0; |
- | |
332 | *buflen = block_size; |
- | |
333 | } |
- | |
334 | } |
- | |
335 | - | ||
336 | return EOK; |
- | |
337 | } |
- | |
338 | - | ||
339 | static bool cache_can_grow(cache_t *cache) |
280 | static bool cache_can_grow(cache_t *cache) |
340 | { |
281 | { |
341 | return true; |
282 | return true; |
342 | } |
283 | } |
343 | 284 | ||
Line 434... | Line 375... | ||
434 | 375 | ||
435 | futex_up(&cache->lock); |
376 | futex_up(&cache->lock); |
436 | return b; |
377 | return b; |
437 | } |
378 | } |
438 | 379 | ||
- | 380 | /** Release a reference to a block. |
|
- | 381 | * |
|
- | 382 | * If the last reference is dropped, the block is put on the free list. If the |
|
- | 383 | * last reference is dropped and the block is dirty, it is first synced with the |
|
- | 384 | * block device. |
|
- | 385 | * |
|
- | 386 | * @param block Block of which a reference is to be released. |
|
- | 387 | */ |
|
439 | void block_put(block_t *block) |
388 | void block_put(block_t *block) |
440 | { |
389 | { |
- | 390 | devcon_t *devcon = devcon_search(block->dev_handle); |
|
- | 391 | cache_t *cache; |
|
- | 392 | ||
- | 393 | assert(devcon); |
|
- | 394 | assert(devcon->cache); |
|
- | 395 | ||
- | 396 | cache = devcon->cache; |
|
- | 397 | futex_down(&cache->lock); |
|
- | 398 | futex_down(&block->lock); |
|
- | 399 | if (!--block->refcnt) { |
|
- | 400 | /* |
|
- | 401 | * Last reference to the block was dropped, put the block on the |
|
- | 402 | * free list. |
|
- | 403 | */ |
|
- | 404 | list_append(&block->free_link, &cache->free_head); |
|
- | 405 | /* Unlock the cache, but not the block. */ |
|
- | 406 | futex_up(&cache->lock); |
|
- | 407 | if (block->dirty) { |
|
- | 408 | /* |
|
- | 409 | * The block is dirty and there is no one using it |
|
- | 410 | * at the moment, write it back to the device. |
|
- | 411 | */ |
|
- | 412 | ||
- | 413 | /* TODO: block_write() */ |
|
- | 414 | block->dirty = false; |
|
- | 415 | } |
|
- | 416 | } else { |
|
- | 417 | futex_up(&cache->lock); |
|
- | 418 | } |
|
- | 419 | futex_up(&block->lock); |
|
- | 420 | } |
|
- | 421 | ||
- | 422 | /** Read data from a block device. |
|
- | 423 | * |
|
- | 424 | * @param dev_handle Device handle of the block device. |
|
- | 425 | * @param bufpos Pointer to the first unread valid offset within the |
|
- | 426 | * communication buffer. |
|
- | 427 | * @param buflen Pointer to the number of unread bytes that are ready in |
|
- | 428 | * the communication buffer. |
|
- | 429 | * @param pos Device position to be read. |
|
- | 430 | * @param dst Destination buffer. |
|
- | 431 | * @param size Size of the destination buffer. |
|
- | 432 | * @param block_size Block size to be used for the transfer. |
|
- | 433 | * |
|
- | 434 | * @return EOK on success or a negative return code on failure. |
|
- | 435 | */ |
|
- | 436 | int |
|
- | 437 | block_read(int dev_handle, off_t *bufpos, size_t *buflen, off_t *pos, void *dst, |
|
- | 438 | size_t size, size_t block_size) |
|
- | 439 | { |
|
- | 440 | off_t offset = 0; |
|
- | 441 | size_t left = size; |
|
- | 442 | devcon_t *devcon = devcon_search(dev_handle); |
|
- | 443 | assert(devcon); |
|
441 | 444 | ||
- | 445 | while (left > 0) { |
|
- | 446 | size_t rd; |
|
- | 447 | ||
- | 448 | if (*bufpos + left < *buflen) |
|
- | 449 | rd = left; |
|
- | 450 | else |
|
- | 451 | rd = *buflen - *bufpos; |
|
- | 452 | ||
- | 453 | if (rd > 0) { |
|
- | 454 | /* |
|
- | 455 | * Copy the contents of the communication buffer to the |
|
- | 456 | * destination buffer. |
|
- | 457 | */ |
|
- | 458 | memcpy(dst + offset, devcon->com_area + *bufpos, rd); |
|
- | 459 | offset += rd; |
|
- | 460 | *bufpos += rd; |
|
- | 461 | *pos += rd; |
|
- | 462 | left -= rd; |
|
- | 463 | } |
|
- | 464 | ||
- | 465 | if (*bufpos == *buflen) { |
|
- | 466 | /* Refill the communication buffer with a new block. */ |
|
- | 467 | ipcarg_t retval; |
|
- | 468 | int rc = async_req_2_1(devcon->dev_phone, RD_READ_BLOCK, |
|
- | 469 | *pos / block_size, block_size, &retval); |
|
- | 470 | if ((rc != EOK) || (retval != EOK)) |
|
- | 471 | return (rc != EOK ? rc : retval); |
|
- | 472 | ||
- | 473 | *bufpos = 0; |
|
- | 474 | *buflen = block_size; |
|
- | 475 | } |
|
- | 476 | } |
|
- | 477 | ||
- | 478 | return EOK; |
|
442 | } |
479 | } |
443 | 480 | ||
444 | /** @} |
481 | /** @} |
445 | */ |
482 | */ |