summaryrefslogtreecommitdiff
path: root/Kernel/Storage/ATA/AHCIController.h
blob: 79abc0d1f74e7e4352ab909794df35246f93d09b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/*
 * Copyright (c) 2021-2022, Liav A. <liavalb@hotmail.co.il>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/OwnPtr.h>
#include <AK/RefPtr.h>
#include <AK/Types.h>
#include <Kernel/Sections.h>
#include <Kernel/Storage/ATA/AHCI.h>
#include <Kernel/Storage/ATA/ATAController.h>
#include <Kernel/Storage/StorageDevice.h>

namespace Kernel {

class AsyncBlockDeviceRequest;
class AHCIInterruptHandler;
class AHCIPort;
class AHCIController final : public ATAController
    , public PCI::Device {
    friend class AHCIInterruptHandler;

public:
    static NonnullRefPtr<AHCIController> initialize(PCI::DeviceIdentifier const& pci_device_identifier);
    virtual ~AHCIController() override;

    virtual RefPtr<StorageDevice> device(u32 index) const override;
    virtual bool reset() override;
    virtual bool shutdown() override;
    virtual size_t devices_count() const override;
    virtual void start_request(ATADevice const&, AsyncBlockDeviceRequest&) override;
    virtual void complete_current_request(AsyncDeviceRequest::RequestResult) override;

    void handle_interrupt_for_port(Badge<AHCIInterruptHandler>, u32 port_index) const;

private:
    void disable_global_interrupts() const;
    void enable_global_interrupts() const;

    explicit AHCIController(PCI::DeviceIdentifier const&);
    void initialize_hba(PCI::DeviceIdentifier const&);

    AHCI::HBADefinedCapabilities capabilities() const;
    RefPtr<StorageDevice> device_by_port(u32 index) const;

    volatile AHCI::PortRegisters& port(size_t port_number) const;
    NonnullOwnPtr<Memory::Region> default_hba_region() const;
    volatile AHCI::HBA& hba() const;

    Array<RefPtr<AHCIPort>, 32> m_ports;
    NonnullOwnPtr<Memory::Region> m_hba_region;
    AHCI::HBADefinedCapabilities m_hba_capabilities;

    // FIXME: There could be multiple IRQ (MSI) handlers for AHCI. Find a way to use all of them.
    OwnPtr<AHCIInterruptHandler> m_irq_handler;

    // Note: This lock is intended to be locked when doing changes to HBA registers
    // that affect its core functionality in a manner that controls all attached storage devices
    // to the HBA SATA ports.
    mutable Spinlock m_hba_control_lock;
};
}