Serenity Operating System
at hosted 517 lines 17 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <AK/ByteBuffer.h> 28#include <AK/StringView.h> 29#include <Kernel/Devices/PATAChannel.h> 30#include <Kernel/Devices/PATADiskDevice.h> 31#include <Kernel/FileSystem/ProcFS.h> 32#include <Kernel/Process.h> 33#include <Kernel/VM/MemoryManager.h> 34#include <LibBareMetal/IO.h> 35 36namespace Kernel { 37 38#define PATA_PRIMARY_IRQ 14 39#define PATA_SECONDARY_IRQ 15 40 41//#define PATA_DEBUG 42 43#define ATA_SR_BSY 0x80 44#define ATA_SR_DRDY 0x40 45#define ATA_SR_DF 0x20 46#define ATA_SR_DSC 0x10 47#define ATA_SR_DRQ 0x08 48#define ATA_SR_CORR 0x04 49#define ATA_SR_IDX 0x02 50#define ATA_SR_ERR 0x01 51 52#define ATA_ER_BBK 0x80 53#define ATA_ER_UNC 0x40 54#define ATA_ER_MC 0x20 55#define ATA_ER_IDNF 0x10 56#define ATA_ER_MCR 0x08 57#define ATA_ER_ABRT 0x04 58#define ATA_ER_TK0NF 0x02 59#define ATA_ER_AMNF 0x01 60 61#define ATA_CMD_READ_PIO 0x20 62#define ATA_CMD_READ_PIO_EXT 0x24 63#define ATA_CMD_READ_DMA 0xC8 64#define ATA_CMD_READ_DMA_EXT 0x25 65#define ATA_CMD_WRITE_PIO 0x30 66#define ATA_CMD_WRITE_PIO_EXT 0x34 67#define ATA_CMD_WRITE_DMA 0xCA 68#define ATA_CMD_WRITE_DMA_EXT 0x35 69#define ATA_CMD_CACHE_FLUSH 0xE7 70#define ATA_CMD_CACHE_FLUSH_EXT 0xEA 71#define ATA_CMD_PACKET 0xA0 72#define ATA_CMD_IDENTIFY_PACKET 0xA1 73#define ATA_CMD_IDENTIFY 0xEC 74 75#define ATAPI_CMD_READ 0xA8 76#define ATAPI_CMD_EJECT 0x1B 77 78#define ATA_IDENT_DEVICETYPE 0 79#define ATA_IDENT_CYLINDERS 2 80#define ATA_IDENT_HEADS 6 81#define ATA_IDENT_SECTORS 12 82#define ATA_IDENT_SERIAL 20 83#define ATA_IDENT_MODEL 54 84#define ATA_IDENT_CAPABILITIES 98 85#define ATA_IDENT_FIELDVALID 106 86#define ATA_IDENT_MAX_LBA 120 87#define ATA_IDENT_COMMANDSETS 164 88#define ATA_IDENT_MAX_LBA_EXT 200 89 90#define IDE_ATA 0x00 91#define IDE_ATAPI 0x01 92 93#define ATA_REG_DATA 0x00 94#define ATA_REG_ERROR 0x01 95#define ATA_REG_FEATURES 0x01 96#define ATA_REG_SECCOUNT0 0x02 97#define ATA_REG_LBA0 0x03 98#define ATA_REG_LBA1 0x04 99#define ATA_REG_LBA2 0x05 100#define ATA_REG_HDDEVSEL 0x06 101#define ATA_REG_COMMAND 0x07 102#define ATA_REG_STATUS 0x07 103#define ATA_CTL_CONTROL 0x00 104#define ATA_CTL_ALTSTATUS 0x00 105#define ATA_CTL_DEVADDRESS 0x01 106 107#define PCI_Mass_Storage_Class 0x1 108#define PCI_IDE_Controller_Subclass 0x1 109static Lock& s_lock() 110{ 111 static Lock* lock; 112 if (!lock) 113 lock = new Lock; 114 115 return *lock; 116}; 117 118OwnPtr<PATAChannel> PATAChannel::create(ChannelType type, bool force_pio) 119{ 120 PCI::Address pci_address; 121 PCI::enumerate_all([&](const PCI::Address& address, PCI::ID id) { 122 if (PCI::get_class(address) == PCI_Mass_Storage_Class && PCI::get_subclass(address) == PCI_IDE_Controller_Subclass) { 123 pci_address = address; 124 klog() << "PATAChannel: PATA Controller found! id=" << String::format("%w", id.vendor_id) << ":" << String::format("%w", id.device_id); 125 } 126 }); 127 return make<PATAChannel>(pci_address, type, force_pio); 128} 129 130PATAChannel::PATAChannel(PCI::Address address, ChannelType type, bool force_pio) 131 : PCI::Device(address, (type == ChannelType::Primary ? PATA_PRIMARY_IRQ : PATA_SECONDARY_IRQ)) 132 , m_channel_number((type == ChannelType::Primary ? 0 : 1)) 133 , m_io_base((type == ChannelType::Primary ? 0x1F0 : 0x170)) 134 , m_control_base((type == ChannelType::Primary ? 0x3f6 : 0x376)) 135 , m_bus_master_base(PCI::get_BAR4(pci_address()) & 0xfffc) 136{ 137 disable_irq(); 138 139 m_dma_enabled.resource() = true; 140 ProcFS::add_sys_bool("ide_dma", m_dma_enabled); 141 142 m_prdt_page = MM.allocate_supervisor_physical_page(); 143 initialize(force_pio); 144 detect_disks(); 145 disable_irq(); 146} 147 148PATAChannel::~PATAChannel() 149{ 150} 151 152void PATAChannel::prepare_for_irq() 153{ 154 cli(); 155 enable_irq(); 156} 157 158void PATAChannel::initialize(bool force_pio) 159{ 160 161 if (force_pio) { 162 klog() << "PATAChannel: Requested to force PIO mode; not setting up DMA"; 163 return; 164 } 165 // Let's try to set up DMA transfers. 166 PCI::enable_bus_mastering(pci_address()); 167 PCI::enable_interrupt_line(pci_address()); 168 prdt().end_of_table = 0x8000; 169 m_dma_buffer_page = MM.allocate_supervisor_physical_page(); 170 klog() << "PATAChannel: Bus master IDE: " << m_bus_master_base; 171} 172 173static void print_ide_status(u8 status) 174{ 175 klog() << "PATAChannel: print_ide_status: DRQ=" << ((status & ATA_SR_DRQ) != 0) << " BSY=" << ((status & ATA_SR_BSY) != 0) << " DRDY=" << ((status & ATA_SR_DRDY) != 0) << " DSC=" << ((status & ATA_SR_DSC) != 0) << " DF=" << ((status & ATA_SR_DF) != 0) << " CORR=" << ((status & ATA_SR_CORR) != 0) << " IDX=" << ((status & ATA_SR_IDX) != 0) << " ERR=" << ((status & ATA_SR_ERR) != 0); 176} 177 178void PATAChannel::wait_for_irq() 179{ 180 Thread::current->wait_on(m_irq_queue); 181 disable_irq(); 182} 183 184void PATAChannel::handle_irq(const RegisterState&) 185{ 186 u8 status = m_io_base.offset(ATA_REG_STATUS).in<u8>(); 187 if (status & ATA_SR_ERR) { 188 print_ide_status(status); 189 m_device_error = m_io_base.offset(ATA_REG_ERROR).in<u8>(); 190 klog() << "PATAChannel: Error " << String::format("%b", m_device_error) << "!"; 191 } else { 192 m_device_error = 0; 193 } 194#ifdef PATA_DEBUG 195 klog() << "PATAChannel: interrupt: DRQ=" << ((status & ATA_SR_DRQ) != 0) << " BSY=" << ((status & ATA_SR_BSY) != 0) << " DRDY=" << ((status & ATA_SR_DRDY) != 0); 196#endif 197 m_irq_queue.wake_all(); 198} 199 200static void io_delay() 201{ 202 for (int i = 0; i < 4; ++i) 203 IO::in8(0x3f6); 204} 205 206void PATAChannel::detect_disks() 207{ 208 // There are only two possible disks connected to a channel 209 for (auto i = 0; i < 2; i++) { 210 m_io_base.offset(ATA_REG_HDDEVSEL).out<u8>(0xA0 | (i << 4)); // First, we need to select the drive itself 211 212 // Apparently these need to be 0 before sending IDENTIFY?! 213 m_io_base.offset(ATA_REG_SECCOUNT0).out<u8>(0x00); 214 m_io_base.offset(ATA_REG_LBA0).out<u8>(0x00); 215 m_io_base.offset(ATA_REG_LBA1).out<u8>(0x00); 216 m_io_base.offset(ATA_REG_LBA2).out<u8>(0x00); 217 218 m_io_base.offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_IDENTIFY); // Send the ATA_IDENTIFY command 219 220 // Wait for the BSY flag to be reset 221 while (m_io_base.offset(ATA_REG_STATUS).in<u8>() & ATA_SR_BSY) 222 ; 223 224 if (m_io_base.offset(ATA_REG_STATUS).in<u8>() == 0x00) { 225#ifdef PATA_DEBUG 226 klog() << "PATAChannel: No " << (i == 0 ? "master" : "slave") << " disk detected!"; 227#endif 228 continue; 229 } 230 231 ByteBuffer wbuf = ByteBuffer::create_uninitialized(512); 232 ByteBuffer bbuf = ByteBuffer::create_uninitialized(512); 233 u8* b = bbuf.data(); 234 u16* w = (u16*)wbuf.data(); 235 const u16* wbufbase = (u16*)wbuf.data(); 236 237 for (u32 i = 0; i < 256; ++i) { 238 u16 data = m_io_base.offset(ATA_REG_DATA).in<u16>(); 239 *(w++) = data; 240 *(b++) = MSB(data); 241 *(b++) = LSB(data); 242 } 243 244 // "Unpad" the device name string. 245 for (u32 i = 93; i > 54 && bbuf[i] == ' '; --i) 246 bbuf[i] = 0; 247 248 u8 cyls = wbufbase[1]; 249 u8 heads = wbufbase[3]; 250 u8 spt = wbufbase[6]; 251 252 klog() << "PATAChannel: Name=" << ((char*)bbuf.data() + 54) << ", C/H/Spt=" << cyls << "/" << heads << "/" << spt; 253 254 int major = (m_channel_number == 0) ? 3 : 4; 255 if (i == 0) { 256 m_master = PATADiskDevice::create(*this, PATADiskDevice::DriveType::Master, major, 0); 257 m_master->set_drive_geometry(cyls, heads, spt); 258 } else { 259 m_slave = PATADiskDevice::create(*this, PATADiskDevice::DriveType::Slave, major, 1); 260 m_slave->set_drive_geometry(cyls, heads, spt); 261 } 262 } 263} 264 265bool PATAChannel::ata_read_sectors_with_dma(u32 lba, u16 count, u8* outbuf, bool slave_request) 266{ 267 LOCKER(s_lock()); 268#ifdef PATA_DEBUG 269 dbg() << "PATAChannel::ata_read_sectors_with_dma (" << lba << " x" << count << ") -> " << outbuf; 270#endif 271 272 prdt().offset = m_dma_buffer_page->paddr(); 273 prdt().size = 512 * count; 274 275 ASSERT(prdt().size <= PAGE_SIZE); 276 277 // Stop bus master 278 m_bus_master_base.out<u8>(0); 279 280 // Write the PRDT location 281 m_bus_master_base.offset(4).out(m_prdt_page->paddr().get()); 282 283 // Turn on "Interrupt" and "Error" flag. The error flag should be cleared by hardware. 284 m_bus_master_base.offset(2).out<u8>(m_bus_master_base.offset(2).in<u8>() | 0x6); 285 286 // Set transfer direction 287 m_bus_master_base.out<u8>(0x8); 288 289 while (m_io_base.offset(ATA_REG_STATUS).in<u8>() & ATA_SR_BSY) 290 ; 291 292 u8 devsel = 0xe0; 293 if (slave_request) 294 devsel |= 0x10; 295 296 m_control_base.offset(ATA_CTL_CONTROL).out<u8>(0); 297 m_io_base.offset(ATA_REG_HDDEVSEL).out<u8>(devsel | (static_cast<u8>(slave_request) << 4)); 298 io_delay(); 299 300 m_io_base.offset(ATA_REG_FEATURES).out<u8>(0); 301 302 m_io_base.offset(ATA_REG_SECCOUNT0).out<u8>(0); 303 m_io_base.offset(ATA_REG_LBA0).out<u8>(0); 304 m_io_base.offset(ATA_REG_LBA1).out<u8>(0); 305 m_io_base.offset(ATA_REG_LBA2).out<u8>(0); 306 307 m_io_base.offset(ATA_REG_SECCOUNT0).out<u8>(count); 308 m_io_base.offset(ATA_REG_LBA0).out<u8>((lba & 0x000000ff) >> 0); 309 m_io_base.offset(ATA_REG_LBA1).out<u8>((lba & 0x0000ff00) >> 8); 310 m_io_base.offset(ATA_REG_LBA2).out<u8>((lba & 0x00ff0000) >> 16); 311 312 for (;;) { 313 auto status = m_io_base.offset(ATA_REG_STATUS).in<u8>(); 314 if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRDY)) 315 break; 316 } 317 318 m_io_base.offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_READ_DMA_EXT); 319 io_delay(); 320 321 prepare_for_irq(); 322 // Start bus master 323 m_bus_master_base.out<u8>(0x9); 324 325 wait_for_irq(); 326 327 if (m_device_error) 328 return false; 329 330 memcpy(outbuf, m_dma_buffer_page->paddr().offset(0xc0000000).as_ptr(), 512 * count); 331 332 // I read somewhere that this may trigger a cache flush so let's do it. 333 m_bus_master_base.offset(2).out<u8>(m_bus_master_base.offset(2).in<u8>() | 0x6); 334 return true; 335} 336 337bool PATAChannel::ata_write_sectors_with_dma(u32 lba, u16 count, const u8* inbuf, bool slave_request) 338{ 339 LOCKER(s_lock()); 340#ifdef PATA_DEBUG 341 dbg() << "PATAChannel::ata_write_sectors_with_dma (" << lba << " x" << count << ") <- " << inbuf; 342#endif 343 344 prdt().offset = m_dma_buffer_page->paddr(); 345 prdt().size = 512 * count; 346 347 memcpy(m_dma_buffer_page->paddr().offset(0xc0000000).as_ptr(), inbuf, 512 * count); 348 349 ASSERT(prdt().size <= PAGE_SIZE); 350 351 // Stop bus master 352 m_bus_master_base.out<u8>(0); 353 354 // Write the PRDT location 355 m_bus_master_base.offset(4).out<u32>(m_prdt_page->paddr().get()); 356 357 // Turn on "Interrupt" and "Error" flag. The error flag should be cleared by hardware. 358 m_bus_master_base.offset(2).out<u8>(m_bus_master_base.offset(2).in<u8>() | 0x6); 359 360 while (m_io_base.offset(ATA_REG_STATUS).in<u8>() & ATA_SR_BSY) 361 ; 362 363 u8 devsel = 0xe0; 364 if (slave_request) 365 devsel |= 0x10; 366 367 m_control_base.offset(ATA_CTL_CONTROL).out<u8>(0); 368 m_io_base.offset(ATA_REG_HDDEVSEL).out<u8>(devsel | (static_cast<u8>(slave_request) << 4)); 369 io_delay(); 370 371 m_io_base.offset(ATA_REG_FEATURES).out<u8>(0); 372 373 m_io_base.offset(ATA_REG_SECCOUNT0).out<u8>(0); 374 m_io_base.offset(ATA_REG_LBA0).out<u8>(0); 375 m_io_base.offset(ATA_REG_LBA1).out<u8>(0); 376 m_io_base.offset(ATA_REG_LBA2).out<u8>(0); 377 378 m_io_base.offset(ATA_REG_SECCOUNT0).out<u8>(count); 379 m_io_base.offset(ATA_REG_LBA0).out<u8>((lba & 0x000000ff) >> 0); 380 m_io_base.offset(ATA_REG_LBA1).out<u8>((lba & 0x0000ff00) >> 8); 381 m_io_base.offset(ATA_REG_LBA2).out<u8>((lba & 0x00ff0000) >> 16); 382 383 for (;;) { 384 auto status = m_io_base.offset(ATA_REG_STATUS).in<u8>(); 385 if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRDY)) 386 break; 387 } 388 389 m_io_base.offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_WRITE_DMA_EXT); 390 io_delay(); 391 392 prepare_for_irq(); 393 // Start bus master 394 m_bus_master_base.out<u8>(0x1); 395 wait_for_irq(); 396 397 if (m_device_error) 398 return false; 399 400 // I read somewhere that this may trigger a cache flush so let's do it. 401 m_bus_master_base.offset(2).out<u8>(m_bus_master_base.offset(2).in<u8>() | 0x6); 402 return true; 403} 404 405bool PATAChannel::ata_read_sectors(u32 start_sector, u16 count, u8* outbuf, bool slave_request) 406{ 407 ASSERT(count <= 256); 408 LOCKER(s_lock()); 409#ifdef PATA_DEBUG 410 dbg() << "PATAChannel::ata_read_sectors request (" << count << " sector(s) @ " << start_sector << " into " << outbuf << ")"; 411#endif 412 413 while (m_io_base.offset(ATA_REG_STATUS).in<u8>() & ATA_SR_BSY) 414 ; 415 416#ifdef PATA_DEBUG 417 klog() << "PATAChannel: Reading " << count << " sector(s) @ LBA " << start_sector; 418#endif 419 420 u8 devsel = 0xe0; 421 if (slave_request) 422 devsel |= 0x10; 423 424 m_io_base.offset(ATA_REG_SECCOUNT0).out<u8>(count == 256 ? 0 : LSB(count)); 425 m_io_base.offset(ATA_REG_LBA0).out<u8>(start_sector & 0xff); 426 m_io_base.offset(ATA_REG_LBA1).out<u8>((start_sector >> 8) & 0xff); 427 m_io_base.offset(ATA_REG_LBA2).out<u8>((start_sector >> 16) & 0xff); 428 m_io_base.offset(ATA_REG_HDDEVSEL).out<u8>(devsel | ((start_sector >> 24) & 0xf)); 429 430 IO::out8(0x3F6, 0x08); 431 while (!(m_io_base.offset(ATA_REG_STATUS).in<u8>() & ATA_SR_DRDY)) 432 ; 433 434 prepare_for_irq(); 435 m_io_base.offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_READ_PIO); 436 wait_for_irq(); 437 438 if (m_device_error) 439 return false; 440 441 for (int i = 0; i < count; i++) { 442 io_delay(); 443 444 while (m_io_base.offset(ATA_REG_STATUS).in<u8>() & ATA_SR_BSY) 445 ; 446 447 u8 status = m_io_base.offset(ATA_REG_STATUS).in<u8>(); 448 ASSERT(status & ATA_SR_DRQ); 449#ifdef PATA_DEBUG 450 dbg() << "PATAChannel: Retrieving 512 bytes (part " << i << ") (status=" << String::format("%b", status) << "), outbuf=(" << (outbuf + (512 * i)) << ")..."; 451#endif 452 453 IO::repeated_in16(m_io_base.offset(ATA_REG_DATA).get(), outbuf + (512 * i), 256); 454 } 455 456 return true; 457} 458 459bool PATAChannel::ata_write_sectors(u32 start_sector, u16 count, const u8* inbuf, bool slave_request) 460{ 461 ASSERT(count <= 256); 462 LOCKER(s_lock()); 463#ifdef PATA_DEBUG 464 klog() << "PATAChannel::ata_write_sectors request (" << count << " sector(s) @ " << start_sector << ")"; 465#endif 466 467 while (m_io_base.offset(ATA_REG_STATUS).in<u8>() & ATA_SR_BSY) 468 ; 469 470#ifdef PATA_DEBUG 471 klog() << "PATAChannel: Writing " << count << " sector(s) @ LBA " << start_sector; 472#endif 473 474 u8 devsel = 0xe0; 475 if (slave_request) 476 devsel |= 0x10; 477 478 m_io_base.offset(ATA_REG_SECCOUNT0).out<u8>(count == 256 ? 0 : LSB(count)); 479 m_io_base.offset(ATA_REG_LBA0).out<u8>(start_sector & 0xff); 480 m_io_base.offset(ATA_REG_LBA1).out<u8>((start_sector >> 8) & 0xff); 481 m_io_base.offset(ATA_REG_LBA2).out<u8>((start_sector >> 16) & 0xff); 482 m_io_base.offset(ATA_REG_HDDEVSEL).out<u8>(devsel | ((start_sector >> 24) & 0xf)); 483 484 IO::out8(0x3F6, 0x08); 485 while (!(m_io_base.offset(ATA_REG_STATUS).in<u8>() & ATA_SR_DRDY)) 486 ; 487 488 m_io_base.offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_WRITE_PIO); 489 490 for (int i = 0; i < count; i++) { 491 io_delay(); 492 while (m_io_base.offset(ATA_REG_STATUS).in<u8>() & ATA_SR_BSY) 493 ; 494 495 u8 status = m_io_base.offset(ATA_REG_STATUS).in<u8>(); 496 ASSERT(status & ATA_SR_DRQ); 497 498#ifdef PATA_DEBUG 499 dbg() << "PATAChannel: Writing 512 bytes (part " << i << ") (status=" << String::format("%b", status) << "), inbuf=(" << (inbuf + (512 * i)) << ")..."; 500#endif 501 502 IO::repeated_out16(m_io_base.offset(ATA_REG_DATA).get(), inbuf + (512 * i), 256); 503 prepare_for_irq(); 504 wait_for_irq(); 505 status = m_io_base.offset(ATA_REG_STATUS).in<u8>(); 506 ASSERT(!(status & ATA_SR_BSY)); 507 } 508 prepare_for_irq(); 509 m_io_base.offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_CACHE_FLUSH); 510 wait_for_irq(); 511 u8 status = m_io_base.offset(ATA_REG_STATUS).in<u8>(); 512 ASSERT(!(status & ATA_SR_BSY)); 513 514 return !m_device_error; 515} 516 517}