blob: 54db4871e512ff981f4d10246a1451fd746be675 [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{
33 outb(ATA_PORT_DRIVE_SEL, 0xe0 | (lba >> 24));
34 outb(ATA_PORT_SECTOR_COUNT, num_sectors);
35 outb(ATA_PORT_LBA_LOW, lba & 0xff);
36 outb(ATA_PORT_LBA_MID, (lba >> 8) & 0xff);
37 outb(ATA_PORT_LBA_HIGH, (lba >> 16) & 0xff);
38}
39
swissChili83db6fd2021-04-05 21:32:49 -070040void ata_pio_read_sectors(void *buffer, uint lba, uchar num_sectors)
swissChili1a3f07f2021-04-05 20:01:55 -070041{
swissChili45df3302021-06-30 20:47:51 -070042 ushort *word_buffer = buffer;
swissChili1a3f07f2021-04-05 20:01:55 -070043
swissChili45df3302021-06-30 20:47:51 -070044 ata_pio_wait_bsy();
swissChili1a3f07f2021-04-05 20:01:55 -070045 ata_pio_send_init(lba, num_sectors);
46 outb(ATA_PORT_CMD, ATA_CMD_READ);
47
swissChili83db6fd2021-04-05 21:32:49 -070048 ata_pio_wait_bsy();
swissChili45df3302021-06-30 20:47:51 -070049
50 if (inb(ATA_PORT_CMD) & ATA_ERR)
51 {
52 kprintf(ERROR "ATA_ERR on read\n");
53 kpanic("Failed to read");
54 }
swissChili1a3f07f2021-04-05 20:01:55 -070055
swissChili45df3302021-06-30 20:47:51 -070056 for (int i = 0; i < num_sectors * 256; i++)
57 {
58 word_buffer[i] = inw(ATA_PORT_DATA);
59 }
swissChili83db6fd2021-04-05 21:32:49 -070060
61 ata_pio_wait_bsy();
swissChili45df3302021-06-30 20:47:51 -070062 outw(ATA_PORT_CMD, ATA_CMD_FLUSH_CACHE);
swissChili1a3f07f2021-04-05 20:01:55 -070063}
64
swissChilie5adca52021-06-16 21:00:31 -070065void ata_pio_write_sectors(uint lba, uchar num_sectors, ushort *buffer)
swissChili1a3f07f2021-04-05 20:01:55 -070066{
67 ata_pio_wait_bsy();
68
69 ata_pio_send_init(lba, num_sectors);
70 outb(ATA_PORT_CMD, ATA_CMD_WRITE);
71
swissChili83db6fd2021-04-05 21:32:49 -070072 ata_pio_wait_bsy();
swissChili1a3f07f2021-04-05 20:01:55 -070073
swissChilie5adca52021-06-16 21:00:31 -070074 for (int i = 0; i < (num_sectors * 256); i++)
75 {
76 outw(ATA_PORT_DATA, buffer[i]);
77 }
swissChili45df3302021-06-30 20:47:51 -070078
79 ata_pio_wait_bsy();
80 outw(ATA_PORT_CMD, ATA_CMD_FLUSH_CACHE);
swissChili1a3f07f2021-04-05 20:01:55 -070081}
82
swissChili2e0febf2021-04-05 21:44:00 -070083static void print_buffer()
84{
85 for (int i = 0; i < 256; i++)
86 {
87 kprintf("%d ", test_buffer[i]);
88 if (i % 16 == 0)
89 kprintf("\n");
90 }
91}
92
swissChili1a3f07f2021-04-05 20:01:55 -070093void test_ata_pio()
94{
swissChili9bd74de2021-06-15 20:30:48 -070095 kprintf(INFO "Going to ata_pio_read_sectors\n");
swissChili1a3f07f2021-04-05 20:01:55 -070096
swissChili2e0febf2021-04-05 21:44:00 -070097 ata_pio_read_sectors(test_buffer, 0, 1);
98 print_buffer();
99
100 for (int i = 0; i < 256; i++)
101 test_buffer[i] = i;
102
swissChilief829f32021-06-13 20:00:54 -0700103 // ata_pio_write_sectors(0, 1, test_buffer);
swissChili2e0febf2021-04-05 21:44:00 -0700104
swissChilief829f32021-06-13 20:00:54 -0700105 // ata_pio_read_sectors(test_buffer, 0, 1);
106 // print_buffer();
swissChili1a3f07f2021-04-05 20:01:55 -0700107}
swissChilie5adca52021-06-16 21:00:31 -0700108
109void ata_pio_handle_irq(struct registers *regs)
110{
111 // TODO: check that this IRQ came from the hard drive
112
113 // TODO: use a lock and inform the scheduler that the thread waiting for
114 // this can stop sleeping
115
116 // Acknowledge the IRQ
117 uchar status = inw(ATA_PORT_STATUS);
118
119 kprintf(DEBUG "ATA PIO IRQ received %d (0x%x)\n", status, status);
120}
121
122void init_ata_pio()
123{
124 add_interrupt_handler(46, ata_pio_handle_irq);
125
126/*
127 // TODO: Consider adding this back.
128
129 // 0xA0 for master, 0xB0 for slave
130 outb(ATA_PORT_DRIVE_SEL, 0xA0);
131
132 outb(ATA_PORT_LBA_LOW, 0);
133 outb(ATA_PORT_LBA_MID, 0);
134 outb(ATA_PORT_LBA_HIGH, 0);
135
136 outb(ATA_PORT_CMD, ATA_CMD_IDENTIFY);
137
138 if (inb(ATA_PORT_STATUS))
139 {
140 kprintf(OKAY "ATA drive exists\n");
141
142 // Wait until either DRQ or ERR is set
143 uchar status;
144 while ((status = inb(ATA_PORT_STATUS)) & (ATA_DRQ | ATA_ERR))
145 {
146 if (status & ATA_ERR)
147 {
148
149 }
150 }
151 }
152 else
153 {
154 kprintf(ERROR "ATA drive does not exist\n");
155 }
156*/
157}