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 #define NDEBUG
0029 
0030 #include <bsp/ata.h>
0031 
0032 #include <bsp.h>
0033 #include <bsp/fatal.h>
0034 #include <bsp/mpc5200.h>
0035 
0036 #include <libcpu/powerpc-utility.h>
0037 
0038 bool ata_execute_io_command(uint8_t command, uint32_t lba, uint32_t sector_count_32)
0039 {
0040   assert(sector_count_32 >= 1);
0041   assert(sector_count_32 <= 256);
0042 
0043   assert(ata_is_drive_ready_for_selection());
0044 
0045   ATA->write.head = (uint8_t) (0xe0 | ((lba >> 24) & 0x0f));
0046 
0047   ata_wait_400_nano_seconds();
0048   ata_wait_for_drive_ready();
0049 
0050   /*
0051    * It seems that the write to the ATA device registers is sometimes not
0052    * successful.  The write is retried until the read back values are all right
0053    * or a timeout is reached.
0054    */
0055   bool ok = false;
0056   uint8_t sector = (uint8_t) lba;
0057   uint8_t cylinder_low = (uint8_t) (lba >> 8);
0058   uint8_t cylinder_high = (uint8_t) (lba >> 16);
0059   uint8_t sector_count = (uint8_t) sector_count_32;
0060   int i;
0061   for (i = 0; !ok && i < 100; ++i) {
0062     ATA->write.sector = sector;
0063     ATA->write.cylinder_low = cylinder_low;
0064     ATA->write.cylinder_high = cylinder_high;
0065     ATA->write.sector_count = sector_count;
0066 
0067     uint8_t actual_sector = ATA->read.sector;
0068     uint8_t actual_cylinder_low = ATA->read.cylinder_low;
0069     uint8_t actual_cylinder_high = ATA->read.cylinder_high;
0070     uint8_t actual_sector_count = ATA->read.sector_count;
0071 
0072     ok = actual_cylinder_high == cylinder_high
0073       && actual_cylinder_low == cylinder_low
0074       && actual_sector == sector
0075       && actual_sector_count == sector_count;
0076   }
0077 
0078   if (ok) {
0079     ATA->write.command = command;
0080   }
0081 
0082   return ok;
0083 }
0084 
0085 void ata_reset_device(void)
0086 {
0087   /* ATA/ATAPI-7 V2, 11.2 Software reset protocol */
0088   ATA->write.control = DCTRL_SRST;
0089   rtems_bsp_delay(5);
0090   ATA->write.control = 0;
0091   rtems_bsp_delay(2000);
0092   ata_wait_for_not_busy();
0093 }
0094 
0095 bool ata_set_transfer_mode(uint8_t mode)
0096 {
0097   assert(ata_is_drive_ready_for_selection());
0098 
0099   ATA->write.head = 0xe0;
0100 
0101   ata_wait_400_nano_seconds();
0102   ata_wait_for_drive_ready();
0103 
0104   ATA->write.feature = 0x3;
0105   ATA->write.sector_count = mode;
0106   ATA->write.command = 0xef;
0107 
0108   ata_wait_for_not_busy();
0109 
0110   return ata_check_status();
0111 }
0112 
0113 static bool probe(void)
0114 {
0115   bool card_present = true;
0116 
0117 #ifdef MPC5200_BOARD_BRS5L
0118   volatile struct mpc5200_gpt *gpt = &mpc5200.gpt[GPT2];
0119 
0120   /* Enable card detection on GPT2 */
0121   gpt->emsel = (GPT_EMSEL_GPIO_IN | GPT_EMSEL_TIMER_MS_GPIO);
0122 
0123   /* Check for card detection (-CD0) */
0124   if ((gpt->status & GPT_STATUS_PIN) != 0) {
0125     card_present = false;
0126   }
0127 #endif
0128 
0129   return card_present;
0130 }
0131 
0132 static void create_lock(ata_driver *self)
0133 {
0134   rtems_status_code sc = rtems_semaphore_create(
0135     rtems_build_name('A', 'T', 'A', ' '),
0136     1,
0137     RTEMS_LOCAL | RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
0138     0,
0139     &self->lock
0140   );
0141   if (sc != RTEMS_SUCCESSFUL) {
0142     bsp_fatal(MPC5200_FATAL_ATA_LOCK_CREATE);
0143   }
0144 }
0145 
0146 static void destroy_lock(const ata_driver *self)
0147 {
0148   rtems_status_code sc = rtems_semaphore_delete(self->lock);
0149   if (sc != RTEMS_SUCCESSFUL) {
0150     bsp_fatal(MPC5200_FATAL_ATA_LOCK_DESTROY);
0151   }
0152 }
0153 
0154 void ata_driver_create(ata_driver *self, const char *device_file_path, rtems_block_device_ioctl io_control)
0155 {
0156   self->card_present = probe();
0157 
0158   if (ata_driver_is_card_present(self)) {
0159     create_lock(self);
0160     ata_reset_device();
0161 
0162     uint16_t sector_buffer[256];
0163     ata_dev_t ata_device;
0164     rtems_status_code sc = ata_identify_device(0, 0, sector_buffer, &ata_device);
0165 
0166     if (sc == RTEMS_SUCCESSFUL && ata_device.lba_avaible) {
0167       sc = ide_controller_config_io_speed(0, ata_device.modes_available);
0168 
0169       if (sc == RTEMS_SUCCESSFUL) {
0170         sc = rtems_blkdev_create(
0171           device_file_path,
0172           ATA_SECTOR_SIZE,
0173           ata_device.lba_sectors,
0174           io_control,
0175           self
0176         );
0177 
0178         if (sc != RTEMS_SUCCESSFUL) {
0179           bsp_fatal(MPC5200_FATAL_ATA_DISK_CREATE);
0180         }
0181       }
0182     }
0183   }
0184 }
0185 
0186 void ata_driver_destroy(ata_driver *self)
0187 {
0188   destroy_lock(self);
0189   /* TODO */
0190   assert(0);
0191 }
0192 
0193 static bool transfer_pio_polled(ata_driver *self, bool read, rtems_blkdev_sg_buffer *sg, size_t sg_count)
0194 {
0195   bool ok = true;
0196 
0197   ata_sg_context sg_context;
0198   ata_sg_create(&sg_context, sg, sg_count);
0199   rtems_blkdev_bnum start_sector = ata_sg_get_start_sector(&sg_context);
0200   rtems_blkdev_bnum sector_count = ata_sg_get_sector_count(&sg_context);
0201   rtems_blkdev_bnum relative_sector = 0;
0202 
0203   uint8_t command = ata_read_or_write_sectors_command(read);
0204 
0205   while (ok && relative_sector < sector_count) {
0206     rtems_blkdev_bnum remaining_sectors = sector_count - relative_sector;
0207     rtems_blkdev_bnum transfer_count = ata_max_transfer_count(remaining_sectors);
0208     rtems_blkdev_bnum transfer_end = relative_sector + transfer_count;
0209 
0210     ok = ata_execute_io_command(command, start_sector + relative_sector, transfer_count);
0211 
0212     rtems_blkdev_bnum transfer;
0213     for (transfer = relative_sector; ok && transfer < transfer_end; ++transfer) {
0214       uint16_t *current = ata_sg_get_sector_data_begin(&sg_context, transfer);
0215       uint16_t *end = ata_sg_get_sector_data_end(&sg_context, current);
0216 
0217       ok = ata_wait_for_data_request();
0218 
0219       if (ok) {
0220         if (read) {
0221           while (current != end) {
0222             *current = ATA->read.data;
0223             ++current;
0224           }
0225         } else {
0226           while (current != end) {
0227             ATA->write.data = *current;
0228             ++current;
0229           }
0230         }
0231       }
0232     }
0233 
0234     if (ok) {
0235       ata_wait_for_not_busy();
0236       ok = ata_check_status();
0237     }
0238 
0239     relative_sector += ATA_PER_TRANSFER_SECTOR_COUNT_MAX;
0240   }
0241 
0242   return ok;
0243 }
0244 
0245 int ata_driver_io_control_pio_polled(
0246   rtems_disk_device *dd,
0247   uint32_t cmd,
0248   void *arg
0249 )
0250 {
0251   return ata_driver_io_control(dd, cmd, arg, transfer_pio_polled);
0252 }