IDEController.cpp 6.8 KB

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