Serenity Operating System
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}