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 | */ |