Serenity Operating System
at portability 536 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 "PATADiskDevice.h" 28#include <AK/ByteBuffer.h> 29#include <Kernel/Devices/PATAChannel.h> 30#include <Kernel/Devices/PIT.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 kprintf("PATAChannel: PATA Controller found! id=%w:%w\n", id.vendor_id, 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{ 136 disable_irq(); 137 138 m_dma_enabled.resource() = true; 139 ProcFS::add_sys_bool("ide_dma", m_dma_enabled); 140 141 m_prdt_page = MM.allocate_supervisor_physical_page(); 142 143 initialize(force_pio); 144 detect_disks(); 145} 146 147PATAChannel::~PATAChannel() 148{ 149} 150 151void PATAChannel::initialize(bool force_pio) 152{ 153 154 if (force_pio) { 155 kprintf("PATAChannel: Requested to force PIO mode; not setting up DMA\n"); 156 return; 157 } 158 159 // Let's try to set up DMA transfers. 160 PCI::enable_bus_mastering(pci_address()); 161 prdt().end_of_table = 0x8000; 162 m_bus_master_base = PCI::get_BAR4(pci_address()) & 0xfffc; 163 m_dma_buffer_page = MM.allocate_supervisor_physical_page(); 164 kprintf("PATAChannel: Bus master IDE: I/O @ %x\n", m_bus_master_base); 165} 166 167static void print_ide_status(u8 status) 168{ 169 kprintf("PATAChannel: print_ide_status: DRQ=%u BSY=%u DRDY=%u DSC=%u DF=%u CORR=%u IDX=%u ERR=%u\n", 170 (status & ATA_SR_DRQ) != 0, 171 (status & ATA_SR_BSY) != 0, 172 (status & ATA_SR_DRDY) != 0, 173 (status & ATA_SR_DSC) != 0, 174 (status & ATA_SR_DF) != 0, 175 (status & ATA_SR_CORR) != 0, 176 (status & ATA_SR_IDX) != 0, 177 (status & ATA_SR_ERR) != 0); 178} 179 180void PATAChannel::wait_for_irq() 181{ 182 cli(); 183 enable_irq(); 184 Thread::current->wait_on(m_irq_queue); 185 disable_irq(); 186} 187 188void PATAChannel::handle_irq(RegisterState&) 189{ 190 u8 status = IO::in8(m_io_base + ATA_REG_STATUS); 191 if (status & ATA_SR_ERR) { 192 print_ide_status(status); 193 m_device_error = IO::in8(m_io_base + ATA_REG_ERROR); 194 kprintf("PATAChannel: Error %b!\n", m_device_error); 195 } else { 196 m_device_error = 0; 197 } 198#ifdef PATA_DEBUG 199 kprintf("PATAChannel: interrupt: DRQ=%u BSY=%u DRDY=%u\n", (status & ATA_SR_DRQ) != 0, (status & ATA_SR_BSY) != 0, (status & ATA_SR_DRDY) != 0); 200#endif 201 m_irq_queue.wake_all(); 202} 203 204static void io_delay() 205{ 206 for (int i = 0; i < 4; ++i) 207 IO::in8(0x3f6); 208} 209 210void PATAChannel::detect_disks() 211{ 212 // There are only two possible disks connected to a channel 213 for (auto i = 0; i < 2; i++) { 214 IO::out8(m_io_base + ATA_REG_HDDEVSEL, 0xA0 | (i << 4)); // First, we need to select the drive itself 215 216 // Apparently these need to be 0 before sending IDENTIFY?! 217 IO::out8(m_io_base + ATA_REG_SECCOUNT0, 0x00); 218 IO::out8(m_io_base + ATA_REG_LBA0, 0x00); 219 IO::out8(m_io_base + ATA_REG_LBA1, 0x00); 220 IO::out8(m_io_base + ATA_REG_LBA2, 0x00); 221 222 IO::out8(m_io_base + ATA_REG_COMMAND, ATA_CMD_IDENTIFY); // Send the ATA_IDENTIFY command 223 224 // Wait for the BSY flag to be reset 225 while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) 226 ; 227 228 if (IO::in8(m_io_base + ATA_REG_STATUS) == 0x00) { 229#ifdef PATA_DEBUG 230 kprintf("PATAChannel: No %s disk detected!\n", (i == 0 ? "master" : "slave")); 231#endif 232 continue; 233 } 234 235 ByteBuffer wbuf = ByteBuffer::create_uninitialized(512); 236 ByteBuffer bbuf = ByteBuffer::create_uninitialized(512); 237 u8* b = bbuf.data(); 238 u16* w = (u16*)wbuf.data(); 239 const u16* wbufbase = (u16*)wbuf.data(); 240 241 for (u32 i = 0; i < 256; ++i) { 242 u16 data = IO::in16(m_io_base + ATA_REG_DATA); 243 *(w++) = data; 244 *(b++) = MSB(data); 245 *(b++) = LSB(data); 246 } 247 248 // "Unpad" the device name string. 249 for (u32 i = 93; i > 54 && bbuf[i] == ' '; --i) 250 bbuf[i] = 0; 251 252 u8 cyls = wbufbase[1]; 253 u8 heads = wbufbase[3]; 254 u8 spt = wbufbase[6]; 255 256 kprintf( 257 "PATAChannel: Name=\"%s\", C/H/Spt=%u/%u/%u\n", 258 bbuf.data() + 54, 259 cyls, 260 heads, 261 spt); 262 263 int major = (m_channel_number == 0) ? 3 : 4; 264 if (i == 0) { 265 m_master = PATADiskDevice::create(*this, PATADiskDevice::DriveType::Master, major, 0); 266 m_master->set_drive_geometry(cyls, heads, spt); 267 } else { 268 m_slave = PATADiskDevice::create(*this, PATADiskDevice::DriveType::Slave, major, 1); 269 m_slave->set_drive_geometry(cyls, heads, spt); 270 } 271 } 272} 273 274bool PATAChannel::ata_read_sectors_with_dma(u32 lba, u16 count, u8* outbuf, bool slave_request) 275{ 276 LOCKER(s_lock()); 277#ifdef PATA_DEBUG 278 kprintf("%s(%u): PATAChannel::ata_read_sectors_with_dma (%u x%u) -> %p\n", 279 Process::current->name().characters(), 280 Process::current->pid(), lba, count, outbuf); 281#endif 282 283 prdt().offset = m_dma_buffer_page->paddr(); 284 prdt().size = 512 * count; 285 286 ASSERT(prdt().size <= PAGE_SIZE); 287 288 // Stop bus master 289 IO::out8(m_bus_master_base, 0); 290 291 // Write the PRDT location 292 IO::out32(m_bus_master_base + 4, m_prdt_page->paddr().get()); 293 294 // Turn on "Interrupt" and "Error" flag. The error flag should be cleared by hardware. 295 IO::out8(m_bus_master_base + 2, IO::in8(m_bus_master_base + 2) | 0x6); 296 297 // Set transfer direction 298 IO::out8(m_bus_master_base, 0x8); 299 300 while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) 301 ; 302 303 u8 devsel = 0xe0; 304 if (slave_request) 305 devsel |= 0x10; 306 307 IO::out8(m_control_base + ATA_CTL_CONTROL, 0); 308 IO::out8(m_io_base + ATA_REG_HDDEVSEL, devsel | (static_cast<u8>(slave_request) << 4)); 309 io_delay(); 310 311 IO::out8(m_io_base + ATA_REG_FEATURES, 0); 312 313 IO::out8(m_io_base + ATA_REG_SECCOUNT0, 0); 314 IO::out8(m_io_base + ATA_REG_LBA0, 0); 315 IO::out8(m_io_base + ATA_REG_LBA1, 0); 316 IO::out8(m_io_base + ATA_REG_LBA2, 0); 317 318 IO::out8(m_io_base + ATA_REG_SECCOUNT0, count); 319 IO::out8(m_io_base + ATA_REG_LBA0, (lba & 0x000000ff) >> 0); 320 IO::out8(m_io_base + ATA_REG_LBA1, (lba & 0x0000ff00) >> 8); 321 IO::out8(m_io_base + ATA_REG_LBA2, (lba & 0x00ff0000) >> 16); 322 323 for (;;) { 324 auto status = IO::in8(m_io_base + ATA_REG_STATUS); 325 if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRDY)) 326 break; 327 } 328 329 IO::out8(m_io_base + ATA_REG_COMMAND, ATA_CMD_READ_DMA_EXT); 330 io_delay(); 331 332 // Start bus master 333 IO::out8(m_bus_master_base, 0x9); 334 335 wait_for_irq(); 336 337 if (m_device_error) 338 return false; 339 340 memcpy(outbuf, m_dma_buffer_page->paddr().offset(0xc0000000).as_ptr(), 512 * count); 341 342 // I read somewhere that this may trigger a cache flush so let's do it. 343 IO::out8(m_bus_master_base + 2, IO::in8(m_bus_master_base + 2) | 0x6); 344 return true; 345} 346 347bool PATAChannel::ata_write_sectors_with_dma(u32 lba, u16 count, const u8* inbuf, bool slave_request) 348{ 349 LOCKER(s_lock()); 350#ifdef PATA_DEBUG 351 kprintf("%s(%u): PATAChannel::ata_write_sectors_with_dma (%u x%u) <- %p\n", 352 Process::current->name().characters(), 353 Process::current->pid(), lba, count, inbuf); 354#endif 355 356 prdt().offset = m_dma_buffer_page->paddr(); 357 prdt().size = 512 * count; 358 359 memcpy(m_dma_buffer_page->paddr().offset(0xc0000000).as_ptr(), inbuf, 512 * count); 360 361 ASSERT(prdt().size <= PAGE_SIZE); 362 363 // Stop bus master 364 IO::out8(m_bus_master_base, 0); 365 366 // Write the PRDT location 367 IO::out32(m_bus_master_base + 4, m_prdt_page->paddr().get()); 368 369 // Turn on "Interrupt" and "Error" flag. The error flag should be cleared by hardware. 370 IO::out8(m_bus_master_base + 2, IO::in8(m_bus_master_base + 2) | 0x6); 371 372 while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) 373 ; 374 375 u8 devsel = 0xe0; 376 if (slave_request) 377 devsel |= 0x10; 378 379 IO::out8(m_control_base + ATA_CTL_CONTROL, 0); 380 IO::out8(m_io_base + ATA_REG_HDDEVSEL, devsel | (static_cast<u8>(slave_request) << 4)); 381 io_delay(); 382 383 IO::out8(m_io_base + ATA_REG_FEATURES, 0); 384 385 IO::out8(m_io_base + ATA_REG_SECCOUNT0, 0); 386 IO::out8(m_io_base + ATA_REG_LBA0, 0); 387 IO::out8(m_io_base + ATA_REG_LBA1, 0); 388 IO::out8(m_io_base + ATA_REG_LBA2, 0); 389 390 IO::out8(m_io_base + ATA_REG_SECCOUNT0, count); 391 IO::out8(m_io_base + ATA_REG_LBA0, (lba & 0x000000ff) >> 0); 392 IO::out8(m_io_base + ATA_REG_LBA1, (lba & 0x0000ff00) >> 8); 393 IO::out8(m_io_base + ATA_REG_LBA2, (lba & 0x00ff0000) >> 16); 394 395 for (;;) { 396 auto status = IO::in8(m_io_base + ATA_REG_STATUS); 397 if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRDY)) 398 break; 399 } 400 401 IO::out8(m_io_base + ATA_REG_COMMAND, ATA_CMD_WRITE_DMA_EXT); 402 io_delay(); 403 404 // Start bus master 405 IO::out8(m_bus_master_base, 0x1); 406 407 wait_for_irq(); 408 409 if (m_device_error) 410 return false; 411 412 // I read somewhere that this may trigger a cache flush so let's do it. 413 IO::out8(m_bus_master_base + 2, IO::in8(m_bus_master_base + 2) | 0x6); 414 return true; 415} 416 417bool PATAChannel::ata_read_sectors(u32 start_sector, u16 count, u8* outbuf, bool slave_request) 418{ 419 ASSERT(count <= 256); 420 LOCKER(s_lock()); 421#ifdef PATA_DEBUG 422 kprintf("%s(%u): PATAChannel::ata_read_sectors request (%u sector(s) @ %u into %p)\n", 423 Process::current->name().characters(), 424 Process::current->pid(), 425 count, 426 start_sector, 427 outbuf); 428#endif 429 430 while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) 431 ; 432 433#ifdef PATA_DEBUG 434 kprintf("PATAChannel: Reading %u sector(s) @ LBA %u\n", count, start_sector); 435#endif 436 437 u8 devsel = 0xe0; 438 if (slave_request) 439 devsel |= 0x10; 440 441 IO::out8(m_io_base + ATA_REG_SECCOUNT0, count == 256 ? 0 : LSB(count)); 442 IO::out8(m_io_base + ATA_REG_LBA0, start_sector & 0xff); 443 IO::out8(m_io_base + ATA_REG_LBA1, (start_sector >> 8) & 0xff); 444 IO::out8(m_io_base + ATA_REG_LBA2, (start_sector >> 16) & 0xff); 445 IO::out8(m_io_base + ATA_REG_HDDEVSEL, devsel | ((start_sector >> 24) & 0xf)); 446 447 IO::out8(0x3F6, 0x08); 448 while (!(IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_DRDY)) 449 ; 450 451 IO::out8(m_io_base + ATA_REG_COMMAND, ATA_CMD_READ_PIO); 452 wait_for_irq(); 453 454 if (m_device_error) 455 return false; 456 457 for (int i = 0; i < count; i++) { 458 io_delay(); 459 460 while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) 461 ; 462 463 u8 status = IO::in8(m_io_base + ATA_REG_STATUS); 464 ASSERT(status & ATA_SR_DRQ); 465#ifdef PATA_DEBUG 466 kprintf("PATAChannel: Retrieving 512 bytes (part %d) (status=%b), outbuf=%p...\n", i, status, outbuf + (512 * i)); 467#endif 468 469 IO::repeated_in16(m_io_base + ATA_REG_DATA, outbuf + (512 * i), 256); 470 } 471 472 return true; 473} 474 475bool PATAChannel::ata_write_sectors(u32 start_sector, u16 count, const u8* inbuf, bool slave_request) 476{ 477 ASSERT(count <= 256); 478 LOCKER(s_lock()); 479#ifdef PATA_DEBUG 480 kprintf("%s(%u): PATAChannel::ata_write_sectors request (%u sector(s) @ %u)\n", 481 Process::current->name().characters(), 482 Process::current->pid(), 483 count, 484 start_sector); 485#endif 486 487 while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) 488 ; 489 490#ifdef PATA_DEBUG 491 kprintf("PATAChannel: Writing %u sector(s) @ LBA %u\n", count, start_sector); 492#endif 493 494 u8 devsel = 0xe0; 495 if (slave_request) 496 devsel |= 0x10; 497 498 IO::out8(m_io_base + ATA_REG_SECCOUNT0, count == 256 ? 0 : LSB(count)); 499 IO::out8(m_io_base + ATA_REG_LBA0, start_sector & 0xff); 500 IO::out8(m_io_base + ATA_REG_LBA1, (start_sector >> 8) & 0xff); 501 IO::out8(m_io_base + ATA_REG_LBA2, (start_sector >> 16) & 0xff); 502 IO::out8(m_io_base + ATA_REG_HDDEVSEL, devsel | ((start_sector >> 24) & 0xf)); 503 504 IO::out8(0x3F6, 0x08); 505 while (!(IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_DRDY)) 506 ; 507 508 IO::out8(m_io_base + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); 509 510 for (int i = 0; i < count; i++) { 511 io_delay(); 512 while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) 513 ; 514 515 u8 status = IO::in8(m_io_base + ATA_REG_STATUS); 516 ASSERT(status & ATA_SR_DRQ); 517 518#ifdef PATA_DEBUG 519 kprintf("PATAChannel: Writing 512 bytes (part %d) (status=%b), inbuf=%p...\n", i, status, inbuf + (512 * i)); 520#endif 521 522 IO::repeated_out16(m_io_base + ATA_REG_DATA, inbuf + (512 * i), 256); 523 wait_for_irq(); 524 status = IO::in8(m_io_base + ATA_REG_STATUS); 525 ASSERT(!(status & ATA_SR_BSY)); 526 } 527 528 IO::out8(m_io_base + ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH); 529 wait_for_irq(); 530 u8 status = IO::in8(m_io_base + ATA_REG_STATUS); 531 ASSERT(!(status & ATA_SR_BSY)); 532 533 return !m_device_error; 534} 535 536}