The Pedigree Project 0.1
modules/drivers/common/ahci/main.cc
1/*
2 * Copyright (c) 2026, Pedigree Developers
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "pedigree/kernel/Log.h"
18#include "pedigree/kernel/linker/KernelElf.h"
19#include "pedigree/kernel/utilities/List.h"
20#include "pedigree/kernel/utilities/new"
21
22#include "AhciController.h"
23#include "modules/Module.h"
24
25namespace {
26List<Device*> candidates;
27List<AhciController*> controllers;
28
29void collect(Device* device) {
30 for (size_t i = 0; i < device->getNumChildren(); ++i) {
31 if (device->getChild(i)->getSpecificType() == String("ahci-controller"))
32 return;
33 }
34 candidates.pushBack(device);
35}
36
37Module::UnloadAdmission admitUnload(bool) {
38 for (auto* controller : controllers) {
39 if (!controller->prepareDiskRemoval()) {
40 for (auto* rollback : controllers)
41 rollback->cancelDiskRemoval();
42 return Module::UnloadAdmission::Busy;
43 }
44 }
45 return Module::UnloadAdmission::Ready;
46}
47
48bool entry() {
49 Device::searchByClassSubclassAndProgInterface(0x01, 0x06, 0x01, collect);
50 while (candidates.count()) {
51 Device* pci = candidates.popFront();
52 auto* controller = new AhciController(pci);
53 if (!controller->initialiseController()) {
54 controller->shutdown();
55 delete controller;
56 continue;
57 }
58 {
60 controller->setParent(pci);
61 pci->addChild(controller);
62 }
63 controllers.pushBack(controller);
64 }
65 if (!controllers.count()) {
66 NOTICE("AHCI: no supported SATA disks found");
67 return false;
68 }
69 return KernelElf::instance().registerUnloadAdmission(&entry, &admitUnload);
70}
71
72void exit() {
73 while (controllers.count()) {
74 AhciController* controller = controllers.popFront();
75 controller->shutdown();
76 {
78 controller->getParent()->removeChild(controller);
79 controller->setParent(nullptr);
80 }
81 delete controller;
82 }
83}
84} // namespace
85
86MODULE_INFO("ahci", &entry, &exit, "pci", "scsi");
void addChild(Device *pDevice)
Definition Device.cc:123
Device * getParent() const
Definition Device.h:161
void setParent(Device *p)
Definition Device.h:165
void removeChild(size_t n)
Definition Device.cc:135
bool registerUnloadAdmission(ModuleEntry ownerEntry, Module::UnloadAdmissionHook hook)
static KernelElf & instance()
Definition KernelElf.h:135
Definition List.h:61
T popFront()
Definition List.h:330
size_t count() const
Definition List.h:212
void pushBack(const T &value)
Definition List.h:216