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 "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}