source: rtems/bsps/powerpc/gen5200/include/bsp/ata.h @ 7de51829

5
Last change on this file since 7de51829 was 7de51829, checked in by Joel Sherrill <joel@…>, on Aug 10, 2018 at 1:18:59 PM

gen5200/include/bsp/ata.h: Fix warning

  • Property mode set to 100644
File size: 8.0 KB
Line 
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
30#include <libcpu/powerpc-utility.h>
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;
104} ata_drive_registers;
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;
200} ata_sg_context;
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{
255  rtems_status_code sc = rtems_semaphore_obtain(self->lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
256  assert(sc == RTEMS_SUCCESSFUL);
257  (void) sc;
258}
259
260static inline void ata_driver_unlock(const ata_driver *self)
261{
262  rtems_status_code sc = rtems_semaphore_release(self->lock);
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);
285  rtems_status_code sc = ok ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR;
286  rtems_blkdev_request_done(request, sc);
287}
288
289static inline int ata_driver_io_control(
290  rtems_disk_device *dd,
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(
311  rtems_disk_device *dd,
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;
328} ata_driver_dma_pio_single;
329
330void ata_driver_dma_pio_single_create(
331  ata_driver_dma_pio_single *self,
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 */
Note: See TracBrowser for help on using the repository browser.