summaryrefslogtreecommitdiffhomepage
path: root/src/modules/NVME/NVME.h
blob: ee9002d474665ed063da9bb04319feef14a0c555 (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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/* ========================================

  Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license.

  Revision History:

  ??/??/24: Added file (amlel)
  23 Jul 24: Update filename to Config.h and using NE_ALIGN_NVME for NVME structs. (amlel)

======================================== */

#ifndef __MODULE_NVME_H__
#define __MODULE_NVME_H__

#include <NeKit/Config.h>

/// @file NVME.h
/// @brief Non Volatile Memory.

#define NE_ALIGN_NVME ATTRIBUTE(aligned(sizeof(Kernel::UInt32)))

namespace Kernel {
struct NE_ALIGN_NVME HAL_NVME_BAR_0 final {
  UInt32 fCapabilities;
  UInt32 fVersion;
  UInt32 fIntMaskSet;
  UInt32 fIntMaskClr;
  UInt32 fContrlConf;
  UInt32 fContrlStat;
  UInt32 fAdminQueueAttr;
  UInt32 fAdminSubmissionQueue;
  UInt32 fAdminCompletionQueue;
};

struct NE_ALIGN_NVME HAL_NVME_QUEUE final {
  UInt32 fOpcode;
  UInt32 fNSID;
  UInt32 fReserved[3];
  UInt32 fMetadataPtr[5];
  UInt32 fDataPtr[9];
  UInt32 CommandSpecific[15];
};

enum {
  kInvalidNVME               = 0xFF,
  kCreateCompletionQueueNVME = 0x05,
  kCreateSubmissionQueueNVME = 0x01,
  kIdentifyNVME              = 0x06,
  kReadNVME                  = 0x02,
  kWriteNVME                 = 0x01,
  kCountNVME                 = 5,
};

/// @brief Creates an admin command for a DMA operation.
template <Int32 Opcode>
inline Bool nvme_create_admin_command(HAL_NVME_QUEUE* entry, UInt32 nsid, UInt32 prpTransfer[3],
                                      UInt32 startingLba[2], UInt32 lowTransferBlocks) {
  if (entry == nullptr) return false;

  entry->CommandSpecific[9]  = startingLba[0];
  entry->CommandSpecific[10] = startingLba[1];

  entry->CommandSpecific[11] = lowTransferBlocks;

  entry->CommandSpecific[5] = prpTransfer[0];
  entry->CommandSpecific[6] = prpTransfer[1];
  entry->CommandSpecific[7] = prpTransfer[2];

  entry->CommandSpecific[0] = nsid;

  return true;
}

/// @brief Creates an I/O command for a DMA operation.
template <Int32 Opcode>
inline Bool nvme_create_io_command(HAL_NVME_QUEUE* entry, UInt64 baseAddress,
                                   UInt32 identLoAndQueueSizeHi, UInt32 flagsLoAndQueueComplIdHi,
                                   UInt32 identify, Bool provideIdentify = false,
                                   Bool namespaceIdentify = false) {
  if (entry == nullptr) return false;

  if (baseAddress == 0) return false;

  entry->fOpcode = Opcode;

  entry->CommandSpecific[5] = (baseAddress & 0xFF);
  entry->CommandSpecific[6] = static_cast<UInt32>(baseAddress);

  if (!provideIdentify) {
    entry->CommandSpecific[9]  = identLoAndQueueSizeHi;
    entry->CommandSpecific[10] = flagsLoAndQueueComplIdHi;
  } else {
    entry->CommandSpecific[9] = identify;

    if (namespaceIdentify) {
      entry->CommandSpecific[0] = YES;
    }
  }

  return true;
}
}  // namespace Kernel

#endif  // ifndef __MODULE_NVME_H__