blob: 17041a82eb3fed062a26f7822b06b2e2ac60cfbe [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>
swissChili1a3f07f2021-04-05 20:01:55 -07006
swissChilief829f32021-06-13 20:00:54 -07007/* TODO: Rewrite all of this to work with dri_ide in the case of multiple
8 * devices */
9
swissChili2e0febf2021-04-05 21:44:00 -070010static ushort test_buffer[256];
swissChili1a3f07f2021-04-05 20:01:55 -070011
12void ata_pio_wait_bsy()
13{
14 while (inb(ATA_PORT_CMD) & ATA_BSY)
swissChilief829f32021-06-13 20:00:54 -070015 {
16 }
swissChili1a3f07f2021-04-05 20:01:55 -070017}
18
19void ata_pio_wait_drq()
20{
21 while (!(inb(ATA_PORT_CMD) & ATA_RDY))
swissChilief829f32021-06-13 20:00:54 -070022 {
23 }
swissChili1a3f07f2021-04-05 20:01:55 -070024}
25
swissChili83db6fd2021-04-05 21:32:49 -070026uint ata_pio_get_error()
27{
swissChili2e0febf2021-04-05 21:44:00 -070028 return inb(ATA_ERR);
swissChili83db6fd2021-04-05 21:32:49 -070029}
30
swissChili1a3f07f2021-04-05 20:01:55 -070031static void ata_pio_send_init(uint lba, uchar num_sectors)
32{
swissChili276b8cf2021-07-16 13:24:42 -070033 outb(ATA_PORT_DRIVE_SEL, 0xe0 | (lba >> 24) & 0x0f);
34 outb(0x1f1, 0x0); // waste some time
swissChili1a3f07f2021-04-05 20:01:55 -070035 outb(ATA_PORT_SECTOR_COUNT, num_sectors);
36 outb(ATA_PORT_LBA_LOW, lba & 0xff);
37 outb(ATA_PORT_LBA_MID, (lba >> 8) & 0xff);
38 outb(ATA_PORT_LBA_HIGH, (lba >> 16) & 0xff);
39}
40
swissChili83db6fd2021-04-05 21:32:49 -070041void ata_pio_read_sectors(void *buffer, uint lba, uchar num_sectors)
swissChili1a3f07f2021-04-05 20:01:55 -070042{
swissChili45df3302021-06-30 20:47:51 -070043 ushort *word_buffer = buffer;
swissChili1a3f07f2021-04-05 20:01:55 -070044
swissChili276b8cf2021-07-16 13:24:42 -070045 for (int sector = 0; sector < num_sectors; sector++)
swissChili45df3302021-06-30 20:47:51 -070046 {
swissChili276b8cf2021-07-16 13:24:42 -070047 ata_pio_wait_bsy();
48 ata_pio_send_init(lba, num_sectors);
49 outb(ATA_PORT_CMD, ATA_CMD_READ);
swissChili1a3f07f2021-04-05 20:01:55 -070050
swissChili276b8cf2021-07-16 13:24:42 -070051 ata_pio_wait_bsy();
52
53 if (inb(ATA_PORT_STATUS) & ATA_ERR)
54 {
55 kprintf(ERROR "ATA_ERR on read\n");
56 kpanic("Failed to read");
57 }
swissChili83db6fd2021-04-05 21:32:49 -070058
swissChili276b8cf2021-07-16 13:24:42 -070059 for (int i = 0; i < 256; i++)
60 {
61 word_buffer[i + sector * 256] = inw(ATA_PORT_DATA);
62 }
63
64 ata_pio_wait_bsy();
65 outw(ATA_PORT_CMD, ATA_CMD_FLUSH_CACHE);
66 }
swissChili1a3f07f2021-04-05 20:01:55 -070067}
68
swissChilie5adca52021-06-16 21:00:31 -070069void ata_pio_write_sectors(uint lba, uchar num_sectors, ushort *buffer)
swissChili1a3f07f2021-04-05 20:01:55 -070070{
swissChili276b8cf2021-07-16 13:24:42 -070071 for (int sector = 0; sector < num_sectors; sector++)
swissChilie5adca52021-06-16 21:00:31 -070072 {
swissChili276b8cf2021-07-16 13:24:42 -070073 ata_pio_wait_bsy();
74 ata_pio_send_init(lba, num_sectors);
75 outb(ATA_PORT_CMD, ATA_CMD_WRITE);
swissChili45df3302021-06-30 20:47:51 -070076
swissChili276b8cf2021-07-16 13:24:42 -070077 ata_pio_wait_bsy();
78
79 if (inb(ATA_PORT_STATUS) & ATA_ERR)
80 {
81 kprintf(ERROR "ATA_ERR on write\n");
82 kpanic("Failed to write");
83 }
84
85 for (int i = 0; i < 256; i++)
86 {
87 outw(ATA_PORT_DATA, buffer[i + sector * 256]);
88 }
89
90 ata_pio_wait_bsy();
91 outw(ATA_PORT_CMD, ATA_CMD_FLUSH_CACHE);
92 }
swissChili1a3f07f2021-04-05 20:01:55 -070093}
94
swissChili2e0febf2021-04-05 21:44:00 -070095static void print_buffer()
96{
swissChili276b8cf2021-07-16 13:24:42 -070097 for (int i = 0; i < 32; i++)
swissChili2e0febf2021-04-05 21:44:00 -070098 {
99 kprintf("%d ", test_buffer[i]);
swissChili276b8cf2021-07-16 13:24:42 -0700100 if ((i + 1) % 16 == 0)
swissChili2e0febf2021-04-05 21:44:00 -0700101 kprintf("\n");
102 }
103}
104
swissChili1a3f07f2021-04-05 20:01:55 -0700105void test_ata_pio()
106{
swissChili276b8cf2021-07-16 13:24:42 -0700107// for (int i = 0; i < 2; i++)
108 {
109 kprintf(DEBUG "Writing 0s and reading back\n");
swissChili1a3f07f2021-04-05 20:01:55 -0700110
swissChili276b8cf2021-07-16 13:24:42 -0700111 // for (int i = 0; i < 256; i++)
112 // test_buffer[i] = 0;
113 // ata_pio_write_sectors(0, 1, test_buffer);
swissChili2e0febf2021-04-05 21:44:00 -0700114
swissChili276b8cf2021-07-16 13:24:42 -0700115 ata_pio_read_sectors(test_buffer, 2, 1);
116 print_buffer();
117 kprintf(DEBUG "again...\n");
118 ata_pio_read_sectors(test_buffer, 2, 1);
119 print_buffer();
swissChili2e0febf2021-04-05 21:44:00 -0700120
swissChili276b8cf2021-07-16 13:24:42 -0700121 for (int i = 0; i < 256; i++)
122 test_buffer[i] = i;
swissChili2e0febf2021-04-05 21:44:00 -0700123
swissChili276b8cf2021-07-16 13:24:42 -0700124 kprintf(DEBUG "Writing 0..256 and reading back\n");
125
126 ata_pio_write_sectors(0, 1, test_buffer);
127
128 ata_pio_read_sectors(test_buffer, 2, 1);
129 print_buffer();
130 kprintf(DEBUG "again...\n");
131 ata_pio_read_sectors(test_buffer, 2, 1);
132 print_buffer();
133 }
swissChili1a3f07f2021-04-05 20:01:55 -0700134}
swissChilie5adca52021-06-16 21:00:31 -0700135
136void ata_pio_handle_irq(struct registers *regs)
137{
138 // TODO: check that this IRQ came from the hard drive
139
140 // TODO: use a lock and inform the scheduler that the thread waiting for
141 // this can stop sleeping
swissChili276b8cf2021-07-16 13:24:42 -0700142
swissChilie5adca52021-06-16 21:00:31 -0700143 // Acknowledge the IRQ
144 uchar status = inw(ATA_PORT_STATUS);
145
swissChili276b8cf2021-07-16 13:24:42 -0700146 // kprintf(DEBUG "ATA PIO IRQ received %d (0x%x)\n", status, status);
swissChilie5adca52021-06-16 21:00:31 -0700147}
148
149void init_ata_pio()
150{
151 add_interrupt_handler(46, ata_pio_handle_irq);
152
153/*
154 // TODO: Consider adding this back.
155
156 // 0xA0 for master, 0xB0 for slave
157 outb(ATA_PORT_DRIVE_SEL, 0xA0);
158
159 outb(ATA_PORT_LBA_LOW, 0);
160 outb(ATA_PORT_LBA_MID, 0);
161 outb(ATA_PORT_LBA_HIGH, 0);
162
163 outb(ATA_PORT_CMD, ATA_CMD_IDENTIFY);
164
165 if (inb(ATA_PORT_STATUS))
166 {
167 kprintf(OKAY "ATA drive exists\n");
168
169 // Wait until either DRQ or ERR is set
170 uchar status;
171 while ((status = inb(ATA_PORT_STATUS)) & (ATA_DRQ | ATA_ERR))
172 {
173 if (status & ATA_ERR)
174 {
175
176 }
177 }
178 }
179 else
180 {
181 kprintf(ERROR "ATA drive does not exist\n");
182 }
183*/
184}