summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/gen5200/include
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-02-18 17:00:28 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-02-20 09:11:41 +0100
commit57bcb88ef5348a18ae22bd45ac42b0a2646a3264 (patch)
treebc3bb8aff9a7d28e035bda23d2871d9d68d79762 /c/src/lib/libbsp/powerpc/gen5200/include
parentbsp/gen5200: Add and use mpc5200_fatal() (diff)
downloadrtems-57bcb88ef5348a18ae22bd45ac42b0a2646a3264.tar.bz2
bsp/gen5200: New ATA driver
This is a replacement for the ATA task. The performance is much better.
Diffstat (limited to 'c/src/lib/libbsp/powerpc/gen5200/include')
-rw-r--r--c/src/lib/libbsp/powerpc/gen5200/include/ata.h338
-rw-r--r--c/src/lib/libbsp/powerpc/gen5200/include/bestcomm.h370
-rw-r--r--c/src/lib/libbsp/powerpc/gen5200/include/bestcomm_ops.h224
-rw-r--r--c/src/lib/libbsp/powerpc/gen5200/include/bsp.h5
4 files changed, 936 insertions, 1 deletions
diff --git a/c/src/lib/libbsp/powerpc/gen5200/include/ata.h b/c/src/lib/libbsp/powerpc/gen5200/include/ata.h
new file mode 100644
index 0000000000..38cd536af0
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/gen5200/include/ata.h
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2010-2013 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef GEN5200_ATA_H
+#define GEN5200_ATA_H
+
+#include "bestcomm.h"
+
+#include <assert.h>
+
+#include <rtems.h>
+#include <rtems/diskdevs.h>
+#include <rtems/bdbuf.h>
+
+#include <libchip/ata_internal.h>
+#include <libchip/ide_ctrl_io.h>
+#include <libchip/ide_ctrl_cfg.h>
+
+#include <libcpu/powerpc-utility.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define DCTRL_SRST BSP_BBIT8(5)
+#define DCTRL_NIEN BSP_BBIT8(6)
+
+#define DAST_BSY BSP_BBIT8(0)
+#define DAST_DRDY BSP_BBIT8(1)
+#define DAST_DRQ BSP_BBIT8(4)
+#define DAST_ERR BSP_BBIT8(7)
+
+#define DST_BSY BSP_BBIT16(0)
+#define DST_DRDY BSP_BBIT16(1)
+#define DST_DRQ BSP_BBIT16(4)
+#define DST_ERR BSP_BBIT16(7)
+
+#define DDMA_HUT BSP_BBIT8(1)
+#define DDMA_FR BSP_BBIT8(2)
+#define DDMA_FE BSP_BBIT8(3)
+#define DDMA_IE BSP_BBIT8(4)
+#define DDMA_UDMA BSP_BBIT8(5)
+#define DDMA_READ BSP_BBIT8(6)
+#define DDMA_WRITE BSP_BBIT8(7)
+
+#define ATA_SECTOR_SHIFT 9
+
+#define ATA_PER_TRANSFER_SECTOR_COUNT_MAX 256
+
+typedef union {
+ struct {
+ uint8_t alternate_status;
+ uint8_t reserved_0[3];
+ uint16_t data;
+ uint8_t reserved_1[2];
+ uint8_t error;
+ uint8_t reserved_2[3];
+ uint8_t sector_count;
+ uint8_t reserved_3[3];
+ uint8_t sector;
+ uint8_t reserved_4[3];
+ uint8_t cylinder_low;
+ uint8_t reserved_5[3];
+ uint8_t cylinder_high;
+ uint8_t reserved_6[3];
+ uint8_t head;
+ uint8_t reserved_7[3];
+ uint16_t status;
+ uint8_t reserved_8[2];
+ } read;
+
+ struct {
+ uint8_t control;
+ uint8_t reserved_0[3];
+ uint16_t data;
+ uint8_t reserved_1[2];
+ uint8_t feature;
+ uint8_t reserved_2[3];
+ uint8_t sector_count;
+ uint8_t reserved_3[3];
+ uint8_t sector;
+ uint8_t reserved_4[3];
+ uint8_t cylinder_low;
+ uint8_t reserved_5[3];
+ uint8_t cylinder_high;
+ uint8_t reserved_6[3];
+ uint8_t head;
+ uint8_t reserved_7[3];
+ uint8_t command;
+ uint8_t dma_control;
+ uint8_t reserved_8[2];
+ } write;
+} ata_drive_registers;
+
+#define ATA ((volatile ata_drive_registers *) 0xf0003a5c)
+
+static inline bool ata_is_data_request(void)
+{
+ return (ATA->read.alternate_status & DAST_DRQ) != 0;
+}
+
+static inline bool ata_is_drive_ready_for_selection(void)
+{
+ return (ATA->read.alternate_status & (DAST_BSY | DAST_DRQ)) == 0;
+}
+
+static inline void ata_wait_400_nano_seconds(void)
+{
+ ATA->read.alternate_status;
+}
+
+static inline void ata_wait_for_drive_ready(void)
+{
+ while ((ATA->read.alternate_status & (DAST_BSY | DAST_DRQ | DAST_DRDY)) != DAST_DRDY) {
+ /* Wait */
+ }
+}
+
+static inline void ata_wait_for_not_busy(void)
+{
+ ata_wait_400_nano_seconds();
+
+ while ((ATA->read.alternate_status & DAST_BSY) != 0) {
+ /* Wait */
+ }
+}
+
+static inline bool ata_wait_for_data_request(void)
+{
+ ata_wait_400_nano_seconds();
+
+ uint8_t alternate_status;
+ do {
+ alternate_status = ATA->read.alternate_status;
+ } while ((alternate_status & DAST_BSY) == DAST_BSY);
+
+ return (alternate_status & (DAST_ERR | DAST_DRQ)) == DAST_DRQ;
+}
+
+static inline bool ata_check_status(void)
+{
+ return (ATA->read.status & (DST_BSY | DST_ERR)) == 0;
+}
+
+static inline void ata_clear_interrupts(void)
+{
+ ATA->read.status;
+}
+
+static inline uint8_t ata_read_or_write_sectors_command(bool read)
+{
+ return read ? 0x20 : 0x30;
+}
+
+static inline rtems_blkdev_bnum ata_max_transfer_count(rtems_blkdev_bnum sector_count)
+{
+ return sector_count > ATA_PER_TRANSFER_SECTOR_COUNT_MAX ?
+ ATA_PER_TRANSFER_SECTOR_COUNT_MAX
+ : sector_count;
+}
+
+static inline void ata_flush_sector(uint16_t *begin)
+{
+ /* XXX: The dcbi operation does not work properly */
+ rtems_cache_flush_multiple_data_lines(begin, ATA_SECTOR_SIZE);
+}
+
+void ata_reset_device();
+
+bool ata_set_transfer_mode(uint8_t mode);
+
+bool ata_execute_io_command(uint8_t command, uint32_t lba, uint32_t sector_count);
+
+static inline bool ata_execute_io_command_with_sg(uint8_t command, const rtems_blkdev_sg_buffer *sg)
+{
+ uint32_t lba = sg->block;
+ uint32_t sector_count = sg->length / ATA_SECTOR_SIZE;
+ return ata_execute_io_command(command, lba, sector_count);
+}
+
+typedef struct {
+ const rtems_blkdev_sg_buffer *sg;
+
+ size_t sg_count;
+
+ rtems_blkdev_bnum sg_buffer_offset_mask;
+
+ int sg_index_shift;
+} ata_sg_context;
+
+static inline void ata_sg_reset(ata_sg_context *self, const rtems_blkdev_sg_buffer *sg, size_t sg_count)
+{
+ self->sg = sg;
+ self->sg_count = sg_count;
+ uint32_t sectors_per_buffer = self->sg[0].length >> ATA_SECTOR_SHIFT;
+ self->sg_buffer_offset_mask = sectors_per_buffer - 1;
+ self->sg_index_shift = __builtin_ffs((int) sectors_per_buffer) - 1;
+}
+
+static inline void ata_sg_create_default(ata_sg_context *self)
+{
+ ata_sg_reset(self, NULL, 0);
+}
+
+static inline void ata_sg_create(ata_sg_context *self, const rtems_blkdev_sg_buffer *sg, size_t sg_count)
+{
+ ata_sg_reset(self, sg, sg_count);
+}
+
+static inline rtems_blkdev_bnum ata_sg_get_start_sector(const ata_sg_context *self)
+{
+ return self->sg[0].block;
+}
+
+static inline rtems_blkdev_bnum ata_sg_get_sector_count(const ata_sg_context *self)
+{
+ return (self->sg_buffer_offset_mask + 1) * self->sg_count;
+}
+
+static inline uint16_t *ata_sg_get_sector_data_begin(const ata_sg_context *self, rtems_blkdev_bnum relative_sector)
+{
+ uint16_t *begin = (uint16_t *)(self->sg[relative_sector >> self->sg_index_shift].buffer);
+
+ return begin + ((relative_sector & self->sg_buffer_offset_mask) << (ATA_SECTOR_SHIFT - 1));
+}
+
+static inline uint16_t *ata_sg_get_sector_data_end(const ata_sg_context *self, uint16_t *begin)
+{
+ return begin + ATA_SECTOR_SIZE / 2;
+}
+
+typedef struct {
+ rtems_id lock;
+
+ bool card_present;
+} ata_driver;
+
+void ata_driver_create(ata_driver *self, const char *device_file_path, rtems_block_device_ioctl io_control);
+
+void ata_driver_destroy(ata_driver *self);
+
+static inline void ata_driver_lock(const ata_driver *self)
+{
+ rtems_status_code sc = rtems_semaphore_obtain(self->lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static inline void ata_driver_unlock(const ata_driver *self)
+{
+ rtems_status_code sc = rtems_semaphore_release(self->lock);
+ assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static inline bool ata_driver_is_card_present(const ata_driver *self)
+{
+ return self->card_present;
+}
+
+static inline void ata_driver_io_request(
+ ata_driver *self,
+ rtems_blkdev_request *request,
+ bool (*transfer)(ata_driver *, bool, rtems_blkdev_sg_buffer *, size_t)
+)
+{
+ assert(request->req == RTEMS_BLKDEV_REQ_READ || request->req == RTEMS_BLKDEV_REQ_WRITE);
+ bool read = request->req != RTEMS_BLKDEV_REQ_WRITE;
+ rtems_blkdev_sg_buffer *sg = &request->bufs[0];
+ uint32_t sg_count = request->bufnum;
+ ata_driver_lock(self);
+ bool ok = (*transfer)(self, read, sg, sg_count);
+ ata_driver_unlock(self);
+ rtems_status_code sc = ok ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR;
+ rtems_blkdev_request_done(request, sc);
+}
+
+static inline int ata_driver_io_control(
+ rtems_disk_device *dd,
+ uint32_t cmd,
+ void *arg,
+ bool (*transfer)(ata_driver *, bool, rtems_blkdev_sg_buffer *, size_t)
+)
+{
+ ata_driver *self = (ata_driver *) rtems_disk_get_driver_data(dd);
+
+ switch (cmd) {
+ case RTEMS_BLKIO_REQUEST:
+ ata_driver_io_request(self, (rtems_blkdev_request *) arg, transfer);
+ return 0;
+ case RTEMS_BLKIO_CAPABILITIES:
+ *(uint32_t *) arg = RTEMS_BLKDEV_CAP_MULTISECTOR_CONT;
+ return 0;
+ default:
+ return rtems_blkdev_ioctl(dd, cmd, arg);
+ }
+}
+
+int ata_driver_io_control_pio_polled(
+ rtems_disk_device *dd,
+ uint32_t cmd,
+ void *arg
+);
+
+typedef struct {
+ ata_driver super;
+
+ bestcomm_task task;
+
+ bool read;
+
+ ata_sg_context sg_context;
+
+ rtems_blkdev_bnum transfer_current;
+
+ rtems_blkdev_bnum transfer_end;
+} ata_driver_dma_pio_single;
+
+void ata_driver_dma_pio_single_create(
+ ata_driver_dma_pio_single *self,
+ const char *device_file_path,
+ TaskId task_index
+);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* GEN5200_ATA_H */
diff --git a/c/src/lib/libbsp/powerpc/gen5200/include/bestcomm.h b/c/src/lib/libbsp/powerpc/gen5200/include/bestcomm.h
new file mode 100644
index 0000000000..7a127b6442
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/gen5200/include/bestcomm.h
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2010-2013 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef GEN5200_BESTCOMM_H
+#define GEN5200_BESTCOMM_H
+
+#include "bestcomm_ops.h"
+
+#include <assert.h>
+
+#include <rtems.h>
+
+#include <bsp/mpc5200.h>
+#include <bsp/bestcomm/bestcomm_api.h>
+#include <bsp/bestcomm/bestcomm_glue.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup BestComm BestComm Support
+ *
+ * @ingroup BestCommm
+ *
+ * @brief BestComm support.
+ *
+ * @{
+ */
+
+typedef struct {
+ uint32_t *tdt_begin;
+ uint32_t *tdt_last;
+ volatile uint32_t (*var_table)[32];
+ uint32_t fdt_and_pragmas;
+ uint32_t reserved_0;
+ uint32_t reserved_1;
+ uint32_t *context_begin;
+ uint32_t reserved_2;
+} bestcomm_task_entry;
+
+#define BESTCOMM_TASK_ENTRY_TABLE ((volatile bestcomm_task_entry *) 0xf0008000)
+
+#define BESTCOMM_IRQ_EVENT RTEMS_EVENT_13
+
+typedef struct {
+ int task_index;
+ rtems_id event_task_id;
+} bestcomm_irq;
+
+void bestcomm_irq_create(bestcomm_irq *self, int task_index);
+
+void bestcomm_irq_destroy(const bestcomm_irq *self);
+
+static inline void bestcomm_irq_enable(const bestcomm_irq *self)
+{
+ bestcomm_glue_irq_enable(self->task_index);
+}
+
+static inline void bestcomm_irq_disable(const bestcomm_irq *self)
+{
+ bestcomm_glue_irq_disable(self->task_index);
+}
+
+static inline void bestcomm_irq_clear(const bestcomm_irq *self)
+{
+ SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend, self->task_index);
+}
+
+static inline int bestcomm_irq_get_task_index(const bestcomm_irq *self)
+{
+ return self->task_index;
+}
+
+static inline rtems_id bestcomm_irq_get_event_task_id(const bestcomm_irq *self)
+{
+ return self->event_task_id;
+}
+
+static inline void bestcomm_irq_set_event_task_id(bestcomm_irq *self, rtems_id id)
+{
+ self->event_task_id = id;
+}
+
+static inline void bestcomm_irq_wakeup_event_task(const bestcomm_irq *self)
+{
+ rtems_status_code sc = rtems_event_send(self->event_task_id, BESTCOMM_IRQ_EVENT);
+ assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static inline void bestcomm_irq_wait(const bestcomm_irq *self)
+{
+ rtems_event_set events;
+ rtems_status_code sc = rtems_event_receive(
+ BESTCOMM_IRQ_EVENT,
+ RTEMS_EVENT_ALL | RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT,
+ &events
+ );
+ assert(sc == RTEMS_SUCCESSFUL);
+ assert(events == BESTCOMM_IRQ_EVENT);
+}
+
+static inline bool bestcomm_irq_peek(const bestcomm_irq *self)
+{
+ rtems_event_set events;
+ rtems_status_code sc = rtems_event_receive(0, 0, 0, &events);
+ assert(sc == RTEMS_SUCCESSFUL);
+
+ return (events & BESTCOMM_IRQ_EVENT) != 0;
+}
+
+typedef struct {
+ volatile uint16_t *task_control_register;
+
+ volatile uint32_t (*variable_table)[32];
+
+ TaskId task_index;
+
+ bestcomm_irq irq;
+
+ uint32_t *tdt_begin;
+
+ size_t tdt_opcode_count;
+} bestcomm_task;
+
+void bestcomm_task_create(bestcomm_task *self, TaskId task_index);
+
+void bestcomm_task_create_and_load(
+ bestcomm_task *self,
+ TaskId task_index,
+ const uint32_t *tdt_source_begin,
+ size_t tdt_size
+);
+
+void bestcomm_task_destroy(bestcomm_task *self);
+
+void bestcomm_task_load(bestcomm_task *self, const uint32_t *tdt_source_begin, size_t tdt_size);
+
+static inline void bestcomm_task_set_priority(bestcomm_task *self, int priority)
+{
+ /* Allow higher priority initiator to block current initiator */
+ mpc5200.sdma.ipr[self->task_index] = SDMA_IPR_PRIOR(priority);
+}
+
+static inline void bestcomm_task_irq_enable(const bestcomm_task *self)
+{
+ bestcomm_irq_enable(&self->irq);
+}
+
+static inline void bestcomm_task_irq_disable(const bestcomm_task *self)
+{
+ bestcomm_irq_disable(&self->irq);
+}
+
+static inline void bestcomm_task_irq_clear(const bestcomm_task *self)
+{
+ bestcomm_irq_clear(&self->irq);
+}
+
+static inline rtems_id bestcomm_task_get_event_task_id(const bestcomm_task *self)
+{
+ return bestcomm_irq_get_event_task_id(&self->irq);
+}
+
+static inline void bestcomm_task_set_event_task_id(bestcomm_task *self, rtems_id id)
+{
+ bestcomm_irq_set_event_task_id(&self->irq, id);
+}
+
+static inline void bestcomm_task_associate_with_current_task(bestcomm_task *self)
+{
+ bestcomm_task_set_event_task_id(self, rtems_task_self());
+}
+
+static inline void bestcomm_task_start(const bestcomm_task *self)
+{
+ *self->task_control_register = SDMA_TCR_EN | SDMA_TCR_HIGH_EN;
+}
+
+static inline void bestcomm_task_start_with_autostart(const bestcomm_task *self)
+{
+ *self->task_control_register = (uint16_t)
+ (SDMA_TCR_EN | SDMA_TCR_HIGH_EN | SDMA_TCR_AUTO_START | SDMA_TCR_AS(self->task_index));
+}
+
+static inline void bestcomm_task_stop(const bestcomm_task *self)
+{
+ *self->task_control_register = 0;
+}
+
+static inline void bestcomm_task_wakeup_event_task(const bestcomm_task *self)
+{
+ bestcomm_irq_wakeup_event_task(&self->irq);
+}
+
+static inline void bestcomm_task_wait(const bestcomm_task *self)
+{
+ bestcomm_irq_wait(&self->irq);
+}
+
+static inline bool bestcomm_task_peek(const bestcomm_task *self)
+{
+ return bestcomm_irq_peek(&self->irq);
+}
+
+static inline bool bestcomm_task_is_running(const bestcomm_task *self)
+{
+ return (*self->task_control_register & SDMA_TCR_EN) != 0;
+}
+
+static inline uint32_t bestcomm_get_task_variable(const bestcomm_task *self, size_t index)
+{
+ assert(index < VAR_COUNT);
+ return (*self->variable_table)[index];
+}
+
+static inline volatile uint32_t *bestcomm_task_get_address_of_variable(const bestcomm_task *self, size_t index)
+{
+ assert(index < VAR_COUNT);
+ return &(*self->variable_table)[index];
+}
+
+static inline void bestcomm_task_set_variable(const bestcomm_task *self, size_t index, uint32_t value)
+{
+ assert(index < VAR_COUNT);
+ (*self->variable_table)[index] = value;
+}
+
+static inline uint32_t bestcomm_task_get_increment_and_condition(const bestcomm_task *self, size_t index)
+{
+ assert(index < INC_COUNT);
+ return (*self->variable_table)[INC(index)];
+}
+
+static inline void bestcomm_task_set_increment_and_condition_32(
+ const bestcomm_task *self,
+ size_t index,
+ uint32_t inc_and_cond
+)
+{
+ assert(index < INC_COUNT);
+ (*self->variable_table)[INC(index)] = inc_and_cond;
+}
+
+static inline void bestcomm_task_set_increment_and_condition(
+ const bestcomm_task *self,
+ size_t index,
+ int16_t inc,
+ int cond
+)
+{
+ bestcomm_task_set_increment_and_condition_32(self, index, INC_INIT(cond, inc));
+}
+
+static inline void bestcomm_task_set_increment(const bestcomm_task *self, size_t index, int16_t inc)
+{
+ bestcomm_task_set_increment_and_condition_32(self, index, INC_INIT(0, inc));
+}
+
+void bestcomm_task_clear_variables(const bestcomm_task *self);
+
+static inline uint32_t bestcomm_task_get_opcode(const bestcomm_task *self, size_t index)
+{
+ assert(index < self->tdt_opcode_count);
+ return self->tdt_begin[index];
+}
+
+static inline void bestcomm_task_set_opcode(bestcomm_task *self, size_t index, uint32_t opcode)
+{
+ assert(index < self->tdt_opcode_count);
+ self->tdt_begin[index] = opcode;
+}
+
+static inline void bestcomm_task_set_initiator(const bestcomm_task *self, int initiator)
+{
+ rtems_interrupt_level level;
+ rtems_interrupt_disable(level);
+ *self->task_control_register = BSP_BFLD16SET(*self->task_control_register, initiator, 3, 7);
+ rtems_interrupt_enable(level);
+}
+
+static inline volatile bestcomm_task_entry *bestcomm_task_get_task_entry(const bestcomm_task *self)
+{
+ return &BESTCOMM_TASK_ENTRY_TABLE[self->task_index];
+}
+
+static inline void bestcomm_task_set_pragma(const bestcomm_task *self, int bit_pos, bool enable)
+{
+ volatile bestcomm_task_entry *entry = bestcomm_task_get_task_entry(self);
+ uint32_t mask = BSP_BIT32(bit_pos);
+ uint32_t bit = enable ? mask : 0;
+ entry->fdt_and_pragmas = (entry->fdt_and_pragmas & ~mask) | bit;
+}
+
+static inline void bestcomm_task_enable_precise_increment(const bestcomm_task *self, bool enable)
+{
+ bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_PRECISE_INC, enable);
+}
+
+static inline void bestcomm_task_enable_error_reset(const bestcomm_task *self, bool enable)
+{
+ bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_RST_ERROR_NO, !enable);
+}
+
+static inline void bestcomm_task_enable_pack_data(const bestcomm_task *self, bool enable)
+{
+ bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_PACK, enable);
+}
+
+static inline void bestcomm_task_enable_integer_mode(const bestcomm_task *self, bool enable)
+{
+ bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_INTEGER, enable);
+}
+
+static inline void bestcomm_task_enable_speculative_read(const bestcomm_task *self, bool enable)
+{
+ bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_SPECREAD, enable);
+}
+
+static inline void bestcomm_task_enable_combined_write(const bestcomm_task *self, bool enable)
+{
+ bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_CW, enable);
+}
+
+static inline void bestcomm_task_enable_read_buffer(const bestcomm_task *self, bool enable)
+{
+ bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_RL, enable);
+}
+
+static inline volatile uint16_t *bestcomm_task_get_task_control_register(const bestcomm_task *self)
+{
+ return self->task_control_register;
+}
+
+static inline int bestcomm_task_get_task_index(const bestcomm_task *self)
+{
+ return self->task_index;
+}
+
+static inline void bestcomm_task_free_tdt(bestcomm_task *self)
+{
+ bestcomm_free(self->tdt_begin);
+ self->tdt_begin = NULL;
+}
+
+static inline void bestcomm_task_clear_pragmas(const bestcomm_task *self)
+{
+ volatile bestcomm_task_entry *entry = bestcomm_task_get_task_entry(self);
+ entry->fdt_and_pragmas &= ~0xffU;
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* GEN5200_BESTCOMM_H */
diff --git a/c/src/lib/libbsp/powerpc/gen5200/include/bestcomm_ops.h b/c/src/lib/libbsp/powerpc/gen5200/include/bestcomm_ops.h
new file mode 100644
index 0000000000..d9fc8f0f46
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/gen5200/include/bestcomm_ops.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2010-2013 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef BESTCOMM_OPS_H
+#define BESTCOMM_OPS_H
+
+#include <bsp/utility.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup BestCommOps BestComm Ops
+ *
+ * @ingroup BestComm
+ *
+ * @brief BestComm ops.
+ *
+ * @{
+ */
+
+#define VAR(i) (i)
+#define VAR_COUNT 24
+#define INC(i) (24 + (i))
+#define INC_COUNT 8
+#define IDX(i) (48 + (i))
+#define IDX_COUNT 8
+
+#define COND_ONCE 0
+#define COND_LT 1
+#define COND_GT 2
+#define COND_NE 3
+#define COND_EQ 4
+#define COND_LE 5
+#define COND_GE 6
+#define COND_FOREVER 7
+
+#define INC_INIT(cond, val) \
+ (BSP_FLD32(cond, 29, 31) \
+ | BSP_FLD32((int16_t) (val), 0, 15))
+
+#define TERM_FIRST 0
+#define TERM_SECOND 1
+#define TERM_INIT 2
+#define TERM_UNUSED 3
+
+#define DEREF 1
+
+#define LCD_TERM(val) BSP_FLD32(val, 13, 14)
+
+#define LCD(deref0, iniidx0, deref1, iniidx1, term, termop, inc0, inc1) \
+ (BSP_BIT32(31) \
+ | BSP_FLD32(deref0, 29, 29) \
+ | BSP_FLD32(iniidx0, 23, 28) \
+ | BSP_FLD32(deref1, 21, 21) \
+ | BSP_FLD32(iniidx1, 15, 20) \
+ | LCD_TERM(term) \
+ | BSP_FLD32(termop, 6, 11) \
+ | BSP_FLD32(inc0, 3, 5) \
+ | BSP_FLD32(inc1, 0, 2))
+
+#define LCDEXT(deref0, iniidx0, deref1, iniidx1, term, termop, inc0, inc1) \
+ (BSP_BIT32(30) \
+ | LCD(deref0, iniidx0, deref1, iniidx1, term, termop, inc0, inc1))
+
+#define LCDPLUS(deref0, iniidx0, deref1, iniidx1, term, termop, inc0, inc1) \
+ (BSP_BIT32(22) \
+ | LCD(deref0, iniidx0, deref1, iniidx1, term, termop, inc0, inc1))
+
+#define LCDINIT(val) \
+ (BSP_BIT32(31) \
+ | BSP_FLD32((val) >> 13, 15, 29) \
+ | LCD_TERM(TERM_INIT) \
+ | BSP_FLD32(val, 0, 12))
+
+#define MORE 0x4
+
+#define TFD 0x2
+
+#define INT 0x1
+
+#define DRD_FLAGS(val) BSP_FLD32(val, 26, 28)
+
+#define INIT_ALWAYS 0
+#define INIT_SCTMR_0 1
+#define INIT_SCTMR_1 2
+#define INIT_FEC_RX 3
+#define INIT_FEC_TX 4
+#define INIT_ATA_RX 5
+#define INIT_ATA_TX 6
+#define INIT_SCPCI_RX 7
+#define INIT_SCPCI_TX 8
+#define INIT_PSC3_RX 9
+#define INIT_PSC3_TX 10
+#define INIT_PSC2_RX 11
+#define INIT_PSC2_TX 12
+#define INIT_PSC1_RX 13
+#define INIT_PSC1_TX 14
+#define INIT_SCTMR_2 15
+#define INIT_SCLPC 16
+#define INIT_PSC5_RX 17
+#define INIT_PSC5_TX 18
+#define INIT_PSC4_RX 19
+#define INIT_PSC4_TX 20
+#define INIT_I2C2_RX 21
+#define INIT_I2C2_TX 22
+#define INIT_I2C1_RX 23
+#define INIT_I2C1_TX 24
+#define INIT_PSC6_RX 25
+#define INIT_PSC6_TX 26
+#define INIT_IRDA_RX 25
+#define INIT_IRDA_TX 26
+#define INIT_SCTMR_3 27
+#define INIT_SCTMR_4 28
+#define INIT_SCTMR_5 29
+#define INIT_SCTMR_6 30
+#define INIT_SCTMR_7 31
+
+#define DRD_INIT(val) BSP_FLD32(val, 21, 25)
+
+#define SZ_8 1
+#define SZ_16 2
+#define SZ_32 0
+#define SZ_DYN 3
+
+#define DRD_RS(val) BSP_FLD32(val, 19, 20)
+
+#define DRD_WS(val) BSP_FLD32(val, 17, 18)
+
+#define DEST_VAR(val) (val)
+#define DEST_IDX(val) (BSP_BIT32(5) | (val))
+#define DEST_DEREF_IDX(val) (BSP_BIT32(5) | BSP_BIT32(4) | (val))
+
+#define SRC_VAR(val) (val)
+#define SRC_INC(val) (BSP_BIT32(5) | (val))
+#define SRC_EU_RESULT (BSP_BIT32(5) | BSP_BIT32(4) | BSP_BIT32(1) | BSP_BIT32(0))
+#define SRC_DEREF_EU_RESULT (BSP_BIT32(6) | BSP_BIT32(4) | BSP_BIT32(1) | BSP_BIT32(0))
+#define SRC_IDX(val) (BSP_BIT32(6) | BSP_BIT32(5) | (val))
+#define SRC_DEREF_IDX(val) (BSP_BIT32(6) | BSP_BIT32(5) | BSP_BIT32(4) | (val))
+#define SRC_NONE (BSP_BIT32(5) | BSP_BIT32(4) | BSP_BIT32(3) | BSP_BIT32(2) | BSP_BIT32(1) | BSP_BIT32(0))
+
+#define DRD1A(flags, init, dest, ws, src, rs) \
+ (DRD_FLAGS(flags) \
+ | DRD_INIT(init) \
+ | DRD_RS(rs) \
+ | DRD_WS(ws) \
+ | BSP_FLD32(dest, 10, 15) \
+ | BSP_FLD32(src, 3, 9))
+
+#define DRD1AEURESULT(flags, init, dest, ws, rs) \
+ (DRD1A(flags, init, rs, ws, dest, SRC_EU_RESULT) \
+ | BSP_FLD32(1, 0, 3))
+
+#define FUNC_LOAD_ACC 0
+#define FUNC_UNLOAD_ACC 1
+#define FUNC_AND 2
+#define FUNC_OR 3
+#define FUNC_XOR 4
+#define FUNC_ANDN 5
+#define FUNC_NOT 6
+#define FUNC_ADD 7
+#define FUNC_SUB 8
+#define FUNC_LSH 9
+#define FUNC_RSH 10
+#define FUNC_CRC8 11
+#define FUNC_CRC16 12
+#define FUNC_CRC32 13
+#define FUNC_ENDIAN32 14
+#define FUNC_ENDIAN16 15
+
+#define DRD2A(flags, func) \
+ (BSP_BIT32(30) | BSP_BIT32(29) \
+ | DRD_FLAGS(flags) \
+ | BSP_FLD32(func, 0, 3))
+
+#define DRD2A5(flags, init, func, ws, rs) \
+ (DRD2A(flags, func) \
+ | DRD_RS(rs) \
+ | DRD_WS(ws) \
+ | DRD_INIT(init))
+
+#define OP_VAR(val) (val)
+#define OP_EU_RESULT (BSP_BIT32(4) | BSP_BIT32(3) | BSP_BIT32(1) | BSP_BIT32(0))
+#define OP_NONE (BSP_BIT32(4) | BSP_BIT32(3) | BSP_BIT32(2) | BSP_BIT32(1) | BSP_BIT32(0))
+#define OP_IDX(val) (BSP_BIT32(5) | (val))
+#define OP_DEREF_IDX(val) (BSP_BIT32(5) | BSP_BIT32(4) | (val))
+
+#define DRD2B1(dest, op0, op1) \
+ (BSP_FLD32(dest, 22, 27) \
+ | BSP_FLD32(SRC_EU_RESULT, 14, 20) \
+ | BSP_FLD32(3, 12, 13) \
+ | BSP_FLD32(op0, 6, 11) \
+ | BSP_FLD32(op1, 0, 5))
+
+#define DRD2B2(op0, op1) \
+ (BSP_BIT32(29) \
+ | BSP_FLD32(3, 26, 27) \
+ | BSP_FLD32(op0, 20, 25) \
+ | BSP_FLD32(op1, 14, 19) \
+ | BSP_FLD32(0, 12, 13) \
+ | BSP_FLD32(OP_NONE, 6, 11) \
+ | BSP_FLD32(OP_NONE, 0, 5))
+
+#define NOP 0x1f8
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* BESTCOMM_OPS_H */
diff --git a/c/src/lib/libbsp/powerpc/gen5200/include/bsp.h b/c/src/lib/libbsp/powerpc/gen5200/include/bsp.h
index 8564936786..9f30e66488 100644
--- a/c/src/lib/libbsp/powerpc/gen5200/include/bsp.h
+++ b/c/src/lib/libbsp/powerpc/gen5200/include/bsp.h
@@ -230,7 +230,10 @@ typedef enum {
MPC5200_FATAL_MSCAN_A_INIT,
MPC5200_FATAL_MSCAN_B_INIT,
MPC5200_FATAL_MSCAN_A_SET_MODE,
- MPC5200_FATAL_MSCAN_B_SET_MODE
+ MPC5200_FATAL_MSCAN_B_SET_MODE,
+ MPC5200_FATAL_ATA_DISK_IO_INIT,
+ MPC5200_FATAL_ATA_DISK_CREATE,
+ MPC5200_FATAL_ATA_DMA_SINGLE_IRQ_INSTALL
} mpc5200_fatal_code;
void mpc5200_fatal(mpc5200_fatal_code code) RTEMS_COMPILER_NO_RETURN_ATTRIBUTE;