IDEController.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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::Address address, bool force_pio)
  17. {
  18. return adopt_ref(*new IDEController(address, 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::Address address, bool force_pio)
  46. : StorageController()
  47. , PCI::Device(address)
  48. {
  49. PCI::enable_io_space(address);
  50. PCI::enable_memory_space(address);
  51. initialize(force_pio);
  52. }
  53. UNMAP_AFTER_INIT IDEController::~IDEController()
  54. {
  55. }
  56. bool IDEController::is_pci_native_mode_enabled() const
  57. {
  58. return (PCI::get_programming_interface(pci_address()) & 0x05) != 0;
  59. }
  60. bool IDEController::is_pci_native_mode_enabled_on_primary_channel() const
  61. {
  62. return (PCI::get_programming_interface(pci_address()) & 0x1) == 0x1;
  63. }
  64. bool IDEController::is_pci_native_mode_enabled_on_secondary_channel() const
  65. {
  66. return (PCI::get_programming_interface(pci_address()) & 0x4) == 0x4;
  67. }
  68. bool IDEController::is_bus_master_capable() const
  69. {
  70. return PCI::get_programming_interface(pci_address()) & (1 << 7);
  71. }
  72. static const char* detect_controller_type(u8 programming_value)
  73. {
  74. switch (programming_value) {
  75. case 0x00:
  76. return "ISA Compatibility mode-only controller";
  77. case 0x05:
  78. return "PCI native mode-only controller";
  79. case 0x0A:
  80. return "ISA Compatibility mode controller, supports both channels switched to PCI native mode";
  81. case 0x0F:
  82. return "PCI native mode controller, supports both channels switched to ISA compatibility mode";
  83. case 0x80:
  84. return "ISA Compatibility mode-only controller, supports bus mastering";
  85. case 0x85:
  86. return "PCI native mode-only controller, supports bus mastering";
  87. case 0x8A:
  88. return "ISA Compatibility mode controller, supports both channels switched to PCI native mode, supports bus mastering";
  89. case 0x8F:
  90. return "PCI native mode controller, supports both channels switched to ISA compatibility mode, supports bus mastering";
  91. default:
  92. VERIFY_NOT_REACHED();
  93. }
  94. VERIFY_NOT_REACHED();
  95. }
  96. UNMAP_AFTER_INIT void IDEController::initialize(bool force_pio)
  97. {
  98. auto bus_master_base = IOAddress(PCI::get_BAR4(pci_address()) & (~1));
  99. dbgln("IDE controller @ {}: bus master base was set to {}", pci_address(), bus_master_base);
  100. dbgln("IDE controller @ {}: interrupt line was set to {}", pci_address(), PCI::get_interrupt_line(pci_address()));
  101. dbgln("IDE controller @ {}: {}", pci_address(), detect_controller_type(PCI::get_programming_interface(pci_address())));
  102. dbgln("IDE controller @ {}: primary channel DMA capable? {}", pci_address(), ((bus_master_base.offset(2).in<u8>() >> 5) & 0b11));
  103. dbgln("IDE controller @ {}: secondary channel DMA capable? {}", pci_address(), ((bus_master_base.offset(2 + 8).in<u8>() >> 5) & 0b11));
  104. if (!is_bus_master_capable())
  105. force_pio = true;
  106. auto bar0 = PCI::get_BAR0(pci_address());
  107. auto primary_base_io = (bar0 == 0x1 || bar0 == 0) ? IOAddress(0x1F0) : IOAddress(bar0 & (~1));
  108. auto bar1 = PCI::get_BAR1(pci_address());
  109. auto primary_control_io = (bar1 == 0x1 || bar1 == 0) ? IOAddress(0x3F6) : IOAddress(bar1 & (~1));
  110. auto bar2 = PCI::get_BAR2(pci_address());
  111. auto secondary_base_io = (bar2 == 0x1 || bar2 == 0) ? IOAddress(0x170) : IOAddress(bar2 & (~1));
  112. auto bar3 = PCI::get_BAR3(pci_address());
  113. auto secondary_control_io = (bar3 == 0x1 || bar3 == 0) ? IOAddress(0x376) : IOAddress(bar3 & (~1));
  114. auto irq_line = PCI::get_interrupt_line(pci_address());
  115. if (is_pci_native_mode_enabled()) {
  116. VERIFY(irq_line != 0);
  117. }
  118. if (is_pci_native_mode_enabled_on_primary_channel()) {
  119. if (force_pio)
  120. m_channels.append(IDEChannel::create(*this, irq_line, { primary_base_io, primary_control_io }, IDEChannel::ChannelType::Primary));
  121. else
  122. m_channels.append(BMIDEChannel::create(*this, irq_line, { primary_base_io, primary_control_io, bus_master_base }, IDEChannel::ChannelType::Primary));
  123. } else {
  124. if (force_pio)
  125. m_channels.append(IDEChannel::create(*this, { primary_base_io, primary_control_io }, IDEChannel::ChannelType::Primary));
  126. else
  127. m_channels.append(BMIDEChannel::create(*this, { primary_base_io, primary_control_io, bus_master_base }, IDEChannel::ChannelType::Primary));
  128. }
  129. m_channels[0].enable_irq();
  130. if (is_pci_native_mode_enabled_on_secondary_channel()) {
  131. if (force_pio)
  132. m_channels.append(IDEChannel::create(*this, irq_line, { secondary_base_io, secondary_control_io }, IDEChannel::ChannelType::Secondary));
  133. else
  134. m_channels.append(BMIDEChannel::create(*this, irq_line, { secondary_base_io, secondary_control_io, bus_master_base.offset(8) }, IDEChannel::ChannelType::Secondary));
  135. } else {
  136. if (force_pio)
  137. m_channels.append(IDEChannel::create(*this, { secondary_base_io, secondary_control_io }, IDEChannel::ChannelType::Secondary));
  138. else
  139. m_channels.append(BMIDEChannel::create(*this, { secondary_base_io, secondary_control_io, bus_master_base.offset(8) }, IDEChannel::ChannelType::Secondary));
  140. }
  141. m_channels[1].enable_irq();
  142. }
  143. RefPtr<StorageDevice> IDEController::device_by_channel_and_position(u32 index) const
  144. {
  145. switch (index) {
  146. case 0:
  147. return m_channels[0].master_device();
  148. case 1:
  149. return m_channels[0].slave_device();
  150. case 2:
  151. return m_channels[1].master_device();
  152. case 3:
  153. return m_channels[1].slave_device();
  154. }
  155. VERIFY_NOT_REACHED();
  156. }
  157. RefPtr<StorageDevice> IDEController::device(u32 index) const
  158. {
  159. NonnullRefPtrVector<StorageDevice> connected_devices;
  160. for (size_t index = 0; index < 4; index++) {
  161. auto checked_device = device_by_channel_and_position(index);
  162. if (checked_device.is_null())
  163. continue;
  164. connected_devices.append(checked_device.release_nonnull());
  165. }
  166. if (index >= connected_devices.size())
  167. return nullptr;
  168. return connected_devices[index];
  169. }
  170. }