AHCIPort.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/OwnPtr.h>
  8. #include <AK/RefPtr.h>
  9. #include <Kernel/Devices/Device.h>
  10. #include <Kernel/IO.h>
  11. #include <Kernel/Interrupts/IRQHandler.h>
  12. #include <Kernel/Locking/Mutex.h>
  13. #include <Kernel/Locking/Spinlock.h>
  14. #include <Kernel/Memory/AnonymousVMObject.h>
  15. #include <Kernel/Memory/PhysicalPage.h>
  16. #include <Kernel/Memory/ScatterGatherList.h>
  17. #include <Kernel/PhysicalAddress.h>
  18. #include <Kernel/Random.h>
  19. #include <Kernel/Sections.h>
  20. #include <Kernel/Storage/AHCI.h>
  21. #include <Kernel/Storage/AHCIPortHandler.h>
  22. #include <Kernel/Storage/StorageDevice.h>
  23. #include <Kernel/WaitQueue.h>
  24. namespace Kernel {
  25. class AsyncBlockDeviceRequest;
  26. class AHCIPortHandler;
  27. class SATADiskDevice;
  28. class AHCIPort : public RefCounted<AHCIPort> {
  29. friend class AHCIPortHandler;
  30. friend class SATADiskDevice;
  31. public:
  32. UNMAP_AFTER_INIT static NonnullRefPtr<AHCIPort> create(const AHCIPortHandler&, volatile AHCI::PortRegisters&, u32 port_index);
  33. u32 port_index() const { return m_port_index; }
  34. u32 representative_port_index() const { return port_index() + 1; }
  35. bool is_operable() const;
  36. bool is_hot_pluggable() const;
  37. bool is_atapi_attached() const { return m_port_registers.sig == (u32)AHCI::DeviceSignature::ATAPI; };
  38. RefPtr<StorageDevice> connected_device() const { return m_connected_device; }
  39. bool reset();
  40. UNMAP_AFTER_INIT bool initialize_without_reset();
  41. void handle_interrupt();
  42. private:
  43. bool is_phy_enabled() const { return (m_port_registers.ssts & 0xf) == 3; }
  44. bool initialize(SpinlockLocker<Spinlock<u8>>&);
  45. UNMAP_AFTER_INIT AHCIPort(const AHCIPortHandler&, volatile AHCI::PortRegisters&, u32 port_index);
  46. ALWAYS_INLINE void clear_sata_error_register() const;
  47. void eject();
  48. const char* try_disambiguate_sata_status();
  49. void try_disambiguate_sata_error();
  50. bool initiate_sata_reset(SpinlockLocker<Spinlock<u8>>&);
  51. void rebase();
  52. void recover_from_fatal_error();
  53. bool shutdown();
  54. ALWAYS_INLINE void spin_up() const;
  55. ALWAYS_INLINE void power_on() const;
  56. void start_request(AsyncBlockDeviceRequest&);
  57. void complete_current_request(AsyncDeviceRequest::RequestResult);
  58. bool access_device(AsyncBlockDeviceRequest::RequestType, u64 lba, u8 block_count);
  59. size_t calculate_descriptors_count(size_t block_count) const;
  60. [[nodiscard]] Optional<AsyncDeviceRequest::RequestResult> prepare_and_set_scatter_list(AsyncBlockDeviceRequest& request);
  61. ALWAYS_INLINE bool is_interrupts_enabled() const;
  62. bool spin_until_ready() const;
  63. bool identify_device(SpinlockLocker<Spinlock<u8>>&);
  64. ALWAYS_INLINE void start_command_list_processing() const;
  65. ALWAYS_INLINE void mark_command_header_ready_to_process(u8 command_header_index) const;
  66. ALWAYS_INLINE void stop_command_list_processing() const;
  67. ALWAYS_INLINE void start_fis_receiving() const;
  68. ALWAYS_INLINE void stop_fis_receiving() const;
  69. ALWAYS_INLINE void set_active_state() const;
  70. ALWAYS_INLINE void set_sleep_state() const;
  71. void set_interface_state(AHCI::DeviceDetectionInitialization);
  72. Optional<u8> try_to_find_unused_command_header();
  73. ALWAYS_INLINE bool is_interface_disabled() const { return (m_port_registers.ssts & 0xf) == 4; };
  74. // Data members
  75. EntropySource m_entropy_source;
  76. RefPtr<AsyncBlockDeviceRequest> m_current_request;
  77. Spinlock<u8> m_hard_lock;
  78. Mutex m_lock { "AHCIPort" };
  79. mutable bool m_wait_for_completion { false };
  80. bool m_wait_connect_for_completion { false };
  81. NonnullRefPtrVector<Memory::PhysicalPage> m_dma_buffers;
  82. NonnullRefPtrVector<Memory::PhysicalPage> m_command_table_pages;
  83. RefPtr<Memory::PhysicalPage> m_command_list_page;
  84. OwnPtr<Memory::Region> m_command_list_region;
  85. RefPtr<Memory::PhysicalPage> m_fis_receive_page;
  86. RefPtr<StorageDevice> m_connected_device;
  87. u32 m_port_index;
  88. volatile AHCI::PortRegisters& m_port_registers;
  89. NonnullRefPtr<AHCIPortHandler> m_parent_handler;
  90. AHCI::PortInterruptStatusBitField m_interrupt_status;
  91. AHCI::PortInterruptEnableBitField m_interrupt_enable;
  92. RefPtr<Memory::ScatterGatherList> m_current_scatter_list;
  93. bool m_disabled_by_firmware { false };
  94. };
  95. }