Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:52

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2010, 2013 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #ifndef GEN5200_ATA_H
0029 #define GEN5200_ATA_H
0030 
0031 #include "bestcomm.h"
0032 
0033 #include <assert.h>
0034 
0035 #include <rtems.h>
0036 #include <rtems/diskdevs.h>
0037 #include <rtems/bdbuf.h>
0038 
0039 #include <libchip/ata_internal.h>
0040 #include <libchip/ide_ctrl_io.h>
0041 #include <libchip/ide_ctrl_cfg.h>
0042 
0043 #include <libcpu/powerpc-utility.h>
0044 
0045 #ifdef __cplusplus
0046 extern "C" {
0047 #endif /* __cplusplus */
0048 
0049 #define DCTRL_SRST BSP_BBIT8(5)
0050 #define DCTRL_NIEN BSP_BBIT8(6)
0051 
0052 #define DAST_BSY BSP_BBIT8(0)
0053 #define DAST_DRDY BSP_BBIT8(1)
0054 #define DAST_DRQ BSP_BBIT8(4)
0055 #define DAST_ERR BSP_BBIT8(7)
0056 
0057 #define DST_BSY BSP_BBIT16(0)
0058 #define DST_DRDY BSP_BBIT16(1)
0059 #define DST_DRQ BSP_BBIT16(4)
0060 #define DST_ERR BSP_BBIT16(7)
0061 
0062 #define DDMA_HUT BSP_BBIT8(1)
0063 #define DDMA_FR BSP_BBIT8(2)
0064 #define DDMA_FE BSP_BBIT8(3)
0065 #define DDMA_IE BSP_BBIT8(4)
0066 #define DDMA_UDMA BSP_BBIT8(5)
0067 #define DDMA_READ BSP_BBIT8(6)
0068 #define DDMA_WRITE BSP_BBIT8(7)
0069 
0070 #define ATA_SECTOR_SHIFT 9
0071 
0072 #define ATA_PER_TRANSFER_SECTOR_COUNT_MAX 256
0073 
0074 typedef union {
0075   struct {
0076     uint8_t alternate_status;
0077     uint8_t reserved_0[3];
0078     uint16_t data;
0079     uint8_t reserved_1[2];
0080     uint8_t error;
0081     uint8_t reserved_2[3];
0082     uint8_t sector_count;
0083     uint8_t reserved_3[3];
0084     uint8_t sector;
0085     uint8_t reserved_4[3];
0086     uint8_t cylinder_low;
0087     uint8_t reserved_5[3];
0088     uint8_t cylinder_high;
0089     uint8_t reserved_6[3];
0090     uint8_t head;
0091     uint8_t reserved_7[3];
0092     uint16_t status;
0093     uint8_t reserved_8[2];
0094   } read;
0095 
0096   struct {
0097     uint8_t control;
0098     uint8_t reserved_0[3];
0099     uint16_t data;
0100     uint8_t reserved_1[2];
0101     uint8_t feature;
0102     uint8_t reserved_2[3];
0103     uint8_t sector_count;
0104     uint8_t reserved_3[3];
0105     uint8_t sector;
0106     uint8_t reserved_4[3];
0107     uint8_t cylinder_low;
0108     uint8_t reserved_5[3];
0109     uint8_t cylinder_high;
0110     uint8_t reserved_6[3];
0111     uint8_t head;
0112     uint8_t reserved_7[3];
0113     uint8_t command;
0114     uint8_t dma_control;
0115     uint8_t reserved_8[2];
0116   } write;
0117 } ata_drive_registers;
0118 
0119 #define ATA ((volatile ata_drive_registers *) 0xf0003a5c)
0120 
0121 static inline bool ata_is_data_request(void)
0122 {
0123   return (ATA->read.alternate_status & DAST_DRQ) != 0;
0124 }
0125 
0126 static inline bool ata_is_drive_ready_for_selection(void)
0127 {
0128   return (ATA->read.alternate_status & (DAST_BSY | DAST_DRQ)) == 0;
0129 }
0130 
0131 static inline void ata_wait_400_nano_seconds(void)
0132 {
0133   ATA->read.alternate_status;
0134 }
0135 
0136 static inline void ata_wait_for_drive_ready(void)
0137 {
0138   while ((ATA->read.alternate_status & (DAST_BSY | DAST_DRQ | DAST_DRDY)) != DAST_DRDY) {
0139     /* Wait */
0140   }
0141 }
0142 
0143 static inline void ata_wait_for_not_busy(void)
0144 {
0145   ata_wait_400_nano_seconds();
0146 
0147   while ((ATA->read.alternate_status & DAST_BSY) != 0) {
0148     /* Wait */
0149   }
0150 }
0151 
0152 static inline bool ata_wait_for_data_request(void)
0153 {
0154   ata_wait_400_nano_seconds();
0155 
0156   uint8_t alternate_status;
0157   do {
0158     alternate_status = ATA->read.alternate_status;
0159   } while ((alternate_status & DAST_BSY) == DAST_BSY);
0160 
0161   return (alternate_status & (DAST_ERR | DAST_DRQ)) == DAST_DRQ;
0162 }
0163 
0164 static inline bool ata_check_status(void)
0165 {
0166   return (ATA->read.status & (DST_BSY | DST_ERR)) == 0;
0167 }
0168 
0169 static inline void ata_clear_interrupts(void)
0170 {
0171   ATA->read.status;
0172 }
0173 
0174 static inline uint8_t ata_read_or_write_sectors_command(bool read)
0175 {
0176   return read ? 0x20 : 0x30;
0177 }
0178 
0179 static inline rtems_blkdev_bnum ata_max_transfer_count(rtems_blkdev_bnum sector_count)
0180 {
0181   return sector_count > ATA_PER_TRANSFER_SECTOR_COUNT_MAX ?
0182     ATA_PER_TRANSFER_SECTOR_COUNT_MAX
0183       : sector_count;
0184 }
0185 
0186 static inline void ata_flush_sector(uint16_t *begin)
0187 {
0188   /* XXX: The dcbi operation does not work properly */
0189   rtems_cache_flush_multiple_data_lines(begin, ATA_SECTOR_SIZE);
0190 }
0191 
0192 void ata_reset_device(void);
0193 
0194 bool ata_set_transfer_mode(uint8_t mode);
0195 
0196 bool ata_execute_io_command(uint8_t command, uint32_t lba, uint32_t sector_count);
0197 
0198 static inline bool ata_execute_io_command_with_sg(uint8_t command, const rtems_blkdev_sg_buffer *sg)
0199 {
0200   uint32_t lba = sg->block;
0201   uint32_t sector_count = sg->length / ATA_SECTOR_SIZE;
0202   return ata_execute_io_command(command, lba, sector_count);
0203 }
0204 
0205 typedef struct {
0206   const rtems_blkdev_sg_buffer *sg;
0207 
0208   size_t sg_count;
0209 
0210   rtems_blkdev_bnum sg_buffer_offset_mask;
0211 
0212   int sg_index_shift;
0213 } ata_sg_context;
0214 
0215 static inline void ata_sg_reset(ata_sg_context *self, const rtems_blkdev_sg_buffer *sg, size_t sg_count)
0216 {
0217   self->sg = sg;
0218   self->sg_count = sg_count;
0219   uint32_t sectors_per_buffer = self->sg[0].length >> ATA_SECTOR_SHIFT;
0220   self->sg_buffer_offset_mask = sectors_per_buffer - 1;
0221   self->sg_index_shift = __builtin_ffs((int) sectors_per_buffer) - 1;
0222 }
0223 
0224 static inline void ata_sg_create_default(ata_sg_context *self)
0225 {
0226   ata_sg_reset(self, NULL, 0);
0227 }
0228 
0229 static inline void ata_sg_create(ata_sg_context *self, const rtems_blkdev_sg_buffer *sg, size_t sg_count)
0230 {
0231   ata_sg_reset(self, sg, sg_count);
0232 }
0233 
0234 static inline rtems_blkdev_bnum ata_sg_get_start_sector(const ata_sg_context *self)
0235 {
0236   return self->sg[0].block;
0237 }
0238 
0239 static inline rtems_blkdev_bnum ata_sg_get_sector_count(const ata_sg_context *self)
0240 {
0241   return (self->sg_buffer_offset_mask + 1) * self->sg_count;
0242 }
0243 
0244 static inline uint16_t *ata_sg_get_sector_data_begin(const ata_sg_context *self, rtems_blkdev_bnum relative_sector)
0245 {
0246   uint16_t *begin = (uint16_t *)(self->sg[relative_sector >> self->sg_index_shift].buffer);
0247 
0248   return begin + ((relative_sector & self->sg_buffer_offset_mask) << (ATA_SECTOR_SHIFT - 1));
0249 }
0250 
0251 static inline uint16_t *ata_sg_get_sector_data_end(const ata_sg_context *self, uint16_t *begin)
0252 {
0253   return begin + ATA_SECTOR_SIZE / 2;
0254 }
0255 
0256 typedef struct {
0257   rtems_id lock;
0258 
0259   bool card_present;
0260 } ata_driver;
0261 
0262 void ata_driver_create(ata_driver *self, const char *device_file_path, rtems_block_device_ioctl io_control);
0263 
0264 void ata_driver_destroy(ata_driver *self);
0265 
0266 static inline void ata_driver_lock(const ata_driver *self)
0267 {
0268   rtems_status_code sc = rtems_semaphore_obtain(self->lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0269   assert(sc == RTEMS_SUCCESSFUL);
0270   (void) sc;
0271 }
0272 
0273 static inline void ata_driver_unlock(const ata_driver *self)
0274 {
0275   rtems_status_code sc = rtems_semaphore_release(self->lock);
0276   assert(sc == RTEMS_SUCCESSFUL);
0277   (void) sc;
0278 }
0279 
0280 static inline bool ata_driver_is_card_present(const ata_driver *self)
0281 {
0282   return self->card_present;
0283 }
0284 
0285 static inline void ata_driver_io_request(
0286   ata_driver *self,
0287   rtems_blkdev_request *request,
0288   bool (*transfer)(ata_driver *, bool, rtems_blkdev_sg_buffer *, size_t)
0289 )
0290 {
0291   assert(request->req == RTEMS_BLKDEV_REQ_READ || request->req == RTEMS_BLKDEV_REQ_WRITE);
0292   bool read = request->req != RTEMS_BLKDEV_REQ_WRITE;
0293   rtems_blkdev_sg_buffer *sg = &request->bufs[0];
0294   uint32_t sg_count = request->bufnum;
0295   ata_driver_lock(self);
0296   bool ok = (*transfer)(self, read, sg, sg_count);
0297   ata_driver_unlock(self);
0298   rtems_status_code sc = ok ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR;
0299   rtems_blkdev_request_done(request, sc);
0300 }
0301 
0302 static inline int ata_driver_io_control(
0303   rtems_disk_device *dd,
0304   uint32_t cmd,
0305   void *arg,
0306   bool (*transfer)(ata_driver *, bool, rtems_blkdev_sg_buffer *, size_t)
0307 )
0308 {
0309   ata_driver *self = (ata_driver *) rtems_disk_get_driver_data(dd);
0310 
0311   switch (cmd) {
0312     case RTEMS_BLKIO_REQUEST:
0313       ata_driver_io_request(self, (rtems_blkdev_request *) arg, transfer);
0314       return 0;
0315     case RTEMS_BLKIO_CAPABILITIES:
0316       *(uint32_t *) arg = RTEMS_BLKDEV_CAP_MULTISECTOR_CONT;
0317       return 0;
0318     default:
0319       return rtems_blkdev_ioctl(dd, cmd, arg);
0320   }
0321 }
0322 
0323 int ata_driver_io_control_pio_polled(
0324   rtems_disk_device *dd,
0325   uint32_t cmd,
0326   void *arg
0327 );
0328 
0329 typedef struct {
0330   ata_driver super;
0331 
0332   bestcomm_task task;
0333 
0334   bool read;
0335 
0336   ata_sg_context sg_context;
0337 
0338   rtems_blkdev_bnum transfer_current;
0339 
0340   rtems_blkdev_bnum transfer_end;
0341 } ata_driver_dma_pio_single;
0342 
0343 void ata_driver_dma_pio_single_create(
0344   ata_driver_dma_pio_single *self,
0345   const char *device_file_path,
0346   TaskId task_index
0347 );
0348 
0349 #ifdef __cplusplus
0350 }
0351 #endif /* __cplusplus */
0352 
0353 #endif /* GEN5200_ATA_H */