* @brief 释放整条描述符链 * * 从链头开始,沿 next 指针遍历并释放所有描述符,直到遇到 * 不含 kDescFNext 标志的描述符为止。 * * 典型用法:在 PopUsed() 获取已完成请求的 head 后, * 用此方法一次性归还整条链的描述符。 * * @param head 描述符链头索引 * @return 成功或失败(如 head 索引无效) * * @warning 非线程安全 * @see virtio-v1.2#2.7.14 Receiving Used Buffers From The Device */
| 528 | * @see virtio-v1.2#2.7.14 Receiving Used Buffers From The Device |
| 529 | */ |
| 530 | auto FreeChain(uint16_t head) -> Expected<void> { |
| 531 | if (head >= queue_size_) { |
| 532 | return std::unexpected(Error{ErrorCode::kInvalidDescriptor}); |
| 533 | } |
| 534 | |
| 535 | uint16_t idx = head; |
| 536 | while (true) { |
| 537 | if (idx >= queue_size_) { |
| 538 | return std::unexpected(Error{ErrorCode::kInvalidDescriptor}); |
| 539 | } |
| 540 | |
| 541 | uint16_t next = desc_[idx].next; |
| 542 | bool has_next = |
| 543 | (desc_[idx].flags & std::to_underlying(DescFlags::kDescFNext)) != 0; |
| 544 | |
| 545 | desc_[idx].next = free_head_; |
| 546 | free_head_ = idx; |
| 547 | ++num_free_; |
| 548 | |
| 549 | if (!has_next) { |
| 550 | break; |
| 551 | } |
| 552 | idx = next; |
| 553 | } |
| 554 | |
| 555 | return {}; |
| 556 | } |
| 557 | |
| 558 | /** |
| 559 | * @brief 获取描述符表的物理地址 |
no outgoing calls
no test coverage detected