RTEMS 5.2
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
ata.h
1/*
2 * Copyright (c) 2010-2013 embedded brains GmbH. All rights reserved.
3 *
4 * embedded brains GmbH
5 * Dornierstr. 4
6 * 82178 Puchheim
7 * Germany
8 * <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#ifndef GEN5200_ATA_H
16#define GEN5200_ATA_H
17
18#include "bestcomm.h"
19
20#include <assert.h>
21
22#include <rtems.h>
23#include <rtems/diskdevs.h>
24#include <rtems/bdbuf.h>
25
26#include <libchip/ata_internal.h>
27#include <libchip/ide_ctrl_io.h>
28#include <libchip/ide_ctrl_cfg.h>
29
31
32#ifdef __cplusplus
33extern "C" {
34#endif /* __cplusplus */
35
36#define DCTRL_SRST BSP_BBIT8(5)
37#define DCTRL_NIEN BSP_BBIT8(6)
38
39#define DAST_BSY BSP_BBIT8(0)
40#define DAST_DRDY BSP_BBIT8(1)
41#define DAST_DRQ BSP_BBIT8(4)
42#define DAST_ERR BSP_BBIT8(7)
43
44#define DST_BSY BSP_BBIT16(0)
45#define DST_DRDY BSP_BBIT16(1)
46#define DST_DRQ BSP_BBIT16(4)
47#define DST_ERR BSP_BBIT16(7)
48
49#define DDMA_HUT BSP_BBIT8(1)
50#define DDMA_FR BSP_BBIT8(2)
51#define DDMA_FE BSP_BBIT8(3)
52#define DDMA_IE BSP_BBIT8(4)
53#define DDMA_UDMA BSP_BBIT8(5)
54#define DDMA_READ BSP_BBIT8(6)
55#define DDMA_WRITE BSP_BBIT8(7)
56
57#define ATA_SECTOR_SHIFT 9
58
59#define ATA_PER_TRANSFER_SECTOR_COUNT_MAX 256
60
61typedef union {
62 struct {
63 uint8_t alternate_status;
64 uint8_t reserved_0[3];
65 uint16_t data;
66 uint8_t reserved_1[2];
67 uint8_t error;
68 uint8_t reserved_2[3];
69 uint8_t sector_count;
70 uint8_t reserved_3[3];
71 uint8_t sector;
72 uint8_t reserved_4[3];
73 uint8_t cylinder_low;
74 uint8_t reserved_5[3];
75 uint8_t cylinder_high;
76 uint8_t reserved_6[3];
77 uint8_t head;
78 uint8_t reserved_7[3];
79 uint16_t status;
80 uint8_t reserved_8[2];
81 } read;
82
83 struct {
84 uint8_t control;
85 uint8_t reserved_0[3];
86 uint16_t data;
87 uint8_t reserved_1[2];
88 uint8_t feature;
89 uint8_t reserved_2[3];
90 uint8_t sector_count;
91 uint8_t reserved_3[3];
92 uint8_t sector;
93 uint8_t reserved_4[3];
94 uint8_t cylinder_low;
95 uint8_t reserved_5[3];
96 uint8_t cylinder_high;
97 uint8_t reserved_6[3];
98 uint8_t head;
99 uint8_t reserved_7[3];
100 uint8_t command;
101 uint8_t dma_control;
102 uint8_t reserved_8[2];
103 } write;
105
106#define ATA ((volatile ata_drive_registers *) 0xf0003a5c)
107
108static inline bool ata_is_data_request(void)
109{
110 return (ATA->read.alternate_status & DAST_DRQ) != 0;
111}
112
113static inline bool ata_is_drive_ready_for_selection(void)
114{
115 return (ATA->read.alternate_status & (DAST_BSY | DAST_DRQ)) == 0;
116}
117
118static inline void ata_wait_400_nano_seconds(void)
119{
120 ATA->read.alternate_status;
121}
122
123static inline void ata_wait_for_drive_ready(void)
124{
125 while ((ATA->read.alternate_status & (DAST_BSY | DAST_DRQ | DAST_DRDY)) != DAST_DRDY) {
126 /* Wait */
127 }
128}
129
130static inline void ata_wait_for_not_busy(void)
131{
132 ata_wait_400_nano_seconds();
133
134 while ((ATA->read.alternate_status & DAST_BSY) != 0) {
135 /* Wait */
136 }
137}
138
139static inline bool ata_wait_for_data_request(void)
140{
141 ata_wait_400_nano_seconds();
142
143 uint8_t alternate_status;
144 do {
145 alternate_status = ATA->read.alternate_status;
146 } while ((alternate_status & DAST_BSY) == DAST_BSY);
147
148 return (alternate_status & (DAST_ERR | DAST_DRQ)) == DAST_DRQ;
149}
150
151static inline bool ata_check_status(void)
152{
153 return (ATA->read.status & (DST_BSY | DST_ERR)) == 0;
154}
155
156static inline void ata_clear_interrupts(void)
157{
158 ATA->read.status;
159}
160
161static inline uint8_t ata_read_or_write_sectors_command(bool read)
162{
163 return read ? 0x20 : 0x30;
164}
165
166static inline rtems_blkdev_bnum ata_max_transfer_count(rtems_blkdev_bnum sector_count)
167{
168 return sector_count > ATA_PER_TRANSFER_SECTOR_COUNT_MAX ?
169 ATA_PER_TRANSFER_SECTOR_COUNT_MAX
170 : sector_count;
171}
172
173static inline void ata_flush_sector(uint16_t *begin)
174{
175 /* XXX: The dcbi operation does not work properly */
176 rtems_cache_flush_multiple_data_lines(begin, ATA_SECTOR_SIZE);
177}
178
179void ata_reset_device(void);
180
181bool ata_set_transfer_mode(uint8_t mode);
182
183bool ata_execute_io_command(uint8_t command, uint32_t lba, uint32_t sector_count);
184
185static inline bool ata_execute_io_command_with_sg(uint8_t command, const rtems_blkdev_sg_buffer *sg)
186{
187 uint32_t lba = sg->block;
188 uint32_t sector_count = sg->length / ATA_SECTOR_SIZE;
189 return ata_execute_io_command(command, lba, sector_count);
190}
191
192typedef struct {
193 const rtems_blkdev_sg_buffer *sg;
194
195 size_t sg_count;
196
197 rtems_blkdev_bnum sg_buffer_offset_mask;
198
199 int sg_index_shift;
201
202static inline void ata_sg_reset(ata_sg_context *self, const rtems_blkdev_sg_buffer *sg, size_t sg_count)
203{
204 self->sg = sg;
205 self->sg_count = sg_count;
206 uint32_t sectors_per_buffer = self->sg[0].length >> ATA_SECTOR_SHIFT;
207 self->sg_buffer_offset_mask = sectors_per_buffer - 1;
208 self->sg_index_shift = __builtin_ffs((int) sectors_per_buffer) - 1;
209}
210
211static inline void ata_sg_create_default(ata_sg_context *self)
212{
213 ata_sg_reset(self, NULL, 0);
214}
215
216static inline void ata_sg_create(ata_sg_context *self, const rtems_blkdev_sg_buffer *sg, size_t sg_count)
217{
218 ata_sg_reset(self, sg, sg_count);
219}
220
221static inline rtems_blkdev_bnum ata_sg_get_start_sector(const ata_sg_context *self)
222{
223 return self->sg[0].block;
224}
225
226static inline rtems_blkdev_bnum ata_sg_get_sector_count(const ata_sg_context *self)
227{
228 return (self->sg_buffer_offset_mask + 1) * self->sg_count;
229}
230
231static inline uint16_t *ata_sg_get_sector_data_begin(const ata_sg_context *self, rtems_blkdev_bnum relative_sector)
232{
233 uint16_t *begin = (uint16_t *)(self->sg[relative_sector >> self->sg_index_shift].buffer);
234
235 return begin + ((relative_sector & self->sg_buffer_offset_mask) << (ATA_SECTOR_SHIFT - 1));
236}
237
238static inline uint16_t *ata_sg_get_sector_data_end(const ata_sg_context *self, uint16_t *begin)
239{
240 return begin + ATA_SECTOR_SIZE / 2;
241}
242
243typedef struct {
244 rtems_id lock;
245
246 bool card_present;
247} ata_driver;
248
249void ata_driver_create(ata_driver *self, const char *device_file_path, rtems_block_device_ioctl io_control);
250
251void ata_driver_destroy(ata_driver *self);
252
253static inline void ata_driver_lock(const ata_driver *self)
254{
256 assert(sc == RTEMS_SUCCESSFUL);
257 (void) sc;
258}
259
260static inline void ata_driver_unlock(const ata_driver *self)
261{
263 assert(sc == RTEMS_SUCCESSFUL);
264 (void) sc;
265}
266
267static inline bool ata_driver_is_card_present(const ata_driver *self)
268{
269 return self->card_present;
270}
271
272static inline void ata_driver_io_request(
273 ata_driver *self,
274 rtems_blkdev_request *request,
275 bool (*transfer)(ata_driver *, bool, rtems_blkdev_sg_buffer *, size_t)
276)
277{
278 assert(request->req == RTEMS_BLKDEV_REQ_READ || request->req == RTEMS_BLKDEV_REQ_WRITE);
279 bool read = request->req != RTEMS_BLKDEV_REQ_WRITE;
280 rtems_blkdev_sg_buffer *sg = &request->bufs[0];
281 uint32_t sg_count = request->bufnum;
282 ata_driver_lock(self);
283 bool ok = (*transfer)(self, read, sg, sg_count);
284 ata_driver_unlock(self);
286 rtems_blkdev_request_done(request, sc);
287}
288
289static inline int ata_driver_io_control(
291 uint32_t cmd,
292 void *arg,
293 bool (*transfer)(ata_driver *, bool, rtems_blkdev_sg_buffer *, size_t)
294)
295{
296 ata_driver *self = (ata_driver *) rtems_disk_get_driver_data(dd);
297
298 switch (cmd) {
299 case RTEMS_BLKIO_REQUEST:
300 ata_driver_io_request(self, (rtems_blkdev_request *) arg, transfer);
301 return 0;
302 case RTEMS_BLKIO_CAPABILITIES:
303 *(uint32_t *) arg = RTEMS_BLKDEV_CAP_MULTISECTOR_CONT;
304 return 0;
305 default:
306 return rtems_blkdev_ioctl(dd, cmd, arg);
307 }
308}
309
310int ata_driver_io_control_pio_polled(
312 uint32_t cmd,
313 void *arg
314);
315
316typedef struct {
317 ata_driver super;
318
319 bestcomm_task task;
320
321 bool read;
322
323 ata_sg_context sg_context;
324
325 rtems_blkdev_bnum transfer_current;
326
327 rtems_blkdev_bnum transfer_end;
329
330void ata_driver_dma_pio_single_create(
332 const char *device_file_path,
333 TaskId task_index
334);
335
336#ifdef __cplusplus
337}
338#endif /* __cplusplus */
339
340#endif /* GEN5200_ATA_H */
Information for the Assert Handler.
Block Device Buffer Management.
#define NULL
Requests a GPIO pin group configuration.
Definition: bestcomm_api.h:77
Block Device Disk Management API.
void rtems_cache_flush_multiple_data_lines(const void *d_addr, size_t n_bytes)
Flushes multiple data cache lines.
Definition: cacheimpl.h:109
#define RTEMS_WAIT
Definition: options.h:53
rtems_status_code rtems_semaphore_release(rtems_id id)
RTEMS Semaphore Release.
Definition: semrelease.c:28
rtems_status_code rtems_semaphore_obtain(rtems_id id, rtems_option option_set, rtems_interval timeout)
RTEMS Obtain Semaphore.
Definition: semobtain.c:51
rtems_status_code
Classic API Status.
Definition: status.h:43
@ RTEMS_SUCCESSFUL
Definition: status.h:47
@ RTEMS_IO_ERROR
Definition: status.h:168
Objects_Id rtems_id
Used to manage and manipulate RTEMS object identifiers.
Definition: types.h:83
#define RTEMS_NO_TIMEOUT
Constant for indefinite wait.
Definition: rtems.h:174
#define RTEMS_BLKDEV_CAP_MULTISECTOR_CONT
Only consecutive multi-sector buffer requests are supported.
Definition: blkdev.h:264
int rtems_blkdev_ioctl(rtems_disk_device *dd, uint32_t req, void *argp)
Common IO control primitive.
Definition: blkdev-ioctl.c:24
@ RTEMS_BLKDEV_REQ_READ
Definition: blkdev.h:50
@ RTEMS_BLKDEV_REQ_WRITE
Definition: blkdev.h:51
uint32_t rtems_blkdev_bnum
Block device block index type.
Definition: diskdevs.h:45
int(* rtems_block_device_ioctl)(rtems_disk_device *dd, uint32_t req, void *argp)
Block device IO control handler type.
Definition: diskdevs.h:50
ssize_t read(int fd, void *buffer, size_t count)
Definition: read.c:27
ssize_t write(int fd, const void *buffer, size_t count)
Definition: write.c:30
General purpose assembler macros, linker command file support and some inline functions for direct re...
Definition: ata.h:316
Definition: ata.h:243
Definition: ata.h:192
Definition: bestcomm.h:127
Definition: intercom.c:74
The block device transfer request is used to read or write a number of blocks from or to the device.
Definition: blkdev.h:102
rtems_blkdev_request_op req
Definition: blkdev.h:106
rtems_blkdev_sg_buffer bufs[RTEMS_ZERO_LENGTH_ARRAY]
Definition: blkdev.h:145
uint32_t bufnum
Definition: blkdev.h:126
Block device scatter or gather buffer structure.
Definition: blkdev.h:68
rtems_blkdev_bnum block
Definition: blkdev.h:72
void * buffer
Definition: blkdev.h:82
uint32_t length
Definition: blkdev.h:77
Description of a disk device (logical and physical disks).
Definition: diskdevs.h:157
Definition: ata.h:61