command_table.rs 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. use core::ptr::NonNull;
  2. use eonix_mm::address::PAddr;
  3. use eonix_mm::paging::Folio as _;
  4. use super::command::Command;
  5. use super::{PRDTEntry, FISH2D};
  6. use crate::kernel::mem::FolioOwned;
  7. pub struct CommandTable {
  8. page: FolioOwned,
  9. cmd_fis: NonNull<FISH2D>,
  10. prdt: NonNull<[PRDTEntry; 248]>,
  11. prdt_entries: usize,
  12. }
  13. unsafe impl Send for CommandTable {}
  14. unsafe impl Sync for CommandTable {}
  15. impl CommandTable {
  16. pub fn new() -> Self {
  17. let page = FolioOwned::alloc();
  18. let base = page.get_ptr();
  19. unsafe {
  20. Self {
  21. page,
  22. cmd_fis: base.cast(),
  23. prdt: base.byte_add(0x80).cast(),
  24. prdt_entries: 0,
  25. }
  26. }
  27. }
  28. pub fn setup(&mut self, cmd: &impl Command) {
  29. unsafe {
  30. self.cmd_fis
  31. .as_mut()
  32. .setup(cmd.cmd(), cmd.lba(), cmd.count());
  33. }
  34. self.prdt_entries = cmd.pages().len();
  35. for (idx, page) in cmd.pages().iter().enumerate() {
  36. unsafe {
  37. self.prdt.as_mut()[idx].setup(page);
  38. }
  39. }
  40. }
  41. pub fn prdt_len(&self) -> usize {
  42. self.prdt_entries
  43. }
  44. pub fn base(&self) -> PAddr {
  45. self.page.start()
  46. }
  47. }