blob: ab6981e4aeef27c92d38d551b9ec6eb7223790e3 [file] [log] [blame]
swissChili1a3f07f2021-04-05 20:01:55 -07001#include <dri/ata_pio/ata_pio.h>
2
3#include <io.h>
4#include <log.h>
swissChilie5adca52021-06-16 21:00:31 -07005#include <pic.h>
swissChili4749d022021-07-19 12:33:06 -07006#include <sync.h>
swissChili1a3f07f2021-04-05 20:01:55 -07007
swissChilief829f32021-06-13 20:00:54 -07008/* TODO: Rewrite all of this to work with dri_ide in the case of multiple
9 * devices */
10
swissChili2e0febf2021-04-05 21:44:00 -070011static ushort test_buffer[256];
swissChili1a3f07f2021-04-05 20:01:55 -070012
swissChili4749d022021-07-19 12:33:06 -070013static semaphore_t lock;
14
swissChili1a3f07f2021-04-05 20:01:55 -070015void ata_pio_wait_bsy()
16{
17 while (inb(ATA_PORT_CMD) & ATA_BSY)
swissChilief829f32021-06-13 20:00:54 -070018 {
19 }
swissChili1a3f07f2021-04-05 20:01:55 -070020}
21
22void ata_pio_wait_drq()
23{
24 while (!(inb(ATA_PORT_CMD) & ATA_RDY))
swissChilief829f32021-06-13 20:00:54 -070025 {
26 }
swissChili1a3f07f2021-04-05 20:01:55 -070027}
28
swissChili83db6fd2021-04-05 21:32:49 -070029uint ata_pio_get_error()
30{
swissChili2e0febf2021-04-05 21:44:00 -070031 return inb(ATA_ERR);
swissChili83db6fd2021-04-05 21:32:49 -070032}
33
swissChili1a3f07f2021-04-05 20:01:55 -070034static void ata_pio_send_init(uint lba, uchar num_sectors)
35{
swissChilicbd43632021-07-17 16:19:44 -070036 outb(ATA_PORT_DRIVE_SEL, 0xe0 | ((lba >> 24) & 0x0f));
swissChili276b8cf2021-07-16 13:24:42 -070037 outb(0x1f1, 0x0); // waste some time
swissChili1a3f07f2021-04-05 20:01:55 -070038 outb(ATA_PORT_SECTOR_COUNT, num_sectors);
39 outb(ATA_PORT_LBA_LOW, lba & 0xff);
40 outb(ATA_PORT_LBA_MID, (lba >> 8) & 0xff);
41 outb(ATA_PORT_LBA_HIGH, (lba >> 16) & 0xff);
42}
43
swissChili83db6fd2021-04-05 21:32:49 -070044void ata_pio_read_sectors(void *buffer, uint lba, uchar num_sectors)
swissChili1a3f07f2021-04-05 20:01:55 -070045{
swissChili4749d022021-07-19 12:33:06 -070046 sm_wait(lock);
47
swissChili45df3302021-06-30 20:47:51 -070048 ushort *word_buffer = buffer;
swissChili1a3f07f2021-04-05 20:01:55 -070049
swissChili276b8cf2021-07-16 13:24:42 -070050 for (int sector = 0; sector < num_sectors; sector++)
swissChili45df3302021-06-30 20:47:51 -070051 {
swissChili276b8cf2021-07-16 13:24:42 -070052 ata_pio_wait_bsy();
53 ata_pio_send_init(lba, num_sectors);
54 outb(ATA_PORT_CMD, ATA_CMD_READ);
swissChili1a3f07f2021-04-05 20:01:55 -070055
swissChili276b8cf2021-07-16 13:24:42 -070056 ata_pio_wait_bsy();
57
58 if (inb(ATA_PORT_STATUS) & ATA_ERR)
59 {
60 kprintf(ERROR "ATA_ERR on read\n");
61 kpanic("Failed to read");
62 }
swissChili83db6fd2021-04-05 21:32:49 -070063
swissChili276b8cf2021-07-16 13:24:42 -070064 for (int i = 0; i < 256; i++)
65 {
66 word_buffer[i + sector * 256] = inw(ATA_PORT_DATA);
67 }
68
69 ata_pio_wait_bsy();
70 outw(ATA_PORT_CMD, ATA_CMD_FLUSH_CACHE);
71 }
swissChili4749d022021-07-19 12:33:06 -070072
73 sm_signal(lock);
swissChili1a3f07f2021-04-05 20:01:55 -070074}
75
swissChilie5adca52021-06-16 21:00:31 -070076void ata_pio_write_sectors(uint lba, uchar num_sectors, ushort *buffer)
swissChili1a3f07f2021-04-05 20:01:55 -070077{
swissChili4749d022021-07-19 12:33:06 -070078 sm_wait(lock);
79
swissChili276b8cf2021-07-16 13:24:42 -070080 for (int sector = 0; sector < num_sectors; sector++)
swissChilie5adca52021-06-16 21:00:31 -070081 {
swissChili276b8cf2021-07-16 13:24:42 -070082 ata_pio_wait_bsy();
83 ata_pio_send_init(lba, num_sectors);
84 outb(ATA_PORT_CMD, ATA_CMD_WRITE);
swissChili45df3302021-06-30 20:47:51 -070085
swissChili276b8cf2021-07-16 13:24:42 -070086 ata_pio_wait_bsy();
87
88 if (inb(ATA_PORT_STATUS) & ATA_ERR)
89 {
90 kprintf(ERROR "ATA_ERR on write\n");
91 kpanic("Failed to write");
92 }
93
94 for (int i = 0; i < 256; i++)
95 {
96 outw(ATA_PORT_DATA, buffer[i + sector * 256]);
97 }
98
99 ata_pio_wait_bsy();
100 outw(ATA_PORT_CMD, ATA_CMD_FLUSH_CACHE);
101 }
swissChili4749d022021-07-19 12:33:06 -0700102
103 sm_signal(lock);
swissChili1a3f07f2021-04-05 20:01:55 -0700104}
105
swissChili2e0febf2021-04-05 21:44:00 -0700106static void print_buffer()
107{
swissChili276b8cf2021-07-16 13:24:42 -0700108 for (int i = 0; i < 32; i++)
swissChili2e0febf2021-04-05 21:44:00 -0700109 {
110 kprintf("%d ", test_buffer[i]);
swissChili276b8cf2021-07-16 13:24:42 -0700111 if ((i + 1) % 16 == 0)
swissChili2e0febf2021-04-05 21:44:00 -0700112 kprintf("\n");
113 }
114}
115
swissChili1a3f07f2021-04-05 20:01:55 -0700116void test_ata_pio()
117{
swissChili4749d022021-07-19 12:33:06 -0700118 kprintf(DEBUG "Testing ATA PIO\n");
119 ata_pio_read_sectors(test_buffer, 2, 1);
120 print_buffer();
swissChili1a3f07f2021-04-05 20:01:55 -0700121}
swissChilie5adca52021-06-16 21:00:31 -0700122
123void ata_pio_handle_irq(struct registers *regs)
124{
125 // TODO: check that this IRQ came from the hard drive
126
127 // TODO: use a lock and inform the scheduler that the thread waiting for
128 // this can stop sleeping
swissChili276b8cf2021-07-16 13:24:42 -0700129
swissChilie5adca52021-06-16 21:00:31 -0700130 // Acknowledge the IRQ
131 uchar status = inw(ATA_PORT_STATUS);
132
swissChili276b8cf2021-07-16 13:24:42 -0700133 // kprintf(DEBUG "ATA PIO IRQ received %d (0x%x)\n", status, status);
swissChilie5adca52021-06-16 21:00:31 -0700134}
135
136void init_ata_pio()
137{
138 add_interrupt_handler(46, ata_pio_handle_irq);
swissChili4749d022021-07-19 12:33:06 -0700139 lock = sm_new();
swissChilie5adca52021-06-16 21:00:31 -0700140}