IDEController.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/OwnPtr.h>
  7. #include <AK/RefPtr.h>
  8. #include <AK/Types.h>
  9. #include <Kernel/Bus/PCI/API.h>
  10. #include <Kernel/FileSystem/ProcFS.h>
  11. #include <Kernel/Sections.h>
  12. #include <Kernel/Storage/BMIDEChannel.h>
  13. #include <Kernel/Storage/IDEController.h>
  14. #include <Kernel/Storage/PATADiskDevice.h>
  15. namespace Kernel {
  16. UNMAP_AFTER_INIT NonnullRefPtr<IDEController> IDEController::initialize(PCI::DeviceIdentifier const& device_identifier, bool force_pio)
  17. {
  18. return adopt_ref(*new IDEController(device_identifier, force_pio));
  19. }
  20. bool IDEController::reset()
  21. {
  22. TODO();
  23. }
  24. bool IDEController::shutdown()
  25. {
  26. TODO();
  27. }
  28. size_t IDEController::devices_count() const
  29. {
  30. size_t count = 0;
  31. for (u32 index = 0; index < 4; index++) {
  32. if (!device(index).is_null())
  33. count++;
  34. }
  35. return count;
  36. }
  37. void IDEController::start_request(const StorageDevice&, AsyncBlockDeviceRequest&)
  38. {
  39. VERIFY_NOT_REACHED();
  40. }
  41. void IDEController::complete_current_request(AsyncDeviceRequest::RequestResult)
  42. {
  43. VERIFY_NOT_REACHED();
  44. }
  45. UNMAP_AFTER_INIT IDEController::IDEController(PCI::DeviceIdentifier const& device_identifier, bool force_pio)
  46. : StorageController()
  47. , PCI::Device(device_identifier.address())
  48. , m_prog_if(device_identifier.prog_if())
  49. , m_interrupt_line(device_identifier.interrupt_line())
  50. {
  51. PCI::enable_io_space(device_identifier.address());
  52. PCI::enable_memory_space(device_identifier.address());
  53. initialize(force_pio);
  54. }
  55. UNMAP_AFTER_INIT IDEController::~IDEController()
  56. {
  57. }
  58. bool IDEController::is_pci_native_mode_enabled() const
  59. {
  60. return (m_prog_if.value() & 0x05) != 0;
  61. }
  62. bool IDEController::is_pci_native_mode_enabled_on_primary_channel() const
  63. {
  64. return (m_prog_if.value() & 0x1) == 0x1;
  65. }
  66. bool IDEController::is_pci_native_mode_enabled_on_secondary_channel() const
  67. {
  68. return (m_prog_if.value() & 0x4) == 0x4;
  69. }
  70. bool IDEController::is_bus_master_capable() const
  71. {
  72. return m_prog_if.value() & (1 << 7);
  73. }
  74. static const char* detect_controller_type(u8 programming_value)
  75. {
  76. switch (programming_value) {
  77. case 0x00:
  78. return "ISA Compatibility mode-only controller";
  79. case 0x05:
  80. return "PCI native mode-only controller";
  81. case 0x0A:
  82. return "ISA Compatibility mode controller, supports both channels switched to PCI native mode";
  83. case 0x0F:
  84. return "PCI native mode controller, supports both channels switched to ISA compatibility mode";
  85. case 0x80:
  86. return "ISA Compatibility mode-only controller, supports bus mastering";
  87. case 0x85:
  88. return "PCI native mode-only controller, supports bus mastering";
  89. case 0x8A:
  90. return "ISA Compatibility mode controller, supports both channels switched to PCI native mode, supports bus mastering";
  91. case 0x8F:
  92. return "PCI native mode controller, supports both channels switched to ISA compatibility mode, supports bus mastering";
  93. default:
  94. VERIFY_NOT_REACHED();
  95. }
  96. VERIFY_NOT_REACHED();
  97. }
  98. UNMAP_AFTER_INIT void IDEController::initialize(bool force_pio)
  99. {
  100. auto bus_master_base = IOAddress(PCI::get_BAR4(pci_address()) & (~1));
  101. dbgln("IDE controller @ {}: bus master base was set to {}", pci_address(), bus_master_base);
  102. dbgln("IDE controller @ {}: interrupt line was set to {}", pci_address(), m_interrupt_line.value());
  103. dbgln("IDE controller @ {}: {}", pci_address(), detect_controller_type(m_prog_if.value()));
  104. dbgln("IDE controller @ {}: primary channel DMA capable? {}", pci_address(), ((bus_master_base.offset(2).in<u8>() >> 5) & 0b11));
  105. dbgln("IDE controller @ {}: secondary channel DMA capable? {}", pci_address(), ((bus_master_base.offset(2 + 8).in<u8>() >> 5) & 0b11));
  106. if (!is_bus_master_capable())
  107. force_pio = true;
  108. auto bar0 = PCI::get_BAR0(pci_address());
  109. auto primary_base_io = (bar0 == 0x1 || bar0 == 0) ? IOAddress(0x1F0) : IOAddress(bar0 & (~1));
  110. auto bar1 = PCI::get_BAR1(pci_address());
  111. auto primary_control_io = (bar1 == 0x1 || bar1 == 0) ? IOAddress(0x3F6) : IOAddress(bar1 & (~1));
  112. auto bar2 = PCI::get_BAR2(pci_address());
  113. auto secondary_base_io = (bar2 == 0x1 || bar2 == 0) ? IOAddress(0x170) : IOAddress(bar2 & (~1));
  114. auto bar3 = PCI::get_BAR3(pci_address());
  115. auto secondary_control_io = (bar3 == 0x1 || bar3 == 0) ? IOAddress(0x376) : IOAddress(bar3 & (~1));
  116. auto irq_line = m_interrupt_line.value();
  117. if (is_pci_native_mode_enabled()) {
  118. VERIFY(irq_line != 0);
  119. }
  120. if (is_pci_native_mode_enabled_on_primary_channel()) {
  121. if (force_pio)
  122. m_channels.append(IDEChannel::create(*this, irq_line, { primary_base_io, primary_control_io }, IDEChannel::ChannelType::Primary));
  123. else
  124. m_channels.append(BMIDEChannel::create(*this, irq_line, { primary_base_io, primary_control_io, bus_master_base }, IDEChannel::ChannelType::Primary));
  125. } else {
  126. if (force_pio)
  127. m_channels.append(IDEChannel::create(*this, { primary_base_io, primary_control_io }, IDEChannel::ChannelType::Primary));
  128. else
  129. m_channels.append(BMIDEChannel::create(*this, { primary_base_io, primary_control_io, bus_master_base }, IDEChannel::ChannelType::Primary));
  130. }
  131. m_channels[0].enable_irq();
  132. if (is_pci_native_mode_enabled_on_secondary_channel()) {
  133. if (force_pio)
  134. m_channels.append(IDEChannel::create(*this, irq_line, { secondary_base_io, secondary_control_io }, IDEChannel::ChannelType::Secondary));
  135. else
  136. m_channels.append(BMIDEChannel::create(*this, irq_line, { secondary_base_io, secondary_control_io, bus_master_base.offset(8) }, IDEChannel::ChannelType::Secondary));
  137. } else {
  138. if (force_pio)
  139. m_channels.append(IDEChannel::create(*this, { secondary_base_io, secondary_control_io }, IDEChannel::ChannelType::Secondary));
  140. else
  141. m_channels.append(BMIDEChannel::create(*this, { secondary_base_io, secondary_control_io, bus_master_base.offset(8) }, IDEChannel::ChannelType::Secondary));
  142. }
  143. m_channels[1].enable_irq();
  144. }
  145. RefPtr<StorageDevice> IDEController::device_by_channel_and_position(u32 index) const
  146. {
  147. switch (index) {
  148. case 0:
  149. return m_channels[0].master_device();
  150. case 1:
  151. return m_channels[0].slave_device();
  152. case 2:
  153. return m_channels[1].master_device();
  154. case 3:
  155. return m_channels[1].slave_device();
  156. }
  157. VERIFY_NOT_REACHED();
  158. }
  159. RefPtr<StorageDevice> IDEController::device(u32 index) const
  160. {
  161. NonnullRefPtrVector<StorageDevice> connected_devices;
  162. for (size_t index = 0; index < 4; index++) {
  163. auto checked_device = device_by_channel_and_position(index);
  164. if (checked_device.is_null())
  165. continue;
  166. connected_devices.append(checked_device.release_nonnull());
  167. }
  168. if (index >= connected_devices.size())
  169. return nullptr;
  170. return connected_devices[index];
  171. }
  172. }