AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
pio.c
Go to the documentation of this file.
1
11
12#include <core/system.h>
13#include <core/panic.h>
14#include <cpu/io.h>
15#include <dev/dev.h>
16#include <fs/vfs.h>
17#include <fs/devfs.h>
18#include <fs/posix.h>
19#include <fs/mbr.h>
20#include <aquila/errno.h>
21#include <dev/pci.h>
22
23#include <ata.h>
24
25#define PIO_MAX_RETRIES 5
26
27/* the most sectors per command: 256 can be given both with LBA28 (as 0)
28 * and LBA48 */
29#define PIO_MAX_SECTORS 256
30
34static ssize_t pio_read_sectors(struct ata_drive *drive, uint64_t lba, size_t count, void *buf)
35{
36 int retry_count = 0;
37
38retry:
39 if (++retry_count == PIO_MAX_RETRIES)
40 return -EIO;
41
42 if (drive->capabilities & ATA_CAP_LBA) {
43 /* the sectors' address and count */
44 ata_setup(drive, lba, count);
45
46 /* the read command */
47 ata_wait(drive);
48
49 if (drive->mode == ATA_MODE_LBA48)
51 else
53
54 ata_wait(drive);
55
56 size_t _count = count;
57 char *_buf = buf;
58
59 while (_count--) {
60 int err;
61 if ((err = ata_poll(drive, 1))) {
62
63 /* the drive aborted the command: try it again, a few
64 * times */
65 if (err == -EAGAIN) {
66 printk("ata: retrying...\n");
67
68 for (int i = 0; i < 5; ++i)
69 ata_wait(drive);
70 goto retry;
71 }
72
73 return -EIO;
74 }
75
76 /* copy a whole sector with one instruction: under KVM that is
77 * one exit to the hypervisor, rather than one per word */
78 __insw(drive->base.addr + ATA_REG_DATA, 256, _buf);
79 _buf += 512;
80 }
81
82 if (ata_poll(drive, 0))
83 return -EIO;
84 } else {
85 /* CHS addressing isn't supported */
86 return -ENOTSUP;
87 }
88
89 return 0;
90}
91
94static ssize_t pio_write_sectors(struct ata_drive *drive, uint64_t lba, size_t count, void *buf)
95{
96 if (!(drive->capabilities & ATA_CAP_LBA))
97 return -ENOTSUP; /* CHS addressing isn't supported */
98
99 ata_setup(drive, lba, count);
100
101 /* the write command */
102 ata_wait(drive);
103
104 if (drive->mode == ATA_MODE_LBA48)
106 else
108
109 while (count--) {
110 uint16_t *_buf = (uint16_t *) buf;
111
112 if (ata_poll(drive, 1)) return -EIO;
113
114 __outsw(drive->base.addr + ATA_REG_DATA, 256, _buf);
115 buf += 512;
116 }
117
118 /* the drive may keep the data in its write cache, until pio_flush() */
119 if (ata_poll(drive, 0)) return -EIO;
120
121 return 0;
122}
123
126static int pio_flush(struct ata_drive *drive)
127{
128 ata_select_drive(drive, drive->mode);
129 ata_wait(drive);
130
131 if (drive->mode == ATA_MODE_LBA48)
133 else
135
136 return ata_poll(drive, 0) ? -EIO : 0;
137}
138
141static ssize_t pio_read(struct ata_drive *drive, uint64_t lba, size_t count, void *buf)
142{
143 while (count) {
144 size_t n = MIN(count, PIO_MAX_SECTORS);
145 ssize_t err;
146
147 if ((err = pio_read_sectors(drive, lba, n, buf)) < 0)
148 return err;
149
150 lba += n;
151 count -= n;
152 buf += n * 512;
153 }
154
155 return 0;
156}
157
160static ssize_t pio_write(struct ata_drive *drive, uint64_t lba, size_t count, void *buf)
161{
162 while (count) {
163 size_t n = MIN(count, PIO_MAX_SECTORS);
164 ssize_t err;
165
166 if ((err = pio_write_sectors(drive, lba, n, buf)) < 0)
167 return err;
168
169 lba += n;
170 count -= n;
171 buf += n * 512;
172 }
173
174 return 0;
175}
176
182void pio_init(struct ata_drive *drive)
183{
184 drive->read = pio_read;
185 drive->write = pio_write;
186 drive->flush = pio_flush;
187 ata_reset(drive);
188}
static void io_out8(struct ioaddr *io, uintptr_t off, uint8_t val)
Writes an 8-, 16- or 32-bit register.
Definition io.h:44
#define __outsw(port, count, buf)
Definition io.h:45
#define __insw(port, count, buf)
Definition io.h:38
void ata_select_drive(struct ata_drive *drive, uint32_t mode)
Selects a drive on its channel, for an addressing mode, if it isn't selected so already,...
Definition ata.c:126
void ata_setup(struct ata_drive *drive, uint64_t lba, size_t count)
Writes the registers of a command on count sectors from lba: the drive, the address and the count.
Definition ata.c:155
void ata_reset(struct ata_drive *drive)
Resets both drives on a drive's channel, and waits until they are done.
Definition ata.c:97
void pio_init(struct ata_drive *drive)
Sets a drive up for PIO, and resets its channel.
Definition pio.c:182
#define ATA_CMD_CACHE_FLUSH
Definition ata.h:53
#define ATA_REG_DATA
Definition ata.h:25
#define ATA_CMD_CACHE_FLUSH_EXT
Definition ata.h:54
#define ATA_CAP_LBA
Definition ata.h:96
#define ATA_CMD_READ_SECTORS
Definition ata.h:45
#define ATA_CMD_WRITE_SECTORS_EXT
Definition ata.h:48
#define ATA_MODE_LBA48
Definition ata.h:101
#define ATA_CMD_READ_SECTORS_EXT
Definition ata.h:46
#define ATA_CMD_WRITE_SECTORS
Definition ata.h:47
#define ATA_REG_CMD
Definition ata.h:33
#define MIN(a, b)
Definition system.h:11
#define PIO_MAX_SECTORS
Definition pio.c:29
static ssize_t pio_read(struct ata_drive *drive, uint64_t lba, size_t count, void *buf)
Reads count sectors from lba on, PIO_MAX_SECTORS per command.
Definition pio.c:141
#define PIO_MAX_RETRIES
Definition pio.c:25
static ssize_t pio_write_sectors(struct ata_drive *drive, uint64_t lba, size_t count, void *buf)
Writes up to PIO_MAX_SECTORS sectors with one command.
Definition pio.c:94
static ssize_t pio_read_sectors(struct ata_drive *drive, uint64_t lba, size_t count, void *buf)
Reads up to PIO_MAX_SECTORS sectors with one command, trying it again a few times if the drive aborts...
Definition pio.c:34
static int pio_flush(struct ata_drive *drive)
Has the drive write what its cache holds to the disk.
Definition pio.c:126
static ssize_t pio_write(struct ata_drive *drive, uint64_t lba, size_t count, void *buf)
Writes count sectors from lba on, PIO_MAX_SECTORS per command.
Definition pio.c:160
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
Definition printk.c:249
unsigned long long int uint64_t
Definition stddef.h:23
unsigned short int uint16_t
Definition stddef.h:21
A drive on a channel.
Definition ata.h:126
struct ioaddr base
Definition ata.h:127
ssize_t(*) read(struct ata_drive *drive, uint64_t lba, size_t count, void *buf)
Definition ata.h:147
int(*) flush(struct ata_drive *drive)
Definition ata.h:149
uint16_t capabilities
Definition ata.h:141
ssize_t(*) write(struct ata_drive *drive, uint64_t lba, size_t count, void *buf)
Definition ata.h:148
uint8_t mode
Definition ata.h:132
uintptr_t addr
Definition io.h:97
long int ssize_t
Definition types.h:12