diff --git a/src/kernel/ahci/hba.cpp b/src/kernel/ahci/hba.cpp index 75c5d0f..245eddc 100644 --- a/src/kernel/ahci/hba.cpp +++ b/src/kernel/ahci/hba.cpp @@ -64,8 +64,9 @@ hba::hba(pci_device *device) uint32_t bar5 = device->get_bar(5); log::debug(logs::driver, "HBA raw BAR5 is %08lx", bar5); - m_data = reinterpret_cast(bar5 & ~0xfffull); - pm->map_offset_pointer(reinterpret_cast(&m_data), 0x2000); + void *data = reinterpret_cast(bar5 & ~0xfffull); + pm->map_offset_pointer(&data, 0x2000); + m_data = reinterpret_cast(data); if (! bitfield_has(m_data->cap, hba_cap::ahci_only)) m_data->host_control |= 0x80000000; // Enable AHCI mode @@ -78,7 +79,7 @@ hba::hba(pci_device *device) log::debug(logs::driver, " %d ports", ports); log::debug(logs::driver, " %d command slots", slots); - port_data *pd = reinterpret_cast( + auto *pd = reinterpret_cast( kutil::offset_pointer(m_data, 0x100)); bool needs_interrupt = false; @@ -99,9 +100,11 @@ hba::hba(pci_device *device) if (!p.active()) continue; if (p.get_type() == sata_signature::sata_drive) { - p.identify_async(); + p.sata_reconnect(); + /* if (fs::partition::load(&p) == 0) dm.register_block_device(&p); + */ } } } @@ -129,7 +132,7 @@ hba::dump() }; cons->printf("HBA Registers:\n"); - uint32_t *data = reinterpret_cast(m_data); + auto *data = reinterpret_cast(m_data); for (int i = 0; i < 11; ++i) { cons->printf(" %s: %08x\n", regs[i], data[i]); } diff --git a/src/kernel/ahci/hba.h b/src/kernel/ahci/hba.h index 2e95043..51d1f42 100644 --- a/src/kernel/ahci/hba.h +++ b/src/kernel/ahci/hba.h @@ -30,7 +30,7 @@ public: private: pci_device *m_device; - hba_data *m_data; + hba_data volatile *m_data; kutil::vector m_ports; }; diff --git a/src/kernel/ahci/port.cpp b/src/kernel/ahci/port.cpp index 80f6d08..76255a1 100644 --- a/src/kernel/ahci/port.cpp +++ b/src/kernel/ahci/port.cpp @@ -15,6 +15,7 @@ namespace ahci { } IS_BITFIELD(ahci::port_cmd); +IS_BITFIELD(volatile ahci::port_cmd); IS_BITFIELD(ahci::cmd_list_flags); namespace ahci { @@ -117,7 +118,7 @@ struct port_data } __attribute__ ((packed)); -port::port(hba *device, uint8_t index, port_data *data, bool impl) : +port::port(hba *device, uint8_t index, port_data volatile *data, bool impl) : m_index(index), m_type(sata_signature::none), m_state(state::unimpl), @@ -351,6 +352,14 @@ port::identify_async() return -1; } +void +port::sata_reconnect() +{ + m_data->serial_control |= 1; + io_wait(1000); // About 1ms + m_data->serial_control &= ~1; +} + bool port::issue_command(int slot) { @@ -378,8 +387,18 @@ port::handle_interrupt() // TODO: handle other states in interrupt_status - if (m_data->interrupt_status & 0x40000000) { + uint32_t is = m_data->interrupt_status; + + if (is & 0x00000040) { + // Port connect status change: For now clear the "exchange" + // bit in SERR, this should probably kick off diagnostics. + m_data->serial_error = 0x04000000; + identify_async(); + } + + if (is & 0x40000000) { log::error(logs::driver, "AHCI task file error"); + dump(); kassert(0, "Task file error"); } @@ -589,7 +608,7 @@ port::dump() }; cons->printf("Port Registers:\n"); - uint32_t *data = reinterpret_cast(m_data); + auto *data = reinterpret_cast(m_data); for (int i = 0; i < 18; ++i) { if (regs[i]) cons->printf(" %s: %08x\n", regs[i], data[i]); } diff --git a/src/kernel/ahci/port.h b/src/kernel/ahci/port.h index 8d1885f..7296d70 100644 --- a/src/kernel/ahci/port.h +++ b/src/kernel/ahci/port.h @@ -27,7 +27,7 @@ public: /// \arg index Index of the port on its HBA /// \arg data Pointer to the device's registers for this port /// \arg impl Whether this port is marked as implemented in the HBA - port(hba *device, uint8_t index, port_data *data, bool impl); + port(hba *device, uint8_t index, port_data volatile *data, bool impl); /// Destructor ~port(); @@ -80,6 +80,10 @@ public: /// \returns A handle to the read operation, or -1 on error int identify_async(); + /// Tell the HBA to reconnect to the SATA device. A successful + /// reconnect will kick off an identify command. + void sata_reconnect(); + /// Handle an incoming interrupt void handle_interrupt(); @@ -123,7 +127,7 @@ private: state m_state; hba *m_hba; - port_data *m_data; + port_data volatile *m_data; void *m_fis; cmd_list_entry *m_cmd_list; cmd_table *m_cmd_table; diff --git a/src/kernel/io.cpp b/src/kernel/io.cpp index 6065c9a..f6a9830 100644 --- a/src/kernel/io.cpp +++ b/src/kernel/io.cpp @@ -31,7 +31,8 @@ wrmsr(uint64_t addr, uint64_t value) } void -io_wait() +io_wait(unsigned times) { - outb(0x80, 0); + for (unsigned i = 0; i < times; ++i) + outb(0x80, 0); } diff --git a/src/kernel/io.h b/src/kernel/io.h index dbd9f67..43e55cd 100644 --- a/src/kernel/io.h +++ b/src/kernel/io.h @@ -25,7 +25,8 @@ uint64_t rdmsr(uint64_t addr); void wrmsr(uint64_t addr, uint64_t value); /// Pause briefly by doing IO to port 0x80 -void io_wait(); +/// \arg times Number of times to delay by writing +void io_wait(unsigned times = 1); } diff --git a/src/modules/kutil/enum_bitfields.h b/src/modules/kutil/enum_bitfields.h index dc55a84..b422190 100644 --- a/src/modules/kutil/enum_bitfields.h +++ b/src/modules/kutil/enum_bitfields.h @@ -8,27 +8,27 @@ struct is_enum_bitfield { static constexpr bool value = false; }; #define IS_BITFIELD(name) \ template<> struct ::is_enum_bitfield {static constexpr bool value=true;} -template +template typename std::enable_if::value,E>::type -operator & (E lhs, E rhs) +operator & (E lhs, F rhs) { return static_cast ( static_cast::type>(lhs) & static_cast::type>(rhs)); } -template +template typename std::enable_if::value,E>::type -operator | (E lhs, E rhs) +operator | (E lhs, F rhs) { return static_cast ( static_cast::type>(lhs) | static_cast::type>(rhs)); } -template +template typename std::enable_if::value,E>::type -operator ^ (E lhs, E rhs) +operator ^ (E lhs, F rhs) { return static_cast ( static_cast::type>(lhs) ^ @@ -42,9 +42,9 @@ operator ~ (E rhs) return static_cast(~static_cast::type>(rhs)); } -template +template typename std::enable_if::value,E>::type& -operator |= (E &lhs, E rhs) +operator |= (E &lhs, F rhs) { lhs = static_cast( static_cast::type>(lhs) | @@ -53,9 +53,9 @@ operator |= (E &lhs, E rhs) return lhs; } -template +template typename std::enable_if::value,E>::type& -operator &= (E &lhs, E rhs) +operator &= (E &lhs, F rhs) { lhs = static_cast( static_cast::type>(lhs) & @@ -64,9 +64,9 @@ operator &= (E &lhs, E rhs) return lhs; } -template +template typename std::enable_if::value,E>::type& -operator ^= (E &lhs, E rhs) +operator ^= (E &lhs, F rhs) { lhs = static_cast( static_cast::type>(lhs) ^