IDEController.cpp 6.7 KB

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