The Pedigree Project 0.1
IrqsCommand.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.
6 */
7
8#include "pedigree/kernel/debugger/DebuggerIO.h"
9#include "pedigree/kernel/debugger/commands/IrqDiagnosticRenderer.h"
10#include "pedigree/kernel/debugger/commands/IrqsCommand.h"
11#include "pedigree/kernel/machine/Machine.h"
12
13namespace {
14const char* skipSpaces(const char* text) {
15 while (*text == ' ' || *text == '\t') {
16 ++text;
17 }
18 return text;
19}
20
21bool consumeCommandName(const char*& text) {
22 static constexpr char Name[] = "irqs";
23 const char* cursor = text;
24 for (size_t i = 0; Name[i]; ++i, ++cursor) {
25 if (*cursor != Name[i]) {
26 return false;
27 }
28 }
29
30 if (*cursor && *cursor != ' ' && *cursor != '\t') {
31 return false;
32 }
33 text = skipSpaces(cursor);
34 return true;
35}
36
37bool parseLineFilter(const HugeStaticString& input, bool& hasFilter, uint8_t& line) {
38 const char* text = skipSpaces(static_cast<const char*>(input));
39 if (!*text) {
40 hasFilter = false;
41 return true;
42 }
43
44 // Also accept direct callers which have not stripped the command name.
45 if (*text == 'i') {
46 if (!consumeCommandName(text)) {
47 return false;
48 }
49 if (!*text) {
50 hasFilter = false;
51 return true;
52 }
53 }
54
55 size_t value = 0;
56 bool sawDigit = false;
57 while (*text >= '0' && *text <= '9') {
58 sawDigit = true;
59 value = value * 10 + static_cast<size_t>(*text - '0');
60 if (value > 255) {
61 return false;
62 }
63 ++text;
64 }
65
66 text = skipSpaces(text);
67 if (!sawDigit || *text) {
68 return false;
69 }
70
71 hasFilter = true;
72 line = static_cast<uint8_t>(value);
73 return true;
74}
75} // namespace
76
77IrqsCommand::IrqsCommand() : DebuggerCommand(), m_Snapshots() {}
78
79IrqsCommand::~IrqsCommand() {}
80
82
84 InterruptState& state, DebuggerIO* screen) {
85 bool hasFilter = false;
86 uint8_t requestedLine = 0;
87 if (!parseLineFilter(input, hasFilter, requestedLine)) {
88 output += "usage: irqs [line]\n";
89 return true;
90 }
91
92 if (!screen) {
93 output += "IRQ diagnostics require a debugger display.\n";
94 return true;
95 }
96
97 IrqManager* manager = Machine::instance().getIrqManager();
98 if (!manager) {
99 output += "IRQ diagnostics are unavailable on this platform.\n";
100 return true;
101 }
102
103 size_t count = manager->snapshotIrqLines(m_Snapshots, SnapshotCapacity);
104 if (count > SnapshotCapacity) {
105 count = SnapshotCapacity;
106 }
107 if (!count) {
108 output += "IRQ diagnostics are unavailable on this platform.\n";
109 return true;
110 }
111
112 bool rendered = false;
113 for (size_t i = 0; i < count; ++i) {
114 if (hasFilter && m_Snapshots[i].line != requestedLine) {
115 continue;
116 }
117
119 IrqDiagnosticRenderer::render(m_Snapshots[i], line);
120 screen->writeCli(line, DebuggerIO::LightGrey, DebuggerIO::Black);
121 rendered = true;
122 }
123
124 if (hasFilter && !rendered) {
125 output += "IRQ line ";
126 output.append(requestedLine);
127 output += " is not present in this snapshot.\n";
128 }
129 return true;
130}
virtual void writeCli(const char *str, Colour foreColour, Colour backColour)
virtual size_t snapshotIrqLines(IrqLineDiagnosticSnapshot *out, size_t capacity) const
Definition IrqManager.cc:33
void autocomplete(const HugeStaticString &input, HugeStaticString &output)
bool execute(const HugeStaticString &input, HugeStaticString &output, InterruptState &state, DebuggerIO *screen)