File indexing completed on 2025-05-11 08:23:52
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
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
0052
0053
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
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
0121 gpt->emsel = (GPT_EMSEL_GPIO_IN | GPT_EMSEL_TIMER_MS_GPIO);
0122
0123
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
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 }