blob: cd426ef6932577f55ad801ca78e587040dbfc183 [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{
42 ata_pio_wait_bsy();
43
44 ata_pio_send_init(lba, num_sectors);
45 outb(ATA_PORT_CMD, ATA_CMD_READ);
46
swissChili83db6fd2021-04-05 21:32:49 -070047 ata_pio_wait_bsy();
swissChili1a3f07f2021-04-05 20:01:55 -070048
swissChilief829f32021-06-13 20:00:54 -070049 asm volatile("rep insw" ::"c"(num_sectors * 256), "d"(ATA_PORT_DATA),
swissChili83db6fd2021-04-05 21:32:49 -070050 "D"(buffer));
51
52 ata_pio_wait_bsy();
swissChili1a3f07f2021-04-05 20:01:55 -070053}
54
swissChilie5adca52021-06-16 21:00:31 -070055void ata_pio_write_sectors(uint lba, uchar num_sectors, ushort *buffer)
swissChili1a3f07f2021-04-05 20:01:55 -070056{
57 ata_pio_wait_bsy();
58
59 ata_pio_send_init(lba, num_sectors);
60 outb(ATA_PORT_CMD, ATA_CMD_WRITE);
61
swissChili83db6fd2021-04-05 21:32:49 -070062 ata_pio_wait_bsy();
swissChili1a3f07f2021-04-05 20:01:55 -070063
swissChilie5adca52021-06-16 21:00:31 -070064 for (int i = 0; i < (num_sectors * 256); i++)
65 {
66 outw(ATA_PORT_DATA, buffer[i]);
67 }
swissChili1a3f07f2021-04-05 20:01:55 -070068}
69
swissChili2e0febf2021-04-05 21:44:00 -070070static void print_buffer()
71{
72 for (int i = 0; i < 256; i++)
73 {
74 kprintf("%d ", test_buffer[i]);
75 if (i % 16 == 0)
76 kprintf("\n");
77 }
78}
79
swissChili1a3f07f2021-04-05 20:01:55 -070080void test_ata_pio()
81{
swissChili9bd74de2021-06-15 20:30:48 -070082 kprintf(INFO "Going to ata_pio_read_sectors\n");
swissChili1a3f07f2021-04-05 20:01:55 -070083
swissChili2e0febf2021-04-05 21:44:00 -070084 ata_pio_read_sectors(test_buffer, 0, 1);
85 print_buffer();
86
87 for (int i = 0; i < 256; i++)
88 test_buffer[i] = i;
89
swissChilief829f32021-06-13 20:00:54 -070090 // ata_pio_write_sectors(0, 1, test_buffer);
swissChili2e0febf2021-04-05 21:44:00 -070091
swissChilief829f32021-06-13 20:00:54 -070092 // ata_pio_read_sectors(test_buffer, 0, 1);
93 // print_buffer();
swissChili1a3f07f2021-04-05 20:01:55 -070094}
swissChilie5adca52021-06-16 21:00:31 -070095
96void ata_pio_handle_irq(struct registers *regs)
97{
98 // TODO: check that this IRQ came from the hard drive
99
100 // TODO: use a lock and inform the scheduler that the thread waiting for
101 // this can stop sleeping
102
103 // Acknowledge the IRQ
104 uchar status = inw(ATA_PORT_STATUS);
105
106 kprintf(DEBUG "ATA PIO IRQ received %d (0x%x)\n", status, status);
107}
108
109void init_ata_pio()
110{
111 add_interrupt_handler(46, ata_pio_handle_irq);
112
113/*
114 // TODO: Consider adding this back.
115
116 // 0xA0 for master, 0xB0 for slave
117 outb(ATA_PORT_DRIVE_SEL, 0xA0);
118
119 outb(ATA_PORT_LBA_LOW, 0);
120 outb(ATA_PORT_LBA_MID, 0);
121 outb(ATA_PORT_LBA_HIGH, 0);
122
123 outb(ATA_PORT_CMD, ATA_CMD_IDENTIFY);
124
125 if (inb(ATA_PORT_STATUS))
126 {
127 kprintf(OKAY "ATA drive exists\n");
128
129 // Wait until either DRQ or ERR is set
130 uchar status;
131 while ((status = inb(ATA_PORT_STATUS)) & (ATA_DRQ | ATA_ERR))
132 {
133 if (status & ATA_ERR)
134 {
135
136 }
137 }
138 }
139 else
140 {
141 kprintf(ERROR "ATA drive does not exist\n");
142 }
143*/
144}