Kernel: Cleanup ATA device initialization
This commit is contained in:
		
							parent
							
								
									a3ba6da6f3
								
							
						
					
					
						commit
						db65cfeb8a
					
				|  | @ -8,43 +8,62 @@ | |||
| namespace Kernel | ||||
| { | ||||
| 
 | ||||
| 	struct ATABus; | ||||
| 	class ATAController; | ||||
| 
 | ||||
| 	class ATADevice final : public StorageDevice | ||||
| 	{ | ||||
| 	public: | ||||
| 		static BAN::ErrorOr<ATADevice*> create(ATAController*, uint16_t, uint16_t, uint8_t); | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<void> read_sectors(uint64_t, uint8_t, uint8_t*) override; | ||||
| 		virtual BAN::ErrorOr<void> write_sectors(uint64_t, uint8_t, const uint8_t*) override; | ||||
| 		virtual uint32_t sector_size() const override { return sector_words * 2; } | ||||
| 		virtual uint64_t total_size() const override { return lba_count * sector_size(); } | ||||
| 		virtual uint32_t sector_size() const override { return m_sector_words * 2; } | ||||
| 		virtual uint64_t total_size() const override { return m_lba_count * sector_size(); } | ||||
| 
 | ||||
| 		BAN::StringView model() const { return m_model; } | ||||
| 
 | ||||
| 	private: | ||||
| 		ATADevice(ATAController* controller, uint16_t base, uint16_t ctrl, uint8_t index) | ||||
| 			: m_controller(controller) | ||||
| 			, m_base(base) | ||||
| 			, m_ctrl(ctrl) | ||||
| 			, m_index(index) | ||||
| 			, m_slave_bit((index & 0x01) << 4) | ||||
| 		{ } | ||||
| 		BAN::ErrorOr<void> initialize(); | ||||
| 
 | ||||
| 		uint8_t io_read(uint16_t); | ||||
| 		void io_write(uint16_t, uint8_t); | ||||
| 		void read_buffer(uint16_t, uint16_t*, size_t); | ||||
| 		void write_buffer(uint16_t, const uint16_t*, size_t); | ||||
| 		BAN::ErrorOr<void> wait(bool); | ||||
| 		BAN::Error error(); | ||||
| 
 | ||||
| 	private: | ||||
| 		enum class DeviceType | ||||
| 		{ | ||||
| 			Unknown, | ||||
| 			ATA, | ||||
| 			ATAPI, | ||||
| 		}; | ||||
| 
 | ||||
| 		DeviceType type; | ||||
| 		uint8_t slave_bit; // 0x00 for master, 0x10 for slave
 | ||||
| 		uint16_t signature; | ||||
| 		uint16_t capabilities; | ||||
| 		uint32_t command_set; | ||||
| 		uint32_t sector_words; | ||||
| 		uint64_t lba_count; | ||||
| 		char model[41]; | ||||
| 		ATAController* m_controller; | ||||
| 		const uint16_t m_base; | ||||
| 		const uint16_t m_ctrl; | ||||
| 		const uint8_t m_index; | ||||
| 		const uint8_t m_slave_bit; | ||||
| 
 | ||||
| 		ATABus* bus; | ||||
| 		ATAController* controller; | ||||
| 		DeviceType m_type; | ||||
| 		uint16_t m_signature; | ||||
| 		uint16_t m_capabilities; | ||||
| 		uint32_t m_command_set; | ||||
| 		uint32_t m_sector_words; | ||||
| 		uint64_t m_lba_count; | ||||
| 		char m_model[41]; | ||||
| 
 | ||||
| 		friend class ATAController; | ||||
| 
 | ||||
| 		char device_name[4] {}; | ||||
| 
 | ||||
| 	public: | ||||
| 		virtual ino_t ino() const override { return !!slave_bit; } | ||||
| 		virtual ino_t ino() const override { return m_index; } | ||||
| 		virtual Mode mode() const override { return { Mode::IFBLK }; } | ||||
| 		virtual nlink_t nlink() const override { return 1; } | ||||
| 		virtual uid_t uid() const override { return 0; } | ||||
|  | @ -55,23 +74,12 @@ namespace Kernel | |||
| 		virtual dev_t dev() const override; | ||||
| 		virtual dev_t rdev() const override { return 0x5429; } | ||||
| 
 | ||||
| 		virtual BAN::StringView name() const override { return BAN::StringView(device_name, sizeof(device_name) - 1); } | ||||
| 		virtual BAN::StringView name() const override { return BAN::StringView(m_device_name, sizeof(m_device_name) - 1); } | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override; | ||||
| 	}; | ||||
| 
 | ||||
| 	struct ATABus | ||||
| 	{ | ||||
| 		uint16_t base; | ||||
| 		uint16_t ctrl; | ||||
| 		ATADevice devices[2]; | ||||
| 
 | ||||
| 		uint8_t read(uint16_t); | ||||
| 		void read_buffer(uint16_t, uint16_t*, size_t); | ||||
| 		void write(uint16_t, uint8_t); | ||||
| 		void write_buffer(uint16_t, const uint16_t*, size_t); | ||||
| 		BAN::ErrorOr<void> wait(bool); | ||||
| 		BAN::Error error(); | ||||
| 	public: | ||||
| 		char m_device_name[4] {}; | ||||
| 	}; | ||||
| 
 | ||||
| 	class ATAController final : public StorageController | ||||
|  | @ -80,15 +88,13 @@ namespace Kernel | |||
| 		static BAN::ErrorOr<ATAController*> create(const PCIDevice&); | ||||
| 
 | ||||
| 	private: | ||||
| 		ATAController(const PCIDevice& device) : m_pci_device(device) {} | ||||
| 		BAN::ErrorOr<void> initialize(); | ||||
| 		ATAController() = default; | ||||
| 		BAN::ErrorOr<void> initialize(const PCIDevice& device); | ||||
| 
 | ||||
| 		BAN::ErrorOr<void> read(ATADevice*, uint64_t, uint8_t, uint8_t*); | ||||
| 		BAN::ErrorOr<void> write(ATADevice*, uint64_t, uint8_t, const uint8_t*); | ||||
| 
 | ||||
| 	private: | ||||
| 		ATABus m_buses[2]; | ||||
| 		const PCIDevice& m_pci_device; | ||||
| 		SpinLock m_lock; | ||||
| 
 | ||||
| 		friend class ATADevice; | ||||
|  |  | |||
|  | @ -1,10 +1,8 @@ | |||
| #include <BAN/ScopeGuard.h> | ||||
| #include <kernel/IO.h> | ||||
| #include <kernel/LockGuard.h> | ||||
| #include <kernel/Storage/ATAController.h> | ||||
| 
 | ||||
| #define ATA_PRIMARY  	0 | ||||
| #define ATA_SECONDARY	1 | ||||
| 
 | ||||
| #define ATA_PORT_DATA				0x00 | ||||
| #define ATA_PORT_ERROR				0x00 | ||||
| #define ATA_PORT_SECTOR_COUNT		0x02 | ||||
|  | @ -18,6 +16,8 @@ | |||
| #define ATA_PORT_CONTROL			0x10 | ||||
| #define ATA_PORT_ALT_STATUS			0x10 | ||||
| 
 | ||||
| #define ATA_CONTROL_nIEN			0x02 | ||||
| 
 | ||||
| #define ATA_ERROR_AMNF				0x01 | ||||
| #define ATA_ERROR_TKZNF				0x02 | ||||
| #define ATA_ERROR_ABRT				0x04 | ||||
|  | @ -34,9 +34,9 @@ | |||
| 
 | ||||
| #define ATA_COMMAND_READ_SECTORS	0x20 | ||||
| #define ATA_COMMAND_WRITE_SECTORS	0x30 | ||||
| #define ATA_COMMAND_IDENTIFY_PACKET	0xA1 | ||||
| #define ATA_COMMAND_CACHE_FLUSH		0xE7 | ||||
| #define ATA_COMMAND_IDENTIFY		0xEC | ||||
| #define ATA_COMMAND_IDENTIFY_PACKET	0xA1 | ||||
| 
 | ||||
| #define ATA_IDENTIFY_SIGNATURE			0 | ||||
| #define ATA_IDENTIFY_MODEL				27 | ||||
|  | @ -52,148 +52,155 @@ | |||
| namespace Kernel | ||||
| { | ||||
| 
 | ||||
| 	BAN::ErrorOr<ATADevice*> ATADevice::create(ATAController* controller, uint16_t base, uint16_t ctrl, uint8_t index) | ||||
| 	{ | ||||
| 		ATADevice* device = new ATADevice(controller, base, ctrl, index); | ||||
| 		if (device == nullptr) | ||||
| 			return BAN::Error::from_errno(ENOMEM); | ||||
| 		BAN::ScopeGuard guard([device] { device->unref(); }); | ||||
| 		TRY(device->initialize()); | ||||
| 		guard.disable(); | ||||
| 		return device; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<ATAController*> ATAController::create(const PCIDevice& device) | ||||
| 	{ | ||||
| 		ATAController* controller = new ATAController(device); | ||||
| 		ATAController* controller = new ATAController(); | ||||
| 		if (controller == nullptr) | ||||
| 			return BAN::Error::from_errno(ENOMEM); | ||||
| 		TRY(controller->initialize()); | ||||
| 		BAN::ScopeGuard guard([controller] { controller->unref(); }); | ||||
| 		TRY(controller->initialize(device)); | ||||
| 		guard.disable(); | ||||
| 		return controller; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> ATAController::initialize() | ||||
| 	BAN::ErrorOr<void> ATADevice::initialize() | ||||
| 	{ | ||||
| 		m_buses[ATA_PRIMARY].base = 0x1F0; | ||||
| 		m_buses[ATA_PRIMARY].ctrl = 0x3F6; | ||||
| 		m_buses[ATA_PRIMARY].write(ATA_PORT_CONTROL, 2); | ||||
| 		io_write(ATA_PORT_CONTROL, ATA_CONTROL_nIEN); | ||||
| 
 | ||||
| 		m_buses[ATA_SECONDARY].base = 0x170; | ||||
| 		m_buses[ATA_SECONDARY].ctrl = 0x376; | ||||
| 		m_buses[ATA_SECONDARY].write(ATA_PORT_CONTROL, 2); | ||||
| 		io_write(ATA_PORT_DRIVE_SELECT, 0xA0 | m_slave_bit); | ||||
| 		PIT::sleep(1); | ||||
| 
 | ||||
| 		uint8_t prog_if = m_pci_device.read_byte(0x09); | ||||
| 		io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY); | ||||
| 		PIT::sleep(1); | ||||
| 
 | ||||
| 		if (io_read(ATA_PORT_STATUS) == 0) | ||||
| 			return BAN::Error::from_c_string(""); | ||||
| 		 | ||||
| 		uint8_t status = 0; | ||||
| 		while (true) | ||||
| 		{ | ||||
| 			status = io_read(ATA_PORT_STATUS); | ||||
| 			if (status & ATA_STATUS_ERR) | ||||
| 				break; | ||||
| 			if (!(status & ATA_STATUS_BSY) && (status && ATA_STATUS_DRQ)) | ||||
| 				break; | ||||
| 		} | ||||
| 
 | ||||
| 		if (status & ATA_STATUS_ERR) | ||||
| 		{ | ||||
| 			uint8_t lba1 = io_read(ATA_PORT_LBA1); | ||||
| 			uint8_t lba2 = io_read(ATA_PORT_LBA2); | ||||
| 
 | ||||
| 			if (lba1 == 0x14 && lba2 == 0xEB) | ||||
| 				m_type = ATADevice::DeviceType::ATAPI; | ||||
| 			else if (lba1 == 0x69 && lba2 == 0x96) | ||||
| 				m_type = ATADevice::DeviceType::ATAPI; | ||||
| 			else | ||||
| 				return BAN::Error::from_c_string("Not ATA/ATAPI device"); | ||||
| 
 | ||||
| 			io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY_PACKET); | ||||
| 			PIT::sleep(1); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			m_type = ATADevice::DeviceType::ATA; | ||||
| 		} | ||||
| 
 | ||||
| 		uint16_t buffer[256] {}; | ||||
| 		read_buffer(ATA_PORT_DATA, buffer, 256); | ||||
| 
 | ||||
| 		m_signature	 = *(uint16_t*)(buffer + ATA_IDENTIFY_SIGNATURE); | ||||
| 		m_capabilities = *(uint16_t*)(buffer + ATA_IDENTIFY_CAPABILITIES); | ||||
| 		m_command_set	 = *(uint32_t*)(buffer + ATA_IDENTIFY_COMMAND_SET); | ||||
| 
 | ||||
| 		if ((buffer[ATA_IDENTIFY_SECTOR_INFO] & (1 << 15)) == 0 && | ||||
| 			(buffer[ATA_IDENTIFY_SECTOR_INFO] & (1 << 14)) != 0 && | ||||
| 			(buffer[ATA_IDENTIFY_SECTOR_INFO] & (1 << 12)) != 0) | ||||
| 		{ | ||||
| 			m_sector_words = *(uint32_t*)(buffer + ATA_IDENTIFY_SECTOR_WORDS); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			m_sector_words = 256; | ||||
| 		} | ||||
| 
 | ||||
| 		m_lba_count = 0; | ||||
| 		if (m_command_set & ATA_COMMANDSET_LBA48_SUPPORTED) | ||||
| 			m_lba_count = *(uint64_t*)(buffer + ATA_IDENTIFY_LBA_COUNT_EXT); | ||||
| 		if (m_lba_count < (1 << 28)) | ||||
| 			m_lba_count = *(uint32_t*)(buffer + ATA_IDENTIFY_LBA_COUNT); | ||||
| 
 | ||||
| 		for (int i = 0; i < 20; i++) | ||||
| 		{ | ||||
| 			uint16_t word = buffer[ATA_IDENTIFY_MODEL + i]; | ||||
| 			m_model[2 * i + 0] = word >> 8; | ||||
| 			m_model[2 * i + 1] = word & 0xFF; | ||||
| 		} | ||||
| 		m_model[40] = 0; | ||||
| 		 | ||||
| 		m_device_name[0] = 'h'; | ||||
| 		m_device_name[1] = 'd'; | ||||
| 		m_device_name[2] = 'a' + m_index; | ||||
| 		m_device_name[3] = '\0'; | ||||
| 
 | ||||
| 		TRY(initialize_partitions()); | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> ATAController::initialize(const PCIDevice& pci_device) | ||||
| 	{ | ||||
| 		struct Bus | ||||
| 		{ | ||||
| 			uint16_t base; | ||||
| 			uint16_t ctrl; | ||||
| 		}; | ||||
| 
 | ||||
| 		Bus buses[2]; | ||||
| 		buses[0].base = 0x1F0; | ||||
| 		buses[0].ctrl = 0x3F6; | ||||
| 
 | ||||
| 		buses[1].base = 0x170; | ||||
| 		buses[1].ctrl = 0x376; | ||||
| 
 | ||||
| 		uint8_t prog_if = pci_device.read_byte(0x09); | ||||
| 		if (prog_if & 0x01) | ||||
| 		{ | ||||
| 			m_buses[ATA_PRIMARY].base = m_pci_device.read_dword(0x10) & 0xFFFFFFFC; | ||||
| 			m_buses[ATA_PRIMARY].ctrl = m_pci_device.read_dword(0x14) & 0xFFFFFFFC; | ||||
| 			buses[0].base = pci_device.read_dword(0x10) & 0xFFFFFFFC; | ||||
| 			buses[0].ctrl = pci_device.read_dword(0x14) & 0xFFFFFFFC; | ||||
| 		} | ||||
| 		if (prog_if & 0x04) | ||||
| 		{ | ||||
| 			m_buses[ATA_SECONDARY].base = m_pci_device.read_dword(0x18) & 0xFFFFFFFC; | ||||
| 			m_buses[ATA_SECONDARY].ctrl = m_pci_device.read_dword(0x1C) & 0xFFFFFFFC; | ||||
| 			buses[1].base = pci_device.read_dword(0x18) & 0xFFFFFFFC; | ||||
| 			buses[1].ctrl = pci_device.read_dword(0x1C) & 0xFFFFFFFC; | ||||
| 		} | ||||
| 
 | ||||
| 		for (uint8_t bus_index = 0; bus_index < 2; bus_index++) | ||||
| 		for (uint8_t drive = 0; drive < 4; drive++) | ||||
| 		{ | ||||
| 			for (uint8_t device_index = 0; device_index < 2; device_index++) | ||||
| 			auto device = ATADevice::create(this, buses[drive / 2].base, buses[drive / 2].ctrl, drive); | ||||
| 			if (device.is_error()) | ||||
| 			{ | ||||
| 				ATABus& bus = m_buses[bus_index]; | ||||
| 				ATADevice& device = bus.devices[device_index]; | ||||
| 
 | ||||
| 				device.type = ATADevice::DeviceType::Unknown; | ||||
| 				device.slave_bit = device_index << 4; | ||||
| 				device.bus = &bus; | ||||
| 				device.controller = this; | ||||
| 
 | ||||
| 				device.device_name[0] = 'h'; | ||||
| 				device.device_name[1] = 'd'; | ||||
| 				device.device_name[2] = 'a' + bus_index * 2 + device_index; | ||||
| 				device.device_name[3] = '\0'; | ||||
| 
 | ||||
| 				bus.write(ATA_PORT_DRIVE_SELECT, 0xA0 | device.slave_bit); | ||||
| 				PIT::sleep(1); | ||||
| 
 | ||||
| 				bus.write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY); | ||||
| 				PIT::sleep(1); | ||||
| 
 | ||||
| 				if (bus.read(ATA_PORT_STATUS) == 0) | ||||
| 					continue; | ||||
| 				 | ||||
| 				uint8_t status = 0; | ||||
| 				while (true) | ||||
| 				{ | ||||
| 					status = bus.read(ATA_PORT_STATUS); | ||||
| 					if (status & ATA_STATUS_ERR) | ||||
| 						break; | ||||
| 					if (!(status & ATA_STATUS_BSY) && (status && ATA_STATUS_DRQ)) | ||||
| 						break; | ||||
| 				} | ||||
| 
 | ||||
| 				auto type = ATADevice::DeviceType::ATA; | ||||
| 
 | ||||
| 				// Not a ATA device, maybe ATAPI
 | ||||
| 				if (status & ATA_STATUS_ERR) | ||||
| 				{ | ||||
| 					uint8_t lba1 = bus.read(ATA_PORT_LBA1); | ||||
| 					uint8_t lba2 = bus.read(ATA_PORT_LBA2); | ||||
| 
 | ||||
| 					if (lba1 == 0x14 && lba2 == 0xEB) | ||||
| 						type = ATADevice::DeviceType::ATAPI; | ||||
| 					else if (lba1 == 0x69 && lba2 == 0x96) | ||||
| 						type = ATADevice::DeviceType::ATAPI; | ||||
| 					else | ||||
| 						continue; | ||||
| 
 | ||||
| 					bus.write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY_PACKET); | ||||
| 					PIT::sleep(1); | ||||
| 				} | ||||
| 
 | ||||
| 				uint16_t buffer[256] {}; | ||||
| 				bus.read_buffer(ATA_PORT_DATA, buffer, 256); | ||||
| 
 | ||||
| 				device.type			= type; | ||||
| 				device.signature	= *(uint16_t*)(buffer + ATA_IDENTIFY_SIGNATURE); | ||||
| 				device.capabilities	= *(uint16_t*)(buffer + ATA_IDENTIFY_CAPABILITIES); | ||||
| 				device.command_set	= *(uint32_t*)(buffer + ATA_IDENTIFY_COMMAND_SET); | ||||
| 
 | ||||
| 				device.sector_words = 256; | ||||
| 				if ((buffer[ATA_IDENTIFY_SECTOR_INFO] & (1 << 15)) == 0 && | ||||
| 					(buffer[ATA_IDENTIFY_SECTOR_INFO] & (1 << 14)) != 0 && | ||||
| 					(buffer[ATA_IDENTIFY_SECTOR_INFO] & (1 << 12)) != 0) | ||||
| 				{ | ||||
| 					device.sector_words	= *(uint32_t*)(buffer + ATA_IDENTIFY_SECTOR_WORDS); | ||||
| 				} | ||||
| 
 | ||||
| 				device.lba_count = 0; | ||||
| 				if (device.command_set & ATA_COMMANDSET_LBA48_SUPPORTED) | ||||
| 					device.lba_count = *(uint64_t*)(buffer + ATA_IDENTIFY_LBA_COUNT_EXT); | ||||
| 				if (device.lba_count < (1 << 28)) | ||||
| 					device.lba_count = *(uint32_t*)(buffer + ATA_IDENTIFY_LBA_COUNT); | ||||
| 
 | ||||
| 				for (int i = 0; i < 20; i++) | ||||
| 				{ | ||||
| 					uint16_t word = buffer[ATA_IDENTIFY_MODEL + i]; | ||||
| 					device.model[2 * i + 0] = word >> 8; | ||||
| 					device.model[2 * i + 1] = word & 0xFF; | ||||
| 				} | ||||
| 				device.model[40] = 0; | ||||
| 
 | ||||
| 				if (auto res = device.initialize_partitions(); res.is_error()) | ||||
| 				{ | ||||
| 					dprintln("could not initialize partitions on device {}", device.device_name); | ||||
| 					device.type = ATADevice::DeviceType::Unknown; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					add_device(&device); | ||||
| 				} | ||||
| 				if (strlen(device.error().get_message()) > 0) | ||||
| 					dprintln("{}", device.error()); | ||||
| 				continue; | ||||
| 			} | ||||
| 			add_device(device.value()); | ||||
| 		} | ||||
| 
 | ||||
| 		for (uint32_t i = 0; i < 2; i++) | ||||
| 		for (StorageDevice* device_ : devices()) | ||||
| 		{ | ||||
| 			for (uint32_t j = 0; j < 2; j++) | ||||
| 			{ | ||||
| 				ATADevice& device = m_buses[i].devices[j]; | ||||
| 				if (device.type == ATADevice::DeviceType::Unknown) | ||||
| 					continue; | ||||
| 				constexpr uint32_t words_per_mib = 1024 * 1024 / 2; | ||||
| 				const char* device_type = | ||||
| 					device.type == ATADevice::DeviceType::ATA ? "ATA" : | ||||
| 					device.type == ATADevice::DeviceType::ATAPI ? "ATAPI" : | ||||
| 					"Unknown"; | ||||
| 				dprintln("Found {} Drive ({} MiB) model {}", device_type, device.lba_count * device.sector_words / words_per_mib, device.model); | ||||
| 			} | ||||
| 			ATADevice& device = *(ATADevice*)device_; | ||||
| 			dprintln("Initialized drive {} ({} MiB) model {}", device.name(), device.total_size() / (1024 * 1024), device.model()); | ||||
| 		} | ||||
| 
 | ||||
| 		return {}; | ||||
|  | @ -201,7 +208,7 @@ namespace Kernel | |||
| 
 | ||||
| 	BAN::ErrorOr<void> ATAController::read(ATADevice* device, uint64_t lba, uint8_t sector_count, uint8_t* buffer) | ||||
| 	{ | ||||
| 		if (lba + sector_count > device->lba_count) | ||||
| 		if (lba + sector_count > device->m_lba_count) | ||||
| 			return BAN::Error::from_c_string("Attempted to read outside of the device boundaries"); | ||||
| 
 | ||||
| 		LockGuard _(m_lock); | ||||
|  | @ -209,17 +216,17 @@ namespace Kernel | |||
| 		if (lba < (1 << 28)) | ||||
| 		{ | ||||
| 			// LBA28
 | ||||
| 			device->bus->write(ATA_PORT_DRIVE_SELECT, 0xE0 | device->slave_bit | ((lba >> 24) & 0x0F)); | ||||
| 			device->bus->write(ATA_PORT_SECTOR_COUNT, sector_count); | ||||
| 			device->bus->write(ATA_PORT_LBA0, (uint8_t)(lba >>  0)); | ||||
| 			device->bus->write(ATA_PORT_LBA1, (uint8_t)(lba >>  8)); | ||||
| 			device->bus->write(ATA_PORT_LBA2, (uint8_t)(lba >> 16)); | ||||
| 			device->bus->write(ATA_PORT_COMMAND, ATA_COMMAND_READ_SECTORS); | ||||
| 			device->io_write(ATA_PORT_DRIVE_SELECT, 0xE0 | device->m_slave_bit | ((lba >> 24) & 0x0F)); | ||||
| 			device->io_write(ATA_PORT_SECTOR_COUNT, sector_count); | ||||
| 			device->io_write(ATA_PORT_LBA0, (uint8_t)(lba >>  0)); | ||||
| 			device->io_write(ATA_PORT_LBA1, (uint8_t)(lba >>  8)); | ||||
| 			device->io_write(ATA_PORT_LBA2, (uint8_t)(lba >> 16)); | ||||
| 			device->io_write(ATA_PORT_COMMAND, ATA_COMMAND_READ_SECTORS); | ||||
| 
 | ||||
| 			for (uint32_t sector = 0; sector < sector_count; sector++) | ||||
| 			{ | ||||
| 				TRY(device->bus->wait(true)); | ||||
| 				device->bus->read_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device->sector_words, device->sector_words); | ||||
| 				TRY(device->wait(true)); | ||||
| 				device->read_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device->m_sector_words, device->m_sector_words); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
|  | @ -233,7 +240,7 @@ namespace Kernel | |||
| 
 | ||||
| 	BAN::ErrorOr<void> ATAController::write(ATADevice* device, uint64_t lba, uint8_t sector_count, const uint8_t* buffer) | ||||
| 	{ | ||||
| 		if (lba + sector_count > device->lba_count) | ||||
| 		if (lba + sector_count > device->m_lba_count) | ||||
| 			return BAN::Error::from_c_string("Attempted to read outside of the device boundaries"); | ||||
| 
 | ||||
| 		LockGuard _(m_lock); | ||||
|  | @ -241,17 +248,17 @@ namespace Kernel | |||
| 		if (lba < (1 << 28)) | ||||
| 		{ | ||||
| 			// LBA28
 | ||||
| 			device->bus->write(ATA_PORT_DRIVE_SELECT, 0xE0 | device->slave_bit | ((lba >> 24) & 0x0F)); | ||||
| 			device->bus->write(ATA_PORT_SECTOR_COUNT, sector_count); | ||||
| 			device->bus->write(ATA_PORT_LBA0, (uint8_t)(lba >>  0)); | ||||
| 			device->bus->write(ATA_PORT_LBA1, (uint8_t)(lba >>  8)); | ||||
| 			device->bus->write(ATA_PORT_LBA2, (uint8_t)(lba >> 16)); | ||||
| 			device->bus->write(ATA_PORT_COMMAND, ATA_COMMAND_WRITE_SECTORS); | ||||
| 			device->io_write(ATA_PORT_DRIVE_SELECT, 0xE0 | device->m_slave_bit | ((lba >> 24) & 0x0F)); | ||||
| 			device->io_write(ATA_PORT_SECTOR_COUNT, sector_count); | ||||
| 			device->io_write(ATA_PORT_LBA0, (uint8_t)(lba >>  0)); | ||||
| 			device->io_write(ATA_PORT_LBA1, (uint8_t)(lba >>  8)); | ||||
| 			device->io_write(ATA_PORT_LBA2, (uint8_t)(lba >> 16)); | ||||
| 			device->io_write(ATA_PORT_COMMAND, ATA_COMMAND_WRITE_SECTORS); | ||||
| 
 | ||||
| 			for (uint32_t sector = 0; sector < sector_count; sector++) | ||||
| 			{ | ||||
| 				TRY(device->bus->wait(false)); | ||||
| 				device->bus->write_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device->sector_words, device->sector_words); | ||||
| 				TRY(device->wait(false)); | ||||
| 				device->write_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device->m_sector_words, device->m_sector_words); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
|  | @ -260,71 +267,71 @@ namespace Kernel | |||
| 			ASSERT(false); | ||||
| 		} | ||||
| 
 | ||||
| 		TRY(device->bus->wait(false)); | ||||
| 		device->bus->write(ATA_PORT_COMMAND, ATA_COMMAND_CACHE_FLUSH); | ||||
| 		TRY(device->wait(false)); | ||||
| 		device->io_write(ATA_PORT_COMMAND, ATA_COMMAND_CACHE_FLUSH); | ||||
| 
 | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> ATADevice::read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer) | ||||
| 	{ | ||||
| 		TRY(controller->read(this, lba, sector_count, buffer)); | ||||
| 		TRY(m_controller->read(this, lba, sector_count, buffer)); | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> ATADevice::write_sectors(uint64_t lba, uint8_t sector_count, const uint8_t* buffer) | ||||
| 	{ | ||||
| 		TRY(controller->write(this, lba, sector_count, buffer)); | ||||
| 		TRY(m_controller->write(this, lba, sector_count, buffer)); | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	uint8_t ATABus::read(uint16_t port) | ||||
| 	uint8_t ATADevice::io_read(uint16_t port) | ||||
| 	{ | ||||
| 		if (port <= 0x07) | ||||
| 			return IO::inb(base + port); | ||||
| 			return IO::inb(m_base + port); | ||||
| 		if (0x10 <= port && port <= 0x11) | ||||
| 			return IO::inb(ctrl + port - 0x10); | ||||
| 			return IO::inb(m_ctrl + port - 0x10); | ||||
| 		ASSERT_NOT_REACHED(); | ||||
| 	} | ||||
| 
 | ||||
| 	void ATABus::read_buffer(uint16_t port, uint16_t* buffer, size_t words) | ||||
| 	void ATADevice::read_buffer(uint16_t port, uint16_t* buffer, size_t words) | ||||
| 	{ | ||||
| 		if (port <= 0x07) | ||||
| 			return IO::insw(base + port - 0x00, buffer, words); | ||||
| 			return IO::insw(m_base + port - 0x00, buffer, words); | ||||
| 		if (0x10 <= port && port <= 0x11) | ||||
| 			return IO::insw(ctrl + port - 0x10, buffer, words); | ||||
| 			return IO::insw(m_ctrl + port - 0x10, buffer, words); | ||||
| 		ASSERT_NOT_REACHED(); | ||||
| 	} | ||||
| 
 | ||||
| 	void ATABus::write(uint16_t port, uint8_t data) | ||||
| 	void ATADevice::io_write(uint16_t port, uint8_t data) | ||||
| 	{ | ||||
| 		if (port <= 0x07) | ||||
| 			return IO::outb(base + port, data); | ||||
| 			return IO::outb(m_base + port, data); | ||||
| 		if (0x10 <= port && port <= 0x11) | ||||
| 			return IO::outb(ctrl + port - 0x10, data); | ||||
| 			return IO::outb(m_ctrl + port - 0x10, data); | ||||
| 		ASSERT_NOT_REACHED(); | ||||
| 	} | ||||
| 
 | ||||
| 	void ATABus::write_buffer(uint16_t port, const uint16_t* buffer, size_t words) | ||||
| 	void ATADevice::write_buffer(uint16_t port, const uint16_t* buffer, size_t words) | ||||
| 	{ | ||||
| 		uint16_t io_port = 0; | ||||
| 		if (port <= 0x07) | ||||
| 			io_port = base + port; | ||||
| 			io_port = m_base + port; | ||||
| 		if (0x10 <= port && port <= 0x11) | ||||
| 			io_port = ctrl + port - 0x10; | ||||
| 			io_port = m_ctrl + port - 0x10; | ||||
| 		ASSERT(io_port); | ||||
| 		for (size_t i = 0; i < words; i++) | ||||
| 			IO::outw(io_port, buffer[i]); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> ATABus::wait(bool wait_drq) | ||||
| 	BAN::ErrorOr<void> ATADevice::wait(bool wait_drq) | ||||
| 	{ | ||||
| 		for (uint32_t i = 0; i < 4; i++) | ||||
| 			read(ATA_PORT_ALT_STATUS); | ||||
| 			io_read(ATA_PORT_ALT_STATUS); | ||||
| 
 | ||||
| 		uint8_t status = ATA_STATUS_BSY; | ||||
| 		while (status & ATA_STATUS_BSY) | ||||
| 			status = read(ATA_PORT_STATUS); | ||||
| 			status = io_read(ATA_PORT_STATUS); | ||||
| 
 | ||||
| 		while (wait_drq && !(status & ATA_STATUS_DRQ)) | ||||
| 		{ | ||||
|  | @ -332,15 +339,15 @@ namespace Kernel | |||
| 				return error(); | ||||
| 			if (status & ATA_STATUS_DF) | ||||
| 				return BAN::Error::from_errno(EIO); | ||||
| 			status = read(ATA_PORT_STATUS); | ||||
| 			status = io_read(ATA_PORT_STATUS); | ||||
| 		} | ||||
| 
 | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::Error ATABus::error() | ||||
| 	BAN::Error ATADevice::error() | ||||
| 	{ | ||||
| 		uint8_t err = read(ATA_PORT_ERROR); | ||||
| 		uint8_t err = io_read(ATA_PORT_ERROR); | ||||
| 		if (err & ATA_ERROR_AMNF) | ||||
| 			return BAN::Error::from_c_string("Address mark not found."); | ||||
| 		if (err & ATA_ERROR_TKZNF) | ||||
|  | @ -362,8 +369,8 @@ namespace Kernel | |||
| 
 | ||||
| 	dev_t ATADevice::dev() const | ||||
| 	{ | ||||
| 		ASSERT(controller); | ||||
| 		return controller->dev(); | ||||
| 		ASSERT(m_controller); | ||||
| 		return m_controller->dev(); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> ATADevice::read(size_t offset, void* buffer, size_t bytes) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue