1/* @title: ATA */
2#pragma once
3#include <block/block.h>
4#include <compiler/core.h>
5#include <log.h>
6#include <stdbool.h>
7#include <stdint.h>
8#include <sync/event.h>
9#include <sync/spinlock.h>
10#include <types/types.h>
11
12#define IDE_CMD_TIMEOUT_MS 5000 // Read/write sector
13#define IDE_IDENT_TIMEOUT_MS 10000 // Identify or cache flush
14#define IDE_RESET_TIMEOUT_MS 30000 // Controller reset or spin-up
15
16#define ATAPI_CMD_TIMEOUT_MS 8000 // Short packet commands
17#define ATAPI_SPINUP_TIMEOUT_MS 15000 // Spinning up disc or loading tray
18#define ATAPI_EJECT_TIMEOUT_MS 20000 // Eject/load tray or seek disc
19
20#define REG_DATA(base) (base + 0)
21#define REG_ERROR(base) (base + 1)
22#define REG_FEATURES(base) (base + 1)
23#define REG_SECTOR_COUNT(base) (base + 2)
24#define REG_LBA_LOW(base) (base + 3)
25#define REG_LBA_MID(base) (base + 4)
26#define REG_LBA_HIGH(base) (base + 5)
27#define REG_DRIVE_HEAD(base) (base + 6)
28#define REG_STATUS(base) (base + 7)
29#define REG_COMMAND(base) (base + 7)
30#define REG_ALT_STATUS(ctrl) (ctrl + 0)
31#define REG_CONTROL(ctrl) (ctrl + 0)
32
33#define STATUS_BSY 0x80
34#define STATUS_DRDY 0x40
35#define STATUS_DRQ 0x08
36#define STATUS_ERR 0x01
37#define STATUS_DF 0x20
38
39#define COMMAND_READ 0x20
40#define COMMAND_WRITE 0x30
41
42#define ATA_CMD_READ_PIO 0x20
43#define ATA_CMD_READ_PIO_EXT 0x24
44#define ATA_CMD_READ_DMA 0xC8
45#define ATA_CMD_READ_DMA_EXT 0x25
46#define ATA_CMD_WRITE_PIO 0x30
47#define ATA_CMD_WRITE_PIO_EXT 0x34
48#define ATA_CMD_WRITE_DMA 0xCA
49#define ATA_CMD_WRITE_DMA_EXT 0x35
50#define ATA_CMD_CACHE_FLUSH 0xE7
51#define ATA_CMD_CACHE_FLUSH_EXT 0xEA
52#define ATA_CMD_PACKET 0xA0
53#define ATA_CMD_IDENTIFY_PACKET 0xA1
54#define ATA_CMD_IDENTIFY 0xEC
55
56#define ATA_PRIMARY_IO 0x1F0
57#define ATA_PRIMARY_CTRL 0x3F6
58#define ATA_SECONDARY_IO 0x170
59#define ATA_SECONDARY_CTRL 0x376
60
61struct pci_device;
62
63enum ide_type {
64 IDE_TYPE_ATA,
65 IDE_TYPE_ATAPI,
66};
67
68struct ide_request {
69 uint64_t lba;
70 void *buffer;
71 uint64_t size;
72 uint64_t sector_count;
73 uint16_t current_sector;
74
75 bool write;
76 volatile bool done;
77 int status;
78
79 void (*on_complete)(struct ide_request *);
80 void *user_data;
81
82 bool trigger_completion;
83 struct event evt;
84 bool has_waiter;
85 struct ide_request *next;
86 struct spinlock lock;
87};
88
89struct ide_channel {
90 struct ide_request *head;
91 struct ide_request *tail;
92
93 bool busy;
94 struct spinlock lock;
95 struct ata_drive *current_drive;
96};
97
98struct ata_drive {
99 bool actually_exists; // it picks everything up
100 uint32_t sector_size;
101 uint16_t io_base;
102 uint16_t ctrl_base;
103 uint16_t slave;
104 enum ide_type type;
105 void *identify_data;
106
107 char model[41]; // 40 chars + null
108 char serial[21]; // 20 chars + null
109 char firmware[9]; // 8 chars + null
110 uint64_t total_sectors;
111 uint8_t supports_lba48;
112 uint8_t supports_dma;
113 uint8_t udma_mode;
114 uint8_t pio_mode;
115 irq_t irq;
116 struct ide_channel channel;
117};
118
119#define IDE_RETRY_COUNT 3
120
121bool ide_read_sector_wrapper(struct block_device *d, uint64_t lba, uint8_t *buf,
122 uint64_t cnt);
123
124bool ide_write_sector_wrapper(struct block_device *d, uint64_t lba,
125 const uint8_t *buf, uint64_t cnt);
126
127uint8_t ide_detect_drives(void);
128
129bool ata_setup_drive(struct ata_drive *ide, struct pci_device *devices,
130 uint64_t count, int channel, bool is_slave);
131
132struct block_device *ide_create_generic(struct ata_drive *ide);
133
134void ide_identify(struct ata_drive *drive);
135void ide_print_info(struct block_device *d);
136
137/* NOTE: offsets and sizes asserted in kernel/drivers/ata/layout.c */
138struct ata_identify {
139 uint16_t config;
140 uint16_t cylinders;
141 uint16_t reserved1;
142 uint16_t heads;
143 uint16_t vendor1[2];
144 uint16_t sectors_per_track;
145 uint16_t vendor2[3];
146 uint16_t serial_number[10];
147 uint16_t vendor3[2];
148 uint16_t obsolete1;
149 uint16_t firmware_revision[4];
150 uint16_t model_number[20];
151 uint16_t max_rw_multiple;
152 uint16_t reserved2;
153 uint16_t capabilities[2];
154 uint16_t obsolete2[2];
155 uint16_t field_validity;
156 uint16_t current_cylinders;
157 uint16_t current_heads;
158 uint16_t current_sectors;
159 uint16_t current_capacity_lo;
160 uint16_t current_capacity_hi;
161 uint16_t rw_multiple;
162 uint32_t lba28_capacity;
163 uint16_t dma_supported;
164 uint16_t advanced_pio_modes;
165 uint16_t min_dma_cycle_time;
166 uint16_t recommended_dma_cycle_time;
167 uint16_t min_pio_cycle_time;
168 uint16_t min_pio_cycle_time_iordy;
169 uint16_t additional_supported;
170 uint16_t reserved3[5];
171 uint16_t queue_depth;
172 uint16_t sata_capabilities;
173 uint16_t sata_additional;
174 uint16_t sata_features_supported;
175 uint16_t sata_features_enabled;
176 uint16_t major_version;
177 uint16_t minor_version;
178 uint16_t command_set_supported[3];
179 uint16_t command_set_enabled[3];
180 uint16_t features_supported_extension;
181 uint16_t security_erase_time;
182 uint16_t enhanced_security_erase_time;
183 uint16_t current_advanced_power_mgmt;
184 uint16_t master_password_revision;
185 uint16_t hardware_reset_result;
186 uint16_t acoustic_management;
187 uint16_t stream_min_req_size;
188 uint16_t stream_transfer_time_dma;
189 uint16_t stream_access_latency;
190 uint32_t streaming_performance_gran;
191 uint64_t lba48_sector_count;
192 uint16_t streaming_transfer_time;
193 uint16_t dsm_cap;
194 uint16_t phys_log_sector_size;
195 uint16_t inter_seek_delay;
196 uint16_t world_wide_name[4];
197 uint16_t reserved4[144];
198} cc_packed;
199
200LOG_SITE_EXTERN(ide);
201LOG_HANDLE_EXTERN(ide);
202
203#define ide_log(log_level, fmt, ...) \
204 log(LOG_SITE(ide), LOG_HANDLE(ide), log_level, fmt, ##__VA_ARGS__)
205
206void ata_ident_print(struct ata_identify *id);
207void ata_select_drive(struct ata_drive *ata_drive);
208void ata_soft_reset(struct ata_drive *ata_drive);
209bool atapi_identify(struct ata_drive *ide);
210void ata_init(struct pci_device *devices, uint64_t count);
211enum irq_result ide_irq_handler(struct irq_context *ct, void *ctx);
212void ide_reorder(struct block_device *disk);
213bool ide_submit_bio_async(struct block_device *d, struct bio_request *b);
214struct block_device *atapi_create_generic(struct ata_drive *d);
215
216void atapi_print_info(struct block_device *disk);
217